Compare commits

...

13 commits

53 changed files with 118099 additions and 1433 deletions

26
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,26 @@
# You can override the included template(s) by including variable overrides
# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/#customization
# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
# Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
# Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages:
- build
- test
- deploy
- review
- dast
- staging
- canary
- production
- incremental rollout 10%
- incremental rollout 25%
- incremental rollout 50%
- incremental rollout 100%
- performance
- cleanup
sast:
stage: test
include:
- template: Auto-DevOps.gitlab-ci.yml

19
README.md Normal file
View file

@ -0,0 +1,19 @@
# LED Cube 5x5x5
Dies ist ein Arduino-Projekt zum Bau eines **LED-Würfels mit 5x5x5 LEDs**. Das Repository enthält alle notwendigen Ressourcen, um den Würfel zu erstellen und zu programmieren:
* **Elektronik und Schaltplan**: Detaillierte Schaltpläne und das KiCAD-Projekt für den Aufbau der Hardware.
* **Arduino-Programm**: Quellcode, der verschiedene Muster und Animationen und Laufschrift auf dem LED-Würfel abspielen lässt.
Der LED-Würfel bietet eine beeindruckende visuelle Darstellung und ist ein großartiges Projekt für Elektronikbegeisterte, Hobbyisten und alle, die ihre Fähigkeiten in Mikrocontroller-Programmierung und LED-Steuerung erweitern möchten.
### Repository klonen
Du kannst das Repository mit HTTPS klonen:
```
git clone https://git.irohlf.de/Projekte/led-cube-555.git
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,83 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "",
"auto_track_width": true,
"hidden_netclasses": [],
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"images": 0.6,
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"ratsnest_display_mode": 0,
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": true,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36
],
"visible_layers": "0001000_ffffffff",
"zone_display_mode": 1
},
"git": {
"repo_password": "",
"repo_type": "",
"repo_username": "",
"ssh_key": ""
},
"meta": {
"filename": "LED-Cube 5x5x5.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View file

@ -0,0 +1,673 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.1,
"copper_line_width": 0.2,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.05,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.1,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.15,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.762,
"height": 1.524,
"width": 1.524
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"45_degree_only": false,
"min_clearance": 0.508
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"holes_co_located": "warning",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "error",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "warning",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zone_has_empty_net": "error",
"zones_intersect": "error"
},
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.0,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.0,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.2,
"min_microvia_drill": 0.1,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.8,
"min_text_thickness": 0.08,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.2,
"min_via_annular_width": 0.05,
"min_via_diameter": 0.4,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": false,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [
0.0,
0.5,
0.8,
1.0
],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
},
{
"diameter": 2.0,
"drill": 0.8
}
],
"zones_allow_external_fillets": false,
"zones_use_no_outline": true
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_label_syntax": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"missing_bidi_pin": "warning",
"missing_input_pin": "warning",
"missing_power_pin": "error",
"missing_unit": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "error",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"simulation_model_issue": "ignore",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "LED-Cube 5x5x5.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.4,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.5,
"via_diameter": 2.0,
"via_drill": 0.8,
"wire_width": 6
},
{
"bus_width": 12,
"clearance": 0.4,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Kurzdistanz",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 1.28,
"via_diameter": 2.0,
"via_drill": 0.8,
"wire_width": 6
},
{
"bus_width": 12,
"clearance": 0.5,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Power",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 1.0,
"via_diameter": 2.0,
"via_drill": 0.8,
"wire_width": 6
},
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "ShiftRegister",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgb(0, 0, 255)",
"track_width": 0.25,
"via_diameter": 0.8,
"via_drill": 0.4,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_export_filename": "",
"bom_fmt_presets": [],
"bom_fmt_settings": {
"field_delimiter": ",",
"keep_line_breaks": false,
"keep_tabs": false,
"name": "CSV",
"ref_delimiter": ",",
"ref_range_delimiter": "",
"string_delimiter": "\""
},
"bom_presets": [],
"bom_settings": {
"exclude_dnp": false,
"fields_ordered": [
{
"group_by": false,
"label": "Reference",
"name": "Reference",
"show": true
},
{
"group_by": true,
"label": "Value",
"name": "Value",
"show": true
},
{
"group_by": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
},
{
"group_by": false,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
}
],
"filter_string": "",
"group_symbols": true,
"name": "Grouped By Value",
"sort_asc": true,
"sort_field": "Referenz"
},
"connection_grid_size": 50.0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"operating_point_overlay_i_precision": 3,
"operating_point_overlay_i_range": "~A",
"operating_point_overlay_v_precision": 3,
"operating_point_overlay_v_range": "~V",
"overbar_offset_ratio": 1.23,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_current_sheet_as_root": false,
"spice_external_command": "spice \"%I\"",
"spice_model_current_sheet_as_root": true,
"spice_save_all_currents": false,
"spice_save_all_dissipations": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"b5dbd2ce-1b55-4734-94ed-9d5a2115f508",
"Stammblatt"
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
{"hostname":"ingo","username":"ingo"}

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

1
doc/Profilbild.md Normal file
View file

@ -0,0 +1 @@
Ein Bild eines aktiven 5x5x5 LED-Würfels, dessen rote 3mm LEDs ein zufälliges Muster aus leutenden und nicht leuchtenden LEDs bildet. die LEDs sind mit silberen, geradem Draht miteinander verbunden. Es ist wichtigt, dass die LEDs alle nach oben gerichtet sind. jeweils 5x5 bilden eine Lage. es gibt 5 lagen. Es leuchten nur etwa die hälfte der LEDs. die anderen sind ausgeschaltet. unterhalb soll in einem durchsichtigen gehäuse ein arduino zu sehen sein.

BIN
doc/Profilbild.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
doc/Profilbild_klein.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 KiB

BIN
doc/bc337-1.pdf Normal file

Binary file not shown.

4
src/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
.pioenvs
.clang_complete
.gcc-flags.json
.piolibdeps

65
src/.travis.yml Normal file
View file

@ -0,0 +1,65 @@
# Continuous Integration (CI) is the practice, in software
# engineering, of merging all developer working copies with a shared mainline
# several times a day < http://docs.platformio.org/en/stable/ci/index.html >
#
# Documentation:
#
# * Travis CI Embedded Builds with PlatformIO
# < https://docs.travis-ci.com/user/integration/platformio/ >
#
# * PlatformIO integration with Travis CI
# < http://docs.platformio.org/en/stable/ci/travis.html >
#
# * User Guide for `platformio ci` command
# < http://docs.platformio.org/en/stable/userguide/cmd_ci.html >
#
#
# Please choice one of the following templates (proposed below) and uncomment
# it (remove "# " before each line) or use own configuration according to the
# Travis CI documentation (see above).
#
#
# Template #1: General project. Test it using existing `platformio.ini`.
#
# language: python
# python:
# - "2.7"
#
# sudo: false
# cache:
# directories:
# - "~/.platformio"
#
# install:
# - pip install -U platformio
#
# script:
# - platformio run
#
# Template #2: The project is intended to by used as a library with examples
#
# language: python
# python:
# - "2.7"
#
# sudo: false
# cache:
# directories:
# - "~/.platformio"
#
# env:
# - PLATFORMIO_CI_SRC=path/to/test/file.c
# - PLATFORMIO_CI_SRC=examples/file.ino
# - PLATFORMIO_CI_SRC=path/to/test/directory
#
# install:
# - pip install -U platformio
#
# script:
# - platformio ci --lib="." --board=TYPE_1 --board=TYPE_2 --board=TYPE_N

View file

@ -1,73 +0,0 @@
#ifndef __CubeRegister__
#define __CubeRegister__
#include <Arduino.h>
class CubeRegister {
public:
static const byte _SER = 0x10; // 0b00010000;
static const byte _OE = 0x08; // 0b00001000;
static const byte _RCLK = 0x04; // 0b00000100;
static const byte _SRCLK = 0x02; // 0b00000010;
static const byte _SRCLR = 0x01; // 0b00000001;
void reset(void);
void output_enable(void);
void output_disable(void);
void clear_register(void);
void shift_bit(bool bit);
void register_to_output(void);
};
/*
Version with digitalWrite
#define PIN_SER 12
#define PIN_OE 11
#define PIN_RCLK 10
#define PIN_SRCLK 9
#define PIN_SRCLR 8
class ShiftRegisterSlow {
public:
void reset() {
pinMode(PIN_SER, OUTPUT);
pinMode(PIN_OE, OUTPUT);
pinMode(PIN_RCLK, OUTPUT);
pinMode(PIN_SRCLK, OUTPUT);
pinMode(PIN_SRCLR, OUTPUT);
output_disable();
clear_register();
register_to_output();
}
void output_enable() {
digitalWrite(PIN_OE, LOW);
}
void output_disable() {
digitalWrite(PIN_OE, HIGH);
}
void clear_register() {
digitalWrite(PIN_SRCLR, HIGH);
digitalWrite(PIN_SRCLK, LOW);
digitalWrite(PIN_RCLK, LOW);
digitalWrite(PIN_SRCLR, LOW);
digitalWrite(PIN_SRCLR, LOW);
digitalWrite(PIN_SRCLR, HIGH);
}
void shift_bit(bool bit) {
digitalWrite(PIN_SER, bit);
digitalWrite(PIN_SRCLK, HIGH);
digitalWrite(PIN_SRCLK, LOW);
}
void register_to_output() {
digitalWrite(PIN_RCLK, HIGH);
digitalWrite(PIN_RCLK, LOW);
}
};
*/
#endif

View file

@ -1,518 +0,0 @@
#include <Arduino.h>
#include "./Timer1.h"
#include "CubeRegister.h"
typedef void(*CubeEffects)(unsigned int frame);
#define CUBESIZE 5
//ShiftRegisterSlow Register ;
CubeRegister Register ;
#define FPS 60
#define LEDLEVEL 8
byte cube[CUBESIZE][CUBESIZE][CUBESIZE];
volatile unsigned long frame = 0;
unsigned long start;
unsigned long ende;
class LED {
public:
byte x;
byte y;
byte z;
byte value;
void show() {
cube[x][y][z] = value;
}
void hide() {
cube[x][y][z] = 0;
}
void randomize() {
x = random(CUBESIZE + 1);
y = random(CUBESIZE + 1);
z = random(CUBESIZE + 1);
value = random(LEDLEVEL + 1);
}
};
class Vector {
public:
int dx;
int dy;
int dz;
};
void draw_cube_layer(byte layer, byte level) {
for (byte z = 0; z < CUBESIZE; z++) {
Register.shift_bit(z == layer);
}
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
Register.shift_bit((cube[x][y][layer] > level));
}
}
Register.register_to_output();
}
void setup() {
// Disable Arduino's default millisecond counter (from now on, millis(), micros(),
// delay() and delayMicroseconds() will not work)
Serial.begin(115200);
//disableMillis();
Register.reset();
Register.output_enable();
//randomize_cube();
// Prepare Timer1 to count
// On 16 MHz Arduino boards, this function has a resolution of 4us
// On 8 MHz Arduino boards, this function has a resolution of 8us
startTimer1(1000000 / (FPS * LEDLEVEL * CUBESIZE));
//draw_cube_layer(1, 1);
}
/*
void randomize_cube() {
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = random(LEDLEVEL + 1);
}
}
}
}
*/
void fill_cube(byte brightness) {
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = min(brightness, LEDLEVEL);
}
}
}
}
/*
void gravity_cube(int x,int y, int z){
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = ;
}
}
}
}
*/
void dimm_cube(int diff = -1) {
diff = constrain(diff, -LEDLEVEL, LEDLEVEL);
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = constrain( cube[x][y][z] + diff, 0, LEDLEVEL);
/* if (cube[x][y][z] > LEDLEVEL) {
cube[x][y][z] = LEDLEVEL;
} else if (cube[x][y][z] < 0) {
cube[x][y][z] = 0;
}*/
}
}
}
}
const unsigned long CHAR_5BIT[42] = {
0B0111010001111111000110001, // 0 A (97/65)
0B1111110001111101000111111, // 1 B
0B0111110000100001000001111, // 2 C
0B1111010001100011000111110, // 3 D
0B1111110000111101000011111, // 4 E
0B1111110000111001000010000, // 5 F
0B0111110000100111000101111, // 6 G
0B1000110001111111000110001, // 7 H
0B0111000100001000010001110, // 8 I
0B0001100001000011000101111, // 9 J
0B1000110010111001001010001, // 10 K
0B1000010000100001000011111, // 11 L
0B1000111011101011000110001, // 12 M
0B1000111001101011001110001, // 13 N
0B0111010001100011000101110, // 14 O
0B1111010001111101000010000, // 15 P
0B1111110001101011111100010, // 16 Q
0B1111010001111101000110001, // 17 R
0B0111110000011100000111110, // 18 S
0B1111100100001000010000100, // 19 T
0B1000110001100011000101110, // 20 U
0B1000110001010100101000100, // 21 V
0B1000110001101011010101010, // 22 W
0B1000101010001000101010001, // 23 X
0B1000110001010100010000100, // 24 Y
0B1111100010001000100011111, // 25 Z (122/90)
0B0111010011101011100101110, // 26 ZERO (48)
0B0010001100001000010001110, // 27 ONE (49)
0B1111000001011101000011111, // 28 TWO (50)
0B1111000001011100000111110, // 29 THREE
0B0010001000101001111100100, // 30 FOUR
0B1111110000111100000111110, // 31 FIVE
0B1111110000111101000111110, // 32 SIX
0B1111100001000100010000100, // 33 SEVEN
0B0111010001011101000101110, // 34 EIGHT
0B0111010001011110000111110, // 35 NINE (57)
0B0000000000000000000000000, // 36 SPACE (32)
0B0010000100001000000000100, // 37 EXCL (33)
0B0000000100000000000000100, // 38 COLON (58)
0B0000000000000000000000100, // 39 POINT (46)
0B0000000000000000010001000, // 40 COMMA (44)
0B0000001010111110111000100 // 41 @ -> Herz (44)
};
unsigned long char_to_5bits(char zeichen) {
// special chars
switch (zeichen) {
case 32: return CHAR_5BIT[36];
case 33: return CHAR_5BIT[37];
case 58: return CHAR_5BIT[38];
case 46: return CHAR_5BIT[39];
case 44: return CHAR_5BIT[40];
case 64: return CHAR_5BIT[41];
}
// upper case letters
if ((zeichen >= 65) & (zeichen <= 90)) {
return CHAR_5BIT[zeichen - 65];
}
// lower case letters
if ((zeichen >= 97) & (zeichen <= 122)) {
return CHAR_5BIT[zeichen - 97];
}
// digits
if ((zeichen >= 48) & (zeichen <= 57)) {
return CHAR_5BIT[zeichen - 22];
}
}
void write_char(char zeichen, int ebene, byte brightness = LEDLEVEL) {
ebene = constrain(ebene, 0, CUBESIZE - 1);
unsigned long pattern = char_to_5bits(zeichen);
unsigned long mask = 0B1000000000000000000000000;
Serial.println("\nPattern: " + (String)(pattern));
for (byte y = 0; y < CUBESIZE; y++) {
for (byte x = 0; x < CUBESIZE; x++) {
Serial.print( pattern & mask );
if (pattern & mask) {
cube[(CUBESIZE - 1) - x][ebene][y] = brightness ;
} else {
cube[(CUBESIZE - 1) - x][ebene][y] = 0 ;
}
mask >>= 1;
//mask = mask << 1;
}
}
}
void hello_cube(int duration) {
const char* message = "mama ist die beste!@!@@ " ;
for (size_t mp = 0; mp < strlen(message); mp++ ) {
int s = CUBESIZE - 1;
for (int i = 0; i < (CUBESIZE + LEDLEVEL); i++) {
dimm_cube(LEDLEVEL / -2);
write_char(message[mp], max(s, 0), LEDLEVEL);
s--;
delay(50);
}
delay(200);
}
}
void text_cube(const char *message){
for (size_t mp = 0; mp < strlen(message); mp++ ) {
int s = CUBESIZE - 1;
for (int i = 0; i < (CUBESIZE + LEDLEVEL); i++) {
dimm_cube(LEDLEVEL / -2 );
write_char(message[mp], max(s, 0), LEDLEVEL);
s--;
delay(50);
}
delay(200);
}
}
void glow_cube(int duration) {
ende = millis() + duration * 1000;
int glow = 0;
int glch = 1;
fill_cube(glow);
while (millis() < ende) {
glow += glch; // ((ende - millis()) / 200) % (LEDLEVEL + 1);
if (glow <= 0){
glow = 0;
glch = 1;
} else if (glow >= LEDLEVEL){
glow = LEDLEVEL;
glch = -1;
}
fill_cube(glow);
delay(100);
}
}
void glitzer_cube(int duration) {
start = millis();
ende = millis() + duration * 1000;
//while ((millis() - start) < 5000 ) {
while (millis() < ende) {
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
if (random(2) > 0) {
cube[x][y][z] = LEDLEVEL;
} else {
cube[x][y][z] = 0;
}
}
}
}
delay(50);
}
}
void glitzer_cube_levels(int duration) {
start = millis();
ende = millis() + duration * 1000;
//while ((millis() - start) < 5000 ) {
while (millis() < ende) {
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = random(LEDLEVEL + 1);
}
}
}
delay(50);
}
}
void glitzer_fade_cube(int duration) {
int cleanup = 5;
fill_cube(0);
/*for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = 0;
}
}
}*/
/* for (byte n = 0; n < traces; n++) {
punkt.randomize();
punkt.show();
}
*/
ende = millis() + duration * 1000;
while (millis() < ende) {
//while ((millis() - start) < 10000 ) {
//punkt.randomize();
//punkt.show();
cube[random(CUBESIZE)][random(CUBESIZE)][random(CUBESIZE)] = random(LEDLEVEL + 1);
cube[random(CUBESIZE)][random(CUBESIZE)][random(CUBESIZE)] = random(LEDLEVEL + 1);
delay(25);
cleanup --;
if (cleanup <= 0) {
cleanup = 5;
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
if (cube[x][y][z] > 0) {
cube[x][y][z] --;
}
}
}
}
}
}
}
void dots_cube(int duration) {
byte x;
byte y;
int speed = 50;
fill_cube(0);
for ( x = 0; x < CUBESIZE; x++) {
for ( y = 0; y < CUBESIZE; y++) {
cube[x][y][0] = LEDLEVEL;
}
}
ende = millis() + duration * 1000;
while (millis() < ende) {
x = random(CUBESIZE);
y = random(CUBESIZE);
if (cube[x][y][0] == 0) {
for (int z = CUBESIZE - 1; z >= 0; --z) {
if (z <= (CUBESIZE - 2))
cube[x][y][z + 2] = 0;
cube[x][y][z + 1] = LEDLEVEL / 2;
cube[x][y][z] = LEDLEVEL;
delay(speed);
}
} else {
for (int z = 1; z < CUBESIZE; z++) {
if (z >= 2)
cube[x][y][z - 2] = 0;
cube[x][y][z - 1] = LEDLEVEL / 2;
cube[x][y][z] = LEDLEVEL;
delay(speed);
}
}
for (byte z = 1; z < CUBESIZE - 1; z++) {
cube[x][y][z] = 0;
}
}
}
void template_cube(int duration) {
// prepare something
ende = millis() + duration * 1000;
while (millis() < ende) {
// manipulate cube[][][]
delay(25);
}
}
void traces_cube() {
start = millis();
int traces = 5;
LED origin[traces];
LED leds[traces];
LED ziel[traces];
int steps[traces];
int pos[traces];
for (byte n = 0; n < traces; n++) {
origin[n] = LED();
origin[n].randomize();
origin[n].z = 0;
leds[n] = LED();
ziel[n] = LED();
ziel[n].randomize();
ziel[n].z = CUBESIZE - 1;
steps[n] = random(5, 20);
pos[n] = 0;
}
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = 0;
}
}
}
while ((millis() - start) < 5000 ) {
for (byte n = 0; n < traces; n++) {
leds[n].hide();
pos[n] ++;
leds[n].x = origin[n].x + ( (ziel[n].x - origin[n].x) * pos[n] / steps[n]);
leds[n].y = origin[n].y + ( (ziel[n].y - origin[n].y) * pos[n] / steps[n]);
leds[n].z = (origin[n]).z + ( ((ziel[n]).z - origin[n].z) * pos[n] / steps[n]);
leds[n].show();
}
delay(100);
}
}
void loop() {
int next_duration = random(5, 10);
switch (random(0, 10)) {
case 0:
glow_cube(next_duration);
break;
case 1:
glitzer_cube(next_duration);
break;
case 2:
glitzer_cube_levels(next_duration);
break;
case 3:
glitzer_fade_cube(next_duration);
break;
case 4:
dots_cube(next_duration);
break;
case 5:
text_cube("i@u");
break;
case 6:
text_cube("benjamin");
break;
case 7:
text_cube("annika");
break;
}
/* glitzer_cube(random(5, 20));
glitzer_fade_cube(random(5, 20));
*/
}
// Define the function which will handle the notifications (interrupts)
ISR(timer1Event)
{
// if (Serial)
// Serial.println(frame);
// Reset Timer1 (resetTimer1 should be the first operation for better timer precision)
resetTimer1();
// For a smaller and faster code, the line above could safely be replaced with a call
// to the function resetTimer1Unsafe() as, despite its name, it IS safe to call
// that function in here (interrupts are disabled)
// Make sure to do your work as fast as possible, since interrupts are automatically
// disabled when this event happens (refer to interrupts() and noInterrupts() for
// more information on that)
draw_cube_layer(frame % CUBESIZE, frame % LEDLEVEL);
frame ++;
}

View file

@ -1,668 +0,0 @@
#include <Arduino.h>
#include "./Timer1.h"
#include "CubeRegister.h"
typedef void(*CubeEffects)(unsigned int frame);
#define CUBESIZE 5
//ShiftRegisterSlow Register ;
CubeRegister Register ;
#define FPS 60
#define LEDLEVEL 8
byte cube[CUBESIZE][CUBESIZE][CUBESIZE];
volatile unsigned long frame = 0;
unsigned long start;
unsigned long ende;
void draw_cube_layer(byte layer, byte level) {
for (byte z = 0; z < CUBESIZE; z++) {
Register.shift_bit(z == layer);
}
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
Register.shift_bit((cube[x][y][layer] > level));
}
}
Register.register_to_output();
}
void setup() {
// Disable Arduino's default millisecond counter (from now on, millis(), micros(),
// delay() and delayMicroseconds() will not work)
Serial.begin(115200);
//disableMillis();
Register.reset();
Register.output_enable();
//randomize_cube();
// Prepare Timer1 to count
// On 16 MHz Arduino boards, this function has a resolution of 4us
// On 8 MHz Arduino boards, this function has a resolution of 8us
startTimer1(1000000 / (FPS * LEDLEVEL * CUBESIZE));
//draw_cube_layer(1, 1);
}
/*
void randomize_cube() {
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = random(LEDLEVEL + 1);
}
}
}
}
*/
void fill_cube(byte brightness) {
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = min(brightness, LEDLEVEL);
}
}
}
}
/*
void gravity_cube(int x,int y, int z){
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = ;
}
}
}
}
*/
void dimm_cube(int diff = -1) {
diff = constrain(diff, -LEDLEVEL, LEDLEVEL);
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = constrain( cube[x][y][z] + diff, 0, LEDLEVEL);
/* if (cube[x][y][z] > LEDLEVEL) {
cube[x][y][z] = LEDLEVEL;
} else if (cube[x][y][z] < 0) {
cube[x][y][z] = 0;
}*/
}
}
}
}
void rotate_ac_cube(int steps) {
byte x = 0;
byte y = 0;
byte backup;
for (int s = 0 ; s <= steps; s++) {
for (byte z = 0; z < CUBESIZE; z++) {
Serial.println("--------------- GO ---------");
Serial.println("Backup: 0,0" + (String)(backup));
backup = cube[0][0][z];
// shift west-side y=0, x=0..max
Serial.println("Links");
y = 0;
for ( x = 1; x < CUBESIZE; x++) {
Serial.println("x" + (String)(x - 1) + ",y" + (String)y + " <= " + "x" + (String)x + ",y" + (String)y);
cube[x - 1][y][z] = cube[x][y][z];
};
// shift north-side y=0..max, x = max
Serial.println("Vorne");
x = CUBESIZE - 1;
for (y = 1; y < CUBESIZE; y++) {
Serial.println("x" + (String)(x) + ",y" + (String)(y - 1) + " <= " + "x" + (String)x + ",y" + (String)y);
cube[x][y - 1][z] = cube[x][y][z];
}
// shift east-side y=max, x=max..1
Serial.println("Rechts");
y = CUBESIZE - 1;
for (x = CUBESIZE - 2 ; x < CUBESIZE; x--) {
Serial.println("x" + (String)(x + 1) + ",y" + (String)y + " <= " + "x" + (String)x + ",y" + (String)y);
cube[x + 1][y][z] = cube[x][y][z];
}
x = 0;
Serial.println("Hinten");
for (y = CUBESIZE - 2 ; y > 0; --y) {
Serial.println("x" + (String)(x) + ",y" + (String)(y + 1) + " <= " + "x" + (String)x + ",y" + (String)y);
cube[x][y + 1][z] = cube[x][y][z];
}
Serial.println("Backup: x0,y1 <= " + (String)(backup));
cube[0][1][z] = backup;
}
delay(50);
}
};
void rotate_cube(int steps, unsigned int frame_delay = 100) {
byte x = 0;
byte y = 0;
byte backup;
for (int s = 0 ; s < steps; s++) {
for (byte z = 0; z < CUBESIZE; z++) {
backup = cube[0][0][z];
// 0,0 -> 0,4 : v
x = 0;
for (y = 1; y < CUBESIZE ; y++) {
cube[x][y - 1][z] = cube[x][y][z];
};
y = CUBESIZE - 1;
for (x = 1; x < CUBESIZE ; x++) {
cube[x - 1][y][z] = cube[x][y][z];
}
x = CUBESIZE - 1;
for (y = CUBESIZE - 2 ; y < CUBESIZE ; --y) {
cube[x][y + 1][z] = cube[x][y][z] ;
}
y = 0 ;
for (x = CUBESIZE - 2 ; x < CUBESIZE ; --x) {
cube[x + 1][y][z] = cube[x][y][z];
}
cube[1][0][z] = backup;
}
delay(frame_delay);
}
};
const unsigned long CHAR_5BIT[] = {
0B0000000000000000000000000, // 36 SPACE (32)
0B0010000100001000000000100, // 37 ! (33)
0B0000001010010100000000000, // 36 " (34)
0B0101011111010101111101010, // 36 # (35)
0B0111010100011100010101110, // 36 $ (36)
0B0000101010001000101010000, // 36 % (37)
0B1000001100011001001011100, // 36 & (38) ??
0B0010000100000000000000000, // 36 '(39)
0B0001000100001000010000010, // 36 ( (40)
0B0100000100001000010001000, // 36 ) (41)
0B0000000100011100101000000, // 36 * (42)
0B0000000100011100010000000, // 36 + (43)
0B0000000000000000010001000, // 36 , (44)
0B0000000000011100000000000, // 36 - (45)
0B0000000000000000000000100, // 39 . (46)
0B0000100010001000100010000, // 36 / (45)
0B0111010011101011100101110, // 26 0 (48)
0B0010001100001000010001110, // 27 1 (49)
0B1111000001011101000011111, // 28 2 (50)
0B1111000001011100000111110, // 29 3
0B0010001000101001111100100, // 30 4
0B1111110000111100000111110, // 31 5
0B1111110000111101000111110, // 32 6
0B1111100001000100010000100, // 33 7
0B0111010001011101000101110, // 34 8
0B0111010001011110000111110, // 35 9 (57)
0B0000000100000000000000100, // 38 : (58)
0B0000000100000000010001000, // 38 ; (59)
0B0000100010001000000000001, // 38 < (60)
0B0000001110000000111000000, // 36 = (61)
0B1000001000001000100010000, // 38 > (62)
0B0111010001001100000000100, // 38 ? (63)
0B0111010111100010111001100, // 38 @ (64
0B0111010001111111000110001, // 0 A (97/65)
0B1111110001111101000111111, // 1 B
0B0111110000100001000001111, // 2 C
0B1111010001100011000111110, // 3 D
0B1111110000111101000011111, // 4 E
0B1111110000111001000010000, // 5 F
0B0111110000100111000101111, // 6 G
0B1000110001111111000110001, // 7 H
0B0111000100001000010001110, // 8 I
0B0001100001000011000101111, // 9 J
0B1000110010111001001010001, // 10 K
0B1000010000100001000011111, // 11 L
0B1000111011101011000110001, // 12 M
0B1000111001101011001110001, // 13 N
0B0111010001100011000101110, // 14 O
0B1111010001111101000010000, // 15 P
0B1111110001101011111100010, // 16 Q
0B1111010001111101000110001, // 17 R
0B0111110000011100000111110, // 18 S
0B1111100100001000010000100, // 19 T
0B1000110001100011000101110, // 20 U
0B1000110001010100101000100, // 21 V
0B1000110001101011010101010, // 22 W
0B1000101010001000101010001, // 23 X
0B1000110001010100010000100, // 24 Y
0B1111100010001000100011111, // 25 Z (122/90)
0B0011100100001000010000111, // 38 [ (91)
0B1000001000001000001000001, // 38 \ (92)
0B1110000100001000010011100, // 38 ] (93)
0B0010001001000000000000000, // 36 ^ (94)
0B0000000000000000000011111, // 36 _ (95)
0B0010000001000000000000000, // 36 ` (96)
0B0011000100011000010000110, // 36 { (123)
0B0010000100001000010000100, // 36 | (124)
0B0110000100001100010001100, // 36 } (125)
0B0000001000101010001000000, // 36 ~ (126)
0B0000001010111110111000100 // 41 @ -> Herz (44)
};
unsigned long char_to_5bits(char zeichen) {
// upper case letters + digits
if ((zeichen >= 32) & (zeichen <= 96)) {
return CHAR_5BIT[zeichen - 32];
}
// lower case letters
if ((zeichen >= 97) & (zeichen <= 122)) {
return CHAR_5BIT[zeichen - 64];
}
// digits
if ((zeichen >= 123) & (zeichen <= 126)) {
return CHAR_5BIT[zeichen - 22];
}
return CHAR_5BIT[69];
}
// 5 * 5 bits/row, top to bottom
/*
const unsigned long CHAR_5BIT[42] = {
0B0111010001111111000110001, // 0 A (97/65)
0B1111110001111101000111111, // 1 B
0B0111110000100001000001111, // 2 C
0B1111010001100011000111110, // 3 D
0B1111110000111101000011111, // 4 E
0B1111110000111001000010000, // 5 F
0B0111110000100111000101111, // 6 G
0B1000110001111111000110001, // 7 H
0B0111000100001000010001110, // 8 I
0B0001100001000011000101111, // 9 J
0B1000110010111001001010001, // 10 K
0B1000010000100001000011111, // 11 L
0B1000111011101011000110001, // 12 M
0B1000111001101011001110001, // 13 N
0B0111010001100011000101110, // 14 O
0B1111010001111101000010000, // 15 P
0B1111110001101011111100010, // 16 Q
0B1111010001111101000110001, // 17 R
0B0111110000011100000111110, // 18 S
0B1111100100001000010000100, // 19 T
0B1000110001100011000101110, // 20 U
0B1000110001010100101000100, // 21 V
0B1000110001101011010101010, // 22 W
0B1000101010001000101010001, // 23 X
0B1000110001010100010000100, // 24 Y
0B1111100010001000100011111, // 25 Z (122/90)
0B0111010011101011100101110, // 26 ZERO (48)
0B0010001100001000010001110, // 27 ONE (49)
0B1111000001011101000011111, // 28 TWO (50)
0B1111000001011100000111110, // 29 THREE
0B0010001000101001111100100, // 30 FOUR
0B1111110000111100000111110, // 31 FIVE
0B1111110000111101000111110, // 32 SIX
0B1111100001000100010000100, // 33 SEVEN
0B0111010001011101000101110, // 34 EIGHT
0B0111010001011110000111110, // 35 NINE (57)
0B0000000000000000000000000, // 36 SPACE (32)
0B0010000100001000000000100, // 37 EXCL (33)
0B0000000100000000000000100, // 38 COLON (58)
0B0000000000000000000000100, // 39 POINT (46)
0B0000000000000000010001000, // 40 COMMA (44)
0B0000001010111110111000100 // 41 @ -> Herz (44)
};
*/
unsigned long char_to_5bits__(char zeichen) {
// special chars
switch (zeichen) {
case 32: return CHAR_5BIT[36];
case 33: return CHAR_5BIT[37];
case 58: return CHAR_5BIT[38];
case 46: return CHAR_5BIT[39];
case 44: return CHAR_5BIT[40];
case 64: return CHAR_5BIT[41];
}
// upper case letters
if ((zeichen >= 65) & (zeichen <= 90)) {
return CHAR_5BIT[zeichen - 65];
}
// lower case letters
if ((zeichen >= 97) & (zeichen <= 122)) {
return CHAR_5BIT[zeichen - 97];
}
// digits
if ((zeichen >= 48) & (zeichen <= 57)) {
return CHAR_5BIT[zeichen - 22];
}
}
void write_char(char zeichen, int ebene = 0, byte brightness = LEDLEVEL) {
ebene = constrain(ebene, 0, CUBESIZE - 1);
unsigned long pattern = char_to_5bits(zeichen);
unsigned long mask = 0B1000000000000000000000000;
Serial.println("\nPattern: " + (String)(pattern));
for (byte y = 0; y < CUBESIZE; y++) {
for (byte x = 0; x < CUBESIZE; x++) {
Serial.print( pattern & mask );
if (pattern & mask) {
cube[(CUBESIZE - 1) - x][ebene][y] = brightness ;
} else {
cube[(CUBESIZE - 1) - x][ebene][y] = 0 ;
}
mask >>= 1;
//mask = mask << 1;
}
}
}
void banner_cube(const char *message, int frame_delay = 100) {
unsigned long pattern;// = char_to_5bits(zeichen);
unsigned long mask;// = 0B1000000000000000000000000;
for (size_t mp = 0; mp < strlen(message); mp++ ) {
pattern = char_to_5bits(message[mp]);
mask = 0B1000000000000000000000000;
for (byte y = 0; y < CUBESIZE; y++) {
mask = 0B1000000000000000000000000;
mask >>= y;// * CUBESIZE;
for (byte z = 0; z < CUBESIZE; z++) {
if (pattern & mask) {
cube[0][CUBESIZE - 1][z] = LEDLEVEL;
} else {
cube[0][CUBESIZE - 1][z] = 0;
}
cube[CUBESIZE - 1][CUBESIZE - 1][z] = 0;
mask >>= CUBESIZE;
}
rotate_cube(1, 150);
}
rotate_cube(1, 150);
}
for (byte cols = 0; cols < (CUBESIZE * 3 - 2); cols++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[CUBESIZE - 1][CUBESIZE - 1][z] = 0;
}
rotate_cube(1, 150);
}
}
void hello_cube(int duration) {
const char* message = "mama ist die beste!@!@@ " ;
for (size_t mp = 0; mp < strlen(message); mp++ ) {
int s = CUBESIZE - 1;
for (int i = 0; i < (CUBESIZE + LEDLEVEL); i++) {
dimm_cube(LEDLEVEL / -2);
write_char(message[mp], max(s, 0), LEDLEVEL);
s--;
delay(50);
}
delay(200);
}
fill_cube(0);
}
void text_cube(const char *message) {
for (size_t mp = 0; mp < strlen(message); mp++ ) {
int s = CUBESIZE - 1;
for (int i = 0; i < (CUBESIZE + LEDLEVEL); i++) {
dimm_cube(LEDLEVEL / -2 );
write_char(message[mp], max(s, 0), LEDLEVEL);
s--;
delay(50);
}
delay(200);
}
fill_cube(0);
}
void glow_cube(int duration) {
ende = millis() + duration * 1000;
int glow = 0;
int glch = 1;
fill_cube(glow);
while (millis() < ende) {
glow += glch; // ((ende - millis()) / 200) % (LEDLEVEL + 1);
if (glow <= 0) {
glow = 0;
glch = 1;
} else if (glow >= LEDLEVEL) {
glow = LEDLEVEL;
glch = -1;
}
fill_cube(glow);
delay(100);
}
}
void glitzer_cube(int duration) {
start = millis();
ende = millis() + duration * 1000;
//while ((millis() - start) < 5000 ) {
while (millis() < ende) {
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
if (random(2) > 0) {
cube[x][y][z] = LEDLEVEL;
} else {
cube[x][y][z] = 0;
}
}
}
}
delay(50);
}
}
void glitzer_cube_levels(int duration) {
start = millis();
ende = millis() + duration * 1000;
//while ((millis() - start) < 5000 ) {
while (millis() < ende) {
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = random(LEDLEVEL + 1);
}
}
}
delay(50);
}
}
void glitzer_fade_cube(int duration) {
int cleanup = 5;
fill_cube(0);
/*for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
cube[x][y][z] = 0;
}
}
}*/
/* for (byte n = 0; n < traces; n++) {
punkt.randomize();
punkt.show();
}
*/
ende = millis() + duration * 1000;
while (millis() < ende) {
//while ((millis() - start) < 10000 ) {
//punkt.randomize();
//punkt.show();
cube[random(CUBESIZE)][random(CUBESIZE)][random(CUBESIZE)] = random(LEDLEVEL + 1);
cube[random(CUBESIZE)][random(CUBESIZE)][random(CUBESIZE)] = random(LEDLEVEL + 1);
delay(25);
cleanup --;
if (cleanup <= 0) {
cleanup = 5;
for (byte x = 0; x < CUBESIZE; x++) {
for (byte y = 0; y < CUBESIZE; y++) {
for (byte z = 0; z < CUBESIZE; z++) {
if (cube[x][y][z] > 0) {
cube[x][y][z] --;
}
}
}
}
}
}
}
void dots_cube(int duration) {
byte x;
byte y;
int speed = 50;
fill_cube(0);
for ( x = 0; x < CUBESIZE; x++) {
for ( y = 0; y < CUBESIZE; y++) {
cube[x][y][0] = LEDLEVEL;
}
}
ende = millis() + duration * 1000;
while (millis() < ende) {
x = random(CUBESIZE);
y = random(CUBESIZE);
if (cube[x][y][0] == 0) {
for (int z = CUBESIZE - 1; z >= 0; --z) {
if (z <= (CUBESIZE - 2))
cube[x][y][z + 2] = 0;
cube[x][y][z + 1] = LEDLEVEL / 2;
cube[x][y][z] = LEDLEVEL;
delay(speed);
}
} else {
for (int z = 1; z < CUBESIZE; z++) {
if (z >= 2)
cube[x][y][z - 2] = 0;
cube[x][y][z - 1] = LEDLEVEL / 2;
cube[x][y][z] = LEDLEVEL;
delay(speed);
}
}
for (byte z = 1; z < CUBESIZE - 1; z++) {
cube[x][y][z] = 0;
}
}
}
void template_cube(int duration) {
// prepare something
ende = millis() + duration * 1000;
while (millis() < ende) {
// manipulate cube[][][]
delay(25);
}
}
// const char* messages = {"I°U", "mama ist die allerbeste!°!°", "benjamin", "annika", "5x5x5 led-cube"};
static const char* const messages[] = {"I°U", "mama ist die allerbeste!°!°", "benjamin", "annika", "5x5x5 led-cube"};
int message_count = 5;
void loop() {
int next_duration = random(10, 20);
switch (random(0, 10)) {
case 0:
glow_cube(next_duration);
break;
case 1:
glitzer_cube(next_duration);
break;
case 2:
glitzer_cube_levels(next_duration);
break;
case 3:
glitzer_fade_cube(next_duration);
break;
case 4:
dots_cube(next_duration);
break;
case 6:
banner_cube(messages[random(message_count)]);
break;
case 7:
text_cube(messages[random(message_count)]);
break;
/*
case 8:
if (random(10) > 5)
text_cube("LED-Cube 5*5*5");
else
banner_cube("LED-Cube 5*5*5 ");
*/
/*write_char('v', 0);
write_char('x', 4);
rotate_cube(10);
fill_cube(0);*/
}
/* glitzer_cube(random(5, 20));
glitzer_fade_cube(random(5, 20));
*/
}
// Define the function which will handle the notifications (interrupts)
ISR(timer1Event)
{
// if (Serial)
// Serial.println(frame);
// Reset Timer1 (resetTimer1 should be the first operation for better timer precision)
resetTimer1();
// For a smaller and faster code, the line above could safely be replaced with a call
// to the function resetTimer1Unsafe() as, despite its name, it IS safe to call
// that function in here (interrupts are disabled)
// Make sure to do your work as fast as possible, since interrupts are automatically
// disabled when this event happens (refer to interrupts() and noInterrupts() for
// more information on that)
draw_cube_layer(frame % CUBESIZE, frame % LEDLEVEL);
frame ++;
}

