#include <Arduino.h>
#define CLK 13
#define DIN 11
#define CS 10
#define XS 8 // X Segments (8 wide)
#define YS 8 // Y Segments (8 high)
#define NUMS (XS * YS) // 64 total segments
#define BORDER 1
#define MAX_X (XS * 8) // 64 pixels wide
#define MAX_Y (YS * 8) // 64 pixels high
#define BALLS 120 // Increased number of balls
// Frame buffer is now 8 rows * 64 segments = 512 bytes
byte fb[8 * NUMS];
int bx[BALLS], by[BALLS], vx[BALLS], vy[BALLS], sz[BALLS];
// Combined Shift function for initialization
void sh(byte a, byte d) {
digitalWrite(CS, LOW);
// Send command to all 64 segments
for (int i = 0; i < NUMS; i++) {
shiftOut(DIN, CLK, MSBFIRST, a);
shiftOut(DIN, CLK, MSBFIRST, d);
}
digitalWrite(CS, HIGH);
}
// Set/Clear Pixel
void p(uint8_t x, uint8_t y, uint8_t m) {
byte *a = &fb[x / 8 + y * XS];
byte mask = 128 >> (x % 8);
if (m == 0) *a &= ~mask; else *a |= mask;
}
// Clear Framebuffer
void c() { for (byte i = 0; i < 8 * NUMS; i++) fb[i] = 0; }
void setup() {
pinMode(CLK, OUTPUT); pinMode(DIN, OUTPUT); pinMode(CS, OUTPUT);
// Initialize all 64 MAX7219 chips
sh(0x0f, 0x00); sh(0x0b, 0x07);
sh(0x0c, 0x01); sh(0x0a, 0x0f);
sh(0x09, 0x00);
c(); // Clear display
randomSeed(analogRead(A0));
for (int i = 0; i < BALLS; i++) {
bx[i] = random(BORDER, MAX_X - BORDER - 2);
by[i] = random(BORDER, MAX_Y - BORDER - 2);
vx[i] = random(-1, 2);
vy[i] = random(-1, 2);
sz[i] = random(1, 4);
}
}
void loop() {
// Move and Redraw Balls (Logic is unchanged, relies on new MAX_X/Y)
for (int i = 0; i < BALLS; i++) {
int s = sz[i];
// Erase
for (int dx = 0; dx < s; dx++)
for (int dy = 0; dy < s; dy++)
p(bx[i] + dx, by[i] + dy, 0);
// Update Position and Check Collision
bx[i] += vx[i]; by[i] += vy[i];
if (bx[i] >= MAX_X - BORDER - s || bx[i] < BORDER) vx[i] = -vx[i];
if (by[i] >= MAX_Y - BORDER - s || by[i] < BORDER) vy[i] = -vy[i];
// Draw
for (int dx = 0; dx < s; dx++)
for (int dy = 0; dy < s; dy++)
p(bx[i] + dx, by[i] + dy, 1);
}
// Show/Display Frame Buffer (Optimized for 8x8 segments)
for (byte r = 0; r < 8; r++) { // Iterate through the 8 rows
digitalWrite(CS, LOW);
// Loop through all 64 segments in reverse order
for (byte s = NUMS - 1; s < NUMS; s--) {
byte x = s % XS;
byte y_start = s / XS * 8; // Row address start (0, 8, 16, 24, 32, 40, 48, 56)
byte addr = (r + y_start) * XS; // Base address in fb
// Logic for zig-zag/alternatingly wired segments (critical for display)
if (s / XS % 2 == 0) { // Even segment rows (0, 2, 4, 6)
shiftOut(DIN, CLK, MSBFIRST, 1 + r); // MAX7219 row address (1-8)
shiftOut(DIN, CLK, MSBFIRST, fb[addr + x]); // Data for segment
} else { // Odd segment rows (1, 3, 5, 7) - Rotated 180 degrees
shiftOut(DIN, CLK, MSBFIRST, 8 - r); // MAX7219 row address (8-1)
shiftOut(DIN, CLK, LSBFIRST, fb[addr + x]); // Data for segment (LSBFIRST flip)
}
}
digitalWrite(CS, HIGH);
}
delay(1); // Small delay to control animation speed
}