From 3fa536d4feee16be414b77f085ccc4588640f2e8 Mon Sep 17 00:00:00 2001 From: Ingo Rohlf Date: Sat, 17 Aug 2024 12:40:02 +0200 Subject: [PATCH 1/3] erste Version --- src/_5x5x5_Led_Cube (working).ino | 372 +++++++++++++++++++++++++ tools/5x5x5 Bohrschablone (1,27cm).odg | Bin 0 -> 9140 bytes tools/Ebenen-Template.fcstd | Bin 0 -> 3324 bytes tools/Ebenen-Template.fcstd1 | Bin 0 -> 3324 bytes 4 files changed, 372 insertions(+) create mode 100644 src/_5x5x5_Led_Cube (working).ino create mode 100644 tools/5x5x5 Bohrschablone (1,27cm).odg create mode 100644 tools/Ebenen-Template.fcstd create mode 100644 tools/Ebenen-Template.fcstd1 diff --git a/src/_5x5x5_Led_Cube (working).ino b/src/_5x5x5_Led_Cube (working).ino new file mode 100644 index 0000000..7e8f3bb --- /dev/null +++ b/src/_5x5x5_Led_Cube (working).ino @@ -0,0 +1,372 @@ +#include + +#define PIN_SER 12 +#define PIN_OE 11 +#define PIN_RCLK 10 +#define PIN_SRCLK 9 +#define PIN_SRCLR 8 + + +typedef void(*CubeEffects)(unsigned int frame); + + + +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); + } +}; + +class ShiftRegister { + public: + const byte _SER = B00010000; + const byte _OE = B00001000; + const byte _RCLK = B00000100; + const byte _SRCLK = B00000010; + const byte _SRCLR = B00000001; + + void reset() { + // Port B Pin 8 - 13 + //Serial.println("reset"); + DDRB |= _SER; // _SER als Output + DDRB |= _OE; // _OE als Output + DDRB |= _RCLK; // _RCLK als Output + DDRB |= _SRCLK; // _SRCLK als Output + DDRB |= _SRCLR; // _SRCLR als Output + + output_disable(); + clear_register(); + register_to_output(); + // Serial.println(PORTB); + } + + void output_enable() { + // OUTPUT für OE auf 0 setzen + PORTB &= ~_OE; // -> LOW + } + void output_disable() { + // OUTPUT für OE auf 1 setzen + PORTB |= _OE; //-> HIGH + } + void clear_register() { + PORTB |= _SRCLR; // -> HIGH + PORTB &= ~_SRCLK; // -> LOW + PORTB &= ~_RCLK; // -> LOW + PORTB &= ~_SRCLR; // -> LOW + PORTB &= ~_SRCLR; // -> LOW + PORTB |= _SRCLR; // -> HIGH + } + + void shift_bit(bool bit) { + //Serial.println("shift_bit " + (String)(bit)); + if (bit == LOW) { + PORTB &= ~_SER; // -> LOW + } else { + PORTB |= _SER; // -> HIGH + } + PORTB |= _SRCLK; // -> HIGH + PORTB &= ~_SRCLK; // -> LOW + }; + + void register_to_output() { + //Serial.println("register_to_output"); + // PORTB &= ~_RCLK; // -> LOW + PORTB |= _RCLK; // -> HIGH + //Serial.println(PORTB); + PORTB &= ~_RCLK; // -> LOW + // Serial.println(PORTB); + } +}; + +#define CUBESIZE 5 + +//ShiftRegisterSlow Register ; +ShiftRegister Register ; + + + +#define FPS 500 +#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) { + byte data = 0; + //Serial.print("Z "); + //Serial.println(layer); + 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++) { + // Serial.print(cube[layer][x][y]); + Register.shift_bit((cube[layer][x][y] > level)); + } + // Serial.println(); + } + 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)); + + //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[z][x][y] = random(LEDLEVEL + 1); + } + } + } + } +*/ + +void glow_cube(int duration) { + ende = millis() + duration * 1000; + int glow = 0; + while (millis() < ende) { + glow = ((ende - millis()) / 200) % (LEDLEVEL + 1); + for (byte x = 0; x < CUBESIZE; x++) { + for (byte y = 0; y < CUBESIZE; y++) { + for (byte z = 0; z < CUBESIZE; z++) { + cube[z][x][y] = glow; + } + } + } + delay(50); + } +} + +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++) { + cube[z][x][y] = random(LEDLEVEL + 1); + } + } + } + delay(100); + } +} + + +void glitzer_fade_cube(int duration) { + int cleanup = 5; + + for (byte x = 0; x < CUBESIZE; x++) { + for (byte y = 0; y < CUBESIZE; y++) { + for (byte z = 0; z < CUBESIZE; z++) { + cube[z][x][y] = 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[z][x][y] > 0) { + cube[z][x][y] --; + } + } + } + } + + } + } +} + + + +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[z][x][y] = 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(10)) { + case 0: + glow_cube(next_duration); + break; + case 1: + glitzer_cube(next_duration); + break; + case 2: + glitzer_fade_cube(next_duration); + 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 ++; +} diff --git a/tools/5x5x5 Bohrschablone (1,27cm).odg b/tools/5x5x5 Bohrschablone (1,27cm).odg new file mode 100644 index 0000000000000000000000000000000000000000..fbfc5b21260ad8e3c88ce7bc884bfe038ecc8a3a GIT binary patch literal 9140 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 E4_CEl$p8QV literal 0 HcmV?d00001 diff --git a/tools/Ebenen-Template.fcstd b/tools/Ebenen-Template.fcstd new file mode 100644 index 0000000000000000000000000000000000000000..364b6fcd34b0d04269484a7fc282ec1517f09e2f GIT binary patch literal 3324 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 A2><{9 literal 0 HcmV?d00001 diff --git a/tools/Ebenen-Template.fcstd1 b/tools/Ebenen-Template.fcstd1 new file mode 100644 index 0000000000000000000000000000000000000000..310b6dfe484aa828ae0fdd31145b830d0e57cb3a GIT binary patch literal 3324 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 literal 0 HcmV?d00001 From e78fde8057d2a0cb2d61c864548720f0338cbd06 Mon Sep 17 00:00:00 2001 From: Ingo Rohlf Date: Sat, 17 Aug 2024 12:43:15 +0200 Subject: [PATCH 2/3] Version 1 --- src/CubeRegister.cpp | 53 +++ src/CubeRegister.h | 73 ++++ src/LedCube555.ino_bak | 518 ++++++++++++++++++++++++ src/LedCube555.ino_rotate_todo | 626 ++++++++++++++++++++++++++++++ src/LedCube555_V1.ino | 518 ++++++++++++++++++++++++ src/Timer1.cpp | 169 ++++++++ src/Timer1.h | 112 ++++++ src/_5x5x5_Led_Cube (working).ino | 372 ------------------ 8 files changed, 2069 insertions(+), 372 deletions(-) create mode 100644 src/CubeRegister.cpp create mode 100644 src/CubeRegister.h create mode 100644 src/LedCube555.ino_bak create mode 100644 src/LedCube555.ino_rotate_todo create mode 100644 src/LedCube555_V1.ino create mode 100644 src/Timer1.cpp create mode 100644 src/Timer1.h delete mode 100644 src/_5x5x5_Led_Cube (working).ino diff --git a/src/CubeRegister.cpp b/src/CubeRegister.cpp new file mode 100644 index 0000000..fcd2419 --- /dev/null +++ b/src/CubeRegister.cpp @@ -0,0 +1,53 @@ +#include "CubeRegister.h" + +void CubeRegister::reset() { + // Port B Pin 8 - 13 + //Serial.println("reset"); + DDRB |= _SER; // _SER als Output + DDRB |= _OE; // _OE als Output + DDRB |= _RCLK; // _RCLK als Output + DDRB |= _SRCLK; // _SRCLK als Output + DDRB |= _SRCLR; // _SRCLR als Output + + output_disable(); + clear_register(); + register_to_output(); + // Serial.println(PORTB); +}; + +void CubeRegister::output_enable() { + // OUTPUT für OE auf 0 setzen + PORTB &= ~_OE; // -> LOW +}; +void CubeRegister::output_disable() { + // OUTPUT für OE auf 1 setzen + PORTB |= _OE; //-> HIGH +}; +void CubeRegister::clear_register() { + PORTB |= _SRCLR; // -> HIGH + PORTB &= ~_SRCLK; // -> LOW + PORTB &= ~_RCLK; // -> LOW + PORTB &= ~_SRCLR; // -> LOW + PORTB &= ~_SRCLR; // -> LOW + PORTB |= _SRCLR; // -> HIGH +}; + +void CubeRegister::shift_bit(bool bit) { + //Serial.println("shift_bit " + (String)(bit)); + if (bit == LOW) { + PORTB &= ~_SER; // -> LOW + } else { + PORTB |= _SER; // -> HIGH + } + PORTB |= _SRCLK; // -> HIGH + PORTB &= ~_SRCLK; // -> LOW +}; + +void CubeRegister::register_to_output() { + //Serial.println("register_to_output"); + // PORTB &= ~_RCLK; // -> LOW + PORTB |= _RCLK; // -> HIGH + //Serial.println(PORTB); + PORTB &= ~_RCLK; // -> LOW + // Serial.println(PORTB); +}; diff --git a/src/CubeRegister.h b/src/CubeRegister.h new file mode 100644 index 0000000..d3051ca --- /dev/null +++ b/src/CubeRegister.h @@ -0,0 +1,73 @@ + +#ifndef __CubeRegister__ +#define __CubeRegister__ +#include + +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 diff --git a/src/LedCube555.ino_bak b/src/LedCube555.ino_bak new file mode 100644 index 0000000..5ce5b06 --- /dev/null +++ b/src/LedCube555.ino_bak @@ -0,0 +1,518 @@ +#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; + + +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 ++; +} diff --git a/src/LedCube555.ino_rotate_todo b/src/LedCube555.ino_rotate_todo new file mode 100644 index 0000000..6db8d50 --- /dev/null +++ b/src/LedCube555.ino_rotate_todo @@ -0,0 +1,626 @@ +#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; + + +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; + }*/ + } + } + } +} + +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) { + 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("Vorne"); + y = 0; + for ( x = 1; x < CUBESIZE - 1; x++) { + Serial.println("x" + (String)(x - 1) + ",y" + (String)y + " <= " + "x" + (String)x + ",y" + (String)y); + cube[x][y][z] = cube[x - 1][y][z]; + }; + + // shift north-side y=0..max, x = max + Serial.println("Links"); + x = CUBESIZE - 1; + for (y = 1; y < CUBESIZE - 1; y++) { + Serial.println("x" + (String)(x) + ",y" + (String)(y - 1) + " <= " + "x" + (String)x + ",y" + (String)y); + cube[x][y][z] = cube[x][y - 1][z]; + } +/* + // shift east-side y=max, x=max..1 + Serial.println("Hinten"); + y = CUBESIZE - 1; + for (x = CUBESIZE - 1 ; x < 1 ; --x) { + Serial.println("x" + (String)(x + 1) + ",y" + (String)y + " <= " + "x" + (String)x + ",y" + (String)y); + cube[x][y][z] = cube[x][y][z]; + } + + x = 0; + Serial.println("Rechts"); + for (y = CUBESIZE - 1 ; y > 1; --y) { + Serial.println("x" + (String)(x) + ",y" + (String)(y + 1) + " <= " + "x" + (String)x + ",y" + (String)y); + cube[x][y][z] = cube[x][y - 1][z]; + } +*/ + Serial.println("Backup: x0,y1 <= " + (String)(backup)); + cube[0][1][z] = backup; + + } + delay(50); + } +}; + +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 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(8, 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; + + case 8: + write_char('g'); + + rotate_cube(20); + 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/LedCube555_V1.ino b/src/LedCube555_V1.ino new file mode 100644 index 0000000..5ce5b06 --- /dev/null +++ b/src/LedCube555_V1.ino @@ -0,0 +1,518 @@ +#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; + + +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 ++; +} diff --git a/src/Timer1.cpp b/src/Timer1.cpp new file mode 100644 index 0000000..b6eeadb --- /dev/null +++ b/src/Timer1.cpp @@ -0,0 +1,169 @@ +// +// 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 � 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 � 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 � AVR Status Register (page 14) + sreg = SREG; + // Disable interrupts + cli(); + // Write TCNTn + resetTimer1Unsafe(); + // Restore global interrupt flag + SREG = sreg; +} diff --git a/src/Timer1.h b/src/Timer1.h new file mode 100644 index 0000000..3f7516f --- /dev/null +++ b/src/Timer1.h @@ -0,0 +1,112 @@ +// +// 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 +// +#ifndef Timer1_h +#define Timer1_h + +// Reference documentation: +// http://www.atmel.com/devices/atmega2560.aspx +// http://www.atmel.com/devices/atmega328.aspx +// +// Timer 1 is available on ATmega168, ATmega328 and on ATmega2560 +// All other timers are only available on ATmega2560 +// +// (The page and chapter numbers refer to the ATmega2560 documentation) + +//********************************************************************************* +// ATmega168, ATmega328: Using Timer 1 disables PWM (analogWrite) on pins 9 and 10 +// ATmega2560: Using Timer 1 disables PWM (analogWrite) on pins 11 and 12 +//********************************************************************************* + +#include + +// 16.9.6 TIMSK0 � Timer/Counter Interrupt Mask Register (page 134) +#ifndef disableMillis +#define disableMillis() TIMSK0 &= ~1 +#endif +#ifndef enableMillis +#define enableMillis() TIMSK0 |= 1 +#endif +#ifndef microsFromCounting +#if (F_CPU == 16000000L) +#define microsFromCounting(COUNTING) ((COUNTING) << 2) +#elif (F_CPU == 8000000L) +#define microsFromCounting(COUNTING) ((COUNTING) << 3) +#else +#error("Unsupported CPU frequency") +#endif +#endif +#ifndef microsFromSlowCounting +#if (F_CPU == 16000000L) +#define microsFromSlowCounting(SLOWCOUNTING) ((SLOWCOUNTING) << 4) +#elif (F_CPU == 8000000L) +#define microsFromSlowCounting(SLOWCOUNTING) ((SLOWCOUNTING) << 5) +#else +#error("Unsupported CPU frequency") +#endif +#endif +#ifndef microsFromUltraSlowCounting +#if (F_CPU == 16000000L) +#define microsFromUltraSlowCounting(SLOWCOUNTING) ((SLOWCOUNTING) << 6) +#elif (F_CPU == 8000000L) +#define microsFromUltraSlowCounting(SLOWCOUNTING) ((SLOWCOUNTING) << 7) +#else +#error("Unsupported CPU frequency") +#endif +#endif + +extern uint8_t __timer1Control; +extern uint16_t __timer1CounterValue; +#define readTimer1Unsafe() TCNT1 +#define resetTimer1Unsafe() TCNT1 = __timer1CounterValue +#define pauseTimer1() TCCR1B = 0 +#define resumeTimer1() TCCR1B = __timer1Control +extern void startTimer1(uint32_t microsecondsInterval); +extern void startCountingTimer1(void); +extern void startSlowCountingTimer1(void); +extern void startUltraSlowCountingTimer1(void); +extern uint16_t readTimer1(void); +extern void resetTimer1(void); + +// 17.9.1 Normal Mode (page 149) +// The simplest mode of operation is the Normal mode (WGMn3:0 = 0). In this mode the counting +// direction is always up (incrementing), and no counter clear is performed. The counter simply +// overruns when it passes its maximum 16-bit value (MAX = 0xFFFF) and then restarts from the +// BOTTOM (0x0000). In normal operation the Timer/Counter Overflow Flag (TOVn) will be set in +// the same timer clock cycle as the TCNTn becomes zero. The TOVn Flag in this case behaves +// like a 17th bit, except that it is only set, not cleared. However, combined with the timer overflow +// interrupt that automatically clears the TOVn Flag, the timer resolution can be increased by software. +// There are no special cases to consider in the Normal mode, a new counter value can be +// written anytime. +#define timer1Event TIMER1_OVF_vect + +#endif diff --git a/src/_5x5x5_Led_Cube (working).ino b/src/_5x5x5_Led_Cube (working).ino deleted file mode 100644 index 7e8f3bb..0000000 --- a/src/_5x5x5_Led_Cube (working).ino +++ /dev/null @@ -1,372 +0,0 @@ -#include - -#define PIN_SER 12 -#define PIN_OE 11 -#define PIN_RCLK 10 -#define PIN_SRCLK 9 -#define PIN_SRCLR 8 - - -typedef void(*CubeEffects)(unsigned int frame); - - - -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); - } -}; - -class ShiftRegister { - public: - const byte _SER = B00010000; - const byte _OE = B00001000; - const byte _RCLK = B00000100; - const byte _SRCLK = B00000010; - const byte _SRCLR = B00000001; - - void reset() { - // Port B Pin 8 - 13 - //Serial.println("reset"); - DDRB |= _SER; // _SER als Output - DDRB |= _OE; // _OE als Output - DDRB |= _RCLK; // _RCLK als Output - DDRB |= _SRCLK; // _SRCLK als Output - DDRB |= _SRCLR; // _SRCLR als Output - - output_disable(); - clear_register(); - register_to_output(); - // Serial.println(PORTB); - } - - void output_enable() { - // OUTPUT für OE auf 0 setzen - PORTB &= ~_OE; // -> LOW - } - void output_disable() { - // OUTPUT für OE auf 1 setzen - PORTB |= _OE; //-> HIGH - } - void clear_register() { - PORTB |= _SRCLR; // -> HIGH - PORTB &= ~_SRCLK; // -> LOW - PORTB &= ~_RCLK; // -> LOW - PORTB &= ~_SRCLR; // -> LOW - PORTB &= ~_SRCLR; // -> LOW - PORTB |= _SRCLR; // -> HIGH - } - - void shift_bit(bool bit) { - //Serial.println("shift_bit " + (String)(bit)); - if (bit == LOW) { - PORTB &= ~_SER; // -> LOW - } else { - PORTB |= _SER; // -> HIGH - } - PORTB |= _SRCLK; // -> HIGH - PORTB &= ~_SRCLK; // -> LOW - }; - - void register_to_output() { - //Serial.println("register_to_output"); - // PORTB &= ~_RCLK; // -> LOW - PORTB |= _RCLK; // -> HIGH - //Serial.println(PORTB); - PORTB &= ~_RCLK; // -> LOW - // Serial.println(PORTB); - } -}; - -#define CUBESIZE 5 - -//ShiftRegisterSlow Register ; -ShiftRegister Register ; - - - -#define FPS 500 -#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) { - byte data = 0; - //Serial.print("Z "); - //Serial.println(layer); - 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++) { - // Serial.print(cube[layer][x][y]); - Register.shift_bit((cube[layer][x][y] > level)); - } - // Serial.println(); - } - 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)); - - //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[z][x][y] = random(LEDLEVEL + 1); - } - } - } - } -*/ - -void glow_cube(int duration) { - ende = millis() + duration * 1000; - int glow = 0; - while (millis() < ende) { - glow = ((ende - millis()) / 200) % (LEDLEVEL + 1); - for (byte x = 0; x < CUBESIZE; x++) { - for (byte y = 0; y < CUBESIZE; y++) { - for (byte z = 0; z < CUBESIZE; z++) { - cube[z][x][y] = glow; - } - } - } - delay(50); - } -} - -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++) { - cube[z][x][y] = random(LEDLEVEL + 1); - } - } - } - delay(100); - } -} - - -void glitzer_fade_cube(int duration) { - int cleanup = 5; - - for (byte x = 0; x < CUBESIZE; x++) { - for (byte y = 0; y < CUBESIZE; y++) { - for (byte z = 0; z < CUBESIZE; z++) { - cube[z][x][y] = 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[z][x][y] > 0) { - cube[z][x][y] --; - } - } - } - } - - } - } -} - - - -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[z][x][y] = 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(10)) { - case 0: - glow_cube(next_duration); - break; - case 1: - glitzer_cube(next_duration); - break; - case 2: - glitzer_fade_cube(next_duration); - 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 ++; -} From 36d9ac17e2e2cc4f90e4c3b9ac26c1c03c7a6ecf Mon Sep 17 00:00:00 2001 From: Ingo Rohlf Date: Sat, 17 Aug 2024 12:43:47 +0200 Subject: [PATCH 3/3] Version 2 --- src/LedCube555_V1.ino | 518 ------------------ ...edCube555.ino_bak => LedCube555_V1.ino_V1} | 0 ...e555.ino_rotate_todo => LedCube555_V2.ino} | 300 +++++----- 3 files changed, 171 insertions(+), 647 deletions(-) delete mode 100644 src/LedCube555_V1.ino rename src/{LedCube555.ino_bak => LedCube555_V1.ino_V1} (100%) rename src/{LedCube555.ino_rotate_todo => LedCube555_V2.ino} (69%) diff --git a/src/LedCube555_V1.ino b/src/LedCube555_V1.ino deleted file mode 100644 index 5ce5b06..0000000 --- a/src/LedCube555_V1.ino +++ /dev/null @@ -1,518 +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; - - -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 ++; -} diff --git a/src/LedCube555.ino_bak b/src/LedCube555_V1.ino_V1 similarity index 100% rename from src/LedCube555.ino_bak rename to src/LedCube555_V1.ino_V1 diff --git a/src/LedCube555.ino_rotate_todo b/src/LedCube555_V2.ino similarity index 69% rename from src/LedCube555.ino_rotate_todo rename to src/LedCube555_V2.ino index 6db8d50..be3f7ef 100644 --- a/src/LedCube555.ino_rotate_todo +++ b/src/LedCube555_V2.ino @@ -25,35 +25,6 @@ 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++) { @@ -188,58 +159,136 @@ void rotate_ac_cube(int steps) { }; -void rotate_cube(int steps) { +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 (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("Vorne"); - y = 0; - for ( x = 1; x < CUBESIZE - 1; x++) { - Serial.println("x" + (String)(x - 1) + ",y" + (String)y + " <= " + "x" + (String)x + ",y" + (String)y); - cube[x][y][z] = cube[x - 1][y][z]; + // 0,0 -> 0,4 : v + x = 0; + for (y = 1; y < CUBESIZE ; y++) { + cube[x][y - 1][z] = cube[x][y][z]; }; - // shift north-side y=0..max, x = max - Serial.println("Links"); + y = CUBESIZE - 1; + for (x = 1; x < CUBESIZE ; x++) { + cube[x - 1][y][z] = cube[x][y][z]; + } + x = CUBESIZE - 1; - for (y = 1; y < CUBESIZE - 1; y++) { - Serial.println("x" + (String)(x) + ",y" + (String)(y - 1) + " <= " + "x" + (String)x + ",y" + (String)y); - cube[x][y][z] = cube[x][y - 1][z]; - } -/* - // shift east-side y=max, x=max..1 - Serial.println("Hinten"); - y = CUBESIZE - 1; - for (x = CUBESIZE - 1 ; x < 1 ; --x) { - Serial.println("x" + (String)(x + 1) + ",y" + (String)y + " <= " + "x" + (String)x + ",y" + (String)y); - cube[x][y][z] = cube[x][y][z]; + for (y = CUBESIZE - 2 ; y < CUBESIZE ; --y) { + cube[x][y + 1][z] = cube[x][y][z] ; } - x = 0; - Serial.println("Rechts"); - for (y = CUBESIZE - 1 ; y > 1; --y) { - Serial.println("x" + (String)(x) + ",y" + (String)(y + 1) + " <= " + "x" + (String)x + ",y" + (String)y); - cube[x][y][z] = cube[x][y - 1][z]; + y = 0 ; + for (x = CUBESIZE - 2 ; x < CUBESIZE ; --x) { + cube[x + 1][y][z] = cube[x][y][z]; } -*/ - Serial.println("Backup: x0,y1 <= " + (String)(backup)); - cube[0][1][z] = backup; - + cube[1][0][z] = backup; } - delay(50); + delay(frame_delay); } }; -const unsigned long CHAR_5BIT[42] = { + + +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 @@ -282,9 +331,9 @@ const unsigned long CHAR_5BIT[42] = { 0B0000000000000000000000100, // 39 POINT (46) 0B0000000000000000010001000, // 40 COMMA (44) 0B0000001010111110111000100 // 41 @ -> Herz (44) -}; - -unsigned long char_to_5bits(char zeichen) { + }; +*/ +unsigned long char_to_5bits__(char zeichen) { // special chars switch (zeichen) { case 32: return CHAR_5BIT[36]; @@ -328,6 +377,40 @@ void write_char(char zeichen, int ebene = 0, byte brightness = LEDLEVEL) { } } +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) { @@ -343,6 +426,7 @@ void hello_cube(int duration) { } delay(200); } + fill_cube(0); } void text_cube(const char *message) { @@ -358,6 +442,7 @@ void text_cube(const char *message) { delay(200); } + fill_cube(0); } void glow_cube(int duration) { @@ -499,13 +584,7 @@ void dots_cube(int duration) { for (byte z = 1; z < CUBESIZE - 1; z++) { cube[x][y][z] = 0; } - - - - } - - } void template_cube(int duration) { @@ -517,55 +596,13 @@ void template_cube(int duration) { } } -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); - } -} - +// 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(5, 10); - switch (random(8, 10)) { + int next_duration = random(10, 20); + switch (random(0, 10)) { case 0: glow_cube(next_duration); break; @@ -581,21 +618,26 @@ void loop() { case 4: dots_cube(next_duration); break; - case 5: - text_cube("i@u"); - break; + case 6: - text_cube("benjamin"); + banner_cube(messages[random(message_count)]); break; case 7: - text_cube("annika"); + text_cube(messages[random(message_count)]); break; - +/* case 8: - write_char('g'); + if (random(10) > 5) + text_cube("LED-Cube 5*5*5"); + else + banner_cube("LED-Cube 5*5*5 "); - rotate_cube(20); - fill_cube(0); +*/ + /*write_char('v', 0); + write_char('x', 4); + + rotate_cube(10); + fill_cube(0);*/ }