Skip to content

Commit 4e9c832

Browse files
authored
core(system): split system accesser features (hybridgroup#1121)
1 parent 1f2c1dd commit 4e9c832

Some content is hidden

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

66 files changed

+1270
-509
lines changed

MIGRATION.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ suitable:
4646
Also those findings needs to be replaced, which usually affects developers, but not users:
4747

4848
* `system.WithDigitalPinGpiodAccess()` --> `system.WithDigitalPinCdevAccess()`
49-
* `IsGpiodDigitalPinAccess()` --> `IsCdevDigitalPinAccess()`
49+
* `IsGpiodDigitalPinAccess()` --> `HasDigitalPinCdevAccess()`
5050

5151
### PocketBeagle adaptor goes cdev
5252

platforms/adaptors/analogpinsadaptor.go

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ func NewAnalogPinsAdaptor(sys *system.Accesser, t analogPinTranslator) *AnalogPi
2727
sys: sys,
2828
translate: t,
2929
}
30+
31+
sys.AddAnalogSupport()
32+
3033
return &a
3134
}
3235

platforms/adaptors/digitalpinsadaptor.go

+32-114
Original file line numberDiff line numberDiff line change
@@ -16,44 +16,12 @@ type (
1616
digitalPinInitializer func(gobot.DigitalPinner) error
1717
)
1818

19-
type digitalPinGpiosForSPI struct {
20-
sclkPin string
21-
ncsPin string
22-
sdoPin string
23-
sdiPin string
24-
}
25-
26-
type digitalPinsDebouncePin struct {
27-
id string
28-
period time.Duration
29-
}
30-
31-
type digitalPinsEventOnEdgePin struct {
32-
id string
33-
handler func(lineOffset int, timestamp time.Duration, detectedEdge string, seqno uint32, lseqno uint32)
34-
}
35-
36-
type digitalPinsPollForEdgeDetectionPin struct {
37-
id string
38-
pollInterval time.Duration
39-
pollQuitChan chan struct{}
40-
}
41-
4219
// digitalPinsConfiguration contains all changeable attributes of the adaptor.
4320
type digitalPinsConfiguration struct {
44-
initialize digitalPinInitializer
45-
useSysfs *bool
46-
gpiosForSPI *digitalPinGpiosForSPI
47-
activeLowPins []string
48-
pullDownPins []string
49-
pullUpPins []string
50-
openDrainPins []string
51-
openSourcePins []string
52-
debouncePins []digitalPinsDebouncePin
53-
eventOnFallingEdgePins []digitalPinsEventOnEdgePin
54-
eventOnRisingEdgePins []digitalPinsEventOnEdgePin
55-
eventOnBothEdgesPins []digitalPinsEventOnEdgePin
56-
pollForEdgeDetectionPins []digitalPinsPollForEdgeDetectionPin
21+
debug bool
22+
initialize digitalPinInitializer
23+
systemOptions []system.AccesserOptionApplier
24+
pinOptions map[string][]func(gobot.DigitalPinOptioner) bool
5725
}
5826

5927
// DigitalPinsAdaptor is a adaptor for digital pins, normally used for composition in platforms.
@@ -62,7 +30,6 @@ type DigitalPinsAdaptor struct {
6230
digitalPinsCfg *digitalPinsConfiguration
6331
translate digitalPinTranslator
6432
pins map[string]gobot.DigitalPinner
65-
pinOptions map[string][]func(gobot.DigitalPinOptioner) bool
6633
mutex sync.Mutex
6734
}
6835

