Table of contents
Abstract
This is an incredible LED Christmas Tree I made by Charlieplexing 206 LEDs. For driving the LEDs I used just an Arduino Nano. No driver IC, transistors, or resistors are used in the project. So, the circuit is very straightforward. For arranging the LEDs I laser cut an acrylic sheet and the tree is organized into 12 layers. All the layers are stacked with M3x15mm Male-to-Female Nylon hex spacers. I was inspired by the project 72LED Christmas tree made with Arduino from radio pliers.
Project
For making the Christmas tree I used 206 LEDs and a Arduino Nano. However, controlling that huge number of LEDs using a microcontroller is not an easy task. If you want to control each LED independently you will be required 206 pins microcontroller for direct connection. But there are other options and using those you can save microcontroller pins and control each LED individually. Connecting LEDs in matrix form or using shift registers are two of them. Using shift registers will increase the complexity and cost of your project. Charlieplexing is another easy and inexpensive method. I used this method for making the project. I only used 15 pins of the Arduino Nano for driving 206 LEDs. The connections are very easy and do not involve lots of wiring. The schematic diagram is as follows.
The brightness of the LEDs can be adjusted programmatically or using a potentiometer connected to the A5 pin of the Nano and this option can be altered by the switch connected to the A4 pin of the Arduino. You don't need any resistor with the LEDs as I used timer interrupt for ON/OFF the LEDs and no LED is on for a long time (40us only).
For organizing the LEDs I used a 2 mm acrylic sheet. The spacing between two pins of a 5 mm LED is 2.54 mm. So 2 mm acrylic sheet is the right selection and it fits well with the LED. I distributed the LEDs into 12 layers. For arranging LEDs in layers I laser cut the acrylic sheet in gear form. The cut sheets are shown below. The design files are attached in a zip file at the last.

At the center of the design, there is a hole that will be used for passing wires from one layer to another. Three M3 size drill holes are made in every layer for attaching one layer with the other using M3x15mm hex spacers. In layer 11 (the bottommost layer) there are 28 teeth and it gradually reduced by two towards the top.
Topmost layer has 6 LEDs. At the top, a star is placed with 5 teeth. The LED distribution is as follows:
28 -> 26 -> 24 -> 22 -> 20 -> 18 -> 16 -> 14 -> 12 -> 10 -> 8 -> 6 (Total: 204 + 2 for start)
The diameter of the bottom layer is 140mm and is gradually reduced by 10mm on every layer.
LED placement of a layer is shown in the following image. Every adjacent LED has the opposite polarity. On one side all the LED pins are soldered together with a copper wire and it looks like a ring. On the other side, two adjacent LEDs are connected with opposite polarity. Every layer has an even number of teeth.
All the layers are prepared before making the tree stacking layers one after another.
I was curious about how it is going to look after attaching all the layers. So, I arranged one after another and it looks like below without any space.

Now, it is time to attach the layers. I added two layers together using three 15mm male-to-female Nylon hex spacers. For connecting LEDs to the Arduino pins I used 24 AWG single strand insulating wire.

For the bottom layer, three additional hex spacers with a bigger gap are attached that will work as a base of the tree.
A closer look with the hex spacers attached.
The final outlook of the completed Christmas tree looks like the image below. It looks great.
I made the Arduino circuit with a switch and resistor in a perfboard.
I used male pin headers for attaching the circuit board with the LED tree.
For the programming, I used the Arduino platform and this program does not need any additional libraries. However, an understanding of timer and timer interrupt is required. Timer 2 was utilized in the sketch. For controlling every layer an uint32 value is used. The value for turning all the LEDs is as follows.

Connections of the layer LEDs with the corresponding pins are illustrated in the following screenshot. It will help you to better understand the Arduino sketch. Let me explain a little more about the connection and control bit. If we consider layer 11, there are 28 LEDs for layer 11 and the common side of the layer is connected to the D2 pin of the Nano. On the common side, the anode of 14 LEDs and the cathode of the other 14 LEDs are connected all together with the copper ring. The minus sign (-) of the above screenshot represents the cathode and the plus sign (+) represents the anode of the LED. That means the anode of the rightmost LED is connected to the D3 pin and the cathode is connected to the D2 pin. Then for the next LED, the anode is connected to the D2 pin, and the cathode is connected to the D3 pin. So, if we want to connect right most LED then D2 should be low and D3 should be high.


