Skip to content

Instantly share code, notes, and snippets.

@smittytone
Created January 23, 2020 21:08
Show Gist options
  • Save smittytone/203587887a83df5ff607fe23ecaeebc0 to your computer and use it in GitHub Desktop.
Save smittytone/203587887a83df5ff607fe23ecaeebc0 to your computer and use it in GitHub Desktop.
Squirrel driver for Grove TM1637 segment LED display
const GROVE_TM1637_HIGH = 1;
const GROVE_TM1637_LOW = 0;
const GROVE_TM1637_ADDR_AUTO = 0x40;
const GROVE_TM1637_ADDR_FIXED = 0x44;
const GROVE_TM1637_DATA_CMD = 0xC0;
const GROVE_TM1637_DISPLAY_CMD = 0x88;
class GroveTM1637 {
// 'Private' properties
_dataPin = null;
_clockPin = null;
_buffer = null;
_chars = [0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, // 0-9
0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71]; // -, degree symbol, space
_brightness = 7;
_colonState = true;
_power = true;
constructor(dataPin = null, clockPin = null) {
// Reject unset parameters
if (dataPin == null || clockPin == null) {
throw "GROVE_TM1637() requires valid clock and data pin objects as parameters";
}
// Configure the clock and data pins as digital outputs, initially low
_dataPin = dataPin;
_dataPin.configure(DIGITAL_OUT, GROVE_TM1637_LOW);
_clockPin = clockPin;
_clockPin.configure(DIGITAL_OUT, GROVE_TM1637_LOW);
// Clear the display (resets the display buffer too)
clearDisplay();
}
function setBrightness(value = 7) {
// Value should be in range 0-7, where
// 0 = 1/16, 7 = 14/16 duty cyle
if (_brightness < 0) _brightness = 0;
if (_brightness > 7) _brightness = 7;
_display();
}
function getBrightness() {
return _brightness;
}
function setColon(state = true) {
// Indicate whether the central colon should be lit (true)
if (typeof state == "bool") _colonState = state;
return this;
}
function getColonState() {
return _colonState;
}
function setDigit(digit = 0, data = 0) {
// Set the digit to the required value:
// 0-17, ie. 0-9, A-F
// Digits are 0-3
if ((typeof data == "integer" && (data < 0 || data >= _chars.len())) || typeof data != "integer") {
server.error("GROVE_TM1637.setDigit() data out of range");
return;
}
_buffer[digit] = _chars[data];
return this;
}
function setGlyph(digit = 0, data = 0x7F) {
// Set the digit to the required glyph, where 'data' indicates
// which segments are to be lit. The segment-to-bit mapping runs
// clockwise from the top around the outside of the
// matrix; the inner segment is bit 6:
//
// 0
// _
// 5 | | 1
// | |
// - <----- 6
// 4 | | 2
// | _ |
// 3
if ((typeof data == "integer" && (data < 0 || data > 0x7F)) || typeof data != "integer") {
server.error("GROVE_TM1637.setGlyph() data out of range");
return;
}
_buffer[digit] = data;
return this;
}
function display() {
// Trigger the display to update
_display();
}
function clearDisplay() {
_buffer = [0,0,0,0];
_colonState = false;
_display();
}
function power(state = true) {
server.log(typeof state);
if (typeof state == "bool" && state != _power) {
_power = state;
_display();
}
}
// ********** Private Functions - Do not call directly **********
function _display() {
// Tell the TM1637 to auto-increment the input data address
_start();
_writeByte(GROVE_TM1637_ADDR_AUTO);
_stop();
// Send the command value, then each segment value
_start();
_writeByte(GROVE_TM1637_DATA_CMD);
for (local i = 0 ; i < 4 ; i++) {
_writeByte(_buffer[i] + (_colonState ? 0x80 : 0x00));
}
_stop();
// Send the display command to draw the display at the requested brightness
_start();
_writeByte(_power ? GROVE_TM1637_DISPLAY_CMD + _brightness : 0x80);
_stop();
}
function _start() {
// Signal the start of data input
_clockPin.write(GROVE_TM1637_HIGH);
_dataPin.write(GROVE_TM1637_HIGH);
_dataPin.write(GROVE_TM1637_LOW);
_clockPin.write(GROVE_TM1637_LOW);
}
function _stop() {
// Signal the end of data input
_clockPin.write(GROVE_TM1637_LOW);
_dataPin.write(GROVE_TM1637_LOW);
_clockPin.write(GROVE_TM1637_HIGH);
_dataPin.write(GROVE_TM1637_HIGH);
}
function _writeByte(value) {
// Send the byte as bits, least significant first and toggling the
// clock pin (low to high) to signal that the data should be read
for (local i = 0 ; i < 8 ; i++) {
_clockPin.write(GROVE_TM1637_LOW);
// Read bit 0 and send high or low accordingly
_dataPin.write(value & 0x01 ? GROVE_TM1637_HIGH : GROVE_TM1637_LOW);
// Shift the next into bit 0 for the next pass
value = value >> 1;
_clockPin.write(GROVE_TM1637_HIGH);
}
// Toggle the clock piun to trigger the TM1637's data ACK
_clockPin.write(GROVE_TM1637_LOW);
_clockPin.write(GROVE_TM1637_HIGH);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment