Mega multiplexing with a Mega 2560

I have been building 5x5 multiplexed light boxes that are sound activated, and they work very well, lot's of fun. I'm using a different color per box, and building custom boards for each one, using a nano v3 for operation, 9v/1A pSU for each one as well.
I would like to put 4 boards on 1 Mega, according to my rudimentary calculations, I have the power, the pins available, pretty much ready to go , but..
Do I write my code as if it were one big array 20 and 20 pins respectively, or can/should I create 4 different arrays 5 and 5 pins per box? Can it even be done the way I think? I don't want to use shift registers because I don't think I need any more parts than necessary, but that could be wrong, and I have 1 box of Red lights so extending the circuits would run me afoul of resistors.
I'm not looking for easy, I'm looking for elegance and function, I'm a newer user but not a noob to the whole thing, any ideas would be appreciated, I'll post the code as soon as I fiugre that out, duh :slight_smile:
Bob

Here is the code I use,
Bob

/*
 * Show animations on a DIMxDIM led matrix
 *
 * Uses Timer1 library to
 * constantly run an interrupt routine
 * at a specified frequency. This
 * refreshes the display without the
 * main loop having to do anything.
 *
 * created by Sam Lin lincomatic@hotmail.com 2/2011
 *
 */
#include <TimerOne.h>

//#define TESTMODE // continuously sequence thru the LED's 
//#define BLINKY // blink LED on pin 13

#define SENSOR_PIN A0 // analog input pin for music
#ifdef BLINKY
#define LED_PIN 13 // digital output pin for LED
#endif // BLINKY

// trigger next frame when music amplitude > threshold
// increase threshold to decrease sensitivity
// decrease threshold to increase sensitivity
int threshold = 5;
// debouncing - filter out consecutive triggers that are too close
// together to slow down the animation.  decrease this value
// to make it more sensitive to shorter beat intervals
int minBeatInterval = 128;

// musicSync =1= sync to music
//           =0= use timer
int musicSync = 1;

// time between frames in ms when musicSync == 0
int frameDelay = 350;


int threshCrossed = 0;

#define DIM 5 // x/y dimension - 5x5 matrix
#define DIM1 (DIM-1)

typedef byte Frame[DIM];

#include "frames.h"

byte row = 0;
byte *curFrame;
int curFrameIdx;

// col[xx] of leds - anodes
// these are the arduino pins assigned to each column
int cols[DIM] = {12,11,10,9,8};

// row[xx] of leds - cathodes
// these are the arduino pins assigned to each row
int rows[DIM] = {7,6,5,4,3};

Frame blankFrame =
{B00000,
 B00000,
 B00000,
 B00000,
 B00000};

// blank the screen
void clearLeds() {
  // blank screen
  curFrame = blankFrame;
}

// select a frame to display
// idx = 0 -> FRAMDECNT-1
void setFrame(int idx) {
  noInterrupts();
  curFrame = Frames[idx];
  interrupts();
}

// Interrupt routine
// each time display() is called, it turns off the previous row
// and turns on the next row
byte bitMask = B00000011;
void display() {
  digitalWrite(rows[row], HIGH);  // Turn whole previous row off

  if (bitMask == B00010000) {
    bitMask = B00000011;  // light the right 2 columns (pins 9,8)
    // increment row and wrap if necessary
    if (++row == DIM) {
      row = 0;
    }
  }
  else if (bitMask == B00000011) {
    bitMask = B00001100;  // light the middle 2 columns (pins 11,10)
  }
  else { // bitMaskIdx == B00001100
    bitMask = B00010000;  // light the leftmost column (pin 12)
  }
  
  // direct port manipulation.
  // PORTB is a pseudo variable for digital pins 8 to 13 The two high bits (6 & 7) map to the crystal pins and are not usable
  // the bottom 5 bits are our columns.  We don't want to change the other bits,
  // so we first mask the bits we ignore, and then set the bits we want to light
  PORTB &= B11100000;
  PORTB |= curFrame[row] & bitMask;
  
  digitalWrite(rows[row], LOW); // Turn whole row on at once (for equal lighting times)
}


void setup() {
  int i;

#if defined(BLINKY)
  pinMode(LED_PIN, OUTPUT);  // setup LED pin for output
#endif // BLINKY
  
  // sets the pins as output
  for (i = 0; i < DIM; i++) {
    pinMode(cols[i], OUTPUT);
    pinMode(rows[i], OUTPUT);
  }

  // set up cols and rows (set display to dark)
  for (i = 0; i < DIM; i++) {
    digitalWrite(cols[i], LOW);
  }

  for (i = 0; i < DIM; i++) {
    digitalWrite(rows[i], HIGH);
  }


  clearLeds();
  
#ifdef TESTMODE  
  while (1) {
  for (i=0;i < DIM;i++) {
    digitalWrite(rows[i],LOW);
    for (int j=0;j < DIM;j++) {
      digitalWrite(cols[j],HIGH);
      delay(250);
      digitalWrite(cols[j],LOW);
    }
    digitalWrite(rows[i],HIGH);
  }
  }
#else // !TESTMODE
  // interrupt interval in uSec
  // this determines how long to keep each row turned on
  // so if we have 5 rows, we redraw the whole screen
  // once every 5 rows * 3 cycles per row * 1000 usec = .015 sec -> 66.67Hz
  // if you perceive flickering you can decrease to 500 for a 133.33Hz rate
  Timer1.initialize(500);
  
  Timer1.attachInterrupt(display); // ISR

  curFrameIdx = -1;
#endif // TESTMODE
                                                 
}

int cnt = 32768;
void loop() {
  if (musicSync) {
    // read the value from the sensor:
    int sensorValue = analogRead(SENSOR_PIN);
    cnt++;
    
    if (sensorValue > threshold) {
      if (!threshCrossed && (cnt > minBeatInterval) ) {
	threshCrossed = 1;
	cnt = 0;
	
	// increment the frame index and wrap if necessary
	if (++curFrameIdx == FRAMECNT) {
	  curFrameIdx = 0;
	}
	
	// select frame for display
	setFrame(curFrameIdx);
      }
#if defined(BLINKY)
    digitalWrite(LED_PIN,HIGH);
#endif // BLINKY
    }
    else { // below threshold
#if defined(BLINKY)
      digitalWrite(LED_PIN,LOW); // turn off LED
#endif // BLINKY
      if (threshCrossed) {
	threshCrossed = 0;
      }
    }
  }
  else { // !musicSync
    // increment the frame index and wrap if necessary
    if (++curFrameIdx == FRAMECNT) {
      curFrameIdx = 0;
    }
    
    // select frame for display
    setFrame(curFrameIdx);
    
    delay(frameDelay); // wait time between frames in ms
  }
}