The Arduino sketch is given below with useful comments. The original program was written by radio pliers. I modified it as my connection and requirement. You are free to modify it and use the program.
#define OFF_TIMER 28800 // Off timer setting value (Set the time until stop in seconds. 28800=8Hr)
#define BRIGHT 80 // Specify the brightness of the LED with a value of 0-100. Effective when not manually adjusting light (A4=HIGH))
#define BRIGHT_MODE_PIN 18 // Brightness setting mode switching pin (A4) If LOW, use variable resistance setting; if HIGH, use program setting value
#define BRIGHTNESS_PIN 19 // Brightness setting variable resistor (A5)
float bMag = 1.0; // Brightness correction magnification α during program dimming (final brightness = αx + β)
float bOffset = 0.0; // Brightness correction offset β during program dimming
volatile byte bSet = 0; // Brightness setting value (value set to interrupt timer, 0-240, if 0, lights off)
volatile long timeElapsed; // elapsed time
volatile uint32_t Ly[12]; // Display pattern memory 12 stages
uint32_t Ly_a[12], Ly_b[12], Ly_c[12]; // Display pattern operation memory
void setup() {
Serial.begin(115200);
pinMode(BRIGHT_MODE_PIN, INPUT_PULLUP); // Presence or absence of brightness setting using variable resistor (HIGH: None, LOW: Yes)
pinMode(BRIGHTNESS_PIN, INPUT_PULLUP);
pinMode(13, OUTPUT);
timeElapsed = 0; // Elapsed time timer
tc2Setup(); // Setting timer 2 (interrupt at 1ms cycle)
show(10); // Dummy execution once for initialization (brightness settings)
//ledTest(); // If uncommented, LED connection test (lights up one by one from the bottom)
}
void loop() {
starSpiralUp(1); // Lights up in a spiral from bottom to top
topExplosion(1);
dimming(1); // dimming
randomStar(2); // Random lighting for 3 seconds with argument 1
fallingRing(3); // falling ring
rotateAndClimb(2); // Climb while rotating
propeller(1); // propeller
stackUpDown(2); // UP/DOWN
swing(1); // swing
verticalSlice(2);
verticalCut(1); // vertical cut
parallelCut(1);
dimming(2); // dimming
show(1000);
Serial.println(timeElapsed);
if (timeElapsed > OFF_TIMER) { // If the display time exceeds the set value
while (1) { // Stop in an infinite loop (break out by resetting)
}
}
}
void tc2Setup() { // TC2 settings for dynamic lighting
cli(); // Disable interrupts
TCCR2B = 0x00; // Stop timer 2
TCCR2A = 0b00000010; // Set the mode again
// |||| ++--- WGM: CTC mode, Clear TCNT2 with OCR2A
// ||++------- COM2B D3 PD3 Standard port operation (OC2A disconnection)
// ++--------- COM2A D11 PB3 Standard port operation (OC2B disconnection)
TCCR2B = 0b00000100; // Clock setting 1/64 (speeding up to prevent flickering as the number of stages increases)
// |+++--- CS:1/64 : 250kHz (4μs step)
// +------ WGM02
/*
// (Below is before change)
TCCR2B = 0b00000101; // Clock setting 1/128
// |+++--- CS:1/128 : 125kHz (8μs step)
// +------ WGM02
*/
OCR2A = 250 - 1; // 250 count cycle (interrupt at 1ms cycle)
OCR2B = 10 - 1; // Interrupt at 10 counts (40us) (value is provisional)
TIMSK2 = 0b00000110;
// ||+---- No TOIE2 overflow interrupt
// |+---- OCIE2A compare match A interrupt enabled
// +------ OCIE2B compare match B interrupt enabled
sei(); // enable interrupts
}
ISR(TIMER2_COMPA_vect) { // Timer 2 A interrupt (lights up the specified LED), interrupt at 1ms cycle
static int scanN = 0; // refresh position counter
static int ttt = 0; // Elapsed time counter
ttt++;
if (ttt >= 1000) { // After 1 second
ttt = 0;
timeElapsed++; // Increment the display timer by 1 second (value used in auto-off timer)
}
if (bSet > 0) { // If the brightness setting value is 0 or more (bSet is 8 bits, so there is no need to disable interrupts)
ledOff(); // Turn off all LEDs (turn off to hide behind the scenes)
switch (scanN) { // Lights up the LED corresponding to the scan number (lights up in time division)
case 0:
d2High(); break;
case 1:
d3High(); break;
case 2:
d4High(); break;
case 3:
d5High(); break;
case 4:
d6High(); break;
case 5:
d7High(); break;
case 6:
d8High(); break;
case 7:
d9High(); break;
case 8:
d10High(); break;
case 9:
d11High(); break;
case 10:
d12High(); break;
case 11:
a0High(); break;
case 12:
a1High(); break;
case 13:
a2High(); break;
case 14:
a3High(); break;
default:
break;
}
}
scanN ++; // Update scan number
if (scanN >= 15) { // Return to zero if the upper limit is exceeded
scanN = 0;
}
// scanN = 11; // force set value for debugging
}
ISR(TIMER2_COMPB_vect) { // Timer 2 B interrupt (turn off and brightness setting)
int bSetBuff;
ledOff(); // Turn off all LEDs
bSetBuff = bSet; // It would be a problem if the value changed during processing, so copy it (bSet is 8 bits, so you don't need to disable interrupts)
if (bSetBuff <= 0) { // If 0 or negative
OCR2B = 0; // Set OCR2B to 0 (Even if you set it to 0, it will remain lit for the minimum time, so forcefully turn it off on the COMPA side)
}
else { // Otherwise (if greater than or equal to 1)
OCR2B = bSetBuff - 1; // Set the value minus 1
}
}
void show(unsigned long t) { // Wait the specified time to show. Perform dimming calculation at the same time
int x;
delay(t);
if (digitalRead(BRIGHT_MODE_PIN) == LOW) { // If brightness adjustment using variable resistor is enabled
x = analogRead(BRIGHTNESS_PIN); // Read the brightness sensor value
x = map(x, 0, 1023, 10, 240); // Scale ADC value to range 10-240
} else { // If you do not use a variable resistor
x = map(BRIGHT, 0, 100, 10, 240); // Use the BRIGHT value of the program settings
}
x = x * bMag + bOffset; // Brightness correction calculation
bSet = constrain(x, 0, 240); // Final brightness (used as PWM settings in interrupt routine)
}
void ledTest() { // LED connection test (lights up the LEDs one by one from the bottom)
for (;;) { // Infinite loop (the contents are the same as starSpiralUp)
Ly[11] = 0x00000004; // Plant the seeds
show(300); // lights up
for (int j = 0; j <= 204; j++) { // to the top
spiralUp(); // spiral up
show(200); // lights up
}
clearArray();
delay(200);
}
}
void ledOff() { // Turn off all LEDs by port operation (set all LED pins to Low by inputting)
PORTD &= B00000011; // D2-7 LOW
PORTB &= B11100000; // D8-12 LOW
PORTC &= B11110000; // A0-A3 Low
DDRD &= B00000010; // Assign D2-7 to input (D0, D1 are serial)
DDRB &= B11100000; // Assign D8-12 to input
DDRC &= B11110000; // Assign A0-A3 to input
}
void allOn() { // Turn on all LEDs in pattern memory)
Ly[0] = 0x0007E000;
Ly[1] = 0x000FF000;
Ly[2] = 0x001FF800;
Ly[3] = 0x003FFC00;
Ly[4] = 0x007FFE00;
Ly[5] = 0x00FFFF00;
Ly[6] = 0x01FFFF80;
Ly[7] = 0x03FFFFC0;
Ly[8] = 0x07FFFFE0;
Ly[9] = 0x0FFFFFF0;
Ly[10] = 0x1FFFFFF8;
Ly[11] = 0x3FFFFFFC;
}
void clearArray() { // Clear pattern memory
for (int i = 0; i < 12; i++) {
Ly[i] = 0;
Ly_a[i] = 0;
Ly_b[i] = 0;
Ly_c[i] = 0;
}
}
void spiralUp() { // Spiral up
Ly[0] &= 0x0007E000; // Clear outside the display area
Ly[1] &= 0x000FF000;
Ly[2] &= 0x001FF800;
Ly[3] &= 0x003FFC00;
Ly[4] &= 0x007FFE00;
Ly[5] &= 0x00FFFF00;
Ly[6] &= 0x01FFFF80;
Ly[7] &= 0x03FFFFC0;
Ly[8] &= 0x07FFFFE0;
Ly[9] &= 0x0FFFFFF0;
Ly[10] &= 0x1FFFFFF8;
Ly[11] &= 0x3FFFFFFC;
Ly[0] = Ly[0] << 1;
if (Ly[1] & 0x00020000) Ly[0] |= 0x00008000; // If the left end of Ly[1] is 1, set the right end of Ly[0] to 1
Ly[1] = Ly[1] << 1;
if (Ly[2] & 0x00040000) Ly[1] |= 0x00004000; // If the left end of Ly[2] is 1, set the right end of Ly[1] to 1
Ly[2] = Ly[2] << 1;
if (Ly[3] & 0x00080000) Ly[2] |= 0x00002000; // If the left end of Ly[3] is 1, set the right end of Ly[2] to 1
Ly[3] = Ly[3] << 1;
if (Ly[4] & 0x00100000) Ly[3] |= 0x00001000; // If the left end of Ly[4] is 1, set the right end of Ly[3] to 1
Ly[4] = Ly[4] << 1;
if (Ly[5] & 0x00200000) Ly[4] |= 0x00000800; // If the left end of Ly[5] is 1, set the right end of Ly[4] to 1
Ly[5] = Ly[5] << 1;
if (Ly[6] & 0x00400000) Ly[5] |= 0x00000400; // If the left end of Ly[6] is 1, set the right end of Ly[5] to 1
Ly[6] = Ly[6] << 1;
if (Ly[7] & 0x00800000) Ly[6] |= 0x00000200; // If the left end of Ly[7] is 1, set the right end of Ly[6] to 1
Ly[7] = Ly[7] << 1;
if (Ly[8] & 0x01000000) Ly[7] |= 0x00000100; // If the left end of Ly[8] is 1, set the right end of Ly[7] to 1
Ly[8] = Ly[8] << 1;
if (Ly[9] & 0x02000000) Ly[8] |= 0x00000080; // If the left end of Ly[9] is 1, set the right end of Ly[8] to 1
Ly[9] = Ly[9] << 1;
if (Ly[10] & 0x04000000) Ly[9] |= 0x00000040; // If the left end of Ly[10] is 1, set the right end of Ly[9] to 1
Ly[10] = Ly[10] << 1;
if (Ly[11] & 0x08000000) Ly[10] |= 0x00000020; // If the left end of Ly[11] is 1, set the right end of Ly[10] to 1
Ly[11] = Ly[11] << 1;
}
void starSpiralUp(int n) { // Light up the LEDs one by one from bottom to top while rotating
for (int i = 0; i < n; i++) { // specified number of times
Ly[11] = 0x00000020; // Put the seeds at the bottom
show(20); //
for (int j = 0; j <= 204; j++) { // to the top
spiralUp(); // spiral up
show(20); // lights up
}
clearArray();
delay(200);
}
}
void topExplosion(int c) { // Explosion at the tip
for (int n = 0; n < c; n++) { // specified number of times
clearArray();
for (int i = 0; i < 12; i++) {
Ly[i] = 0xFFFFFFFF; // Lights from top to bottom
show(30); // Wait
}
}
delay(500); // Wait for a while with all lights on
}
void randomStar(int n) { // Light up randomly
for (int i = 0; i < n; i++) { // number of times specified by argument
for (int j = 0; j < 40; j++) { // 6 seconds (0.15 seconds x 40 times)
Ly[0] |= 0x00018000; // The two tips are always lit
Ly[1] = random(0, 0xFFFFFFF) & random(0, 0xFFFFFFF); // Lights up with probability 1/4
Ly[2] = random(0, 0xFFFFFFF) & random(0, 0xFFFFFFF); // It didn't work when I set the upper limit of random numbers to the full 32 bits, so I kept it at 28 bits.
Ly[3] = random(0, 0xFFFFFFF) & random(0, 0xFFFFFFF);
Ly[4] = random(0, 0xFFFFFFF) & random(0, 0xFFFFFFF);
Ly[5] = random(0, 0xFFFFFFF) & random(0, 0xFFFFFFF);
Ly[6] = random(0, 0xFFFFFFF) & random(0, 0xFFFFFFF);
Ly[7] = random(0, 0xFFFFFFF) & random(0, 0xFFFFFFF);
Ly[8] = random(0, 0xFFFFFFF) & random(0, 0xFFFFFFF);
Ly[9] = random(0, 0xFFFFFFF) & random(0, 0xFFFFFFF);
Ly[10] = random(0, 0xFFFFFFF) & random(0, 0xFFFFFFF);
Ly[11] = random(0, 0xFFFFFFF) & random(0, 0xFFFFFFF);
show(150);
}
} // n
clearArray();
show(1000);
}
void dimming(int c) { // Slowly brightening and dimming
float x, ratio;
bMag = 0.0; // Set light intensity to zero
show(10); // Reflect the brightness setting value
allOn(); // All lights on
x = OCR2B; // Record the starting brightness
ratio = pow(2.0 * x, 1.0 / 40.0); // Calculate the brightness increase ratio to double the brightness
for (int j = 0; j < c; j++) { // specified number of times
bMag = 1.0/x;
for (int i = 0; i <= 40; i++) { // Brightening in a geometric series
bMag *= ratio; // Correct the value
show(30);
}
for (int i = 40; i >= 0; i--) { // dimming
bMag /= ratio;
show(30);
}
show(100);
}
clearArray(); // Clear pattern memory
bMag = 1.0; // Return brightness correction coefficient to default
// show(500); // Turns off finally
}
void fallingRing(int c) { // Drop the ring from above
for (int n = 0; n < c; n++) { // specified number of times
clearArray();
Ly[0] = 0xFFFFFFFF; // Put the story at the beginning
show(100); // Wait a moment to show
for (int i = 0; i < 11; i++) {
Ly[i + 1] = Ly[i]; // Shift backward (down)
Ly[i] = 0;
show(70); // Wait
}
}
clearArray(); // Turns off at the end
delay(200);
}
void rotateAndClimb(int n) { // Climb while rotating
clearArray();
for (int i = 0; i < n; i++) { // specified number of times
for (int j = 0; j < 200; j++) {
if ( (j % 18) > 8) { // every 8th time,
Ly[11] |= 0x00000004; // Embed a star at the bottom
} else {
Ly[11] &= ~0x00000004; // Erase the star
}
show(40);
spiralUp();
}
for (int j = 0; j < 204; j++) {
Ly[11] &= ~0x00000004;
show(40);
spiralUp();
}
}
clearArray();
delay(500);
}
void propeller(int n) { // Propeller display
int a;
for (int i = 0; i < n; i++) { // Repeat the number of times specified by the argument
for (a = 0; a < 1680 * 2; a += 7) { // Forward rotation (1680 is the least common multiple of 16,14,12,10)
invertV(a); // Display an inverted V shape at the specified angle
show(5);
}
for (a = 1680 * 2; a > 0; a -= 7) { // Reverse rotation
invertV(a);
show(5);
}
}
delay(300);
}
void invertV(int k) { // Lights up in an inverted V shape at the specified angle (half turn with argument 840)
Ly[0] = 0b00000000000000011000000000000000; // The top two are always lit
Ly[1] = 0b00000000000000101000000000000000 >> ((k / 420) % 2); // Move the V-shaped pattern to the specified angle
Ly[2] = 0b00000000000001001000000000000000 >> ((k / 280) % 3); // Note that 840 is the least common multiple of 8,7,6,5,4,3,2
Ly[3] = 0b00000000000010001000000000000000 >> ((k / 210) % 4);
Ly[4] = 0b00000000000100001000000000000000 >> ((k / 168) % 5);
Ly[5] = 0b00000000001000001000000000000000 >> ((k / 140) % 6);
Ly[6] = 0b00000000010000001000000000000000 >> ((k / 120) % 7);
Ly[7] = 0b00000000100000001000000000000000 >> ((k / 105) % 8);
Ly[8] = 0b00000001000000001000000000000000 >> ((k / 93) % 9); //
Ly[9] = 0b00000010000000001000000000000000 >> ((k / 84) % 10);
Ly[10] = 0b00000100000000001000000000000000 >> ((k / 76) % 11);
Ly[11] = 0b00001000000000001000000000000000 >> ((k / 70) % 12);
}
void stackUpDown(int n) { // Turns on when stacking, turns off when stacking down
for (int i = 0; i < n; i++) {
for (int z = 11; z >= 0; z--) { // Stack lights from bottom to top
Ly[z] = 0xFFFFFFFF;
show(30);
}
show(200); // Wait for a while with all lights on
for (int z = 11; z >= 0; z--) { // turn off from bottom to top
Ly[z] = 0x0000;
show(30);
}
show(200); // Wait for a while with all lights off
for (int z = 0; z <= 11; z++) { // Light stacked upside down from top to bottom
Ly[z] = 0xFFFFFFFF;
show(30);
}
show(200); // Wait for a while with all lights on
for (int z = 0; z <= 11; z++) { // Turn off from top to bottom
Ly[z] = 0x0000;
show(30);
}
show(300); // Wait for a while with all lights off
} // repeat n times
}
void swing(int n) { // Move diagonal line to the right
for (int i = 0; i < n; i++) { // specified number of times
for (int j = 0; j < 1; j++) { // 1 time for left rotation
Ly[0] = 0x00010000; // Draw a diagonal line on the left side
Ly[1] = 0x00020000;
Ly[2] = 0x00040000;
Ly[3] = 0x00080000;
Ly[4] = 0x00100000;
Ly[5] = 0x00200000;
Ly[6] = 0x00400000;
Ly[7] = 0x00800000;
Ly[8] = 0x01000000;
Ly[9] = 0x02000000;
Ly[10] = 0x04000000;
Ly[11] = 0x08000000;
for (int k = 0; k < 22; k++) { // 22 times
for (int m = 0; m < 12; m++) { // for each layer
Ly[m] = Ly[m] >> 1; // Shift the image to the right
}
show(50); // Wait for display
}
}
show(200);
for (int j = 0; j < 1; j++) { // 1 time for right rotation
Ly[0] = 0x00008000; // Draw a diagonal line on the right side
Ly[1] = 0x00004000;
Ly[2] = 0x00002000;
Ly[3] = 0x00001000;
Ly[4] = 0x00000800;
Ly[5] = 0x00000400;
Ly[6] = 0x00000200;
Ly[7] = 0x00000100;
Ly[8] = 0x00000080;
Ly[9] = 0x00000040;
Ly[10] = 0x00000020;
Ly[11] = 0x00000010;
for (int k = 0; k < 22; k++) { // 22 times
for (int m = 0; m < 12; m++) {
Ly[m] = Ly[m] << 1; // Shift the image to the right
}
show(50); // Wait for display
}
}
show(200);
for (int j = 0; j < 1; j++) { // once with cross swing
Ly_a[0] = 0x00010000; Ly_b[0] = 0x00008000; // Add diagonal lines on both sides
Ly_a[1] = 0x00020000; Ly_b[1] = 0x00004000;
Ly_a[2] = 0x00040000; Ly_b[2] = 0x00002000;
Ly_a[3] = 0x00080000; Ly_b[3] = 0x00001000;
Ly_a[4] = 0x00100000; Ly_b[4] = 0x00000800;
Ly_a[5] = 0x00200000; Ly_b[5] = 0x00000400;
Ly_a[6] = 0x00400000; Ly_b[6] = 0x00000200;
Ly_a[7] = 0x00800000; Ly_b[7] = 0x00000100;
Ly_a[8] = 0x01000000; Ly_b[8] = 0x00000080;
Ly_a[9] = 0x02000000; Ly_b[9] = 0x00000040;
Ly_a[10] = 0x04000000; Ly_b[10] = 0x00000020;
Ly_a[11] = 0x08000000; Ly_b[11] = 0x00000010;
for (int k = 0; k < 22; k++) { // 22 times
for (int m = 0; m < 12; m++) {
Ly_a[m] = Ly_a[m] >> 1; // Shift the image of a buffer to the right
}
for (int m = 0; m < 12; m++) {
Ly_b[m] = Ly_b[m] << 1; // Shift the image of b buffer to the left
}
for (int m = 0; m < 12; m++) {
Ly[m] = Ly_a[m] | Ly_b[m]; // Synthesize into display memory
}
show(50); // Wait for display
}
}
show(300);
}
}
void verticalCut(int n) { // Vertical cut to turn on and off horizontally
clearArray();
for (int i = 0; i < n; i++) { // specified number of times
vSliceTogle(1); cutShow(); // Lights from right to left
vSliceTogle(2); cutShow();
vSliceTogle(3); cutShow();
vSliceTogle(4); cutShow();
vSliceTogle(5); cutShow();
vSliceTogle(6); cutShow();
vSliceTogle(7); cutShow();
vSliceTogle(8); cutShow();
vSliceTogle(9); cutShow();
vSliceTogle(10); cutShow();
vSliceTogle(11); cutShow();
vSliceTogle(12); // All lights on
show(500);
vSliceTogle(1); cutShow(); // Turn off from right to left (reverse with XOR)
vSliceTogle(2); cutShow();
vSliceTogle(3); cutShow();
vSliceTogle(4); cutShow();
vSliceTogle(5); cutShow();
vSliceTogle(6); cutShow();
vSliceTogle(7); cutShow();
vSliceTogle(8); cutShow();
vSliceTogle(9); cutShow();
vSliceTogle(10); cutShow();
vSliceTogle(11); cutShow();
vSliceTogle(12); cutShow();
show(500); // Turn off all lights
vSliceTogle(12); cutShow(); // Lights from left to right
vSliceTogle(11); cutShow();
vSliceTogle(10); cutShow();
vSliceTogle(9); cutShow();
vSliceTogle(8); cutShow();
vSliceTogle(7); cutShow();
vSliceTogle(6); cutShow();
vSliceTogle(5); cutShow();
vSliceTogle(4); cutShow();
vSliceTogle(3); cutShow();
vSliceTogle(2); cutShow();
vSliceTogle(1); cutShow();
show(500); // All lights on
vSliceTogle(12); cutShow(); // Turns off from left to right
vSliceTogle(11); cutShow();
vSliceTogle(10); cutShow();
vSliceTogle(9); cutShow();
vSliceTogle(8); cutShow();
vSliceTogle(7); cutShow();
vSliceTogle(6); cutShow();
vSliceTogle(5); cutShow();
vSliceTogle(4); cutShow();
vSliceTogle(3); cutShow();
vSliceTogle(2); cutShow();
vSliceTogle(1); cutShow();
show(500); // Turn off all lights
clearArray();
}
}
void parallelCut(int n) { // Vertical cut to turn on and off horizontally
clearArray();
for (int i = 0; i < n; i++) { // specified number of times
vSliceTogle(1);
vSliceTogle(12); cutShow();
vSliceTogle(2);
vSliceTogle(11); cutShow();
vSliceTogle(3);
vSliceTogle(10); cutShow();
vSliceTogle(4);
vSliceTogle(9); cutShow();
vSliceTogle(5);
vSliceTogle(8); cutShow();
vSliceTogle(6);
vSliceTogle(7);
show(1000);
vSliceTogle(1);
vSliceTogle(12); cutShow();
vSliceTogle(2);
vSliceTogle(11); cutShow();
vSliceTogle(3);
vSliceTogle(10); cutShow();
vSliceTogle(4);
vSliceTogle(9); cutShow();
vSliceTogle(5);
vSliceTogle(8); cutShow();
vSliceTogle(6);
vSliceTogle(7);
show(1000);
clearArray();
}
}
void verticalSlice(int n) {
clearArray();
for (int i = 0; i < n; i++) { // specified number of times
vSliceTogle(1); cutShow();
vSliceTogle(1); vSliceTogle(2); cutShow(); // Move slice from right to left
vSliceTogle(2); vSliceTogle(3); cutShow();
vSliceTogle(3); vSliceTogle(4); cutShow();
vSliceTogle(4); vSliceTogle(5); cutShow();
vSliceTogle(5); vSliceTogle(6); cutShow();
vSliceTogle(6); vSliceTogle(7); cutShow();
vSliceTogle(7); vSliceTogle(8); cutShow();
vSliceTogle(8); vSliceTogle(9); cutShow();
vSliceTogle(9); vSliceTogle(10); cutShow();
vSliceTogle(10); vSliceTogle(11); cutShow();
vSliceTogle(11); vSliceTogle(12); cutShow();
vSliceTogle(12); delay(200);
vSliceTogle(12); cutShow();
vSliceTogle(12); vSliceTogle(11); cutShow(); // left to right
vSliceTogle(11); vSliceTogle(10); cutShow();
vSliceTogle(10); vSliceTogle(9); cutShow();
vSliceTogle(9); vSliceTogle(8); cutShow();
vSliceTogle(8); vSliceTogle(7); cutShow();
vSliceTogle(7); vSliceTogle(6); cutShow();
vSliceTogle(6); vSliceTogle(5); cutShow();
vSliceTogle(5); vSliceTogle(4); cutShow();
vSliceTogle(4); vSliceTogle(3); cutShow();
vSliceTogle(3); vSliceTogle(2); cutShow();
vSliceTogle(2); vSliceTogle(1); cutShow();
vSliceTogle(1); delay(400);
}
}
void cutShow() { // Wait for the specified time (source shortening measure)
show(50);
}
void vSliceTogle(int n) { // Invert the specified column (invert the bits vertically using XOR)
switch (n) {
case 1:
Ly[11] ^= 0b00000000000000000000010000000000;
break;
case 2:
Ly[8] ^= 0b00000000000000000000100000000000;
Ly[9] ^= 0b00000000000000000000110000000000;
Ly[10] ^= 0b00000000000000000000101000000000;
Ly[11] ^= 0b00000000000000000000100100000000;
break;
case 3:
Ly[6] ^= 0b00000000000000000001000000000000;
Ly[7] ^= 0b00000000000000000001100000000000;
Ly[8] ^= 0b00000000000000000001010000000000;
Ly[9] ^= 0b00000000000000000001001000000000;
Ly[10] ^= 0b00000000000000000001000100000000;
Ly[11] ^= 0b00000000000000000001000010000000;
break;
case 4:
Ly[4] ^= 0b00000000000000000010000000000000;
Ly[5] ^= 0b00000000000000000011000000000000;
Ly[6] ^= 0b00000000000000000010100000000000;
Ly[7] ^= 0b00000000000000000010010000000000;
Ly[8] ^= 0b00000000000000000010001000000000;
Ly[9] ^= 0b00000000000000000010000100000000;
Ly[10] ^= 0b00000000000000000010000010000000;
Ly[11] ^= 0b00000000000000000010000001000000;
break;
case 5:
Ly[2] ^= 0b00000000000000000100000000000000;
Ly[3] ^= 0b00000000000000000110000000000000;
Ly[4] ^= 0b00000000000000000101000000000000;
Ly[5] ^= 0b00000000000000000100100000000000;
Ly[6] ^= 0b00000000000000000100010000000000;
Ly[7] ^= 0b00000000000000000100001000000000;
Ly[8] ^= 0b00000000000000000100000100000000;
Ly[9] ^= 0b00000000000000000100000010000000;
Ly[10] ^= 0b00000000000000000100000001000000;
Ly[11] ^= 0b00000000000000000100000000100000;
break;
case 6:
Ly[0] ^= 0b00000000000000001000000000000000;
Ly[1] ^= 0b00000000000000001100000000000000;
Ly[2] ^= 0b00000000000000001010000000000000;
Ly[3] ^= 0b00000000000000001001000000000000;
Ly[4] ^= 0b00000000000000001000100000000000;
Ly[5] ^= 0b00000000000000001000010000000000;
Ly[6] ^= 0b00000000000000001000001000000000;
Ly[7] ^= 0b00000000000000001000000100000000;
Ly[8] ^= 0b00000000000000001000000010000000;
Ly[9] ^= 0b00000000000000001000000001000000;
Ly[10] ^= 0b00000000000000001000000000100000;
Ly[11] ^= 0b00000000000000001000000000010000;
break;
case 7:
Ly[0] ^= 0b00000000000000010000000000000000;
Ly[1] ^= 0b00000000000000110000000000000000;
Ly[2] ^= 0b00000000000001010000000000000000;
Ly[3] ^= 0b00000000000010010000000000000000;
Ly[4] ^= 0b00000000000100010000000000000000;
Ly[5] ^= 0b00000000001000010000000000000000;
Ly[6] ^= 0b00000000010000010000000000000000;
Ly[7] ^= 0b00000000100000010000000000000000;
Ly[8] ^= 0b00000001000000010000000000000000;
Ly[9] ^= 0b00000010000000010000000000000000;
Ly[10] ^= 0b00000100000000010000000000000000;
Ly[11] ^= 0b00001000000000010000000000000000;
break;
case 8:
Ly[2] ^= 0b00000000000000100000000000000000;
Ly[3] ^= 0b00000000000001100000000000000000;
Ly[4] ^= 0b00000000000010100000000000000000;
Ly[5] ^= 0b00000000000100100000000000000000;
Ly[6] ^= 0b00000000001000100000000000000000;
Ly[7] ^= 0b00000000010000100000000000000000;
Ly[8] ^= 0b00000000100000100000000000000000;
Ly[9] ^= 0b00000001000000100000000000000000;
Ly[10] ^= 0b00000010000000100000000000000000;
Ly[11] ^= 0b00000100000000100000000000000000;
break;
case 9:
Ly[4] ^= 0b00000000000001000000000000000000;
Ly[5] ^= 0b00000000000011000000000000000000;
Ly[6] ^= 0b00000000000101000000000000000000;
Ly[7] ^= 0b00000000001001000000000000000000;
Ly[8] ^= 0b00000000010001000000000000000000;
Ly[9] ^= 0b00000000100001000000000000000000;
Ly[10] ^= 0b00000001000001000000000000000000;
Ly[11] ^= 0b00000010000001000000000000000000;
break;
case 10:
Ly[6] ^= 0b00000000000010000000000000000000;
Ly[7] ^= 0b00000000000110000000000000000000;
Ly[8] ^= 0b00000000001010000000000000000000;
Ly[9] ^= 0b00000000010010000000000000000000;
Ly[10] ^= 0b00000000100010000000000000000000;
Ly[11] ^= 0b00000001000010000000000000000000;
break;
case 11:
Ly[8] ^= 0b00000000000100000000000000000000;
Ly[9] ^= 0b00000000001100000000000000000000;
Ly[10] ^= 0b00000000010100000000000000000000;
Ly[11] ^= 0b00000000100100000000000000000000;
break;
case 12:
Ly[11] ^= 0b00000000001000000000000000000000;
break;
default:
break;
}
}
// Light up the corresponding LED with Charlie Plexing
// corresponding DDR bit is 1 for OUTPUT
void d2High() { // Output High from D2 and light the specified LED (turn the other port Low)
if ( Ly[11] & 0x10000000 ) DDRD |= B00001000; // D3
if ( Ly[11] & 0x04000000 ) DDRD |= B00010000; // D4
if ( Ly[11] & 0x01000000 ) DDRD |= B00100000; // D5
if ( Ly[11] & 0x00400000 ) DDRD |= B01000000; // D6
if ( Ly[11] & 0x00100000 ) DDRD |= B10000000; // D7
if ( Ly[11] & 0x00040000 ) DDRB |= B00000001; // D8
if ( Ly[11] & 0x00010000 ) DDRB |= B00000010; // D9
if ( Ly[11] & 0x00004000 ) DDRB |= B00000100; // D10
if ( Ly[11] & 0x00001000 ) DDRB |= B00001000; // D11
if ( Ly[11] & 0x00000400 ) DDRB |= B00010000; // D12
if ( Ly[11] & 0x00000100 ) DDRC |= B00000001; // A0
if ( Ly[11] & 0x00000040 ) DDRC |= B00000010; // A1
if ( Ly[11] & 0x00000010 ) DDRC |= B00000100; // A2
if ( Ly[11] & 0x00000004 ) DDRC |= B00001000; // A3
DDRD |= B00000100; // Assign D2 to output
PORTD |= B00000100; // D2 High. Now turn on the LED (do this last to minimize the amount of light)
}
void d3High() { // Output High from D3 and light the specified LED
if ( Ly[11] & 0x20000000 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x08000000 ) DDRD |= B00010000; // D4
if ( Ly[10] & 0x02000000 ) DDRD |= B00100000; // D5
if ( Ly[10] & 0x00800000 ) DDRD |= B01000000; // D6
if ( Ly[10] & 0x00200000 ) DDRD |= B10000000; // D7
if ( Ly[10] & 0x00080000 ) DDRB |= B00000001; // D8
if ( Ly[10] & 0x00020000 ) DDRB |= B00000010; // D9
if ( Ly[10] & 0x00008000 ) DDRB |= B00000100; // D10
if ( Ly[10] & 0x00002000 ) DDRB |= B00001000; // D11
if ( Ly[10] & 0x00000800 ) DDRB |= B00010000; // D12
if ( Ly[10] & 0x00000200 ) DDRC |= B00000001; // A0
if ( Ly[10] & 0x00000080 ) DDRC |= B00000010; // A1
if ( Ly[10] & 0x00000020 ) DDRC |= B00000100; // A2
if ( Ly[10] & 0x00000008 ) DDRC |= B00001000; // A3
DDRD |= B00001000; // Assign D3 to output
PORTD |= B00001000; // Set D3 to High (LED will light up)
}
void d4High() { // Output High from D4 and light the specified LED
if ( Ly[11] & 0x08000000 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x10000000 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x04000000 ) DDRD |= B00100000; // D5
if ( Ly[9] & 0x01000000 ) DDRD |= B01000000; // D6
if ( Ly[9] & 0x00400000 ) DDRD |= B10000000; // D7
if ( Ly[9] & 0x00100000 ) DDRB |= B00000001; // D8
if ( Ly[9] & 0x00040000 ) DDRB |= B00000010; // D9
if ( Ly[9] & 0x00010000 ) DDRB |= B00000100; // D10
if ( Ly[9] & 0x00004000 ) DDRB |= B00001000; // D11
if ( Ly[9] & 0x00001000 ) DDRB |= B00010000; // D12
if ( Ly[9] & 0x00000400 ) DDRC |= B00000001; // A0
if ( Ly[9] & 0x00000100 ) DDRC |= B00000010; // A1
if ( Ly[9] & 0x00000040 ) DDRC |= B00000100; // A2
if ( Ly[9] & 0x00000010 ) DDRC |= B00001000; // A3
DDRD |= B00010000; // Assign D4 to output
PORTD |= B00010000; // Set D4 to High (LED will light up)
}
void d5High() { // Output High from D5 and light the specified LED
if ( Ly[11] & 0x02000000 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x04000000 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x08000000 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x02000000 ) DDRD |= B01000000; // D6
if ( Ly[8] & 0x00800000 ) DDRD |= B10000000; // D7
if ( Ly[8] & 0x00200000 ) DDRB |= B00000001; // D8
if ( Ly[8] & 0x00080000 ) DDRB |= B00000010; // D9
if ( Ly[8] & 0x00020000 ) DDRB |= B00000100; // D10
if ( Ly[8] & 0x00008000 ) DDRB |= B00001000; // D11
if ( Ly[8] & 0x00002000 ) DDRB |= B00010000; // D12
if ( Ly[8] & 0x00000800 ) DDRC |= B00000001; // A0
if ( Ly[8] & 0x00000200 ) DDRC |= B00000010; // A1
if ( Ly[8] & 0x00000080 ) DDRC |= B00000100; // A2
if ( Ly[8] & 0x00000020 ) DDRC |= B00001000; // A3
DDRD |= B00100000; // Assign D5 to output
PORTD |= B00100000; // Set D5 to High (LED will light up)
}
void d6High() { // Output High from D6 and light the specified LED
if ( Ly[11] & 0x00800000 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x01000000 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x02000000 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x04000000 ) DDRD |= B00100000; // D5
if ( Ly[7] & 0x01000000 ) DDRD |= B10000000; // D7
if ( Ly[7] & 0x00400000 ) DDRB |= B00000001; // D8
if ( Ly[7] & 0x00100000 ) DDRB |= B00000010; // D9
if ( Ly[7] & 0x00040000 ) DDRB |= B00000100; // D10
if ( Ly[7] & 0x00010000 ) DDRB |= B00001000; // D11
if ( Ly[7] & 0x00004000 ) DDRB |= B00010000; // D12
if ( Ly[7] & 0x00001000 ) DDRC |= B00000001; // A0
if ( Ly[7] & 0x00000400 ) DDRC |= B00000010; // A1
if ( Ly[7] & 0x00000100 ) DDRC |= B00000100; // A2
if ( Ly[7] & 0x00000040 ) DDRC |= B00001000; // A3
DDRD |= B01000000; // Assign D6 to output
PORTD |= B01000000; // Set D6 to High (LED will light up)
}
void d7High() { // Output High from D7 and light the specified LED
if ( Ly[11] & 0x00200000 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x00400000 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x00800000 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x01000000 ) DDRD |= B00100000; // D5
if ( Ly[7] & 0x02000000 ) DDRD |= B01000000; // D6
if ( Ly[6] & 0x00800000 ) DDRB |= B00000001; // D8
if ( Ly[6] & 0x00200000 ) DDRB |= B00000010; // D9
if ( Ly[6] & 0x00080000 ) DDRB |= B00000100; // D10
if ( Ly[6] & 0x00020000 ) DDRB |= B00001000; // D11
if ( Ly[6] & 0x00008000 ) DDRB |= B00010000; // D12
if ( Ly[6] & 0x00002000 ) DDRC |= B00000001; // A0
if ( Ly[6] & 0x00000800 ) DDRC |= B00000010; // A1
if ( Ly[6] & 0x00000200 ) DDRC |= B00000100; // A2
if ( Ly[6] & 0x00000080 ) DDRC |= B00001000; // A3
DDRD |= B10000000; // Assign D7 to output
PORTD |= B10000000; // Set D7 to High (LED will light up)
}
void d8High() { // Output High from D8 and light the specified LED
if ( Ly[11] & 0x00080000 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x00100000 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x00200000 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x00400000 ) DDRD |= B00100000; // D5
if ( Ly[7] & 0x00800000 ) DDRD |= B01000000; // D6
if ( Ly[6] & 0x01000000 ) DDRD |= B10000000; // D7
if ( Ly[5] & 0x00800000 ) DDRB |= B00000010; // D9
if ( Ly[5] & 0x00200000 ) DDRB |= B00000100; // D10
if ( Ly[5] & 0x00080000 ) DDRB |= B00001000; // D11
if ( Ly[5] & 0x00020000 ) DDRB |= B00010000; // D12
if ( Ly[5] & 0x00008000 ) DDRC |= B00000001; // A0
if ( Ly[5] & 0x00002000 ) DDRC |= B00000010; // A1
if ( Ly[5] & 0x00000800 ) DDRC |= B00000100; // A2
if ( Ly[5] & 0x00000200 ) DDRC |= B00001000; // A3
DDRB |= B00000001; // Assign D8 to output
PORTB |= B00000001; // Set D8 to High (LED will light up)
}
void d9High() { // Output High from D9 and light the specified LED
if ( Ly[11] & 0x00020000 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x00040000 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x00080000 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x00100000 ) DDRD |= B00100000; // D5
if ( Ly[7] & 0x00200000 ) DDRD |= B01000000; // D6
if ( Ly[6] & 0x00400000 ) DDRD |= B10000000; // D7
if ( Ly[5] & 0x00400000 ) DDRB |= B00000001; // D8
if ( Ly[4] & 0x00400000 ) DDRB |= B00000100; // D10
if ( Ly[4] & 0x00100000 ) DDRB |= B00001000; // D11
if ( Ly[4] & 0x00040000 ) DDRB |= B00010000; // D12
if ( Ly[4] & 0x00010000 ) DDRC |= B00000001; // A0
if ( Ly[4] & 0x00004000 ) DDRC |= B00000010; // A1
if ( Ly[4] & 0x00001000 ) DDRC |= B00000100; // A2
if ( Ly[4] & 0x00000400 ) DDRC |= B00001000; // A3
DDRB |= B00000010; // Assign D9 to output
PORTB |= B00000010; // Set D9 to High (LED will light up)
}
void d10High() { // Output High from D10 and light the specified LED
if ( Ly[11] & 0x00008000 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x00010000 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x00020000 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x00040000 ) DDRD |= B00100000; // D5
if ( Ly[7] & 0x00080000 ) DDRD |= B01000000; // D6
if ( Ly[6] & 0x00100000 ) DDRD |= B10000000; // D7
if ( Ly[5] & 0x00100000 ) DDRB |= B00000001; // D8
if ( Ly[4] & 0x00200000 ) DDRB |= B00000010; // D9
if ( Ly[3] & 0x00200000 ) DDRB |= B00001000; // D11
if ( Ly[3] & 0x00080000 ) DDRB |= B00010000; // D12
if ( Ly[3] & 0x00020000 ) DDRC |= B00000001; // A0
if ( Ly[3] & 0x00008000 ) DDRC |= B00000010; // A1
if ( Ly[3] & 0x00002000 ) DDRC |= B00000100; // A2
if ( Ly[3] & 0x00000800 ) DDRC |= B00001000; // A3
DDRB |= B00000100; // Assign D10 to output
PORTB |= B00000100; // Set D10 to High (LED will light up)
}
void d11High() { // Output High from D11 and light the specified LED
if ( Ly[11] & 0x00002000 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x00004000 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x00008000 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x00010000 ) DDRD |= B00100000; // D5
if ( Ly[7] & 0x00020000 ) DDRD |= B01000000; // D6
if ( Ly[6] & 0x00040000 ) DDRD |= B10000000; // D7
if ( Ly[5] & 0x00040000 ) DDRB |= B00000001; // D8
if ( Ly[4] & 0x00080000 ) DDRB |= B00000010; // D9
if ( Ly[3] & 0x00100000 ) DDRB |= B00000100; // D10
if ( Ly[2] & 0x00080000 ) DDRB |= B00010000; // D12
if ( Ly[2] & 0x00020000 ) DDRC |= B00000001; // A0
if ( Ly[2] & 0x00008000 ) DDRC |= B00000010; // A1
if ( Ly[2] & 0x00002000 ) DDRC |= B00000100; // A2
if ( Ly[2] & 0x00000800 ) DDRC |= B00001000; // A3
DDRB |= B00001000; // Assign D11 to output
PORTB |= B00001000; // Set D11 to High (LED will light up)
}
void d12High() { // Output High from D12 and light the specified LED
if ( Ly[11] & 0x00000800 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x00001000 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x00002000 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x00004000 ) DDRD |= B00100000; // D5
if ( Ly[7] & 0x00008000 ) DDRD |= B01000000; // D6
if ( Ly[6] & 0x00010000 ) DDRD |= B10000000; // D7
if ( Ly[5] & 0x00010000 ) DDRB |= B00000001; // D8
if ( Ly[4] & 0x00020000 ) DDRB |= B00000010; // D9
if ( Ly[3] & 0x00040000 ) DDRB |= B00000100; // D10
if ( Ly[2] & 0x00100000 ) DDRB |= B00001000; // D11
if ( Ly[1] & 0x00080000 ) DDRC |= B00000001; // A0
if ( Ly[1] & 0x00020000 ) DDRC |= B00000010; // A1
if ( Ly[1] & 0x00008000 ) DDRC |= B00000100; // A2
if ( Ly[1] & 0x00002000 ) DDRC |= B00001000; // A3
DDRB |= B00010000; // Assign D12 to output
PORTB |= B00010000; // Set D12 to High (LED will light up)
}
void a0High() { // Outputs High from A0 and lights up the specified LED (turns the other port Low)
if ( Ly[11] & 0x00000200 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x00000400 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x00000800 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x00001000 ) DDRD |= B00100000; // D5
if ( Ly[7] & 0x00002000 ) DDRD |= B01000000; // D6
if ( Ly[6] & 0x00004000 ) DDRD |= B10000000; // D7
if ( Ly[5] & 0x00004000 ) DDRB |= B00000001; // D8
if ( Ly[4] & 0x00008000 ) DDRB |= B00000010; // D9
if ( Ly[3] & 0x00010000 ) DDRB |= B00000100; // D10
if ( Ly[2] & 0x00040000 ) DDRB |= B00001000; // D11
if ( Ly[1] & 0x00040000 ) DDRB |= B00010000; // D12
if ( Ly[0] & 0x00020000 ) DDRC |= B00000010; // A1
if ( Ly[0] & 0x00008000 ) DDRC |= B00000100; // A2
if ( Ly[0] & 0x00002000 ) DDRC |= B00001000; // A3
DDRC |= B00000001; // Assign A0 to output
PORTC |= B00000001; // A0 High. Now turn on the LED (do this last to minimize the amount of light)
}
void a1High() { // Outputs High from A0 and lights up the specified LED (turns the other port Low)
if ( Ly[11] & 0x00000080 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x00000100 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x00000200 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x00000400 ) DDRD |= B00100000; // D5
if ( Ly[7] & 0x00000800 ) DDRD |= B01000000; // D6
if ( Ly[6] & 0x00001000 ) DDRD |= B10000000; // D7
if ( Ly[5] & 0x00001000 ) DDRB |= B00000001; // D8
if ( Ly[4] & 0x00002000 ) DDRB |= B00000010; // D9
if ( Ly[3] & 0x00004000 ) DDRB |= B00000100; // D10
if ( Ly[2] & 0x00010000 ) DDRB |= B00001000; // D11
if ( Ly[1] & 0x00010000 ) DDRB |= B00010000; // D12
if ( Ly[0] & 0x00040000 ) DDRC |= B00000010; // A1
DDRC |= B00000010; // Assign A1 to output
PORTC |= B00000010; // A1 High. Now turn on the LED (do this last to minimize the amount of light)
}
void a2High() { // Outputs High from A0 and lights up the specified LED (turns the other port Low)
if ( Ly[11] & 0x00000020 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x00000040 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x00000080 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x00000100 ) DDRD |= B00100000; // D5
if ( Ly[7] & 0x00000200 ) DDRD |= B01000000; // D6
if ( Ly[6] & 0x00000400 ) DDRD |= B10000000; // D7
if ( Ly[5] & 0x00000400 ) DDRB |= B00000001; // D8
if ( Ly[4] & 0x00000800 ) DDRB |= B00000010; // D9
if ( Ly[3] & 0x00001000 ) DDRB |= B00000100; // D10
if ( Ly[2] & 0x00004000 ) DDRB |= B00001000; // D11
if ( Ly[1] & 0x00004000 ) DDRB |= B00010000; // D12
if ( Ly[0] & 0x00010000 ) DDRC |= B00000010; // A1
DDRC |= B00000100; // Assign A2 to output
PORTC |= B00000100; // A2 High. Now turn on the LED (do this last to minimize the amount of light)
}
void a3High() { // Outputs High from A0 and lights up the specified LED (turns the other port Low)
if ( Ly[11] & 0x00000008 ) DDRD |= B00000100; // D2
if ( Ly[10] & 0x00000010 ) DDRD |= B00001000; // D3
if ( Ly[9] & 0x00000020 ) DDRD |= B00010000; // D4
if ( Ly[8] & 0x00000040 ) DDRD |= B00100000; // D5
if ( Ly[7] & 0x00000080 ) DDRD |= B01000000; // D6
if ( Ly[6] & 0x00000100 ) DDRD |= B10000000; // D7
if ( Ly[5] & 0x00000100 ) DDRB |= B00000001; // D8
if ( Ly[4] & 0x00000200 ) DDRB |= B00000010; // D9
if ( Ly[3] & 0x00000400 ) DDRB |= B00000100; // D10
if ( Ly[2] & 0x00001000 ) DDRB |= B00001000; // D11
if ( Ly[1] & 0x00001000 ) DDRB |= B00010000; // D12
if ( Ly[0] & 0x00004000 ) DDRC |= B00000010; // A1
DDRC |= B00001000; // Assign A3 to output
PORTC |= B00001000; // A3 High. Now turn on the LED (do this last to minimize the amount of light)
}
The demo video in action is added below.
Attachments
Arduino sketch and schematic.zipReferences
The original project was published here and written in Japanese.
Top Comments