Skip to content

Commit

Permalink
adaptors(pwm): introduce scale option for servo
Browse files Browse the repository at this point in the history
  • Loading branch information
gen2thomas committed Dec 5, 2023
1 parent be1ccf0 commit e189a87
Show file tree
Hide file tree
Showing 27 changed files with 1,382 additions and 896 deletions.
269 changes: 44 additions & 225 deletions platforms/adaptors/digitalpinsadaptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,6 @@ type (
digitalPinInitializer func(gobot.DigitalPinner) error
)

type digitalPinsOptioner interface {
setDigitalPinInitializer(initializer digitalPinInitializer)
setDigitalPinsForSystemGpiod()
setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin string)
prepareDigitalPinsActiveLow(pin string, otherPins ...string)
prepareDigitalPinsPullDown(pin string, otherPins ...string)
prepareDigitalPinsPullUp(pin string, otherPins ...string)
prepareDigitalPinsOpenDrain(pin string, otherPins ...string)
prepareDigitalPinsOpenSource(pin string, otherPins ...string)
prepareDigitalPinDebounce(pin string, period time.Duration)
prepareDigitalPinEventOnFallingEdge(pin string, handler func(lineOffset int, timestamp time.Duration,
detectedEdge string, seqno uint32, lseqno uint32))
prepareDigitalPinEventOnRisingEdge(pin string, handler func(lineOffset int, timestamp time.Duration,
detectedEdge string, seqno uint32, lseqno uint32))
prepareDigitalPinEventOnBothEdges(pin string, handler func(lineOffset int, timestamp time.Duration,
detectedEdge string, seqno uint32, lseqno uint32))
prepareDigitalPinPollForEdgeDetection(pin string, pollInterval time.Duration, pollQuitChan chan struct{})
}

// DigitalPinsAdaptor is a adaptor for digital pins, normally used for composition in platforms.
type DigitalPinsAdaptor struct {
sys *system.Accesser
Expand All @@ -53,7 +34,7 @@ type DigitalPinsAdaptor struct {
func NewDigitalPinsAdaptor(
sys *system.Accesser,
t digitalPinTranslator,
options ...func(Optioner),
options ...func(DigitalPinsOptioner),
) *DigitalPinsAdaptor {
a := &DigitalPinsAdaptor{
sys: sys,
Expand All @@ -67,149 +48,114 @@ func NewDigitalPinsAdaptor(
}

// WithDigitalPinInitializer can be used to substitute the default initializer.
func WithDigitalPinInitializer(pc digitalPinInitializer) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.setDigitalPinInitializer(pc)
}
func WithDigitalPinInitializer(pc digitalPinInitializer) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.setDigitalPinInitializer(pc)
}
}

// WithGpiodAccess can be used to change the default sysfs implementation to the character device Kernel ABI.
// The access is provided by the gpiod package.
func WithGpiodAccess() func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.setDigitalPinsForSystemGpiod()
}
func WithGpiodAccess() func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.setDigitalPinsForSystemGpiod()
}
}

// WithSpiGpioAccess can be used to switch the default SPI implementation to GPIO usage.
func WithSpiGpioAccess(sclkPin, nssPin, mosiPin, misoPin string) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin)
}
func WithSpiGpioAccess(sclkPin, nssPin, mosiPin, misoPin string) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin)
}
}

// WithGpiosActiveLow prepares the given pins for inverse reaction on next initialize.
// This is working for inputs and outputs.
func WithGpiosActiveLow(pin string, otherPins ...string) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.prepareDigitalPinsActiveLow(pin, otherPins...)
}
func WithGpiosActiveLow(pin string, otherPins ...string) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.prepareDigitalPinsActiveLow(pin, otherPins...)
}
}

// WithGpiosPullDown prepares the given pins to be pulled down (high impedance to GND) on next initialize.
// This is working for inputs and outputs since Kernel 5.5, but will be ignored with sysfs ABI.
func WithGpiosPullDown(pin string, otherPins ...string) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.prepareDigitalPinsPullDown(pin, otherPins...)
}
func WithGpiosPullDown(pin string, otherPins ...string) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.prepareDigitalPinsPullDown(pin, otherPins...)
}
}

