0

Sorry for my code is long and my English is not good.

I'm working with 8x8x8 LED cube project using Arduino nano. I tried to understand code, but I don't understand how cube[][] data write on pins.

I just want to know, how write the data from cube[8][8] to hardware using SPI. code download using this link.

Thanks in advance.

My code is here :

#define AXIS_X 1
#define AXIS_Y 2
#define AXIS_Z 3
#define REFRESH_RATE 120
int CUBE_SIZE = 8;
int SPI_CS = 10;// This SPI Chip Select pin controls the MAX72xx
byte value[8];
volatile unsigned char cube[8][8];
volatile int current_layer = 0;
void setup()
{
 Serial.begin (115200);
 Serial.println("jolliFactory 8x8x8 jolliCube Demo example 1.0"); 
 pinMode(SPI_CS, OUTPUT);
 SPI.begin();
 maxTransferAll(0x0F, 0x00); // 00 - Turn off Test mode
 maxTransferAll(0x09, 0x00); // Register 09 - BCD Decoding // 0 = No decoding
 maxTransferAll(0x0B, 0x07); // Register B - Scan limit 1-7 // 7 = All LEDS
 maxTransferAll(0x0C, 0x01); // 01 = on 00 = Power saving mode or shutdown
 maxTransferAll(0x0A, 0x0F); // Set Brightness Intensity
 setUpInterrupts();
}
// Get the current status of a voxel
unsigned char getvoxel(int x, int y, int z)
{
 if (inrange(x,y,z))
 {
 if (cube[z][y] & (1 << x))
 {
 return 0x01;
 } else
 {
 return 0x00;
 }
 } else
 {
 return 0x00;
 }
}
void maxTransferAll(uint8_t address, uint8_t value)
{
 digitalWrite(SPI_CS, LOW); 
 for ( int c=1; c<= CUBE_SIZE;c++) {
 SPI.transfer(address);
 SPI.transfer(value);
 }
 digitalWrite(SPI_CS, HIGH); 
}
void maxTransferOne(uint8_t whichMax, uint8_t address, uint8_t value)
{
 byte noop_reg = 0x00; //max72xx No op register
 byte noop_value = 0x00; //value
 digitalWrite(SPI_CS, LOW); 
 for (int i=CUBE_SIZE; i>0; i--) // Loop through our number of Max72xx ICs 
 {
 if (i==whichMax)
 {
 SPI.transfer(address);
 SPI.transfer(value);
 }
 else
 {
 SPI.transfer(noop_reg);
 SPI.transfer(noop_value);
 }
 }
 digitalWrite(SPI_CS, HIGH);
}
void maxTransferLEDCube(uint8_t address)
{
 digitalWrite(SPI_CS, LOW); 
 for (int i=0; i<CUBE_SIZE; i++) // Loop through our number of Max72xx ICs 
 {
 SPI.transfer(address);
 SPI.transfer(value[CUBE_SIZE-i-1]);
 }
 digitalWrite(SPI_CS, HIGH);
}
void setUpInterrupts()
{
 cli();//stop interrupts while we set them up
 //set up an interrupt with timer1
 TCCR1A = 0;
 TCCR1B = 0;
 TCNT1 = 0;
 OCR1A = (16000000/REFRESH_RATE/1024/CUBE_SIZE -1);
 TCCR1B |= (1 << WGM12);
 // Set to CS10 and CS12 so we have the 1024
 TCCR1B |= (1 << CS12) | (1 << CS10); 
 TIMSK1 |= (1 << OCIE1A);
 sei();//re-allow interrupts 
}
ISR(TIMER1_COMPA_vect)
{ 
 for(byte y = 0 ; y < CUBE_SIZE ; y++)
 {
 byte b = 0;
 for(byte x = 0 ; x < CUBE_SIZE ; x++)
 {
 //form data byte
 b = b << 1;
 if (getvoxel(x,y,current_layer)==1)
 {
 b |= 1; 
 }
 }
 value[y] = b; 
 }
 maxTransferLEDCube(CUBE_SIZE - current_layer);
 current_layer++;
 if (current_layer == 8)
 current_layer = 0;
}
asked Jul 22, 2016 at 13:26

1 Answer 1

1

First, you need to know how the LEDs are arranged. There are 8 layers, each with 8 rows, each with 8 LEDs.

Each LED is represented as a single bit inside unsigned char cube[8][8]; - the first [8] is the array of layers, the second [8] is the array of rows, and the unsigned char holds 8 bits to represent the state of the 8 LEDs in that row.

Each LED layer has one MAX7219 8x8 LED Matrix Controller. To tell it what to do you need to give it a Command byte and a Data byte. So to tell it to light up LEDs 1, 2, and 7 on the fourth row, you need to tell it 0x04 0x86. You send this command by setting CS LOW, sending the 16 bits of the Command+Data, then setting CS HIGH.

Each MAX7219 is connected one after the other in an SPI string. To command all of them at once you need to set CS LOW, send 16 bits for each MAX7219 (128 bits in all), then set CS HIGH. If you only want to command one MAX7219, you need to send a NOP Command+Data (0x00 0x00) to all the others.

The way the program works is:

  1. setup()

    a. Initialise the Serial port, and print a message.
    b. Set the CS pin as an OUTPUT, then initialise SPI.
    c. Initialise all the MAX7219 chips by sending a series of commands -
    the same Command+Data to each of them (maxTransferAll()).
    d. Initialise the Timer interrupt (setUpInterrupts()).

  2. loop()
    This isn't shown in the code. Presumably it alters the cube[8][8] array to make the special effects.

  3. TIMER1_COMPA_vect (the interrupt handler)
    Every time the timer ticks, the handler will command all of the MAX7219s to show the next row of LEDs. This will last until the next timer tick, when the next row will be displayed. If this is done fast enough, the human eye's "persistence of vision" will not see the rows flickering.

    For each row (`y`) in the `cube` array
     Set `b` to 0
     For each bit ('x') in the `cube` data
     If the bit is set (`getvoxel(...)`) set a bit in `b`.
     Store `b` in the `value[y]` array
    

value now holds the bytes needed as Data for the next row for each of the MAX7219 chips.

 Send value over SPI using `maxTransferLEDCube(...)`

Since the cube displays the same row for each layer simultaneously, the Command doesn't have to change, only the Data does. That's what the value array holds: the Data to be sent to each MAX7219 chip.

answered Jul 22, 2016 at 14:30

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.