tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/hd44780/gpio.go (about)

     1  package hd44780
     2  
     3  import (
     4  	"errors"
     5  
     6  	"machine"
     7  )
     8  
     9  type GPIO struct {
    10  	dataPins []machine.Pin
    11  	en       machine.Pin
    12  	rw       machine.Pin
    13  	rs       machine.Pin
    14  
    15  	write func(data byte)
    16  	read  func() byte
    17  }
    18  
    19  func newGPIO(dataPins []machine.Pin, en, rs, rw machine.Pin, mode byte) Device {
    20  	pins := make([]machine.Pin, len(dataPins))
    21  	for i := 0; i < len(dataPins); i++ {
    22  		dataPins[i].Configure(machine.PinConfig{Mode: machine.PinOutput})
    23  		pins[i] = dataPins[i]
    24  	}
    25  	en.Configure(machine.PinConfig{Mode: machine.PinOutput})
    26  	rs.Configure(machine.PinConfig{Mode: machine.PinOutput})
    27  	rw.Configure(machine.PinConfig{Mode: machine.PinOutput})
    28  	rw.Low()
    29  
    30  	gpio := GPIO{
    31  		dataPins: pins,
    32  		en:       en,
    33  		rs:       rs,
    34  		rw:       rw,
    35  	}
    36  
    37  	if mode == DATA_LENGTH_4BIT {
    38  		gpio.write = gpio.write4BitMode
    39  		gpio.read = gpio.read4BitMode
    40  	} else {
    41  		gpio.write = gpio.write8BitMode
    42  		gpio.read = gpio.read8BitMode
    43  	}
    44  
    45  	return Device{
    46  		bus:        &gpio,
    47  		datalength: mode,
    48  	}
    49  }
    50  
    51  // SetCommandMode sets command/instruction mode
    52  func (g *GPIO) SetCommandMode(set bool) {
    53  	if set {
    54  		g.rs.Low()
    55  	} else {
    56  		g.rs.High()
    57  	}
    58  }
    59  
    60  // WriteOnly is true if you passed rw in as machine.NoPin
    61  func (g *GPIO) WriteOnly() bool {
    62  	return g.rw == machine.NoPin
    63  }
    64  
    65  // Write writes len(data) bytes from data to display driver
    66  func (g *GPIO) Write(data []byte) (n int, err error) {
    67  	if !g.WriteOnly() {
    68  		g.rw.Low()
    69  	}
    70  	for _, d := range data {
    71  		g.write(d)
    72  		n++
    73  	}
    74  	return n, nil
    75  }
    76  
    77  func (g *GPIO) write8BitMode(data byte) {
    78  	g.en.High()
    79  	g.setPins(data)
    80  	g.en.Low()
    81  }
    82  
    83  func (g *GPIO) write4BitMode(data byte) {
    84  	g.en.High()
    85  	g.setPins(data >> 4)
    86  	g.en.Low()
    87  
    88  	g.en.High()
    89  	g.setPins(data)
    90  	g.en.Low()
    91  }
    92  
    93  // Read reads len(data) bytes from display RAM to data starting from RAM address counter position
    94  // Ram address can be changed by writing address in command mode
    95  func (g *GPIO) Read(data []byte) (n int, err error) {
    96  	if len(data) == 0 {
    97  		return 0, errors.New("length greater than 0 is required")
    98  	}
    99  	if g.WriteOnly() {
   100  		return 0, errors.New("Read not supported if RW not wired")
   101  	}
   102  	g.rw.High()
   103  	g.reconfigureGPIOMode(machine.PinInput)
   104  	for i := 0; i < len(data); i++ {
   105  		data[i] = g.read()
   106  		n++
   107  	}
   108  	g.rw.Low()
   109  	g.reconfigureGPIOMode(machine.PinOutput)
   110  	return n, nil
   111  }
   112  
   113  func (g *GPIO) read4BitMode() byte {
   114  	g.en.High()
   115  	data := (g.pins() << 4 & 0xF0)
   116  	g.en.Low()
   117  
   118  	g.en.High()
   119  	data |= (g.pins() & 0x0F)
   120  	g.en.Low()
   121  	return data
   122  }
   123  
   124  func (g *GPIO) read8BitMode() byte {
   125  	g.en.High()
   126  	data := g.pins()
   127  	g.en.Low()
   128  	return data
   129  }
   130  
   131  func (g *GPIO) reconfigureGPIOMode(mode machine.PinMode) {
   132  	for i := 0; i < len(g.dataPins); i++ {
   133  		g.dataPins[i].Configure(machine.PinConfig{Mode: mode})
   134  	}
   135  }
   136  
   137  // setPins sets high or low state on all data pins depending on data
   138  func (g *GPIO) setPins(data byte) {
   139  	mask := byte(1)
   140  	for i := 0; i < len(g.dataPins); i++ {
   141  		if (data & mask) != 0 {
   142  			g.dataPins[i].High()
   143  		} else {
   144  			g.dataPins[i].Low()
   145  		}
   146  		mask = mask << 1
   147  	}
   148  }
   149  
   150  // pins returns current state of data pins. MSB is D7
   151  func (g *GPIO) pins() byte {
   152  	bits := byte(0)
   153  	for i := uint8(0); i < uint8(len(g.dataPins)); i++ {
   154  		if g.dataPins[i].Get() {
   155  			bits |= (1 << i)
   156  		}
   157  	}
   158  	return bits
   159  }