byte letterP[8] = {B00000000, B00111000, B00100100, B00100100, B00111000, B00100000, B00100000, B00000000 }; //P

byte letterE[8] = {B00000000, B00111100, B00100000, B00111000, B00111000, B00100000, B00111100, B00000000 }; //E

byte letterD[8] = {B00000000, B00111000, B00100100, B00100100, B00100100, B00100100, B00111000, B00000000 }; //D

byte letterR[8] = {B00000000, B00111000, B00100100, B00100100, B00111000, B00101000, B00100100, B00000000 }; //R

byte letterO[8] = {B00000000, B00011000, B00100100, B00100100, B00100100, B00100100, B00011000, B00000000 }; //0

P E

00000000 00000000

00000000 00000000

01111110 01111110

01001000 01011010

01001000 01011010

00110000 01000010

00000000 00000000

00000000 00000000

(These might need rotating 90 degrees counterclockwise)

You have code that does SPI.transfer's with data from displayArray[] every 1mS or something, yes?

So we'll just move data thru that array.

Make a 40 letter storage array:

displayStore[0] = letterP[0];

displayStore[1] = letterP[1];

displayStore[2] = letterP[2];

displayStore[3] = letterP[3];

displayStore[4] = letterP[4];

displayStore[5] = letterP[5];

displayStore[6] = letterP[6];

displayStore[7] = letterP[7];

displayStore[8] = letterE[0];

displayStore[9] = letterE[1];

displayStore[10] = letterE[2];

displayStore[11] = letterE[3];

displayStore[12] = letterE[4];

displayStore[13] = letterE[5];

displayStore[14] = letterE[6];

displayStore[15] = letterE[7];

displayStore[16] = letterD[0];

displayStore[17] = letterD[1];

displayStore[18] = letterD[2];

displayStore[19] = letterD[3];

displayStore[20] = letterD[4];

displayStore[21] = letterD[5];

displayStore[22] = letterD[6];

displayStore[23] = letterD[7];

displayStore[24] = letterR[0];

displayStore[25] = letterR[1];

displayStore[26] = letterR[2];

displayStore[27] = letterR[3];

displayStore[28] = letterR[4];

displayStore[29] = letterR[5];

displayStore[30] = letterR[6];

displayStore[31] = letterR[7];

displayStore[32] = letterO[0];

displayStore[33] = letterO[1];

displayStore[34] = letterO[2];

displayStore[35] = letterO[3];

displayStore[36] = letterO[4];

displayStore[37] = letterO[5];

displayStore[38] = letterO[6];

displayStore[39] = letterO[7];

displayStore[40] = 0;

displayStore[41] = 0;

displayStore[42] = 0;

displayStore[43] = 0;

displayStore[44] = 0;

displayStore[45] = 0;

displayStore[46] = 0;

displayStore[47] = 0;

And now every 1/2 second we'll move data from displayStore into displayArray to be shifted out:

currentStore = millis();

if (currentStore - previousStore >= elapsedStore){

previousStore = previous + elapsedStore;

storePointer = storePointer +1;

if (storePointer == 41){storePointer = 0;} // reset to start of storage

//loop thru the 8 columns

for (arrayPointer = 0; arrayPointer <8; arrayPointer = arrayPointer+1){

// and update the displayArray

displayArray[arrayPointer] = storeArray[storePointer +arrayPointer]; // so [0] = storePointer + 0, [1] = sP +1 ...

}

}

// now on next 1mS interval, the new data will get shifted out

There's better ways to do this, with the letter definitions being stored in program memory and accessed from there, but this gives you the basics of having an array that that gets put into the shift registers, and updating that array from somewhere else:

P E D R O blank...

123456712345671234567123456712345671234567

| | show these 8

| | then 1/2 second later these 8

| | then 1/2 second later these 8

| | and so on every 1/2 second

| | and after these go back to the beginning