Skip to content

Commit da730b2

Browse files
authored
i2c(all): ensure halt is idempotent (#1171)
1 parent ad23d7b commit da730b2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+963
-635
lines changed

drivers/i2c/adafruit1109_driver.go

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,23 @@ type Adafruit1109Driver struct {
2626
*MCP23017Driver
2727
*gpio.HD44780Driver
2828

29-
name string
30-
redPin adafruit1109PortPin
31-
greenPin adafruit1109PortPin
32-
bluePin adafruit1109PortPin
33-
selectPin adafruit1109PortPin
34-
upPin adafruit1109PortPin
35-
downPin adafruit1109PortPin
36-
leftPin adafruit1109PortPin
37-
rightPin adafruit1109PortPin
38-
rwPin adafruit1109PortPin
39-
rsPin adafruit1109PortPin
40-
enPin adafruit1109PortPin
41-
dataPinD4 adafruit1109PortPin
42-
dataPinD5 adafruit1109PortPin
43-
dataPinD6 adafruit1109PortPin
44-
dataPinD7 adafruit1109PortPin
29+
name string
30+
redPin adafruit1109PortPin
31+
greenPin adafruit1109PortPin
32+
bluePin adafruit1109PortPin
33+
selectPin adafruit1109PortPin
34+
upPin adafruit1109PortPin
35+
downPin adafruit1109PortPin
36+
leftPin adafruit1109PortPin
37+
rightPin adafruit1109PortPin
38+
rwPin adafruit1109PortPin
39+
rsPin adafruit1109PortPin
40+
enPin adafruit1109PortPin
41+
dataPinD4 adafruit1109PortPin
42+
dataPinD5 adafruit1109PortPin
43+
dataPinD6 adafruit1109PortPin
44+
dataPinD7 adafruit1109PortPin
45+
mcpStarted bool
4546
}
4647

4748
// NewAdafruit1109Driver creates is a new driver for the 2x16 LCD display with RGB backlit and 5 keys.
@@ -120,6 +121,8 @@ func (d *Adafruit1109Driver) Start() error {
120121
return err
121122
}
122123

124+
d.mcpStarted = true
125+
123126
// set all to output (inputs will be set by initButton)
124127
for pin := uint8(0); pin <= 7; pin++ {
125128
if err := d.SetPinMode(pin, "A", 0); err != nil {
@@ -169,15 +172,20 @@ func (d *Adafruit1109Driver) Halt() error {
169172
if err := d.HD44780Driver.Halt(); err != nil {
170173
errors = append(errors, err.Error())
171174
}
172-
// switch off the background light
173-
if err := d.SetRGB(false, false, false); err != nil {
174-
errors = append(errors, err.Error())
175-
}
176-
// must be after HD44780Driver
177-
if err := d.MCP23017Driver.Halt(); err != nil {
178-
errors = append(errors, err.Error())
175+
176+
if d.mcpStarted {
177+
// switch off the background light
178+
if err := d.SetRGB(false, false, false); err != nil {
179+
errors = append(errors, err.Error())
180+
}
181+
// must be after HD44780Driver
182+
if err := d.MCP23017Driver.Halt(); err != nil {
183+
errors = append(errors, err.Error())
184+
}
179185
}
180186

187+
d.mcpStarted = false
188+
181189
if len(errors) > 0 {
182190
return fmt.Errorf("'Halt' the driver %s", strings.Join(errors, ", "))
183191
}

drivers/i2c/adafruit1109_driver_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ func TestAdafruit1109StartReadErr(t *testing.T) {
8888

8989
func TestAdafruit1109Halt(t *testing.T) {
9090
d, _ := initTestAdafruit1109WithStubbedAdaptor()
91-
_ = d.Start()
91+
require.NoError(t, d.Halt()) // must be idempotent
92+
require.NoError(t, d.Start())
9293
require.NoError(t, d.Halt())
9394
}
9495

drivers/i2c/adafruit2327_driver_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ func TestNewAdafruit2327Driver(t *testing.T) {
3232
assert.Equal(t, 0x40, d.defaultAddress)
3333
}
3434

35+
func TestAdafruit2327Halt(t *testing.T) {
36+
// arrange
37+
d := NewAdafruit2327Driver(newI2cTestAdaptor())
38+
// act, assert
39+
require.NoError(t, d.Halt()) // must be idempotent
40+
require.NoError(t, d.Start())
41+
require.NoError(t, d.Halt())
42+
}
43+
3544
func TestAdafruit2327Options(t *testing.T) {
3645
// This is a general test, that options are applied in constructor by using the common WithBus() option and
3746
// least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)".

drivers/i2c/adafruit2348_driver.go

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -125,54 +125,54 @@ func NewAdafruit2348Driver(c Connector, options ...func(Config)) *Adafruit2348Dr
125125
}
126126

127127
// SetDCMotorSpeed will set the appropriate pins to run the specified DC motor for the given speed.
128-
func (a *Adafruit2348Driver) SetDCMotorSpeed(dcMotor int, speed int32) error {
129-
return a.SetPWM(int(a.dcMotors[dcMotor].pwmPin), 0, uint16(speed*16)) //nolint:gosec // TODO: fix later
128+
func (d *Adafruit2348Driver) SetDCMotorSpeed(dcMotor int, speed int32) error {
129+
return d.SetPWM(int(d.dcMotors[dcMotor].pwmPin), 0, uint16(speed*16)) //nolint:gosec // TODO: fix later
130130
}
131131

132132
// RunDCMotor will set the appropriate pins to run the specified DC motor for the given direction.
133-
func (a *Adafruit2348Driver) RunDCMotor(dcMotor int, dir Adafruit2348Direction) error {
133+
func (d *Adafruit2348Driver) RunDCMotor(dcMotor int, dir Adafruit2348Direction) error {
134134
switch dir {
135135
case Adafruit2348Forward:
136-
if err := a.setPin(a.dcMotors[dcMotor].in2Pin, 0); err != nil {
136+
if err := d.setPin(d.dcMotors[dcMotor].in2Pin, 0); err != nil {
137137
return err
138138
}
139-
if err := a.setPin(a.dcMotors[dcMotor].in1Pin, 1); err != nil {
139+
if err := d.setPin(d.dcMotors[dcMotor].in1Pin, 1); err != nil {
140140
return err
141141
}
142142
case Adafruit2348Backward:
143-
if err := a.setPin(a.dcMotors[dcMotor].in1Pin, 0); err != nil {
143+
if err := d.setPin(d.dcMotors[dcMotor].in1Pin, 0); err != nil {
144144
return err
145145
}
146-
if err := a.setPin(a.dcMotors[dcMotor].in2Pin, 1); err != nil {
146+
if err := d.setPin(d.dcMotors[dcMotor].in2Pin, 1); err != nil {
147147
return err
148148
}
149149
case Adafruit2348Release:
150-
if err := a.setPin(a.dcMotors[dcMotor].in1Pin, 0); err != nil {
150+
if err := d.setPin(d.dcMotors[dcMotor].in1Pin, 0); err != nil {
151151
return err
152152
}
153-
if err := a.setPin(a.dcMotors[dcMotor].in2Pin, 0); err != nil {
153+
if err := d.setPin(d.dcMotors[dcMotor].in2Pin, 0); err != nil {
154154
return err
155155
}
156156
}
157157
return nil
158158
}
159159

160160
// SetStepperMotorSpeed sets the seconds-per-step for the given stepper motor. It is applied in the next cycle.
161-
func (a *Adafruit2348Driver) SetStepperMotorSpeed(stepperMotor int, rpm int) error {
162-
a.stepperSpeedMutex.Lock()
163-
defer a.stepperSpeedMutex.Unlock()
161+
func (d *Adafruit2348Driver) SetStepperMotorSpeed(stepperMotor int, rpm int) error {
162+
d.stepperSpeedMutex.Lock()
163+
defer d.stepperSpeedMutex.Unlock()
164164

165-
revSteps := a.stepperMotors[stepperMotor].revSteps
166-
a.stepperMotors[stepperMotor].secPerStep = 60.0 / float64(revSteps*rpm)
165+
revSteps := d.stepperMotors[stepperMotor].revSteps
166+
d.stepperMotors[stepperMotor].secPerStep = 60.0 / float64(revSteps*rpm)
167167
return nil
168168
}
169169

170170
// Step will rotate the stepper motor the given number of steps, in the given direction and step style.
171-
func (a *Adafruit2348Driver) Step(motor, steps int, dir Adafruit2348Direction, style Adafruit2348StepStyle) error {
172-
a.stepperSpeedMutex.Lock()
173-
defer a.stepperSpeedMutex.Unlock()
171+
func (d *Adafruit2348Driver) Step(motor, steps int, dir Adafruit2348Direction, style Adafruit2348StepStyle) error {
172+
d.stepperSpeedMutex.Lock()
173+
defer d.stepperSpeedMutex.Unlock()
174174

175-
secPerStep := a.stepperMotors[motor].secPerStep
175+
secPerStep := d.stepperMotors[motor].secPerStep
176176
var latestStep int
177177
var err error
178178
if style == Adafruit2348Interleave {
@@ -186,7 +186,7 @@ func (a *Adafruit2348Driver) Step(motor, steps int, dir Adafruit2348Direction, s
186186
log.Printf("[adafruit2348_driver] %f seconds per step", secPerStep)
187187
}
188188
for i := 0; i < steps; i++ {
189-
if latestStep, err = a.oneStep(motor, dir, style); err != nil {
189+
if latestStep, err = d.oneStep(motor, dir, style); err != nil {
190190
return err
191191
}
192192
time.Sleep(time.Duration(secPerStep) * time.Second)
@@ -195,7 +195,7 @@ func (a *Adafruit2348Driver) Step(motor, steps int, dir Adafruit2348Direction, s
195195
// This is an edge case, if we are in between full steps, keep going to end on a full step
196196
if style == Adafruit2348Microstep {
197197
for latestStep != 0 && latestStep != adafruit2348StepperMicrosteps {
198-
if latestStep, err = a.oneStep(motor, dir, style); err != nil {
198+
if latestStep, err = d.oneStep(motor, dir, style); err != nil {
199199
return err
200200
}
201201
time.Sleep(time.Duration(secPerStep) * time.Second)
@@ -204,94 +204,94 @@ func (a *Adafruit2348Driver) Step(motor, steps int, dir Adafruit2348Direction, s
204204
return nil
205205
}
206206

207-
func (a *Adafruit2348Driver) oneStep(motor int, dir Adafruit2348Direction, style Adafruit2348StepStyle) (int, error) {
207+
func (d *Adafruit2348Driver) oneStep(motor int, dir Adafruit2348Direction, style Adafruit2348StepStyle) (int, error) {
208208
pwmA := 255
209209
pwmB := 255
210210

211211
// Determine the stepping procedure
212212
switch style {
213213
case Adafruit2348Single:
214-
if (a.stepperMotors[motor].currentStep / (adafruit2348StepperMicrosteps / 2) % 2) != 0 {
214+
if (d.stepperMotors[motor].currentStep / (adafruit2348StepperMicrosteps / 2) % 2) != 0 {
215215
// we're at an odd step
216216
if dir == Adafruit2348Forward {
217-
a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps / 2
217+
d.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps / 2
218218
} else {
219-
a.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps / 2
219+
d.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps / 2
220220
}
221221
} else {
222222
// go to next even step
223223
if dir == Adafruit2348Forward {
224-
a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps
224+
d.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps
225225
} else {
226-
a.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps
226+
d.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps
227227
}
228228
}
229229
case Adafruit2348Double:
230-
if (a.stepperMotors[motor].currentStep / (adafruit2348StepperMicrosteps / 2) % 2) == 0 {
230+
if (d.stepperMotors[motor].currentStep / (adafruit2348StepperMicrosteps / 2) % 2) == 0 {
231231
// we're at an even step, weird
232232
if dir == Adafruit2348Forward {
233-
a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps / 2
233+
d.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps / 2
234234
} else {
235-
a.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps / 2
235+
d.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps / 2
236236
}
237237
} else {
238238
// go to next odd step
239239
if dir == Adafruit2348Forward {
240-
a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps
240+
d.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps
241241
} else {
242-
a.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps
242+
d.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps
243243
}
244244
}
245245
case Adafruit2348Interleave:
246246
if dir == Adafruit2348Forward {
247-
a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps / 2
247+
d.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps / 2
248248
} else {
249-
a.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps / 2
249+
d.stepperMotors[motor].currentStep -= adafruit2348StepperMicrosteps / 2
250250
}
251251
case Adafruit2348Microstep:
252252
if dir == Adafruit2348Forward {
253-
a.stepperMotors[motor].currentStep++
253+
d.stepperMotors[motor].currentStep++
254254
} else {
255-
a.stepperMotors[motor].currentStep--
255+
d.stepperMotors[motor].currentStep--
256256
}
257257
// go to next step and wrap around
258-
a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps * 4
259-
a.stepperMotors[motor].currentStep %= adafruit2348StepperMicrosteps * 4
258+
d.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps * 4
259+
d.stepperMotors[motor].currentStep %= adafruit2348StepperMicrosteps * 4
260260

261261
pwmA = 0
262262
pwmB = 0
263-
currStep := a.stepperMotors[motor].currentStep
263+
currStep := d.stepperMotors[motor].currentStep
264264
switch {
265265
case currStep >= 0 && currStep < adafruit2348StepperMicrosteps:
266-
pwmA = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps-currStep]
267-
pwmB = a.stepperMicrostepCurve[currStep]
266+
pwmA = d.stepperMicrostepCurve[adafruit2348StepperMicrosteps-currStep]
267+
pwmB = d.stepperMicrostepCurve[currStep]
268268
case currStep >= adafruit2348StepperMicrosteps && currStep < adafruit2348StepperMicrosteps*2:
269-
pwmA = a.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps]
270-
pwmB = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps*2-currStep]
269+
pwmA = d.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps]
270+
pwmB = d.stepperMicrostepCurve[adafruit2348StepperMicrosteps*2-currStep]
271271
case currStep >= adafruit2348StepperMicrosteps*2 && currStep < adafruit2348StepperMicrosteps*3:
272-
pwmA = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps*3-currStep]
273-
pwmB = a.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps*2]
272+
pwmA = d.stepperMicrostepCurve[adafruit2348StepperMicrosteps*3-currStep]
273+
pwmB = d.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps*2]
274274
case currStep >= adafruit2348StepperMicrosteps*3 && currStep < adafruit2348StepperMicrosteps*4:
275-
pwmA = a.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps*3]
276-
pwmB = a.stepperMicrostepCurve[adafruit2348StepperMicrosteps*4-currStep]
275+
pwmA = d.stepperMicrostepCurve[currStep-adafruit2348StepperMicrosteps*3]
276+
pwmB = d.stepperMicrostepCurve[adafruit2348StepperMicrosteps*4-currStep]
277277
}
278278
} // switch
279279

280280
// go to next 'step' and wrap around
281-
a.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps * 4
282-
a.stepperMotors[motor].currentStep %= adafruit2348StepperMicrosteps * 4
281+
d.stepperMotors[motor].currentStep += adafruit2348StepperMicrosteps * 4
282+
d.stepperMotors[motor].currentStep %= adafruit2348StepperMicrosteps * 4
283283

284284
// only really used for microstepping, otherwise always on!
285285
//nolint:gosec // TODO: fix later
286-
if err := a.SetPWM(int(a.stepperMotors[motor].pwmPinA), 0, uint16(pwmA*16)); err != nil {
286+
if err := d.SetPWM(int(d.stepperMotors[motor].pwmPinA), 0, uint16(pwmA*16)); err != nil {
287287
return 0, err
288288
}
289289
//nolint:gosec // TODO: fix later
290-
if err := a.SetPWM(int(a.stepperMotors[motor].pwmPinB), 0, uint16(pwmB*16)); err != nil {
290+
if err := d.SetPWM(int(d.stepperMotors[motor].pwmPinB), 0, uint16(pwmB*16)); err != nil {
291291
return 0, err
292292
}
293293
var coils []int32
294-
currStep := a.stepperMotors[motor].currentStep
294+
currStep := d.stepperMotors[motor].currentStep
295295
if style == Adafruit2348Microstep {
296296
switch {
297297
case currStep >= 0 && currStep < adafruit2348StepperMicrosteps:
@@ -305,34 +305,34 @@ func (a *Adafruit2348Driver) oneStep(motor int, dir Adafruit2348Direction, style
305305
}
306306
} else {
307307
// step-2-coils is initialized in init()
308-
coils = a.step2coils[(currStep / (adafruit2348StepperMicrosteps / 2))]
308+
coils = d.step2coils[(currStep / (adafruit2348StepperMicrosteps / 2))]
309309
}
310310
if adafruit2348Debug {
311311
log.Printf("[adafruit2348_driver] currStep: %d, index into step2coils: %d\n",
312312
currStep, (currStep / (adafruit2348StepperMicrosteps / 2)))
313313
log.Printf("[adafruit2348_driver] coils state = %v", coils)
314314
}
315-
if err := a.setPin(a.stepperMotors[motor].ain2, coils[0]); err != nil {
315+
if err := d.setPin(d.stepperMotors[motor].ain2, coils[0]); err != nil {
316316
return 0, err
317317
}
318-
if err := a.setPin(a.stepperMotors[motor].bin1, coils[1]); err != nil {
318+
if err := d.setPin(d.stepperMotors[motor].bin1, coils[1]); err != nil {
319319
return 0, err
320320
}
321-
if err := a.setPin(a.stepperMotors[motor].ain1, coils[2]); err != nil {
321+
if err := d.setPin(d.stepperMotors[motor].ain1, coils[2]); err != nil {
322322
return 0, err
323323
}
324-
if err := a.setPin(a.stepperMotors[motor].bin2, coils[3]); err != nil {
324+
if err := d.setPin(d.stepperMotors[motor].bin2, coils[3]); err != nil {
325325
return 0, err
326326
}
327-
return a.stepperMotors[motor].currentStep, nil
327+
return d.stepperMotors[motor].currentStep, nil
328328
}
329329

330-
func (a *Adafruit2348Driver) setPin(pin byte, value int32) error {
330+
func (d *Adafruit2348Driver) setPin(pin byte, value int32) error {
331331
if value == 0 {
332-
return a.SetPWM(int(pin), 0, 4096)
332+
return d.SetPWM(int(pin), 0, 4096)
333333
}
334334
if value == 1 {
335-
return a.SetPWM(int(pin), 4096, 0)
335+
return d.SetPWM(int(pin), 4096, 0)
336336
}
337337
return errors.New("invalid pin")
338338
}

drivers/i2c/adafruit2348_driver_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@ func TestNewAdafruit2348Driver(t *testing.T) {
3333
assert.Equal(t, 0x60, d.GetAddressOrDefault(d.defaultAddress)) // the really used address
3434
}
3535

36+
func TestAdafruit2348Halt(t *testing.T) {
37+
// arrange
38+
d := NewAdafruit2348Driver(newI2cTestAdaptor())
39+
// act, assert
40+
require.NoError(t, d.Halt()) // must be idempotent
41+
require.NoError(t, d.Start())
42+
require.NoError(t, d.Halt())
43+
}
44+
3645
func TestAdafruit2348Options(t *testing.T) {
3746
// This is a general test, that options are applied in constructor by using the common WithBus() option and
3847
// least one of this driver. Further tests for options can also be done by call of "WithOption(val)(d)".

drivers/i2c/ads1x15_driver.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -476,11 +476,11 @@ func (d *ADS1x15Driver) waitForConversionFinished(delay time.Duration) error {
476476
}
477477

478478
func (d *ADS1x15Driver) writeWordBigEndian(reg uint8, val uint16) error {
479-
return d.connection.WriteWordData(reg, swapBytes(val))
479+
return d.writeWordData(reg, swapBytes(val))
480480
}
481481

482482
func (d *ADS1x15Driver) readWordBigEndian(reg uint8) (uint16, error) {
483-
data, err := d.connection.ReadWordData(reg)
483+
data, err := d.readWordData(reg)
484484
if err != nil {
485485
return 0, err
486486
}

0 commit comments

Comments
 (0)