More cleanups and testing work

pull/91/head
George Sexton 1 year ago
parent 98dbd48829
commit 4242fd7315

@ -36,8 +36,9 @@ MatrixOrbital LK2047T, the AdaFruit USB+Serial Backpack etc.
The driver package is designed to use the gpio.Group interface. This allows The driver package is designed to use the gpio.Group interface. This allows
the LCD driver to be agnostic about the physical connection between the display the LCD driver to be agnostic about the physical connection between the display
and the host device. Any host/expander that supports the GPIO group can be used and the host device. Any host/expander that supports the
to easily drive the LCD display. periph.io/x/conn/v3/gpio.Group interface can be used to easily drive the LCD
display.
## Hardware Notes ## Hardware Notes
@ -52,5 +53,8 @@ transistor (2N2222 or equivalent).
If nothing displays at all, check the contrast. Adjust the contrast control If nothing displays at all, check the contrast. Adjust the contrast control
until the 5x7 dot grid on the display is visible. until the 5x7 dot grid on the display is visible.
If the first row contains blocks of dots, and the other rows are blank, then
the initialization of the device failed. Check IO pins are connected properly.
If the text is garbled, verify the gpio.Group is configured and the IO Pins If the text is garbled, verify the gpio.Group is configured and the IO Pins
are connected to the right pins of the LCD display. are connected to the right pins of the LCD display.

@ -49,12 +49,14 @@ func NewAdafruitI2CBackpack(bus i2c.Bus, address uint16, rows, cols int) (*HD447
// This function returns a display configured to use the SPI side of the Adafruit // This function returns a display configured to use the SPI side of the Adafruit
// I2c/SPI backpack. The SPI side uses a 74HC595 Serial->Parallel shift register. // I2c/SPI backpack. The SPI side uses a 74HC595 Serial->Parallel shift register.
func NewAdafruitSPIBackpack(conn spi.Conn, rows, cols int) (*HD44780, error) { func NewAdafruitSPIBackpack(conn spi.Conn, rows, cols int) (*HD44780, error) {
chip := nxp74hc595.New(conn) chip, err := nxp74hc595.New(conn)
if err != nil {
return nil, err
}
// The SPI side has the same pins but in reverse order from the I2C side. // The SPI side has the same pins but in reverse order from the I2C side.
gr, _ := chip.Group(d7, d6, d5, d4) gr, _ := chip.Group(d7, d6, d5, d4)
rs := &chip.Pins[rsPin] rs := &chip.Pins[rsPin]
e := &chip.Pins[enablePin] e := &chip.Pins[enablePin]
bl := &chip.Pins[backlightPin] bl := chip.Pins[backlightPin]
return NewHD44780(gr, rs, e, NewBacklight(bl), rows, cols) return NewHD44780(gr, rs, e, NewBacklight(bl), rows, cols)
} }

@ -5,6 +5,8 @@
package hd44780 package hd44780
import ( import (
"fmt"
"periph.io/x/conn/v3/display" "periph.io/x/conn/v3/display"
"periph.io/x/conn/v3/gpio" "periph.io/x/conn/v3/gpio"
) )
@ -31,4 +33,8 @@ func (bl *GPIOMonoBacklight) Backlight(intensity display.Intensity) (err error)
return err return err
} }
func (bl *GPIOMonoBacklight) String() string {
return fmt.Sprintf("%#v", bl)
}
var _ display.DisplayBacklight = &GPIOMonoBacklight{} var _ display.DisplayBacklight = &GPIOMonoBacklight{}

