/*
Controlling MAX7219 LED Dot Matrix using Arduino SPI.
Copyright (C) 2021, Uri Shaked.
*/
#include <SPI.h>
#include <avr/pgmspace.h>
#define CLK_PIN 13
#define DATA_PIN 11
#define CS_PIN 10
#define SEGMENT_COUNT 2
#define MAX7219_ROWS 8
#define INVERT true
uint8_t buffer[SEGMENT_COUNT][MAX7219_ROWS];
const byte digits[10][8] PROGMEM = {
{B00000000, B00111000, B01000100, B01001100, B01010100, B01100100, B01000100, B00111000}, // 0
{B00000000, B00010000, B00110000, B00010000, B00010000, B00010000, B00010000, B00111000}, // 1
{B00000000, B00111000, B01000100, B00000100, B00001000, B00010000, B00100000, B01111100}, // 2
{B00000000, B01111100, B00001000, B00010000, B00001000, B00000100, B01000100, B00111000}, // 3
{B00000000, B00001000, B00011000, B00101000, B01001000, B01111100, B00001000, B00001000}, // 4
{B00000000, B01111100, B01000000, B01111000, B00000100, B00000100, B01000100, B00111000}, // 5
{B00000000, B00011000, B00100000, B01000000, B01111000, B01000100, B01000100, B00111000}, // 6
{B00000000, B01111100, B00000100, B00001000, B00010000, B00100000, B01000000, B01000000}, // 7
{B00000000, B00111000, B01000100, B01000100, B00111000, B01000100, B01000100, B00111000}, // 8
{B00000000, B00111000, B01000100, B01000100, B00111100, B00000100, B00001000, B00110000}, // 9
};
void clearBuffers() {
for (int row = 0; row < SEGMENT_COUNT; row++) {
for (int col = 0; col < 8; col++) {
buffer[row][col] = 0;
}
}
}
void clearBuffer(int addr) {
for (int col = 0; col < 8; col++) {
buffer[addr][col] = 0;
}
}
void setPixel(int x, int y) {
digitalWrite(CS_PIN, LOW);
SPI.transfer(x);
SPI.transfer(y);
digitalWrite(CS_PIN, HIGH);
}
void sendAll(int registerIndex, int value) {
digitalWrite(CS_PIN, LOW);
for (int i = 0; i < SEGMENT_COUNT; i++) {
SPI.transfer(registerIndex);
SPI.transfer(value);
}
digitalWrite(CS_PIN, HIGH);
}
void clearRow(int row) {
sendAll(row, 0);
}
void clearDisplays() {
for (int row = 1; row <= 8; row++) {
clearRow(row);
}
}
void setRow(int row) {
digitalWrite(CS_PIN, LOW);
for (int i=SEGMENT_COUNT-1; i>=0; i--) {
SPI.transfer(row);
#if INVERT
SPI.transfer(reverse(buffer[i][row]));
#else
SPI.transfer(buffer[i][row]);
#endif
}
digitalWrite(CS_PIN, HIGH);
}
void update() {
clearDisplays();
for (int i=SEGMENT_COUNT-1; i>0; i--) {
for (int j=1; j<=8; j++) {
setRow(j);
}
}
}
/*
void setDigit(int addr, int digit) {
uint8_t *pattern = digits[digit];
for (int i=8; i>=1; i--) {
uint8_t line = pattern[i-1];
buffer[addr][i] = line;
}
update();
}
*/
void setDigit(int addr, int digit) {
uint8_t pattern[8];
for (int i = 0; i < 8; i++) {
pattern[i] = pgm_read_byte_near(&(digits[digit][i]));
}
for (int i = 8; i >= 1; i--) {
uint8_t line = pattern[i - 1];
buffer[addr][i] = line;
}
update();
}
void demo1() {
setPixel(1,255);
setPixel(1,254);
}
void demo2() {
setDigit(0,9);
setDigit(1,5);
}
byte reverse(unsigned char num) {
byte reversed = 0;
int i;
for (i = 0; i < 8; i++) {
// Shift the reversed number to the left and add the least significant bit of the input number
reversed = (reversed << 1) | (num & 1);
num >>= 1;
}
return reversed;
}
void setup() {
// Change SPI speed from 4mhz to 1mhz
SPI.setClockDivider(SPI_CLOCK_DIV16);
SPI.begin();
sendAll(0xf, 0); // Disable test mode
sendAll(0xb, 7); // Set scanlines to 8
//transfer(0x0A, 0x00); // Use lowest intensity
clearDisplays();
sendAll(0xc, 1); // Enable display
//demo1();
demo2();
}
void loop() {
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
m1:V+
m1:GND
m1:DIN
m1:CS
m1:CLK
m1:V+.2
m1:GND.2
m1:DOUT
m1:CS.2
m1:CLK.2
m2:V+
m2:GND
m2:DIN
m2:CS
m2:CLK
m2:V+.2
m2:GND.2
m2:DOUT
m2:CS.2
m2:CLK.2