const int N_ROW = 12;
const int N_COL = 16;

// bitmasks for the colors
const unsigned long RGB_MASKS[] = {0b00001001001001001001001001001001, // RED
				   0b00010010010010010010010010010010, // GREEN
				   0b11100100100100100100100100100100}; // BLUE
const unsigned long   *RED = &RGB_MASKS[0];
const unsigned long *GREEN = &RGB_MASKS[1];
const unsigned long  *BLUE = &RGB_MASKS[2];
uint32_t* buffer;

// Modified from Peggy2.cpp
unsigned char SPI_TX(char cData)
{
  SPDR = cData;
  //Wait for transmission complete:
  while (!(SPSR & _BV(SPIF))) ;
  return SPDR;
} 
// Modified from Peggy2.cpp
void RefreshAllFast(unsigned int refreshNum){ 
  unsigned int refresh_k;
  unsigned char col_j;
  unsigned char rgb_i;
  
  union mix_t {
    unsigned long atemp; 
    unsigned char c[4];
  } mix;
  
  refresh_k = 0;
  while (refresh_k != refreshNum){
    refresh_k++;
    col_j = 0;
    while (col_j < N_COL){
      rgb_i = 0;
      while(rgb_i < 3){
	if (col_j == 0)
	  PORTD = 160; // why 160?
	else
	  PORTD = col_j;
	  
	mix.atemp = buffer[col_j] & RGB_MASKS[rgb_i];
delay(500);
      
	SPI_TX(mix.c[3]);
	SPI_TX(mix.c[2]);
	SPI_TX(mix.c[1]);
	
	//PORTD = 32;  // Turn displays off
 
	SPI_TX(mix.c[0]); 
	PORTB |= 2U;    //Latch Pulse 
	PORTB &= 253U;
	rgb_i++;
      }
      col_j++;
    }
  }
}

void setup(){
  pinMode(8, OUTPUT);
  buffer = (uint32_t*)calloc(N_COL, sizeof(uint32_t));
  memset(buffer, 255, N_COL*sizeof(uint32_t)); // ALL ON: WHITE

  PORTD = 0U;
  DDRD = 255U;
  
  ////SET MOSI, SCK Output, all other SPI as input: 
  DDRB |= _BV(5) | _BV(3) | _BV(2) | _BV(1);
  
  //ENABLE SPI, MASTER, CLOCK RATE fck/4:  
  SPCR =  _BV(SPE) |  _BV(MSTR) ;
  
  //  Flush SPI LED drivers::
  SPI_TX(0);
  SPI_TX(0);
  SPI_TX(0);
  SPI_TX(0);

  PORTB |= 2;    //Latch Pulse 
  PORTB &= 253;  

}
void loop(){
  RefreshAllFast(1);
}
