#define CLK 13
#define DIN 11
#define CS 10
#define X_SEGMENTS 4
#define Y_SEGMENTS 4
#define NUM_SEGMENTS (X_SEGMENTS * Y_SEGMENTS)
// a framebuffer to hold the state of the entire matrix of LEDs
// laid out in raster order, with (0, 0) at the top-left
byte fb[8 * NUM_SEGMENTS];
const int ukHrf = 8;
// Define character data for "O" and "k"
const byte O_data[ukHrf] = {
0b00111100,
0b01000010,
0b10000001,
0b10000001,
0b10000001,
0b10000001,
0b01000010,
0b00111100
};
const byte K_data[8] = {
0b10000000,
0b10000000,
0b10010000,
0b10100000,
0b11000000,
0b10100000,
0b10010000,
};
void set_pixel(uint8_t x, uint8_t y, uint8_t mode) {
byte *addr = &fb[x / ukHrf + y * X_SEGMENTS];
byte mask = 128 >> (x % ukHrf);
switch (mode) {
case 0: // clear pixel
*addr &= ~mask;
break;
case 1: // plot pixel
*addr |= mask;
break;
case 2: // XOR pixel
*addr ^= mask;
break;
}
}
void shiftAll(byte send_to_address, byte send_this_data)
{
digitalWrite(CS, LOW);
for (int i = 0; i < NUM_SEGMENTS; i++) {
shiftOut(DIN, CLK, MSBFIRST, send_to_address);
shiftOut(DIN, CLK, MSBFIRST, send_this_data);
}
digitalWrite(CS, HIGH);
}
void safe_pixel(uint8_t x, uint8_t y, uint8_t mode) {
if ((x >= X_SEGMENTS * ukHrf) || (y >= Y_SEGMENTS * ukHrf))
return;
set_pixel(x, y, mode);
}
void setup() {
Serial.begin(115200);
pinMode(CLK, OUTPUT);
pinMode(DIN, OUTPUT);
pinMode(CS, OUTPUT);
// Setup each MAX7219
shiftAll(0x0f, 0x00); //display test register - test mode off
shiftAll(0x0b, 0x07); //scan limit register - display digits 0 thru 7
shiftAll(0x0c, 0x01); //shutdown register - normal operation
shiftAll(0x0a, 0x0f); //intensity register - max brightness
shiftAll(0x09, 0x00); //decode mode register - No decode
}
void clear() {
byte *addr = fb;
for (byte i = 0; i < ukHrf * NUM_SEGMENTS; i++)
*addr++ = 0;
}
void show() {
for (byte row = 0; row < ukHrf; row++) {
digitalWrite(CS, LOW);
byte segment = NUM_SEGMENTS;
while (segment--) {
byte x = segment % X_SEGMENTS;
byte y = segment / X_SEGMENTS * ukHrf;
byte addr = (row + y) * X_SEGMENTS;
if (segment & X_SEGMENTS) { // odd rows of segments
shiftOut(DIN, CLK, MSBFIRST, ukHrf - row);
shiftOut(DIN, CLK, LSBFIRST, fb[addr + x]);
} else { // even rows of segments
shiftOut(DIN, CLK, MSBFIRST, 1 + row);
shiftOut(DIN, CLK, MSBFIRST, fb[addr - x + X_SEGMENTS - 1]);
}
}
digitalWrite(CS, HIGH);
}
}
void loop() {
clear();
// Define starting positions for characters
int x_offset_O = 0;
int y_offset_O = 0;
int x_offset_k = x_offset_O+ukHrf;
int y_offset_k = y_offset_O;
// Draw "O" character
for (int y = 0; y < ukHrf; y++) {
byte data = O_data[y];
for (int x = 0; x < ukHrf; x++) {
if (data & (1 << ((ukHrf-1) - x))) {
safe_pixel(x_offset_O + x, y_offset_O + y, 1);
}
}
}
// Draw "k" character
for (int y = 0; y < ukHrf; y++) {
byte data = K_data[y];
for (int x = 0; x < (ukHrf); x++) { // Adjust for the width of "k"
if (data & (1 << ((ukHrf) - x))) {
safe_pixel(x_offset_k + x, y_offset_k + y, 1);
}
}
}
show();
delay(1000);
}