@@ -76,15 +43,27 @@ func NewDigitalPinsAdaptor(
7643
t digitalPinTranslator,
7744
opts ...DigitalPinsOptionApplier,
7845
) *DigitalPinsAdaptor {
79-
a := &DigitalPinsAdaptor{
80-
sys: sys,
81-
digitalPinsCfg: &digitalPinsConfiguration{initialize: func(pin gobot.DigitalPinner) error { return pin.Export() }},
82-
translate: t,
46+
a := DigitalPinsAdaptor{
47+
sys: sys,
48+
digitalPinsCfg: &digitalPinsConfiguration{
49+
initialize: func(pin gobot.DigitalPinner) error { return pin.Export() },
50+
pinOptions: make(map[string][]func(gobot.DigitalPinOptioner) bool),
51+
},
52+
translate: t,
8353
}
54+
8455
for _, o := range opts {
8556
o.apply(a.digitalPinsCfg)
8657
}
87-
return a
58+
59+
a.sys.AddDigitalPinSupport(a.digitalPinsCfg.systemOptions...)
60+
61+
return &a
62+
}
63+
64+
// WithDigitalPinDebug can be used to switch on debugging for SPI implementation.
65+
func WithDigitalPinDebug() digitalPinsDebugOption {
66+
return digitalPinsDebugOption(true)
8867
}
8968

9069
// WithDigitalPinInitializer can be used to substitute the default initializer.
@@ -104,18 +83,6 @@ func WithGpioSysfsAccess() digitalPinsSystemSysfsOption {
10483
return digitalPinsSystemSysfsOption(true)
10584
}
10685

107-
// WithSpiGpioAccess can be used to switch the default SPI implementation to GPIO usage.
108-
func WithSpiGpioAccess(sclkPin, ncsPin, sdoPin, sdiPin string) digitalPinsForSystemSpiOption {
109-
o := digitalPinsForSystemSpiOption{
110-
sclkPin: sclkPin,
111-
ncsPin: ncsPin,
112-
sdoPin: sdoPin,
113-
sdiPin: sdiPin,
114-
}
115-
116-
return o
117-
}
118-
11986
// WithGpiosActiveLow prepares the given pins for inverse reaction on next initialize.
12087
// This is working for inputs and outputs.
12188
func WithGpiosActiveLow(pin string, otherPins ...string) digitalPinsActiveLowOption {
@@ -196,69 +163,16 @@ func (a *DigitalPinsAdaptor) Connect() error {
196163
a.mutex.Lock()
197164
defer a.mutex.Unlock()
198165

199-
if a.pinOptions != nil {
200-
return fmt.Errorf("digital pin adaptor already connected, please call Finalize() for re-connect")
201-
}
202-
203-
cfg := a.digitalPinsCfg
204-
205-
if cfg.useSysfs != nil {
206-
if *cfg.useSysfs {
207-
system.WithDigitalPinSysfsAccess()(a.sys)
208-
} else {
209-
system.WithDigitalPinCdevAccess()(a.sys)
210-
}
211-
}
212-
213-
if cfg.gpiosForSPI != nil {
214-
system.WithSpiGpioAccess(a, cfg.gpiosForSPI.sclkPin, cfg.gpiosForSPI.ncsPin, cfg.gpiosForSPI.sdoPin,
215-
cfg.gpiosForSPI.sdiPin)(a.sys)
166+
if a.digitalPinsCfg.debug {
167+
fmt.Println("connect the digital pins adaptor")
216168
}
217169

218-
a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool)
219-
220-
for _, pin := range cfg.activeLowPins {
221-
a.pinOptions[pin] = append(a.pinOptions[pin], system.WithPinActiveLow())
222-
}
223-
224-
for _, pin := range cfg.pullDownPins {
225-
a.pinOptions[pin] = append(a.pinOptions[pin], system.WithPinPullDown())
226-
}
227-
228-
for _, pin := range cfg.pullUpPins {
229-
a.pinOptions[pin] = append(a.pinOptions[pin], system.WithPinPullUp())
230-
}
231-
232-
for _, pin := range cfg.openDrainPins {
233-
a.pinOptions[pin] = append(a.pinOptions[pin], system.WithPinOpenDrain())
234-
}
235-
236-
for _, pin := range cfg.openSourcePins {
237-
a.pinOptions[pin] = append(a.pinOptions[pin], system.WithPinOpenSource())
238-
}
239-
240-
for _, pin := range cfg.debouncePins {
241-
a.pinOptions[pin.id] = append(a.pinOptions[pin.id], system.WithPinDebounce(pin.period))
242-
}
243-
244-
for _, pin := range cfg.eventOnFallingEdgePins {
245-
a.pinOptions[pin.id] = append(a.pinOptions[pin.id], system.WithPinEventOnFallingEdge(pin.handler))
246-
}
247-
248-
for _, pin := range cfg.eventOnRisingEdgePins {
249-
a.pinOptions[pin.id] = append(a.pinOptions[pin.id], system.WithPinEventOnRisingEdge(pin.handler))
250-
}
251-
252-
for _, pin := range cfg.eventOnBothEdgesPins {
253-
a.pinOptions[pin.id] = append(a.pinOptions[pin.id], system.WithPinEventOnBothEdges(pin.handler))
254-
}
255-
256-
for _, pin := range cfg.pollForEdgeDetectionPins {
257-
a.pinOptions[pin.id] = append(a.pinOptions[pin.id],
258-
system.WithPinPollForEdgeDetection(pin.pollInterval, pin.pollQuitChan))
170+
if a.pins != nil {
171+
return fmt.Errorf("digital pin adaptor already connected, please call Finalize() for re-connect")
259172
}
260173

261174
a.pins = make(map[string]gobot.DigitalPinner)
175+
262176
return nil
263177
}
264178

@@ -267,6 +181,10 @@ func (a *DigitalPinsAdaptor) Finalize() error {
267181
a.mutex.Lock()
268182
defer a.mutex.Unlock()
269183

184+
if a.digitalPinsCfg.debug {
185+
fmt.Println("finalize the digital pins adaptor")
186+
}
187+
270188
var err error
271189
for _, pin := range a.pins {
272190
if pin != nil {
@@ -276,7 +194,7 @@ func (a *DigitalPinsAdaptor) Finalize() error {
276194
}
277195
}
278196
a.pins = nil
279-
a.pinOptions = nil
197+
280198
return err
281199
}
282200

@@ -321,7 +239,7 @@ func (a *DigitalPinsAdaptor) digitalPin(
321239
return nil, fmt.Errorf("not connected for pin %s", id)
322240
}
323241

324-
o := append(a.pinOptions[id], opts...)
242+
o := append(a.digitalPinsCfg.pinOptions[id], opts...)
325243
pin := a.pins[id]
326244

327245
if pin == nil {

platforms/adaptors/digitalpinsadaptor_test.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,17 @@ func TestNewDigitalPinsAdaptor(t *testing.T) {
5454
// arrange
5555
translate := func(string) (string, int, error) { return "", 0, nil }
5656
sys := system.NewAccesser()
57+
// arrange for cdev needed
58+
sys.UseMockFilesystem([]string{"/dev/gpiochip"})
5759
// act
5860
a := NewDigitalPinsAdaptor(sys, translate)
5961
// assert
6062
assert.IsType(t, &DigitalPinsAdaptor{}, a)
6163
assert.NotNil(t, a.sys)
6264
assert.NotNil(t, a.digitalPinsCfg)
6365
assert.NotNil(t, a.translate)
64-
assert.Nil(t, a.pins) // will be created on connect
65-
assert.Nil(t, a.pinOptions) // will be created on connect
66-
assert.True(t, a.sys.IsCdevDigitalPinAccess())
66+
assert.Nil(t, a.pins) // will be created on connect
67+
assert.True(t, a.sys.HasDigitalPinCdevAccess())
6768
}
6869

6970
func TestDigitalPinsConnect(t *testing.T) {

platforms/adaptors/digitalpinsadaptoroptions.go

+41-28
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package adaptors
22

33
import (
44
"time"
5+
6+
"gobot.io/x/gobot/v2/system"
57
)
68

79
// DigitalPinsOptionApplier is the interface for digital adaptors options. This provides the possibility for change the
@@ -11,16 +13,16 @@ type DigitalPinsOptionApplier interface {
1113
apply(cfg *digitalPinsConfiguration)
1214
}
1315

16+
// digitalPinsDebugOption is the type to switch on digital pin related debug messages.
17+
type digitalPinsDebugOption bool
18+
1419
// digitalPinInitializeOption is the type for applying another than the default initializer
1520
type digitalPinsInitializeOption digitalPinInitializer
1621

1722
// digitalPinsSystemSysfsOption is the type to change the default character device implementation to the legacy
1823
// sysfs Kernel ABI
1924
type digitalPinsSystemSysfsOption bool
2025

21-
// digitalPinsForSystemSpiOption is the type to switch the default SPI implementation to GPIO usage
22-
type digitalPinsForSystemSpiOption digitalPinGpiosForSPI
23-
2426
// digitalPinsActiveLowOption is the type to prepare the given pins for inverse reaction on next initialize
2527
type digitalPinsActiveLowOption []string
2628

@@ -75,6 +77,10 @@ type digitalPinsPollForEdgeDetectionOption struct {
7577
pollQuitChan chan struct{}
7678
}
7779

80+
func (o digitalPinsDebugOption) String() string {
81+
return "switch on debugging for digital pins option"
82+
}
83+
7884
func (o digitalPinsInitializeOption) String() string {
7985
return "pin initializer option for digital IO's"
8086
}
@@ -83,10 +89,6 @@ func (o digitalPinsSystemSysfsOption) String() string {
8389
return "use sysfs vs. cdev system access option for digital pins"
8490
}
8591

86-
func (o digitalPinsForSystemSpiOption) String() string {
87-
return "use digital pins for SPI option"
88-
}
89-
9092
func (o digitalPinsActiveLowOption) String() string {
9193
return "digital pins set to active low option"
9294
}
@@ -127,61 +129,72 @@ func (o digitalPinsPollForEdgeDetectionOption) String() string {
127129
return "discrete polling function for edge detection on digital pin option"
128130
}
129131

132+
func (o digitalPinsDebugOption) apply(cfg *digitalPinsConfiguration) {
133+
cfg.debug = bool(o)
134+
cfg.systemOptions = append(cfg.systemOptions, system.WithDigitalPinDebug())
135+
}
136+
130137
func (o digitalPinsInitializeOption) apply(cfg *digitalPinsConfiguration) {
131138
cfg.initialize = digitalPinInitializer(o)
132139
}
133140

134141
func (o digitalPinsSystemSysfsOption) apply(cfg *digitalPinsConfiguration) {
135-
c := bool(o)
136-
cfg.useSysfs = &c
137-
}
142+
useSysFs := bool(o)
138143

139-
func (o digitalPinsForSystemSpiOption) apply(cfg *digitalPinsConfiguration) {
140-
c := digitalPinGpiosForSPI(o)
141-
cfg.gpiosForSPI = &c
144+
if useSysFs {
145+
cfg.systemOptions = append(cfg.systemOptions, system.WithDigitalPinSysfsAccess())
146+
} else {
147+
cfg.systemOptions = append(cfg.systemOptions, system.WithDigitalPinCdevAccess())
148+
}
142149
}
143150

144151
func (o digitalPinsActiveLowOption) apply(cfg *digitalPinsConfiguration) {
145-
cfg.activeLowPins = append(cfg.activeLowPins, o...)
152+
for _, pin := range o {
153+
cfg.pinOptions[pin] = append(cfg.pinOptions[pin], system.WithPinActiveLow())
154+
}
146155
}
147156

148157
func (o digitalPinsPullDownOption) apply(cfg *digitalPinsConfiguration) {
149-
cfg.pullDownPins = append(cfg.pullDownPins, o...)
158+
for _, pin := range o {
159+
cfg.pinOptions[pin] = append(cfg.pinOptions[pin], system.WithPinPullDown())
160+
}
150161
}
151162

152163
func (o digitalPinsPullUpOption) apply(cfg *digitalPinsConfiguration) {
153-
cfg.pullUpPins = append(cfg.pullUpPins, o...)
164+
for _, pin := range o {
165+
cfg.pinOptions[pin] = append(cfg.pinOptions[pin], system.WithPinPullUp())
166+
}
154167
}
155168

156169
func (o digitalPinsOpenDrainOption) apply(cfg *digitalPinsConfiguration) {
157-
cfg.openDrainPins = append(cfg.openDrainPins, o...)
170+
for _, pin := range o {
171+
cfg.pinOptions[pin] = append(cfg.pinOptions[pin], system.WithPinOpenDrain())
172+
}
158173
}
159174

160175
func (o digitalPinsOpenSourceOption) apply(cfg *digitalPinsConfiguration) {
161-
cfg.openSourcePins = append(cfg.openSourcePins, o...)
176+
for _, pin := range o {
177+
cfg.pinOptions[pin] = append(cfg.pinOptions[pin], system.WithPinOpenSource())
178+
}
162179
}
163180

164181
func (o digitalPinsDebounceOption) apply(cfg *digitalPinsConfiguration) {
165-
pinCfg := digitalPinsDebouncePin(o)
166-
cfg.debouncePins = append(cfg.debouncePins, pinCfg)
182+
cfg.pinOptions[o.id] = append(cfg.pinOptions[o.id], system.WithPinDebounce(o.period))
167183
}
168184

169185
func (o digitalPinsEventOnFallingEdgeOption) apply(cfg *digitalPinsConfiguration) {
170-
pinCfg := digitalPinsEventOnEdgePin(o)
171-
cfg.eventOnFallingEdgePins = append(cfg.eventOnFallingEdgePins, pinCfg)
186+
cfg.pinOptions[o.id] = append(cfg.pinOptions[o.id], system.WithPinEventOnFallingEdge(o.handler))
172187
}
173188

174189
func (o digitalPinsEventOnRisingEdgeOption) apply(cfg *digitalPinsConfiguration) {
175-
pinCfg := digitalPinsEventOnEdgePin(o)
176-
cfg.eventOnRisingEdgePins = append(cfg.eventOnRisingEdgePins, pinCfg)
190+
cfg.pinOptions[o.id] = append(cfg.pinOptions[o.id], system.WithPinEventOnRisingEdge(o.handler))
177191
}
178192

179193
func (o digitalPinsEventOnBothEdgesOption) apply(cfg *digitalPinsConfiguration) {
180-
pinCfg := digitalPinsEventOnEdgePin(o)
181-
cfg.eventOnBothEdgesPins = append(cfg.eventOnBothEdgesPins, pinCfg)
194+
cfg.pinOptions[o.id] = append(cfg.pinOptions[o.id], system.WithPinEventOnBothEdges(o.handler))
182195
}
183196

184197
func (o digitalPinsPollForEdgeDetectionOption) apply(cfg *digitalPinsConfiguration) {
185-
pinCfg := digitalPinsPollForEdgeDetectionPin(o)
186-
cfg.pollForEdgeDetectionPins = append(cfg.pollForEdgeDetectionPins, pinCfg)
198+
cfg.pinOptions[o.id] = append(cfg.pinOptions[o.id],
199+
system.WithPinPollForEdgeDetection(o.pollInterval, o.pollQuitChan))
187200
}

0 commit comments

Comments
 (0)