// WithGpiosPullUp prepares the given pins to be pulled up (high impedance to VDD) on next initialize.
// This is working for inputs and outputs since Kernel 5.5, but will be ignored with sysfs ABI.
func WithGpiosPullUp(pin string, otherPins ...string) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.prepareDigitalPinsPullUp(pin, otherPins...)
}
func WithGpiosPullUp(pin string, otherPins ...string) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.prepareDigitalPinsPullUp(pin, otherPins...)
}
}

// WithGpiosOpenDrain prepares the given output pins to be driven with open drain/collector on next initialize.
// This will be ignored for inputs or with sysfs ABI.
func WithGpiosOpenDrain(pin string, otherPins ...string) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.prepareDigitalPinsOpenDrain(pin, otherPins...)
}
func WithGpiosOpenDrain(pin string, otherPins ...string) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.prepareDigitalPinsOpenDrain(pin, otherPins...)
}
}

// WithGpiosOpenSource prepares the given output pins to be driven with open source/emitter on next initialize.
// This will be ignored for inputs or with sysfs ABI.
func WithGpiosOpenSource(pin string, otherPins ...string) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.prepareDigitalPinsOpenSource(pin, otherPins...)
}
func WithGpiosOpenSource(pin string, otherPins ...string) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.prepareDigitalPinsOpenSource(pin, otherPins...)
}
}

// WithGpioDebounce prepares the given input pin to be debounced on next initialize.
// This is working for inputs since Kernel 5.10, but will be ignored for outputs or with sysfs ABI.
func WithGpioDebounce(pin string, period time.Duration) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.prepareDigitalPinDebounce(pin, period)
}
func WithGpioDebounce(pin string, period time.Duration) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.prepareDigitalPinDebounce(pin, period)
}
}

// WithGpioEventOnFallingEdge prepares the given input pin to be generate an event on falling edge.
// This is working for inputs since Kernel 5.10, but will be ignored for outputs or with sysfs ABI.
func WithGpioEventOnFallingEdge(pin string, handler func(lineOffset int, timestamp time.Duration, detectedEdge string,
seqno uint32, lseqno uint32),
) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.prepareDigitalPinEventOnFallingEdge(pin, handler)
}
) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.prepareDigitalPinEventOnFallingEdge(pin, handler)
}
}

// WithGpioEventOnRisingEdge prepares the given input pin to be generate an event on rising edge.
// This is working for inputs since Kernel 5.10, but will be ignored for outputs or with sysfs ABI.
func WithGpioEventOnRisingEdge(pin string, handler func(lineOffset int, timestamp time.Duration, detectedEdge string,
seqno uint32, lseqno uint32),
) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.prepareDigitalPinEventOnRisingEdge(pin, handler)
}
) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.prepareDigitalPinEventOnRisingEdge(pin, handler)
}
}

// WithGpioEventOnBothEdges prepares the given input pin to be generate an event on rising and falling edges.
// This is working for inputs since Kernel 5.10, but will be ignored for outputs or with sysfs ABI.
func WithGpioEventOnBothEdges(pin string, handler func(lineOffset int, timestamp time.Duration, detectedEdge string,
seqno uint32, lseqno uint32),
) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.prepareDigitalPinEventOnBothEdges(pin, handler)
}
) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.prepareDigitalPinEventOnBothEdges(pin, handler)
}
}

