diff --git a/bbb.go b/bbb.go new file mode 100644 index 0000000..91cc6ce --- /dev/null +++ b/bbb.go @@ -0,0 +1,71 @@ +package embd + +func init() { + Describers[HostBBB] = func(rev int) *Descriptor { + return &Descriptor{ + GPIO: func() GPIO { + return newGPIODriver(bbbPins) + }, + I2C: newI2CDriver, + } + } +} + +var bbbPins = PinMap{ + &PinDesc{66, []string{"P8_07", "GPIO_66", "TIMER4"}, CapNormal | CapGPMC}, + &PinDesc{67, []string{"P8_08", "GPIO_67", "TIMER7"}, CapNormal | CapGPMC}, + &PinDesc{69, []string{"P8_09", "GPIO_69", "TIMER5"}, CapNormal | CapGPMC}, + &PinDesc{68, []string{"P8_10", "GPIO_68", "TIMER6"}, CapNormal | CapGPMC}, + &PinDesc{45, []string{"P8_11", "GPIO_45"}, CapNormal | CapGPMC}, + &PinDesc{44, []string{"P8_12", "GPIO_44"}, CapNormal | CapGPMC}, + &PinDesc{23, []string{"P8_13", "GPIO_23", "EHRPWM2B"}, CapNormal | CapGPMC}, + &PinDesc{26, []string{"P8_14", "GPIO_26"}, CapNormal | CapGPMC}, + &PinDesc{47, []string{"P8_15", "GPIO_47"}, CapNormal | CapGPMC}, + &PinDesc{46, []string{"P8_16", "GPIO_46"}, CapNormal | CapGPMC}, + &PinDesc{27, []string{"P8_17", "GPIO_27"}, CapNormal | CapGPMC}, + &PinDesc{65, []string{"P8_18", "GPIO_65"}, CapNormal | CapGPMC}, + &PinDesc{22, []string{"P8_19", "GPIO_22", "EHRPWM2A"}, CapNormal | CapGPMC}, + &PinDesc{61, []string{"P8_26", "GPIO_61"}, CapNormal | CapGPMC}, + &PinDesc{86, []string{"P8_27", "GPIO_86"}, CapNormal | CapLCD}, + &PinDesc{88, []string{"P8_28", "GPIO_88"}, CapNormal | CapLCD}, + &PinDesc{87, []string{"P8_29", "GPIO_87"}, CapNormal | CapLCD}, + &PinDesc{89, []string{"P8_30", "GPIO_89"}, CapNormal | CapLCD}, + &PinDesc{10, []string{"P8_31", "GPIO_10", "UART5_CTSN"}, CapNormal | CapLCD}, + &PinDesc{11, []string{"P8_32", "GPIO_11", "UART5_RTSN"}, CapNormal | CapLCD}, + &PinDesc{9, []string{"P8_33", "GPIO_9 ", "UART4_RTSN"}, CapNormal | CapLCD}, + &PinDesc{81, []string{"P8_34", "GPIO_81", "UART3_RTSN"}, CapNormal | CapLCD}, + &PinDesc{8, []string{"P8_35", "GPIO_8 ", "UART4_CTSN"}, CapNormal | CapLCD}, + &PinDesc{80, []string{"P8_36", "GPIO_80", "UART3_CTSN"}, CapNormal | CapLCD}, + &PinDesc{78, []string{"P8_37", "GPIO_78", "UART5_TXD"}, CapNormal | CapLCD}, + &PinDesc{79, []string{"P8_38", "GPIO_79", "UART5_RXD"}, CapNormal | CapLCD}, + &PinDesc{76, []string{"P8_39", "GPIO_76"}, CapNormal | CapLCD}, + &PinDesc{77, []string{"P8_40", "GPIO_77"}, CapNormal | CapLCD}, + &PinDesc{74, []string{"P8_41", "GPIO_74"}, CapNormal | CapLCD}, + &PinDesc{75, []string{"P8_42", "GPIO_75"}, CapNormal | CapLCD}, + &PinDesc{72, []string{"P8_43", "GPIO_72"}, CapNormal | CapLCD}, + &PinDesc{73, []string{"P8_44", "GPIO_73"}, CapNormal | CapLCD}, + &PinDesc{70, []string{"P8_45", "GPIO_70"}, CapNormal | CapLCD}, + &PinDesc{71, []string{"P8_46", "GPIO_71"}, CapNormal | CapLCD}, + + &PinDesc{30, []string{"P9_11", "GPIO_30", "UART4_RXD"}, CapNormal | CapUART}, + &PinDesc{60, []string{"P9_12", "GPIO_60", "GPIO1_28"}, CapNormal}, + &PinDesc{31, []string{"P9_13", "GPIO_31", "UART4_TXD"}, CapNormal | CapUART}, + &PinDesc{50, []string{"P9_14", "GPIO_50", "EHRPWM1A"}, CapNormal | CapPWM}, + &PinDesc{48, []string{"P9_15", "GPIO_48", "GPIO1_16"}, CapNormal}, + &PinDesc{51, []string{"P9_16", "GPIO_51", "EHRPWM1B"}, CapNormal | CapPWM}, + &PinDesc{5, []string{"P9_17", "GPIO_5", "I2C1_SCL"}, CapNormal | CapI2C}, + &PinDesc{4, []string{"P9_18", "GPIO_4", "I2C1_SDA"}, CapNormal | CapI2C}, + &PinDesc{13, []string{"P9_19", "GPIO_13", "I2C2_SCL"}, CapNormal | CapI2C}, + &PinDesc{12, []string{"P9_20", "GPIO_12", "I2C2_SDA"}, CapNormal | CapI2C}, + &PinDesc{3, []string{"P9_21", "GPIO_3", "UART2_TXD"}, CapNormal | CapUART}, + &PinDesc{2, []string{"P9_22", "GPIO_2", "UART2_RXD"}, CapNormal | CapUART}, + &PinDesc{49, []string{"P9_23", "GPIO_49", "GPIO1_17"}, CapNormal}, + &PinDesc{15, []string{"P9_24", "GPIO_15", "UART1_TXD"}, CapNormal | CapUART}, + &PinDesc{117, []string{"P9_25", "GPIO_117", "GPIO3_21"}, CapNormal}, + &PinDesc{14, []string{"P9_26", "GPIO_14", "UART1_RXD"}, CapNormal | CapUART}, + &PinDesc{115, []string{"P9_27", "GPIO_115", "GPIO3_19"}, CapNormal}, + &PinDesc{113, []string{"P9_28", "GPIO_113", "SPI1_CS0"}, CapNormal | CapSPI}, + &PinDesc{111, []string{"P9_29", "GPIO_111", "SPI1_D0"}, CapNormal | CapSPI}, + &PinDesc{112, []string{"P9_30", "GPIO_112", "SPI1_D1"}, CapNormal | CapSPI}, + &PinDesc{110, []string{"P9_31", "GPIO_110", "SPI1_SCLK"}, CapNormal | CapSPI}, +} diff --git a/controller/mcp4725/mcp4725.go b/controller/mcp4725/mcp4725.go index 83ba553..80e3158 100644 --- a/controller/mcp4725/mcp4725.go +++ b/controller/mcp4725/mcp4725.go @@ -4,8 +4,7 @@ package mcp4725 import ( "log" "sync" - - "github.com/kidoman/embd/i2c" + "github.com/kidoman/embd" ) const ( @@ -20,7 +19,7 @@ const ( // MCP4725 represents a MCP4725 DAC. type MCP4725 struct { // Bus to communicate over. - Bus i2c.Bus + Bus embd.I2CBus // Addr of the sensor. Addr byte @@ -32,7 +31,7 @@ type MCP4725 struct { } // New creates a new MCP4725 sensor. -func New(bus i2c.Bus, addr byte) *MCP4725 { +func New(bus embd.I2CBus, addr byte) *MCP4725 { return &MCP4725{ Bus: bus, Addr: addr, diff --git a/controller/pca9685/pca9685.go b/controller/pca9685/pca9685.go index 695aad7..751dbe0 100644 --- a/controller/pca9685/pca9685.go +++ b/controller/pca9685/pca9685.go @@ -6,8 +6,7 @@ import ( "math" "sync" "time" - - "github.com/kidoman/embd/i2c" + "github.com/kidoman/embd" "github.com/kidoman/embd/util" ) @@ -28,7 +27,7 @@ const ( // PCA9685 represents a PCA9685 PWM generator. type PCA9685 struct { - Bus i2c.Bus + Bus embd.I2CBus Addr byte Freq int @@ -39,7 +38,7 @@ type PCA9685 struct { } // New creates a new PCA9685 interface. -func New(bus i2c.Bus, addr byte) *PCA9685 { +func New(bus embd.I2CBus, addr byte) *PCA9685 { return &PCA9685{ Bus: bus, Addr: addr, diff --git a/host/descriptor.go b/descriptor.go similarity index 69% rename from host/descriptor.go rename to descriptor.go index 5f89fc7..3001acb 100644 --- a/host/descriptor.go +++ b/descriptor.go @@ -1,18 +1,18 @@ -package host +package embd import "fmt" type Descriptor struct { - GPIO func() interface{} - I2C func() interface{} + GPIO func() GPIO + I2C func() I2C } type Describer func(rev int) *Descriptor var Describers = map[Host]Describer{} -func Describe() (*Descriptor, error) { - host, rev, err := Detect() +func DescribeHost() (*Descriptor, error) { + host, rev, err := DetectHost() if err != nil { return nil, err } diff --git a/host/detect.go b/detect.go similarity index 85% rename from host/detect.go rename to detect.go index bdfb469..e1c1acc 100644 --- a/host/detect.go +++ b/detect.go @@ -1,4 +1,4 @@ -package host +package embd import ( "fmt" @@ -10,11 +10,11 @@ import ( type Host int const ( - Null Host = iota - RPi - BBB - CubieTruck - Galileo + HostNull Host = iota + HostRPi + HostBBB + HostCubieTruck + HostGalileo ) func execOutput(name string, arg ...string) (output string, err error) { @@ -60,20 +60,20 @@ func kernelVersion() (major, minor, patch int, err error) { return parseVersion(output) } -func Detect() (Host, int, error) { +func DetectHost() (Host, int, error) { major, minor, patch, err := kernelVersion() if err != nil { - return Null, 0, err + return HostNull, 0, err } if major < 3 || (major == 3 && minor < 8) { err = fmt.Errorf("embd: linux kernel versions lower than 3.8 are not supported. you have %v.%v.%v", major, minor, patch) - return Null, 0, err + return HostNull, 0, err } node, err := nodeName() if err != nil { - return Null, 0, err + return HostNull, 0, err } var host Host @@ -81,12 +81,12 @@ func Detect() (Host, int, error) { switch node { case "raspberrypi": - host = RPi + host = HostRPi case "beaglebone": - host = BBB + host = HostBBB default: err = fmt.Errorf("embd: your host %q is not supported at this moment. please request support at https://github.com/kidoman/embd/issues", node) - return Null, 0, err + return HostNull, 0, err } return host, rev, nil diff --git a/host/detect_test.go b/detect_test.go similarity index 97% rename from host/detect_test.go rename to detect_test.go index de8a6cd..48c539e 100644 --- a/host/detect_test.go +++ b/detect_test.go @@ -1,4 +1,4 @@ -package host +package embd import "testing" diff --git a/driver/linux/gpio/digitalpin.go b/driver/linux/gpio/digitalpin.go deleted file mode 100644 index 8619ec1..0000000 --- a/driver/linux/gpio/digitalpin.go +++ /dev/null @@ -1,126 +0,0 @@ -package gpio - -import ( - "errors" - "fmt" - "os" - "path" - - "github.com/kidoman/embd/gpio" -) - -type digitalPin struct { - n int - - dir *os.File - val *os.File - activeLow *os.File - edge *os.File -} - -func newDigitalPin(n int) (*digitalPin, error) { - p := &digitalPin{n: n} - if err := p.init(); err != nil { - return nil, err - } - return p, nil -} - -func (p *digitalPin) init() error { - var err error - if p.dir, err = p.directionFile(); err != nil { - return err - } - if p.val, err = p.valueFile(); err != nil { - return err - } - if p.activeLow, err = p.activeLowFile(); err != nil { - return err - } - - return nil -} - -func (p *digitalPin) basePath() string { - return fmt.Sprintf("/sys/class/gpio/gpio%v", p.n) -} - -func (p *digitalPin) openFile(path string) (*os.File, error) { - return os.OpenFile(path, os.O_RDWR, os.ModeExclusive) -} - -func (p *digitalPin) directionFile() (*os.File, error) { - return p.openFile(path.Join(p.basePath(), "direction")) -} - -func (p *digitalPin) valueFile() (*os.File, error) { - return p.openFile(path.Join(p.basePath(), "value")) -} - -func (p *digitalPin) activeLowFile() (*os.File, error) { - return p.openFile(path.Join(p.basePath(), "active_low")) -} - -func (p *digitalPin) SetDirection(dir gpio.Direction) error { - str := "in" - if dir == gpio.Out { - str = "out" - } - _, err := p.dir.WriteString(str) - return err -} - -func (p *digitalPin) Read() (int, error) { - buf := make([]byte, 1) - if _, err := p.val.Read(buf); err != nil { - return 0, err - } - var val int - if buf[0] == '1' { - val = 1 - } - return val, nil -} - -func (p *digitalPin) Write(val int) error { - str := "0" - if val == gpio.High { - str = "1" - } - _, err := p.val.WriteString(str) - return err -} - -func (p *digitalPin) ActiveLow(b bool) error { - str := "0" - if b { - str = "1" - } - _, err := p.activeLow.WriteString(str) - return err -} - -func (p *digitalPin) PullUp() error { - return errors.New("not implemented") -} - -func (p *digitalPin) PullDown() error { - return errors.New("not implemented") -} - -func (p *digitalPin) Close() error { - if err := p.dir.Close(); err != nil { - return err - } - if err := p.val.Close(); err != nil { - return err - } - if err := p.activeLow.Close(); err != nil { - return err - } - if err := p.edge.Close(); err != nil { - return err - } - - return nil -} diff --git a/driver/linux/gpio/gpio.go b/driver/linux/gpio/gpio.go deleted file mode 100644 index 5736c71..0000000 --- a/driver/linux/gpio/gpio.go +++ /dev/null @@ -1,154 +0,0 @@ -package gpio - -import ( - "fmt" - "os" - "strconv" - - "github.com/golang/glog" - "github.com/kidoman/embd/gpio" -) - -const ( - Normal int = 1 << iota - I2C - UART - SPI - GPMC - LCD - PWM -) - -type PinDesc struct { - N int - IDs []string - Caps int -} - -type PinMap []*PinDesc - -func (m PinMap) Lookup(k interface{}) (*PinDesc, bool) { - switch key := k.(type) { - case int: - for i := range m { - if m[i].N == key { - return m[i], true - } - } - case string: - for i := range m { - for j := range m[i].IDs { - if m[i].IDs[j] == key { - return m[i], true - } - } - } - } - - return nil, false -} - -type GPIO struct { - exporter, unexporter *os.File - - initialized bool - - pinMap PinMap - initializedPins map[int]*digitalPin -} - -func New(pinMap PinMap) *GPIO { - return &GPIO{ - pinMap: pinMap, - initializedPins: map[int]*digitalPin{}, - } -} - -func (io *GPIO) init() error { - if io.initialized { - return nil - } - - var err error - if io.exporter, err = os.OpenFile("/sys/class/gpio/export", os.O_WRONLY, os.ModeExclusive); err != nil { - return err - } - if io.unexporter, err = os.OpenFile("/sys/class/gpio/unexport", os.O_WRONLY, os.ModeExclusive); err != nil { - return err - } - - io.initialized = true - - return nil -} - -func (io *GPIO) lookupKey(key interface{}) (*PinDesc, bool) { - return io.pinMap.Lookup(key) -} - -func (io *GPIO) export(n int) error { - _, err := io.exporter.WriteString(strconv.Itoa(n)) - return err -} - -func (io *GPIO) unexport(n int) error { - _, err := io.unexporter.WriteString(strconv.Itoa(n)) - return err -} - -func (io *GPIO) digitalPin(key interface{}) (*digitalPin, error) { - pd, found := io.lookupKey(key) - if !found { - err := fmt.Errorf("gpio: could not find pin matching %q", key) - return nil, err - } - - n := pd.N - - p, ok := io.initializedPins[n] - if ok { - return p, nil - } - - if pd.Caps&Normal == 0 { - err := fmt.Errorf("gpio: sorry, pin %q cannot be used for GPIO", key) - return nil, err - } - - if pd.Caps != Normal { - glog.Infof("gpio: pin %q is not a dedicated GPIO pin. please refer to the system reference manual for more details", key) - } - - if err := io.export(n); err != nil { - return nil, err - } - - p, err := newDigitalPin(n) - if err != nil { - io.unexport(n) - return nil, err - } - - io.initializedPins[n] = p - - return p, nil -} - -func (io *GPIO) DigitalPin(key interface{}) (gpio.DigitalPin, error) { - if err := io.init(); err != nil { - return nil, err - } - - return io.digitalPin(key) -} - -func (io *GPIO) Close() error { - for n := range io.initializedPins { - io.unexport(n) - } - - io.exporter.Close() - io.unexporter.Close() - - return nil -} diff --git a/driver/linux/i2c/i2c.go b/driver/linux/i2c/i2c.go deleted file mode 100644 index e967323..0000000 --- a/driver/linux/i2c/i2c.go +++ /dev/null @@ -1,43 +0,0 @@ -// Package i2c enables gophers i2c speaking ability. -package i2c - -import ( - "sync" - - "github.com/kidoman/embd/i2c" -) - -type I2C struct { - busMap map[byte]*bus - busMapLock sync.Mutex -} - -func New() *I2C { - return &I2C{ - busMap: make(map[byte]*bus), - } -} - -func (i *I2C) Bus(l byte) i2c.Bus { - i.busMapLock.Lock() - defer i.busMapLock.Unlock() - - var b *bus - - if b = i.busMap[l]; b == nil { - b = &bus{l: l} - i.busMap[l] = b - } - - return b -} - -func (i *I2C) Close() error { - for _, b := range i.busMap { - b.Close() - - delete(i.busMap, b.l) - } - - return nil -} diff --git a/gpio/gpio.go b/gpio.go similarity index 80% rename from gpio/gpio.go rename to gpio.go index fad4ff2..6332822 100644 --- a/gpio/gpio.go +++ b/gpio.go @@ -1,6 +1,4 @@ -package gpio - -import "github.com/kidoman/embd/host" +package embd type Direction int @@ -27,31 +25,31 @@ type DigitalPin interface { Close() error } -type gpio interface { +type GPIO interface { DigitalPin(key interface{}) (DigitalPin, error) Close() error } -var instance gpio +var gpioInstance GPIO -func Open() error { - desc, err := host.Describe() +func InitGPIO() error { + desc, err := DescribeHost() if err != nil { return err } - instance = desc.GPIO().(gpio) + gpioInstance = desc.GPIO() return nil } -func Close() error { - return instance.Close() +func CloseGPIO() error { + return gpioInstance.Close() } func NewDigitalPin(key interface{}) (DigitalPin, error) { - return instance.DigitalPin(key) + return gpioInstance.DigitalPin(key) } func DigitalWrite(key interface{}, val int) error { diff --git a/gpiogeneric.go b/gpiogeneric.go new file mode 100644 index 0000000..0e32b94 --- /dev/null +++ b/gpiogeneric.go @@ -0,0 +1,271 @@ +package embd + +import ( + "errors" + "fmt" + "os" + "path" + "strconv" + + "github.com/golang/glog" +) + +const ( + CapNormal int = 1 << iota + CapI2C + CapUART + CapSPI + CapGPMC + CapLCD + CapPWM +) + +type PinDesc struct { + N int + IDs []string + Caps int +} + +type PinMap []*PinDesc + +func (m PinMap) Lookup(k interface{}) (*PinDesc, bool) { + switch key := k.(type) { + case int: + for i := range m { + if m[i].N == key { + return m[i], true + } + } + case string: + for i := range m { + for j := range m[i].IDs { + if m[i].IDs[j] == key { + return m[i], true + } + } + } + } + + return nil, false +} + +type gpioDriver struct { + exporter, unexporter *os.File + + initialized bool + + pinMap PinMap + initializedPins map[int]*digitalPin +} + +func newGPIODriver(pinMap PinMap) *gpioDriver { + return &gpioDriver{ + pinMap: pinMap, + initializedPins: map[int]*digitalPin{}, + } +} + +func (io *gpioDriver) init() error { + if io.initialized { + return nil + } + + var err error + if io.exporter, err = os.OpenFile("/sys/class/gpio/export", os.O_WRONLY, os.ModeExclusive); err != nil { + return err + } + if io.unexporter, err = os.OpenFile("/sys/class/gpio/unexport", os.O_WRONLY, os.ModeExclusive); err != nil { + return err + } + + io.initialized = true + + return nil +} + +func (io *gpioDriver) lookupKey(key interface{}) (*PinDesc, bool) { + return io.pinMap.Lookup(key) +} + +func (io *gpioDriver) export(n int) error { + _, err := io.exporter.WriteString(strconv.Itoa(n)) + return err +} + +func (io *gpioDriver) unexport(n int) error { + _, err := io.unexporter.WriteString(strconv.Itoa(n)) + return err +} + +func (io *gpioDriver) digitalPin(key interface{}) (*digitalPin, error) { + pd, found := io.lookupKey(key) + if !found { + err := fmt.Errorf("gpio: could not find pin matching %q", key) + return nil, err + } + + n := pd.N + + p, ok := io.initializedPins[n] + if ok { + return p, nil + } + + if pd.Caps&CapNormal == 0 { + err := fmt.Errorf("gpio: sorry, pin %q cannot be used for GPIO", key) + return nil, err + } + + if pd.Caps != CapNormal { + glog.Infof("gpio: pin %q is not a dedicated GPIO pin. please refer to the system reference manual for more details", key) + } + + if err := io.export(n); err != nil { + return nil, err + } + + p, err := newDigitalPin(n) + if err != nil { + io.unexport(n) + return nil, err + } + + io.initializedPins[n] = p + + return p, nil +} + +func (io *gpioDriver) DigitalPin(key interface{}) (DigitalPin, error) { + if err := io.init(); err != nil { + return nil, err + } + + return io.digitalPin(key) +} + +func (io *gpioDriver) Close() error { + for n := range io.initializedPins { + io.unexport(n) + } + + io.exporter.Close() + io.unexporter.Close() + + return nil +} + +type digitalPin struct { + n int + + dir *os.File + val *os.File + activeLow *os.File + edge *os.File +} + +func newDigitalPin(n int) (*digitalPin, error) { + p := &digitalPin{n: n} + if err := p.init(); err != nil { + return nil, err + } + return p, nil +} + +func (p *digitalPin) init() error { + var err error + if p.dir, err = p.directionFile(); err != nil { + return err + } + if p.val, err = p.valueFile(); err != nil { + return err + } + if p.activeLow, err = p.activeLowFile(); err != nil { + return err + } + + return nil +} + +func (p *digitalPin) basePath() string { + return fmt.Sprintf("/sys/class/gpio/gpio%v", p.n) +} + +func (p *digitalPin) openFile(path string) (*os.File, error) { + return os.OpenFile(path, os.O_RDWR, os.ModeExclusive) +} + +func (p *digitalPin) directionFile() (*os.File, error) { + return p.openFile(path.Join(p.basePath(), "direction")) +} + +func (p *digitalPin) valueFile() (*os.File, error) { + return p.openFile(path.Join(p.basePath(), "value")) +} + +func (p *digitalPin) activeLowFile() (*os.File, error) { + return p.openFile(path.Join(p.basePath(), "active_low")) +} + +func (p *digitalPin) SetDirection(dir Direction) error { + str := "in" + if dir == Out { + str = "out" + } + _, err := p.dir.WriteString(str) + return err +} + +func (p *digitalPin) Read() (int, error) { + buf := make([]byte, 1) + if _, err := p.val.Read(buf); err != nil { + return 0, err + } + var val int + if buf[0] == '1' { + val = 1 + } + return val, nil +} + +func (p *digitalPin) Write(val int) error { + str := "0" + if val == High { + str = "1" + } + _, err := p.val.WriteString(str) + return err +} + +func (p *digitalPin) ActiveLow(b bool) error { + str := "0" + if b { + str = "1" + } + _, err := p.activeLow.WriteString(str) + return err +} + +func (p *digitalPin) PullUp() error { + return errors.New("not implemented") +} + +func (p *digitalPin) PullDown() error { + return errors.New("not implemented") +} + +func (p *digitalPin) Close() error { + if err := p.dir.Close(); err != nil { + return err + } + if err := p.val.Close(); err != nil { + return err + } + if err := p.activeLow.Close(); err != nil { + return err + } + if err := p.edge.Close(); err != nil { + return err + } + + return nil +} diff --git a/host/bbb/data.go b/host/bbb/data.go deleted file mode 100644 index 541cc82..0000000 --- a/host/bbb/data.go +++ /dev/null @@ -1,64 +0,0 @@ -package bbb - -import ( - "github.com/kidoman/embd/driver/linux/gpio" -) - -var pins = gpio.PinMap{ - &gpio.PinDesc{66, []string{"P8_07", "GPIO_66", "TIMER4"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{67, []string{"P8_08", "GPIO_67", "TIMER7"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{69, []string{"P8_09", "GPIO_69", "TIMER5"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{68, []string{"P8_10", "GPIO_68", "TIMER6"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{45, []string{"P8_11", "GPIO_45"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{44, []string{"P8_12", "GPIO_44"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{23, []string{"P8_13", "GPIO_23", "EHRPWM2B"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{26, []string{"P8_14", "GPIO_26"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{47, []string{"P8_15", "GPIO_47"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{46, []string{"P8_16", "GPIO_46"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{27, []string{"P8_17", "GPIO_27"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{65, []string{"P8_18", "GPIO_65"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{22, []string{"P8_19", "GPIO_22", "EHRPWM2A"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{61, []string{"P8_26", "GPIO_61"}, gpio.Normal | gpio.GPMC}, - &gpio.PinDesc{86, []string{"P8_27", "GPIO_86"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{88, []string{"P8_28", "GPIO_88"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{87, []string{"P8_29", "GPIO_87"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{89, []string{"P8_30", "GPIO_89"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{10, []string{"P8_31", "GPIO_10", "UART5_CTSN"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{11, []string{"P8_32", "GPIO_11", "UART5_RTSN"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{9, []string{"P8_33", "GPIO_9 ", "UART4_RTSN"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{81, []string{"P8_34", "GPIO_81", "UART3_RTSN"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{8, []string{"P8_35", "GPIO_8 ", "UART4_CTSN"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{80, []string{"P8_36", "GPIO_80", "UART3_CTSN"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{78, []string{"P8_37", "GPIO_78", "UART5_TXD"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{79, []string{"P8_38", "GPIO_79", "UART5_RXD"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{76, []string{"P8_39", "GPIO_76"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{77, []string{"P8_40", "GPIO_77"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{74, []string{"P8_41", "GPIO_74"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{75, []string{"P8_42", "GPIO_75"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{72, []string{"P8_43", "GPIO_72"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{73, []string{"P8_44", "GPIO_73"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{70, []string{"P8_45", "GPIO_70"}, gpio.Normal | gpio.LCD}, - &gpio.PinDesc{71, []string{"P8_46", "GPIO_71"}, gpio.Normal | gpio.LCD}, - - &gpio.PinDesc{30, []string{"P9_11", "GPIO_30", "UART4_RXD"}, gpio.Normal | gpio.UART}, - &gpio.PinDesc{60, []string{"P9_12", "GPIO_60", "GPIO1_28"}, gpio.Normal}, - &gpio.PinDesc{31, []string{"P9_13", "GPIO_31", "UART4_TXD"}, gpio.Normal | gpio.UART}, - &gpio.PinDesc{50, []string{"P9_14", "GPIO_50", "EHRPWM1A"}, gpio.Normal | gpio.PWM}, - &gpio.PinDesc{48, []string{"P9_15", "GPIO_48", "GPIO1_16"}, gpio.Normal}, - &gpio.PinDesc{51, []string{"P9_16", "GPIO_51", "EHRPWM1B"}, gpio.Normal | gpio.PWM}, - &gpio.PinDesc{5, []string{"P9_17", "GPIO_5", "I2C1_SCL"}, gpio.Normal | gpio.I2C}, - &gpio.PinDesc{4, []string{"P9_18", "GPIO_4", "I2C1_SDA"}, gpio.Normal | gpio.I2C}, - &gpio.PinDesc{13, []string{"P9_19", "GPIO_13", "I2C2_SCL"}, gpio.Normal | gpio.I2C}, - &gpio.PinDesc{12, []string{"P9_20", "GPIO_12", "I2C2_SDA"}, gpio.Normal | gpio.I2C}, - &gpio.PinDesc{3, []string{"P9_21", "GPIO_3", "UART2_TXD"}, gpio.Normal | gpio.UART}, - &gpio.PinDesc{2, []string{"P9_22", "GPIO_2", "UART2_RXD"}, gpio.Normal | gpio.UART}, - &gpio.PinDesc{49, []string{"P9_23", "GPIO_49", "GPIO1_17"}, gpio.Normal}, - &gpio.PinDesc{15, []string{"P9_24", "GPIO_15", "UART1_TXD"}, gpio.Normal | gpio.UART}, - &gpio.PinDesc{117, []string{"P9_25", "GPIO_117", "GPIO3_21"}, gpio.Normal}, - &gpio.PinDesc{14, []string{"P9_26", "GPIO_14", "UART1_RXD"}, gpio.Normal | gpio.UART}, - &gpio.PinDesc{115, []string{"P9_27", "GPIO_115", "GPIO3_19"}, gpio.Normal}, - &gpio.PinDesc{113, []string{"P9_28", "GPIO_113", "SPI1_CS0"}, gpio.Normal | gpio.SPI}, - &gpio.PinDesc{111, []string{"P9_29", "GPIO_111", "SPI1_D0"}, gpio.Normal | gpio.SPI}, - &gpio.PinDesc{112, []string{"P9_30", "GPIO_112", "SPI1_D1"}, gpio.Normal | gpio.SPI}, - &gpio.PinDesc{110, []string{"P9_31", "GPIO_110", "SPI1_SCLK"}, gpio.Normal | gpio.SPI}, -} diff --git a/host/bbb/descriptor.go b/host/bbb/descriptor.go deleted file mode 100644 index 429ca14..0000000 --- a/host/bbb/descriptor.go +++ /dev/null @@ -1,22 +0,0 @@ -package bbb - -import ( - lgpio "github.com/kidoman/embd/driver/linux/gpio" - li2c "github.com/kidoman/embd/driver/linux/i2c" - "github.com/kidoman/embd/host" -) - -func init() { - host.Describers[host.BBB] = describer -} - -func describer(rev int) *host.Descriptor { - return &host.Descriptor{ - GPIO: func() interface{} { - return lgpio.New(pins) - }, - I2C: func() interface{} { - return li2c.New() - }, - } -} diff --git a/host/rpi/data.go b/host/rpi/data.go deleted file mode 100644 index abf1025..0000000 --- a/host/rpi/data.go +++ /dev/null @@ -1,45 +0,0 @@ -package rpi - -import ( - "github.com/kidoman/embd/driver/linux/gpio" -) - -var rev1Pins = gpio.PinMap{ - &gpio.PinDesc{0, []string{"P1_3", "GPIO_0", "SDA", "I2C0_SDA"}, gpio.Normal | gpio.I2C}, - &gpio.PinDesc{1, []string{"P1_5", "GPIO_1", "SCL", "I2C0_SCL"}, gpio.Normal | gpio.I2C}, - &gpio.PinDesc{4, []string{"P1_7", "GPIO_4", "GPCLK0"}, gpio.Normal}, - &gpio.PinDesc{14, []string{"P1_8", "GPIO_14", "TXD", "UART0_TXD"}, gpio.Normal | gpio.UART}, - &gpio.PinDesc{15, []string{"P1_10", "GPIO_15", "RXD", "UART0_RXD"}, gpio.Normal | gpio.UART}, - &gpio.PinDesc{17, []string{"P1_11", "GPIO_17"}, gpio.Normal}, - &gpio.PinDesc{18, []string{"P1_12", "GPIO_18", "PCM_CLK"}, gpio.Normal}, - &gpio.PinDesc{21, []string{"P1_13", "GPIO_21"}, gpio.Normal}, - &gpio.PinDesc{22, []string{"P1_15", "GPIO_22"}, gpio.Normal}, - &gpio.PinDesc{23, []string{"P1_16", "GPIO_23"}, gpio.Normal}, - &gpio.PinDesc{24, []string{"P1_18", "GPIO_24"}, gpio.Normal}, - &gpio.PinDesc{10, []string{"P1_19", "GPIO_10", "MOSI", "SPI0_MOSI"}, gpio.Normal | gpio.SPI}, - &gpio.PinDesc{9, []string{"P1_21", "GPIO_9", "MISO", "SPI0_MISO"}, gpio.Normal | gpio.SPI}, - &gpio.PinDesc{25, []string{"P1_22", "GPIO_25"}, gpio.Normal}, - &gpio.PinDesc{11, []string{"P1_23", "GPIO_11", "SCLK", "SPI0_SCLK"}, gpio.Normal | gpio.SPI}, - &gpio.PinDesc{8, []string{"P1_24", "GPIO_8", "CE0", "SPI0_CE0_N"}, gpio.Normal | gpio.SPI}, - &gpio.PinDesc{7, []string{"P1_26", "GPIO_7", "CE1", "SPI0_CE1_N"}, gpio.Normal | gpio.SPI}, -} - -var rev2Pins = gpio.PinMap{ - &gpio.PinDesc{2, []string{"P1_3", "GPIO_2", "SDA", "I2C1_SDA"}, gpio.Normal | gpio.I2C}, - &gpio.PinDesc{3, []string{"P1_5", "GPIO_3", "SCL", "I2C1_SCL"}, gpio.Normal | gpio.I2C}, - &gpio.PinDesc{4, []string{"P1_7", "GPIO_4", "GPCLK0"}, gpio.Normal}, - &gpio.PinDesc{14, []string{"P1_8", "GPIO_14", "TXD", "UART0_TXD"}, gpio.Normal | gpio.UART}, - &gpio.PinDesc{15, []string{"P1_10", "GPIO_15", "RXD", "UART0_RXD"}, gpio.Normal | gpio.UART}, - &gpio.PinDesc{17, []string{"P1_11", "GPIO_17"}, gpio.Normal}, - &gpio.PinDesc{18, []string{"P1_12", "GPIO_18", "PCM_CLK"}, gpio.Normal}, - &gpio.PinDesc{27, []string{"P1_13", "GPIO_27"}, gpio.Normal}, - &gpio.PinDesc{22, []string{"P1_15", "GPIO_22"}, gpio.Normal}, - &gpio.PinDesc{23, []string{"P1_16", "GPIO_23"}, gpio.Normal}, - &gpio.PinDesc{24, []string{"P1_18", "GPIO_24"}, gpio.Normal}, - &gpio.PinDesc{10, []string{"P1_19", "GPIO_10", "MOSI", "SPI0_MOSI"}, gpio.Normal | gpio.SPI}, - &gpio.PinDesc{9, []string{"P1_21", "GPIO_9", "MISO", "SPI0_MISO"}, gpio.Normal | gpio.SPI}, - &gpio.PinDesc{25, []string{"P1_22", "GPIO_25"}, gpio.Normal}, - &gpio.PinDesc{11, []string{"P1_23", "GPIO_11", "SCLK", "SPI0_SCLK"}, gpio.Normal | gpio.SPI}, - &gpio.PinDesc{8, []string{"P1_24", "GPIO_8", "CE0", "SPI0_CE0_N"}, gpio.Normal | gpio.SPI}, - &gpio.PinDesc{7, []string{"P1_26", "GPIO_7", "CE1", "SPI0_CE1_N"}, gpio.Normal | gpio.SPI}, -} diff --git a/host/rpi/descriptor.go b/host/rpi/descriptor.go deleted file mode 100644 index 2ba07d2..0000000 --- a/host/rpi/descriptor.go +++ /dev/null @@ -1,27 +0,0 @@ -package rpi - -import ( - lgpio "github.com/kidoman/embd/driver/linux/gpio" - li2c "github.com/kidoman/embd/driver/linux/i2c" - "github.com/kidoman/embd/host" -) - -func init() { - host.Describers[host.RPi] = describer -} - -func describer(rev int) *host.Descriptor { - var pins = rev1Pins - if rev > 1 { - pins = rev2Pins - } - - return &host.Descriptor{ - GPIO: func() interface{} { - return lgpio.New(pins) - }, - I2C: func() interface{} { - return li2c.New() - }, - } -} diff --git a/i2c/i2c.go b/i2c.go similarity index 76% rename from i2c/i2c.go rename to i2c.go index b786147..85060c2 100644 --- a/i2c/i2c.go +++ b/i2c.go @@ -1,9 +1,6 @@ -// Package i2c enables gophers i2c speaking ability. -package i2c +package embd -import "github.com/kidoman/embd/host" - -type Bus interface { +type I2CBus interface { // ReadByte reads a byte from the given address. ReadByte(addr byte) (value byte, err error) // WriteByte writes a byte to the given address. @@ -27,28 +24,28 @@ type Bus interface { } type I2C interface { - Bus(l byte) Bus + Bus(l byte) I2CBus Close() error } -var instance I2C +var i2cInstance I2C -func Open() error { - desc, err := host.Describe() +func InitI2C() error { + desc, err := DescribeHost() if err != nil { return err } - instance = desc.I2C().(I2C) + i2cInstance = desc.I2C() return nil } -func Close() error { - return instance.Close() +func CloseI2C() error { + return i2cInstance.Close() } -func NewBus(l byte) Bus { - return instance.Bus(l) +func NewI2CBus(l byte) I2CBus { + return i2cInstance.Bus(l) } diff --git a/driver/linux/i2c/bus.go b/i2cgeneric.go similarity index 78% rename from driver/linux/i2c/bus.go rename to i2cgeneric.go index e7074a8..81e0394 100644 --- a/driver/linux/i2c/bus.go +++ b/i2cgeneric.go @@ -1,4 +1,4 @@ -package i2c +package embd import ( "fmt" @@ -10,6 +10,41 @@ import ( "unsafe" ) +type i2cDriver struct { + busMap map[byte]*i2cBus + busMapLock sync.Mutex +} + +func newI2CDriver() I2C { + return &i2cDriver{ + busMap: make(map[byte]*i2cBus), + } +} + +func (i *i2cDriver) Bus(l byte) I2CBus { + i.busMapLock.Lock() + defer i.busMapLock.Unlock() + + var b *i2cBus + + if b = i.busMap[l]; b == nil { + b = &i2cBus{l: l} + i.busMap[l] = b + } + + return b +} + +func (i *i2cDriver) Close() error { + for _, b := range i.busMap { + b.Close() + + delete(i.busMap, b.l) + } + + return nil +} + const ( delay = 20 @@ -31,15 +66,15 @@ type i2c_rdwr_ioctl_data struct { nmsg uint32 } -type bus struct { +type i2cBus struct { l byte file *os.File addr byte mu sync.Mutex } -func newBus(l byte) (*bus, error) { - b := &bus{l: l} +func newI2CBus(l byte) (*i2cBus, error) { + b := &i2cBus{l: l} var err error if b.file, err = os.OpenFile(fmt.Sprintf("/dev/i2c-%v", b.l), os.O_RDWR, os.ModeExclusive); err != nil { @@ -49,14 +84,14 @@ func newBus(l byte) (*bus, error) { return b, nil } -func (b *bus) Close() error { +func (b *i2cBus) Close() error { b.mu.Lock() defer b.mu.Unlock() return b.file.Close() } -func (b *bus) setAddress(addr byte) (err error) { +func (b *i2cBus) setAddress(addr byte) (err error) { if addr != b.addr { if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, b.file.Fd(), slaveCmd, uintptr(addr)); errno != 0 { err = syscall.Errno(errno) @@ -69,7 +104,7 @@ func (b *bus) setAddress(addr byte) (err error) { return } -func (b *bus) ReadByte(addr byte) (value byte, err error) { +func (b *i2cBus) ReadByte(addr byte) (value byte, err error) { b.mu.Lock() defer b.mu.Unlock() @@ -89,7 +124,7 @@ func (b *bus) ReadByte(addr byte) (value byte, err error) { return } -func (b *bus) WriteByte(addr, value byte) (err error) { +func (b *i2cBus) WriteByte(addr, value byte) (err error) { b.mu.Lock() defer b.mu.Unlock() @@ -106,7 +141,7 @@ func (b *bus) WriteByte(addr, value byte) (err error) { return } -func (b *bus) WriteBytes(addr byte, value []byte) (err error) { +func (b *i2cBus) WriteBytes(addr byte, value []byte) (err error) { b.mu.Lock() defer b.mu.Unlock() @@ -130,7 +165,7 @@ func (b *bus) WriteBytes(addr byte, value []byte) (err error) { return nil } -func (b *bus) ReadFromReg(addr, reg byte, value []byte) (err error) { +func (b *i2cBus) ReadFromReg(addr, reg byte, value []byte) (err error) { b.mu.Lock() defer b.mu.Unlock() @@ -163,7 +198,7 @@ func (b *bus) ReadFromReg(addr, reg byte, value []byte) (err error) { return nil } -func (b *bus) ReadByteFromReg(addr, reg byte) (value byte, err error) { +func (b *i2cBus) ReadByteFromReg(addr, reg byte) (value byte, err error) { buf := make([]byte, 1) if err = b.ReadFromReg(addr, reg, buf); err != nil { return @@ -172,7 +207,7 @@ func (b *bus) ReadByteFromReg(addr, reg byte) (value byte, err error) { return } -func (b *bus) ReadWordFromReg(addr, reg byte) (value uint16, err error) { +func (b *i2cBus) ReadWordFromReg(addr, reg byte) (value uint16, err error) { buf := make([]byte, 2) if err = b.ReadFromReg(addr, reg, buf); err != nil { return @@ -181,7 +216,7 @@ func (b *bus) ReadWordFromReg(addr, reg byte) (value uint16, err error) { return } -func (b *bus) WriteToReg(addr, reg byte, value []byte) (err error) { +func (b *i2cBus) WriteToReg(addr, reg byte, value []byte) (err error) { b.mu.Lock() defer b.mu.Unlock() @@ -212,7 +247,7 @@ func (b *bus) WriteToReg(addr, reg byte, value []byte) (err error) { return } -func (b *bus) WriteByteToReg(addr, reg, value byte) (err error) { +func (b *i2cBus) WriteByteToReg(addr, reg, value byte) (err error) { b.mu.Lock() defer b.mu.Unlock() @@ -244,7 +279,7 @@ func (b *bus) WriteByteToReg(addr, reg, value byte) (err error) { return } -func (b *bus) WriteWordToReg(addr, reg byte, value uint16) (err error) { +func (b *i2cBus) WriteWordToReg(addr, reg byte, value uint16) (err error) { b.mu.Lock() defer b.mu.Unlock() diff --git a/rpi.go b/rpi.go new file mode 100644 index 0000000..c9c97aa --- /dev/null +++ b/rpi.go @@ -0,0 +1,57 @@ +package embd + +func init() { + Describers[HostRPi] = func(rev int) *Descriptor { + var pins = rpiRev1Pins + if rev > 1 { + pins = rpiRev2Pins + } + + return &Descriptor{ + GPIO: func() GPIO { + return newGPIODriver(pins) + }, + I2C: newI2CDriver, + } + } +} + +var rpiRev1Pins = PinMap{ + &PinDesc{0, []string{"P1_3", "GPIO_0", "SDA", "I2C0_SDA"}, CapNormal | CapI2C}, + &PinDesc{1, []string{"P1_5", "GPIO_1", "SCL", "I2C0_SCL"}, CapNormal | CapI2C}, + &PinDesc{4, []string{"P1_7", "GPIO_4", "GPCLK0"}, CapNormal}, + &PinDesc{14, []string{"P1_8", "GPIO_14", "TXD", "UART0_TXD"}, CapNormal | CapUART}, + &PinDesc{15, []string{"P1_10", "GPIO_15", "RXD", "UART0_RXD"}, CapNormal | CapUART}, + &PinDesc{17, []string{"P1_11", "GPIO_17"}, CapNormal}, + &PinDesc{18, []string{"P1_12", "GPIO_18", "PCM_CLK"}, CapNormal}, + &PinDesc{21, []string{"P1_13", "GPIO_21"}, CapNormal}, + &PinDesc{22, []string{"P1_15", "GPIO_22"}, CapNormal}, + &PinDesc{23, []string{"P1_16", "GPIO_23"}, CapNormal}, + &PinDesc{24, []string{"P1_18", "GPIO_24"}, CapNormal}, + &PinDesc{10, []string{"P1_19", "GPIO_10", "MOSI", "SPI0_MOSI"}, CapNormal | CapSPI}, + &PinDesc{9, []string{"P1_21", "GPIO_9", "MISO", "SPI0_MISO"}, CapNormal | CapSPI}, + &PinDesc{25, []string{"P1_22", "GPIO_25"}, CapNormal}, + &PinDesc{11, []string{"P1_23", "GPIO_11", "SCLK", "SPI0_SCLK"}, CapNormal | CapSPI}, + &PinDesc{8, []string{"P1_24", "GPIO_8", "CE0", "SPI0_CE0_N"}, CapNormal | CapSPI}, + &PinDesc{7, []string{"P1_26", "GPIO_7", "CE1", "SPI0_CE1_N"}, CapNormal | CapSPI}, +} + +var rpiRev2Pins = PinMap{ + &PinDesc{2, []string{"P1_3", "GPIO_2", "SDA", "I2C1_SDA"}, CapNormal | CapI2C}, + &PinDesc{3, []string{"P1_5", "GPIO_3", "SCL", "I2C1_SCL"}, CapNormal | CapI2C}, + &PinDesc{4, []string{"P1_7", "GPIO_4", "GPCLK0"}, CapNormal}, + &PinDesc{14, []string{"P1_8", "GPIO_14", "TXD", "UART0_TXD"}, CapNormal | CapUART}, + &PinDesc{15, []string{"P1_10", "GPIO_15", "RXD", "UART0_RXD"}, CapNormal | CapUART}, + &PinDesc{17, []string{"P1_11", "GPIO_17"}, CapNormal}, + &PinDesc{18, []string{"P1_12", "GPIO_18", "PCM_CLK"}, CapNormal}, + &PinDesc{27, []string{"P1_13", "GPIO_27"}, CapNormal}, + &PinDesc{22, []string{"P1_15", "GPIO_22"}, CapNormal}, + &PinDesc{23, []string{"P1_16", "GPIO_23"}, CapNormal}, + &PinDesc{24, []string{"P1_18", "GPIO_24"}, CapNormal}, + &PinDesc{10, []string{"P1_19", "GPIO_10", "MOSI", "SPI0_MOSI"}, CapNormal | CapSPI}, + &PinDesc{9, []string{"P1_21", "GPIO_9", "MISO", "SPI0_MISO"}, CapNormal | CapSPI}, + &PinDesc{25, []string{"P1_22", "GPIO_25"}, CapNormal}, + &PinDesc{11, []string{"P1_23", "GPIO_11", "SCLK", "SPI0_SCLK"}, CapNormal | CapSPI}, + &PinDesc{8, []string{"P1_24", "GPIO_8", "CE0", "SPI0_CE0_N"}, CapNormal | CapSPI}, + &PinDesc{7, []string{"P1_26", "GPIO_7", "CE1", "SPI0_CE1_N"}, CapNormal | CapSPI}, +} diff --git a/samples/bh1750fvi.go b/samples/bh1750fvi.go index 2ab570e..631281c 100644 --- a/samples/bh1750fvi.go +++ b/samples/bh1750fvi.go @@ -6,17 +6,17 @@ import ( "log" "time" - "github.com/kidoman/embd/i2c" + "github.com/kidoman/embd" "github.com/kidoman/embd/sensor/bh1750fvi" ) func main() { - if err := i2c.Open(); err != nil { + if err := embd.InitI2C(); err != nil { panic(err) } - defer i2c.Close() + defer embd.CloseI2C() - bus := i2c.NewBus(1) + bus := embd.NewI2CBus(1) sensor := bh1750fvi.New(bh1750fvi.High, bus) defer sensor.Close() @@ -24,7 +24,7 @@ func main() { for { lighting, err := sensor.Lighting() if err != nil { - log.Panic(err) + panic(err) } log.Printf("Lighting is %v lx", lighting) diff --git a/samples/bmp085.go b/samples/bmp085.go index 4a3e8b4..29e5c36 100644 --- a/samples/bmp085.go +++ b/samples/bmp085.go @@ -6,17 +6,17 @@ import ( "log" "time" - "github.com/kidoman/embd/i2c" + "github.com/kidoman/embd" "github.com/kidoman/embd/sensor/bmp085" ) func main() { - if err := i2c.Open(); err != nil { + if err := embd.InitI2C(); err != nil { panic(err) } - defer i2c.Close() + defer embd.CloseI2C() - bus := i2c.NewBus(1) + bus := embd.NewI2CBus(1) baro := bmp085.New(bus) defer baro.Close() diff --git a/samples/bmp180.go b/samples/bmp180.go index ea8328a..448deaf 100644 --- a/samples/bmp180.go +++ b/samples/bmp180.go @@ -6,17 +6,17 @@ import ( "log" "time" - "github.com/kidoman/embd/i2c" + "github.com/kidoman/embd" "github.com/kidoman/embd/sensor/bmp180" ) func main() { - if err := i2c.Open(); err != nil { + if err := embd.InitI2C(); err != nil { panic(err) } - defer i2c.Close() + defer embd.CloseI2C() - bus := i2c.NewBus(1) + bus := embd.NewI2CBus(1) baro := bmp180.New(bus) defer baro.Close() diff --git a/samples/gpio.go b/samples/gpio.go index 42087e0..4de86f1 100644 --- a/samples/gpio.go +++ b/samples/gpio.go @@ -5,31 +5,31 @@ package main import ( "time" - "github.com/kidoman/embd/gpio" + "github.com/kidoman/embd" ) func main() { - if err := gpio.Open(); err != nil { + if err := embd.InitGPIO(); err != nil { panic(err) } - defer gpio.Close() + defer embd.CloseGPIO() - led, err := gpio.NewDigitalPin(10) + led, err := embd.NewDigitalPin(10) if err != nil { panic(err) } defer led.Close() - if err := led.SetDirection(gpio.Out); err != nil { + if err := led.SetDirection(embd.Out); err != nil { panic(err) } - if err := led.Write(gpio.High); err != nil { + if err := led.Write(embd.High); err != nil { panic(err) } time.Sleep(1 * time.Second) - if err := led.SetDirection(gpio.In); err != nil { + if err := led.SetDirection(embd.In); err != nil { panic(err) } } diff --git a/samples/gpiodetect.go b/samples/gpiodetect.go index 1d57039..e0c202e 100644 --- a/samples/gpiodetect.go +++ b/samples/gpiodetect.go @@ -5,12 +5,11 @@ package main import ( "time" - "github.com/kidoman/embd/gpio" - "github.com/kidoman/embd/host" + "github.com/kidoman/embd" ) func main() { - h, _, err := host.Detect() + h, _, err := embd.DetectHost() if err != nil { return } @@ -18,35 +17,35 @@ func main() { var pinNo interface{} switch h { - case host.BBB: + case embd.HostBBB: pinNo = "P9_31" - case host.RPi: + case embd.HostRPi: pinNo = 10 default: panic("host not supported (yet :P)") } - if err := gpio.Open(); err != nil { + if err := embd.InitGPIO(); err != nil { panic(err) } - defer gpio.Close() + defer embd.CloseGPIO() - led, err := gpio.NewDigitalPin(pinNo) + led, err := embd.NewDigitalPin(pinNo) if err != nil { panic(err) } defer led.Close() - if err := led.SetDirection(gpio.Out); err != nil { + if err := led.SetDirection(embd.Out); err != nil { panic(err) } - if err := led.Write(gpio.High); err != nil { + if err := led.Write(embd.High); err != nil { panic(err) } time.Sleep(1 * time.Second) - if err := led.SetDirection(gpio.In); err != nil { + if err := led.SetDirection(embd.In); err != nil { panic(err) } } diff --git a/samples/gpiodirect.go b/samples/gpiodirect.go index 4f7622e..0047b7e 100644 --- a/samples/gpiodirect.go +++ b/samples/gpiodirect.go @@ -5,25 +5,25 @@ package main import ( "time" - "github.com/kidoman/embd/gpio" + "github.com/kidoman/embd" ) func main() { - if err := gpio.Open(); err != nil { + if err := embd.InitGPIO(); err != nil { panic(err) } - defer gpio.Close() + defer embd.CloseGPIO() - if err := gpio.SetDirection(10, gpio.Out); err != nil { + if err := embd.SetDirection(10, embd.Out); err != nil { panic(err) } - if err := gpio.DigitalWrite(10, gpio.High); err != nil { + if err := embd.DigitalWrite(10, embd.High); err != nil { panic(err) } time.Sleep(1 * time.Second) - if err := gpio.SetDirection(10, gpio.In); err != nil { + if err := embd.SetDirection(10, embd.In); err != nil { panic(err) } } diff --git a/samples/gpioshort.go b/samples/gpioshort.go index ba7d4c7..f669cbe 100644 --- a/samples/gpioshort.go +++ b/samples/gpioshort.go @@ -2,12 +2,12 @@ package main -import "github.com/kidoman/embd/gpio" +import "github.com/kidoman/embd" func main() { - gpio.Open() - defer gpio.Close() + embd.InitGPIO() + defer embd.CloseGPIO() - gpio.SetDirection(10, gpio.Out) - gpio.DigitalWrite(10, gpio.High) + embd.SetDirection(10, embd.Out) + embd.DigitalWrite(10, embd.High) } diff --git a/samples/l3gd20.go b/samples/l3gd20.go index fe1f8be..be820f3 100644 --- a/samples/l3gd20.go +++ b/samples/l3gd20.go @@ -8,17 +8,17 @@ import ( "os/signal" "time" - "github.com/kidoman/embd/i2c" + "github.com/kidoman/embd" "github.com/kidoman/embd/sensor/l3gd20" ) func main() { - if err := i2c.Open(); err != nil { + if err := embd.InitI2C(); err != nil { panic(err) } - defer i2c.Close() + defer embd.CloseI2C() - bus := i2c.NewBus(1) + bus := embd.NewI2CBus(1) gyro := l3gd20.New(bus, l3gd20.R250DPS) gyro.Debug = true diff --git a/samples/lsm303.go b/samples/lsm303.go index 856e34a..232f3d5 100644 --- a/samples/lsm303.go +++ b/samples/lsm303.go @@ -6,17 +6,17 @@ import ( "log" "time" - "github.com/kidoman/embd/i2c" + "github.com/kidoman/embd" "github.com/kidoman/embd/sensor/lsm303" ) func main() { - if err := i2c.Open(); err != nil { + if err := embd.InitI2C(); err != nil { panic(err) } - defer i2c.Close() + defer embd.CloseI2C() - bus := i2c.NewBus(1) + bus := embd.NewI2CBus(1) mems := lsm303.New(bus) defer mems.Close() diff --git a/samples/mcp4725.go b/samples/mcp4725.go index 5eaef1c..913062d 100644 --- a/samples/mcp4725.go +++ b/samples/mcp4725.go @@ -8,17 +8,17 @@ import ( "os" "os/signal" + "github.com/kidoman/embd" "github.com/kidoman/embd/controller/mcp4725" - "github.com/kidoman/embd/i2c" ) func main() { - if err := i2c.Open(); err != nil { + if err := embd.InitI2C(); err != nil { panic(err) } - defer i2c.Close() + defer embd.CloseI2C() - bus := i2c.NewBus(1) + bus := embd.NewI2CBus(1) dac := mcp4725.New(bus, 0x62) defer dac.Close() diff --git a/samples/pca9685.go b/samples/pca9685.go index d7ef81a..49aabf8 100644 --- a/samples/pca9685.go +++ b/samples/pca9685.go @@ -8,17 +8,17 @@ import ( "os/signal" "time" + "github.com/kidoman/embd" "github.com/kidoman/embd/controller/pca9685" - "github.com/kidoman/embd/i2c" ) func main() { - if err := i2c.Open(); err != nil { + if err := embd.InitI2C(); err != nil { panic(err) } - defer i2c.Close() + defer embd.CloseI2C() - bus := i2c.NewBus(1) + bus := embd.NewI2CBus(1) pca9685 := pca9685.New(bus, 0x41) pca9685.Freq = 1000 diff --git a/samples/servo.go b/samples/servo.go index 6f22279..35124c2 100644 --- a/samples/servo.go +++ b/samples/servo.go @@ -7,18 +7,18 @@ import ( "os/signal" "time" + "github.com/kidoman/embd" "github.com/kidoman/embd/controller/pca9685" - "github.com/kidoman/embd/i2c" "github.com/kidoman/embd/motion/servo" ) func main() { - if err := i2c.Open(); err != nil { + if err := embd.InitI2C(); err != nil { panic(err) } - defer i2c.Close() + defer embd.CloseI2C() - bus := i2c.NewBus(1) + bus := embd.NewI2CBus(1) pwm := pca9685.New(bus, 0x41) pwm.Freq = 50 diff --git a/samples/tmp006.go b/samples/tmp006.go index 3107e36..6aca27d 100644 --- a/samples/tmp006.go +++ b/samples/tmp006.go @@ -7,17 +7,17 @@ import ( "os" "os/signal" - "github.com/kidoman/embd/i2c" + "github.com/kidoman/embd" "github.com/kidoman/embd/sensor/tmp006" ) func main() { - if err := i2c.Open(); err != nil { + if err := embd.InitI2C(); err != nil { panic(err) } - defer i2c.Close() + defer embd.CloseI2C() - bus := i2c.NewBus(1) + bus := embd.NewI2CBus(1) sensor := tmp006.New(bus, 0x40) if status, err := sensor.Present(); err != nil || !status { diff --git a/samples/us020.go b/samples/us020.go index 6c28519..02ca1de 100644 --- a/samples/us020.go +++ b/samples/us020.go @@ -6,21 +6,21 @@ import ( "log" "time" - "github.com/kidoman/embd/gpio" + "github.com/kidoman/embd" "github.com/kidoman/embd/sensor/us020" ) func main() { - if err := gpio.Open(); err != nil { + if err := embd.InitGPIO(); err != nil { panic(err) } - defer gpio.Close() + defer embd.CloseGPIO() - echoPin, err := gpio.NewDigitalPin(10) + echoPin, err := embd.NewDigitalPin(10) if err != nil { panic(err) } - triggerPin, err := gpio.NewDigitalPin(9) + triggerPin, err := embd.NewDigitalPin(9) if err != nil { panic(err) } diff --git a/samples/watersensor.go b/samples/watersensor.go index 4325542..361ff8c 100644 --- a/samples/watersensor.go +++ b/samples/watersensor.go @@ -6,17 +6,17 @@ import ( "time" "github.com/golang/glog" - "github.com/kidoman/embd/gpio" + "github.com/kidoman/embd" "github.com/kidoman/embd/sensor/watersensor" ) func main() { - if err := gpio.Open(); err != nil { + if err := embd.InitGPIO(); err != nil { panic(err) } - defer gpio.Close() + defer embd.CloseGPIO() - pin, err := gpio.NewDigitalPin(7) + pin, err := embd.NewDigitalPin(7) if err != nil { panic(err) } diff --git a/sensor/bh1750fvi/bh1750fvi.go b/sensor/bh1750fvi/bh1750fvi.go index 285eba4..ba17186 100644 --- a/sensor/bh1750fvi/bh1750fvi.go +++ b/sensor/bh1750fvi/bh1750fvi.go @@ -6,7 +6,7 @@ import ( "sync" "time" - "github.com/kidoman/embd/i2c" + "github.com/kidoman/embd" ) //accuracy = sensorValue/actualValue] (min = 0.96, typ = 1.2, max = 1.44 @@ -25,62 +25,42 @@ const ( pollDelay = 150 ) -// A BH1750FVI interface implements access to the sensor. -type BH1750FVI interface { - // Run starts continuous sensor data acquisition loop. - Run() error +type BH1750FVI struct { + Bus embd.I2CBus + Poll int - // Lighting returns the ambient lighting in lx. - Lighting() (lighting float64, err error) - - // Close. - Close() - - // SetPollDelay sets the delay between run of data acquisition loop. - SetPollDelay(delay int) -} - -type bh1750fvi struct { - bus i2c.Bus - mu *sync.RWMutex + mu sync.RWMutex lightingReadings chan float64 quit chan bool i2cAddr byte operationCode byte - - poll int } -// Supports three modes: -// "H" -> High resolution mode (1lx), takes 120ms (recommended). -// "H2" -> High resolution mode 2 (0.5lx), takes 120ms (only use for low light). - -// New creates a new BH1750FVI interface according to the mode passed. -func New(mode string, bus i2c.Bus) BH1750FVI { +func New(mode string, bus embd.I2CBus) *BH1750FVI { switch mode { case High: - return &bh1750fvi{bus: bus, i2cAddr: sensorI2cAddr, operationCode: highResOpCode, mu: new(sync.RWMutex)} + return &BH1750FVI{Bus: bus, i2cAddr: sensorI2cAddr, operationCode: highResOpCode, Poll: pollDelay} case High2: - return &bh1750fvi{bus: bus, i2cAddr: sensorI2cAddr, operationCode: highResMode2OpCode, mu: new(sync.RWMutex)} + return &BH1750FVI{Bus: bus, i2cAddr: sensorI2cAddr, operationCode: highResMode2OpCode, Poll: pollDelay} default: - return &bh1750fvi{bus: bus, i2cAddr: sensorI2cAddr, operationCode: highResOpCode, mu: new(sync.RWMutex)} + return &BH1750FVI{Bus: bus, i2cAddr: sensorI2cAddr, operationCode: highResOpCode, Poll: pollDelay} } } // NewHighMode returns a BH1750FVI inteface on high resolution mode (1lx resolution) -func NewHighMode(bus i2c.Bus) BH1750FVI { +func NewHighMode(bus embd.I2CBus) *BH1750FVI { return New(High, bus) } // NewHighMode returns a BH1750FVI inteface on high resolution mode2 (0.5lx resolution) -func NewHigh2Mode(bus i2c.Bus) BH1750FVI { +func NewHigh2Mode(bus embd.I2CBus) *BH1750FVI { return New(High2, bus) } -func (d *bh1750fvi) measureLighting() (lighting float64, err error) { - err = d.bus.WriteByte(d.i2cAddr, d.operationCode) +func (d *BH1750FVI) measureLighting() (lighting float64, err error) { + err = d.Bus.WriteByte(d.i2cAddr, d.operationCode) if err != nil { log.Print("bh1750fvi: Failed to initialize sensor") return @@ -88,7 +68,7 @@ func (d *bh1750fvi) measureLighting() (lighting float64, err error) { time.Sleep(180 * time.Millisecond) var reading uint16 - if reading, err = d.bus.ReadWordFromReg(d.i2cAddr, defReadReg); err != nil { + if reading, err = d.Bus.ReadWordFromReg(d.i2cAddr, defReadReg); err != nil { return } @@ -97,7 +77,7 @@ func (d *bh1750fvi) measureLighting() (lighting float64, err error) { } // Lighting returns the ambient lighting in lx. -func (d *bh1750fvi) Lighting() (lighting float64, err error) { +func (d *BH1750FVI) Lighting() (lighting float64, err error) { select { case lighting = <-d.lightingReadings: return @@ -107,11 +87,11 @@ func (d *bh1750fvi) Lighting() (lighting float64, err error) { } // Run starts continuous sensor data acquisition loop. -func (d *bh1750fvi) Run() (err error) { +func (d *BH1750FVI) Run() (err error) { go func() { d.quit = make(chan bool) - timer := time.Tick(time.Duration(d.poll) * time.Millisecond) + timer := time.Tick(time.Duration(d.Poll) * time.Millisecond) var lighting float64 @@ -135,14 +115,9 @@ func (d *bh1750fvi) Run() (err error) { } // Close. -func (d *bh1750fvi) Close() { +func (d *BH1750FVI) Close() { if d.quit != nil { d.quit <- true } return } - -// SetPollDelay sets the delay between run of data acquisition loop. -func (d *bh1750fvi) SetPollDelay(delay int) { - d.poll = delay -} diff --git a/sensor/bmp085/bmp085.go b/sensor/bmp085/bmp085.go index a801a5e..5955f54 100644 --- a/sensor/bmp085/bmp085.go +++ b/sensor/bmp085/bmp085.go @@ -8,7 +8,7 @@ import ( "sync" "time" - "github.com/kidoman/embd/i2c" + "github.com/kidoman/embd" ) const ( @@ -38,26 +38,12 @@ const ( pollDelay = 250 ) -// A BMP085 implements access to the Bosch BMP085 sensor. -type BMP085 interface { - // SetPollDelay sets the delay between runs of the data acquisition loop. - SetPollDelay(delay int) +type BMP085 struct { + Bus embd.I2CBus + Poll int - // Temperature returns the current temperature reading. - Temperature() (temp float64, err error) - // Pressure returns the current pressure reading. - Pressure() (pressure int, err error) - // Altitude returns the current altitude reading. - Altitude() (altitude float64, err error) + Debug bool - // Run starts the sensor data acquisition loop. - Run() error - // Close. - Close() -} - -type bmp085 struct { - bus i2c.Bus oss uint ac1, ac2, ac3 int16 @@ -65,29 +51,19 @@ type bmp085 struct { b1, b2, mb, mc, md int16 b5 int32 calibrated bool - cmu *sync.RWMutex + cmu sync.RWMutex - poll int temps chan uint16 pressures chan int32 altitudes chan float64 quit chan struct{} - - debug bool } -// New creates a new BMP085 interface. The bus variable controls -// the I2C bus used to communicate with the device. -func New(bus i2c.Bus) BMP085 { - return &bmp085{bus: bus, cmu: new(sync.RWMutex), poll: pollDelay} +func New(bus embd.I2CBus) *BMP085 { + return &BMP085{Bus: bus, Poll: pollDelay} } -// SetPollDelay sets the delay between runs of the data acquisition loop. -func (d *bmp085) SetPollDelay(delay int) { - d.poll = delay -} - -func (d *bmp085) calibrate() (err error) { +func (d *BMP085) calibrate() (err error) { d.cmu.RLock() if d.calibrated { d.cmu.RUnlock() @@ -100,7 +76,7 @@ func (d *bmp085) calibrate() (err error) { readInt16 := func(reg byte) (value int16, err error) { var v uint16 - if v, err = d.bus.ReadWordFromReg(address, reg); err != nil { + if v, err = d.Bus.ReadWordFromReg(address, reg); err != nil { return } value = int16(v) @@ -109,7 +85,7 @@ func (d *bmp085) calibrate() (err error) { readUInt16 := func(reg byte) (value uint16, err error) { var v uint16 - if v, err = d.bus.ReadWordFromReg(address, reg); err != nil { + if v, err = d.Bus.ReadWordFromReg(address, reg); err != nil { return } value = uint16(v) @@ -163,7 +139,7 @@ func (d *bmp085) calibrate() (err error) { d.calibrated = true - if d.debug { + if d.Debug { log.Print("bmp085: calibration data retrieved") log.Printf("bmp085: param AC1 = %v", d.ac1) log.Printf("bmp085: param AC2 = %v", d.ac2) @@ -181,18 +157,18 @@ func (d *bmp085) calibrate() (err error) { return } -func (d *bmp085) readUncompensatedTemp() (temp uint16, err error) { - if err = d.bus.WriteByteToReg(address, control, readTempCmd); err != nil { +func (d *BMP085) readUncompensatedTemp() (temp uint16, err error) { + if err = d.Bus.WriteByteToReg(address, control, readTempCmd); err != nil { return } time.Sleep(tempReadDelay) - if temp, err = d.bus.ReadWordFromReg(address, tempData); err != nil { + if temp, err = d.Bus.ReadWordFromReg(address, tempData); err != nil { return } return } -func (d *bmp085) calcTemp(utemp uint16) uint16 { +func (d *BMP085) calcTemp(utemp uint16) uint16 { x1 := ((int(utemp) - int(d.ac6)) * int(d.ac5)) >> 15 x2 := (int(d.mc) << 11) / (x1 + int(d.md)) @@ -203,7 +179,7 @@ func (d *bmp085) calcTemp(utemp uint16) uint16 { return uint16((d.b5 + 8) >> 4) } -func (d *bmp085) measureTemp() (temp uint16, err error) { +func (d *BMP085) measureTemp() (temp uint16, err error) { if err = d.calibrate(); err != nil { return } @@ -212,25 +188,25 @@ func (d *bmp085) measureTemp() (temp uint16, err error) { if utemp, err = d.readUncompensatedTemp(); err != nil { return } - if d.debug { + if d.Debug { log.Printf("bcm085: uncompensated temp: %v", utemp) } temp = d.calcTemp(utemp) - if d.debug { + if d.Debug { log.Printf("bcm085: compensated temp %v", temp) } return } // Temperature returns the current temperature reading. -func (d *bmp085) Temperature() (temp float64, err error) { +func (d *BMP085) Temperature() (temp float64, err error) { select { case t := <-d.temps: temp = float64(t) / 10 return default: - if d.debug { + if d.Debug { log.Print("bcm085: no temps available... measuring") } var t uint16 @@ -243,14 +219,14 @@ func (d *bmp085) Temperature() (temp float64, err error) { } } -func (d *bmp085) readUncompensatedPressure() (pressure uint32, err error) { - if err = d.bus.WriteByteToReg(address, control, byte(readPressureCmd+(d.oss<<6))); err != nil { +func (d *BMP085) readUncompensatedPressure() (pressure uint32, err error) { + if err = d.Bus.WriteByteToReg(address, control, byte(readPressureCmd+(d.oss<<6))); err != nil { return } time.Sleep(time.Duration(2+(3<> 15 x2 := (int(d.mc) << 11) / (x1 + int(d.md)) @@ -203,7 +179,7 @@ func (d *bmp180) calcTemp(utemp uint16) uint16 { return uint16((d.b5 + 8) >> 4) } -func (d *bmp180) measureTemp() (temp uint16, err error) { +func (d *BMP180) measureTemp() (temp uint16, err error) { if err = d.calibrate(); err != nil { return } @@ -212,26 +188,26 @@ func (d *bmp180) measureTemp() (temp uint16, err error) { if utemp, err = d.readUncompensatedTemp(); err != nil { return } - if d.debug { - log.Printf("bcm180: uncompensated temp: %v", utemp) + if d.Debug { + log.Printf("bcm085: uncompensated temp: %v", utemp) } temp = d.calcTemp(utemp) - if d.debug { - log.Printf("bcm180: compensated temp %v", temp) + if d.Debug { + log.Printf("bcm085: compensated temp %v", temp) } return } // Temperature returns the current temperature reading. -func (d *bmp180) Temperature() (temp float64, err error) { +func (d *BMP180) Temperature() (temp float64, err error) { select { case t := <-d.temps: temp = float64(t) / 10 return default: - if d.debug { - log.Print("bcm180: no temps available... measuring") + if d.Debug { + log.Print("bcm085: no temps available... measuring") } var t uint16 t, err = d.measureTemp() @@ -243,14 +219,14 @@ func (d *bmp180) Temperature() (temp float64, err error) { } } -func (d *bmp180) readUncompensatedPressure() (pressure uint32, err error) { - if err = d.bus.WriteByteToReg(address, control, byte(readPressureCmd+(d.oss<<6))); err != nil { +func (d *BMP180) readUncompensatedPressure() (pressure uint32, err error) { + if err = d.Bus.WriteByteToReg(address, control, byte(readPressureCmd+(d.oss<<6))); err != nil { return } time.Sleep(time.Duration(2+(3<