Merge pull request #69 from kidoman/update

Add support for CHIP; merge piled-up PRs
This commit is contained in:
Thorsten von Eicken 2016-09-25 11:48:02 -07:00 committed by GitHub
commit adc3d47305
21 changed files with 352 additions and 122 deletions

View File

@ -5,11 +5,10 @@ branches:
- go-rpi
go:
- 1.2.2
- 1.3.3
- 1.4
- tip
- 1.6
- 1.7
script:
- go test -bench=. -v ./... | grep -v 'no test files' ; test ${PIPESTATUS[0]} -eq 0
- cd samples; find . -name "*.go" -print0 | xargs -0 -n1 go build
- cd ../embd; go build .

View File

@ -1,8 +1,17 @@
Karan Misra <kidoman@gmail.com>
adeschamps <anthony.j.deschamps@gmail.com>
alsm <asm@rndm.io>
Al S-M <asm@rndm.io>
Ben Delarre <ben@delarre.net>
Ben Schwartz <benschw@gmail.com>
Gavin Cabbage <gavincabbage@gmail.com>
gotang <gotang@foxmail.com>
Kashyap Kopparam <kashyapkopparam@gmail.com>
Kunal Powar <kunalpowar1203@gmail.com>
Marco P. Monteiro <marco_monteiro@sv.comcast.com>
Matthew Dale <matthew@matthewrdale.com>
Nikesh Vora <nikesh.voratp@gmail.com>
SjB <steve@sagacity.ca>
Steve Beaulac <steve@beaulac.me>
Al S-M <asm@rndm.io>
Ben Delarre <ben@delarre.net>
Thorsten von Eicken <tve@rightscale.com>
wiless <wiless.bytes@gmail.com>
Wu Jiang <wu@morediff.info>

View File

