// This version uses bit-banged SPI.
// If you see tearing (jagged edges on the circles) try the version
// which uses AVR's hardware SPI peripheral:
// https://wokwi.com/arduino/projects/318868939929027156
#define CLK1 9
#define DIN1 11
#define CS 10
#define CLK2 8
#define DIN2 12
const int MAX_Y_SCREN=16;
const int MAX_X_SCREN=64;
const int SIN[]={0/*0degree*/,1/*90degree*/,0/*180degree*/,-1/*270degree*/};
const int COS[]={1/*0degree*/,0/*90degree*/,-1/*180degree*/,0/*270degree*/};
const byte Angle_0=0,Angle_90=1,Angle_180=2,Angle_270=3;
const static uint8_t System5x7[] PROGMEM =
{
// 0x0, 0x0, // size of zero indicates fixed width font, actual length is width * height
0x05, // width
0x07, // height
0x20, // first char
0x60, // char count
0X00,0X00,0X00,0X00,0X00,// (space)
0X00,0X00,0X5F,0X00,0X00,// !
0X00,0X07,0X00,0X07,0X00,// "
0X14,0X7F,0X14,0X7F,0X14,// #
0X12,0X2A,0X7F,0X2A,0X24,// $
0X62,0X64,0X08,0X13,0X23,// %
0X50,0X22,0X55,0X49,0X36,// &
0X00,0X00,0X03,0X05,0X00,// '
0X00,0X41,0X22,0X1C,0X00,// (
0X00,0X1C,0X22,0X41,0X00,// )
0X08,0X2A,0X1C,0X2A,0X08,// *
0X08,0X08,0X3E,0X08,0X08,// +
0X00,0X00,0X30,0X50,0X00,// ,
0X08,0X08,0X08,0X08,0X08,// -
0X00,0X00,0X60,0X60,0X00,// .
0X02,0X04,0X08,0X10,0X20,// /
0X3E,0X41,0X41,0X41,0X3E,// 0
0X00,0X40,0X7F,0X42,0X00,// 1
0X46,0X49,0X51,0X61,0X42,// 2
0X31,0X4B,0X45,0X41,0X21,// 3
0X10,0X7F,0X12,0X14,0X18,// 4
0X39,0X45,0X45,0X45,0X27,// 5
0X30,0X49,0X49,0X4A,0X3C,// 6
0X03,0X05,0X09,0X71,0X01,// 7
0X36,0X49,0X49,0X49,0X36,// 8
0X1E,0X29,0X49,0X49,0X06,// 9
0X00,0X00,0X36,0X36,0X00,// :
0X00,0X00,0X36,0X56,0X00,// ;
0X41,0X22,0X14,0X08,0X00,// <
0X14,0X14,0X14,0X14,0X14,// =
0X00,0X08,0X14,0X22,0X41,// >
0X06,0X09,0X51,0X01,0X02,// ?
0X3E,0X41,0X79,0X49,0X32,// @
0X7E,0X11,0X11,0X11,0X7E,// A
0X36,0X49,0X49,0X49,0X7F,// B
0X22,0X41,0X41,0X41,0X3E,// C
0X1C,0X22,0X41,0X41,0X7F,// D
0X41,0X49,0X49,0X49,0X7F,// E
0X01,0X01,0X09,0X09,0X7F,// F
0X32,0X51,0X41,0X41,0X3E,// G
0X7F,0X08,0X08,0X08,0X7F,// H
0X00,0X41,0X7F,0X41,0X00,// I
0X01,0X3F,0X41,0X40,0X20,// J
0X41,0X22,0X14,0X08,0X7F,// K
0X40,0X40,0X40,0X40,0X7F,// L
0X7F,0X02,0X04,0X02,0X7F,// M
0X7F,0X10,0X08,0X04,0X7F,// N
0X3E,0X41,0X41,0X41,0X3E,// O
0X06,0X09,0X09,0X09,0X7F,// P
0X5E,0X21,0X51,0X41,0X3E,// Q
0X46,0X29,0X19,0X09,0X7F,// R
0X31,0X49,0X49,0X49,0X46,// S
0X01,0X01,0X7F,0X01,0X01,// T
0X3F,0X40,0X40,0X40,0X3F,// U
0X1F,0X20,0X40,0X20,0X1F,// V
0X7F,0X20,0X18,0X20,0X7F,// W
0X63,0X14,0X08,0X14,0X63,// X
0X03,0X04,0X78,0X04,0X03,// Y
0X43,0X45,0X49,0X51,0X61,// Z
0X41,0X41,0X7F,0X00,0X00,// [
0X20,0X10,0X08,0X04,0X02,// \
0X00,0X00,0X7F,0X41,0X41,// ]
0X04,0X02,0X01,0X02,0X04,// ^
0X40,0X40,0X40,0X40,0X40,// _
0X00,0X04,0X02,0X01,0X00,// `
0X78,0X54,0X54,0X54,0X20,// a
0X38,0X44,0X44,0X48,0X7F,// b
0X20,0X44,0X44,0X44,0X38,// c
0X7F,0X48,0X44,0X44,0X38,// d
0X18,0X54,0X54,0X54,0X38,// e
0X02,0X01,0X09,0X7E,0X08,// f
0X3C,0X54,0X54,0X14,0X08,// g
0X78,0X04,0X04,0X08,0X7F,// h
0X00,0X40,0X7D,0X44,0X00,// i
0X00,0X3D,0X44,0X40,0X20,// j
0X44,0X28,0X10,0X7F,0X00,// k
0X00,0X40,0X7F,0X41,0X00,// l
0X78,0X04,0X18,0X04,0X7C,// m
0X78,0X04,0X04,0X08,0X7C,// n
0X38,0X44,0X44,0X44,0X38,// o
0X08,0X14,0X14,0X14,0X7C,// p
0X7C,0X18,0X14,0X14,0X08,// q
0X08,0X04,0X04,0X08,0X7C,// r
0X20,0X54,0X54,0X54,0X48,// s
0X20,0X40,0X44,0X3F,0X04,// t
0X7C,0X20,0X40,0X40,0X3C,// u
0X1C,0X20,0X40,0X20,0X1C,// v
0X3C,0X40,0X30,0X40,0X3C,// w
0X44,0X28,0X10,0X28,0X44,// x
0X3C,0X50,0X50,0X50,0X0C,// y
0X44,0X4C,0X54,0X64,0X44,// z
0X00,0X41,0X36,0X08,0X00,// {
0X00,0X00,0X7F,0X00,0X00,// |
0X00,0X08,0X36,0X41,0X00,// }
0X08,0X1C,0X2A,0X08,0X08,//->
0x08,0x08,0x2A,0x1C, 0x08// <-
};
const static uint8_t System7x12[] PROGMEM = {
0x0C, // Y_SIZE
0x07, // X_SIZE
0x30, // first char
0x0B, //char count
0x1C,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C, // Code for char num 48
0x18,0x1E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // Code for char num 49
0x3E,0x63,0x61,0x60,0x60,0x30,0x18,0x0C,0x06,0x03,0x03,0x7F, // Code for char num 50
0x3E,0x63,0x61,0x60,0x60,0x3C,0x60,0x60,0x60,0x61,0x63,0x3E, // Code for char num 51
0x30,0x30,0x38,0x38,0x3C,0x36,0x36,0x33,0x7F,0x30,0x30,0x30, // Code for char num 52
0x7F,0x03,0x03,0x03,0x3F,0x63,0x60,0x60,0x60,0x61,0x63,0x3E, // Code for char num 53
0x3C,0x06,0x03,0x03,0x03,0x3F,0x63,0x63,0x63,0x63,0x63,0x3E, // Code for char num 54
0x7F,0x60,0x60,0x30,0x30,0x18,0x18,0x18,0x0C,0x0C,0x0C,0x0C, // Code for char num 55
0x3E,0x63,0x63,0x63,0x63,0x3E,0x63,0x63,0x63,0x63,0x63,0x3E, // Code for char num 56
0x3E,0x63,0x63,0x63,0x63,0x63,0x7E,0x60,0x60,0x60,0x30,0x1E, // Code for char num 57
0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x03 // Code for char num 58
};
byte scren[16][8];
void shiftAll(byte send_to_address, byte send_this_data){
digitalWrite(CS, LOW);
for (int SEGMENTS = 0; SEGMENTS <8;SEGMENTS++) {
shiftOut(DIN1, CLK1, MSBFIRST, send_to_address);
shiftOut(DIN1, CLK1, MSBFIRST, send_this_data);
shiftOut(DIN2, CLK2, MSBFIRST, send_to_address);
shiftOut(DIN2, CLK2, MSBFIRST, send_this_data);
}
digitalWrite(CS, HIGH);
}
void display_scren(){
for (int segmen_width =1; segmen_width<9;segmen_width++) {//y
int segmen_scren1 =(16-segmen_width);
int segmen_scren2 =(8-segmen_width);
digitalWrite(CS, LOW);
for (int segmen_length = 0; segmen_length<8;segmen_length++) {//x
shiftOut(DIN1, CLK1, MSBFIRST,segmen_width);
shiftOut(DIN1, CLK1, MSBFIRST, scren[segmen_scren1][segmen_length]);
shiftOut(DIN2, CLK2, MSBFIRST,segmen_width);
shiftOut(DIN2, CLK2, MSBFIRST,scren[segmen_scren2][segmen_length]);
}
digitalWrite(CS, HIGH);
}
}
void setup() {
Serial.begin(115200);
pinMode(CLK1, OUTPUT);
pinMode(DIN1, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(CLK2, OUTPUT);
pinMode(DIN2, 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
font_set(System5x7);
for(int num='0';num<='9';num++){
for(int Angle=Angle_0;Angle<=Angle_270;Angle++){
Write_char(0,0,num,Angle);
display_scren();delay(1000);
Write_char(0,0,' ',Angle);
}
}
}
void loop(){
}
void write_pixcel(int x, int y, byte pixcel){
int x_addr_byte = x/8;
int x_addr_pix =x%8;
bitWrite(scren[y][x_addr_byte], x_addr_pix, pixcel);
}
byte Y_pixel_size;
byte X_pixel_size;
int X_SIZE_BYTE;
byte X_SIZE_BIT;
int Y_SIZE_BYTE;
byte start_char;
byte stop_char;
int size_font;
int start_add_font;
void font_set(int font){
Y_pixel_size=pgm_read_byte_near(font);
X_pixel_size=pgm_read_byte_near(font+1);
start_char=pgm_read_byte_near(font+2);
stop_char=start_char+pgm_read_byte_near(font+3)-1;
X_SIZE_BYTE=(X_pixel_size/8);
if((X_pixel_size%8)>0){X_SIZE_BYTE+=1;}
size_font=Y_pixel_size*X_SIZE_BYTE;
start_add_font=4+font;
}
void Write_char(int x,int y,char CHAR,byte Angle){
int startAdd_char_forFont = (CHAR-start_char)*size_font;
startAdd_char_forFont +=start_add_font;
int Y_SCROLL=(X_pixel_size*SIN[Angle])+(Y_pixel_size*COS[Angle]);
int X_SCROLL=(X_pixel_size*COS[Angle])-(Y_pixel_size*SIN[Angle]);
byte data_char1Byte=0;
if(X_SCROLL<0){X_SCROLL=abs(X_SCROLL)-1+x;}
else{X_SCROLL=x;}
if(Y_SCROLL<0){Y_SCROLL=abs(Y_SCROLL)+y-1;}
else{Y_SCROLL=y;}
for (int Y_add_char=0;Y_add_char<Y_pixel_size;Y_add_char++){
int X_SCREN=0, Y_SCREN =0, X_CHAR=0, Y_CHAR=Y_add_char;
int add_char_read_flash=((Y_pixel_size-Y_add_char-1)*X_SIZE_BYTE)+startAdd_char_forFont;
byte X_max_add_char=X_SIZE_BYTE-1;
for (int X_add_char=0;X_add_char<X_SIZE_BYTE;X_add_char++){
add_char_read_flash+=X_add_char;
if(CHAR<start_char||CHAR>stop_char)data_char1Byte=0;
else data_char1Byte=pgm_read_byte_near(add_char_read_flash);
if(X_add_char==X_max_add_char){X_SIZE_BIT=X_pixel_size%8;}
else{X_SIZE_BIT=8;}
for(int X_pixel_char=0;X_pixel_char<X_SIZE_BIT;X_pixel_char++){
Y_SCREN= (X_CHAR*SIN[Angle])+(Y_CHAR*COS[Angle])+Y_SCROLL;
X_SCREN= (X_CHAR*COS[Angle])-(Y_CHAR*SIN[Angle])+X_SCROLL;
if(Y_SCREN>-1&&X_SCREN>-1&&Y_SCREN<MAX_Y_SCREN&&X_SCREN<MAX_X_SCREN){
byte X_BYTE_SCREN=X_SCREN/8;
byte X_BIT_SCREN=X_SCREN%8;
bitWrite(scren[Y_SCREN][X_BYTE_SCREN],X_BIT_SCREN,bitRead(data_char1Byte,X_pixel_char));
}
X_CHAR+=1;
}
}
}
}
void Set_char(int x,int y,char CHAR,byte Angle){
int startAdd_char_forFont = (CHAR-start_char)*size_font;
startAdd_char_forFont +=start_add_font;
int Y_SCROLL=(X_pixel_size*SIN[Angle])+(Y_pixel_size*COS[Angle]);
int X_SCROLL=(X_pixel_size*COS[Angle])-(Y_pixel_size*SIN[Angle]);
byte data_char1Byte=0;
if(X_SCROLL<0){X_SCROLL=abs(X_SCROLL)+x-1;}
else{X_SCROLL=x;}
if(Y_SCROLL<0){Y_SCROLL=abs(Y_SCROLL)+y-1;}
else{Y_SCROLL=y;}
for (int Y_add_char=0;Y_add_char<Y_pixel_size;Y_add_char++){
int X_SCREN=0, Y_SCREN =0, X_CHAR=0, Y_CHAR=Y_add_char;
int add_char_read_flash=((Y_pixel_size-Y_add_char-1)*X_SIZE_BYTE)+startAdd_char_forFont;
byte X_max_add_char=X_SIZE_BYTE-1;
for (int X_add_char=0;X_add_char<X_SIZE_BYTE;X_add_char++){
add_char_read_flash+=X_add_char;
if(CHAR<start_char||CHAR>stop_char)data_char1Byte=0;
else data_char1Byte=pgm_read_byte_near(add_char_read_flash);
if(X_add_char==X_max_add_char){X_SIZE_BIT=X_pixel_size%8;}
else{X_SIZE_BIT=8;}
for(int X_pixel_char=0;X_pixel_char<X_SIZE_BIT;X_pixel_char++){
if(bitRead(data_char1Byte,X_pixel_char)>0){
Y_SCREN= (X_CHAR*SIN[Angle])+(Y_CHAR*COS[Angle])+Y_SCROLL;
X_SCREN= (X_CHAR*COS[Angle])-(Y_CHAR*SIN[Angle])+X_SCROLL;
if(Y_SCREN>-1&&X_SCREN>-1&&Y_SCREN<MAX_Y_SCREN&&X_SCREN<MAX_X_SCREN){
byte X_BYTE_SCREN=X_SCREN/8;
byte X_BIT_SCREN=X_SCREN%8;
bitSet(scren[Y_SCREN][X_BYTE_SCREN],X_BIT_SCREN);
}
}
X_CHAR+=1;
}
}
}
}