View file

@ -1,169 +0,0 @@
//
// ArduinoTimer is distributed under the FreeBSD License
//
// Copyright (c) 2013, Carlos Rafael Gimenes das Neves
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those
// of the authors and should not be interpreted as representing official policies,
// either expressed or implied, of the FreeBSD Project.
//
// https://github.com/carlosrafaelgn/ArduinoTimer
//
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "Timer1.h"
uint8_t __timer1Control;
uint16_t __timer1CounterValue;
// On 16 MHz Arduino boards, this function has a resolution of 4us, for intervals <= 262000, a resolution of 16us for intervals <= 1048000, and a resolution of 64us for intervals <= 4194000
// On 8 MHz Arduino boards, this function has a resolution of 8us, for intervals <= 524000, a resolution of 32us for intervals <= 2097000, and a resolution os 128us for intervals <= 8388000
void startTimer1(uint32_t microsecondsInterval) {
pauseTimer1();
// 18. Timer/Counter 0, 1, 3, 4, and 5 Prescaler (page 169)
// 17.9.1 Normal Mode (page 149)
TCCR1A = 0;
TCCR1C = 0;
// 17.11.5 TCCR1B (page 160)
// 0 0 0 No clock source (Timer/Counter stopped)
// 0 0 1 clkIO/1 (No prescaling)
// 0 1 0 clkIO/8 (From prescaler)
// 0 1 1 clkIO/64 (From prescaler)
// 1 0 0 clkIO/256 (From prescaler)
// 1 0 1 clkIO/1024 (From prescaler)
#if (F_CPU == 16000000L)
if (microsecondsInterval <= 262000L) {
__timer1Control = B00000011;
// The proper way of doing this would be:
// 65536 - (microsecondsInterval / 4)
// But, in order to save one 32-bit operation, this "- 1" is necessary...
__timer1CounterValue = 65535 - ((uint16_t)(microsecondsInterval >> 2) - 1);
} else if (microsecondsInterval <= 1048000L) {
__timer1Control = B00000100;
__timer1CounterValue = 65535 - ((uint16_t)(microsecondsInterval >> 4) - 1);
} else {
__timer1Control = B00000101;
__timer1CounterValue = 65535 - ((uint16_t)(microsecondsInterval >> 6) - 1);
}
#elif (F_CPU == 8000000L)
if (microsecondsInterval <= 524000L) {
__timer1Control = B00000011;
__timer1CounterValue = 65535 - ((uint16_t)(microsecondsInterval >> 3) - 1);
} else if (microsecondsInterval <= 2097000L) {
__timer1Control = B00000100;
__timer1CounterValue = 65535 - ((uint16_t)(microsecondsInterval >> 5) - 1);
} else {
__timer1Control = B00000101;
__timer1CounterValue = 65535 - ((uint16_t)(microsecondsInterval >> 7) - 1);
}
#else
#error("Unsupported CPU frequency")
#endif
resetTimer1();
// 17.11.37 TIFR1 <20> Timer/Counter1 Interrupt Flag Register (page 167)
TIFR1 = 0;
TIMSK1 = 1;
resumeTimer1();
}
// On 16 MHz Arduino boards, this function has a resolution of 4us
// On 8 MHz Arduino boards, this function has a resolution of 8us
void startCountingTimer1(void) {
pauseTimer1();
TCCR1A = 0;
TCCR1C = 0;
#if (F_CPU == 16000000L) || (F_CPU == 8000000L)
__timer1Control = B00000011;
__timer1CounterValue = 0;
#else
#error("Unsupported CPU frequency")
#endif
resetTimer1();
TIFR1 = 0;
TIMSK1 = 0;
resumeTimer1();
}
// On 16 MHz Arduino boards, this function has a resolution of 16us
// On 8 MHz Arduino boards, this function has a resolution of 32us
void startSlowCountingTimer1(void) {
pauseTimer1();
TCCR1A = 0;
TCCR1C = 0;
#if (F_CPU == 16000000L) || (F_CPU == 8000000L)
__timer1Control = B00000100;
__timer1CounterValue = 0;
#else
#error("Unsupported CPU frequency")
#endif
resetTimer1();
TIFR1 = 0;
TIMSK1 = 0;
resumeTimer1();
}
// On 16 MHz Arduino boards, this function has a resolution of 64us
// On 8 MHz Arduino boards, this function has a resolution of 128us
void startUltraSlowCountingTimer1(void) {
pauseTimer1();
TCCR1A = 0;
TCCR1C = 0;
#if (F_CPU == 16000000L) || (F_CPU == 8000000L)
__timer1Control = B00000101;
__timer1CounterValue = 0;
#else
#error("Unsupported CPU frequency")
#endif
resetTimer1();
TIFR1 = 0;
TIMSK1 = 0;
resumeTimer1();
}
uint16_t readTimer1(void) {
// 17.3 Accessing 16-bit Registers (page 138)
uint8_t sreg;
uint16_t i;
// Save global interrupt flag
// 7.4.1 SREG <20> AVR Status Register (page 14)
sreg = SREG;
// Disable interrupts
cli();
// Read TCNTn
i = readTimer1Unsafe();
// Restore global interrupt flag
SREG = sreg;
return i;
}
void resetTimer1(void) {
// 17.3 Accessing 16-bit Registers (page 138)
uint8_t sreg;
// Save global interrupt flag
// 7.4.1 SREG <20> AVR Status Register (page 14)
sreg = SREG;
// Disable interrupts
cli();
// Write TCNTn
resetTimer1Unsafe();
// Restore global interrupt flag
SREG = sreg;
}