@ -2,9 +2,24 @@
**embd** is a hardware abstraction layer (HAL) for embedded systems.
It allows you to start your hardware hack on easily available hobby boards (like the Raspberry Pi, BeagleBone Black, etc.) by giving you staight forward access to the board's capabilities as well as a plethora of **sensors** (like accelerometers, gyroscopes, thermometers, etc.) and **controllers** (PWM generators, digital-to-analog convertors) for which we have written drivers. And when things get serious, you dont have to throw away the code. You carry forward the effort onto more custom designed boards where the HAL abstraction of EMBD will save you precious time.
It allows you to start your hardware hack on easily available hobby boards
(like the Raspberry Pi, BeagleBone Black, C.H.I.P., etc.) by giving you
straight-forward access to the board's capabilities as well as a plethora of
**sensors** (like accelerometers, gyroscopes, thermometers, etc.) and
**controllers** (PWM generators, digital-to-analog convertors) for
which it includes drivers. If you move to custom designed boards
you have to throw away your code: you carry forward the effort
where the HAL abstraction of EMBD will save you precious time.
Development supported and sponsored by [**SoStronk**](https://www.sostronk.com) and [**ThoughtWorks**](http://www.thoughtworks.com/)
The overall strategy used in embd is to use Linux device drivers to access gpio pins,
SPI and I2C buses, as well as interrupts. This makes it easy to port from one platform
to another and it enables kernel code to handle the devices as efficiently as possible.
What embd then adds is first a Golang library interface on top of the various Linux
devices and then another layer of user-level drivers for specific sensors and controllers
that are connected to gpio pins or one of the buses.
Development supported and sponsored by [**SoStronk**](https://www.sostronk.com) and
[**ThoughtWorks**](http://www.thoughtworks.com/).
Also, you might be interested in: [Why Golang?](https://github.com/kidoman/embd/wiki/Why-Go)
@ -12,7 +27,9 @@ Also, you might be interested in: [Why Golang?](https://github.com/kidoman/embd/
## Getting Started
After installing Go* and setting up your [GOPATH](http://golang.org/doc/code.html#GOPATH), create your first .go file. We'll call it ```simpleblinker.go```.
Install Go version 1.6 or later to make compiling for ARM easy.
The set up your [GOPATH](http://golang.org/doc/code.html#GOPATH),
and create your first .go file. We'll call it `simpleblinker.go`.
```go
package main
@ -32,11 +49,11 @@ func main() {
}
```
Then install the EMBD package (go1.2 and greater is required):
Then install the EMBD package:
$ go get github.com/kidoman/embd
Build the binary*:
Build the binary for linux/ARM:
$ export GOOS=linux
$ export GOARCH=arm
@ -46,7 +63,7 @@ Copy the cross-compiled binary to your RaspberryPi*:
$ scp simpleblinker pi@192.168.2.2:~
Then run the program with ```sudo```*:
Then on the rPi run the program with ```sudo```*:
$ sudo ./simpleblinker
@ -54,25 +71,21 @@ Then run the program with ```sudo```*:
**<nowiki>*</nowiki> Notes**
* Please install the cross compilers. Mac users: ```brew install go --cross-compile-common```. [goxc](https://github.com/laher/goxc) can be a big help as well
* We are instructing the ```go``` compiler to create a binary which will run on the RaspberryPi processor
* Assuming your RaspberryPi has an IP address of ```192.168.2.2```. Substitute as necessary
* ```sudo``` (root) permission is required as we are controlling the hardware by writing to special files
* This sample program is optimized for brevity and does not clean up after itself. Click here to see the [full version](https://github.com/kidoman/embd/blob/master/samples/fullblinker.go)
* `sudo` (root) permission is required as we are controlling the hardware by writing to special files
* This sample program is optimized for brevity and does not clean up after itself. Click here to
see the [full version](https://github.com/kidoman/embd/blob/master/samples/fullblinker.go)
## Getting Help
Join the [mailing list](https://groups.google.com/forum/#!forum/go-embd)
Join the [slack channel](https://gophers.slack.com/archives/embd)
## Platforms Supported
* [RaspberryPi](http://www.raspberrypi.org/) (including [A+](http://www.raspberrypi.org/products/model-a-plus/) and [B+](http://www.raspberrypi.org/products/model-b-plus/))
* [RaspberryPi 2](http://www.raspberrypi.org/)
* [NextThing C.H.I.P](https://www.nextthing.co/pages/chip)
* [BeagleBone Black](http://beagleboard.org/Products/BeagleBone%20Black)
* [Intel Edison](http://www.intel.com/content/www/us/en/do-it-yourself/galileo-maker-quark-board.html) **coming soon**
* [Radxa](http://radxa.com/) **coming soon**
* [Cubietruck](http://www.cubietruck.com/) **coming soon**
* Bring Your Own **coming soon**
## The command line tool
@ -80,8 +93,6 @@ Join the [mailing list](https://groups.google.com/forum/#!forum/go-embd)
will install a command line utility ```embd``` which will allow you to quickly get started with prototyping. The binary should be available in your ```$GOPATH/bin```. However, to be able to run this on a ARM based device, you will need to build it with ```GOOS=linux``` and ```GOARCH=arm``` environment variables set.
But, since I am feeling so generous, a prebuilt/tested version is available for direct download and deployment [here](https://dl.dropboxusercontent.com/u/6727135/Binaries/embd/linux-arm/embd).
For example, if you run ```embd detect``` on a **BeagleBone Black**:
root@beaglebone:~# embd detect
@ -214,17 +225,11 @@ platforms.
## Sensors Supported
* **TMP006** Thermopile sensor [Documentation](http://godoc.org/github.com/kidoman/embd/sensor/tmp006), [Datasheet](http://www.adafruit.com/datasheets/tmp006.pdf), [Userguide](http://www.adafruit.com/datasheets/tmp006ug.pdf)
* **BMP085** Barometric pressure sensor [Documentation](http://godoc.org/github.com/kidoman/embd/sensor/bmp085), [Datasheet](https://www.sparkfun.com/datasheets/Components/General/BST-BMP085-DS000-05.pdf)
* **BMP180** Barometric pressure sensor [Documentation](http://godoc.org/github.com/kidoman/embd/sensor/bmp180), [Datasheet](http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf)
* **LSM303** Accelerometer and magnetometer [Documentation](http://godoc.org/github.com/kidoman/embd/sensor/lsm303), [Datasheet](https://www.sparkfun.com/datasheets/Sensors/Magneto/LSM303%20Datasheet.pdf)
* **L3GD20** Gyroscope [Documentation](http://godoc.org/github.com/kidoman/embd/sensor/l3gd20), [Datasheet](http://www.adafruit.com/datasheets/L3GD20.pdf)
* **US020** Ultrasonic proximity sensor [Documentation](http://godoc.org/github.com/kidoman/embd/sensor/us020), [Product Page](http://www.digibay.in/sensor/object-detection-and-proximity?product_id=239)
* **BH1750FVI** Luminosity sensor [Documentation](http://godoc.org/github.com/kidoman/embd/sensor/bh1750fvi), [Datasheet](http://www.elechouse.com/elechouse/images/product/Digital%20light%20Sensor/bh1750fvi-e.pdf)
## Interfaces
@ -234,9 +239,7 @@ platforms.
## Controllers
* **PCA9685** 16-channel, 12-bit PWM Controller with I2C protocol [Documentation](http://godoc.org/github.com/kidoman/embd/controller/pca9685), [Datasheet](http://www.adafruit.com/datasheets/PCA9685.pdf), [Product Page](http://www.adafruit.com/products/815)
* **MCP4725** 12-bit DAC [Documentation](http://godoc.org/github.com/kidoman/embd/controller/mcp4725), [Datasheet](http://www.adafruit.com/datasheets/mcp4725.pdf), [Product Page](http://www.adafruit.com/products/935)
* **ServoBlaster** RPi PWM/PCM based PWM controller [Documentation](http://godoc.org/github.com/kidoman/embd/controller/servoblaster), [Product Page](https://github.com/richardghirst/PiBits/tree/master/ServoBlaster)
## Convertors
@ -245,9 +248,11 @@ platforms.
## Contributing
We look forward to your pull requests, but contributions which abide by the [guidelines](https://github.com/kidoman/embd/blob/master/CONTRIBUTING.md) will get a free beer!
File an [issue](https://github.com/kidoman/embd/issues), open a [pull request](https://github.com/kidoman/embd/pulls). We are waiting.
[Pull requests](https://github.com/kidoman/embd/pulls) that follow the
[guidelines](https://github.com/kidoman/embd/blob/master/CONTRIBUTING.md) are very appreciated.
If you find a problem but are not up to coding a fix please file an
[issue](https://github.com/kidoman/embd/issues).
Thank you!
## About

2
controller/doc.go Normal file
View File

@ -0,0 +1,2 @@
// Package controller is a container for the various device controllers supported by EMBD.
package controller

View File

@ -131,6 +131,7 @@ type mockI2CBus struct {
closed bool
}
func (bus *mockI2CBus) ReadBytes(addr byte, num int) ([]byte, error) { return []byte{0x00}, nil }
func (bus *mockI2CBus) ReadByte(addr byte) (byte, error) { return 0x00, nil }
func (bus *mockI2CBus) WriteBytes(addr byte, value []byte) error { return nil }
func (bus *mockI2CBus) ReadFromReg(addr, reg byte, value []byte) error { return nil }

View File

@ -31,6 +31,9 @@ const (
// HostRadxa represents the Radxa board.
HostRadxa = "Radxa"
// HostCHIP represents the NextThing C.H.I.P.
HostCHIP = "CHIP"
)
func execOutput(name string, arg ...string) (output string, err error) {
@ -92,7 +95,7 @@ func cpuInfo() (model, hardware string, revision int, err error) {
}
revision = int(rev)
case strings.HasPrefix(fields[0], "Hardware"):
hardware = fields[1]
hardware = strings.TrimSpace(fields[1])
case strings.HasPrefix(fields[0], "model name"):
model = fields[1]
}
@ -108,7 +111,9 @@ func DetectHost() (host Host, rev int, err error) {
}
if major < 3 || (major == 3 && minor < 8) {
return HostNull, 0, fmt.Errorf("embd: linux kernel versions lower than 3.8 are not supported. you have %v.%v.%v", major, minor, patch)
return HostNull, 0, fmt.Errorf(
"embd: linux kernel versions lower than 3.8 are not supported, "+
"you have %v.%v.%v", major, minor, patch)
}
model, hardware, rev, err := cpuInfo()
@ -121,6 +126,13 @@ func DetectHost() (host Host, rev int, err error) {
return HostBBB, rev, nil
case strings.Contains(hardware, "BCM2708") || strings.Contains(hardware, "BCM2709"):
return HostRPi, rev, nil
case hardware == "Allwinner sun4i/sun5i Families":
if major < 4 || (major == 4 && minor < 4) {
return HostNull, 0, fmt.Errorf(
"embd: linux kernel version 4.4+ required, you have %v.%v",
major, minor)
}
return HostCHIP, rev, nil
default:
return HostNull, 0, fmt.Errorf(`embd: your host "%v:%v" is not supported at this moment. request support at https://github.com/kidoman/embd/issues`, host, model)
}

169
doc.go
View File

@ -1,88 +1,119 @@
/*
Package embd provides a hardware abstraction layer for doing embedded programming
on supported platforms like the Raspberry Pi and BeagleBone Black. Most of the examples below
will work without change (i.e. the same binary) on all supported platforms. How cool is that?
Package embd provides a hardware abstraction layer for doing embedded programming
on supported platforms like the Raspberry Pi, BeagleBone Black and CHIP. Most of the examples below
will work without change (i.e. the same binary) on all supported platforms.
Although samples are all present in the samples folder, we will show a few choice examples here.
== Overall structure
Use the LED driver to toggle LEDs on the BBB:
It's best to think of the top-level embd package as a switchboard that doesn't implement anything
on its own but rather relies on sub-packages for hosts drivers and devices and stitches them
together. The exports in the top-level package serve a number of different purposes,
which can be confusing at first:
- it defines a number of driver interfaces, such as the GPIODriver, this is the interface that
the driver for each specific platform must implement and is not something of concern to the
typical user.
- it defines the main low-level hardware interface types: analog pins, digital pins,
interrupt pins, I2Cbuses, SPI buses, PWM pins and LEDs. Each type has a New function to
instantiate one of these pins or buses.
- it defines a number of InitXXX functions that initialize the various drivers, however, these
are called by the coresponding NewXXX functions, so can be ignored.
- it defines a number of top-level convenience functions, such as DigitalWrite, that can be
called as 1-liners instead of first instantiating a DigitalPin and then writing to it
import "github.com/kidoman/embd"
...
embd.InitLED()
defer embd.CloseLED()
...
led, err := embd.NewLED("USR3")
...
led.Toggle()
To get started a host driver needs to be registered with the top-level embd package. This is
most easily accomplished by doing an "underscore import" on of the sub-packages of embd/host,
e.g., `import _ "github.com/kidoman/embd/host/chip"`. An `Init()` function in the host driver
registers all the individual drivers with embd.
Even shorter while prototyping:
After getting the host driver the next step might be to instantiate a GPIO pin using
`NewDigitalPin` or an I2CBus using `NewI2CBus`. Such a pin or bus can be used directly but
often it is passed into the initializer of a sensor, controller or other user-level driver
which provides a high-level interface to some device. For example, the New function
for the BMP180 type in the `embd/sensor/bmp180` package takes an I2CBus as argument, which
it will use to reach the sensor.
import "github.com/kidoman/embd"
...
embd.InitLED()
defer embd.CloseLED()
...
embd.ToggleLED(3)
== Samples
BBB + PWM:
This section shows a few choice samples, more are available in the samples folder.
import "github.com/kidoman/embd"
...
embd.InitGPIO()
defer embd.CloseGPIO()
...
pwm, _ := embd.NewPWMPin("P9_14")
defer pwm.Close()
...
pwm.SetDuty(1000)
Use the LED driver to toggle LEDs on the BBB:
Control GPIO pins on the RaspberryPi / BeagleBone Black:
import "github.com/kidoman/embd"
...
embd.InitLED()
defer embd.CloseLED()
...
led, err := embd.NewLED("USR3")
...
led.Toggle()
import "github.com/kidoman/embd"
...
embd.InitGPIO()
defer embd.CloseGPIO()
...
embd.SetDirection(10, embd.Out)
embd.DigitalWrite(10, embd.High)
Even shorter while prototyping:
Could also do:
import "github.com/kidoman/embd"
...
embd.InitLED()
defer embd.CloseLED()
...
embd.ToggleLED(3)
import "github.com/kidoman/embd"
...
embd.InitGPIO()
defer embd.CloseGPIO()
...
pin, err := embd.NewDigitalPin(10)
...
pin.SetDirection(embd.Out)
pin.Write(embd.High)
BBB + PWM:
Or read data from the Bosch BMP085 barometric sensor:
import "github.com/kidoman/embd"
...
embd.InitGPIO()
defer embd.CloseGPIO()
...
pwm, _ := embd.NewPWMPin("P9_14")
defer pwm.Close()
...
pwm.SetDuty(1000)
import "github.com/kidoman/embd"
import "github.com/kidoman/embd/sensor/bmp085"
...
bus := embd.NewI2CBus(1)
...
baro := bmp085.New(bus)
...
temp, err := baro.Temperature()
altitude, err := baro.Altitude()
Control GPIO pins on the RaspberryPi / BeagleBone Black:
Even find out the heading from the LSM303 magnetometer:
import "github.com/kidoman/embd"
...
embd.InitGPIO()
defer embd.CloseGPIO()
...
embd.SetDirection(10, embd.Out)
embd.DigitalWrite(10, embd.High)
import "github.com/kidoman/embd"
import "github.com/kidoman/embd/sensor/lsm303"
...
bus := embd.NewI2CBus(1)
...
mag := lsm303.New(bus)
...
heading, err := mag.Heading()
Could also do:
The above two examples depend on I2C and therefore will work without change on almost all
platforms.
import "github.com/kidoman/embd"
...
embd.InitGPIO()
defer embd.CloseGPIO()
...
pin, err := embd.NewDigitalPin(10)
...
pin.SetDirection(embd.Out)
pin.Write(embd.High)
Or read data from the Bosch BMP085 barometric sensor:
import "github.com/kidoman/embd"
import "github.com/kidoman/embd/sensor/bmp085"
...
bus := embd.NewI2CBus(1)
...
baro := bmp085.New(bus)
...
temp, err := baro.Temperature()
altitude, err := baro.Altitude()
Even find out the heading from the LSM303 magnetometer:
import "github.com/kidoman/embd"
import "github.com/kidoman/embd/sensor/lsm303"
...
bus := embd.NewI2CBus(1)
...
mag := lsm303.New(bus)
...
heading, err := mag.Heading()
The above two examples depend on I2C and therefore will work without change on almost all
platforms.
*/
package embd

View File

@ -33,7 +33,11 @@ const (
EdgeBoth Edge = "both"
)
// InterruptPin implements access to a Interruptable capable GPIO pin.
// InterruptPin implements access to an interrupt capable GPIO pin.
// The basic capability provided is to watch for a transition on the pin and
// generate a callback to a handler when a transition occurs.
// On Linux the underlying implementation generally uses epoll to receive the
// interrupts at user-level.
type InterruptPin interface {
// Start watching this pin for interrupt

View File

@ -95,7 +95,7 @@ var ledMap = embd.LEDMap{
"beaglebone:green:usr3": []string{"3", "USR3", "usr3"},
}
var spiDeviceMinor byte = 1
var spiDeviceMinor int = 1
func ensureFeatureEnabled(id string) error {
glog.V(3).Infof("bbb: enabling feature %v", id)

34
host/chip/README.md Normal file
View File

@ -0,0 +1,34 @@
# Using embd on CHIP
The CHIP drivers support gpio, I2C, SPI, and pin interrupts. Not supported are PWM or LED.
The names of the pins on chip have multiple aliases. The official CHIP pin names are supported,
for example XIO-P1 or LCD-D2 and the pin number are also supported, such as U14-14 (same as XIO-P1)
or U13-17. Some of the alternate function names are also supported, like "SPI2_MOSI", and the
linux 4.4 kernel gpio pin numbers as well, e.g., 1017 for XIO-P1. Finally, the official GPIO pins
(XIO-P0 thru XIO-P7) can be addressed as gpio0-gpio7.
A simple demo to blink an LED connected with a small resistor between XIO-P6 and 3.3V is
```
package main
import (
"time"
"github.com/kidoman/embd"
_ "github.com/kidoman/embd/host/chip"
)
func main() {
embd.InitGPIO()
defer embd.CloseGPIO()
embd.SetDirection("gpio6", embd.Out)
on := 0
for {
embd.DigitalWrite("gpio6", on)
on = 1 - on
time.Sleep(250 * time.Millisecond)
}
}
```
Run it as root: `sudo ./blinky`

99
host/chip/chip.go Normal file
View File

@ -0,0 +1,99 @@
// Copyright 2016 by Thorsten von Eicken, see LICENSE file
// Package chip provides NextThing C.H.I.P. support.
// References:
// http://docs.getchip.com/chip.html#chip-hardware
// http://www.chip-community.org/index.php/Hardware_Information
//
// The following features are supported on Linux kernel 4.4+
// GPIO (digital (rw))
// I²C
// SPI
// Could add LED support by following https://bbs.nextthing.co/t/pwr-and-stat-leds/748/5
package chip
import (
"github.com/kidoman/embd"
"github.com/kidoman/embd/host/generic"
)
var spiDeviceMinor = 32766
var chipPins = embd.PinMap{
// official GPIO pins (U14 connector) using the pcf8574a
&embd.PinDesc{"XIO-P0", []string{"1016", "0", "U14-13", "gpio0"}, embd.CapDigital, 1016, 0},
&embd.PinDesc{"XIO-P1", []string{"1017", "1", "U14-14", "gpio1"}, embd.CapDigital, 1017, 0},
&embd.PinDesc{"XIO-P2", []string{"1018", "2", "U14-15", "gpio2"}, embd.CapDigital, 1018, 0},
&embd.PinDesc{"XIO-P3", []string{"1019", "3", "U14-16", "gpio3"}, embd.CapDigital, 1019, 0},
&embd.PinDesc{"XIO-P4", []string{"1020", "4", "U14-17", "gpio4"}, embd.CapDigital, 1020, 0},
&embd.PinDesc{"XIO-P5", []string{"1021", "5", "U14-18", "gpio5"}, embd.CapDigital, 1021, 0},
&embd.PinDesc{"XIO-P6", []string{"1022", "6", "U14-19", "gpio6"}, embd.CapDigital, 1022, 0},
&embd.PinDesc{"XIO-P7", []string{"1023", "7", "U14-20", "gpio7"}, embd.CapDigital, 1023, 0},
// pins usable on the U13 connector
&embd.PinDesc{"TWI1-SDA", []string{"48", "U13-9", "I2C0_SDA"}, embd.CapDigital | embd.CapI2C, 48, 0},
&embd.PinDesc{"TWI1-SCK", []string{"47", "U13-11", "I2C0_SCK"}, embd.CapDigital | embd.CapI2C, 47, 0},
&embd.PinDesc{"PWM0", []string{"34", "U13-18"}, embd.CapDigital | embd.CapPWM, 34, 0},
&embd.PinDesc{"LCD-D2", []string{"98", "U13-17"}, embd.CapDigital, 98, 0},
&embd.PinDesc{"LCD-D3", []string{"99", "U13-20"}, embd.CapDigital, 99, 0},
&embd.PinDesc{"LCD-D4", []string{"100", "U13-19"}, embd.CapDigital, 100, 0},
&embd.PinDesc{"LCD-D5", []string{"101", "U13-22"}, embd.CapDigital, 101, 0},
&embd.PinDesc{"LCD-D6", []string{"102", "U13-21"}, embd.CapDigital, 102, 0},
&embd.PinDesc{"LCD-D7", []string{"103", "U13-24"}, embd.CapDigital, 103, 0},
&embd.PinDesc{"LCD-D10", []string{"106", "U13-23"}, embd.CapDigital, 106, 0},
&embd.PinDesc{"LCD-D11", []string{"107", "U13-26"}, embd.CapDigital, 107, 0},
&embd.PinDesc{"LCD-D12", []string{"108", "U13-25"}, embd.CapDigital, 108, 0},
&embd.PinDesc{"LCD-D13", []string{"109", "U13-28"}, embd.CapDigital, 109, 0},
&embd.PinDesc{"LCD-D14", []string{"110", "U13-27"}, embd.CapDigital, 110, 0},
&embd.PinDesc{"LCD-D15", []string{"111", "U13-30"}, embd.CapDigital, 111, 0},
&embd.PinDesc{"LCD-D18", []string{"114", "U13-29"}, embd.CapDigital, 114, 0},
&embd.PinDesc{"LCD-D19", []string{"115", "U13-32"}, embd.CapDigital, 115, 0},
&embd.PinDesc{"LCD-D20", []string{"116", "U13-31"}, embd.CapDigital, 116, 0},
&embd.PinDesc{"LCD-D21", []string{"117", "U13-34"}, embd.CapDigital, 117, 0},
&embd.PinDesc{"LCD-D22", []string{"118", "U13-33"}, embd.CapDigital, 118, 0},
&embd.PinDesc{"LCD-D23", []string{"119", "U13-36"}, embd.CapDigital, 119, 0},
&embd.PinDesc{"LCD-CLK", []string{"120", "U13-35"}, embd.CapDigital, 120, 0},
&embd.PinDesc{"LCD-VSYNC", []string{"123", "U13-37"}, embd.CapDigital, 123, 0},
&embd.PinDesc{"LCD-HSYNC", []string{"122", "U13-38"}, embd.CapDigital, 122, 0},
&embd.PinDesc{"LCD-DE", []string{"121", "U13-40"}, embd.CapDigital, 121, 0},
// pins usable on the U14 connector
&embd.PinDesc{"UART1-TX", []string{"195", "U14-3", "EINT3"}, embd.CapDigital | embd.CapUART, 195, 0},
&embd.PinDesc{"UART1-RX", []string{"196", "U14-5", "EINT4"}, embd.CapDigital | embd.CapUART, 196, 0},
&embd.PinDesc{"AP-EINT1", []string{"193", "U14-23", "EINT1"}, embd.CapDigital, 193, 0},
&embd.PinDesc{"AP-EINT3", []string{"35", "U14-24", "EINT3"}, embd.CapDigital, 35, 0},
&embd.PinDesc{"TWI2-SDA", []string{"50", "U14-25", "I2C2_SDA"}, embd.CapDigital | embd.CapI2C, 50, 0},
&embd.PinDesc{"TWI2-SCK", []string{"49", "U14-26", "I2C2_SCK"}, embd.CapDigital | embd.CapI2C, 49, 0},
&embd.PinDesc{"CSIPCK", []string{"128", "U14-27", "SPI2_SCO", "SPI2_CS0"}, embd.CapDigital | embd.CapSPI, 128, 0},
&embd.PinDesc{"CSICK", []string{"129", "U14-28", "SPI2_CLK"}, embd.CapDigital | embd.CapSPI, 129, 0},
&embd.PinDesc{"CSIHSYNC", []string{"130", "U14-29", "SPI2_MOSI"}, embd.CapDigital | embd.CapSPI, 130, 0},
&embd.PinDesc{"CSIVSYNC", []string{"131", "U14-30", "SPI2_MISO"}, embd.CapDigital | embd.CapSPI, 131, 0},
&embd.PinDesc{"CSID0", []string{"132", "U14-31"}, embd.CapDigital, 132, 0},
&embd.PinDesc{"CSID1", []string{"133", "U14-32"}, embd.CapDigital, 133, 0},
&embd.PinDesc{"CSID2", []string{"134", "U14-33"}, embd.CapDigital, 134, 0},
&embd.PinDesc{"CSID3", []string{"135", "U14-34"}, embd.CapDigital, 135, 0},
&embd.PinDesc{"CSID4", []string{"136", "U14-35"}, embd.CapDigital, 136, 0},
&embd.PinDesc{"CSID5", []string{"137", "U14-36"}, embd.CapDigital, 137, 0},
&embd.PinDesc{"CSID6", []string{"138", "U14-37", "UART1_TX"}, embd.CapDigital | embd.CapUART, 138, 0},
&embd.PinDesc{"CSID7", []string{"139", "U14-38", "UART1_RX"}, embd.CapDigital | embd.CapUART, 139, 0},
}
func init() {
embd.Register(embd.HostCHIP, func(rev int) *embd.Descriptor {
return &embd.Descriptor{
GPIODriver: func() embd.GPIODriver {
return embd.NewGPIODriver(chipPins, generic.NewDigitalPin, nil, nil)
},
I2CDriver: func() embd.I2CDriver {
return embd.NewI2CDriver(generic.NewI2CBus)
},
//LEDDriver: func() embd.LEDDriver {
// return embd.NewLEDDriver(ledMap, generic.NewLED)
//},
SPIDriver: func() embd.SPIDriver {
return embd.NewSPIDriver(spiDeviceMinor, generic.NewSPIBus, nil)
},
}
})
}

View File

@ -10,6 +10,7 @@ import (
"os"
"path"
"strconv"
"syscall"
"time"
"github.com/kidoman/embd"
@ -69,6 +70,9 @@ func (p *digitalPin) export() error {
}
defer exporter.Close()
_, err = exporter.WriteString(strconv.Itoa(p.n))
if e, ok := err.(*os.PathError); ok && e.Err == syscall.EBUSY {
return nil // EBUSY -> the pin has already been exported
}
return err
}

View File

@ -101,6 +101,28 @@ func (b *i2cBus) ReadByte(addr byte) (byte, error) {
return bytes[0], nil
}
func (b *i2cBus) ReadBytes(addr byte, num int) ([]byte, error) {
b.mu.Lock()
defer b.mu.Unlock()
if err := b.init(); err != nil {
return []byte{0}, err
}
if err := b.setAddress(addr); err != nil {
return []byte{0}, err
}
bytes := make([]byte, num)
n, _ := b.file.Read(bytes)
if n != num {
return []byte{0}, fmt.Errorf("i2c: Unexpected number (%v) of bytes read", n)
}
return bytes, nil
}
func (b *i2cBus) WriteByte(addr, value byte) error {
b.mu.Lock()
defer b.mu.Unlock()
@ -223,7 +245,7 @@ func (b *i2cBus) WriteToReg(addr, reg byte, value []byte) error {
message.addr = uint16(addr)
message.flags = 0
message.len = uint16(len(outbuf))
message.buf = uintptr(unsafe.Pointer(&hdrp.Data))
message.buf = uintptr(unsafe.Pointer(hdrp.Data))
var packets i2c_rdwr_ioctl_data

View File

@ -61,11 +61,13 @@ func initEpollListener() *epollListener {
if err != nil {
panic(fmt.Sprintf("EpollWait error: %v", err))
}
listener.mu.Lock()
for i := 0; i < n; i++ {
if irq, ok := listener.interruptablePins[int(epollEvents[i].Fd)]; ok {
irq.Signal()
}
}
listener.mu.Unlock()
}
}()
return listener

View File

@ -36,12 +36,14 @@ type spiIOCTransfer struct {
speedHz uint32
delayus uint16
bitsPerWord uint8
csChange uint8
pad uint32
}
type spiBus struct {
file *os.File
spiDevMinor byte
spiDevMinor int
channel byte
mode byte
@ -61,7 +63,7 @@ func spiIOCMessageN(n uint32) uint32 {
return (spiIOCMessage0 + (n * spiIOCIncrementor))
}
func NewSPIBus(spiDevMinor, mode, channel byte, speed, bpw, delay int, i func() error) embd.SPIBus {
func NewSPIBus(spiDevMinor int, mode, channel byte, speed, bpw, delay int, i func() error) embd.SPIBus {
return &spiBus{
spiDevMinor: spiDevMinor,
mode: mode,

View File

@ -13,7 +13,7 @@ import (
"github.com/kidoman/embd/host/generic"
)
var spiDeviceMinor = byte(0)
var spiDeviceMinor = 0
var rev1Pins = embd.PinMap{
&embd.PinDesc{ID: "P1_3", Aliases: []string{"0", "GPIO_0", "SDA", "I2C0_SDA"}, Caps: embd.CapDigital | embd.CapI2C, DigitalLogical: 0},

2
i2c.go
View File

@ -6,6 +6,8 @@ package embd
type I2CBus interface {
// ReadByte reads a byte from the given address.
ReadByte(addr byte) (value byte, err error)
// ReadBytes reads a slice of bytes from the given address.
ReadBytes(addr byte, num int) (value []byte, err error)
// WriteByte writes a byte to the given address.
WriteByte(addr, value byte) error
// WriteBytes writes a slice bytes to the given address.

View File

@ -24,25 +24,25 @@ func main() {
panic(err)
}
fmt.Println("received data is: %v", dataBuf)
fmt.Println("received data is:", dataBuf)
dataReceived, err := spiBus.ReceiveData(3)
if err != nil {
panic(err)
}
fmt.Println("received data is: %v", dataReceived)
fmt.Println("received data is:", dataReceived)
dataByte := byte(1)
receivedByte, err := spiBus.TransferAndReceiveByte(dataByte)
if err != nil {
panic(err)
}
fmt.Println("received byte is: %v", receivedByte)
fmt.Println("received byte is:", receivedByte)
receivedByte, err = spiBus.ReceiveByte()
if err != nil {
panic(err)
}
fmt.Println("received byte is: %v", receivedByte)
fmt.Println("received byte is:", receivedByte)
}

View File

@ -2,10 +2,10 @@ package embd
import "sync"
type spiBusFactory func(byte, byte, byte, int, int, int, func() error) SPIBus
type spiBusFactory func(int, byte, byte, int, int, int, func() error) SPIBus
type spiDriver struct {
spiDevMinor byte
spiDevMinor int
initializer func() error
busMap map[byte]SPIBus
@ -16,7 +16,7 @@ type spiDriver struct {
// NewSPIDriver returns a SPIDriver interface which allows control
// over the SPI bus.
func NewSPIDriver(spiDevMinor byte, sbf spiBusFactory, i func() error) SPIDriver {
func NewSPIDriver(spiDevMinor int, sbf spiBusFactory, i func() error) SPIDriver {
return &spiDriver{
spiDevMinor: spiDevMinor,
sbf: sbf,

View File

@ -1,3 +0,0 @@
#!/usr/bin/env bash
git log --all --format='%cN <%cE>' | sort -u | grep -v karan.misra@gmail.com > CONTRIBUTORS

5
update_contributors.sh Executable file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env bash
git log --all --format='%cN <%cE>' | sort -u | grep -v karan.misra@gmail.com |\
grep -v noreply@ | cat CONTRIBUTORS - | sort | uniq > CONTRIBUTORS.new
mv CONTRIBUTORS.new CONTRIBUTORS