mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-04-26 13:48:49 +08:00
fixed PinMode, SetPullUp and SetPolarity, unit tests activated
This commit is contained in:
parent
37eeda80f5
commit
d43d3430d9
@ -9,9 +9,17 @@ import (
|
||||
)
|
||||
|
||||
// default address for device when a2/a1/a0 pins are all tied to ground
|
||||
// please consider special handling for MCP23S17
|
||||
const mcp23017Address = 0x20
|
||||
|
||||
const debug = false // toggle debugging information
|
||||
const mcp23017Debug = false // toggle debugging information
|
||||
|
||||
type bitState uint8
|
||||
|
||||
const (
|
||||
clear bitState = 0x00
|
||||
set = 0x01
|
||||
)
|
||||
|
||||
// port contains all the registers for the device.
|
||||
type port struct {
|
||||
@ -107,6 +115,8 @@ func WithMCP23017Disslw(val uint8) func(Config) {
|
||||
}
|
||||
|
||||
// WithMCP23017Haen option sets the MCP23017Driver Haen option
|
||||
// This feature is only available for MCP23S17.
|
||||
// Address pins are always enabled on the MCP23017.
|
||||
func WithMCP23017Haen(val uint8) func(Config) {
|
||||
return func(c Config) {
|
||||
d, ok := c.(*MCP23017Driver)
|
||||
@ -222,51 +232,21 @@ func (m *MCP23017Driver) Start() (err error) {
|
||||
// WriteGPIO writes a value to a gpio pin (0-7) and a port (A or B).
|
||||
func (m *MCP23017Driver) WriteGPIO(pin uint8, val uint8, portStr string) (err error) {
|
||||
selectedPort := m.getPort(portStr)
|
||||
// read current value of IODIR register
|
||||
iodir, err := m.read(selectedPort.IODIR)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// set pin as output by clearing bit
|
||||
iodirVal := clearBit(iodir, uint8(pin))
|
||||
// write IODIR register bit
|
||||
err = m.write(selectedPort.IODIR, uint8(pin), uint8(iodirVal))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// read current value of OLAT register
|
||||
olat, err := m.read(selectedPort.OLAT)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// set or clear olat value, 0 is no output, 1 is an output
|
||||
var olatVal uint8
|
||||
if val == 0 {
|
||||
olatVal = clearBit(olat, uint8(pin))
|
||||
} else {
|
||||
olatVal = setBit(olat, uint8(pin))
|
||||
}
|
||||
// write OLAT register bit
|
||||
err = m.write(selectedPort.OLAT, uint8(pin), uint8(olatVal))
|
||||
err = m.write(selectedPort.IODIR, pin, clear)
|
||||
// write value to OLAT register bit
|
||||
err = m.write(selectedPort.OLAT, pin, bitState(val))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadGPIO reads a value from a given gpio pin (0-7) and a
|
||||
// port (A or B).
|
||||
// ReadGPIO reads a value from a given gpio pin (0-7) and a port (A or B).
|
||||
func (m *MCP23017Driver) ReadGPIO(pin uint8, portStr string) (val uint8, err error) {
|
||||
selectedPort := m.getPort(portStr)
|
||||
// read current value of IODIR register
|
||||
iodir, err := m.read(selectedPort.IODIR)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// set pin as input by setting bit
|
||||
iodirVal := setBit(iodir, uint8(pin))
|
||||
// write IODIR register bit
|
||||
err = m.write(selectedPort.IODIR, uint8(pin), uint8(iodirVal))
|
||||
err = m.write(selectedPort.IODIR, pin, set)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -286,7 +266,7 @@ func (m *MCP23017Driver) ReadGPIO(pin uint8, portStr string) (val uint8, err err
|
||||
// val = 0 pull up disabled.
|
||||
func (m *MCP23017Driver) SetPullUp(pin uint8, val uint8, portStr string) error {
|
||||
selectedPort := m.getPort(portStr)
|
||||
return m.write(selectedPort.GPPU, pin, val)
|
||||
return m.write(selectedPort.GPPU, pin, bitState(val))
|
||||
}
|
||||
|
||||
// SetGPIOPolarity will change a given pin's polarity based on the value:
|
||||
@ -294,7 +274,7 @@ func (m *MCP23017Driver) SetPullUp(pin uint8, val uint8, portStr string) error {
|
||||
// val = 0 same logic state of the input pin.
|
||||
func (m *MCP23017Driver) SetGPIOPolarity(pin uint8, val uint8, portStr string) (err error) {
|
||||
selectedPort := m.getPort(portStr)
|
||||
return m.write(selectedPort.IPOL, pin, val)
|
||||
return m.write(selectedPort.IPOL, pin, bitState(val))
|
||||
}
|
||||
|
||||
// PinMode set pin mode of a given pin based on the value:
|
||||
@ -303,42 +283,43 @@ func (m *MCP23017Driver) SetGPIOPolarity(pin uint8, val uint8, portStr string) (
|
||||
func (m *MCP23017Driver) PinMode(pin, val uint8, portStr string) (err error) {
|
||||
selectedPort := m.getPort(portStr)
|
||||
// Set IODIR register bit for given pin to an output/input.
|
||||
if err = m.write(selectedPort.IODIR, uint8(pin), val); err != nil {
|
||||
if err = m.write(selectedPort.IODIR, uint8(pin), bitState(val)); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// write gets the value of the passed in register, and then overwrites
|
||||
// the bit specified by the pin, with the given value.
|
||||
func (m *MCP23017Driver) write(reg uint8, pin uint8, val uint8) (err error) {
|
||||
ioval := val
|
||||
if debug {
|
||||
// write gets the value of the passed in register, and then sets the bit specified
|
||||
// by the pin to the given state.
|
||||
func (m *MCP23017Driver) write(reg uint8, pin uint8, state bitState) (err error) {
|
||||
var ioval uint8
|
||||
iodir, err := m.read(reg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if state == set {
|
||||
ioval = setBit(iodir, pin)
|
||||
} else {
|
||||
ioval = clearBit(iodir, pin)
|
||||
}
|
||||
if mcp23017Debug {
|
||||
log.Printf("write: MCP address: 0x%X, register: 0x%X, name: %s, value: 0x%X\n",
|
||||
m.GetAddressOrDefault(mcp23017Address), reg, m.getRegName(reg), ioval)
|
||||
}
|
||||
if _, err = m.connection.Write([]uint8{reg, val}); err != nil {
|
||||
if err = m.connection.WriteByteData(reg, ioval); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// read get the data from a given register
|
||||
// it is mainly a wrapper to create additional debug messages, when activated
|
||||
func (m *MCP23017Driver) read(reg uint8) (val uint8, err error) {
|
||||
buf := []byte{0}
|
||||
if _, err := m.connection.Write([]uint8{reg}); err != nil {
|
||||
return val, err
|
||||
}
|
||||
bytesRead, err := m.connection.Read(buf)
|
||||
val, err = m.connection.ReadByteData(reg)
|
||||
if err != nil {
|
||||
return val, err
|
||||
}
|
||||
if bytesRead != 1 {
|
||||
err = ErrNotEnoughBytes
|
||||
return
|
||||
}
|
||||
val = buf[0]
|
||||
if debug {
|
||||
if mcp23017Debug {
|
||||
log.Printf("reading: MCP address: 0x%X, register:0x%X, name: %s, value: 0x%X\n",
|
||||
m.GetAddressOrDefault(mcp23017Address), reg, m.getRegName(reg), val)
|
||||
}
|
||||
|
@ -277,15 +277,13 @@ func TestMCP23017DriverPinMode(t *testing.T) {
|
||||
// arrange some values
|
||||
testPort := "A"
|
||||
testPin := uint8(7)
|
||||
wantReg := uint8(0x00) // IODIRA
|
||||
returnRead := uint8(0xFF) // emulate all ports are inputs
|
||||
/*
|
||||
wantRegVal := returnRead & 0x7F // bit 7 reset, all other untouched
|
||||
if bitState == 1 {
|
||||
returnRead = 0x00 // emulate all ports are outputs
|
||||
wantRegVal = returnRead | 0x80 // bit 7 set, all other untouched
|
||||
}
|
||||
*/
|
||||
wantReg := uint8(0x00) // IODIRA
|
||||
returnRead := uint8(0xFF) // emulate all ports are inputs
|
||||
wantRegVal := returnRead & 0x7F // bit 7 reset, all other untouched
|
||||
if bitState == 1 {
|
||||
returnRead = 0x00 // emulate all ports are outputs
|
||||
wantRegVal = returnRead | 0x80 // bit 7 set, all other untouched
|
||||
}
|
||||
// arrange reads
|
||||
numCallsRead := 0
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
@ -300,9 +298,7 @@ func TestMCP23017DriverPinMode(t *testing.T) {
|
||||
gobottest.Assert(t, len(adaptor.written), 3)
|
||||
gobottest.Assert(t, adaptor.written[0], wantReg)
|
||||
gobottest.Assert(t, adaptor.written[1], wantReg)
|
||||
/* TODO this line cause an exception now after switch to #569
|
||||
gobottest.Assert(t, adaptor.written[2], wantRegVal)
|
||||
*/
|
||||
gobottest.Assert(t, numCallsRead, 1)
|
||||
}
|
||||
}
|
||||
@ -335,14 +331,12 @@ func TestMCP23017DriverSetPullUp(t *testing.T) {
|
||||
testPort := "A"
|
||||
wantReg := uint8(0x0C) // GPPUA
|
||||
testPin := uint8(5)
|
||||
returnRead := uint8(0xFF) // emulate all I's with pull up
|
||||
/*
|
||||
wantSetVal := returnRead & 0xDF // bit 5 cleared, all other unchanged
|
||||
if bitState == 1 {
|
||||
returnRead = uint8(0x00) // emulate all I's without pull up
|
||||
wantSetVal = returnRead | 0x20 // bit 5 set, all other unchanged
|
||||
}
|
||||
*/
|
||||
returnRead := uint8(0xFF) // emulate all I's with pull up
|
||||
wantSetVal := returnRead & 0xDF // bit 5 cleared, all other unchanged
|
||||
if bitState == 1 {
|
||||
returnRead = uint8(0x00) // emulate all I's without pull up
|
||||
wantSetVal = returnRead | 0x20 // bit 5 set, all other unchanged
|
||||
}
|
||||
// arrange reads
|
||||
numCallsRead := 0
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
@ -357,9 +351,7 @@ func TestMCP23017DriverSetPullUp(t *testing.T) {
|
||||
gobottest.Assert(t, len(adaptor.written), 3)
|
||||
gobottest.Assert(t, adaptor.written[0], wantReg)
|
||||
gobottest.Assert(t, adaptor.written[1], wantReg)
|
||||
/* TODO this line cause an exception now after switch to #569
|
||||
gobottest.Assert(t, adaptor.written[2], wantSetVal)
|
||||
*/
|
||||
gobottest.Assert(t, numCallsRead, 1)
|
||||
}
|
||||
}
|
||||
@ -392,14 +384,12 @@ func TestMCP23017DriverSetGPIOPolarity(t *testing.T) {
|
||||
testPort := "B"
|
||||
wantReg := uint8(0x03) // IPOLB
|
||||
testPin := uint8(6)
|
||||
returnRead := uint8(0xFF) // emulate all I's negotiated
|
||||
/*
|
||||
wantSetVal := returnRead & 0xBF // bit 6 cleared, all other unchanged
|
||||
if bitState == 1 {
|
||||
returnRead = uint8(0x00) // emulate all I's not negotiated
|
||||
wantSetVal = returnRead | 0x40 // bit 6 set, all other unchanged
|
||||
}
|
||||
*/
|
||||
returnRead := uint8(0xFF) // emulate all I's negotiated
|
||||
wantSetVal := returnRead & 0xBF // bit 6 cleared, all other unchanged
|
||||
if bitState == 1 {
|
||||
returnRead = uint8(0x00) // emulate all I's not negotiated
|
||||
wantSetVal = returnRead | 0x40 // bit 6 set, all other unchanged
|
||||
}
|
||||
// arrange reads
|
||||
numCallsRead := 0
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
@ -414,9 +404,7 @@ func TestMCP23017DriverSetGPIOPolarity(t *testing.T) {
|
||||
gobottest.Assert(t, len(adaptor.written), 3)
|
||||
gobottest.Assert(t, adaptor.written[0], wantReg)
|
||||
gobottest.Assert(t, adaptor.written[1], wantReg)
|
||||
/* TODO this line cause an exception now after switch to #569
|
||||
gobottest.Assert(t, adaptor.written[2], wantSetVal)
|
||||
*/
|
||||
gobottest.Assert(t, numCallsRead, 1)
|
||||
}
|
||||
}
|
||||
@ -510,10 +498,6 @@ func TestMCP23017Driver_read(t *testing.T) {
|
||||
// read
|
||||
mcp, adaptor = initTestMCP23017DriverWithStubbedAdaptor(0)
|
||||
port = mcp.getPort("A")
|
||||
_, err = mcp.read(port.IODIR)
|
||||
gobottest.Assert(t, err, ErrNotEnoughBytes)
|
||||
mcp, adaptor = initTestMCP23017DriverWithStubbedAdaptor(0)
|
||||
port = mcp.getPort("A")
|
||||
adaptor.i2cReadImpl = func(b []byte) (int, error) {
|
||||
copy(b, []byte{255})
|
||||
return 1, nil
|
||||
|
Loading…
x
Reference in New Issue
Block a user