38
src/lib/readme.txt Normal file
View file

@ -0,0 +1,38 @@
This directory is intended for the project specific (private) libraries.
PlatformIO will compile them to static libraries and link to executable file.
The source code of each library should be placed in separate directory, like
"lib/private_lib/[here are source files]".
For example, see how can be organized `Foo` and `Bar` libraries:
|--lib
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |- readme.txt --> THIS FILE
|- platformio.ini
|--src
|- main.c
Then in `src/main.c` you should use:
#include <Foo.h>
#include <Bar.h>
// rest H/C/CPP code
PlatformIO will find your libraries automatically, configure preprocessor's
include paths and build them.
See additional options for PlatformIO Library Dependency Finder `lib_*`:
http://docs.platformio.org/en/stable/projectconf.html#lib-install

10
src/platformio.ini Normal file
View file

@ -0,0 +1,10 @@
#
# PlatformIO Project Configuration File
#
# Please make sure to read documentation with examples first
# http://docs.platformio.org/en/stable/projectconf.html
#
[env:nanoatmega328]
platform = atmelavr
framework = arduino
board = nanoatmega328

110
src/src/CubeAnimations.cpp Normal file
View file

@ -0,0 +1,110 @@
#include "CubeAnimations.h"
CubeAnimations::CubeAnimations(
LedCube myCube,
unsigned char throttle = 50,
unsigned int duration = 15000):
myCube(myCube),
speed(throttle),
duration(duration){
};
void CubeAnimations::start(void){
myCube.reset();
myCube.start();
}
void CubeAnimations::stop(void){
myCube.reset();
}
void CubeAnimations::setSpeed(unsigned char throttle){
speed = constrain(throttle, 0, 100);
}
void CubeAnimations::setDuration(unsigned int duration){
duration = constrain(duration, 0, 100);
}
bool CubeAnimations::isRunning(void){
return millis() <= effect_ende;
}
void CubeAnimations::startAnimation(void){
effect_ende = millis() + duration;
}
void CubeAnimations::wait(unsigned long time){
delay((time * speed)/ 100);
}
void CubeAnimations::glow(void){
startAnimation();
unsigned char glow = 0;
bool glow_up;
while (isRunning()){
if (glow == 0){
glow_up = true;
} else if (glow == myCube.shades()) {
glow_up = false;
}
glow_up ? glow++ : glow--;
myCube.fill(glow);
wait(200);
}
}
void CubeAnimations::glitter(unsigned char filling = 50){
startAnimation();
filling = constrain(filling, 0, 100);
unsigned char value;
while (isRunning()){
for (byte x = 0; x < myCube.size(); x++) {
for (byte y = 0; y < myCube.size(); y++) {
for (byte z = 0; z < myCube.size(); z++) {
value = random(100) < filling ? myCube.shades() : 0;
myCube.pixel(x,y,z, value);
}
}
}
wait(100);
}
}
void CubeAnimations::shaded_glitter(unsigned char filling = 50){
startAnimation();
filling = constrain(filling, 0, 100);
unsigned char value;
while (isRunning()){
for (byte x = 0; x < myCube.size(); x++) {
for (byte y = 0; y < myCube.size(); y++) {
for (byte z = 0; z < myCube.size(); z++) {
value = random(100) < filling ? random(myCube.shades() + 1) : 0;
myCube.pixel(x,y,z, value);
}
}
}
wait(100);
}
}
void CubeAnimations::dimed_glitter(unsigned char filling = 50){
startAnimation();
filling = constrain(filling, 0, 100);
// (total_leds * filling) / (100 * shades)
// (125 * 50) / (100 * 8) = 7
unsigned char update_count = (myCube.size()^3 * 100) / (filling * myCube.shades());
unsigned char x,y,z;
while (isRunning()){
myCube.shade(-1);
for (unsigned char n=0;n<=update_count;n++){
x = random(myCube.size());
y = random(myCube.size());
z = random(myCube.size());
myCube.pixel(x,y,z, random(myCube.shades() + 1));
}
wait(100);
}
}

