├── LICENSE ├── README.md ├── dxf ├── customfan.dxf ├── fan_40.dxf ├── hk_25mm.dxf ├── hk_50mm.dxf └── odroid.dxf ├── lib ├── antenna.scad ├── audio.scad ├── b2b.scad ├── battery.scad ├── button.scad ├── cm.scad ├── discrete.scad ├── display.scad ├── fan.scad ├── fillets.scad ├── fpc.scad ├── gpio.scad ├── header.scad ├── heatsink.scad ├── heatsinks │ ├── Khadas_Heatsink.stl │ ├── Khadas_Heatsink_Fan.stl │ ├── Odroid-H2_Heatsink.stl │ ├── Odroid-M1_Heatsink.stl │ ├── Odroid-N2+_Heatsink.stl │ ├── Odroid-N2_Heatsink.stl │ ├── Radxa_Heatsink.stl │ └── rpi5_oem.dxf ├── ic.scad ├── jst.scad ├── memory.scad ├── molex.scad ├── network.scad ├── pcb.scad ├── pcie.scad ├── pillar.scad ├── place.scad ├── power.scad ├── shape.scad ├── smd.scad ├── storage.scad ├── switch.scad ├── terminal.scad ├── uart.scad ├── usb2.scad ├── usb3.scad ├── usbc.scad └── video.scad ├── sbc_models.cfg ├── sbc_models.png ├── sbc_models.scad ├── sbc_models_library.scad ├── sbc_models_viewer.gif └── sbc_models_viewer.scad /lib/antenna.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: antenna 20 | DESCRIPTION: creates antenna components. 21 | TODO: 22 | 23 | USAGE: antenna(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "ipex" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | pcbsize_z = pcb thickness 32 | enablemask = true produces mask, false produces model 33 | mask[0] = component mask true, false 34 | mask[1] = length 35 | mask[2] = set back 36 | mask[3] = mstyle "default" 37 | 38 | */ 39 | 40 | module antenna(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 41 | 42 | // type ipex surface mount 43 | if(type == "ipex" && enablemask == false) { 44 | place(loc_x, loc_y, loc_z, 2.5, 2.75, rotation, side, pcbsize_z) 45 | union() { 46 | color("white") cube([2.5,2.75,.35]); 47 | difference() { 48 | color("silver") translate([2.5/2, 2.75/2, .45]) cylinder(d=2, h=.8); 49 | color("silver") translate([2.5/2, 2.75/2, .6]) cylinder(d=1.8, h=1); 50 | } 51 | color("gold") translate([2.5/2, 2.75/2, .6]) cylinder(d=.5, h=.6); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/audio.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: audio 20 | DESCRIPTION: creates audio components. 21 | TODO: 22 | 23 | USAGE: audio(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "audio_micro" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | pcbsize_z = pcb thickness 32 | enablemask = true produces mask, false produces model 33 | mask[0] = component mask true, false 34 | mask[1] = length 35 | mask[2] = set back 36 | mask[3] = mstyle "default" 37 | 38 | type = "jack_3.5", "jack_3.5-2 39 | loc_x = x location placement 40 | loc_y = y location placement 41 | loc_z = z location placement 42 | side = "top", "bottom" 43 | rotation[] = object rotation 44 | size[0] = body size_x 45 | size[1] = body size_y 46 | size[2] = body size_z 47 | data[0] = neck diameter 48 | data[1] = z adjustment 49 | pcbsize_z = pcb thickness 50 | enablemask = true produces mask, false produces model 51 | mask[0] = component mask true, false 52 | mask[1] = length 53 | mask[2] = set back 54 | mask[3] = mstyle "default" 55 | 56 | type = "mic_round" 57 | loc_x = x location placement 58 | loc_y = y location placement 59 | loc_z = z location placement 60 | side = "top", "bottom" 61 | rotation[] = object rotation 62 | size[0] = body diameter 63 | size[1] = 64 | size[2] = body height 65 | pcbsize_z = pcb thickness 66 | enablemask = true produces mask, false produces model 67 | mask[0] = component mask true, false 68 | mask[1] = length 69 | mask[2] = set back 70 | mask[3] = mstyle "default" 71 | 72 | type = "out-in-spdif" 73 | loc_x = x location placement 74 | loc_y = y location placement 75 | loc_z = z location placement 76 | side = "top", "bottom" 77 | rotation[] = object rotation 78 | pcbsize_z = pcb thickness 79 | enablemask = true produces mask, false produces model 80 | mask[0] = component mask true, false 81 | mask[1] = length 82 | mask[2] = set back 83 | mask[3] = mstyle "default" 84 | 85 | */ 86 | 87 | module audio(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 88 | 89 | cmask = mask[0]; 90 | mlen = mask[1]; 91 | back = mask[2]; 92 | mstyle = mask[3]; 93 | adj = .01; 94 | $fn = 90; 95 | 96 | // out in and spdif stacked type 97 | if(type == "out-in-spdif") { 98 | 99 | size_x = 12.7; 100 | size_y = 21.5; 101 | size_z = 35; 102 | size_xm = 13; 103 | size_ym = mlen; 104 | size_zm = 35.5; 105 | 106 | if(enablemask == true && cmask == true && mstyle == "default") { 107 | if(side == "top" && rotation == 0) { 108 | place(loc_x-(size_xm-size_x)/2, loc_y-size_ym+back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 109 | cube([size_xm, mlen, size_zm]); 110 | } 111 | if(side == "top" && rotation == 90) { 112 | place(loc_x-size_ym+back, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 113 | cube([size_xm, mlen, size_zm]); 114 | } 115 | if(side == "top" && rotation == 180) { 116 | place(loc_x-(size_xm-size_x)/2, loc_y+size_y-back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 117 | cube([size_xm, mlen, size_zm]); 118 | } 119 | if(side == "top" && rotation == 270) { 120 | place(loc_x+size_y-back, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 121 | cube([size_xm, mlen, size_zm]); 122 | } 123 | if(side == "bottom" && rotation == 0) { 124 | place(loc_x-(size_xm-size_x)/2, loc_y-size_ym+back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 125 | cube([size_xm, mlen, size_zm]); 126 | } 127 | if(side == "bottom" && rotation == 90) { 128 | place(loc_x+size_y-back, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 129 | cube([size_xm, mlen, size_zm]); 130 | } 131 | if(side == "bottom" && rotation == 180) { 132 | place(loc_x-(size_xm-size_x)/2, loc_y+size_y-back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 133 | cube([size_xm, mlen, size_zm]); 134 | } 135 | if(side == "bottom" && rotation == 270) { 136 | place(loc_x-size_ym+back, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 137 | cube([size_xm, mlen, size_zm]); 138 | } 139 | } 140 | if(enablemask == false) { 141 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 142 | union() { 143 | difference () { 144 | union() { 145 | color("silver") cube([size_x, size_y, size_z]); 146 | color("black") translate([6.35, -3.2, 17]) rotate([-90, 0, 0]) 147 | cylinder(d=8, h=6.25); 148 | color("black") translate([6.35, -3.2, 29]) rotate([-90, 0, 0]) 149 | cylinder(d=8, h=6.25); 150 | color("dimgray") translate([1.85, -2.0, 2]) cube([9, 2, 9]); 151 | } 152 | color("dimgray") translate([6.35, -3.25, 17]) rotate([-90, 0, 0]) 153 | cylinder(d=3.75, h=9); 154 | color("dimgray") translate([6.35, -3.25, 29]) rotate([-90, 0, 0]) 155 | cylinder(d=3.75, h=9); 156 | difference() { 157 | color("dimgray") translate([2.85, -2.1, 3]) cube([7, 9, 7]); 158 | color("dimgray") translate([1.85, -2, 3]) rotate([0, 45, 0]) cube([1.5, 9, 1.5]); 159 | color("dimgray") translate([8.75, -2, 3]) rotate([0, 45, 0]) cube([1.5, 9, 1.5]); 160 | } 161 | } 162 | } 163 | } 164 | } 165 | 166 | // 3.5mm jack type 167 | if(type == "jack_3.5" || type == "jack_3.5-2") { 168 | 169 | size_x = size[0]; 170 | size_y = size[1]; 171 | size_z = size[2]; 172 | size_xm = size_x+1; 173 | size_ym = size_y; 174 | size_zm = size_z+1; 175 | bdiam = data[0]; 176 | badj = data[1]; 177 | 178 | if(enablemask == true && cmask == true && mstyle == "default") { 179 | if(side == "top" && rotation == 0) { 180 | place(loc_x-.5, loc_y-2.5+back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 181 | union() { 182 | cube([size_xm, 2.5, size_zm]); 183 | translate([size_xm/2, 2, (size_z/2)+badj]) rotate([90, 0, 0]) cylinder(d=bdiam+1, h=mlen); 184 | } 185 | } 186 | if(side == "top" && rotation == 90) { 187 | place(loc_x-2.5+back, loc_y-.5, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 188 | union() { 189 | cube([size_xm, 2.5, size_zm]); 190 | translate([size_xm/2, 2, (size_z/2)+badj]) rotate([90, 0, 0]) cylinder(d=bdiam+1, h=mlen); 191 | } 192 | } 193 | if(side == "top" && rotation == 180) { 194 | place(loc_x-.5, loc_y+2.5-back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 195 | union() { 196 | cube([size_xm, 2.5, size_zm]); 197 | translate([size_xm/2, 2, (size_z/2)+badj]) rotate([90, 0, 0]) cylinder(d=bdiam+1, h=mlen); 198 | } 199 | } 200 | if(side == "top" && rotation == 270) { 201 | place(loc_x+2.5-back, loc_y-.5, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 202 | union() { 203 | cube([size_xm, 2.5, size_zm]); 204 | translate([size_xm/2, 2, (size_z/2)+badj]) rotate([90, 0, 0]) cylinder(d=bdiam+1, h=mlen); 205 | } 206 | } 207 | if(side == "bottom" && rotation == 0) { 208 | place(loc_x-.5, loc_y-2.5+back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 209 | union() { 210 | cube([size_xm, 2.5, size_zm]); 211 | translate([size_xm/2, 2, (size_z/2)+badj]) rotate([90, 0, 0]) cylinder(d=bdiam+1, h=mlen); 212 | } 213 | } 214 | if(side == "bottom" && rotation == 90) { 215 | place(loc_x+2.5-back, loc_y-.5, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 216 | union() { 217 | cube([size_xm, 2.5, size_zm]); 218 | translate([size_xm/2, 2, (size_z/2)+badj]) rotate([90, 0, 0]) cylinder(d=bdiam+1, h=mlen); 219 | } 220 | } 221 | if(side == "bottom" && rotation == 180) { 222 | place(loc_x-.5, loc_y+2.5-back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 223 | union() { 224 | cube([size_xm, 2.5, size_zm]); 225 | translate([size_xm/2, 2, (size_z/2)+badj]) rotate([90, 0, 0]) cylinder(d=bdiam+2, h=mlen); 226 | } 227 | } 228 | if(side == "bottom" && rotation == 270) { 229 | place(loc_x-2.5+back, loc_y-.5, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 230 | union() { 231 | cube([size_xm, 2.5, size_zm]); 232 | translate([size_xm/2, 2, (size_z/2)+badj]) rotate([90, 0, 0]) cylinder(d=bdiam+1, h=mlen); 233 | } 234 | } 235 | } 236 | if(enablemask == false) { 237 | if(type == "jack_3.5") { 238 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 239 | union() { 240 | difference () { 241 | union() { 242 | color("silver") cube([size_x, 2, size_z]); 243 | color("black") translate([0, 2-adj, 0]) cube([size_x, size_y, size_z]); 244 | color("black") translate([size_x/2, -2, (size_z/2)+badj]) rotate([-90, 0, 0]) cylinder(d=bdiam, h=6.25); 245 | } 246 | color("dimgray") translate([size_x/2, -2.5, (size_z/2)+badj]) rotate([-90, 0, 0]) cylinder(d=3.5, h=6); 247 | } 248 | } 249 | } 250 | if(type == "jack_3.5-2") { 251 | size_x = 6.5; 252 | size_y = 13.5; 253 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 254 | difference () { 255 | union() { 256 | color("dimgray") cube([size_x,size_y,3]); 257 | color("dimgray") translate([0,size_y-5.6,0]) cube([size_x,5.6,4]); 258 | color("dimgray") translate([size_x/2,0,2.25]) rotate([270,0,0]) cylinder(d=6, h=size_y); 259 | } 260 | color("gray") translate([size_x/2,-1,2.25]) rotate([270,0,0]) cylinder(d=3, h=size_y+.01); 261 | } 262 | } 263 | } 264 | } 265 | 266 | // audio micro connector type 267 | if(type == "audio_micro") { 268 | 269 | size_x = 7.5; 270 | size_y = 3.75; 271 | size_z = 4.75; 272 | size_xm = 7.5; 273 | size_ym = mlen; 274 | size_zm = 4; 275 | 276 | if(enablemask == true && cmask == true && mstyle == "default") { 277 | if(side == "top" && rotation == 0) { 278 | place(loc_x-(size_xm-size_x)/2, loc_y-size_ym+back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 279 | cube([size_xm, mlen, size_zm]); 280 | } 281 | if(side == "top" && rotation == 90) { 282 | place(loc_x-size_ym+back, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 283 | cube([size_xm, mlen, size_zm]); 284 | } 285 | if(side == "top" && rotation == 180) { 286 | place(loc_x-(size_xm-size_x)/2, loc_y+size_y-back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 287 | cube([size_xm, mlen, size_zm]); 288 | } 289 | if(side == "top" && rotation == 270) { 290 | place(loc_x+size_y-back, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 291 | cube([size_xm, mlen, size_zm]); 292 | } 293 | if(side == "bottom" && rotation == 0) { 294 | place(loc_x-(size_xm-size_x)/2, loc_y-size_ym+back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 295 | cube([size_xm, mlen, size_zm]); 296 | } 297 | if(side == "bottom" && rotation == 90) { 298 | place(loc_x+size_y-back, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 299 | cube([size_xm, mlen, size_zm]); 300 | } 301 | if(side == "bottom" && rotation == 180) { 302 | place(loc_x-(size_xm-size_x)/2, loc_y+size_y-back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 303 | cube([size_xm, mlen, size_zm]); 304 | } 305 | if(side == "bottom" && rotation == 270) { 306 | place(loc_x-size_ym+back, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 307 | cube([size_xm, mlen, size_zm]); 308 | } 309 | } 310 | if(enablemask == false) { 311 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 312 | translate([size_xm, size_y+1.5, 3.75]) rotate([-90, 0, 180]) 313 | union() { 314 | difference () { 315 | color("white") cube([size_x, size_y, size_z]); 316 | color("darkgray") translate([1.5, .5, 1]) cube([4.5, 2.75, 6]); 317 | color("white") translate([-.5, .75, -.5]) cube([1, 2.5, 6]); 318 | color("white") translate([7, .75, -.5]) cube([1, 2.5, 6]); 319 | color("darkgray") translate([2.25, -.5, 1]) cube([3, 2, 6]); 320 | } 321 | color("silver") translate ([2.75, 2, .5]) cube([.6, .6, 4]); 322 | color("silver") translate ([4.5, 2, .5]) cube([.6, .6, 4]); 323 | } 324 | } 325 | } 326 | 327 | // mic_round type 328 | if(type == "mic_round" && enablemask == false) { 329 | 330 | size_x = size[0]; 331 | size_y = size[0]; 332 | size_z = size[2]; 333 | 334 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 335 | union() { 336 | color("silver") cylinder(d=size_x, h=size_z); 337 | color("#353535") translate ([0, 0, size_z-.01]) cylinder(d=size_x-.5, h=.15); 338 | } 339 | } 340 | } 341 | -------------------------------------------------------------------------------- /lib/b2b.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: b2b 20 | DESCRIPTION: creates b2b headers in size, pitch and stacking height. 21 | TODO: shielded 22 | 23 | USAGE: b2b(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "df40" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | size[0] = #pins 32 | size[2] = stacking height (1.5, 2, 2.5, 3, 3.5, 4) 33 | data[0] = "default" 34 | data[1] = body color 35 | data[2] = "male", "female" 36 | pcbsize_z = pcb thickness 37 | enablemask = true produces mask, false produces model 38 | 39 | */ 40 | 41 | module b2b(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 42 | 43 | pins = size[0]; 44 | height = size[2]-.05; 45 | style = data[0]; 46 | hcolor = data[1]; 47 | gender = data[2]; 48 | 49 | adj = .01; 50 | $fn = 90; 51 | 52 | 53 | // df40 style header 54 | if(type=="df40" && enablemask == false) { 55 | 56 | pitch = .4; 57 | wallthick = .25; 58 | pcolor = "#fee5a6"; 59 | 60 | if(gender == "female") { 61 | 62 | lead_in = 1.3; 63 | pinsize = .12; 64 | smtlead = [pinsize,.25,.15]; 65 | size_x = pitch * (pins/2) + (2*lead_in); 66 | size_y = 2.88; 67 | 68 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 69 | union() { 70 | difference() { 71 | color(hcolor) cube([size_x, size_y, height]); 72 | translate([.75,-1,height-.25]) color("#252525") cube([size_x-1.5, size_y+2, 1]); 73 | translate([wallthick,wallthick,wallthick]) color("#252525") 74 | cube([size_x-(2*wallthick), .625, height]); 75 | translate([wallthick,size_y-wallthick-.625,wallthick]) color("#252525") 76 | cube([size_x-(2*wallthick), .625, height]); 77 | translate([wallthick,wallthick,wallthick]) color("#252525") 78 | cube([(lead_in-wallthick), size_y-(2*wallthick), height]); 79 | translate([size_x-wallthick-(lead_in-wallthick),wallthick,wallthick]) 80 | color("#252525") cube([lead_in-wallthick, size_y-(2*wallthick), height]); 81 | 82 | } 83 | for(c=[lead_in+(pitch/2):pitch:size_x-lead_in]) { 84 | color(pcolor) translate([c-(pinsize/2), (size_y-1.5)/2-(pinsize/2)+.125, adj]) 85 | cube([pinsize,pinsize,height-.25+adj]); 86 | color(pcolor) translate([c-(pinsize/2), (size_y-1.5)/2-(pinsize/2)+1.475, adj]) 87 | cube([pinsize, pinsize, height-.25+adj]); 88 | color(pcolor) translate([c-(pinsize/2), -smtlead[1], 0]) cube(smtlead); 89 | color(pcolor) translate([c-(pinsize/2), size_y-adj, 0]) cube(smtlead); 90 | } 91 | } 92 | } 93 | if(gender == "male") { 94 | 95 | lead_in = .75; 96 | pinsize = .12; 97 | smtlead = [pinsize,.56,.15]; 98 | size_x = pitch * (pins/2) + (2*lead_in); 99 | size_y = 1.85; 100 | height = 1.14; 101 | 102 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 103 | union() { 104 | difference() { 105 | color(hcolor) cube([size_x, size_y, height]); 106 | color("#252525") translate([wallthick*3, wallthick, wallthick]) 107 | cube([size_x-(6*wallthick), size_y-(2*wallthick), height]); 108 | } 109 | for(c=[lead_in+(pitch/2):pitch:size_x-lead_in]) { 110 | color(pcolor) translate([c-(pinsize/2), wallthick-(pinsize/2), adj]) 111 | cube([pinsize, pinsize, height+adj]); 112 | color(pcolor) translate([c-(pinsize/2), size_y-wallthick-(pinsize/2), adj]) 113 | cube([pinsize, pinsize, height+adj]); 114 | color(pcolor) translate([c-(pinsize/2), -smtlead[1], 0]) cube(smtlead); 115 | color(pcolor) translate([c-(pinsize/2), size_y-adj, 0]) cube(smtlead); 116 | } 117 | } 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /lib/battery.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: battery 20 | DESCRIPTION: creates batteries and support components. 21 | TODO: 22 | 23 | USAGE: battery(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "bat_hold_1", "rtc_micro" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | pcbsize_z = pcb thickness 32 | enablemask = true produces mask, false produces model 33 | mask[0] = true enables component mask 34 | mask[1] = mask length 35 | mask[2] = mask setback 36 | mask[3] = mstyle "default" 37 | 38 | */ 39 | 40 | module battery(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 41 | 42 | // type battery holder 1 43 | if(type == "bat_hold_1" && enablemask == false) { 44 | 45 | size_x = 22; 46 | size_y = 16; 47 | 48 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 49 | union() { 50 | difference() { 51 | union() { 52 | color("LightYellow") cube([size_x, size_y, 6]); 53 | color("LightYellow") translate([-3.2499, 4.5, 0]) cube([3.25, 7, 6]); 54 | color("LightYellow") translate([21.999, 4.5, 0]) cube([3.25, 7, 6]); 55 | } 56 | color("LightYellow") translate([11, 8, 2]) cylinder(d=20, h=5, $fn=360); 57 | color("LightYellow") translate([-3.259, 5, 5]) cube([28.6, 5.5, 3]); 58 | color("LightYellow") translate([-3.25, 5.5, 5]) cube([28.5, 5.5, 3]); 59 | 60 | color("LightYellow") translate([-4.251, 5, -1]) cube([2, 6, 8]); 61 | color("LightYellow") translate([.5, 5, 2]) cube([1, 6, 8]); 62 | 63 | color("LightYellow") translate([24.25, 5, -1]) cube([2, 6, 8]); 64 | color("LightYellow") translate([20, 5, 2]) cube([1, 6, 8]); 65 | 66 | color("LightYellow") translate([22, 15, -1]) rotate([0, 0, 45]) cube([2, 2, 8]); 67 | 68 | /* bottom cut outs */ 69 | color("LightYellow") translate([7, 2.5, -1]) cylinder(d=2.5, h=4, $fn=360); 70 | color("LightYellow") translate([3.75, 1.25, -1]) cube([3.5, 2.5, 3.75]); 71 | color("LightYellow") translate([15, 2.5, -1]) cylinder(d=2.5, h=4, $fn=360); 72 | color("LightYellow") translate([15, 1.25, -1]) cube([3.3,2.5,3.75]); 73 | color("LightYellow") translate([7, 13.5, -1]) cylinder(d=2.5, h=4, $fn=360); 74 | color("LightYellow") translate([3.75, 12.25, -1]) cube([3.5, 2.5, 3.75]); 75 | color("LightYellow") translate([15, 13.5, -1]) cylinder(d=2.5, h=4, $fn=360); 76 | color("LightYellow") translate([15, 12.25, -1]) cube([3.3, 2.5, 3.75]); 77 | } 78 | color("Gold") translate([-2.25199, 5, 0]) cube([1, 6, 6]); 79 | color("Gold") translate([0, 5, 0]) cube([1, 6, 6]); 80 | color("Gold") translate([-2.25199, 5, 5]) cube([3, 6, 1]); 81 | 82 | color("Gold") translate([20.99, 5, 2]) cube([1, 6, 4]); 83 | color("Gold") translate([23.251, 5, 0]) cube([1, 6, 6]); 84 | color("Gold") translate([21, 5, 5]) cube([3, 6, 1]); 85 | 86 | /* right contacts */ 87 | color("Gold") translate([15, 6, 2.5]) rotate([0, 5, 0]) cube([6, 1, .5]); 88 | color("Gold") translate([15, 9, 2.5]) rotate([0, 5, 0]) cube([6, 1, .5]); 89 | color("Gold") translate([20.5, 5, 2]) cube([1, 6, .5]); 90 | 91 | /* left contacts */ 92 | color("Gold") translate([1.5, 6, 2.5]) rotate([0, 5, 0]) cube([.5, 1, 3]); 93 | color("Gold") translate([2, 6, 5]) rotate([0, 5, 0]) cube([.5,1 , .5]); 94 | color("Gold") translate([1.5, 9, 2.5]) rotate([0 ,5, 0]) cube([.5, 1, 3]); 95 | color("Gold") translate([2, 9, 5]) rotate([0, 5, 0]) cube([.5, 1, .5]); 96 | color("Gold") translate([1, 5, 2]) cube([1, 6, .5]); 97 | } 98 | } 99 | 100 | // rtc micro connector type 101 | if(type == "rtc_micro" && enablemask == false) { 102 | size_x = 7.5; 103 | size_y = 3.75; 104 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 105 | union() { 106 | difference () { 107 | color("white") cube([size_x, size_y, 4.75]); 108 | color("darkgray") translate([1.5, .5, 1]) cube([4.5, 2.75, 6]); 109 | color("white") translate([-.5, .75, -.5]) cube([1, 2.5, 6]); 110 | color("white") translate([7, .75, -.5]) cube([1, 2.5, 6]); 111 | color("darkgray") translate([2.25, -.5, 1]) cube([3, 2, 6]); 112 | } 113 | color("silver") translate([2.75, 2, .5]) cube([.6, .6, 4]); 114 | color("silver") translate([4.5, 2, .5]) cube([.6, .6, 4]); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /lib/cm.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | cm(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) 19 | cm_holder(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) 20 | 21 | */ 22 | 23 | /* 24 | 25 | CLASS NAME: cm 26 | DESCRIPTION: creates compute modules as library components 27 | TODO: CM1,CM3,CM4S SOC location 28 | 29 | USAGE: cm(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 30 | 31 | type = "cm1","cm3","cm3l","cm4s","cm4","cm4l","jetsonnano","soedge" 32 | loc_x = x location placement 33 | loc_y = y location placement 34 | loc_z = z location placement 35 | side = "top", "bottom" 36 | rotation[] = object rotation 37 | data[0] = fan size 38 | data[1] = cm pcb color 39 | pcbsize_z = pcb thickness 40 | enablemask = true produces mask, false produces model 41 | mask[0] = true enables component mask 42 | mask[1] = mask length 43 | mask[2] = mask setback 44 | mask[3] = mstyle "default" 45 | 46 | 47 | CLASS NAME: cm_holder 48 | DESCRIPTION: creates compute module holder 49 | TODO: "cm1","cm3","cm3l","cm4s" 50 | 51 | USAGE: cm_holder(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 52 | 53 | type = "jetsonnano" 54 | loc_x = x location placement 55 | loc_y = y location placement 56 | loc_z = z location placement 57 | side = "top", "bottom" 58 | rotation[] = object rotation 59 | data[0] = cm pcb color 60 | pcbsize_z = pcb thickness 61 | enablemask = true produces mask, false produces model 62 | mask[0] = true enables component mask 63 | mask[1] = mask length 64 | mask[2] = mask setback 65 | mask[3] = mstyle "default" 66 | 67 | 68 | */ 69 | 70 | module cm(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 71 | 72 | fsize = data[0]; 73 | pcbcolor = data[1]; 74 | cmask = mask[0]; 75 | mlen = mask[1]; 76 | back = mask[2]; 77 | mstyle = mask[3]; 78 | size_x = 67.6; 79 | size_y = type == "cm1" ? 30 : 31; 80 | size_z = 1; 81 | $fn=90; 82 | 83 | if(type == "cm1" || type == "cm3" || type == "cm3l" || type == "cm3+" || type == "cm4s") { 84 | 85 | if(enablemask == true && cmask == true && mstyle == "default") { 86 | 87 | } 88 | if(enablemask == false) { 89 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 90 | union() { 91 | difference () { 92 | union() { 93 | color(pcbcolor) cube([size_x,size_y,size_z]); 94 | color("#fee5a6") translate([3, 27, .99]) cylinder(d=5, h=.2); 95 | color("#fee5a6") translate([3, 27, -.01]) cylinder(d=5, h=.2); 96 | color("#fee5a6") translate([64.6, 27, .99]) cylinder(d=5, h=.2); 97 | color("#fee5a6") translate([64.6, 27, -.01]) cylinder(d=5,h =.2); 98 | } 99 | color(pcbcolor) translate([15.75+.5, -1, -1]) rotate([0, 0, 90]) slot(1, 5, 3); 100 | color(pcbcolor) translate([0, 21, -1]) cylinder(d=3, h=3); 101 | color(pcbcolor) translate([size_x, 21, -1]) cylinder(d=3, h=3); 102 | color(pcbcolor) translate([3, 27, -1]) cylinder(d=2.3, h=3); 103 | color(pcbcolor) translate([64.6, 27, -1]) cylinder(d=2.3, h=3); 104 | } 105 | for (i=[0:.5:14.5]) { 106 | color("#fee5a6") translate ([i+.5, 0, -.24]) cube([.25, 2, .25]); 107 | color("#fee5a6") translate ([i+.5, 0, .99]) cube([.25, 2, .25]); 108 | } 109 | for (i=[16.75:.5:66.5]) { 110 | color("#fee5a6") translate ([i+.5, 0, -.24]) cube([.25, 2, .25]); 111 | color("#fee5a6") translate ([i+.5, 0, .99]) cube([.25, 2, .25]); 112 | } 113 | } 114 | } 115 | } 116 | if(type == "cm4" || type == "cm4l") { 117 | 118 | pcbcolor = data[1]; 119 | size_x = 55; 120 | size_y = 40; 121 | size_z = 1.2; 122 | 123 | if(enablemask == true && cmask == true && mstyle == "default") { 124 | 125 | } 126 | if(enablemask == false) { 127 | 128 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 129 | union() { 130 | difference () { 131 | union() { 132 | color(pcbcolor) slab([size_x, size_y, size_z],3); 133 | color("#fee5a6") translate([3.5, 3.5, -.01]) cylinder(d=5, h=size_z+.2); 134 | color("#fee5a6") translate([3.5, size_y-3.5, -.01]) cylinder(d=5, h=size_z+.2); 135 | color("#fee5a6") translate([size_x-3.5, 3.5, -.01]) cylinder(d=5, h=size_z+.2); 136 | color("#fee5a6") translate([size_x-3.5, size_y-3.5, -.01]) cylinder(d=5, h=size_z+.2); 137 | } 138 | //color(pcbcolor) translate([-1, 18.5, -1]) cube([7.5, 11, 3]); 139 | color(pcbcolor) translate([2.56, 31, -1]) cylinder(d=1.5, h=3); 140 | color(pcbcolor) translate([3.5, 3.5, -1]) cylinder(d=2.5, h=3); 141 | color(pcbcolor) translate([3.5, size_y-3.5, -1]) cylinder(d=2.5, h=3); 142 | color(pcbcolor) translate([size_x-3.5, 3.5, -1]) cylinder(d=2.5, h=3); 143 | color(pcbcolor) translate([size_x-3.5, size_y-3.5, -1]) cylinder(d=2.5, h=3); 144 | } 145 | pcbsoc("raised", 25, 10, 0, "top", 0, [13,13,1.25], data, size_z, false, [false,10,2,"default"]); 146 | if(type == "cm4") { 147 | ic("generic", 20.9, 27, 0, "top", 0, [13, 11.75, .8], ["dimgrey"], size_z, false, [false,10,2,"default"]); 148 | } 149 | ic("generic", 42.5, 9.5, 0, "top", 0, [10, 15, .8], ["dimgrey"], size_z, false, [false,10,2,"default"]); 150 | ic("generic", 38, 30.5, 0, "top", 0, [7, 7, 1.5], ["dimgrey"], size_z, false, [false,10,2,"default"]); 151 | ic("generic", 4.5, 9.25, 0, "top", 0, [5.25, 5.25, .8], ["dimgrey"], size_z, false, [false,10,2,"default"]); 152 | ic("generic", 8.75, 21, 0, "top", 0, [11, 14, .8], ["dimgrey"], size_z, false, [false,10,2,"default"]); 153 | antenna("ipex", 1.315, 29.675, 0, "top", 0, [0,0,0], [0], size_z, false, [false,10,2,"default"]); 154 | } 155 | } 156 | } 157 | 158 | if(type == "jetsonnano") { 159 | 160 | size_x = 70; 161 | size_y = 45; 162 | 163 | if(enablemask == true && cmask == true) { 164 | 165 | size_x = 58; 166 | size_y = 40; 167 | 168 | if(mstyle == "open" || mstyle == "default") { 169 | 170 | xoffset = 6.5; 171 | yoffset = 4.5; 172 | zoffset = 9.5; 173 | size_xm = 60; 174 | size_ym = 42; 175 | 176 | if(side == "top" && rotation == 0) { 177 | place(loc_x, loc_y, loc_z-back, size_xm, size_ym, rotation, side, pcbsize_z) 178 | translate([xoffset-(size_xm-size_x)/2, yoffset-(size_ym-size_y)/2, zoffset-back]) cube([size_xm, size_ym, mlen]); 179 | } 180 | } 181 | if(mstyle == "fan_open" || mstyle == "fan_1" || mstyle == "fan_2" || mstyle == "fan_hex") { 182 | 183 | xoffset = 16.25; 184 | yoffset = 6; 185 | zoffset = 26.5; 186 | size_xm = 60; 187 | size_ym = 42; 188 | 189 | place(loc_x, loc_y, loc_z-back, size_xm, size_ym, rotation, side, pcbsize_z) 190 | translate([(40-fsize)/2+xoffset-(size_xm-size_x)/2, (40-fsize)/2+yoffset-(size_ym-size_y)/2, zoffset-back]) 191 | heatsink_mask(fsize, mlen, mstyle); 192 | } 193 | } 194 | if(enablemask == false) { 195 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 196 | union() { 197 | difference () { 198 | 199 | color("#151515") translate([0, 0, 7]) cube([size_x, size_y, 1.4]); 200 | color("black") translate([37, -1, 6]) cube([1, 5, 4]); 201 | color("dimgray") translate([-1, 18, 6]) cube([3, 4, 4]); 202 | color("dimgray") translate([size_x-2, 18, 6]) cube([3, 4, 4]); 203 | color("dimgray") translate([size_x-3, size_y-3, 6]) cylinder(d=3, h=3); 204 | color("dimgray") translate([3, size_y-3, 6]) cylinder(d=3, h=3); 205 | 206 | } 207 | for (i=[2:.5:36]) { 208 | color("gold") translate ([i+.5, 0, 6.8]) cube([.25, 2, .25]); 209 | color("gold") translate ([i+.5, 0, 8.4]) cube([.25, 2, .25]); 210 | } 211 | for (i=[37.5:.5:67]) { 212 | color("gold") translate ([i+.5, 0, 6.8]) cube([.25, 2, .25]); 213 | color("gold") translate ([i+.5, 0, 8.4]) cube([.25, 2, .25]); 214 | } 215 | color("dimgrey") translate([20, 13, 8.3]) cube([14, 14, 1.2]); 216 | difference() { 217 | color("black") translate([6.5, 4.5, 9.5]) cube([58, 40, 16]); 218 | color("dimgrey") translate([0, 25.375, 13.5]) rotate([90, 2.5, 90]) linear_extrude(70) { 219 | polygon(points = [[0,0], [-.5,13], [4,13], [3.5,0]]);} 220 | color("dimgrey") translate([0, 20.675, 13.5]) rotate([90, -2.5, 90]) linear_extrude(70) { 221 | polygon(points = [[0,0], [-.5,13], [4,13], [3.5,0]]);} 222 | color("dimgrey") translate([0, 30.5, 13.5]) rotate([90, 5, 90]) linear_extrude(70) { 223 | polygon(points = [[0,0], [-.5,13], [4,13], [3.5,0]]);} 224 | color("dimgrey") translate([0, 15.25, 13.5]) rotate([90, -5, 90]) linear_extrude(70) { 225 | polygon(points = [[0,0], [-.5,13], [4,13], [3.5,0]]);} 226 | color("dimgrey") translate([0, 35, 13.5]) rotate([90, 10, 90]) linear_extrude(70) { 227 | polygon(points = [[0,0], [-.5,10.5], [4,10.5], [3.5,0]]);} 228 | color("dimgrey") translate([0, 10.5, 13]) rotate([90, -10, 90]) linear_extrude(70) { 229 | polygon(points = [[0,0], [-.5,10.5], [4,10.5], [3.5,0]]);} 230 | color("dimgrey") translate([0, 36.5, 20]) cube([70, 10, 4]); 231 | color("dimgrey") translate([0, 1.5, 20]) cube([70, 10, 4]); 232 | color("dimgrey") translate([0, 39.5, 13]) rotate([90, 10, 90]) linear_extrude(70) { 233 | polygon(points = [[0,0], [0,10.5], [3,10.5], [3,0]]);} 234 | color("dimgrey") translate([0, 6.5, 12.5]) rotate([90, -10, 90]) linear_extrude(70) { 235 | polygon(points = [[0,0], [0,10.5], [3,10.5], [3,0]]);} 236 | color("dimgrey") translate([19, 9, 22]) cylinder(d=3, h=5); 237 | color("dimgrey") translate([51, 9, 22]) cylinder(d=3, h=5); 238 | color("dimgrey") translate([19, 41, 22]) cylinder(d=3, h=5); 239 | color("dimgrey") translate([51, 41, 22]) cylinder(d=3, h=5); 240 | 241 | } 242 | difference() { 243 | union() { 244 | color("silver") translate([size_x-3, size_y-3, 0]) cylinder(d=5.2, h=7, $fn=6); 245 | color("silver") translate([3, size_y-3, 0]) cylinder(d=5.2, h=7, $fn=6); 246 | } 247 | color("silver") translate([size_x-3, size_y-3, -.1]) cylinder(d=3, h=13); 248 | color("silver") translate([3, size_y-3, -.1]) cylinder(d=3, h=13); 249 | } 250 | } 251 | } 252 | } 253 | 254 | 255 | if(type == "soedge") { 256 | 257 | if(enablemask == true && cmask == true && mstyle == "default") { 258 | 259 | } 260 | if(enablemask == false) { 261 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 262 | union() { 263 | difference () { 264 | color(pcbcolor) cube([size_x,size_y,size_z]); 265 | color(pcbcolor) translate([15.75+.5, -1, -1]) rotate([0, 0, 90]) slot(1, 5, 3); 266 | color(pcbcolor) translate([0, 21, -1]) cylinder(d=3, h=3); 267 | color(pcbcolor) translate([size_x, 21, -1]) cylinder(d=3, h=3); 268 | } 269 | for (i=[0:.5:14.5]) { 270 | color("#fee5a6") translate ([i+.5, 0, -.24]) cube([.25, 2, .25]); 271 | color("#fee5a6") translate ([i+.5, 0, .99]) cube([.25, 2, .25]); 272 | } 273 | for (i=[16.75:.5:66.5]) { 274 | color("#fee5a6") translate ([i+.5, 0, -.24]) cube([.25, 2, .25]); 275 | color("#fee5a6") translate ([i+.5, 0, .99]) cube([.25, 2, .25]); 276 | } 277 | ic("generic", 28.5, 9.5, 0, "top", 0, [14.5, 14.5, .8], ["dimgrey"], size_z, false, [false,10,2,"default"]); 278 | ic("generic", 47.5, 6, 0, "top", 0, [13.5, 8.5, .8], ["dimgrey"], size_z, false, [false,10,2,"default"]); 279 | ic("generic", 47.5, 18, 0, "top", 0, [13.5, 8.5, .8], ["dimgrey"], size_z, false, [false,10,2,"default"]); 280 | ic("generic", 8.5, 14, 0, "top", 0, [7, 7, .8], ["dimgrey"], size_z, false, [false,10,2,"default"]); 281 | button("momentary_4x2x1", 22.5, 26.5, 0, "top", 0, [7, 7, .8], ["0"], size_z, false, [false,10,2,"default"]); 282 | memory("emmc_plug", 18, 26.5, 0, "bottom", 0, [7, 7, .8], ["0"], size_z, false, [false,10,2,"default"]); 283 | } 284 | } 285 | } 286 | 287 | } 288 | 289 | 290 | 291 | module cm_holder(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 292 | 293 | // jetson nano 294 | if(type == "jetsonnano") { 295 | size_x = 73; 296 | size_y = 6.5; 297 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 298 | union() { 299 | difference () { 300 | color("dimgray") cube([size_x, size_y, 9.2]); 301 | color("dimgray") translate([1.5, -1, 5.7]) cube([70, 3, 5]); 302 | color("dimgray") translate([3.5, -1, 5.7]) cube([28.5, 5.25, .92]); 303 | color("dimgray") translate([34.5, -1, 5.7]) cube([35, 5.25, .92]); 304 | } 305 | for (i=[2:.5:31]) { 306 | color("gold") translate ([i+.5, 2, 5.7]) cube([.25, 2, .25]); 307 | } 308 | for (i=[34:.5:69]) { 309 | color("gold") translate ([i+.5, 2, 5.7]) cube([.25, 2, .25]); 310 | } 311 | } 312 | } 313 | } 314 | 315 | -------------------------------------------------------------------------------- /lib/discrete.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: discrete 20 | DESCRIPTION: creates discrete components 21 | TODO: 22 | 23 | USAGE: discrete(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "ir_dual", "ir_3" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | pcbsize_z = pcb thickness 32 | enablemask = true produces mask, false produces model 33 | mask[0] = true enables component mask 34 | mask[1] = mask length 35 | mask[2] = mask setback 36 | mask[3] = mstyle "default" 37 | 38 | type = "ir_1", "ir_2" 39 | loc_x = x location placement 40 | loc_y = y location placement 41 | loc_z = z location placement 42 | side = "top", "bottom" 43 | rotation[] = object rotation 44 | size[2] = height 45 | pcbsize_z = pcb thickness 46 | enablemask = true produces mask, false produces model 47 | mask[0] = true enables component mask 48 | mask[1] = mask length 49 | mask[2] = mask setback 50 | mask[3] = mstyle "default" 51 | 52 | type = "capacitor" 53 | loc_x = x location placement 54 | loc_y = y location placement 55 | loc_z = z location placement 56 | side = "top", "bottom" 57 | rotation[] = object rotation 58 | size[0] = diameter 59 | size[2] = height 60 | pcbsize_z = pcb thickness 61 | enablemask = true produces mask, false produces model 62 | 63 | type = "led" 64 | loc_x = x location placement 65 | loc_y = y location placement 66 | loc_z = z location placement 67 | side = "top", "bottom" 68 | rotation[] = object rotation 69 | size[0] = diameter 70 | size[2] = height 71 | data[0] = style "default" 72 | data[1] = led color 73 | pcbsize_z = pcb thickness 74 | enablemask = true produces mask, false produces model 75 | 76 | */ 77 | 78 | // discrete class 79 | module discrete(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 80 | 81 | cmask = mask[0]; 82 | mlen = mask[1]; 83 | back = mask[2]; 84 | mstyle = mask[3]; 85 | pcolor = "#fee5a6"; 86 | adj = .01; 87 | $fn = 90; 88 | 89 | // type ir 90 | if(type=="ir_1") { 91 | 92 | size_x = 7; 93 | size_y = 3; 94 | size_z = size[2]; 95 | size_xm = 5; 96 | size_ym = 3.5; 97 | 98 | if(enablemask == true && cmask == true && mstyle == "default") { 99 | if(side == "top" && rotation == 0) { 100 | place(loc_x+size_x/2, loc_y+back, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 101 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 102 | } 103 | if(side == "top" && rotation == 90) { 104 | place(loc_x+back, loc_y-1.5, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 105 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 106 | } 107 | if(side == "top" && rotation == 180) { 108 | place(loc_x-1.5, loc_y-.5-back, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 109 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 110 | } 111 | if(side == "top" && rotation == 270) { 112 | place(loc_x-back, loc_y+3.5, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 113 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 114 | } 115 | if(side == "bottom" && rotation == 0) { 116 | place(loc_x-1.5, loc_y+back, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 117 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 118 | } 119 | if(side == "bottom" && rotation == 90) { 120 | place(loc_x-back, loc_y-1.5, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 121 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 122 | } 123 | if(side == "bottom" && rotation == 180) { 124 | place(loc_x+size_x/2, loc_y-.5-back, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 125 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 126 | } 127 | if(side == "bottom" && rotation == 270) { 128 | place(loc_x+back, loc_y+3.5, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 129 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 130 | } 131 | } 132 | if(enablemask == false) { 133 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 134 | union() { 135 | color("silver") translate([0, 0, size_z]) cube([size_x, size_y, 8]); 136 | color("dimgray") translate([3.5, .5, size_z+3.5]) sphere(d=5); 137 | color("silver") translate ([1, 1.25, 0]) cube([.64, .5, size_z+adj]); 138 | color("silver") translate ([3.25, 1.25, 0]) cube([.64, .5, size_z+adj]); 139 | color("silver") translate ([5.5, 1.25, 0]) cube([.64, .5, size_z+adj]); 140 | } 141 | } 142 | } 143 | 144 | if(type=="ir_2") { 145 | 146 | size_x = 5; 147 | size_y = 3; 148 | size_z = size[2]; 149 | size_xm = 5; 150 | size_ym = 3.5; 151 | 152 | if(enablemask == true && cmask == true && mstyle == "default") { 153 | if(side == "top" && rotation == 0) { 154 | place(loc_x+size_x/2, loc_y+back, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 155 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 156 | } 157 | if(side == "top" && rotation == 90) { 158 | place(loc_x+back, loc_y-2.5, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 159 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 160 | } 161 | if(side == "top" && rotation == 180) { 162 | place(loc_x-1.5, loc_y-.5-back, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 163 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 164 | } 165 | if(side == "top" && rotation == 270) { 166 | place(loc_x-back, loc_y+3.5, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 167 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 168 | } 169 | if(side == "bottom" && rotation == 0) { 170 | place(loc_x-1.5, loc_y+back, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 171 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 172 | } 173 | if(side == "bottom" && rotation == 90) { 174 | place(loc_x-back, loc_y-2.5, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 175 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 176 | } 177 | if(side == "bottom" && rotation == 180) { 178 | place(loc_x+size_x/2, loc_y-.5-back, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 179 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 180 | } 181 | if(side == "bottom" && rotation == 270) { 182 | place(loc_x+back, loc_y+3.5, loc_z+size_z+3.5, size_xm, size_ym, rotation, side, pcbsize_z) 183 | rotate([90, 0, 0]) cylinder(d = size_xm, h = mlen); 184 | } 185 | } 186 | if(enablemask == false) { 187 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 188 | union() { 189 | color("#353535") translate([0, 0, size_z]) cube([size_x, size_y, 6]); 190 | color("dimgray") translate([2.5, .5, size_z+3.5]) sphere(d=4); 191 | color("silver") translate ([.5, 1.25, 0]) cube([.64, .5, size_z+adj]); 192 | color("silver") translate ([2.25, 1.25, 0]) cube([.64, .5, size_z+adj]); 193 | color("silver") translate ([3.86, 1.25, 0]) cube([.64, .5, size_z+adj]); 194 | } 195 | } 196 | } 197 | 198 | if(type=="ir_3") { 199 | 200 | size_x = 4.75; 201 | size_y = 6; 202 | size_xm = 4; 203 | size_ym = 4; 204 | 205 | if(enablemask == true && cmask == true && mstyle == "default") { 206 | if(side == "top" && rotation == 0) { 207 | place(loc_x, loc_y+back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 208 | translate([size_x/2,0,5.25]) rotate([90, 0, 0]) cylinder(d=size_xm, h=mlen); 209 | } 210 | if(side == "top" && rotation == 90) { 211 | place(loc_x+back, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 212 | translate([1.625,0,5.25]) rotate([90, 0, 0]) cylinder(d=size_xm, h=mlen); 213 | } 214 | if(side == "top" && rotation == 180) { 215 | place(loc_x, loc_y-back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 216 | translate([1.625,0,5.25]) rotate([90, 0, 0]) cylinder(d=size_xm, h=mlen); 217 | } 218 | if(side == "top" && rotation == 270) { 219 | place(loc_x-back, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 220 | translate([size_x/2,0,5.25]) rotate([90, 0, 0]) cylinder(d=size_xm, h=mlen); 221 | } 222 | if(side == "bottom" && rotation == 0) { 223 | place(loc_x, loc_y+back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 224 | translate([1.625,0,5.25]) rotate([90, 0, 0]) cylinder(d=size_xm, h=mlen); 225 | } 226 | if(side == "bottom" && rotation == 90) { 227 | place(loc_x-back, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 228 | translate([1.625,0,5.25]) rotate([90, 0, 0]) cylinder(d=size_xm, h=mlen); 229 | } 230 | if(side == "bottom" && rotation == 180) { 231 | place(loc_x, loc_y-back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 232 | translate([size_x/2,0,5.25]) rotate([90, 0, 0]) cylinder(d=size_xm, h=mlen); 233 | } 234 | if(side == "bottom" && rotation == 270) { 235 | place(loc_x+back, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 236 | translate([size_x/2,0,5.25]) rotate([90, 0, 0]) cylinder(d=size_xm, h=mlen); 237 | } 238 | } 239 | if(enablemask == false) { 240 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 241 | union() { 242 | color("#353535") translate([0, 0, 0]) cube([size_x, size_y, 7.5]); 243 | color("gray") translate([size_x/2, -2, 5.25]) rotate([270,0,0]) cylinder(d=4, h=2); 244 | color("gray") translate([size_x/2, -2, 5.25]) sphere(d=4); 245 | } 246 | } 247 | } 248 | 249 | if(type=="ir_dual") { 250 | 251 | size_x = 6.5; 252 | size_y = 2; 253 | size_xm = 3; 254 | size_ym = 6.5; 255 | 256 | if(enablemask == true && cmask == true && mstyle == "default") { 257 | if(side == "top" && rotation == 0) { 258 | place(loc_x+size_x/2, loc_y+back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 259 | translate([-3.25,0,1.75]) rotate([90, 0, 0]) slot(size_xm, size_ym, mlen); 260 | } 261 | if(side == "top" && rotation == 90) { 262 | place(loc_x+back, loc_y-1.75, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 263 | translate([-5.25,0,1.75]) rotate([90, 0, 0]) slot(size_xm, size_ym, mlen); 264 | } 265 | if(side == "top" && rotation == 180) { 266 | place(loc_x-1.5, loc_y-back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 267 | translate([-5,4.5,1.75]) rotate([90, 0, 0]) slot(size_xm, size_ym, mlen); 268 | } 269 | if(side == "top" && rotation == 270) { 270 | place(loc_x-4.5-back, loc_y+3.25, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 271 | translate([-3.25,0,1.75]) rotate([90, 0, 0]) slot(size_xm, size_ym, mlen); 272 | } 273 | if(side == "bottom" && rotation == 0) { 274 | place(loc_x-1.75, loc_y+back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 275 | translate([-5.25,0,1.75]) rotate([90, 0, 0]) slot(size_xm, size_ym, mlen); 276 | } 277 | if(side == "bottom" && rotation == 90) { 278 | place(loc_x-4.5-back, loc_y+.25, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 279 | translate([-3.25,0,1.75]) rotate([90, 0, 0]) slot(size_xm, size_ym, mlen); 280 | } 281 | if(side == "bottom" && rotation == 180) { 282 | place(loc_x+size_x/2, loc_y-back, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 283 | translate([-3.25,4.5,1.75]) rotate([90, 0, 0]) slot(size_xm, size_ym, mlen); 284 | } 285 | if(side == "bottom" && rotation == 270) { 286 | place(loc_x+back, loc_y+3.25, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 287 | translate([-3.25,0,1.75]) rotate([90, 0, 0]) slot(size_xm, size_ym, mlen); 288 | } 289 | } 290 | if(enablemask == false) { 291 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 292 | union() { 293 | color("silver") translate([0, 0, 0]) cube([size_x, size_y, 3.25]); 294 | color("dimgray") translate([1.5, .5, 1.75]) sphere(d=3); 295 | color("dimgray") translate([5, .5, 1.75]) sphere(d=3); 296 | } 297 | } 298 | } 299 | 300 | // can capacitor 301 | if(type=="capacitor" && enablemask == false) { 302 | 303 | size_x = size[0]; 304 | size_y = size[0]; 305 | height = size[2]; 306 | 307 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 308 | union() { 309 | color("dimgray") cylinder(d=size_x+.5, h=.5); 310 | color("silver") translate([0, 0, .5]) cylinder(d=size_x+.5, h=.5); 311 | color("silver") translate([0, 0, 1]) cylinder(d=size_x, h=height-1); 312 | color(pcolor) translate([-size_x/3, -.32, -3.2]) cube([.64, .64, 3.3]); 313 | color(pcolor) translate([(size_x/2)-(size_x/4), -.32, -3.2]) cube([.64, .64, 3.3]); 314 | } 315 | } 316 | // led 317 | if(type=="led" && enablemask == false) { 318 | 319 | size_x = size[0]; 320 | size_y = size[0]; 321 | height = size[2]; 322 | style = data[0]; 323 | lcolor = data[1]; 324 | 325 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 326 | union() { 327 | color(lcolor, .6) cylinder(d=size_x+1, h=.5); 328 | color(lcolor, .6) translate([0, 0, .4]) cylinder(d=size_x, h=height-size_x/2-.6); 329 | color(lcolor, .6) translate([0, 0, height-size_x/2]) sphere(d=size_x); 330 | color(pcolor) translate([-size_x/3, -.32, -3.2]) cube([.64,.64,3.3]); 331 | color(pcolor) translate([(size_x/2)-(size_x/4), -.32, -3.2]) cube([.64, .64, 3.3]); 332 | } 333 | } 334 | } 335 | -------------------------------------------------------------------------------- /lib/display.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: display 20 | DESCRIPTION: creates flat panel displays 21 | TODO: 22 | 23 | USAGE: display(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "lcd_2.2", "mipi_csi", "mipi_dsi" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | pcbsize_z = pcb thickness 32 | enablemask = true produces mask, false produces model 33 | mask[0] = component mask true, false 34 | mask[1] = mask length 35 | mask[2] = mask setback 36 | mask[3] = mstyle "default" 37 | 38 | */ 39 | 40 | // display class 41 | module display(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 42 | 43 | cmask = mask[0]; 44 | mlen = mask[1]; 45 | back = mask[2]; 46 | mstyle = mask[3]; 47 | 48 | // type lcd_2.2 49 | if(type == "lcd_2.2") { 50 | 51 | size_x = 56; 52 | size_y = 38; 53 | size_xm = 45; 54 | size_ym = 34; 55 | 56 | if(enablemask == true && cmask == true && mstyle == "default") { 57 | if(side == "top" && rotation == 0) { 58 | place(loc_x+4, loc_y+1, loc_z+4, size_xm, size_ym, rotation, side, pcbsize_z) 59 | cube([size_xm, size_ym, mlen]); 60 | } 61 | if(side == "bottom" && rotation == 0) { 62 | place(loc_x+7, loc_y+1, loc_z+4, size_xm, size_ym, rotation, side, pcbsize_z) 63 | cube([size_xm, size_ym, mlen]); 64 | } 65 | } 66 | if(enablemask == false) { 67 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 68 | union() { 69 | difference() { 70 | union() { 71 | color("white") cube([size_x, size_y, 1.5]); 72 | color("grey") translate([1, 1, 1.5]) cube([size_x-2, size_y-2, 1.85]); 73 | } 74 | color("black") translate([54.5, 4, -.01]) cube([2, 30, 4]); 75 | } 76 | color("dimgrey") translate([4.25, .9, 3.35]) cube([45, 34, .25]); 77 | } 78 | } 79 | } 80 | // mipi csi port 81 | if(type=="mipi_csi" && enablemask == false) { 82 | size_x = 21; 83 | size_y = 3; 84 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 85 | union() { 86 | difference() { 87 | color("white") cube([size_x, size_y, 5]); 88 | color("white") translate([-1, -1, 3.5]) cube([23, 3.5, 5]); 89 | color("white") translate([-1, -1, 3.5]) cube([3, 5, 5]); 90 | color("white") translate([19, -1, 3.5]) cube([3, 5, 5]); 91 | } 92 | difference() { 93 | color("black") translate([-1, 0, 3.5]) cube([23, 3.5, 1]); 94 | color("dimgrey") translate([2, 2.9, 3.49]) cube([17, 3, 2]); 95 | } 96 | } 97 | } 98 | // mipi csi port 99 | if(type=="mipi_csi_90" && enablemask == false) { 100 | size_x = 21; 101 | size_y = 3; 102 | place(loc_x, loc_y-3, loc_z, size_x, size_y, rotation, side, pcbsize_z) 103 | rotate([90, 0, 0]) 104 | union() { 105 | difference() { 106 | color("white") cube([size_x, size_y, 5]); 107 | color("white") translate([-1, -1, 3.5]) cube([23, 3.5, 5]); 108 | color("white") translate([-1, -1, 3.5]) cube([3, 5, 5]); 109 | color("white") translate([19, -1, 3.5]) cube([3, 5, 5]); 110 | } 111 | difference() { 112 | color("black") translate([-1, 0, 3.5]) cube([23, 3.5 ,1]); 113 | color("dimgrey") translate([2, 2.9, 3.49]) cube([17, 3, 2]); 114 | } 115 | } 116 | } 117 | // mipi dsi port 118 | if(type=="mipi_dsi" && enablemask == false) { 119 | size_x = 10; 120 | size_y = 3; 121 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 122 | union() { 123 | color("black") cube([size_x, 1.5, 2]); 124 | color("saddlebrown") translate([0, 1.5, 0]) cube([size_x, 1.5, 2]); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /lib/fan.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: fan 20 | DESCRIPTION: creates fan support components 21 | TODO: 22 | 23 | USAGE: fan(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "fan_micro", "encl_pmw", "encl_pmw_h" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | pcbsize_z = pcb thickness 32 | enablemask = true produces mask, false produces model 33 | mask[0] = component mask true, false 34 | mask[1] = mask length 35 | mask[2] = mask setback 36 | mask[3] = mstyle "default" 37 | 38 | */ 39 | 40 | // fan class 41 | module fan(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 42 | 43 | // micro connector type 44 | if(type=="fan_micro" && enablemask == false) { 45 | size_x = 7.5; 46 | size_y = 3.75; 47 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 48 | union() { 49 | difference () { 50 | color("white") cube([size_x, size_y, 4.75]); 51 | color("darkgray") translate([1.5, .5, 1]) cube([4.5, 2.75, 6]); 52 | color("white") translate([-.5, .75, -.5]) cube([1, 2.5, 6]); 53 | color("white") translate([7, .75, -.5]) cube([1, 2.5, 6]); 54 | color("darkgray") translate([2.25, -.5, 1]) cube([3, 2, 6]); 55 | } 56 | color("silver") translate ([2.75, 2, .5]) cube([.6, .6, 4]); 57 | color("silver") translate ([4.5, 2, .5]) cube([.6, .6, 4]); 58 | } 59 | } 60 | 61 | // pmw-standard connector type 62 | if(type=="encl_pmw" && enablemask == false) { 63 | size_x = 11.6; 64 | size_y = 4.3; 65 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 66 | union() { 67 | difference () { 68 | color("white") cube([size_x, size_y, 7]); 69 | color("darkgray") translate([.5, .5, 1]) cube([10.5, 3, 8]); 70 | //color("white") translate([-.5, .75, -.5]) cube([1, 2.5, 6]); 71 | //color("white") translate([11, .75, -.5]) cube([1, 2.5, 6]); 72 | color("darkgray") translate([2.25, -.5, 1]) cube([7.5, 2, 8]); 73 | } 74 | for (i=[2:2.54:11.7]) { 75 | color("silver") translate ([i, 2.54, 2]) cylinder(d=.67, h=5, $fn=30); 76 | } 77 | } 78 | } 79 | 80 | // pmw-standard connector type horizontal and 45 degrees 81 | if(type=="encl_pmw_h" && enablemask == false) { 82 | size_x = 11.6; 83 | size_y = 4.3; 84 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 85 | translate([11.6, 0, 5]) rotate([-90, 0, -45]) 86 | union() { 87 | difference () { 88 | color("white") cube([size_x, size_y, 4]); 89 | color("darkgray") translate([.5, .5, 1]) cube([10.5, 3, 8]); 90 | //color("white") translate([-.5, .75, -.5]) cube([1, 2.5, 6]); 91 | //color("white") translate([11, .75, -.5]) cube([1, 2.5, 6]); 92 | color("darkgray") translate([2.25, -.5, 1]) cube([7.5, 2, 8]); 93 | } 94 | for (i=[2:2.54:11.7]) { 95 | color("silver") translate ([i, 2.54, 2]) cylinder(d=.67, h=2, $fn=30); 96 | } 97 | } 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /lib/fillets.scad: -------------------------------------------------------------------------------- 1 | // Stephanie Shaltes 2 | // https://github.com/StephS/i2_xends/blob/master/inc/fillets.scad 3 | // 4 | // 20200329 Additional maintenance and debug by hominoid @ www.forum.odroid.com 5 | 6 | function poly_sides_r(r) = (max(round(4 * r),3)+1); 7 | 8 | // 2d primitive for outside fillets. 9 | module fillet_2d_o(fillet_r, fillet_angle=90, fillet_fn=0) { 10 | add=0.01; 11 | f_fn=(fillet_fn>0) ? fillet_fn*4 : (ceil(poly_sides_r(fillet_r)/4)*4); 12 | if (fillet_r>0) { 13 | intersection() { 14 | circle(r=fillet_r, $fn=f_fn); 15 | polygon([ 16 | [0-add, 0-add], 17 | [0-add, fillet_r], 18 | [fillet_r * tan(fillet_angle/2), fillet_r], 19 | [fillet_r * sin(fillet_angle), fillet_r * cos(fillet_angle)-add] 20 | ]); 21 | } 22 | } 23 | } 24 | 25 | // 2d primitive for inside fillets. 26 | module fillet_2d_i(fillet_r, fillet_angle=90, fillet_fn=0) { 27 | add=0.01; 28 | f_fn=(fillet_fn>0) ? fillet_fn*4 : (ceil(poly_sides_r(fillet_r)/4)*4); 29 | if (fillet_r>0) { 30 | translate([fillet_r * tan(fillet_angle/2), fillet_r, 0]) 31 | difference() { 32 | polygon([ 33 | [0, 0], 34 | [0, -fillet_r-add], 35 | [-fillet_r * tan(fillet_angle/2)-add, -fillet_r-add], 36 | [-fillet_r * sin(fillet_angle)-add, -fillet_r * cos(fillet_angle)] 37 | ]); 38 | circle(r=fillet_r, $fn=f_fn); 39 | } 40 | } 41 | } 42 | 43 | // 3d rotated outside fillet. 44 | module fillet_polar_o(inner_r, fillet_r, fillet_angle=90, fillet_fn=0, rotate_fn=0) { 45 | if (fillet_r>0) { 46 | rotate_extrude(convexity=8, $fn=rotate_fn) { 47 | translate([inner_r, 0, 0]) { 48 | fillet_2d_o(fillet_r, fillet_angle, fillet_fn); 49 | } 50 | } 51 | } 52 | } 53 | 54 | // 3d rotated inside fillet. 55 | module fillet_polar_i(inner_r, fillet_r, fillet_angle=90, fillet_fn=0, rotate_fn=0) { 56 | if (fillet_r>0) { 57 | rotate_extrude(convexity=8, $fn=rotate_fn) { 58 | translate([inner_r, 0, 0]) { 59 | fillet_2d_i(fillet_r, fillet_angle, fillet_fn); } 60 | } 61 | } 62 | } 63 | 64 | // 3d rotated inside fillet negative. 65 | module fillet_polar_i_n(outer_r, fillet_r, fillet_angle=90, fillet_fn=0, rotate_fn=0) { 66 | if (fillet_r>0) { 67 | rotate_extrude(convexity=8, $fn=rotate_fn) { 68 | translate([outer_r, 0, 0]) { 69 | rotate(90) fillet_2d_i(fillet_r, fillet_angle, fillet_fn); } 70 | } 71 | } 72 | } 73 | 74 | // 3d linear outside fillet. 75 | module fillet_linear_o(l, fillet_r, fillet_angle=90, fillet_fn=0, add=0.02) { 76 | if (fillet_r>0) { 77 | translate([0,0,-add/2]) 78 | linear_extrude(height=l+add, center=false) { 79 | fillet_2d_o(fillet_r, fillet_angle, fillet_fn); 80 | } 81 | } 82 | } 83 | 84 | // 3d linear inside fillet. 85 | module fillet_linear_i(l, fillet_r, fillet_angle=90, fillet_fn=0, add=0.02) { 86 | if (fillet_r>0) { 87 | translate([0,0,-add/2]) 88 | linear_extrude(height=l+add, center=false) { 89 | fillet_2d_i(fillet_r, fillet_angle, fillet_fn); 90 | } 91 | } 92 | } 93 | 94 | module cube_negative_fillet(size, radius=-1, vertical=[3,3,3,3], top=[0,0,0,0], bottom=[0,0,0,0], $fn=90, vertical_fn=[0,0,0,0], top_fn=[0,0,0,0], bottom_fn=[0,0,0,0]){ 95 | 96 | vertical_fn= ($fn>0) ? [$fn,$fn,$fn,$fn] : vertical_fn; 97 | top_fn= ($fn>0) ? [$fn,$fn,$fn,$fn] : top_fn; 98 | bottom_fn= ($fn>0) ? [$fn,$fn,$fn,$fn] : bottom_fn; 99 | 100 | 101 | j=[1,0,1,0]; 102 | 103 | for (i=[0:3]) { 104 | if (radius > -1) { 105 | rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) translate([0, 0, -size[2]/2]) rotate([0,0,180]) fillet_linear_i(l=size[2], fillet_r=radius, fillet_angle=90, fillet_fn=$fn); //fillet(radius, size[2], $fn=$fn); 106 | } else { 107 | rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) translate([0, 0, -size[2]/2]) rotate([0,0,180]) fillet_linear_i(l=size[2], fillet_r=vertical[i], fillet_angle=90, fillet_fn=vertical_fn[i]); //fillet(vertical[i], size[2], $fn=$fn); 108 | } 109 | rotate([90*i, -90, 0]) translate([size[2]/2, size[j[i]]/2, 0 ]) translate([0, 0, -size[1-j[(i)]]/2]) rotate([0,0,180]) fillet_linear_i(l=size[1-j[(i)]], fillet_r=top[(i)], fillet_angle=90, fillet_fn=top_fn[i]); // fillet(top[i], size[1-j[i]], $fn=$fn); 110 | rotate([90*(4-i), 90, 0]) translate([size[2]/2, size[j[i]]/2, 0]) translate([0, 0, -size[1-j[(i)]]/2]) rotate([0,0,180]) fillet_linear_i(l=size[1-j[(i)]], fillet_r=bottom[(i)], fillet_angle=90, fillet_fn=bottom_fn[i]); //fillet(bottom[i], size[1-j[i]], $fn=$fn); 111 | 112 | } 113 | } 114 | 115 | module cube_positive_fillet(size, radius=-1, vertical=[0,0,0,0], top=[0,0,0,0], bottom=[0,0,0,0], vertical_angle=[90,90,90,90], top_angle=[90,90,90,90], bottom_angle=[90,90,90,90], vertical_flip=[0,0,0,0], top_flip=[0,0,0,0], bottom_flip=[0,0,0,0], $fn=0){ 116 | 117 | j=[1,0,1,0]; 118 | 119 | for (i=[0:3]) { 120 | if (radius > -1) { 121 | rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) translate([0, 0, -size[2]/2]) rotate([0,0,90]) fillet_linear_i(l=size[2], fillet_r=radius, fillet_angle=90, fillet_fn=$fn); //fillet(radius, size[2], $fn=$fn); 122 | } else { 123 | rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) translate([0, 0, -size[2]/2]) rotate([0,0,180-vertical_angle[i]+(90+vertical_angle[i])*vertical_flip[i]]) fillet_linear_i(l=size[2], fillet_r=vertical[i], fillet_angle=vertical_angle[i], fillet_fn=$fn); //fillet(vertical[i], size[2], $fn=$fn); 124 | } 125 | rotate([90*i, -90, 0]) translate([size[2]/2, size[j[i]]/2, 0 ]) translate([0, 0, -size[1-j[(i)]]/2]) rotate([0,0,(180-top_angle[i])+(90+top_angle[i])*top_flip[i]]) fillet_linear_i(l=size[1-j[(i)]], fillet_r=top[(i)], fillet_angle=180-top_angle[i], fillet_fn=$fn); // fillet(top[i], size[1-j[i]], $fn=$fn); 126 | rotate([90*(4-i), 90, 0]) translate([size[2]/2, size[j[i]]/2, 0]) translate([0, 0, -size[1-j[(i)]]/2]) rotate([0,0,180-bottom_angle[i]+(90+bottom_angle[i])*bottom_flip[i]]) fillet_linear_i(l=size[1-j[(i)]], fillet_r=bottom[(i)], fillet_angle=bottom_angle[i], fillet_fn=$fn); //fillet(bottom[i], size[1-j[i]], $fn=$fn); 127 | 128 | } 129 | } 130 | 131 | module cube_positive_fillet_corners(size, radius=-1, vertical=[0,0,0,0], top=[0,0,0,0], bottom=[0,0,0,0], vertical_angle=[90,90,90,90], top_angle=[90,90,90,90], bottom_angle=[90,90,90,90], vertical_flip=[0,0,0,0], top_flip=[0,0,0,0], bottom_flip=[0,0,0,0], $fn=90){ 132 | 133 | j=[1,0,1,0]; 134 | 135 | //bottom 136 | for (i=[0:3]) { 137 | render(convexity=4) intersection() { 138 | /* 139 | if (radius > -1) { 140 | rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) translate([0, 0, -size[2]/2-radius]) rotate([0,0,90]) fillet_linear_i(l=size[2]+radius*2, r=radius, fillet_angle=90, fillet_fn=$fn); //fillet(radius, size[2], $fn=$fn); 141 | } else { 142 | rotate([0, 0, 90*i]) translate([size[1-j[i]]/2, size[j[i]]/2, 0]) translate([0, 0, -size[2]/2-vertical[i]]) rotate([0,0,180-vertical_angle[i]+(90+vertical_angle[i])*vertical_flip[i]]) fillet_linear_i(l=size[2]+vertical[i]*2, r=vertical[i], fillet_angle=vertical_angle[i], fillet_fn=$fn); //fillet(vertical[i], size[2], $fn=$fn); 143 | } 144 | */ 145 | rotate([90*(4-i), 90, 0]) translate([size[2]/2, size[j[i]]/2, 0]) translate([0, 0, -size[1-j[(i)]]/2-bottom[(i)]]) rotate([0,0,180-bottom_angle[i]+(90+bottom_angle[i])*bottom_flip[i]]) fillet_linear_i(l=size[1-j[(i)]]+bottom[(i)]*4, fillet_r=bottom[(i)], fillet_angle=bottom_angle[i], fillet_fn=$fn); //fillet(bottom[i], size[1-j[i]], $fn=$fn); 146 | rotate([90*(4-((i+1)%4)), 90, 0]) translate([size[2]/2, size[j[((i+1)%4)]]/2, 0]) translate([0, 0, -size[1-j[((i+1)%4)]]/2-bottom[((i+1)%4)]]) rotate([0,0,180-bottom_angle[((i+1)%4)]+(90+bottom_angle[((i+1)%4)])*bottom_flip[((i+1)%4)]]) fillet_linear_i(l=size[1-j[(((i+1)%4))]]+bottom[(((i+1)%4))]*4, fillet_r=bottom[(((i+1)%4))], fillet_angle=bottom_angle[((i+1)%4)], fillet_fn=$fn); //fillet(bottom[i], size[1-j[i]], $fn=$fn); 147 | } 148 | } 149 | 150 | // top 151 | for (i=[0:3]) { 152 | render(convexity=4) intersection() { 153 | rotate([90*i, -90, 0]) translate([size[2]/2, size[j[i]]/2, 0 ]) translate([0, 0, -size[1-j[(i)]]/2-top[(i)]]) rotate([0,0,(180-top_angle[i])+(90+top_angle[i])*top_flip[i]]) fillet_linear_i(l=size[1-j[(i)]]+top[(i)]*4, fillet_r=top[(i)], fillet_angle=180-top_angle[i], fillet_fn=$fn); // fillet(top[i], size[1-j[i]], $fn=$fn); 154 | rotate([90*((i+1)%4), -90, 0]) translate([size[2]/2, size[j[((i+1)%4)]]/2, 0 ]) translate([0, 0, -size[1-j[(((i+1)%4))]]/2-top[(((i+1)%4))]]) rotate([0,0,(180-top_angle[((i+1)%4)])+(90+top_angle[((i+1)%4)])*top_flip[((i+1)%4)]]) fillet_linear_i(l=size[1-j[(((i+1)%4))]]+top[(((i+1)%4))]*4, fillet_r=top[(((i+1)%4))], fillet_angle=180-top_angle[((i+1)%4)], fillet_fn=$fn); // fillet(top[i], size[1-j[i]], $fn=$fn); 155 | } 156 | } 157 | } 158 | 159 | module cube_fillet_inside(size, radius=-1, vertical=[0,0,0,0], top=[0,0,0,0], bottom=[0,0,0,0], $fn=90, vertical_fn=[0,0,0,0], top_fn=[0,0,0,0], bottom_fn=[0,0,0,0]){ 160 | //makes CENTERED cube with round corners 161 | // if you give it radius, it will fillet vertical corners. 162 | //othervise use vertical, top, bottom arrays 163 | //when viewed from top, it starts in upper right corner (+x,+y quadrant) , goes counterclockwise 164 | //top/bottom fillet starts in direction of Y axis and goes CCW too 165 | 166 | if (radius == 0) { 167 | cube(size, center=true); 168 | } else { 169 | difference() { 170 | cube(size, center=true); 171 | cube_negative_fillet(size, radius, vertical, top, bottom, $fn, vertical_fn, top_fn, bottom_fn); 172 | } 173 | } 174 | } 175 | 176 | module cylinder_fillet_inside(h=10, r=10, top=3, bottom=3, $fn=0, fillet_fn=0, center=false) { 177 | c_fn=($fn>0) ? $fn : poly_sides_r(r); 178 | rotfix=(($fn>0) ? 0 : 180/c_fn); 179 | cent=(center) ? -h/2 : 0; 180 | // echo (c_fn); 181 | translate([0,0,cent]) 182 | difference() { 183 | cylinder(h=h,r=r,$fn=c_fn); 184 | rotate ([0,0,rotfix]) { 185 | fillet_polar_i_n(outer_r=r, fillet_r=bottom, 186 | fillet_angle=90, fillet_fn=fillet_fn, rotate_fn=c_fn); 187 | translate([0,0,h]) mirror ([0,0,1]) 188 | fillet_polar_i_n(outer_r=r, fillet_r=top, 189 | fillet_angle=90, fillet_fn=fillet_fn, rotate_fn=c_fn); 190 | } 191 | } 192 | } 193 | 194 | module cylinder_fillet_outside(h=10, r=10, top=3, bottom=3, $fn=0, fillet_fn=0, center=false) { 195 | c_fn=($fn>0) ? $fn : poly_sides_r(r); 196 | rotfix=(($fn>0) ? 0 : 180/c_fn); 197 | cent=(center) ? -h/2 : 0; 198 | // echo (c_fn); 199 | translate([0,0,cent]) { 200 | cylinder(h=h,r=r,$fn=c_fn); 201 | rotate ([0,0,rotfix]) { 202 | fillet_polar_i(inner_r=r, fillet_r=bottom, fillet_angle=90, 203 | fillet_fn=fillet_fn, rotate_fn=c_fn); 204 | translate([0,0,h]) mirror ([0,0,1]) 205 | fillet_polar_i(inner_r=r, fillet_r=top, fillet_angle=90, 206 | fillet_fn=fillet_fn, rotate_fn=c_fn); 207 | } 208 | } 209 | } 210 | 211 | 212 | //cube([20,20,20], center=true); 213 | //cube_positive_fillet_corners([20,20,20], radius=-1, vertical=[0,0,0,0], top=[3,3,3,3], bottom=[3,3,3,3], top_angle=[90,90,90,90], top_flip=[0,0,0,0], $fn=10); 214 | //cube_positive_fillet([20,20,20], radius=-1, vertical=[0,0,0,0], top=[3,3,3,3], bottom=[3,3,3,3], top_angle=[90,90,90,90], top_flip=[0,0,0,0], $fn=10); 215 | 216 | //translate([-12,23,0]) cube_fillet_inside([20,20,20], vertical=[0,0,0,0], top=[3,3,3,3], bottom=[3,3,3,3], $fn=10); 217 | 218 | //translate([23,-12,0]) cylinder_fillet_inside(h=20, r=10, top=3, bottom=3, $fn=0, fillet_fn=10, center=true); 219 | 220 | //translate([0,0,23]) cylinder_fillet_outside(h=20, r=10, top=3, bottom=3, $fn=0, fillet_fn=10, center=true); 221 | 222 | -------------------------------------------------------------------------------- /lib/fpc.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: fpc 20 | DESCRIPTION: creates fpc connectors 21 | TODO: add other styles 22 | 23 | USAGE: fpc(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "fh19" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | size[0] = #pins 32 | data[0] = "smt" 33 | data[1] = "side" 34 | data[2] = body color 35 | data[3] = tab color 36 | pcbsize_z = pcb thickness 37 | enablemask = true produces mask, false produces model 38 | mask[0] = true enables component mask 39 | mask[1] = mask length 40 | mask[2] = mask setback 41 | mask[3] = mstyle "default" 42 | 43 | type = "fh12" 44 | loc_x = x location placement 45 | loc_y = y location placement 46 | loc_z = z location placement 47 | side = "top", "bottom" 48 | rotation[] = object rotation 49 | size[0] = #pins 50 | data[0] = "smt" 51 | data[1] = "top" 52 | data[2] = body color 53 | data[3] = tab color 54 | pcbsize_z = pcb thickness 55 | enablemask = true produces mask, false produces model 56 | mask[0] = true enables component mask 57 | mask[1] = mask length 58 | mask[2] = mask setback 59 | mask[3] = mstyle "default" 60 | 61 | */ 62 | 63 | // fpc connector class 64 | module fpc(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 65 | 66 | row = size[0]; 67 | style = data[0]; 68 | entry = data[1]; 69 | bcolor = data[2]; 70 | tcolor = data[3]; 71 | pcolor = "#fee5a6"; 72 | cmask = mask[0]; 73 | mlen = mask[1]; 74 | back = mask[2]; 75 | mstyle = mask[3]; 76 | 77 | /* 78 | p p 79 | i i 80 | n n 81 | 82 | b t 83 | w o o 84 | b a p p t p p 85 | o l i i i 86 | d s s l n n h h n 87 | p y i i e e 88 | t i z z s x y i i s 89 | y t a e e i a a g g i 90 | p c d z d d h h z 91 | e h j y z e j j t t e 92 | */ 93 | fpc_data = [ 94 | ["fh19", .5, 2, 2.5, .9, .25, 1.25, 2.4, 3.4, 1, .15], 95 | ["fh12", .5, 1.9, 3.5, 3.6, .25, 1.9, 2.4, 3.4, 1, .15] 96 | ]; 97 | 98 | adj = .01; 99 | $fn = 90; 100 | 101 | s = search([type],fpc_data); 102 | 103 | pitch = fpc_data[s[0]][1]; 104 | body_adj = fpc_data[s[0]][2]; 105 | size_x = body_adj+(row*pitch); 106 | size_y = fpc_data[s[0]][3]; 107 | size_z = fpc_data[s[0]][4]; 108 | wall_size = fpc_data[s[0]][5]; 109 | pin_xadj = fpc_data[s[0]][6]; 110 | pin_yadj = fpc_data[s[0]][7]; 111 | pbheight = fpc_data[s[0]][8]; 112 | ptheight = fpc_data[s[0]][9]; 113 | pinsize = fpc_data[s[0]][10]; 114 | smtlead = [pinsize,.5,.15]; 115 | size_xm = size_x; 116 | size_ym = size_y; 117 | size_zm = 2; 118 | 119 | if(entry == "top" && enablemask == false) { 120 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 121 | union() { 122 | difference() { 123 | color(bcolor) cube([size_x, size_y, size_z]); 124 | translate([-2,-1,size_z-.5]) color(bcolor) cube([3, size_y+2, 3]); 125 | translate([size_x-1,-1,size_z-.5]) color(bcolor) cube([3, size_y+2, 3]); 126 | translate([-2,-1,size_z-.5]) color(bcolor) cube([size_x+2, size_y, 3]); 127 | translate([-.5,-5.25,-adj]) color(bcolor) cylinder(d=12, h=4); 128 | translate([size_x+.5,-5.25,-adj]) color(bcolor) cylinder(d=12, h=4); 129 | } 130 | difference() { 131 | translate([-.5,-.25,size_z-.5-adj]) color(tcolor) cube([size_x+1, size_y+.5, .45+adj]); 132 | translate([.5,size_y-.1,size_z-2]) color(tcolor) cube([size_x-1, size_y, 3]); 133 | translate([-.5,-5.5,-adj]) color(tcolor) cylinder(d=12, h=4); 134 | translate([size_x+.5,-5.5,-adj]) color(tcolor) cylinder(d=12, h=4); 135 | } 136 | if(style == "thruhole") { 137 | for(r=[pin_xadj-(pinsize/2):pitch:size_x-pitch]) { 138 | color(pcolor) translate([r, pin_yadj-(pinsize/2), -pbheight+adj]) 139 | cube([pinsize, pinsize, pbheight+ptheight]); 140 | } 141 | } 142 | if(style == "smt") { 143 | for(r=[body_adj/2+pinsize:pitch:size_x-(body_adj/2)-pinsize]) { 144 | color(pcolor) translate([r, size_y-adj, 0]) 145 | cube(smtlead); 146 | } 147 | } 148 | } 149 | } 150 | if(entry == "side" && enablemask == true && cmask == true && mstyle == "default") { 151 | if(side == "top" && rotation == 0) { 152 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 153 | translate([0, back, size_zm/3]) rotate([90, 0, 0]) slot(size_zm, size_x, mlen); 154 | } 155 | if(side == "top" && rotation == 90) { 156 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 157 | translate([0, back, size_zm/3]) rotate([90, 0, 0]) slot(size_zm, size_x, mlen); 158 | } 159 | if(side == "top" && rotation == 180) { 160 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 161 | translate([0, 1+back, size_zm/3]) rotate([90, 0, 0]) slot(size_zm, size_x, mlen); 162 | } 163 | if(side == "top" && rotation == 270) { 164 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 165 | translate([0, .5+back, size_zm/3]) rotate([90, 0, 0]) slot(size_zm, size_x, mlen); 166 | } 167 | if(side == "bottom" && rotation == 0) { 168 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 169 | translate([0, back, size_zm/3]) rotate([90, 0, 0]) slot(size_zm, size_x, mlen); 170 | } 171 | if(side == "bottom" && rotation == 90) { 172 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 173 | translate([0, .5+back, size_zm/3]) rotate([90, 0, 0]) slot(size_zm, size_x, mlen); 174 | } 175 | if(side == "bottom" && rotation == 180) { 176 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 177 | translate([0, 1+back, size_zm/3]) rotate([90, 0, 0]) slot(size_zm, size_x, mlen); 178 | } 179 | if(side == "bottom" && rotation == 270) { 180 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 181 | translate([0, back, size_zm/3]) rotate([90, 0, 0]) slot(size_zm, size_x, mlen); 182 | } 183 | } 184 | if(entry == "side" && enablemask == true && cmask == true && mstyle == "block") { 185 | if(side == "top" && rotation == 270) { 186 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 187 | translate([0, -1.5+back, size_zm-5.5]) rotate([90, 0, 0]) cube([size_x, size_zm+3.5, mlen]); 188 | } 189 | } 190 | if(entry == "side" && enablemask == false) { 191 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 192 | union() { 193 | difference() { 194 | color(bcolor) cube([size_x, size_y, size_z]); 195 | color("#353535") translate([body_adj/2, -wall_size, .31]) 196 | cube([size_x-body_adj, size_y, size_z]); 197 | } 198 | if(type == "fh19") { 199 | difference() { 200 | color(tcolor) translate([.125+body_adj/2, -.5,.5]) cube([size_x-body_adj-.25, 2.625, .25]); 201 | color(tcolor) translate([.115+body_adj/2, -.55,0]) cube([(size_x-body_adj-.25)/3, .25, 3]); 202 | color(tcolor) translate([(.135+body_adj/2)+(size_x-body_adj-.25)/1.5, -.55,0]) 203 | cube([(size_x-body_adj-.25)/3, .25, 3]); 204 | } 205 | } 206 | if(style == "smt") { 207 | for(r=[pin_xadj-(pinsize/2):pitch:size_x-body_adj/2]) { 208 | color(pcolor) translate([r, -adj, .21]) 209 | cube([pinsize, ptheight, pinsize]); 210 | color(pcolor) translate([r, size_y-adj, 0]) 211 | cube(smtlead); 212 | } 213 | } 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /lib/header.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: header 20 | DESCRIPTION: creates pin headers in any size or pitch. 21 | TODO: "angled-boxed" and male pitchs besides 2.54. 22 | 23 | USAGE: header(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "open","boxed","angled" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | size[0] = #row 32 | size[1] = #columns 33 | size[2] = pin height 34 | data[0] = style ("thruhole", "smt") 35 | data[1] = header color 36 | data[2] = "male", "female" 37 | data[3] = pitch 38 | data[4] = pin color 39 | pcbsize_z = pcb thickness 40 | enablemask = true produces mask, false produces model 41 | mask[0] = true, false 42 | mask[1] = length 43 | mask[2] = set back 44 | mask[3] = mstyle "default" 45 | 46 | */ 47 | 48 | // header class 49 | module header(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 50 | 51 | row = size[0]; 52 | column = size[1]; 53 | height = size[2]; 54 | style = data[0]; 55 | hcolor = data[1]; 56 | gender = data[2]; 57 | pitch = data[3]; 58 | pcolor = data[4]; 59 | 60 | size_y = pitch == 2.54 && style == "smt" ? (2.5 * column) : (pitch * column); 61 | size_x = pitch == 2.54 && style == "smt" ? (2.54 * row) : (pitch * row); 62 | bheight = pitch == 2.54 ? 2.5 : 1; 63 | pheight = pitch == 2.54 ? 3.2 : 2; 64 | pinsize = pitch == 2.54 ? .64 : .3; 65 | theight = bheight + pheight + height; 66 | smtlead = [pinsize, .925, .32]; 67 | wall = .1; 68 | walloffset = pitch+wall; 69 | 70 | adj = .01; 71 | $fn = 90; 72 | 73 | // thruhole headers 74 | if(style == "thruhole" && enablemask == false) { 75 | 76 | if((type == "open" || type == "boxed") && gender == "male") { 77 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 78 | union() { 79 | color(hcolor) cube([size_x, size_y, bheight]); 80 | for(c=[pitch/2:pitch:size_x]) { 81 | for(r=[pitch/2:pitch:size_y]) { 82 | color(pcolor) translate([c-(pinsize/2), r-(pinsize/2), -pheight]) cube([pinsize, pinsize, theight+adj]); 83 | } 84 | } 85 | } 86 | if(type == "boxed") { 87 | difference() { 88 | color(hcolor) translate([-walloffset,-wall,0]) cube([size_x+2*2.56, size_y+2*wall, height+bheight]); 89 | color(hcolor) translate([-walloffset+wall,0,wall]) cube([size_x+2*walloffset-4*wall, size_y, height+bheight+adj]); 90 | } 91 | } 92 | } 93 | if(type == "open" && gender == "female") { 94 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 95 | union() { 96 | difference() { 97 | color(hcolor) cube([size_x, size_y, height]); 98 | for(c=[pitch/2:pitch:size_x]) { 99 | for(r=[pitch/2:pitch:size_y]) { 100 | color("#888888") translate([c-(pinsize/2), r-(pinsize/2), height-5+adj]) cube([pinsize, pinsize, height-1]); 101 | color("#888888") translate([c-(pinsize/2),r-(pinsize/2),-pheight]) cube([pinsize, pinsize, pheight+adj]); 102 | } 103 | } 104 | } 105 | for(c=[pitch/2:pitch:size_x]) { 106 | for(r=[pitch/2:pitch:size_y]) { 107 | color(pcolor) translate([c-(pinsize/2), r-(pinsize/2), -pheight]) cube([pinsize, pinsize, pheight+adj]); 108 | } 109 | } 110 | } 111 | } 112 | if(type == "angled" && gender == "male") { 113 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 114 | union() { 115 | color(hcolor) cube([size_x, bheight, size_y]); 116 | for(c=[pitch/2:pitch:size_x]) { 117 | for(r=[pitch/2:pitch:size_y]) { 118 | if(r <= pitch) { 119 | color(pcolor) translate([c-(pinsize/2)+pinsize, pitch+1.5*pinsize, -(pitch/2)+r+(1.5*pinsize)-adj]) 120 | rotate([0,270,0]) rotate_extrude(angle=90, convexity = 0) square([pinsize, pinsize]); 121 | color(pcolor) translate([c-(pinsize/2), pitch+1.5*pinsize, -pheight-(pitch/2)+r+(1.5*pinsize)]) 122 | cube([pinsize,pinsize,pheight]); 123 | color(pcolor) translate([c-(pinsize/2), -height+pinsize/2, r-(pinsize/2)]) 124 | cube([pinsize, pheight + height, pinsize]); 125 | } 126 | else { 127 | color(pcolor) translate([c-(pinsize/2)+pinsize, (2*pitch)+1.5*pinsize, -(pitch/2)+r+(1.5*pinsize)-adj]) 128 | rotate([0,270,0]) rotate_extrude(angle=90, convexity = 0) square([pinsize, pinsize]); 129 | color(pcolor) translate([c-(pinsize/2), 2*pitch+1.5*pinsize, -height-(pitch/2)+r+(2*pinsize)+(height-6)]) 130 | cube([pinsize,pinsize,pheight+pitch]); 131 | color(pcolor) translate([c-(pinsize/2), -height+pinsize/2, r-(pinsize/2)]) 132 | cube([pinsize, pheight+height+pitch, pinsize]); 133 | } 134 | } 135 | } 136 | } 137 | } 138 | if(type == "angled" && gender == "female") { 139 | size_y = pitch == 2.54 && style == "smt" ? (2.5 * column) : (pitch * column)+1; 140 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 141 | union() { 142 | difference() { 143 | color(hcolor) cube([size_x, height, size_y]); 144 | for(c=[pitch/2:pitch:size_x+pitch]) { 145 | for(r=[pitch/2:pitch:size_y]) { 146 | color("#888888") translate([c-(pinsize/2), r-(pinsize/2)-bheight, +1+pinsize/2]) 147 | cube([pinsize, height-1, pinsize]); 148 | color("#888888") translate([c-(pinsize/2),r-(pinsize/2)-bheight, pheight+.5+pinsize/2]) 149 | cube([pinsize, pheight+adj, pinsize]); 150 | } 151 | } 152 | } 153 | translate([0, height-1.5, .5]) for(c=[pitch/2:pitch:size_x]) { 154 | for(r=[pitch/2:pitch:size_y]) { 155 | if(r <= pitch) { 156 | color(pcolor) translate([c-(pinsize/2)+pinsize, pitch+1.5*pinsize, -(pitch/2)+r+(1.5*pinsize)-adj]) 157 | rotate([0,270,0]) rotate_extrude(angle=90, convexity = 0) square([pinsize, pinsize]); 158 | color(pcolor) translate([c-(pinsize/2), pitch+1.5*pinsize, -pheight-(pitch/2)+r+(1.5*pinsize)-.5]) 159 | cube([pinsize,pinsize,pheight+.5]); 160 | color(pcolor) translate([c-(pinsize/2), pinsize/2, r-(pinsize/2)]) 161 | cube([pinsize, pheight, pinsize]); 162 | } 163 | else { 164 | color(pcolor) translate([c-(pinsize/2)+pinsize, (2*pitch)+1.5*pinsize, -(pitch/2)+r+(1.5*pinsize)-adj]) 165 | rotate([0,270,0]) rotate_extrude(angle=90, convexity = 0) square([pinsize, pinsize]); 166 | color(pcolor) translate([c-(pinsize/2), 2*pitch+1.5*pinsize, -height-(pitch/2)+r+(2*pinsize)+(height-6)-.5]) 167 | cube([pinsize,pinsize,pheight+pitch+.5]); 168 | color(pcolor) translate([c-(pinsize/2), pinsize/2, r-(pinsize/2)]) 169 | cube([pinsize, pheight+pitch, pinsize]); 170 | } 171 | } 172 | } 173 | } 174 | } 175 | } 176 | // smt headers 177 | if(style == "smt" && enablemask == false) { 178 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 179 | union() { 180 | if((type == "open" || type == "boxed") && gender == "male") { 181 | union() { 182 | color(hcolor) cube([size_x, size_y, bheight]); 183 | for(c=[pitch/2:pitch:size_x]) { 184 | for(r=[pitch/2:pitch:size_y]) { 185 | color(pcolor) translate([c-(pinsize/2), r-(pinsize/2), bheight-adj]) cube([pinsize, pinsize, height]); 186 | } 187 | } 188 | } 189 | if(type == "boxed") { 190 | difference() { 191 | color(hcolor) translate([-walloffset,-wall,0]) cube([size_x+2*2.56, size_y+2*wall, height+bheight]); 192 | color(hcolor) translate([-walloffset+wall,0,wall]) cube([size_x+2*walloffset-4*wall, size_y, height+bheight+adj]); 193 | } 194 | } 195 | } 196 | if(gender == "female") { 197 | union() { 198 | difference() { 199 | color(hcolor) cube([size_x, size_y, height]); 200 | for(c=[pitch/2:pitch:size_x]) { 201 | for(r=[pitch/2:pitch:size_y]) { 202 | color("#888888") translate([c-(pinsize/2), r-(pinsize/2), adj]) cube([pinsize, pinsize, height]); 203 | } 204 | } 205 | } 206 | } 207 | } 208 | if(size_x >= size_y) { 209 | for(r=[pitch/2:pitch:size_x]) { 210 | for(c=[pitch/2:pitch:size_y]) { 211 | color(pcolor) translate ([r-(pinsize/2), -smtlead[1], 0]) cube(smtlead); 212 | color(pcolor) translate ([r-(pinsize/2), size_y-adj, 0]) cube(smtlead); 213 | } 214 | } 215 | } 216 | else { 217 | for(r=[pitch/2:pitch:size_x]) { 218 | for(c=[pitch/2:pitch:size_y]) { 219 | color(pcolor) translate ([-smtlead[1]+adj, c-(pinsize/2), 0]) cube([smtlead[1], smtlead[0], smtlead[2]]); 220 | color(pcolor) translate ([size_x-adj, c-(pinsize/2), 0]) cube([smtlead[1], smtlead[0], smtlead[2]]); 221 | } 222 | } 223 | } 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /lib/heatsinks/Odroid-N2_Heatsink.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hominoids/SBC_Model_Framework/0128dd7014f54863a99b1c547d2d0e290dff64c4/lib/heatsinks/Odroid-N2_Heatsink.stl -------------------------------------------------------------------------------- /lib/ic.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: ic 20 | DESCRIPTION: creates intergrated circuits 21 | TODO: 22 | 23 | USAGE: ic(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "generic" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | size[0] = size_x 32 | size[1] = size_y 33 | size[2] = size_z 34 | data[0] = icolor 35 | pcbsize_z = pcb thickness 36 | enablemask = true produces mask, false produces model 37 | mask[0] = true, false 38 | mask[1] = length 39 | mask[2] = set back 40 | mask[3] = mstyle "default" 41 | 42 | */ 43 | 44 | // ic class 45 | module ic(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 46 | 47 | size_x = size[0]; 48 | size_y = size[1]; 49 | size_z = size[2]; 50 | icolor = data[0]; 51 | 52 | // generic ic 53 | if (type == "generic" && enablemask == false) { 54 | 55 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 56 | color(icolor) cube([size_x, size_y, size_z]); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib/jst.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | CLASS NAME: jst 19 | DESCRIPTION: creates jst connectors for xh, ph, zh, sh, pa. 20 | TODO: flange for sh 21 | 22 | USAGE: jst(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 23 | 24 | type = "xh","ph","zh","sh","pa" 25 | loc_x = x location placement 26 | loc_y = y location placement 27 | loc_z = z location placement 28 | side = "top", "bottom" 29 | rotation[] = object rotation 30 | size[0] = #pins 31 | data[0] = "thruhole", "smt" 32 | data[1] = "top", "side" 33 | data[2] = body color 34 | pcbsize_z = pcb thickness 35 | enablemask = true, false 36 | mask[0] = true, false 37 | mask[1] = length 38 | mask[2] = set back 39 | mask[3] = mstyle "default" 40 | 41 | */ 42 | 43 | // JST connector class 44 | module jst(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 45 | 46 | row = size[0]; 47 | style = data[0]; 48 | entry = data[1]; 49 | bcolor = data[2]; 50 | pcolor = "silver"; 51 | cmask = mask[0]; 52 | mlen = mask[1]; 53 | back = mask[2]; 54 | mstyle = mask[3]; 55 | 56 | /* 57 | p p 58 | i i 59 | n n 60 | 61 | b t 62 | w o o 63 | b a p p t p p 64 | o l i i i 65 | d s s l n n h h n 66 | p y i i e e 67 | t i z z s x y i i s 68 | y t a e e i a a g g i 69 | p c d z d d h h z 70 | e h j y z e j j t t e 71 | */ 72 | jst_data = [ 73 | ["xh", 2.5, 2.45, 5.75, 7, .5, 2.35, 2.4, 3.4, 7, .64], 74 | ["ph", 2, 1.95, 4.5, 6, .5, 1.95, 1.7, 3.4, 5, .5], 75 | ["zh", 1.5, 1.5, 3.5, 4.5, .35, 1.5, 1.3, 3.4, 3.5, .5], 76 | ["sh", 1, 1, 2.9, 4.25, .35, 1, 1.25, 3.4, 4, .25], 77 | ["pa", 2, 2, 4, 8, .35, 2, 2, 3.4, 4.5, .5] 78 | ]; 79 | 80 | adj = .01; 81 | $fn = 90; 82 | 83 | s = search([type],jst_data); 84 | 85 | pitch = jst_data[s[0]][1]; 86 | body_adj = jst_data[s[0]][2]; 87 | size_x = body_adj+(row*pitch); 88 | size_y = jst_data[s[0]][3]; 89 | size_z = jst_data[s[0]][4]; 90 | wall_size = jst_data[s[0]][5]; 91 | pin_xadj = jst_data[s[0]][6]; 92 | pin_yadj = jst_data[s[0]][7]; 93 | pbheight = jst_data[s[0]][8]; 94 | ptheight = jst_data[s[0]][9]; 95 | pinsize = jst_data[s[0]][10]; 96 | smtlead = [pinsize,.925,.32]; 97 | 98 | if(entry == "top" && enablemask == false) { 99 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 100 | union() { 101 | difference() { 102 | union() { 103 | color(bcolor) cube([size_x, size_y, size_z]); 104 | if(type == "pa") { 105 | color(bcolor) translate([0, -.75+adj, 1.5]) cube([1.5, .75, size_z-3.01]); 106 | color(bcolor) translate([size_x-1.5, -.75+adj, 1.5]) cube([1.5, .75, size_z-3.01]); 107 | if(row >= 6) { 108 | color(bcolor) translate([2.5, -.75+adj, 1.5]) cube([1.5, .75, size_z-3.01]); 109 | color(bcolor) translate([size_x-4, -.75+adj, 1.5]) cube([1.5, .75, size_z-3.01]); 110 | } 111 | } 112 | } 113 | color(bcolor) translate([wall_size, wall_size, wall_size]) 114 | cube([size_x-(2*wall_size), size_y-(2*wall_size), size_z]); 115 | if(type == "xh") { 116 | color(bcolor) translate([2, -.1, size_z/2]) cube([1.5, size_y-2, 4]); 117 | color(bcolor) translate([size_x-3.5, -.1, size_z/2]) cube([1.5, size_y-2, 4]); 118 | color(bcolor) translate([-1, .75, 5]) cube([2, .75, 3]); 119 | color(bcolor) translate([size_x-2, .75, 5]) cube([size_y-2, .25*size[0], 3]); 120 | } 121 | if(type == "ph") { 122 | color(bcolor) translate([2, -.1, 2]) cube([size_x-(2*pitch), size_y-2, 5]); 123 | color(bcolor) translate([-1, 1.25, 4]) cube([size_y-2, .25*size[0], size_z]); 124 | color(bcolor) translate([size_x-2, 1.25, 4]) cube([size_y-2, .25*size[0], size_z]); 125 | } 126 | if(type == "zh") { 127 | color(bcolor) translate([-1, 1.25, size_z/2]) cube([size_y-2, .25*size[0], size_z]); 128 | color(bcolor) translate([size_x-1, 1.25, size_z/2]) cube([size_y-2, 0.25*size[0], size_z]); 129 | } 130 | if(type == "sh") { 131 | color(bcolor) translate([.25, .75, size_z/2]) cube([.25, .25, size_z]); 132 | color(bcolor) translate([size_x-.5, .75, size_z/2]) cube([.25, .25, size_z]); 133 | } 134 | if(type == "pa") { 135 | color(bcolor) translate([-1., -2.5, 6]) cube([size_x+2, 5, 4]); 136 | color(bcolor) translate([1.5 ,2, size_z-1]) cube([size_x-3, 4, 4]); 137 | color(bcolor) translate([wall_size, -.75+adj+wall_size, 1.5]) 138 | cube([1.5-(2*wall_size), 1, size_z-3.01]); 139 | color(bcolor) translate([size_x-1.5+wall_size, -.75+adj+wall_size, 1.5]) 140 | cube([1.5-(2*wall_size), 1, size_z-3.01]); 141 | if(row >= 6) { 142 | color(bcolor) translate([2.875, -.5+adj, 1.75]) cube([1.5-(2*wall_size), 1, size_z-3.01]); 143 | color(bcolor) translate([size_x-3.675, -.5+adj, 1.75]) cube([1.5-(2*wall_size), 1, size_z-3.01]); 144 | } 145 | } 146 | } 147 | if(type == "sh") { 148 | color(bcolor) translate([.25, size_y-.75, 0]) cube([.5, .5, size_z]); 149 | color(bcolor) translate([size_x-.75, size_y-.75, 0]) cube([.5, .5, size_z]); 150 | } 151 | if(style == "thruhole") { 152 | for(r=[pin_xadj-(pinsize/2):pitch:size_x-pitch]) { 153 | color("silver") translate([r, pin_yadj-(pinsize/2), -pbheight+adj]) 154 | cube([pinsize, pinsize, pbheight+ptheight]); 155 | } 156 | } 157 | if(style == "smt") { 158 | for(r=[pin_xadj-(pinsize/2):pitch:size_x-pitch]) { 159 | color("silver") translate([r, pin_yadj-(pinsize/2), adj]) 160 | cube([pinsize, pinsize, ptheight]); 161 | color("silver") translate([r, size_y-adj, 0]) 162 | cube(smtlead); 163 | } 164 | } 165 | } 166 | } 167 | if(entry == "side" && enablemask == false) { 168 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 169 | union() { 170 | difference() { 171 | color(bcolor) cube([size_x, size_z, size_y]); 172 | color(bcolor) translate([wall_size, -wall_size, wall_size]) 173 | cube([size_x-(2*wall_size), size_z, size_y-(2*wall_size)]); 174 | if(type == "xh") { 175 | color(bcolor) translate([2, -.1, size_z/2]) cube([1.5, 4, size_y-2]); 176 | color(bcolor) translate([size_x-3.5, -.1, size_z/2]) cube([1.5, 4, size_y-2]); 177 | color(bcolor) translate([-1, -.75, 4]) cube([2, 3, .75]); 178 | color(bcolor) translate([size_x-1, -.75, 4]) cube([2, 3, .25*size[0]]); 179 | } 180 | if(type == "ph") { 181 | color(bcolor) translate([2, -.1, 3]) cube([size_x-(2*pitch), 5, 2]); 182 | color(bcolor) translate([-1, -4, size_y-2]) cube([size_y-2, size_z, 1]); 183 | color(bcolor) translate([size_x-2, -4, size_y-2]) cube([size_y-2, size_z, 1]); 184 | } 185 | if(type == "zh") { 186 | color(bcolor) translate([-1, -size_z+1.25, size_y-1.25]) cube([size_y-2, size_z, .25*size[0]]); 187 | color(bcolor) translate([size_x-1, -size_z+1.25, size_y-1.25]) cube([size_y-2, size_z, 0.25*size[0]]); 188 | } 189 | if(type == "sh") { 190 | color(bcolor) translate([.25, 0, size_z/2]) cube([.25, size_z, .25]); 191 | color(bcolor) translate([size_x-.5, 0, size_z/2]) cube([.25, size_z, .25]); 192 | } 193 | } 194 | if(type == "xh") { 195 | difference() { 196 | union() { 197 | color(bcolor) translate([0, size_z, 0]) cube([1, 3.5, 4.5]); 198 | color(bcolor) translate([size_x-1, size_z, 0]) cube([1, 3.5, 4.5]); 199 | } 200 | color(bcolor) translate([-1, size_z, 4.5]) rotate([-30, 0, 0]) cube([size_x+2, 5.5, 4]); 201 | } 202 | } 203 | if(type == "ph") { 204 | difference() { 205 | union() { 206 | color(bcolor) translate([0, size_z, 0]) cube([.75, 1.6, 3]); 207 | color(bcolor) translate([size_x-.75, size_z, 0]) cube([.75, 1.6, 3]); 208 | } 209 | color(bcolor) translate([-1, size_z, 3]) rotate([-30, 0,0 ]) cube([size_x+2, 5.5, 4]); 210 | } 211 | } 212 | if(type == "zh") { 213 | difference() { 214 | union() { 215 | color(bcolor) translate([0, size_z, 0]) cube([.5, 1.5, 2.5]); 216 | color(bcolor) translate([size_x-.5, size_z, 0]) cube([.5, 1.5, 2.5]); 217 | } 218 | color(bcolor) translate([-1, size_z, 2.5]) rotate([-30, 0, 0]) cube([size_x+2, 5.5, 4]); 219 | } 220 | } 221 | if(type == "sh") { 222 | color(bcolor) translate([wall_size, 0, wall_size]) cube([.5, size_z, .5]); 223 | color(bcolor) translate([size_x-.75, 0, wall_size]) cube([.5, size_z, .5]); 224 | } 225 | if(style == "thruhole") { 226 | for(r=[pin_xadj-(pinsize/2):pitch:size_x-pitch]) { 227 | color("silver") translate([r, -adj, size_y-(pin_yadj+(pinsize/2))]) 228 | cube([pinsize, ptheight, pinsize]); 229 | color("silver") translate([r, size_z-pinsize, -pbheight+adj]) cube([pinsize, pinsize, pbheight]); 230 | } 231 | } 232 | if(style == "smt") { 233 | for(r=[pin_xadj-(pinsize/2):pitch:size_x-pitch]) { 234 | color("silver") translate([r, -adj, size_y-(pin_yadj+(pinsize/2))]) 235 | cube([pinsize, ptheight, pinsize]); 236 | color("silver") translate([r, size_z-adj, 0]) 237 | cube(smtlead); 238 | } 239 | } 240 | } 241 | } 242 | if(entry == "side" && enablemask == true && cmask == true && mstyle == "default") { 243 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 244 | translate([0-.5,-mlen+back,0]) cube([size_x+1, mlen, size_y+.5]); 245 | } 246 | } -------------------------------------------------------------------------------- /lib/memory.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: memory 20 | DESCRIPTION: creates memory components 21 | TODO: 22 | 23 | USAGE: memory(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "emmc", "emmc_plug", "emmc_plug_double", "sodimm_5.2", "sodimm_9.2" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | enablemask = true produces mask, false produces model 32 | mask[0] = true enables component mask 33 | mask[1] = mask length 34 | mask[2] = mask setback 35 | mask[3] = mstyle "default" 36 | 37 | */ 38 | 39 | // memory class 40 | module memory(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 41 | 42 | cmask = mask[0]; 43 | mlen = mask[1]; 44 | back = mask[2]; 45 | mstyle = mask[3]; 46 | 47 | // socketed emmc 48 | if(type == "emmc") { 49 | 50 | size_x = 13.5; 51 | size_y = 18.5; 52 | size_xm = 14.5; 53 | size_ym = 19.5; 54 | size_zm = mlen; 55 | 56 | if(enablemask == true && cmask == true && mstyle == "default") { 57 | if(side == "top" && rotation == 0) { 58 | place(loc_x-(size_xm-size_x)/2, loc_y-(size_ym-size_y)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 59 | cube([size_xm, size_ym, size_zm]); 60 | } 61 | if(side == "top" && rotation == 90) { 62 | place(loc_x-(size_xm-size_x)/2, loc_y-(size_ym-size_y)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 63 | cube([size_xm, size_ym, size_zm]); 64 | } 65 | if(side == "top" && rotation == 180) { 66 | place(loc_x-(size_xm-size_x)/2, loc_y-(size_ym-size_y)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 67 | cube([size_xm, size_ym, size_zm]); 68 | } 69 | if(side == "top" && rotation == 270) { 70 | place(loc_x-(size_xm-size_x)/2, loc_y-(size_ym-size_y)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 71 | cube([size_xm, size_ym, size_zm]); 72 | } 73 | if(side == "bottom" && rotation == 0) { 74 | place(loc_x-(size_xm-size_x)/2, loc_y-(size_ym-size_y)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 75 | cube([size_xm, size_ym, size_zm]); 76 | } 77 | if(side == "bottom" && rotation == 90) { 78 | place(loc_x-(size_xm-size_x)/2, loc_y-(size_ym-size_y)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 79 | cube([size_xm, size_ym, size_zm]); 80 | } 81 | if(side == "bottom" && rotation == 180) { 82 | place(loc_x-(size_xm-size_x)/2, loc_y-(size_ym-size_y)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 83 | cube([size_xm, size_ym, size_zm]); 84 | } 85 | if(side == "bottom" && rotation == 270) { 86 | place(loc_x-(size_xm-size_x)/2, loc_y-(size_ym-size_y)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 87 | cube([size_xm, size_ym, size_zm]); 88 | } 89 | } 90 | if(enablemask == false) { 91 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 92 | union (){ 93 | color("darkred") translate([0, 0, 1.1]) cube([size_x, size_y, .8]); 94 | color("dimgray") translate([1, 2, 1.9]) cube([11.5, 13, .9]); 95 | difference() { 96 | color("dimgray") translate([2, 13.5, 0]) cube([9.3, 3.4, 1.1]); 97 | color("dimgray") translate([2.5, 14.5, -.1]) cube([8.3, .5, 1.1]); 98 | color("dimgray") translate([2.5, 15.9, -.1]) cube([8.3, .5, 1.1]); 99 | color("dimgray") translate([2.5, 14.5, -.1]) cube([.5, 1.8, 1.1]); 100 | color("dimgray") translate([10.3, 14.5, -.1]) cube([.5, 1.8, 1.1]); 101 | } 102 | } 103 | } 104 | } 105 | 106 | // emmc plug 107 | if(type == "emmc_plug" || type == "emmc_plug_double") { 108 | 109 | size_x = 8.3; 110 | size_y = 2.16; 111 | size_xm = 14.5; 112 | size_ym = 19.5; 113 | size_zm = mlen; 114 | offsetm = 2.5; 115 | 116 | if(enablemask == true && cmask == true && mstyle == "default") { 117 | if(side == "top" && rotation == 0) { 118 | place(loc_x-(size_xm-size_x)/2, loc_y-offsetm-12.34, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 119 | cube([size_xm, size_ym, size_zm]); 120 | } 121 | if(side == "top" && rotation == 90) { 122 | place(loc_x-offsetm-12.34, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 123 | cube([size_xm, size_ym, size_zm]); 124 | } 125 | if(side == "top" && rotation == 180) { 126 | place(loc_x-(size_xm-size_x)/2, loc_y-offsetm, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 127 | cube([size_xm, size_ym, size_zm]); 128 | } 129 | if(side == "top" && rotation == 270) { 130 | place(loc_x-offsetm, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 131 | cube([size_xm, size_ym, size_zm]); 132 | } 133 | if(side == "bottom" && rotation == 0) { 134 | place(loc_x-(size_xm-size_x)/2, loc_y-offsetm-12.34, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 135 | cube([size_xm, size_ym, size_zm]); 136 | } 137 | if(side == "bottom" && rotation == 90) { 138 | place(loc_x-offsetm, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 139 | cube([size_xm, size_ym, size_zm]); 140 | } 141 | if(side == "bottom" && rotation == 180) { 142 | place(loc_x-(size_xm-size_x)/2, loc_y-offsetm, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 143 | cube([size_xm, size_ym, size_zm]); 144 | } 145 | if(side == "bottom" && rotation == 270) { 146 | place(loc_x-offsetm, loc_y-(size_xm-size_x)/2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 147 | cube([size_xm, size_ym, size_zm]); 148 | } 149 | } 150 | if(enablemask == false) { 151 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 152 | union (){ 153 | difference() { 154 | color("black") cube([size_x, size_y, .82]); 155 | color("black") translate([1, .25, .15]) cube([6.3, 1.65, 1]); 156 | color("black") translate([1, 0, .72]) cube([6.3, 2.5, 2]); 157 | } 158 | for (i=[1.25:.4:7.2]) { 159 | color("gold") translate ([i, -.05, 0]) cube([.16, .3, .82]); 160 | color("gold") translate ([i, 1.9, 0]) cube([.16, .3, .82]); 161 | } 162 | if(type == "emmc_plug_double") { 163 | union (){ 164 | difference() { 165 | translate([0,-13,0]) color("black") cube([size_x, size_y, .82]); 166 | translate([0,-13,0]) color("black") translate([1, .25, .15]) cube([6.3, 1.65, 1]); 167 | translate([0,-13,0]) color("black") translate([1, 0, .72]) cube([6.3, 2.5, 2]); 168 | } 169 | for (i=[1.25:.4:7.2]) { 170 | translate([0,-13,0]) color("gold") translate ([i, -.05, 0]) cube([.16, .3, .82]); 171 | translate([0,-13,0]) color("gold") translate ([i, 1.9, 0]) cube([.16, .3, .82]); 172 | } 173 | } 174 | } 175 | } 176 | } 177 | } 178 | 179 | // sodimm-5.2 socket 180 | if(type == "sodimm_5.2" && enablemask == false) { 181 | size_x = 73; 182 | size_y = 6.5; 183 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 184 | union() { 185 | difference () { 186 | 187 | color("dimgray") cube([size_x, size_y, 5.2]); 188 | color("dimgray") translate([2, -1, 1.75]) cube([69, 3, 5]); 189 | color("dimgray") translate([3.5, -1, 1.75]) cube([28.5, 5.25, .92]); 190 | color("dimgray") translate([34.5, -1, 1.75]) cube([35, 5.25, .92]); 191 | } 192 | for (i=[2:.5:31]) { 193 | color("gold") translate ([i+.5, 2, 1.75]) cube([.25, 2, .25]); 194 | } 195 | for (i=[34:.5:69]) { 196 | color("gold") translate ([i+.5, 2, 1.75]) cube([.25, 2, .25]); 197 | } 198 | } 199 | } 200 | 201 | // sodimm-9.2 socket 202 | if(type == "sodimm_9.2" && enablemask == false) { 203 | size_x = 73; 204 | size_y = 6.5; 205 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 206 | union() { 207 | difference () { 208 | 209 | color("dimgray") cube([size_x, size_y, 9.2]); 210 | color("dimgray") translate([2, -1, 5.7]) cube([69, 3, 5]); 211 | color("dimgray") translate([3.5, -1, 5.7]) cube([28.5, 5.25, .92]); 212 | color("dimgray") translate([34.5, -1, 5.7]) cube([35, 5.25, .92]); 213 | } 214 | for (i=[2:.5:31]) { 215 | color("gold") translate ([i+.5, 2, 5.7]) cube([.25, 2, .25]); 216 | } 217 | for (i=[34:.5:69]) { 218 | color("gold") translate ([i+.5, 2, 5.7]) cube([.25, 2, .25]); 219 | } 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /lib/molex.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: molex 20 | DESCRIPTION: creates molex series connectors. 21 | TODO: "5267", "5268" 22 | 23 | USAGE: molex(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "7478","5046" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | size[0] = #pins 32 | data[0] = "thruhole", "smt" 33 | data[1] = "top", "side" 34 | pcbsize_z = pcb thickness 35 | enablemask = true produces mask, false produces model 36 | mask[0] = true enables component mask 37 | mask[1] = mask length 38 | mask[2] = mask setback 39 | mask[3] = mstyle "default" 40 | 41 | */ 42 | 43 | // molex connector class 44 | module molex(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 45 | 46 | row = size[0]; 47 | style = data[0]; 48 | entry = data[1]; 49 | bcolor = "white"; 50 | pcolor = "silver"; 51 | cmask = mask[0]; 52 | mlen = mask[1]; 53 | back = mask[2]; 54 | mstyle = mask[3]; 55 | 56 | /* 57 | p p 58 | i i 59 | n n 60 | 61 | b t p p 62 | w o o i i 63 | b a p p t p p n n 64 | o l i i i 65 | d s s l n n h h n o r 66 | p y i i e e f a 67 | t i z z s x y i i s f d 68 | y t a e e i a a g g i s i 69 | p c d z d d h h z e u 70 | e h j y z e j j t t e t s 71 | */ 72 | molex_data = [ 73 | ["7478", 2.54, 0, 6.5, 3.18, 0, 0, 3.25, 3.4, 9.25, .64, 3, 1.17, 0], 74 | ["5046", 2.54, 0, 6.5, 3.18, 0, 0, 0.64, 6.25, 5.75, .64, 2, 1.17, 2.62] 75 | ]; 76 | 77 | adj = .01; 78 | $fn = 90; 79 | 80 | s = search([type],molex_data); 81 | 82 | pitch = molex_data[s[0]][1]; 83 | body_adj = molex_data[s[0]][2]; 84 | size_x = body_adj+(row*pitch); 85 | size_y = molex_data[s[0]][3]; 86 | size_z = molex_data[s[0]][4]; 87 | wall_size = molex_data[s[0]][5]; 88 | pin_xadj = molex_data[s[0]][6]; 89 | pin_yadj = molex_data[s[0]][7]; 90 | pbheight = molex_data[s[0]][8]; 91 | ptheight = molex_data[s[0]][9]; 92 | pinsize = molex_data[s[0]][10]; 93 | pinoffset = molex_data[s[0]][11]; 94 | pinradius = molex_data[s[0]][12]; 95 | pinbhadj = molex_data[s[0]][13]; 96 | smtlead = [pinsize,.925,.32]; 97 | 98 | 99 | if(entry == "top" && enablemask == false) { 100 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 101 | union() { 102 | difference() { 103 | union() { 104 | color(bcolor) cube([size_x, size_y, size_z]); 105 | if(type == "7478") { 106 | color(bcolor) translate([pitch/4, size_y-1, 0]) cube([size_x-pitch/2, 1, size_z+5.5]); 107 | color(bcolor) translate([pitch/4, size_y-1, size_z+4.5]) rotate([0, 90, 0]) 108 | cylinder(d=2, h=size_x-pitch/2); 109 | } 110 | } 111 | if(type == "7478") { 112 | for(r=[pitch/2-(pinsize/2)-.5:pitch:size_x]) { 113 | color(bcolor) translate([r, -1, -1]) cube([1.5, size_y+2, 1.5]); 114 | } 115 | } 116 | } 117 | if(style == "thruhole") { 118 | for(r=[pitch/2-(pinsize/2):pitch:size_x]) { 119 | color("silver") translate([r, pin_yadj-(pinsize/2), -pbheight+adj]) 120 | cube([pinsize, pinsize, pbheight+ptheight]); 121 | } 122 | } 123 | if(style == "smt") { 124 | for(r=[pitch/2-(pinsize/2):pitch:size_x-pitch]) { 125 | color("silver") translate([r, pin_yadj-(pinsize/2), adj]) 126 | cube([pinsize, pinsize, ptheight]); 127 | color("silver") translate([r, size_y-adj, 0]) 128 | cube(smtlead); 129 | } 130 | } 131 | } 132 | } 133 | if(entry == "side" && enablemask == true && cmask == true && mstyle == "default") { 134 | 135 | size_xm = size_x; 136 | size_ym = size_y+.5; 137 | size_zm = 5; 138 | 139 | if(side == "top" && rotation == 0) { 140 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 141 | translate([0, back, 0]) rotate([90, 0, 0]) slab([size_x, size_ym, mlen], .5); 142 | } 143 | if(side == "top" && rotation == 90) { 144 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 145 | translate([0, back, 0]) rotate([90, 0, 0]) slab([size_x, size_ym, mlen], .5); 146 | } 147 | if(side == "top" && rotation == 180) { 148 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 149 | translate([0, back+.5, 0]) rotate([90, 0, 0]) slab([size_x, size_ym, mlen], .5); 150 | } 151 | if(side == "top" && rotation == 270) { 152 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 153 | translate([0, back+.5, 0]) rotate([90, 0, 0]) slab([size_x, size_ym, mlen], .5); 154 | } 155 | if(side == "bottom" && rotation == 0) { 156 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 157 | translate([0, back, 0]) rotate([90, 0, 0]) slab([size_x, size_ym, mlen],.5); 158 | } 159 | if(side == "bottom" && rotation == 90) { 160 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 161 | translate([0, back+.5, 0]) rotate([90, 0, 0]) slab([size_x, size_ym, mlen],.5); 162 | } 163 | if(side == "bottom" && rotation == 180) { 164 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 165 | translate([0, back+.5, 0]) rotate([90, 0, 0]) slab([size_x, size_ym, mlen], .5); 166 | } 167 | if(side == "bottom" && rotation == 270) { 168 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 169 | translate([0, back, 0]) rotate([90, 0, 0]) slab([size_x, size_ym, mlen], .5); 170 | } 171 | } 172 | if(entry == "side" && enablemask == false) { 173 | 174 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 175 | union() { 176 | difference() { 177 | union() { 178 | color(bcolor) cube([size_x, size_z, size_y]); 179 | if(type == "7478") { 180 | color(bcolor) translate([pitch/4,-size_z-5.5,size_y-1]) cube([size_x-pitch/2, size_z+5.5, 1]); 181 | color(bcolor) translate([pitch/4, -size_z-4.5, size_y-1]) rotate([0, 90, 0]) 182 | cylinder(d=2, h=size_x-pitch/2); 183 | } 184 | if(type == "5046") { 185 | color(bcolor) translate([pitch/4,-size_z-5.5,size_y-3.5]) cube([size_x-pitch/2, size_z+5.5, 1]); 186 | color(bcolor) translate([pitch/4, -size_z-1.5, size_y-2.5]) rotate([0, 90, 0]) 187 | cylinder(d=2, h=size_x-pitch/2); 188 | color(bcolor) translate([0,size_z,0]) cube([.75,3,3]); 189 | color(bcolor) translate([size_x-.75,size_z,0]) cube([.75,3,3]); 190 | } 191 | } 192 | if(type == "7478" || type == "5046") { 193 | for(r=[pitch/2-(pinsize/2)-.5:pitch:size_x]) { 194 | color(bcolor) translate([r, -1,-1]) cube([1.5, size_y+2, 1.5]); 195 | } 196 | } 197 | } 198 | if(style == "thruhole") { 199 | for(r=[pitch/2-(pinsize/2):pitch:size_x]) { 200 | if(type == "7478") { 201 | color("silver") translate([r, -ptheight+adj, size_y-(pin_yadj+(pinsize/2))]) 202 | cube([pinsize, ptheight+size_z+pinsize+pinsize/2, pinsize]); 203 | color("silver") translate([r, size_z+pinoffset-pinsize/2, -pbheight+adj+pinbhadj]) 204 | cube([pinsize, pinsize, pbheight+pinsize+pinsize/2]); 205 | rotate([0,270,0]) translate([pinsize+(pinsize/2)+pinbhadj-(3*adj), size_z+pinsize+.04, r-size_x]) color("silver") 206 | rotate_extrude(angle=90, convexity = 10) translate([2, 0, 0]) square([pinsize, pinsize]); 207 | } 208 | if(type == "5046") { 209 | color("silver") translate([r, -ptheight+adj-3, size_y-(pin_yadj+(pinsize/2))]) 210 | cube([pinsize, ptheight+size_z+pinsize+pinsize/2, pinsize]); 211 | color("silver") translate([r, size_z+pinoffset-pinsize/2, -pbheight+adj+pinbhadj]) 212 | cube([pinsize, pinsize, pbheight+pinsize+pinsize/2]); 213 | rotate([0,270,0]) translate([pinsize+(pinsize/2)+pinbhadj-(3*adj), size_z+pinsize+.04-1, r-size_x]) color("silver") 214 | rotate_extrude(angle=90, convexity = 10) translate([2, 0, 0]) square([pinsize, pinsize]); 215 | } 216 | } 217 | } 218 | if(style == "smt") { 219 | for(r=[pitch/2-(pinsize/2):pitch:size_x-pitch]) { 220 | color("silver") translate([r, -adj, size_y-(pin_yadj+(pinsize/2))]) 221 | cube([pinsize, ptheight, pinsize]); 222 | color("silver") translate([r, size_z-adj, 0]) 223 | cube(smtlead); 224 | } 225 | } 226 | } 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /lib/pcb.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: pcbhole 20 | DESCRIPTION: creates pcb hole 21 | TODO: cu edge shapes 22 | 23 | USAGE: pcbhole(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "round" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | size[0] = hole diameter 32 | data[0] = style 33 | data[1] = hole color 34 | data[2] = sidewall support("none","left","right","rear","front") 35 | data[3] = trace diameter 36 | data[4] = position "left_rear","left_front","right_rear","right_front","middle_rear","middle_front", 37 | "heatsink_left","heatsink_right","heatsink_rear","heatsink_front","pcie_1","gpio_1","misc_1" 38 | pcbsize_z = pcb thickness 39 | enablemask = true produces mask, false produces model 40 | mask[0] = true enables component mask 41 | mask[1] = mask length 42 | mask[2] = mask setback 43 | mask[3] = mstyle "default" 44 | 45 | 46 | CLASS NAME: pcbsoc 47 | DESCRIPTION: creates soc components 48 | TODO: add other styles 49 | 50 | USAGE: pcbsoc(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 51 | 52 | type = "flat", "raised", "mid-raised", "rk3399", "rk3588" 53 | loc_x = x location placement 54 | loc_y = y location placement 55 | loc_z = z location placement 56 | side = "top", "bottom" 57 | rotation[] = object rotation 58 | size[0] = size_x 59 | size[1] = size_y 60 | size[2] = size_z 61 | pcbsize_z = pcb thickness 62 | enablemask = true produces mask, false produces model 63 | mask[0] = true enables component mask 64 | mask[1] = mask length 65 | mask[2] = mask setback 66 | mask[3] = mstyle "default" 67 | 68 | 69 | CLASS NAME: pcbpad 70 | DESCRIPTION: creates pcb pads 71 | TODO: 72 | 73 | USAGE: pcbpad(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 74 | 75 | type = "round", "square", "sqround", "castellation" 76 | loc_x = x location placement 77 | loc_y = y location placement 78 | loc_z = z location placement 79 | side = "top", "bottom" 80 | rotation[] = object rotation 81 | size[0] = #pad x 82 | size[1] = #pad y 83 | data[0] = hole size 84 | data[1] = pad color 85 | data[2] = pad size 86 | data[5] = pad_trim ("front", "rear") 87 | pcbsize_z = pcb thickness 88 | enablemask = true produces mask, false produces model 89 | mask[0] = true enables component mask 90 | mask[1] = mask length 91 | mask[2] = mask setback 92 | mask[3] = mstyle "default" 93 | 94 | 95 | CLASS NAME: pcb 96 | DESCRIPTION: creates pcb and features 97 | TODO: 98 | 99 | USAGE: pcb(size[], radius) 100 | 101 | size[0] = size_x 102 | size[1] = size_y 103 | size[2] = size_z 104 | radius = corner radius 105 | 106 | */ 107 | 108 | // pcb board 109 | module pcb(size, radius) { 110 | x = size[0]; 111 | y = size[1]; 112 | z = size[2]; 113 | linear_extrude(height = z) 114 | hull() { 115 | translate([0+radius ,0+radius, 0]) circle(r = radius); 116 | translate([0+radius, y-radius, 0]) circle(r = radius); 117 | translate([x-radius, y-radius, 0]) circle(r = radius); 118 | translate([x-radius, 0+radius, 0]) circle(r = radius); 119 | } 120 | } 121 | 122 | 123 | // pcb hole additions 124 | module pcbhole(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 125 | 126 | // pcbhole class 127 | if(type == "round" && enablemask == false) { 128 | 129 | size_x = size[0]; 130 | size_y = size[0]; 131 | style = data[0]; 132 | hcolor = data[1]; 133 | support = data[2]; 134 | pad_size = data[3]; 135 | hole_position = data[4]; 136 | 137 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 138 | difference() { 139 | color(hcolor) translate([0, 0, -.0635-pcbsize_z]) cylinder(d=pad_size, pcbsize_z+.127); 140 | color(hcolor) translate([0, 0, -1.127-pcbsize_z]) cylinder(d=size_x-.127, pcbsize_z+2); 141 | } 142 | } 143 | } 144 | 145 | 146 | // pcb soc class 147 | module pcbsoc(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 148 | 149 | size_x = size[0]; 150 | size_y = size[1]; 151 | size_z = size[2]; 152 | 153 | if(type == "flat" && enablemask == false) { 154 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 155 | color("dimgray") cube([size_x, size_y, size_z]); 156 | } 157 | if(type == "rk3399") { 158 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 159 | union() { 160 | color("silver") cube([size_x, size_y, size_z]); 161 | translate([2, 2, size_z-.01]) color("silver") slab([size_x-4, size_y-4, .6],2); 162 | } 163 | } 164 | if(type == "raised" && enablemask == false) { 165 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 166 | union() { 167 | color("silver") cube([size_x, size_y, size_z]); 168 | translate([2, 2, size_z-.01]) color("silver") slab([size_x-4, size_y-4, .6],.5); 169 | } 170 | } 171 | if(type == "rk3588" && enablemask == false) { 172 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 173 | union() { 174 | color("silver") cube([size_x, size_y, size_z]); 175 | translate([2, 2, size_z-.01]) color("silver") slab([size_x-4, size_y-4, .6],.5); 176 | } 177 | } 178 | if(type == "mid-raised" && enablemask == false) { 179 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 180 | union() { 181 | color("silver") cube([size_x, size_y, size_z]); 182 | color("silver") translate([data[0], data[1], size_z-.01]) rotate([90,0,90]) slot(data[5], data[3], data[4]); 183 | } 184 | } 185 | } 186 | 187 | 188 | // pcb pad matrix 189 | module pcbpad(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 190 | 191 | size_x = 2.54 * (size[0]-1); 192 | size_y = 2.54 * (size[1]-1);; 193 | 194 | hole_size = data[0]; 195 | hcolor = data[1]; 196 | pad_size = data[2]; 197 | pad_trim = data[3]; 198 | 199 | adj = .01; 200 | $fn = 90; 201 | 202 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 203 | union() { 204 | for (c=[0:2.54:size_y]) { 205 | for (r=[0:2.54:size_x]) { 206 | if(type == "round") { 207 | difference() { 208 | color(hcolor) translate ([r, c, -.0635-pcbsize_z]) cylinder(d=pad_size, h=pcbsize_z+.127); 209 | color(hcolor) translate([r, c, -1.127-pcbsize_z]) cylinder(d=hole_size, h=pcbsize_z+2); 210 | } 211 | } 212 | if(type == "sqround") { 213 | if(c != 0) { 214 | difference() { 215 | color(hcolor) translate ([r, c, -.0635-pcbsize_z]) cylinder(d=pad_size, h=pcbsize_z+.127); 216 | color(hcolor) translate([r, c, -1.127-pcbsize_z]) cylinder(d=hole_size, h=pcbsize_z+2); 217 | } 218 | } 219 | else { 220 | difference() { 221 | color(hcolor) translate ([r-pad_size/2, c-pad_size/2, -.0635-pcbsize_z]) cube([pad_size, pad_size, pcbsize_z+.127]); 222 | color(hcolor) translate([r, c, -1.127-pcbsize_z]) cylinder(d=hole_size, h=pcbsize_z+2); 223 | } 224 | } 225 | } 226 | if(type == "square") { 227 | difference() { 228 | color(hcolor) translate ([r-pad_size/2, c-pad_size/2, -.0635-pcbsize_z]) cube([pad_size, pad_size, pcbsize_z+.127]); 229 | color(hcolor) translate([r, c, -1.127-pcbsize_z]) cylinder(d=hole_size, h=pcbsize_z+2); 230 | } 231 | } 232 | if(type == "castellation") { 233 | difference() { 234 | color(hcolor) translate ([r, c, -.0635-pcbsize_z]) cylinder(d=pad_size, h=pcbsize_z+.127); 235 | color(hcolor) translate([r, c, -1.127-pcbsize_z]) cylinder(d=hole_size, h=pcbsize_z+2); 236 | if(pad_trim == "rear") { 237 | color(hcolor) translate([r, c-1.5-adj, 0]) cube([3,3,5], center=true); 238 | } 239 | if(pad_trim == "front") { 240 | color(hcolor) translate([r, c+1.5+adj, 0]) cube([3,3,5], center=true); 241 | } 242 | } 243 | } 244 | } 245 | } 246 | } 247 | } -------------------------------------------------------------------------------- /lib/pcie.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: pcie 20 | DESCRIPTION: creates pcie components 21 | TODO: 22 | 23 | USAGE: pcie(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "x1", "x4" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | pcbsize_z = pcb thickness 32 | enablemask = true produces mask, false produces model 33 | mask[0] = true enables component mask 34 | mask[1] = mask length 35 | mask[2] = mask setback 36 | mask[3] = mstyle "default" 37 | 38 | */ 39 | 40 | // pcie class 41 | module pcie(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 42 | 43 | // PCIE 44 | if ((type == "x1" || type == "x4") && enablemask == false) { 45 | size_x = type == "x1" ? 25 : 39; 46 | pin = type == "x1" ? 36/2 : 64/2; 47 | size_y = 8.5; 48 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 49 | union() { 50 | difference() { 51 | color("black") cube([size_x, size_y, 11.1]); 52 | color("dimgrey") translate([1.55, (size_y/2)-.8, 2]) cube([11.5, 1.6, 11]); 53 | color("dimgrey") translate([15.5, (size_y/2)-.8, 2]) cube([pin-10.5, 1.6, 11]); 54 | } 55 | for (i=[1:1:11.5]) { 56 | color("#fee5a6") translate ([i+1, 2.75, -3]) cube([.5, .7, 13.75]); 57 | color("#fee5a6") translate ([i+1, 4.75, -3]) cube([.5, .7, 13.75]); 58 | color("#fee5a6") translate ([i+1, 1.375, -3]) cube([.5, .7, 3.5]); 59 | color("#fee5a6") translate ([i+1, 6.125, -3]) cube([.5, .7, 3.5]); 60 | } 61 | for (i=[16:1:pin+4]) { 62 | color("#fee5a6") translate ([i, 2.75, -3]) cube([.5, .7, 13.75]); 63 | color("#fee5a6") translate ([i, 4.75, -3]) cube([.5, .7, 13.75]); 64 | color("#fee5a6") translate ([i, 1.375, -3]) cube([.5, .7, 3.5]); 65 | color("#fee5a6") translate ([i, 6.125, -3]) cube([.5, .7, 3.5]); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/pillar.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: pillar 20 | DESCRIPTION: creates pillars 21 | TODO: add other genders and styles 22 | 23 | USAGE: pillar(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "hex", "round" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | size[0] = outside dia 32 | size[1] = inside dia 33 | size[2] = height 34 | data[1] = body color 35 | pcbsize_z = pcb thickness 36 | enablemask = true produces mask, false produces model 37 | mask[0] = true enables component mask 38 | mask[1] = mask length 39 | mask[2] = mask setback 40 | mask[3] = mstyle "default" 41 | 42 | */ 43 | 44 | // pillar class 45 | module pillar(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 46 | 47 | // type hex 48 | if(type=="hex" && enablemask == false) { 49 | 50 | size_x = size[0]; 51 | size_y = size[1]; 52 | size_z = size[2]; 53 | pcolor = data[1]; 54 | 55 | if(enablemask == false) { 56 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 57 | difference() { 58 | color(pcolor) rotate([rotation]) cylinder(d=size_x*2/sqrt(3), h=size_z, $fn=6); 59 | color(pcolor) translate([0, 0, -.1]) rotate([rotation]) cylinder(d=size_y, h=size_z+.2); 60 | } 61 | } 62 | } 63 | // type hex 64 | if(type=="round" && enablemask == false) { 65 | 66 | size_x = size[0]; 67 | size_y = size[1]; 68 | size_z = size[2]; 69 | pcolor = data[1]; 70 | 71 | if(enablemask == false) { 72 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 73 | difference() { 74 | color(pcolor) rotate([rotation]) cylinder(d=size_x, h=size_z, $fn=60); 75 | color(pcolor) translate([0, 0, -.1]) rotate([rotation]) cylinder(d=size_y, h=size_z+.2); 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /lib/place.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | DESCRIPTION: places components on top or bottom and rotates in position 20 | TODO: 21 | 22 | USAGE: place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 23 | 24 | loc_x = x location placement 25 | loc_y = y location placement 26 | loc_z = z location placement 27 | size_x = object x dimension 28 | size_y = object y dimension 29 | rotation = object z-axis rotation 30 | side = "top", "bottom" 31 | pcbsize_z = pcb thickness 32 | 33 | */ 34 | 35 | module place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) { 36 | 37 | if (side == "top") { 38 | if ((rotation >= 0 && rotation < 90) || (rotation < -270 && rotation > -360)) 39 | translate([loc_x, loc_y, pcbsize_z+loc_z]) rotate([0, 0, -rotation]) children(); 40 | 41 | if ((rotation >= 90 && rotation < 180) || (rotation < -180 && rotation >= -270)) 42 | translate([loc_x, loc_y+size_x, pcbsize_z+loc_z]) rotate([0, 0, -rotation]) children(); 43 | 44 | if ((rotation >= 180 && rotation < 270) || (rotation < -90 && rotation >= -180)) 45 | translate([loc_x+size_x, loc_y+size_y, pcbsize_z+loc_z]) rotate([0, 0, -rotation]) children(0); 46 | 47 | if ((rotation >= 270 && rotation < 360) || (rotation < 0 && rotation >= -90)) 48 | translate([loc_x+size_y, loc_y, pcbsize_z+loc_z]) rotate([0, 0, -rotation]) children(); 49 | } 50 | if (side == "bottom") { 51 | if ((rotation >= 0 && rotation < 90) || (rotation < -270 && rotation > -360)) 52 | translate([loc_x+size_x, loc_y, -loc_z]) rotate([0, 180, rotation]) children(); 53 | 54 | if ((rotation >= 90 && rotation < 180) || (rotation < -180 && rotation >= -270)) 55 | translate([loc_x+size_y, loc_y+size_x, -loc_z]) rotate([0, 180, rotation]) children(); 56 | 57 | if ((rotation >= 180 && rotation < 270) || (rotation < -90 && rotation >= -180)) 58 | translate([loc_x, loc_y+size_y, -loc_z]) rotate([0, 180, rotation]) children(); 59 | 60 | if ((rotation >= 270 && rotation < 360) || (rotation < 0 && rotation >= -90)) 61 | translate([loc_x, loc_y, -loc_z]) rotate([0, 180, rotation]) children(); 62 | } 63 | children([1:1:$children-1]); 64 | } 65 | -------------------------------------------------------------------------------- /lib/shape.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | DESCRIPTION: creates geometric shapes 20 | TODO: 21 | 22 | USAGE: shape(type, size[], data[]) 23 | 24 | type = "rectangle", "round", "slot", "polygon", "dxf" 25 | size[0] = size_x 26 | size[1] = size_y 27 | size[2] = size_z 28 | data[0] = body color 29 | data[2] = polygon data or dxf file 30 | 31 | USAGE: slab(size[], radius]) 32 | 33 | size[0] = size_x 34 | size[1] = size_y 35 | size[2] = size_z 36 | radius = corner radius 37 | 38 | USAGE: slab_r(size[], radius[]]) 39 | 40 | size[0] = size_x 41 | size[1] = size_y 42 | size[2] = size_z 43 | radius[0] = corner radius 44 | radius[1] = corner radius 45 | radius[2] = corner radius 46 | radius[3] = corner radius 47 | 48 | USAGE: slot(hole, length, depth) 49 | 50 | hole = radius diameter 51 | length = total length 52 | depth = thickness 53 | 54 | USAGE: long_slot(hole, length, depth) 55 | 56 | hole = radius diameter 57 | length = total length 58 | depth = thickness 59 | 60 | USAGE: knockout(width, depth, gap, thick, fillet, shape) 61 | 62 | width = length 63 | depth = width 64 | gap = space between 65 | thick = thickness 66 | fillet = corner fillet 67 | shape = "slot", "rectangle", "round" 68 | 69 | USAGE: vent(width, length, height, gap, rows, columns, orientation) 70 | 71 | width = coloumn size_x 72 | length = column size_y 73 | height = size_z 74 | gap = space between 75 | rows = #row 76 | columns = #columns 77 | orientation = "horizontal", "vertical" 78 | 79 | USAGE: vent_hex(cells_x, cells_y, thickness, cell_size, cell_spacing, orientation) 80 | cells_x = #rows 81 | cells_y = #columns 82 | thickness = 83 | cell_size = size of hex 84 | cell_spacing = space between hex 85 | orientation = "horizontal", "vertical" 86 | 87 | */ 88 | 89 | /* shape module */ 90 | module shape(type, size, data) { 91 | 92 | if(type == "rectangle") { 93 | cube([size[0], size[1], size[2]]); 94 | } 95 | if(type == "round") { 96 | cylinder(d=size[0], h=size[2]); 97 | } 98 | if(type == "slot") { 99 | slot(size[0], size[1], size[2]); 100 | } 101 | if(type == "polygon") { 102 | linear_extrude(height = size[2]) polygon(data[2]); 103 | } 104 | if(type == "dxf") { 105 | linear_extrude(height = size[2]) import(file = data[2], scale=data[3]); 106 | } 107 | } 108 | 109 | /* slab module */ 110 | module slab(size, radius) { 111 | 112 | x = size[0]; 113 | y = size[1]; 114 | z = size[2]; 115 | linear_extrude(height=z) 116 | hull() { 117 | translate([0+radius ,0+radius, 0]) circle(r=radius); 118 | translate([0+radius, y-radius, 0]) circle(r=radius); 119 | translate([x-radius, y-radius, 0]) circle(r=radius); 120 | translate([x-radius, 0+radius, 0]) circle(r=radius); 121 | } 122 | } 123 | 124 | 125 | /* multi-radius round slab */ 126 | module slab_r(size, radius) { 127 | 128 | x = size[0]; 129 | y = size[1]; 130 | z = size[2]; 131 | r0 = radius[0]; 132 | r1 = radius[1]; 133 | r2 = radius[2]; 134 | r3 = radius[3]; 135 | 136 | linear_extrude(height=z) 137 | hull() { 138 | translate([0+radius[0] ,0+radius[0], 0]) circle(r=radius[0]); 139 | translate([0+radius[1], y-radius[1], 0]) circle(r=radius[1]); 140 | translate([x-radius[2], y-radius[2], 0]) circle(r=radius[2]); 141 | translate([x-radius[3], 0+radius[3], 0]) circle(r=radius[3]); 142 | } 143 | } 144 | 145 | 146 | /* 147 | NAME: slot 148 | DESCRIPTION: create slot shape to length 149 | TODO: none 150 | 151 | USAGE: slot(hole, length, depth) 152 | 153 | hole = diameter of slot 154 | length = length of slot 155 | depth = thickness of slot 156 | */ 157 | 158 | module slot(hole,length,depth) { 159 | 160 | hull() { 161 | translate([hole/2, 0, 0]) cylinder(d=hole, h=depth); 162 | translate([length-hole/2, 0, 0]) cylinder(d=hole, h=depth); 163 | } 164 | } 165 | 166 | 167 | /* 168 | NAME: long_slot 169 | DESCRIPTION: create slot shape with full movement of length 170 | TODO: none 171 | 172 | USAGE: long_slot(hole, length, depth) 173 | 174 | hole = diameter of slot 175 | length = length of slot 176 | depth = thickness of slot 177 | */ 178 | 179 | module long_slot(hole, length, depth) { 180 | 181 | hull() { 182 | translate([0,0,0]) cylinder(d=hole,h=depth); 183 | translate([length,0,0]) cylinder(d=hole,h=depth); 184 | } 185 | } 186 | 187 | 188 | /* knockout opening */ 189 | module knockout(width,depth,gap,thick,fillet,shape) { 190 | 191 | adj = .01; 192 | $fn=90; 193 | 194 | // slot knockout 195 | if(shape == "slot") { 196 | difference() { 197 | slot(depth, width, thick); 198 | translate([gap/2, 0, -adj]) slot(depth-gap, width-gap, thick+(2*adj)); 199 | // cross ties 200 | translate([(depth/2), -(depth/2)-1, -adj]) cube([2, depth+2, thick+(2*adj)]); 201 | translate([(width/2)-1-(width/4)+4, -(depth/2)-1, -adj]) cube([2,depth+2, thick+(2*adj)]); 202 | translate([(width/2)-1+(width/4)-4, -(depth/2)-1, -adj]) cube([2, depth+2, thick+(2*adj)]); 203 | translate([width-(depth/2)-2, -(depth/2)-1, -adj]) cube([2, depth+2, thick+(2*adj)]); 204 | } 205 | } 206 | if(shape == "rectangle") { 207 | difference() { 208 | translate([(width/2), (depth/2), thick/2]) 209 | cube_fillet_inside([width, depth, thick], 210 | vertical=[fillet, fillet, fillet, fillet], 211 | top=[0, 0, 0, 0], bottom=[0, 0, 0, 0], $fn=90); 212 | translate([(width/2), (depth/2), (thick/2)-adj]) 213 | cube_fillet_inside([width-gap, depth-gap, thick+(3*adj)], 214 | vertical=[fillet, fillet, fillet, fillet], 215 | top=[0, 0, 0, 0], bottom=[0, 0, 0, 0], $fn=90); 216 | // cross ties 217 | translate([-1, (depth/2)-1, -adj]) cube([gap+2, 2, thick+(2*adj)]); 218 | translate([width-4, depth-gap-1, -adj]) cube([2, gap+2, thick+(2*adj)]); 219 | translate([2, depth-gap-1, -adj]) cube([2, gap+2, thick+(2*adj)]); 220 | translate([width-gap-1, (depth/2)-1, -adj]) cube([gap+2, 2, thick+(2*adj)]); 221 | translate([width-4, -1, -adj]) cube([2, gap+2, thick+(2*adj)]); 222 | translate([2, -1, -adj]) cube([2, gap+2, thick+(2*adj)]); 223 | } 224 | } 225 | if(shape == "round") { 226 | difference() { 227 | translate([(width/2),(width/2),0]) 228 | cylinder(d=width, h=thick); 229 | translate([(width/2), (width/2), -adj]) 230 | cylinder(d=width-gap, h=thick+2*adj); 231 | // cross ties 232 | translate([-1, (depth/2)-1, -adj]) cube([gap+2, 2, thick+(2*adj)]); 233 | translate([(width/2)-1, depth-gap-1, -adj]) cube([2, gap+2, thick+(2*adj)]); 234 | translate([width-gap-1, (depth/2)-1, -adj]) cube([gap+2, 2, thick+(2*adj)]); 235 | translate([(width/2)-1, -1, -adj]) cube([2, gap+2, thick+(2*adj)]); 236 | } 237 | } 238 | } 239 | 240 | 241 | /* vent opening */ 242 | module vent(width,length,height,gap,rows,columns,orientation) { 243 | 244 | fillet = width/2; 245 | adj = .01; 246 | $fn=90; 247 | 248 | // vertical orientation 249 | if(orientation == "vertical") { rotate([90 ,0, 0]) 250 | for (r=[0 : length+gap:rows*(length+gap)-1]) { 251 | for (c=[0 : width+(2*gap) : (columns*(width+(2*gap)))-1]) { 252 | translate ([c, r, -1]) cube([width, length, height]); 253 | } 254 | } 255 | } 256 | // horizontal orientation 257 | if(orientation == "horizontal") { 258 | for (r=[0 : length+(2*gap) : rows*(length+gap)]) { 259 | for (c=[0 : width+(2*gap) : (columns*(width+(2*gap)))-1]) { 260 | translate ([c,r,-1]) cube([width, length, height]); 261 | } 262 | } 263 | } 264 | } 265 | 266 | 267 | /* hex vent opening */ 268 | module vent_hex(cells_x, cells_y, thickness, cell_size, cell_spacing, orientation) { 269 | xs = cell_size + cell_spacing; 270 | ys = xs * sqrt(3/4); 271 | rot = (orientation == "vertical") ? 90 : 0; 272 | 273 | rotate([rot, 0, 0]) translate([cell_size/2, cell_size*sqrt(1/3),-1]) { 274 | for (ix=[0 : ceil(cells_x/2)-1]) { 275 | for (iy = [0 : 2 : cells_y-1]) { 276 | translate([ix*xs, iy*ys, 0]) rotate([0, 0, 90]) 277 | cylinder(r=cell_size/sqrt(3), h=thickness, $fn=6); 278 | } 279 | } 280 | for (ix=[0 : (cells_x/2)-1]) { 281 | for (iy = [1 : 2 : cells_y-1]) { 282 | translate([(ix+0.5)*xs, iy*ys, 0]) rotate([0, 0, 90]) 283 | cylinder(r=cell_size/sqrt(3), h=thickness, $fn=6); 284 | } 285 | } 286 | } 287 | } 288 | 289 | -------------------------------------------------------------------------------- /lib/smd.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: smd 20 | DESCRIPTION: creates smd components 21 | TODO: add other components 22 | 23 | USAGE: smd(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "led" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | size[0] = size_x 32 | size[1] = size_y 33 | size[2] = size_z 34 | data[0] = body color 35 | pcbsize_z = pcb thickness 36 | enablemask = true produces mask, false produces model 37 | mask[0] = true enables component mask 38 | mask[1] = mask length 39 | mask[2] = mask setback 40 | mask[3] = mstyle "default" 41 | 42 | */ 43 | 44 | // smd class 45 | module smd(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 46 | 47 | size_x = size[0]; 48 | size_y = size[1]; 49 | size_z = size[2]; 50 | bcolor = data[0]; 51 | adj = .01; 52 | 53 | // type led surface mount 54 | if(type=="led" && enablemask == false) { 55 | 56 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 57 | union() { 58 | color(bcolor) cube([size_x, size_y, size_z]); 59 | if(size_x >= size_y) { 60 | color("silver") translate([-adj, -adj, 0]) cube([size_x/6, size_y+(2*adj), size_z+adj]); 61 | color("silver") translate([size_x-(size_x/6)+adj, -adj, 0]) cube([size_x/6, size_y+(2*adj), size_z+adj]); 62 | } 63 | else { 64 | color("silver") translate([-adj, -adj, 0]) cube([size_x+(2*adj), (size_y/6), size_z+adj]); 65 | color("silver") translate([-adj, size_y-(size_y/6)+adj, 0]) cube([size_x+(2*adj), size_y/6, size_z+adj]); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/switch.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: switch 20 | DESCRIPTION: creates switches 21 | TODO: add other styles 22 | 23 | USAGE: switch(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "slide_4x9", "slide_7x3.5x1" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | pcbsize_z = pcb thickness 32 | enablemask = true produces mask, false produces model 33 | mask[0] = true enables component mask 34 | mask[1] = mask length 35 | mask[2] = mask setback 36 | mask[3] = mstyle "default" 37 | 38 | */ 39 | 40 | // switch class 41 | module switch(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 42 | 43 | cmask = mask[0]; 44 | mlen = mask[1]; 45 | back = mask[2]; 46 | mstyle = mask[3]; 47 | 48 | if(type == "slide_4x9") { 49 | 50 | size_x = 9; 51 | size_y = 3.75; 52 | size_xm = 9; 53 | size_ym = 4; 54 | 55 | if(enablemask == true && cmask == true && mstyle == "default") { 56 | // switch opening 57 | if(side == "top" && rotation == 0) { 58 | place(loc_x, loc_y-mlen+back, loc_z+.25, size_ym, size_xm, rotation, side, pcbsize_z) 59 | cube([size_xm, mlen, size_ym]); 60 | } 61 | if(side == "top" && rotation == 90) { 62 | place(loc_x-mlen+back, loc_y+5, loc_z+.25, size_ym, size_xm, rotation, side, pcbsize_z) 63 | cube([size_xm, mlen, size_ym]); 64 | } 65 | if(side == "top" && rotation == 180) { 66 | place(loc_x+5, loc_y-5.25+mlen-back, loc_z+.25, size_ym, size_xm, rotation, side, pcbsize_z) 67 | cube([size_xm, mlen, size_ym]); 68 | } 69 | if(side == "top" && rotation == 270) { 70 | place(loc_x-5.25+mlen-back, loc_y, loc_z+.25, size_ym, size_xm, rotation, side, pcbsize_z) 71 | cube([size_xm, mlen, size_ym]); 72 | } 73 | if(side == "bottom" && rotation == 0) { 74 | place(loc_x+5, loc_y-mlen+back, loc_z+.25, size_ym, size_xm, rotation, side, pcbsize_z) 75 | cube([size_xm, mlen, size_ym]); 76 | } 77 | if(side == "bottom" && rotation == 90) { 78 | place(loc_x-5.25+mlen-back, loc_y+5, loc_z+.25, size_ym, size_xm, rotation, side, pcbsize_z) 79 | cube([size_xm, mlen, size_ym]); 80 | } 81 | if(side == "bottom" && rotation == 180) { 82 | place(loc_x, loc_y-5.25+mlen-back, loc_z+.25, size_ym, size_xm, rotation, side, pcbsize_z) 83 | cube([size_xm, mlen, size_ym]); 84 | } 85 | if(side == "bottom" && rotation == 270) { 86 | place(loc_x-mlen+back, loc_y, loc_z+.25, size_ym, size_xm, rotation, side, pcbsize_z) 87 | cube([size_xm, mlen, size_ym]); 88 | } 89 | } 90 | if(enablemask == false) { 91 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 92 | union() { 93 | color("silver") translate([0, 0, .5]) cube([size_x, size_y, 3.5]); 94 | color("white") translate([3.75, -1.99, 1.75]) cube([3, 2, 1.5]); 95 | } 96 | } 97 | } 98 | if(type == "slide_7x3.5x1") { 99 | 100 | size_x = 7; 101 | size_y = 3.5; 102 | size_xm = 7; 103 | size_ym = 1.75; 104 | 105 | if(enablemask == true && cmask == true && mstyle == "default") { 106 | // switch opening 107 | if(side == "top" && rotation == 0) { 108 | place(loc_x, loc_y-mlen+back, loc_z, size_ym-.5, size_xm, rotation, side, pcbsize_z) 109 | cube([size_xm, mlen, size_ym]); 110 | } 111 | if(side == "top" && rotation == 90) { 112 | place(loc_x-mlen+back, loc_y+5, loc_z, size_ym-.5, size_xm, rotation, side, pcbsize_z) 113 | cube([size_xm, mlen, size_ym]); 114 | } 115 | if(side == "top" && rotation == 180) { 116 | place(loc_x+5, loc_y-5.25+mlen-back, loc_z-.5, size_ym, size_xm, rotation, side, pcbsize_z) 117 | cube([size_xm, mlen, size_ym]); 118 | } 119 | if(side == "top" && rotation == 270) { 120 | place(loc_x-5.25+mlen-back, loc_y, loc_z-.5, size_ym, size_xm, rotation, side, pcbsize_z) 121 | cube([size_xm, mlen, size_ym]); 122 | } 123 | if(side == "bottom" && rotation == 0) { 124 | place(loc_x+5, loc_y-mlen+back, loc_z-.5, size_ym, size_xm, rotation, side, pcbsize_z) 125 | cube([size_xm, mlen, size_ym]); 126 | } 127 | if(side == "bottom" && rotation == 90) { 128 | place(loc_x-5.25+mlen-back, loc_y+5, loc_z-.5, size_ym, size_xm, rotation, side, pcbsize_z) 129 | cube([size_xm, mlen, size_ym]); 130 | } 131 | if(side == "bottom" && rotation == 180) { 132 | place(loc_x, loc_y-5.25+mlen-back, loc_z-.5, size_ym, size_xm, rotation, side, pcbsize_z) 133 | cube([size_xm, mlen, size_ym]); 134 | } 135 | if(side == "bottom" && rotation == 270) { 136 | place(loc_x-mlen+back, loc_y, loc_z-.5, size_ym, size_xm, rotation, side, pcbsize_z) 137 | cube([size_xm, mlen, size_ym]); 138 | } 139 | } 140 | if(enablemask == false) { 141 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 142 | union() { 143 | color("silver") translate([0, 0, 0]) cube([size_x, size_y, 1.5]); 144 | color("white") translate([2, -.7, .25]) cube([3, .75, 1]); 145 | } 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /lib/terminal.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: terminal 20 | DESCRIPTION: creates terminal blocks 21 | TODO: add other styles 22 | 23 | USAGE: terminal(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) 24 | 25 | type = "gtb" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | size[0] = #positions 32 | size[1] = body depth 33 | size[2] = height 34 | data[0] = pitch 35 | data[1] = body color 36 | pcbsize_z = pcb thickness 37 | enablemask = true produces mask, false produces model 38 | mask[0] = true enables component mask 39 | mask[1] = mask length 40 | mask[2] = mask setback 41 | mask[3] = mstyle "default" 42 | 43 | */ 44 | 45 | // terminal block class 46 | module terminal(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 47 | 48 | cmask = mask[0]; 49 | mlen = mask[1]; 50 | back = mask[2]; 51 | mstyle = mask[3]; 52 | 53 | // type green terminal block 54 | if(type=="gtb") { 55 | 56 | pitch = data[0]; 57 | hcolor = data[1]; 58 | rows = size[0]; 59 | size_x = pitch * rows; 60 | size_y = size[1]; 61 | height = size[2]; 62 | pcolor = "#fee5a6"; 63 | 64 | adj = .01; 65 | $fn = 90; 66 | size_xm = size_x+2; 67 | size_ym = size_y+.5; 68 | 69 | if(enablemask == true && cmask == true && mstyle == "default") { 70 | if(side == "top" && rotation == 0) { 71 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 72 | union() { 73 | translate([0, back, 3]) rotate([90, 0, 0]) slot(5, size_x, mlen); 74 | for(r=[pitch/2:pitch:size_x]) { 75 | translate([r, 4.15, height-back]) cylinder(d=3.7, h=mlen); 76 | } 77 | } 78 | } 79 | if(side == "top" && rotation == 90) { 80 | place(loc_x, loc_y-2, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 81 | union() { 82 | translate([0, back, 3]) rotate([90, 0, 0]) slot(5, size_x, mlen); 83 | for(r=[pitch/2:pitch:size_x]) { 84 | translate([r, 4.15, height-back]) cylinder(d=3.7, h=mlen); 85 | } 86 | } 87 | } 88 | if(side == "top" && rotation == 180) { 89 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 90 | union() { 91 | translate([2,1+back,3]) rotate([90, 0, 0]) slot(5, size_x, mlen); 92 | for(r=[pitch/2:pitch:size_x]) { 93 | translate([r+2, 4.5, height-back]) cylinder(d=3.7, h=mlen); 94 | } 95 | } 96 | } 97 | if(side == "top" && rotation == 270) { 98 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 99 | union() { 100 | translate([0,.5+back,3]) rotate([90, 0, 0]) slot(5, size_x, mlen); 101 | for(r=[pitch/2:pitch:size_x]) { 102 | translate([r, 4.5, height-back]) cylinder(d=3.7, h=mlen); 103 | } 104 | } 105 | } 106 | if(side == "bottom" && rotation == 0) { 107 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 108 | union() { 109 | translate([2, back, 3]) rotate([90, 0, 0]) slot(5, size_x, mlen); 110 | for(r=[pitch/2:pitch:size_x]) { 111 | translate([r+2, 4.15, height-back]) cylinder(d=3.7, h=mlen); 112 | } 113 | } 114 | } 115 | if(side == "bottom" && rotation == 90) { 116 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 117 | union() { 118 | translate([2, .5+back, 3]) rotate([90, 0, 0]) slot(5, size_x, mlen); 119 | for(r=[pitch/2:pitch:size_x]) { 120 | translate([r+2, 4.5, height-back]) cylinder(d=3.7, h=mlen); 121 | } 122 | } 123 | } 124 | if(side == "bottom" && rotation == 180) { 125 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 126 | union() { 127 | translate([0, 1+back, 3]) rotate([90, 0, 0]) slot(5, size_x, mlen); 128 | for(r=[pitch/2:pitch:size_x]) { 129 | translate([r, 4.5, height-back]) cylinder(d=3.7, h=mlen); 130 | } 131 | } 132 | } 133 | if(side == "bottom" && rotation == 270) { 134 | place(loc_x, loc_y, loc_z, size_xm, size_ym, rotation, side, pcbsize_z) 135 | union() { 136 | translate([0, back, 3]) rotate([90, 0, 0]) slot(5, size_x, mlen); 137 | for(r=[pitch/2:pitch:size_x]) { 138 | translate([r, 4.15, height-back]) cylinder(d=3.7, h=mlen); 139 | } 140 | } 141 | } 142 | } 143 | if(enablemask == false) { 144 | 145 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 146 | union() { 147 | difference() { 148 | union() { 149 | color(hcolor) cube([size_x, size_y, height/2]); 150 | color(hcolor) translate([0, 0, (height/2)-.01]) cube([size_x, size_y, height/2]); 151 | } 152 | color(hcolor) translate([-1, -3, 6.99]) rotate([-15, 0, 0]) cube([(pitch*rows)+2, 3, 10]); 153 | color(hcolor) translate([-1, 8, 10]) rotate([15, 0, 0]) cube([(pitch*rows)+2, 3, 10]); 154 | for(r=[pitch/2:pitch:size_x]) { 155 | color(hcolor) translate([r, 4.15, height-3]) cylinder(d=3.7, h=4); 156 | } 157 | for(r=[.75:pitch:size_x]) { 158 | color(hcolor) translate([r, -1, 1]) cube([3.5,5,4]); 159 | } 160 | } 161 | for(r=[pitch/2:pitch:size_x]) { 162 | color(pcolor) translate([r, 4.15, -3.2]) cube([.64, .64, 3.3]); 163 | difference() { 164 | color("silver") translate([r, 4.15, height-2.5]) cylinder(d=3.7, h=2); 165 | color("silver") translate([r-.5, 4.15-(4.15/2), height-1.25]) cube([1,4,1]); 166 | } 167 | } 168 | for(r=[1:pitch:size_x]) { 169 | color("silver") translate([r, .5, 1]) cube([3, 4, .25]); 170 | color("silver") translate([r, .5, 4.5]) cube([3, 4, .5]); 171 | } 172 | } 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /lib/uart.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: uart 20 | DESCRIPTION: creates uart ports. 21 | TODO: 22 | 23 | USAGE: uart(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "molex_5267", "molex_5268" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | pcbsize_z = pcb thickness 32 | enablemask = true produces mask, false produces model 33 | mask[0] = true enables component mask 34 | mask[1] = mask length 35 | mask[2] = mask setback 36 | mask[3] = mstyle "none", "open", "knockout" 37 | 38 | */ 39 | 40 | // uart class 41 | module uart(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 42 | 43 | cmask = mask[0]; 44 | mlen = mask[1]; 45 | back = mask[2]; 46 | mstyle = mask[3]; 47 | knock_gap = 2; 48 | 49 | // uart micro connector straight 50 | if(type == "molex_5267") { 51 | 52 | size_x = 12.4; 53 | size_y = 5; 54 | size_z = 6; 55 | size_xm = size_x+2; 56 | size_zm = 6; 57 | 58 | if(enablemask == true && cmask == true && mstyle == "open") { 59 | 60 | if(side == "top" && rotation == 0) { 61 | place(loc_x-(size_xm-size_x)/2, loc_y-mlen+back, loc_z+5, size_x, mlen, rotation, side, pcbsize_z) 62 | cube([size_xm, mlen, size_zm]); 63 | } 64 | if(side == "top" && rotation == 90) { 65 | place(loc_x-mlen+back, loc_y+(size_xm-size_x)/2, loc_z+5, size_x, mlen, rotation, side, pcbsize_z) 66 | cube([size_xm, mlen, size_zm]); 67 | } 68 | if(side == "top" && rotation == 180) { 69 | place(loc_x+(size_xm-size_x)/2, loc_y+size_y-back, loc_z+5, size_x, mlen, rotation, side, pcbsize_z) 70 | cube([size_xm, mlen, size_zm]); 71 | } 72 | if(side == "top" && rotation == 270) { 73 | place(loc_x+size_y-back, loc_y-(size_xm-size_x)/2, loc_z+5, size_x, mlen, rotation, side, pcbsize_z) 74 | cube([size_xm, mlen, size_zm]); 75 | } 76 | if(side == "bottom" && rotation == 0) { 77 | place(loc_x+(size_xm-size_x)/2, loc_y-mlen+back, loc_z+5, size_x, mlen, rotation, side, pcbsize_z) 78 | cube([size_xm, mlen, size_zm]); 79 | } 80 | if(side == "bottom" && rotation == 90) { 81 | place(loc_x+size_y-back, loc_y+(size_xm-size_x)/2, loc_z+5, size_x, mlen, rotation, side, pcbsize_z) 82 | cube([size_xm, mlen, size_zm]); 83 | } 84 | if(side == "bottom" && rotation == 180) { 85 | place(loc_x-(size_xm-size_x)/2, loc_y+size_y-back, loc_z+5, size_x, mlen, rotation, side, pcbsize_z) 86 | cube([size_xm, mlen, size_zm]); 87 | } 88 | if(side == "bottom" && rotation == 270) { 89 | place(loc_x-mlen+back, loc_y-(size_xm-size_x)/2, loc_z+5, size_x, mlen, rotation, side, pcbsize_z) 90 | cube([size_xm, mlen, size_zm]); 91 | } 92 | } 93 | if(enablemask == true && cmask == true && (mstyle == "knockout" || mstyle == "default")) { 94 | 95 | if(side == "top" && rotation == 0) { 96 | place(loc_x-(size_xm-size_x)/2, loc_y, loc_z+5+back, size_x, mlen, rotation, side, pcbsize_z) 97 | rotate([90, 0, 0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 98 | } 99 | if(side == "top" && rotation == 90) { 100 | place(loc_x, loc_y+(size_xm-size_x)/2, loc_z+5, size_x, mlen, rotation, side, pcbsize_z) 101 | rotate([90, 0, 0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 102 | } 103 | if(side == "top" && rotation == 180) { 104 | place(loc_x+(size_xm-size_x)/2, loc_y-size_y, loc_z+5+back, size_x, mlen, rotation, side, pcbsize_z) 105 | rotate([90, 0, 0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 106 | } 107 | if(side == "top" && rotation == 270) { 108 | place(loc_x-size_y, loc_y-(size_xm-size_x)/2, loc_z+5+back, size_x, mlen, rotation, side, pcbsize_z) 109 | rotate([90, 0, 0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 110 | } 111 | if(side == "bottom" && rotation == 0) { 112 | place(loc_x+(size_xm-size_x)/2, loc_y, loc_z+5+back, size_x, mlen, rotation, side, pcbsize_z) 113 | rotate([90, 0, 0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 114 | } 115 | if(side == "bottom" && rotation == 90) { 116 | place(loc_x-size_y, loc_y+(size_xm-size_x)/2, loc_z+5+back, size_x, mlen, rotation, side, pcbsize_z) 117 | rotate([90, 0, 0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 118 | } 119 | if(side == "bottom" && rotation == 180) { 120 | place(loc_x-(size_xm-size_x)/2, loc_y-size_y, loc_z+5+back, size_x, mlen, rotation, side, pcbsize_z) 121 | rotate([90, 0, 0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 122 | } 123 | if(side == "bottom" && rotation == 270) { 124 | place(loc_x, loc_y-(size_xm-size_x)/2, loc_z+5+back, size_x, mlen, rotation, side, pcbsize_z) 125 | rotate([90, 0, 0]) knockout(size_xm, size_zm, 1, mlen, 2, "rectangle"); 126 | } 127 | } 128 | if(enablemask == false) { 129 | 130 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 131 | union() { 132 | difference() { 133 | union() { 134 | 135 | difference () { 136 | color("white") cube([size_x, size_y, 6]); 137 | color("white") translate([.5, .5, 2]) cube([11.5, 4, 6]); 138 | } 139 | color("white") translate([12, 3.75, .5]) rotate([0, 0, 45]) cube([1, 2, 5.5]); 140 | color("white") translate([-0.2, 4, .5]) rotate([0, 0, -45]) cube([1, 2, 5.5]); 141 | } 142 | color("white") translate([12.4, 0, -.5]) cube([2, 6, 7]); 143 | color("white") translate([-1, 0, -.5]) cube([1, 6, 7]); 144 | color("white") translate([-1, 5, -.5]) cube([14, 2, 7]); 145 | color("white") translate([-0.7, 4.5, -.1]) rotate([0, 0, -45]) cube([1, 2, 7]); 146 | color("white") translate([-1, 1.5, 2]) cube([14, 1, 7]); 147 | } 148 | for (i=[2.5:2.5:10]) { 149 | color("silver") translate ([i, 3, .5]) cube([.6, .6, 5]); 150 | } 151 | } 152 | } 153 | } 154 | // uart micro connector right angle 155 | if(type == "molex_5268") { 156 | 157 | size_x = 12.5; 158 | size_y = 6; 159 | size_z = 5; 160 | size_xm = size_x+2; 161 | size_zm = size_z+.5; 162 | 163 | if(enablemask == true && cmask == true && mstyle == "open") { 164 | if(side == "top" && rotation == 0) { 165 | place(loc_x-(size_xm-size_x)/2, loc_y-mlen+back, loc_z, size_x, mlen, rotation, side, pcbsize_z) 166 | cube([size_xm, mlen, size_zm]); 167 | } 168 | if(side == "top" && rotation == 90) { 169 | place(loc_x-mlen+back, loc_y+(size_xm-size_x)/2, loc_z, size_x, mlen, rotation, side, pcbsize_z) 170 | cube([size_xm, mlen, size_zm]); 171 | } 172 | if(side == "top" && rotation == 180) { 173 | place(loc_x+(size_xm-size_x)/2, loc_y+size_y-back, loc_z, size_x, mlen, rotation, side, pcbsize_z) 174 | cube([size_xm, mlen, size_zm]); 175 | } 176 | if(side == "top" && rotation == 270) { 177 | place(loc_x+size_y-back, loc_y-(size_xm-size_x)/2, loc_z, size_x, mlen, rotation, side, pcbsize_z) 178 | cube([size_xm, mlen, size_zm]); 179 | } 180 | if(side == "bottom" && rotation == 0) { 181 | place(loc_x+(size_xm-size_x)/2, loc_y-mlen+back, loc_z, size_x, mlen, rotation, side, pcbsize_z) 182 | cube([size_xm, mlen, size_zm]); 183 | } 184 | if(side == "bottom" && rotation == 90) { 185 | place(loc_x+size_y-back, loc_y+(size_xm-size_x)/2, loc_z, size_x, mlen, rotation, side, pcbsize_z) 186 | cube([size_xm, mlen, size_zm]); 187 | } 188 | if(side == "bottom" && rotation == 180) { 189 | place(loc_x-(size_xm-size_x)/2, loc_y+size_y-back, loc_z, size_x, mlen, rotation, side, pcbsize_z) 190 | cube([size_xm, mlen, size_zm]); 191 | } 192 | if(side == "bottom" && rotation == 270) { 193 | place(loc_x-mlen+back, loc_y-(size_xm-size_x)/2, loc_z, size_x, mlen, rotation, side, pcbsize_z) 194 | cube([size_xm, mlen, size_zm]); 195 | } 196 | } 197 | if(enablemask == true && cmask == true && (mstyle == "knockout" || mstyle == "default")) { 198 | 199 | if(side == "top" && rotation == 0) { 200 | place(loc_x-(size_xm-size_x)/2, loc_y, loc_z+back, size_x, mlen, rotation, side, pcbsize_z) 201 | rotate([90,0,0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 202 | } 203 | if(side == "top" && rotation == 90) { 204 | place(loc_x, loc_y+(size_xm-size_x)/2, loc_z, size_x, mlen, rotation, side, pcbsize_z) 205 | rotate([90,0,0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 206 | } 207 | if(side == "top" && rotation == 180) { 208 | place(loc_x+(size_xm-size_x)/2, loc_y-4, loc_z+back, size_x, mlen, rotation, side, pcbsize_z) 209 | rotate([90,0,0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 210 | } 211 | if(side == "top" && rotation == 270) { 212 | place(loc_x-4, loc_y-(size_xm-size_x)/2, loc_z+back, size_x, mlen, rotation, side, pcbsize_z) 213 | rotate([90,0,0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 214 | } 215 | if(side == "bottom" && rotation == 0) { 216 | place(loc_x+(size_xm-size_x)/2, loc_y, loc_z+back, size_x, mlen, rotation, side, pcbsize_z) 217 | rotate([90,0,0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 218 | } 219 | if(side == "bottom" && rotation == 90) { 220 | place(loc_x-4, loc_y+(size_xm-size_x)/2, loc_z+back, size_x, mlen, rotation, side, pcbsize_z) 221 | rotate([90,0,0]) knockout(size_xm, size_zm, 1, mlen, 2, "rectangle"); 222 | } 223 | if(side == "bottom" && rotation == 180) { 224 | place(loc_x-(size_xm-size_x)/2, loc_y-4, loc_z+back, size_x, mlen, rotation, side, pcbsize_z) 225 | rotate([90,0,0]) knockout(size_xm, size_zm, 1, mlen, 2, "rectangle"); 226 | } 227 | if(side == "bottom" && rotation == 270) { 228 | place(loc_x, loc_y-(size_xm-size_x)/2, loc_z+back, size_x, mlen, rotation, side, pcbsize_z) 229 | rotate([90,0,0]) knockout(size_xm, size_zm, knock_gap, mlen, 2, "rectangle"); 230 | } 231 | } 232 | if(enablemask == false) { 233 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 234 | rotate([0,0,0]) translate([0, 0, 0]) union() { 235 | difference() { 236 | union() { 237 | 238 | difference () { 239 | color("white") cube([size_x, size_y, size_z]); 240 | color("white") translate([.5, -2, .5]) cube([size_x-1, size_y, size_z-1]); 241 | } 242 | color("white") translate([0, 5, 3.925]) rotate([90, 45, 0]) cube([.75, 1.5, 5]); 243 | color("white") translate([11.9675, 5, 3.40625]) rotate([90, -45, 0]) cube([.75, 1.5, 5]); 244 | } 245 | color("white") translate([-1, 6.5, 4]) rotate([90, 45, 0]) cube([1, 4, 7]); 246 | color("white") translate([-1, 4, 1]) rotate([90, 0, 0]) cube([14, 1, 7]); 247 | } 248 | for (i=[2.5:2.5:10]) { 249 | color("silver") translate ([i, 0, 2.38]) cube([.6, 5, .6]); 250 | } 251 | } 252 | } 253 | } 254 | } -------------------------------------------------------------------------------- /lib/usbc.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | 18 | 19 | CLASS NAME: usbc 20 | DESCRIPTION: creates usbc ports. 21 | TODO: 22 | 23 | USAGE: usbc(type, loc_x, loc_y, loc_z, side, rotation[], size[], data[], pcbsize_z, enablemask, mask[]) 24 | 25 | type = "single_horizontal", "single_vertical" 26 | loc_x = x location placement 27 | loc_y = y location placement 28 | loc_z = z location placement 29 | side = "top", "bottom" 30 | rotation[] = object rotation 31 | pcbsize_z = pcb thickness 32 | enablemask = true produces mask, false produces model 33 | mask[0] = true enables component mask 34 | mask[1] = mask length 35 | mask[2] = mask setback 36 | mask[3] = mstyle "default" 37 | 38 | 39 | */ 40 | 41 | 42 | // usbc port class 43 | module usbc(type, loc_x, loc_y, loc_z, side, rotation, size, data, pcbsize_z, enablemask, mask) { 44 | 45 | cmask = mask[0]; 46 | mlen = mask[1]; 47 | back = mask[2]; 48 | mstyle = mask[3]; 49 | $fn=90; 50 | 51 | // usbc horizontal type 52 | if(type == "single_horizontal") { 53 | 54 | size_x = 9; 55 | size_xm = 10; 56 | size_y = 7; 57 | dia = 3.5; 58 | diam = 4.5; 59 | 60 | if(enablemask == true && cmask == true && mstyle == "default") { 61 | // single horizontal usbc opening 62 | if(side == "top" && rotation == 0) { 63 | place(loc_x+(size_x-size_xm)/2, loc_y+back, loc_z-.125+diam/2, size_x, mlen, rotation, side, pcbsize_z) 64 | rotate([90, 0, 0]) slot(diam, size_xm, mlen); 65 | } 66 | if(side == "top" && rotation == 90) { 67 | place(loc_x+back, loc_y-(size_x-size_xm)/2, loc_z-.125+diam/2, size_x, mlen, rotation, side, pcbsize_z) 68 | rotate([90, 0, 0]) slot(diam, size_xm, mlen); 69 | } 70 | if(side == "top" && rotation == 180) { 71 | place(loc_x-(size_x-size_xm)/2, loc_y-3-back, loc_z-.375+diam/2, size_x, mlen, rotation, side, pcbsize_z) 72 | rotate([90, 0, 0]) slot(diam, size_xm, mlen); 73 | } 74 | if(side == "top" && rotation == 270) { 75 | place(loc_x-3-back, loc_y+(size_x-size_xm)/2, loc_z+diam/2, size_x, mlen, rotation, side, pcbsize_z) 76 | rotate([90, 0, 0]) slot(diam, size_xm, mlen); 77 | } 78 | if(side == "bottom" && rotation == 0) { 79 | place(loc_x-(size_x-size_xm)/2, loc_y+back, loc_z-.125+diam/2, size_x, mlen, rotation, side, pcbsize_z) 80 | rotate([90, 0, 0]) slot(diam, size_xm, mlen); 81 | } 82 | if(side == "bottom" && rotation == 90) { 83 | place(loc_x-3-back, loc_y-(size_x-size_xm)/2, loc_z+diam/2, size_x, mlen, rotation, side, pcbsize_z) 84 | rotate([90, 0, 0]) slot(diam, size_xm, mlen); 85 | } 86 | if(side == "bottom" && rotation == 180) { 87 | place(loc_x+(size_x-size_xm)/2, loc_y-3-back, loc_z+diam/2, size_x-(size_x-size_xm), mlen, rotation, side, pcbsize_z) 88 | rotate([90, 0, 0]) slot(diam, size_xm, mlen); 89 | } 90 | if(side == "bottom" && rotation == 270) { 91 | place(loc_x+back, loc_y+(size_x-size_xm)/2, loc_z-.125+diam/2, size_x, mlen, rotation, side, pcbsize_z) 92 | rotate([90, 0, 0]) slot(diam, size_xm, mlen); 93 | } 94 | } 95 | if(enablemask == false) { 96 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 97 | rotate([90, 0, 0]) translate([dia/2, dia/2, -size_y]) union() { 98 | difference () { 99 | color("silver") 100 | hull() { 101 | cylinder(d=dia, h=size_y); 102 | translate([size_x-dia, 0, 0]) cylinder(d=dia, h=size_y); 103 | } 104 | color("silver") translate([0,0,1]) 105 | hull() { 106 | cylinder(d=3, h=size_y+.2); 107 | translate([size_x-dia, 0, 0]) cylinder(d=3, h=size_y+.2); 108 | } 109 | } 110 | color("black") translate([0, -1.2/2, .1]) cube([5.5, 1.2, 6]); 111 | } 112 | } 113 | } 114 | 115 | // usbc vertical type 116 | if(type == "single_vertical") { 117 | 118 | size_x = 9; 119 | size_y = 7; 120 | size_xm = 10; 121 | size_ym = 7; 122 | dia = 3.5; 123 | diam = 4; 124 | height = .5; 125 | 126 | if(enablemask == true && cmask == true && mstyle == "default") { 127 | // single vertical usbc opening 128 | if(side == "top" && rotation == 0) { 129 | place(loc_x-(diam-dia)/2+diam/2, loc_y+back, loc_z+size_xm, size_xm, mlen, rotation, side, pcbsize_z) 130 | rotate([90, 90, 0]) slot(diam, size_xm, mlen); 131 | } 132 | if(side == "top" && rotation == 90) { 133 | place(loc_x+back, loc_y-dia+(diam-dia)+height, loc_z+size_xm, size_xm, mlen, rotation, side, pcbsize_z) 134 | rotate([90, 90, 0]) slot(diam, size_xm, mlen); 135 | } 136 | if(side == "top" && rotation == 180) { 137 | place(loc_x-dia+(diam-dia)+height, loc_y-2-back, loc_z+size_xm, mlen, size_xm, rotation, side, pcbsize_z) 138 | rotate([90, 90, 0]) slot(diam, size_xm, mlen); 139 | } 140 | if(side == "top" && rotation == 270) { 141 | place(loc_x-2-back, loc_y-(diam-dia)/2+diam/2, loc_z+size_xm, mlen, size_xm, rotation, side, pcbsize_z) 142 | rotate([90, 90, 0]) slot(diam, size_xm, mlen); 143 | } 144 | if(side == "bottom" && rotation == 0) { 145 | place(loc_x-dia+(diam-dia)+height, loc_y+back, loc_z+size_xm, size_xm, mlen, rotation, side, pcbsize_z) 146 | rotate([90, 90, 0]) slot(diam, size_xm, mlen); 147 | } 148 | if(side == "bottom" && rotation == 90) { 149 | place(loc_x-back, loc_y-dia+(diam-dia)+height, loc_z+size_xm, size_xm, size_y, rotation, side, pcbsize_z) 150 | rotate([90, 90, 0]) slot(diam, size_xm, mlen); 151 | } 152 | if(side == "bottom" && rotation == 180) { 153 | place(loc_x-(diam-dia)/2+diam/2, loc_y-2-back, loc_z+size_xm, mlen, size_xm, rotation, side, pcbsize_z) 154 | rotate([90, 90, 0]) slot(diam, size_xm, mlen); 155 | } 156 | if(side == "bottom" && rotation == 270) { 157 | place(loc_x+back, loc_y-(diam-dia)/2+diam/2, loc_z+size_xm, size_xm, mlen, rotation, side, pcbsize_z) 158 | rotate([90, 90, 0]) slot(diam, size_xm, mlen); 159 | } 160 | } 161 | if(enablemask == false) { 162 | place(loc_x, loc_y, loc_z, size_x, size_y, rotation, side, pcbsize_z) 163 | rotate([90, 90 ,0]) translate([-size_y-.25-height, dia/2, -size_y]) 164 | union() { 165 | difference () { 166 | color("silver") 167 | hull() { 168 | cylinder(d=dia,h=size_y); 169 | translate([size_x-dia, 0, 0]) cylinder(d=dia, h=size_y); 170 | } 171 | color("silver") translate([0 ,0, 1]) 172 | hull() { 173 | cylinder(d=3, h=size_y+.2); 174 | translate([size_x-dia, 0, 0]) cylinder(d=3, h=size_y+.2); 175 | } 176 | } 177 | color("black") translate([0, -1.2/2, 1]) cube([5.5, 1.2, 6]); 178 | } 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /sbc_models.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hominoids/SBC_Model_Framework/0128dd7014f54863a99b1c547d2d0e290dff64c4/sbc_models.png -------------------------------------------------------------------------------- /sbc_models_library.scad: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of SBC Model Framework https://github.com/hominoids/SBC_Model_Framework 3 | Copyright 2019,2020,2021,2022,2023,2024 Edward A. Kisiel hominoid@cablemi.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see 16 | Code released under GPLv3: http://www.gnu.org/licenses/gpl.html 17 | */ 18 | 19 | include <./lib/place.scad> 20 | include <./lib/antenna.scad> 21 | include <./lib/audio.scad> 22 | include <./lib/b2b.scad> 23 | include <./lib/battery.scad> 24 | include <./lib/button.scad> 25 | include <./lib/cm.scad> 26 | include <./lib/discrete.scad> 27 | include <./lib/display.scad> 28 | include <./lib/fan.scad> 29 | include <./lib/fillets.scad> 30 | include <./lib/fpc.scad> 31 | include <./lib/gpio.scad> 32 | include <./lib/header.scad> 33 | include <./lib/heatsink.scad> 34 | include <./lib/ic.scad> 35 | include <./lib/jst.scad> 36 | include <./lib/memory.scad> 37 | include <./lib/molex.scad> 38 | include <./lib/network.scad> 39 | include <./lib/pcb.scad> 40 | include <./lib/pcie.scad> 41 | include <./lib/pillar.scad> 42 | include <./lib/power.scad> 43 | include <./lib/shape.scad> 44 | include <./lib/smd.scad> 45 | include <./lib/storage.scad> 46 | include <./lib/switch.scad> 47 | include <./lib/terminal.scad> 48 | include <./lib/uart.scad> 49 | include <./lib/usb2.scad> 50 | include <./lib/usb3.scad> 51 | include <./lib/usbc.scad> 52 | include <./lib/video.scad> -------------------------------------------------------------------------------- /sbc_models_viewer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hominoids/SBC_Model_Framework/0128dd7014f54863a99b1c547d2d0e290dff64c4/sbc_models_viewer.gif --------------------------------------------------------------------------------