Files
2022-01-20 20:01:37 +01:00

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
}