|
|
|
@ -12,7 +12,6 @@ import (
|
|
|
|
"errors"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"log"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"time"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
|
"periph.io/x/conn/v3/physic"
|
|
|
|
"periph.io/x/conn/v3/physic"
|
|
|
|
@ -52,7 +51,6 @@ const (
|
|
|
|
// Type for a Maxim MAX7219/MAX7221 device.
|
|
|
|
// Type for a Maxim MAX7219/MAX7221 device.
|
|
|
|
type Dev struct {
|
|
|
|
type Dev struct {
|
|
|
|
conn spi.Conn
|
|
|
|
conn spi.Conn
|
|
|
|
mu sync.Mutex
|
|
|
|
|
|
|
|
// decode mode for all data registers
|
|
|
|
// decode mode for all data registers
|
|
|
|
decode DecodeMode
|
|
|
|
decode DecodeMode
|
|
|
|
// units is the number of 7219 units daisy-chained together.
|
|
|
|
// units is the number of 7219 units daisy-chained together.
|
|
|
|
@ -88,7 +86,6 @@ func (d *Dev) init() {
|
|
|
|
{_REGISTER_SCAN_LIMIT, d.digits - 1},
|
|
|
|
{_REGISTER_SCAN_LIMIT, d.digits - 1},
|
|
|
|
{_REGISTER_SHUTDOWN, 0x01}}
|
|
|
|
{_REGISTER_SHUTDOWN, 0x01}}
|
|
|
|
|
|
|
|
|
|
|
|
d.mu.Lock()
|
|
|
|
|
|
|
|
for _, cmd := range initCommands {
|
|
|
|
for _, cmd := range initCommands {
|
|
|
|
err := d.sendCommand(cmd[0], cmd[1])
|
|
|
|
err := d.sendCommand(cmd[0], cmd[1])
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
@ -96,7 +93,6 @@ func (d *Dev) init() {
|
|
|
|
break
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
d.mu.Unlock()
|
|
|
|
|
|
|
|
if d.units == 1 {
|
|
|
|
if d.units == 1 {
|
|
|
|
_ = d.SetDecode(DecodeB)
|
|
|
|
_ = d.SetDecode(DecodeB)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
@ -123,12 +119,13 @@ func (d *Dev) sendCommand(register, data byte) error {
|
|
|
|
// of Max7219 chips daisy-chained together. numDigits is the number of digits
|
|
|
|
// of Max7219 chips daisy-chained together. numDigits is the number of digits
|
|
|
|
// displayed.
|
|
|
|
// displayed.
|
|
|
|
func NewSPI(p spi.Port, units, numDigits int) (*Dev, error) {
|
|
|
|
func NewSPI(p spi.Port, units, numDigits int) (*Dev, error) {
|
|
|
|
if numDigits <= 0 {
|
|
|
|
|
|
|
|
return nil, errors.New("invalid value for number of digits")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if units <= 0 {
|
|
|
|
if units <= 0 {
|
|
|
|
return nil, errors.New("invalid value for number of cascaded units")
|
|
|
|
return nil, errors.New("max7219: invalid value for number of cascaded units")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if numDigits <= 0 || numDigits > 8 {
|
|
|
|
|
|
|
|
return nil, errors.New("max7219: invalid value for number of digits")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// It works in Mode0, Mode2 and Mode3.
|
|
|
|
// It works in Mode0, Mode2 and Mode3.
|
|
|
|
c, err := p.Connect(10*physic.MegaHertz, spi.Mode0, 8)
|
|
|
|
c, err := p.Connect(10*physic.MegaHertz, spi.Mode0, 8)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
@ -242,8 +239,6 @@ func (d *Dev) ScrollChars(data []byte, scrollCount int, updateInterval time.Dura
|
|
|
|
// just writing digits, you just need 0-9 and whatever punctuation marks you
|
|
|
|
// just writing digits, you just need 0-9 and whatever punctuation marks you
|
|
|
|
// need.
|
|
|
|
// need.
|
|
|
|
func (d *Dev) SetGlyphs(glyphs [][]byte, reverse bool) {
|
|
|
|
func (d *Dev) SetGlyphs(glyphs [][]byte, reverse bool) {
|
|
|
|
d.mu.Lock()
|
|
|
|
|
|
|
|
defer d.mu.Unlock()
|
|
|
|
|
|
|
|
if reverse {
|
|
|
|
if reverse {
|
|
|
|
d.glyphs = reverseGlyphs(glyphs)
|
|
|
|
d.glyphs = reverseGlyphs(glyphs)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
@ -256,8 +251,6 @@ func (d *Dev) SetGlyphs(glyphs [][]byte, reverse bool) {
|
|
|
|
// for more detailed information.
|
|
|
|
// for more detailed information.
|
|
|
|
func (d *Dev) SetDecode(mode DecodeMode) error {
|
|
|
|
func (d *Dev) SetDecode(mode DecodeMode) error {
|
|
|
|
d.decode = mode
|
|
|
|
d.decode = mode
|
|
|
|
d.mu.Lock()
|
|
|
|
|
|
|
|
defer d.mu.Unlock()
|
|
|
|
|
|
|
|
return d.sendCommand(_REGISTER_DECODE_MODE, byte(mode))
|
|
|
|
return d.sendCommand(_REGISTER_DECODE_MODE, byte(mode))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -272,8 +265,6 @@ func (d *Dev) SetIntensity(intensity byte) error {
|
|
|
|
// and the intensity to maximum. If you're using multiple units, you should be
|
|
|
|
// and the intensity to maximum. If you're using multiple units, you should be
|
|
|
|
// aware of the current draw, and limit how long you leave this on.
|
|
|
|
// aware of the current draw, and limit how long you leave this on.
|
|
|
|
func (d *Dev) TestDisplay(on bool) error {
|
|
|
|
func (d *Dev) TestDisplay(on bool) error {
|
|
|
|
d.mu.Lock()
|
|
|
|
|
|
|
|
defer d.mu.Unlock()
|
|
|
|
|
|
|
|
if on {
|
|
|
|
if on {
|
|
|
|
return d.sendCommand(_REGISTER_DISPLAY_TEST, 1)
|
|
|
|
return d.sendCommand(_REGISTER_DISPLAY_TEST, 1)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
@ -354,8 +345,6 @@ func (d *Dev) Write(bytes []byte) error {
|
|
|
|
// single-unit numeric display.
|
|
|
|
// single-unit numeric display.
|
|
|
|
var digit = d.digits
|
|
|
|
var digit = d.digits
|
|
|
|
w := make([]byte, 2)
|
|
|
|
w := make([]byte, 2)
|
|
|
|
d.mu.Lock()
|
|
|
|
|
|
|
|
defer d.mu.Unlock()
|
|
|
|
|
|
|
|
for _, val := range bytes {
|
|
|
|
for _, val := range bytes {
|
|
|
|
w[0] = digit
|
|
|
|
w[0] = digit
|
|
|
|
w[1] = val
|
|
|
|
w[1] = val
|
|
|
|
@ -396,12 +385,9 @@ func (d *Dev) Write(bytes []byte) error {
|
|
|
|
// value on the display. It will work for either matrixes (with a glyph set)
|
|
|
|
// value on the display. It will work for either matrixes (with a glyph set)
|
|
|
|
// or numeric displays.
|
|
|
|
// or numeric displays.
|
|
|
|
func (d *Dev) WriteInt(value int) error {
|
|
|
|
func (d *Dev) WriteInt(value int) error {
|
|
|
|
var digits int
|
|
|
|
digits := d.units
|
|
|
|
if d.decode == DecodeNone {
|
|
|
|
if d.decode != DecodeNone {
|
|
|
|
// This is a matrix
|
|
|
|
digits *= int(d.digits)
|
|
|
|
digits = d.units
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
digits = d.units * int(d.digits)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return d.Write([]byte(fmt.Sprintf("%*d", digits, value)))
|
|
|
|
return d.Write([]byte(fmt.Sprintf("%*d", digits, value)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -413,8 +399,6 @@ func (d *Dev) WriteInt(value int) error {
|
|
|
|
// to the next in a chain.
|
|
|
|
// to the next in a chain.
|
|
|
|
func (d *Dev) WriteCascadedUnits(bytes [][]byte) error {
|
|
|
|
func (d *Dev) WriteCascadedUnits(bytes [][]byte) error {
|
|
|
|
matrixCount := len(bytes)
|
|
|
|
matrixCount := len(bytes)
|
|
|
|
d.mu.Lock()
|
|
|
|
|
|
|
|
defer d.mu.Unlock()
|
|
|
|
|
|
|
|
for rasterLine := 0; rasterLine < int(d.digits); rasterLine++ {
|
|
|
|
for rasterLine := 0; rasterLine < int(d.digits); rasterLine++ {
|
|
|
|
w := make([]byte, 0)
|
|
|
|
w := make([]byte, 0)
|
|
|
|
for matrix := matrixCount - 1; matrix >= 0; matrix-- {
|
|
|
|
for matrix := matrixCount - 1; matrix >= 0; matrix-- {
|
|
|
|
@ -447,8 +431,6 @@ func (d *Dev) WriteCascadedUnit(offset int, data []byte) error {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
d.mu.Lock()
|
|
|
|
|
|
|
|
defer d.mu.Unlock()
|
|
|
|
|
|
|
|
err := d.conn.Tx(w, nil)
|
|
|
|
err := d.conn.Tx(w, nil)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
|