mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-03 06:27:47 +00:00
a53a39922b
On some HD44780 boards (eg the Keyestudio LCD1602 expansion shield), the RW pin isn't brought out and is permanently grounded. This means that the board can't be read from, and in particular the busy status can't be read. This patch adapts the package to work with boards like these. To signal this to the package, set the RW pin to machine.NoPin. The package will then disallow all reading and use adjustable timing based writing. The timing can be adjusted the configuration.
158 lines
3.1 KiB
Go
158 lines
3.1 KiB
Go
package hd44780
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"machine"
|
|
)
|
|
|
|
type GPIO struct {
|
|
dataPins []machine.Pin
|
|
en machine.Pin
|
|
rw machine.Pin
|
|
rs machine.Pin
|
|
|
|
write func(data byte)
|
|
read func() byte
|
|
}
|
|
|
|
func newGPIO(dataPins []machine.Pin, en, rs, rw machine.Pin, mode byte) Device {
|
|
pins := make([]machine.Pin, len(dataPins))
|
|
for i := 0; i < len(dataPins); i++ {
|
|
dataPins[i].Configure(machine.PinConfig{Mode: machine.PinOutput})
|
|
pins[i] = dataPins[i]
|
|
}
|
|
en.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
|
rs.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
|
rw.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
|
rw.Low()
|
|
|
|
gpio := GPIO{
|
|
dataPins: pins,
|
|
en: en,
|
|
rs: rs,
|
|
rw: rw,
|
|
}
|
|
|
|
if mode == DATA_LENGTH_4BIT {
|
|
gpio.write = gpio.write4BitMode
|
|
gpio.read = gpio.read4BitMode
|
|
} else {
|
|
gpio.write = gpio.write8BitMode
|
|
gpio.read = gpio.read8BitMode
|
|
}
|
|
|
|
return Device{
|
|
bus: &gpio,
|
|
datalength: mode,
|
|
}
|
|
}
|
|
|
|
// SetCommandMode sets command/instruction mode
|
|
func (g *GPIO) SetCommandMode(set bool) {
|
|
if set {
|
|
g.rs.Low()
|
|
} else {
|
|
g.rs.High()
|
|
}
|
|
}
|
|
|
|
// WriteOnly is true if you passed rw in as machine.NoPin
|
|
func (g *GPIO) WriteOnly() bool {
|
|
return g.rw == machine.NoPin
|
|
}
|
|
|
|
// Write writes len(data) bytes from data to display driver
|
|
func (g *GPIO) Write(data []byte) (n int, err error) {
|
|
if !g.WriteOnly() {
|
|
g.rw.Low()
|
|
}
|
|
for _, d := range data {
|
|
g.write(d)
|
|
n++
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
func (g *GPIO) write8BitMode(data byte) {
|
|
g.en.High()
|
|
g.setPins(data)
|
|
g.en.Low()
|
|
}
|
|
|
|
func (g *GPIO) write4BitMode(data byte) {
|
|
g.en.High()
|
|
g.setPins(data >> 4)
|
|
g.en.Low()
|
|
|
|
g.en.High()
|
|
g.setPins(data)
|
|
g.en.Low()
|
|
}
|
|
|
|
// Read reads len(data) bytes from display RAM to data starting from RAM address counter position
|
|
// Ram address can be changed by writing address in command mode
|
|
func (g *GPIO) Read(data []byte) (n int, err error) {
|
|
if len(data) == 0 {
|
|
return 0, errors.New("length greater than 0 is required")
|
|
}
|
|
if g.WriteOnly() {
|
|
return 0, errors.New("Read not supported if RW not wired")
|
|
}
|
|
g.rw.High()
|
|
g.reconfigureGPIOMode(machine.PinInput)
|
|
for i := 0; i < len(data); i++ {
|
|
data[i] = g.read()
|
|
n++
|
|
}
|
|
g.reconfigureGPIOMode(machine.PinInput)
|
|
return n, nil
|
|
}
|
|
|
|
func (g *GPIO) read4BitMode() byte {
|
|
g.en.High()
|
|
data := (g.pins() << 4 & 0xF0)
|
|
g.en.Low()
|
|
g.en.High()
|
|
data |= (g.pins() & 0x0F)
|
|
g.en.Low()
|
|
return data
|
|
}
|
|
|
|
func (g *GPIO) read8BitMode() byte {
|
|
g.en.High()
|
|
data := g.pins()
|
|
g.en.Low()
|
|
return data
|
|
}
|
|
|
|
func (g *GPIO) reconfigureGPIOMode(mode machine.PinMode) {
|
|
for i := 0; i < len(g.dataPins); i++ {
|
|
g.dataPins[i].Configure(machine.PinConfig{Mode: mode})
|
|
}
|
|
}
|
|
|
|
// setPins sets high or low state on all data pins depending on data
|
|
func (g *GPIO) setPins(data byte) {
|
|
mask := byte(1)
|
|
for i := 0; i < len(g.dataPins); i++ {
|
|
if (data & mask) != 0 {
|
|
g.dataPins[i].High()
|
|
} else {
|
|
g.dataPins[i].Low()
|
|
}
|
|
mask = mask << 1
|
|
}
|
|
}
|
|
|
|
// pins returns current state of data pins. MSB is D7
|
|
func (g *GPIO) pins() byte {
|
|
bits := byte(0)
|
|
for i := uint8(0); i < uint8(len(g.dataPins)); i++ {
|
|
if g.dataPins[i].Get() {
|
|
bits |= (1 << i)
|
|
}
|
|
}
|
|
return bits
|
|
}
|