39
src/src/CubeAnimations.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef __CUBE_ANIMATIONS__
#define __CUBE_ANIMATIONS__
#include "LedCube.h"
class CubeAnimations{
public:
CubeAnimations(
LedCube myCube,
unsigned char throttle,
unsigned int duration
);
void start(void);
void stop(void);
void setSpeed(unsigned char throttle);
void setDuration(unsigned int duration);
bool isRunning(void);
void glow(void);
void glitter( unsigned char filling);
void shaded_glitter(unsigned char filling);
void dimed_glitter(unsigned char filling);
private:
void startAnimation(void);
void wait(unsigned long time);
LedCube myCube;
unsigned char status;
unsigned char speed;
unsigned int duration;
unsigned long effect_ende;
};
#endif //__CUBE_ANIMATIONS__

View file

@ -1,5 +1,7 @@
#include "CubeRegister.h"
CubeRegister CubeRegisterPortB;
void CubeRegister::reset() {
// Port B Pin 8 - 13
//Serial.println("reset");
@ -23,6 +25,7 @@ void CubeRegister::output_disable() {
// OUTPUT für OE auf 1 setzen
PORTB |= _OE; //-> HIGH
};
void CubeRegister::clear_register() {
PORTB |= _SRCLR; // -> HIGH
PORTB &= ~_SRCLK; // -> LOW
@ -33,21 +36,21 @@ void CubeRegister::clear_register() {
};
void CubeRegister::shift_bit(bool bit) {
//Serial.println("shift_bit " + (String)(bit));
//
// copy bit to SER (input) of shift regitster
if (bit == LOW) {
PORTB &= ~_SER; // -> LOW
} else {
PORTB |= _SER; // -> HIGH
}
// clock signal for shift registers
PORTB |= _SRCLK; // -> HIGH
PORTB &= ~_SRCLK; // -> LOW
};
// copy shift registers to output registers
void CubeRegister::register_to_output() {
//Serial.println("register_to_output");
// PORTB &= ~_RCLK; // -> LOW
// clock signal for output registers
PORTB |= _RCLK; // -> HIGH
//Serial.println(PORTB);
PORTB &= ~_RCLK; // -> LOW
// Serial.println(PORTB);
};

34
src/src/CubeRegister.h Normal file
View file

@ -0,0 +1,34 @@
#ifndef __CubeRegister__
#define __CubeRegister__
#include <Arduino.h>
class CubeRegister {
public:
/*
singnals for IC SN74HC595 8-bit shift registers with 3-state output registers
SER - PIN 14
OE - PIN 13
RCLK - PIN 12
SRCLK - PIN 11
SRCLR - PIN 10
*/
// bitmasks for PORTB Pin 8 - 13
static const byte _SER = 0x10; // 0b00010000; // D12
static const byte _OE = 0x08; // 0b00001000; // D11
static const byte _RCLK = 0x04; // 0b00000100; // D10
static const byte _SRCLK = 0x02; // 0b00000010; // D9
static const byte _SRCLR = 0x01; // 0b00000001; // D8
void reset(void);
void output_enable(void);
void output_disable(void);
void clear_register(void);
void shift_bit(bool bit);
void register_to_output(void);
};
extern CubeRegister CubeRegisterPortB;
#endif

207
src/src/LedCube.cpp Normal file
View file

@ -0,0 +1,207 @@
#include "LedCube.h"
//#include "TimerOne.h"
#include "TimerOne.h"
LedCube myCube(DEFAULT_CUBESIZE, DEFAULT_SHADES, CubeRegisterPortB);
myCube.framerate(DEFAULT_FRAMERATE);
LedCube::LedCube( const unsigned char size,
const unsigned char shades,
CubeRegister output = CubeRegister())
:_cubesize(size), _shades(shades), myRegister(output){
_framerate = DEFAULT_FRAMERATE;
// unsigned char pixels[5][5][5];
pixels = new unsigned char**[_cubesize];
for (unsigned char x=0;x<_cubesize;x++){
pixels[x] = new unsigned char*[_cubesize];
for (unsigned char y=0;y<_cubesize;y++){
pixels[x][y] = new unsigned char[_cubesize];
}
}
reset();
};
LedCube::~LedCube(void){
for (unsigned char x=0;x<_cubesize;x++){
for (unsigned char y=0;y<_cubesize;y++){
delete [] pixels[x][y];
}
delete [] pixels[x];
}
delete [] pixels;
}
void LedCube::toSerial(void){
if (Serial){
Serial.println("LedCube "+ String(_cubesize) + "x"+ String(_cubesize) +"x"+ String(_cubesize) +" @" + String(_framerate)+ "Hz and " + String(_shades) + " shades of grey\n");
}
}
void LedCube::start(void){
reset();
myRegister.reset();
myRegister.output_enable();
if (Serial){ Serial.println("[LedCube] startTimer1(" + String(1000000 / (_framerate * _shades * _cubesize)) + ");"); }
delay(500);
//startTimer1(1000000 / (_framerate * _shades * _cubesize));
unsigned long timer_interval = 1000000 / (_framerate * _shades * _cubesize);
Timer1.initialize(timer_interval);
Timer1.attachInterrupt(myCube.draw_layer);
delay(500);
if (Serial){ Serial.println("LedCube::start :-)"); }
}
void LedCube::reset(void){
Timer1.detachInterrupt();
//resetTimer1();
myRegister.reset();
layer = 0;
level = 0;
}
void LedCube::framerate(unsigned char framerate){
_framerate = framerate;
}
unsigned char LedCube::size(void){
return _cubesize;
}
unsigned char LedCube::shades(void){
return _shades;
}
unsigned char LedCube::pixel(unsigned char x, unsigned char y, unsigned char z){
return pixels[x][y][z];
}
void LedCube::pixel(unsigned char x, unsigned char y, unsigned char z, unsigned char value){
pixels[x][y][z] = constrain(value, 0, _shades);
}
void LedCube::draw_layer(void){
layer = layer++ % _cubesize;
if (layer == 0){
level = level++ % _shades;
};
for (unsigned char z = 0; z < _cubesize; z++) {
myRegister.shift_bit(z == layer);
}
for (unsigned char x = 0; x < _cubesize; x++) {
for (unsigned char y = 0; y < _cubesize; y++) {
myRegister.shift_bit((pixels[x][y][layer] > level));
}
}
myRegister.register_to_output();
}
void LedCube::fill(unsigned char brightness){
unsigned char value = min(brightness, _shades);
for (unsigned char x = 0; x < _cubesize; x++) {
for (unsigned char y = 0; y < _cubesize; y++) {
for (unsigned char z = 0; z < _cubesize; z++) {
pixels[x][y][z] = value;
}
}
}
}
void LedCube::shade(char diff = -1){
char value = constrain(diff, -_shades, _shades);
for (unsigned char x = 0; x < _cubesize; x++) {
for (unsigned char y = 0; y < _cubesize; y++) {
for (unsigned char z = 0; z < _cubesize; z++) {
pixels[x][y][z] = constrain(pixels[x][y][z] + value, 0, _shades);
}
}
}
}
void LedCube::rotate_cover(int steps, unsigned int frame_delay = 100) {
unsigned char x = 0;
unsigned char y = 0;
unsigned char z = 0;
unsigned char backup;
for (int s = 0; s < steps; s++) {
for (z = 0; z < _cubesize; z++) {
backup = pixels[0][0][z];
// 0,0 -> 0,4 : v
x = 0;
for (y = 1; y < _cubesize; y++) {
pixels[x][y - 1][z] = pixels[x][y][z];
};
y = _cubesize - 1;
for (x = 1; x < _cubesize; x++) {
pixels[x - 1][y][z] = pixels[x][y][z];
}
x = _cubesize - 1;
for (y = _cubesize - 2; y < _cubesize; --y) {
pixels[x][y + 1][z] = pixels[x][y][z];
}
y = 0;
for (x = _cubesize - 2; x < _cubesize; --x) {
pixels[x + 1][y][z] = pixels[x][y][z];
}
pixels[1][0][z] = backup;
}
delay(frame_delay);
}
};
void LedCube::rotate(int steps, unsigned int frame_delay = 100) {
unsigned char x = 0;
unsigned char y = 0;
unsigned char z = 0;
unsigned char backup;
for (int s = 0; s < steps; s++) {
for (z = 0; z < _cubesize; z++) {
backup = pixels[0][0][z];
// 0,0 -> 0,4 : v
x = 0;
for (y = 1; y < _cubesize; y++) {
pixels[x][y - 1][z] = pixels[x][y][z];
};
y = _cubesize - 1;
for (x = 1; x < _cubesize; x++) {
pixels[x - 1][y][z] = pixels[x][y][z];
}
x = _cubesize - 1;
for (y = _cubesize - 2; y < _cubesize; --y) {
pixels[x][y + 1][z] = pixels[x][y][z];
}
y = 0;
for (x = _cubesize - 2; x < _cubesize; --x) {
pixels[x + 1][y][z] = pixels[x][y][z];
}
pixels[1][0][z] = backup;
}
delay(frame_delay);
}
};

49
src/src/LedCube.h Normal file
View file

@ -0,0 +1,49 @@
#ifndef __LedCube__
#define __LedCube__
#include "CubeRegister.h"
#define DEFAULT_FRAMERATE 30
#define DEFAULT_SHADES 8
#define DEFAULT_CUBESIZE 5
class LedCube {
public:
LedCube(unsigned char size, unsigned char shades, CubeRegister output);
~LedCube();
void start(void);
void reset(void);
void draw_layer();
void framerate(unsigned char framerate);
unsigned char shades(void);
unsigned char size(void);
void toSerial(void);
unsigned char pixel(unsigned char x, unsigned char y, unsigned char z);
void pixel(unsigned char x, unsigned char y, unsigned char z, unsigned char value);
void fill(unsigned char brightness);
// void dim(unsigned char diff);
void shade(char diff);
void rotate_cover(int steps, unsigned int frame_delay);
void rotate(int steps, unsigned int frame_delay);
private:
const unsigned char _cubesize;
const unsigned char _shades;
unsigned char _framerate;
CubeRegister myRegister;
volatile unsigned char layer = 0;
volatile unsigned char level = 0;
unsigned char ***pixels;
};
extern LedCube myCube;
#endif // __LedCube__

74
src/src/LedCube555_V4.ino Normal file
View file

@ -0,0 +1,74 @@
#include <Arduino.h>
#include "LedCube.h"
#include "CubeAnimations.h"
CubeRegister out;
// new LedCube 5x5x5, 8 greytones
LedCube cube(5,8, out);
// new CubeAnimations with cube, speed (0-100%), duration in ms (default: 15000ms)
CubeAnimations animation(cube, 50, 5000);
void setup() {
Serial.begin(115200);
cube.framerate(30);
cube.toSerial();
delay(1000);
cube.start();
Serial.println("setup() done.");
}
//static const char *const messages[] = {"I°arduino", "make: something",
// "einfach.machen.", "5x5x5 led-cube"};
//int message_count = 5;
void loop() {
// int next_duration = random(10, 20);
int ani = random(0,10);
if (Serial){
Serial.println("next Animation: " + String(ani));
}
switch (ani) {
case 0:
animation.glow();
break;
case 1:
animation.glitter(40);
break;
case 2:
animation.shaded_glitter(60);
break;
case 3:
animation.dimed_glitter(70);
break;
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
}
};
/*
ISR(TIMER1_COMPA_vect) {
cube.draw_layer();
};*/

101
src/src/TimerOne.cpp Normal file
View file

@ -0,0 +1,101 @@
/*
* Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
* Original code by Jesse Tane for http://labs.ideo.com August 2008
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
* Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
*
* This is free software. You can redistribute it and/or modify it under
* the terms of Creative Commons Attribution 3.0 United States License.
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
*
*/
#include "TimerOne.h"
TimerOne Timer1; // preinstatiate
ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined function supplied by attachInterrupt
{
Timer1.isrCallback();
}
void TimerOne::initialize(long microseconds)
{
TCCR1A = 0; // clear control register A
TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer
setPeriod(microseconds);
}
void TimerOne::setPeriod(long microseconds)
{
long cycles = (F_CPU * microseconds) / 2000000; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2
if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8
else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256
else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024
else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum
ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
TCCR1B |= clockSelectBits; // reset clock select register
}
void TimerOne::setPwmDuty(char pin, int duty)
{
unsigned long dutyCycle = pwmPeriod;
dutyCycle *= duty;
dutyCycle >>= 10;
if(pin == 1 || pin == 9) OCR1A = dutyCycle;
else if(pin == 2 || pin == 10) OCR1B = dutyCycle;
}
void TimerOne::pwm(char pin, int duty, long microseconds) // expects duty cycle to be 10 bit (1024)
{
if(microseconds > 0) setPeriod(microseconds);
if(pin == 1 || pin == 9) {
DDRB |= _BV(PORTB1); // sets data direction register for pwm output pin
TCCR1A |= _BV(COM1A1); // activates the output pin
}
else if(pin == 2 || pin == 10) {
DDRB |= _BV(PORTB2);
TCCR1A |= _BV(COM1B1);
}
setPwmDuty(pin, duty);
start();
}
void TimerOne::disablePwm(char pin)
{
if(pin == 1 || pin == 9) TCCR1A &= ~_BV(COM1A1); // clear the bit that enables pwm on PB1
else if(pin == 2 || pin == 10) TCCR1A &= ~_BV(COM1B1); // clear the bit that enables pwm on PB2
}
void TimerOne::attachInterrupt(void (*isr)(), long microseconds)
{
if(microseconds > 0) setPeriod(microseconds);
isrCallback = isr; // register the user's callback with the real ISR
TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit
sei(); // ensures that interrupts are globally enabled
start();
}
void TimerOne::detachInterrupt()
{
TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow interrupt enable bit
}
void TimerOne::start()
{
TCCR1B |= clockSelectBits;
}
void TimerOne::stop()
{
TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits
}
void TimerOne::restart()
{
TCNT1 = 0;
}

41
src/src/TimerOne.h Normal file
View file

@ -0,0 +1,41 @@
/*
* Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
* Original code by Jesse Tane for http://labs.ideo.com August 2008
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
* Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
*
* This is free software. You can redistribute it and/or modify it under
* the terms of Creative Commons Attribution 3.0 United States License.
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
*
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#define RESOLUTION 65536 // Timer1 is 16 bit
class TimerOne
{
public:
// properties
unsigned int pwmPeriod;
unsigned char clockSelectBits;
// methods
void initialize(long microseconds=1000000);
void start();
void stop();
void restart();
void pwm(char pin, int duty, long microseconds=-1);
void disablePwm(char pin);
void attachInterrupt(void (*isr)(), long microseconds=-1);
void detachInterrupt();
void setPeriod(long microseconds);
void setPwmDuty(char pin, int duty);
void (*isrCallback)();
};
extern TimerOne Timer1;