mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-16 21:03:23 +00:00
tester: add a mock for command-oriented i2c devices
This commit is contained in:
@@ -10,6 +10,9 @@ type I2CDevice interface {
|
|||||||
// WriteRegister implements I2C.WriteRegister.
|
// WriteRegister implements I2C.WriteRegister.
|
||||||
WriteRegister(r uint8, buf []byte) error
|
WriteRegister(r uint8, buf []byte) error
|
||||||
|
|
||||||
|
// Tx implements I2C.Tx
|
||||||
|
Tx(w, r []byte) error
|
||||||
|
|
||||||
// Addr returns the Device address.
|
// Addr returns the Device address.
|
||||||
Addr() uint8
|
Addr() uint8
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,3 +72,9 @@ func (d *I2CDevice16) WriteRegister(r uint8, buf []byte) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tx implements I2C.Tx.
|
||||||
|
func (bus *I2CDevice16) Tx(w, r []byte) error {
|
||||||
|
// TODO: implement this
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,6 +53,12 @@ func (d *I2CDevice8) WriteRegister(r uint8, buf []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tx implements I2C.Tx.
|
||||||
|
func (bus *I2CDevice8) Tx(w, r []byte) error {
|
||||||
|
// TODO: implement this
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// assertRegisterRange asserts that reading or writing the given
|
// assertRegisterRange asserts that reading or writing the given
|
||||||
// register and subsequent registers is in range of the available registers.
|
// register and subsequent registers is in range of the available registers.
|
||||||
func (d *I2CDevice8) assertRegisterRange(r uint8, buf []byte) {
|
func (d *I2CDevice8) assertRegisterRange(r uint8, buf []byte) {
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
package tester
|
||||||
|
|
||||||
|
// Cmd represents a command sent via I2C to a device.
|
||||||
|
//
|
||||||
|
// A command matches when (Command & Mask) == (Data & Mask). If
|
||||||
|
// a command is recognized, Response bytes is returned.
|
||||||
|
type Cmd struct {
|
||||||
|
Command []byte
|
||||||
|
Mask []byte
|
||||||
|
Response []byte
|
||||||
|
Invocations int
|
||||||
|
}
|
||||||
|
|
||||||
|
// I2CDeviceCmd represents a mock I2C device that does not
|
||||||
|
// have 'registers', but has a command/response model.
|
||||||
|
//
|
||||||
|
// Commands and canned responses are pre-loaded into the
|
||||||
|
// Commands member. For each command the mock receives it
|
||||||
|
// will lookup the command and return the corresponding
|
||||||
|
// canned response.
|
||||||
|
type I2CDeviceCmd struct {
|
||||||
|
c Failer
|
||||||
|
|
||||||
|
// addr is the i2c device address.
|
||||||
|
addr uint8
|
||||||
|
|
||||||
|
// Commands are the commands the device recognizes and responds to.
|
||||||
|
Commands map[uint8]*Cmd
|
||||||
|
|
||||||
|
// Command response that is pending (used with a command is split over)
|
||||||
|
// two transactions
|
||||||
|
pendingResponse []byte
|
||||||
|
|
||||||
|
// If Err is non-nil, it will be returned as the error from the
|
||||||
|
// I2C methods.
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewI2CDeviceCmd returns a new mock I2C device.
|
||||||
|
func NewI2CDeviceCmd(c Failer, addr uint8) *I2CDeviceCmd {
|
||||||
|
return &I2CDeviceCmd{
|
||||||
|
c: c,
|
||||||
|
addr: addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addr returns the Device address.
|
||||||
|
func (d *I2CDeviceCmd) Addr() uint8 {
|
||||||
|
return d.addr
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadRegister implements I2C.ReadRegister.
|
||||||
|
func (d *I2CDeviceCmd) ReadRegister(r uint8, buf []byte) error {
|
||||||
|
if d.Err != nil {
|
||||||
|
return d.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteRegister implements I2C.WriteRegister.
|
||||||
|
func (d *I2CDeviceCmd) WriteRegister(r uint8, buf []byte) error {
|
||||||
|
if d.Err != nil {
|
||||||
|
return d.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tx implements I2C.Tx.
|
||||||
|
func (d *I2CDeviceCmd) Tx(w, r []byte) error {
|
||||||
|
if d.Err != nil {
|
||||||
|
return d.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(w) == 0 && len(d.pendingResponse) != 0 {
|
||||||
|
return d.respond(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := d.FindCommand(w)
|
||||||
|
if cmd == nil {
|
||||||
|
d.c.Fatalf("command [%#x] not identified", w)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Invocations++
|
||||||
|
d.pendingResponse = cmd.Response
|
||||||
|
return d.respond(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *I2CDeviceCmd) FindCommand(command []byte) *Cmd {
|
||||||
|
for _, c := range d.Commands {
|
||||||
|
if len(c.Command) > len(command) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
match := true
|
||||||
|
for i := 0; i < len(c.Command); i++ {
|
||||||
|
mask := c.Mask[i]
|
||||||
|
if (c.Command[i] & mask) != (command[i] & mask) {
|
||||||
|
match = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if match {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *I2CDeviceCmd) respond(r []byte) error {
|
||||||
|
if len(r) > len(d.pendingResponse) {
|
||||||
|
d.c.Fatalf("read too large (expected: <= %#x, got: %#x)",
|
||||||
|
len(d.pendingResponse), len(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(r) > 0 {
|
||||||
|
copy(r, d.pendingResponse[:len(r)])
|
||||||
|
d.pendingResponse = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+1
-2
@@ -48,8 +48,7 @@ func (bus *I2CBus) WriteRegister(addr uint8, r uint8, buf []byte) error {
|
|||||||
|
|
||||||
// Tx implements I2C.Tx.
|
// Tx implements I2C.Tx.
|
||||||
func (bus *I2CBus) Tx(addr uint16, w, r []byte) error {
|
func (bus *I2CBus) Tx(addr uint16, w, r []byte) error {
|
||||||
// TODO: implement this
|
return bus.FindDevice(uint8(addr)).Tx(w, r)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindDevice returns the device with the given address.
|
// FindDevice returns the device with the given address.
|
||||||
|
|||||||
Reference in New Issue
Block a user