Last active
December 24, 2015 01:59
-
-
Save c00kiemon5ter/6727747 to your computer and use it in GitHub Desktop.
Revisions
-
c00kiemon5ter revised this gist
Sep 27, 2013 . 1 changed file with 3 additions and 11 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -76,17 +76,9 @@ static void check_mcp(void) { else Serial.println("done\n"); } static void print_gpio_state(const byte gpio) { Serial.print("gpio state: "); Serial.println(gpio, BIN); } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ -
c00kiemon5ter revised this gist
Sep 27, 2013 . No changes.There are no files selected for viewing
-
c00kiemon5ter created this gist
Sep 27, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,340 @@ /* Cube project throug mcp23017 */ #include <Wire.h> static const byte MCP_ADDR = 0x20; // I2C Address of MCP23017 Chip static const byte GPIO_A = 0x12; // Register Address of Port A static const byte GPIO_B = 0x13; // Register Address of Port B /* global state of gpio ports */ static byte gpio_a; static byte gpio_b; /* Working with a 3x3 Cube */ static const unsigned CUBE_SIDE = 3; /* each pin belongs in a bank and has a mask */ struct pin { const byte gpio; const byte mask; }; /* 3 Levels of 3x3=9 leds each */ static const struct pin LVL_0 = { GPIO_B, 0b00000001 }; static const struct pin LVL_1 = { GPIO_B, 0b00000100 }; static const struct pin LVL_2 = { GPIO_B, 0b00000010 }; static const struct pin levels[CUBE_SIDE] = { LVL_0, LVL_1, LVL_2 }; /* 3x3=9 columns in a grid - COL_<y><x> */ static const struct pin COL_00 = { GPIO_B, 0b00100000 }; static const struct pin COL_01 = { GPIO_B, 0b00001000 }; static const struct pin COL_02 = { GPIO_B, 0b00010000 }; static const struct pin COL_10 = { GPIO_A, 0b00000100 }; static const struct pin COL_11 = { GPIO_A, 0b00010000 }; static const struct pin COL_12 = { GPIO_A, 0b00001000 }; static const struct pin COL_20 = { GPIO_A, 0b00100000 }; static const struct pin COL_21 = { GPIO_A, 0b01000000 }; static const struct pin COL_22 = { GPIO_A, 0b10000000 }; static const pin columns[CUBE_SIDE][CUBE_SIDE] = { { COL_00, COL_01, COL_02 }, { COL_10, COL_11, COL_12 }, { COL_20, COL_21, COL_22 }, }; /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ /* DEBUG HELPERS */ /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ static void check_mcp(void) { byte error, address; int nDevices; Serial.println("Scanning for I2C..."); nDevices = 0; for(address = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); nDevices++; } else if (error == 4) { Serial.print("Unknow error at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); } static void print_gpio_a_state(void) { Serial.print("gpioa state: "); Serial.println(gpio_a, BIN); } static void print_gpio_b_state(void) { Serial.print("gpiob state: "); Serial.println(gpio_b, BIN); } static void print_gpio_state(void) { print_gpio_a_state(); print_gpio_b_state(); } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ /* INIT STATE */ /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ void setup(void) { Wire.begin(); Serial.begin(9600); Wire.beginTransmission(MCP_ADDR); Wire.write(0b00000000); Wire.write(0b00000000); // set all of GPIO A to outputs Wire.write(0b00000000); // set all of GPIO B to outputs Wire.endTransmission(); /* clear all GPIO A pins */ Wire.beginTransmission(MCP_ADDR); Wire.write(GPIO_A); Wire.write(0b00000000); Wire.endTransmission(); /* clear all GPIO B pins */ Wire.beginTransmission(MCP_ADDR); Wire.write(GPIO_B); Wire.write(0b00000000); Wire.endTransmission(); /* initialize randomizer */ randomSeed(analogRead(0)); } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ /* MAIN EXECUTION */ /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ static inline const byte bit_clear(byte * const gpio, const struct pin pin) { return (*gpio &= ~pin.mask); } static inline const byte bit_set (byte * const gpio, const struct pin pin) { return (*gpio |= pin.mask); } static const byte (* const operation[2])(byte * const gpio, const struct pin pin) = { bit_clear, bit_set }; static void set_pin(const struct pin pin, const bool state) { Wire.beginTransmission(MCP_ADDR); Wire.write(pin.gpio); switch (pin.gpio) { case GPIO_A: Wire.write((operation[state](&gpio_a, pin))); break; case GPIO_B: Wire.write((operation[state](&gpio_b, pin))); break; } Wire.endTransmission(); } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ static void set_led(const unsigned z, const unsigned y, const unsigned x, const bool state) { set_pin(levels[z], state); set_pin(columns[y][x], state); } static void set_all_lvls(const bool state) { for (unsigned lvl=0; lvl<CUBE_SIDE; ++lvl) set_pin(levels[lvl], state); } static void set_all_cols(const bool state) { for (unsigned y=0; y<CUBE_SIDE; ++y) for (unsigned x=0; x<CUBE_SIDE; ++x) set_pin(columns[y][x], state); } static void set_all(const bool state) { set_all_lvls(state); set_all_cols(state); } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ static void blink_all(const unsigned d = 500) { set_all(HIGH); delay(d); set_all(LOW); delay(d); } static void zig_zag(const unsigned d = 500) { const struct pin order[CUBE_SIDE * CUBE_SIDE] = { COL_00, COL_01, COL_02, COL_12, COL_11, COL_10, COL_20, COL_21, COL_22, }; set_all_cols(LOW); set_all_lvls(HIGH); for (unsigned col=0; col<CUBE_SIDE*CUBE_SIDE; ++col) { set_pin(order[col], HIGH); delay(d); } } static void spin(const unsigned d = 500) { const struct { struct pin led[CUBE_SIDE]; } order[CUBE_SIDE+1] = { { { COL_10, COL_11, COL_12 } }, { { COL_00, COL_11, COL_22 } }, { { COL_01, COL_11, COL_21 } }, { { COL_02, COL_11, COL_20 } }, }; set_all_lvls(HIGH); for (unsigned i = 0; i<CUBE_SIDE+1; ++i) { for (unsigned l = 0; l<CUBE_SIDE; ++l) set_pin(order[i].led[l], HIGH); delay(d); for (unsigned l = 0; l<CUBE_SIDE; ++l) set_pin(order[i].led[l], LOW); } } static void spin_outer(const unsigned d = 500) { const struct { struct pin led[2]; } order[CUBE_SIDE+1] = { { { COL_10, COL_12 } }, { { COL_00, COL_22 } }, { { COL_01, COL_21 } }, { { COL_02, COL_20 } }, }; set_all_lvls(HIGH); for (unsigned i = 0; i<CUBE_SIDE+1; ++i) { for (unsigned l=0; l<2; ++l) set_pin(order[i].led[l], HIGH); delay(d); for (unsigned l=0; l<2; ++l) set_pin(order[i].led[l], LOW); } } static void rain(const unsigned d = 500) { for (unsigned i=0; i<CUBE_SIDE*CUBE_SIDE; ++i) { long x1 = random(CUBE_SIDE); long y1 = random(CUBE_SIDE); long x2 = random(CUBE_SIDE); long y2 = random(CUBE_SIDE); for (int lvl=CUBE_SIDE-1; lvl>=0; --lvl) { set_pin(levels[lvl], HIGH); set_pin(columns[y1][x1], HIGH); set_pin(columns[y2][x2], HIGH); delay(d); set_pin(levels[lvl], LOW); set_pin(columns[y1][x1], LOW); set_pin(columns[y2][x2], LOW); } } } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ static void set_slice(const unsigned slice, const char axis, const uint8_t state) { switch (axis) { case 'x': set_all_lvls(state); for (unsigned x=0; x<CUBE_SIDE; ++x) set_pin(columns[slice][x], state); break; case 'y': set_all_lvls(state); for (unsigned y=0; y<CUBE_SIDE; ++y) set_pin(columns[y][slice], state); break; case 'z': set_all_cols(state); set_pin(levels[slice], state); break; } } static void cube_slices(const unsigned d = 500) { for (char *p = "xyz"; *p; ++p) { for (unsigned slice=0; slice<CUBE_SIDE; ++slice) { set_slice(slice, *p, HIGH); delay(d); set_slice(slice, *p, LOW); } } } static void up_down(const unsigned d = 500) { const unsigned lvl_order[CUBE_SIDE+1] = { 0, 1, 2, 1, }; /* light all columns */ set_all_cols(HIGH); set_all_lvls(LOW); /* light each level in order */ for (unsigned lvl=0; lvl<CUBE_SIDE+1; ++lvl) { set_slice(lvl_order[(CUBE_SIDE+lvl)%(CUBE_SIDE+1)], 'z', LOW); set_slice(lvl_order[lvl], 'z', HIGH); delay(d); } } static void cube_sides(const unsigned d = 500) { const struct { unsigned slice; char axis; } order[CUBE_SIDE*2] = { {0, 'x'}, {0, 'y'}, {2, 'z'}, {2, 'x'}, {2, 'y'}, {0, 'z'}, }; set_all(LOW); for (unsigned i=0; i<CUBE_SIDE*2; ++i) { set_slice(order[i].slice, order[i].axis, HIGH); delay(d); set_slice(order[i].slice, order[i].axis, LOW); } } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ void loop(void) { static const unsigned fast = 150; static const unsigned norm = 400; static const unsigned slow = 600; static struct effect { const unsigned repeat; void (* const effect)(const unsigned interval); const unsigned interval; } effects[] = { { 2, blink_all, slow }, { 3, blink_all, norm }, { 5, blink_all, fast }, { 2, cube_slices, norm }, { 3, up_down, norm }, { 2, cube_sides, norm }, { 3, zig_zag, fast }, { 6, spin, fast }, { 5, spin_outer, fast }, { 4, rain, fast }, /* -- end of effects -- */ { 0, NULL, 0 }, }; for (struct effect *e = effects; e; ++e) for (unsigned i=0; i<e->repeat; ++i) e->effect(e->interval); } -
grobotronics renamed this gist
Sep 16, 2013 . 1 changed file with 40 additions and 57 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -99,23 +99,21 @@ void setup(void) Serial.begin(9600); Wire.beginTransmission(MCP_ADDR); Wire.write(0b00000000); Wire.write(0b00000000); // set all of GPIO A to outputs Wire.write(0b00000000); // set all of GPIO B to outputs Wire.endTransmission(); /* clear all GPIO A pins */ Wire.beginTransmission(MCP_ADDR); Wire.write(GPIO_A); Wire.write(0b00000000); Wire.endTransmission(); /* clear all GPIO B pins */ Wire.beginTransmission(MCP_ADDR); Wire.write(GPIO_B); Wire.write(0b00000000); Wire.endTransmission(); /* initialize randomizer */ @@ -189,73 +187,58 @@ static void zig_zag(const unsigned d = 500) { static void spin(const unsigned d = 500) { const struct { struct pin led[CUBE_SIDE]; } order[CUBE_SIDE+1] = { { { COL_10, COL_11, COL_12 } }, { { COL_00, COL_11, COL_22 } }, { { COL_01, COL_11, COL_21 } }, { { COL_02, COL_11, COL_20 } }, }; set_all_lvls(HIGH); for (unsigned i = 0; i<CUBE_SIDE+1; ++i) { for (unsigned l = 0; l<CUBE_SIDE; ++l) set_pin(order[i].led[l], HIGH); delay(d); for (unsigned l = 0; l<CUBE_SIDE; ++l) set_pin(order[i].led[l], LOW); } } static void spin_outer(const unsigned d = 500) { const struct { struct pin led[2]; } order[CUBE_SIDE+1] = { { { COL_10, COL_12 } }, { { COL_00, COL_22 } }, { { COL_01, COL_21 } }, { { COL_02, COL_20 } }, }; set_all_lvls(HIGH); for (unsigned i = 0; i<CUBE_SIDE+1; ++i) { for (unsigned l=0; l<2; ++l) set_pin(order[i].led[l], HIGH); delay(d); for (unsigned l=0; l<2; ++l) set_pin(order[i].led[l], LOW); } } static void rain(const unsigned d = 500) { for (unsigned i=0; i<CUBE_SIDE*CUBE_SIDE; ++i) { long x1 = random(CUBE_SIDE); long y1 = random(CUBE_SIDE); long x2 = random(CUBE_SIDE); long y2 = random(CUBE_SIDE); for (int lvl=CUBE_SIDE-1; lvl>=0; --lvl) { set_pin(levels[lvl], HIGH); set_pin(columns[y1][x1], HIGH); set_pin(columns[y2][x2], HIGH); delay(d); set_pin(levels[lvl], LOW); set_pin(columns[y1][x1], LOW); set_pin(columns[y2][x2], LOW); } } } @@ -341,7 +324,7 @@ void loop(void) { 3, blink_all, norm }, { 5, blink_all, fast }, { 2, cube_slices, norm }, { 3, up_down, norm }, { 2, cube_sides, norm }, { 3, zig_zag, fast }, { 6, spin, fast }, @@ -351,7 +334,7 @@ void loop(void) { 0, NULL, 0 }, }; for (struct effect *e = effects; e; ++e) for (unsigned i=0; i<e->repeat; ++i) e->effect(e->interval); } -
grobotronics revised this gist
Sep 16, 2013 . 1 changed file with 45 additions and 34 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,7 +14,7 @@ static const unsigned CUBE_SIDE = 3; /* each pin belongs in a bank and has a mask */ struct pin { const byte gpio; const byte mask; }; @@ -46,7 +46,7 @@ static const pin columns[CUBE_SIDE][CUBE_SIDE] = { /* DEBUG HELPERS */ /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ static void check_mcp(void) { byte error, address; int nDevices; @@ -76,15 +76,15 @@ void check_mcp(void) { else Serial.println("done\n"); } static void print_gpio_a_state(void) { Serial.print("gpioa state: "); Serial.println(gpio_a, BIN); } static void print_gpio_b_state(void) { Serial.print("gpiob state: "); Serial.println(gpio_b, BIN); } static void print_gpio_state(void) { print_gpio_a_state(); print_gpio_b_state(); } @@ -142,36 +142,36 @@ static void set_pin(const struct pin pin, const bool state) { /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ static void set_led(const unsigned z, const unsigned y, const unsigned x, const bool state) { set_pin(levels[z], state); set_pin(columns[y][x], state); } static void set_all_lvls(const bool state) { for (unsigned lvl=0; lvl<CUBE_SIDE; ++lvl) set_pin(levels[lvl], state); } static void set_all_cols(const bool state) { for (unsigned y=0; y<CUBE_SIDE; ++y) for (unsigned x=0; x<CUBE_SIDE; ++x) set_pin(columns[y][x], state); } static void set_all(const bool state) { set_all_lvls(state); set_all_cols(state); } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ static void blink_all(const unsigned d = 500) { set_all(HIGH); delay(d); set_all(LOW); delay(d); } static void zig_zag(const unsigned d = 500) { const struct pin order[CUBE_SIDE * CUBE_SIDE] = { COL_00, COL_01, COL_02, COL_12, COL_11, COL_10, @@ -187,7 +187,7 @@ void zig_zag(const unsigned d = 500) { } } static void spin(const unsigned d = 500) { const struct { struct { unsigned y; @@ -215,7 +215,7 @@ void spin(const unsigned d = 500) { } } static void spin_outer(const unsigned d = 500) { const struct { struct { unsigned y; @@ -241,7 +241,7 @@ void spin_outer(const unsigned d = 500) { } } static void rain(const unsigned d = 500) { for (unsigned i=0; i<CUBE_SIDE*CUBE_SIDE; ++i) { long x1 = random(CUBE_SIDE); long y1 = random(CUBE_SIDE); @@ -262,7 +262,7 @@ void rain(const unsigned d = 500) { /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ static void set_slice(const unsigned slice, const char axis, const uint8_t state) { switch (axis) { case 'x': set_all_lvls(state); @@ -281,7 +281,7 @@ void set_slice(const unsigned slice, const char axis, const uint8_t state) { } } static void cube_slices(const unsigned d = 500) { for (char *p = "xyz"; *p; ++p) { for (unsigned slice=0; slice<CUBE_SIDE; ++slice) { set_slice(slice, *p, HIGH); @@ -291,23 +291,22 @@ void light_each_slice(const unsigned d = 500) { } } static void up_down(const unsigned d = 500) { const unsigned lvl_order[CUBE_SIDE+1] = { 0, 1, 2, 1, }; /* light all columns */ set_all_cols(HIGH); set_all_lvls(LOW); /* light each level in order */ for (unsigned lvl=0; lvl<CUBE_SIDE+1; ++lvl) { set_slice(lvl_order[(CUBE_SIDE+lvl)%(CUBE_SIDE+1)], 'z', LOW); set_slice(lvl_order[lvl], 'z', HIGH); delay(d); } } static void cube_sides(const unsigned d = 500) { const struct { unsigned slice; char axis; @@ -329,18 +328,30 @@ void cube_sides(const unsigned d = 500) { void loop(void) { static const unsigned fast = 150; static const unsigned norm = 400; static const unsigned slow = 600; static struct effect { const unsigned repeat; void (* const effect)(const unsigned interval); const unsigned interval; } effects[] = { { 2, blink_all, slow }, { 3, blink_all, norm }, { 5, blink_all, fast }, { 2, cube_slices, norm }, { 5, up_down, norm }, { 2, cube_sides, norm }, { 3, zig_zag, fast }, { 6, spin, fast }, { 5, spin_outer, fast }, { 4, rain, fast }, /* -- end of effects -- */ { 0, NULL, 0 }, }; for (struct effect *e = effects; e; ++e) for (unsigned i=0; i<e->repeat; ++i) e->effect(e->interval); } -
grobotronics created this gist
Sep 16, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,346 @@ /* Cube project throug mcp23017 */ #include <Wire.h> static const byte MCP_ADDR = 0x20; // I2C Address of MCP23017 Chip static const byte GPIO_A = 0x12; // Register Address of Port A static const byte GPIO_B = 0x13; // Register Address of Port B /* global state of gpio ports */ static byte gpio_a; static byte gpio_b; /* Working with a 3x3 Cube */ static const unsigned CUBE_SIDE = 3; /* each pin belongs in a bank and has a mask */ struct pin { const byte gpio; const byte mask; }; /* 3 Levels of 3x3=9 leds each */ static const struct pin LVL_0 = { GPIO_B, 0b00000001 }; static const struct pin LVL_1 = { GPIO_B, 0b00000100 }; static const struct pin LVL_2 = { GPIO_B, 0b00000010 }; static const struct pin levels[CUBE_SIDE] = { LVL_0, LVL_1, LVL_2 }; /* 3x3=9 columns in a grid - COL_<y><x> */ static const struct pin COL_00 = { GPIO_B, 0b00100000 }; static const struct pin COL_01 = { GPIO_B, 0b00001000 }; static const struct pin COL_02 = { GPIO_B, 0b00010000 }; static const struct pin COL_10 = { GPIO_A, 0b00000100 }; static const struct pin COL_11 = { GPIO_A, 0b00010000 }; static const struct pin COL_12 = { GPIO_A, 0b00001000 }; static const struct pin COL_20 = { GPIO_A, 0b00100000 }; static const struct pin COL_21 = { GPIO_A, 0b01000000 }; static const struct pin COL_22 = { GPIO_A, 0b10000000 }; static const pin columns[CUBE_SIDE][CUBE_SIDE] = { { COL_00, COL_01, COL_02 }, { COL_10, COL_11, COL_12 }, { COL_20, COL_21, COL_22 }, }; /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ /* DEBUG HELPERS */ /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ void check_mcp(void) { byte error, address; int nDevices; Serial.println("Scanning for I2C..."); nDevices = 0; for(address = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); nDevices++; } else if (error == 4) { Serial.print("Unknow error at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); } void print_gpio_a_state(void) { Serial.print("gpioa state: "); Serial.println(gpio_a, BIN); } void print_gpio_b_state(void) { Serial.print("gpiob state: "); Serial.println(gpio_b, BIN); } void print_gpio_state(void) { print_gpio_a_state(); print_gpio_b_state(); } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ /* INIT STATE */ /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ void setup(void) { Wire.begin(); Serial.begin(9600); Wire.beginTransmission(MCP_ADDR); Wire.write((byte)0x00); Wire.write((byte)0x00); // set all of GPIO A to outputs Wire.write((byte)0x00); // set all of GPIO B to outputs Wire.endTransmission(); /* clear all GPIOA pins */ gpio_a = 0b00000000; Wire.beginTransmission(MCP_ADDR); Wire.write(GPIO_A); Wire.write(gpio_a); Wire.endTransmission(); /* clear all GPIOB pins */ gpio_b = 0b00000000; Wire.beginTransmission(MCP_ADDR); Wire.write(GPIO_B); Wire.write(gpio_b); Wire.endTransmission(); /* initialize randomizer */ randomSeed(analogRead(0)); } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ /* MAIN EXECUTION */ /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ static inline const byte bit_clear(byte * const gpio, const struct pin pin) { return (*gpio &= ~pin.mask); } static inline const byte bit_set (byte * const gpio, const struct pin pin) { return (*gpio |= pin.mask); } static const byte (* const operation[2])(byte * const gpio, const struct pin pin) = { bit_clear, bit_set }; static void set_pin(const struct pin pin, const bool state) { Wire.beginTransmission(MCP_ADDR); Wire.write(pin.gpio); switch (pin.gpio) { case GPIO_A: Wire.write((operation[state](&gpio_a, pin))); break; case GPIO_B: Wire.write((operation[state](&gpio_b, pin))); break; } Wire.endTransmission(); } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ void set_led(const unsigned z, const unsigned y, const unsigned x, const bool state) { set_pin(levels[z], state); set_pin(columns[y][x], state); } void set_all_lvls(const bool state) { for (unsigned lvl=0; lvl<CUBE_SIDE; ++lvl) set_pin(levels[lvl], state); } void set_all_cols(const bool state) { for (unsigned y=0; y<CUBE_SIDE; ++y) for (unsigned x=0; x<CUBE_SIDE; ++x) set_pin(columns[y][x], state); } void set_all(const bool state) { set_all_lvls(state); set_all_cols(state); } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ void blink_all(const unsigned d = 500) { set_all(HIGH); delay(d); set_all(LOW); delay(d); } void zig_zag(const unsigned d = 500) { const struct pin order[CUBE_SIDE * CUBE_SIDE] = { COL_00, COL_01, COL_02, COL_12, COL_11, COL_10, COL_20, COL_21, COL_22, }; set_all_cols(LOW); set_all_lvls(HIGH); for (unsigned col=0; col<CUBE_SIDE*CUBE_SIDE; ++col) { set_pin(order[col], HIGH); delay(d); } } void spin(const unsigned d = 500) { const struct { struct { unsigned y; unsigned x; } led_cords[3]; } order[CUBE_SIDE+1] = { { { {1,0}, {1,1}, {1,2} } }, { { {0,0}, {1,1}, {2,2} } }, { { {2,1}, {1,1}, {0,1} } }, { { {2,0}, {1,1}, {0,2} } } }; for (unsigned i = 0; i<CUBE_SIDE+1; ++i) { for (unsigned lvl=0; lvl<CUBE_SIDE; ++lvl) { set_led(lvl, order[i].led_cords[0].y, order[i].led_cords[0].x, HIGH); set_led(lvl, order[i].led_cords[1].y, order[i].led_cords[1].x, HIGH); set_led(lvl, order[i].led_cords[2].y, order[i].led_cords[2].x, HIGH); } delay(d); for (unsigned lvl=0; lvl<CUBE_SIDE; ++lvl) { set_led(lvl, order[i].led_cords[0].y, order[i].led_cords[0].x, LOW); set_led(lvl, order[i].led_cords[1].y, order[i].led_cords[1].x, LOW); set_led(lvl, order[i].led_cords[2].y, order[i].led_cords[2].x, LOW); } } } void spin_outer(const unsigned d = 500) { const struct { struct { unsigned y; unsigned x; } led_cords[2]; } order[CUBE_SIDE+1] = { { { {1,0}, {1,2} } }, { { {0,0}, {2,2} } }, { { {2,1}, {0,1} } }, { { {2,0}, {0,2} } } }; for (unsigned i = 0; i<CUBE_SIDE+1; ++i) { for (unsigned lvl=0; lvl<CUBE_SIDE; ++lvl) { set_led(lvl, order[i].led_cords[0].y, order[i].led_cords[0].x, HIGH); set_led(lvl, order[i].led_cords[1].y, order[i].led_cords[1].x, HIGH); } delay(d); for (unsigned lvl=0; lvl<CUBE_SIDE; ++lvl) { set_led(lvl, order[i].led_cords[0].y, order[i].led_cords[0].x, LOW); set_led(lvl, order[i].led_cords[1].y, order[i].led_cords[1].x, LOW); } } } void rain(const unsigned d = 500) { for (unsigned i=0; i<CUBE_SIDE*CUBE_SIDE; ++i) { long x1 = random(CUBE_SIDE); long y1 = random(CUBE_SIDE); long x2 = random(CUBE_SIDE); long y2 = random(CUBE_SIDE); for (int lvl=CUBE_SIDE-1; lvl>=0; --lvl) { set_pin(levels[lvl], HIGH); set_pin(columns[y1][x1], HIGH); set_pin(columns[y2][x2], HIGH); delay(d); set_pin(levels[lvl], LOW); set_pin(columns[y1][x1], LOW); set_pin(columns[y2][x2], LOW); } } } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ void set_slice(const unsigned slice, const char axis, const uint8_t state) { switch (axis) { case 'x': set_all_lvls(state); for (unsigned x=0; x<CUBE_SIDE; ++x) set_pin(columns[slice][x], state); break; case 'y': set_all_lvls(state); for (unsigned y=0; y<CUBE_SIDE; ++y) set_pin(columns[y][slice], state); break; case 'z': set_all_cols(state); set_pin(levels[slice], state); break; } } void light_each_slice(const unsigned d = 500) { for (char *p = "xyz"; *p; ++p) { for (unsigned slice=0; slice<CUBE_SIDE; ++slice) { set_slice(slice, *p, HIGH); delay(d); set_slice(slice, *p, LOW); } } } void up_down(const unsigned d = 500, unsigned loops = 12) { const unsigned lvl_order[CUBE_SIDE+1] = { 0, 1, 2, 1, }; /* light all columns */ set_all_cols(HIGH); set_all_lvls(LOW); /* light each level in order */ for (unsigned lvl = 0; loops>0; --loops) { set_slice(lvl_order[(CUBE_SIDE+lvl)%(CUBE_SIDE+1)], 'z', LOW); set_slice(lvl_order[lvl], 'z', HIGH); lvl = (lvl + 1) % (CUBE_SIDE+1); delay(d); } } void cube_sides(const unsigned d = 500) { const struct { unsigned slice; char axis; } order[CUBE_SIDE*2] = { {0, 'x'}, {0, 'y'}, {2, 'z'}, {2, 'x'}, {2, 'y'}, {0, 'z'}, }; set_all(LOW); for (unsigned i=0; i<CUBE_SIDE*2; ++i) { set_slice(order[i].slice, order[i].axis, HIGH); delay(d); set_slice(order[i].slice, order[i].axis, LOW); } } /* --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- */ void loop(void) { const unsigned fast = 150; const unsigned norm = 400; const unsigned slow = 600; for (unsigned i=0; i<2; ++i) blink_all(slow); for (unsigned i=0; i<3; ++i) blink_all(norm); for (unsigned i=0; i<5; ++i) blink_all(fast); for (unsigned i=0; i<2; ++i) light_each_slice(norm); for (unsigned i=0; i<1; ++i) up_down(norm); for (unsigned i=0; i<2; ++i) cube_sides(norm); for (unsigned i=0; i<3; ++i) zig_zag(fast); for (unsigned i=0; i<6; ++i) spin(fast); for (unsigned i=0; i<5; ++i) spin_outer(fast); for (unsigned i=0; i<4; ++i) rain(fast); }