From 7978e3c22b22ec6b32c2f4e1102827be8bc695b1 Mon Sep 17 00:00:00 2001 From: Shannon Wynter Date: Fri, 20 Dec 2024 10:29:41 +1000 Subject: [PATCH] ep0099: optionally read device state on init --- ep0099/ep0099.go | 33 ++++++++++++++++++++++++++++++--- ep0099/ep0099_test.go | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/ep0099/ep0099.go b/ep0099/ep0099.go index e0d764a..410ecec 100644 --- a/ep0099/ep0099.go +++ b/ep0099/ep0099.go @@ -25,7 +25,15 @@ type Dev struct { state [4]State } +type Opts struct { + ReadStates bool // ReadStates from the device on startup instead of resetting the device. +} + func New(bus i2c.Bus, address uint16) (*Dev, error) { + return NewWithOpts(bus, address, nil) +} + +func NewWithOpts(bus i2c.Bus, address uint16, opts *Opts) (*Dev, error) { if err := isValidAddress(address); err != nil { return nil, err } @@ -34,7 +42,12 @@ func New(bus i2c.Bus, address uint16) (*Dev, error) { i2c: i2c.Dev{Bus: bus, Addr: address}, } - if err := d.reset(); err != nil { + bootFn := d.Reset + if opts != nil && opts.ReadStates { + bootFn = d.ReadStates + } + + if err := bootFn(); err != nil { return nil, err } @@ -42,7 +55,7 @@ func New(bus i2c.Bus, address uint16) (*Dev, error) { } func (d *Dev) Halt() error { - return d.reset() + return d.Reset() } func (d *Dev) On(channel uint8) error { @@ -72,6 +85,20 @@ func (d *Dev) State(channel uint8) (State, error) { return d.state[channel-1], nil } +func (d *Dev) ReadStates() error { + for i, channel := range d.AvailableChannels() { + read := make([]byte, 1) + + if err := d.i2c.Tx([]byte{channel}, read); err != nil { + return err + } + + d.state[i] = State(read[0]) + } + + return nil +} + func (d *Dev) AvailableChannels() []uint8 { return []uint8{0x01, 0x02, 0x03, 0x04} } @@ -83,7 +110,7 @@ func (s State) String() string { return "on" } -func (d *Dev) reset() error { +func (d *Dev) Reset() error { for _, channel := range d.AvailableChannels() { err := d.Off(channel) if err != nil { diff --git a/ep0099/ep0099_test.go b/ep0099/ep0099_test.go index 2d661b5..5c38746 100644 --- a/ep0099/ep0099_test.go +++ b/ep0099/ep0099_test.go @@ -12,6 +12,7 @@ import ( "testing" "periph.io/x/conn/v3/i2c/i2ctest" + "periph.io/x/conn/v3/physic" ) const ( @@ -90,6 +91,22 @@ func TestOff(t *testing.T) { checkChannelState(t, dev, 4, StateOff) } +func TestReadState(t *testing.T) { + bus := initTestBus() + bus.Bus = &testBus{states: [4]State{StateOff, StateOn, StateOff, StateOn}} + + dev, err := NewWithOpts(bus, testDefaultValidAddress, &Opts{ReadStates: true}) + + if err != nil { + t.Fatal("Failed to create dev with ReadStates, got ", err) + } + + checkChannelState(t, dev, 1, StateOff) + checkChannelState(t, dev, 2, StateOn) + checkChannelState(t, dev, 3, StateOff) + checkChannelState(t, dev, 4, StateOn) +} + func TestReturnErrorForInvalidChannel(t *testing.T) { bus := initTestBus() dev, _ := New(bus, testDefaultValidAddress) @@ -153,3 +170,27 @@ func checkDevReset(t *testing.T, dev *Dev, bus *i2ctest.Record) { checkBusHasWrite(t, bus, []byte{4, byte(StateOff)}) checkChannelState(t, dev, 4, StateOff) } + +type testBus struct { + states [4]State +} + +func (b *testBus) String() string { + return "ep0099 test i2c bus" +} + +func (b *testBus) Tx(addr uint16, w, r []byte) error { + if len(w) == 1 && len(r) == 1 { + if w[0] < 1 || w[0] > 4 { + return errors.New("Invalid port") + } + + r[0] = byte(b.states[w[0]-1]) + } + + return nil +} + +func (b *testBus) SetSpeed(f physic.Frequency) error { + return nil +}