Skip to content

Commit 281c85c

Browse files
authored
[RSDK-1963] servo digital interrupts are only in the raspberry pi code (viamrobotics#3369)
I had this much, much cleaner, where the only part left in the `board` package was the interface, and all the implementation details were left up to the boards. but then it turned out that a bunch of unit tests were using these as well, and I had to put a bunch of stuff back. Main changes: - The `PostProcessor` type is gone. The `Formula` field in the interrupt config is gone. - There is a copy of all the digital interrupt stuff (including the configs) in board/pi/impl/ now. That component uses this new copy. - The main (non-pi) version of digital interrupts no longer has a `ServoDigitalInterrupt` implementation. - The main (non-pi) version of digital interrupt configs no longer takes a Type.
1 parent 89c8bf3 commit 281c85c

19 files changed

+452
-315
lines changed

components/board/board.go

-5
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,6 @@ type AnalogReader interface {
8888
Close(ctx context.Context) error
8989
}
9090

91-
// A PostProcessor takes a raw input and transforms it into a new value.
92-
// Multiple post processors can be stacked on each other. This is currently
93-
// only used in DigitalInterrupt readings.
94-
type PostProcessor func(raw int64) int64
95-
9691
// FromDependencies is a helper for getting the named board from a collection of
9792
// dependencies.
9893
func FromDependencies(deps resource.Dependencies, name string) (Board, error) {

components/board/client.go

-4
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,6 @@ func (dic *digitalInterruptClient) RemoveCallback(c chan Tick) {
253253
panic(errUnimplemented)
254254
}
255255

256-
func (dic *digitalInterruptClient) AddPostProcessor(pp PostProcessor) {
257-
panic(errUnimplemented)
258-
}
259-
260256
// gpioPinClient satisfies a gRPC based board.GPIOPin. Refer to the interface
261257
// for descriptions of its methods.
262258
type gpioPinClient struct {

components/board/config.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,8 @@ func (config *AnalogReaderConfig) Validate(path string) error {
5151

5252
// DigitalInterruptConfig describes the configuration of digital interrupt for a board.
5353
type DigitalInterruptConfig struct {
54-
Name string `json:"name"`
55-
Pin string `json:"pin"`
56-
Type string `json:"type,omitempty"` // e.g. basic, servo
57-
Formula string `json:"formula,omitempty"`
54+
Name string `json:"name"`
55+
Pin string `json:"pin"`
5856
}
5957

6058
// Validate ensures all parts of the config are valid.

components/board/digital_interrupts.go

+2-179
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,7 @@ import (
55
"sync"
66
"sync/atomic"
77

8-
"github.com/erh/scheme"
98
"github.com/pkg/errors"
10-
11-
"go.viam.com/rdk/utils"
129
)
1310

1411
// ServoRollingAverageWindow is how many entries to average over for
@@ -27,8 +24,7 @@ type Tick struct {
2724
}
2825

2926
// A DigitalInterrupt represents a configured interrupt on the board that
30-
// when interrupted, calls the added callbacks. Post processors can also
31-
// be added to modify what Value ultimately returns.
27+
// when interrupted, calls the added callbacks.
3228
type DigitalInterrupt interface {
3329
// Value returns the current value of the interrupt which is
3430
// based on the type of interrupt.
@@ -44,10 +40,6 @@ type DigitalInterrupt interface {
4440
// happens.
4541
AddCallback(c chan Tick)
4642

47-
// AddPostProcessor adds a post processor that should be used to modify
48-
// what is returned by Value.
49-
AddPostProcessor(pp PostProcessor)
50-
5143
// RemoveCallback removes a listener for interrupts
5244
RemoveCallback(c chan Tick)
5345

@@ -64,19 +56,7 @@ type ReconfigurableDigitalInterrupt interface {
6456
// CreateDigitalInterrupt is a factory method for creating a specific DigitalInterrupt based
6557
// on the given config. If no type is specified, a BasicDigitalInterrupt is returned.
6658
func CreateDigitalInterrupt(cfg DigitalInterruptConfig) (ReconfigurableDigitalInterrupt, error) {
67-
if cfg.Type == "" {
68-
cfg.Type = "basic"
69-
}
70-
71-
var i ReconfigurableDigitalInterrupt
72-
switch cfg.Type {
73-
case "basic":
74-
i = &BasicDigitalInterrupt{}
75-
case "servo":
76-
i = &ServoDigitalInterrupt{ra: utils.NewRollingAverage(ServoRollingAverageWindow)}
77-
default:
78-
panic(errors.Errorf("unknown interrupt type (%s)", cfg.Type))
79-
}
59+
i := &BasicDigitalInterrupt{}
8060

8161
if err := i.Reconfigure(cfg); err != nil {
8262
return nil, err
@@ -93,24 +73,13 @@ type BasicDigitalInterrupt struct {
9373

9474
mu sync.RWMutex
9575
cfg DigitalInterruptConfig
96-
pp PostProcessor
97-
}
98-
99-
// Config returns the config used to create this interrupt.
100-
func (i *BasicDigitalInterrupt) Config(ctx context.Context) (DigitalInterruptConfig, error) {
101-
i.mu.RLock()
102-
defer i.mu.RUnlock()
103-
return i.cfg, nil
10476
}
10577

10678
// Value returns the amount of ticks that have occurred.
10779
func (i *BasicDigitalInterrupt) Value(ctx context.Context, extra map[string]interface{}) (int64, error) {
10880
i.mu.RLock()
10981
defer i.mu.RUnlock()
11082
count := atomic.LoadInt64(&i.count)
111-
if i.pp != nil {
112-
return i.pp(count), nil
113-
}
11483
return count, nil
11584
}
11685

@@ -165,162 +134,16 @@ func (i *BasicDigitalInterrupt) RemoveCallback(c chan Tick) {
165134
}
166135
}
167136

168-
// AddPostProcessor sets the post processor that will modify the value that
169-
// Value returns.
170-
func (i *BasicDigitalInterrupt) AddPostProcessor(pp PostProcessor) {
171-
i.mu.Lock()
172-
defer i.mu.Unlock()
173-
i.pp = pp
174-
}
175-
176137
// Close does nothing.
177138
func (i *BasicDigitalInterrupt) Close(ctx context.Context) error {
178139
return nil
179140
}
180141

181-
func processFormula(oldFormula, newFormula, name string) (func(raw int64) int64, bool, error) {
182-
if oldFormula == newFormula {
183-
return nil, false, nil
184-
}
185-
x, err := scheme.Parse(newFormula)
186-
if err != nil {
187-
return nil, false, errors.Wrapf(err, "couldn't parse formula for %s", name)
188-
}
189-
190-
testScope := scheme.Scope{}
191-
num := 1.0
192-
testScope["raw"] = &scheme.Value{Float: &num}
193-
_, err = scheme.Eval(x, testScope)
194-
if err != nil {
195-
return nil, false, errors.Wrapf(err, "test exec failed for %s", name)
196-
}
197-
198-
return func(raw int64) int64 {
199-
scope := scheme.Scope{}
200-
rr := float64(raw) // TODO(erh): fix
201-
scope["raw"] = &scheme.Value{Float: &rr}
202-
res, err := scheme.Eval(x, scope)
203-
if err != nil {
204-
panic(err)
205-
}
206-
f, err := res.ToFloat()
207-
if err != nil {
208-
panic(err)
209-
}
210-
return int64(f)
211-
}, true, nil
212-
}
213-
214142
// Reconfigure reconfigures this digital interrupt with a new formula.
215143
func (i *BasicDigitalInterrupt) Reconfigure(conf DigitalInterruptConfig) error {
216144
i.mu.Lock()
217145
defer i.mu.Unlock()
218146

219-
newFormula, isNew, err := processFormula(i.cfg.Formula, conf.Formula, conf.Name)
220-
if err != nil {
221-
return err
222-
}
223-
if !isNew {
224-
return nil
225-
}
226-
i.pp = newFormula
227147
i.cfg = conf
228148
return nil
229149
}
230-
231-
// A ServoDigitalInterrupt is an interrupt associated with a servo in order to
232-
// track the amount of time that has passed between low signals (pulse width). Post processors
233-
// make meaning of these widths.
234-
type ServoDigitalInterrupt struct {
235-
last uint64
236-
ra *utils.RollingAverage
237-
238-
mu sync.RWMutex
239-
cfg DigitalInterruptConfig
240-
pp PostProcessor
241-
}
242-
243-
// Config returns the config the interrupt was created with.
244-
func (i *ServoDigitalInterrupt) Config(ctx context.Context) (DigitalInterruptConfig, error) {
245-
i.mu.RLock()
246-
defer i.mu.RUnlock()
247-
return i.cfg, nil
248-
}
249-
250-
// Value will return the window averaged value followed by its post processed
251-
// result.
252-
func (i *ServoDigitalInterrupt) Value(ctx context.Context, extra map[string]interface{}) (int64, error) {
253-
i.mu.RLock()
254-
defer i.mu.RUnlock()
255-
v := int64(i.ra.Average())
256-
if i.pp != nil {
257-
return i.pp(v), nil
258-
}
259-
260-
return v, nil
261-
}
262-
263-
// Tick records the time between two successive low signals (pulse width). How it is
264-
// interpreted is based off the consumer of Value.
265-
func (i *ServoDigitalInterrupt) Tick(ctx context.Context, high bool, now uint64) error {
266-
i.mu.RLock()
267-
defer i.mu.RUnlock()
268-
diff := now - i.last
269-
i.last = now
270-
271-
if i.last == 0 {
272-
return nil
273-
}
274-
275-
if high {
276-
// this is time between signals, ignore
277-
return nil
278-
}
279-
280-
i.ra.Add(int(diff / 1000))
281-
return nil
282-
}
283-
284-
// AddCallback currently panics.
285-
func (i *ServoDigitalInterrupt) AddCallback(c chan Tick) {
286-
i.mu.Lock()
287-
defer i.mu.Unlock()
288-
panic("servos can't have callback")
289-
}
290-
291-
// RemoveCallback currently panics.
292-
func (i *ServoDigitalInterrupt) RemoveCallback(c chan Tick) {
293-
i.mu.Lock()
294-
defer i.mu.Unlock()
295-
panic("servos can't have callback")
296-
}
297-
298-
// AddPostProcessor sets the post processor that will modify the value that
299-
// Value returns.
300-
func (i *ServoDigitalInterrupt) AddPostProcessor(pp PostProcessor) {
301-
i.mu.Lock()
302-
defer i.mu.Unlock()
303-
i.pp = pp
304-
}
305-
306-
// Reconfigure reconfigures this digital interrupt with a new formula.
307-
func (i *ServoDigitalInterrupt) Reconfigure(conf DigitalInterruptConfig) error {
308-
i.mu.Lock()
309-
defer i.mu.Unlock()
310-
311-
newFormula, isNew, err := processFormula(i.cfg.Formula, conf.Formula, conf.Name)
312-
if err != nil {
313-
return err
314-
}
315-
if !isNew {
316-
return nil
317-
}
318-
i.pp = newFormula
319-
i.cfg = conf
320-
return nil
321-
}
322-
323-
// Close does nothing.
324-
func (i *ServoDigitalInterrupt) Close(ctx context.Context) error {
325-
return nil
326-
}

components/board/digital_interrupts_test.go

+4-50
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,23 @@ func nowNanosecondsTest() uint64 {
1515

1616
func TestBasicDigitalInterrupt1(t *testing.T) {
1717
config := DigitalInterruptConfig{
18-
Name: "i1",
19-
Formula: "(+ 1 raw)",
18+
Name: "i1",
2019
}
2120

2221
i, err := CreateDigitalInterrupt(config)
2322
test.That(t, err, test.ShouldBeNil)
2423

2524
intVal, err := i.Value(context.Background(), nil)
2625
test.That(t, err, test.ShouldBeNil)
27-
test.That(t, intVal, test.ShouldEqual, int64(1))
26+
test.That(t, intVal, test.ShouldEqual, int64(0))
2827
test.That(t, i.Tick(context.Background(), true, nowNanosecondsTest()), test.ShouldBeNil)
2928
intVal, err = i.Value(context.Background(), nil)
3029
test.That(t, err, test.ShouldBeNil)
31-
test.That(t, intVal, test.ShouldEqual, int64(2))
30+
test.That(t, intVal, test.ShouldEqual, int64(1))
3231
test.That(t, i.Tick(context.Background(), false, nowNanosecondsTest()), test.ShouldBeNil)
3332
intVal, err = i.Value(context.Background(), nil)
3433
test.That(t, err, test.ShouldBeNil)
35-
test.That(t, intVal, test.ShouldEqual, int64(2))
34+
test.That(t, intVal, test.ShouldEqual, int64(1))
3635

3736
c := make(chan Tick)
3837
i.AddCallback(c)
@@ -149,48 +148,3 @@ func TestRemoveCallbackDigitalInterrupt(t *testing.T) {
149148
test.That(t, err, test.ShouldBeNil)
150149
test.That(t, intVal, test.ShouldEqual, int64(3))
151150
}
152-
153-
func TestServoInterrupt(t *testing.T) {
154-
config := DigitalInterruptConfig{
155-
Name: "s1",
156-
Type: "servo",
157-
}
158-
159-
s, err := CreateDigitalInterrupt(config)
160-
test.That(t, err, test.ShouldBeNil)
161-
162-
now := uint64(0)
163-
for i := 0; i < 20; i++ {
164-
test.That(t, s.Tick(context.Background(), true, now), test.ShouldBeNil)
165-
now += 1500 * 1000 // this is what we measure
166-
test.That(t, s.Tick(context.Background(), false, now), test.ShouldBeNil)
167-
now += 1000 * 1000 * 1000 // this is between measurements
168-
}
169-
170-
intVal, err := s.Value(context.Background(), nil)
171-
test.That(t, err, test.ShouldBeNil)
172-
test.That(t, intVal, test.ShouldEqual, int64(1500))
173-
}
174-
175-
func TestServoInterruptWithPP(t *testing.T) {
176-
config := DigitalInterruptConfig{
177-
Name: "s1",
178-
Type: "servo",
179-
Formula: "(+ 1 raw)",
180-
}
181-
182-
s, err := CreateDigitalInterrupt(config)
183-
test.That(t, err, test.ShouldBeNil)
184-
185-
now := uint64(0)
186-
for i := 0; i < 20; i++ {
187-
test.That(t, s.Tick(context.Background(), true, now), test.ShouldBeNil)
188-
now += 1500 * 1000 // this is what we measure
189-
test.That(t, s.Tick(context.Background(), false, now), test.ShouldBeNil)
190-
now += 1000 * 1000 * 1000 // this is between measurements
191-
}
192-
193-
intVal, err := s.Value(context.Background(), nil)
194-
test.That(t, err, test.ShouldBeNil)
195-
test.That(t, intVal, test.ShouldEqual, int64(1501))
196-
}

components/board/fake/board.go

-13
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,6 @@ type DigitalInterruptWrapper struct {
349349
di board.DigitalInterrupt
350350
conf board.DigitalInterruptConfig
351351
callbacks map[chan board.Tick]struct{}
352-
pps []board.PostProcessor
353352
}
354353

355354
// NewDigitalInterruptWrapper returns a new digital interrupt to be used for testing.
@@ -380,9 +379,6 @@ func (s *DigitalInterruptWrapper) reset(conf board.DigitalInterruptConfig) error
380379
for c := range s.callbacks {
381380
s.di.AddCallback(c)
382381
}
383-
for _, pp := range s.pps {
384-
s.di.AddPostProcessor(pp)
385-
}
386382
return nil
387383
}
388384
// reconf
@@ -420,15 +416,6 @@ func (s *DigitalInterruptWrapper) AddCallback(c chan board.Tick) {
420416
s.di.AddCallback(c)
421417
}
422418

423-
// AddPostProcessor adds a post processor that should be used to modify
424-
// what is returned by Value.
425-
func (s *DigitalInterruptWrapper) AddPostProcessor(pp board.PostProcessor) {
426-
s.mu.Lock()
427-
defer s.mu.Unlock()
428-
s.pps = append(s.pps, pp)
429-
s.di.AddPostProcessor(pp)
430-
}
431-
432419
// RemoveCallback removes a listener for interrupts.
433420
func (s *DigitalInterruptWrapper) RemoveCallback(c chan board.Tick) {
434421
s.mu.Lock()

components/board/fake/board_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func TestFakeBoard(t *testing.T) {
1919
},
2020
DigitalInterrupts: []board.DigitalInterruptConfig{
2121
{Name: "i1", Pin: "35"},
22-
{Name: "i2", Pin: "31", Type: "servo"},
22+
{Name: "i2", Pin: "31"},
2323
{Name: "a", Pin: "38"},
2424
{Name: "b", Pin: "40"},
2525
},

0 commit comments

Comments
 (0)