From 2a3c9fc96a3ed7d0a81ca0d3507248eca321762c Mon Sep 17 00:00:00 2001 From: Ingo Rohlf Date: Sat, 17 Aug 2024 12:57:38 +0200 Subject: [PATCH] Arduino 168, PlatormIO Projekt --- src/.gitignore | 4 + src/.travis.yml | 65 +++ src/LedCube555_V2.ino | 668 ----------------------------- src/lib/readme.txt | 38 ++ src/platformio.ini | 10 + src/src/CubeBase.h | 175 ++++++++ src/src/CubeEffects.h | 181 ++++++++ src/{ => src}/CubeRegister.cpp | 0 src/{ => src}/CubeRegister.h | 0 src/src/CubeTextEffects.h | 164 +++++++ src/{ => src}/LedCube555_V1.ino_V1 | 0 src/src/LedCube555_V3.ino | 64 +++ src/{ => src}/Timer1.cpp | 0 src/{ => src}/Timer1.h | 0 14 files changed, 701 insertions(+), 668 deletions(-) create mode 100644 src/.gitignore create mode 100644 src/.travis.yml delete mode 100644 src/LedCube555_V2.ino create mode 100644 src/lib/readme.txt create mode 100644 src/platformio.ini create mode 100644 src/src/CubeBase.h create mode 100644 src/src/CubeEffects.h rename src/{ => src}/CubeRegister.cpp (100%) rename src/{ => src}/CubeRegister.h (100%) create mode 100644 src/src/CubeTextEffects.h rename src/{ => src}/LedCube555_V1.ino_V1 (100%) create mode 100644 src/src/LedCube555_V3.ino rename src/{ => src}/Timer1.cpp (100%) rename src/{ => src}/Timer1.h (100%) diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..ef55f84 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,4 @@ +.pioenvs +.clang_complete +.gcc-flags.json +.piolibdeps diff --git a/src/.travis.yml b/src/.travis.yml new file mode 100644 index 0000000..9171b89 --- /dev/null +++ b/src/.travis.yml @@ -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 diff --git a/src/LedCube555_V2.ino b/src/LedCube555_V2.ino deleted file mode 100644 index be3f7ef..0000000 --- a/src/LedCube555_V2.ino +++ /dev/null @@ -1,668 +0,0 @@ -#include - -#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 ++; -} diff --git a/src/lib/readme.txt b/src/lib/readme.txt new file mode 100644 index 0000000..0d0e7be --- /dev/null +++ b/src/lib/readme.txt @@ -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 +#include + +// 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 + diff --git a/src/platformio.ini b/src/platformio.ini new file mode 100644 index 0000000..4b88ea8 --- /dev/null +++ b/src/platformio.ini @@ -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:nanoatmega168] +platform = atmelavr +framework = arduino +board = nanoatmega168 diff --git a/src/src/CubeBase.h b/src/src/CubeBase.h new file mode 100644 index 0000000..5b8842d --- /dev/null +++ b/src/src/CubeBase.h @@ -0,0 +1,175 @@ +#ifndef __CUBE_BASE__ +#define __CUBE_BASE__ + +#include "./Timer1.h" +#include "CubeRegister.h" +#include +CubeRegister myRegister = CubeRegister(); + +#define CUBESIZE 5 +#define FPS 60 +#define LEDLEVEL 8 + +byte cube[CUBESIZE][CUBESIZE][CUBESIZE]; + +volatile unsigned long frame = 0; + +void init_cube(void) { + myRegister.reset(); + myRegister.output_enable(); + startTimer1(1000000 / (FPS * LEDLEVEL * CUBESIZE)); +} + +void draw_cube_layer(byte layer, byte level) { + + for (byte z = 0; z < CUBESIZE; z++) { + myRegister.shift_bit(z == layer); + } + for (byte x = 0; x < CUBESIZE; x++) { + for (byte y = 0; y < CUBESIZE; y++) { + myRegister.shift_bit((cube[x][y][layer] > level)); + } + } + myRegister.register_to_output(); +} + +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 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); + } + } + } +} + +void cube_rotate_cover(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); + } +}; + +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); + } +}; + +/* + 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 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); + } + } + } + } + */ + +// 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++; +}; + +#endif diff --git a/src/src/CubeEffects.h b/src/src/CubeEffects.h new file mode 100644 index 0000000..7b67b75 --- /dev/null +++ b/src/src/CubeEffects.h @@ -0,0 +1,181 @@ +#ifndef __CUBE_EFFECTS__ +#define __CUBE_EFFECTS__ + +#include "CubeBase.h" +#include + +// unsigned long effect_start; +unsigned long effect_ende; +#define MAX_DURATION 20 +#define MIN_DURATION 10 + +void cube_effect_template(int duration = 0) { + // prepare something + if (duration <= 0) + duration = random(MIN_DURATION, MAX_DURATION); + effect_ende = millis() + duration * 1000; + while (millis() < effect_ende) { + // manipulate cube[][][] + delay(25); + } +} + +void cube_startup(int duration = 0) { + if (duration <= 0) + duration = random(MIN_DURATION, MAX_DURATION); + effect_ende = millis() + duration * 1000; + fill_cube(0); + for (int y = 0; y < LEDLEVEL; y++) { + for (int i = 0; i < LEDLEVEL; i++) { + cube[CUBESIZE / 2][CUBESIZE / 2][CUBESIZE - 1] = random(0, y); + delay(25); + } + } + cube[CUBESIZE / 2][CUBESIZE / 2][CUBESIZE - 1] = LEDLEVEL; + delay(250); + for (int z = CUBESIZE - 1; z > 0; z--) { + delay(250); + cube[CUBESIZE / 2][CUBESIZE / 2][z] += LEDLEVEL; + } + + while (millis() < effect_ende) { + } +}; + +void cube_effect_glow(int duration = 0) { + if (duration <= 0) + duration = random(MIN_DURATION, MAX_DURATION); + effect_ende = millis() + duration * 1000; + int glow = 0; + int glch = 1; + fill_cube(glow); + while (millis() < effect_ende) { + glow += glch; // ((effect_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 cube_effect_glitzer(int duration = 0) { + if (duration <= 0) + duration = random(MIN_DURATION, MAX_DURATION); + effect_ende = millis() + duration * 1000; + while (millis() < effect_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 cube_effect_glitzer_levels(int duration = 0) { + if (duration <= 0) + duration = random(MIN_DURATION, MAX_DURATION); + effect_ende = millis() + duration * 1000; + + while (millis() < effect_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 cube_effect_glitzer_fade(int duration = 0) { + int cleanup = 5; + fill_cube(0); + + if (duration <= 0) + duration = random(MIN_DURATION, MAX_DURATION); + effect_ende = millis() + duration * 1000; + while (millis() < effect_ende) { + + // while ((millis() - effect_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 cube_effect_dots(int duration = 0) { + 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; + } + } + + if (duration <= 0) + duration = random(MIN_DURATION, MAX_DURATION); + effect_ende = millis() + duration * 1000; + while (millis() < effect_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; + } + } +}; + +#endif diff --git a/src/CubeRegister.cpp b/src/src/CubeRegister.cpp similarity index 100% rename from src/CubeRegister.cpp rename to src/src/CubeRegister.cpp diff --git a/src/CubeRegister.h b/src/src/CubeRegister.h similarity index 100% rename from src/CubeRegister.h rename to src/src/CubeRegister.h diff --git a/src/src/CubeTextEffects.h b/src/src/CubeTextEffects.h new file mode 100644 index 0000000..f817773 --- /dev/null +++ b/src/src/CubeTextEffects.h @@ -0,0 +1,164 @@ +#ifndef __CUBE_TEXT_EFFECTS__ +#define __CUBE_TEXT_EFFECTS__ + +#include "./Timer1.h" +#include "CubeBase.h" +#include + +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]; +} + +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; + for (byte y = 0; y < CUBESIZE; y++) { + for (byte x = 0; x < CUBESIZE; x++) { + if (pattern & mask) { + cube[(CUBESIZE - 1) - x][ebene][y] = brightness; + } else { + cube[(CUBESIZE - 1) - x][ebene][y] = 0; + } + mask >>= 1; + } + } +} + +void cube_text_warp(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 cube_text_banner(const char *message, int frame_delay = 100) { + + unsigned long pattern; // = char_to_5bits(zeichen); + unsigned long mask; // = 0B1000000000000000000000000; + fill_cube(0); + + 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; + } + cube_rotate_cover(1, 150); + } + cube_rotate_cover(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; + } + cube_rotate_cover(1, 150); + } +}; + +#endif diff --git a/src/LedCube555_V1.ino_V1 b/src/src/LedCube555_V1.ino_V1 similarity index 100% rename from src/LedCube555_V1.ino_V1 rename to src/src/LedCube555_V1.ino_V1 diff --git a/src/src/LedCube555_V3.ino b/src/src/LedCube555_V3.ino new file mode 100644 index 0000000..c20dcaa --- /dev/null +++ b/src/src/LedCube555_V3.ino @@ -0,0 +1,64 @@ +#include + +#include "CubeBase.h" +#include "CubeEffects.h" +#include "CubeTextEffects.h" + +void setup() { + Serial.begin(115200); + init_cube(); + cube_startup(); +} + +// 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: + cube_effect_glow(); + break; + case 1: + cube_effect_glitzer(); + break; + case 2: + cube_effect_glitzer_levels(); + break; + case 3: + cube_effect_glitzer_fade(); + break; + case 4: + cube_effect_dots(); + break; + case 5: + cube_startup(); + break; + case 6: + cube_text_banner(messages[random(message_count)]); + break; + case 7: + cube_text_warp(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)); + */ +} diff --git a/src/Timer1.cpp b/src/src/Timer1.cpp similarity index 100% rename from src/Timer1.cpp rename to src/src/Timer1.cpp diff --git a/src/Timer1.h b/src/src/Timer1.h similarity index 100% rename from src/Timer1.h rename to src/src/Timer1.h