Skip to content

Commit

Permalink
Merge pull request hybridgroup#209 from mattetti/ma-jhd1313m1-refacto…
Browse files Browse the repository at this point in the history
…ring

Fixes LCD setup + wait times to avoid bugs + refactoring
  • Loading branch information
zankich committed Jul 12, 2015
2 parents 00f1a41 + 6cef217 commit f63fab8
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 55 deletions.
2 changes: 1 addition & 1 deletion examples/edison_grove_lcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func main() {
screen.Clear()
screen.Home()
screen.SetRGB(0, 255, 0)
screen.Write("goodbye")
screen.Write("goodbye\nhave a nice day")
})

screen.Home()
Expand Down
7 changes: 4 additions & 3 deletions platforms/i2c/i2c.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
)

var (
ErrEncryptedBytes = errors.New("Encrypted bytes")
ErrNotEnoughBytes = errors.New("Not enough bytes read")
ErrNotReady = errors.New("Device is not ready")
ErrEncryptedBytes = errors.New("Encrypted bytes")
ErrNotEnoughBytes = errors.New("Not enough bytes read")
ErrNotReady = errors.New("Device is not ready")
ErrInvalidPosition = errors.New("Invalid position value")
)

const (
Expand Down
146 changes: 95 additions & 51 deletions platforms/i2c/jhd1313m1_driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,26 @@ const (
LCD_MOVERIGHT = 0x04
LCD_MOVELEFT = 0x00
LCD_2LINE = 0x08
LCD_CMD = 0x80
LCD_DATA = 0x40

LCD_2NDLINEOFFSET = 0x40
)

var _ gobot.Driver = (*JHD1313M1Driver)(nil)

// JHD1313M1Driver is a driver for the Jhd1313m1 LCD display which has two i2c addreses,
// one belongs to a controller and the other controls solely the backlight.
// This module was tested with the Seed Grove LCD RGB Backlight v2.0 display which requires 5V to operate.
// http://www.seeedstudio.com/wiki/Grove_-_LCD_RGB_Backlight
type JHD1313M1Driver struct {
name string
connection I2c
lcdAddress int
rgbAddress int
}

// NewJHD1313M1Driver creates a new driver with specified name and i2c interface
// NewJHD1313M1Driver creates a new driver with specified name and i2c interface.
func NewJHD1313M1Driver(a I2c, name string) *JHD1313M1Driver {
return &JHD1313M1Driver{
name: name,
Expand All @@ -55,11 +63,16 @@ func NewJHD1313M1Driver(a I2c, name string) *JHD1313M1Driver {
}
}

func (h *JHD1313M1Driver) Name() string { return h.name }
func (h *JHD1313M1Driver) Connection() gobot.Connection { return h.connection.(gobot.Connection) }
// Name returns the name the JHD1313M1 Driver was given when created.
func (h *JHD1313M1Driver) Name() string { return h.name }

// Connection returns the driver connection to the device.
func (h *JHD1313M1Driver) Connection() gobot.Connection {
return h.connection.(gobot.Connection)
}

func (h *JHD1313M1Driver) Start() (errs []error) {
cmd := uint8(0)
// Start starts the backlit and the screen and initializes the states.
func (h *JHD1313M1Driver) Start() []error {
if err := h.connection.I2cStart(h.lcdAddress); err != nil {
return []error{err}
}
Expand All @@ -68,40 +81,29 @@ func (h *JHD1313M1Driver) Start() (errs []error) {
return []error{err}
}

cmd |= LCD_2LINE

<-time.After(30 * time.Millisecond)

if err := h.connection.I2cWrite(h.lcdAddress, []byte{0x80, LCD_FUNCTIONSET | cmd}); err != nil {
return []error{err}
<-time.After(50000 * time.Microsecond)
payload := []byte{LCD_CMD, LCD_FUNCTIONSET | LCD_2LINE}
if err := h.connection.I2cWrite(h.lcdAddress, payload); err != nil {
if err := h.connection.I2cWrite(h.lcdAddress, payload); err != nil {
return []error{err}
}
}
<-time.After(40 * time.Nanosecond)

if err := h.connection.I2cWrite(h.lcdAddress, []byte{0x80, LCD_FUNCTIONSET | cmd}); err != nil {
return []error{err}
}
<-time.After(150 * time.Microsecond)
if err := h.connection.I2cWrite(h.lcdAddress, []byte{0x80, LCD_FUNCTIONSET | cmd}); err != nil {
<-time.After(100 * time.Microsecond)
if err := h.connection.I2cWrite(h.lcdAddress, []byte{LCD_CMD, LCD_DISPLAYCONTROL | LCD_DISPLAYON}); err != nil {
return []error{err}
}
if err := h.connection.I2cWrite(h.lcdAddress, []byte{0x80, LCD_FUNCTIONSET | cmd}); err != nil {
return []error{err}
}
cmd |= LCD_DISPLAYON

if err := h.connection.I2cWrite(h.lcdAddress, []byte{0x80, LCD_DISPLAYCONTROL | cmd}); err != nil {
<-time.After(100 * time.Microsecond)
if err := h.Clear(); err != nil {
return []error{err}
}

h.Clear()

cmd |= LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT

if err := h.connection.I2cWrite(h.lcdAddress, []byte{0x80, LCD_ENTRYMODESET | cmd}); err != nil {
if err := h.connection.I2cWrite(h.lcdAddress, []byte{LCD_CMD, LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT}); err != nil {
return []error{err}
}

if err := h.setReg(0, 1); err != nil {
if err := h.setReg(0, 0); err != nil {
return []error{err}
}
if err := h.setReg(1, 0); err != nil {
Expand All @@ -115,45 +117,87 @@ func (h *JHD1313M1Driver) Start() (errs []error) {
return []error{err}
}

return
return nil
}

func (h *JHD1313M1Driver) SetRGB(r, g, b int) (err error) {
if err = h.setReg(REG_RED, r); err != nil {
return
// SetRGB sets the Red Green Blue value of backlit.
func (h *JHD1313M1Driver) SetRGB(r, g, b int) error {
if err := h.setReg(REG_RED, r); err != nil {
return err
}
if err = h.setReg(REG_GREEN, g); err != nil {
return
if err := h.setReg(REG_GREEN, g); err != nil {
return err
}
return h.setReg(REG_BLUE, b)
}

func (h *JHD1313M1Driver) setReg(command int, data int) (err error) {
if err = h.connection.I2cWrite(h.rgbAddress, []byte{byte(command), byte(data)}); err != nil {
return
}
return
}

func (h *JHD1313M1Driver) Clear() (err error) {
return h.command([]byte{LCD_CLEARDISPLAY})
// Clear clears the text on the lCD display.
func (h *JHD1313M1Driver) Clear() error {
err := h.command([]byte{LCD_CLEARDISPLAY})
return err
}

func (h *JHD1313M1Driver) Home() (err error) {
return h.command([]byte{LCD_RETURNHOME})
// Home sets the cursor to the origin position on the display.
func (h *JHD1313M1Driver) Home() error {
err := h.command([]byte{LCD_RETURNHOME})
// This wait fixes a race condition when calling home and clear back to back.
<-time.After(2 * time.Millisecond)
return err
}

func (h *JHD1313M1Driver) Write(message string) (err error) {
// Write displays the passed message on the screen.
func (h *JHD1313M1Driver) Write(message string) error {
// This wait fixes an odd bug where the clear function doesn't always work properly.
<-time.After(1 * time.Millisecond)
for _, val := range message {
if err = h.connection.I2cWrite(h.lcdAddress, []byte{0x40, byte(val)}); err != nil {
break
if val == '\n' {
if err := h.SetPosition(16); err != nil {
return err
}
continue
}
if err := h.connection.I2cWrite(h.lcdAddress, []byte{LCD_DATA, byte(val)}); err != nil {
return err
}
}
return nil
}

// SetPosition sets the cursor and the data display to pos.
// 0..15 are the positions in the first display line.
// 16..32 are the positions in the second display line.
func (h *JHD1313M1Driver) SetPosition(pos int) (err error) {
if pos < 0 || pos > 31 {
err = ErrInvalidPosition
return
}
offset := byte(pos)
if pos >= 16 {
offset -= 16
offset |= LCD_2NDLINEOFFSET
}
err = h.command([]byte{LCD_SETDDRAMADDR | offset})
return
}

func (h *JHD1313M1Driver) Halt() (errs []error) { return }
func (h *JHD1313M1Driver) Scroll(leftToRight bool) error {
if leftToRight {
return h.connection.I2cWrite(h.rgbAddress, []byte{LCD_CMD, LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT})
}

return h.connection.I2cWrite(h.rgbAddress, []byte{LCD_CMD, LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT})
}

// Halt is a noop function.
func (h *JHD1313M1Driver) Halt() []error { return nil }

func (h *JHD1313M1Driver) setReg(command int, data int) error {
if err := h.connection.I2cWrite(h.rgbAddress, []byte{byte(command), byte(data)}); err != nil {
return err
}
return nil
}

func (h *JHD1313M1Driver) command(buf []byte) (err error) {
return h.connection.I2cWrite(h.lcdAddress, append([]byte{0x80}, buf...))
func (h *JHD1313M1Driver) command(buf []byte) error {
return h.connection.I2cWrite(h.lcdAddress, append([]byte{LCD_CMD}, buf...))
}

0 comments on commit f63fab8

Please sign in to comment.