// WithGpioPollForEdgeDetection prepares the given input pin to use a discrete input pin polling function together with
// edge detection.
func WithGpioPollForEdgeDetection(pin string, pollInterval time.Duration, pollQuitChan chan struct{}) func(Optioner) {
return func(o Optioner) {
a, ok := o.(digitalPinsOptioner)
if ok {
a.prepareDigitalPinPollForEdgeDetection(pin, pollInterval, pollQuitChan)
}
func WithGpioPollForEdgeDetection(
pin string,
pollInterval time.Duration,
pollQuitChan chan struct{},
) func(DigitalPinsOptioner) {
return func(o DigitalPinsOptioner) {
o.prepareDigitalPinPollForEdgeDetection(pin, pollInterval, pollQuitChan)
}
}

Expand Down Expand Up @@ -273,133 +219,6 @@ func (a *DigitalPinsAdaptor) DigitalWrite(id string, val byte) error {
return pin.Write(int(val))
}

func (a *DigitalPinsAdaptor) setDigitalPinInitializer(pinInit digitalPinInitializer) {
a.initialize = pinInit
}

func (a *DigitalPinsAdaptor) setDigitalPinsForSystemGpiod() {
system.WithDigitalPinGpiodAccess()(a.sys)
}

func (a *DigitalPinsAdaptor) setDigitalPinsForSystemSpi(sclkPin, nssPin, mosiPin, misoPin string) {
system.WithSpiGpioAccess(a, sclkPin, nssPin, mosiPin, misoPin)(a.sys)
}

func (a *DigitalPinsAdaptor) prepareDigitalPinsActiveLow(id string, otherIDs ...string) {
ids := []string{id}
ids = append(ids, otherIDs...)

if a.pinOptions == nil {
a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool)
}

for _, i := range ids {
a.pinOptions[i] = append(a.pinOptions[i], system.WithPinActiveLow())
}
}

func (a *DigitalPinsAdaptor) prepareDigitalPinsPullDown(id string, otherIDs ...string) {
ids := []string{id}
ids = append(ids, otherIDs...)

if a.pinOptions == nil {
a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool)
}

for _, i := range ids {
a.pinOptions[i] = append(a.pinOptions[i], system.WithPinPullDown())
}
}

func (a *DigitalPinsAdaptor) prepareDigitalPinsPullUp(id string, otherIDs ...string) {
ids := []string{id}
ids = append(ids, otherIDs...)

if a.pinOptions == nil {
a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool)
}

for _, i := range ids {
a.pinOptions[i] = append(a.pinOptions[i], system.WithPinPullUp())
}
}

func (a *DigitalPinsAdaptor) prepareDigitalPinsOpenDrain(id string, otherIDs ...string) {
ids := []string{id}
ids = append(ids, otherIDs...)

if a.pinOptions == nil {
a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool)
}

for _, i := range ids {
a.pinOptions[i] = append(a.pinOptions[i], system.WithPinOpenDrain())
}
}

func (a *DigitalPinsAdaptor) prepareDigitalPinsOpenSource(id string, otherIDs ...string) {
ids := []string{id}
ids = append(ids, otherIDs...)

if a.pinOptions == nil {
a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool)
}

for _, i := range ids {
a.pinOptions[i] = append(a.pinOptions[i], system.WithPinOpenSource())
}
}

func (a *DigitalPinsAdaptor) prepareDigitalPinDebounce(id string, period time.Duration) {
if a.pinOptions == nil {
a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool)
}

a.pinOptions[id] = append(a.pinOptions[id], system.WithPinDebounce(period))
}

func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnFallingEdge(id string, handler func(int, time.Duration, string,
uint32, uint32),
) {
if a.pinOptions == nil {
a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool)
}

a.pinOptions[id] = append(a.pinOptions[id], system.WithPinEventOnFallingEdge(handler))
}

func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnRisingEdge(id string, handler func(int, time.Duration, string,
uint32, uint32),
) {
if a.pinOptions == nil {
a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool)
}

a.pinOptions[id] = append(a.pinOptions[id], system.WithPinEventOnRisingEdge(handler))
}

func (a *DigitalPinsAdaptor) prepareDigitalPinEventOnBothEdges(id string, handler func(int, time.Duration, string,
uint32, uint32),
) {
if a.pinOptions == nil {
a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool)
}

a.pinOptions[id] = append(a.pinOptions[id], system.WithPinEventOnBothEdges(handler))
}

func (a *DigitalPinsAdaptor) prepareDigitalPinPollForEdgeDetection(
id string,
pollInterval time.Duration,
pollQuitChan chan struct{},
) {
if a.pinOptions == nil {
a.pinOptions = make(map[string][]func(gobot.DigitalPinOptioner) bool)
}

a.pinOptions[id] = append(a.pinOptions[id], system.WithPinPollForEdgeDetection(pollInterval, pollQuitChan))
}

func (a *DigitalPinsAdaptor) digitalPin(
id string,
opts ...func(gobot.DigitalPinOptioner) bool,
Expand Down
Loading

0 comments on commit e189a87

Please sign in to comment.