Created
January 23, 2020 21:03
-
-
Save smittytone/31686e2c04942f5cd3e14e92fa417277 to your computer and use it in GitHub Desktop.
Squirrel class for 8x8 LED matrix displays driven by the MAX7219 controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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