add: humidity (WIP)
This commit is contained in:
		
							
								
								
									
										25
									
								
								vendor/periph.io/x/periph/conn/gpio/func.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/periph.io/x/periph/conn/gpio/func.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
// Copyright 2018 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package gpio
 | 
			
		||||
 | 
			
		||||
import "periph.io/x/periph/conn/pin"
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Inputs
 | 
			
		||||
	IN      pin.Func = "IN"      // Input
 | 
			
		||||
	IN_HIGH pin.Func = "In/High" // Read high
 | 
			
		||||
	IN_LOW  pin.Func = "In/Low"  // Read low
 | 
			
		||||
 | 
			
		||||
	// Outputs
 | 
			
		||||
	OUT      pin.Func = "OUT"      // Output, drive
 | 
			
		||||
	OUT_OC   pin.Func = "OUT_OPEN" // Output, open collector/drain
 | 
			
		||||
	OUT_HIGH pin.Func = "Out/High" // Drive high
 | 
			
		||||
	OUT_LOW  pin.Func = "Out/Low"  // Drive low; open collector low
 | 
			
		||||
 | 
			
		||||
	FLOAT pin.Func = "FLOAT" // Input float or Output open collector high
 | 
			
		||||
 | 
			
		||||
	CLK pin.Func = "CLK" // Clock is a subset of a PWM, with a 50% duty cycle
 | 
			
		||||
	PWM pin.Func = "PWM" // Pulse Width Modulation, which is a clock with variable duty cycle
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										329
									
								
								vendor/periph.io/x/periph/conn/gpio/gpio.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										329
									
								
								vendor/periph.io/x/periph/conn/gpio/gpio.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,329 @@
 | 
			
		||||
// Copyright 2016 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package gpio defines digital pins.
 | 
			
		||||
//
 | 
			
		||||
// All GPIO implementations are expected to implement PinIO but the device
 | 
			
		||||
// driver may accept a more specific one like PinIn or PinOut.
 | 
			
		||||
package gpio
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph/conn/physic"
 | 
			
		||||
	"periph.io/x/periph/conn/pin"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Interfaces
 | 
			
		||||
 | 
			
		||||
// Level is the level of the pin: Low or High.
 | 
			
		||||
