├── .gitignore
├── .gitmodules
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── README_dotstar_8x8.md
├── case
├── dotstar_8x8
│ ├── 3mf
│ │ ├── base.3mf
│ │ ├── button_peg_backing.3mf
│ │ ├── button_peg_shaft.3mf
│ │ ├── prusa_slicer_project.3mf
│ │ └── top_cover.3mf
│ ├── dep
│ │ ├── NopSCADlib
│ │ │ ├── CHANGELOG.md
│ │ │ ├── COPYING
│ │ │ ├── core.scad
│ │ │ ├── global_defs.scad
│ │ │ ├── readme.md
│ │ │ ├── utils
│ │ │ │ ├── core
│ │ │ │ │ ├── bom.scad
│ │ │ │ │ ├── clip.scad
│ │ │ │ │ ├── core.scad
│ │ │ │ │ ├── global.scad
│ │ │ │ │ ├── polyholes.scad
│ │ │ │ │ ├── rounded_rectangle.scad
│ │ │ │ │ ├── sphere.scad
│ │ │ │ │ └── teardrops.scad
│ │ │ │ ├── dogbones.scad
│ │ │ │ ├── fillet.scad
│ │ │ │ ├── maths.scad
│ │ │ │ ├── quadrant.scad
│ │ │ │ ├── rounded_cylinder.scad
│ │ │ │ ├── sweep.scad
│ │ │ │ ├── thread.scad
│ │ │ │ └── tube.scad
│ │ │ └── vitamins
│ │ │ │ ├── insert.scad
│ │ │ │ ├── inserts.scad
│ │ │ │ ├── nut.scad
│ │ │ │ ├── nuts.scad
│ │ │ │ ├── pin_header.scad
│ │ │ │ ├── pin_headers.scad
│ │ │ │ ├── screw.scad
│ │ │ │ ├── screws.scad
│ │ │ │ ├── washer.scad
│ │ │ │ └── washers.scad
│ │ └── mattwach
│ │ │ ├── util.scad
│ │ │ └── vitamins
│ │ │ └── electronics
│ │ │ ├── adafruit_dotstar_8x8_matrix.scad
│ │ │ ├── buttons.scad
│ │ │ ├── cr2032_battery.scad
│ │ │ ├── ds3231_rtc.scad
│ │ │ └── pi_pico.scad
│ ├── lib
│ │ ├── matrix_clock_assembled_board.scad
│ │ ├── matrix_clock_kicad_pcb.step
│ │ └── matrix_clock_kicad_pcb.stl
│ └── matrix_clock_case.scad
└── led_matrix_64x32
│ ├── dep
│ ├── button_pcb.scad
│ ├── button_pcb_kicad.stl
│ ├── main_pcb.scad
│ └── main_pcb.stl
│ ├── export
│ ├── bottom_support.3mf
│ └── top_support.3mf
│ ├── led_matrix_64x32.scad
│ └── lib
│ ├── NopSCADlib
│ ├── CHANGELOG.md
│ ├── COPYING
│ ├── core.scad
│ ├── global_defs.scad
│ ├── readme.md
│ ├── utils
│ │ ├── core
│ │ │ ├── bom.scad
│ │ │ ├── clip.scad
│ │ │ ├── core.scad
│ │ │ ├── global.scad
│ │ │ ├── polyholes.scad
│ │ │ ├── rounded_rectangle.scad
│ │ │ ├── sphere.scad
│ │ │ └── teardrops.scad
│ │ ├── dogbones.scad
│ │ ├── fillet.scad
│ │ ├── maths.scad
│ │ ├── quadrant.scad
│ │ ├── rounded_cylinder.scad
│ │ ├── sweep.scad
│ │ ├── thread.scad
│ │ └── tube.scad
│ └── vitamins
│ │ ├── button.scad
│ │ ├── buttons.scad
│ │ ├── insert.scad
│ │ ├── inserts.scad
│ │ ├── nut.scad
│ │ ├── nuts.scad
│ │ ├── pin_header.scad
│ │ ├── pin_headers.scad
│ │ ├── screw.scad
│ │ ├── screws.scad
│ │ ├── washer.scad
│ │ └── washers.scad
│ └── mattwach
│ ├── honeycomb.scad
│ ├── util.scad
│ └── vitamins
│ └── electronics
│ ├── cr2032_battery.scad
│ ├── ds3231_rtc.scad
│ ├── led_panel_64x32.scad
│ └── pi_pico.scad
├── firmware
├── matrix_clock_dotstar_8x8.uf2
└── matrix_clock_led_64x32.uf2
├── images
├── button_hardware.jpg
├── clock_set.jpg
├── completed_pcb.jpg
├── console.png
├── ds8x8
│ ├── 3d_case_underside.png
│ ├── 3d_printed_case.png
│ ├── ds_matrix_clock.jpg
│ ├── matrix_clock2.jpg
│ ├── minicom.jpg
│ ├── numbers.jpg
│ ├── opened_clock.jpg
│ └── schematic.png
├── kicad_button_layout.png
├── kicad_layout.png
├── matrix_back.jpg
├── matrix_clock.jpg
├── matrix_only.jpg
├── matrix_with_numbers.jpg
├── openscad_bottom.png
├── openscad_model.png
├── openscad_top.png
├── other_matrix_modes.jpg
└── schematic.png
├── schematic
├── button_pcb_kicad
│ ├── button_pcb_kicad.kicad_pcb
│ ├── button_pcb_kicad.kicad_prl
│ ├── button_pcb_kicad.kicad_pro
│ ├── button_pcb_kicad.kicad_sch
│ ├── flatcam
│ │ ├── Project_20230128_192544.FlatPrj
│ │ ├── button_pcb_kicad-Edge_Cuts.gbr_cutout_cnc.nc
│ │ ├── button_pcb_kicad-F_Cu.gbr_iso_combined_cnc.nc
│ │ ├── button_pcb_kicad-NPTH.drl_cnc.nc
│ │ ├── button_pcb_kicad-PTH.drl_cnc.nc
│ │ └── test.nc
│ ├── fp-info-cache
│ └── gerber
│ │ ├── button_pcb_kicad-Edge_Cuts.gbr
│ │ ├── button_pcb_kicad-F_Cu.gbr
│ │ ├── button_pcb_kicad-NPTH.drl
│ │ ├── button_pcb_kicad-PTH.drl
│ │ └── button_pcb_kicad-job.gbrjob
├── dotstar_8x8_kicad
│ ├── export
│ │ ├── matrix_clock_kicad-B_Cu.gbr
│ │ ├── matrix_clock_kicad-Edge_Cuts.gbr
│ │ ├── matrix_clock_kicad-NPTH.drl
│ │ ├── matrix_clock_kicad-PTH.drl
│ │ └── matrix_clock_kicad-job.gbrjob
│ ├── flatcam
│ │ ├── matrix_clock.FlatPrj
│ │ ├── matrix_clock_kicad-B_Cu.gbr_iso_combined_cnc.nc
│ │ ├── matrix_clock_kicad-Edge_Cuts.gbr_edit_cutout_cnc.nc
│ │ ├── matrix_clock_kicad-PTH.mounting_drill.nc
│ │ ├── matrix_clock_kicad-PTH.small_drill.nc
│ │ └── test.nc
│ ├── fp-info-cache
│ ├── matrix_clock_kicad.kicad_pcb
│ ├── matrix_clock_kicad.kicad_prl
│ ├── matrix_clock_kicad.kicad_pro
│ ├── matrix_clock_kicad.kicad_sch
│ └── matrix_clock_kicad.net
└── led_matrix_64x32_kicad
│ ├── flatcam
│ ├── Project_20230127_103059.FlatPrj
│ └── led_matrix_64x32_kicad-F_Paste.nc
│ ├── fp-info-cache
│ ├── gerber
│ ├── led_matrix_64x32_kicad-F_Mask.gbr
│ ├── led_matrix_64x32_kicad-F_Mask.svg
│ ├── led_matrix_64x32_kicad-F_Paste.gbr
│ ├── led_matrix_64x32_kicad-F_Paste.svg
│ └── led_matrix_64x32_kicad-job.gbrjob
│ ├── led_matrix_64x32_kicad.kicad_pcb
│ ├── led_matrix_64x32_kicad.kicad_prl
│ ├── led_matrix_64x32_kicad.kicad_pro
│ ├── led_matrix_64x32_kicad.kicad_sch
│ └── led_matrix_64x32_kicad.net
└── src
├── CMakeLists.txt
├── bootstrap.sh
├── buttons.c
├── buttons.h
├── clock.h
├── clock_ds3231.c
├── clock_pico_internal.c
├── clock_render.c
├── clock_render.h
├── clock_settings.c
├── clock_settings.h
├── colors.c
├── colors.h
├── debounce.c
├── debounce.h
├── debug.c
├── debug.h
├── led_matrix.h
├── led_matrix_64x32.c
├── led_matrix_dotstar.c
├── main.c
├── monitor.c
├── monitor.h
├── number_draw.c
├── number_draw.h
├── pico_sdk_import.cmake
├── render
├── blank.c
├── blank.h
├── bounce.c
├── bounce.h
├── distances.inc
├── drops.c
├── drops.h
├── fade.c
├── fade.h
├── matrix.c
├── matrix.h
├── matrix_with_numbers.c
├── matrix_with_numbers.h
├── number_cascade.c
├── number_cascade.h
├── number_cascade_hires.c
├── number_cascade_hires.h
├── waveform.c
└── waveform.h
├── set_time_high_res.c
├── set_time_high_res.h
├── set_time_low_res.c
├── set_time_low_res.h
└── tools
└── distance_generator.py
/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | *-backups
3 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/pico_uart_console"]
2 | path = src/pico_uart_console
3 | url = https://github.com/mattwach/pico_uart_console.git
4 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cmake.sourceDirectory": "${workspaceFolder}/src",
3 | "cSpell.words": [
4 | "Dotstar",
5 | "Microcontroller",
6 | "Pico",
7 | "pullup",
8 | "TLDR"
9 | ]
10 | }
--------------------------------------------------------------------------------
/case/dotstar_8x8/3mf/base.3mf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/case/dotstar_8x8/3mf/base.3mf
--------------------------------------------------------------------------------
/case/dotstar_8x8/3mf/button_peg_backing.3mf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/case/dotstar_8x8/3mf/button_peg_backing.3mf
--------------------------------------------------------------------------------
/case/dotstar_8x8/3mf/button_peg_shaft.3mf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/case/dotstar_8x8/3mf/button_peg_shaft.3mf
--------------------------------------------------------------------------------
/case/dotstar_8x8/3mf/prusa_slicer_project.3mf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/case/dotstar_8x8/3mf/prusa_slicer_project.3mf
--------------------------------------------------------------------------------
/case/dotstar_8x8/3mf/top_cover.3mf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/case/dotstar_8x8/3mf/top_cover.3mf
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/core.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | // Include this file to use the minimum library plus screws, nuts and washers
22 | //
23 | include
24 | //
25 | // Fasteners used by a lot of other vitamins
26 | //
27 | include
28 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/global_defs.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | // This file included directly or indirectly in every scad file.
22 | //
23 | // This scheme allows the following:
24 | // bom defaults to 0
25 | // Setting $bom on the command line or in the main file before including lib.scad overrides it everywhere.
26 | // Setting $bom after including lib overrides bom in the libs but not in the local file.
27 | // Setting $_bom in the local file overrides it in the local file but not in the libs.
28 | //
29 | rr_green = [0, 146/255, 0]; // RepRap logo colour
30 | crimson = [220/255, 20/255, 60/255];
31 |
32 | $_bom = is_undef($bom) ? 0 : $bom; // 0 no bom, 1 assemblies and stls, 2 vitamins as well
33 | $exploded = is_undef($explode) ? 0 : $explode; // 1 for exploded view
34 | layer_height = is_undef($layer_height) ? 0.25 : $layer_height; // layer height when printing
35 | extrusion_width = is_undef($extrusion_width) ? 0.5 : $extrusion_width; // filament width when printing
36 | nozzle = is_undef($nozzle) ? 0.45 : $nozzle; // 3D printer nozzle
37 | cnc_bit_r = is_undef($cnc_bit_r) ? 1.2 : $cnc_bit_r; // minimum tool radius when milling 2D objects
38 | pp1_colour = is_undef($pp1_colour) ? rr_green : $pp1_colour; // printed part colour 1, RepRap logo colour
39 | pp2_colour = is_undef($pp2_colour) ? crimson : $pp2_colour; // printed part colour 2
40 | pp3_colour = is_undef($pp3_colour) ? "SteelBlue" : $pp3_colour; // printed part colour 3
41 | pp4_colour = is_undef($pp4_colour) ? "darkorange" : $pp4_colour;// printed part colour 4
42 | show_rays = is_undef($show_rays) ? false : $show_rays; // show camera sight lines and light direction
43 | show_threads = is_undef($show_threads) ? false : $show_threads; // show screw threads
44 |
45 | // Minimum wall is about two filaments wide but we extrude it closer to get better bonding
46 | squeezed_wall = $preview ? 2 * extrusion_width - layer_height * (1 - PI / 4)
47 | : extrusion_width - layer_height / 2 + nozzle / 2 + extrusion_width / 2;
48 |
49 | inf = 1e10; // very big
50 | eps = 1/128; // small fudge factor to stop CSG barfing on coincident faces.
51 | $fa = 6;
52 | $fs = extrusion_width / 2;
53 |
54 | function round_to_layer(z) = ceil(z / layer_height) * layer_height;
55 | // Some additional named colours
56 | function grey(n) = [0.01, 0.01, 0.01] * n; //! Generate a shade of grey to pass to color().
57 | silver = [0.75, 0.75, 0.75];
58 | gold = [255, 215, 0] / 255;
59 | brass = [255, 220, 100] / 255;
60 | copper = [230, 140, 51] / 255;
61 |
62 | /*
63 | * Enums
64 | */
65 | //
66 | // Screws
67 | //
68 | hs_cap = 0;
69 | hs_pan = 1;
70 | hs_cs = 2; // counter sunk
71 | hs_hex = 3;
72 | hs_grub = 4; // pulley set screw
73 | hs_cs_cap = 5;
74 | hs_dome = 6;
75 | //
76 | // Hot end descriptions
77 | //
78 | jhead = 1;
79 | e3d = 2;
80 | //
81 | // Face enumeration
82 | //
83 | f_bottom = 0;
84 | f_top = 1;
85 | f_left = 2;
86 | f_right = 3;
87 | f_front = 4;
88 | f_back = 5;
89 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/utils/core/clip.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Construct arbitrarily large box to partition 3D space and clip objects, useful for creating cross sections to see the inside when debugging.
22 | //!
23 | //! Original version by Doug Moen on the OpenSCAD forum
24 | //
25 | //
26 | module box(xmin, ymin, zmin, xmax, ymax, zmax) //! Construct a box given its bounds
27 | polyhedron(
28 | [[xmin, ymin, zmin], // 0
29 | [xmin, ymin, zmax], // 1
30 | [xmin, ymax, zmin], // 2
31 | [xmin, ymax, zmax], // 3
32 | [xmax, ymin, zmin], // 4
33 | [xmax, ymin, zmax], // 5
34 | [xmax, ymax, zmin], // 6
35 | [xmax, ymax, zmax]], // 7
36 | [[7,5,1,3], // top
37 | [2,0,4,6], // bottom
38 | [5,4,0,1], // front
39 | [3,2,6,7], // back
40 | [5,7,6,4], // right
41 | [0,2,3,1]] // left
42 | );
43 |
44 | module clip(xmin = -inf, ymin = -inf, zmin = -inf, xmax = inf, ymax = inf, zmax = inf) //! Clip child to specified boundaries
45 | render() intersection() {
46 | children();
47 |
48 | box(xmin, ymin, zmin, xmax, ymax, zmax);
49 | }
50 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/utils/core/core.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | // Include this file to use the minimum library
22 | //
23 | include <../../global_defs.scad>
24 | //
25 | // Global functions and modules
26 | //
27 | use
28 |
29 | module use_stl(name) { //! Import an STL to make a build platter
30 | stl(name);
31 | path = is_undef($target) ? "../stls/" : str($cwd, "/", $target, "/stls/");
32 | import(str(path, name, ".stl"));
33 | }
34 |
35 | module use_dxf(name) { //! Import a DXF to make a build panel
36 | dxf(name);
37 | path = is_undef($target) ? "../dxfs/" : str($cwd, "/", $target, "/dxfs/");
38 | import(str(path, name, ".dxf"));
39 | }
40 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/utils/core/global.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Global constants, functions and modules. This file is used directly or indirectly in every scad file.
22 | //
23 | include <../../global_defs.scad>
24 |
25 | function inch(x) = x * 25.4; //! Inch to mm conversion (For fractional inches, 'inch(1 + 7/8)' will work as expected.)
26 | function foot(x) = x * 25.4 * 12; //! Foot to mm conversion
27 | function yard(x) = x * 25.4 * 12 * 3; //! Yard to mm conversion
28 | function mm(x) = x; //! Explicit mm specified
29 | function cm(x) = x * 10.0; //! cm to mm conversion
30 | function m(x) = x * 1000.0; //! m to mm conversion
31 |
32 | function sqr(x) = x * x; //! Returns the square of `x`
33 | function echoit(x) = echo(x) x; //! Echo expression and return it, useful for debugging
34 | function no_point(str) = chr([for(c = str(str)) if(c == ".") ord("p") else ord(c)]);//! Replace decimal point in string with 'p'
35 | function in(list, x) = !!len([for(v = list) if(v == x) true]); //! Returns true if `x` is an element in the `list`
36 | function Len(x) = is_list(x) ? len(x) : 0; //! Returns the length of a list or 0 if `x` is not a list
37 | function r2sides(r) = $fn ? $fn : ceil(max(min(360/ $fa, r * 2 * PI / $fs), 5)); //! Replicates the OpenSCAD logic to calculate the number of sides from the radius
38 | function r2sides4n(r) = floor((r2sides(r) + 3) / 4) * 4; //! Round up the number of sides to a multiple of 4 to ensure points land on all axes
39 | function limit(x, min, max) = max(min(x, max), min); //! Force x in range min <= x <= max
40 |
41 | module translate_z(z) translate([0, 0, z]) children(); //! Shortcut for Z only translations
42 | module vflip(flip=true) rotate([flip ? 180 : 0, 0, 0]) children(); //! Invert children by doing a 180° flip around the X axis
43 | module hflip(flip=true) rotate([0, flip ? 180: 0, 0]) children(); //! Invert children by doing a 180° flip around the Y axis
44 | module ellipse(xr, yr) scale([1, yr / xr]) circle4n(xr); //! Draw an ellipse
45 |
46 | function slice_str(str, start, end, s ="") = start >= end ? s : slice_str(str, start + 1, end, str(s, str[start])); // Helper for slice()
47 |
48 | function slice(list, start = 0, end = undef) = let( //! Slice a list or string with Python type semantics
49 | len = len(list),
50 | start = limit(start < 0 ? len + start : start, 0, len),
51 | end = is_undef(end) ? len : limit(end < 0 ? len + end : end, 0, len)
52 | ) is_string(list) ? slice_str(list, start, end) : [for(i = [start : 1 : end - 1]) list[i]];
53 |
54 |
55 | module render_if(render = true, convexity = 2) //! Renders an object if `render` is true, otherwise leaves it unrendered
56 | if (render)
57 | render(convexity = convexity)
58 | children();
59 | else
60 | children();
61 |
62 | module extrude_if(h, center = true) //! Extrudes 2D object to 3D when `h` is nonzero, otherwise leaves it 2D
63 | if(h)
64 | linear_extrude(h, center = center, convexity = 2) // 3D
65 | children();
66 | else
67 | children(); // 2D
68 |
69 | module circle4n(r, d = undef) { //! Circle with multiple of 4 vertices
70 | R = is_undef(d) ? r : d / 2;
71 | circle(R, $fn = r2sides4n(R));
72 | }
73 |
74 | module semi_circle(r, d = undef) //! A semi circle in the positive Y domain
75 | intersection() {
76 | R = is_undef(d) ? r : d / 2;
77 | circle4n(R);
78 |
79 | sq = R + 1;
80 | translate([-sq, 0])
81 | square([2 * sq, sq]);
82 | }
83 |
84 | module right_triangle(width, height, h, center = true) //! A right angled triangle with the 90° corner at the origin. 3D when `h` is nonzero, otherwise 2D
85 | extrude_if(h, center = center)
86 | polygon(points = [[0,0], [width, 0], [0, height]]);
87 |
88 | include
89 | include
90 | include
91 | include
92 | include
93 | include
94 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/utils/core/rounded_rectangle.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Rectangle with rounded corners.
22 | //
23 | module rounded_square(size, r, center = true) //! Like `square()` but with with rounded corners
24 | {
25 | assert(r < min(size.x, size.y) / 2);
26 | $fn = r2sides4n(r);
27 | offset(r) offset(-r) square(size, center = center);
28 | }
29 |
30 | module rounded_rectangle(size, r, center = false, xy_center = true) //! Like `cube()` but corners rounded in XY plane and separate centre options for xy and z.
31 | {
32 | extrude_if(size.z, center = center)
33 | rounded_square([size.x, size.y], r, xy_center);
34 | }
35 |
36 | module rounded_cube_xy(size, r = 0, xy_center = false, z_center = false) //! Like `cube()` but corners rounded in XY plane and separate centre options for xy and z.
37 | {
38 | extrude_if(size.z, center = z_center)
39 | rounded_square([size.x, size.y], r, xy_center);
40 | }
41 |
42 | module rounded_cube_xz(size, r = 0, xy_center = false, z_center = false) //! Like `cube()` but corners rounded in XZ plane and separate centre options for xy and z.
43 | {
44 | translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, z_center ? 0 : size.z / 2])
45 | rotate([90, 0, 0])
46 | rounded_cube_xy([size.x, size.z, size.y], r, xy_center = true, z_center = true);
47 | }
48 |
49 | module rounded_cube_yz(size, r = 0, xy_center = false, z_center = false) //! Like `cube()` but corners rounded in YX plane and separate centre options for xy and z.
50 | {
51 | translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, z_center ? 0 : size.z / 2])
52 | rotate([90, 0, 90])
53 | rounded_cube_xy([size.y, size.z, size.x], r, xy_center = true, z_center = true);
54 | }
55 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/utils/core/sphere.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //! Redefines `sphere()` to always have a vertex on all six half axes I.e. vertices at the poles and the equator and `$fn` a multiple of four.
21 | //! This ensures `hull` and `minkowski` results have the correct dimensions when spheres are placed at the corners.
22 |
23 | module sphere(r = 1, d = undef) { //! Override `sphere` so that has vertices on all three axes. Has the advantage of giving correct dimensions when hulled
24 | R = is_undef(d) ? r : d / 2;
25 | rotate_extrude($fn = r2sides4n(R))
26 | rotate(-90)
27 | semi_circle(R);
28 | }
29 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/utils/dogbones.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! When square holes are cut with a CNC bit they get rounded corners. If it is important that
22 | //! a square cornered part fits in the hole then circles are placed in the corners making a bone shape.
23 | //
24 | include <../utils/core/core.scad>
25 |
26 | module dogbone_square(size, r = cnc_bit_r, center = true, x_offset, y_offset) //! Square with circles at the corners, with optional offsets
27 | {
28 | x_offset = is_undef(x_offset) ? r / sqrt(2) : x_offset;
29 | y_offset = is_undef(y_offset) ? r / sqrt(2) : y_offset;
30 |
31 | union() {
32 | square(size, center = center);
33 |
34 | if(r > 0) {
35 | origin = center ? [0, 0] : size / 2;
36 |
37 | for(x = [-1, 1], y = [-1, 1])
38 | translate(origin + [x * (size.x / 2 - x_offset), y * (size.y / 2 - y_offset)])
39 | drill(r, 0);
40 | }
41 | }
42 | }
43 |
44 | module dogbone_rectangle(size, r = cnc_bit_r, center = true, xy_center = true, x_offset, y_offset) //! Rectangle with cylinders at the corners
45 | {
46 | extrude_if(h = size.z, center = center)
47 | dogbone_square([size.x, size.y], r, xy_center, x_offset, y_offset);
48 | }
49 |
50 | module dogbone_rectangle_x(size, r = cnc_bit_r, center = true, xy_center = true) //! Rectangle with cylinders at the corners, offset in the x direction
51 | {
52 | dogbone_rectangle(size = size, r = r, center = center, x_offset = 0, y_offset = r);
53 | }
54 |
55 | module dogbone_rectangle_y(size, r = cnc_bit_r, center = true, xy_center = true) //! Rectangle with cylinders at the corners, offset in the y direction
56 | {
57 | dogbone_rectangle(size = size, r = r, center = center, x_offset = r, y_offset = 0);
58 | }
59 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/utils/fillet.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Rounded fillet for adding to corners.
22 | //
23 | include <../utils/core/core.scad>
24 |
25 | module fillet(r, h, center = false) //! Fillet with specified radius and height
26 | extrude_if(h, center = center)
27 | difference() {
28 | translate([-eps, -eps, 0])
29 | square(r + eps);
30 |
31 | translate([r, r])
32 | circle(r + eps);
33 | }
34 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/utils/quadrant.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Square with one rounded corner.
22 | //
23 | include <../utils/core/core.scad>
24 |
25 | module quadrant(w, r, center = false) { //! Draw a square with one rounded corner, can be centered on the arc centre, when `center` is `true`.
26 | h = is_list(w) ? w.y : w;
27 | w = is_list(w) ? w.x : w;
28 | offset_w = center ? r - w : 0;
29 | offset_h = center ? r - h : 0;
30 | translate([offset_w, offset_h])
31 | hull() {
32 | intersection() {
33 | translate([w - r, h - r])
34 | circle4n(r);
35 |
36 | square([w, h]);
37 | }
38 |
39 | square([w, eps]);
40 |
41 | square([eps, h]);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/utils/rounded_cylinder.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Cylinder with a rounded end.
22 | //
23 | include <../utils/core/core.scad>
24 |
25 | module rounded_corner(r, h, r2, ir = 0) { //! 2D version
26 | assert(ir <= r - r2);
27 |
28 | translate([ir , 0])
29 | hull() {
30 | square([eps, h]);
31 |
32 | square([r - ir, eps]);
33 |
34 | translate([r - r2 - ir, h - r2])
35 | intersection() {
36 | circle4n(r2, $fs = 0.2);
37 |
38 | square(r2);
39 | }
40 | }
41 | }
42 |
43 | module rounded_cylinder(r, h, r2, ir = 0, angle = 360) //! Rounded cylinder given radius `r`, height `h`, optional internal radius `ir` and optional `angle`
44 | {
45 | rotate_extrude(angle = angle)
46 | rounded_corner(r, h, r2, ir);
47 | }
48 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/utils/tube.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Simple tube or ring
22 | //
23 | include <../utils/core/core.scad>
24 |
25 | module ring(or, ir) //! Create a ring with specified external and internal radii
26 | difference() {
27 | circle4n(or);
28 | circle4n(ir);
29 | }
30 |
31 | module tube(or, ir, h, center = true) //! Create a tube with specified external and internal radii and height `h`
32 | linear_extrude(h, center = center, convexity = 5)
33 | ring(or, ir);
34 |
35 | module woven_tube(or, ir, h, center= true, colour = grey(30), colour2, warp = 2, weft) {//! Create a woven tube with specified external and internal radii, height `h`, colours, warp and weft
36 | colour2 = colour2 ? colour2 : colour * 0.8;
37 | weft = weft ? weft : warp;
38 | warp_count = max(floor(PI * or / warp), 0.5);
39 | angle = 360 / (2 * warp_count);
40 |
41 | module layer(weft) {
42 | points = [[ir, weft / 2], [or, weft / 2], [or, -weft / 2], [ir, -weft / 2]];
43 | color(colour)
44 | for (i = [0 : warp_count])
45 | rotate(2 * i * angle)
46 | rotate_extrude(angle = angle)
47 | polygon(points);
48 | color(colour2)
49 | for (i = [0 : warp_count])
50 | rotate((2 * i + 1) * angle)
51 | rotate_extrude(angle = angle)
52 | polygon(points);
53 | }
54 |
55 | translate_z(center ? -h / 2 : 0) {
56 | weft_count = floor(h / weft);
57 | if (weft_count > 0)
58 | for (i = [0 : weft_count - 1]) {
59 | translate_z(i * weft + weft / 2)
60 | rotate(i * angle)
61 | layer(weft);
62 | }
63 | remainder = h - weft * weft_count;
64 | if (remainder) {
65 | translate_z(weft_count * weft + remainder / 2)
66 | rotate(weft_count * angle)
67 | layer(remainder);
68 | }
69 | }
70 | }
71 |
72 | module rectangular_tube(size, center = true, thickness = 1, fillet = 0.5) { //! Create a rectangular tube with filleted corners
73 | extrude_if(size.z, center = center)
74 | difference() {
75 | rounded_square([size.x, size.y], fillet);
76 | rounded_square([size.x - 2 * thickness, size.y - 2 * thickness], fillet);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/vitamins/inserts.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | // Threaded inserts
22 | //
23 | // l o h s b r r r
24 | // e u o c a i i i
25 | // n t l r r n n n
26 | // g e e e r g g g
27 | // t r w e 1 2 3
28 | // h d l
29 | // d d h d d
30 | // d
31 | //
32 | F1BM2 = [ "F1BM2", 4.0, 3.6, 3.2, 2, 3.0, 1.0, 3.4, 3.1 ];
33 | F1BM2p5 = [ "F1BM2p5", 5.8, 4.6, 4.0, 2.5, 3.65, 1.6, 4.4, 3.9 ];
34 | F1BM3 = [ "F1BM3", 5.8, 4.6, 4.0, 3, 3.65, 1.6, 4.4, 3.9 ];
35 | F1BM4 = [ "F1BM4", 8.2, 6.3, 5.6, 4, 5.15, 2.3, 6.0, 5.55 ];
36 |
37 | inserts = [ F1BM2, F1BM2p5, F1BM3, F1BM4 ];
38 |
39 | use
40 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/vitamins/nuts.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 | include
20 | //
21 | // Nuts
22 | //
23 | M2_nut_trap_depth = 2.5;
24 | M2p5_nut_trap_depth = 2.5;
25 | M3_nut_trap_depth = 3;
26 | M4_nut_trap_depth = 4;
27 | M5_nut_depth = 4;
28 | M6_nut_depth = 5;
29 | M8_nut_depth = 6.5;
30 |
31 | // s r t n w t t
32 | // c a h y a r h
33 | // r d i l s a r
34 | // e i c o h p e
35 | // w u k c e d
36 | // s n r d
37 | // e t e p
38 | // s h p i
39 | // s k t t
40 | // h c
41 | // h
42 | M2_nut = ["M2_nut", 2, 4.9, 1.6, 2.4, M2_washer, M2_nut_trap_depth, 0];
43 | M2p5_nut = ["M2p5_nut", 2.5, 5.8, 2.2, 3.8, M2p5_washer, M2p5_nut_trap_depth, 0];
44 | M3_nut = ["M3_nut", 3, 6.4, 2.4, 4, M3_washer, M3_nut_trap_depth, 0];
45 | M4_nut = ["M4_nut", 4, 8.1, 3.2, 5, M4_washer, M4_nut_trap_depth, 0];
46 | M5_nut = ["M5_nut", 5, 9.2, 4, 6.25, M5_washer, M5_nut_depth, 0];
47 | M6_nut = ["M6_nut", 6, 11.5, 5, 8, M6_washer, M6_nut_depth, 0];
48 | M6_half_nut = ["M6_half_nut", 6, 11.5, 3, 8, M6_washer, 3, 0];
49 | M8_nut = ["M8_nut", 8, 15, 6.5, 8, M8_washer, M8_nut_depth, 0];
50 | toggle_nut = ["toggle_nut", 6.1, 9.2, 1.5, 1.5, M6_washer, 1.5, inch(1/40)];
51 |
52 | M4_wingnut = ["M4_wingnut", 4, 10, 3.75,8, M4_washer, 0, 22, 10, 6, 3];
53 | // sx ty1 ty2 hammer
54 | M3_sliding_t_nut = ["M3_sliding_t_nut", 3, 6, 3.0, 4.0, false, 0, 10, 10, 6, false];
55 | M4_sliding_t_nut = ["M4_sliding_t_nut", 4, 6, 3.25,4.5, false, 0, 11, 10, 6, false];
56 | M5_sliding_t_nut = ["M5_sliding_t_nut", 5, 6, 3.25,4.5, false, 0, 11, 10, 7, false];
57 | M3_hammer_nut = ["M3_hammer_nut", 3, 6, 2.75,4.0, false, 0, 5.5, 10, 6, true];
58 | M4_hammer_nut = ["M4_hammer_nut", 4, 6, 3.25,4.5, false, 0, 5.5, 10, 6, true];
59 |
60 | // DIN 562 (thin) square nuts
61 | // s w h
62 | // c i e
63 | // r d i
64 | // e t g
65 | // w h h
66 | // t
67 | //
68 | M3nS_thin_nut = ["M3nS_thin_nut", 3, 5.5, 1.8];
69 | M4nS_thin_nut = ["M4nS_thin_nut", 4, 7, 2.2];
70 | M5nS_thin_nut = ["M5nS_thin_nut", 5, 8, 2.7];
71 | M6nS_thin_nut = ["M6nS_thin_nut", 6, 10, 3.2];
72 | M8nS_thin_nut = ["M8nS_thin_nut", 8, 13, 4];
73 |
74 | nuts = [M2_nut, M2p5_nut, M3_nut, M4_nut, M5_nut, M6_nut, M8_nut];
75 |
76 | use
77 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/vitamins/pin_headers.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | // p p b p p b s b b p r r
21 | // i i e i i a o o o i a a
22 | // t n l n n s c x x n
23 | // c o e k b h
24 | // h l w w c s t y
25 | // c h z o
26 | // f
27 | 2p54header = ["2p54header", 2.54, 11.6, 3.2, 0.66, gold, grey(20), 8.5, [0, 0, 8.7], 2.4, 0, 0, 0 ];
28 | 2p54joiner = ["2p54joiner", 2.54, 6.86, 2.5, 0.66, gold, grey(20), 8.5, [0, 0, 8.7], 2.4, 0, 0, 0 ]; // Cropped pins for joining PCBs
29 |
30 | jst_xh_header = ["jst_xh_header",2.5, 10, 3.4, 0.64, gold, grey(90), 0, [4.9, 5.75, 7], 0.8, 0.525, 0.6, 6.1];
31 | jst_ph_header = ["jst_ph_header",2.0, 9, 3.4, 0.64, silver, grey(90), 0, [3.9, 4.5, 6], 0.6, 0.55, 0.25, 4.8];
32 |
33 | pin_headers = [ 2p54header ];
34 |
35 | use
36 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/NopSCADlib/vitamins/washers.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | // Washers
22 | //
23 | // s d t s s s s p
24 | // c i h o t p p e
25 | // r a i f a r r n
26 | // e m c t r i i n
27 | // w e k n n y
28 | // t n d g g
29 | // e e i v
30 | // r s a d t e
31 | // s i h r
32 | // a k
33 | M3_penny_washer = ["M3_penny", 3, 12, 0.8, false, 5.8, 5.6, 1.0, true];
34 | M4_penny_washer = ["M4_penny", 4, 14, 0.8, false, 7.9, 7.0, 1.2, true];
35 | M5_penny_washer = ["M5_penny", 5, 20, 1.4, false, 9.0, 8.8, 1.6, true];
36 | M6_penny_washer = ["M6_penny", 6, 26, 1.5, false, 10.6, 9.9, 1.6, true];
37 | M8_penny_washer = ["M8_penny", 8, 30, 1.5, false, 13.8, 12.7, 2.0, true];
38 |
39 | M2_washer = ["M2", 2, 5, 0.3, false, 4.5, 4.4, 0.5, undef];
40 | M2p5_washer = ["M2p5", 2.5, 5.9, 0.5, false, 5.4, 5.1, 0.6, undef];
41 | M3_washer = ["M3", 3, 7, 0.5, false, 5.8, 5.6, 1.0, M3_penny_washer];
42 | M3p5_washer = ["M3p5", 3.5, 8, 0.5, false, 6.9, 6.2, 1.0, undef];
43 | M4_washer = ["M4", 4, 9, 0.8, false, 7.9, 7.0, 1.2, M4_penny_washer];
44 | M5_washer = ["M5", 5, 10, 1.0, false, 9.0, 8.8, 1.6, M5_penny_washer];
45 | M6_washer = ["M6", 6, 12.5, 1.5, false, 10.6, 9.9, 1.6, M6_penny_washer];
46 | M8_washer = ["M8", 8, 17, 1.6, false, 13.8, 12.7, 2.0, M8_penny_washer];
47 | toggle_washer = ["toggle", 6.1,12, 0.6, false, 10, 0, 0, undef];
48 |
49 | M3_rubber_washer= ["M3_rubber",3, 10, 1.5, true, 5.8, M3_penny_washer];
50 |
51 | washers = [M2_washer, M2p5_washer, M3_washer, M3p5_washer, M4_washer, M5_washer, M6_washer, M8_washer, M3_rubber_washer];
52 |
53 | use
54 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/mattwach/util.scad:
--------------------------------------------------------------------------------
1 | module tx(x) translate([x,0,0]) children();
2 | module ty(y) translate([0,y,0]) children();
3 | module tz(z) translate([0,0,z]) children();
4 |
5 | // Planes
6 | module txy(x, y) translate([x,y,0]) children();
7 | module txz(x, z) translate([x,0,z]) children();
8 | module tyz(y, z) translate([0,y,z]) children();
9 |
10 | module boardxy(x, y, pin_spacing=2.54) {
11 | translate([x * pin_spacing, y * pin_spacing,0]) children();
12 | }
13 |
14 |
15 | module rx(x) rotate([x,0,0]) children();
16 | module ry(y) rotate([0,y,0]) children();
17 | module rz(z) rotate([0,0,z]) children();
18 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/mattwach/vitamins/electronics/adafruit_dotstar_8x8_matrix.scad:
--------------------------------------------------------------------------------
1 | use <../../util.scad>
2 |
3 | DOTSTAR_8X8_BASE_WIDTH = 25.4;
4 | DOTSTAR_8X8_WIDTH_WITH_TABS = 35.8;
5 | DOTSTAR_8X8_TAB_WIDTH = (DOTSTAR_8X8_WIDTH_WITH_TABS - DOTSTAR_8X8_BASE_WIDTH) / 2;
6 | DOTSTAR_8X8_TAB_HOLE_DIAMETER = 3.3;
7 | DOTSTAR_8X8_PCB_THICKNESS = 1.5;
8 | DOTSTAR_8X8_THICKNESS = 2.4;
9 | DOTSTAR_8X8_BOLT_SPAN = DOTSTAR_8X8_BASE_WIDTH - DOTSTAR_8X8_TAB_WIDTH;
10 |
11 | module adafruit_dotstar_8x8_matrix(include_tabs=true) {
12 | overlap = 0.01;
13 |
14 | module base_pcb() {
15 | color("#222") cube([
16 | DOTSTAR_8X8_BASE_WIDTH,
17 | DOTSTAR_8X8_BASE_WIDTH,
18 | DOTSTAR_8X8_PCB_THICKNESS]);
19 | }
20 |
21 | module tab() {
22 | module main() {
23 | color("#222") cube([
24 | DOTSTAR_8X8_TAB_WIDTH,
25 | DOTSTAR_8X8_TAB_WIDTH,
26 | DOTSTAR_8X8_PCB_THICKNESS]);
27 | }
28 | module hole() {
29 | translate([
30 | DOTSTAR_8X8_TAB_WIDTH / 2,
31 | DOTSTAR_8X8_TAB_WIDTH / 2,
32 | -overlap]) cylinder(
33 | d=DOTSTAR_8X8_TAB_HOLE_DIAMETER,
34 | DOTSTAR_8X8_PCB_THICKNESS + overlap * 2);
35 | }
36 | difference() {
37 | main();
38 | hole();
39 | }
40 | }
41 |
42 | module pads() {
43 | pad_side_offset = 1.27;
44 | pad_diameter = 2;
45 | pad_spacing = 2.54;
46 | pad_depth = 0.1;
47 | pad_text_size = 1.2;
48 | module pad() {
49 | tz(-overlap) color("gold") cylinder(d=pad_diameter, h=pad_depth);
50 | }
51 |
52 | module bottom_pads() {
53 | module pad_with_label(label) {
54 | txy(pad_side_offset, pad_side_offset) pad();
55 | translate([
56 | pad_side_offset - (pad_text_size / 2),
57 | pad_spacing,
58 | pad_depth - overlap])
59 | color("white")
60 | ry(180) rz(90)
61 | linear_extrude(pad_depth) text(label, size=pad_text_size);
62 | }
63 |
64 | pad_with_label("COUT");
65 | tx(pad_spacing) pad_with_label("DOUT");
66 | tx(pad_spacing * 2) pad_with_label("GND");
67 | tx(pad_spacing * 3) pad_with_label("+5V");
68 | }
69 |
70 | module top_pads() {
71 | module pad_with_label(label) {
72 | txy(DOTSTAR_8X8_BASE_WIDTH - pad_side_offset,
73 | DOTSTAR_8X8_BASE_WIDTH - pad_side_offset) pad();
74 | translate([
75 | DOTSTAR_8X8_BASE_WIDTH - pad_side_offset - (pad_text_size / 2),
76 | DOTSTAR_8X8_BASE_WIDTH - pad_spacing,
77 | pad_depth - overlap])
78 | color("white")
79 | ry(180) rz(90)
80 | linear_extrude(pad_depth) text(label, size=pad_text_size, halign="right");
81 | }
82 |
83 | pad_with_label("CIN");
84 | tx(-pad_spacing) pad_with_label("DIN");
85 | tx(-pad_spacing * 2) pad_with_label("GND");
86 | tx(-pad_spacing * 3) pad_with_label("+5V");
87 | }
88 |
89 | module center_pads() {
90 | center_pad_yoffset = 14.5;
91 | center_pad_span = 6.2;
92 | center_pad_xoffset = (DOTSTAR_8X8_BASE_WIDTH - center_pad_span) / 2;
93 | module pad_with_label(label) {
94 | txy(center_pad_xoffset, center_pad_yoffset) {
95 | pad();
96 | translate([
97 | 0,
98 | pad_diameter / 2,
99 | pad_depth - overlap]) ry(180) color("white")
100 | linear_extrude(pad_depth)
101 | text(label, size=pad_text_size, halign="center");
102 | }
103 | }
104 | pad_with_label("+5V");
105 | tx(center_pad_span) pad_with_label("GND");
106 | }
107 |
108 | bottom_pads();
109 | top_pads();
110 | center_pads();
111 | }
112 |
113 | module led_matrix() {
114 | led_matrix_span = 23.7;
115 | led_side_count = 8;
116 | led_offset = (DOTSTAR_8X8_BASE_WIDTH - led_matrix_span) / 2;
117 | led_width = 2;
118 | led_spacing = (led_matrix_span - led_width) / (led_side_count - 1);
119 | module led() {
120 | led_thickness = DOTSTAR_8X8_THICKNESS - DOTSTAR_8X8_PCB_THICKNESS;
121 | translate([
122 | led_offset,
123 | led_offset,
124 | DOTSTAR_8X8_PCB_THICKNESS]) color("#ddd", 0.5) cube([
125 | led_width,
126 | led_width,
127 | led_thickness]);
128 | }
129 | for (y = [0:led_side_count-1]) {
130 | for (x = [0:led_side_count-1]) {
131 | txy(x * led_spacing, y * led_spacing) led();
132 | }
133 | }
134 | }
135 |
136 | base_pcb();
137 |
138 | if (include_tabs) {
139 | tx(-DOTSTAR_8X8_TAB_WIDTH) tab();
140 | tx(DOTSTAR_8X8_BASE_WIDTH) tab();
141 | txy(-DOTSTAR_8X8_TAB_WIDTH,
142 | DOTSTAR_8X8_BASE_WIDTH - DOTSTAR_8X8_TAB_WIDTH) tab();
143 | txy(DOTSTAR_8X8_BASE_WIDTH,
144 | DOTSTAR_8X8_BASE_WIDTH - DOTSTAR_8X8_TAB_WIDTH) tab();
145 | }
146 |
147 | pads();
148 | led_matrix();
149 | }
150 |
151 | /*
152 | $fa=2;
153 | $fs=0.2;
154 | adafruit_dotstar_8x8_matrix();
155 | */
156 |
157 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/dep/mattwach/vitamins/electronics/cr2032_battery.scad:
--------------------------------------------------------------------------------
1 | use <../../util.scad>
2 |
3 | CR2032_DIAMETER = 20;
4 | CR2032_THICKNESS = 3.2;
5 |
6 | module cr2032() {
7 | negative_diameter = 17.7;
8 | negative_height = 0.3;
9 | overlap = 0.01;
10 | marker_thickness = 0.5;
11 | marker_length = 5;
12 | marker_depth = 0.1;
13 | module cell() {
14 | color("silver") union() {
15 | cylinder(d=negative_diameter, h=negative_height + overlap);
16 | tz(negative_height) cylinder(d=CR2032_DIAMETER, h=CR2032_THICKNESS-negative_height);
17 | }
18 | }
19 |
20 | module positive_marker() {
21 | color("#aaa") union() {
22 | translate([
23 | -marker_length / 2,
24 | -marker_thickness / 2,
25 | CR2032_THICKNESS - marker_depth + overlap
26 | ]) cube([marker_length, marker_thickness, marker_depth]);
27 | translate([
28 | -marker_thickness / 2,
29 | -marker_length / 2,
30 | CR2032_THICKNESS - marker_depth + overlap
31 | ]) cube([marker_thickness, marker_length, marker_depth]);
32 | }
33 | }
34 |
35 | module negative_marker() {
36 | color("#aaa") translate([
37 | -marker_length / 2,
38 | -marker_thickness / 2,
39 | -overlap
40 | ]) cube([marker_length, marker_thickness, marker_depth]);
41 | }
42 |
43 | difference() {
44 | cell();
45 | negative_marker();
46 | positive_marker();
47 | }
48 | }
49 |
50 | /*
51 | $fa=2;
52 | $fs=0.5;
53 | cr2032();
54 | */
55 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/lib/matrix_clock_assembled_board.scad:
--------------------------------------------------------------------------------
1 | use <../dep/mattwach/util.scad>
2 | use <../dep/mattwach/vitamins/electronics/buttons.scad>
3 | include <../dep/mattwach/vitamins/electronics/pi_pico.scad>
4 | include <../dep/mattwach/vitamins/electronics/ds3231_rtc.scad>
5 | include <../dep/NopSCADlib/core.scad>
6 | include <../dep/NopSCADlib/vitamins/pin_headers.scad>
7 |
8 | MATRIX_CLOCK_PCB_LENGTH = 63.5;
9 | MATRIX_CLOCK_PCB_WIDTH = 54.6;
10 | MATRIX_CLOCK_PCB_THICKNESS = 1.6;
11 |
12 | module matrix_clock_assembled_board() {
13 | overlap = 0.01;
14 |
15 | module pcb() {
16 | color("#760") translate([
17 | MATRIX_CLOCK_PCB_LENGTH,
18 | MATRIX_CLOCK_PCB_WIDTH,
19 | 0]) rz(-90) import("lib/matrix_clock_kicad_pcb.stl");
20 | }
21 |
22 | module pico() {
23 | translate([
24 | 59.8,
25 | 25.7,
26 | -overlap * 2]) ry(180) pi_pico();
27 | }
28 |
29 | module rtc() {
30 | pin_x_offset = 47.6;
31 | pin_y_offset = 4.5;
32 | pin_z_offset = 2.4 + MATRIX_CLOCK_PCB_THICKNESS + 3;
33 | module clock_pins() {
34 | translate([
35 | pin_x_offset,
36 | pin_y_offset,
37 | pin_z_offset]) ry(180) pin_header(2p54header, 4, 1);
38 | }
39 |
40 | module clock_module() {
41 | translate([
42 | 58.8,
43 | 40.3,
44 | pin_z_offset + 1.6]) rz(-90) rx(180) ds3231_rtc();
45 | }
46 |
47 | clock_pins();
48 | clock_module();
49 | }
50 |
51 | module led_matrix_interface() {
52 | translate([
53 | 3.8,
54 | 41.9,
55 | MATRIX_CLOCK_PCB_THICKNESS]) rz(-90) jst_xh_header(jst_xh_header, 4);
56 | }
57 |
58 | module interface_buttons() {
59 | button_y_offset = 4.6;
60 | button_z_offset = 2;
61 | translate([
62 | 10.2,
63 | button_y_offset,
64 | button_z_offset]) push_switch_12x12(include_button=false);
65 | translate([
66 | 24.8,
67 | button_y_offset,
68 | button_z_offset]) push_switch_12x12(include_button=false);
69 | }
70 |
71 | module reset_button() {
72 | reset_button_length = 6.3;
73 | reset_button_width = 2.4;
74 | reset_button_height = 3;
75 | translate([
76 | 26,
77 | 50,
78 | -reset_button_height]) cube([
79 | reset_button_length,
80 | reset_button_width,
81 | reset_button_height]);
82 | }
83 |
84 | pcb();
85 | pico();
86 | rtc();
87 | led_matrix_interface();
88 | interface_buttons();
89 | reset_button();
90 | }
91 |
92 | /*
93 | $fa=2;
94 | $fs=0.2;
95 | matrix_clock_assembled_board();
96 | */
97 |
--------------------------------------------------------------------------------
/case/dotstar_8x8/lib/matrix_clock_kicad_pcb.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/case/dotstar_8x8/lib/matrix_clock_kicad_pcb.stl
--------------------------------------------------------------------------------
/case/led_matrix_64x32/dep/button_pcb.scad:
--------------------------------------------------------------------------------
1 | use <../lib/mattwach/util.scad>
2 | include <../lib/NopSCADlib/core.scad>
3 | include <../lib/NopSCADlib/vitamins/buttons.scad>
4 | include <../lib/NopSCADlib/vitamins/pin_headers.scad>
5 |
6 | module button_pcb() {
7 | pcb_zsize = 1.6;
8 |
9 | module pcb() {
10 | rz(90) color("#262") import("dep/button_pcb_kicad.stl");
11 | }
12 |
13 | module buttons() {
14 | module button() {
15 | translate([
16 | 4.65,
17 | 18.6,
18 | pcb_zsize
19 | ]) square_button(button_6mm);
20 | }
21 |
22 | button();
23 | ty(10.7) button();
24 | }
25 |
26 | module pins() {
27 | translate([
28 | 4.5,
29 | 9,
30 | 0]) rz(180) ry(180) pin_header(2p54header, 3, 1, right_angle=true);
31 | }
32 |
33 | pcb();
34 | buttons();
35 | pins();
36 | }
37 |
38 | /*
39 | $fa=2;
40 | $fs=0.2;
41 | button_pcb();
42 | */
43 |
44 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/dep/button_pcb_kicad.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/case/led_matrix_64x32/dep/button_pcb_kicad.stl
--------------------------------------------------------------------------------
/case/led_matrix_64x32/dep/main_pcb.scad:
--------------------------------------------------------------------------------
1 | use <../lib/mattwach/util.scad>
2 | use <../lib/mattwach/vitamins/electronics/pi_pico.scad>
3 | include <../lib/mattwach/vitamins/electronics/ds3231_rtc.scad>
4 | include <../lib/NopSCADlib/core.scad>
5 | include <../lib/NopSCADlib/vitamins/pin_headers.scad>
6 |
7 | module main_pcb() {
8 | pcb_zsize = 1.6;
9 |
10 | module pcb() {
11 | rz(90) color("#262") import("dep/main_pcb.stl");
12 | }
13 |
14 | module pico() {
15 | translate([
16 | 58.65,
17 | 54.2,
18 | pcb_zsize]) rz(180) pi_pico();
19 | }
20 |
21 | module rtc() {
22 | pin_x_offset = 41.05;
23 | pin_y_offset = 4.05;
24 | pin_z_offset = -2.54;
25 | module clock_pins() {
26 | translate([
27 | pin_x_offset,
28 | pin_y_offset,
29 | pin_z_offset]) pin_header(2p54header, 4, 1);
30 | }
31 |
32 | module clock_module() {
33 | translate([
34 | 29.9,
35 | -31.7,
36 | -2.54]) ry(180) rz(90) ds3231_rtc();
37 | }
38 |
39 | clock_pins();
40 | clock_module();
41 | }
42 |
43 | module led_interface_pins() {
44 | translate([
45 | 23.25,
46 | 13.35,
47 | pcb_zsize]) rz(-90) pin_header(2p54header, 8, 2, right_angle=true);
48 | }
49 |
50 | module button_pins() {
51 | translate([
52 | 55,
53 | 21.6,
54 | pcb_zsize]) pin_header(2p54header, 3, 1, right_angle=true);
55 | }
56 |
57 | module power_pins() {
58 | translate([
59 | 18.65,
60 | 64.65,
61 | pcb_zsize]) rz(-90) pin_header(2p54header, 2, 1, right_angle=true);
62 | }
63 |
64 | pcb();
65 | pico();
66 | rtc();
67 | led_interface_pins();
68 | button_pins();
69 | power_pins();
70 | }
71 |
72 | /*
73 | $fa=2;
74 | $fs=0.2;
75 | main_pcb();
76 | */
77 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/dep/main_pcb.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/case/led_matrix_64x32/dep/main_pcb.stl
--------------------------------------------------------------------------------
/case/led_matrix_64x32/export/bottom_support.3mf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/case/led_matrix_64x32/export/bottom_support.3mf
--------------------------------------------------------------------------------
/case/led_matrix_64x32/export/top_support.3mf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/case/led_matrix_64x32/export/top_support.3mf
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/core.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | // Include this file to use the minimum library plus screws, nuts and washers
22 | //
23 | include
24 | //
25 | // Fasteners used by a lot of other vitamins
26 | //
27 | include
28 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/global_defs.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | // This file included directly or indirectly in every scad file.
22 | //
23 | // This scheme allows the following:
24 | // bom defaults to 0
25 | // Setting $bom on the command line or in the main file before including lib.scad overrides it everywhere.
26 | // Setting $bom after including lib overrides bom in the libs but not in the local file.
27 | // Setting $_bom in the local file overrides it in the local file but not in the libs.
28 | //
29 | rr_green = [0, 146/255, 0]; // RepRap logo colour
30 | crimson = [220/255, 20/255, 60/255];
31 |
32 | $_bom = is_undef($bom) ? 0 : $bom; // 0 no bom, 1 assemblies and stls, 2 vitamins as well
33 | $exploded = is_undef($explode) ? 0 : $explode; // 1 for exploded view
34 | layer_height = is_undef($layer_height) ? 0.25 : $layer_height; // layer height when printing
35 | extrusion_width = is_undef($extrusion_width) ? 0.5 : $extrusion_width; // filament width when printing
36 | nozzle = is_undef($nozzle) ? 0.45 : $nozzle; // 3D printer nozzle
37 | cnc_bit_r = is_undef($cnc_bit_r) ? 1.2 : $cnc_bit_r; // minimum tool radius when milling 2D objects
38 | pp1_colour = is_undef($pp1_colour) ? rr_green : $pp1_colour; // printed part colour 1, RepRap logo colour
39 | pp2_colour = is_undef($pp2_colour) ? crimson : $pp2_colour; // printed part colour 2
40 | pp3_colour = is_undef($pp3_colour) ? "SteelBlue" : $pp3_colour; // printed part colour 3
41 | pp4_colour = is_undef($pp4_colour) ? "darkorange" : $pp4_colour;// printed part colour 4
42 | show_rays = is_undef($show_rays) ? false : $show_rays; // show camera sight lines and light direction
43 | show_threads = is_undef($show_threads) ? false : $show_threads; // show screw threads
44 |
45 | // Minimum wall is about two filaments wide but we extrude it closer to get better bonding
46 | squeezed_wall = $preview ? 2 * extrusion_width - layer_height * (1 - PI / 4)
47 | : extrusion_width - layer_height / 2 + nozzle / 2 + extrusion_width / 2;
48 |
49 | inf = 1e10; // very big
50 | eps = 1/128; // small fudge factor to stop CSG barfing on coincident faces.
51 | $fa = 6;
52 | $fs = extrusion_width / 2;
53 |
54 | function round_to_layer(z) = ceil(z / layer_height) * layer_height;
55 | // Some additional named colours
56 | function grey(n) = [0.01, 0.01, 0.01] * n; //! Generate a shade of grey to pass to color().
57 | silver = [0.75, 0.75, 0.75];
58 | gold = [255, 215, 0] / 255;
59 | brass = [255, 220, 100] / 255;
60 | copper = [230, 140, 51] / 255;
61 |
62 | /*
63 | * Enums
64 | */
65 | //
66 | // Screws
67 | //
68 | hs_cap = 0;
69 | hs_pan = 1;
70 | hs_cs = 2; // counter sunk
71 | hs_hex = 3;
72 | hs_grub = 4; // pulley set screw
73 | hs_cs_cap = 5;
74 | hs_dome = 6;
75 | //
76 | // Hot end descriptions
77 | //
78 | jhead = 1;
79 | e3d = 2;
80 | //
81 | // Face enumeration
82 | //
83 | f_bottom = 0;
84 | f_top = 1;
85 | f_left = 2;
86 | f_right = 3;
87 | f_front = 4;
88 | f_back = 5;
89 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/utils/core/clip.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Construct arbitrarily large box to partition 3D space and clip objects, useful for creating cross sections to see the inside when debugging.
22 | //!
23 | //! Original version by Doug Moen on the OpenSCAD forum
24 | //
25 | //
26 | module box(xmin, ymin, zmin, xmax, ymax, zmax) //! Construct a box given its bounds
27 | polyhedron(
28 | [[xmin, ymin, zmin], // 0
29 | [xmin, ymin, zmax], // 1
30 | [xmin, ymax, zmin], // 2
31 | [xmin, ymax, zmax], // 3
32 | [xmax, ymin, zmin], // 4
33 | [xmax, ymin, zmax], // 5
34 | [xmax, ymax, zmin], // 6
35 | [xmax, ymax, zmax]], // 7
36 | [[7,5,1,3], // top
37 | [2,0,4,6], // bottom
38 | [5,4,0,1], // front
39 | [3,2,6,7], // back
40 | [5,7,6,4], // right
41 | [0,2,3,1]] // left
42 | );
43 |
44 | module clip(xmin = -inf, ymin = -inf, zmin = -inf, xmax = inf, ymax = inf, zmax = inf) //! Clip child to specified boundaries
45 | render() intersection() {
46 | children();
47 |
48 | box(xmin, ymin, zmin, xmax, ymax, zmax);
49 | }
50 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/utils/core/core.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | // Include this file to use the minimum library
22 | //
23 | include <../../global_defs.scad>
24 | //
25 | // Global functions and modules
26 | //
27 | use
28 |
29 | module use_stl(name) { //! Import an STL to make a build platter
30 | stl(name);
31 | path = is_undef($target) ? "../stls/" : str($cwd, "/", $target, "/stls/");
32 | import(str(path, name, ".stl"));
33 | }
34 |
35 | module use_dxf(name) { //! Import a DXF to make a build panel
36 | dxf(name);
37 | path = is_undef($target) ? "../dxfs/" : str($cwd, "/", $target, "/dxfs/");
38 | import(str(path, name, ".dxf"));
39 | }
40 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/utils/core/global.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Global constants, functions and modules. This file is used directly or indirectly in every scad file.
22 | //
23 | include <../../global_defs.scad>
24 |
25 | function inch(x) = x * 25.4; //! Inch to mm conversion (For fractional inches, 'inch(1 + 7/8)' will work as expected.)
26 | function foot(x) = x * 25.4 * 12; //! Foot to mm conversion
27 | function yard(x) = x * 25.4 * 12 * 3; //! Yard to mm conversion
28 | function mm(x) = x; //! Explicit mm specified
29 | function cm(x) = x * 10.0; //! cm to mm conversion
30 | function m(x) = x * 1000.0; //! m to mm conversion
31 |
32 | function sqr(x) = x * x; //! Returns the square of `x`
33 | function echoit(x) = echo(x) x; //! Echo expression and return it, useful for debugging
34 | function no_point(str) = chr([for(c = str(str)) if(c == ".") ord("p") else ord(c)]);//! Replace decimal point in string with 'p'
35 | function in(list, x) = !!len([for(v = list) if(v == x) true]); //! Returns true if `x` is an element in the `list`
36 | function Len(x) = is_list(x) ? len(x) : 0; //! Returns the length of a list or 0 if `x` is not a list
37 | function r2sides(r) = $fn ? $fn : ceil(max(min(360/ $fa, r * 2 * PI / $fs), 5)); //! Replicates the OpenSCAD logic to calculate the number of sides from the radius
38 | function r2sides4n(r) = floor((r2sides(r) + 3) / 4) * 4; //! Round up the number of sides to a multiple of 4 to ensure points land on all axes
39 | function limit(x, min, max) = max(min(x, max), min); //! Force x in range min <= x <= max
40 |
41 | module translate_z(z) translate([0, 0, z]) children(); //! Shortcut for Z only translations
42 | module vflip(flip=true) rotate([flip ? 180 : 0, 0, 0]) children(); //! Invert children by doing a 180° flip around the X axis
43 | module hflip(flip=true) rotate([0, flip ? 180: 0, 0]) children(); //! Invert children by doing a 180° flip around the Y axis
44 | module ellipse(xr, yr) scale([1, yr / xr]) circle4n(xr); //! Draw an ellipse
45 |
46 | function slice_str(str, start, end, s ="") = start >= end ? s : slice_str(str, start + 1, end, str(s, str[start])); // Helper for slice()
47 |
48 | function slice(list, start = 0, end = undef) = let( //! Slice a list or string with Python type semantics
49 | len = len(list),
50 | start = limit(start < 0 ? len + start : start, 0, len),
51 | end = is_undef(end) ? len : limit(end < 0 ? len + end : end, 0, len)
52 | ) is_string(list) ? slice_str(list, start, end) : [for(i = [start : 1 : end - 1]) list[i]];
53 |
54 |
55 | module render_if(render = true, convexity = 2) //! Renders an object if `render` is true, otherwise leaves it unrendered
56 | if (render)
57 | render(convexity = convexity)
58 | children();
59 | else
60 | children();
61 |
62 | module extrude_if(h, center = true) //! Extrudes 2D object to 3D when `h` is nonzero, otherwise leaves it 2D
63 | if(h)
64 | linear_extrude(h, center = center, convexity = 2) // 3D
65 | children();
66 | else
67 | children(); // 2D
68 |
69 | module circle4n(r, d = undef) { //! Circle with multiple of 4 vertices
70 | R = is_undef(d) ? r : d / 2;
71 | circle(R, $fn = r2sides4n(R));
72 | }
73 |
74 | module semi_circle(r, d = undef) //! A semi circle in the positive Y domain
75 | intersection() {
76 | R = is_undef(d) ? r : d / 2;
77 | circle4n(R);
78 |
79 | sq = R + 1;
80 | translate([-sq, 0])
81 | square([2 * sq, sq]);
82 | }
83 |
84 | module right_triangle(width, height, h, center = true) //! A right angled triangle with the 90° corner at the origin. 3D when `h` is nonzero, otherwise 2D
85 | extrude_if(h, center = center)
86 | polygon(points = [[0,0], [width, 0], [0, height]]);
87 |
88 | include
89 | include
90 | include
91 | include
92 | include
93 | include
94 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/utils/core/rounded_rectangle.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Rectangle with rounded corners.
22 | //
23 | module rounded_square(size, r, center = true) //! Like `square()` but with with rounded corners
24 | {
25 | assert(r < min(size.x, size.y) / 2);
26 | $fn = r2sides4n(r);
27 | offset(r) offset(-r) square(size, center = center);
28 | }
29 |
30 | module rounded_rectangle(size, r, center = false, xy_center = true) //! Like `cube()` but corners rounded in XY plane and separate centre options for xy and z.
31 | {
32 | extrude_if(size.z, center = center)
33 | rounded_square([size.x, size.y], r, xy_center);
34 | }
35 |
36 | module rounded_cube_xy(size, r = 0, xy_center = false, z_center = false) //! Like `cube()` but corners rounded in XY plane and separate centre options for xy and z.
37 | {
38 | extrude_if(size.z, center = z_center)
39 | rounded_square([size.x, size.y], r, xy_center);
40 | }
41 |
42 | module rounded_cube_xz(size, r = 0, xy_center = false, z_center = false) //! Like `cube()` but corners rounded in XZ plane and separate centre options for xy and z.
43 | {
44 | translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, z_center ? 0 : size.z / 2])
45 | rotate([90, 0, 0])
46 | rounded_cube_xy([size.x, size.z, size.y], r, xy_center = true, z_center = true);
47 | }
48 |
49 | module rounded_cube_yz(size, r = 0, xy_center = false, z_center = false) //! Like `cube()` but corners rounded in YX plane and separate centre options for xy and z.
50 | {
51 | translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, z_center ? 0 : size.z / 2])
52 | rotate([90, 0, 90])
53 | rounded_cube_xy([size.y, size.z, size.x], r, xy_center = true, z_center = true);
54 | }
55 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/utils/core/sphere.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //! Redefines `sphere()` to always have a vertex on all six half axes I.e. vertices at the poles and the equator and `$fn` a multiple of four.
21 | //! This ensures `hull` and `minkowski` results have the correct dimensions when spheres are placed at the corners.
22 |
23 | module sphere(r = 1, d = undef) { //! Override `sphere` so that has vertices on all three axes. Has the advantage of giving correct dimensions when hulled
24 | R = is_undef(d) ? r : d / 2;
25 | rotate_extrude($fn = r2sides4n(R))
26 | rotate(-90)
27 | semi_circle(R);
28 | }
29 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/utils/dogbones.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! When square holes are cut with a CNC bit they get rounded corners. If it is important that
22 | //! a square cornered part fits in the hole then circles are placed in the corners making a bone shape.
23 | //
24 | include <../utils/core/core.scad>
25 |
26 | module dogbone_square(size, r = cnc_bit_r, center = true, x_offset, y_offset) //! Square with circles at the corners, with optional offsets
27 | {
28 | x_offset = is_undef(x_offset) ? r / sqrt(2) : x_offset;
29 | y_offset = is_undef(y_offset) ? r / sqrt(2) : y_offset;
30 |
31 | union() {
32 | square(size, center = center);
33 |
34 | if(r > 0) {
35 | origin = center ? [0, 0] : size / 2;
36 |
37 | for(x = [-1, 1], y = [-1, 1])
38 | translate(origin + [x * (size.x / 2 - x_offset), y * (size.y / 2 - y_offset)])
39 | drill(r, 0);
40 | }
41 | }
42 | }
43 |
44 | module dogbone_rectangle(size, r = cnc_bit_r, center = true, xy_center = true, x_offset, y_offset) //! Rectangle with cylinders at the corners
45 | {
46 | extrude_if(h = size.z, center = center)
47 | dogbone_square([size.x, size.y], r, xy_center, x_offset, y_offset);
48 | }
49 |
50 | module dogbone_rectangle_x(size, r = cnc_bit_r, center = true, xy_center = true) //! Rectangle with cylinders at the corners, offset in the x direction
51 | {
52 | dogbone_rectangle(size = size, r = r, center = center, x_offset = 0, y_offset = r);
53 | }
54 |
55 | module dogbone_rectangle_y(size, r = cnc_bit_r, center = true, xy_center = true) //! Rectangle with cylinders at the corners, offset in the y direction
56 | {
57 | dogbone_rectangle(size = size, r = r, center = center, x_offset = r, y_offset = 0);
58 | }
59 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/utils/fillet.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Rounded fillet for adding to corners.
22 | //
23 | include <../utils/core/core.scad>
24 |
25 | module fillet(r, h, center = false) //! Fillet with specified radius and height
26 | extrude_if(h, center = center)
27 | difference() {
28 | translate([-eps, -eps, 0])
29 | square(r + eps);
30 |
31 | translate([r, r])
32 | circle(r + eps);
33 | }
34 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/utils/quadrant.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Square with one rounded corner.
22 | //
23 | include <../utils/core/core.scad>
24 |
25 | module quadrant(w, r, center = false) { //! Draw a square with one rounded corner, can be centered on the arc centre, when `center` is `true`.
26 | h = is_list(w) ? w.y : w;
27 | w = is_list(w) ? w.x : w;
28 | offset_w = center ? r - w : 0;
29 | offset_h = center ? r - h : 0;
30 | translate([offset_w, offset_h])
31 | hull() {
32 | intersection() {
33 | translate([w - r, h - r])
34 | circle4n(r);
35 |
36 | square([w, h]);
37 | }
38 |
39 | square([w, eps]);
40 |
41 | square([eps, h]);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/utils/rounded_cylinder.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Cylinder with a rounded end.
22 | //
23 | include <../utils/core/core.scad>
24 |
25 | module rounded_corner(r, h, r2, ir = 0) { //! 2D version
26 | assert(ir <= r - r2);
27 |
28 | translate([ir , 0])
29 | hull() {
30 | square([eps, h]);
31 |
32 | square([r - ir, eps]);
33 |
34 | translate([r - r2 - ir, h - r2])
35 | intersection() {
36 | circle4n(r2, $fs = 0.2);
37 |
38 | square(r2);
39 | }
40 | }
41 | }
42 |
43 | module rounded_cylinder(r, h, r2, ir = 0, angle = 360) //! Rounded cylinder given radius `r`, height `h`, optional internal radius `ir` and optional `angle`
44 | {
45 | rotate_extrude(angle = angle)
46 | rounded_corner(r, h, r2, ir);
47 | }
48 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/utils/tube.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! Simple tube or ring
22 | //
23 | include <../utils/core/core.scad>
24 |
25 | module ring(or, ir) //! Create a ring with specified external and internal radii
26 | difference() {
27 | circle4n(or);
28 | circle4n(ir);
29 | }
30 |
31 | module tube(or, ir, h, center = true) //! Create a tube with specified external and internal radii and height `h`
32 | linear_extrude(h, center = center, convexity = 5)
33 | ring(or, ir);
34 |
35 | module woven_tube(or, ir, h, center= true, colour = grey(30), colour2, warp = 2, weft) {//! Create a woven tube with specified external and internal radii, height `h`, colours, warp and weft
36 | colour2 = colour2 ? colour2 : colour * 0.8;
37 | weft = weft ? weft : warp;
38 | warp_count = max(floor(PI * or / warp), 0.5);
39 | angle = 360 / (2 * warp_count);
40 |
41 | module layer(weft) {
42 | points = [[ir, weft / 2], [or, weft / 2], [or, -weft / 2], [ir, -weft / 2]];
43 | color(colour)
44 | for (i = [0 : warp_count])
45 | rotate(2 * i * angle)
46 | rotate_extrude(angle = angle)
47 | polygon(points);
48 | color(colour2)
49 | for (i = [0 : warp_count])
50 | rotate((2 * i + 1) * angle)
51 | rotate_extrude(angle = angle)
52 | polygon(points);
53 | }
54 |
55 | translate_z(center ? -h / 2 : 0) {
56 | weft_count = floor(h / weft);
57 | if (weft_count > 0)
58 | for (i = [0 : weft_count - 1]) {
59 | translate_z(i * weft + weft / 2)
60 | rotate(i * angle)
61 | layer(weft);
62 | }
63 | remainder = h - weft * weft_count;
64 | if (remainder) {
65 | translate_z(weft_count * weft + remainder / 2)
66 | rotate(weft_count * angle)
67 | layer(remainder);
68 | }
69 | }
70 | }
71 |
72 | module rectangular_tube(size, center = true, thickness = 1, fillet = 0.5) { //! Create a rectangular tube with filleted corners
73 | extrude_if(size.z, center = center)
74 | difference() {
75 | rounded_square([size.x, size.y], fillet);
76 | rounded_square([size.x - 2 * thickness, size.y - 2 * thickness], fillet);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/vitamins/button.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | //! PCB mounted buttons. Can optionally have a coloured cap
22 | //
23 | include <../utils/core/core.scad>
24 | use <../utils/rounded_cylinder.scad>
25 |
26 | function square_button_width(type) = type[1]; //! Width and depth of the base
27 | function square_button_height(type) = type[2]; //! Height of the base
28 | function square_button_wall(type) = type[3]; //! Offset of the metal part
29 | function square_button_rivit(type) = type[4]; //! Size of the corner rivets
30 | function square_button_d(type) = type[5]; //! Button diameter
31 | function square_button_h(type) = type[6]; //! Height of the button above the PCB
32 | function square_button_cap_flange_d(type) = type[7]; //! Diameter of the flange of the cap
33 | function square_button_cap_d(type) = type[8]; //! Diameter of the body of the cap
34 | function square_button_cap_h(type) = type[9]; //! Height of the cap including the stem
35 | function square_button_cap_stem(type) = type[10]; //! Length of the cap stem
36 | function square_button_cap_flange_h(type) = type[11]; //! Height of the cap flange
37 |
38 | module square_button(type, colour = "yellow") { //! Draw square button with specified cap colour if it has a cap
39 | w = square_button_width(type);
40 | flange_d = square_button_cap_flange_d(type);
41 | vitamin(str("square_button(", type[0], flange_d ? str(", \"", colour, "\"") : "", "): Square button ", w, "mm",
42 | flange_d ? str(" with ", colour, " cap") : ""));
43 | h = square_button_height(type);
44 | wall = square_button_wall(type);
45 | rivit = square_button_rivit(type);
46 | pitch = (w/ 2 - wall - rivit * 0.75);
47 | stem = square_button_cap_stem(type);
48 |
49 | color(grey(20)) {
50 | rounded_rectangle([w, w, h - 0.5], r = wall);
51 |
52 | for(x = [-1, 1], y = [-1, 1])
53 | translate([x * pitch, y * pitch])
54 | cylinder(d = rivit, h = h);
55 |
56 | cylinder(d = square_button_d(type), h = square_button_h(type));
57 | }
58 |
59 | color("silver")
60 | translate_z(h - 0.5)
61 | rounded_rectangle([w - 2 * wall, w - 2 * wall, 0.2], r = wall, center = true);
62 |
63 | if(flange_d)
64 | translate_z(square_button_h(type))
65 | color(colour) rotate_extrude() {
66 | square([square_button_d(type) / 2, stem]);
67 |
68 | translate([0, stem]) {
69 | square([flange_d / 2, square_button_cap_flange_h(type)]);
70 |
71 | rounded_corner(r = square_button_cap_d(type) / 2, h = square_button_cap_h(type) - stem, r2 = 0.5);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/vitamins/buttons.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | // w h w r b b c c c c c
22 | // i e a i u u a a a a a
23 | // d i l v t t p p p p p
24 | // t g l i
25 | // h h t d h f d h s f
26 | // d t h
27 | button_12mm = ["button_12mm", 12, 4.0, 0.8, 1.5, 6.8, 4.3, 12.86, 11.44, 8.15, 2.7, 1.4];
28 | button_6mm = ["button_6mm", 6, 4.0, 0.2, 1.0, 3.5, 5.0, 0];
29 | button_4p5mm= ["button_4p5mm", 4.5, 3.1, 0.1, 0.9, 2.4, 4.5, 0];
30 |
31 | buttons = [button_4p5mm, button_6mm, button_12mm];
32 |
33 | use
34 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/vitamins/inserts.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | // Threaded inserts
22 | //
23 | // l o h s b r r r
24 | // e u o c a i i i
25 | // n t l r r n n n
26 | // g e e e r g g g
27 | // t r w e 1 2 3
28 | // h d l
29 | // d d h d d
30 | // d
31 | //
32 | F1BM2 = [ "F1BM2", 4.0, 3.6, 3.2, 2, 3.0, 1.0, 3.4, 3.1 ];
33 | F1BM2p5 = [ "F1BM2p5", 5.8, 4.6, 4.0, 2.5, 3.65, 1.6, 4.4, 3.9 ];
34 | F1BM3 = [ "F1BM3", 5.8, 4.6, 4.0, 3, 3.65, 1.6, 4.4, 3.9 ];
35 | F1BM4 = [ "F1BM4", 8.2, 6.3, 5.6, 4, 5.15, 2.3, 6.0, 5.55 ];
36 |
37 | inserts = [ F1BM2, F1BM2p5, F1BM3, F1BM4 ];
38 |
39 | use
40 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/vitamins/nuts.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 | include
20 | //
21 | // Nuts
22 | //
23 | M2_nut_trap_depth = 2.5;
24 | M2p5_nut_trap_depth = 2.5;
25 | M3_nut_trap_depth = 3;
26 | M4_nut_trap_depth = 4;
27 | M5_nut_depth = 4;
28 | M6_nut_depth = 5;
29 | M8_nut_depth = 6.5;
30 |
31 | // s r t n w t t
32 | // c a h y a r h
33 | // r d i l s a r
34 | // e i c o h p e
35 | // w u k c e d
36 | // s n r d
37 | // e t e p
38 | // s h p i
39 | // s k t t
40 | // h c
41 | // h
42 | M2_nut = ["M2_nut", 2, 4.9, 1.6, 2.4, M2_washer, M2_nut_trap_depth, 0];
43 | M2p5_nut = ["M2p5_nut", 2.5, 5.8, 2.2, 3.8, M2p5_washer, M2p5_nut_trap_depth, 0];
44 | M3_nut = ["M3_nut", 3, 6.4, 2.4, 4, M3_washer, M3_nut_trap_depth, 0];
45 | M4_nut = ["M4_nut", 4, 8.1, 3.2, 5, M4_washer, M4_nut_trap_depth, 0];
46 | M5_nut = ["M5_nut", 5, 9.2, 4, 6.25, M5_washer, M5_nut_depth, 0];
47 | M6_nut = ["M6_nut", 6, 11.5, 5, 8, M6_washer, M6_nut_depth, 0];
48 | M6_half_nut = ["M6_half_nut", 6, 11.5, 3, 8, M6_washer, 3, 0];
49 | M8_nut = ["M8_nut", 8, 15, 6.5, 8, M8_washer, M8_nut_depth, 0];
50 | toggle_nut = ["toggle_nut", 6.1, 9.2, 1.5, 1.5, M6_washer, 1.5, inch(1/40)];
51 |
52 | M4_wingnut = ["M4_wingnut", 4, 10, 3.75,8, M4_washer, 0, 22, 10, 6, 3];
53 | // sx ty1 ty2 hammer
54 | M3_sliding_t_nut = ["M3_sliding_t_nut", 3, 6, 3.0, 4.0, false, 0, 10, 10, 6, false];
55 | M4_sliding_t_nut = ["M4_sliding_t_nut", 4, 6, 3.25,4.5, false, 0, 11, 10, 6, false];
56 | M5_sliding_t_nut = ["M5_sliding_t_nut", 5, 6, 3.25,4.5, false, 0, 11, 10, 7, false];
57 | M3_hammer_nut = ["M3_hammer_nut", 3, 6, 2.75,4.0, false, 0, 5.5, 10, 6, true];
58 | M4_hammer_nut = ["M4_hammer_nut", 4, 6, 3.25,4.5, false, 0, 5.5, 10, 6, true];
59 |
60 | // DIN 562 (thin) square nuts
61 | // s w h
62 | // c i e
63 | // r d i
64 | // e t g
65 | // w h h
66 | // t
67 | //
68 | M3nS_thin_nut = ["M3nS_thin_nut", 3, 5.5, 1.8];
69 | M4nS_thin_nut = ["M4nS_thin_nut", 4, 7, 2.2];
70 | M5nS_thin_nut = ["M5nS_thin_nut", 5, 8, 2.7];
71 | M6nS_thin_nut = ["M6nS_thin_nut", 6, 10, 3.2];
72 | M8nS_thin_nut = ["M8nS_thin_nut", 8, 13, 4];
73 |
74 | nuts = [M2_nut, M2p5_nut, M3_nut, M4_nut, M5_nut, M6_nut, M8_nut];
75 |
76 | use
77 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/vitamins/pin_headers.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | // p p b p p b s b b p r r
21 | // i i e i i a o o o i a a
22 | // t n l n n s c x x n
23 | // c o e k b h
24 | // h l w w c s t y
25 | // c h z o
26 | // f
27 | 2p54header = ["2p54header", 2.54, 11.6, 3.2, 0.66, gold, grey(20), 8.5, [0, 0, 8.7], 2.4, 0, 0, 0 ];
28 | 2p54joiner = ["2p54joiner", 2.54, 6.86, 2.5, 0.66, gold, grey(20), 8.5, [0, 0, 8.7], 2.4, 0, 0, 0 ]; // Cropped pins for joining PCBs
29 |
30 | jst_xh_header = ["jst_xh_header",2.5, 10, 3.4, 0.64, gold, grey(90), 0, [4.9, 5.75, 7], 0.8, 0.525, 0.6, 6.1];
31 | jst_ph_header = ["jst_ph_header",2.0, 9, 3.4, 0.64, silver, grey(90), 0, [3.9, 4.5, 6], 0.6, 0.55, 0.25, 4.8];
32 |
33 | pin_headers = [ 2p54header ];
34 |
35 | use
36 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/NopSCADlib/vitamins/washers.scad:
--------------------------------------------------------------------------------
1 | //
2 | // NopSCADlib Copyright Chris Palmer 2018
3 | // nop.head@gmail.com
4 | // hydraraptor.blogspot.com
5 | //
6 | // This file is part of NopSCADlib.
7 | //
8 | // NopSCADlib is free software: you can redistribute it and/or modify it under the terms of the
9 | // GNU General Public License as published by the Free Software Foundation, either version 3 of
10 | // the License, or (at your option) any later version.
11 | //
12 | // NopSCADlib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 | // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | // See the GNU General Public License for more details.
15 | //
16 | // You should have received a copy of the GNU General Public License along with NopSCADlib.
17 | // If not, see .
18 | //
19 |
20 | //
21 | // Washers
22 | //
23 | // s d t s s s s p
24 | // c i h o t p p e
25 | // r a i f a r r n
26 | // e m c t r i i n
27 | // w e k n n y
28 | // t n d g g
29 | // e e i v
30 | // r s a d t e
31 | // s i h r
32 | // a k
33 | M3_penny_washer = ["M3_penny", 3, 12, 0.8, false, 5.8, 5.6, 1.0, true];
34 | M4_penny_washer = ["M4_penny", 4, 14, 0.8, false, 7.9, 7.0, 1.2, true];
35 | M5_penny_washer = ["M5_penny", 5, 20, 1.4, false, 9.0, 8.8, 1.6, true];
36 | M6_penny_washer = ["M6_penny", 6, 26, 1.5, false, 10.6, 9.9, 1.6, true];
37 | M8_penny_washer = ["M8_penny", 8, 30, 1.5, false, 13.8, 12.7, 2.0, true];
38 |
39 | M2_washer = ["M2", 2, 5, 0.3, false, 4.5, 4.4, 0.5, undef];
40 | M2p5_washer = ["M2p5", 2.5, 5.9, 0.5, false, 5.4, 5.1, 0.6, undef];
41 | M3_washer = ["M3", 3, 7, 0.5, false, 5.8, 5.6, 1.0, M3_penny_washer];
42 | M3p5_washer = ["M3p5", 3.5, 8, 0.5, false, 6.9, 6.2, 1.0, undef];
43 | M4_washer = ["M4", 4, 9, 0.8, false, 7.9, 7.0, 1.2, M4_penny_washer];
44 | M5_washer = ["M5", 5, 10, 1.0, false, 9.0, 8.8, 1.6, M5_penny_washer];
45 | M6_washer = ["M6", 6, 12.5, 1.5, false, 10.6, 9.9, 1.6, M6_penny_washer];
46 | M8_washer = ["M8", 8, 17, 1.6, false, 13.8, 12.7, 2.0, M8_penny_washer];
47 | toggle_washer = ["toggle", 6.1,12, 0.6, false, 10, 0, 0, undef];
48 |
49 | M3_rubber_washer= ["M3_rubber",3, 10, 1.5, true, 5.8, M3_penny_washer];
50 |
51 | washers = [M2_washer, M2p5_washer, M3_washer, M3p5_washer, M4_washer, M5_washer, M6_washer, M8_washer, M3_rubber_washer];
52 |
53 | use
54 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/mattwach/honeycomb.scad:
--------------------------------------------------------------------------------
1 | // Implements a honeycomb grid
2 |
3 | module honeycomb(size, side_width, gap) {
4 | xsize = size[0];
5 | ysize = size[1];
6 | zsize = size[2];
7 | span = side_width + gap;
8 |
9 | xsteps = floor(xsize / span);
10 | ysteps = floor(ysize / span);
11 |
12 | module hexagon() {
13 | r = side_width * 0.5 / cos(30);
14 | linear_extrude(zsize)
15 | polygon([ for (a = [0:60:360]) [cos(a) * r, sin(a) * r]]);
16 | }
17 |
18 | translate([
19 | -cos(30) * span * xsteps / 2,
20 | span * (-sin(30) * xsteps - ysteps) / 2,
21 | 0
22 | ])
23 | for (x = [0:xsteps]) {
24 | translate([cos(30) * span * x, sin(30) * span * x, 0])
25 | for (y = [0:ysteps]) {
26 | translate([0, y * span, 0]) hexagon();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/mattwach/util.scad:
--------------------------------------------------------------------------------
1 | module tx(x) translate([x,0,0]) children();
2 | module ty(y) translate([0,y,0]) children();
3 | module tz(z) translate([0,0,z]) children();
4 |
5 | // Planes
6 | module txy(x, y) translate([x,y,0]) children();
7 | module txz(x, z) translate([x,0,z]) children();
8 | module tyz(y, z) translate([0,y,z]) children();
9 |
10 | module boardxy(x, y, pin_spacing=2.54) {
11 | translate([x * pin_spacing, y * pin_spacing,0]) children();
12 | }
13 |
14 |
15 | module rx(x) rotate([x,0,0]) children();
16 | module ry(y) rotate([0,y,0]) children();
17 | module rz(z) rotate([0,0,z]) children();
18 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/mattwach/vitamins/electronics/cr2032_battery.scad:
--------------------------------------------------------------------------------
1 | use <../../util.scad>
2 |
3 | CR2032_DIAMETER = 20;
4 | CR2032_THICKNESS = 3.2;
5 |
6 | module cr2032() {
7 | negative_diameter = 17.7;
8 | negative_height = 0.3;
9 | overlap = 0.01;
10 | marker_thickness = 0.5;
11 | marker_length = 5;
12 | marker_depth = 0.1;
13 | module cell() {
14 | color("silver") union() {
15 | cylinder(d=negative_diameter, h=negative_height + overlap);
16 | tz(negative_height) cylinder(d=CR2032_DIAMETER, h=CR2032_THICKNESS-negative_height);
17 | }
18 | }
19 |
20 | module positive_marker() {
21 | color("#aaa") union() {
22 | translate([
23 | -marker_length / 2,
24 | -marker_thickness / 2,
25 | CR2032_THICKNESS - marker_depth + overlap
26 | ]) cube([marker_length, marker_thickness, marker_depth]);
27 | translate([
28 | -marker_thickness / 2,
29 | -marker_length / 2,
30 | CR2032_THICKNESS - marker_depth + overlap
31 | ]) cube([marker_thickness, marker_length, marker_depth]);
32 | }
33 | }
34 |
35 | module negative_marker() {
36 | color("#aaa") translate([
37 | -marker_length / 2,
38 | -marker_thickness / 2,
39 | -overlap
40 | ]) cube([marker_length, marker_thickness, marker_depth]);
41 | }
42 |
43 | difference() {
44 | cell();
45 | negative_marker();
46 | positive_marker();
47 | }
48 | }
49 |
50 | /*
51 | $fa=2;
52 | $fs=0.5;
53 | cr2032();
54 | */
55 |
--------------------------------------------------------------------------------
/case/led_matrix_64x32/lib/mattwach/vitamins/electronics/led_panel_64x32.scad:
--------------------------------------------------------------------------------
1 | use <../../util.scad>
2 |
3 | LED_PANEL_64_32_BACK_LENGTH = 253;
4 | LED_PANEL_64_32_BACK_WIDTH = 125.8;
5 | LED_PANEL_64_32_FRONT_LENGTH = 256;
6 | LED_PANEL_64_32_FRONT_WIDTH = 128;
7 | LED_PANEL_64_32_THICKNESS = 14;
8 |
9 | LED_PANEL_64_32_BOLT_HOLE_WSPAN = 112;
10 | LED_PANEL_64_32_BOLT_HOLE_WOFFSET = (
11 | LED_PANEL_64_32_BACK_WIDTH - LED_PANEL_64_32_BOLT_HOLE_WSPAN) / 2;
12 | LED_PANEL_64_32_BOLT_HOLE_LSPAN = 120;
13 | LED_PANEL_64_32_BOLT_HOLE_LOFFSET =
14 | LED_PANEL_64_32_BACK_LENGTH / 2 - LED_PANEL_64_32_BOLT_HOLE_LSPAN;
15 |
16 |
17 | module led_panel_64x32() {
18 | overlap = 0.01;
19 | pcb_thickness = 2;
20 | side_support_thickness = 10.9;
21 | end_support_thickness = 10.7;
22 | inner_support_thinkness = 12;
23 | center_support_thickness = 13.8;
24 |
25 | end_cutout_xsize = 45.9;
26 | inner_cutout_width = LED_PANEL_64_32_BACK_WIDTH - (side_support_thickness * 2);
27 | cutout_depth = LED_PANEL_64_32_THICKNESS - pcb_thickness + overlap;
28 |
29 | inner_cutout_xsize =
30 | (LED_PANEL_64_32_BACK_LENGTH -
31 | end_support_thickness * 2 -
32 | inner_support_thinkness * 2 -
33 | end_cutout_xsize * 2 -
34 | center_support_thickness) / 2;
35 |
36 | module shell() {
37 | xoffset = (LED_PANEL_64_32_BACK_LENGTH - LED_PANEL_64_32_FRONT_LENGTH) / 2;
38 | yoffset = (LED_PANEL_64_32_BACK_WIDTH - LED_PANEL_64_32_FRONT_WIDTH) / 2;
39 |
40 | hull() {
41 | cube([
42 | LED_PANEL_64_32_BACK_LENGTH,
43 | LED_PANEL_64_32_BACK_WIDTH,
44 | overlap]);
45 | translate([
46 | xoffset,
47 | yoffset,
48 | LED_PANEL_64_32_THICKNESS - pcb_thickness]) cube([
49 | LED_PANEL_64_32_FRONT_LENGTH,
50 | LED_PANEL_64_32_FRONT_WIDTH,
51 | pcb_thickness]);
52 | }
53 | }
54 |
55 | module end_cutout() {
56 | cutout_bump_span = 90;
57 |
58 | module main_cutout() {
59 | translate([
60 | end_support_thickness,
61 | side_support_thickness,
62 | -overlap]) cube([
63 | end_cutout_xsize,
64 | inner_cutout_width,
65 | cutout_depth]);
66 | }
67 |
68 | module slanted_cutout() {
69 | slanted_cutout_width1 = 33.8;
70 | slanted_cutout_support_thickness = 6;
71 | slanted_cutout_width2 = slanted_cutout_width1 + (end_support_thickness - slanted_cutout_support_thickness) * 2;
72 | hull() {
73 | translate([
74 | slanted_cutout_support_thickness,
75 | (LED_PANEL_64_32_BACK_WIDTH - slanted_cutout_width1) / 2,
76 | -overlap]) cube([
77 | overlap,
78 | slanted_cutout_width1,
79 | cutout_depth]);
80 | translate([
81 | end_support_thickness - overlap,
82 | (LED_PANEL_64_32_BACK_WIDTH - slanted_cutout_width2) / 2,
83 | -overlap]) cube([
84 | overlap * 2,
85 | slanted_cutout_width2,
86 | cutout_depth]);
87 | }
88 | }
89 |
90 | module bump() {
91 | cutout_bump_diameter = 13.5;
92 | cutout_bump_offset = (LED_PANEL_64_32_BACK_WIDTH - cutout_bump_span) / 2;
93 | translate([
94 | cutout_bump_diameter / 2,
95 | cutout_bump_offset,
96 | -overlap]) cylinder(
97 | d = cutout_bump_diameter,
98 | h = cutout_depth);
99 | }
100 |
101 | difference() {
102 | union() {
103 | main_cutout();
104 | slanted_cutout();
105 | }
106 | bump();
107 | ty(cutout_bump_span) bump();
108 | }
109 | }
110 |
111 | module middle_cutout() {
112 | translate([
113 | end_support_thickness + end_cutout_xsize + inner_support_thinkness,
114 | side_support_thickness,
115 | -overlap]) cube([
116 | inner_cutout_xsize,
117 | inner_cutout_width,
118 | cutout_depth]);
119 | }
120 |
121 | module bolt_holes() {
122 | module hole() {
123 | hole_diameter = 3;
124 | hole_depth = cutout_depth;
125 | tz(-overlap) cylinder(d=hole_diameter, h=hole_depth);
126 | }
127 |
128 | module hole_row() {
129 | hole();
130 | ty(LED_PANEL_64_32_BOLT_HOLE_WSPAN) hole();
131 | }
132 |
133 | txy(LED_PANEL_64_32_BOLT_HOLE_LOFFSET, LED_PANEL_64_32_BOLT_HOLE_WOFFSET) {
134 | hole_row();
135 | tx(LED_PANEL_64_32_BOLT_HOLE_LSPAN) hole_row();
136 | tx(LED_PANEL_64_32_BOLT_HOLE_LSPAN * 2) hole_row();
137 | }
138 | }
139 |
140 | difference() {
141 | color("#444") shell();
142 | color("#222") end_cutout();
143 | color("#222") txy(
144 | LED_PANEL_64_32_BACK_LENGTH,
145 | LED_PANEL_64_32_BACK_WIDTH
146 | ) rz(180) end_cutout();
147 | color("#222") middle_cutout();
148 | color("#222") tx(inner_cutout_xsize + center_support_thickness) middle_cutout();
149 | color("gold") bolt_holes();
150 | }
151 | }
152 |
153 | /*
154 | $fa=2;
155 | $fs=0.5;
156 | led_panel_64x32();
157 | */
158 |
--------------------------------------------------------------------------------
/firmware/matrix_clock_dotstar_8x8.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/firmware/matrix_clock_dotstar_8x8.uf2
--------------------------------------------------------------------------------
/firmware/matrix_clock_led_64x32.uf2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/firmware/matrix_clock_led_64x32.uf2
--------------------------------------------------------------------------------
/images/button_hardware.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/button_hardware.jpg
--------------------------------------------------------------------------------
/images/clock_set.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/clock_set.jpg
--------------------------------------------------------------------------------
/images/completed_pcb.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/completed_pcb.jpg
--------------------------------------------------------------------------------
/images/console.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/console.png
--------------------------------------------------------------------------------
/images/ds8x8/3d_case_underside.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/ds8x8/3d_case_underside.png
--------------------------------------------------------------------------------
/images/ds8x8/3d_printed_case.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/ds8x8/3d_printed_case.png
--------------------------------------------------------------------------------
/images/ds8x8/ds_matrix_clock.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/ds8x8/ds_matrix_clock.jpg
--------------------------------------------------------------------------------
/images/ds8x8/matrix_clock2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/ds8x8/matrix_clock2.jpg
--------------------------------------------------------------------------------
/images/ds8x8/minicom.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/ds8x8/minicom.jpg
--------------------------------------------------------------------------------
/images/ds8x8/numbers.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/ds8x8/numbers.jpg
--------------------------------------------------------------------------------
/images/ds8x8/opened_clock.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/ds8x8/opened_clock.jpg
--------------------------------------------------------------------------------
/images/ds8x8/schematic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/ds8x8/schematic.png
--------------------------------------------------------------------------------
/images/kicad_button_layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/kicad_button_layout.png
--------------------------------------------------------------------------------
/images/kicad_layout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/kicad_layout.png
--------------------------------------------------------------------------------
/images/matrix_back.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/matrix_back.jpg
--------------------------------------------------------------------------------
/images/matrix_clock.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/matrix_clock.jpg
--------------------------------------------------------------------------------
/images/matrix_only.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/matrix_only.jpg
--------------------------------------------------------------------------------
/images/matrix_with_numbers.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/matrix_with_numbers.jpg
--------------------------------------------------------------------------------
/images/openscad_bottom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/openscad_bottom.png
--------------------------------------------------------------------------------
/images/openscad_model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/openscad_model.png
--------------------------------------------------------------------------------
/images/openscad_top.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/openscad_top.png
--------------------------------------------------------------------------------
/images/other_matrix_modes.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/other_matrix_modes.jpg
--------------------------------------------------------------------------------
/images/schematic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/images/schematic.png
--------------------------------------------------------------------------------
/schematic/button_pcb_kicad/button_pcb_kicad.kicad_prl:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "active_layer": 31,
4 | "active_layer_preset": "",
5 | "auto_track_width": true,
6 | "hidden_nets": [],
7 | "high_contrast_mode": 0,
8 | "net_color_mode": 1,
9 | "opacity": {
10 | "pads": 1.0,
11 | "tracks": 1.0,
12 | "vias": 1.0,
13 | "zones": 0.6
14 | },
15 | "ratsnest_display_mode": 0,
16 | "selection_filter": {
17 | "dimensions": true,
18 | "footprints": true,
19 | "graphics": true,
20 | "keepouts": true,
21 | "lockedItems": true,
22 | "otherItems": true,
23 | "pads": true,
24 | "text": true,
25 | "tracks": true,
26 | "vias": true,
27 | "zones": true
28 | },
29 | "visible_items": [
30 | 0,
31 | 1,
32 | 2,
33 | 3,
34 | 4,
35 | 5,
36 | 8,
37 | 9,
38 | 10,
39 | 11,
40 | 12,
41 | 13,
42 | 14,
43 | 15,
44 | 16,
45 | 17,
46 | 18,
47 | 19,
48 | 20,
49 | 21,
50 | 22,
51 | 23,
52 | 24,
53 | 25,
54 | 26,
55 | 27,
56 | 28,
57 | 29,
58 | 30,
59 | 32,
60 | 33,
61 | 34,
62 | 35,
63 | 36
64 | ],
65 | "visible_layers": "ffcf2ff_ffffffff",
66 | "zone_display_mode": 1
67 | },
68 | "meta": {
69 | "filename": "button_pcb_kicad.kicad_prl",
70 | "version": 3
71 | },
72 | "project": {
73 | "files": []
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/schematic/button_pcb_kicad/flatcam/Project_20230128_192544.FlatPrj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/schematic/button_pcb_kicad/flatcam/Project_20230128_192544.FlatPrj
--------------------------------------------------------------------------------
/schematic/button_pcb_kicad/flatcam/button_pcb_kicad-NPTH.drl_cnc.nc:
--------------------------------------------------------------------------------
1 | (G-CODE GENERATED BY FLATCAM v8.994 - www.flatcam.org - Version Date: 2020/11/7)
2 |
3 | (Name: button_pcb_kicad-NPTH.drl_cnc)
4 | (Type: G-code from Geometry)
5 | (Units: MM)
6 |
7 | (Created on Saturday, 28 January 2023 at 19:33)
8 |
9 | (Specially modified by mattwach to work with the Sainsmart 3080 that I have.)
10 |
11 |
12 | (TOOLS DIAMETER: )
13 | (Tool: 1 -> Dia: 2.2)
14 |
15 | (FEEDRATE Z: )
16 | (Tool: 1 -> Feedrate: 180.0)
17 |
18 | (FEEDRATE RAPIDS: )
19 | (Tool: 1 -> Feedrate Rapids: 1500)
20 |
21 | (Z_CUT: )
22 | (Tool: 1 -> Z_Cut: -1.7)
23 |
24 | (Tools Offset: )
25 | (Tool: 1 -> Offset Z: 0.0)
26 |
27 | (Z_MOVE: )
28 | (Tool: 1 -> Z_Move: 2)
29 |
30 | (Z Toolchange: 15.0 mm)
31 | (X,Y Toolchange: 0.0000, 0.0000 mm)
32 | (Z Start: None mm)
33 | (Z End: 10.0 mm)
34 | (X,Y End: 0.0000, 0.0000 mm)
35 | (Steps per circle: 64)
36 | (Preprocessor Excellon: default)
37 |
38 | (X range: 1.9000 ... 40.1000 mm)
39 | (Y range: -6.1000 ... -3.9000 mm)
40 |
41 | (Spindle Speed: 10000 RPM)
42 | G21
43 | G90
44 | G17
45 | G94
46 |
47 |
48 | G01 F180.00
49 |
50 | M5
51 | G00 Z15.0000
52 | G00 X0.0000 Y0.0000
53 | G00 Z15.0000
54 |
55 | G01 F180.00
56 | M03 S10000
57 | G00 X3.0000 Y-5.0000
58 | G01 Z-1.7000
59 | G01 Z0
60 | G00 Z2.0000
61 | G00 X39.0000 Y-5.0000
62 | G01 Z-1.7000
63 | G01 Z0
64 | G00 Z2.0000
65 | M05
66 | G00 Z10.00
67 | G00 X0.0 Y0.0
68 |
69 |
70 |
--------------------------------------------------------------------------------
/schematic/button_pcb_kicad/flatcam/button_pcb_kicad-PTH.drl_cnc.nc:
--------------------------------------------------------------------------------
1 | (G-CODE GENERATED BY FLATCAM v8.994 - www.flatcam.org - Version Date: 2020/11/7)
2 |
3 | (Name: button_pcb_kicad-PTH.drl_cnc)
4 | (Type: G-code from Geometry)
5 | (Units: MM)
6 |
7 | (Created on Saturday, 28 January 2023 at 19:33)
8 |
9 | (Specially modified by mattwach to work with the Sainsmart 3080 that I have.)
10 |
11 |
12 | (TOOLS DIAMETER: )
13 | (Tool: 1 -> Dia: 1.1)
14 |
15 | (FEEDRATE Z: )
16 | (Tool: 1 -> Feedrate: 300)
17 |
18 | (FEEDRATE RAPIDS: )
19 | (Tool: 1 -> Feedrate Rapids: 1500)
20 |
21 | (Z_CUT: )
22 | (Tool: 1 -> Z_Cut: -1.7)
23 |
24 | (Tools Offset: )
25 | (Tool: 1 -> Offset Z: 0.0)
26 |
27 | (Z_MOVE: )
28 | (Tool: 1 -> Z_Move: 2)
29 |
30 | (Z Toolchange: 10.0 mm)
31 | (X,Y Toolchange: 0.0000, 0.0000 mm)
32 | (Z Start: None mm)
33 | (Z End: 10.0 mm)
34 | (X,Y End: 0.0000, 0.0000 mm)
35 | (Steps per circle: 64)
36 | (Preprocessor Excellon: default)
37 |
38 | (X range: 14.7940 ... 33.0620 mm)
39 | (Y range: -7.4430 ... -1.8430 mm)
40 |
41 | (Spindle Speed: 10000 RPM)
42 | G21
43 | G90
44 | G17
45 | G94
46 |
47 |
48 | G01 F300.00
49 |
50 | M5
51 | G00 Z10.0000
52 | G00 X0.0000 Y0.0000
53 | G00 Z10.0000
54 |
55 | G01 F300.00
56 | M03 S10000
57 | G00 X15.3440 Y-2.3930
58 | G01 Z-1.7000
59 | G01 Z0
60 | G00 Z2.0000
61 | G00 X32.5120 Y-6.8930
62 | G01 Z-1.7000
63 | G01 Z0
64 | G00 Z2.0000
65 | G00 X32.5120 Y-2.3930
66 | G01 Z-1.7000
67 | G01 Z0
68 | G00 Z2.0000
69 | G00 X26.0120 Y-6.8930
70 | G01 Z-1.7000
71 | G01 Z0
72 | G00 Z2.0000
73 | G00 X26.0120 Y-2.3930
74 | G01 Z-1.7000
75 | G01 Z0
76 | G00 Z2.0000
77 | G00 X21.8440 Y-6.8930
78 | G01 Z-1.7000
79 | G01 Z0
80 | G00 Z2.0000
81 | G00 X21.8440 Y-2.3930
82 | G01 Z-1.7000
83 | G01 Z0
84 | G00 Z2.0000
85 | G00 X15.3440 Y-6.8930
86 | G01 Z-1.7000
87 | G01 Z0
88 | G00 Z2.0000
89 | M05
90 | G00 Z10.00
91 | G00 X0.0 Y0.0
92 |
93 |
94 |
--------------------------------------------------------------------------------
/schematic/button_pcb_kicad/flatcam/test.nc:
--------------------------------------------------------------------------------
1 | (CNC Regtangle Test File)
2 |
3 | G21 (Units in MM)
4 | G90 (Absolute positioning)
5 | G94 (Units per minute feed rate mode)
6 |
7 | G01 F200 (Move to starting position)
8 | G01 Z10
9 | G00 X-1 Y1
10 | M03 S10000.0 (Start motor)
11 | G01 Z1.0 (Move to dwell height)
12 |
13 | G01 F60 (Approach material)
14 | G01 Z0.0
15 | G01 F120.0 (Draw rectangle)
16 | G01 X43
17 | G01 Y-10
18 | G01 X-1
19 | G01 Y1
20 |
21 | G01 F200
22 | G01 Z10 (Exit material)
23 | M05 (Stop motor)
24 | (Test complete, EOF)
25 |
26 |
--------------------------------------------------------------------------------
/schematic/button_pcb_kicad/gerber/button_pcb_kicad-Edge_Cuts.gbr:
--------------------------------------------------------------------------------
1 | %TF.GenerationSoftware,KiCad,Pcbnew,6.0.9+dfsg-1*%
2 | %TF.CreationDate,2023-01-28T14:04:22-08:00*%
3 | %TF.ProjectId,button_pcb_kicad,62757474-6f6e-45f7-9063-625f6b696361,rev?*%
4 | %TF.SameCoordinates,PX791ddc0PY5e69ec0*%
5 | %TF.FileFunction,Profile,NP*%
6 | %FSLAX46Y46*%
7 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
8 | G04 Created by KiCad (PCBNEW 6.0.9+dfsg-1) date 2023-01-28 14:04:22*
9 | %MOMM*%
10 | %LPD*%
11 | G01*
12 | G04 APERTURE LIST*
13 | %TA.AperFunction,Profile*%
14 | %ADD10C,0.150000*%
15 | %TD*%
16 | G04 APERTURE END LIST*
17 | D10*
18 | X0Y0D02*
19 | X0Y-9000000D01*
20 | X42000000Y0D02*
21 | X0Y0D01*
22 | X42000000Y-9000000D02*
23 | X42000000Y0D01*
24 | X0Y-9000000D02*
25 | X42000000Y-9000000D01*
26 | M02*
27 |
--------------------------------------------------------------------------------
/schematic/button_pcb_kicad/gerber/button_pcb_kicad-NPTH.drl:
--------------------------------------------------------------------------------
1 | M48
2 | ; DRILL file {KiCad 6.0.9+dfsg-1} date Sat 28 Jan 2023 02:04:25 PM PST
3 | ; FORMAT={-:-/ absolute / metric / decimal}
4 | ; #@! TF.CreationDate,2023-01-28T14:04:25-08:00
5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,6.0.9+dfsg-1
6 | ; #@! TF.FileFunction,NonPlated,1,2,NPTH
7 | FMAT,2
8 | METRIC
9 | ; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill
10 | T1C2.200
11 | %
12 | G90
13 | G05
14 | T1
15 | X3.0Y-5.0
16 | X39.0Y-5.0
17 | T0
18 | M30
19 |
--------------------------------------------------------------------------------
/schematic/button_pcb_kicad/gerber/button_pcb_kicad-PTH.drl:
--------------------------------------------------------------------------------
1 | M48
2 | ; DRILL file {KiCad 6.0.9+dfsg-1} date Sat 28 Jan 2023 02:04:25 PM PST
3 | ; FORMAT={-:-/ absolute / metric / decimal}
4 | ; #@! TF.CreationDate,2023-01-28T14:04:25-08:00
5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,6.0.9+dfsg-1
6 | ; #@! TF.FileFunction,Plated,1,2,PTH
7 | FMAT,2
8 | METRIC
9 | ; #@! TA.AperFunction,Plated,PTH,ComponentDrill
10 | T1C1.100
11 | %
12 | G90
13 | G05
14 | T1
15 | X15.344Y-2.393
16 | X15.344Y-6.893
17 | X21.844Y-2.393
18 | X21.844Y-6.893
19 | X26.012Y-2.393
20 | X26.012Y-6.893
21 | X32.512Y-2.393
22 | X32.512Y-6.893
23 | T0
24 | M30
25 |
--------------------------------------------------------------------------------
/schematic/button_pcb_kicad/gerber/button_pcb_kicad-job.gbrjob:
--------------------------------------------------------------------------------
1 | {
2 | "Header": {
3 | "GenerationSoftware": {
4 | "Vendor": "KiCad",
5 | "Application": "Pcbnew",
6 | "Version": "6.0.9+dfsg-1"
7 | },
8 | "CreationDate": "2023-01-28T14:04:22-08:00"
9 | },
10 | "GeneralSpecs": {
11 | "ProjectId": {
12 | "Name": "button_pcb_kicad",
13 | "GUID": "62757474-6f6e-45f7-9063-625f6b696361",
14 | "Revision": "rev?"
15 | },
16 | "Size": {
17 | "X": 42.15,
18 | "Y": 9.15
19 | },
20 | "LayerNumber": 2,
21 | "BoardThickness": 1.6,
22 | "Finish": "None"
23 | },
24 | "DesignRules": [
25 | {
26 | "Layers": "Outer",
27 | "PadToPad": 0.2,
28 | "PadToTrack": 0.2,
29 | "TrackToTrack": 0.2,
30 | "MinLineWidth": 0.4,
31 | "TrackToRegion": 0.508,
32 | "RegionToRegion": 0.508
33 | }
34 | ],
35 | "FilesAttributes": [
36 | {
37 | "Path": "button_pcb_kicad-F_Cu.gbr",
38 | "FileFunction": "Copper,L1,Top",
39 | "FilePolarity": "Positive"
40 | },
41 | {
42 | "Path": "button_pcb_kicad-Edge_Cuts.gbr",
43 | "FileFunction": "Profile",
44 | "FilePolarity": "Positive"
45 | }
46 | ],
47 | "MaterialStackup": [
48 | {
49 | "Type": "Legend",
50 | "Name": "Top Silk Screen"
51 | },
52 | {
53 | "Type": "SolderPaste",
54 | "Name": "Top Solder Paste"
55 | },
56 | {
57 | "Type": "SolderMask",
58 | "Thickness": 0.01,
59 | "Name": "Top Solder Mask"
60 | },
61 | {
62 | "Type": "Copper",
63 | "Thickness": 0.035,
64 | "Name": "F.Cu"
65 | },
66 | {
67 | "Type": "Dielectric",
68 | "Thickness": 1.51,
69 | "Material": "FR4",
70 | "Name": "F.Cu/B.Cu",
71 | "Notes": "Type: dielectric layer 1 (from F.Cu to B.Cu)"
72 | },
73 | {
74 | "Type": "Copper",
75 | "Thickness": 0.035,
76 | "Name": "B.Cu"
77 | },
78 | {
79 | "Type": "SolderMask",
80 | "Thickness": 0.01,
81 | "Name": "Bottom Solder Mask"
82 | },
83 | {
84 | "Type": "SolderPaste",
85 | "Name": "Bottom Solder Paste"
86 | },
87 | {
88 | "Type": "Legend",
89 | "Name": "Bottom Silk Screen"
90 | }
91 | ]
92 | }
93 |
--------------------------------------------------------------------------------
/schematic/dotstar_8x8_kicad/export/matrix_clock_kicad-Edge_Cuts.gbr:
--------------------------------------------------------------------------------
1 | %TF.GenerationSoftware,KiCad,Pcbnew,6.0.7+dfsg-3*%
2 | %TF.CreationDate,2022-12-10T17:15:55-08:00*%
3 | %TF.ProjectId,matrix_clock_kicad,6d617472-6978-45f6-936c-6f636b5f6b69,rev?*%
4 | %TF.SameCoordinates,PX69fa208PY4509570*%
5 | %TF.FileFunction,Profile,NP*%
6 | %FSLAX46Y46*%
7 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
8 | G04 Created by KiCad (PCBNEW 6.0.7+dfsg-3) date 2022-12-10 17:15:55*
9 | %MOMM*%
10 | %LPD*%
11 | G01*
12 | G04 APERTURE LIST*
13 | %TA.AperFunction,Profile*%
14 | %ADD10C,0.100000*%
15 | %TD*%
16 | G04 APERTURE END LIST*
17 | D10*
18 | X4875000Y-56610000D02*
19 | G75*
20 | G03*
21 | X4875000Y-56610000I-1000000J0D01*
22 | G01*
23 | X51875000Y-3610000D02*
24 | G75*
25 | G03*
26 | X51875000Y-3610000I-1000000J0D01*
27 | G01*
28 | X0Y0D02*
29 | X0Y-63500000D01*
30 | X54610000Y0D02*
31 | X0Y0D01*
32 | X54610000Y-63500000D02*
33 | X54610000Y0D01*
34 | X0Y-63500000D02*
35 | X54610000Y-63500000D01*
36 | M02*
37 |
--------------------------------------------------------------------------------
/schematic/dotstar_8x8_kicad/export/matrix_clock_kicad-NPTH.drl:
--------------------------------------------------------------------------------
1 | M48
2 | ; DRILL file {KiCad 6.0.7+dfsg-3} date Sat 10 Dec 2022 05:16:35 PM PST
3 | ; FORMAT={-:-/ absolute / metric / decimal}
4 | ; #@! TF.CreationDate,2022-12-10T17:16:35-08:00
5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,6.0.7+dfsg-3
6 | ; #@! TF.FileFunction,NonPlated,1,2,NPTH
7 | FMAT,2
8 | METRIC
9 | ; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill
10 | T1C1.500
11 | ; #@! TA.AperFunction,NonPlated,NPTH,ComponentDrill
12 | T2C1.800
13 | %
14 | G90
15 | G05
16 | T1
17 | X15.99Y-8.24
18 | X20.84Y-8.24
19 | T2
20 | X15.69Y-5.21
21 | X21.14Y-5.21
22 | T0
23 | M30
24 |
--------------------------------------------------------------------------------
/schematic/dotstar_8x8_kicad/export/matrix_clock_kicad-PTH.drl:
--------------------------------------------------------------------------------
1 | M48
2 | ; DRILL file {KiCad 6.0.7+dfsg-3} date Sat 10 Dec 2022 05:16:35 PM PST
3 | ; FORMAT={-:-/ absolute / metric / decimal}
4 | ; #@! TF.CreationDate,2022-12-10T17:16:35-08:00
5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,6.0.7+dfsg-3
6 | ; #@! TF.FileFunction,Plated,1,2,PTH
7 | FMAT,2
8 | METRIC
9 | ; #@! TA.AperFunction,Plated,PTH,ComponentDrill
10 | T1C0.800
11 | ; #@! TA.AperFunction,Plated,PTH,ComponentDrill
12 | T2C1.000
13 | ; #@! TA.AperFunction,Plated,PTH,ComponentDrill
14 | T3C1.020
15 | ; #@! TA.AperFunction,Plated,PTH,ComponentDrill
16 | T4C1.300
17 | %
18 | G90
19 | G05
20 | T1
21 | X24.13Y-58.42
22 | X24.13Y-60.92
23 | T2
24 | X8.89Y-59.69
25 | X11.43Y-59.69
26 | X13.97Y-59.69
27 | X16.51Y-59.69
28 | X50.165Y-12.075
29 | X50.165Y-14.615
30 | X50.165Y-17.155
31 | X50.165Y-19.695
32 | T3
33 | X9.525Y-5.08
34 | X9.525Y-7.62
35 | X9.525Y-10.16
36 | X9.525Y-12.7
37 | X9.525Y-15.24
38 | X9.525Y-17.78
39 | X9.525Y-20.32
40 | X9.525Y-22.86
41 | X9.525Y-25.4
42 | X9.525Y-27.94
43 | X9.525Y-30.48
44 | X9.525Y-33.02
45 | X9.525Y-35.56
46 | X9.525Y-38.1
47 | X9.525Y-40.64
48 | X9.525Y-43.18
49 | X9.525Y-45.72
50 | X9.525Y-48.26
51 | X9.525Y-50.8
52 | X9.525Y-53.34
53 | X15.875Y-53.11
54 | X18.415Y-53.11
55 | X20.955Y-53.11
56 | X27.305Y-5.08
57 | X27.305Y-7.62
58 | X27.305Y-10.16
59 | X27.305Y-12.7
60 | X27.305Y-15.24
61 | X27.305Y-17.78
62 | X27.305Y-20.32
63 | X27.305Y-22.86
64 | X27.305Y-25.4
65 | X27.305Y-27.94
66 | X27.305Y-30.48
67 | X27.305Y-33.02
68 | X27.305Y-35.56
69 | X27.305Y-38.1
70 | X27.305Y-40.64
71 | X27.305Y-43.18
72 | X27.305Y-45.72
73 | X27.305Y-48.26
74 | X27.305Y-50.8
75 | X27.305Y-53.34
76 | T4
77 | X37.32Y-33.655
78 | X37.32Y-38.655
79 | X37.465Y-48.26
80 | X37.465Y-53.26
81 | X49.82Y-33.655
82 | X49.82Y-38.655
83 | X49.965Y-48.26
84 | X49.965Y-53.26
85 | T0
86 | M30
87 |
--------------------------------------------------------------------------------
/schematic/dotstar_8x8_kicad/export/matrix_clock_kicad-job.gbrjob:
--------------------------------------------------------------------------------
1 | {
2 | "Header": {
3 | "GenerationSoftware": {
4 | "Vendor": "KiCad",
5 | "Application": "Pcbnew",
6 | "Version": "6.0.7+dfsg-3"
7 | },
8 | "CreationDate": "2022-12-10T17:15:55-08:00"
9 | },
10 | "GeneralSpecs": {
11 | "ProjectId": {
12 | "Name": "matrix_clock_kicad",
13 | "GUID": "6d617472-6978-45f6-936c-6f636b5f6b69",
14 | "Revision": "rev?"
15 | },
16 | "Size": {
17 | "X": 54.71,
18 | "Y": 63.6
19 | },
20 | "LayerNumber": 2,
21 | "BoardThickness": 1.6,
22 | "Finish": "None"
23 | },
24 | "DesignRules": [
25 | {
26 | "Layers": "Outer",
27 | "PadToPad": 0.2,
28 | "PadToTrack": 0.2,
29 | "TrackToTrack": 0.2,
30 | "MinLineWidth": 0.5,
31 | "TrackToRegion": 0.508,
32 | "RegionToRegion": 0.508
33 | }
34 | ],
35 | "FilesAttributes": [
36 | {
37 | "Path": "matrix_clock_kicad-B_Cu.gbr",
38 | "FileFunction": "Copper,L2,Bot",
39 | "FilePolarity": "Positive"
40 | },
41 | {
42 | "Path": "matrix_clock_kicad-Edge_Cuts.gbr",
43 | "FileFunction": "Profile",
44 | "FilePolarity": "Positive"
45 | }
46 | ],
47 | "MaterialStackup": [
48 | {
49 | "Type": "Legend",
50 | "Name": "Top Silk Screen"
51 | },
52 | {
53 | "Type": "SolderPaste",
54 | "Name": "Top Solder Paste"
55 | },
56 | {
57 | "Type": "SolderMask",
58 | "Thickness": 0.01,
59 | "Name": "Top Solder Mask"
60 | },
61 | {
62 | "Type": "Copper",
63 | "Thickness": 0.035,
64 | "Name": "F.Cu"
65 | },
66 | {
67 | "Type": "Dielectric",
68 | "Thickness": 1.51,
69 | "Material": "FR4",
70 | "Name": "F.Cu/B.Cu",
71 | "Notes": "Type: dielectric layer 1 (from F.Cu to B.Cu)"
72 | },
73 | {
74 | "Type": "Copper",
75 | "Thickness": 0.035,
76 | "Name": "B.Cu"
77 | },
78 | {
79 | "Type": "SolderMask",
80 | "Thickness": 0.01,
81 | "Name": "Bottom Solder Mask"
82 | },
83 | {
84 | "Type": "SolderPaste",
85 | "Name": "Bottom Solder Paste"
86 | },
87 | {
88 | "Type": "Legend",
89 | "Name": "Bottom Silk Screen"
90 | }
91 | ]
92 | }
93 |
--------------------------------------------------------------------------------
/schematic/dotstar_8x8_kicad/flatcam/matrix_clock.FlatPrj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/schematic/dotstar_8x8_kicad/flatcam/matrix_clock.FlatPrj
--------------------------------------------------------------------------------
/schematic/dotstar_8x8_kicad/flatcam/matrix_clock_kicad-PTH.mounting_drill.nc:
--------------------------------------------------------------------------------
1 | (G-CODE GENERATED BY FLATCAM v8.994 - www.flatcam.org - Version Date: 2020/11/7)
2 |
3 | (Name: matrix_clock_kicad-PTH.drl_edit_3_cnc)
4 | (Type: G-code from Geometry)
5 | (Units: MM)
6 |
7 | (Created on Sunday, 11 December 2022 at 07:05)
8 |
9 | (Specially modified by mattwach to work with the Sainsmart 3080 that I have.)
10 |
11 |
12 | (TOOLS DIAMETER: )
13 | (Tool: 1 -> Dia: 2.0)
14 |
15 | (FEEDRATE Z: )
16 | (Tool: 1 -> Feedrate: 120.0)
17 |
18 | (FEEDRATE RAPIDS: )
19 | (Tool: 1 -> Feedrate Rapids: 1500)
20 |
21 | (Z_CUT: )
22 | (Tool: 1 -> Z_Cut: -1.7)
23 |
24 | (Tools Offset: )
25 | (Tool: 1 -> Offset Z: 0.0)
26 |
27 | (Z_MOVE: )
28 | (Tool: 1 -> Z_Move: 2)
29 |
30 | (Z Toolchange: 15 mm)
31 | (X,Y Toolchange: 0.0000, 0.0000 mm)
32 | (Z Start: None mm)
33 | (Z End: 0.5 mm)
34 | (X,Y End: 0.0000, 0.0000 mm)
35 | (Steps per circle: 64)
36 | (Preprocessor Excellon: default)
37 |
38 | (X range: 2.7000 ... 51.8000 mm)
39 | (Y range: -57.7000 ... -2.6000 mm)
40 |
41 | (Spindle Speed: 10000 RPM)
42 | G21
43 | G90
44 | G17
45 | G94
46 |
47 |
48 | G01 F120.00
49 |
50 | M5
51 | G00 Z15.0000
52 | G00 X0.0000 Y0.0000
53 | (MSG, Change to Tool Dia = 2.0000 ||| Total drills for tool T1 = 2)
54 | G00 Z15.0000
55 |
56 | G01 F120.00
57 | M03 S10000
58 | G00 X3.7000 Y-3.6000
59 | G01 Z-1.7000
60 | G01 Z0
61 | G00 Z2.0000
62 | G00 X50.8000 Y-56.7000
63 | G01 Z-1.7000
64 | G01 Z0
65 | G00 Z2.0000
66 | M05
67 | G00 Z0.50
68 | G00 X0.0 Y0.0
69 |
70 |
71 |
--------------------------------------------------------------------------------
/schematic/dotstar_8x8_kicad/flatcam/matrix_clock_kicad-PTH.small_drill.nc:
--------------------------------------------------------------------------------
1 | (G-CODE GENERATED BY FLATCAM v8.994 - www.flatcam.org - Version Date: 2020/11/7)
2 |
3 | (Name: matrix_clock_kicad-PTH.drl_edit_5_cnc)
4 | (Type: G-code from Geometry)
5 | (Units: MM)
6 |
7 | (Created on Monday, 12 December 2022 at 09:11)
8 |
9 | (Specially modified by mattwach to work with the Sainsmart 3080 that I have.)
10 |
11 |
12 | (TOOLS DIAMETER: )
13 | (Tool: 1 -> Dia: 0.9)
14 |
15 | (FEEDRATE Z: )
16 | (Tool: 1 -> Feedrate: 300)
17 |
18 | (FEEDRATE RAPIDS: )
19 | (Tool: 1 -> Feedrate Rapids: 1500)
20 |
21 | (Z_CUT: )
22 | (Tool: 1 -> Z_Cut: -1.7)
23 |
24 | (Tools Offset: )
25 | (Tool: 1 -> Offset Z: 0.0)
26 |
27 | (Z_MOVE: )
28 | (Tool: 1 -> Z_Move: 2)
29 |
30 | (Z Toolchange: 15 mm)
31 | (X,Y Toolchange: 0.0000, 0.0000 mm)
32 | (Z Start: None mm)
33 | (Z End: 0.5 mm)
34 | (X,Y End: 0.0000, 0.0000 mm)
35 | (Steps per circle: 64)
36 | (Preprocessor Excellon: default)
37 |
38 | (X range: 3.9900 ... 46.1650 mm)
39 | (Y range: -61.3700 ... -11.6250 mm)
40 |
41 | (Spindle Speed: 10000 RPM)
42 | G21
43 | G90
44 | G17
45 | G94
46 |
47 |
48 | G01 F300.00
49 |
50 | M5
51 | G00 Z15.0000
52 | G00 X0.0000 Y0.0000
53 | G00 Z15.0000
54 |
55 | G01 F300.00
56 | M03 S10000
57 | G00 X30.4750 Y-58.4200
58 | G01 Z-1.7000
59 | G01 Z0
60 | G00 Z2.0000
61 | G00 X4.6400 Y-53.2600
62 | G01 Z-1.7000
63 | G01 Z0
64 | G00 Z2.0000
65 | G00 X4.6400 Y-48.2600
66 | G01 Z-1.7000
67 | G01 Z0
68 | G00 Z2.0000
69 | G00 X4.7850 Y-38.6550
70 | G01 Z-1.7000
71 | G01 Z0
72 | G00 Z2.0000
73 | G00 X4.7850 Y-33.6550
74 | G01 Z-1.7000
75 | G01 Z0
76 | G00 Z2.0000
77 | G00 X17.1400 Y-53.2600
78 | G01 Z-1.7000
79 | G01 Z0
80 | G00 Z2.0000
81 | G00 X17.1400 Y-48.2600
82 | G01 Z-1.7000
83 | G01 Z0
84 | G00 Z2.0000
85 | G00 X17.2850 Y-38.6550
86 | G01 Z-1.7000
87 | G01 Z0
88 | G00 Z2.0000
89 | G00 X17.2850 Y-33.6550
90 | G01 Z-1.7000
91 | G01 Z0
92 | G00 Z2.0000
93 | G00 X4.4400 Y-19.6950
94 | G01 Z-1.7000
95 | G01 Z0
96 | G00 Z2.0000
97 | G00 X4.4400 Y-17.1550
98 | G01 Z-1.7000
99 | G01 Z0
100 | G00 Z2.0000
101 | G00 X4.4400 Y-14.6150
102 | G01 Z-1.7000
103 | G01 Z0
104 | G00 Z2.0000
105 | G00 X4.4400 Y-12.0750
106 | G01 Z-1.7000
107 | G01 Z0
108 | G00 Z2.0000
109 | G00 X38.0950 Y-59.6900
110 | G01 Z-1.7000
111 | G01 Z0
112 | G00 Z2.0000
113 | G00 X40.6350 Y-59.6900
114 | G01 Z-1.7000
115 | G01 Z0
116 | G00 Z2.0000
117 | G00 X43.1750 Y-59.6900
118 | G01 Z-1.7000
119 | G01 Z0
120 | G00 Z2.0000
121 | G00 X45.7150 Y-59.6900
122 | G01 Z-1.7000
123 | G01 Z0
124 | G00 Z2.0000
125 | G00 X30.4750 Y-60.9200
126 | G01 Z-1.7000
127 | G01 Z0
128 | G00 Z2.0000
129 | M05
130 | G00 Z0.50
131 | G00 X0.0 Y0.0
132 |
133 |
134 |
--------------------------------------------------------------------------------
/schematic/dotstar_8x8_kicad/flatcam/test.nc:
--------------------------------------------------------------------------------
1 | (CNC Regtangle Test File)
2 |
3 | G21 (Units in MM)
4 | G90 (Absolute positioning)
5 | G94 (Units per minute feed rate mode)
6 |
7 | G01 F200 (Move to starting position)
8 | G01 Z10
9 | G00 X-1 Y1
10 | M03 S10000.0 (Start motor)
11 | G01 Z1.0 (Move to dwell height)
12 |
13 | G01 F60 (Approach material)
14 | G01 Z0.0
15 | G01 F120.0 (Draw rectangle)
16 | G01 X55
17 | G01 Y-64
18 | G01 X-1
19 | G01 Y1
20 |
21 | G01 F200
22 | G01 Z10 (Exit material)
23 | M05 (Stop motor)
24 | (Test complete, EOF)
25 |
26 |
--------------------------------------------------------------------------------
/schematic/dotstar_8x8_kicad/fp-info-cache:
--------------------------------------------------------------------------------
1 | 4957761239997
2 | Raspberry_Pi_Pico
3 | Crystal_SMD_HC49-US
4 | SMD Crystal HC-49-SD http://cdn-reichelt.de/documents/datenblatt/B400/xxx-HC49-SMD.pdf, 11.4x4.7mm^2 package
5 | SMD SMT crystal
6 | 0
7 | 2
8 | 2
9 | Raspberry_Pi_Pico
10 | RP2040-QFN-56
11 | QFN, 56 Pin (http://www.cypress.com/file/416486/download#page=40), generated with kicad-footprint-generator ipc_dfn_qfn_generator.py
12 | QFN DFN_QFN
13 | 0
14 | 70
15 | 57
16 | Raspberry_Pi_Pico
17 | RPi_Pico_SMD_TH
18 | Through hole straight pin header, 2x20, 2.54mm pitch, double rows
19 | Through hole pin header THT 2x20 2.54mm double row
20 | 0
21 | 86
22 | 43
23 |
--------------------------------------------------------------------------------
/schematic/dotstar_8x8_kicad/matrix_clock_kicad.kicad_prl:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "active_layer": 37,
4 | "active_layer_preset": "All Layers",
5 | "auto_track_width": true,
6 | "hidden_nets": [],
7 | "high_contrast_mode": 0,
8 | "net_color_mode": 1,
9 | "opacity": {
10 | "pads": 1.0,
11 | "tracks": 1.0,
12 | "vias": 1.0,
13 | "zones": 0.6
14 | },
15 | "ratsnest_display_mode": 0,
16 | "selection_filter": {
17 | "dimensions": true,
18 | "footprints": true,
19 | "graphics": true,
20 | "keepouts": true,
21 | "lockedItems": true,
22 | "otherItems": true,
23 | "pads": true,
24 | "text": true,
25 | "tracks": true,
26 | "vias": true,
27 | "zones": true
28 | },
29 | "visible_items": [
30 | 0,
31 | 1,
32 | 2,
33 | 3,
34 | 4,
35 | 5,
36 | 8,
37 | 9,
38 | 10,
39 | 11,
40 | 12,
41 | 13,
42 | 14,
43 | 15,
44 | 16,
45 | 17,
46 | 18,
47 | 19,
48 | 20,
49 | 21,
50 | 22,
51 | 23,
52 | 24,
53 | 25,
54 | 26,
55 | 27,
56 | 28,
57 | 29,
58 | 30,
59 | 32,
60 | 33,
61 | 34,
62 | 35,
63 | 36
64 | ],
65 | "visible_layers": "fffffff_ffffffff",
66 | "zone_display_mode": 0
67 | },
68 | "meta": {
69 | "filename": "matrix_clock_kicad.kicad_prl",
70 | "version": 3
71 | },
72 | "project": {
73 | "files": []
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/schematic/led_matrix_64x32_kicad/flatcam/Project_20230127_103059.FlatPrj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mattwach/matrix_clock/750646eb556ee4517caf140ce9ef55ca965173a1/schematic/led_matrix_64x32_kicad/flatcam/Project_20230127_103059.FlatPrj
--------------------------------------------------------------------------------
/schematic/led_matrix_64x32_kicad/fp-info-cache:
--------------------------------------------------------------------------------
1 | 5011857610853
2 | PI Pico
3 | Crystal_SMD_HC49-US
4 | SMD Crystal HC-49-SD http://cdn-reichelt.de/documents/datenblatt/B400/xxx-HC49-SMD.pdf, 11.4x4.7mm^2 package
5 | SMD SMT crystal
6 | 0
7 | 2
8 | 2
9 | PI Pico
10 | RP2040-QFN-56
11 | QFN, 56 Pin (http://www.cypress.com/file/416486/download#page=40), generated with kicad-footprint-generator ipc_dfn_qfn_generator.py
12 | QFN DFN_QFN
13 | 0
14 | 70
15 | 57
16 | PI Pico
17 | RPi_Pico_SMD_TH
18 | Through hole straight pin header, 2x20, 2.54mm pitch, double rows
19 | Through hole pin header THT 2x20 2.54mm double row
20 | 0
21 | 86
22 | 43
23 |
--------------------------------------------------------------------------------
/schematic/led_matrix_64x32_kicad/gerber/led_matrix_64x32_kicad-F_Paste.gbr:
--------------------------------------------------------------------------------
1 | %TF.GenerationSoftware,KiCad,Pcbnew,6.0.9+dfsg-1*%
2 | %TF.CreationDate,2023-01-27T09:36:51-08:00*%
3 | %TF.ProjectId,led_matrix_64x32_kicad,6c65645f-6d61-4747-9269-785f33327836,rev?*%
4 | %TF.SameCoordinates,PX2efe460PY2edf448*%
5 | %TF.FileFunction,Paste,Top*%
6 | %TF.FilePolarity,Positive*%
7 | %FSLAX46Y46*%
8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
9 | G04 Created by KiCad (PCBNEW 6.0.9+dfsg-1) date 2023-01-27 09:36:51*
10 | %MOMM*%
11 | %LPD*%
12 | G01*
13 | G04 APERTURE LIST*
14 | G04 Aperture macros list*
15 | %AMRoundRect*
16 | 0 Rectangle with rounded corners*
17 | 0 $1 Rounding radius*
18 | 0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
19 | 0 Add a 4 corners polygon primitive as box body*
20 | 4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
21 | 0 Add four circle primitives for the rounded corners*
22 | 1,1,$1+$1,$2,$3*
23 | 1,1,$1+$1,$4,$5*
24 | 1,1,$1+$1,$6,$7*
25 | 1,1,$1+$1,$8,$9*
26 | 0 Add four rect primitives between the rounded corners*
27 | 20,1,$1+$1,$2,$3,$4,$5,0*
28 | 20,1,$1+$1,$4,$5,$6,$7,0*
29 | 20,1,$1+$1,$6,$7,$8,$9,0*
30 | 20,1,$1+$1,$8,$9,$2,$3,0*%
31 | G04 Aperture macros list end*
32 | %TA.AperFunction,Profile*%
33 | %ADD10C,0.100000*%
34 | %TD*%
35 | %ADD11RoundRect,0.250000X0.337500X0.475000X-0.337500X0.475000X-0.337500X-0.475000X0.337500X-0.475000X0*%
36 | %ADD12R,0.510000X0.700000*%
37 | %ADD13RoundRect,0.250000X-0.350000X-0.450000X0.350000X-0.450000X0.350000X0.450000X-0.350000X0.450000X0*%
38 | %ADD14RoundRect,0.500000X0.500000X0.500000X-0.500000X0.500000X-0.500000X-0.500000X0.500000X-0.500000X0*%
39 | G04 APERTURE END LIST*
40 | D10*
41 | X0Y0D02*
42 | X70104000Y0D01*
43 | X70104000Y0D02*
44 | X70104000Y-61976000D01*
45 | X0Y-61976000D02*
46 | X70104000Y-61976000D01*
47 | X0Y0D02*
48 | X0Y-61976000D01*
49 | D11*
50 | %TO.C,C3*%
51 | X66294000Y-55880000D03*
52 | X64219000Y-55880000D03*
53 | %TD*%
54 | D12*
55 | %TO.C,U2*%
56 | X66101000Y-45978500D03*
57 | X65151000Y-45978500D03*
58 | X64201000Y-45978500D03*
59 | X64201000Y-48298500D03*
60 | X66101000Y-48298500D03*
61 | %TD*%
62 | D13*
63 | %TO.C,R1*%
64 | X64167000Y-51583500D03*
65 | X66167000Y-51583500D03*
66 | %TD*%
67 | D14*
68 | %TO.C,SW3*%
69 | X27432000Y-31877000D03*
70 | X27432000Y-39877000D03*
71 | %TD*%
72 | D11*
73 | %TO.C,C2*%
74 | X66167000Y-42545000D03*
75 | X64092000Y-42545000D03*
76 | %TD*%
77 | M02*
78 |
--------------------------------------------------------------------------------
/schematic/led_matrix_64x32_kicad/gerber/led_matrix_64x32_kicad-job.gbrjob:
--------------------------------------------------------------------------------
1 | {
2 | "Header": {
3 | "GenerationSoftware": {
4 | "Vendor": "KiCad",
5 | "Application": "Pcbnew",
6 | "Version": "6.0.9+dfsg-1"
7 | },
8 | "CreationDate": "2023-01-27T09:36:51-08:00"
9 | },
10 | "GeneralSpecs": {
11 | "ProjectId": {
12 | "Name": "led_matrix_64x32_kicad",
13 | "GUID": "6c65645f-6d61-4747-9269-785f33327836",
14 | "Revision": "rev?"
15 | },
16 | "Size": {
17 | "X": 70.204,
18 | "Y": 62.076
19 | },
20 | "LayerNumber": 2,
21 | "BoardThickness": 1.6,
22 | "Finish": "None"
23 | },
24 | "DesignRules": [
25 | {
26 | "Layers": "Outer",
27 | "PadToPad": 0.2,
28 | "PadToTrack": 0.2,
29 | "TrackToTrack": 0.2,
30 | "MinLineWidth": 0.4,
31 | "TrackToRegion": 0.508,
32 | "RegionToRegion": 0.508
33 | }
34 | ],
35 | "FilesAttributes": [
36 | {
37 | "Path": "led_matrix_64x32_kicad-F_Paste.gbr",
38 | "FileFunction": "SolderPaste,Top",
39 | "FilePolarity": "Positive"
40 | }
41 | ],
42 | "MaterialStackup": [
43 | {
44 | "Type": "Legend",
45 | "Name": "Top Silk Screen"
46 | },
47 | {
48 | "Type": "SolderPaste",
49 | "Name": "Top Solder Paste"
50 | },
51 | {
52 | "Type": "SolderMask",
53 | "Thickness": 0.01,
54 | "Name": "Top Solder Mask"
55 | },
56 | {
57 | "Type": "Copper",
58 | "Thickness": 0.035,
59 | "Name": "F.Cu"
60 | },
61 | {
62 | "Type": "Dielectric",
63 | "Thickness": 1.51,
64 | "Material": "FR4",
65 | "Name": "F.Cu/B.Cu",
66 | "Notes": "Type: dielectric layer 1 (from F.Cu to B.Cu)"
67 | },
68 | {
69 | "Type": "Copper",
70 | "Thickness": 0.035,
71 | "Name": "B.Cu"
72 | },
73 | {
74 | "Type": "SolderMask",
75 | "Thickness": 0.01,
76 | "Name": "Bottom Solder Mask"
77 | },
78 | {
79 | "Type": "SolderPaste",
80 | "Name": "Bottom Solder Paste"
81 | },
82 | {
83 | "Type": "Legend",
84 | "Name": "Bottom Silk Screen"
85 | }
86 | ]
87 | }
88 |
--------------------------------------------------------------------------------
/schematic/led_matrix_64x32_kicad/led_matrix_64x32_kicad.kicad_prl:
--------------------------------------------------------------------------------
1 | {
2 | "board": {
3 | "active_layer": 36,
4 | "active_layer_preset": "",
5 | "auto_track_width": true,
6 | "hidden_nets": [],
7 | "high_contrast_mode": 0,
8 | "net_color_mode": 1,
9 | "opacity": {
10 | "pads": 1.0,
11 | "tracks": 1.0,
12 | "vias": 1.0,
13 | "zones": 0.6
14 | },
15 | "ratsnest_display_mode": 0,
16 | "selection_filter": {
17 | "dimensions": true,
18 | "footprints": true,
19 | "graphics": true,
20 | "keepouts": true,
21 | "lockedItems": true,
22 | "otherItems": true,
23 | "pads": true,
24 | "text": true,
25 | "tracks": true,
26 | "vias": true,
27 | "zones": true
28 | },
29 | "visible_items": [
30 | 0,
31 | 1,
32 | 2,
33 | 3,
34 | 4,
35 | 5,
36 | 8,
37 | 9,
38 | 10,
39 | 11,
40 | 12,
41 | 13,
42 | 14,
43 | 15,
44 | 16,
45 | 17,
46 | 18,
47 | 19,
48 | 20,
49 | 21,
50 | 22,
51 | 23,
52 | 24,
53 | 25,
54 | 26,
55 | 27,
56 | 28,
57 | 29,
58 | 30,
59 | 32,
60 | 33,
61 | 34,
62 | 35,
63 | 36
64 | ],
65 | "visible_layers": "fffffef_ffffffff",
66 | "zone_display_mode": 1
67 | },
68 | "meta": {
69 | "filename": "led_matrix_64x32_kicad.kicad_prl",
70 | "version": 3
71 | },
72 | "project": {
73 | "files": []
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.12)
2 |
3 | # Pull in SDK (must be before project)
4 | include(pico_sdk_import.cmake)
5 |
6 | project(pico_examples C CXX ASM)
7 | set(CMAKE_C_STANDARD 11)
8 | set(CMAKE_CXX_STANDARD 17)
9 |
10 | if (PICO_SDK_VERSION_STRING VERSION_LESS "1.3.0")
11 | message(FATAL_ERROR "Raspberry Pi Pico SDK version 1.3.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
12 | endif()
13 |
14 | set(PICO_EXAMPLES_PATH ${PROJECT_SOURCE_DIR})
15 |
16 | # Choose a clock source
17 | set(CLOCK_SOURCE clock_ds3231)
18 | #set(CLOCK_SOURCE clock_pico_internal)
19 |
20 | # Choose an led matrix
21 | #set(LED_MATRIX_SOURCE led_matrix_dotstar)
22 | set(LED_MATRIX_SOURCE led_matrix_64x32)
23 |
24 | # Initialize the SDK
25 | pico_sdk_init()
26 |
27 | add_compile_options(-Wall
28 | -Wno-format # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int
29 | -Wno-unused-function # we have some for the docs that aren't called
30 | -Wno-maybe-uninitialized
31 | -D${LED_MATRIX_SOURCE}
32 | )
33 |
34 | add_executable(matrix_clock
35 | ${CLOCK_SOURCE}.c
36 | ${LED_MATRIX_SOURCE}.c
37 | buttons.c
38 | clock_render.c
39 | clock_settings.c
40 | colors.c
41 | debounce.c
42 | debug.c
43 | main.c
44 | monitor.c
45 | number_draw.c
46 | set_time_low_res.c
47 | set_time_high_res.c
48 | render/blank.c
49 | render/bounce.c
50 | render/fade.c
51 | render/drops.c
52 | render/matrix.c
53 | render/matrix_with_numbers.c
54 | render/number_cascade.c
55 | render/number_cascade_hires.c
56 | render/waveform.c
57 | )
58 |
59 | # pull in common dependencies
60 | target_link_libraries(matrix_clock
61 | pico_stdlib
62 | UART_CONSOLE
63 | )
64 |
65 | if(CLOCK_SOURCE STREQUAL clock_pico_internal)
66 | target_link_libraries(matrix_clock
67 | hardware_rtc
68 | )
69 | endif()
70 |
71 | if(CLOCK_SOURCE STREQUAL clock_ds3231)
72 | target_link_libraries(matrix_clock
73 | hardware_i2c
74 | )
75 | endif()
76 |
77 | if(LED_MATRIX_SOURCE STREQUAL led_matrix_dotstar)
78 | target_link_libraries(matrix_clock
79 | hardware_spi
80 | )
81 | endif()
82 |
83 | if(LED_MATRIX_SOURCE STREQUAL led_matrix_64x32)
84 | target_link_libraries(matrix_clock
85 | pico_multicore
86 | )
87 | endif()
88 |
89 | # enable usb output, disable uart output
90 | pico_enable_stdio_usb(matrix_clock 1)
91 | pico_enable_stdio_uart(matrix_clock 0)
92 |
93 | # create map/bin/hex file etc.
94 | pico_add_extra_outputs(matrix_clock)
95 |
96 | add_subdirectory(pico_uart_console)
97 |
--------------------------------------------------------------------------------
/src/bootstrap.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ ! -f pico_uart_console/CMakeLists.txt ]; then
4 | git submodule init
5 | git submodule update
6 | fi
7 |
8 | rm -rf build
9 | mkdir build
10 | cd build
11 | cmake ..
12 |
13 |
--------------------------------------------------------------------------------
/src/buttons.c:
--------------------------------------------------------------------------------
1 | #include "buttons.h"
2 | #include "debounce.h"
3 | #include "led_matrix.h"
4 | #include "hardware/gpio.h"
5 | #include "pico/stdlib.h"
6 |
7 | #if defined(led_matrix_dotstar)
8 | #define INCREMENT_BUTTON_GPIO 15
9 | #define SELECT_BUTTON_GPIO 14
10 | #elif defined(led_matrix_64x32)
11 | #define INCREMENT_BUTTON_GPIO 26
12 | #define SELECT_BUTTON_GPIO 27
13 | #else
14 | #error Unknown LED_MATRIX_SOURCE
15 | #endif
16 |
17 | #define CURRENT_OVER_GPIO 7
18 | #define CURRENT_OVER_FRAMES (5000 / FRAME_DELAY_MS)
19 | #define DEBOUNCE_MS 10
20 |
21 | struct Debounce select_db;
22 | struct Debounce increment_db;
23 | uint8_t button_bit_array;
24 | uint32_t current_over_frames;
25 |
26 | static inline uint32_t uptime_ms() {
27 | return to_ms_since_boot(get_absolute_time());
28 | }
29 |
30 | // Callback for gpio_set_irq_callback. Since it's an ISR,
31 | // try to avoid expensive operations.
32 | static void button_pressed_callback(uint gpio, uint32_t events) {
33 | switch (gpio) {
34 | case SELECT_BUTTON_GPIO:
35 | // The callback helper helps filter away debounce glitches
36 | // The debounce_gpio_irq_callback_helper has a side effect (updates state in
37 | // the debounce structure so it should always be called.
38 | if (debounce_gpio_irq_callback_helper(&select_db, uptime_ms(), events) &&
39 | select_db.val) {
40 | button_bit_array |= SELECT_BUTTON;
41 | }
42 | break;
43 | case INCREMENT_BUTTON_GPIO:
44 | // The comment for SELECT_BUTTON_GPIO above also apply here.
45 | if (debounce_gpio_irq_callback_helper(&increment_db, uptime_ms(), events) &&
46 | increment_db.val) {
47 | button_bit_array |= INCREMENT_BUTTON;
48 | }
49 | break;
50 | case CURRENT_OVER_GPIO:
51 | current_over_frames = CURRENT_OVER_FRAMES;
52 | break;
53 | }
54 | }
55 |
56 | // Sets up a pin to sense a button press. Hardware-wise the button is
57 | // connected to the pin and to ground. The code below sets the internal
58 | // pullup for the button so the pin will sit at 3.3V when the button
59 | // is not pressed. When the button is pressed, the 3.3V will be pulled
60 | // to ground which is an event that the pico is configured to recognize
61 | // and raise an interrupt for.
62 | static void setup_gpio(uint gpio) {
63 | gpio_init(gpio);
64 | gpio_set_dir(gpio, GPIO_IN);
65 | gpio_pull_up(gpio);
66 | sleep_ms(1); // give the pullup some time to do it's thing. Maybe not needed.
67 | gpio_set_irq_enabled(gpio, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true);
68 | }
69 |
70 | void buttons_init(void) {
71 | // Setup two GPIOs for select and increment buttons.
72 | // These are connected to ground though a button. The chip
73 | // is then configured to use internal pullup resistors.
74 | setup_gpio(SELECT_BUTTON_GPIO);
75 | setup_gpio(INCREMENT_BUTTON_GPIO);
76 |
77 | // current over is for detecting if the current was limited
78 | setup_gpio(CURRENT_OVER_GPIO);
79 |
80 | gpio_set_irq_callback(button_pressed_callback);
81 | irq_set_enabled(IO_IRQ_BANK0, true);
82 |
83 | debounce_init(&select_db, DEBOUNCE_MS);
84 | debounce_init(&increment_db, DEBOUNCE_MS);
85 | button_bit_array = 0x00;
86 | }
87 |
88 | uint8_t is_current_over(void) {
89 | if (current_over_frames > 0) {
90 | --current_over_frames;
91 | return 1;
92 | }
93 | return 0;
94 | }
95 |
96 | uint8_t buttons_get(void) {
97 | const uint8_t value = button_bit_array;
98 | button_bit_array = 0x00; // reset
99 | return value;
100 | }
101 |
--------------------------------------------------------------------------------
/src/buttons.h:
--------------------------------------------------------------------------------
1 | #ifndef BUTTONS_H
2 | #define BUTTONS_H
3 | // Manages button state
4 |
5 | #include
6 |
7 | // These define bits in the return array. Sequence should be 1, 2, 4, 8, ...
8 | #define SELECT_BUTTON 1
9 | #define INCREMENT_BUTTON 2
10 |
11 | void buttons_init(void);
12 |
13 | // returns current button state as a bit array
14 | // Note that reading the value also resets the state back to unpressed
15 | // e.g.
16 | // * somewone presses and releases the SELECT_BUTTON
17 | // * some amount of time goes by
18 | // * buttons_get() is called
19 | // * SELECT_BUTTON is returned
20 | // * any future calls to buttons_get() return zero until a button
21 | // is pressed again.
22 | uint8_t buttons_get(void);
23 |
24 | // returns a 1 if there is a recent current overload event.
25 | uint8_t is_current_over(void);
26 |
27 | #endif
28 |
--------------------------------------------------------------------------------
/src/clock.h:
--------------------------------------------------------------------------------
1 | #ifndef CLOCK_H
2 | #define CLOCK_H
3 |
4 | // Generic clock header.
5 | //
6 | // The currently-implemented .c file talks to a DS3231 RTC module but
7 | // you can use other modules, an atomic clock receiver, a gps module,
8 | // internet itme or whatever you want on the backend - it just has to
9 | // provide the following functions as-declared below. Thhen just
10 | // link in the new implementation in CMakeLists.txt
11 |
12 | #include "pico/stdlib.h"
13 |
14 | // gets the current time in HHMM format (0000 - 2359)
15 | // For example, if 1354 is returned, the time is 13:54 (or
16 | // 1:34 PM if you prefer)
17 | uint16_t clock_get_time();
18 |
19 | // Sets the time. For example: time_hhmm = 1234 would set the
20 | // time to 12:34. Note that 24h time is always used so 1234
21 | // is 12:34 PM and 0034 is 12:34 AM.
22 | void clock_set_time(uint16_t time_hhmm);
23 |
24 | // initialize the clock
25 | void clock_init();
26 |
27 | #endif
28 |
--------------------------------------------------------------------------------
/src/clock_ds3231.c:
--------------------------------------------------------------------------------
1 | #include "clock.h"
2 | #include "hardware/i2c.h"
3 | #include
4 |
5 | // GP4 - Pin6 is the default
6 | #define SDA_PIN PICO_DEFAULT_I2C_SDA_PIN
7 | // GP5 - Pin 7 is the default
8 | #define SCL_PIN PICO_DEFAULT_I2C_SCL_PIN
9 |
10 | #define DS3231_I2C_ADDRESS 0x68
11 |
12 | uint16_t clock_get_time() {
13 | // Need two bytes of data to capture hours and minutes from tje
14 | // DS3231.
15 | uint8_t buf[2];
16 | const uint8_t addr = 0x01; // register address that starts with minute
17 |
18 | // Read address 0x01 and 0x02 from the DS3231
19 | i2c_write_blocking(i2c0, DS3231_I2C_ADDRESS, &addr, 1, true);
20 | const int err = i2c_read_blocking(i2c0, DS3231_I2C_ADDRESS, buf, 2, false);
21 | if (err < 0) {
22 | return 100 - err;
23 | }
24 | // The minute byte is not a direct binary number but is instead
25 | // has a bit format of 0HHHLLLL, where H is the "tens" place and
26 | // L is the "ones"
27 | const uint8_t minute = (buf[0] & 0x0F) + ((buf[0] >> 4) * 10);
28 |
29 | // Hours is a bit more involved to process due to the possibility
30 | // of 12h and 24h modes. If you know what mode the clock is going
31 | // to be in, then the code below can be simplified.
32 | uint8_t hours = buf[1] & 0x0F;
33 | if (buf[1] & 0x10) {
34 | hours += 10;
35 | }
36 | if (buf[1] & 0x40) {
37 | // 12 hour mode
38 | if (buf[1] & 0x20) {
39 | hours += 12;
40 | }
41 | } else {
42 | if (buf[1] & 0x20) {
43 | hours += 20;
44 | }
45 | }
46 | return (hours * 100) + minute;
47 | }
48 |
49 | void clock_set_time(uint16_t time_hhmm) {
50 | const uint8_t minutes_ones = time_hhmm % 10;
51 | const uint8_t minutes_tens = (time_hhmm / 10) % 10;
52 | const uint8_t hours_ones = (time_hhmm / 100) % 10;
53 | const uint8_t hours_tens = (time_hhmm / 1000) % 10;
54 | // set to 15:04:05
55 | uint8_t buf[4];
56 | buf[0] = 0x00; // Register address
57 | buf[1] = 0x00; // seconds
58 | buf[2] = (minutes_tens << 4) | minutes_ones; // minutes
59 | buf[3] = (hours_tens << 4) | hours_ones; // hours, in 24h format
60 | int err = i2c_write_blocking(i2c0, DS3231_I2C_ADDRESS, buf, 4, false);
61 | if (err >= 0) {
62 | printf("Clock set to %02d:%02d.\n", time_hhmm / 100, time_hhmm % 100);
63 | } else {
64 | printf("Clock set error %d\n", err);
65 | }
66 | }
67 |
68 | void clock_init() {
69 | i2c_init(i2c0, 100 * 1000);
70 | gpio_set_function(SDA_PIN, GPIO_FUNC_I2C);
71 | gpio_set_function(SCL_PIN, GPIO_FUNC_I2C);
72 | }
73 |
--------------------------------------------------------------------------------
/src/clock_pico_internal.c:
--------------------------------------------------------------------------------
1 | #include "clock.h"
2 | #include "hardware/rtc.h"
3 | #include "pico/stdlib.h"
4 | #include "pico/util/datetime.h"
5 | #include
6 |
7 | uint16_t clock_get_time() {
8 | datetime_t t;
9 | rtc_get_datetime(&t);
10 | return (t.hour * 100) + t.min;
11 | }
12 |
13 | void clock_set_time(uint16_t time_hhmm) {
14 | const uint8_t hours = time_hhmm / 100;
15 | const uint8_t minutes = time_hhmm % 100;
16 |
17 | // Date does not matter for this application.
18 | datetime_t t = {
19 | .year = 2023,
20 | .month = 1,
21 | .day = 7,
22 | .dotw = 6, // Saturday
23 | .hour = hours,
24 | .min = minutes,
25 | .sec = 00
26 | };
27 |
28 | // Start the RTC and wait for it to take effect
29 | rtc_set_datetime(&t);
30 | sleep_us(64);
31 | printf("Clock set to %02d:%02d.\n", hours, minutes);
32 | }
33 |
34 | void clock_init() {
35 | rtc_init();
36 | clock_set_time(1345);
37 | }
38 |
--------------------------------------------------------------------------------
/src/clock_render.h:
--------------------------------------------------------------------------------
1 | #ifndef CLOCK_RENDER_H
2 | #define CLOCK_RENDER_H
3 |
4 | #include
5 | #include "clock_settings.h"
6 |
7 | #if defined(led_matrix_64x32)
8 | #define MATRIX_ONLY_MODE_INDEX 1
9 | #endif
10 |
11 | // provides a common interface for rendering a clock
12 | uint8_t clock_render(
13 | uint32_t* led,
14 | uint8_t button_pressed,
15 | uint32_t frame_index,
16 | uint16_t time_hhmm,
17 | const struct ClockSettings* settings);
18 |
19 | // returns the number of available display modes
20 | uint8_t clock_render_num_display_modes(void);
21 | // maps a display mode index to a name.
22 | const char* clock_render_display_mode_name(uint8_t mode);
23 | // change current display mode
24 | void clock_render_set_display_mode(uint8_t mode);
25 | uint8_t clock_render_get_display_mode(void);
26 | void clock_render_reset_mode_change(void);
27 | // returns the next mode change time in hhmm
28 | uint16_t clock_render_next_mode_change(void);
29 |
30 | #endif
31 |
--------------------------------------------------------------------------------
/src/clock_settings.h:
--------------------------------------------------------------------------------
1 | // Contains program settings, stored in flash
2 | #ifndef CLOCK_SETTINGS_H
3 | #define CLOCK_SETTINGS_H
4 |
5 | // This module handles user settings. It handles both the user interface
6 | // (shell prompt over USB) and storing/loading from flash.
7 |
8 | #include
9 |
10 | //Change this when adding fields. It will cause all settings to reset
11 | #define CLOCK_SETTINGS_VERSION 4
12 |
13 | // Here are the settings. The checksum, eyecatcher and version fields
14 | // are there to detect the cases where setting have not ever been written
15 | // or were updated in an incompatible way. Bad/unreliable flash could also
16 | // cause mismatches here. Having the eyscatcher is probably caution overkill
17 | // but it can help in troubleshooting efforts.
18 | struct ClockSettings {
19 | uint32_t checksum; // the sum of all byte in this structure except for this one
20 | uint8_t eyecatcher[4]; // 'MCLK'
21 | uint32_t version; // bump this when structure changes
22 |
23 | uint8_t brightness_step; // brightness value
24 | uint8_t startup_display_mode; // This is "normal" by default but the user can
25 | // change it if preferred.
26 |
27 | // sleep settings in hhmm format. If they are equal, then sleep is OFF
28 | uint16_t sleep_time;
29 | uint16_t wake_time;
30 |
31 | // mode change settings
32 | uint16_t enabled_modes;
33 | uint16_t mode_change_minutes;
34 | };
35 |
36 | void clock_settings_init(void);
37 |
38 | // Call this regularly to give the user a responsive USB shell.
39 | // returns a 1 if the frame_index needs to be reset
40 | uint8_t clock_settings_poll(uint16_t time_hhmm, uint32_t last_fps);
41 |
42 | // Get a read-only copy of the settings.
43 | const struct ClockSettings* clock_settings(void);
44 |
45 | // Converts a ClockSettings->brightness to 0-255 brightness
46 | uint8_t brightness_step_to_brightness(const struct ClockSettings* settings);
47 |
48 | #endif
49 |
--------------------------------------------------------------------------------
/src/colors.c:
--------------------------------------------------------------------------------
1 | #include "colors.h"
2 |
3 | struct Color {
4 | uint32_t value;
5 | const char* name;
6 | };
7 |
8 | // defines colors
9 | static struct Color colors[10] = {
10 | { 0x352311, "brown" }, // 0
11 | { 0xFF0000, "red" }, // 1
12 | { 0xD05000, "orange" }, // 2
13 | { 0xFFFF10, "yellow" }, // 3
14 | { 0x00FF00, "green" }, // 4
15 | { 0x0000FF, "blue" }, // 5
16 | { 0x00FFFF, "cyan" }, // 6
17 | { 0xFF00FF, "magenta" }, // 7
18 | { 0xA03030, "pink" }, // 8
19 | { 0xFFFFFF, "white" }, // 9
20 | };
21 |
22 | uint32_t get_color(uint8_t number) {
23 | return colors[number].value;
24 | }
25 |
26 | const char* get_color_name(uint8_t number) {
27 | return colors[number].name;
28 | }
29 |
--------------------------------------------------------------------------------
/src/colors.h:
--------------------------------------------------------------------------------
1 | #ifndef COLORS_H
2 | #define COLORS_H
3 |
4 | #include
5 |
6 | // pass a number 0-9 to get a color in 0xVVRRGGBB format where
7 | // VV is birghtness
8 | // RR is red
9 | // GG is green
10 | // BB is blue
11 | // All range 0-255
12 | uint32_t get_color(uint8_t number);
13 | // pass a number to gt a color name
14 | const char* get_color_name(uint8_t number);
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/src/debounce.c:
--------------------------------------------------------------------------------
1 | #include "debounce.h"
2 | #ifdef LIB_PICO_PLATFORM
3 | #include "hardware/gpio.h"
4 | #else
5 | #define GPIO_IRQ_EDGE_FALL 4
6 | #define GPIO_IRQ_EDGE_RISE 8
7 | #endif
8 |
9 |
10 | void debounce_init(struct Debounce* db, uint8_t hold_time_ms) {
11 | db->hold_time_ms = hold_time_ms;
12 | db->last_sample_time_ms = 0;
13 | db->val = 0;
14 | }
15 |
16 | uint8_t debounce_sample(struct Debounce* db, uint32_t time_ms, uint8_t val) {
17 | if (val == db->val) {
18 | return 0; // didn't change
19 | }
20 | if ((db->last_sample_time_ms == 0) ||
21 | (time_ms < db->last_sample_time_ms) ||
22 | time_ms >= (db->last_sample_time_ms + db->hold_time_ms)) {
23 | db->val = val;
24 | db->last_sample_time_ms = time_ms;
25 | return 1;
26 | }
27 | return 0;
28 | }
29 |
30 | // IRQ callback that handles the not-so-intuitive logic of converting a set
31 | // of rising and falling edges into a clean signal that filters away debounce
32 | // noise without losing presses.
33 | uint8_t debounce_gpio_irq_callback_helper(struct Debounce* db, uint32_t time_ms, uint32_t events) {
34 | uint8_t val = 0;
35 | switch (events) {
36 | case 0x00:
37 | val = db->val; // keep it the same
38 | break;
39 | case GPIO_IRQ_EDGE_FALL:
40 | val = 1; // it's pressed
41 | break;
42 | case GPIO_IRQ_EDGE_RISE:
43 | break; // not pressed
44 | case GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL:
45 | val = 1 - db->val; // invert the current state
46 | break;
47 | }
48 | return debounce_sample(db, time_ms, val);
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/src/debounce.h:
--------------------------------------------------------------------------------
1 | #ifndef LIB_UTIL_DEBOUNCE_H
2 | #define LIB_UTIL_DEBOUNCE_H
3 | // Simple debounce logic that throttles the update of a value.
4 | //
5 | // Poll example:
6 | //
7 | // void main(void) {
8 | // struct Debounce db;
9 | // debounce_init(&db, 8);
10 | // uint32_t time_ms = 0;
11 | // for (;; ++time_ms) {
12 | // // PB0 will only update every 8ms
13 | // if (debounce_sample(&db, time_ms, PINB & 0x01)) {
14 | // if (db.val) {
15 | // // button was pushed
16 | // } else {
17 | // // button was released
18 | // }
19 | // }
20 | // _delay_ms(1);
21 | // }
22 | // }
23 | //
24 | // Interrupt example
25 | //
26 | // volatile uint32_t counter;
27 | // struct Debounce db;
28 | // void main(void) {
29 | // time_measure_init();
30 | // debounce_init(&db, 8);
31 | // // Setup pin change interrupt on PB0
32 | // GIMSK |= 1 << INT0;
33 | //
34 | // while (1) {
35 | // lowpower_powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
36 | // cli();
37 | // const uint32_t local_counter = counter;
38 | // sei();
39 | // // do something with counter (print it, etc)
40 | // _delay_ms(1000);
41 | // }
42 | // }
43 | //
44 | // ISR(PCINT0_vect)
45 | // {
46 | // // called on real (and bouncy) rising and falling edges.
47 | // // rising is intersting to register the press
48 | // // falling is interesting to filter away decontact bounces.
49 | // if (debounce_sample(&db, time_measure_ms(), PINB & 0x01)) {
50 | // if (db.val) {
51 | // ++counter;
52 | // } else {
53 | // // do something on on up position if you want to
54 | // }
55 | // }
56 | // }
57 |
58 | #include
59 |
60 | struct Debounce {
61 | volatile uint32_t last_sample_time_ms; // the last time a sample was recorded
62 | uint8_t hold_time_ms; // How long to filter away debounce signals
63 | volatile uint8_t val;
64 | };
65 |
66 | // Initialize
67 | //
68 | // db: Debounce structure
69 | // hold_time_ms: The length of time to filter away debounce signals
70 | void debounce_init(struct Debounce* db, uint8_t hold_time_ms);
71 |
72 |
73 | // Provides a new value. If the time difference is < hold_time_ms, then
74 | // the old value will be returned (debounce).
75 | //
76 | // db: Debounce structure
77 | // time_ms: A timetamp, in milliseconds
78 | // val: Latest value
79 | //
80 | // Returns: 1 if the value changed AND time_ms is high enough, zero otherwise
81 | uint8_t debounce_sample(struct Debounce* db, uint32_t time_ms, uint8_t val);
82 |
83 | // Callback helper for pi pico.
84 | //
85 | // Bascially the gpio_set_irq_callback is tricky to deal with because of the
86 | // surprising behavoir of GPIO_IRQ_EDGE_FALL and GPIO_IRQ_EDGE_RISE sometimes
87 | // both being active on the same callback. This quickly lead to the realization
88 | // of "which one happened first?" "does it matter?"
89 | //
90 | // I went through this entire exersize in an isolated project named button_interrupt_analyze
91 | // where all callback events were held in a ring buffer. This allowed me to
92 | // work out and verify the handling logic that is in this helper function.
93 | //
94 | // Usage:
95 | //
96 | // struct Debounce db;
97 | //
98 | // void main() {
99 | // ...
100 | // // can also to all of this with gpio_set_irq_enabled_with callback if you only
101 | // // have one button.
102 | // gpio_set_irq_enabled(BUTTON_GPIO, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true);
103 | // gpio_set_irq_callback(button_pressed_callback);
104 | // irq_set_enabled(IO_IRQ_BANK0, true);
105 | // ...
106 | // }
107 | //
108 | // static void button_pressed_callback(uint gpio, uint32_t events) {
109 | // const uint8_t triggered = gpio_irq_callback_helper(&db, events);
110 | // const uint8_t is_pressed = db.val;
111 | // ...
112 | // }
113 | uint8_t debounce_gpio_irq_callback_helper(struct Debounce* db, uint32_t time_ms, uint32_t events);
114 |
115 | #endif
116 |
--------------------------------------------------------------------------------
/src/debug.c:
--------------------------------------------------------------------------------
1 | #include "debug.h"
2 | #include
3 | #include
4 |
5 | #include "led_matrix.h"
6 |
7 | #define RED_BIT 0x04
8 | #define GREEN_BIT 0x02
9 | #define BLUE_BIT 0x01
10 | static void dump_point(uint32_t pixel) {
11 | if ((pixel & 0xFF000000) == 0) {
12 | putchar(pixel ? '?' : '.');
13 | return;
14 | }
15 | // only look at bit 3-7
16 | uint8_t color = 0x00;
17 | if ((pixel >> 16) & 0xF0) {
18 | color |= RED_BIT;
19 | }
20 | if ((pixel >> 8) & 0xF0) {
21 | color |= GREEN_BIT;
22 | }
23 | if (pixel & 0xF0) {
24 | color |= BLUE_BIT;
25 | }
26 | char c = ':';
27 | switch (color) {
28 | case BLUE_BIT:
29 | c = 'B';
30 | break;
31 | case GREEN_BIT:
32 | c = 'G';
33 | break;
34 | case BLUE_BIT | GREEN_BIT:
35 | c = 'A';
36 | break;
37 | case RED_BIT:
38 | c = 'R';
39 | break;
40 | case RED_BIT | BLUE_BIT:
41 | c = 'M';
42 | break;
43 | case RED_BIT | GREEN_BIT:
44 | c = 'Y';
45 | break;
46 | case RED_BIT | GREEN_BIT | BLUE_BIT:
47 | c = 'W';
48 | break;
49 | }
50 | putchar(c);
51 | }
52 |
53 | void debug_dump_led(const uint32_t* led) {
54 | for (int8_t y=LED_MATRIX_HEIGHT - 1; y >= 0; --y) {
55 | for (uint8_t x=0; x
6 |
7 | void debug_printf(const char* fmt, ...);
8 |
9 | // dump led state to stdout
10 | void debug_dump_led(const uint32_t* led);
11 |
12 | // wait for a keypress
13 | void debug_wait_for_key(void);
14 |
15 | // convienence
16 | void debug_dump_led_with_wait(const char* msg, const uint32_t* led);
17 |
18 | #endif
19 |
20 |
--------------------------------------------------------------------------------
/src/led_matrix.h:
--------------------------------------------------------------------------------
1 | #ifndef LED_MATRIX_H
2 | #define LED_MATRIX_H
3 | // This file is the front-end abstraction for any number of
4 | // "LED HARDWARE" modules. The idea is that you change the .c
5 | // file in CMakeLists.txt to correspond to the hardware you
6 | // actually have and the link process will then bundle the
7 | // appropriate code into the driver.
8 |
9 | #include
10 |
11 | #if defined(led_matrix_dotstar)
12 | #define LED_MATRIX_WIDTH 8
13 | #define LED_MATRIX_HEIGHT 8
14 | #define FRAME_DELAY_MS 25 // 40FPS
15 | #elif defined(led_matrix_64x32)
16 | #define LED_MATRIX_WIDTH 32
17 | #define LED_MATRIX_HEIGHT 64
18 | #define FRAME_DELAY_MS 5 // 200FPS
19 | #else
20 | #error Unknown LED_MATRIX_SOURCE
21 | #endif
22 |
23 | // Matrix dimensions. You may need to change these if your's
24 | // is different as well as attend to code that might not
25 | // like your chosen numbers.
26 | #define LED_MATRIX_COUNT (LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT)
27 |
28 | // Initialize the matrix
29 | void led_matrix_init();
30 |
31 | // render the matrix.
32 | // data is of the form 0xIIRRGGBB where
33 | // II -> Intensity (brightness)
34 | // RR -> Red
35 | // GG -> Green
36 | // BB -> Blue
37 | //
38 | // Values are 0-255
39 | // format is horizontal rows. The first pixel
40 | // sent is the southwest corner of the matrix.
41 | void led_matrix_render(uint32_t* data);
42 |
43 | // stop any background operations. This is needed to
44 | // safely write settings to flash. Some drivers will
45 | // not need to do anything here. Another call to
46 | // led_matrix_render would be expected to start things
47 | // back up.
48 | void led_matrix_stop(void);
49 |
50 | // converts a x,y coordinate to a pixel index
51 | static inline uint32_t get_pixel_idx(uint16_t x, uint16_t y) {
52 | return (y * LED_MATRIX_WIDTH) + x;
53 | }
54 |
55 | // sets a pixel
56 | static inline void set_pixel(
57 | uint32_t* led, // matrix
58 | uint16_t x,
59 | uint16_t y,
60 | uint8_t br, // brightness
61 | uint8_t r, // red
62 | uint8_t g, // green
63 | uint8_t b // blue
64 | ) {
65 | const uint32_t pixel = (br << 24) | (r << 16) | (g << 8) | b;
66 | const uint16_t idx = get_pixel_idx(x, y);
67 | led[idx] = pixel;
68 | }
69 |
70 | // sets a pixel from a color
71 | static inline void set_pixel2(
72 | uint32_t* led, // matrix
73 | uint16_t x,
74 | uint16_t y,
75 | uint32_t pixel
76 | ) {
77 | const uint16_t idx = get_pixel_idx(x, y);
78 | led[idx] = pixel;
79 | }
80 |
81 | #endif
82 |
--------------------------------------------------------------------------------
/src/led_matrix_dotstar.c:
--------------------------------------------------------------------------------
1 | // LED matrix implementation for dotstar hardware
2 | #include "led_matrix.h"
3 | #include "pico/stdlib.h"
4 | #include "hardware/spi.h"
5 |
6 | #define SCK_PIN 18
7 | #define MOSI_PIN 19
8 | #define SPI_SPEED 1000000
9 |
10 | void led_matrix_init() {
11 | spi_init(spi0, SPI_SPEED);
12 | gpio_set_function(SCK_PIN, GPIO_FUNC_SPI);
13 | gpio_set_function(MOSI_PIN, GPIO_FUNC_SPI);
14 | }
15 |
16 | // writes 4 bytes via SPI
17 | static inline void write_bytes(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) {
18 | uint8_t msg[4] = {b1, b2, b3, b4};
19 | spi_write_blocking(spi0, msg, 4);
20 | }
21 |
22 | // starts a new frame
23 | static inline void start_frame() {
24 | write_bytes(0, 0, 0, 0);
25 | }
26 |
27 | // displays a given color
28 | static inline void color(uint32_t pixel) {
29 | const uint8_t br = pixel >> 27; // The harware handles 0-31 only
30 | const uint8_t red = (pixel >> 16) & 0xFF;
31 | const uint8_t green = (pixel >> 8) & 0xFF;
32 | const uint8_t blue = pixel & 0xFF;
33 | write_bytes(0xE0 | br, blue, green, red);
34 | }
35 |
36 | void led_matrix_render(uint32_t* data) {
37 | start_frame();
38 | for (uint8_t i=0; i < LED_MATRIX_COUNT; ++i) {
39 | color(data[i]);
40 | }
41 | }
42 |
43 | void led_matrix_stop(void) { }
44 |
45 |
--------------------------------------------------------------------------------
/src/main.c:
--------------------------------------------------------------------------------
1 | // Matrix clock
2 | //
3 | // By: Matt Wachowski
4 |
5 | #include "pico/stdlib.h"
6 | #include
7 | #include "clock.h"
8 | #include "clock_render.h"
9 | #include "clock_settings.h"
10 | #include "led_matrix.h"
11 | #include "monitor.h"
12 | #include "buttons.h"
13 | #include "set_time_low_res.h"
14 | #include "set_time_high_res.h"
15 |
16 | #if defined(led_matrix_dotstar)
17 | #define SET_TIME_RENDER set_time_lowres_render
18 | #elif defined(led_matrix_64x32)
19 | #define SET_TIME_RENDER set_time_highres_render
20 | #else
21 | #error Unknown LED_MATRIX_SOURCE
22 | #endif
23 |
24 | #define TIME_UPDATE_FRAMES (1000/FRAME_DELAY_MS)
25 | #define LED_PIN PICO_DEFAULT_LED_PIN
26 |
27 | // set to 1 if the user is setting the time
28 | uint8_t setting_time;
29 |
30 | // format is 0xIIRRGGBB See led_matrix.h for mor details.
31 | uint32_t led[LED_MATRIX_COUNT];
32 | uint16_t time_hhmm; // a cache of the time to avoid calling for it as much
33 |
34 | struct Monitor monitor;
35 |
36 | static inline uint32_t uptime_ms() {
37 | return to_ms_since_boot(get_absolute_time());
38 | }
39 |
40 | // Initialization function
41 | static void init(void) {
42 | setting_time = 0;
43 | gpio_init(LED_PIN);
44 | gpio_set_dir(LED_PIN, GPIO_OUT);
45 | clock_settings_init();
46 | led_matrix_init();
47 | clock_init();
48 | buttons_init();
49 | sleep_ms(50);
50 | time_hhmm = clock_get_time();
51 | monitor_init(&monitor);
52 | }
53 |
54 | // Updates time_hhmm periocially (based on TIME_UPDATE_FRAMES)
55 | static void maybe_update_time(uint32_t frame_idx) {
56 | if ((frame_idx % TIME_UPDATE_FRAMES) == 0) {
57 | time_hhmm = clock_get_time();
58 | }
59 | }
60 |
61 | // called repeatedly by main to render a frame
62 | static uint32_t render(uint32_t frame_idx) {
63 | uint32_t t1 = uptime_ms();
64 | maybe_update_time(frame_idx);
65 | memset(led, 0, sizeof(led));
66 | uint8_t toggle_setting_time = 0;
67 | uint8_t buttons = buttons_get();
68 | buttons |= clock_settings_poll(time_hhmm, monitor.last_fps);
69 | if (setting_time) {
70 | toggle_setting_time = SET_TIME_RENDER(
71 | led, buttons, frame_idx, time_hhmm, clock_settings());
72 | } else {
73 | toggle_setting_time = clock_render(
74 | led, buttons, frame_idx, time_hhmm, clock_settings());
75 | }
76 | ++frame_idx;
77 | if (toggle_setting_time) {
78 | setting_time = !setting_time;
79 | frame_idx = 0;
80 | }
81 | led_matrix_render(led);
82 | // calculate tdelta to get a smooth frame rate, even if the loop time
83 | // varies.
84 | uint32_t tdelta = uptime_ms() - t1;
85 | if (tdelta < FRAME_DELAY_MS) {
86 | sleep_ms(FRAME_DELAY_MS - tdelta);
87 | }
88 | return frame_idx;
89 | }
90 |
91 | // Program starting point
92 | int main() {
93 | init();
94 | uint32_t frame_idx = 0;
95 | while (1) {
96 | frame_idx = render(frame_idx);
97 | gpio_put(LED_PIN, is_current_over());
98 | monitor_frame(&monitor);
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/monitor.c:
--------------------------------------------------------------------------------
1 | #include "monitor.h"
2 |
3 | #include "pico/stdlib.h"
4 |
5 | #define FPS_SAMPLES 500
6 |
7 | static inline uint32_t uptime_ms() {
8 | return to_ms_since_boot(get_absolute_time());
9 | }
10 |
11 | void monitor_init(struct Monitor* m) {
12 | m->fps_idx = 0;
13 | m->last_fps_sample = uptime_ms();
14 | m->last_fps = 0;
15 | }
16 |
17 | void monitor_frame(struct Monitor* m) {
18 | ++m->fps_idx;
19 | if (m->fps_idx == FPS_SAMPLES) {
20 | const uint32_t new_fps_sample = uptime_ms();
21 | m->last_fps = m->fps_idx * 1000 / (new_fps_sample - m->last_fps_sample);
22 | m->last_fps_sample = new_fps_sample;
23 | m->fps_idx = 0;
24 | }
25 | }
--------------------------------------------------------------------------------
/src/monitor.h:
--------------------------------------------------------------------------------
1 | #ifndef MONITOR_H
2 | #define MONITOR_H
3 |
4 | #include
5 |
6 | // usage:
7 | // struct Monitor m;
8 | //
9 | // int main() {
10 | // monitor_init(&m);
11 | // while (1) {
12 | // render_frame();
13 | // monitor_frame(&m)
14 | // // m.last_fps is periodically updated with an fps value
15 | // }
16 | // ...
17 | //}
18 |
19 | struct Monitor {
20 | uint32_t last_fps;
21 | uint32_t fps_idx;
22 | uint32_t last_fps_sample;
23 | };
24 |
25 | void monitor_init(struct Monitor* m);
26 |
27 | void monitor_frame(struct Monitor* m);
28 |
29 | #endif
30 |
--------------------------------------------------------------------------------
/src/number_draw.c:
--------------------------------------------------------------------------------
1 | #include "number_draw.h"
2 | #include "colors.h"
3 | #include "led_matrix.h"
4 | #include
5 |
6 | // numbers are made of lines
7 | // Each line is on a coordinate system from 0x00 to 0x10
8 | // end with all -1
9 | //
10 | // Note: 0,0 is lower, left
11 | struct Line {
12 | int8_t x0;
13 | int8_t y0;
14 | int8_t x1;
15 | int8_t y1;
16 | };
17 |
18 | struct Line zero[] = {
19 | {0, 0, 16, 0},
20 | {0, 0, 0, 16},
21 | {0, 16, 16, 16},
22 | {16, 0, 16, 16},
23 | {-1, -1, -1, -1},
24 | };
25 |
26 | struct Line one[] = {
27 | {8, 0, 8, 16},
28 | {0, 0, 16, 0},
29 | {0, 16, 8, 16},
30 | {-1, -1, -1, -1},
31 | };
32 |
33 | struct Line two[] = {
34 | {0, 0, 16, 0},
35 | {0, 0, 0, 8},
36 | {0, 8, 16, 8},
37 | {16, 8, 16, 16},
38 | {0, 16, 16, 16},
39 | {-1, -1, -1, -1},
40 | };
41 |
42 |
43 | struct Line three[] = {
44 | {0, 0, 16, 0},
45 | {0, 8, 16, 8},
46 | {0, 16, 16, 16},
47 | {16, 0, 16, 16},
48 | {-1, -1, -1, -1},
49 | };
50 |
51 | struct Line four[] = {
52 | {16, 0, 16, 16},
53 | {0, 8, 0, 16},
54 | {0, 8, 16, 8},
55 | {-1, -1, -1, -1},
56 | };
57 |
58 | struct Line five[] = {
59 | {0, 0, 16, 0},
60 | {16, 0, 16, 8},
61 | {0, 8, 16, 8},
62 | {0, 8, 0, 16},
63 | {0, 16, 16, 16},
64 | {-1, -1, -1, -1},
65 | };
66 |
67 | struct Line six[] = {
68 | {0, 0, 16, 0},
69 | {0, 0, 0, 16},
70 | {0, 8, 16, 8},
71 | {0, 16, 16, 16},
72 | {16, 0, 16, 8},
73 | {-1, -1, -1, -1},
74 | };
75 |
76 | struct Line seven[] = {
77 | {0, 16, 16, 16},
78 | {16, 0, 16, 16},
79 | {-1, -1, -1, -1},
80 | };
81 |
82 | struct Line eight[] = {
83 | {0, 0, 16, 0},
84 | {0, 8, 16, 8},
85 | {0, 16, 16, 16},
86 | {0, 0, 0, 16},
87 | {16, 0, 16, 16},
88 | {-1, -1, -1, -1},
89 | };
90 |
91 | struct Line nine[] = {
92 | {0, 16, 16, 16},
93 | {0, 8, 0, 16},
94 | {0, 8, 16, 8},
95 | {16, 0, 16, 16},
96 | {0, 0, 16, 0},
97 | {-1, -1, -1, -1},
98 | };
99 |
100 | struct Line* font_lines[] = {
101 | zero,
102 | one,
103 | two,
104 | three,
105 | four,
106 | five,
107 | six,
108 | seven,
109 | eight,
110 | nine,
111 | };
112 |
113 | // draws a single pixel to the set matrix
114 | static void pixel(
115 | uint32_t* led,
116 | int16_t x,
117 | int16_t y,
118 | uint32_t color_with_brightness) {
119 | if ((x < 0) || (x >= LED_MATRIX_WIDTH)) {
120 | return;
121 | }
122 | if ((y < 0) || (y >= LED_MATRIX_HEIGHT)) {
123 | return;
124 | }
125 | uint16_t pixel_idx = get_pixel_idx(x, y);
126 | led[pixel_idx] = color_with_brightness;
127 | }
128 |
129 | void number_font_init(
130 | struct NumberFont* font,
131 | uint8_t brightness,
132 | uint8_t char_width,
133 | uint8_t char_height,
134 | uint8_t char_spacing) {
135 | if (char_width & 1) {
136 | --char_width;
137 | }
138 | if (char_height & 1) {
139 | --char_height;
140 | }
141 | font->x = 0;
142 | font->y = 0;
143 | font->brightness = brightness;
144 | font->char_width = char_width;
145 | font->char_height = char_height;
146 | font->char_spacing = char_spacing;
147 | }
148 |
149 | static inline void draw_line(
150 | struct NumberFont* font,
151 | uint32_t* led,
152 | const struct Line* line) {
153 | // scale from the 0-16 scale to the provided width/height values
154 | const int16_t x0 = font->x + ((line->x0 * font->char_width) >> 4);
155 | const int16_t y0 = font->y + ((line->y0 * font->char_height) >> 4);
156 | const int16_t x1 = font->x + ((line->x1 * font->char_width) >> 4);
157 | const int16_t y1 = font->y + ((line->y1 * font->char_height) >> 4);
158 |
159 | const int8_t xdir = x1 > x0 ? 1 : -1;
160 | const int8_t ydir = y1 > y0 ? 1 : -1;
161 |
162 | const int16_t dx = (x1 - x0) * xdir;
163 | const int16_t dy = (y1 - y0) * ydir;
164 |
165 | int16_t D = 2 * dy - dx;
166 | int16_t x = x0;
167 | int16_t y = y0;
168 |
169 | pixel(led, x, y, font->color);
170 |
171 | while (x != x1 || y != y1) {
172 | if (D > 0) {
173 | y += ydir;
174 | D -= 2 * dx;
175 | }
176 |
177 | if (D <= 0) {
178 | x += xdir;
179 | D += 2 * dy;
180 | }
181 |
182 | pixel(led, x, y, font->color);
183 | }
184 | }
185 |
186 | // Draws a number 0-9 at the specified cordinates
187 | void number_draw_mode(
188 | struct NumberFont* font,
189 | uint32_t* led,
190 | uint8_t digit,
191 | uint8_t mode) {
192 | if (digit > 9) {
193 | return;
194 | }
195 | const struct Line* lines = font_lines[digit];
196 | if (mode == DRAW_MODE_NUMBER) {
197 | font->color = ((uint32_t)font->brightness << 24) | get_color(digit);
198 | }
199 |
200 | for (; lines[0].x0 >= 0; ++lines) {
201 | draw_line(font, led, lines);
202 | }
203 | font->x += font->char_spacing;
204 | }
205 |
206 | void number_draw_dash(struct NumberFont* font, uint32_t* led) {
207 | font->color = ((uint32_t)font->brightness << 24) | 0xFFFFFF; // white
208 | const struct Line dash1 = {0, 4, 0, 5};
209 | draw_line(font, led, &dash1);
210 | const struct Line dash2 = {0, 12, 0, 13};
211 | draw_line(font, led, &dash2);
212 | font->x += 2;
213 | }
214 |
215 | // Draws val to led memory. val must be 0-99.
216 | void draw_numbers(
217 | struct NumberFont* font,
218 | uint32_t* led,
219 | uint8_t val) {
220 | const uint8_t tens = val / 10;
221 | number_draw(font, led, tens);
222 | const uint8_t ones = val % 10;
223 | number_draw(font, led, ones);
224 | }
225 |
226 |
--------------------------------------------------------------------------------
/src/number_draw.h:
--------------------------------------------------------------------------------
1 | #ifndef NUMBER_DRAW_H
2 | #define NUMBER_DRAW_H
3 | // Draws a number to the LED matrix
4 |
5 | #include
6 |
7 | #define DRAW_MODE_NUMBER 0
8 | #define DRAW_MODE_COLOR 1
9 |
10 | struct NumberFont {
11 | uint32_t color;
12 | int16_t x;
13 | int16_t y;
14 | uint8_t brightness;
15 | uint8_t char_width;
16 | uint8_t char_height;
17 | uint8_t char_spacing;
18 | };
19 |
20 | // initialize a font
21 | // char spacing does not include char_width
22 | // char width and height will be made odd for better rendering
23 | void number_font_init(
24 | struct NumberFont* font,
25 | uint8_t brightness,
26 | uint8_t char_width,
27 | uint8_t char_height,
28 | uint8_t char_spacing);
29 |
30 | // draws dashes between numbers
31 | void number_draw_dash(struct NumberFont* font, uint32_t* led);
32 |
33 | void number_draw_mode(
34 | struct NumberFont* font,
35 | uint32_t* led,
36 | uint8_t digit,
37 | uint8_t mode);
38 |
39 | // draws a digit with an indexed color. Off screen for x,y is OK
40 | static inline void number_draw(
41 | struct NumberFont* font,
42 | uint32_t* led,
43 | uint8_t digit) {
44 | number_draw_mode(font, led, digit, DRAW_MODE_NUMBER);
45 | }
46 |
47 | // draws two digits with an indexed color
48 | void draw_numbers(
49 | struct NumberFont* font,
50 | uint32_t* led,
51 | uint8_t val);
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/src/pico_sdk_import.cmake:
--------------------------------------------------------------------------------
1 | # This is a copy of /external/pico_sdk_import.cmake
2 |
3 | # This can be dropped into an external project to help locate this SDK
4 | # It should be include()ed prior to project()
5 |
6 | if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
7 | set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
8 | message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
9 | endif ()
10 |
11 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
12 | set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
13 | message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
14 | endif ()
15 |
16 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
17 | set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
18 | message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
19 | endif ()
20 |
21 | set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
22 | set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
23 | set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
24 |
25 | if (NOT PICO_SDK_PATH)
26 | if (PICO_SDK_FETCH_FROM_GIT)
27 | include(FetchContent)
28 | set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
29 | if (PICO_SDK_FETCH_FROM_GIT_PATH)
30 | get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
31 | endif ()
32 | FetchContent_Declare(
33 | pico_sdk
34 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
35 | GIT_TAG master
36 | )
37 | if (NOT pico_sdk)
38 | message("Downloading Raspberry Pi Pico SDK")
39 | FetchContent_Populate(pico_sdk)
40 | set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
41 | endif ()
42 | set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
43 | else ()
44 | message(FATAL_ERROR
45 | "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
46 | )
47 | endif ()
48 | endif ()
49 |
50 | get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
51 | if (NOT EXISTS ${PICO_SDK_PATH})
52 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
53 | endif ()
54 |
55 | set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
56 | if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
57 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
58 | endif ()
59 |
60 | set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
61 |
62 | include(${PICO_SDK_INIT_CMAKE_FILE})
63 |
--------------------------------------------------------------------------------
/src/render/blank.c:
--------------------------------------------------------------------------------
1 | #include "blank.h"
2 |
3 | #include "../led_matrix.h"
4 | #include
5 |
6 | void blank_render(
7 | uint32_t* led,
8 | uint32_t unused_frame_index,
9 | uint16_t unused_time_hhmm,
10 | const struct ClockSettings* unused_settings) {
11 | memset(led, 0, LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT * sizeof(uint32_t));
12 | }
13 |
--------------------------------------------------------------------------------
/src/render/blank.h:
--------------------------------------------------------------------------------
1 | #ifndef RENDER_BLANK_H
2 | #define RENDER_BLANK_H
3 |
4 | #include
5 | #include "../clock_settings.h"
6 |
7 | // Turns off all LEDs
8 | void blank_render(
9 | uint32_t* led,
10 | uint32_t frame_index,
11 | uint16_t time_hhmm,
12 | const struct ClockSettings* settings);
13 | #endif
14 |
15 |
--------------------------------------------------------------------------------
/src/render/bounce.h:
--------------------------------------------------------------------------------
1 | #ifndef RENDER_BOUNCE_H
2 | #define RENDER_BOUNCE_H
3 |
4 | #include
5 | #include "../clock_settings.h"
6 |
7 | // Turns off all LEDs
8 | void bounce_render(
9 | uint32_t* led,
10 | uint32_t frame_index,
11 | uint16_t time_hhmm,
12 | const struct ClockSettings* settings);
13 | #endif
14 |
15 |
--------------------------------------------------------------------------------
/src/render/distances.inc:
--------------------------------------------------------------------------------
1 | // This file was generated by running matrix_clock/tools/distance_generator.py
2 | // with no arguments and redirecting the output to a file.
3 |
4 | #define NUM_DISTANCES 11 // MAX is -1 this val
5 |
6 | // Each number below is the weight to apply to a color at a given
7 | // distance. The range is 0x00-0xFF.
8 |
9 | uint8_t distance_weights[NUM_DISTANCES] __in_flash() = {
10 | 0xFF, // 0
11 | 0x99, // 1
12 | 0x6D, // 2
13 | 0x55, // 3
14 | 0x46, // 4
15 | 0x3B, // 5
16 | 0x33, // 6
17 | 0x2D, // 7
18 | 0x28, // 8
19 | 0x24, // 9
20 | 0x21, // 10
21 | };
22 |
23 |
24 | // Each number below is the offset into the array for the given
25 | // distance. The next element is used to calculate the length.
26 | // The final element is used only for the length calculation
27 |
28 | uint16_t distance_offsets[NUM_DISTANCES + 1] __in_flash() = {
29 | 0x0000, // 0
30 | 0x0001, // 1
31 | 0x0004, // 2
32 | 0x0009, // 3
33 | 0x0010, // 4
34 | 0x0019, // 5
35 | 0x0024, // 6
36 | 0x0031, // 7
37 | 0x0040, // 8
38 | 0x0051, // 9
39 | 0x0064, // 10
40 | 0x0079,
41 | };
42 |
43 | // each element is of the format 0xXXYY
44 | uint16_t distance_points[121] __in_flash() = {
45 | // 0
46 | 0x0000,
47 | // 1
48 | 0x0100, 0x0101, 0x0001,
49 | // 2
50 | 0x0200, 0x0201, 0x0101, 0x0102, 0x0002,
51 | // 3
52 | 0x0300, 0x0301, 0x0302, 0x0202, 0x0203, 0x0103, 0x0003,
53 | // 4
54 | 0x0400, 0x0401, 0x0402, 0x0302, 0x0303, 0x0203, 0x0204, 0x0104,
55 | 0x0004,
56 | // 5
57 | 0x0500, 0x0501, 0x0502, 0x0402, 0x0403, 0x0404, 0x0304, 0x0204,
58 | 0x0205, 0x0105, 0x0005,
59 | // 6
60 | 0x0600, 0x0601, 0x0602, 0x0502, 0x0503, 0x0504, 0x0404, 0x0405,
61 | 0x0305, 0x0205, 0x0206, 0x0106, 0x0006,
62 | // 7
63 | 0x0700, 0x0701, 0x0702, 0x0703, 0x0603, 0x0604, 0x0504, 0x0505,
64 | 0x0405, 0x0406, 0x0306, 0x0307, 0x0207, 0x0107, 0x0007,
65 | // 8
66 | 0x0800, 0x0801, 0x0802, 0x0803, 0x0703, 0x0704, 0x0705, 0x0605,
67 | 0x0606, 0x0506, 0x0507, 0x0407, 0x0307, 0x0308, 0x0208, 0x0108,
68 | 0x0008,
69 | // 9
70 | 0x0900, 0x0901, 0x0902, 0x0903, 0x0803, 0x0804, 0x0805, 0x0705,
71 | 0x0706, 0x0606, 0x0607, 0x0507, 0x0508, 0x0408, 0x0308, 0x0309,
72 | 0x0209, 0x0109, 0x0009,
73 | // 10
74 | 0x0A00, 0x0A01, 0x0A02, 0x0A03, 0x0903, 0x0904, 0x0905, 0x0805,
75 | 0x0806, 0x0807, 0x0707, 0x0708, 0x0608, 0x0508, 0x0509, 0x0409,
76 | 0x0309, 0x030A, 0x020A, 0x010A, 0x000A,
77 | };
78 |
79 |
--------------------------------------------------------------------------------
/src/render/drops.h:
--------------------------------------------------------------------------------
1 | #ifndef RENDER_DROPS_H
2 | #define RENDER_DROPS_H
3 |
4 | #include
5 | #include "../clock_settings.h"
6 |
7 | void drops_render(
8 | uint32_t* led,
9 | uint32_t frame_index,
10 | uint16_t time_hhmm,
11 | const struct ClockSettings* settings);
12 | #endif
13 |
14 |
--------------------------------------------------------------------------------
/src/render/fade.c:
--------------------------------------------------------------------------------
1 | #include "fade.h"
2 |
3 | #include "../clock_settings.h"
4 | #include "../led_matrix.h"
5 | #include "../number_draw.h"
6 | #include
7 | #include
8 |
9 | // Note, this code assumes 256 LED max. If oyu have more,
10 | // you'll need to change data types or simply disable this module.
11 |
12 | // Contains the order in which the fade should happen
13 | // each value is an offset into the matrix. The array order determines
14 | // the order.
15 | static uint16_t fade_order[LED_MATRIX_COUNT];
16 |
17 | // we need to hold our data becuase it is added to each frame
18 | static uint32_t data[LED_MATRIX_COUNT];
19 | static uint32_t target[LED_MATRIX_COUNT];
20 |
21 | // update these at the start to avoid odd changing mid animation
22 | static uint8_t minutes;
23 |
24 | static struct NumberFont font;
25 |
26 | // how fast the fade occurs
27 | #define FRAMES_PER_FADE_PIXEL 1
28 |
29 | // we take a frame_index modulus and compare to the following
30 | // thresholds to determine what the render should be doing
31 | #define BUILD_HOUR_DIGITS (FRAMES_PER_FADE_PIXEL * LED_MATRIX_COUNT)
32 | #define SHOW_HOUR (BUILD_HOUR_DIGITS + 50)
33 | #define BUILD_MINUTE_DIGITS (SHOW_HOUR + FRAMES_PER_FADE_PIXEL * LED_MATRIX_COUNT)
34 | #define SHOW_MINUTE (BUILD_MINUTE_DIGITS + 50)
35 | #define BLANK_OUT (SHOW_MINUTE + FRAMES_PER_FADE_PIXEL * LED_MATRIX_COUNT)
36 | #define SHOW_BLANK (BLANK_OUT + 50)
37 | #define STATE_MODULUS SHOW_BLANK
38 |
39 | static void swap_with_random_fade_slot(uint16_t i) {
40 | const uint16_t j = (uint8_t)(random() % LED_MATRIX_COUNT);
41 | const uint16_t tmp = fade_order[i];
42 | fade_order[i] = fade_order[j];
43 | fade_order[j] = tmp;
44 | }
45 |
46 | static void shuffle_fade_order(void) {
47 | for (uint16_t i=0; i < LED_MATRIX_COUNT; ++i) {
48 | swap_with_random_fade_slot(i);
49 | }
50 | }
51 |
52 | static void init(uint8_t brightness) {
53 | memset(data, 0, sizeof(data));
54 | for (uint16_t i=0; i
5 | #include "../clock_settings.h"
6 |
7 | // Turns off all LEDs
8 | void fade_render(
9 | uint32_t* led,
10 | uint32_t frame_index,
11 | uint16_t time_hhmm,
12 | const struct ClockSettings* settings);
13 | #endif
14 |
15 |
--------------------------------------------------------------------------------
/src/render/matrix.h:
--------------------------------------------------------------------------------
1 | #ifndef RENDER_MATRIX_H
2 | #define RENDER_MATRIX_H
3 |
4 | #include
5 | #include "../clock_settings.h"
6 |
7 | // Renders the "falling point" matrix-style effect
8 | // where particle speed is the time digit e.g.
9 | // 13:45 ->
10 | //
11 | // The 1 is dropped.
12 | // The 3 is represented by slow points
13 | // The 4 is rpresented by medium-speed points
14 | // The 5 is represented by fast points
15 | //
16 | // The digits themselves (0-9) are represented
17 | // by colors as-defined in colors.c. Under current
18 | // definitions this would represent 13:45 as
19 | // 1 -> dropped
20 | // 3 -> yellow (slow)
21 | // 4 -> green (medium speed)
22 | // 5 -> blue (fast)
23 | void matrix_render(
24 | uint32_t* led,
25 | uint32_t frame_index,
26 | uint16_t time_hhmm,
27 | const struct ClockSettings* settings);
28 | #endif
29 |
30 |
--------------------------------------------------------------------------------
/src/render/matrix_with_numbers.c:
--------------------------------------------------------------------------------
1 | #include "matrix_with_numbers.h"
2 | #include "matrix.h"
3 | #include "../led_matrix.h"
4 | #include "../number_draw.h"
5 |
6 | #define FONT_XPAD 1
7 | #define FONT_YPAD 1
8 |
9 | static struct NumberFont font;
10 |
11 | static void overlay_numbers(uint32_t* led, uint16_t time_hhmm) {
12 | font.x = LED_MATRIX_WIDTH - font.char_spacing * 4 - 2 - FONT_XPAD + 1;
13 | font.y = FONT_YPAD;
14 |
15 | draw_numbers(&font, led, time_hhmm / 100);
16 | number_draw_dash(&font, led);
17 | draw_numbers(&font, led, time_hhmm % 100);
18 | }
19 |
20 | void matrix_with_numbers_render(
21 | uint32_t* led,
22 | uint32_t frame_index,
23 | uint16_t time_hhmm,
24 | const struct ClockSettings* settings) {
25 | if (frame_index == 0) {
26 | number_font_init(&font, brightness_step_to_brightness(settings), 3, 5, 4);
27 | }
28 | matrix_render(led, frame_index, time_hhmm, settings);
29 | overlay_numbers(led, time_hhmm);
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/src/render/matrix_with_numbers.h:
--------------------------------------------------------------------------------
1 | #ifndef RENDER_MATRIX_WITH_NUMBERS_H
2 | #define RENDER_MATRIX_WITH_NUMBERS_H
3 |
4 | #include
5 | #include "../clock_settings.h"
6 |
7 | // calls matrix and overlays numbers
8 | void matrix_with_numbers_render(
9 | uint32_t* led,
10 | uint32_t frame_index,
11 | uint16_t time_hhmm,
12 | const struct ClockSettings* settings);
13 | #endif
14 |
15 |
--------------------------------------------------------------------------------
/src/render/number_cascade.c:
--------------------------------------------------------------------------------
1 | #include "number_cascade.h"
2 |
3 | #include "../led_matrix.h"
4 | #include "../number_draw.h"
5 |
6 | #define FRAMES_PER_SCROLL 7
7 | #define FONT FONT3X5
8 |
9 | static int8_t hours_ypos; // upper right of hour text
10 | static struct NumberFont font;
11 |
12 | void number_cascade_render(
13 | uint32_t* led,
14 | uint32_t frame_index,
15 | uint16_t time_hhmm,
16 | const struct ClockSettings* settings) {
17 | if (frame_index == 0) {
18 | hours_ypos = 0;
19 | frame_index = 1; // don't scroll right away
20 | number_font_init(
21 | &font,
22 | brightness_step_to_brightness(settings),
23 | (LED_MATRIX_WIDTH / 2) - 1,
24 | LED_MATRIX_HEIGHT / 2 + 2,
25 | LED_MATRIX_WIDTH / 2);
26 | }
27 | font.y = hours_ypos;
28 | uint8_t show_hours = 1;
29 | for (;
30 | font.y < LED_MATRIX_HEIGHT;
31 | font.y += font.char_height, show_hours = !show_hours) {
32 | font.x = show_hours ? 0 : LED_MATRIX_WIDTH - (font.char_spacing * 2);
33 | const int8_t val = show_hours ? time_hhmm / 100 : time_hhmm % 100;
34 | draw_numbers(&font, led, val);
35 | }
36 | if ((frame_index % FRAMES_PER_SCROLL) == 0) {
37 | ++hours_ypos;
38 | if (hours_ypos > 0) {
39 | // need to set the ypos so that bottom
40 | // row of the minutes is showing
41 | hours_ypos = -(font.char_height * 2) + 1;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/render/number_cascade.h:
--------------------------------------------------------------------------------
1 | #ifndef RENDER_NUMBER_CASCADE_H
2 | #define RENDER_NUMBER_CASCADE_H
3 |
4 | #include
5 | #include "../clock_settings.h"
6 |
7 | // Cascades time numbers
8 | void number_cascade_render(
9 | uint32_t* led,
10 | uint32_t frame_index,
11 | uint16_t time_hhmm,
12 | const struct ClockSettings* settings);
13 | #endif
14 |
15 |
--------------------------------------------------------------------------------
/src/render/number_cascade_hires.h:
--------------------------------------------------------------------------------
1 | #ifndef RENDER_NUMBER_CASCADE_HIRES_H
2 | #define RENDER_NUMBER_CASCADE_HIRES_H
3 |
4 | #include
5 | #include "../clock_settings.h"
6 |
7 | // Cascades time numbers
8 | void number_cascade_hires_render(
9 | uint32_t* led,
10 | uint32_t frame_index,
11 | uint16_t time_hhmm,
12 | const struct ClockSettings* settings);
13 | #endif
14 |
15 |
--------------------------------------------------------------------------------
/src/render/waveform.c:
--------------------------------------------------------------------------------
1 | #include "waveform.h"
2 |
3 | #include "../led_matrix.h"
4 | #include "../number_draw.h"
5 | #include "../colors.h"
6 | #include
7 | #include
8 |
9 | #define MIN_DIRECTION_WEIGHT 0x85
10 | #define MAX_DIRECTION_WEIGHT 0xFF
11 | #define MAX_DELTA 4
12 | #define WAVEFORM_COUNT 3
13 |
14 | #define FONT_WIDTH 15
15 | #define FONT_HEIGHT 13
16 | #define FONT_XOFFSET ((LED_MATRIX_WIDTH - FONT_WIDTH) >> 1)
17 | #define FONT_YSPACING 16
18 |
19 | struct Waveform {
20 | // 0xIIRRGGBB
21 | uint32_t color;
22 | int8_t dir;
23 | uint8_t dir_weight;
24 | // an xpos for each given ypos. -1 means "nothing"
25 | // ypos is the (index + frame_index) % LED_MATRIX_HEIGHT
26 | int8_t xpos[LED_MATRIX_HEIGHT];
27 | };
28 |
29 | static struct Waveform waves[WAVEFORM_COUNT];
30 | static struct NumberFont font;
31 |
32 | static inline int16_t rand_range(int16_t min, int16_t max) {
33 | return min + (random() % (max - min));
34 | }
35 |
36 | static inline void reverse_wave(struct Waveform* w) {
37 | w->dir = 0 - w->dir;
38 | w->dir_weight = rand_range(MIN_DIRECTION_WEIGHT, MAX_DIRECTION_WEIGHT);
39 | }
40 |
41 | static void add_wave_point(struct Waveform* w, uint8_t head_idx) {
42 | const int8_t prev_head_idx = head_idx == 0 ? LED_MATRIX_HEIGHT - 1 : head_idx - 1;
43 | const int8_t prev_x = w->xpos[prev_head_idx];
44 | if (prev_x < 0) {
45 | // just initialized (or bug)
46 | w->xpos[head_idx] = random() % LED_MATRIX_WIDTH;
47 | return;
48 | }
49 | // The logic below chooses an xdelta and direction from the
50 | // previous x position. It leans toward using w->dir (-1 or 1)
51 | // as a direction, weighted by 0-MAX_DELTA. The chances
52 | // of this happening are w->dir_weight / 255. Otherwise
53 | // the wave will proceed in the oppossite direction to
54 | // create a chaotic feel to the rendering.
55 | uint16_t r = random();
56 | // -1 means reverse
57 | const int8_t reverse = (r & 0xFF) < w->dir_weight ? 1 : -1;
58 | r >>= 8;
59 | const int8_t delta = reverse * w->dir * ((int8_t)(r % MAX_DELTA));
60 | int8_t new_x = prev_x + delta;
61 | if ((new_x < 0) || (new_x >= LED_MATRIX_WIDTH)) {
62 | new_x = prev_x - delta; // go the other way instead
63 | reverse_wave(w);
64 | }
65 | w->xpos[head_idx] = new_x;
66 | }
67 |
68 | static void add_wave_points(uint32_t frame_index) {
69 | for (uint8_t i=0; ixpos[head_idx];
77 | for (uint16_t y=0; yxpos[head_idx];
79 | if (targetx < 0) {
80 | // all done
81 | return;
82 | }
83 | if (targetx == xcursor) {
84 | set_pixel2(led, xcursor, y, w->color);
85 | } else {
86 | const int8_t dir = targetx > xcursor ? 1 : -1;
87 | for (; xcursor != targetx; xcursor += dir) {
88 | set_pixel2(led, xcursor, y, w->color);
89 | }
90 | }
91 | head_idx = head_idx == 0 ? LED_MATRIX_HEIGHT - 1 : head_idx - 1;
92 | }
93 | }
94 |
95 | static void render_waves(uint32_t* led, uint32_t frame_index, uint16_t time_hhmm, uint32_t br_mask) {
96 | for (uint8_t i=0; icolor = br_mask | get_color(time_hhmm % 10);
100 | render_wave(led, w, head_idx);
101 | time_hhmm /= 10;
102 | }
103 | }
104 |
105 | static void overlay_time(
106 | uint32_t* led, uint16_t time_hhmm, uint32_t br_mask) {
107 | for (uint8_t i=0; i<4; ++i) {
108 | font.x = FONT_XOFFSET;
109 | font.y = 1 + i * FONT_YSPACING;
110 | font.color = br_mask | 0x00FFFFFF;
111 | number_draw_mode(&font, led, time_hhmm % 10, DRAW_MODE_COLOR);
112 | time_hhmm = time_hhmm / 10;
113 | }
114 | }
115 |
116 | static void init_wave(struct Waveform* w, uint8_t idx, uint8_t brightness) {
117 | w->dir_weight = rand_range(MIN_DIRECTION_WEIGHT, MAX_DIRECTION_WEIGHT);
118 | w->dir = random() & 1 ? -1 : 1;
119 | for (uint8_t i = 0; i < LED_MATRIX_HEIGHT; ++i) {
120 | w->xpos[i] = -1;
121 | }
122 | w->color = 0;
123 | }
124 |
125 | static void init(const uint8_t brightness) {
126 | number_font_init(&font, brightness, FONT_WIDTH, FONT_HEIGHT, FONT_WIDTH + 1);
127 | for (uint8_t i=0; i
5 | #include "../clock_settings.h"
6 |
7 | // Turns off all LEDs
8 | void waveform_render(
9 | uint32_t* led,
10 | uint32_t frame_index,
11 | uint16_t time_hhmm,
12 | const struct ClockSettings* settings);
13 | #endif
14 |
15 |
--------------------------------------------------------------------------------
/src/set_time_high_res.c:
--------------------------------------------------------------------------------
1 | #include "set_time_high_res.h"
2 |
3 | #include "buttons.h"
4 | #include "clock.h"
5 | #include "colors.h"
6 | #include "led_matrix.h"
7 | #include "number_draw.h"
8 | #include
9 |
10 | #define DIGIT_CURRENT_BRIGHTNESS 0xFF
11 | #define DIGIT_SELECTED_BRIGHTNESS 0xFF
12 | #define DIGIT_OTHER_BRIGHTNESS 0x80
13 | // hold the time when the state was first entered. This
14 | // is used to avoid setting the clock (which changes seconds
15 | // to zero) if the user just scrolls through the time without
16 | // changing anything.
17 | static uint16_t orig_time;
18 |
19 | #define PLACE_HOUR_TENS 0
20 | #define PLACE_HOUR_ONES 1
21 | #define PLACE_MINUTE_TENS 2
22 | #define PLACE_MINUTE_ONES 3
23 | static uint8_t place;
24 | static uint8_t digits[4];
25 |
26 | static struct NumberFont font;
27 |
28 | static void init(uint16_t time_hhmm) {
29 | orig_time = time_hhmm;
30 | digits[0] = time_hhmm / 1000;
31 | digits[1] = (time_hhmm / 100) % 10;
32 | digits[2] = (time_hhmm / 10) % 10;
33 | digits[3] = time_hhmm % 10;
34 | place = PLACE_HOUR_TENS;
35 | // assuming a 64x32 display for the font sizes
36 | number_font_init(
37 | &font,
38 | 0xFF,
39 | 6,
40 | 5,
41 | 7
42 | );
43 | }
44 |
45 | static void render_digits(
46 | uint32_t* led,
47 | uint8_t val,
48 | uint8_t max_val,
49 | int16_t x,
50 | uint8_t is_current) {
51 | font.y = LED_MATRIX_HEIGHT - font.char_height - 3;
52 | for (uint8_t v=0; v <= max_val; ++v, font.y -= (font.char_height + 2)) {
53 | font.x = x;
54 | if (v != val) {
55 | font.char_width -= 2;
56 | font.x += 1;
57 | font.brightness = DIGIT_OTHER_BRIGHTNESS;
58 | number_draw(&font, led, v);
59 | font.char_width += 2;
60 | font.x -= 1;
61 | } else if (is_current) {
62 | font.brightness = DIGIT_CURRENT_BRIGHTNESS;
63 | number_draw(&font, led, v);
64 | } else {
65 | font.brightness = DIGIT_SELECTED_BRIGHTNESS;
66 | number_draw(&font, led, v);
67 | }
68 | }
69 |
70 | if (is_current) {
71 | // draw a line on the top and bottom to indicate the
72 | // current slot
73 | const uint32_t color = 0xFF000000 | get_color(val);
74 | for (uint16_t cx=0; cx max_val) {
112 | digits[p] = 0;
113 | }
114 | }
115 | }
116 |
117 | // public interface. Called to show and allow changing of the time
118 | uint8_t set_time_highres_render(
119 | uint32_t* led,
120 | uint8_t button_pressed,
121 | uint32_t frame_index,
122 | uint16_t time_hhmm,
123 | const struct ClockSettings* settings) {
124 | if (frame_index == 0) {
125 | init(time_hhmm);
126 | }
127 |
128 | if (button_pressed & SELECT_BUTTON) {
129 | ++place;
130 | if (place == 4) {
131 | maybe_set_time();
132 | return 1;
133 | }
134 | }
135 |
136 | if (button_pressed & INCREMENT_BUTTON) {
137 | ++digits[place];
138 | check_for_digit_wrap();
139 | }
140 |
141 | render_digits(
142 | led,
143 | digits[0],
144 | 2,
145 | 0,
146 | place == 0);
147 | render_digits(
148 | led,
149 | digits[1],
150 | digits[0] == 2 ? 3 : 9,
151 | font.char_spacing + 1,
152 | place == 1);
153 | render_digits(
154 | led,
155 | digits[2],
156 | 5,
157 | LED_MATRIX_WIDTH - 2 - font.char_spacing * 2,
158 | place == 2);
159 | render_digits(
160 | led,
161 | digits[3],
162 | 9,
163 | LED_MATRIX_WIDTH - 1 - font.char_spacing,
164 | place == 3);
165 | return 0;
166 | }
167 |
--------------------------------------------------------------------------------
/src/set_time_high_res.h:
--------------------------------------------------------------------------------
1 | #ifndef SET_TIME_HIRES_H
2 | #define SET_TIME_HIRES_H
3 |
4 | #include
5 | #include "clock_settings.h"
6 |
7 | // provides a common interface for rendering a clock
8 |
9 | uint8_t set_time_highres_render(
10 | uint32_t* led,
11 | uint8_t button_pressed,
12 | uint32_t frame_index,
13 | uint16_t time_hhmm,
14 | const struct ClockSettings* settings);
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/src/set_time_low_res.c:
--------------------------------------------------------------------------------
1 | #include "set_time_low_res.h"
2 |
3 | #include "buttons.h"
4 | #include "clock.h"
5 | #include "led_matrix.h"
6 | #include "number_draw.h"
7 | #include
8 |
9 | // hold the time when the state was first entered. This
10 | // is used to avoid setting the clock (which changes seconds
11 | // to zero) if the user just scrolls through the time without
12 | // changing anything.
13 | static uint16_t orig_time;
14 |
15 | // UI state.
16 | static uint8_t hours;
17 | static uint8_t minutes;
18 | static uint8_t showing_minutes;
19 |
20 | static struct NumberFont font;
21 |
22 | // Increments minutes
23 | static void increment_minutes(void) {
24 | ++minutes;
25 | if (minutes >= 60) {
26 | minutes = 0;
27 | }
28 | }
29 |
30 | // Increments hours
31 | static void increment_hours(void) {
32 | ++hours;
33 | if (hours >= 24) {
34 | hours = 0;
35 | }
36 | }
37 |
38 | // Increments either the hours or minutes
39 | static void increment_current(void) {
40 | if (showing_minutes) {
41 | increment_minutes();
42 | } else {
43 | increment_hours();
44 | }
45 | }
46 |
47 | // public interface. Called to show and allow changing of the time
48 | uint8_t set_time_lowres_render(
49 | uint32_t* led,
50 | uint8_t button_pressed,
51 | uint32_t frame_index,
52 | uint16_t time_hhmm,
53 | const struct ClockSettings* settings) {
54 | if (frame_index == 0) {
55 | orig_time = time_hhmm;
56 | hours = time_hhmm / 100;
57 | minutes = time_hhmm % 100;
58 | showing_minutes = 0;
59 | number_font_init(
60 | &font,
61 | brightness_step_to_brightness(settings),
62 | LED_MATRIX_WIDTH / 2 - 1,
63 | LED_MATRIX_HEIGHT,
64 | LED_MATRIX_WIDTH / 4);
65 | }
66 | font.x = 0;
67 | font.y = 0;
68 | draw_numbers(
69 | &font,
70 | led,
71 | showing_minutes ? minutes : hours);
72 | if (button_pressed & INCREMENT_BUTTON) {
73 | increment_current();
74 | }
75 | if (button_pressed & SELECT_BUTTON) {
76 | if (showing_minutes) {
77 | const uint16_t new_time = hours * 100 + minutes;
78 | if (new_time != orig_time) {
79 | clock_set_time(new_time);
80 | }
81 | return 1;
82 | }
83 | showing_minutes = 1;
84 | }
85 | return 0;
86 | }
87 |
--------------------------------------------------------------------------------
/src/set_time_low_res.h:
--------------------------------------------------------------------------------
1 | #ifndef SET_TIME_LOWRES_H
2 | #define SET_TIME_LOWRES_H
3 |
4 | #include
5 | #include "clock_settings.h"
6 |
7 | // provides a common interface for rendering a clock
8 |
9 | uint8_t set_time_lowres_render(
10 | uint32_t* led,
11 | uint8_t button_pressed,
12 | uint32_t frame_index,
13 | uint16_t time_hhmm,
14 | const struct ClockSettings* settings);
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/src/tools/distance_generator.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | """This program calculates x,y coordinates for 90 angle arcs at various
4 | distances from a point.
5 |
6 | The format is included in the generated include file for clarity.
7 | """
8 |
9 | import math
10 | from typing import TextIO
11 |
12 | DISTANCE_SCALE = 1.5
13 | MIN_WEIGHT = 0x20
14 | ANGLE_INCREMENT = math.pi / 1800
15 |
16 | def get_weight(distance: int) -> int:
17 | if distance == 0:
18 | return 255
19 | scale = float(distance) / DISTANCE_SCALE
20 | return round(255.0 / (1 + scale))
21 |
22 |
23 | def calc_weights() -> list[int]:
24 | weights = []
25 | distance = 0
26 | while True:
27 | w = get_weight(distance)
28 | if w < MIN_WEIGHT:
29 | return weights
30 | weights.append(w)
31 | distance = distance + 1.0
32 |
33 | def gen_points(distance: int) -> list[tuple[int, int]]:
34 | """Format is (x, y)"""
35 | data = []
36 | angle = 0.0
37 | while True:
38 | x = round(distance * math.cos(angle))
39 | y = round(distance * math.sin(angle))
40 | if not data or data[-1] != (x, y):
41 | data.append((x, y))
42 | angle = angle + ANGLE_INCREMENT
43 | if angle > math.pi / 2.0:
44 | break
45 | return data
46 |
47 | def generate_header() -> None:
48 | output = (
49 | '// This file was generated by running matrix_clock/tools/distance_generator.py',
50 | '// with no arguments and redirecting the output to a file.',
51 | '',
52 | )
53 | print('\n'.join(output))
54 |
55 | def generate_weights(weights: list[int]) -> None:
56 | data = (
57 | f'#define NUM_DISTANCES {len(weights)} // MAX is -1 this val',
58 | '',
59 | '// Each number below is the weight to apply to a color at a given ',
60 | '// distance. The range is 0x00-0xFF.',
61 | '',
62 | 'uint8_t distance_weights[NUM_DISTANCES] __in_flash() = {',
63 | )
64 | print('\n'.join(data))
65 | for idx, w in enumerate(weights):
66 | print(' 0x%02X, // %d' % (w, idx))
67 | print('};\n')
68 |
69 | def generate_offsets(distances: list[list[tuple[int, int]]]) -> None:
70 | data = (
71 | '',
72 | '// Each number below is the offset into the array for the given ',
73 | '// distance. The next element is used to calculate the length.',
74 | '// The final element is used only for the length calculation',
75 | '',
76 | 'uint16_t distance_offsets[NUM_DISTANCES + 1] __in_flash() = {',
77 | )
78 | print('\n'.join(data))
79 | offset = 0;
80 | for idx, point_list in enumerate(distances):
81 | print(f' 0x%04X, // %d' % (offset, idx))
82 | offset += len(point_list)
83 | print(f' 0x%04X,' % offset)
84 | print('};\n')
85 |
86 | def chunks(lst, n):
87 | """Yield successive n-sized chunks from lst."""
88 | for i in range(0, len(lst), n):
89 | yield lst[i:i + n]
90 |
91 | def generate_point_list(idx: int, points: list[tuple[int, int]]) -> None:
92 | print(f' // {idx}')
93 | for pl in chunks(points, 8):
94 | line = [' ']
95 | for p in pl:
96 | x, y = p
97 | line.append('0x%02X%02X,' % (x, y))
98 | print(' '.join(line))
99 |
100 | def generate_data(distances: list[list[tuple[int, int]]]) -> None:
101 | num_points = sum(len(pl) for pl in distances)
102 | data = (
103 | '// each element is of the format 0xXXYY',
104 | 'uint16_t distance_points[%u] __in_flash() = {' % num_points,
105 | )
106 | print('\n'.join(data))
107 | for idx, point_list in enumerate(distances):
108 | generate_point_list(idx, point_list)
109 | print('};\n')
110 |
111 |
112 | def generate_output(
113 | weights: list[int], distances: list[list[tuple[int, int]]]) -> None:
114 | generate_header()
115 | generate_weights(weights)
116 | generate_offsets(distances)
117 | generate_data(distances)
118 |
119 | def main() -> None:
120 | weights = calc_weights()
121 | distances = [gen_points(d) for d in range(len(weights))]
122 | generate_output(weights, distances)
123 |
124 | if __name__ == '__main__':
125 | main()
126 |
127 |
--------------------------------------------------------------------------------