Hello!
Using arduino pro mini 5V 16Mhz,but can test with arduino UNO as well.
Arduino IDE 2.3.2
Daisy chained 74595 shift registers.
So, I got basic code working, and prime goal for now is to create class from the code, just so all irrelevant functions could be called; as I believe is one of reasons to create class in first place. Now then, actually making class didn't pose problem, but what I can't understand is severe framerate drop. I'm planning on making this library to act as both software SPI and hardware SPI, depending on constructor, which I succeeded already, but without getting too sidetracked too much....gotta deal with this framerate drop first. Framerate drop is severe enough so I can see matrix flicker, which is big no for led display obviously. The code has flaw about possible ghosting, but that issue is easy to fix once it happens.
I don't have any actual measurements/data about framerate drop, but I can get them if needed.
Also fontmap is not yet read from flash, It's on the to-do-list as well.
Actual codes;
Fontmap.h
//<-LEFTMOST COLUMN
//LSB=uppest dot
byte ledMatrixFont_8x8 [1008] = //numbers stored here
{ //Position, Character
B00000000, B00000000, B00111110, B01010001, B01001001, B01000101, B00111110, B00000000, // 0 0
B00000000, B00000000, B01000100, B01000010, B01111111, B01000000, B01000000, B00000000, // 1 1
B00000000, B00000000, B01100010, B01010001, B01001001, B01001001, B01000110, B00000000, // 2 2
B00000000, B00000000, B00100010, B01000001, B01001001, B01001001, B00110110, B00000000, // 3 3
B00000000, B00000000, B00011000, B00010100, B00010010, B01111111, B00010000, B00000000, // 4 4
B00000000, B00000000, B00100111, B01000101, B01000101, B01000101, B00111001, B00000000, // 5 5
B00000000, B00000000, B00111100, B01001010, B01001001, B01001001, B00110000, B00000000, // 6 6
B00000000, B00000000, B00000001, B01110001, B00001001, B00000101, B00000011, B00000000, // 7 7
B00000000, B00000000, B00110110, B01001001, B01001001, B01001001, B00110110, B00000000, // 8 8
B00000000, B00000000, B00000110, B01001001, B01001001, B00101001, B00011110, B00000000, // 9 9
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 10 /n
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 11
0x81, B01000010, B00000000, B00011000, B00011000, B00000000, B01000010, 0x01, // 12
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 13 /r ALIENI
B00000000, B00011000, 0x28, 0x48, 0xfe, 0x08, B00000000, B00000000, // 14
B00000000, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, B00000000, B00000000, // 15
B00000000, 0x3c, B01010010, 0x92, 0x92, 0x0c, B00000000, B00000000, // 16
B00000000, 0x80, 0x8e, 0x90, 0xa0, 0xc0, B00000000, B00000000, // 17
B00000000, 0x6c, 0x92, 0x92, 0x92, 0x6c, B00000000, B00000000, // 18
B00000000, 0x60, 0x92, 0x92, 0x94, B01111000, B00000000, B00000000, // 19
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 20
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // 21
0x81, B01000010, B00000000, B00011000, B00011000, B00000000, B01000010, 0x01, // 22
B00000000, 0x84, 0x82, 0xa2, 0xd2, 0x8c, B00000000, B00000000, // 23
B00000000, B00011000, 0x28, 0x48, 0xfe, 0x08, B00000000, B00000000, // 24
B00000000, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, B00000000, B00000000, // 25
B00000000, 0x3c, B01010010, 0x92, 0x92, 0x0c, B00000000, B00000000, // 26
B00000000, 0x80, 0x8e, 0x90, 0xa0, 0xc0, B00000000, B00000000, // 27 /esc
B00000000, 0x6c, 0x92, 0x92, 0x92, 0x6c, B00000000, B00000000, // 28
B00000000, 0x60, 0x92, 0x92, 0x94, B01111000, B00000000, B00000000, // 29
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 30
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // 31
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 32 "space"
B00000000, B00000000, B00000000, 0xFB, 0xFB, B00000000, B00000000, B00000000, // 33 !
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 34 "
B00000000, B00000000, B00010100, B01111111, B00010100, B01111111, B00010100, B00000000, // 35 #
B00000000, B00000000, B00100100, B00101010, B01111111, B00101010, B00010010, B00000000,// 36 $
B00000000, B00000000, B00100011, B00010011, B00001000, B01100100, B01100010, B00000000, // 37 %
B00000000, B00000000, B00110110, B01001001, B01010101, B00100010, B01010000, B00000000, // 38 &
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 39 '
B00000000, B00000000, B00000000, B00011100, B00100010, B01000001, B00000000, B00000000, // 40 (
B00000000, B00000000, B00000000, B01000001, B00100010, B00011100, B00000000, B00000000, // 41 )
B00000000, B00000000, B00101000, B00010000, B01111100, B00010000, B00101000, B00000000, // 42 *
B00000000, B00000000, B00010000, B00010000, B01111100, B00010000, B00010000, B00000000, // 43 +
B00000000, B00000000, B00000000, B01010000, B00110000, B00000000, B00000000, B00000000, // 44 ,
B00000000, B00000000, B00010000, B00010000, B00010000, B00010000, B00010000, B00000000, // 45 -
B00000000, B00000000, B01100000, B01100000, B00000000, B00000000, B00000000, B00000000, // 46 .
B00000000, B00000000, B01000000, B00100000, B00010000, B00001000, B00000100, B00000000,// 47 /
B00000000, B00000000, B00111110, B01010001, B01001001, B01000101, B00111110, B00000000, // 0 0
B00000000, B00000000, B01000100, B01000010, B01111111, B01000000, B01000000, B00000000, // 1 1
B00000000, B00000000, B01100010, B01010001, B01001001, B01001001, B01000110, B00000000, // 2 2
B00000000, B00000000, B00100010, B01000001, B01001001, B01001001, B00110110, B00000000, // 3 3
B00000000, B00000000, B00011000, B00010100, B00010010, B01111111, B00010000, B00000000, // 4 4
B00000000, B00000000, B00100111, B01000101, B01000101, B01000101, B00111001, B00000000, // 5 5
B00000000, B00000000, B00111100, B01001010, B01001001, B01001001, B00110000, B00000000, // 6 6
B00000000, B00000000, B00000001, B01110001, B00001001, B00000101, B00000011, B00000000, // 7 7
B00000000, B00000000, B00110110, B01001001, B01001001, B01001001, B00110110, B00000000, // 8 8
B00000000, B00000000, B00000110, B01001001, B01001001, B00101001, B00011110, B00000000, // 9 9
B00000000, B00000000, B00000000, B00110110, B00110110, B00000000, B00000000, B00000000, // 58 :
B00000000, B00000000, B00000000, B01010110, B00110110 , B00000000, B00000000, B00000000, // 59 ;
B00000000, B00000000, B00000000, B00001000, B00010100, B00100010, B01000001, B00000000,// 60 <
B00000000, B00000000, B00101000, B00101000, B00101000, B00101000, B00101000, B00000000,// 61 =
B00000000, B00000000, B00000000, B01000001, B00100010, B00010100, B00001000, B00000000, // 62 >
B00000000, B00000000, B00000010, B00000001, B01010001, B00001001, B00000110, B00000000, // 63 ?
B00000000, B00000000, B00110010, B01001001, B01111001, B01000001, B00111110, B00000000, // 64 @
B00000000, B00000000, B01111100, B00001010, B00001010, B00001010, B01111100, B00000000, // 65 A
B00000000, B00000000, B01111110, B01001010, B01001010, B01001010, B00110100, B00000000, // 66 B
B00000000, B00000000, B00111100, B01000010, B01000010, B01000010, B00100100, B00000000, // 67 C
B00000000, B00000000, B01111110, B01000010, B01000010, B01000010, B00111100, B00000000, // 68 D
B00000000, B00000000, B01111110, B01001010, B01001010, B01001010, B01001010, B00000000, // 69 E
B00000000, B00000000, B01111111, B00001001, B00001001, B00001001, B00000001, B00000000, // 70 F
B00000000, B00000000, B00111100, B01000010, B01010010, B01010010, B00110100, B00000000, // 71 G
B00000000, B00000000, B01111110, B00010000, B00010000, B00010000, B01111110, B00000000, // 72 H
B00000000, B00000000, B00000000, B01000010, B01111110, B01000010, B00000000, B00000000, // 73 I
B00000000, B00000000, B00100000, B01000000, B01000000, B00111010, B00000000, B00000000, // 74 J
B00000000, B00000000, B01111110, B00011000, B00100100, B01000010, B00000000, B00000000, // 75 K
B00000000, B00000000, B01111110, B01000000, B01000000, B01000000, B01000000, B00000000, // 76 L
B00000000, B00000000, B01111110, B00000100, B00001000, B00000100, B01111110, B00000000, // 77 M
B00000000, B00000000, B01111110, B00000100, B00011000, B00100000, B01111110, B00000000, // 78 N
B00000000, B00000000, B00111110, B01000001, B01000001, B01000001, B00111110, B00000000, // 111 O
B00000000, B00000000, B01111110, B00001010, B00001010, B00001010, B00000100, B00000000, // 80 P
B00000000, B00000000, B00111100, B01000010, B01010010, B01100010, B00111100, B00000000, // 81 Q
B00000000, B00000000, B01111100, B00001010, B00011010, B00101010, B01000100, B00000000, // 82 R
B00000000, B00000000, B00100100, B01001010, B01011010, B01010010, B00100100, B00000000, // 83 S
B00000000, B00000000, B00000010, B00000010, B01111110, B00000010, B00000010, B00000000, // 84 T
B00000000, B00000000, B00111110, B01000000, B01000000, B01000000, B00111110, B00000000, // 85 U
B00000000, B00000000, B00011110, B00100000, B01000000, B00100000, B00011110, B00000000, // 86 V
B00000000, B00000000, B00111111, B01000000, B00111000, B01000000, B00111111, B00000000, // 87 W
B00000000, B00000000, B01000010, B00100100, B00011000, B00100100, B01000010, B00000000, // 88 X
B00000000, B00000000, B00000010, B00000100, B01111000, B00000100, B00000010, B00000000, // 89 Y
B00000000, B01000010, B01100010, B01010010, B01001010, B01000110, B01000010, B00000000,// 90 Z
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 91
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 92
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 93
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 94
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 95
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 96
B00000000, B00000000, B00100000, B01010100, B01010100, B01010100, B01111000, B00000000, // 97 a
B00000000, B00000000, B01111111, B01001000, B01000100, B01000100, B00111000, B00000000, // 98 b
B00000000, B00000000, B00111000, B01000100, B01000100, B01000100, B00000000, B00000000, // 99 c
B00000000, B00000000, B00111000, B01000100, B01000100, B01001000, B01111111, B00000000, // 100 d
B00000000, B00000000, B00111000, B01010100, B01010100, B01010100, B00011000, B00000000, // 101 e
B00000000, B00000000, B00001000, B01111110, B00001001, B00000001, B00000010, B00000000, // 102 f
B00000000, B00000000, B00001000, B01010100, B01010100, B01010100, B00111100, B00000000, // 103 g
B00000000, B00000000, B01111111, B00001000, B00000100, B00000100, B01111000, B00000000, // 104 h
B00000000, B00000000, B00000000, B01001000, B01111101, B01000000, B00000000, B00000000, // 105 i
B00000000, B00000000, B00100000, B01000000, B01000100, B00111101, B00000000, B00000000, // 106 j
B00000000, B00000000, B00000000, B01111111, B00010000, B00101000, B01000100, B00000000, // 107 k
B00000000, B00000000, B00000000, B01000001, B01111111, B01000000, B00000000, B00000000, // 108 l
B00000000, B00000000, B01111100, B00000100, B01111000, B00000100, B01111000, B00000000, // 109 m
B00000000, B00000000, B01111000, B00001000, B00000100, B00000100, B01111000, B00000000, // 110 n
B00000000, B00000000, B00111000, B01000100, B01000100, B01000100, B00111000, B00000000, // 111 o
B00000000, B00000000, B01111100, B00010100, B00010100, B00010100, B00001000, B00000000, // 112 p
B00000000, B00000000, B00001000, B00010100, B00010100, B00010100, B01111100, B00000000, // 113 q
B00000000, B00000000, B01111100, B00001000, B00000100, B00000100, B00001000, B00000000, // 114 r
B00000000, B00000000, B01001000, B01010100, B01010100, B01010100, B00100000, B00000000, // 115 s
B00000000, B00000000, B00000100, B00111111, B01000100, B01000000, B00100000, B00000000, // 116 t
B00000000, B00000000, B00111100, B01000000, B01000000, B00100000, B01111100, B00000000, // 117 u
B00000000, B00000000, B00011100, B00100000, B01000000, B00100000, B00011100, B00000000, // 118 v
B00000000, B00000000, B00111100, B01000000, B00011000, B01000000, B00111100, B00000000, // 119 w
B00000000, B00000000, B01000100, B00101000, B00010000, B00101000, B01000100, B00000000, // 120 x
B00000000, B00000000, B00001100, B01010000, B01010000, B01010000, B00111100, B00000000, // 121 y
B00000000, B00000000, B01000100, B01100100, B01010100, B01001100, B01000100, B00000000, // 122 z
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, // 123
B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000 // 124
};
.INO before wrapping it into class;
#include "FontMap.h" //font is in external file
#include <digitalWriteFast.h>
#define matrises 4 //define number of matrises, 4-22
#define columns matrises * 8 //calculate columns based how many matrises are in use
byte displayPointer = 0;
int dataPosition;
byte screenBuffer[columns]; // buffer for screen,4x8=32
int screenBufferIndex;
byte pixel, bitMask;
byte xPositionIndex, yPositionIndex;
byte disp, disp2;
byte pixels[8] = { 128, 64, 32, 16, 8, 4, 2, 1 }; //for each column B10000000->B00000001
byte SPIDataOutPin = 2;
byte SPIChipSelectPin = 3;
byte SPIClockPin = 4;
void draw() {
digitalWriteFast(SPIChipSelectPin, LOW);
setColumn(displayPointer); //column scanning
setData(screenBuffer[displayPointer]); //bit banging shift registers
digitalWriteFast(SPIChipSelectPin, HIGH);
if (++displayPointer == columns) //32 LED row sections in total
{
displayPointer = 0;
}
}
void setColumn(byte columnToCheck) //loop that takes care of column scanning
{
for (dataPosition = columns; dataPosition > -1; dataPosition--) {
if (columnToCheck == dataPosition) {
digitalWriteFast(SPIDataOutPin, HIGH);
} else {
digitalWriteFast(SPIDataOutPin, LOW);
}
digitalWriteFast(SPIClockPin, HIGH);
digitalWriteFast(SPIClockPin, LOW);
}
}
void setData(byte dat) {
for (dataPosition = B10000000; dataPosition > 0; dataPosition >>= 1) {
if (dat & dataPosition) {
digitalWriteFast(SPIDataOutPin, HIGH);
} else {
digitalWriteFast(SPIDataOutPin, LOW);
}
digitalWriteFast(SPIClockPin, HIGH);
digitalWriteFast(SPIClockPin, LOW);
}
}
void clearBuffer() //clear display buffer
{
for (screenBufferIndex = 0; screenBufferIndex < columns; screenBufferIndex++) // Empty display buffer
{
screenBuffer[screenBufferIndex] = 0;
}
}
void setPixel(signed char xPosition, signed char yPosition, byte condition) {
if (xPosition < 0 || yPosition < 0) {
return; // outside drawing limits negative
}
if (xPosition > (columns - 1) || yPosition > 7) {
return; // outside drawing limits positive, x=32, y=8
}
pixel = pixels[yPosition];
bitMask = screenBuffer[xPosition]; // get exsisting data
if (condition == 2)
pixel ^= bitMask; //XOR data to screen
else if (condition == 1) {
pixel = ~pixel;
pixel &= bitMask; // AND data to screen
} else {
pixel |= bitMask; // OR data to screen
}
screenBuffer[xPosition] = pixel; // apply changes
}
void drawCharacter(char character, signed char xPosition, signed char yPosition, byte rotation) {
for (xPositionIndex = 0; xPositionIndex < 8; xPositionIndex++) // eight rows
{
disp = ledMatrixFont_8x8[xPositionIndex + (character * 8)]; //look data from fontmap, (ch<<3)==(ch *8)
for (yPositionIndex = 0; yPositionIndex < 8; yPositionIndex++) // eight pixels
{
disp2 = disp & pixels[yPositionIndex];
if (disp2 > 0) {
if (rotation == 0) {
setPixel(xPosition + xPositionIndex, yPosition + yPositionIndex, 0); //0 degrees
} else if (rotation == 1) {
setPixel(7 - (yPosition + yPositionIndex), (xPosition + xPositionIndex), 0); //90 degrees, flip to left
} else if (rotation == 2) {
setPixel(7 - (xPosition + xPositionIndex), 7 - (yPosition + yPositionIndex), 0);
} else {
setPixel(yPosition + yPositionIndex, 7 - (xPosition + xPositionIndex), 0); //90 degrees, flip to right
}
}
}
}
}
void drawText(char* character, signed char xPosition, signed char yPosition, byte rotation) //strput relies on charput
{
while (*character) {
drawCharacter(*character++, xPosition, yPosition, rotation); //write a string to the display buffer
xPosition += 7;
}
}
void setup() {
pinModeFast(SPIDataOutPin, OUTPUT);
pinModeFast(SPIChipSelectPin, OUTPUT);
pinModeFast(SPIClockPin, OUTPUT);
}
void loop() {
clearBuffer();
drawText("Hello", 0, 0, 0);
draw();
}
And finally, the class version that has framerate issues;
#include "FontMap.h" //font is in external file
#include <digitalWriteFast.h>
class LedMatrix {
public:
LedMatrix(byte SPIDataOutPin, byte SPIChipSelectPin, byte SPIClockPin) {
_SPIDataOutPin = SPIDataOutPin;
_SPIChipSelectPin = SPIChipSelectPin;
_SPIClockPin = SPIClockPin;
pinModeFast(_SPIDataOutPin, OUTPUT);
pinModeFast(_SPIChipSelectPin, OUTPUT);
pinModeFast(_SPIClockPin, OUTPUT);
};
#define matrises 4 //define number of matrises, 4-22
#define columns matrises * 8 //calculate columns based how many matrises are in use
byte displayPointer = 0;
int dataPosition;
byte screenBuffer[columns]; // buffer for screen,4x8=32
int screenBufferIndex;
byte pixel, bitMask;
byte xPositionIndex, yPositionIndex;
byte disp, disp2;
byte pixels[8] = { 128, 64, 32, 16, 8, 4, 2, 1 }; //for each column B10000000->B00000001
void draw() {
digitalWriteFast(_SPIChipSelectPin, LOW);
setColumn(displayPointer); //column scanning
setData(screenBuffer[displayPointer]); //bit banging shift registers
digitalWriteFast(_SPIChipSelectPin, HIGH);
if (++displayPointer == columns) //32 LED row sections in total
{
displayPointer = 0;
}
}
void setColumn(byte columnToCheck) //loop that takes care of column scanning
{
for (dataPosition = columns; dataPosition > -1; dataPosition--) {
if (columnToCheck == dataPosition) {
digitalWriteFast(_SPIDataOutPin, HIGH);
} else {
digitalWriteFast(_SPIDataOutPin, LOW);
}
digitalWriteFast(_SPIClockPin, HIGH);
digitalWriteFast(_SPIClockPin, LOW);
}
}
void setData(byte dat) {
for (dataPosition = B10000000; dataPosition > 0; dataPosition >>= 1) {
if (dat & dataPosition) {
digitalWriteFast(_SPIDataOutPin, HIGH);
} else {
digitalWriteFast(_SPIDataOutPin, LOW);
}
digitalWriteFast(_SPIClockPin, HIGH);
digitalWriteFast(_SPIClockPin, LOW);
}
}
void clearBuffer() //clear display buffer
{
for (screenBufferIndex = 0; screenBufferIndex < columns; screenBufferIndex++) // Empty display buffer
{
screenBuffer[screenBufferIndex] = 0;
}
}
void setPixel(signed char xPosition, signed char yPosition, byte condition) {
if (xPosition < 0 || yPosition < 0) {
return; // outside drawing limits negative
}
if (xPosition > (columns - 1) || yPosition > 7) {
return; // outside drawing limits positive, x=32, y=8
}
pixel = pixels[yPosition];
bitMask = screenBuffer[xPosition]; // get exsisting data
if (condition == 2)
pixel ^= bitMask; //XOR data to screen
else if (condition == 1) {
pixel = ~pixel;
pixel &= bitMask; // AND data to screen
} else {
pixel |= bitMask; // OR data to screen
}
screenBuffer[xPosition] = pixel; // apply changes
}
void drawCharacter(char character, signed char xPosition, signed char yPosition, byte rotation) {
for (xPositionIndex = 0; xPositionIndex < 8; xPositionIndex++) // eight rows
{
disp = ledMatrixFont_8x8[xPositionIndex + (character * 8)]; //look data from fontmap, (ch<<3)==(ch *8)
for (yPositionIndex = 0; yPositionIndex < 8; yPositionIndex++) // eight pixels
{
disp2 = disp & pixels[yPositionIndex];
if (disp2 > 0) {
if (rotation == 0) {
setPixel(xPosition + xPositionIndex, yPosition + yPositionIndex, 0); //0 degrees
} else if (rotation == 1) {
setPixel(7 - (yPosition + yPositionIndex), (xPosition + xPositionIndex), 0); //90 degrees, flip to left
} else if (rotation == 2) {
setPixel(7 - (xPosition + xPositionIndex), 7 - (yPosition + yPositionIndex), 0);
} else {
setPixel(yPosition + yPositionIndex, 7 - (xPosition + xPositionIndex), 0); //90 degrees, flip to right
}
}
}
}
}
void drawText(char* character, signed char xPosition, signed char yPosition, byte rotation) //strput relies on charput
{
while (*character) {
drawCharacter(*character++, xPosition, yPosition, rotation); //write a string to the display buffer
xPosition += 7;
}
}
private:
byte _SPIDataOutPin;
byte _SPIChipSelectPin;
byte _SPIClockPin;
};
byte SPIDataOutPin = 2;
byte SPIChipSelectPin = 3;
byte SPIClockPin = 4;
LedMatrix newMatrix(SPIDataOutPin, SPIChipSelectPin, SPIClockPin);
void setup() {
Serial.begin(115200);
}
void loop() {
newMatrix.clearBuffer();
newMatrix.drawText("Hello", 0, 0, 0);
newMatrix.draw();
}
I think that's all info I can give at this point.