#define CLK 13
#define DIN 11
#define CS 10
#define X_SEGMENTS 4
#define Y_SEGMENTS 4
#define NUM_SEGMENTS (X_SEGMENTS * Y_SEGMENTS)
byte fb[8 * NUM_SEGMENTS];
byte mouthFrames[3][128] = {
{
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00010010, B00000000, B00000000, B01001000,
B00001100, B00000000, B00000000, B00110000,
B00000111, B11111111, B11111111, B11110000,
B00000011, B11111111, B11111111, B11100000,
B00000001, B11111111, B11111111, B11000000,
B00000000, B11111111, B11111111, B10000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000
},
{
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00010010, B00000000, B00000000, B01001000,
B00001100, B00000000, B00000000, B00110000,
B00000111, B11111111, B11111111, B11110000,
B00000011, B11111111, B11111111, B11100000,
B00000001, B11111111, B11111111, B11000000,
B00000000, B11111111, B11111111, B10000000,
B00000000, B01111111, B11111110, B00000000,
B00000000, B00011111, B11110000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000
},
{
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00010010, B00000000, B00000000, B01001000,
B00001100, B00000000, B00000000, B00110000,
B00000111, B11111111, B11111111, B11110000,
B00000011, B11111111, B11111111, B11100000,
B00000001, B11111111, B11111111, B11000000,
B00000000, B11111111, B11111111, B10000000,
B00000000, B01111111, B11111110, B00000000,
B00000000, B00011111, B11110000, B00000000,
B00000000, B00000000, B00000000, B00000000,
B00000000, B00000000, B00000000, B00000000
}
};
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 setup() {
Serial.begin(115200);
pinMode(CLK, OUTPUT);
pinMode(DIN, OUTPUT);
pinMode(CS, OUTPUT);
shiftAll(0x0f, 0x00);
shiftAll(0x0b, 0x07);
shiftAll(0x0c, 0x01);
shiftAll(0x0a, 0x0f);
shiftAll(0x09, 0x00);
clear();
drawRobotFace(0);
show();
}
void loop() {
for (int frame = 0; frame < 3; frame++) {
drawRobotFace(frame);
show();
delay(200);
}
}
void set_pixel(uint8_t x, uint8_t y, uint8_t mode) {
byte *addr = &fb[x / 8 + y * X_SEGMENTS];
byte mask = 128 >> (x % 8);
switch (mode) {
case 0:
*addr &= ~mask;
break;
case 1:
*addr |= mask;
break;
case 2:
*addr ^= mask;
break;
}
}
void safe_pixel(uint8_t x, uint8_t y, uint8_t mode) {
if ((x >= X_SEGMENTS * 8) || (y >= Y_SEGMENTS * 8))
return;
set_pixel(x, y, mode);
}
void clear() {
byte *addr = fb;
for (byte i = 0; i < 8 * NUM_SEGMENTS; i++)
*addr++ = 0;
}
void show() {
for (byte row = 0; row < 8; row++) {
digitalWrite(CS, LOW);
byte segment = NUM_SEGMENTS;
while (segment--) {
byte x = segment % X_SEGMENTS;
byte y = segment / X_SEGMENTS * 8;
byte addr = (row + y) * X_SEGMENTS;
if (segment & X_SEGMENTS) {
shiftOut(DIN, CLK, MSBFIRST, 8 - row);
shiftOut(DIN, CLK, LSBFIRST, fb[addr + x]);
} else {
shiftOut(DIN, CLK, MSBFIRST, 1 + row);
shiftOut(DIN, CLK, MSBFIRST, fb[addr - x + X_SEGMENTS - 1]);
}
}
digitalWrite(CS, HIGH);
}
}
void drawRobotFace(int frame) {
clear();
for (uint8_t y = 0; y < 32; y++) {
for (uint8_t x = 0; x < 32; x++) {
if (mouthFrames[frame][y * 4 + (x / 8)] & (1 << (7 - (x % 8)))) {
safe_pixel(x, y, 1);
}
}
}
}