@ -10,14 +10,15 @@ import (
"log" "log"
"time" "time"
"golang.org/x/exp/io/spi"
"periph.io/x/conn/v3/display" "periph.io/x/conn/v3/display"
"periph.io/x/conn/v3/display/displaytest" "periph.io/x/conn/v3/display/displaytest"
"periph.io/x/conn/v3/gpio" "periph.io/x/conn/v3/gpio"
"periph.io/x/conn/v3/i2c/i2creg" "periph.io/x/conn/v3/i2c/i2creg"
"periph.io/x/conn/v3/physic" "periph.io/x/conn/v3/physic"
"periph.io/x/conn/v3/spi"
"periph.io/x/conn/v3/spi/spireg" "periph.io/x/conn/v3/spi/spireg"
"periph.io/x/devices/v3/hd44780" "periph.io/x/devices/v3/hd44780"
"periph.io/x/devices/v3/pcf857x"
"periph.io/x/host/v3" "periph.io/x/host/v3"
"periph.io/x/host/v3/gpioioctl" "periph.io/x/host/v3/gpioioctl"
) )
@ -54,13 +55,13 @@ func Example() {
fmt.Printf("n=%d, err=%s\n", n, err) fmt.Printf("n=%d, err=%s\n", n, err)
fmt.Println("lcd=", lcd.String()) fmt.Println("lcd=", lcd.String())
lcd.Home() _ = lcd.Home()
lcd.MoveTo(1, 1) _ = lcd.MoveTo(1, 1)
lcd.WriteString("Line 1") _, _ = lcd.WriteString("Line 1")
lcd.MoveTo(2, 2) _ = lcd.MoveTo(2, 2)
lcd.WriteString("Line 2") _, _ = lcd.WriteString("Line 2")
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
lcd.Clear() _ = lcd.Clear()
fmt.Println("calling TestTextDisplay") fmt.Println("calling TestTextDisplay")
@ -91,8 +92,8 @@ func ExampleNewAdafruitI2CBackpack() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
dev.Clear() _ = dev.Clear()
dev.WriteString("Hello") _, _ = dev.WriteString("Hello")
fmt.Println("wrote hello") fmt.Println("wrote hello")
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
fmt.Println("calling test text display") fmt.Println("calling test text display")
@ -144,14 +145,14 @@ func ExampleNewPCF857xBackpack() {
} }
for range 5 { for range 5 {
fmt.Println("toggling backlight") fmt.Println("toggling backlight")
dev.Backlight(0) _ = dev.Backlight(0)
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
dev.Backlight(255) _ = dev.Backlight(255)
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
} }
dev.Clear() _ = dev.Clear()
dev.WriteString("Hello") _, _ = dev.WriteString("Hello")
fmt.Println("wrote hello") fmt.Println("wrote hello")
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
fmt.Println("calling test text display") fmt.Println("calling test text display")

