From 59958d7dfc6093df5a288fcb483a0767b4a26825 Mon Sep 17 00:00:00 2001 From: kunalpowar Date: Sat, 3 May 2014 21:35:09 +0530 Subject: [PATCH] mcp3008: added package and samples for mcp3008 10-bit 8-channel adc --- convertors/mcp3008/mcp3008.go | 52 +++++++++++++++++++++++++++++++++++ host/bbb/bbb.go | 5 ++++ host/generic/spibus.go | 28 ++++++++++++++++--- samples/.gitignore | 2 ++ samples/mcp3008.go | 33 ++++++++++++++++++++++ samples/spimcp3008.go | 46 +++++++++++++++++++++++++++++++ spidriver.go | 1 + 7 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 convertors/mcp3008/mcp3008.go create mode 100644 samples/mcp3008.go create mode 100644 samples/spimcp3008.go diff --git a/convertors/mcp3008/mcp3008.go b/convertors/mcp3008/mcp3008.go new file mode 100644 index 0000000..2684c4c --- /dev/null +++ b/convertors/mcp3008/mcp3008.go @@ -0,0 +1,52 @@ +package mcp3008 + +import ( + "github.com/golang/glog" + "github.com/kidoman/embd" + + _ "github.com/kidoman/embd/host/all" +) + +type mcp3008 struct { + mode int + + bus embd.SPIBus +} + +const ( + SingleMode = int(1) + DifferenceMode = int(0) +) + +func New(mode, spiChan, speed int) (*mcp3008, error) { + if err := embd.InitSPI(); err != nil { + return nil, err + } + glog.V(3).Infof("mcp3008: getting spiBus with mode: %v, channel: %v, speed: %v", mode, spiChan, speed) + spiBus := embd.NewSPIBus(embd.SpiMode0, byte(spiChan), speed, 0, 0) + return &mcp3008{mode, spiBus}, nil +} + +func (m *mcp3008) AnalogValueAt(chanNum int) (int, error) { + data := make([]uint8, 3) + data[0] = 1 + data[1] = uint8(m.mode)<<7 | uint8(chanNum)<<4 + data[2] = 0 + + if err := m.bus.TransferAndRecieveData(data); err != nil { + return 0, err + } + + return int(uint16(data[1]&0x03)<<8 | uint16(data[2])), nil +} + +func (m *mcp3008) Close() error { + glog.V(2).Infoln("mcp3008: performing cleanup") + if err := m.bus.Close(); err != nil { + return err + } + if err := embd.CloseSPI(); err != nil { + return err + } + return nil +} diff --git a/host/bbb/bbb.go b/host/bbb/bbb.go index 2088b69..118cf7d 100644 --- a/host/bbb/bbb.go +++ b/host/bbb/bbb.go @@ -15,6 +15,8 @@ import ( "os" "strings" + "github.com/golang/glog" + "github.com/kidoman/embd" "github.com/kidoman/embd/host/generic" ) @@ -97,6 +99,7 @@ var ledMap = embd.LEDMap{ var spiDeviceMinor = byte(1) func ensureFeatureEnabled(id string) error { + glog.V(3).Infof("bbb: enabling feature %v", id) pattern := "/sys/devices/bone_capemgr.*/slots" file, err := embd.FindFirstMatchingFile(pattern) if err != nil { @@ -108,6 +111,7 @@ func ensureFeatureEnabled(id string) error { } str := string(bytes) if strings.Contains(str, id) { + glog.V(3).Infof("bbb: feature %v already enabled", id) return nil } slots, err := os.OpenFile(file, os.O_WRONLY, os.ModeExclusive) @@ -115,6 +119,7 @@ func ensureFeatureEnabled(id string) error { return err } defer slots.Close() + glog.V(3).Infof("bbb: writing %v to slots file", id) _, err = slots.WriteString(id) return err } diff --git a/host/generic/spibus.go b/host/generic/spibus.go index 661ec3a..9d2d114 100644 --- a/host/generic/spibus.go +++ b/host/generic/spibus.go @@ -76,6 +76,10 @@ func NewSPIBus(spiDevMinor, mode, channel byte, speed, bpw, delay int, shouldIni } func (b *spiBus) init() error { + if b.initialized { + return nil + } + if b.shouldInitialize { if err := b.initializer(); err != nil { return err @@ -83,14 +87,11 @@ func (b *spiBus) init() error { b.shouldInitialize = false } - if b.initialized { - return nil - } - var err error if b.file, err = os.OpenFile(fmt.Sprintf("/dev/spidev%v.%v", b.spiDevMinor, b.channel), os.O_RDWR, os.ModeExclusive); err != nil { return err } + glog.V(3).Infof("spi: sucessfully opened file /dev/spidev%v.%v", b.spiDevMinor, b.channel) err = b.setMode() if err != nil { @@ -112,6 +113,7 @@ func (b *spiBus) init() error { b.setDelay() glog.V(2).Infof("spi: bus %v initialized", b.channel) + glog.V(3).Infof("spi: bus %v initialized with spiIocTransfer as %v", b.channel, b.spiTransferData) b.initialized = true return nil @@ -187,6 +189,10 @@ func (b *spiBus) setDelay() { } func (b *spiBus) TransferAndRecieveData(dataBuffer []uint8) error { + if err := b.init(); err != nil { + return err + } + len := len(dataBuffer) dataCarrier := b.spiTransferData @@ -194,16 +200,22 @@ func (b *spiBus) TransferAndRecieveData(dataBuffer []uint8) error { dataCarrier.txBuf = uint64(uintptr(unsafe.Pointer(&dataBuffer[0]))) dataCarrier.rxBuf = uint64(uintptr(unsafe.Pointer(&dataBuffer[0]))) + glog.V(3).Infof("spi: sending dataBuffer %v with carrier %v", dataBuffer, dataCarrier) _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, b.file.Fd(), uintptr(spiIocMessageN(1)), uintptr(unsafe.Pointer(&dataCarrier))) if errno != 0 { err := syscall.Errno(errno) glog.V(3).Infof("spi: failed to read due to %v", err.Error()) return err } + glog.V(3).Infof("spi: read into dataBuffer %v", dataBuffer) return nil } func (b *spiBus) ReceiveData(len int) ([]uint8, error) { + if err := b.init(); err != nil { + return nil, err + } + data := make([]uint8, len) var err error err = b.TransferAndRecieveData(data) @@ -214,6 +226,10 @@ func (b *spiBus) ReceiveData(len int) ([]uint8, error) { } func (b *spiBus) TransferAndReceiveByte(data byte) (byte, error) { + if err := b.init(); err != nil { + return 0, err + } + d := make([]uint8, 1) d[0] = uint8(data) err := b.TransferAndRecieveData(d) @@ -224,6 +240,10 @@ func (b *spiBus) TransferAndReceiveByte(data byte) (byte, error) { } func (b *spiBus) ReceiveByte() (byte, error) { + if err := b.init(); err != nil { + return 0, err + } + d := make([]uint8, 1) err := b.TransferAndRecieveData(d) if err != nil { diff --git a/samples/.gitignore b/samples/.gitignore index f48626d..af9b180 100644 --- a/samples/.gitignore +++ b/samples/.gitignore @@ -24,3 +24,5 @@ universalblinker us020 watersensor spi +mcp3008 +spimcp3008 diff --git a/samples/mcp3008.go b/samples/mcp3008.go new file mode 100644 index 0000000..252f2d1 --- /dev/null +++ b/samples/mcp3008.go @@ -0,0 +1,33 @@ +// +build ignore + +package main + +import ( + "flag" + "fmt" + "time" + + "github.com/kidoman/embd/convertors/mcp3008" +) + +func main() { + flag.Parse() + fmt.Println("This is a sample code for mcp3008 10bit 8 channel ADC") + + adc, err := mcp3008.New(mcp3008.SingleMode, 0, 1000000) + if err != nil { + panic(err) + } + defer adc.Close() + + for i := 0; i < 20; i++ { + time.Sleep(1 * time.Second) + val, err := adc.AnalogValueAt(0) + if err != nil { + panic(err) + } + + fmt.Printf("Analog value is: %v\n", val) + } + +} diff --git a/samples/spimcp3008.go b/samples/spimcp3008.go new file mode 100644 index 0000000..12b60d8 --- /dev/null +++ b/samples/spimcp3008.go @@ -0,0 +1,46 @@ +package main + +import ( + "flag" + "fmt" + "time" + + "github.com/kidoman/embd" + _ "github.com/kidoman/embd/host/all" +) + +func main() { + flag.Parse() + if err := embd.InitSPI(); err != nil { + panic(err) + } + + bus := embd.NewSPIBus(embd.SpiMode0, 0, 1000000, 8, 0) + + defer clean(bus) + + for i := 0; i < 30; i++ { + time.Sleep(1 * time.Second) + val, _ := getSensorValue(bus) + fmt.Printf("value is: %v\n", val) + } + +} + +func clean(bus embd.SPIBus) { + bus.Close() + embd.CloseSPI() +} + +func getSensorValue(bus embd.SPIBus) (uint16, error) { + data := make([]uint8, 3) + data[0] = 1 + data[1] = 128 + data[2] = 0 + var err error + err = bus.TransferAndRecieveData(data) + if err != nil { + return uint16(0), err + } + return uint16(data[1]&0x03)<<8 | uint16(data[2]), nil +} diff --git a/spidriver.go b/spidriver.go index f12c86c..bd7ec9d 100644 --- a/spidriver.go +++ b/spidriver.go @@ -29,6 +29,7 @@ func (s *spiDriver) Bus(mode, channel byte, speed, bpw, delay int) SPIBus { defer s.busMapLock.Unlock() b := s.sbf(s.spiDevMinor, mode, channel, speed, bpw, delay, s.shouldInitialize, s.initializer) + s.busMap = make(map[byte]SPIBus) s.busMap[channel] = b return b }