mirror of https://github.com/kidoman/embd
Merge c868297e0b
into d3d8c0c5c6
This commit is contained in:
commit
21cd597fdd
|
@ -15,6 +15,7 @@ type Descriptor struct {
|
||||||
I2CDriver func() I2CDriver
|
I2CDriver func() I2CDriver
|
||||||
LEDDriver func() LEDDriver
|
LEDDriver func() LEDDriver
|
||||||
SPIDriver func() SPIDriver
|
SPIDriver func() SPIDriver
|
||||||
|
W1Driver func() W1Driver
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Describer type is a Descriptor provider.
|
// The Describer type is a Descriptor provider.
|
||||||
|
|
|
@ -0,0 +1,188 @@
|
||||||
|
// I²C support.
|
||||||
|
|
||||||
|
package rpi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/kidoman/embd"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
type w1Bus struct {
|
||||||
|
l byte
|
||||||
|
busMap map[string]embd.W1Device
|
||||||
|
Mu sync.Mutex
|
||||||
|
|
||||||
|
initialized bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type w1Device struct {
|
||||||
|
file *os.File
|
||||||
|
addr string
|
||||||
|
initialized bool
|
||||||
|
bus *w1Bus
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewW1Bus(l byte) embd.W1Bus {
|
||||||
|
return &w1Bus{l: l, busMap: make(map[string]embd.W1Device)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *w1Bus) init() error {
|
||||||
|
if b.initialized {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if _, err = os.Stat("/sys/bus/w1"); os.IsNotExist(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(2).Infof("onewire: bus %v initialized", b.l)
|
||||||
|
|
||||||
|
b.initialized = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *w1Device) init() error {
|
||||||
|
if d.initialized {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if d.file, err = os.OpenFile(fmt.Sprintf("/sys/bus/w1/devices/%s/rw", d.addr), os.O_RDWR, os.ModeExclusive); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(2).Infof("onewire: device %s initialized", d.addr)
|
||||||
|
|
||||||
|
d.initialized = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *w1Device) ReadByte() (byte, error) {
|
||||||
|
d.bus.Mu.Lock()
|
||||||
|
defer d.bus.Mu.Unlock()
|
||||||
|
|
||||||
|
if err := d.init(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes := make([]byte, 1)
|
||||||
|
n, _ := d.file.Read(bytes)
|
||||||
|
|
||||||
|
if n != 1 {
|
||||||
|
return 0, fmt.Errorf("onewire: Unexpected number (%v) of bytes read in ReadByte", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *w1Device) WriteByte(value byte) error {
|
||||||
|
d.bus.Mu.Lock()
|
||||||
|
defer d.bus.Mu.Unlock()
|
||||||
|
|
||||||
|
if err := d.init(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := d.file.Write([]byte{value})
|
||||||
|
|
||||||
|
if n != 1 {
|
||||||
|
err = fmt.Errorf("onewire: Unexpected number (%v) of bytes written in WriteByte", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *w1Device) WriteBytes(value []byte) error {
|
||||||
|
d.bus.Mu.Lock()
|
||||||
|
defer d.bus.Mu.Unlock()
|
||||||
|
|
||||||
|
if err := d.init(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range value {
|
||||||
|
n, err := d.file.Write([]byte{value[i]})
|
||||||
|
|
||||||
|
if n != 1 {
|
||||||
|
return fmt.Errorf("onewire: Unexpected number (%v) of bytes written in WriteBytes", n)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *w1Device) ReadBytes(number int) (value []byte, err error) {
|
||||||
|
d.bus.Mu.Lock()
|
||||||
|
defer d.bus.Mu.Unlock()
|
||||||
|
|
||||||
|
if err := d.init(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes := make([]byte, number)
|
||||||
|
n, _ := d.file.Read(bytes)
|
||||||
|
|
||||||
|
if n != number {
|
||||||
|
return nil, fmt.Errorf("onewire: Unexpected number (%v) of bytes read in ReadBytes", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *w1Bus) ListDevices() (devices []string, err error) {
|
||||||
|
dir, err := ioutil.ReadDir("/sys/bus/w1/devices/")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
devs := make([]string, len(dir))
|
||||||
|
|
||||||
|
for index, element := range dir {
|
||||||
|
devs[index] = element.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
return devs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *w1Bus) Open(address string) (device embd.W1Device, err error) {
|
||||||
|
b.Mu.Lock()
|
||||||
|
defer b.Mu.Unlock()
|
||||||
|
|
||||||
|
if d, ok := b.busMap[address]; ok {
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
d := &w1Device{addr: address, bus: b}
|
||||||
|
b.busMap[address] = d
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *w1Bus) Close() error {
|
||||||
|
b.Mu.Lock()
|
||||||
|
defer b.Mu.Unlock()
|
||||||
|
|
||||||
|
for _, b := range b.busMap {
|
||||||
|
b.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *w1Device) Close() error {
|
||||||
|
|
||||||
|
if !d.initialized {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.file.Close()
|
||||||
|
}
|
|
@ -5,6 +5,8 @@
|
||||||
GPIO (digital (rw))
|
GPIO (digital (rw))
|
||||||
I²C
|
I²C
|
||||||
LED
|
LED
|
||||||
|
W1 - make sure that w1-gpio kernel module is loaded. If you wish to use it with sensors directly (e.g. DS18B20 etc)
|
||||||
|
make sure to disable respective kernel modules (e.g. w1-therm) in /etc/modprobe.d/blacklist.conf.
|
||||||
*/
|
*/
|
||||||
package rpi
|
package rpi
|
||||||
|
|
||||||
|
@ -97,6 +99,9 @@ func init() {
|
||||||
SPIDriver: func() embd.SPIDriver {
|
SPIDriver: func() embd.SPIDriver {
|
||||||
return embd.NewSPIDriver(spiDeviceMinor, generic.NewSPIBus, nil)
|
return embd.NewSPIDriver(spiDeviceMinor, generic.NewSPIBus, nil)
|
||||||
},
|
},
|
||||||
|
W1Driver: func() embd.W1Driver {
|
||||||
|
return embd.NewW1Driver(NewW1Bus)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
//OneWire support.
|
||||||
|
|
||||||
|
package embd
|
||||||
|
|
||||||
|
// W1Bus interface is used to interact with the OneWire bus.
|
||||||
|
type W1Bus interface {
|
||||||
|
|
||||||
|
// List devices on the bus
|
||||||
|
ListDevices() (devices []string, err error)
|
||||||
|
|
||||||
|
// Open a device
|
||||||
|
Open(address string) (device W1Device, err error)
|
||||||
|
|
||||||
|
// Close releases the resources associated with the bus.
|
||||||
|
Close() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// W1Device interface is user to interact with the OneWire device.
|
||||||
|
type W1Device interface {
|
||||||
|
// ReadByte reads a byte from the device.
|
||||||
|
ReadByte() (value byte, err error)
|
||||||
|
// ReadByte number of bytes from the device.
|
||||||
|
ReadBytes(number int) (value []byte, err error)
|
||||||
|
// WriteByte writes a byte to the device.
|
||||||
|
WriteByte(value byte) error
|
||||||
|
// WriteBytes writes a slice bytes to the device.
|
||||||
|
WriteBytes(value []byte) error
|
||||||
|
|
||||||
|
// Close releases the resources associated with the device.
|
||||||
|
Close() error
|
||||||
|
}
|
||||||
|
|
||||||
|
// W1Driver interface interacts with the host descriptors to allow us
|
||||||
|
// control of OneWire communication.
|
||||||
|
type W1Driver interface {
|
||||||
|
Bus(l byte) W1Bus
|
||||||
|
|
||||||
|
// Close releases the resources associated with the driver.
|
||||||
|
Close() error
|
||||||
|
}
|
||||||
|
|
||||||
|
var w1DriverInitialized bool
|
||||||
|
var w1DriverInstance W1Driver
|
||||||
|
|
||||||
|
// InitW1 initializes the W1 driver.
|
||||||
|
func InitW1() error {
|
||||||
|
if w1DriverInitialized {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
desc, err := DescribeHost()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if desc.W1Driver == nil {
|
||||||
|
return ErrFeatureNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
|
w1DriverInstance = desc.W1Driver()
|
||||||
|
w1DriverInitialized = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseW1 releases resources associated with the OneWire driver.
|
||||||
|
func CloseW1() error {
|
||||||
|
return w1DriverInstance.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewW1Bus returns a W1Bus.
|
||||||
|
func NewW1Bus(l byte) W1Bus {
|
||||||
|
if err := InitW1(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return w1DriverInstance.Bus(l)
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Generic OneWire driver.
|
||||||
|
|
||||||
|
package embd
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
type w1BusFactory func(byte) W1Bus
|
||||||
|
|
||||||
|
type w1Driver struct {
|
||||||
|
busMap map[byte]W1Bus
|
||||||
|
busMapLock sync.Mutex
|
||||||
|
|
||||||
|
ibf w1BusFactory
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewW1Driver returns a W1Driver interface which allows control
|
||||||
|
// over the OneWire subsystem.
|
||||||
|
func NewW1Driver(ibf w1BusFactory) W1Driver {
|
||||||
|
return &w1Driver{
|
||||||
|
busMap: make(map[byte]W1Bus),
|
||||||
|
ibf: ibf,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *w1Driver) Bus(l byte) W1Bus {
|
||||||
|
i.busMapLock.Lock()
|
||||||
|
defer i.busMapLock.Unlock()
|
||||||
|
|
||||||
|
if b, ok := i.busMap[l]; ok {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
b := i.ibf(l)
|
||||||
|
i.busMap[l] = b
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *w1Driver) Close() error {
|
||||||
|
for _, b := range i.busMap {
|
||||||
|
b.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/kidoman/embd"
|
||||||
|
_ "github.com/kidoman/embd/host/all"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := embd.InitW1(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer embd.CloseW1()
|
||||||
|
|
||||||
|
w1 := embd.NewW1Bus(0)
|
||||||
|
|
||||||
|
devs, err := w1.ListDevices()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dev := range devs {
|
||||||
|
fmt.Printf("OneWire device: %s\n", dev)
|
||||||
|
}
|
||||||
|
|
||||||
|
w1d, err := w1.Open("28-011572120bff")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%v\n", w1d)
|
||||||
|
|
||||||
|
err = w1d.WriteByte(0x44)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for ret, err := w1d.ReadByte(); ret == 0 && err != nil; {}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = w1d.WriteByte(0xBE)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := w1d.ReadBytes(9)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("res: ")
|
||||||
|
for _, val := range res {
|
||||||
|
fmt.Printf("0x%02X ", val)
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
var temp float64 = float64(float64(res[1]) * 256. + float64(res[0])) / 16.
|
||||||
|
fmt.Printf("%f\n", temp)
|
||||||
|
|
||||||
|
fmt.Println("Done")
|
||||||
|
}
|
Loading…
Reference in New Issue