@ -41,7 +41,8 @@ type HD44780 struct {
dataPins gpio.Group dataPins gpio.Group
resetPin gpio.PinOut resetPin gpio.PinOut
enablePin gpio.PinOut enablePin gpio.PinOut
bl interface{} blMono display.DisplayBacklight
blRGB display.DisplayRGBBacklight
mode ifMode mode ifMode
rows int rows int
cols int cols int
@ -70,18 +71,20 @@ func getRowConstant(row, maxcols int) byte {
return rowConstants[offset][row] return rowConstants[offset][row]
} }
// NewHD44780 takes a GPIO group, and gpio.PinOut for reset, enable, and // NewHD44780 takes a GPIO group, and gpio.PinOut for reset and enable. It
// backlight. It returns a the HD44780 device in an initialized state and // returns an HD44780 device in an initialized state and ready for use.
// ready for use.
// //
// The first 4 or 8 pins of the data group must be connected to the data lines // The first 4 or 8 pins of the data group must be connected to the data lines
// To use 4 bit mode, you would connect lines D4-D7 on the display, and for // To use 4 bit mode, you would connect lines D4-D7 on the display, and for 8
// 8 bit mode, D0-D7. If dataPinGroup is 8 or more pins, then it's assumed the display is // bit mode, D0-D7. If dataPinGroup is 8 or more pins, then it's assumed the
// connected using all 8 pins. // display is connected using all 8 pins.
//
// backlight should implement either display.DisplayBacklight or
// display.DisplayRGBBacklight. See GPIOMonoBacklight.
func NewHD44780( func NewHD44780(
dataPinGroup gpio.Group, dataPinGroup gpio.Group,
resetPin, enablePin *gpio.PinOut, resetPin, enablePin *gpio.PinOut,
backlight interface{}, backlight any,
rows, cols int) (*HD44780, error) { rows, cols int) (*HD44780, error) {
mode := mode4Bit mode := mode4Bit
@ -89,17 +92,22 @@ func NewHD44780(
mode = mode8Bit mode = mode8Bit
} }
display := &HD44780{ lcd := &HD44780{
dataPins: dataPinGroup, dataPins: dataPinGroup,
resetPin: *resetPin, resetPin: *resetPin,
enablePin: *enablePin, enablePin: *enablePin,
bl: backlight,
mode: mode, mode: mode,
rows: rows, rows: rows,
cols: cols, cols: cols,
on: true, on: true,
} }
return display, display.init() switch bl := backlight.(type) {
case display.DisplayBacklight:
lcd.blMono = bl
case display.DisplayRGBBacklight:
lcd.blRGB = bl
}
return lcd, lcd.init()
} }
// Not supported by this device. Returns display.ErrNotImplemented // Not supported by this device. Returns display.ErrNotImplemented
@ -206,7 +214,7 @@ func (lcd *HD44780) Rows() int {
// Return info about the dsiplay. // Return info about the dsiplay.
func (lcd *HD44780) String() string { func (lcd *HD44780) String() string {
return fmt.Sprintf("HD44780::%s - Rows: %d, Cols: %d", lcd.dataPins.String(), lcd.rows, lcd.cols) return fmt.Sprintf("HD44780 - Rows: %d, Cols: %d", lcd.rows, lcd.cols)
} }
// Turn the display on / off // Turn the display on / off
@ -280,39 +288,35 @@ func (lcd *HD44780) Halt() error {
// Set the backlight intensity. // Set the backlight intensity.
func (lcd *HD44780) Backlight(intensity display.Intensity) error { func (lcd *HD44780) Backlight(intensity display.Intensity) error {
switch bl := lcd.bl.(type) { if lcd.blMono != nil {
case display.DisplayBacklight: return lcd.blMono.Backlight(intensity)
return bl.Backlight(intensity) } else if lcd.blRGB != nil {
case display.DisplayRGBBacklight: return lcd.blRGB.RGBBacklight(intensity, intensity, intensity)
return bl.RGBBacklight(intensity, intensity, intensity)
default:
return display.ErrNotImplemented
} }
return display.ErrNotImplemented
} }
// For units that have an RGB Backlight, set the backlight color/intensity. // For units that have an RGB Backlight, set the backlight color/intensity.
// The range of the values is 0-255. // The range of the values is 0-255.
func (lcd *HD44780) RGBBacklight(red, green, blue display.Intensity) error { func (lcd *HD44780) RGBBacklight(red, green, blue display.Intensity) error {
switch bl := lcd.bl.(type) { if lcd.blRGB != nil {
case display.DisplayRGBBacklight: return lcd.blRGB.RGBBacklight(red, green, blue)
return bl.RGBBacklight(red, green, blue) } else if lcd.blMono != nil {
case display.DisplayBacklight: return lcd.blMono.Backlight(red | green | blue)
return bl.Backlight(red | green | blue)
default:
return display.ErrNotImplemented
} }
return display.ErrNotImplemented
} }
// delayWrite looks at the time of the last LCD write and if // delayWrite looks at the time of the last LCD write and if the specified
// the specified microseconds period has not elapsed, it // microseconds period has not elapsed, it invokes time.Sleep() with the
// invokes time.Sleep() with the difference. // difference.
// //
// Some I/O methods, like direct GPIO on a Pi are very fast, while other methods // Some I/O methods, like direct GPIO on a Pi are very fast, while other methods
// like i2c take longer. Without delays, on very fast I/O paths, the LCD will // like i2c take longer. Without delays, on very fast I/O paths, the LCD will
// display garbage. The correct way to handle this would be to read the Busy flag // display garbage. The correct way to handle this would be to read the Busy
// on the LCD display. However, some backpacks don't have the capability to // flag on the LCD display. However, some backpacks don't have the capability to
// check the Busy flag because the R/W pin isn't connected. So, we can't correctly // check the Busy flag because the R/W pin isn't connected. So, we can't
// handle io delays. This handles the very fast interfaces, while not // correctly handle io delays. This handles the very fast interfaces, while not
// penalizing the slower ones with unnecessary delays. // penalizing the slower ones with unnecessary delays.
// //
// The value of lcd.lastWrite is updated to the current time by the call. // The value of lcd.lastWrite is updated to the current time by the call.
@ -380,8 +384,9 @@ func (lcd *HD44780) init() error {
_ = lcd.Display(true) _ = lcd.Display(true)
_ = lcd.Clear() _ = lcd.Clear()
_ = lcd.Home() _ = lcd.Home()
// If there's not a backlight, ignore the error.
return lcd.Backlight(0xff) _ = lcd.Backlight(0xff)
return nil
} }
func (lcd *HD44780) sendCommand(commands []byte) error { func (lcd *HD44780) sendCommand(commands []byte) error {
@ -431,4 +436,5 @@ func (lcd *HD44780) writeBits(value, mask gpio.GPIOValue) error {
var _ display.TextDisplay = &HD44780{} var _ display.TextDisplay = &HD44780{}
var _ display.DisplayBacklight = &HD44780{} var _ display.DisplayBacklight = &HD44780{}
var _ display.DisplayRGBBacklight = &HD44780{}
var _ conn.Resource = &HD44780{} var _ conn.Resource = &HD44780{}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save