beaglebone: handle gpio pinmux without relying on specific pre-existing setup
Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
parent
c10828baf9
commit
07a24b2f69
|
@ -15,28 +15,39 @@ import (
|
||||||
"gobot.io/x/gobot/sysfs"
|
"gobot.io/x/gobot/sysfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type pwmPinData struct {
|
||||||
|
channel int
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
const pwmDefaultPeriod = 500000
|
const pwmDefaultPeriod = 500000
|
||||||
|
|
||||||
// Adaptor is the gobot.Adaptor representation for the Beaglebone
|
// Adaptor is the gobot.Adaptor representation for the Beaglebone
|
||||||
type Adaptor struct {
|
type Adaptor struct {
|
||||||
name string
|
name string
|
||||||
digitalPins []*sysfs.DigitalPin
|
digitalPins []*sysfs.DigitalPin
|
||||||
pwmPins map[string]*sysfs.PWMPin
|
pwmPins map[string]*sysfs.PWMPin
|
||||||
i2cBuses map[int]i2c.I2cDevice
|
i2cBuses map[int]i2c.I2cDevice
|
||||||
usrLed string
|
usrLed string
|
||||||
analogPath string
|
analogPath string
|
||||||
slots string
|
slots string
|
||||||
mutex *sync.Mutex
|
pinMap map[string]int
|
||||||
|
pwmPinMap map[string]pwmPinData
|
||||||
|
analogPinMap map[string]string
|
||||||
|
mutex *sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAdaptor returns a new Beaglebone Adaptor
|
// NewAdaptor returns a new Beaglebone Adaptor
|
||||||
func NewAdaptor() *Adaptor {
|
func NewAdaptor() *Adaptor {
|
||||||
b := &Adaptor{
|
b := &Adaptor{
|
||||||
name: gobot.DefaultName("Beaglebone"),
|
name: gobot.DefaultName("Beaglebone"),
|
||||||
digitalPins: make([]*sysfs.DigitalPin, 120),
|
digitalPins: make([]*sysfs.DigitalPin, 120),
|
||||||
pwmPins: make(map[string]*sysfs.PWMPin),
|
pwmPins: make(map[string]*sysfs.PWMPin),
|
||||||
i2cBuses: make(map[int]i2c.I2cDevice),
|
i2cBuses: make(map[int]i2c.I2cDevice),
|
||||||
mutex: &sync.Mutex{},
|
mutex: &sync.Mutex{},
|
||||||
|
pinMap: bbbPinMap,
|
||||||
|
pwmPinMap: bbbPwmPinMap,
|
||||||
|
analogPinMap: bbbAnalogPinMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
b.setSlots()
|
b.setSlots()
|
||||||
|
@ -163,6 +174,10 @@ func (b *Adaptor) DigitalPin(pin string, dir string) (sysfsPin sysfs.DigitalPinn
|
||||||
}
|
}
|
||||||
if b.digitalPins[i] == nil {
|
if b.digitalPins[i] == nil {
|
||||||
b.digitalPins[i] = sysfs.NewDigitalPin(i)
|
b.digitalPins[i] = sysfs.NewDigitalPin(i)
|
||||||
|
if err = muxPin(pin, "gpio"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err := b.digitalPins[i].Export()
|
err := b.digitalPins[i].Export()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -188,7 +203,7 @@ func (b *Adaptor) PWMPin(pin string) (sysfsPin sysfs.PWMPinner, err error) {
|
||||||
newPin := sysfs.NewPWMPin(pinInfo.channel)
|
newPin := sysfs.NewPWMPin(pinInfo.channel)
|
||||||
newPin.Path = pinInfo.path
|
newPin.Path = pinInfo.path
|
||||||
|
|
||||||
if err = muxPWMPin(pin); err != nil {
|
if err = muxPin(pin, "pwm"); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = newPin.Export(); err != nil {
|
if err = newPin.Export(); err != nil {
|
||||||
|
@ -256,7 +271,7 @@ func (b *Adaptor) GetDefaultBus() int {
|
||||||
|
|
||||||
// translatePin converts digital pin name to pin position
|
// translatePin converts digital pin name to pin position
|
||||||
func (b *Adaptor) translatePin(pin string) (value int, err error) {
|
func (b *Adaptor) translatePin(pin string) (value int, err error) {
|
||||||
if val, ok := pins[pin]; ok {
|
if val, ok := b.pinMap[pin]; ok {
|
||||||
value = val
|
value = val
|
||||||
} else {
|
} else {
|
||||||
err = errors.New("Not a valid pin")
|
err = errors.New("Not a valid pin")
|
||||||
|
@ -265,7 +280,7 @@ func (b *Adaptor) translatePin(pin string) (value int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Adaptor) translatePwmPin(pin string) (p pwmPinData, err error) {
|
func (b *Adaptor) translatePwmPin(pin string) (p pwmPinData, err error) {
|
||||||
if val, ok := pwmPins[pin]; ok {
|
if val, ok := b.pwmPinMap[pin]; ok {
|
||||||
p = val
|
p = val
|
||||||
} else {
|
} else {
|
||||||
err = errors.New("Not a valid PWM pin")
|
err = errors.New("Not a valid PWM pin")
|
||||||
|
@ -275,7 +290,7 @@ func (b *Adaptor) translatePwmPin(pin string) (p pwmPinData, err error) {
|
||||||
|
|
||||||
// translateAnalogPin converts analog pin name to pin position
|
// translateAnalogPin converts analog pin name to pin position
|
||||||
func (b *Adaptor) translateAnalogPin(pin string) (value string, err error) {
|
func (b *Adaptor) translateAnalogPin(pin string) (value string, err error) {
|
||||||
if val, ok := analogPins[pin]; ok {
|
if val, ok := b.analogPinMap[pin]; ok {
|
||||||
value = val
|
value = val
|
||||||
} else {
|
} else {
|
||||||
err = errors.New("Not a valid analog pin")
|
err = errors.New("Not a valid analog pin")
|
||||||
|
@ -316,13 +331,13 @@ func ensureSlot(slots, item string) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func muxPWMPin(pin string) error {
|
func muxPin(pin, cmd string) error {
|
||||||
path := fmt.Sprintf("/sys/devices/platform/ocp/ocp:%s_pinmux/state", pin)
|
path := fmt.Sprintf("/sys/devices/platform/ocp/ocp:%s_pinmux/state", pin)
|
||||||
fi, e := sysfs.OpenFile(path, os.O_WRONLY, 0666)
|
fi, e := sysfs.OpenFile(path, os.O_WRONLY, 0666)
|
||||||
defer fi.Close()
|
defer fi.Close()
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
_, e = fi.WriteString("pwm")
|
_, e = fi.WriteString(cmd)
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,11 @@ func TestBeagleboneAdaptor(t *testing.T) {
|
||||||
"/dev/i2c-2",
|
"/dev/i2c-2",
|
||||||
"/sys/devices/platform/bone_capemgr",
|
"/sys/devices/platform/bone_capemgr",
|
||||||
"/sys/devices/platform/bone_capemgr/slots",
|
"/sys/devices/platform/bone_capemgr/slots",
|
||||||
"/sys/devices/platform/ocp/ocp:P9_21_pinmux/state",
|
"/sys/devices/platform/ocp/ocp:P8_7_pinmux/state",
|
||||||
|
"/sys/devices/platform/ocp/ocp:P9_11_pinmux/state",
|
||||||
|
"/sys/devices/platform/ocp/ocp:P9_12_pinmux/state",
|
||||||
"/sys/devices/platform/ocp/ocp:P9_22_pinmux/state",
|
"/sys/devices/platform/ocp/ocp:P9_22_pinmux/state",
|
||||||
|
"/sys/devices/platform/ocp/ocp:P9_21_pinmux/state",
|
||||||
"/sys/class/leds/beaglebone:green:usr1/brightness",
|
"/sys/class/leds/beaglebone:green:usr1/brightness",
|
||||||
"/sys/bus/iio/devices/iio:device0/in_voltage1_raw",
|
"/sys/bus/iio/devices/iio:device0/in_voltage1_raw",
|
||||||
"/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/export",
|
"/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0/export",
|
||||||
|
@ -204,6 +207,7 @@ func TestBeagleboneDigitalPinDirectionFileError(t *testing.T) {
|
||||||
"/sys/devices/platform/bone_capemgr/slots",
|
"/sys/devices/platform/bone_capemgr/slots",
|
||||||
"/sys/class/gpio/export",
|
"/sys/class/gpio/export",
|
||||||
"/sys/class/gpio/gpio60/value",
|
"/sys/class/gpio/gpio60/value",
|
||||||
|
"/sys/devices/platform/ocp/ocp:P9_12_pinmux/state",
|
||||||
})
|
})
|
||||||
sysfs.SetFilesystem(fs)
|
sysfs.SetFilesystem(fs)
|
||||||
|
|
||||||
|
@ -223,6 +227,7 @@ func TestBeagleboneDigitalPinFinalizeFileError(t *testing.T) {
|
||||||
"/sys/class/gpio/export",
|
"/sys/class/gpio/export",
|
||||||
"/sys/class/gpio/gpio60/value",
|
"/sys/class/gpio/gpio60/value",
|
||||||
"/sys/class/gpio/gpio60/direction",
|
"/sys/class/gpio/gpio60/direction",
|
||||||
|
"/sys/devices/platform/ocp/ocp:P9_12_pinmux/state",
|
||||||
})
|
})
|
||||||
sysfs.SetFilesystem(fs)
|
sysfs.SetFilesystem(fs)
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
package beaglebone
|
package beaglebone
|
||||||
|
|
||||||
type pwmPinData struct {
|
var bbbPinMap = map[string]int{
|
||||||
channel int
|
|
||||||
path string
|
|
||||||
}
|
|
||||||
|
|
||||||
var pins = map[string]int{
|
|
||||||
// P8_1 - P8_2 GND
|
// P8_1 - P8_2 GND
|
||||||
// P8_3 - P8_6 EMCC
|
// P8_3 - P8_6 EMCC
|
||||||
"P8_7": 66,
|
"P8_7": 66,
|
||||||
|
@ -54,7 +49,7 @@ var pins = map[string]int{
|
||||||
"P9_31": 110,
|
"P9_31": 110,
|
||||||
}
|
}
|
||||||
|
|
||||||
var pwmPins = map[string]pwmPinData{
|
var bbbPwmPinMap = map[string]pwmPinData{
|
||||||
"P8_13": {path: "/sys/devices/platform/ocp/48304000.epwmss/48304200.pwm/pwm/pwmchip4", channel: 1},
|
"P8_13": {path: "/sys/devices/platform/ocp/48304000.epwmss/48304200.pwm/pwm/pwmchip4", channel: 1},
|
||||||
"P8_19": {path: "/sys/devices/platform/ocp/48304000.epwmss/48304200.pwm/pwm/pwmchip4", channel: 0},
|
"P8_19": {path: "/sys/devices/platform/ocp/48304000.epwmss/48304200.pwm/pwm/pwmchip4", channel: 0},
|
||||||
|
|
||||||
|
@ -62,10 +57,10 @@ var pwmPins = map[string]pwmPinData{
|
||||||
"P9_16": {path: "/sys/devices/platform/ocp/48302000.epwmss/48302200.pwm/pwm/pwmchip2", channel: 1},
|
"P9_16": {path: "/sys/devices/platform/ocp/48302000.epwmss/48302200.pwm/pwm/pwmchip2", channel: 1},
|
||||||
"P9_21": {path: "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0", channel: 1},
|
"P9_21": {path: "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0", channel: 1},
|
||||||
"P9_22": {path: "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0", channel: 0},
|
"P9_22": {path: "/sys/devices/platform/ocp/48300000.epwmss/48300200.pwm/pwm/pwmchip0", channel: 0},
|
||||||
//"P9_42": {path: "", channel: 0}, TODO: implement this pwm
|
"P9_42": {path: "/sys/devices/platform/ocp/48300000.epwmss/48300100.ecap/pwm/pwmchip0", channel: 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
var analogPins = map[string]string{
|
var bbbAnalogPinMap = map[string]string{
|
||||||
"P9_39": "in_voltage0_raw",
|
"P9_39": "in_voltage0_raw",
|
||||||
"P9_40": "in_voltage1_raw",
|
"P9_40": "in_voltage1_raw",
|
||||||
"P9_37": "in_voltage2_raw",
|
"P9_37": "in_voltage2_raw",
|
||||||
|
|
Loading…
Reference in New Issue