Skip to content

Instantly share code, notes, and snippets.

@electricimp
Created November 11, 2014 15:45
Show Gist options
  • Save electricimp/93e20924417f50361e5f to your computer and use it in GitHub Desktop.
Save electricimp/93e20924417f50361e5f to your computer and use it in GitHub Desktop.
Squirrel class for 8x8 LED matrix displays driven by the MAX7219 controller
class MAX7219
{
// 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) Jume 2014
// Version 1.0
MAX7219_REGISTER_BCD = 0x09
MAX7219_REGISTER_BRIGHT = 0x0A
MAX7219_REGISTER_SCAN = 0x0B
MAX7219_REGISTER_PWR_MODE = 0x0C
MAX7219_REGISTER_TEST_MODE = 0x0F
// Define the Ascii character set
charset = [
[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0], // Space - Ascii 32
[0x0,0x10,0x10,0x10,0x10,0x0,0x10,0x0], // !
[0x0,0x24,0x24,0x0,0x0,0x0,0x0,0x0], // ”
[0x0,0x24,0x7E,0x24,0x24,0x7E,0x24,0x0], // #
[0x0,0x8,0x3E,0x28,0x3E,0xA,0x3E,0x8], // $
[0x0,0x62,0x64,0x8,0x10,0x26,0x46,0x0], // %
[0x0,0x10,0x28,0x10,0x2A,0x44,0x3A,0x0], // &
[0x0,0x8,0x10,0x0,0x0,0x0,0x0,0x0], // ‘
[0x0,0x4,0x8,0x8,0x8,0x8,0x4,0x0], // (
[0x0,0x20,0x10,0x10,0x10,0x10,0x20,0x0], // )
[0x0,0x0,0x14,0x8,0x3E,0x8,0x14,0x0], // *
[0x0,0x0,0x8,0x8,0x3E,0x8,0x8,0x0], // +
[0x0,0x0,0x0,0x0,0x0,0x8,0x8,0x10], // ,
[0x0,0x0,0x0,0x0,0x3E,0x0,0x0,0x0], // -
[0x0,0x0,0x0,0x0,0x0,0x18,0x18,0x0], // .
[0x0,0x2,0x4,0x8,0x10,0x20,0x40,0x0], // /
[0x0,0x3C,0x46,0x4A,0x52,0x62,0x3C,0x0], // 0 - Ascii 48
[0x0,0x30,0x50,0x10,0x10,0x10,0x7C,0x0], // 1
[0x0,0x3C,0x42,0x2,0x3C,0x40,0x7E,0x0], // 2
[0x0,0x3C,0x42,0xC,0x2,0x42,0x3C,0x0], // 3
[0x0,0x8,0x18,0x28,0x48,0x7E,0x8,0x0], // 4
[0x0,0x7E,0x40,0x7C,0x2,0x42,0x3C,0x0], // 5
[0x0,0x3C,0x40,0x7C,0x42,0x42,0x3C,0x0], // 6
[0x0,0x7E,0x2,0x4,0x8,0x10,0x10,0x0], // 7
[0x0,0x3C,0x42,0x3C,0x42,0x42,0x3C,0x0], // 8
[0x0,0x3C,0x42,0x42,0x3E,0x2,0x3C,0x0], // 9
[0x0,0x0,0x10,0x0,0x0,0x0,0x10,0x0], // : - Ascii 58
[0x0,0x0,0x10,0x0,0x0,0x10,0x10,0x20], //
[0x0,0x0,0x4,0x8,0x10,0x8,0x4,0x0], // <
[0x0,0x0,0x0,0x3E,0x0,0x3E,0x0,0x0], // =
[0x0,0x0,0x10,0x8,0x4,0x8,0x10,0x0], // >
[0x0,0x3C,0x42,0x4,0x8,0x0,0x8,0x0], // ?
[0x0,0x3C,0x4A,0x56,0x5E,0x40,0x3C,0x0], // @
[0x0,0x3C,0x42,0x42,0x7E,0x42,0x42,0x0], // A - Ascii 65
[0x0,0x7C,0x42,0x7C,0x42,0x42,0x7C,0x0], // B
[0x0,0x3C,0x42,0x40,0x40,0x42,0x3C,0x0], // C
[0x0,0x78,0x44,0x42,0x42,0x44,0x78,0x0], // D
[0x0,0x7E,0x40,0x7C,0x40,0x40,0x7E,0x0], // E
[0x0,0x7E,0x40,0x7C,0x40,0x40,0x40,0x0], // F
[0x0,0x3C,0x42,0x40,0x4E,0x42,0x3C,0x0], // G
[0x0,0x42,0x42,0x7E,0x42,0x42,0x42,0x0], // H
[0x0,0x7C,0x10,0x10,0x10,0x10,0x7C,0x0], // I
[0x0,0x2,0x2,0x2,0x2,0x42,0x3C,0x0], // J
[0x0,0x44,0x48,0x70,0x48,0x44,0x42,0x0], // K
[0x0,0x40,0x40,0x40,0x40,0x40,0x7E,0x0], // L
[0x0,0x42,0x66,0x5A,0x42,0x42,0x42,0x0], // M
[0x0,0x42,0x62,0x52,0x4A,0x46,0x42,0x0], // N
[0x0,0x3C,0x42,0x42,0x42,0x42,0x3C,0x0], // O
[0x0,0x7C,0x42,0x42,0x7C,0x40,0x40,0x0], // P
[0x0,0x3C,0x42,0x42,0x52,0x4A,0x3C,0x0], // Q
[0x0,0x7C,0x42,0x42,0x7C,0x44,0x42,0x0], // R
[0x0,0x3C,0x40,0x3C,0x2,0x42,0x3C,0x0], // S
[0x0,0x7C,0x10,0x10,0x10,0x10,0x10,0x0], // T
[0x0,0x42,0x42,0x42,0x42,0x42,0x3C,0x0], // U
[0x0,0x42,0x42,0x42,0x42,0x24,0x18,0x0], // V
[0x0,0x42,0x42,0x42,0x42,0x5A,0x24,0x0], // W
[0x0,0x42,0x24,0x18,0x18,0x24,0x42,0x0], // X
[0x0,0x44,0x28,0x10,0x10,0x10,0x10,0x0], // Y
[0x0,0x7E,0x4,0x8,0x10,0x20,0x7E,0x0], // Z - Ascii 90
[0x0,0xE,0x8,0x8,0x8,0x8,0xE,0x0], // [
[0x0,0x0,0x40,0x20,0x10,0x8,0x4,0x0], // \
[0x0,0x70,0x10,0x10,0x10,0x10,0x70,0x0], // ]
[0x0,0x10,0x38,0x54,0x10,0x10,0x10,0x0], // ^
[0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xFF], // _
[0x0,0x1C,0x22,0x78,0x20,0x20,0x7E,0x0], // £
[0x0,0x0,0x38,0x4,0x3C,0x44,0x3C,0x0], // a - Ascii 97
[0x0,0x40,0x40,0x78,0x44,0x44,0x78,0x0], // b
[0x0,0x0,0x38,0x40,0x40,0x40,0x38,0x0], // c
[0x0,0x4,0x4,0x3C,0x44,0x44,0x3C,0x0], // d
[0x0,0x0,0x38,0x44,0x78,0x40,0x3C,0x0], // e
[0x0,0x30,0x40,0x60,0x40,0x40,0x40,0x0], // f
[0x0,0x3C,0x44,0x44,0x3C,0x4,0x38,0x0], // g
[0x0,0x40,0x40,0x40,0x78,0x44,0x44,0x0], // h
[0x0,0x20,0x0,0x60,0x20,0x20,0x70,0x0], // i
[0x0,0x8,0x0,0x8,0x8,0x48,0x30,0x0], // j
[0x0,0x40,0x50,0x60,0x60,0x50,0x48,0x0], // k
[0x0,0x40,0x40,0x40,0x40,0x40,0x30,0x0], // l
[0x0,0x0,0x68,0x54,0x54,0x54,0x54,0x0], // m
[0x0,0x0,0x78,0x44,0x44,0x44,0x44,0x0], // n
[0x0,0x0,0x38,0x44,0x44,0x44,0x38,0x0], // o
[0x0,0x78,0x44,0x44,0x78,0x40,0x40,0x0], // p
[0x0,0x3C,0x44,0x44,0x3C,0x4,0x6,0x0], // q
[0x0,0x0,0x1C,0x20,0x20,0x20,0x20,0x0], // r
[0x0,0x0,0x38,0x40,0x38,0x4,0x78,0x0], // s
[0x0,0x20,0x70,0x20,0x20,0x20,0x18,0x0], // t
[0x0,0x0,0x44,0x44,0x44,0x44,0x38,0x0], // u
[0x0,0x0,0x44,0x44,0x28,0x28,0x10,0x0], // v
[0x0,0x0,0x44,0x54,0x54,0x54,0x28,0x0], // w
[0x0,0x0,0x44,0x28,0x10,0x28,0x44,0x0], // x
[0x0,0x0,0x44,0x44,0x3C,0x4,0x38,0x0], // y
[0x0,0x0,0x7C,0x8,0x10,0x20,0x7C,0x0], // z - Ascii 122
[0x0,0xE,0x8,0x30,0x8,0x8,0xE,0x0], // {
[0x0,0x8,0x8,0x8,0x8,0x8,0x8,0x0], // |
[0x0,0x70,0x10,0xC,0x10,0x10,0x70,0x0], // }
[0x0,0x14,0x28,0x0,0x0,0x0,0x0,0x0], // ~
[0x3C,0x42,0x99,0xA1,0xA1,0x99,0x42,0x3C], // © - Ascii 127
[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF], // Block Graphic 1
[0xF,0xF,0xF,0xF,0xFF,0xFF,0xFF,0xFF],
[0xF0,0xF0,0xF0,0xF0,0xFF,0xFF,0xFF,0xFF],
[0x0,0x0,0x0,0x0,0xFF,0xFF,0xFF,0xFF],
[0xFF,0xFF,0xFF,0xFF,0xF,0xF,0xF,0xF],
[0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF],
[0xF0,0xF0,0xF0,0xF0,0xF,0xF,0xF,0xF],
[0x0,0x0,0x0,0x0,0xF,0xF,0xF,0xF],
[0xFF,0xFF,0xFF,0xFF,0x55,0xAA,0x55,0xAA],
[0xAA,0x55,0xAA,0x55,0xFF,0xFF,0xFF,0xFF],
[0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55], // Block Graphic 11
]
// 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, 0x02) // 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(0)
din.write(byteVal & 0x80) // Extract bit 8 and write it to the LED
byteValue = byteVal << 1 // Shift the data bits left by one bit
clk.write(1)
}
}
function write(RegAddress, value)
{
// Writes a single value to the MAX7219, preceded by the register
// it is being written to
cs.write(0)
writeByte(RegAddress)
writeByte(value)
cs.write(1)
}
function clearDisplay()
{
displayLine(" ")
}
function displayIcon(inputMatrix = [0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF])
{
inputMatrix = rotateMatrix(inputMatrix)
for (local k = 0 ; k < 8 ; k++)
{
if (inverseVideoFlag)
{
write(k + 1, ~inputMatrix[k])
}
else
{
write(k + 1, inputMatrix[k])
}
}
}
function displayChar(asciiVal = 32)
{
asciiVal = asciiVal - 32
if (asciiVal < 0 || asciiVal > _alphaCount) asciiVal = 0
local inputMatrix = clone(charset[asciiVal])
inputMatrix = rotateMatrix(inputMatrix)
for (local k = 0 ; k < 8 ; k++)
{
if (inverseVideoFlag == 1)
{
write(k + 1, ~inputMatrix[k])
}
else
{
write(k + 1, inputMatrix[k])
}
}
}
function displayLine(line = "No text entered")
{
// Bit-scroll through the characters in the variable ‘line’
local a = 0
local b = 0
local count = 0
local outputMatrix = [0,0,0,0,0,0,0,0]
local matrixOne = [0,0,0,0,0,0,0,0]
local matrixTwo = [0,0,0,0,0,0,0,0]
count = line.len()
if (count == 1)
{
count = 2
line = " " + line
}
for (local k = 0 ; k < (count - 1) ; k++)
{
// Run through the line character by character up to the penultimate character
// Get the current character to be displayed and the next character along by
// copying them from the character set array
a = line[k]
b = line[k + 1]
matrixOne = clone(charset[a - 32])
matrixTwo = clone(charset[b - 32])
for (local j = 0 ; j < 8 ; j++)
{
// We use two character matrices, one on the left and one on the right.
// Line by line, we shift the left matrix's bit pattern one bit at a time.
// If the seventh bit of a line in the right-hand matrix is set,
// we then set bit 0 of the left-hand matrix.
// We then shift the right-hand matrix leftward one bit.
outputMatrix = matrixOne
outputMatrix = rotateMatrix(outputMatrix)
for (local i = 0 ; i < 8 ; i++)
{
// Write the current character’s matrix
if (inverseVideoFlag)
{
write(i + 1, ~outputMatrix[i])
}
else
{
write(i + 1, outputMatrix[i])
}
// Use the Logical Shift Left operator to move the line one pixel
matrixOne[i] = matrixOne[i] << 1
// Move over second matrix by one pixel
if ((matrixTwo[i] & 128) > 0)
{
// If bit 7 of the right-hand character’s line is set,
// carry it over to bit 0 of the left-hand character
matrixOne[i] = matrixOne[i] | (1 << 0)
}
// Shift right-hand character line left one pixel
matrixTwo[i] = (matrixTwo[i] << 1)
}
imp.sleep(0.04)
}
}
// For the final character, we need to perform a last pixel shift to leave
// the character completely on the display
outputMatrix = matrixOne
outputMatrix = rotateMatrix(outputMatrix)
for (local i = 0 ; i < 8 ; i++)
{
if (inverseVideoFlag)
{
write(i + 1, ~outputMatrix[i])
}
else
{
write(i + 1, outputMatrix[i])
}
matrixOne[i] = matrixOne[i] << 1
if ((matrixTwo[i] & 128) > 0) matrixOne[i] = matrixOne[i] | (1 << 0)
matrixTwo[i] = (matrixTwo[i] << 1)
}
imp.sleep(0.04)
}
function rotateMatrix(inputMatrix)
{
// Only rotate the matrix if rotate_matrix_flag has not been set
if (rotateMatrixFlag == false) return 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 = [0,0,0,0,0,0,0,0]
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