#include <SPI.h>
IntervalTimer myTimer;
volatile uint8_t stripeRow = 0;
volatile uint16_t updateCnt = 0;
// Global constants
// ============================================================================
// SPI and and I2C communication parameters
//const uint8_t SPI_NUM_SLAVES = 8; // # panels which can be stacked
const uint8_t SPI_NUM_SLAVES = 2; // # panels which can be stacked
const uint8_t I2C_NUM_SLAVES = 4; // Four i2c slaves per panel
//const uint8_t SPI_PIN_ARRAY[SPI_NUM_SLAVES] = {2,5,6,7,8,9,3,4}; // SPI chip select lines
//const uint8_t SPI_PIN_ARRAY[SPI_NUM_SLAVES] = {2,4,5,6,7}; // SPI chip select lines
//const uint8_t SPI_PIN_ARRAY[SPI_NUM_SLAVES] = {2,4,5}; // SPI chip select lines
const uint8_t SPI_PIN_ARRAY[SPI_NUM_SLAVES] = {10,31}; // SPI chip select lines
const uint8_t I2C_TYPE_2_MSG_SIZE = 9;
const uint8_t I2C_TYPE_16_MSG_SIZE = 33;
const uint8_t SPI_TYPE_2_MSG_SIZE = 4*I2C_TYPE_2_MSG_SIZE;
const uint8_t SPI_TYPE_16_MSG_SIZE = 4*I2C_TYPE_16_MSG_SIZE;
EventResponder event;
EventResponder event1;
void Event_SPI0_Responder(EventResponderRef event_responder){
}
void Event_SPI1_Responder(EventResponderRef event_responder){
}
SPISettings settingsA(4200000, MSBFIRST, SPI_MODE0);
//pattern sent to the panels, it is bar moving from left to right
const uint8_t barBuffer[16][132] ={{1,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,1,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,1,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,1,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,1,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,1,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,1,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,1,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,1,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,1,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,1,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,1,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,1,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,1,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,1,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,1,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15,0,0,0,15},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,1,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240,0,0,0,240}};
// PWM type identifiers
const uint8_t PWM_TYPE_2 = 0;
const uint8_t PWM_TYPE_16 = 1;
//const uint8_t PWM_TYPE_MASK = 0x01;
// Counter used for updating to next pattern in buffer - sets stripe speed.
//const uint16_t PWM_UPDATE_CNT_TYPE_16 = 15;
const uint16_t PWM_UPDATE_CNT_TYPE_16 = 30;
const uint16_t PWM_UPDATE_CNT_TYPE_2 = 100;
// Display configuration parameters
const uint8_t MATRIX_NUM_ROW = 8;
const uint8_t MATRIX_NUM_COL = 8;
const uint8_t PANEL_NUM_ROW = 2*MATRIX_NUM_ROW;
// Timing parameters
const uint16_t LOOP_DELAY_TYPE_16 = 300; // us
const uint16_t LOOP_DELAY_TYPE_2 = 150; // us
// Demo pwm type
const uint8_t DEMO_PWM_TYPE = PWM_TYPE_16;
//const uint8_t DEMO_PWM_TYPE = PWM_TYPE_2;
// Function prototypes
// ============================================================================
// Display update demo functions
inline void type16DisplayUpdate();
// Arduino entry point functions
// ============================================================================
void setup()
{
Serial.begin(115200);
// Initialize SPI communications
for (uint8_t spiSlave=0; spiSlave < SPI_NUM_SLAVES; spiSlave++)
{
pinMode(SPI_PIN_ARRAY[spiSlave], OUTPUT);
digitalWrite(SPI_PIN_ARRAY[spiSlave], HIGH);
}
event.attachImmediate(&Event_SPI0_Responder);
event1.attachImmediate(&Event_SPI1_Responder);
SPI.usingInterrupt(myTimer);
SPI1.usingInterrupt(myTimer);
SPI.begin();
SPI1.begin();
SPI.beginTransaction(settingsA);
SPI1.beginTransaction(settingsA);
SPI.transfer(0);
SPI1.transfer(0);
//check the SPI speed
uint32_t wt;
uint32_t start;
uint32_t end;
while(!Serial);
Serial.print("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n");
Serial.flush();
delay(2);
start = millis();
while(start == millis());
//measure the SPI throughts on SPI0 and SPI1
for (uint16_t iteration=0; iteration<1000; iteration++)
{
digitalWrite(10, LOW);
//SPI.transfer(&barBuffer[stripeRow][0],nullptr,132);
SPI.transfer(&barBuffer[stripeRow][0],nullptr,132, event);
digitalWrite(10, HIGH);
digitalWrite(31, LOW);
//SPI1.transfer(&barBuffer[stripeRow][0],nullptr,132);
SPI1.transfer(&barBuffer[stripeRow][0],nullptr,132, event1);
digitalWrite(31, HIGH);
SPI.endTransaction();
SPI1.endTransaction();
}
end = millis();
wt = (end - start) - 1;
Serial.print("Time to write 132000 bytes:");
Serial.print(wt, DEC);
Serial.println("ms");
float bpms = 132000.0 / wt;
Serial.print(bpms, 0);
Serial.println("Bytes/msec");
//printf_P(PSTR("%f Bytes/msec\r\n%f Bytes/sec\r\n"), bpms, bpms * 1000);
myTimer.begin(type16DisplayUpdate, 1000); // type16DisplayUpdate to run every 1000 mseconds
}
void loop()
{
}
void type16DisplayUpdate()
{
SPI.beginTransaction(settingsA);
SPI1.beginTransaction(settingsA);
digitalWrite(10, LOW);
SPI.transfer(&barBuffer[stripeRow][0],nullptr,132, event);
//SPI.transfer(&barBuffer[stripeRow][0],nullptr,132);
digitalWrite(10, HIGH);
digitalWrite(31, LOW);
SPI1.transfer(&barBuffer[stripeRow][0],nullptr,132, event1);
//SPI1.transfer(&barBuffer[stripeRow][0],nullptr,132);
digitalWrite(31, HIGH);
// Update pattern information
updateCnt++;
if (updateCnt%PWM_UPDATE_CNT_TYPE_16 == 0)
{
stripeRow = (stripeRow + 1)%PANEL_NUM_ROW;
}
}