mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +00:00
160 lines
3.1 KiB
Go
160 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.rw.Low()
|
|
g.reconfigureGPIOMode(machine.PinOutput)
|
|
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
|
|
}
|