type Level bool
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Low represents 0v.
 | 
			
		||||
	Low Level = false
 | 
			
		||||
	// High represents Vin, generally 3.3v or 5v.
 | 
			
		||||
	High Level = true
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (l Level) String() string {
 | 
			
		||||
	if l == Low {
 | 
			
		||||
		return "Low"
 | 
			
		||||
	}
 | 
			
		||||
	return "High"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Pull specifies the internal pull-up or pull-down for a pin set as input.
 | 
			
		||||
type Pull uint8
 | 
			
		||||
 | 
			
		||||
// Acceptable pull values.
 | 
			
		||||
const (
 | 
			
		||||
	PullNoChange Pull = 0 // Do not change the previous pull resistor setting or an unknown value
 | 
			
		||||
	Float        Pull = 1 // Let the input float
 | 
			
		||||
	PullDown     Pull = 2 // Apply pull-down
 | 
			
		||||
	PullUp       Pull = 3 // Apply pull-up
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const pullName = "PullNoChangeFloatPullDownPullUp"
 | 
			
		||||
 | 
			
		||||
var pullIndex = [...]uint8{0, 12, 17, 25, 31}
 | 
			
		||||
 | 
			
		||||
func (i Pull) String() string {
 | 
			
		||||
	if i >= Pull(len(pullIndex)-1) {
 | 
			
		||||
		return "Pull(" + strconv.Itoa(int(i)) + ")"
 | 
			
		||||
	}
 | 
			
		||||
	return pullName[pullIndex[i]:pullIndex[i+1]]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Edge specifies if an input pin should have edge detection enabled.
 | 
			
		||||
//
 | 
			
		||||
// Only enable it when needed, since this causes system interrupts.
 | 
			
		||||
type Edge int
 | 
			
		||||
 | 
			
		||||
// Acceptable edge detection values.
 | 
			
		||||
const (
 | 
			
		||||
	NoEdge      Edge = 0
 | 
			
		||||
	RisingEdge  Edge = 1
 | 
			
		||||
	FallingEdge Edge = 2
 | 
			
		||||
	BothEdges   Edge = 3
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const edgeName = "NoEdgeRisingEdgeFallingEdgeBothEdges"
 | 
			
		||||
 | 
			
		||||
var edgeIndex = [...]uint8{0, 6, 16, 27, 36}
 | 
			
		||||
 | 
			
		||||
func (i Edge) String() string {
 | 
			
		||||
	if i >= Edge(len(edgeIndex)-1) {
 | 
			
		||||
		return "Edge(" + strconv.Itoa(int(i)) + ")"
 | 
			
		||||
	}
 | 
			
		||||
	return edgeName[edgeIndex[i]:edgeIndex[i+1]]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// DutyMax is a duty cycle of 100%.
 | 
			
		||||
	DutyMax Duty = 1 << 24
 | 
			
		||||
	// DutyHalf is a 50% duty PWM, which boils down to a normal clock.
 | 
			
		||||
	DutyHalf Duty = DutyMax / 2
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Duty is the duty cycle for a PWM.
 | 
			
		||||
//
 | 
			
		||||
// Valid values are between 0 and DutyMax.
 | 
			
		||||
type Duty int32
 | 
			
		||||
 | 
			
		||||
func (d Duty) String() string {
 | 
			
		||||
	// TODO(maruel): Implement one fractional number.
 | 
			
		||||
	return strconv.Itoa(int((d+50)/(DutyMax/100))) + "%"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Valid returns true if the Duty cycle value is valid.
 | 
			
		||||
func (d Duty) Valid() bool {
 | 
			
		||||
	return d >= 0 && d <= DutyMax
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseDuty parses a string and converts it to a Duty value.
 | 
			
		||||
func ParseDuty(s string) (Duty, error) {
 | 
			
		||||
	percent := strings.HasSuffix(s, "%")
 | 
			
		||||
	if percent {
 | 
			
		||||
		s = s[:len(s)-1]
 | 
			
		||||
	}
 | 
			
		||||
	i64, err := strconv.ParseInt(s, 10, 32)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	i := Duty(i64)
 | 
			
		||||
	if percent {
 | 
			
		||||
		// TODO(maruel): Add support for fractional number.
 | 
			
		||||
		if i < 0 {
 | 
			
		||||
			return 0, errors.New("duty must be >= 0%")
 | 
			
		||||
		}
 | 
			
		||||
		if i > 100 {
 | 
			
		||||
			return 0, errors.New("duty must be <= 100%")
 | 
			
		||||
		}
 | 
			
		||||
		return ((i * DutyMax) + 49) / 100, nil
 | 
			
		||||
	}
 | 
			
		||||
	if i < 0 {
 | 
			
		||||
		return 0, errors.New("duty must be >= 0")
 | 
			
		||||
	}
 | 
			
		||||
	if i > DutyMax {
 | 
			
		||||
		return 0, errors.New("duty must be <= " + strconv.Itoa(int(DutyMax)))
 | 
			
		||||
	}
 | 
			
		||||
	return i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PinIn is an input GPIO pin.
 | 
			
		||||
//
 | 
			
		||||
// It may optionally support internal pull resistor and edge based triggering.
 | 
			
		||||
//
 | 
			
		||||
// A button is semantically a PinIn. So if you are looking to read from a
 | 
			
		||||
// button, PinIn is the interface you are looking for.
 | 
			
		||||
type PinIn interface {
 | 
			
		||||
	pin.Pin
 | 
			
		||||
	// In setups a pin as an input.
 | 
			
		||||
	//
 | 
			
		||||
	// If WaitForEdge() is planned to be called, make sure to use one of the Edge
 | 
			
		||||
	// value. Otherwise, use NoEdge to not generated unneeded hardware interrupts.
 | 
			
		||||
	//
 | 
			
		||||
	// Calling In() will try to empty the accumulated edges but it cannot be 100%
 | 
			
		||||
	// reliable due to the OS (linux) and its driver. It is possible that on a
 | 
			
		||||
	// gpio that is as input, doing a quick Out(), In() may return an edge that
 | 
			
		||||
	// occurred before the Out() call.
 | 
			
		||||
	In(pull Pull, edge Edge) error
 | 
			
		||||
	// Read return the current pin level.
 | 
			
		||||
	//
 | 
			
		||||
	// Behavior is undefined if In() wasn't used before.
 | 
			
		||||
	//
 | 
			
		||||
	// In some rare case, it is possible that Read() fails silently. This happens
 | 
			
		||||
	// if another process on the host messes up with the pin after In() was
 | 
			
		||||
	// called. In this case, call In() again.
 | 
			
		||||
	Read() Level
 | 
			
		||||
	// WaitForEdge() waits for the next edge or immediately return if an edge
 | 
			
		||||
	// occurred since the last call.
 | 
			
		||||
	//
 | 
			
		||||
	// Only waits for the kind of edge as specified in a previous In() call.
 | 
			
		||||
	// Behavior is undefined if In() with a value other than NoEdge wasn't called
 | 
			
		||||
	// before.
 | 
			
		||||
	//
 | 
			
		||||
	// Returns true if an edge was detected during or before this call. Return
 | 
			
		||||
	// false if the timeout occurred or In() was called while waiting, causing the
 | 
			
		||||
	// function to exit.
 | 
			
		||||
	//
 | 
			
		||||
	// Multiple edges may or may not accumulate between two calls to
 | 
			
		||||
	// WaitForEdge(). The behavior in this case is undefined and is OS driver
 | 
			
		||||
	// specific.
 | 
			
		||||
	//
 | 
			
		||||
	// It is not required to call Read() to reset the edge detection.
 | 
			
		||||
	//
 | 
			
		||||
	// Specify -1 to effectively disable timeout.
 | 
			
		||||
	WaitForEdge(timeout time.Duration) bool
 | 
			
		||||
	// Pull returns the internal pull resistor if the pin is set as input pin.
 | 
			
		||||
	//
 | 
			
		||||
	// Returns PullNoChange if the value cannot be read.
 | 
			
		||||
	Pull() Pull
 | 
			
		||||
	// DefaultPull returns the pull that is initialized on CPU/device reset. This
 | 
			
		||||
	// is useful to determine if the pin is acceptable for operation with
 | 
			
		||||
	// certain devices.
 | 
			
		||||
	DefaultPull() Pull
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PinOut is an output GPIO pin.
 | 
			
		||||
//
 | 
			
		||||
// A LED, a buzzer, a servo, are semantically a PinOut. So if you are looking
 | 
			
		||||
// to control these, PinOut is the interface you are looking for.
 | 
			
		||||
type PinOut interface {
 | 
			
		||||
	pin.Pin
 | 
			
		||||
	// Out sets a pin as output if it wasn't already and sets the initial value.
 | 
			
		||||
	//
 | 
			
		||||
	// After the initial call to ensure that the pin has been set as output, it
 | 
			
		||||
	// is generally safe to ignore the error returned.
 | 
			
		||||
	//
 | 
			
		||||
	// Out() tries to empty the accumulated edges detected if the gpio was
 | 
			
		||||
	// previously set as input but this is not 100% guaranteed due to the OS.
 | 
			
		||||
	Out(l Level) error
 | 
			
		||||
	// PWM sets the PWM output on supported pins, if the pin has hardware PWM
 | 
			
		||||
	// support.
 | 
			
		||||
	//
 | 
			
		||||
	// To use as a general purpose clock, set duty to DutyHalf. Some pins may
 | 
			
		||||
	// only support DutyHalf and no other value.
 | 
			
		||||
	//
 | 
			
		||||
	// Using 0 as frequency will use the optimal value as supported/preferred by
 | 
			
		||||
	// the pin.
 | 
			
		||||
	//
 | 
			
		||||
	// To use as a servo, see https://en.wikipedia.org/wiki/Servo_control as an
 | 
			
		||||
	// explanation how to calculate duty.
 | 
			
		||||
	PWM(duty Duty, f physic.Frequency) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PinIO is a GPIO pin that supports both input and output. It matches both
 | 
			
		||||
// interfaces PinIn and PinOut.
 | 
			
		||||
//
 | 
			
		||||
// A GPIO pin implementing PinIO may fail at either input or output or both.
 | 
			
		||||
type PinIO interface {
 | 
			
		||||
	pin.Pin
 | 
			
		||||
	// PinIn
 | 
			
		||||
	In(pull Pull, edge Edge) error
 | 
			
		||||
	Read() Level
 | 
			
		||||
	WaitForEdge(timeout time.Duration) bool
 | 
			
		||||
	Pull() Pull
 | 
			
		||||
	DefaultPull() Pull
 | 
			
		||||
	// PinOut
 | 
			
		||||
	Out(l Level) error
 | 
			
		||||
	PWM(duty Duty, f physic.Frequency) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// INVALID implements PinIO and fails on all access.
 | 
			
		||||
var INVALID PinIO
 | 
			
		||||
 | 
			
		||||
// RealPin is implemented by aliased pin and allows the retrieval of the real
 | 
			
		||||
// pin underlying an alias.
 | 
			
		||||
//
 | 
			
		||||
// Aliases are created by RegisterAlias. Aliases permits presenting a user
 | 
			
		||||
// friendly GPIO pin name while representing the underlying real pin.
 | 
			
		||||
//
 | 
			
		||||
// The purpose of the RealPin is to be able to cleanly test whether an arbitrary
 | 
			
		||||
// gpio.PinIO returned by ByName is an alias for another pin, and resolve it.
 | 
			
		||||
type RealPin interface {
 | 
			
		||||
	Real() PinIO // Real returns the real pin behind an Alias
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// errInvalidPin is returned when trying to use INVALID.
 | 
			
		||||
var errInvalidPin = errors.New("gpio: invalid pin")
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	INVALID = invalidPin{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// invalidPin implements PinIO for compatibility but fails on all access.
 | 
			
		||||
type invalidPin struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) String() string {
 | 
			
		||||
	return "INVALID"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) Halt() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) Number() int {
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) Name() string {
 | 
			
		||||
	return "INVALID"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) Function() string {
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) Func() pin.Func {
 | 
			
		||||
	return pin.FuncNone
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) SupportedFuncs() []pin.Func {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) SetFunc(f pin.Func) error {
 | 
			
		||||
	return errInvalidPin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) In(Pull, Edge) error {
 | 
			
		||||
	return errInvalidPin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) Read() Level {
 | 
			
		||||
	return Low
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) WaitForEdge(timeout time.Duration) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) Pull() Pull {
 | 
			
		||||
	return PullNoChange
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) DefaultPull() Pull {
 | 
			
		||||
	return PullNoChange
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) Out(Level) error {
 | 
			
		||||
	return errInvalidPin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (invalidPin) PWM(Duty, physic.Frequency) error {
 | 
			
		||||
	return errInvalidPin
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ PinIn = INVALID
 | 
			
		||||
var _ PinOut = INVALID
 | 
			
		||||
var _ PinIO = INVALID
 | 
			
		||||
var _ pin.PinFunc = &invalidPin{}
 | 
			
		||||
							
								
								
									
										213
									
								
								vendor/periph.io/x/periph/conn/gpio/gpioreg/gpioreg.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								vendor/periph.io/x/periph/conn/gpio/gpioreg/gpioreg.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,213 @@
 | 
			
		||||
// Copyright 2017 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package gpioreg defines a registry for the known digital pins.
 | 
			
		||||
package gpioreg
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph/conn/gpio"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ByName returns a GPIO pin from its name, gpio number or one of its aliases.
 | 
			
		||||
//
 | 
			
		||||
// For example on a Raspberry Pi, the following values will return the same
 | 
			
		||||
// GPIO: the gpio as a number "2", the chipset name "GPIO2", the board pin
 | 
			
		||||
// position "P1_3", it's function name "I2C1_SDA".
 | 
			
		||||
//
 | 
			
		||||
// Returns nil if the gpio pin is not present.
 | 
			
		||||
func ByName(name string) gpio.PinIO {
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	if p, ok := byName[name]; ok {
 | 
			
		||||
		return p
 | 
			
		||||
	}
 | 
			
		||||
	if dest, ok := byAlias[name]; ok {
 | 
			
		||||
		if p := getByNameDeep(dest); p != nil {
 | 
			
		||||
			// Wraps the destination in an alias, so the name makes sense to the user.
 | 
			
		||||
			// The main drawback is that casting into other gpio interfaces like
 | 
			
		||||
			// gpio.PinPWM requires going through gpio.RealPin first.
 | 
			
		||||
			return &pinAlias{p, name}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// All returns all the GPIO pins available on this host.
 | 
			
		||||
//
 | 
			
		||||
// The list is guaranteed to be in order of name using 'natural sorting'.
 | 
			
		||||
//
 | 
			
		||||
// This list excludes aliases.
 | 
			
		||||
//
 | 
			
		||||
// This list excludes non-GPIO pins like GROUND, V3_3, etc, since they are not
 | 
			
		||||
// GPIO.
 | 
			
		||||
func All() []gpio.PinIO {
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	out := make([]gpio.PinIO, 0, len(byName))
 | 
			
		||||
	for _, p := range byName {
 | 
			
		||||
		out = insertPinByName(out, p)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Aliases returns all pin aliases.
 | 
			
		||||
//
 | 
			
		||||
// The list is guaranteed to be in order of aliase name.
 | 
			
		||||
func Aliases() []gpio.PinIO {
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	out := make([]gpio.PinIO, 0, len(byAlias))
 | 
			
		||||
	for name, dest := range byAlias {
 | 
			
		||||
		// Skip aliases that were not resolved.
 | 
			
		||||
		if p := getByNameDeep(dest); p != nil {
 | 
			
		||||
			out = insertPinByName(out, &pinAlias{p, name})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Register registers a GPIO pin.
 | 
			
		||||
//
 | 
			
		||||
// Registering the same pin number or name twice is an error.
 | 
			
		||||
//
 | 
			
		||||
// The pin registered cannot implement the interface RealPin.
 | 
			
		||||
func Register(p gpio.PinIO) error {
 | 
			
		||||
	name := p.Name()
 | 
			
		||||
	if len(name) == 0 {
 | 
			
		||||
		return errors.New("gpioreg: can't register a pin with no name")
 | 
			
		||||
	}
 | 
			
		||||
	if r, ok := p.(gpio.RealPin); ok {
 | 
			
		||||
		return errors.New("gpioreg: can't register pin " + strconv.Quote(name) + ", it is already an alias to " + strconv.Quote(r.Real().String()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	if orig, ok := byName[name]; ok {
 | 
			
		||||
		return errors.New("gpioreg: can't register pin " + strconv.Quote(name) + " twice; already registered as " + strconv.Quote(orig.String()))
 | 
			
		||||
	}
 | 
			
		||||
	if dest, ok := byAlias[name]; ok {
 | 
			
		||||
		return errors.New("gpioreg: can't register pin " + strconv.Quote(name) + "; an alias already exist to: " + strconv.Quote(dest))
 | 
			
		||||
	}
 | 
			
		||||
	byName[name] = p
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RegisterAlias registers an alias for a GPIO pin.
 | 
			
		||||
//
 | 
			
		||||
// It is possible to register an alias for a pin that itself has not been
 | 
			
		||||
// registered yet. It is valid to register an alias to another alias. It is
 | 
			
		||||
// valid to register the same alias multiple times, overriding the previous
 | 
			
		||||
// alias.
 | 
			
		||||
func RegisterAlias(alias string, dest string) error {
 | 
			
		||||
	if len(alias) == 0 {
 | 
			
		||||
		return errors.New("gpioreg: can't register an alias with no name")
 | 
			
		||||
	}
 | 
			
		||||
	if len(dest) == 0 {
 | 
			
		||||
		return errors.New("gpioreg: can't register alias " + strconv.Quote(alias) + " with no dest")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	if _, ok := byName[alias]; ok {
 | 
			
		||||
		return errors.New("gpioreg: can't register alias " + strconv.Quote(alias) + " for a pin that exists")
 | 
			
		||||
	}
 | 
			
		||||
	byAlias[alias] = dest
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unregister removes a previously registered GPIO pin or alias from the GPIO
 | 
			
		||||
// pin registry.
 | 
			
		||||
//
 | 
			
		||||
// This can happen when a GPIO pin is exposed via an USB device and the device
 | 
			
		||||
// is unplugged, or when a generic OS provided pin is superseded by a CPU
 | 
			
		||||
// specific implementation.
 | 
			
		||||
func Unregister(name string) error {
 | 
			
		||||
	mu.Lock()
 | 
			
		||||
	defer mu.Unlock()
 | 
			
		||||
	if _, ok := byName[name]; ok {
 | 
			
		||||
		delete(byName, name)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if _, ok := byAlias[name]; ok {
 | 
			
		||||
		delete(byAlias, name)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return errors.New("gpioreg: can't unregister unknown pin name " + strconv.Quote(name))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	mu      sync.Mutex
 | 
			
		||||
	byName  = map[string]gpio.PinIO{}
 | 
			
		||||
	byAlias = map[string]string{}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// pinAlias implements an alias for a PinIO.
 | 
			
		||||
//
 | 
			
		||||
// pinAlias implements the RealPin interface, which allows querying for the
 | 
			
		||||
// real pin under the alias.
 | 
			
		||||
type pinAlias struct {
 | 
			
		||||
	gpio.PinIO
 | 
			
		||||
	name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String returns the alias name along the real pin's Name() in parenthesis, if
 | 
			
		||||
// known, else the real pin's number.
 | 
			
		||||
func (a *pinAlias) String() string {
 | 
			
		||||
	return a.name + "(" + a.PinIO.Name() + ")"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Name returns the pinAlias's name.
 | 
			
		||||
func (a *pinAlias) Name() string {
 | 
			
		||||
	return a.name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Real returns the real pin behind the alias
 | 
			
		||||
func (a *pinAlias) Real() gpio.PinIO {
 | 
			
		||||
	return a.PinIO
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getByNameDeep recursively resolves the aliases to get the pin.
 | 
			
		||||
func getByNameDeep(name string) gpio.PinIO {
 | 
			
		||||
	if p, ok := byName[name]; ok {
 | 
			
		||||
		return p
 | 
			
		||||
	}
 | 
			
		||||
	if dest, ok := byAlias[name]; ok {
 | 
			
		||||
		if p := getByNameDeep(dest); p != nil {
 | 
			
		||||
			// Return the deep pin directly, bypassing the aliases.
 | 
			
		||||
			return p
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// insertPinByName inserts pin p into list l while keeping l ordered by name.
 | 
			
		||||
func insertPinByName(l []gpio.PinIO, p gpio.PinIO) []gpio.PinIO {
 | 
			
		||||
	n := p.Name()
 | 
			
		||||
	i := search(len(l), func(i int) bool { return lessNatural(n, l[i].Name()) })
 | 
			
		||||
	l = append(l, nil)
 | 
			
		||||
	copy(l[i+1:], l[i:])
 | 
			
		||||
	l[i] = p
 | 
			
		||||
	return l
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// search implements the same algorithm as sort.Search().
 | 
			
		||||
//
 | 
			
		||||
// It was extracted to to not depend on sort, which depends on reflect.
 | 
			
		||||
func search(n int, f func(int) bool) int {
 | 
			
		||||
	lo := 0
 | 
			
		||||
	for hi := n; lo < hi; {
 | 
			
		||||
		if i := int(uint(lo+hi) >> 1); !f(i) {
 | 
			
		||||
			lo = i + 1
 | 
			
		||||
		} else {
 | 
			
		||||
			hi = i
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return lo
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										76
									
								
								vendor/periph.io/x/periph/conn/gpio/gpioreg/natsort.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								vendor/periph.io/x/periph/conn/gpio/gpioreg/natsort.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
// Copyright 2018 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package gpioreg
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// lessNatural does a 'natural' comparison on the two strings.
 | 
			
		||||
//
 | 
			
		||||
// It is extracted from https://github.com/maruel/natural.
 | 
			
		||||
func lessNatural(a, b string) bool {
 | 
			
		||||
	for {
 | 
			
		||||
		if a == b {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		if p := commonPrefix(a, b); p != 0 {
 | 
			
		||||
			a = a[p:]
 | 
			
		||||
			b = b[p:]
 | 
			
		||||
		}
 | 
			
		||||
		if ia := digits(a); ia > 0 {
 | 
			
		||||
			if ib := digits(b); ib > 0 {
 | 
			
		||||
				// Both sides have digits.
 | 
			
		||||
				an, aerr := strconv.ParseUint(a[:ia], 10, 64)
 | 
			
		||||
				bn, berr := strconv.ParseUint(b[:ib], 10, 64)
 | 
			
		||||
				if aerr == nil && berr == nil {
 | 
			
		||||
					if an != bn {
 | 
			
		||||
						return an < bn
 | 
			
		||||
					}
 | 
			
		||||
					// Semantically the same digits, e.g. "00" == "0", "01" == "1". In
 | 
			
		||||
					// this case, only continue processing if there's trailing data on
 | 
			
		||||
					// both sides, otherwise do lexical comparison.
 | 
			
		||||
					if ia != len(a) && ib != len(b) {
 | 
			
		||||
						a = a[ia:]
 | 
			
		||||
						b = b[ib:]
 | 
			
		||||
						continue
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return a < b
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// commonPrefix returns the common prefix except for digits.
 | 
			
		||||
func commonPrefix(a, b string) int {
 | 
			
		||||
	m := len(a)
 | 
			
		||||
	if n := len(b); n < m {
 | 
			
		||||
		m = n
 | 
			
		||||
	}
 | 
			
		||||
	if m == 0 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	_ = a[m-1]
 | 
			
		||||
	_ = b[m-1]
 | 
			
		||||
	for i := 0; i < m; i++ {
 | 
			
		||||
		ca := a[i]
 | 
			
		||||
		cb := b[i]
 | 
			
		||||
		if (ca >= '0' && ca <= '9') || (cb >= '0' && cb <= '9') || ca != cb {
 | 
			
		||||
			return i
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func digits(s string) int {
 | 
			
		||||
	for i := 0; i < len(s); i++ {
 | 
			
		||||
		c := s[i]
 | 
			
		||||
		if c < '0' || c > '9' {
 | 
			
		||||
			return i
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return len(s)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										217
									
								
								vendor/periph.io/x/periph/conn/gpio/gpiostream/gpiostream.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								vendor/periph.io/x/periph/conn/gpio/gpiostream/gpiostream.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,217 @@
 | 
			
		||||
// Copyright 2017 The Periph Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed under the Apache License, Version 2.0
 | 
			
		||||
// that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package gpiostream defines digital streams.
 | 
			
		||||
//
 | 
			
		||||
// Warning
 | 
			
		||||
//
 | 
			
		||||
// This package is still in flux as development is on-going.
 | 
			
		||||
package gpiostream
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"periph.io/x/periph/conn/gpio"
 | 
			
		||||
	"periph.io/x/periph/conn/physic"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Stream is the interface to define a generic stream.
 | 
			
		||||
type Stream interface {
 | 
			
		||||
	// Frequency is the minimum data rate at which the binary stream is usable.
 | 
			
		||||
	//
 | 
			
		||||
	// For example, a bit stream may have a 10kHz data rate.
 | 
			
		||||
	Frequency() physic.Frequency
 | 
			
		||||
	// Duration of the binary stream. For infinitely looping streams, it is the
 | 
			
		||||
	// duration of the non-looping part.
 | 
			
		||||
	Duration() time.Duration
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BitStream is a stream of bits to be written or read.
 | 
			
		||||
type BitStream struct {
 | 
			
		||||
	// Bits is a densely packed bitstream.
 | 
			
		||||
	//
 | 
			
		||||
	// The stream is required to be a multiple of 8 samples.
 | 
			
		||||
	Bits []byte
 | 
			
		||||
	// Freq is the rate at each the bit (not byte) stream should be processed.
 | 
			
		||||
	Freq physic.Frequency
 | 
			
		||||
	// LSBF when true means than Bits is in LSB-first. When false, the data is
 | 
			
		||||
	// MSB-first.
 | 
			
		||||
	//
 | 
			
		||||
	// With MSBF, the first bit processed is the most significant one (0x80). For
 | 
			
		||||
	// example, IยฒC, I2S PCM and SPI use MSB-first at the word level. This
 | 
			
		||||
	// requires to pack words correctly.
 | 
			
		||||
	//
 | 
			
		||||
	// With LSBF, the first bit processed is the least significant one (0x01).
 | 
			
		||||
	// For example, Ethernet uses LSB-first at the byte level and MSB-first at
 | 
			
		||||
	// the word level.
 | 
			
		||||
	LSBF bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Frequency implements Stream.
 | 
			
		||||
func (b *BitStream) Frequency() physic.Frequency {
 | 
			
		||||
	return b.Freq
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Duration implements Stream.
 | 
			
		||||
func (b *BitStream) Duration() time.Duration {
 | 
			
		||||
	if b.Freq == 0 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	return b.Freq.Duration() * time.Duration(len(b.Bits)*8)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GoString implements fmt.GoStringer.
 | 
			
		||||
func (b *BitStream) GoString() string {
 | 
			
		||||
	return fmt.Sprintf("&gpiostream.BitStream{Bits: %x, Freq:%s, LSBF:%t}", b.Bits, b.Freq, b.LSBF)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EdgeStream is a stream of edges to be written.
 | 
			
		||||
//
 | 
			
		||||
// This struct is more efficient than BitStream for short repetitive pulses,
 | 
			
		||||
// like controlling a servo. A PWM can be created by specifying a slice of
 | 
			
		||||
// twice the same resolution and make it looping via a Program.
 | 
			
		||||
type EdgeStream struct {
 | 
			
		||||
	// Edges is the list of Level change. It is assumed that the signal starts
 | 
			
		||||
	// with gpio.High. Use a duration of 0 for Edges[0] to start with a Low
 | 
			
		||||
	// instead of the default High.
 | 
			
		||||
	//
 | 
			
		||||
	// The value is a multiple of Res. Use a 0 value to 'extend' a continuous
 | 
			
		||||
	// signal that lasts more than "2^16-1*Res" duration by skipping a pulse.
 | 
			
		||||
	Edges []uint16
 | 
			
		||||
	// Res is the minimum resolution at which the edges should be
 | 
			
		||||
	// rasterized.
 | 
			
		||||
	//
 | 
			
		||||
	// The lower the value, the more memory shall be used when rasterized.
 | 
			
		||||
	Freq physic.Frequency
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Frequency implements Stream.
 | 
			
		||||
func (e *EdgeStream) Frequency() physic.Frequency {
 | 
			
		||||
	return e.Freq
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Duration implements Stream.
 | 
			
		||||
func (e *EdgeStream) Duration() time.Duration {
 | 
			
		||||
	if e.Freq == 0 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	t := 0
 | 
			
		||||
	for _, edge := range e.Edges {
 | 
			
		||||
		t += int(edge)
 | 
			
		||||
	}
 | 
			
		||||
	return e.Freq.Duration() * time.Duration(t)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Program is a loop of streams.
 | 
			
		||||
//
 | 
			
		||||
// This is itself a stream, it can be used to reduce memory usage when repeated
 | 
			
		||||
// patterns are used.
 | 
			
		||||
type Program struct {
 | 
			
		||||
	Parts []Stream // Each part must be a BitStream, EdgeStream or Program
 | 
			
		||||
	Loops int      // Set to -1 to create an infinite loop
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Frequency implements Stream.
 | 
			
		||||
func (p *Program) Frequency() physic.Frequency {
 | 
			
		||||
	if p.Loops == 0 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	var buf [16]physic.Frequency
 | 
			
		||||
	freqs := buf[:0]
 | 
			
		||||
	for _, part := range p.Parts {
 | 
			
		||||
		if f := part.Frequency(); f != 0 {
 | 
			
		||||
			freqs = insertFreq(freqs, f)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(freqs) == 0 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	f := freqs[0]
 | 
			
		||||
	for i := 1; i < len(freqs); i++ {
 | 
			
		||||
		if r := freqs[i]; r*2 < f {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		// Take in account Nyquist rate. https://wikipedia.org/wiki/Nyquist_rate
 | 
			
		||||
		f *= 2
 | 
			
		||||
	}
 | 
			
		||||
	return f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Duration implements Stream.
 | 
			
		||||
func (p *Program) Duration() time.Duration {
 | 
			
		||||
	if p.Loops == 0 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	var d time.Duration
 | 
			
		||||
	for _, s := range p.Parts {
 | 
			
		||||
		d += s.Duration()
 | 
			
		||||
	}
 | 
			
		||||
	if p.Loops > 1 {
 | 
			
		||||
		d *= time.Duration(p.Loops)
 | 
			
		||||
	}
 | 
			
		||||
	return d
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// PinIn allows to read a bit stream from a pin.
 | 
			
		||||
//
 | 
			
		||||
// Caveat
 | 
			
		||||
//
 | 
			
		||||
// This interface doesn't enable sampling multiple pins in a
 | 
			
		||||
// synchronized way or reading in a continuous uninterrupted way. As such, it
 | 
			
		||||
// should be considered experimental.
 | 
			
		||||
type PinIn interface {
 | 
			
		||||
	// StreamIn reads for the pin at the specified resolution to fill the
 | 
			
		||||
	// provided buffer.
 | 
			
		||||
	//
 | 
			
		||||
	// May only support a subset of the structs implementing Stream.
 | 
			
		||||
	StreamIn(p gpio.Pull, b Stream) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PinOut allows to stream to a pin.
 | 
			
		||||
//
 | 
			
		||||
// The Stream may be a Program, a BitStream or an EdgeStream. If it is a
 | 
			
		||||
// Program that is an infinite loop, a separate goroutine can be used to cancel
 | 
			
		||||
// the program. In this case StreamOut() returns without an error.
 | 
			
		||||
//
 | 
			
		||||
// Caveat
 | 
			
		||||
//
 | 
			
		||||
// This interface doesn't enable streaming to multiple pins in a
 | 
			
		||||
// synchronized way or reading in a continuous uninterrupted way. As such, it
 | 
			
		||||
// should be considered experimental.
 | 
			
		||||
type PinOut interface {
 | 
			
		||||
	StreamOut(s Stream) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// insertFreq inserts in reverse order, highest frequency first.
 | 
			
		||||
func insertFreq(l []physic.Frequency, f physic.Frequency) []physic.Frequency {
 | 
			
		||||
	i := search(len(l), func(i int) bool { return l[i] < f })
 | 
			
		||||
	l = append(l, 0)
 | 
			
		||||
	copy(l[i+1:], l[i:])
 | 
			
		||||
	l[i] = f
 | 
			
		||||
	return l
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// search implements the same algorithm as sort.Search().
 | 
			
		||||
//
 | 
			
		||||
// It was extracted to to not depend on sort, which depends on reflect.
 | 
			
		||||
func search(n int, f func(int) bool) int {
 | 
			
		||||
	lo := 0
 | 
			
		||||
	for hi := n; lo < hi; {
 | 
			
		||||
		if i := int(uint(lo+hi) >> 1); !f(i) {
 | 
			
		||||
			lo = i + 1
 | 
			
		||||
		} else {
 | 
			
		||||
			hi = i
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return lo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ Stream = &BitStream{}
 | 
			
		||||
var _ Stream = &EdgeStream{}
 | 
			
		||||
var _ Stream = &Program{}
 | 
			
		||||
		Reference in New Issue
	
	Block a user