Skip to content

Instantly share code, notes, and snippets.

@smittytone
Created January 23, 2020 21:03
Show Gist options
  • Save smittytone/31686e2c04942f5cd3e14e92fa417277 to your computer and use it in GitHub Desktop.
Save smittytone/31686e2c04942f5cd3e14e92fa417277 to your computer and use it in GitHub Desktop.
Squirrel class for 8x8 LED matrix displays driven by the MAX7219 controller
enum MAX7219_REGISTER {
BCD = 0x09,
BRIGHT = 0x0A,
SCAN = 0x0B,
PWR_MODE = 0x0C,
TEST_MODE = 0x0F
}
enum MAX7219_STATE {
HI = 1,
LO = 0
}
class MAX7219PRO {
// Squirrel class for 8x8 LED matrix displays driven by the MAX7219 controller
// For example: https://www.sparkfun.com/products/11861
// Communicates with any imp GPIO (three pins)
// Written by Tony Smith (@smittytone) February 2015
// Version 1.0.0
// Define the proportionally spaced Ascii character set
pcharset = [
[0x00, 0x00], // space - Ascii 32
[0xfa], // !
[0xc0, 0x00, 0xc0], // "
[0x24, 0x7e, 0x24, 0x7e, 0x24], // #
[0x24, 0xd4, 0x56, 0x48], // $
[0xc6, 0xc8, 0x10, 0x26, 0xc6], // %
[0x6c, 0x92, 0x6a, 0x04, 0x0a], // &
[0xc0], // '
[0x7c, 0x82], // (
[0x82, 0x7c], // )
[0x10, 0x7c, 0x38, 0x7c, 0x10], // *
[0x10, 0x10, 0x7c, 0x10, 0x10], // +
[0x06, 0x07], // ,
[0x10, 0x10, 0x10, 0x10, 0x10], // -
[0x06, 0x06], // .
[0x04, 0x08, 0x10, 0x20, 0x40], // /
[0x7c, 0x8a, 0x92, 0xa2, 0x7c], // 0 - Ascii 48
[0x42, 0xfe, 0x02], // 1
[0x46, 0x8a, 0x92, 0x92, 0x62], // 2
[0x44, 0x92, 0x92, 0x92, 0x6c], // 3
[0x18, 0x28, 0x48, 0xfe, 0x08], // 4
[0xf4, 0x92, 0x92, 0x92, 0x8c], // 5
[0x3c, 0x52, 0x92, 0x92, 0x8c], // 6
[0x80, 0x8e, 0x90, 0xa0, 0xc0], // 7
[0x6c, 0x92, 0x92, 0x92, 0x6c], // 8
[0x60, 0x92, 0x92, 0x94, 0x78], // 9
[0x36, 0x36], // : - Ascii 58
[0x36, 0x37], // ;
[0x10, 0x28, 0x44, 0x82], // <
[0x24, 0x24, 0x24, 0x24, 0x24], // =
[0x82, 0x44, 0x28, 0x10], // >
[0x60, 0x80, 0x9a, 0x90, 0x60], // ?
[0x7c, 0x82, 0xba, 0xaa, 0x78], // @
[0x7e, 0x90, 0x90, 0x90, 0x7e], // A - Ascii 65
[0xfe, 0x92, 0x92, 0x92, 0x6c], // B
[0x7c, 0x82, 0x82, 0x82, 0x44], // C
[0xfe, 0x82, 0x82, 0x82, 0x7c], // D
[0xfe, 0x92, 0x92, 0x92, 0x82], // E
[0xfe, 0x90, 0x90, 0x90, 0x80], // F
[0x7c, 0x82, 0x92, 0x92, 0x5c], // G
[0xfe, 0x10, 0x10, 0x10, 0xfe], // H
[0x82, 0xfe, 0x82], // I
[0x0c, 0x02, 0x02, 0x02, 0xfc], // J
[0xfe, 0x10, 0x28, 0x44, 0x82], // K
[0xfe, 0x02, 0x02, 0x02, 0x02], // L
[0xfe, 0x40, 0x20, 0x40, 0xfe], // M
[0xfe, 0x40, 0x20, 0x10, 0xfe], // N
[0x7c, 0x82, 0x82, 0x82, 0x7c], // O
[0xfe, 0x90, 0x90, 0x90, 0x60], // P
[0x7c, 0x82, 0x92, 0x8c, 0x7a], // Q
[0xfe, 0x90, 0x90, 0x98, 0x66], // R
[0x64, 0x92, 0x92, 0x92, 0x4c], // S
[0x80, 0x80, 0xfe, 0x80, 0x80], // T
[0xfc, 0x02, 0x02, 0x02, 0xfc], // U
[0xf8, 0x04, 0x02, 0x04, 0xf8], // V
[0xfc, 0x02, 0x3c, 0x02, 0xfc], // W
[0xc6, 0x28, 0x10, 0x28, 0xc6], // X
[0xe0, 0x10, 0x0e, 0x10, 0xe0], // Y
[0x86, 0x8a, 0x92, 0xa2, 0xc2], // Z - Ascii 90
[0xfe, 0x82, 0x82], // [
[0x40, 0x20, 0x10, 0x08, 0x04], // \
[0x82, 0x82, 0xfe], // ]
[0x20, 0x40, 0x80, 0x40, 0x20], // ^
[0x02, 0x02, 0x02, 0x02, 0x02], // _
[0xc0, 0xe0], // '
[0x04, 0x2a, 0x2a, 0x1e], // a - Ascii 97
[0xfe, 0x22, 0x22, 0x1c], // b
[0x1c, 0x22, 0x22, 0x22], // c
[0x1c, 0x22, 0x22, 0xfc], // d
[0x1c, 0x2a, 0x2a, 0x10], // e
[0x10, 0x7e, 0x90, 0x80], // f
[0x18, 0x25, 0x25, 0x3e], // g
[0xfe, 0x20, 0x20, 0x1e], // h
[0xbc, 0x02], // i
[0x02, 0x01, 0x21, 0xbe], // j
[0xfe, 0x08, 0x14, 0x22], // k
[0xfc, 0x02], // l
[0x3e, 0x20, 0x18, 0x20, 0x1e], // m
[0x3e, 0x20, 0x20 0x1e], // n
[0x1c, 0x22, 0x22, 0x1c], // o
[0x3f, 0x22, 0x22, 0x1c], // p
[0x1c, 0x22, 0x22, 0x3f], // q
[0x22, 0x1e, 0x20, 0x10], // r
[0x12, 0x2a, 0x2a, 0x04], // s
[0x20, 0x7c, 0x22, 0x04], // t
[0x3c, 0x02, 0x02, 0x3e], // u
[0x38, 0x04, 0x02, 0x04, 0x38], // v
[0x3c, 0x06, 0x0c, 0x06, 0x3c], // w
[0x22, 0x14, 0x08, 0x14, 0x22], // x
[0x39, 0x05, 0x06, 0x3c], // y
[0x26, 0x2a, 0x2a, 0x32], // z - Ascii 122
[0x10, 0x7c, 0x82, 0x82], // {
[0xee], // |
[0x82, 0x82, 0x7c, 0x10], // }
[0x40, 0x80, 0x40, 0x80], // ~
[0x60, 0x90, 0x90, 0x60] // Degrees sign - Ascii 127
];
// Display Properties
_clk = null;
_din = null;
_cs = null;
_inverseVideoFlag = false;
_rotateMatrixFlag = false;
// Set the number of characters in your character set
_alphaCount = 107
constructor(clockPin, dataPin, selectPin, shouldRotate = false) {
_clk = clockPin;
_din = dataPin;
_cs = selectPin;
// Set these pins as digital outputs
clk.configure(DIGITAL_OUT);
cs.configure(DIGITAL_OUT);
din.configure(DIGITAL_OUT);
// Set screen rotation flag
rotateMatrixFlag = shouldRotate;
}
function init() {
// Initialise the MAX7219’s parameter registers by writing
// the register’s address followed by its 8-bit value
// Address and data values from the Maxim Integrated MAX7219 Datasheet:
// http://www.maximintegrated.com/datasheet/index.mvp/id/1339
write(MAX7219_REGISTER.BCD, 0x00); // Set MAX7219’s BCD decode mode to ‘none’
write(MAX7219_REGISTER.BRIGHT, 0x00); // Set MAX7219’s LED intensity to a 5/32 duty cycle
write(MAX7219_REGISTER.SCAN, 0x07); // Set MAX7219’s scan limit to all eight LED columns
write(MAX7219_REGISTER.PWR_MODE, 0x01); // Set MAX7219’s power mode. 0 = power down, 1 = normal
write(MAX7219_REGISTER.TEST_MODE, 0x00); // Set MAX7219’s display test mode off
}
function writeByte(byteVal) {
// Writes a single byte of data to the MAX7219 display controller one bit at a time.
// Writes data to the LED in the MAX7219’s 16-bit serial format, which puts the
// register address in the first eight bits then the data in the second set of eight bits.
for (local i = 8 ; i > 0 ; i--) {
clk.write(MAX7219_STATE.LO);
din.write(byteVal & 0x80); // Extract bit 8 and write it to the LED
byteVal = byteVal << 1; // Shift the data bits left by one bit
clk.write(MAX7219_STATE.HI);
}
}
function write(regAddress, value) {
// Writes a single value to the MAX7219, preceded by the register
// it is being written to
cs.write(MAX7219_STATE.LO);
writeByte(regAddress);
writeByte(value);
cs.write(MAX7219_STATE.HI);
}
function clearDisplay() {
displayText(" ");
}
function displayIcon(inputMatrix = "\xFF\x81\x81\x81\x81\x81\x81\xFF") {
inputMatrix = rotateMatrix(inputMatrix);
for (local k = 0 ; k < 8 ; k++) {
write(k + 1, (inverseVideoFlag ? ~inputMatrix[k] : inputMatrix[k]));
}
}
function displayChar(asciiVal = 32) {
asciiVal -= 32;
if (asciiVal < 0 || asciiVal > _alphaCount) asciiVal = 0;
local inputMatrix = clone(pcharset[asciiVal]);
local l = ((8 - inputMatrix.len()) / 2).tointeger();
clearDisplay();
for (local k = l ; k < inputMatrix.len() ; k++)
{
if (inverseVideoFlag == 1)
{
write(k + 1, ~(flip(inputMatrix[k])))
}
else
{
write(k + 1, flip(inputMatrix[k]))
}
}
}
function displayText(line = "ERROR - No text entered")
{
if (line == null || line == "") return
foreach (index, character in line)
{
local glyph = clone(pcharset[character - 32])
// Add a spacer column to the character
glyph.append(0x00)
foreach (column, columnValue in glyph) {
local cursor = column;
local glyphToDraw = glyph;
local increment = 1;
local outputFrame = blob(8);
for (local k = 0 ; k < 8 ; k ++) {
if (cursor < glyphToDraw.len()) {
outputFrame[k] = flip(glyphToDraw[cursor])
cursor++;
} else {
if (index + increment < line.len()) {
glyphToDraw = clone(pcharset[line[index + increment] - 32]);
glyphToDraw.append(0x00);
increment++;
cursor = 1;
outputFrame[k] = flip(glyphToDraw[0]);
}
}
}
for (local k = 0 ; k < 8 ; k++) {
write(k + 1, (inverseVideoFlag ? ~outputFrame[k] : outputFrame[k]))
}
imp.sleep(0.04);
}
}
}
function flip(value) {
local a = 0;
local b = 0;
for (local i = 0 ; i < 8 ; i++) {
a = value & math.pow(2, i).tointeger();
if (a > 0) b += math.pow(2, 7 - i).tointeger()
}
return b;
}
function rotateMatrix(inputMatrix) {
// Rotate the character matrix through 90 degrees anti-clockwise
// Used if the LED matrix pins are connected directly to a breadboard
local a = 0;
local lineValue = 0;
local outputMatrix = blob(8);
for (local i = 0 ; i < 8 ; i++) {
lineValue = inputMatrix[i];
for (local j = 7 ; j > -1 ; j--) {
a = (lineValue & math.pow(2, j).tointeger());
if (a > 0) outputMatrix[7 - j] = outputMatrix[7 - j] + math.pow(2, i).tointeger();
}
}
return outputMatrix;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment