-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tm1637: add support for tm1637 7-segment LED
- Loading branch information
1 parent
df34319
commit f7dc106
Showing
4 changed files
with
274 additions
and
1 deletion.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package main | ||
|
||
import ( | ||
"machine" | ||
"time" | ||
|
||
"tinygo.org/x/drivers/tm1637" | ||
) | ||
|
||
func main() { | ||
|
||
tm := tm1637.New(machine.D2, machine.D3, 7) // clk, dio, brightness | ||
tm.Configure() | ||
|
||
tm.ClearDisplay() | ||
|
||
tm.DisplayText([]byte("Tiny")) | ||
time.Sleep(time.Millisecond * 1000) | ||
|
||
tm.ClearDisplay() | ||
|
||
tm.DisplayChr(byte('G'), 1) | ||
tm.DisplayDigit(0, 2) // looks like O | ||
time.Sleep(time.Millisecond * 1000) | ||
|
||
tm.DisplayClock(12, 59, true) | ||
|
||
for i := uint8(0); i < 8; i++ { | ||
tm.Brightness(i) | ||
time.Sleep(time.Millisecond * 200) | ||
} | ||
|
||
i := int16(0) | ||
for { | ||
tm.DisplayNumber(i) | ||
i++ | ||
time.Sleep(time.Millisecond * 50) | ||
} | ||
|
||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package tm1637 | ||
|
||
const ( | ||
TM1637_CMD1 = 0x40 | ||
TM1637_CMD2 = 0xC0 | ||
TM1637_CMD3 = 0x80 | ||
TM1637_DSP_ON = 0x08 | ||
TM1637_DELAY = uint8(10) | ||
) | ||
|
||
// 7-segment characters encoding for 0-9, A-Z, a-z, blank, dash, star | ||
var segments []byte = []byte{ | ||
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, | ||
0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x3D, 0x76, 0x06, 0x1E, | ||
0x76, 0x38, 0x55, 0x54, 0x3F, 0x73, 0x67, 0x50, 0x6D, 0x78, | ||
0x3E, 0x1C, 0x2A, 0x76, 0x6E, 0x5B, 0x00, 0x40, 0x63} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
// Package tm1637 provides a driver for the TM1637 4-digit 7-segment LED display. | ||
// | ||
// Datasheet: https://www.mcielectronics.cl/website_MCI/static/documents/Datasheet_TM1637.pdf | ||
// | ||
package tm1637 | ||
|
||
import ( | ||
"machine" | ||
"time" | ||
) | ||
|
||
// Device wraps the pins of the TM1637. | ||
type Device struct { | ||
clk machine.Pin | ||
dio machine.Pin | ||
brightness uint8 | ||
} | ||
|
||
// New creates a new TM1637 device. | ||
func New(clk machine.Pin, dio machine.Pin, brightness uint8) Device { | ||
return Device{clk: clk, dio: dio, brightness: brightness} | ||
} | ||
|
||
// Configure sets up the pins. | ||
func (d *Device) Configure() { | ||
pinMode(d.clk, false) | ||
pinMode(d.dio, false) | ||
d.clk.Low() // required for future pull-down | ||
d.dio.Low() // required for future pull-down | ||
} | ||
|
||
// Brightness sets the brightness of the display (0-7). | ||
func (d *Device) Brightness(brightness uint8) { | ||
if brightness > 7 { | ||
brightness = 7 | ||
} | ||
d.brightness = brightness | ||
d.writeCmd() | ||
d.writeDsp() | ||
} | ||
|
||
// ClearDisplay clears the display. | ||
func (d *Device) ClearDisplay() { | ||
d.writeData([]byte{0, 0, 0, 0}, 0) | ||
} | ||
|
||
// DisplayText shows a text on the display. | ||
// | ||
// Only the first 4 letters in the array text would be shown. | ||
func (d *Device) DisplayText(text []byte) { | ||
var sequences []byte | ||
for i, t := range text { | ||
if i > 3 { | ||
break | ||
} | ||
sequences = append(sequences, encodeChr(t)) | ||
} | ||
d.writeData(sequences, 0) | ||
} | ||
|
||
// DisplayChr shows a single character (A-Z, a-z) | ||
// on the display at position 0-3. | ||
func (d *Device) DisplayChr(chr byte, pos uint8) { | ||
if pos > 3 { | ||
pos = 3 | ||
} | ||
d.writeData([]byte{encodeChr(chr)}, pos) | ||
} | ||
|
||
// DisplayNumber shows a number on the display. | ||
// | ||
// Only 4 rightmost digits of the number would be shown. | ||
// | ||
// For negative numbers, only -999 to -1 would be | ||
// shown with a negaive sign. | ||
func (d *Device) DisplayNumber(num int16) { | ||
var sequences []byte | ||
var start int16 | ||
if num < 0 { | ||
sequences = append(sequences, segments[37]) | ||
num *= -1 | ||
start = 100 | ||
num %= 1000 | ||
} else { | ||
start = 1000 | ||
num %= 10000 | ||
} | ||
for i := start; i >= 1; i /= 10 { | ||
if num >= i { | ||
n := (num / int16(i)) % 10 | ||
sequences = append(sequences, segments[n]) | ||
} else { | ||
if i == 1 && num == 0 { | ||
sequences = append(sequences, segments[0]) | ||
} else { | ||
sequences = append(sequences, 0) | ||
} | ||
} | ||
} | ||
d.writeData(sequences, 0) | ||
} | ||
|
||
// DisplayDigit shows a single-digit number (0-9) | ||
// at position 0-3. | ||
func (d *Device) DisplayDigit(digit uint8, pos uint8) { | ||
digit %= 10 | ||
d.writeData([]byte{segments[digit]}, pos) | ||
} | ||
|
||
// DisplayClock allows you to display hour and minute numbers | ||
// together with the colon on/off. | ||
func (d *Device) DisplayClock(num1 uint8, num2 uint8, colon bool) { | ||
var sequences []byte | ||
num := []uint8{num1 % 100, num2 % 100} | ||
for k := 0; k < 2; k++ { | ||
for i := 10; i >= 1; i /= 10 { | ||
n := (num[k] / uint8(i)) % 10 | ||
sequences = append(sequences, segments[n]) | ||
} | ||
} | ||
if colon { | ||
sequences[1] |= 1 << 7 | ||
} | ||
d.writeData(sequences, 0) | ||
} | ||
|
||
func encodeChr(c byte) byte { | ||
r := rune(c) | ||
switch { | ||
case r == 32: | ||
return segments[36] // space | ||
case r == 42: | ||
return segments[38] // star/degrees | ||
case r == 45: | ||
return segments[37] // dash | ||
case r >= 65 && r <= 90: | ||
return segments[r-55] // uppercase A-Z | ||
case r >= 97 && r <= 122: | ||
return segments[r-87] // lowercase a-z | ||
case r >= 48 && r <= 57: | ||
return segments[r-48] // 0-9 | ||
default: | ||
return byte(0) | ||
} | ||
} | ||
|
||
func delaytm() { | ||
time.Sleep(time.Microsecond * time.Duration(TM1637_DELAY)) | ||
} | ||
|
||
func pinMode(pin machine.Pin, mode bool) { | ||
// TM1637 has internal pull-up resistors for both CLK and DIO pins. | ||
// Set them to input mode will pull them high, | ||
// and set them to output mode will pull them down | ||
// (since we did so in the beginning.) | ||
// The High()/Low() method don't work on some boards. | ||
if mode { | ||
pin.Configure(machine.PinConfig{Mode: machine.PinInput}) | ||
} else { | ||
pin.Configure(machine.PinConfig{Mode: machine.PinOutput}) | ||
} | ||
} | ||
|
||
func (d *Device) start() { | ||
pinMode(d.dio, false) | ||
delaytm() | ||
pinMode(d.clk, false) | ||
} | ||
|
||
func (d *Device) stop() { | ||
pinMode(d.dio, false) | ||
delaytm() | ||
pinMode(d.clk, true) | ||
delaytm() | ||
pinMode(d.dio, true) | ||
} | ||
|
||
func (d *Device) writeByte(data uint8) { | ||
for i := 0; i < 8; i++ { | ||
pinMode(d.dio, data&(1<<i) > 0) // send bits from LSB to MSB | ||
delaytm() | ||
pinMode(d.clk, true) | ||
delaytm() | ||
pinMode(d.clk, false) | ||
delaytm() | ||
} | ||
pinMode(d.clk, false) | ||
delaytm() | ||
pinMode(d.clk, true) | ||
delaytm() | ||
pinMode(d.clk, false) | ||
} | ||
|
||
func (d *Device) writeCmd() { | ||
d.start() | ||
d.writeByte(TM1637_CMD1) | ||
d.stop() | ||
} | ||
|
||
func (d *Device) writeDsp() { | ||
d.start() | ||
d.writeByte(TM1637_CMD3 | TM1637_DSP_ON | d.brightness) | ||
d.stop() | ||
} | ||
|
||
func (d *Device) writeData(segments []byte, position uint8) { | ||
d.writeCmd() | ||
d.start() | ||
d.writeByte(TM1637_CMD2 | position) | ||
for _, seg := range segments { | ||
d.writeByte(seg) | ||
} | ||
d.stop() | ||
d.writeDsp() | ||
} |