#include <Arduino.h>
#include <math.h>
#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];
// 8x8 font for digits 0-9
const byte digit[10][8] = {
{0x3C,0x66,0x6E,0x76,0x66,0x66,0x3C,0x00}, // 0
{0x18,0x38,0x18,0x18,0x18,0x18,0x3C,0x00}, // 1
{0x3C,0x66,0x06,0x0C,0x18,0x30,0x7E,0x00}, // 2
{0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3
{0x0C,0x1C,0x3C,0x6C,0x7E,0x0C,0x1E,0x00}, // 4
{0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 5
{0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, // 6
{0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00}, // 7
{0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8
{0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00} // 9
};
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 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) { // odd rows
shiftOut(DIN, CLK, MSBFIRST, 8 - row);
shiftOut(DIN, CLK, LSBFIRST, fb[addr + x]);
} else { // even rows
shiftOut(DIN, CLK, MSBFIRST, 1 + row);
shiftOut(DIN, CLK, MSBFIRST, fb[addr - x + X_SEGMENTS - 1]);
}
}
digitalWrite(CS, HIGH);
}
}
void draw_digit(byte num, int x_offset, int y_offset) {
if (num > 9) return;
for (byte row = 0; row < 8; row++) {
byte rowdata = digit[num][row];
for (byte col = 0; col < 8; col++) {
byte pixel = (rowdata >> (7 - col)) & 0x01;
safe_pixel(x_offset + col, y_offset + row, pixel);
}
}
}
void setup() {
Serial.begin(115200);
pinMode(CLK, OUTPUT);
pinMode(DIN, OUTPUT);
pinMode(CS, OUTPUT);
shiftAll(0x0f, 0x00); // display test off
shiftAll(0x0b, 0x07); // scan limit 0-7
shiftAll(0x0c, 0x01); // normal operation
shiftAll(0x0a, 0x0f); // max brightness
shiftAll(0x09, 0x00); // no decode
clear();
show();
}
void loop() {
String input = "1234"; // default number to show
// If Wokwi Serial Monitor is used, override default
while (Serial.available()) {
char c = Serial.read();
if (c >= '0' && c <= '9') input += c;
}
clear();
int x = 0;
for (int i = 0; i < input.length(); i++) {
if (isDigit(input[i])) {
draw_digit(input[i] - '0', x, 0);
x += 8;
}
}
show();
delay(1000);
}(click to edit)