add: humidity (WIP)

This commit is contained in:
Markus Pesch 2018-12-04 19:11:50 +01:00
parent ba9f0c59f3
commit 81600154f0
Signed by: volker.raschek
GPG Key ID: 852BCC170D81A982
141 changed files with 18562 additions and 4 deletions

51
Gopkg.lock generated
View File

@ -3,11 +3,19 @@
[[projects]]
branch = "master"
digest = "1:ab8875db0749c2b2d147b0d250b73e45a2a722da4dd3664729ac207f1e6dcf9c"
digest = "1:36cccfe52f1b5332dd9374abca00bdb31b99a757c15b8a2b103f3f7b4541816b"
name = "git.cryptic.systems/fh-trier/go-flucky-server"
packages = ["pkg/types"]
pruneopts = "UT"
revision = "09990bcc64b4c240c53c0e98c03add895c1902c1"
revision = "3ce11606f75951619536ec3e3e501bc31dc53dd7"
[[projects]]
branch = "master"
digest = "1:2afcd3229edbe02821d3b2fc69ebd0e31365ad7f98ee88a08abb69d2c92b48be"
name = "github.com/MichaelS11/go-dht"
packages = ["."]
pruneopts = "UT"
revision = "be44b9ee7fec8f81d57dea89c17d26961183266e"
[[projects]]
digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"
@ -49,11 +57,50 @@
pruneopts = "UT"
revision = "3cf383a406247c49e48a80014f3e17ddee418742"
[[projects]]
digest = "1:9ad50a8dc9edeed28acefe7117cae2de893b5fbbbe551ebfad26d56304cc83d8"
name = "periph.io/x/periph"
packages = [
".",
"conn",
"conn/gpio",
"conn/gpio/gpioreg",
"conn/gpio/gpiostream",
"conn/i2c",
"conn/i2c/i2creg",
"conn/physic",
"conn/pin",
"conn/pin/pinreg",
"conn/spi",
"conn/spi/spireg",
"host",
"host/allwinner",
"host/am335x",
"host/bcm283x",
"host/beagle/black",
"host/beagle/bone",
"host/beagle/green",
"host/chip",
"host/cpu",
"host/distro",
"host/fs",
"host/odroidc1",
"host/pine64",
"host/pmem",
"host/rpi",
"host/sysfs",
"host/videocore",
]
pruneopts = "UT"
revision = "f44fc121a350041e7a23acc3ccf87edc8780f3ba"
version = "v3.3.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types",
"github.com/MichaelS11/go-dht",
"github.com/satori/go.uuid",
"github.com/spf13/cobra",
"github.com/yryz/ds18b20",

View File

@ -2,6 +2,7 @@ package cmd
import (
"git.cryptic.systems/fh-trier/go-flucky/cmd/config"
"git.cryptic.systems/fh-trier/go-flucky/cmd/humidity"
"git.cryptic.systems/fh-trier/go-flucky/cmd/remote"
"git.cryptic.systems/fh-trier/go-flucky/cmd/sensor"
"git.cryptic.systems/fh-trier/go-flucky/cmd/temperature"
@ -22,6 +23,7 @@ func Execute(version string) {
rootCmd.PersistentFlags().StringVarP(&configDir, "config", "c", "/etc/flucky", "The base directory for all configuration files.")
config.InitCmd(rootCmd, configDir)
humidity.InitCmd(rootCmd, configDir)
remote.InitCmd(rootCmd, configDir)
sensor.InitCmd(rootCmd, configDir)
temperature.InitCmd(rootCmd, configDir)

28
cmd/humidity/get.go Normal file
View File

@ -0,0 +1,28 @@
package humidity
import (
"log"
"git.cryptic.systems/fh-trier/go-flucky/pkg/humidity"
"github.com/spf13/cobra"
)
var follow, push bool
var getHumidityCmd = &cobra.Command{
Use: "get",
Short: "get humidity from sensor",
Run: func(cmd *cobra.Command, args []string) {
if err := humidity.Get(); err != nil {
log.Fatal(err)
}
},
}
func init() {
humidityCmd.AddCommand(getHumidityCmd)
// getTemperatureCmd.Flags().BoolVarP(&follow, "follow", "f", false, "Follow output")
// getTemperatureCmd.Flags().BoolVarP(&push, "push", "p", false, "Push to remote server")
}

20
cmd/humidity/humidity.go Normal file
View File

@ -0,0 +1,20 @@
package humidity
import (
"github.com/spf13/cobra"
)
var configDir string
var humidityCmd = &cobra.Command{
Use: "humidity",
Short: "Read humidity from sensor",
}
// Execute a
func InitCmd(cmd *cobra.Command, cnf string) {
configDir = cnf
cmd.AddCommand(humidityCmd)
}

30
pkg/humidity/humidity.go Normal file
View File

@ -0,0 +1,30 @@
package humidity
import (
"fmt"
dht "github.com/MichaelS11/go-dht"
)
func Get() error {
err := dht.HostInit()
if err != nil {
return fmt.Errorf("HostInit error: %v", err)
}
dht, err := dht.NewDHT("GPIO19", dht.Celsius, "dht11")
if err != nil {
return fmt.Errorf("NewDHT error: %v", err)
}
humidity, temperature, err := dht.ReadRetry(10)
if err != nil {
return fmt.Errorf("Read error: %v", err)
}
fmt.Printf("humidity: %v\n", humidity)
fmt.Printf("temperature: %v\n", temperature)
return nil
}

View File

@ -85,7 +85,7 @@ func ListTemperatures(configDir string, w io.Writer) error {
// print headline
fmt.Fprint(tw, "\t")
for _, sensor := range sensors {
fmt.Fprintf(tw, "%v\t", sensor.HumanName())
fmt.Fprintf(tw, "%v\t", sensor.ReadableSensorName())
}
if len(sensors) > 0 {
fmt.Fprint(tw, "\n")

View File

@ -36,6 +36,36 @@ func (d *Device) DecodeFromJSON(r io.Reader) error {
return nil
}
// Failnoise ...
type Failnoise struct {
FailnoiseID string `json:"failnoise_id"`
FailnoiseCounter int `json:"failnoise_counter,string"`
FailnoiseStartDate time.Time `json:"failnoise_start_date"`
FailnoiseEndDate time.Time `json:"failnoise_end_date"`
SensorID string `json:"sensor_id"`
CreationDate time.Time `json:"creation_date"`
}
// EncodeToJSON needs a writer to write the struct into json string
func (f *Failnoise) EncodeToJSON(w io.Writer) error {
encoder := json.NewEncoder(w)
encoder.SetIndent("", " ")
err := encoder.Encode(&f)
if err != nil {
return fmt.Errorf("Error in encoding struct to json: %v", err)
}
return nil
}
// DecodeFromJSON decode a json string from a reader into a struct
func (f *Failnoise) DecodeFromJSON(r io.Reader) error {
decoder := json.NewDecoder(r)
if err := decoder.Decode(&f); err != nil {
return fmt.Errorf("Can not unmarshal JSON: %v", err)
}
return nil
}
// Humidity ...
type Humidity struct {
HumidityID string `json:"humidity_id"`
@ -65,6 +95,36 @@ func (h *Humidity) DecodeFromJSON(r io.Reader) error {
return nil
}
// Knock ...
type Knock struct {
KnockID string `json:"knock_id"`
KnockCounter int `json:"knock_counter,string"`
KnockStartDate time.Time `json:"knock_start_date"`
KnockEndDate time.Time `json:"knock_end_date"`
SensorID string `json:"sensor_id"`
CreationDate time.Time `json:"creation_date"`
}
// EncodeToJSON needs a writer to write the struct into json string
func (k *Knock) EncodeToJSON(w io.Writer) error {
encoder := json.NewEncoder(w)
encoder.SetIndent("", " ")
err := encoder.Encode(&k)
if err != nil {
return fmt.Errorf("Error in encoding struct to json: %v", err)
}
return nil
}
// DecodeFromJSON decode a json string from a reader into a struct
func (k *Knock) DecodeFromJSON(r io.Reader) error {
decoder := json.NewDecoder(r)
if err := decoder.Decode(&k); err != nil {
return fmt.Errorf("Can not unmarshal JSON: %v", err)
}
return nil
}
// Sensor ...
type Sensor struct {
SensorID string `json:"sensor_id"`
@ -99,7 +159,8 @@ func (s *Sensor) DecodeFromJSON(r io.Reader) error {
return nil
}
func (s *Sensor) HumanName() string {
// ReadableSensorName returns a readable sensor name
func (s *Sensor) ReadableSensorName() string {
if s.SensorName != nil {
return *s.SensorName
}
@ -137,3 +198,33 @@ func (t *Temperature) DecodeFromJSON(r io.Reader) error {
}
return nil
}
// Throughput ...
type Throughput struct {
ThroughputID string `json:"throughput_id"`
ThroughputAverage float64 `json:"throughput_average,string"`
ThroughputStartDate time.Time `json:"throughput_start_date"`
ThroughputEndDate time.Time `json:"throughput_end_date"`
SensorID string `json:"sensor_id"`
CreationDate time.Time `json:"creation_date"`
}
// EncodeToJSON needs a writer to write the struct into json string
func (t *Throughput) EncodeToJSON(w io.Writer) error {
encoder := json.NewEncoder(w)
encoder.SetIndent("", " ")
err := encoder.Encode(&t)
if err != nil {
return fmt.Errorf("Error in encoding struct to json: %v", err)
}
return nil
}
// DecodeFromJSON decode a json string from a reader into a struct
func (t *Throughput) DecodeFromJSON(r io.Reader) error {
decoder := json.NewDecoder(r)
if err := decoder.Decode(&t); err != nil {
return fmt.Errorf("Can not unmarshal JSON: %v", err)
}
return nil
}

21
vendor/github.com/MichaelS11/go-dht/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 MichaelS11
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

144
vendor/github.com/MichaelS11/go-dht/README.md generated vendored Normal file
View File

@ -0,0 +1,144 @@
# Go DHT22 / AM2302 / DHT11 interface
Golang DHT22 / AM2302 / DHT11 interface using periph.io driver
[![GoDoc Reference](https://godoc.org/github.com/MichaelS11/go-dht?status.svg)](http://godoc.org/github.com/MichaelS11/go-dht)
[![Go Report Card](https://goreportcard.com/badge/github.com/MichaelS11/go-dht)](https://goreportcard.com/report/github.com/MichaelS11/go-dht)
## Please note
Please make sure to setup your DHT22 / AM2302 / DHT11 correctly. Do a search on the internet to find guide. Here is an example of a guide:
https://learn.adafruit.com/dht/connecting-to-a-dhtxx-sensor
The examples below are from using a Raspberry Pi 3 with GPIO 19 for the pin. Your setup may be different, if so, your pin names would need to change in each example.
Side note, in my testing the sensor has a fairly high level of read errors, suggest using ReadRetry or ReadBackground rather then just Read.
Tested on Raspberry Pi 3 with AM2302. Please open an issue if there are any issues.
## Get
go get github.com/MichaelS11/go-dht
## ReadRetry example
```go
package main
import (
"fmt"
"github.com/MichaelS11/go-dht"
)
func main() {
err := dht.HostInit()
if err != nil {
fmt.Println("HostInit error:", err)
return
}
dht, err := dht.NewDHT("GPIO19", dht.Fahrenheit, "")
if err != nil {
fmt.Println("NewDHT error:", err)
return
}
humidity, temperature, err := dht.ReadRetry(11)
if err != nil {
fmt.Println("Read error:", err)
return
}
fmt.Printf("humidity: %v\n", humidity)
fmt.Printf("temperature: %v\n", temperature)
}
```
## ReadBackground example
```go
package main
import (
"fmt"
"time"
"github.com/MichaelS11/go-dht"
)
func main() {
err := dht.HostInit()
if err != nil {
fmt.Println("HostInit error:", err)
return
}
dht, err := dht.NewDHT("GPIO19", dht.Fahrenheit, "")
if err != nil {
fmt.Println("NewDHT error:", err)
return
}
stop := make(chan struct{})
stopped := make(chan struct{})
var humidity float64
var temperature float64
// get sensor reading every 20 seconds in background
go dht.ReadBackground(&humidity, &temperature, 20*time.Second, stop, stopped)
// should have at least read the sensor twice after 30 seconds
time.Sleep(30 * time.Second)
fmt.Printf("humidity: %v\n", humidity)
fmt.Printf("temperature: %v\n", temperature)
// to stop ReadBackground after done with reading, close the stop channel
close(stop)
// can check stopped channel to know when ReadBackground has stopped
<-stopped
}
```
## Read example
```go
package main
import (
"fmt"
"github.com/MichaelS11/go-dht"
)
func main() {
err := dht.HostInit()
if err != nil {
fmt.Println("HostInit error:", err)
return
}
dht, err := dht.NewDHT("GPIO19", dht.Fahrenheit, "")
if err != nil {
fmt.Println("NewDHT error:", err)
return
}
humidity, temperature, err := dht.Read()
if err != nil {
fmt.Println("Read error:", err)
return
}
fmt.Printf("humidity: %v\n", humidity)
fmt.Printf("temperature: %v\n", temperature)
}
```

196
vendor/github.com/MichaelS11/go-dht/dht.go generated vendored Normal file
View File

@ -0,0 +1,196 @@
package dht
import (
"fmt"
"time"
"periph.io/x/periph/host"
)
// HostInit calls periph.io host.Init(). This needs to be done before DHT can be used.
func HostInit() error {
_, err := host.Init()
return err
}
// Read reads the sensor once, returing humidity and temperature, or an error.
// Note that Read will sleep for at least 2 seconds between last call.
// Each reads error adds a half second to sleep time to max of 30 seconds.
func (dht *DHT) Read() (humidity float64, temperature float64, err error) {
// set sleepTime
var sleepTime time.Duration
if dht.numErrors < 57 {
sleepTime = (2 * time.Second) + (time.Duration(dht.numErrors) * 500 * time.Millisecond)
} else {
// sleep max of 30 seconds
sleepTime = 30 * time.Second
}
sleepTime -= time.Since(dht.lastRead)
// sleep between 2 and 30 seconds
time.Sleep(sleepTime)
// read bits from sensor
var bits []int
bits, err = dht.readBits()
if err != nil {
return
}
// covert bits to humidity and temperature
humidity, temperature, err = dht.bitsToValues(bits)
return
}
// bitsToValues will convert the bits into humidity and temperature values
func (dht *DHT) bitsToValues(bits []int) (humidity float64, temperature float64, err error) {
var sum8 uint8
var sumTotal uint8
var checkSum uint8
var i int
var humidityInt int
var temperatureInt int
// get humidityInt value
for i = 0; i < 16; i++ {
humidityInt = humidityInt << 1
humidityInt += bits[i]
// sum 8 bits for checkSum
sum8 = sum8 << 1
sum8 += uint8(bits[i])
if i == 7 || i == 15 {
// got 8 bits, add to sumTotal for checkSum
sumTotal += sum8
sum8 = 0
}
}
// get temperatureInt value
for i = 16; i < 32; i++ {
temperatureInt = temperatureInt << 1
temperatureInt += bits[i]
// sum 8 bits for checkSum
sum8 = sum8 << 1
sum8 += uint8(bits[i])
if i == 23 || i == 31 {
// got 8 bits, add to sumTotal for checkSum
sumTotal += sum8
sum8 = 0
}
}
// if high 16 bit is set, value is negtive
// 1000000000000000 = 0x8000
if (temperatureInt & 0x8000) > 0 {
// flip bits 16 and lower to get negtive number for int
// 1111111111111111 = 0xffff
temperatureInt |= ^0xffff
}
// get checkSum value
for i = 32; i < 40; i++ {
checkSum = checkSum << 1
checkSum += uint8(bits[i])
}
if dht.sensorType != "dht11" {
// humidity is between 0 % to 100 %
if humidityInt < 0 || humidityInt > 1000 {
err = fmt.Errorf("bad data - humidity: %v", humidityInt)
return
}
// temperature between -40 C to 80 C
if temperatureInt < -400 || temperatureInt > 800 {
err = fmt.Errorf("bad data - temperature: %v", temperatureInt)
return
}
// check checkSum
if checkSum != sumTotal {
err = fmt.Errorf("bad data - check sum fail")
}
humidity = float64(humidityInt) / 10.0
if dht.temperatureUnit == Celsius {
temperature = float64(temperatureInt) / 10.0
} else {
temperature = float64(temperatureInt)*9.0/50.0 + 32.0
}
return
}
// humidity is between 0 % to 100 %
if humidityInt < 0 || humidityInt > 100 {
err = fmt.Errorf("bad data - humidity: %v", humidityInt)
return
}
// temperature between 0 C to 50 C
if temperatureInt < 0 || temperatureInt > 50 {
err = fmt.Errorf("bad data - temperature: %v", temperatureInt)
return
}
// check checkSum
if checkSum != sumTotal {
err = fmt.Errorf("bad data - check sum fail")
}
humidity = float64(humidityInt)
if dht.temperatureUnit == Celsius {
temperature = float64(temperatureInt)
} else {
temperature = float64(temperatureInt)*9.0/5.0 + 32.0
}
return
}
// ReadRetry will call Read until there is no errors or the maxRetries is hit.
// Suggest maxRetries to be set around 11.
func (dht *DHT) ReadRetry(maxRetries int) (humidity float64, temperature float64, err error) {
for i := 0; i < maxRetries; i++ {
humidity, temperature, err = dht.Read()
if err == nil {
return
}
}
return
}
// ReadBackground it meant to be run in the background, run as a Goroutine.
// sleepDuration is how long it will try to sleep between reads.
// If there is ongoing read errors there will be no notice except that the values will not be updated.
// Will continue to read sensor until stop is closed.
// After it has been stopped, the stopped chan will be closed.
// Will panic if humidity, temperature, or stop are nil.
func (dht *DHT) ReadBackground(humidity *float64, temperature *float64, sleepDuration time.Duration, stop chan struct{}, stopped chan struct{}) {
var humidityTemp float64
var temperatureTemp float64
var err error
var startTime time.Time
Loop:
for {
startTime = time.Now()
humidityTemp, temperatureTemp, err = dht.Read()
if err == nil {
// no read error, save result
*humidity = humidityTemp
*temperature = temperatureTemp
// wait for sleepDuration or stop
select {
case <-time.After(sleepDuration - time.Since(startTime)):
case <-stop:
break Loop
}
} else {
// read error, just check for stop
select {
case <-stop:
break Loop
default:
}
}
}
close(stopped)
}

155
vendor/github.com/MichaelS11/go-dht/dhtNotWindows.go generated vendored Normal file
View File

@ -0,0 +1,155 @@
// +build !windows
package dht
import (
"fmt"
"log"
"runtime/debug"
"strings"
"time"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/gpio/gpioreg"
)
// NewDHT to create a new DHT struct.
// sensorType is dht11 for DHT11, anything else for AM2302 / DHT22.
func NewDHT(pinName string, temperatureUnit TemperatureUnit, sensorType string) (*DHT, error) {
dht := &DHT{temperatureUnit: temperatureUnit}
// set sensorType
sensorType = strings.ToLower(sensorType)
if sensorType == "dht11" {
dht.sensorType = "dht11"
}
// get pin
dht.pin = gpioreg.ByName(pinName)
if dht.pin == nil {
return nil, fmt.Errorf("pin is nill")
}
// set pin to high so ready for first read
err := dht.pin.Out(gpio.High)
if err != nil {
return nil, fmt.Errorf("pin out high error: %v", err)
}
// set lastRead a second before to give the pin a second to warm up
dht.lastRead = time.Now().Add(-1 * time.Second)
return dht, nil
}
// readBits will get the bits for humidity and temperature
func (dht *DHT) readBits() ([]int, error) {
// create variables ahead of time before critical timing part
var i int
var startTime time.Time
var levelPrevious gpio.Level
var level gpio.Level
levels := make([]gpio.Level, 0, 84)
durations := make([]time.Duration, 0, 84)
// set lastRead so do not read more than once every 2 seconds
dht.lastRead = time.Now()
// disable garbage collection during critical timing part
gcPercent := debug.SetGCPercent(-1)
// send start low
err := dht.pin.Out(gpio.Low)
if err != nil {
dht.pin.Out(gpio.High)
return nil, fmt.Errorf("pin out low error: %v", err)
}
time.Sleep(time.Millisecond)
// send start high
err = dht.pin.In(gpio.PullUp, gpio.NoEdge)
if err != nil {
dht.pin.Out(gpio.High)
return nil, fmt.Errorf("pin in error: %v", err)
}
// read levels and durations with busy read
// hope there is a better way in the future
// tried to use WaitForEdge but seems to miss edges and/or take too long to detect them
// note that pin read takes around .2 microsecond (us) on Raspberry PI 3
// note that 1000 microsecond (us) = 1 millisecond (ms)
levelPrevious = dht.pin.Read()
level = levelPrevious
for i = 0; i < 84; i++ {
startTime = time.Now()
for levelPrevious == level && time.Since(startTime) < time.Millisecond {
level = dht.pin.Read()
}
durations = append(durations, time.Since(startTime))
levels = append(levels, levelPrevious)
levelPrevious = level
}
// enable garbage collection, done with critical part
debug.SetGCPercent(gcPercent)
log.Printf("%v\n", levels)
// set pin to high so ready for next time
err = dht.pin.Out(gpio.High)
if err != nil {
return nil, fmt.Errorf("pin out high error: %v", err)
}
// get last low reading so know start of data
var endNumber int
for i = len(levels) - 1; ; i-- {
if levels[i] == gpio.Low {
endNumber = i
break
}
if i < 80 {
// not enough readings, i = 79 means endNumber is 78 or less
return nil, fmt.Errorf("missing some readings - low level not found")
}
}
startNumber := endNumber - 79
// covert pulses into bits and check high levels
bits := make([]int, 40)
index := 0
for i = startNumber; i < endNumber; i += 2 {
// check high levels
if levels[i] != gpio.High {
return nil, fmt.Errorf("missing some readings - level not high")
}
// high should not be longer then 90 microseconds
if durations[i] > 90*time.Microsecond {
return nil, fmt.Errorf("missing some readings - high level duration too long: %v", durations[i])
}
// bit is 0 if less than or equal to 30 microseconds
if durations[i] > 30*time.Microsecond {
// bit is 1 if more than 30 microseconds
bits[index] = 1
}
index++
}
// check low levels
for i = startNumber + 1; i < endNumber+1; i += 2 {
// check low levels
if levels[i] != gpio.Low {
return nil, fmt.Errorf("missing some readings - level not low")
}
// low should not be longer then 70 microseconds
if durations[i] > 70*time.Microsecond {
return nil, fmt.Errorf("missing some readings - low level duration too long: %v", durations[i])
}
// low should not be shorter then 35 microseconds
if durations[i] < 35*time.Microsecond {
return nil, fmt.Errorf("missing some readings - low level duration too short: %v", durations[i])
}
}
return bits, nil
}

35
vendor/github.com/MichaelS11/go-dht/dhtWindows.go generated vendored Normal file
View File

@ -0,0 +1,35 @@
// +build windows
package dht
import (
"strings"
"time"
)
// NewDHT to create a new DHT struct.
// sensorType is dht11 for DHT11, anything else for AM2302 / DHT22.
func NewDHT(pinName string, temperatureUnit TemperatureUnit, sensorType string) (*DHT, error) {
dht := &DHT{temperatureUnit: temperatureUnit}
// set sensorType
sensorType = strings.ToLower(sensorType)
if sensorType == "dht11" {
dht.sensorType = "dht11"
}
// set lastRead a second before to give the pin a second to warm up
dht.lastRead = time.Now().Add(-1 * time.Second)
return dht, nil
}
// readBits will get the bits for humidity and temperature
func (dht *DHT) readBits() ([]int, error) {
// set lastRead so do not read more than once every 2 seconds
dht.lastRead = time.Now()
bits := make([]int, 40)
return bits, nil
}

27
vendor/github.com/MichaelS11/go-dht/globals.go generated vendored Normal file
View File

@ -0,0 +1,27 @@
package dht
import (
"time"
"periph.io/x/periph/conn/gpio"
)
// TemperatureUnit is the temperature unit wanted, either Celsius or Fahrenheit
type TemperatureUnit int
const (
// Celsius temperature unit
Celsius TemperatureUnit = iota
// Fahrenheit temperature unit
Fahrenheit
)
// DHT struct to interface with the sensor.
// Call NewDHT to create a new one.
type DHT struct {
pin gpio.PinIO
temperatureUnit TemperatureUnit
sensorType string
numErrors int
lastRead time.Time
}

1
vendor/periph.io/x/periph/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
bin

227
vendor/periph.io/x/periph/.gohci.yml generated vendored Normal file
View File

@ -0,0 +1,227 @@
# See https://github.com/periph/gohci
version: 1
workers:
- name: beaglebone-4373
checks:
- cmd:
- go
- install
- -v
- ./cmd/headers-list
- ./cmd/i2c-list
- ./cmd/periph-info
- ./cmd/spi-list
- cmd:
- periph-info
- cmd:
- headers-list
- -f
- cmd:
- i2c-list
- cmd:
- spi-list
- name: chip-a87d
checks:
- cmd:
- go
- install
- -v
- ./cmd/gpio-list
- ./cmd/headers-list
- ./cmd/i2c-list
- ./cmd/periph-info
- ./cmd/periph-smoketest
- ./cmd/spi-list
- cmd:
- periph-info
- cmd:
- gpio-list
- -f
- cmd:
- headers-list
- -f
- cmd:
- i2c-list
- cmd:
- spi-list
- cmd:
- periph-smoketest
- chip
- cmd:
- periph-smoketest
- i2c-testboard
- -bus
- 1
- cmd:
- periph-smoketest
- onewire-testboard
- -i2cbus
- 1
- cmd:
- periph-smoketest
- sysfs-benchmark
- -p
- 1013
- -short
- cmd:
- periph-smoketest
- sysfs-benchmark
- -p
- 132
- -short
- cmd:
- periph-smoketest
- allwinner-benchmark
- -p
- 132
- -short
- cmd:
- periph-smoketest
- spi-testboard
- name: mbp
checks:
- cmd:
- go
- test
- -race
- ./...
- cmd:
- go
- install
- -v
- ./cmd/gpio-list
- ./cmd/headers-list
- ./cmd/i2c-list
- ./cmd/periph-info
- ./cmd/spi-list
- cmd:
- periph-info
- cmd:
- gpio-list
- -f
- cmd:
- headers-list
- -f
- cmd:
- i2c-list
- cmd:
- spi-list
- name: odroid-483d
checks:
- cmd:
- go
- test
- -cover
- -bench=.
- -benchtime=1000ms
- -benchmem
- ./...
- ./...
- cmd:
- go
- install
- -v
- ./cmd/gpio-list
- ./cmd/headers-list
- ./cmd/i2c-list
- ./cmd/periph-info
- ./cmd/periph-smoketest
- ./cmd/spi-list
- cmd:
- periph-info
- cmd:
- gpio-list
- -f
- cmd:
- headers-list
- -f
- cmd:
- i2c-list
- cmd:
- spi-list
- cmd:
- periph-smoketest
- odroid-c1
- cmd:
- periph-smoketest
- i2c-testboard
- cmd:
- periph-smoketest
- onewire-testboard
- cmd:
- periph-smoketest
- spi-testboard
- cmd:
- periph-smoketest
- sysfs-benchmark
- -p
- 97
- -short
- name: raspberrypi-2f34
checks:
- cmd:
- go
- install
- -v
- ./cmd/gpio-list
- ./cmd/headers-list
- ./cmd/i2c-list
- ./cmd/periph-info
- ./cmd/periph-smoketest
- ./cmd/spi-list
- cmd:
- periph-info
- cmd:
- gpio-list
- -f
- cmd:
- headers-list
- -f
- cmd:
- i2c-list
- cmd:
- spi-list
- cmd:
- periph-smoketest
- i2c-testboard
- cmd:
- periph-smoketest
- onewire-testboard
- -i2cbus
- 1
- cmd:
- periph-smoketest
- spi-testboard
- cmd:
- periph-smoketest
- sysfs-benchmark
- -p
- 12
- -short
- cmd:
- periph-smoketest
- bcm283x-benchmark
- -p
- 12
- -short
- name: win10
checks:
- cmd:
- go
- test
- -cover
- -bench=.
- -benchtime=1000ms
- -benchmem
- ./...
- cmd:
- go
- test
- -race
- ./...
- cmd:
- go
- vet
- -all
- -unsafeptr=false
- ./...

25
vendor/periph.io/x/periph/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,25 @@
language: go
sudo: false
go_import_path: periph.io/x/periph
go:
- 1.5.4
- 1.7.6
- 1.11.1
before_script:
- echo $TRAVIS_GO_VERSION
- go get -t -v periph.io/x/periph/...
script:
# Things run only on the latest version.
- if [[ $TRAVIS_GO_VERSION == 1.11.1 ]]; then echo 'Check Code is well formatted'; ! gofmt -s -d . | read; fi
- if [[ $TRAVIS_GO_VERSION == 1.11.1 ]]; then echo 'Looking for external dependencies:'; go list -f '{{join .Imports "\n"}}' periph.io/x/periph/... | sort | uniq | grep -v ^periph.io/x/periph | xargs go list -f '{{if not .Standard}}- {{.ImportPath}}{{end}}'; fi
- if [[ $TRAVIS_GO_VERSION == 1.11.1 ]]; then echo 'Erroring on external dependencies:'; ! go list -f '{{join .Imports "\n"}}' periph.io/x/periph/... | sort | uniq | grep -v ^periph.io/x/periph | xargs go list -f '{{if not .Standard}}Remove {{.ImportPath}}{{end}}' | grep -q Remove; fi
- if [[ $TRAVIS_GO_VERSION == 1.11.1 ]]; then echo 'Erroring on /host depending on /devices:'; ! go list -f '{{.ImportPath}} depends on {{join .Imports ", "}}' periph.io/x/periph/host/... | sort | uniq | grep periph.io/x/periph/devices; fi
- if [[ $TRAVIS_GO_VERSION == 1.11.1 ]]; then echo 'Erroring on /conn depending on /devices:'; ! go list -f '{{.ImportPath}} depends on {{join .Imports ", "}}' periph.io/x/periph/conn/... | sort | uniq | grep periph.io/x/periph/devices; fi
- if [[ $TRAVIS_GO_VERSION == 1.11.1 ]]; then echo 'Erroring on /conn depending on /host:'; ! go list -f '{{.ImportPath}} depends on {{join .Imports ", "}}' periph.io/x/periph/conn/... | sort | uniq | grep periph.io/x/periph/host; fi
- if [[ $TRAVIS_GO_VERSION == 1.11.1 ]]; then bash -c 'set -e; echo "" > coverage.txt; for d in $(go list ./...); do go test -covermode=count -coverprofile=p.out $d; if [ -f p.out ]; then cat p.out >> coverage.txt; rm p.out; fi; done'; fi
- if [[ $TRAVIS_GO_VERSION == 1.11.1 ]]; then go test -race ./...; fi
# The only thing run on older versions.
- if [[ $TRAVIS_GO_VERSION != 1.11.1 ]]; then go test ./...; fi
after_success:
- if [[ $TRAVIS_GO_VERSION == 1.11.1 ]]; then bash <(curl -s https://codecov.io/bash); fi

15
vendor/periph.io/x/periph/AUTHORS generated vendored Normal file
View File

@ -0,0 +1,15 @@
# This is the list of The Periph Authors for copyright purposes.
#
# This does not necessarily list everyone who has contributed code, since in
# some cases, their employer may be the copyright holder. To see the full list
# of contributors, see the revision history in source control.
Cássio Botaro <cassiobotaro@gmail.com>
Fractal Industries, Inc
Google Inc.
Josh Gardiner
Matt Aimonetti <mattaimonetti@gmail.com>
Max Ekman <max@looplab.se>
Rifiniti, Inc
Stephan Sperber
Thorsten von Eicken <tve@voneicken.com>

4
vendor/periph.io/x/periph/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,4 @@
# Contributing
Thanks for contributing to the project! Please look at [the periph contribution
guidelines](https://periph.io/project/contributing/) first.

40
vendor/periph.io/x/periph/CONTRIBUTORS generated vendored Normal file
View File

@ -0,0 +1,40 @@
# This is the official list of people who can contribute
# (and typically have contributed) code to the periph repository.
# The AUTHORS file lists the copyright holders; this file
# lists people. For example, Google employees are listed here
# but not in AUTHORS, because Google holds the copyright.
#
# Names should be added to this file only after verifying that
# the individual or the individual's organization has agreed to
# the appropriate Contributor License Agreement, found here:
#
# https://cla.developers.google.com/
#
# When adding J Random Contributor's name to this file,
# either J's name or J's organization's name should be
# added to the AUTHORS file, depending on whether the
# individual or corporate CLA was used.
# Names should be added to this file like so:
# Individual's name <submission email address>
# Individual's name <submission email address> <email2> <emailN>
#
# An entry with multiple email addresses specifies that the
# first address should be used in the submit logs and
# that the other addresses should be recognized as the
# same person when interacting with Gerrit.
# Please keep the list sorted.
Cássio Botaro <cassiobotaro@gmail.com>
Eugene Dzhurynsky <jdevelop@gmail.com>
Hidetoshi Shimokawa <smkwhdts@gmail.com>
Josh Gardiner <josh@zool.com>
Marc-Antoine Ruel <maruel@chromium.org> <maruel@gmail.com>
Matt Aimonetti <mattaimonetti@gmail.com>
Max Ekman <max@looplab.se>
Matias Insaurralde <matias@insaurral.de>
Seán C McCord <ulexus@gmail.com> <scm@cycoresys.com>
Stephan Sperber <sperberstephan@googlemail.com>
Thorsten von Eicken <tve@voneicken.com>

202
vendor/periph.io/x/periph/LICENSE generated vendored Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

59
vendor/periph.io/x/periph/Makefile generated vendored Normal file
View File

@ -0,0 +1,59 @@
# Copyright 2016 The Periph Authors. All rights reserved.
# Use of this source code is governed under the Apache License, Version 2.0
# that can be found in the LICENSE file.
# This Makefile captures common tasks for the periph library. The hope is that this Makefile can remain
# simple and straightforward...
# *** This Makefile is a work in progress, please help impove it! ***
# not sure yet what all should do...
all:
@echo Available targets: test build
.PHONY: all test clean depend
# test runs the platform independent tests
# (gofmt|grep is used to obtain a non-zero exit status if the formatting is off)
test:
go test ./...
@if gofmt -l . | grep .go; then \
echo "Repo contains improperly formatted go files; run gofmt on above files" && exit 1; \
else echo "OK gofmt"; fi
-go vet -unsafeptr=false ./...
# BUILD
#
# The build target cross compiles each program in cmd to a binary for each platform in the bin
# directory. It is assumed that each command has a main.go file in its directory. Trying to keep all
# this relatively simple and not descend into makefile hell...
# Get a list of all main.go in cmd subdirs
# MAINS becomes: cmd/gpio-list/main.go cmd/periph-info/main.go ...
MAINS := $(wildcard cmd/*/main.go)
# Get a list of all the commands, i.e. names of dirs that contain a main.go
# CMDS becomes: gpio-list periph-info ...
CMDS := $(patsubst cmd/%/main.go,%,$(MAINS))
# Get a list of binaries to build
# BINS becomes: bin/gpio-list-arm bin/periph-info-arm ... bin/gpio-list-arm64 bin/periph-info-arm64 ...
ARCHS := arm arm64 amd64 win64.exe
BINS=$(foreach arch,$(ARCHS),$(foreach cmd,$(CMDS),bin/$(cmd)-$(arch)))
build: depend bin $(BINS)
bin:
mkdir bin
# Rules to build binaries for a command in cmd. The prereqs could be improved...
bin/%-arm: cmd/%/*.go
GOARCH=arm GOOS=linux go build -o $@ ./cmd/$*
bin/%-arm64: cmd/%/*.go
GOARCH=arm64 GOOS=linux go build -o $@ ./cmd/$*
bin/%-amd64: cmd/%/*.go
GOARCH=amd64 GOOS=linux go build -o $@ ./cmd/$*
bin/%-win64.exe: cmd/%/*.go
GOARCH=amd64 GOOS=windows go build -o $@ ./cmd/$*
# clean removes all compiled binaries
clean:
rm bin/*-*
rmdir bin

59
vendor/periph.io/x/periph/README.md generated vendored Normal file
View File

@ -0,0 +1,59 @@
# periph - Peripherals I/O in Go
[![mascot](https://raw.githubusercontent.com/periph/website/master/site/static/img/periph-mascot-280.png)](https://periph.io/)
Documentation is at https://periph.io
[![GoDoc](https://godoc.org/periph.io/x/periph?status.svg)](https://godoc.org/periph.io/x/periph)
[![Go Report Card](https://goreportcard.com/badge/periph.io/x/periph)](https://goreportcard.com/report/periph.io/x/periph)
[![Coverage Status](https://codecov.io/gh/google/periph/graph/badge.svg)](https://codecov.io/gh/google/periph)
[![Build Status](https://travis-ci.org/google/periph.svg)](https://travis-ci.org/google/periph)
Join us for a chat on
[gophers.slack.com/messages/periph](https://gophers.slack.com/messages/periph),
get an [invite here](https://invite.slack.golangbridge.org/).
## Example
Blink a LED:
~~~go
package main
import (
"time"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/host"
"periph.io/x/periph/host/rpi"
)
func main() {
host.Init()
t := time.NewTicker(500 * time.Millisecond)
for l := gpio.Low; ; l = !l {
rpi.P1_33.Out(l)
<-t.C
}
}
~~~
Curious? Look at [supported devices](https://periph.io/device/) for more
examples!
## Authors
`periph` was initiated with ❤️️ and passion by [Marc-Antoine
Ruel](https://github.com/maruel). The full list of contributors is in
[AUTHORS](https://github.com/google/periph/blob/master/AUTHORS) and
[CONTRIBUTORS](https://github.com/google/periph/blob/master/CONTRIBUTORS).
## Disclaimer
This is not an official Google product (experimental or otherwise), it
is just code that happens to be owned by Google.
This project is not affiliated with the Go project.

103
vendor/periph.io/x/periph/conn/conn.go generated vendored Normal file
View File

@ -0,0 +1,103 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package conn
import "strconv"
// Resource is a basic resource (like a gpio pin) or a device.
type Resource interface {
// String returns a human readable identifier representing this resource in a
// descriptive way for the user. It is the same signature as fmt.Stringer.
String() string
// Halt stops the resource.
//
// Unlike a Conn, a Resource may not be closable, On the other hand, a
// resource can be halted. What halting entails depends on the resource
// device but it should stop motion, sensing loop, light emission or PWM
// output and go back into an inert state.
Halt() error
}
// Duplex declares whether communication can happen simultaneously both ways.
//
// Some protocol can be either depending on configuration settings, like UART.
type Duplex int
const (
// DuplexUnknown is used when the duplex of a connection is yet to be known.
//
// Some protocol can be configured either as half-duplex or full-duplex and
// the connection is not yet is a determinate state.
DuplexUnknown Duplex = 0
// Half means that communication can only occurs one way at a time.
//
// Examples include 1-wire and I²C.
Half Duplex = 1
// Full means that communication occurs simultaneously both ways in a
// synchronized manner.
//
// Examples include SPI (except 3-wire variant).
Full Duplex = 2
)
const duplexName = "DuplexUnknownHalfFull"
var duplexIndex = [...]uint8{0, 13, 17, 21}
func (i Duplex) String() string {
if i < 0 || i >= Duplex(len(duplexIndex)-1) {
return "Duplex(" + strconv.Itoa(int(i)) + ")"
}
return duplexName[duplexIndex[i]:duplexIndex[i+1]]
}
// Conn defines the interface for a connection on a point-to-point
// communication channel.
//
// The connection can either be unidirectional (read-only, write-only) or
// bidirectional (read-write). It can either be half-duplex or full duplex.
//
// This is the lowest common denominator for all point-to-point communication
// channels.
//
// Implementation are expected but not required to also implement the following
// interfaces:
//
// - fmt.Stringer which returns something meaningful to the user like "SPI0.1",
// "I2C1.76", "COM6", etc.
//
// - io.Reader and io.Writer as a way to use io.Copy() for half duplex
// operation.
//
// - io.Closer for the owner of the communication channel.
type Conn interface {
String() string
// Tx does a single transaction.
//
// For full duplex protocols (generally SPI, UART), the two buffers must have
// the same length as both reading and writing happen simultaneously.
//
// For half duplex protocols (I²C), there is no restriction as reading
// happens after writing, and r can be nil.
//
// Query Limits.MaxTxSize() to know if there is a limit on the buffer size
// per Tx() call.
Tx(w, r []byte) error
// Duplex returns the current duplex setting for this point-to-point
// connection.
//
// It is expected to be either Half or Full unless the connection itself is
// in an unknown state.
Duplex() Duplex
}
// Limits returns information about the connection's limits.
type Limits interface {
// MaxTxSize returns the maximum allowed data size to be sent as a single
// I/O.
//
// Returns 0 if undefined.
MaxTxSize() int
}

63
vendor/periph.io/x/periph/conn/doc.go generated vendored Normal file
View File

@ -0,0 +1,63 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package conn defines core interfaces for protocols and connections.
//
// This package and its subpackages describe the base interfaces to connect the
// software with the real world. It doesn't contain any implementation but
// includes registries to enable the application to discover the available
// hardware.
//
// Concepts
//
// periph uses 3 layered concepts for interfacing:
//
// Bus → Port → Conn
//
// Not every subpackage expose all 3 concepts. In fact, most packages don't.
// For example, SPI doesn't expose Bus as the OSes generally only expose the
// Port, that is, a Chip Select (CS) line must be selected right upfront to get
// an handle. For I²C, there's no Port to configure, so selecting a "slave"
// address is sufficient to jump directly from a Bus to a Conn.
//
// periph doesn't have yet a concept of star-like communication network, like
// an IP network.
//
// Bus
//
// A Bus is a multi-point communication channel where one "master" and multiple
// "slaves" communicate together. In the case of periph, the Bus handle is
// assumed to be the "master". The "master" generally initiates communications
// and selects the "slave" to talk to.
//
// As the "master" selects a "slave" over a bus, a virtual Port is
// automatically created.
//
// Examples include SPI, I²C and 1-wire. In each case, selecting a
// communication line (Chip Select (CS) line for SPI, address for I²C or
// 1-wire) converts the Bus into a Port.
//
// Port
//
// A port is a point-to-point communication channel that is yet to be
// initialized. It cannot be used for communication until it is connected and
// transformed into a Conn. Configuring a Port converts it into a Conn. Not all
// Port need configuration.
//
// Conn
//
// A Conn is a fully configured half or full duplex communication channel that
// is point-to-point, only between two devices. It is ready to use like any
// readable and/or writable pipe.
//
// Subpackages
//
// Most connection-type specific subpackages include subpackages:
//
// → XXXreg: registry as that is populated by the host drivers and that can be
// leveraged by applications.
//
// → XXXtest: fake implementation that can be leveraged when writing device
// driver unit test.
package conn

3
vendor/periph.io/x/periph/conn/duplex_string.go generated vendored Normal file
View File

@ -0,0 +1,3 @@
// Code generated by "stringer -type Duplex"; DO NOT EDIT
package conn

25
vendor/periph.io/x/periph/conn/gpio/func.go generated vendored Normal file
View File

@ -0,0 +1,25 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package gpio
import "periph.io/x/periph/conn/pin"
const (
// Inputs
IN pin.Func = "IN" // Input
IN_HIGH pin.Func = "In/High" // Read high
IN_LOW pin.Func = "In/Low" // Read low
// Outputs
OUT pin.Func = "OUT" // Output, drive
OUT_OC pin.Func = "OUT_OPEN" // Output, open collector/drain
OUT_HIGH pin.Func = "Out/High" // Drive high
OUT_LOW pin.Func = "Out/Low" // Drive low; open collector low
FLOAT pin.Func = "FLOAT" // Input float or Output open collector high
CLK pin.Func = "CLK" // Clock is a subset of a PWM, with a 50% duty cycle
PWM pin.Func = "PWM" // Pulse Width Modulation, which is a clock with variable duty cycle
)

329
vendor/periph.io/x/periph/conn/gpio/gpio.go generated vendored Normal file
View File

@ -0,0 +1,329 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package gpio defines digital pins.
//
// All GPIO implementations are expected to implement PinIO but the device
// driver may accept a more specific one like PinIn or PinOut.
package gpio
import (
"errors"
"strconv"
"strings"
"time"
"periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/pin"
)
// Interfaces
// Level is the level of the pin: Low or High.
type Level bool
const (
// Low represents 0v.
Low Level = false
// High represents Vin, generally 3.3v or 5v.
High Level = true
)
func (l Level) String() string {
if l == Low {
return "Low"
}
return "High"
}
// Pull specifies the internal pull-up or pull-down for a pin set as input.
type Pull uint8
// Acceptable pull values.
const (
PullNoChange Pull = 0 // Do not change the previous pull resistor setting or an unknown value
Float Pull = 1 // Let the input float
PullDown Pull = 2 // Apply pull-down
PullUp Pull = 3 // Apply pull-up
)
const pullName = "PullNoChangeFloatPullDownPullUp"
var pullIndex = [...]uint8{0, 12, 17, 25, 31}
func (i Pull) String() string {
if i >= Pull(len(pullIndex)-1) {
return "Pull(" + strconv.Itoa(int(i)) + ")"
}
return pullName[pullIndex[i]:pullIndex[i+1]]
}
// Edge specifies if an input pin should have edge detection enabled.
//
// Only enable it when needed, since this causes system interrupts.
type Edge int
// Acceptable edge detection values.
const (
NoEdge Edge = 0
RisingEdge Edge = 1
FallingEdge Edge = 2
BothEdges Edge = 3
)
const edgeName = "NoEdgeRisingEdgeFallingEdgeBothEdges"
var edgeIndex = [...]uint8{0, 6, 16, 27, 36}
func (i Edge) String() string {
if i >= Edge(len(edgeIndex)-1) {
return "Edge(" + strconv.Itoa(int(i)) + ")"
}
return edgeName[edgeIndex[i]:edgeIndex[i+1]]
}
const (
// DutyMax is a duty cycle of 100%.
DutyMax Duty = 1 << 24
// DutyHalf is a 50% duty PWM, which boils down to a normal clock.
DutyHalf Duty = DutyMax / 2
)
// Duty is the duty cycle for a PWM.
//
// Valid values are between 0 and DutyMax.
type Duty int32
func (d Duty) String() string {
// TODO(maruel): Implement one fractional number.
return strconv.Itoa(int((d+50)/(DutyMax/100))) + "%"
}
// Valid returns true if the Duty cycle value is valid.
func (d Duty) Valid() bool {
return d >= 0 && d <= DutyMax
}
// ParseDuty parses a string and converts it to a Duty value.
func ParseDuty(s string) (Duty, error) {
percent := strings.HasSuffix(s, "%")
if percent {
s = s[:len(s)-1]
}
i64, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return 0, err
}
i := Duty(i64)
if percent {
// TODO(maruel): Add support for fractional number.
if i < 0 {
return 0, errors.New("duty must be >= 0%")
}
if i > 100 {
return 0, errors.New("duty must be <= 100%")
}
return ((i * DutyMax) + 49) / 100, nil
}
if i < 0 {
return 0, errors.New("duty must be >= 0")
}
if i > DutyMax {
return 0, errors.New("duty must be <= " + strconv.Itoa(int(DutyMax)))
}
return i, nil
}
// PinIn is an input GPIO pin.
//
// It may optionally support internal pull resistor and edge based triggering.
//
// A button is semantically a PinIn. So if you are looking to read from a
// button, PinIn is the interface you are looking for.
type PinIn interface {
pin.Pin
// In setups a pin as an input.
//
// If WaitForEdge() is planned to be called, make sure to use one of the Edge
// value. Otherwise, use NoEdge to not generated unneeded hardware interrupts.
//
// Calling In() will try to empty the accumulated edges but it cannot be 100%
// reliable due to the OS (linux) and its driver. It is possible that on a
// gpio that is as input, doing a quick Out(), In() may return an edge that
// occurred before the Out() call.
In(pull Pull, edge Edge) error
// Read return the current pin level.
//
// Behavior is undefined if In() wasn't used before.
//
// In some rare case, it is possible that Read() fails silently. This happens
// if another process on the host messes up with the pin after In() was
// called. In this case, call In() again.
Read() Level
// WaitForEdge() waits for the next edge or immediately return if an edge
// occurred since the last call.
//
// Only waits for the kind of edge as specified in a previous In() call.
// Behavior is undefined if In() with a value other than NoEdge wasn't called
// before.
//
// Returns true if an edge was detected during or before this call. Return
// false if the timeout occurred or In() was called while waiting, causing the
// function to exit.
//
// Multiple edges may or may not accumulate between two calls to
// WaitForEdge(). The behavior in this case is undefined and is OS driver
// specific.
//
// It is not required to call Read() to reset the edge detection.
//
// Specify -1 to effectively disable timeout.
WaitForEdge(timeout time.Duration) bool
// Pull returns the internal pull resistor if the pin is set as input pin.
//
// Returns PullNoChange if the value cannot be read.
Pull() Pull
// DefaultPull returns the pull that is initialized on CPU/device reset. This
// is useful to determine if the pin is acceptable for operation with
// certain devices.
DefaultPull() Pull
}
// PinOut is an output GPIO pin.
//
// A LED, a buzzer, a servo, are semantically a PinOut. So if you are looking
// to control these, PinOut is the interface you are looking for.
type PinOut interface {
pin.Pin
// Out sets a pin as output if it wasn't already and sets the initial value.
//
// After the initial call to ensure that the pin has been set as output, it
// is generally safe to ignore the error returned.
//
// Out() tries to empty the accumulated edges detected if the gpio was
// previously set as input but this is not 100% guaranteed due to the OS.
Out(l Level) error
// PWM sets the PWM output on supported pins, if the pin has hardware PWM
// support.
//
// To use as a general purpose clock, set duty to DutyHalf. Some pins may
// only support DutyHalf and no other value.
//
// Using 0 as frequency will use the optimal value as supported/preferred by
// the pin.
//
// To use as a servo, see https://en.wikipedia.org/wiki/Servo_control as an
// explanation how to calculate duty.
PWM(duty Duty, f physic.Frequency) error
}
// PinIO is a GPIO pin that supports both input and output. It matches both
// interfaces PinIn and PinOut.
//
// A GPIO pin implementing PinIO may fail at either input or output or both.
type PinIO interface {
pin.Pin
// PinIn
In(pull Pull, edge Edge) error
Read() Level
WaitForEdge(timeout time.Duration) bool
Pull() Pull
DefaultPull() Pull
// PinOut
Out(l Level) error
PWM(duty Duty, f physic.Frequency) error
}
// INVALID implements PinIO and fails on all access.
var INVALID PinIO
// RealPin is implemented by aliased pin and allows the retrieval of the real
// pin underlying an alias.
//
// Aliases are created by RegisterAlias. Aliases permits presenting a user
// friendly GPIO pin name while representing the underlying real pin.
//
// The purpose of the RealPin is to be able to cleanly test whether an arbitrary
// gpio.PinIO returned by ByName is an alias for another pin, and resolve it.
type RealPin interface {
Real() PinIO // Real returns the real pin behind an Alias
}
//
// errInvalidPin is returned when trying to use INVALID.
var errInvalidPin = errors.New("gpio: invalid pin")
func init() {
INVALID = invalidPin{}
}
// invalidPin implements PinIO for compatibility but fails on all access.
type invalidPin struct {
}
func (invalidPin) String() string {
return "INVALID"
}
func (invalidPin) Halt() error {
return nil
}
func (invalidPin) Number() int {
return -1
}
func (invalidPin) Name() string {
return "INVALID"
}
func (invalidPin) Function() string {
return ""
}
func (invalidPin) Func() pin.Func {
return pin.FuncNone
}
func (invalidPin) SupportedFuncs() []pin.Func {
return nil
}
func (invalidPin) SetFunc(f pin.Func) error {
return errInvalidPin
}
func (invalidPin) In(Pull, Edge) error {
return errInvalidPin
}
func (invalidPin) Read() Level {
return Low
}
func (invalidPin) WaitForEdge(timeout time.Duration) bool {
return false
}
func (invalidPin) Pull() Pull {
return PullNoChange
}
func (invalidPin) DefaultPull() Pull {
return PullNoChange
}
func (invalidPin) Out(Level) error {
return errInvalidPin
}
func (invalidPin) PWM(Duty, physic.Frequency) error {
return errInvalidPin
}
var _ PinIn = INVALID
var _ PinOut = INVALID
var _ PinIO = INVALID
var _ pin.PinFunc = &invalidPin{}

213
vendor/periph.io/x/periph/conn/gpio/gpioreg/gpioreg.go generated vendored Normal file
View File

@ -0,0 +1,213 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package gpioreg defines a registry for the known digital pins.
package gpioreg
import (
"errors"
"strconv"
"sync"
"periph.io/x/periph/conn/gpio"
)
// ByName returns a GPIO pin from its name, gpio number or one of its aliases.
//
// For example on a Raspberry Pi, the following values will return the same
// GPIO: the gpio as a number "2", the chipset name "GPIO2", the board pin
// position "P1_3", it's function name "I2C1_SDA".
//
// Returns nil if the gpio pin is not present.
func ByName(name string) gpio.PinIO {
mu.Lock()
defer mu.Unlock()
if p, ok := byName[name]; ok {
return p
}
if dest, ok := byAlias[name]; ok {
if p := getByNameDeep(dest); p != nil {
// Wraps the destination in an alias, so the name makes sense to the user.
// The main drawback is that casting into other gpio interfaces like
// gpio.PinPWM requires going through gpio.RealPin first.
return &pinAlias{p, name}
}
}
return nil
}
// All returns all the GPIO pins available on this host.
//
// The list is guaranteed to be in order of name using 'natural sorting'.
//
// This list excludes aliases.
//
// This list excludes non-GPIO pins like GROUND, V3_3, etc, since they are not
// GPIO.
func All() []gpio.PinIO {
mu.Lock()
defer mu.Unlock()
out := make([]gpio.PinIO, 0, len(byName))
for _, p := range byName {
out = insertPinByName(out, p)
}
return out
}
// Aliases returns all pin aliases.
//
// The list is guaranteed to be in order of aliase name.
func Aliases() []gpio.PinIO {
mu.Lock()
defer mu.Unlock()
out := make([]gpio.PinIO, 0, len(byAlias))
for name, dest := range byAlias {
// Skip aliases that were not resolved.
if p := getByNameDeep(dest); p != nil {
out = insertPinByName(out, &pinAlias{p, name})
}
}
return out
}
// Register registers a GPIO pin.
//
// Registering the same pin number or name twice is an error.
//
// The pin registered cannot implement the interface RealPin.
func Register(p gpio.PinIO) error {
name := p.Name()
if len(name) == 0 {
return errors.New("gpioreg: can't register a pin with no name")
}
if r, ok := p.(gpio.RealPin); ok {
return errors.New("gpioreg: can't register pin " + strconv.Quote(name) + ", it is already an alias to " + strconv.Quote(r.Real().String()))
}
mu.Lock()
defer mu.Unlock()
if orig, ok := byName[name]; ok {
return errors.New("gpioreg: can't register pin " + strconv.Quote(name) + " twice; already registered as " + strconv.Quote(orig.String()))
}
if dest, ok := byAlias[name]; ok {
return errors.New("gpioreg: can't register pin " + strconv.Quote(name) + "; an alias already exist to: " + strconv.Quote(dest))
}
byName[name] = p
return nil
}
// RegisterAlias registers an alias for a GPIO pin.
//
// It is possible to register an alias for a pin that itself has not been
// registered yet. It is valid to register an alias to another alias. It is
// valid to register the same alias multiple times, overriding the previous
// alias.
func RegisterAlias(alias string, dest string) error {
if len(alias) == 0 {
return errors.New("gpioreg: can't register an alias with no name")
}
if len(dest) == 0 {
return errors.New("gpioreg: can't register alias " + strconv.Quote(alias) + " with no dest")
}
mu.Lock()
defer mu.Unlock()
if _, ok := byName[alias]; ok {
return errors.New("gpioreg: can't register alias " + strconv.Quote(alias) + " for a pin that exists")
}
byAlias[alias] = dest
return nil
}
// Unregister removes a previously registered GPIO pin or alias from the GPIO
// pin registry.
//
// This can happen when a GPIO pin is exposed via an USB device and the device
// is unplugged, or when a generic OS provided pin is superseded by a CPU
// specific implementation.
func Unregister(name string) error {
mu.Lock()
defer mu.Unlock()
if _, ok := byName[name]; ok {
delete(byName, name)
return nil
}
if _, ok := byAlias[name]; ok {
delete(byAlias, name)
return nil
}
return errors.New("gpioreg: can't unregister unknown pin name " + strconv.Quote(name))
}
//
var (
mu sync.Mutex
byName = map[string]gpio.PinIO{}
byAlias = map[string]string{}
)
// pinAlias implements an alias for a PinIO.
//
// pinAlias implements the RealPin interface, which allows querying for the
// real pin under the alias.
type pinAlias struct {
gpio.PinIO
name string
}
// String returns the alias name along the real pin's Name() in parenthesis, if
// known, else the real pin's number.
func (a *pinAlias) String() string {
return a.name + "(" + a.PinIO.Name() + ")"
}
// Name returns the pinAlias's name.
func (a *pinAlias) Name() string {
return a.name
}
// Real returns the real pin behind the alias
func (a *pinAlias) Real() gpio.PinIO {
return a.PinIO
}
// getByNameDeep recursively resolves the aliases to get the pin.
func getByNameDeep(name string) gpio.PinIO {
if p, ok := byName[name]; ok {
return p
}
if dest, ok := byAlias[name]; ok {
if p := getByNameDeep(dest); p != nil {
// Return the deep pin directly, bypassing the aliases.
return p
}
}
return nil
}
// insertPinByName inserts pin p into list l while keeping l ordered by name.
func insertPinByName(l []gpio.PinIO, p gpio.PinIO) []gpio.PinIO {
n := p.Name()
i := search(len(l), func(i int) bool { return lessNatural(n, l[i].Name()) })
l = append(l, nil)
copy(l[i+1:], l[i:])
l[i] = p
return l
}
// search implements the same algorithm as sort.Search().
//
// It was extracted to to not depend on sort, which depends on reflect.
func search(n int, f func(int) bool) int {
lo := 0
for hi := n; lo < hi; {
if i := int(uint(lo+hi) >> 1); !f(i) {
lo = i + 1
} else {
hi = i
}
}
return lo
}

76
vendor/periph.io/x/periph/conn/gpio/gpioreg/natsort.go generated vendored Normal file
View File

@ -0,0 +1,76 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package gpioreg
import (
"strconv"
)
// lessNatural does a 'natural' comparison on the two strings.
//
// It is extracted from https://github.com/maruel/natural.
func lessNatural(a, b string) bool {
for {
if a == b {
return false
}
if p := commonPrefix(a, b); p != 0 {
a = a[p:]
b = b[p:]
}
if ia := digits(a); ia > 0 {
if ib := digits(b); ib > 0 {
// Both sides have digits.
an, aerr := strconv.ParseUint(a[:ia], 10, 64)
bn, berr := strconv.ParseUint(b[:ib], 10, 64)
if aerr == nil && berr == nil {
if an != bn {
return an < bn
}
// Semantically the same digits, e.g. "00" == "0", "01" == "1". In
// this case, only continue processing if there's trailing data on
// both sides, otherwise do lexical comparison.
if ia != len(a) && ib != len(b) {
a = a[ia:]
b = b[ib:]
continue
}
}
}
}
return a < b
}
}
// commonPrefix returns the common prefix except for digits.
func commonPrefix(a, b string) int {
m := len(a)
if n := len(b); n < m {
m = n
}
if m == 0 {
return 0
}
_ = a[m-1]
_ = b[m-1]
for i := 0; i < m; i++ {
ca := a[i]
cb := b[i]
if (ca >= '0' && ca <= '9') || (cb >= '0' && cb <= '9') || ca != cb {
return i
}
}
return m
}
func digits(s string) int {
for i := 0; i < len(s); i++ {
c := s[i]
if c < '0' || c > '9' {
return i
}
}
return len(s)
}

View File

@ -0,0 +1,217 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package gpiostream defines digital streams.
//
// Warning
//
// This package is still in flux as development is on-going.
package gpiostream
import (
"fmt"
"time"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/physic"
)
// Stream is the interface to define a generic stream.
type Stream interface {
// Frequency is the minimum data rate at which the binary stream is usable.
//
// For example, a bit stream may have a 10kHz data rate.
Frequency() physic.Frequency
// Duration of the binary stream. For infinitely looping streams, it is the
// duration of the non-looping part.
Duration() time.Duration
}
// BitStream is a stream of bits to be written or read.
type BitStream struct {
// Bits is a densely packed bitstream.
//
// The stream is required to be a multiple of 8 samples.
Bits []byte
// Freq is the rate at each the bit (not byte) stream should be processed.
Freq physic.Frequency
// LSBF when true means than Bits is in LSB-first. When false, the data is
// MSB-first.
//
// With MSBF, the first bit processed is the most significant one (0x80). For
// example, I²C, I2S PCM and SPI use MSB-first at the word level. This
// requires to pack words correctly.
//
// With LSBF, the first bit processed is the least significant one (0x01).
// For example, Ethernet uses LSB-first at the byte level and MSB-first at
// the word level.
LSBF bool
}
// Frequency implements Stream.
func (b *BitStream) Frequency() physic.Frequency {
return b.Freq
}
// Duration implements Stream.
func (b *BitStream) Duration() time.Duration {
if b.Freq == 0 {
return 0
}
return b.Freq.Duration() * time.Duration(len(b.Bits)*8)
}
// GoString implements fmt.GoStringer.
func (b *BitStream) GoString() string {
return fmt.Sprintf("&gpiostream.BitStream{Bits: %x, Freq:%s, LSBF:%t}", b.Bits, b.Freq, b.LSBF)
}
// EdgeStream is a stream of edges to be written.
//
// This struct is more efficient than BitStream for short repetitive pulses,
// like controlling a servo. A PWM can be created by specifying a slice of
// twice the same resolution and make it looping via a Program.
type EdgeStream struct {
// Edges is the list of Level change. It is assumed that the signal starts
// with gpio.High. Use a duration of 0 for Edges[0] to start with a Low
// instead of the default High.
//
// The value is a multiple of Res. Use a 0 value to 'extend' a continuous
// signal that lasts more than "2^16-1*Res" duration by skipping a pulse.
Edges []uint16
// Res is the minimum resolution at which the edges should be
// rasterized.
//
// The lower the value, the more memory shall be used when rasterized.
Freq physic.Frequency
}
// Frequency implements Stream.
func (e *EdgeStream) Frequency() physic.Frequency {
return e.Freq
}
// Duration implements Stream.
func (e *EdgeStream) Duration() time.Duration {
if e.Freq == 0 {
return 0
}
t := 0
for _, edge := range e.Edges {
t += int(edge)
}
return e.Freq.Duration() * time.Duration(t)
}
// Program is a loop of streams.
//
// This is itself a stream, it can be used to reduce memory usage when repeated
// patterns are used.
type Program struct {
Parts []Stream // Each part must be a BitStream, EdgeStream or Program
Loops int // Set to -1 to create an infinite loop
}
// Frequency implements Stream.
func (p *Program) Frequency() physic.Frequency {
if p.Loops == 0 {
return 0
}
var buf [16]physic.Frequency
freqs := buf[:0]
for _, part := range p.Parts {
if f := part.Frequency(); f != 0 {
freqs = insertFreq(freqs, f)
}
}
if len(freqs) == 0 {
return 0
}
f := freqs[0]
for i := 1; i < len(freqs); i++ {
if r := freqs[i]; r*2 < f {
break
}
// Take in account Nyquist rate. https://wikipedia.org/wiki/Nyquist_rate
f *= 2
}
return f
}
// Duration implements Stream.
func (p *Program) Duration() time.Duration {
if p.Loops == 0 {
return 0
}
var d time.Duration
for _, s := range p.Parts {
d += s.Duration()
}
if p.Loops > 1 {
d *= time.Duration(p.Loops)
}
return d
}
//
// PinIn allows to read a bit stream from a pin.
//
// Caveat
//
// This interface doesn't enable sampling multiple pins in a
// synchronized way or reading in a continuous uninterrupted way. As such, it
// should be considered experimental.
type PinIn interface {
// StreamIn reads for the pin at the specified resolution to fill the
// provided buffer.
//
// May only support a subset of the structs implementing Stream.
StreamIn(p gpio.Pull, b Stream) error
}
// PinOut allows to stream to a pin.
//
// The Stream may be a Program, a BitStream or an EdgeStream. If it is a
// Program that is an infinite loop, a separate goroutine can be used to cancel
// the program. In this case StreamOut() returns without an error.
//
// Caveat
//
// This interface doesn't enable streaming to multiple pins in a
// synchronized way or reading in a continuous uninterrupted way. As such, it
// should be considered experimental.
type PinOut interface {
StreamOut(s Stream) error
}
//
// insertFreq inserts in reverse order, highest frequency first.
func insertFreq(l []physic.Frequency, f physic.Frequency) []physic.Frequency {
i := search(len(l), func(i int) bool { return l[i] < f })
l = append(l, 0)
copy(l[i+1:], l[i:])
l[i] = f
return l
}
// search implements the same algorithm as sort.Search().
//
// It was extracted to to not depend on sort, which depends on reflect.
func search(n int, f func(int) bool) int {
lo := 0
for hi := n; lo < hi; {
if i := int(uint(lo+hi) >> 1); !f(i) {
lo = i + 1
} else {
hi = i
}
}
return lo
}
var _ Stream = &BitStream{}
var _ Stream = &EdgeStream{}
var _ Stream = &Program{}

12
vendor/periph.io/x/periph/conn/i2c/func.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package i2c
import "periph.io/x/periph/conn/pin"
const (
SCL pin.Func = "I2C_SCL" // Clock
SDA pin.Func = "I2C_SDA" // Data
)

114
vendor/periph.io/x/periph/conn/i2c/i2c.go generated vendored Normal file
View File

@ -0,0 +1,114 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package i2c defines the API to communicate with devices over the I²C
// protocol.
//
// As described in https://periph.io/x/periph/conn#hdr-Concepts, periph.io uses
// the concepts of Bus, Port and Conn.
//
// In the package i2c, 'Port' is not exposed, since once you know the I²C
// device address, there's no unconfigured Port to configure.
//
// Instead, the package includes the adapter 'Dev' to directly convert an I²C
// bus 'i2c.Bus' into a connection 'conn.Conn' by only specifying the device
// I²C address.
//
// See https://en.wikipedia.org/wiki/I%C2%B2C for more information.
package i2c
import (
"io"
"strconv"
"periph.io/x/periph/conn"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/physic"
)
// Bus defines the interface a concrete I²C driver must implement.
//
// This interface is consummed by a device driver for a device sitting on a bus.
//
// This interface doesn't implement conn.Conn since a device address must be
// specified. Use i2cdev.Dev as an adapter to get a conn.Conn compatible
// object.
type Bus interface {
String() string
// Tx does a transaction at the specified device address.
//
// Write is done first, then read. One of 'w' or 'r' can be omitted for a
// unidirectional operation.
Tx(addr uint16, w, r []byte) error
// SetSpeed changes the bus speed, if supported.
//
// On linux due to the way the I²C sysfs driver is exposed in userland,
// calling this function will likely affect *all* I²C buses on the host.
SetSpeed(f physic.Frequency) error
}
// BusCloser is an I²C bus that can be closed.
//
// This interface is meant to be handled by the application and not the device
// driver. A device driver doesn't "own" a bus, hence it must operate on a Bus,
// not a BusCloser.
type BusCloser interface {
io.Closer
Bus
}
// Pins defines the pins that an I²C bus interconnect is using on the host.
//
// It is expected that a implementer of Bus also implement Pins but this is not
// a requirement.
type Pins interface {
// SCL returns the CLK (clock) pin.
SCL() gpio.PinIO
// SDA returns the DATA pin.
SDA() gpio.PinIO
}
// Dev is a device on a I²C bus.
//
// It implements conn.Conn.
//
// It saves from repeatedly specifying the device address.
type Dev struct {
Bus Bus
Addr uint16
}
func (d *Dev) String() string {
s := "<nil>"
if d.Bus != nil {
s = d.Bus.String()
}
return s + "(" + strconv.Itoa(int(d.Addr)) + ")"
}
// Tx does a transaction by adding the device's address to each command.
//
// It's a wrapper for Bus.Tx().
func (d *Dev) Tx(w, r []byte) error {
return d.Bus.Tx(d.Addr, w, r)
}
// Write writes to the I²C bus without reading, implementing io.Writer.
//
// It's a wrapper for Tx()
func (d *Dev) Write(b []byte) (int, error) {
if err := d.Tx(b, nil); err != nil {
return 0, err
}
return len(b), nil
}
// Duplex always return conn.Half for I²C.
func (d *Dev) Duplex() conn.Duplex {
return conn.Half
}
//
var _ conn.Conn = &Dev{}

252
vendor/periph.io/x/periph/conn/i2c/i2creg/i2creg.go generated vendored Normal file
View File

@ -0,0 +1,252 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package i2creg defines I²C bus registry to list buses present on the host.
package i2creg
import (
"errors"
"strconv"
"strings"
"sync"
"periph.io/x/periph/conn/i2c"
)
// Opener opens an handle to a bus.
//
// It is provided by the actual bus driver.
type Opener func() (i2c.BusCloser, error)
// Ref references an I²C bus.
//
// It is returned by All() to enumerate all registered buses.
type Ref struct {
// Name of the bus.
//
// It must not be a sole number. It must be unique across the host.
Name string
// Aliases are the alternative names that can be used to reference this bus.
Aliases []string
// Number of the bus or -1 if the bus doesn't have any "native" number.
//
// Buses provided by the CPU normally have a 0 based number. Buses provided
// via an addon (like over USB) generally are not numbered.
Number int
// Open is the factory to open an handle to this I²C bus.
Open Opener
}
// Open opens an I²C bus by its name, an alias or its number and returns an
// handle to it.
//
// Specify the empty string "" to get the first available bus. This is the
// recommended default value unless an application knows the exact bus to use.
//
// Each bus can register multiple aliases, each leading to the same bus handle.
//
// "Bus number" is a generic concept that is highly dependent on the platform
// and OS. On some platform, the first bus may have the number 0, 1 or higher.
// Bus numbers are not necessarily continuous and may not start at 0. It was
// observed that the bus number as reported by the OS may change across OS
// revisions.
//
// When the I²C bus is provided by an off board plug and play bus like USB via
// a FT232H USB device, there can be no associated number.
func Open(name string) (i2c.BusCloser, error) {
var r *Ref
var err error
func() {
mu.Lock()
defer mu.Unlock()
if len(byName) == 0 {
err = errors.New("i2creg: no bus found; did you forget to call Init()?")
return
}
if len(name) == 0 {
r = getDefault()
return
}
// Try by name, by alias, by number.
if r = byName[name]; r == nil {
if r = byAlias[name]; r == nil {
if i, err2 := strconv.Atoi(name); err2 == nil {
r = byNumber[i]
}
}
}
}()
if err != nil {
return nil, err
}
if r == nil {
return nil, errors.New("i2creg: can't open unknown bus: " + strconv.Quote(name))
}
return r.Open()
}
// All returns a copy of all the registered references to all know I²C buses
// available on this host.
//
// The list is sorted by the bus name.
func All() []*Ref {
mu.Lock()
defer mu.Unlock()
out := make([]*Ref, 0, len(byName))
for _, v := range byName {
r := &Ref{Name: v.Name, Aliases: make([]string, len(v.Aliases)), Number: v.Number, Open: v.Open}
copy(r.Aliases, v.Aliases)
out = insertRef(out, r)
}
return out
}
// Register registers an I²C bus.
//
// Registering the same bus name twice is an error, e.g. o.Name(). o.Number()
// can be -1 to signify that the bus doesn't have an inherent "bus number". A
// good example is a bus provided over a FT232H device connected on an USB bus.
// In this case, the bus name should be created from the serial number of the
// device for unique identification.
func Register(name string, aliases []string, number int, o Opener) error {
if len(name) == 0 {
return errors.New("i2creg: can't register a bus with no name")
}
if o == nil {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " with nil Opener")
}
if number < -1 {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " with invalid bus number " + strconv.Itoa(number))
}
if _, err := strconv.Atoi(name); err == nil {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " with name being only a number")
}
if strings.Contains(name, ":") {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " with name containing ':'")
}
for _, alias := range aliases {
if len(alias) == 0 {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " with an empty alias")
}
if name == alias {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " with an alias the same as the bus name")
}
if _, err := strconv.Atoi(alias); err == nil {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " with an alias that is a number: " + strconv.Quote(alias))
}
if strings.Contains(alias, ":") {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " with an alias containing ':': " + strconv.Quote(alias))
}
}
mu.Lock()
defer mu.Unlock()
if _, ok := byName[name]; ok {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " twice")
}
if _, ok := byAlias[name]; ok {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " twice; it is already an alias")
}
if number != -1 {
if _, ok := byNumber[number]; ok {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + "; bus number " + strconv.Itoa(number) + " is already registered")
}
}
for _, alias := range aliases {
if _, ok := byName[alias]; ok {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " twice; alias " + strconv.Quote(alias) + " is already a bus")
}
if _, ok := byAlias[alias]; ok {
return errors.New("i2creg: can't register bus " + strconv.Quote(name) + " twice; alias " + strconv.Quote(alias) + " is already an alias")
}
}
r := &Ref{Name: name, Aliases: make([]string, len(aliases)), Number: number, Open: o}
copy(r.Aliases, aliases)
byName[name] = r
if number != -1 {
byNumber[number] = r
}
for _, alias := range aliases {
byAlias[alias] = r
}
return nil
}
// Unregister removes a previously registered I²C bus.
//
// This can happen when an I²C bus is exposed via an USB device and the device
// is unplugged.
func Unregister(name string) error {
mu.Lock()
defer mu.Unlock()
r := byName[name]
if r == nil {
return errors.New("i2creg: can't unregister unknown bus name " + strconv.Quote(name))
}
delete(byName, name)
delete(byNumber, r.Number)
for _, alias := range r.Aliases {
delete(byAlias, alias)
}
return nil
}
//
var (
mu sync.Mutex
byName = map[string]*Ref{}
// Caches
byNumber = map[int]*Ref{}
byAlias = map[string]*Ref{}
)
// getDefault returns the Ref that should be used as the default bus.
func getDefault() *Ref {
var o *Ref
if len(byNumber) == 0 {
// Fallback to use byName using a lexical sort.
name := ""
for n, o2 := range byName {
if len(name) == 0 || n < name {
o = o2
name = n
}
}
return o
}
number := int((^uint(0)) >> 1)
for n, o2 := range byNumber {
if number > n {
number = n
o = o2
}
}
return o
}
func insertRef(l []*Ref, r *Ref) []*Ref {
n := r.Name
i := search(len(l), func(i int) bool { return l[i].Name > n })
l = append(l, nil)
copy(l[i+1:], l[i:])
l[i] = r
return l
}
// search implements the same algorithm as sort.Search().
//
// It was extracted to to not depend on sort, which depends on reflect.
func search(n int, f func(int) bool) int {
lo := 0
for hi := n; lo < hi; {
if i := int(uint(lo+hi) >> 1); !f(i) {
lo = i + 1
} else {
hi = i
}
}
return lo
}

9
vendor/periph.io/x/periph/conn/physic/doc.go generated vendored Normal file
View File

@ -0,0 +1,9 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package physic declares types for physical input, outputs and measurement
// units.
//
// This includes temperature, humidity, pressure, tension, current, etc.
package physic

42
vendor/periph.io/x/periph/conn/physic/physic.go generated vendored Normal file
View File

@ -0,0 +1,42 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package physic
import (
"time"
"periph.io/x/periph/conn"
)
// Env represents measurements from an environmental sensor.
type Env struct {
Temperature Temperature
Pressure Pressure
Humidity RelativeHumidity
}
// SenseEnv represents an environmental sensor.
type SenseEnv interface {
conn.Resource
// Sense returns the value read from the sensor. Unsupported metrics are not
// modified.
Sense(env *Env) error
// SenseContinuous initiates a continuous sensing at the specified interval.
//
// It is important to call Halt() once done with the sensing, which will turn
// the device off and will close the channel.
SenseContinuous(interval time.Duration) (<-chan Env, error)
// Precision returns this sensor's precision.
//
// The env values are set to the number of bits that are significant for each
// items that this sensor can measure.
//
// Precision is not accuracy. The sensor may have absolute and relative
// errors in its measurement, that are likely well above the reported
// precision. Accuracy may be improved on some sensor by using oversampling,
// or doing oversampling in software. Refer to its datasheet if available.
Precision(env *Env)
}

1043
vendor/periph.io/x/periph/conn/physic/units.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

58
vendor/periph.io/x/periph/conn/pin/func.go generated vendored Normal file
View File

@ -0,0 +1,58 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package pin
import (
"strconv"
"strings"
)
// Func is a pin function.
//
// The Func format must be "[A-Z]+", "[A-Z]+_[A-Z]+" or exceptionally
// "(In|Out)/(Low|High)".
type Func string
// FuncNone is returned by PinFunc.Func() for a Pin without an active
// functionality.
const FuncNone Func = ""
// Specialize converts a "BUS_LINE" function and appends the bug number and
// line number, to look like "BUS0_LINE1".
//
// Use -1 to not add a bus or line number.
func (f Func) Specialize(b, l int) Func {
if f == FuncNone {
return FuncNone
}
if b != -1 {
parts := strings.SplitN(string(f), "_", 2)
if len(parts) == 1 {
return FuncNone
}
f = Func(parts[0] + strconv.Itoa(b) + "_" + parts[1])
}
if l != -1 {
f += Func(strconv.Itoa(l))
}
return f
}
// Generalize is the reverse of Specialize().
func (f Func) Generalize() Func {
parts := strings.SplitN(string(f), "_", 2)
f = Func(strings.TrimRightFunc(parts[0], isNum))
if len(parts) == 2 {
f += "_"
f += Func(strings.TrimRightFunc(parts[1], isNum))
}
return f
}
//
func isNum(r rune) bool {
return r >= '0' && r <= '9'
}

139
vendor/periph.io/x/periph/conn/pin/pin.go generated vendored Normal file
View File

@ -0,0 +1,139 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package pin declare well known pins.
//
// pin is about physical pins, not about their logical function.
//
// While not a protocol strictly speaking, these are "well known constants".
package pin
import (
"errors"
"periph.io/x/periph/conn"
)
// These are well known pins.
var (
INVALID *BasicPin // Either floating or invalid pin
GROUND *BasicPin // Ground
V1_8 *BasicPin // 1.8V (filtered)
V2_8 *BasicPin // 2.8V (filtered)
V3_3 *BasicPin // 3.3V (filtered)
V5 *BasicPin // 5V (filtered)
DC_IN *BasicPin // DC IN; this is normally the 5V input
BAT_PLUS *BasicPin // LiPo Battery + connector
)
// Pin is the minimal common interface shared between gpio.PinIO and
// analog.PinIO.
type Pin interface {
conn.Resource
// Name returns the name of the pin.
Name() string
// Number returns the logical pin number or a negative number if the pin is
// not a GPIO, e.g. GROUND, V3_3, etc.
Number() int
// Function returns a user readable string representation of what the pin is
// configured to do. Common case is In and Out but it can be bus specific pin
// name.
//
// Deprecated: Use PinFunc.Func. Will be removed in v4.
Function() string
}
// PinFunc is a supplementary interface that enables specifically querying for
// the pin function.
//
// TODO(maruel): It will be merged into interface Pin for v4.
type PinFunc interface {
// Func returns the pin's current function.
//
// The returned value may be specialized or generalized, depending on the
// actual port. For example it will likely be generalized for ports served
// over USB (like a FT232H with D0 set as SPI_MOSI) but specialized for
// ports on the base board (like a RPi3 with GPIO10 set as SPI0_MOSI).
Func() Func
// SupportedFuncs returns the possible functions this pin support.
//
// Do not mutate the returned slice.
SupportedFuncs() []Func
// SetFunc sets the pin function.
//
// Example use is to reallocate a RPi3's GPIO14 active function between
// UART0_TX and UART1_TX.
SetFunc(f Func) error
}
//
// BasicPin implements Pin as a static pin.
//
// It doesn't have a usable functionality.
type BasicPin struct {
N string
}
// String implements conn.Resource.
func (b *BasicPin) String() string {
return b.N
}
// Halt implements conn.Resource.
func (b *BasicPin) Halt() error {
return nil
}
// Name implements Pin.
func (b *BasicPin) Name() string {
return b.N
}
// Number implements Pin.
//
// Returns -1 as pin number.
func (b *BasicPin) Number() int {
return -1
}
// Function implements Pin.
//
// Returns "" as pin function.
func (b *BasicPin) Function() string {
return ""
}
// Func implements PinFunc.
//
// Returns FuncNone as pin function.
func (b *BasicPin) Func() Func {
return FuncNone
}
// SupportedFuncs implements PinFunc.
//
// Returns nil.
func (b *BasicPin) SupportedFuncs() []Func {
return nil
}
// SetFunc implements PinFunc.
func (b *BasicPin) SetFunc(f Func) error {
return errors.New("pin: can't change static pin function")
}
func init() {
INVALID = &BasicPin{N: "INVALID"}
GROUND = &BasicPin{N: "GROUND"}
V1_8 = &BasicPin{N: "1.8V"}
V2_8 = &BasicPin{N: "2.8V"}
V3_3 = &BasicPin{N: "3.3V"}
V5 = &BasicPin{N: "5V"}
DC_IN = &BasicPin{N: "DC_IN"}
BAT_PLUS = &BasicPin{N: "BAT+"}
}
var _ Pin = INVALID
var _ PinFunc = INVALID

7
vendor/periph.io/x/periph/conn/pin/pinreg/doc.go generated vendored Normal file
View File

@ -0,0 +1,7 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package pinreg is a registry for the physical headers (made up of pins) on
// a host.
package pinreg

148
vendor/periph.io/x/periph/conn/pin/pinreg/pinreg.go generated vendored Normal file
View File

@ -0,0 +1,148 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package pinreg
import (
"errors"
"strconv"
"sync"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/gpio/gpioreg"
"periph.io/x/periph/conn/pin"
)
// All contains all the on-board headers on a micro computer.
//
// The map key is the header name, e.g. "P1" or "EULER" and the value is a
// slice of slice of pin.Pin. For a 2x20 header, it's going to be a slice of
// [20][2]pin.Pin.
func All() map[string][][]pin.Pin {
mu.Lock()
defer mu.Unlock()
out := make(map[string][][]pin.Pin, len(allHeaders))
for k, v := range allHeaders {
outV := make([][]pin.Pin, len(v))
for i, w := range v {
outW := make([]pin.Pin, len(w))
copy(outW, w)
outV[i] = outW
}
out[k] = outV
}
return out
}
// Position returns the position on a pin if found.
//
// The header and the pin number. Pin numbers are 1-based.
//
// Returns "", 0 if not connected.
func Position(p pin.Pin) (string, int) {
mu.Lock()
defer mu.Unlock()
pos, _ := byPin[realPin(p).Name()]
return pos.name, pos.number
}
// IsConnected returns true if the pin is on a header.
func IsConnected(p pin.Pin) bool {
_, i := Position(p)
return i != 0
}
// Register registers a physical header.
//
// It automatically registers all gpio pins to gpioreg.
func Register(name string, allPins [][]pin.Pin) error {
mu.Lock()
defer mu.Unlock()
if _, ok := allHeaders[name]; ok {
return errors.New("pinreg: header " + strconv.Quote(name) + " was already registered")
}
for i, line := range allPins {
for j, pin := range line {
if pin == nil || len(pin.Name()) == 0 {
return errors.New("pinreg: invalid pin on header " + name + "[" + strconv.Itoa(i+1) + "][" + strconv.Itoa(j+1) + "]")
}
}
}
allHeaders[name] = allPins
number := 1
for _, line := range allPins {
for _, p := range line {
byPin[realPin(p).Name()] = position{name, number}
number++
}
}
count := 0
for _, row := range allPins {
for _, p := range row {
count++
if _, ok := p.(gpio.PinIO); ok {
if err := gpioreg.RegisterAlias(name+"_"+strconv.Itoa(count), p.Name()); err != nil {
// Unregister as much as possible.
_ = unregister(name)
return errors.New("pinreg: " + err.Error())
}
}
}
}
return nil
}
// Unregister removes a previously registered header.
//
// This can happen when an USB device, which exposed an header, is unplugged.
// This is also useful for unit testing.
func Unregister(name string) error {
mu.Lock()
defer mu.Unlock()
return unregister(name)
}
//
type position struct {
name string // Header name
number int // Pin number
}
var (
mu sync.Mutex
allHeaders = map[string][][]pin.Pin{} // every known headers as per internal lookup table
byPin = map[string]position{} // GPIO pin name to position
)
func unregister(name string) error {
if hdr, ok := allHeaders[name]; ok {
var err error
delete(allHeaders, name)
count := 0
for _, row := range hdr {
for _, p := range row {
count++
if _, ok := p.(gpio.PinIO); ok {
if err1 := gpioreg.Unregister(name + "_" + strconv.Itoa(count)); err1 != nil && err == nil {
// Continue unregistering as much as possible.
err = errors.New("pinreg: " + err1.Error())
}
}
}
}
return err
}
return errors.New("pinreg: can't unregister unknown header name " + strconv.Quote(name))
}
// realPin returns the real pin from an alias.
func realPin(p pin.Pin) pin.Pin {
if r, ok := p.(gpio.RealPin); ok {
p = r.Real()
}
return p
}

14
vendor/periph.io/x/periph/conn/spi/func.go generated vendored Normal file
View File

@ -0,0 +1,14 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package spi
import "periph.io/x/periph/conn/pin"
const (
CLK pin.Func = "SPI_CLK" // Clock
CS pin.Func = "SPI_CS" // Chip select
MISO pin.Func = "SPI_MISO" // Master in
MOSI pin.Func = "SPI_MOSI" // Master out
)

187
vendor/periph.io/x/periph/conn/spi/spi.go generated vendored Normal file
View File

@ -0,0 +1,187 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package spi defines the API to communicate with devices over the SPI
// protocol.
//
// As described in https://periph.io/x/periph/conn#hdr-Concepts, periph.io uses
// the concepts of Bus, Port and Conn.
//
// In the package spi, 'Bus' is not exposed, as it would be SPI bus number
// without a CS line, for example on linux asking for "/dev/spi0" without the
// ".0" suffix.
//
// The OS doesn't allow that so it is counter productive to express this at the
// API layer, so 'Port' is exposed directly instead.
//
// Use Port.Connect() converts the uninitialized Port into a Conn.
//
// See https://en.wikipedia.org/wiki/Serial_Peripheral_Interface for more
// information.
package spi
import (
"io"
"strconv"
"periph.io/x/periph/conn"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/physic"
)
// Mode determines how communication is done.
//
// The bits can be OR'ed to change the parameters used for
// communication.
//
type Mode int
// Mode determines the SPI communication parameters.
//
// CPOL means the clock polarity. Idle is High when set.
//
// CPHA is the clock phase, sample on trailing edge when set.
const (
Mode0 Mode = 0x0 // CPOL=0, CPHA=0
Mode1 Mode = 0x1 // CPOL=0, CPHA=1
Mode2 Mode = 0x2 // CPOL=1, CPHA=0
Mode3 Mode = 0x3 // CPOL=1, CPHA=1
// HalfDuplex specifies that MOSI and MISO use the same wire, and that only
// one duplex is used at a time.
HalfDuplex Mode = 0x4
// NoCS request the driver to not use the CS line.
NoCS Mode = 0x8
// LSBFirst requests the words to be encoded in little endian instead of the
// default big endian.
LSBFirst = 0x10
)
func (m Mode) String() string {
s := ""
switch m & Mode3 {
case Mode0:
s = "Mode0"
case Mode1:
s = "Mode1"
case Mode2:
s = "Mode2"
case Mode3:
s = "Mode3"
}
m &^= Mode3
if m&HalfDuplex != 0 {
s += "|HalfDuplex"
}
m &^= HalfDuplex
if m&NoCS != 0 {
s += "|NoCS"
}
m &^= NoCS
if m&LSBFirst != 0 {
s += "|LSBFirst"
}
m &^= LSBFirst
if m != 0 {
s += "|0x"
s += strconv.FormatUint(uint64(m), 16)
}
return s
}
// Packet represents one packet when sending multiple packets as a transaction.
type Packet struct {
// W and R are the output and input data. When HalfDuplex is specified to
// Connect, only one of the two can be set.
W, R []byte
// BitsPerWord overrides the default bits per word value set in Connect.
BitsPerWord uint8
// KeepCS tells the driver to keep CS asserted after this packet is
// completed. This can be leveraged to create long transaction as multiple
// packets like to use 9 bits commands then 8 bits data.
//
// Normally during a spi.Conn.TxPackets() call, KeepCS should be set to true
// for all packets except the last one. If the last one is set to true, the
// CS line stays asserted, leaving the transaction hanging on the bus.
//
// KeepCS is ignored when NoCS was specified to Connect.
KeepCS bool
}
// Conn defines the interface a concrete SPI driver must implement.
//
// Implementers can optionally implement io.Writer and io.Reader for
// unidirectional operation.
type Conn interface {
conn.Conn
// TxPackets does multiple operations over the SPI connection.
//
// The maximum number of bytes can be limited depending on the driver. Query
// conn.Limits.MaxTxSize() can be used to determine the limit.
//
// If the last packet has KeepCS:true, the CS line stays asserted. This
// enables doing SPI transaction over multiple calls.
//
// Conversely, if any packet beside the last one has KeepCS:false, the CS
// line will blip for a short amount of time to force a new transaction.
//
// It was observed on RPi3 hardware to have a one clock delay between each
// packet.
TxPackets(p []Packet) error
}
// Port is the interface to be provided to device drivers.
//
// The device driver, that is the driver for the peripheral connected over
// this port, calls Connect() to retrieve a configured connection as Conn.
type Port interface {
String() string
// Connect sets the communication parameters of the connection for use by a
// device.
//
// The device driver must call this function exactly once.
//
// f must specify the maximum rated speed by the device's spec. The lowest
// speed between the port speed and the device speed is selected. Use 0 for f
// if there is no known maximum value for this device.
//
// mode specifies the clock and signal polarities, if the port is using half
// duplex (shared MISO and MOSI) or if CS is not needed.
//
// bits is the number of bits per word. Generally you should use 8.
Connect(f physic.Frequency, mode Mode, bits int) (Conn, error)
}
// PortCloser is a SPI port that can be closed.
//
// This interface is meant to be handled by the application.
type PortCloser interface {
io.Closer
Port
// LimitSpeed sets the maximum port speed.
//
// It lets an application use a device at a lower speed than the maximum
// speed as rated by the device driver. This is useful for example when the
// wires are long or the connection is of poor quality.
//
// This function can be called multiple times and resets the previous value.
// 0 is not a valid value for f. The lowest speed between the port speed and
// the device speed is selected.
LimitSpeed(f physic.Frequency) error
}
// Pins defines the pins that a SPI port interconnect is using on the host.
//
// It is expected that a implementer of ConnCloser or Conn also implement Pins
// but this is not a requirement.
type Pins interface {
// CLK returns the SCK (clock) pin.
CLK() gpio.PinOut
// MOSI returns the SDO (master out, slave in) pin.
MOSI() gpio.PinOut
// MISO returns the SDI (master in, slave out) pin.
MISO() gpio.PinIn
// CS returns the CSN (chip select) pin.
CS() gpio.PinOut
}

262
vendor/periph.io/x/periph/conn/spi/spireg/spireg.go generated vendored Normal file
View File

@ -0,0 +1,262 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package spireg defines the SPI registry for SPI ports discovered on the host.
//
// SPI ports discovered on the host are automatically registered in the SPI
// registry by host.Init().
package spireg
import (
"errors"
"strconv"
"strings"
"sync"
"periph.io/x/periph/conn/spi"
)
// Opener opens an handle to a port.
//
// It is provided by the actual port driver.
type Opener func() (spi.PortCloser, error)
// Ref references a SPI port.
//
// It is returned by All() to enumerate all registered ports.
type Ref struct {
// Name of the port.
//
// It must not be a sole number. It must be unique across the host.
Name string
// Aliases are the alternative names that can be used to reference this port.
Aliases []string
// Number of the bus or -1 if the bus doesn't have any "native" number.
//
// Buses provided by the CPU normally have a 0 based number. Buses provided
// via an addon (like over USB) generally are not numbered.
//
// The port is a bus number plus a CS line.
Number int
// Open is the factory to open an handle to this SPI port.
Open Opener
}
// Open opens a SPI port by its name, an alias or its number and returns an
// handle to it.
//
// Specify the empty string "" to get the first available port. This is the
// recommended default value unless an application knows the exact port to use.
//
// Each port can register multiple aliases, each leading to the same port
// handle.
//
// "Bus number" is a generic concept that is highly dependent on the platform
// and OS. On some platform, the first port may have the number 0, 1 or as high
// as 32766. Bus numbers are not necessarily continuous and may not start at 0.
// It was observed that the bus number as reported by the OS may change across
// OS revisions.
//
// A SPI port is constructed of the bus number and the chip select (CS) number.
//
// When the SPI port is provided by an off board plug and play bus like USB via
// a FT232H USB device, there can be no associated number.
func Open(name string) (spi.PortCloser, error) {
var r *Ref
var err error
func() {
mu.Lock()
defer mu.Unlock()
if len(byName) == 0 {
err = errors.New("spireg: no port found; did you forget to call Init()?")
return
}
if len(name) == 0 {
r = getDefault()
return
}
// Try by name, by alias, by number.
if r = byName[name]; r == nil {
if r = byAlias[name]; r == nil {
if i, err2 := strconv.Atoi(name); err2 == nil {
r = byNumber[i]
}
}
}
}()
if err != nil {
return nil, err
}
if r == nil {
return nil, errors.New("spireg: can't open unknown port: " + strconv.Quote(name))
}
return r.Open()
}
// All returns a copy of all the registered references to all know SPI ports
// available on this host.
//
// The list is sorted by the port name.
func All() []*Ref {
mu.Lock()
defer mu.Unlock()
out := make([]*Ref, 0, len(byName))
for _, v := range byName {
r := &Ref{Name: v.Name, Aliases: make([]string, len(v.Aliases)), Number: v.Number, Open: v.Open}
copy(r.Aliases, v.Aliases)
out = insertRef(out, r)
}
return out
}
// Register registers a SPI port.
//
// Registering the same port name twice is an error, e.g. o.Name(). o.Number()
// can be -1 to signify that the port doesn't have an inherent "bus number". A
// good example is a port provided over a FT232H device connected on an USB bus.
// In this case, the port name should be created from the serial number of the
// device for unique identification.
//
// Only ports with the CS #0 are registered with their number.
func Register(name string, aliases []string, number int, o Opener) error {
if len(name) == 0 {
return errors.New("spireg: can't register a port with no name")
}
if o == nil {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " with nil Opener")
}
if number < -1 {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " with invalid port number " + strconv.Itoa(number))
}
if _, err := strconv.Atoi(name); err == nil {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " with name being only a number")
}
if strings.Contains(name, ":") {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " with name containing ':'")
}
for _, alias := range aliases {
if len(alias) == 0 {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " with an empty alias")
}
if name == alias {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " with an alias the same as the port name")
}
if _, err := strconv.Atoi(alias); err == nil {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " with an alias that is a number: " + strconv.Quote(alias))
}
if strings.Contains(alias, ":") {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " with an alias containing ':': " + strconv.Quote(alias))
}
}
mu.Lock()
defer mu.Unlock()
if _, ok := byName[name]; ok {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " twice")
}
if _, ok := byAlias[name]; ok {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " twice; it is already an alias")
}
if number != -1 {
if _, ok := byNumber[number]; ok {
return errors.New("spireg: can't register port " + strconv.Quote(name) + "; port number " + strconv.Itoa(number) + " is already registered")
}
}
for _, alias := range aliases {
if _, ok := byName[alias]; ok {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " twice; alias " + strconv.Quote(alias) + " is already a port")
}
if _, ok := byAlias[alias]; ok {
return errors.New("spireg: can't register port " + strconv.Quote(name) + " twice; alias " + strconv.Quote(alias) + " is already an alias")
}
}
r := &Ref{Name: name, Aliases: make([]string, len(aliases)), Number: number, Open: o}
copy(r.Aliases, aliases)
byName[name] = r
if number != -1 {
byNumber[number] = r
}
for _, alias := range aliases {
byAlias[alias] = r
}
return nil
}
// Unregister removes a previously registered SPI port.
//
// This can happen when a SPI port is exposed via an USB device and the device
// is unplugged.
func Unregister(name string) error {
mu.Lock()
defer mu.Unlock()
r := byName[name]
if r == nil {
return errors.New("spireg: can't unregister unknown port name " + strconv.Quote(name))
}
delete(byName, name)
delete(byNumber, r.Number)
for _, alias := range r.Aliases {
delete(byAlias, alias)
}
return nil
}
//
var (
mu sync.Mutex
byName = map[string]*Ref{}
// Caches
byNumber = map[int]*Ref{}
byAlias = map[string]*Ref{}
)
// getDefault returns the Ref that should be used as the default port.
func getDefault() *Ref {
var o *Ref
if len(byNumber) == 0 {
// Fallback to use byName using a lexical sort.
name := ""
for n, o2 := range byName {
if len(name) == 0 || n < name {
o = o2
name = n
}
}
return o
}
number := int((^uint(0)) >> 1)
for n, o2 := range byNumber {
if number > n {
number = n
o = o2
}
}
return o
}
func insertRef(l []*Ref, r *Ref) []*Ref {
n := r.Name
i := search(len(l), func(i int) bool { return l[i].Name > n })
l = append(l, nil)
copy(l[i+1:], l[i:])
l[i] = r
return l
}
// search implements the same algorithm as sort.Search().
//
// It was extracted to to not depend on sort, which depends on reflect.
func search(n int, f func(int) bool) int {
lo := 0
for hi := n; lo < hi; {
if i := int(uint(lo+hi) >> 1); !f(i) {
lo = i + 1
} else {
hi = i
}
}
return lo
}

220
vendor/periph.io/x/periph/host/allwinner/a20.go generated vendored Normal file
View File

@ -0,0 +1,220 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// This file contains pin mapping information that is specific to the Allwinner
// A20 model.
package allwinner
import (
"strings"
"periph.io/x/periph/conn/pin"
"periph.io/x/periph/host/sysfs"
)
// mappingA20 describes the mapping of the A20 processor gpios to their
// alternate functions.
//
// It omits the in & out functions which are available on all gpio.
//
// The mapping comes from the datasheet page 241:
// http://dl.linux-sunxi.org/A20/A20%20User%20Manual%202013-03-22.pdf
var mappingA20 = map[string][5]pin.Func{
"PA0": {"ERXD3", "SPI1_CS0", "UART2_RTS", "GRXD3"},
"PA1": {"ERXD2", "SPI1_CLK", "UART2_CTS", "GRXD2"},
"PA2": {"ERXD1", "SPI1_MOSI", "UART2_TX", "GRXD1"},
"PA3": {"ERXD0", "SPI1_MISO", "UART2_RX", "GRXD0"},
"PA4": {"ETXD3", "SPI1_CS1", "", "GTXD3"},
"PA5": {"ETXD2", "SPI3_CS0", "", "GTXD2"},
"PA6": {"ETXD1", "SPI3_CLK", "", "GTXD1"},
"PA7": {"ETXD0", "SPI3_MOSI", "", "GTXD0"},
"PA8": {"ERXCK", "SPI3_MISO", "", "CRXCK"},
"PA9": {"ERXERR", "SPI3_CS1", "", "GNULL", "I2S1_MCLK"},
"PA10": {"ERXDV", "", "UART1_TX", "GRXCTL"},
"PA11": {"EMDC", "", "UART1_RX", "GMDC"},
"PA12": {"EMDIO", "UART6_TX", "UART1_RTS", "GMDIO"},
"PA13": {"ETXEN", "UART6_RX", "UART1_CTS", "GTXCTL"},
"PA14": {"ETXCK", "UART7_TX", "UART1_DTR", "GNULL", "I2S1_SCK"},
"PA15": {"ECRS", "UART7_RX", "UART1_DSR", "GTXCK", "I2S1_WS"},
"PA16": {"ECOL", "CAN_TX", "UART1_DCD", "GCLKIN", "I2S1_DOUT"},
"PA17": {"ETXERR", "CAN_RX", "UART1_RI", "GNULL", "I2S1_DIN"},
"PB0": {"I2C0_SCL"},
"PB1": {"I2C0_SDA"},
"PB2": {"PWM0"},
"PB3": {"IR0_TX", "", "SPDIF_MCLK", "", "STANBYWFI"},
"PB4": {"IR0_RX"},
"PB5": {"I2S0_MCLK", "AC97_MCLK"},
"PB6": {"I2S0_SCK", "AC97_SCK"},
"PB7": {"I2S0_WS", "AC97_SYNC"},
"PB8": {"I2S0_DOUT0", "AC97_DOUT"},
"PB9": {"I2S0_DOUT1"},
"PB10": {"I2S0_DOUT2"},
"PB11": {"I2S0_DOUT3"},
"PB12": {"I2S0_DIN", "AC97_DI", "SPDIF_DI"},
"PB13": {"SPI2_CS1", "", "SPDIF_DO"},
"PB14": {"SPI2_CS0", "JTAG0_TMS"},
"PB15": {"SPI2_CLK", "JTAG0_TCK"},
"PB16": {"SPI2_MOSI", "JTAG0_TDO"},
"PB17": {"SPI2_MISO", "JTAG0_TDI"},
"PB18": {"I2C1_SCL"},
"PB19": {"I2C1_SDA"},
"PB20": {"I2C2_SCL"},
"PB21": {"I2C2_SDA"},
"PB22": {"UART0_TX", "IR1_TX"},
"PB23": {"UART0_RX", "IR1_RX"},
"PC0": {"NWE#", "SPI0_MOSI"},
"PC1": {"NALE", "SPI0_MISO"},
"PC2": {"NCLE", "SPI0_CLK"},
"PC3": {"NCE1"},
"PC4": {"NCE0"},
"PC5": {"NRE#"},
"PC6": {"NRB0", "SDC2_CMD"},
"PC7": {"NRB1", "SDC2_CLK"},
"PC8": {"NDQ0", "SDC2_D0"},
"PC9": {"NDQ1", "SDC2_D1"},
"PC10": {"NDQ2", "SDC2_D2"},
"PC11": {"NDQ3", "SDC2_D3"},
"PC12": {"NDQ4"},
"PC13": {"NDQ5"},
"PC14": {"NDQ6"},
"PC15": {"NDQ7"},
"PC16": {"NWP"},
"PC17": {"NCE2"},
"PC18": {"NCE3"},
"PC19": {"NCE4", "SPI2_CS0", "", "", "PC_EINT12"},
"PC20": {"NCE5", "SPI2_CLK", "", "", "PC_EINT13"},
"PC21": {"NCE6", "SPI2_MOSI", "", "", "PC_EINT14"},
"PC22": {"NCE7", "SPI2_MISO", "", "", "PC_EINT15"},
"PC23": {"", "SPI2_CS0"},
"PC24": {"NDQS"},
"PD0": {"LCD0_D0", "LVDS0_VP0"},
"PD1": {"LCD0_D1", "LVDS0_VN0"},
"PD2": {"LCD0_D2", "LVDS0_VP1"},
"PD3": {"LCD0_D3", "LVDS0_VN1"},
"PD4": {"LCD0_D4", "LVDS0_VP2"},
"PD5": {"LCD0_D5", "LVDS0_VN2"},
"PD6": {"LCD0_D6", "LVDS0_VPC"},
"PD7": {"LCD0_D7", "LVDS0_VNC"},
"PD8": {"LCD0_D8", "LVDS0_VP3"},
"PD9": {"LCD0_D9", "LVDS0_VN3"},
"PD10": {"LCD0_D10", "LVDS1_VP0"},
"PD11": {"LCD0_D11", "LVDS1_VN0"},
"PD12": {"LCD0_D12", "LVDS1_VP1"},
"PD13": {"LCD0_D13", "LVDS1_VN1"},
"PD14": {"LCD0_D14", "LVDS1_VP2"},
"PD15": {"LCD0_D15", "LVDS1_VN2"},
"PD16": {"LCD0_D16", "LVDS1_VPC"},
"PD17": {"LCD0_D17", "LVDS1_VNC"},
"PD18": {"LCD0_D18", "LVDS1_VP3"},
"PD19": {"LCD0_D19", "LVDS1_VN3"},
"PD20": {"LCD0_D20", "CSI1_MCLK"},
"PD21": {"LCD0_D21", "SMC_VPPEN"},
"PD22": {"LCD0_D22", "SMC_VPPPP"},
"PD23": {"LCD0_D23", "SMC_DET"},
"PD24": {"LCD0_CLK", "SMC_VCCEN"},
"PD25": {"LCD0_DE", "SMC_RST"},
"PD26": {"LCD0_HSYNC", "SMC_SLK"},
"PD27": {"LCD0_VSYNC", "SMC_SDA"},
"PE0": {"TS0_CLK", "CSI0_PCLK"},
"PE1": {"TS0_ERR", "CSI0_MCLK"},
"PE2": {"TS0_SYNC", "CSI0_HSYNC"},
"PE3": {"TS0_DLVD", "CSI0_VSYNC"},
"PE4": {"TS0_D0", "CSI0_D0"},
"PE5": {"TS0_D1", "CSI0_D1"},
"PE6": {"TS0_D2", "CSI0_D2"},
"PE7": {"TS0_D3", "CSI0_D3"},
"PE8": {"TS0_D4", "CSI0_D4"},
"PE9": {"TS0_D5", "CSI0_D5"},
"PE10": {"TS0_D6", "CSI0_D6"},
"PE11": {"TS0_D7", "CSI0_D7"},
"PF0": {"SDC0_D1", "", "JTAG1_TMS"},
"PF1": {"SDC0_D0", "", "JTAG1_TDI"},
"PF2": {"SDC0_CLK", "", "UART0_TX"},
"PF3": {"SDC0_CMD", "", "JTAG1_TDO"},
"PF4": {"SDC0_D3", "", "UART0_RX"},
"PF5": {"SDC0_D2", "", "JTAG1_TCK"},
"PG0": {"TS1_CLK", "CSI1_PCLK", "SDC1_CMD"},
"PG1": {"TS1_ERR", "CSI1_MCLK", "SDC1_CLK"},
"PG2": {"TS1_SYNC", "CSI1_HSYNC", "SDC1_D0"},
"PG3": {"TS1_DVLD", "CSI1_VSYNC", "SDC1_D1"},
"PG4": {"TS1_D0", "CSI1_D0", "SDC1_D2", "CSI0_D8"},
"PG5": {"TS1_D1", "CSI1_D1", "SDC1_D3", "CSI0_D9"},
"PG6": {"TS1_D2", "CSI1_D2", "UART3_TX", "CSI0_D10"},
"PG7": {"TS1_D3", "CSI1_D3", "UART3_RX", "CSI0_D11"},
"PG8": {"TS1_D4", "CSI1_D4", "UART3_RTS", "CSI0_D12"},
"PG9": {"TS1_D5", "CSI1_D4", "UART3_CTS", "CSI0_D13"},
"PG10": {"TS1_D6", "CSI1_D6", "UART4_TX", "CSI0_D14"},
"PG11": {"TS1_D7", "CSI1_D7", "UART4_RX", "CSI0_D15"},
"PH0": {"LCD1_D0", "", "UART3_TX", "", "PH_EINT0"},
"PH1": {"LCD1_D1", "", "UART3_RX", "", "PH_EINT1"},
"PH2": {"LCD1_D2", "", "UART3_RTS", "", "PH_EINT2"},
"PH3": {"LCD1_D3", "", "UART3_CTS", "", "PH_EINT3"},
"PH4": {"LCD1_D4", "", "UART4_TX", "", "PH_EINT4"},
"PH5": {"LCD1_D5", "", "UART4_RX", "", "PH_EINT5"},
"PH6": {"LCD1_D6", "", "UART5_TX", "MS_BS", "PH_EINT6"},
"PH7": {"LCD1_D7", "", "UART5_RX", "MS_CLK", "PH_EINT7"},
"PH8": {"LCD1_D8", "ERXD3", "KP_IN0", "MS_D0", "PH_EINT8"},
"PH9": {"LCD1_D9", "ERXD2", "KP_IN1", "MS_D1", "PH_EINT9"},
"PH10": {"LCD1_D10", "ERXD1", "KP_IN2", "MS_D2", "PH_EINT10"},
"PH11": {"LCD1_D11", "ERXD0", "KP_IN3", "MS_D3", "PH_EINT11"},
"PH12": {"LCD1_D12", "", "PS2_SCK1", "", "PH_EINT12"},
"PH13": {"LCD1_D13", "", "PS2_SDA1", "SMC_RST", "PH_EINT13"},
"PH14": {"LCD1_D14", "ETXD3", "KP_IN4", "SMC_VPPEN", "PH_EINT14"},
"PH15": {"LCD1_D15", "ETXD2", "KP_IN5", "SMC_VPPPP", "PH_EINT15"},
"PH16": {"LCD1_D16", "ETXD1", "KP_IN6", "SMC_DET", "PH_EINT16"},
"PH17": {"LCD1_D17", "ETXD0", "KP_IN7", "SMC_VCCEN", "PH_EINT17"},
"PH18": {"LCD1_D18", "ERXCK", "KP_OUT0", "SMC_SLK", "PH_EINT18"},
"PH19": {"LCD1_D19", "ERXERR", "KP_OUT1", "SMC_SDA", "PH_EINT19"},
"PH20": {"LCD1_D20", "ERXDV", "CAN_TX", "", "PH_EINT20"},
"PH21": {"LCD1_D21", "EMDC", "CAN_RX", "", "PH_EINT21"},
"PH22": {"LCD1_D22", "EMDIO", "KP_OUT2", "SDC1_CMD", ""},
"PH23": {"LCD1_D23", "ETXEN", "KP_OUT3", "SDC1_CLK", ""},
"PH24": {"LCD1_CLK", "ETXCK", "KP_OUT4", "SDC1_D0", ""},
"PH25": {"LCD1_DE", "ECRS", "KP_OUT5", "SDC1_D1", ""},
"PH26": {"LCD1_HSYNC", "ECOL", "KP_OUT6", "SDC1_D2", ""},
"PH27": {"LCD1_VSYNC", "ETXERR", "KP_OUT7", "SDC1_D3", ""},
"PI0": {"", "I2C3_SCL"},
"PI1": {"", "I2C3_SDA"},
"PI2": {"", "I2C4_SCL"},
"PI3": {"PWM1", "I2C4_SDA"},
"PI4": {"SDC3_CMD"},
"PI5": {"SDC3_CLK"},
"PI6": {"SDC3_D0"},
"PI7": {"SDC3_D1"},
"PI8": {"SDC3_D2"},
"PI9": {"SDC3_D3"},
"PI10": {"SPI0_CS0", "UART5_TX", "", "PI_EINT22"},
"PI11": {"SPI0_CLK", "UART5_RX", "", "PI_EINT23"},
"PI12": {"SPI0_MOSI", "UART6_TX", "CLK_OUT_A", "PI_EINT24"},
"PI13": {"SPI0_MISO", "UART6_RX", "CLK_OUT_B", "PI_EINT25"},
"PI14": {"SPI0_CS0", "PS2_SCK1", "TCLKIN0", "PI_EINT26"},
"PI15": {"SPI1_CS1", "PS2_SDA1", "TCLKIN1", "PI_EINT27"},
"PI16": {"SPI1_CS0", "UART2_RTS", "", "PI_EINT28"},
"PI17": {"SPI1_CLK", "UART2_CTS", "", "PI_EINT29"},
"PI18": {"SPI1_MOSI", "UART2_TX", "", "PI_EINT30"},
"PI19": {"SPI1_MISO", "UART2_RX", "", "PI_EINT31"},
"PI20": {"PS2_SCK0", "UART7_TX", "HSCL"},
"PI21": {"PS2_SDA0", "UART7_RX", "HSDA"},
}
// mapA20Pins uses mappingA20 to actually set the altFunc fields of all gpio
// and mark them as available.
//
// It is called by the generic allwinner processor code if an A20 is detected.
func mapA20Pins() error {
for name, altFuncs := range mappingA20 {
pin := cpupins[name]
pin.altFunc = altFuncs
pin.available = true
if strings.Contains(string(altFuncs[4]), "_EINT") ||
strings.Contains(string(altFuncs[3]), "_EINT") {
pin.supportEdge = true
}
// Initializes the sysfs corresponding pin right away.
pin.sysfsPin = sysfs.Pins[pin.Number()]
}
return nil
}

174
vendor/periph.io/x/periph/host/allwinner/a64.go generated vendored Normal file
View File

@ -0,0 +1,174 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// This file contains pin mapping information that is specific to the Allwinner
// A64 model.
package allwinner
import (
"strings"
"periph.io/x/periph/conn/pin"
"periph.io/x/periph/host/sysfs"
)
// A64 specific pins.
var (
X32KFOUT *pin.BasicPin // Clock output of 32Khz crystal
KEY_ADC *pin.BasicPin // 6 bits resolution ADC for key application; can work up to 250Hz conversion rate; reference voltage is 2.0V
EAROUTP *pin.BasicPin // Earpiece amplifier negative differential output
EAROUTN *pin.BasicPin // Earpiece amplifier positive differential output
)
//
func init() {
X32KFOUT = &pin.BasicPin{N: "X32KFOUT"}
// BUG(maruel): These need to be converted to an analog.PinIO implementation
// once analog support is implemented.
KEY_ADC = &pin.BasicPin{N: "KEY_ADC"}
EAROUTP = &pin.BasicPin{N: "EAROUTP"}
EAROUTN = &pin.BasicPin{N: "EAROUTN"}
}
// mappingA64 describes the mapping of the A64 processor gpios to their
// alternate functions.
//
// It omits the in & out functions which are available on all gpio.
//
// The mapping comes from the datasheet page 23:
// http://files.pine64.org/doc/datasheet/pine64/A64_Datasheet_V1.1.pdf
//
// - The datasheet uses TWI instead of I2C but it is renamed here for
// consistency.
// - AIF is an audio interface, i.e. to connect to S/PDIF.
// - RGMII means Reduced gigabit media-independent interface.
// - SDC means SDCard?
// - NAND connects to a NAND flash controller.
// - CSI and CCI are for video capture.
var mappingA64 = map[string][5]pin.Func{
"PB0": {"UART2_TX", "", "JTAG0_TMS", "", "PB_EINT0"},
"PB1": {"UART2_RX", "", "JTAG0_TCK", "SIM_PWREN", "PB_EINT1"},
"PB2": {"UART2_RTS", "", "JTAG0_TDO", "SIM_VPPEN", "PB_EINT2"},
"PB3": {"UART2_CTS", "I2S0_MCLK", "JTAG0_TDI", "SIM_VPPPP", "PB_EINT3"},
"PB4": {"AIF2_SYNC", "I2S0_WS", "", "SIM_CLK", "PB_EINT4"},
"PB5": {"AIF2_BCLK", "I2S0_SCK", "", "SIM_DATA", "PB_EINT5"},
"PB6": {"AIF2_DOUT", "I2S0_DOUT", "", "SIM_RST", "PB_EINT6"},
"PB7": {"AIF2_DIN", "I2S0_DIN", "", "SIM_DET", "PB_EINT7"},
"PB8": {"", "", "UART0_TX", "", "PB_EINT8"},
"PB9": {"", "", "UART0_RX", "", "PB_EINT9"},
"PC0": {"NAND_WE", "", "SPI0_MOSI"},
"PC1": {"NAND_ALE", "SDC2_DS", "SPI0_MISO"},
"PC2": {"NAND_CLE", "", "SPI0_CLK"},
"PC3": {"NAND_CE1", "", "SPI0_CS0"},
"PC4": {"NAND_CE0"},
"PC5": {"NAND_RE", "SDC2_CLK"},
"PC6": {"NAND_RB0", "SDC2_CMD"},
"PC7": {"NAND_RB1"},
"PC8": {"NAND_DQ0", "SDC2_D0"},
"PC9": {"NAND_DQ1", "SDC2_D1"},
"PC10": {"NAND_DQ2", "SDC2_D2"},
"PC11": {"NAND_DQ3", "SDC2_D3"},
"PC12": {"NAND_DQ4", "SDC2_D4"},
"PC13": {"NAND_DQ5", "SDC2_D5"},
"PC14": {"NAND_DQ6", "SDC2_D6"},
"PC15": {"NAND_DQ7", "SDC2_D7"},
"PC16": {"NAND_DQS", "SDC2_RST"},
"PD0": {"LCD_D2", "UART3_TX", "SPI1_CS0", "CCIR_CLK"},
"PD1": {"LCD_D3", "UART3_RX", "SPI1_CLK", "CCIR_DE"},
"PD2": {"LCD_D4", "UART4_TX", "SPI1_MOSI", "CCIR_HSYNC"},
"PD3": {"LCD_D5", "UART4_RX", "SPI1_MISO", "CCIR_VSYNC"},
"PD4": {"LCD_D6", "UART4_RTS", "", "CCIR_D0"},
"PD5": {"LCD_D7", "UART4_CTS", "", "CCIR_D1"},
"PD6": {"LCD_D10", "", "", "CCIR_D2"},
"PD7": {"LCD_D11", "", "", "CCIR_D3"},
"PD8": {"LCD_D12", "", "RGMII_RXD3", "CCIR_D4"},
"PD9": {"LCD_D13", "", "RGMII_RXD2", "CCIR_D5"},
"PD10": {"LCD_D14", "", "RGMII_RXD1"},
"PD11": {"LCD_D15", "", "RGMII_RXD0"},
"PD12": {"LCD_D18", "LVDS_VP0", "RGMII_RXCK"},
"PD13": {"LCD_D19", "LVDS_VN0", "RGMII_RXCT"},
"PD14": {"LCD_D20", "LVDS_VP1", "RGMII_RXER"},
"PD15": {"LCD_D21", "LVDS_VN1", "RGMII_TXD3", "CCIR_D6"},
"PD16": {"LCD_D22", "LVDS_VP2", "RGMII_TXD2", "CCIR_D7"},
"PD17": {"LCD_D23", "LVDS_VN2", "RGMII_TXD1"},
"PD18": {"LCD_CLK", "LVDS_VPC", "RGMII_TXD0"},
"PD19": {"LCD_DE", "LVDS_VNC", "RGMII_TXCK"},
"PD20": {"LCD_HSYNC", "LVDS_VP3", "RGMII_TXCT"},
"PD21": {"LCD_VSYNC", "LVDS_VN3", "RGMII_CLKI"},
"PD22": {"PWM0", "", "MDC"},
"PD23": {"", "", "MDIO"},
"PD24": {""},
"PE0": {"CSI_PCLK", "", "TS_CLK"},
"PE1": {"CSI_MCLK", "", "TS_ERR"},
"PE2": {"CSI_HSYNC", "", "TS_SYNC"},
"PE3": {"CSI_VSYNC", "", "TS_DVLD"},
"PE4": {"CSI_D0", "", "TS_D0"},
"PE5": {"CSI_D1", "", "TS_D1"},
"PE6": {"CSI_D2", "", "TS_D2"},
"PE7": {"CSI_D3", "", "TS_D3"},
"PE8": {"CSI_D4", "", "TS_D4"},
"PE9": {"CSI_D5", "", "TS_D5"},
"PE10": {"CSI_D6", "", "TS_D6"},
"PE11": {"CSI_D7", "", "TS_D7"},
"PE12": {"CSI_SCK"},
"PE13": {"CSI_SDA"},
"PE14": {"PLL_LOCK_DBG", "I2C2_SCL"},
"PE15": {"", "I2C2_SDA"},
"PE16": {""},
"PE17": {""},
"PF0": {"SDC0_D1", "JTAG1_TMS"},
"PF1": {"SDC0_D0", "JTAG1_TDI"},
"PF2": {"SDC0_CLK", "UART0_TX"},
"PF3": {"SDC0_CMD", "JTAG1_TDO"},
"PF4": {"SDC0_D3", "UART0_RX"},
"PF5": {"SDC0_D2", "JTAG1_TCK"},
"PF6": {""},
"PG0": {"SDC1_CLK", "", "", "", "PG_EINT0"},
"PG1": {"SDC1_CMD", "", "", "", "PG_EINT1"},
"PG2": {"SDC1_D0", "", "", "", "PG_EINT2"},
"PG3": {"SDC1_D1", "", "", "", "PG_EINT3"},
"PG4": {"SDC1_D2", "", "", "", "PG_EINT4"},
"PG5": {"SDC1_D3", "", "", "", "PG_EINT5"},
"PG6": {"UART1_TX", "", "", "", "PG_EINT6"},
"PG7": {"UART1_RX", "", "", "", "PG_EINT7"},
"PG8": {"UART1_RTS", "", "", "", "PG_EINT8"},
"PG9": {"UART1_CTS", "", "", "", "PG_EINT9"},
"PG10": {"AIF3_SYNC", "I2S1_WS", "", "", "PG_EINT10"},
"PG11": {"AIF3_BCLK", "I2S1_SCK", "", "", "PG_EINT11"},
"PG12": {"AIF3_DOUT", "I2S1_DOUT", "", "", "PG_EINT12"},
"PG13": {"AIF3_DIN", "I2S1_DIN", "", "", "PG_EINT13"},
"PH0": {"I2C0_SCL", "", "", "", "PH_EINT0"},
"PH1": {"I2C0_SDA", "", "", "", "PH_EINT1"},
"PH2": {"I2C1_SCL", "", "", "", "PH_EINT2"},
"PH3": {"I2C1_SDA", "", "", "", "PH_EINT3"},
"PH4": {"UART3_TX", "", "", "", "PH_EINT4"},
"PH5": {"UART3_RX", "", "", "", "PH_EINT5"},
"PH6": {"UART3_RTS", "", "", "", "PH_EINT6"},
"PH7": {"UART3_CTS", "", "", "", "PH_EINT7"},
"PH8": {"OWA_OUT", "", "", "", "PH_EINT8"},
"PH9": {"", "", "", "", "PH_EINT9"},
"PH10": {"MIC_CLK", "", "", "", "PH_EINT10"},
"PH11": {"MIC_DATA", "", "", "", "PH_EINT11"},
}
// mapA64Pins uses mappingA64 to actually set the altFunc fields of all gpio
// and mark them as available.
//
// It is called by the generic allwinner processor code if an A64 is detected.
func mapA64Pins() error {
for name, altFuncs := range mappingA64 {
pin := cpupins[name]
pin.altFunc = altFuncs
pin.available = true
if strings.Contains(string(altFuncs[4]), "_EINT") {
pin.supportEdge = true
}
// Initializes the sysfs corresponding pin right away.
pin.sysfsPin = sysfs.Pins[pin.Number()]
}
return nil
}

View File

@ -0,0 +1,7 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package allwinner
const isArm = true

View File

@ -0,0 +1,9 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build arm64
package allwinner
const isArm = true

View File

@ -0,0 +1,9 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build !arm,!arm64
package allwinner
const isArm = false

281
vendor/periph.io/x/periph/host/allwinner/clock.go generated vendored Normal file
View File

@ -0,0 +1,281 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package allwinner
const (
clockSPIEnable clockSPI = 1 << 31 // SCLK_GATING
// 30:26 reserved
clockSPIOSC24M clockSPI = 0 << 24 // CLK_SRC_SEL
clockSPIPLL6 clockSPI = 1 << 24 // A64: PLL_PERIPH0(1X)
clockSPIPLL5 clockSPI = 2 << 24 // A64: PLL_PERIPH1(1X) R8: PLL5 = DDR
// 23:18 reserved
clockSPIDiv1a clockSPI = 0 << 16 // CLK_DIV_RATIO_N
clockSPIDiv2a clockSPI = 1 << 16 //
clockSPIDiv4a clockSPI = 2 << 16 //
clockSPIDiv8a clockSPI = 3 << 16 //
// 15:4 reserved
clockSPIDiv1b clockSPI = 0 << 0 // CLK_DIV_RATIO_M
clockSPIDiv2b clockSPI = 1 << 0 //
clockSPIDiv3b clockSPI = 2 << 0 //
clockSPIDiv4b clockSPI = 3 << 0 //
clockSPIDiv5b clockSPI = 4 << 0 //
clockSPIDiv6b clockSPI = 5 << 0 //
clockSPIDiv7b clockSPI = 6 << 0 //
clockSPIDiv8b clockSPI = 7 << 0 //
clockSPIDiv9b clockSPI = 8 << 0 //
clockSPIDiv10b clockSPI = 9 << 0 //
clockSPIDiv11b clockSPI = 10 << 0 //
clockSPIDiv12b clockSPI = 11 << 0 //
clockSPIDiv13b clockSPI = 12 << 0 //
clockSPIDiv14b clockSPI = 13 << 0 //
clockSPIDiv15b clockSPI = 14 << 0 //
clockSPIDiv16b clockSPI = 15 << 0 //
)
// Also valid for IR.
//
// SPI0_SCLK_CFG_REG / SPI1_SCLK_CFG_REG / SPI2_SCLK_CFG_REG / IR_SCLK_CFG_REG
//
// A64: Page 110-111. (Also Page 554?)
// R8: Page 71.
type clockSPI uint32
const (
clockPLL6Enable clockPLL6R8Ctl = 1 << 31 // PLL6_Enable
clockPLL6Force24Mhz clockPLL6R8Ctl = 1 << 30 // PLL6_BYPASS_EN; force 24Mhz
// 29:13 reserved
clockPLL6FactorMulN0 clockPLL6R8Ctl = 0 << 8 // PLL6_FACTOR_N
clockPLL6FactorMulN1 clockPLL6R8Ctl = 1 << 8 //
clockPLL6FactorMulN2 clockPLL6R8Ctl = 2 << 8 //
clockPLL6FactorMulN3 clockPLL6R8Ctl = 3 << 8 //
clockPLL6FactorMulN4 clockPLL6R8Ctl = 4 << 8 //
clockPLL6FactorMulN5 clockPLL6R8Ctl = 5 << 8 //
clockPLL6FactorMulN6 clockPLL6R8Ctl = 6 << 8 //
clockPLL6FactorMulN7 clockPLL6R8Ctl = 7 << 8 //
clockPLL6FactorMulN8 clockPLL6R8Ctl = 8 << 8 //
clockPLL6FactorMulN9 clockPLL6R8Ctl = 9 << 8 //
clockPLL6FactorMulN10 clockPLL6R8Ctl = 10 << 8 //
clockPLL6FactorMulN11 clockPLL6R8Ctl = 11 << 8 //
clockPLL6FactorMulN12 clockPLL6R8Ctl = 12 << 8 //
clockPLL6FactorMulN13 clockPLL6R8Ctl = 13 << 8 //
clockPLL6FactorMulN14 clockPLL6R8Ctl = 14 << 8 //
clockPLL6FactorMulN15 clockPLL6R8Ctl = 15 << 8 //
clockPLL6FactorMulN16 clockPLL6R8Ctl = 16 << 8 //
clockPLL6FactorMulN17 clockPLL6R8Ctl = 17 << 8 //
clockPLL6FactorMulN18 clockPLL6R8Ctl = 18 << 8 //
clockPLL6FactorMulN19 clockPLL6R8Ctl = 19 << 8 //
clockPLL6FactorMulN20 clockPLL6R8Ctl = 20 << 8 //
clockPLL6FactorMulN21 clockPLL6R8Ctl = 21 << 8 //
clockPLL6FactorMulN22 clockPLL6R8Ctl = 22 << 8 //
clockPLL6FactorMulN23 clockPLL6R8Ctl = 23 << 8 //
clockPLL6FactorMulN24 clockPLL6R8Ctl = 24 << 8 //
clockPLL6FactorMulN25 clockPLL6R8Ctl = 25 << 8 //
clockPLL6FactorMulN26 clockPLL6R8Ctl = 26 << 8 //
clockPLL6FactorMulN27 clockPLL6R8Ctl = 27 << 8 //
clockPLL6FactorMulN28 clockPLL6R8Ctl = 28 << 8 //
clockPLL6FactorMulN29 clockPLL6R8Ctl = 29 << 8 //
clockPLL6FactorMulN30 clockPLL6R8Ctl = 30 << 8 //
clockPLL6FactorMulN31 clockPLL6R8Ctl = 31 << 8 //
clockPLL6Damping clockPLL6R8Ctl = 2 << 6 //
clockPLL6FactorMulK1 clockPLL6R8Ctl = 0 << 4 // PLL6_FACTOR_K
clockPLL6FactorMulK2 clockPLL6R8Ctl = 1 << 4 //
clockPLL6FactorMulK3 clockPLL6R8Ctl = 2 << 4 //
clockPLL6FactorMulK4 clockPLL6R8Ctl = 3 << 4 //
// 3:2 reserved
clockPLL6FactorDivM1 clockPLL6R8Ctl = 0 << 4 // PLL6_FACTOR_M
clockPLL6FactorDivM2 clockPLL6R8Ctl = 1 << 4 //
clockPLL6FactorDivM3 clockPLL6R8Ctl = 2 << 4 //
clockPLL6FactorDivM4 clockPLL6R8Ctl = 3 << 4 //
)
// PLL6_CFG_REG
// R8: Page 63; default 0x21009931
//
// Output = (24MHz*N*K)/M/2
// Note: the output 24MHz*N*K clock must be in the range of 240MHz~3GHz if the
// bypass is disabled.
type clockPLL6R8Ctl uint32
// clockMap is the mapping of important registers across CPUs.
type clockMap struct {
reserved0 [0xA0 / 4]uint32 //
spi0Clk clockSPI // 0x0A0 SPI0_SCLK_CFG_REG SPI0 Clock
spi1Clk clockSPI // 0x0A4 SPI1_SCLK_CFG_REG SPI1 Clock
spi2Clk clockSPI // 0x0A8 SPI2_SCLK_CFG_REG SPI2 Clock (Not on A64)
}
// R8: Page 57-59.
type clockMapR8 struct {
r0 uint32 // 0x000 PLL1_CFG_REG PLL1 Control
r1 uint32 // 0x004 PLL1_TUN_REG PLL1 Tuning
r2 uint32 // 0x008 PLL2_CFG_REG PLL2 Control
r3 uint32 // 0x00C PLL2_TUN_REG PLL2 Tuning
r4 uint32 // 0x010 PLL3_CFG_REG PLL3 Control
r5 uint32 // 0x014
r6 uint32 // 0x018 PLL4_CFG_REG PLL4 Control
r7 uint32 // 0x01C
r8 uint32 // 0x020 PLL5_CFG_REG PLL5 Control
r9 uint32 // 0x024 PLL5_TUN_REG PLL5 Tuning
r10 clockPLL6R8Ctl // 0x028 PLL6_CFG_REG PLL6 Control
r11 uint32 // 0x02C PLL6 Tuning
r12 uint32 // 0x030 PLL7_CFG_REG
r13 uint32 // 0x034
r14 uint32 // 0x038 PLL1_TUN2_REG PLL1 Tuning2
r15 uint32 // 0x03C PLL5_TUN2_REG PLL5 Tuning2
r16 uint32 // 0x04C
r17 uint32 // 0x050 OSC24M_CFG_REG OSC24M control
r18 uint32 // 0x054 CPU_AHB_APB0_CFG_REG CPU, AHB And APB0 Divide Ratio
r19 uint32 // 0x058 APB1_CLK_DIV_REG APB1 Clock Divider
r20 uint32 // 0x05C AXI_GATING_REG AXI Module Clock Gating
r21 uint32 // 0x060 AHB_GATING_REG0 AHB Module Clock Gating 0
r22 uint32 // 0x064 AHB_GATING_REG1 AHB Module Clock Gating 1
r23 uint32 // 0x068 APB0_GATING_REG APB0 Module Clock Gating
r24 uint32 // 0x06C APB1_GATING_REG APB1 Module Clock Gating
r25 uint32 // 0x080 NAND_SCLK_CFG_REG Nand Flash Clock
r26 uint32 // 0x084
r27 uint32 // 0x088 SD0_SCLK_CFG_REG SD0 Clock
r28 uint32 // 0x08C SD1_SCLK_CFG_REG SD1 Clock
r29 uint32 // 0x090 SD2_SCLK_CFG_REG SD2 Clock
r30 uint32 // 0x094
r31 uint32 // 0x098
r32 uint32 // 0x09C CE_SCLK_CFG_REG Crypto Engine Clock
spi0Clk clockSPI // 0x0A0 SPI0_SCLK_CFG_REG SPI0 Clock
spi1Clk clockSPI // 0x0A4 SPI1_SCLK_CFG_REG SPI1 Clock
spi2Clk clockSPI // 0x0A8 SPI2_SCLK_CFG_REG SPI2 Clock
r33 uint32 // 0x0AC
irClk clockSPI // 0x0B0 IR_SCLK_CFG_REG IR Clock
r34 uint32 // 0x0B4
r35 uint32 // 0x0B8
r36 uint32 // 0x0BC
r37 uint32 // 0x0C0
r38 uint32 // 0x0C4
r39 uint32 // 0x0C8
r40 uint32 // 0x0CC
r41 uint32 // 0x0D0
r42 uint32 // 0x0D4
r43 uint32 // 0x100 DRAM_SCLK_CFG_REG DRAM Clock
r44 uint32 // 0x104 BE_CFG_REG Display Engine Backend Clock
r45 uint32 // 0x108
r46 uint32 // 0x10C FE_CFG_REG Display Engine Front End Clock
r47 uint32 // 0x110
r48 uint32 // 0x114
r49 uint32 // 0x118
r50 uint32 // 0x11C
r51 uint32 // 0x120
r52 uint32 // 0x124
r53 uint32 // 0x128
r54 uint32 // 0x12C LCD_CH1_CFG_REG LCD Channel1 Clock
r55 uint32 // 0x130
r56 uint32 // 0x134 CSI_CFG_REG CSI Clock
r57 uint32 // 0x138
r58 uint32 // 0x13C VE_CFG_REG Video Engine Clock
r59 uint32 // 0x140 AUDIO_CODEC_SCLK_CFG_REG Audio Codec Gating Special Clock
r60 uint32 // 0x144 AVS_SCLK_CFG_REG AVS Gating Special Clock
r61 uint32 // 0x148
r62 uint32 // 0x14C
r63 uint32 // 0x150
r64 uint32 // 0x154 MALI_CLOCK_CFG_REG Mali400 Gating Special Clock
r65 uint32 // 0x158
r66 uint32 // 0x15C MBUS_SCLK_CFG_REG MBUS Gating Clock
r67 uint32 // 0x160 IEP_SCLK_CFG_REG IEP Gating Clock
}
// A64: Page 81-84.
type clockMapA64 struct {
r0 uint32 // 0x000 PLL_CPUX_CTRL_REG PLL_CPUX Control Register
r1 uint32 // 0x008 PLL_AUDIO_CTRL_REG PLL_AUDIO Control Register
r2 uint32 // 0x010 PLL_VIDEO0_CTRL_REG PLL_VIDEO0 Control Register
r3 uint32 // 0x018 PLL_VE_CTRL_REG PLL_VE Control Register
r4 uint32 // 0x020 PLL_DDR0_CTRL_REG PLL_DDR0 Control Register
r5 uint32 // 0x028 PLL_PERIPH0_CTRL_REG PLL_PERIPH0 Control Register
r6 uint32 // 0x02C PLL_PERIPH1_CTRL_REG PLL_PERIPH1 Control Register
r7 uint32 // 0x030 PLL_VIDEO1_CTRL_REG PLL_VIDEO1 Control Register
r8 uint32 // 0x038 PLL_GPU_CTRL_REG PLL_GPU Control Register
r9 uint32 // 0x040 PLL_MIPI_CTRL_REG PLL_MIPI Control Register
r10 uint32 // 0x044 PLL_HSIC_CTRL_REG PLL_HSIC Control Register
r11 uint32 // 0x048 PLL_DE_CTRL_REG PLL_DE Control Register
r12 uint32 // 0x04C PLL_DDR1_CTRL_REG PLL_DDR1 Control Register
r13 uint32 // 0x050 CPU_AXI_CFG_REG CPUX/AXI Configuration Register
r14 uint32 // 0x054 AHB1_APB1_CFG_REG AHB1/APB1 Configuration Register
r15 uint32 // 0x058 APB2_CFG_REG APB2 Configuration Register
r16 uint32 // 0x05C AHB2_CFG_REG AHB2 Configuration Register
r17 uint32 // 0x060 BUS_CLK_GATING_REG0 Bus Clock Gating Register 0
r18 uint32 // 0x064 BUS_CLK_GATING_REG1 Bus Clock Gating Register 1
r19 uint32 // 0x068 BUS_CLK_GATING_REG2 Bus Clock Gating Register 2
r20 uint32 // 0x06C BUS_CLK_GATING_REG3 Bus Clock Gating Register 3
r21 uint32 // 0x070 BUS_CLK_GATING_REG4 Bus Clock Gating Register 4
r22 uint32 // 0x074 THS_CLK_REG THS Clock Register
r23 uint32 // 0x080 NAND_CLK_REG NAND Clock Register
r24 uint32 // 0x088 SDMMC0_CLK_REG SDMMC0 Clock Register
r25 uint32 // 0x08C SDMMC1_CLK_REG SDMMC1 Clock Register
r26 uint32 // 0x090 SDMMC2_CLK_REG SDMMC2 Clock Register
r27 uint32 // 0x098 TS_CLK_REG TS Clock Register
r28 uint32 // 0x09C CE_CLK_REG CE Clock Register
spi0Clk clockSPI // 0x0A0 SPI0_CLK_REG SPI0 Clock Register
spi1Clk clockSPI // 0x0A4 SPI1_CLK_REG SPI1 Clock Register
r29 uint32 // 0x0B0 I2S/PCM-0_CLK_REG I2S/PCM-0 Clock Register
r30 uint32 // 0x0B4 I2S/PCM-1_CLK_REG I2S/PCM-1 Clock Register
r31 uint32 // 0x0B8 I2S/PCM-2_CLK_REG I2S/PCM-2 Clock Register
r32 uint32 // 0x0C0 SPDIF_CLK_REG SPDIF Clock Register
r33 uint32 // 0x0CC USBPHY_CFG_REG USBPHY Configuration Register
r34 uint32 // 0x0F4 DRAM_CFG_REG DRAM Configuration Register
r35 uint32 // 0x0F8 PLL_DDR_CFG_REG PLL_DDR Configuration Register
r36 uint32 // 0x0FC MBUS_RST_REG MBUS Reset Register
r37 uint32 // 0x100 DRAM_CLK_GATING_REG DRAM Clock Gating Register
r38 uint32 // 0x104 DE_CLK_REG DE Clock Register
r39 uint32 // 0x118 TCON0_CLK_REG TCON0 Clock Register
r40 uint32 // 0x11C TCON1_CLK_REG TCON1 Clock Register
r41 uint32 // 0x124 DEINTERLACE_CLK_REG DEINTERLACE Clock Register
r42 uint32 // 0x130 CSI_MISC_CLK_REG CSI_MISC Clock Register
r43 uint32 // 0x134 CSI_CLK_REG CSI Clock Register
r44 uint32 // 0x13C VE_CLK_REG VE Clock Register
r45 uint32 // 0x140 AC_DIG_CLK_REG AC Digital Clock Register
r46 uint32 // 0x144 AVS_CLK_REG AVS Clock Register
r47 uint32 // 0x150 HDMI_CLK_REG HDMI Clock Register
r48 uint32 // 0x154 HDMI_SLOW_CLK_REG HDMI Slow Clock Register
r49 uint32 // 0x15C MBUS_CLK_REG MBUS Clock Register
r50 uint32 // 0x168 MIPI_DSI_CLK_REG MIPI_DSI Clock Register
r51 uint32 // 0x1A0 GPU_CLK_REG GPU Clock Register
r52 uint32 // 0x200 PLL_STABLE_TIME_REG0 PLL Stable Time Register0
r53 uint32 // 0x204 PLL_STABLE_TIME_REG1 PLL Stable Time Register1
r54 uint32 // 0x21C PLL_PERIPH1_BIAS_REG PLL_PERIPH1 Bias Register
r55 uint32 // 0x220 PLL_CPUX_BIAS_REG PLL_CPUX Bias Register
r56 uint32 // 0x224 PLL_AUDIO_BIAS_REG PLL_AUDIO Bias Register
r57 uint32 // 0x228 PLL_VIDEO0_BIAS_REG PLL_VIDEO0 Bias Register
r58 uint32 // 0x22C PLL_VE_BIAS_REG PLL_VE Bias Register
r59 uint32 // 0x230 PLL_DDR0_BIAS_REG PLL_DDR0 Bias Register
r60 uint32 // 0x234 PLL_PERIPH0_BIAS_REG PLL_PERIPH0 Bias Register
r61 uint32 // 0x238 PLL_VIDEO1_BIAS_REG PLL_VIDEO1 Bias Register
r62 uint32 // 0x23C PLL_GPU_BIAS_REG PLL_GPU Bias Register
r63 uint32 // 0x240 PLL_MIPI_BIAS_REG PLL_MIPI Bias Register
r64 uint32 // 0x244 PLL_HSIC_BIAS_REG PLL_HSIC Bias Register
r65 uint32 // 0x248 PLL_DE_BIAS_REG PLL_DE Bias Register
r66 uint32 // 0x24C PLL_DDR1_BIAS_REG PLL_DDR1 Bias Register
r67 uint32 // 0x250 PLL_CPUX_TUN_REG PLL_CPUX Tuning Register
r68 uint32 // 0x260 PLL_DDR0_TUN_REG PLL_DDR0 Tuning Register
r69 uint32 // 0x270 PLL_MIPI_TUN_REG PLL_MIPI Tuning Register
r70 uint32 // 0x27C PLL_PERIPH1_PAT_CTRL_REG PLL_PERIPH1 Pattern Control Register
r71 uint32 // 0x280 PLL_CPUX_PAT_CTRL_REG PLL_CPUX Pattern Control Register
r72 uint32 // 0x284 PLL_AUDIO_PAT_CTRL_REG PLL_AUDIO Pattern Control Register
r73 uint32 // 0x288 PLL_VIDEO0_PAT_CTRL_REG PLL_VIDEO0 Pattern Control Register
r74 uint32 // 0x28C PLL_VE_PAT_CTRL_REG PLL_VE Pattern Control Register
r75 uint32 // 0x290 PLL_DDR0_PAT_CTRL_REG PLL_DDR0 Pattern Control Register
r76 uint32 // 0x298 PLL_VIDEO1_PAT_CTRL_REG PLL_VIDEO1 Pattern Control Register
r77 uint32 // 0x29C PLL_GPU_PAT_CTRL_REG PLL_GPU Pattern Control Register
r78 uint32 // 0x2A0 PLL_MIPI_PAT_CTRL_REG PLL_MIPI Pattern Control Register
r79 uint32 // 0x2A4 PLL_HSIC_PAT_CTRL_REG PLL_HSIC Pattern Control Register
r80 uint32 // 0x2A8 PLL_DE_PAT_CTRL_REG PLL_DE Pattern Control Register
r81 uint32 // 0x2AC PLL_DDR1_PAT_CTRL_REG0 PLL_DDR1 Pattern Control Register0
r82 uint32 // 0x2B0 PLL_DDR1_PAT_CTRL_REG1 PLL_DDR1 Pattern Control Register1
r83 uint32 // 0x2C0 BUS_SOFT_RST_REG0 Bus Software Reset Register 0
r84 uint32 // 0x2C4 BUS_SOFT_RST_REG1 Bus Software Reset Register 1
r85 uint32 // 0x2C8 BUS_SOFT_RST_REG2 Bus Software Reset Register 2
r86 uint32 // 0x2D0 BUS_SOFT_RST_REG3 Bus Software Reset Register 3
r87 uint32 // 0x2D8 BUS_SOFT_RST_REG4 Bus Software Reset Register 4
r88 uint32 // 0x2F0 CCM_SEC_SWITCH_REG CCM Security Switch Register
r89 uint32 // 0x300 PS_CTRL_REG PS Control Register
r90 uint32 // 0x304 PS_CNT_REG PS Counter Register
r91 uint32 // 0x320 PLL_LOCK_CTRL_REG PLL Lock Control Register
}

98
vendor/periph.io/x/periph/host/allwinner/detect.go generated vendored Normal file
View File

@ -0,0 +1,98 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package allwinner
import (
"strings"
"sync"
"periph.io/x/periph/host/distro"
)
// Present detects whether the host CPU is an Allwinner CPU.
//
// https://en.wikipedia.org/wiki/Allwinner_Technology
func Present() bool {
detection.do()
return detection.isAllwinner
}
// IsR8 detects whether the host CPU is an Allwinner R8 CPU.
//
// It looks for the string "sun5i-r8" in /proc/device-tree/compatible.
func IsR8() bool {
detection.do()
return detection.isR8
}
// IsA20 detects whether the host CPU is an Allwinner A20 CPU.
//
// It first looks for the string "sun71-a20" in /proc/device-tree/compatible,
// and if that fails it checks for "Hardware : sun7i" in /proc/cpuinfo.
func IsA20() bool {
detection.do()
return detection.isA20
}
// IsA64 detects whether the host CPU is an Allwinner A64 CPU.
//
// It looks for the string "sun50iw1p1" in /proc/device-tree/compatible.
func IsA64() bool {
detection.do()
return detection.isA64
}
//
type detectionS struct {
mu sync.Mutex
done bool
isAllwinner bool
isR8 bool
isA20 bool
isA64 bool
}
var detection detectionS
// do contains the CPU detection logic that determines whether we have an
// Allwinner CPU and if so, which exact model.
//
// Sadly there is no science behind this, it's more of a trial and error using
// as many boards and OS flavors as possible.
func (d *detectionS) do() {
d.mu.Lock()
defer d.mu.Unlock()
if !d.done {
d.done = true
if isArm {
for _, c := range distro.DTCompatible() {
if strings.Contains(c, "sun50iw1p1") {
d.isA64 = true
}
if strings.Contains(c, "sun5i-r8") {
d.isR8 = true
}
if strings.Contains(c, "sun7i-a20") {
d.isA20 = true
}
}
d.isAllwinner = d.isA64 || d.isR8 || d.isA20
if !d.isAllwinner {
// The kernel in the image that comes pre-installed on the pcDuino3 Nano
// is an old 3.x kernel that doesn't expose the device-tree in procfs,
// so do an extra check in cpuinfo as well if we haven't detected
// anything yet.
// Distros based on 4.x kernels do expose it.
if hw, ok := distro.CPUInfo()["Hardware"]; ok {
if hw == "sun7i" {
d.isA20 = true
}
}
}
}
}
}

474
vendor/periph.io/x/periph/host/allwinner/dma.go generated vendored Normal file
View File

@ -0,0 +1,474 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Unlike the bcm283x, the allwinner CPUs do not have a "clear bit" and "set
// bit" registers, they only have the data register. Also, allwinner CPUs do
// not support linked lists of DMA buffers. On the other hand, the Allwinner DMA
// controller supports 8 bits transfers instead of 32-128 bits that the bcm283x
// DMA controller supports.
//
// This means that only 8 bits can be used per sample, and only one stream is
// necessary. This results in 1/8th th memory usage than on the bcm283x. The
// drawback is that a block of 8 contiguous GPIO pins must be dedicated to the
// stream.
package allwinner
import (
"errors"
"fmt"
"log"
"os"
"periph.io/x/periph"
"periph.io/x/periph/host/pmem"
)
// dmaMap represents the DMA memory mapped CPU registers.
//
// This map is specific to the currently supported CPUs and will have to be
// adapted as more CPUs are supported. In particular the number of physical
// channels varies across different CPUs.
//
// Note that we modify the DMA controllers without telling the kernel driver.
// The driver keeps its own table of which DMA channel is available so this
// code could effectively crash the whole system. It practice this works.
// #everythingisfine
type dmaMap struct {
irqEn dmaR8Irq // DMA_IRQ_EN_REG
irqPendStas dmaR8PendingIrq // DMA_IRQ_PEND_STAS_REG
reserved0 [(0x100 - 8) / 4]uint32 //
normal [8]dmaR8NormalGroup // 0x100 The "8" "normal" DMA channels (only one active at a time so there's effectively one)
reserved1 [0x100 / 4]uint32 //
dedicated [8]dmaDedicatedGroup // 0x300 The 8 "dedicated" (as in actually existing) DMA channels
}
func (d *dmaMap) getDedicated() int {
for i := len(d.dedicated) - 1; i >= 0; i-- {
if d.dedicated[i].isAvailable() {
return i
}
}
return -1
}
// dmaNormalGroup is the control registers for the first block of 8 DMA
// controllers.
//
// They can be intentionally slowed down, unlike the dedicated DMA ones.
//
// The big caveat is that only one controller can be active at a time and the
// execution sequence is in accordance with the priority level. This means that
// two normal DMA cannot be used to do simultaneous read and write. This
// feature is critical for bus bitbanging.
type dmaR8NormalGroup struct {
cfg ndmaR8Cfg // NDMA_CTRL_REG
srcAddr uint32 // NDMA_SRC_ADDR_REG
dstAddr uint32 // NDMA_DEST_ADDR_REG
byteCounter uint32 // NDMA_BC_REG
reserved [4]uint32 //
}
func (d *dmaR8NormalGroup) isAvailable() bool {
return d.cfg == 0 && d.srcAddr == 0 && d.dstAddr == 0 && d.byteCounter == 0
}
func (d *dmaR8NormalGroup) release() error {
d.srcAddr = 0
d.dstAddr = 0
d.byteCounter = 0
d.cfg = ndmaLoad
//drvDMA.dmaMemory.irqEn &^= ...
//drvDMA.dmaMemory.irqPendStas &^= ...
return nil
}
// dmaNormalGroup is the control registers for the second block of 8 DMA
// controllers.
//
// They support different DReq and can do non-linear streaming.
type dmaDedicatedGroup struct {
cfg ddmaR8Cfg // DDMA_CTRL_REG
srcAddr uint32 // DDMA_SRC_ADDR_REG
dstAddr uint32 // DDMA_DEST_ADDR_REG
byteCounter uint32 // DDMA_BC_REG (24 bits)
reserved0 [2]uint32 //
param ddmaR8Param // DDMA_PARA_REG (dedicated DMA only)
reserved1 uint32 //
}
func (d *dmaDedicatedGroup) isAvailable() bool {
return d.cfg == 0 && d.srcAddr == 0 && d.dstAddr == 0 && d.byteCounter == 0 && d.param == 0
}
func (d *dmaDedicatedGroup) set(srcAddr, dstAddr, l uint32, srcIO, dstIO bool, src ddmaR8Cfg) {
d.srcAddr = srcAddr
d.dstAddr = dstAddr
d.byteCounter = l
// TODO(maruel): Slow down the clock by another 2*250x
//d.param = ddmaR8Param(250 | 250<<16)
d.param = ddmaR8Param(1<<24 | 1<<8 | 1)
// All these have value 0. This statement only exist for documentation.
cfg := ddmaDstWidth8 | ddmaDstBurst1 | ddmaDstLinear | ddmaSrcWidth8 | ddmaSrcLinear | ddmaSrcBurst1
cfg |= src | ddmaBCRemain
if srcIO {
cfg |= ddmaSrcIOMode
} else if dstIO {
cfg |= ddmaDstIOMode
}
d.cfg = ddmaLoad | cfg
for i := 0; d.cfg&ddmaLoad != 0 && i < 100000; i++ {
}
if d.cfg&ddmaLoad != 0 {
log.Printf("failed to load DDMA: %# v\n", d)
}
}
func (d *dmaDedicatedGroup) release() error {
d.param = 0
d.srcAddr = 0
d.dstAddr = 0
d.byteCounter = 0
d.cfg = ddmaLoad
//drvDMA.dmaMemory.irqEn &^= ...
//drvDMA.dmaMemory.irqPendStas &^= ...
return nil
}
const (
// 31 reserved
dma7QueueEndIrq dmaA64Irq = 1 << 30 // DMA7_END_IRQ_EN; DMA 7 Queue End Transfer Interrupt Enable.
dma7PackageEndIrq dmaA64Irq = 1 << 29 // DMA7_PKG_IRQ_EN; DMA 7 Package End Transfer Interrupt Enable.
dma7HalfIrq dmaA64Irq = 1 << 28 // DMA7_HLAF_IRQ_EN; DMA 7 Half Package Transfer Interrupt Enable.
// ...
// 3 reserved
dma0QueueEndIrq dmaA64Irq = 1 << 2 // DMA0_END_IRQ_EN; DMA 0 Queue End Transfer Interrupt Enable.
dma0PackageEndIrq dmaA64Irq = 1 << 1 // DMA0_PKG_IRQ_EN; DMA 0 Package End Transfer Interrupt Enable.
dma0HalfIrq dmaA64Irq = 1 << 0 // DMA0_HLAF_IRQ_EN; DMA 0 Half Package Transfer Interrupt Enable.
)
// DMA_IRQ_EN_REG
// A64: Page 199-201.
type dmaA64Irq uint32
const (
ddma7EndIrq dmaR8Irq = 1 << 31 // DDMA7_END_IRQ_EN
ddma7HalfIreq dmaR8Irq = 1 << 30 // DDMA7_HF_IRQ_EN
// ...
ddma0EndIrq dmaR8Irq = 1 << 17 // DDMA0_END_IRQ_EN
ddma0HalfIreq dmaR8Irq = 1 << 16 // DDMA0_HF_IRQ_EN
ndma7EndIrq dmaR8Irq = 1 << 15 // NDMA7_END_IRQ_EN
ndma7HalfIreq dmaR8Irq = 1 << 16 // NDDMA7_HF_IRQ_EN
// ...
ndma0EndIrq dmaR8Irq = 1 << 1 // NDMA0_END_IRQ_EN
ndma0HFIreq dmaR8Irq = 1 << 0 // NDMA0_HF_IRQ_EN
)
// DMA_IRQ_EN_REG
// R8: Page 124-126.
type dmaR8Irq uint32
const (
// 31 reserved
dma7QueueEndIrqPend dmaA64PendingIrq = 1 << 30 // DMA7_QUEUE_IRQ_PEND; DMA 7 Queue End Transfer Interrupt Pending. Set 1 to the bit will clear it.
dma7PackageEndIrqPend dmaA64PendingIrq = 1 << 29 // DMA7_PKG_IRQ_PEND; DMA 7 Package End Transfer Interrupt Pending. Set 1 to the bit will clear it.
dma7HalfIrqPend dmaA64PendingIrq = 1 << 28 // DMA7_HLAF_IRQ_PEND; DMA 7 Half Package Transfer Interrupt Pending. Set 1 to the bit will clear it.
// ...
// 3 reserved
dma0QueueEndIrqPend dmaA64PendingIrq = 1 << 2 // DMA0_QUEUE_IRQ_PEND; DMA 0 Queue End Transfer Interrupt Pending. Set 1 to the bit will clear it.
dma0PackageEndIrqPend dmaA64PendingIrq = 1 << 1 // DMA0_PKG_IRQ_PEND; DMA 0 Package End Transfer Interrupt Pending. Set 1 to the bit will clear it.
dma0HalfIrqPend dmaA64PendingIrq = 1 << 0 // DMA0_HLAF_IRQ_PEND; DMA 0 Half Package Transfer Interrupt Pending. Set 1 to the bit will clear it.
)
// DMA_IRQ_PEND_REG0
// A64: Page 201-203.
type dmaA64PendingIrq uint32
const (
ddma7EndIrqPend dmaR8PendingIrq = 1 << 31 // DDMA7_END_IRQ_PEND
ddma7HalfIreqPend dmaR8PendingIrq = 1 << 30 // DDMA7_HF_IRQ_PEND
// ...
ddma0EndIrqPend dmaR8PendingIrq = 1 << 17 // DDMA0_END_IRQ_PEND
ddma0HalfIreqPend dmaR8PendingIrq = 1 << 16 // DDMA0_HF_IRQ_PEND
ndma7EndIrqPend dmaR8PendingIrq = 1 << 15 // NDMA7_END_IRQ_PEND
ndma7HalfIreqPend dmaR8PendingIrq = 1 << 16 // NDDMA7_HF_IRQ_PEND
// ...
ndma0EndIrqPend dmaR8PendingIrq = 1 << 1 // NDMA0_END_IRQ_PEND
ndma0HalfIreqPend dmaR8PendingIrq = 1 << 0 // NDMA0_HF_IRQ_PEND
)
// DMA_IRQ_PEND_STAS_REG
// R8: Page 126-129.
type dmaR8PendingIrq uint32
const (
ndmaLoad ndmaR8Cfg = 1 << 31 // NDMA_LOAD
ndmaContinuous ndmaR8Cfg = 1 << 30 // NDMA_CONTI_EN Continuous mode
ndmaWaitClk0 ndmaR8Cfg = 0 << 27 // NDMA_WAIT_STATE Number of clock to wait for
ndmaWaitClk2 ndmaR8Cfg = 1 << 27 // 2(n+1)
ndmaWaitClk6 ndmaR8Cfg = 2 << 27 //
ndmaWaitClk8 ndmaR8Cfg = 3 << 27 //
ndmaWaitClk10 ndmaR8Cfg = 4 << 27 //
ndmaWaitClk12 ndmaR8Cfg = 5 << 27 //
ndmaWaitClk14 ndmaR8Cfg = 6 << 27 //
ndmaWaitClk16 ndmaR8Cfg = 7 << 27 //
ndmaDstWidth32 ndmaR8Cfg = 2 << 25 // NDMA_DST_DATA_WIDTH
ndmaDstWidth16 ndmaR8Cfg = 1 << 25 //
ndmaDstWidth8 ndmaR8Cfg = 0 << 25 //
ndmaDstBurst8 ndmaR8Cfg = 2 << 23 // NDMA_DST_BST_LEN
ndmaDstBurst4 ndmaR8Cfg = 1 << 23 //
ndmaDstBurst1 ndmaR8Cfg = 0 << 23 //
// 22 reserved NDMA_CFG_DST_NON_SECURE ?
ndmaDstAddrNoInc ndmaR8Cfg = 1 << 21 // NDMA_DST_ADDR_TYPE
ndmaDstDrqIRTX ndmaR8Cfg = 0 << 16 // NDMA_DST_DRQ_TYPE
ndmaDstDrqUART1TX ndmaR8Cfg = 9 << 16 //
ndmaDstDrqUART3TX ndmaR8Cfg = 11 << 16 //
ndmaDstDrqAudio ndmaR8Cfg = 19 << 16 // 24.576MHz (Page 53)
ndmaDstDrqSRAM ndmaR8Cfg = 21 << 16 //
ndmaDstDrqSPI0TX ndmaR8Cfg = 24 << 16 //
ndmaDstDrqSPI1TX ndmaR8Cfg = 25 << 16 //
ndmaDstDrqSPI2TX ndmaR8Cfg = 26 << 16 //
ndmaDstDrqUSB1 ndmaR8Cfg = 27 << 16 // 480MHz
ndmaDstDrqUSB2 ndmaR8Cfg = 28 << 16 //
ndmaDstDrqUSB3 ndmaR8Cfg = 29 << 16 //
ndmaDstDrqUSB4 ndmaR8Cfg = 30 << 16 //
ndmaDstDrqUSB5 ndmaR8Cfg = 31 << 16 //
ndmaBCRemain ndmaR8Cfg = 1 << 15 // BC_MODE_SEL
// 14:11 reserved
ndmaSrcWidth32 ndmaR8Cfg = 2 << 9 // NDMA_SRC_DATA_WIDTH
ndmaSrcWidth16 ndmaR8Cfg = 1 << 9 //
ndmaSrcWidth8 ndmaR8Cfg = 0 << 9 //
ndmaSrcBurst8 ndmaR8Cfg = 2 << 7 // NDMA_SRC_BST_LEN
ndmaSrcBurst4 ndmaR8Cfg = 1 << 7 //
ndmaSrcBurst1 ndmaR8Cfg = 0 << 7 //
// 6 reserved NDMA_CFG_SRC_NON_SECURE ?
ndmaSrcAddrNoInc ndmaR8Cfg = 1 << 5 // NDMA_SRC_ADDR_TYPE
ndmaSrcDrqIRTX ndmaR8Cfg = 0 << 0 // NDMA_SRC_DRQ_TYPE
ndmaSrcDrqUART1RX ndmaR8Cfg = 9 << 0 //
ndmaSrcDrqUART3RX ndmaR8Cfg = 11 << 0 //
ndmaSrcDrqAudio ndmaR8Cfg = 19 << 0 // 24.576MHz (Page 53)
ndmaSrcDrqSRAM ndmaR8Cfg = 21 << 0 //
ndmaSrcDrqSDRAM ndmaR8Cfg = 22 << 0 // 0~400MHz
ndmaSrcDrqTPAD ndmaR8Cfg = 23 << 0 //
ndmaSrcDrqSPI0RX ndmaR8Cfg = 24 << 0 //
ndmaSrcDrqSPI1RX ndmaR8Cfg = 25 << 0 //
ndmaSrcDrqSPI2RX ndmaR8Cfg = 26 << 0 //
ndmaSrcDrqUSB1 ndmaR8Cfg = 27 << 0 // 480MHz
ndmaSrcDrqUSB2 ndmaR8Cfg = 28 << 0 //
ndmaSrcDrqUSB3 ndmaR8Cfg = 29 << 0 //
ndmaSrcDrqUSB4 ndmaR8Cfg = 30 << 0 //
ndmaSrcDrqUSB5 ndmaR8Cfg = 31 << 0 //
)
// NDMA_CTRL_REG
// R8: Page 129-131.
type ndmaR8Cfg uint32
const (
ddmaLoad ddmaR8Cfg = 1 << 31 // DDMA_LOAD
ddmaBusy ddmaR8Cfg = 1 << 30 // DDMA_BSY_STA
ddmaContinuous ddmaR8Cfg = 1 << 29 // DDMA_CONTI_MODE_EN
// 28:27 reserved 28 = DDMA_CFG_DST_NON_SECURE ?
ddmaDstWidth32 ddmaR8Cfg = 2 << 25 // DDMA_DST_DATA_WIDTH
ddmaDstWidth16 ddmaR8Cfg = 1 << 25 //
ddmaDstWidth8 ddmaR8Cfg = 0 << 25 //
ddmaDstBurst8 ddmaR8Cfg = 2 << 23 // DDMA_DST_BST_LEN
ddmaDstBurst4 ddmaR8Cfg = 1 << 23 //
ddmaDstBurst1 ddmaR8Cfg = 0 << 23 //
ddmaDstVertical ddmaR8Cfg = 3 << 21 // DDMA_ADDR_MODE; no idea what it's use it. It's not explained in the datasheet ...
ddmaDstHorizontal ddmaR8Cfg = 2 << 21 // ... and the official drivers/dma/sun6i-dma.c driver doesn't use it
ddmaDstIOMode ddmaR8Cfg = 1 << 21 // Non incrementing
ddmaDstLinear ddmaR8Cfg = 0 << 21 // Normal incrementing position
ddmaDstDrqSRAM ddmaR8Cfg = 0 << 16 // DDMA_DST_DRQ_SEL
ddmaDstDrqSDRAM ddmaR8Cfg = 1 << 16 // DDR ram speed
ddmaDstDrqNAND ddmaR8Cfg = 3 << 16 //
ddmaDstDrqUSB0 ddmaR8Cfg = 4 << 16 //
ddmaDstDrqSPI1TX ddmaR8Cfg = 8 << 16 //
ddmaDstDrqCryptoTX ddmaR8Cfg = 10 << 16 //
ddmaDstDrqTCON0 ddmaR8Cfg = 14 << 16 //
ddmaDstDrqSPI0TX ddmaR8Cfg = 26 << 16 //
ddmaDstDrqSPI2TX ddmaR8Cfg = 28 << 16 //
ddmaBCRemain ddmaR8Cfg = 1 << 15 // BC_MODE_SEL
// 14:11 reserved
ddmaSrcWidth32 ddmaR8Cfg = 2 << 9 // DDMA_SRC_DATA_WIDTH
ddmaSrcWidth16 ddmaR8Cfg = 1 << 9 //
ddmaSrcWidth8 ddmaR8Cfg = 0 << 9 //
ddmaSrcBurst8 ddmaR8Cfg = 2 << 7 // DDMA_SRC_BST_LEN
ddmaSrcBurst4 ddmaR8Cfg = 1 << 7 //
ddmaSrcBurst1 ddmaR8Cfg = 0 << 7 //
ddmaSrcVertical ddmaR8Cfg = 3 << 5 // DDMA_SRC_ADDR_MODE
ddmaSrcHorizontal ddmaR8Cfg = 2 << 5 //
ddmaSrcIOMode ddmaR8Cfg = 1 << 5 // Non incrementing
ddmaSrcLinear ddmaR8Cfg = 0 << 5 // Normal incrementing position
// 4:0 drq
ddmaSrcDrqSRAM ddmaR8Cfg = 0 << 0 // DDMA_SRC_DRQ_TYPE
ddmaSrcDrqSDRAM ddmaR8Cfg = 1 << 0 //
ddmaSrcDrqNAND ddmaR8Cfg = 3 << 0 //
ddmaSrcDrqUSB0 ddmaR8Cfg = 4 << 0 //
ddmaSrcDrqSPI1RX ddmaR8Cfg = 9 << 0 //
ddmaSrcDrqCryptoRX ddmaR8Cfg = 11 << 0 //
ddmaSrcDrqSPI0RX ddmaR8Cfg = 27 << 0 //
ddmaSrcDrqSPI2RX ddmaR8Cfg = 29 << 0 //
)
// DDMA_CFG_REG
// R8: Page 131-134.
type ddmaR8Cfg uint32
const (
// For each value, N+1 is actually used.
ddmaDstBlkSizeMask ddmaR8Param = 0xFF << 24 // DEST_DATA_BLK_SIZE
ddmaDstWaitClkCycleMask ddmaR8Param = 0xFF << 16 // DEST_WAIT_CLK_CYC
ddmaSrcBlkSizeMask ddmaR8Param = 0xFF << 8 // SRC_DATA_BLK_SIZE
ddmaSrcWaitClkCycleMask ddmaR8Param = 0xFF << 0 // SRC_WAIT_CLK_CYC
)
// DDMA_PARA_REG
// R8: Page 134.
type ddmaR8Param uint32
// smokeTest allocates two physical pages, ask the DMA controller to copy the
// data from one page to another (with a small offset) and make sure the
// content is as expected.
//
// This should take a fraction of a second and will make sure the driver is
// usable.
func smokeTest() error {
const size = 4096 // 4kb
const holeSize = 1 // Minimum DMA alignment.
alloc := func(s int) (pmem.Mem, error) {
return pmem.Alloc(s)
}
copyMem := func(pDst, pSrc uint64) error {
n := drvDMA.dmaMemory.getDedicated()
if n == -1 {
return errors.New("no channel available")
}
drvDMA.dmaMemory.irqEn &^= 3 << uint(2*n+16)
drvDMA.dmaMemory.irqPendStas = 3 << uint(2*n+16)
ch := &drvDMA.dmaMemory.dedicated[n]
defer func() {
_ = ch.release()
}()
ch.set(uint32(pSrc), uint32(pDst)+holeSize, 4096-2*holeSize, false, false, ddmaDstDrqSDRAM|ddmaSrcDrqSDRAM)
for ch.cfg&ddmaBusy != 0 {
}
return nil
}
return pmem.TestCopy(size, holeSize, alloc, copyMem)
}
// driverDMA implements periph.Driver.
//
// It implements much more than the DMA controller, it also exposes the clocks,
// the PWM and PCM controllers.
type driverDMA struct {
// dmaMemory is the memory map of the CPU DMA registers.
dmaMemory *dmaMap
// pwmMemory is the memory map of the CPU PWM registers.
pwmMemory *pwmMap
// spiMemory is the memory mapping for the spi CPU registers.
spiMemory *spiMap
// clockMemory is the memory mapping for the clock CPU registers.
clockMemory *clockMap
// timerMemory is the memory mapping for the timer CPU registers.
timerMemory *timerMap
}
func (d *driverDMA) String() string {
return "allwinner-dma"
}
func (d *driverDMA) Prerequisites() []string {
return []string{"allwinner-gpio"}
}
func (d *driverDMA) After() []string {
return nil
}
func (d *driverDMA) Init() (bool, error) {
// dmaBaseAddr is the physical base address of the DMA registers.
var dmaBaseAddr uint32
// pwmBaseAddr is the physical base address of the PWM registers.
var pwmBaseAddr uint32
// spiBaseAddr is the physical base address of the clock registers.
var spiBaseAddr uint32
// clockBaseAddr is the physical base address of the clock registers.
var clockBaseAddr uint32
// timerBaseAddr is the physical base address of the timer registers.
var timerBaseAddr uint32
if IsA64() {
// Page 198.
dmaBaseAddr = 0x1C02000
// Page 194.
pwmBaseAddr = 0x1C21400
// Page 161.
timerBaseAddr = 0x1C20C00
// Page 81.
clockBaseAddr = 0x1C20000
// Page Page 545.
spiBaseAddr = 0x01C68000
} else if IsR8() {
// Page 124.
dmaBaseAddr = 0x1C02000
// Page 83.
pwmBaseAddr = 0x1C20C00 + 0x200
// Page 85.
timerBaseAddr = 0x1C20C00
// Page 57.
clockBaseAddr = 0x1C20000
// Page 151.
spiBaseAddr = 0x01C05000
} else {
// H3
// Page 194.
//dmaBaseAddr = 0x1C02000
// Page 187.
//pwmBaseAddr = 0x1C21400
// Page 154.
//timerBaseAddr = 0x1C20C00
return false, errors.New("unsupported CPU architecture")
}
if err := pmem.MapAsPOD(uint64(dmaBaseAddr), &d.dmaMemory); err != nil {
if os.IsPermission(err) {
return true, fmt.Errorf("need more access, try as root: %v", err)
}
return true, err
}
if err := pmem.MapAsPOD(uint64(pwmBaseAddr), &d.pwmMemory); err != nil {
return true, err
}
if err := pmem.MapAsPOD(uint64(timerBaseAddr), &d.timerMemory); err != nil {
return true, err
}
if err := pmem.MapAsPOD(uint64(clockBaseAddr), &d.clockMemory); err != nil {
return true, err
}
if err := pmem.MapAsPOD(uint64(spiBaseAddr), &d.spiMemory); err != nil {
return true, err
}
return true, smokeTest()
}
func (d *driverDMA) Close() error {
// Stop DMA and PWM controllers.
return nil
}
func init() {
if false && isArm {
// TODO(maruel): This is intense, wait to be sure it works.
periph.MustRegister(&drvDMA)
}
}
var drvDMA driverDMA

33
vendor/periph.io/x/periph/host/allwinner/doc.go generated vendored Normal file
View File

@ -0,0 +1,33 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package allwinner exposes the GPIO functionality that is common to all
// AllWinner processors.
//
// This driver implements memory-mapped GPIO pin manipulation and leverages
// sysfs-gpio for edge detection.
//
// If you are looking at the actual implementation, open doc.go for further
// implementation details.
//
// Datasheets
//
// A64: http://files.pine64.org/doc/datasheet/pine64/Allwinner_A64_User_Manual_V1.0.pdf
//
// H3: http://dl.linux-sunxi.org/H3/Allwinner_H3_Datasheet_V1.0.pdf
//
// R8: https://github.com/NextThingCo/CHIP-Hardware/raw/master/CHIP%5Bv1_0%5D/CHIPv1_0-BOM-Datasheets/Allwinner%20R8%20User%20Manual%20V1.1.pdf
//
// Physical overview: http://files.pine64.org/doc/datasheet/pine64/A64_Datasheet_V1.1.pdf
package allwinner
// Other implementation details
//
// The most active kernel branch is
// https://github.com/linux-sunxi/linux-sunxi/commits/sunxi-next
//
// In particular look at
// https://github.com/linux-sunxi/linux-sunxi/blob/sunxi-next/drivers/dma/sun4i-dma.c
// and
// https://github.com/linux-sunxi/linux-sunxi/blob/sunxi-next/drivers/dma/sun6i-dma.c

1065
vendor/periph.io/x/periph/host/allwinner/gpio.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

563
vendor/periph.io/x/periph/host/allwinner/gpio_pl.go generated vendored Normal file
View File

@ -0,0 +1,563 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package allwinner
import (
"errors"
"fmt"
"os"
"path"
"strconv"
"strings"
"time"
"periph.io/x/periph"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/gpio/gpioreg"
"periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/pin"
"periph.io/x/periph/host/pmem"
"periph.io/x/periph/host/sysfs"
)
// All the pins in the PL group.
var PL0, PL1, PL2, PL3, PL4, PL5, PL6, PL7, PL8, PL9, PL10, PL11, PL12 *PinPL
// PinPL defines one CPU supported pin in the PL group.
//
// PinPL implements gpio.PinIO.
type PinPL struct {
// Immutable.
offset uint8 // as per register offset calculation
name string // name as per datasheet
defaultPull gpio.Pull // default pull at startup
// Immutable after driver initialization.
sysfsPin *sysfs.Pin // Set to the corresponding sysfs.Pin, if any.
available bool // Set when the pin is available on this CPU architecture.
// Mutable.
usingEdge bool // Set when edge detection is enabled.
}
// String implements conn.Resource.
//
// It returns the pin name and number, ex: "PL5(352)".
func (p *PinPL) String() string {
return fmt.Sprintf("%s(%d)", p.name, p.Number())
}
// Halt implements conn.Resource.
//
// It stops edge detection if enabled.
func (p *PinPL) Halt() error {
if p.usingEdge {
if err := p.sysfsPin.Halt(); err != nil {
return p.wrap(err)
}
p.usingEdge = false
}
return nil
}
// Name implements pin.Pin.
//
// It returns the pin name, ex: "PL5".
func (p *PinPL) Name() string {
return p.name
}
// Number implements pin.Pin.
//
// It returns the GPIO pin number as represented by gpio sysfs.
func (p *PinPL) Number() int {
return 11*32 + int(p.offset)
}
// Function implements pin.Pin.
func (p *PinPL) Function() string {
return string(p.Func())
}
// Func implements pin.PinFunc.
func (p *PinPL) Func() pin.Func {
if !p.available {
// We do not want the error message about uninitialized system.
return pin.FuncNone
}
if drvGPIOPL.gpioMemoryPL == nil {
if p.sysfsPin == nil {
return pin.Func("ERR")
}
return p.sysfsPin.Func()
}
switch f := p.function(); f {
case in:
if p.FastRead() {
return gpio.IN_HIGH
}
return gpio.IN_LOW
case out:
if p.FastRead() {
return gpio.OUT_HIGH
}
return gpio.OUT_LOW
case alt1:
if s := mappingPL[p.offset][0]; len(s) != 0 {
return pin.Func(s)
}
return pin.Func("ALT1")
case alt2:
if s := mappingPL[p.offset][1]; len(s) != 0 {
return pin.Func(s)
}
return pin.Func("ALT2")
case alt3:
if s := mappingPL[p.offset][2]; len(s) != 0 {
return pin.Func(s)
}
return pin.Func("ALT3")
case alt4:
if s := mappingPL[p.offset][3]; len(s) != 0 {
return pin.Func(s)
}
return pin.Func("ALT4")
case alt5:
if s := mappingPL[p.offset][4]; len(s) != 0 {
if strings.Contains(string(s), "_EINT") {
// It's an input supporting interrupts.
if p.FastRead() {
return gpio.IN_HIGH
}
return gpio.IN_LOW
}
return pin.Func(s)
}
return pin.Func("ALT5")
case disabled:
return pin.FuncNone
default:
return pin.FuncNone
}
}
// SupportedFuncs implements pin.PinFunc.
func (p *PinPL) SupportedFuncs() []pin.Func {
f := make([]pin.Func, 0, 2+2)
f = append(f, gpio.IN, gpio.OUT)
for _, m := range mappingPL[p.offset] {
if m != pin.FuncNone && !strings.Contains(string(m), "_EINT") {
f = append(f, m)
}
}
return f
}
// SetFunc implements pin.PinFunc.
func (p *PinPL) SetFunc(f pin.Func) error {
switch f {
case gpio.FLOAT:
return p.In(gpio.Float, gpio.NoEdge)
case gpio.IN:
return p.In(gpio.PullNoChange, gpio.NoEdge)
case gpio.IN_LOW:
return p.In(gpio.PullDown, gpio.NoEdge)
case gpio.IN_HIGH:
return p.In(gpio.PullUp, gpio.NoEdge)
case gpio.OUT_HIGH:
return p.Out(gpio.High)
case gpio.OUT_LOW:
return p.Out(gpio.Low)
default:
isGeneral := f == f.Generalize()
for i, m := range mappingPL[p.offset] {
if m == f || (isGeneral && m.Generalize() == f) {
if err := p.Halt(); err != nil {
return err
}
switch i {
case 0:
p.setFunction(alt1)
case 1:
p.setFunction(alt2)
case 2:
p.setFunction(alt3)
case 3:
p.setFunction(alt4)
case 4:
p.setFunction(alt5)
}
return nil
}
}
return p.wrap(errors.New("unsupported function"))
}
}
// In implements gpio.PinIn.
func (p *PinPL) In(pull gpio.Pull, edge gpio.Edge) error {
if !p.available {
// We do not want the error message about uninitialized system.
return p.wrap(errors.New("not available on this CPU architecture"))
}
if p.usingEdge && edge == gpio.NoEdge {
if err := p.sysfsPin.Halt(); err != nil {
return p.wrap(err)
}
p.usingEdge = false
}
if drvGPIOPL.gpioMemoryPL == nil {
if p.sysfsPin == nil {
return p.wrap(errors.New("subsystem gpiomem not initialized and sysfs not accessible; try running as root?"))
}
if pull != gpio.PullNoChange {
return p.wrap(errors.New("pull cannot be used when subsystem gpiomem not initialized; try running as root?"))
}
if err := p.sysfsPin.In(pull, edge); err != nil {
return p.wrap(err)
}
p.usingEdge = edge != gpio.NoEdge
return nil
}
if !p.setFunction(in) {
return p.wrap(errors.New("failed to set pin as input"))
}
if pull != gpio.PullNoChange {
off := p.offset / 16
shift := 2 * (p.offset % 16)
// Do it in a way that is concurrent safe.
drvGPIOPL.gpioMemoryPL.pull[off] &^= 3 << shift
switch pull {
case gpio.PullDown:
drvGPIOPL.gpioMemoryPL.pull[off] = 2 << shift
case gpio.PullUp:
drvGPIOPL.gpioMemoryPL.pull[off] = 1 << shift
default:
}
}
if edge != gpio.NoEdge {
if p.sysfsPin == nil {
return p.wrap(fmt.Errorf("pin %d is not exported by sysfs", p.Number()))
}
// This resets pending edges.
if err := p.sysfsPin.In(gpio.PullNoChange, edge); err != nil {
return p.wrap(err)
}
p.usingEdge = true
}
return nil
}
// Read implements gpio.PinIn.
func (p *PinPL) Read() gpio.Level {
if drvGPIOPL.gpioMemoryPL == nil {
if p.sysfsPin == nil {
return gpio.Low
}
return p.sysfsPin.Read()
}
return gpio.Level(drvGPIOPL.gpioMemoryPL.data&(1<<p.offset) != 0)
}
// FastRead reads without verification.
func (p *PinPL) FastRead() gpio.Level {
return gpio.Level(drvGPIOPL.gpioMemoryPL.data&(1<<p.offset) != 0)
}
// WaitForEdge implements gpio.PinIn.
func (p *PinPL) WaitForEdge(timeout time.Duration) bool {
if p.sysfsPin != nil {
return p.sysfsPin.WaitForEdge(timeout)
}
return false
}
// Pull implements gpio.PinIn.
func (p *PinPL) Pull() gpio.Pull {
if drvGPIOPL.gpioMemoryPL == nil {
// If gpioMemoryPL is set, p.available is true.
return gpio.PullNoChange
}
switch (drvGPIOPL.gpioMemoryPL.pull[p.offset/16] >> (2 * (p.offset % 16))) & 3 {
case 0:
return gpio.Float
case 1:
return gpio.PullUp
case 2:
return gpio.PullDown
default:
// Confused.
return gpio.PullNoChange
}
}
// DefaultPull implements gpio.PinIn.
func (p *PinPL) DefaultPull() gpio.Pull {
return p.defaultPull
}
// Out implements gpio.PinOut.
func (p *PinPL) Out(l gpio.Level) error {
if !p.available {
// We do not want the error message about uninitialized system.
return p.wrap(errors.New("not available on this CPU architecture"))
}
if drvGPIOPL.gpioMemoryPL == nil {
if p.sysfsPin != nil {
return p.wrap(errors.New("subsystem gpiomem not initialized and sysfs not accessible; try running as root?"))
}
return p.sysfsPin.Out(l)
}
// First disable edges.
if err := p.Halt(); err != nil {
return err
}
p.FastOut(l)
if !p.setFunction(out) {
return p.wrap(errors.New("failed to set pin as output"))
}
return nil
}
// FastOut sets a pin output level with Absolutely No error checking.
//
// See Pin.FastOut for more information.
func (p *PinPL) FastOut(l gpio.Level) {
bit := uint32(1 << p.offset)
if l {
drvGPIOPL.gpioMemoryPL.data |= bit
} else {
drvGPIOPL.gpioMemoryPL.data &^= bit
}
}
// PWM implements gpio.PinOut.
func (p *PinPL) PWM(gpio.Duty, physic.Frequency) error {
// TODO(maruel): PWM support for PL10.
return p.wrap(errors.New("not available on this CPU architecture"))
}
//
// function returns the current GPIO pin function.
//
// It must not be called if drvGPIOPL.gpioMemoryPL is nil.
func (p *PinPL) function() function {
shift := 4 * (p.offset % 8)
return function((drvGPIOPL.gpioMemoryPL.cfg[p.offset/8] >> shift) & 7)
}
// setFunction changes the GPIO pin function.
//
// Returns false if the pin was in AltN. Only accepts in and out
//
// It must not be called if drvGPIOPL.gpioMemoryPL is nil.
func (p *PinPL) setFunction(f function) bool {
if f != in && f != out {
return false
}
// Interrupt based edge triggering is Alt5 but this is only supported on some
// pins.
// TODO(maruel): This check should use a whitelist of pins.
if actual := p.function(); actual != in && actual != out && actual != disabled && actual != alt5 {
// Pin is in special mode.
return false
}
off := p.offset / 8
shift := 4 * (p.offset % 8)
mask := uint32(disabled) << shift
v := (uint32(f) << shift) ^ mask
// First disable, then setup. This is concurrent safe.
drvGPIOPL.gpioMemoryPL.cfg[off] |= mask
drvGPIOPL.gpioMemoryPL.cfg[off] &^= v
if p.function() != f {
panic(f)
}
return true
}
func (p *PinPL) wrap(err error) error {
return fmt.Errorf("allwinner-gpio-pl (%s): %v", p, err)
}
//
// cpuPinsPL is all the pins as supported by the CPU. There is no guarantee that
// they are actually connected to anything on the board.
var cpuPinsPL = []PinPL{
{offset: 0, name: "PL0", defaultPull: gpio.PullUp},
{offset: 1, name: "PL1", defaultPull: gpio.PullUp},
{offset: 2, name: "PL2", defaultPull: gpio.Float},
{offset: 3, name: "PL3", defaultPull: gpio.Float},
{offset: 4, name: "PL4", defaultPull: gpio.Float},
{offset: 5, name: "PL5", defaultPull: gpio.Float},
{offset: 6, name: "PL6", defaultPull: gpio.Float},
{offset: 7, name: "PL7", defaultPull: gpio.Float},
{offset: 8, name: "PL8", defaultPull: gpio.Float},
{offset: 9, name: "PL9", defaultPull: gpio.Float},
{offset: 10, name: "PL10", defaultPull: gpio.Float},
{offset: 11, name: "PL11", defaultPull: gpio.Float},
{offset: 12, name: "PL12", defaultPull: gpio.Float},
}
// See gpio.go for details.
var mappingPL = [13][5]pin.Func{
{"RSB_SCK", "I2C_SCL", "", "", "PL_EINT0"}, // PL0
{"RSB_SDA", "I2C_SDA", "", "", "PL_EINT1"}, // PL1
{"UART_TX", "", "", "", "PL_EINT2"}, // PL2
{"UART_RX", "", "", "", "PL_EINT3"}, // PL3
{"JTAG_TMS", "", "", "", "PL_EINT4"}, // PL4
{"JTAG_TCK", "", "", "", "PL_EINT5"}, // PL5
{"JTAG_TDO", "", "", "", "PL_EINT6"}, // PL6
{"JTAG_TDI", "", "", "", "PL_EINT7"}, // PL7
{"I2C_SCL", "", "", "", "PL_EINT8"}, // PL8
{"I2C_SDA", "", "", "", "PL_EINT9"}, // PL9
{"PWM0", "", "", "", "PL_EINT10"}, // PL10
{"CIR_RX", "", "", "", "PL_EINT11"}, // PL11
{"", "", "", "", "PL_EINT12"}, // PL12
}
func init() {
PL0 = &cpuPinsPL[0]
PL1 = &cpuPinsPL[1]
PL2 = &cpuPinsPL[2]
PL3 = &cpuPinsPL[3]
PL4 = &cpuPinsPL[4]
PL5 = &cpuPinsPL[5]
PL6 = &cpuPinsPL[6]
PL7 = &cpuPinsPL[7]
PL8 = &cpuPinsPL[8]
PL9 = &cpuPinsPL[9]
PL10 = &cpuPinsPL[10]
PL11 = &cpuPinsPL[11]
PL12 = &cpuPinsPL[12]
}
// getBaseAddressPL queries the virtual file system to retrieve the base address
// of the GPIO registers for GPIO pins in group PL.
//
// Defaults to 0x01F02C00 as per datasheet if could query the file system.
func getBaseAddressPL() uint64 {
base := uint64(0x01F02C00)
link, err := os.Readlink("/sys/bus/platform/drivers/sun50i-r-pinctrl/driver")
if err != nil {
return base
}
parts := strings.SplitN(path.Base(link), ".", 2)
if len(parts) != 2 {
return base
}
base2, err := strconv.ParseUint(parts[0], 16, 64)
if err != nil {
return base
}
return base2
}
// driverGPIOPL implements periph.Driver.
type driverGPIOPL struct {
// gpioMemoryPL is only the PL group in that case. Note that groups PI, PJ, PK
// do not exist.
gpioMemoryPL *gpioGroup
}
func (d *driverGPIOPL) String() string {
return "allwinner-gpio-pl"
}
func (d *driverGPIOPL) Prerequisites() []string {
return nil
}
func (d *driverGPIOPL) After() []string {
return []string{"sysfs-gpio"}
}
func (d *driverGPIOPL) Init() (bool, error) {
// BUG(maruel): H3 supports group PL too.
if !IsA64() {
return false, errors.New("A64 CPU not detected")
}
// Mark the right pins as available even if the memory map fails so they can
// callback to sysfs.Pins.
functions := map[pin.Func]struct{}{}
for i := range cpuPinsPL {
name := cpuPinsPL[i].Name()
num := strconv.Itoa(cpuPinsPL[i].Number())
cpuPinsPL[i].available = true
gpion := "GPIO" + num
// Unregister the pin if already registered. This happens with sysfs-gpio.
// Do not error on it, since sysfs-gpio may have failed to load.
_ = gpioreg.Unregister(gpion)
_ = gpioreg.Unregister(num)
// Register the pin with gpio.
if err := gpioreg.Register(&cpuPinsPL[i]); err != nil {
return true, err
}
if err := gpioreg.RegisterAlias(gpion, name); err != nil {
return true, err
}
if err := gpioreg.RegisterAlias(num, name); err != nil {
return true, err
}
switch f := cpuPinsPL[i].Func(); f {
case gpio.IN, gpio.OUT, pin.FuncNone:
default:
// Registering the same alias twice fails. This can happen if two pins
// are configured with the same function.
if _, ok := functions[f]; !ok {
// TODO(maruel): We'd have to clear out the ones from allwinner-gpio
// too.
functions[f] = struct{}{}
_ = gpioreg.RegisterAlias(string(f), name)
}
}
}
// Now do a second loop but do the alternate functions.
for i := range cpuPinsPL {
for _, f := range cpuPinsPL[i].SupportedFuncs() {
switch f {
case gpio.IN, gpio.OUT:
default:
if _, ok := functions[f]; !ok {
// TODO(maruel): We'd have to clear out the ones from allwinner-gpio
// too.
functions[f] = struct{}{}
_ = gpioreg.RegisterAlias(string(f), cpuPinsPL[i].name)
}
}
}
}
m, err := pmem.Map(getBaseAddressPL(), 4096)
if err != nil {
if os.IsPermission(err) {
return true, fmt.Errorf("need more access, try as root: %v", err)
}
return true, err
}
if err := m.AsPOD(&d.gpioMemoryPL); err != nil {
return true, err
}
return true, nil
}
func init() {
if isArm {
periph.MustRegister(&drvGPIOPL)
}
}
var drvGPIOPL driverGPIOPL
var _ gpio.PinIO = &PinPL{}
var _ gpio.PinIn = &PinPL{}
var _ gpio.PinOut = &PinPL{}
var _ pin.PinFunc = &PinPL{}

197
vendor/periph.io/x/periph/host/allwinner/pwm.go generated vendored Normal file
View File

@ -0,0 +1,197 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package allwinner
import (
"fmt"
"strings"
"time"
)
const pwmClock = 24000000
const pwmMaxPeriod = 0x10000
// prescalers is the value for pwm0Prescale*
var prescalers = []struct {
freq uint32
scaler pwmPrescale
}{
// Base frequency (min freq is half that) / PWM clock at pwmMaxPeriod
{pwmClock, pwmPrescale1}, // 24MHz / 366Hz
{pwmClock / 120, pwmPrescale120}, // 200kHz / 3Hz
{pwmClock / 180, pwmPrescale180}, // 133kHz / 2Hz
{pwmClock / 240, pwmPrescale240}, // 100kHz / 1.5Hz
{pwmClock / 360, pwmPrescale360}, // 66kHz / 1.01Hz
{pwmClock / 480, pwmPrescale480}, // 50kHz / 0.7Hz
{pwmClock / 12000, pwmPrescale12000}, // 2kHz
{pwmClock / 24000, pwmPrescale24000}, // 1kHz
{pwmClock / 36000, pwmPrescale36000}, // 666 Hz
{pwmClock / 48000, pwmPrescale48000}, // 500 Hz
{pwmClock / 72000, pwmPrescale72000}, // 333 Hz / 0.005Hz
}
const (
// 31:29 reserved
pwmBusy pwmCtl = 1 << 28 // PWM0_RDY
// 27:10 reserved (used for pwm1)
pwm0Mask pwmCtl = (1 << 10) - 1
pwm0Bypass pwmCtl = 1 << 9 // PWM0_BYPASS (marked as unused on some drivers?)
pwm0PulseStart pwmCtl = 1 << 8 // PWM_CH0_PUL_START
pwm0ModePulse pwmCtl = 1 << 7 // PWM_CHANNEL0_MODE
pwm0SCLK pwmCtl = 1 << 6 // SCLK_CH0_GATING
pwm0Polarity pwmCtl = 1 << 5 // PWM_CH0_ACT_STA
pwm0Enable pwmCtl = 1 << 4 // PWM_CH0_EN
// 3:0
pwm0PrescaleMask pwmCtl = pwmCtl(pwmPrescaleMask) // PWM_CH0_PRESCAL
pwm0Prescale120 pwmCtl = pwmCtl(pwmPrescale120)
pwm0Prescale180 pwmCtl = pwmCtl(pwmPrescale180)
pwm0Prescale240 pwmCtl = pwmCtl(pwmPrescale240)
pwm0Prescale360 pwmCtl = pwmCtl(pwmPrescale360)
pwm0Prescale480 pwmCtl = pwmCtl(pwmPrescale480)
// 5, 6, 7 reserved
pwm0Prescale12000 pwmCtl = pwmCtl(pwmPrescale12000)
pwm0Prescale24000 pwmCtl = pwmCtl(pwmPrescale24000)
pwm0Prescale36000 pwmCtl = pwmCtl(pwmPrescale36000)
pwm0Prescale48000 pwmCtl = pwmCtl(pwmPrescale48000)
pwm0Prescale72000 pwmCtl = pwmCtl(pwmPrescale72000)
// 13, 14 reserved
pwm0Prescale1 pwmCtl = pwmCtl(pwmPrescale1)
)
// A64: Pages 194-195.
// R8: Pages 83-84.
type pwmCtl uint32
func (p pwmCtl) String() string {
var out []string
if p&pwmBusy != 0 {
out = append(out, "PWM0_RDY")
p &^= pwmBusy
}
if p&pwm0Bypass != 0 {
out = append(out, "PWM0_BYPASS")
p &^= pwm0Bypass
}
if p&pwm0PulseStart != 0 {
out = append(out, "PWM0_CH0_PUL_START")
p &^= pwm0PulseStart
}
if p&pwm0ModePulse != 0 {
out = append(out, "PWM0_CHANNEL0_MODE")
p &^= pwm0ModePulse
}
if p&pwm0SCLK != 0 {
out = append(out, "SCLK_CH0_GATING")
p &^= pwm0SCLK
}
if p&pwm0Polarity != 0 {
out = append(out, "PWM_CH0_ACT_STA")
p &^= pwm0Polarity
}
if p&pwm0Enable != 0 {
out = append(out, "PWM_CH0_EN")
p &^= pwm0Enable
}
out = append(out, pwmPrescale(p&pwm0PrescaleMask).String())
p &^= pwm0PrescaleMask
if p != 0 {
out = append(out, fmt.Sprintf("Unknown(0x%08X)", uint32(p)))
}
return strings.Join(out, "|")
}
const (
pwmPrescaleMask pwmPrescale = 0xF
pwmPrescale120 pwmPrescale = 0
pwmPrescale180 pwmPrescale = 1
pwmPrescale240 pwmPrescale = 2
pwmPrescale360 pwmPrescale = 3
pwmPrescale480 pwmPrescale = 4
// 5, 6, 7 reserved
pwmPrescale12000 pwmPrescale = 8
pwmPrescale24000 pwmPrescale = 9
pwmPrescale36000 pwmPrescale = 10
pwmPrescale48000 pwmPrescale = 11
pwmPrescale72000 pwmPrescale = 12
// 13, 14 reserved
pwmPrescale1 pwmPrescale = 15
)
type pwmPrescale uint32
func (p pwmPrescale) String() string {
switch p {
case pwmPrescale120:
return "/120"
case pwmPrescale180:
return "/180"
case pwmPrescale240:
return "/240"
case pwmPrescale360:
return "/360"
case pwmPrescale480:
return "/480"
case pwmPrescale12000:
return "/12k"
case pwmPrescale24000:
return "/24k"
case pwmPrescale36000:
return "/36k"
case pwmPrescale48000:
return "/48k"
case pwmPrescale72000:
return "/72k"
case pwmPrescale1:
return "/1"
default:
return fmt.Sprintf("InvalidScalar(%d)", p&pwmPrescaleMask)
}
}
// A64: Page 195.
// R8: Page 84
type pwmPeriod uint32
func (p pwmPeriod) String() string {
return fmt.Sprintf("%d/%d", p&0xFFFF, uint32((p>>16)&0xFFFF)+1)
}
func toPeriod(total uint32, active uint16) pwmPeriod {
if total > pwmMaxPeriod {
total = pwmMaxPeriod
}
return pwmPeriod(total-1)<<16 | pwmPeriod(active)
}
// getBestPrescale finds the best prescaler.
//
// Cycles must be between 2 and 0x10000/2.
func getBestPrescale(period time.Duration) pwmPrescale {
// TODO(maruel): Rewrite this function, it is incorrect.
for _, v := range prescalers {
p := time.Second / time.Duration(v.freq)
smallest := (period / pwmMaxPeriod)
largest := (period / 2)
if p > smallest && p < largest {
return v.scaler
}
}
// Period is longer than 196s.
return pwmPrescale72000
}
// pwmMap represents the PWM memory mapped CPU registers.
//
// The base frequency is 24Mhz.
//
// TODO(maruel): Some CPU have 2 PWMs.
type pwmMap struct {
ctl pwmCtl // PWM_CTRL_REG
period pwmPeriod // PWM_CH0_PERIOD
}
func (p *pwmMap) String() string {
return fmt.Sprintf("pwmMap{%s, %v}", p.ctl, p.period)
}

149
vendor/periph.io/x/periph/host/allwinner/r8.go generated vendored Normal file
View File

@ -0,0 +1,149 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// This file contains pin mapping information that is specific to the Allwinner
// R8 model.
package allwinner
import (
"strings"
"periph.io/x/periph/conn/pin"
"periph.io/x/periph/host/sysfs"
)
// R8 specific pins.
var (
FEL *pin.BasicPin // Boot mode selection
MIC_IN *pin.BasicPin // Microphone in
MIC_GND *pin.BasicPin // Microphone ground
HP_LEFT *pin.BasicPin // Left speaker out
HP_RIGHT *pin.BasicPin // Right speaker out
HP_COM *pin.BasicPin // Speaker common
X1, X2, Y1, Y2 *pin.BasicPin // Touch screen pins
)
//
func init() {
FEL = &pin.BasicPin{N: "FEL"}
MIC_IN = &pin.BasicPin{N: "MIC_IN"}
MIC_GND = &pin.BasicPin{N: "MIC_GND"}
HP_LEFT = &pin.BasicPin{N: "HP_LEFT"}
HP_RIGHT = &pin.BasicPin{N: "HP_RIGHT"}
HP_COM = &pin.BasicPin{N: "HP_COM"}
X1 = &pin.BasicPin{N: "X1"}
X2 = &pin.BasicPin{N: "X2"}
Y1 = &pin.BasicPin{N: "Y1"}
Y2 = &pin.BasicPin{N: "Y2"}
}
// mappingR8 describes the mapping of each R8 processor gpio to their alternate
// functions.
//
// It omits the in & out functions which are available on all pins.
//
// The mapping comes from the datasheet page 18:
// https://github.com/NextThingCo/CHIP-Hardware/raw/master/CHIP%5Bv1_0%5D/CHIPv1_0-BOM-Datasheets/Allwinner%20R8%20Datasheet%20V1.2.pdf
//
// - The datasheet uses TWI instead of I2C but this is renamed here for consistency.
var mappingR8 = map[string][5]pin.Func{
"PB0": {"I2C0_SCL"},
"PB1": {"I2C0_SDA"},
"PB2": {"PWM0", "", "", "", "EINT16"},
"PB3": {"IR_TX", "", "", "", "EINT17"},
"PB4": {"IR_RX", "", "", "", "EINT18"},
"PB10": {"SPI2_CS1"},
"PB15": {"I2C1_SCL"},
"PB16": {"I2C1_SDA"},
"PB17": {"I2C2_SCL"},
"PB18": {"I2C2_SDA"},
"PC0": {"NAND_WE", "SPI0_MOSI"},
"PC1": {"NAND_ALE", "SPI0_MISO"},
"PC2": {"NAND_CLE", "SPI0_CLK"},
"PC3": {"NAND_CE1", "SPI0_CS0"},
"PC4": {"NAND_CE0"},
"PC5": {"NAND_RE"},
"PC6": {"NAND_RB0", "SDC2_CMD"},
"PC7": {"NAND_RB1", "SDC2_CLK"},
"PC8": {"NAND_DQ0", "SDC2_D0"},
"PC9": {"NAND_DQ1", "SDC2_D1"},
"PC10": {"NAND_DQ2", "SDC2_D2"},
"PC11": {"NAND_DQ3", "SDC2_D3"},
"PC12": {"NAND_DQ4", "SDC2_D4"},
"PC13": {"NAND_DQ5", "SDC2_D5"},
"PC14": {"NAND_DQ6", "SDC2_D6"},
"PC15": {"NAND_DQ7", "SDC2_D7"},
"PC19": {""},
"PD2": {"LCD_D2", "UART2_TX"},
"PD3": {"LCD_D3", "UART2_RX"},
"PD4": {"LCD_D4", "UART2_CTX"},
"PD5": {"LCD_D5", "UART2_RTS"},
"PD6": {"LCD_D6", "ECRS"},
"PD7": {"LCD_D7", "ECOL"},
"PD10": {"LCD_D10", "ERXD0"},
"PD11": {"LCD_D11", "ERXD1"},
"PD12": {"LCD_D12", "ERXD2"},
"PD13": {"LCD_D13", "ERXD3"},
"PD14": {"LCD_D14", "ERXCK"},
"PD15": {"LCD_D15", "ERXERR"},
"PD18": {"LCD_D18", "ERXDV"},
"PD19": {"LCD_D19", "ETXD0"},
"PD20": {"LCD_D20", "ETXD1"},
"PD21": {"LCD_D21", "ETXD2"},
"PD22": {"LCD_D22", "ETXD3"},
"PD23": {"LCD_D23", "ETXEN"},
"PD24": {"LCD_CLK", "ETXCK"},
"PD25": {"LCD_DE", "ETXERR"},
"PD26": {"LCD_HSYNC", "EMDC"},
"PD27": {"LCD_VSYNC", "EMDIO"},
"PE0": {"TS_CLK", "CSI_PCLK", "SPI2_CS0", "", "EINT14"},
"PE1": {"TS_ERR", "CSI_MCLK", "SPI2_CLK", "", "EINT15"},
"PE2": {"TS_SYNC", "CSI_HSYNC", "SPI2_MOSI"},
"PE3": {"TS_DVLD", "CSI_VSYNC", "SPI2_MISO"},
"PE4": {"TS_D0", "CSI_D0", "SDC2_D0"},
"PE5": {"TS_D1", "CSI_D1", "SDC2_D1"},
"PE6": {"TS_D2", "CSI_D2", "SDC2_D2"},
"PE7": {"TS_D3", "CSI_D3", "SDC2_D3"},
"PE8": {"TS_D4", "CSI_D4", "SDC2_CMD"},
"PE9": {"TS_D5", "CSI_D5", "SDC2_CLK"},
"PE10": {"TS_D6", "CSI_D6", "UART1_TX"},
"PE11": {"TS_D7", "CSI_D7", "UART1_RX"},
"PF0": {"SDC0_D1", "", "JTAG1_TMS"},
"PF1": {"SDC0_D0", "", "JTAG1_TDI"},
"PF2": {"SDC0_CLK", "", "UART0_TX"},
"PF3": {"SDC0_CMD", "", "JTAG1_TDO"},
"PF4": {"SDC0_D3", "", "UART0_RX"},
"PF5": {"SDC0_D2", "", "JTAG1_TCK"},
"PG0": {"GPS_CLK", "", "", "", "EINT0"},
"PG1": {"GPS_SIGN", "", "", "", "EINT1"},
"PG2": {"GPS_MAG", "", "", "", "EINT2"},
"PG3": {"", "", "UART1_TX", "", "EINT3"},
"PG4": {"", "", "UART1_RX", "", "EINT4"},
"PG9": {"SPI1_CS0", "UART3_TX", "", "", "EINT9"},
"PG10": {"SPI1_CLK", "UART3_RX", "", "", "EINT10"},
"PG11": {"SPI1_MOSI", "UART3_CTS", "", "", "EINT11"},
"PG12": {"SPI1_MISO", "UART3_RTS", "", "", "EINT12"},
}
// mapR8Pins uses mappingR8 to actually set the altFunc fields of all gpio and
// mark them as available.
//
// It is called by the generic allwinner processor code if a R8 is detected.
func mapR8Pins() error {
for name, altFuncs := range mappingR8 {
pin := cpupins[name]
pin.altFunc = altFuncs
pin.available = true
if strings.Contains(string(altFuncs[4]), "EINT") {
pin.supportEdge = true
}
// Initializes the sysfs corresponding pin right away.
pin.sysfsPin = sysfs.Pins[pin.Number()]
}
return nil
}

207
vendor/periph.io/x/periph/host/allwinner/spi.go generated vendored Normal file
View File

@ -0,0 +1,207 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package allwinner
import (
"errors"
"fmt"
"log"
"time"
)
const (
// 31:20 reserved
// Set this bit to 1 to make the internal read sample point with a delay of
// half cycle of SPI_CLK. It is used in high speed read operation to reduce
// the error caused by the time delay of SPI_CLK propagating between master
// and slave.
// 1 delay internal read sample point
// 0 normal operation, do not delay internal read sample point
spiR8HalfDelay spiR8Ctl = 1 << 19 // Master Sample Data Control
spiR8TransmitPause spiR8Ctl = 1 << 18 // Transmit Pause Enable
spiR8CSLevel spiR8Ctl = 1 << 17 // SS_LEVEL; Chip Select level
spiR8CSManual spiR8Ctl = 1 << 16 // SS_CTRL; Do not switch CS automatically
spiR8DiscardHash spiR8Ctl = 1 << 15 // DHB
spiR8DummyBurst spiR8Ctl = 1 << 14 // DDB
spiR8CS0 spiR8Ctl = 0 << 12 // SS; Which CS line to use. For SPI0 only
spiR8CS1 spiR8Ctl = 1 << 12 //
spiR8CS2 spiR8Ctl = 2 << 12 //
spiR8CS3 spiR8Ctl = 3 << 12 //
spiR8RapidsReadMode spiR8Ctl = 1 << 11 // RPSM
spiR8ExchangeBurst spiR8Ctl = 1 << 10 // XCH
spiR8RXFIFOReset spiR8Ctl = 1 << 9 // RXFIFO Reset; Write to reset the FIFO as empty
spiR8TXFIFOReset spiR8Ctl = 1 << 8 // TXFIFO Reset; Write to reset the FIFO as empty
spiR8CSBetweenBursts spiR8Ctl = 1 << 7 // SSCTL
spiR8LSB spiR8Ctl = 1 << 6 // LMTF; MSB by default, LSB when set
spiR8DDMA spiR8Ctl = 1 << 5 // DMAM; Use dedicated DMA if set, normal DMA otherwise
spiR8CSActiveLow spiR8Ctl = 1 << 4 // SSPOL; CS line polarity
spiR8ClkActiveLow spiR8Ctl = 1 << 3 // POL; Clock line polarity
spiR8PHA spiR8Ctl = 1 << 2 // PHA; Phase 1 if set (leading edge for setup data)
spiR8Master spiR8Ctl = 1 << 1 // MODE; Slave mode if not set
spiR8Enable spiR8Ctl = 1 << 0 // EN; Enable mode
)
// SPI_CTL
// R8: Page 153-155. Default: 0x0002001C
type spiR8Ctl uint32
// SPI_INTCTL
// R8: Page 155-156.
type spiR8IntCtl uint32
const (
spiR8ClearInterrupt spiR8IntStatus = 1 << 31 // Clear interrupt busy flag
// 30:18 reserved
spiR8InvalidSS spiR8IntStatus = 1 << 17 // SSI
spiR8TC spiR8IntStatus = 1 << 16 // TC; Transfer Completed
)
// SPI_INT_STA
// R8: Page 156-157.
type spiR8IntStatus uint32
const (
// 31:13 reserved
spiR8DMATX3Quarter spiR8DMACtl = 1 << 12 // TXFIFO 3/4 empty
spiR8DMATX1Quarter spiR8DMACtl = 1 << 11 // TXFIFO 1/4 empty
spiR8DMATXByte spiR8DMACtl = 1 << 10 // TXFIFO Not Full
spiR8DMATXHalf spiR8DMACtl = 1 << 9 // TXFIFO 1/2 empty
spiR8DMATXEmpty spiR8DMACtl = 1 << 8 // TXFIFO empty
// 7:5 reserved
spiR8DMARX3Quarter spiR8DMACtl = 1 << 4 // RXFIFO 3/4 empty
spiR8DMARX1Quarter spiR8DMACtl = 1 << 3 // RXFIFO 1/4 empty
spiR8DMARXByte spiR8DMACtl = 1 << 2 // RXFIFO Not Full
spiR8DMARXHalf spiR8DMACtl = 1 << 1 // RXFIFO 1/2 empty
spiR8DMARXEmpty spiR8DMACtl = 1 << 0 // RXFIFO empty
)
// SPI_DMACTL
// R8: Page 158.
type spiR8DMACtl uint32
const (
// 31:13 reserved
spiR8DivRateSelect2 spiR8ClockCtl = 1 << 12 // DRS; Use spiDivXX if set, use mask otherwise
spiR8Div2 spiR8ClockCtl = 0 << 8 // CDR1; Use divisor 2^(n+1)
spiR8Div4 spiR8ClockCtl = 1 << 8 //
spiR8Div8 spiR8ClockCtl = 2 << 8 //
spiR8Div16 spiR8ClockCtl = 3 << 8 //
spiR8Div32 spiR8ClockCtl = 4 << 8 //
spiR8Div64 spiR8ClockCtl = 5 << 8 //
spiR8Div128 spiR8ClockCtl = 6 << 8 //
spiR8Div256 spiR8ClockCtl = 7 << 8 //
spiR8Div512 spiR8ClockCtl = 8 << 8 //
spiR8Div1024 spiR8ClockCtl = 9 << 8 //
spiR8Div2048 spiR8ClockCtl = 10 << 8 //
spiR8Div4096 spiR8ClockCtl = 11 << 8 //
spiR8Div8192 spiR8ClockCtl = 12 << 8 //
spiR8Div16384 spiR8ClockCtl = 13 << 8 //
spiR8Div32768 spiR8ClockCtl = 14 << 8 //
spiR8Div65536 spiR8ClockCtl = 15 << 8 //
spiR8Div1Mask spiR8ClockCtl = 0xFF // CDR2; Use divisor 2*(n+1)
)
// SPI_CCTL
// R8: Page 159.
type spiR8ClockCtl uint32
const (
// 31:25 reserved
spiR8FIFOTXShift = 16 // 0 to 64
// 15:7 reserved
spiR8FIFORXShift = 0 // 0 to 64
)
// SPI_FIFO_STA
// R8: Page 160.
type spiR8FIFOStatus uint32
func (s spiR8FIFOStatus) tx() uint8 {
return uint8((uint32(s) >> 16) & 127)
}
func (s spiR8FIFOStatus) rx() uint8 {
return uint8(uint32(s) & 127)
}
// spiR8Group is the mapping of SPI registers for one SPI controller.
// R8: Page 152-153.
type spiR8Group struct {
rx uint32 // 0x00 SPI_RX_DATA RX Data
tx uint32 // 0x04 SPI_TX_DATA TX Data
ctl spiR8Ctl // 0x08 SPI_CTL Control
intCtl spiR8IntCtl // 0x0C SPI_INTCTL Interrupt Control
status spiR8IntStatus // 0x10 SPI_ST Status
dmaCtl spiR8DMACtl // 0x14 SPI_DMACTL DMA Control
wait uint32 // 0x18 SPI_WAIT Clock Counter; 16 bits
clockCtl spiR8ClockCtl // 0x1C SPI_CCTL Clock Rate Control
burstCounter uint32 // 0x20 SPI_BC Burst Counter; 24 bits
transmitCounter uint32 // 0x24 SPI_TC Transmit Counter; 24 bits
fifoStatus spiR8FIFOStatus // 0x28 SPI_FIFO_STA FIFO Status
reserved [(0x1000 - 0x02C) / 4]uint32
}
func (s *spiR8Group) setup() {
s.intCtl = 0
s.status = 0
//s.dmaCtl = spiR8DMARXByte
s.dmaCtl = 0
s.wait = 2
s.clockCtl = spiR8DivRateSelect2 | spiR8Div1024
// spiR8DDMA
s.ctl = spiR8CSManual | spiR8LSB | spiR8Master | spiR8Enable
}
// spiMap is the mapping of SPI registers.
// R8: Page 152-153.
type spiMap struct {
groups [3]spiR8Group
}
// spi2Write do a write on SPI2_MOSI via polling.
func spi2Write(w []byte) error {
if drvDMA.clockMemory == nil || drvDMA.spiMemory == nil {
return errors.New("subsystem not initialized")
}
// Make sure the source clock is disabled. Set it at 250kHz.
//drvDMA.clockMemory.spi2Clk &^= clockSPIEnable
drvDMA.clockMemory.spi2Clk |= clockSPIEnable
drvDMA.clockMemory.spi2Clk = clockSPIDiv8a | clockSPIDiv12b
ch := &drvDMA.spiMemory.groups[2]
ch.setup()
fmt.Printf("Setup done\n")
for i := 0; i < len(w)/4; i++ {
// TODO(maruel): Access it in 8bit mode.
ch.tx = uint32(w[0])
for ch.fifoStatus.tx() == 0 {
log.Printf("Waiting for bit %# v\n", ch)
time.Sleep(time.Second)
}
}
fmt.Printf("Done\n")
return nil
}
// spi2Read do a read on SPI2_MISO via polling.
func spi2Read(r []byte) error {
if drvDMA.clockMemory == nil || drvDMA.spiMemory == nil {
return errors.New("subsystem not initialized")
}
// Make sure the source clock is disabled. Set it at 250kHz.
//drvDMA.clockMemory.spi2Clk &^= clockSPIEnable
drvDMA.clockMemory.spi2Clk |= clockSPIEnable
drvDMA.clockMemory.spi2Clk = clockSPIDiv8a | clockSPIDiv12b
ch := &drvDMA.spiMemory.groups[2]
ch.setup()
for i := 0; i < len(r)/4; i++ {
ch.tx = 0
for ch.status&spiR8TC == 0 {
}
// TODO(maruel): Access it in 8bit mode.
r[i] = uint8(ch.rx)
}
fmt.Printf("Done\n")
return nil
}

128
vendor/periph.io/x/periph/host/allwinner/timer.go generated vendored Normal file
View File

@ -0,0 +1,128 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package allwinner
import (
"time"
"periph.io/x/periph/host/cpu"
)
// ReadTime returns the time on a monotonic timer.
//
// It only works if allwinner-dma successfully loaded. Otherwise it returns 0.
func ReadTime() time.Duration {
if drvDMA.timerMemory == nil {
return 0
}
v := uint64(drvDMA.timerMemory.counterHigh)<<32 | uint64(drvDMA.timerMemory.counterLow)
if v == 0 {
// BUG(maruel): Implement using AVS_CNT0_REG on A64.
return 0
}
// BUG(maruel): Assumes that counterCtrl & timerPLL6 is not set.
const tick = time.Microsecond / 24
return time.Duration(v) * tick
}
// Nanospin spins the CPU without calling into the kernel code if possible.
func Nanospin(t time.Duration) {
start := ReadTime()
if start == 0 {
// Use the slow generic version.
cpu.Nanospin(t)
return
}
for ReadTime()-start < t {
}
}
//
const (
// 31:3 reserved
timerPLL6 timerCtrl = 2 << 1 // CONT64_CLK_SRC_SEL; OSC24M if not set;
timerReadLatchEnable timerCtrl = 1 << 1 // CONT64_RLATCH_EN; 1 to latch the counter to the registers
timerClear = 1 << 0 // CONT64_CLR_EN; clears the counter
)
// R8: Page 96
type timerCtrl uint32
// timerMap is the mapping of important registers across CPUs.
type timerMap struct {
reserved0 [0x80 / 4]uint32 //
cntCtl timerCtrl // 0x80 AVS_CNT_CTL_REG AVS Control Register
cnt0 uint32 // 0x84 AVS_CNT0_REG AVS Counter 0 Register
cnt1 uint32 // 0x88 AVS_CNT1_REG AVS Counter 1 Register
cndDrv uint32 // 0x8C AVS_CNT_DIV_REG AVS Divisor Register
reserved1 [0x10 / 4]uint32 // On R8 only.
counterCtrl timerCtrl // 0x0A0 COUNTER64_CTRL_REG 64-bit Counter control
counterLow uint32 // 0x0A4 COUNTER64_LOW_REG 64-bit Counter low
counterHigh uint32 // 0x0A8 COUNTER64_HI_REG 64-bit Counter high
}
// A64: Page 161.
type timerMapA64 struct {
reserved0 uint32 // 0x0 TMR_IRQ_EN_REG Timer IRQ Enable Register
reserved1 uint32 // 0x4 TMR_IRQ_STA_REG Timer Status Register
reserved2 uint32 // 0x10 TMR0_CTRL_REG Timer 0 Control Register
reserved3 uint32 // 0x14 TMR0_INTV_VALUE_REG Timer 0 Interval Value Register
reserved4 uint32 // 0x18 TMR0_CUR_VALUE_REG Timer 0 Current Value Register
reserved5 uint32 // 0x20 TMR1_CTRL_REG Timer 1 Control Register
reserved6 uint32 // 0x24 TMR1_INTV_VALUE_REG Timer 1 Interval Value Register
reserved7 uint32 // 0x28 TMR1_CUR_VALUE_REG Timer 1 Current Value Register
cntCtl timerCtrl // 0x80 AVS_CNT_CTL_REG AVS Control Register
cnt0 uint32 // 0x84 AVS_CNT0_REG AVS Counter 0 Register
cnt1 uint32 // 0x88 AVS_CNT1_REG AVS Counter 1 Register
cndDrv uint32 // 0x8C AVS_CNT_DIV_REG AVS Divisor Register
reserved8 uint32 // 0xA0 WDOG0_IRQ_EN_REG Watchdog 0 IRQ Enable Register
reserved9 uint32 // 0xA4 WDOG0_IRQ_STA_REG Watchdog 0 Status Register
reserved10 uint32 // 0xB0 WDOG0_CTRL_REG Watchdog 0 Control Register
reserved11 uint32 // 0xB4 WDOG0_CFG_REG Watchdog 0 Configuration Register
reserved12 uint32 // 0xB8 WDOG0_MODE_REG Watchdog 0 Mode Register
}
// R8: Page 85
type timerMapR8 struct {
reserved0 uint32 // 0x000 ASYNC_TMR_IRQ_EN_REG Timer IRQ Enable
reserved1 uint32 // 0x004 ASYNC_TMR_IRQ_STAS_REG Timer Status
reserved2 [2]uint32 // 0x008-0x00C
reserved3 uint32 // 0x010 ASYNC_TMR0_CTRL_REG Timer 0 Control
reserved4 uint32 // 0x014 ASYNC_TMR0_INTV_VALUE_REG Timer 0 Interval Value
reserved5 uint32 // 0x018 ASYNC_TMR0_CURNT_VALUE_REG Timer 0 Current Value
reserved6 uint32 // 0x01C
reserved7 uint32 // 0x020 ASYNC_TMR1_CTRL_REG Timer 1 Control
reserved8 uint32 // 0x024 ASYNC_TMR1_INTV_VALUE_REG Timer 1 Interval Value
reserved9 uint32 // 0x028 ASYNC_TMR1_CURNT_VALUE_REG Timer 1 Current Value
reserved10 uint32 // 0x02C
reserved11 uint32 // 0x030 ASYNC_TMR2_CTRL_REG Timer 2 Control
reserved12 uint32 // 0x034 ASYNC_TMR2_INTV_VALUE_REG Timer 2 Interval Value
reserved13 uint32 // 0x038 ASYNC_TMR2_CURNT_VALUE_REG Timer 2 Current Value
reserved14 uint32 // 0x03C
reserved15 uint32 // 0x040 ASYNC_TMR3_CTRL_REG Timer 3 Control
reserved16 uint32 // 0x044 ASYNC_TMR3_INTV_VALUE_REG Timer 3 Interval Value
reserved17 [2]uint32 // 0x048-0x04C
reserved18 uint32 // 0x050 ASYNC_TMR4_CTRL_REG Timer 4 Control
reserved19 uint32 // 0x054 ASYNC_TMR4_INTV_VALUE_REG Timer 4 Interval Value
reserved20 uint32 // 0x058 ASYNC_TMR4_CURNT_VALUE_REG Timer 4 Current Value
reserved21 uint32 // 0x05C
reserved22 uint32 // 0x060 ASYNC_TMR5_CTRL_REG Timer 5 Control
reserved23 uint32 // 0x064 ASYNC_TMR5_INTV_VALUE_REG Timer 5 Interval Value
reserved24 uint32 // 0x068 ASYNC_TMR5_CURNT_VALUE_REG Timer 5 Current Value
reserved25 [5]uint32 // 0x06C-0x07C
cntCtl timerCtrl // 0x080 AVS_CNT_CTL_REG AVS Control Register
cnt0 uint32 // 0x084 AVS_CNT0_REG AVS Counter 0 Register
cnt1 uint32 // 0x088 AVS_CNT1_REG AVS Counter 1 Register
cndDiv uint32 // 0x08C AVS_CNT_DIVISOR_REG AVS Divisor
reserved26 uint32 // 0x090 WDOG_CTRL_REG
reserved27 uint32 // 0x094 WDOG_MODE_REG Watchdog Mode
reserved28 [2]uint32 // 0x098-0x09C
counterCtrl timerCtrl // 0x0A0 COUNTER64_CTRL_REG 64-bit Counter control
counterLow uint32 // 0x0A4 COUNTER64_LOW_REG 64-bit Counter low
counterHigh uint32 // 0x0A8 COUNTER64_HI_REG 64-bit Counter high
reserved29 [0x94]uint32 // 0x0AC-0x13C
reserved30 uint32 // 0x140 CPU_CFG_REG CPU configuration register
}

52
vendor/periph.io/x/periph/host/am335x/am335x.go generated vendored Normal file
View File

@ -0,0 +1,52 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package am335x
import (
"errors"
"strings"
"periph.io/x/periph"
"periph.io/x/periph/host/distro"
)
// Present returns true if a TM AM335x processor is detected.
func Present() bool {
if isArm {
return strings.HasPrefix(distro.DTModel(), "TI AM335x")
}
return false
}
// driver implements periph.Driver.
type driver struct {
}
func (d *driver) String() string {
return "am335x"
}
func (d *driver) Prerequisites() []string {
return nil
}
func (d *driver) After() []string {
return nil
}
func (d *driver) Init() (bool, error) {
if !Present() {
return false, errors.New("am335x CPU not detected")
}
return true, nil
}
func init() {
if isArm {
periph.MustRegister(&drv)
}
}
var drv driver

7
vendor/periph.io/x/periph/host/am335x/am335x_arm.go generated vendored Normal file
View File

@ -0,0 +1,7 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package am335x
const isArm = true

View File

@ -0,0 +1,9 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build !arm
package am335x
const isArm = false

28
vendor/periph.io/x/periph/host/am335x/doc.go generated vendored Normal file
View File

@ -0,0 +1,28 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package am335x exposes functionality for the Texas Instruments Sitara AM335x
// processor family.
//
// This processor family is found on the BeagleBone. PRU-ICSS functionality is
// implemented in package pru.
//
// The GPIO pins of the AM335x CPU are grouped into 3 groups of 32 pins: GPIO0,
// GPIO1, and GPIO2. The CPU documentation refers to GPIO in the form of
// GPIOx_y. To get the absolute number, as exposed by sysfs, use 32*x+y to get
// the absolute number.
//
// Datasheet
//
// Technical Reference Manual
// https://www.ti.com/lit/ug/spruh73p/spruh73p.pdf
//
// Other
//
// Marketing page
// https://www.ti.com/processors/sitara/arm-cortex-a8/am335x/overview.html
//
// Family overview
// https://www.ti.com/lit/ds/symlink/am3359.pdf
package am335x

View File

@ -0,0 +1,7 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package bcm283x
const isArm = true

View File

@ -0,0 +1,9 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build arm64
package bcm283x
const isArm = true

View File

@ -0,0 +1,9 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build !arm,!arm64
package bcm283x
const isArm = false

330
vendor/periph.io/x/periph/host/bcm283x/clock.go generated vendored Normal file
View File

@ -0,0 +1,330 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package bcm283x
import (
"errors"
"fmt"
"strings"
"time"
"periph.io/x/periph/conn/physic"
)
// errClockRegister is returned in a situation where the clock memory is not
// working as expected. It is mocked in tests.
var errClockRegister = errors.New("can't write to clock divisor CPU register")
// Clock sources frequency in hertz.
const (
clk19dot2MHz = 19200 * physic.KiloHertz
clk500MHz = 500 * physic.MegaHertz
)
const (
// 31:24 password
clockPasswdCtl clockCtl = 0x5A << 24 // PASSWD
// 23:11 reserved
clockMashMask clockCtl = 3 << 9 // MASH
clockMash0 clockCtl = 0 << 9 // src_freq / divI (ignores divF)
clockMash1 clockCtl = 1 << 9
clockMash2 clockCtl = 2 << 9
clockMash3 clockCtl = 3 << 9 // will cause higher spread
clockFlip clockCtl = 1 << 8 // FLIP
clockBusy clockCtl = 1 << 7 // BUSY
// 6 reserved
clockKill clockCtl = 1 << 5 // KILL
clockEnable clockCtl = 1 << 4 // ENAB
clockSrcMask clockCtl = 0xF << 0 // SRC
clockSrcGND clockCtl = 0 // 0Hz
clockSrc19dot2MHz clockCtl = 1 // 19.2MHz
clockSrcTestDebug0 clockCtl = 2 // 0Hz
clockSrcTestDebug1 clockCtl = 3 // 0Hz
clockSrcPLLA clockCtl = 4 // 0Hz
clockSrcPLLC clockCtl = 5 // 1000MHz (changes with overclock settings)
clockSrcPLLD clockCtl = 6 // 500MHz
clockSrcHDMI clockCtl = 7 // 216MHz; may be disabled
// 8-15 == GND.
)
// clockCtl controls the clock properties.
//
// It must not be changed while busy is set or a glitch may occur.
//
// Page 107
type clockCtl uint32
func (c clockCtl) String() string {
var out []string
if c&0xFF000000 == clockPasswdCtl {
c &^= 0xFF000000
out = append(out, "PWD")
}
switch c & clockMashMask {
case clockMash1:
out = append(out, "Mash1")
case clockMash2:
out = append(out, "Mash2")
case clockMash3:
out = append(out, "Mash3")
default:
}
c &^= clockMashMask
if c&clockFlip != 0 {
out = append(out, "Flip")
c &^= clockFlip
}
if c&clockBusy != 0 {
out = append(out, "Busy")
c &^= clockBusy
}
if c&clockKill != 0 {
out = append(out, "Kill")
c &^= clockKill
}
if c&clockEnable != 0 {
out = append(out, "Enable")
c &^= clockEnable
}
switch x := c & clockSrcMask; x {
case clockSrcGND:
out = append(out, "GND(0Hz)")
case clockSrc19dot2MHz:
out = append(out, "19.2MHz")
case clockSrcTestDebug0:
out = append(out, "Debug0(0Hz)")
case clockSrcTestDebug1:
out = append(out, "Debug1(0Hz)")
case clockSrcPLLA:
out = append(out, "PLLA(0Hz)")
case clockSrcPLLC:
out = append(out, "PLLD(1000MHz)")
case clockSrcPLLD:
out = append(out, "PLLD(500MHz)")
case clockSrcHDMI:
out = append(out, "HDMI(216MHz)")
default:
out = append(out, fmt.Sprintf("GND(%d)", x))
}
c &^= clockSrcMask
if c != 0 {
out = append(out, fmt.Sprintf("clockCtl(0x%0x)", uint32(c)))
}
return strings.Join(out, "|")
}
const (
// 31:24 password
clockPasswdDiv clockDiv = 0x5A << 24 // PASSWD
// Integer part of the divisor
clockDiviShift = 12
clockDiviMax = (1 << 12) - 1
clockDiviMask clockDiv = clockDiviMax << clockDiviShift // DIVI
// Fractional part of the divisor
clockDivfMask clockDiv = (1 << 12) - 1 // DIVF
)
// clockDiv is a 12.12 fixed point value.
//
// The fractional part generates a significant amount of noise so it is
// preferable to not use it.
//
// Page 108
type clockDiv uint32
func (c clockDiv) String() string {
i := (c & clockDiviMask) >> clockDiviShift
c &^= clockDiviMask
if c == 0 {
return fmt.Sprintf("%d.0", i)
}
return fmt.Sprintf("%d.(%d/%d)", i, c, clockDiviMax)
}
// clock is a pair of clockCtl / clockDiv.
//
// It can be set to one of the sources: clockSrc19dot2MHz(19.2MHz) and
// clockSrcPLLD(500Mhz), then divided to a value to get the resulting clock.
// Per spec the resulting frequency should be under 25Mhz.
type clock struct {
ctl clockCtl
div clockDiv
}
// findDivisorExact finds the clock divisor and wait cycles to reduce src to
// desired hz.
//
// The clock divisor is capped to clockDiviMax.
//
// Returns clock divisor, wait cycles. Returns 0, 0 if no exact match is found.
// Favorizes high clock divisor value over high clock wait cycles. This means
// that the function is slower than it could be, but results in more stable
// clock.
func findDivisorExact(src, desired physic.Frequency, maxWaitCycles uint32) (uint32, uint32) {
if src < desired || src%desired != 0 || src/physic.Frequency(maxWaitCycles*clockDiviMax) > desired {
// Can't attain without oversampling (too low) or desired frequency is
// higher than the source (too high) or is not a multiple.
return 0, 0
}
factor := uint32(src / desired)
// TODO(maruel): Only iterate over valid divisors to save a bit more
// calculations. Since it's is only doing 32 loops, this is not a big deal.
for wait := uint32(1); wait <= maxWaitCycles; wait++ {
if rest := factor % wait; rest != 0 {
continue
}
clk := factor / wait
if clk == 0 {
break
}
if clk <= clockDiviMax {
return clk, wait
}
}
return 0, 0
}
// findDivisorOversampled tries to find the lowest allowed oversampling to make
// desiredHz a multiple of srcHz.
//
// Allowed oversampling depends on the desiredHz. Cap oversampling because
// oversampling at 10x in the 1Mhz range becomes unreasonable in term of
// memory usage.
func findDivisorOversampled(src, desired physic.Frequency, maxWaitCycles uint32) (uint32, uint32, physic.Frequency) {
//log.Printf("findDivisorOversampled(%s, %s, %d)", src, desired, maxWaitCycles)
// There are 2 reasons:
// - desired is so low it is not possible to lower src to this frequency
// - not a multiple, there's a need for a prime number
// TODO(maruel): Rewrite without a loop, this is not needed. Leverage primes
// to reduce the number of iterations.
for multiple := physic.Frequency(2); ; multiple++ {
n := multiple * desired
if n > 100*physic.KiloHertz && multiple > 10 {
break
}
if clk, wait := findDivisorExact(src, n, maxWaitCycles); clk != 0 {
return clk, wait, n
}
}
return 0, 0, 0
}
// calcSource choose the best source to get the exact desired clock.
//
// It calculates the clock source, the clock divisor and the wait cycles, if
// applicable. Wait cycles is 'div minus 1'.
func calcSource(f physic.Frequency, maxWaitCycles uint32) (clockCtl, uint32, uint32, physic.Frequency, error) {
if f < physic.Hertz {
return 0, 0, 0, 0, fmt.Errorf("bcm283x-clock: desired frequency %s must be >1hz", f)
}
if f > 125*physic.MegaHertz {
return 0, 0, 0, 0, fmt.Errorf("bcm283x-clock: desired frequency %s is too high", f)
}
// http://elinux.org/BCM2835_datasheet_errata states that clockSrc19dot2MHz
// is the cleanest clock source so try it first.
div, wait := findDivisorExact(clk19dot2MHz, f, maxWaitCycles)
if div != 0 {
return clockSrc19dot2MHz, div, wait, f, nil
}
// Try 500Mhz.
div, wait = findDivisorExact(clk500MHz, f, maxWaitCycles)
if div != 0 {
return clockSrcPLLD, div, wait, f, nil
}
// Try with up to 10x oversampling. This is generally useful for lower
// frequencies, below 10kHz. Prefer the one with less oversampling. Only for
// non-aliased matches.
div19, wait19, f19 := findDivisorOversampled(clk19dot2MHz, f, maxWaitCycles)
div500, wait500, f500 := findDivisorOversampled(clk500MHz, f, maxWaitCycles)
if div19 != 0 && (div500 == 0 || f19 < f500) {
return clockSrc19dot2MHz, div19, wait19, f19, nil
}
if div500 != 0 {
return clockSrcPLLD, div500, wait500, f500, nil
}
return 0, 0, 0, 0, errors.New("failed to find a good clock")
}
// set changes the clock frequency to the desired value or the closest one
// otherwise.
//
// f=0 means disabled.
//
// maxWaitCycles is the maximum oversampling via an additional wait cycles that
// can further divide the clock. Use 1 if no additional wait cycle is
// available. It is expected to be dmaWaitcyclesMax+1.
//
// Returns the actual clock used and divisor.
func (c *clock) set(f physic.Frequency, maxWaitCycles uint32) (physic.Frequency, uint32, error) {
if f == 0 {
c.ctl = clockPasswdCtl | clockKill
for c.ctl&clockBusy != 0 {
}
return 0, 0, nil
}
ctl, div, div2, actual, err := calcSource(f, maxWaitCycles)
if err != nil {
return 0, 0, err
}
return actual, div2, c.setRaw(ctl, div)
}
// setRaw sets the clock speed with the clock source and the divisor.
func (c *clock) setRaw(ctl clockCtl, div uint32) error {
if div < 1 || div > clockDiviMax {
return errors.New("invalid clock divisor")
}
if ctl != clockSrc19dot2MHz && ctl != clockSrcPLLD {
return errors.New("invalid clock control")
}
// Stop the clock.
// TODO(maruel): Do not stop the clock if the current clock rate is the one
// desired.
for c.ctl&clockBusy != 0 {
c.ctl = clockPasswdCtl | clockKill
}
d := clockDiv(div << clockDiviShift)
c.div = clockPasswdDiv | d
Nanospin(10 * time.Nanosecond)
// Page 107
c.ctl = clockPasswdCtl | ctl
Nanospin(10 * time.Nanosecond)
c.ctl = clockPasswdCtl | ctl | clockEnable
if c.div != d {
// This error is mocked out in tests, so the code path of set() callers can
// follow on.
return errClockRegister
}
return nil
}
func (c *clock) String() string {
return fmt.Sprintf("%s / %s", c.ctl, c.div)
}
// clockMap is the memory mapped clock registers.
//
// The clock #1 must not be touched since it is being used by the ethernet
// controller.
//
// Page 107 for gp0~gp2.
// https://scribd.com/doc/127599939/BCM2835-Audio-clocks for PCM/PWM.
type clockMap struct {
reserved0 [0x70 / 4]uint32 //
gp0 clock // CM_GP0CTL+CM_GP0DIV; 0x70-0x74 (125MHz max)
gp1ctl uint32 // CM_GP1CTL+CM_GP1DIV; 0x78-0x7A must not use (used by ethernet)
gp1div uint32 // CM_GP1CTL+CM_GP1DIV; 0x78-0x7A must not use (used by ethernet)
gp2 clock // CM_GP2CTL+CM_GP2DIV; 0x80-0x84 (125MHz max)
reserved1 [(0x98 - 0x88) / 4]uint32 // 0x88-0x94
pcm clock // CM_PCMCTL+CM_PCMDIV 0x98-0x9C
pwm clock // CM_PWMCTL+CM_PWMDIV 0xA0-0xA4
}
func (c *clockMap) GoString() string {
return fmt.Sprintf(
"{\n gp0: %s,\n gp1: %s,\n gp2: %s,\n pcm: %sw,\n pwm: %s,\n}",
&c.gp0, &clock{clockCtl(c.gp1ctl), clockDiv(c.gp1div)}, &c.gp2, &c.pcm, &c.pwm)
}

1224
vendor/periph.io/x/periph/host/bcm283x/dma.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

42
vendor/periph.io/x/periph/host/bcm283x/doc.go generated vendored Normal file
View File

@ -0,0 +1,42 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package bcm283x exposes the BCM283x GPIO functionality.
//
// This driver implements memory-mapped GPIO pin manipulation and leverages
// sysfs-gpio for edge detection.
//
// If you are looking for the actual implementation, open doc.go for further
// implementation details.
//
// GPIOs
//
// Aliases for GPCLK0, GPCLK1, GPCLK2 are created for corresponding CLKn pins.
// Same for PWM0_OUT and PWM1_OUT, which point respectively to PWM0 and PWM1.
//
// Datasheet
//
// https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
//
// Its crowd-sourced errata: http://elinux.org/BCM2835_datasheet_errata
//
// BCM2836:
// https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf
//
// Another doc about PCM and PWM:
// https://scribd.com/doc/127599939/BCM2835-Audio-clocks
//
// GPIO pad control:
// https://scribd.com/doc/101830961/GPIO-Pads-Control2
package bcm283x
// Other implementations details
//
// mainline:
// https://github.com/torvalds/linux/blob/master/drivers/dma/bcm2835-dma.c
// https://github.com/torvalds/linux/blob/master/drivers/gpio
//
// Raspbian kernel:
// https://github.com/raspberrypi/linux/blob/rpi-4.11.y/drivers/dma
// https://github.com/raspberrypi/linux/blob/rpi-4.11.y/drivers/gpio

1361
vendor/periph.io/x/periph/host/bcm283x/gpio.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

234
vendor/periph.io/x/periph/host/bcm283x/pcm.go generated vendored Normal file
View File

@ -0,0 +1,234 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// pcm means I2S.
package bcm283x
import (
"errors"
"fmt"
"time"
"periph.io/x/periph/conn/physic"
)
type pcmCS uint32
// Pages 126-129
const (
// 31:26 reserved
pcmStandby pcmCS = 1 << 25 // STBY Allow at least 4 PCM clock cycles to take effect
pcmSync pcmCS = 1 << 24 // SYNC Two PCM clocks have occurred since last write
pcmRXSignExtend pcmCS = 1 << 23 // RXSEX Sign extend RXZ data
pcmRXFull pcmCS = 1 << 22 // RXF RX FIFO is full
pcmTXEmpty pcmCS = 1 << 21 // TXE TX FIFO is empty
pcmRXData pcmCS = 1 << 20 // RXD RX FIFO contains data
pcmTXData pcmCS = 1 << 19 // TXD TX FIFO ready to accept data
pcmRXR pcmCS = 1 << 18 // RXR RX FIFO needs reading
pcmTXW pcmCS = 1 << 17 // TXW TX FIFO needs writing
pcmRXErr pcmCS = 1 << 16 // RXERR RX FIFO error
pcmTXErr pcmCS = 1 << 15 // TXERR TX FIFO error
pcmRXSync pcmCS = 1 << 14 // RXSYNC RX FIFO is out of sync
pcmTXSync pcmCS = 1 << 13 // TXSYNC TX FIFO is out of sync
// 12:10 reserved
pcmDMAEnable pcmCS = 1 << 9 // DMAEN Generate TX&RX DMA DREQ
// 8:7 RXTHR controls when pcmRXR is set
pcmRXThresholdOne pcmCS = 0 << 7 // One sample in RX FIFO
pcmRXThreshold1 pcmCS = 1 << 7 // RX FIFO is at least (?) full
pcmRXThreshold2 pcmCS = 2 << 7 // ?
pcmRXThresholdFull pcmCS = 3 << 7 // RX is full
// 6:5 TXTHR controls when pcmTXW is set
pcmTXThresholdEmpty pcmCS = 0 << 5 // TX FIFO is empty
pcmTXThresholdNotFull1 pcmCS = 1 << 5 // At least one sample can be put
pcmTXThresholdNotFull2 pcmCS = 2 << 5 // At least one sample can be put
pcmTXThresholdOne pcmCS = 3 << 5 // One sample can be put
pcmRXClear pcmCS = 1 << 4 // RXCLR Clear RX FIFO; takes 2 PCM clock to take effect
pcmTXClear pcmCS = 1 << 3 // TXCLR Clear TX FIFO; takes 2 PCM clock to take effect
pcmTXEnable pcmCS = 1 << 2 // TXON Enable TX
pcmRXEnable pcmCS = 1 << 1 // RXON Enable FX
pcmEnable pcmCS = 1 << 0 // EN Enable the PCM
)
type pcmMode uint32
// Page 129-131
const (
// 31:29 reserved
pcmClockDisable pcmMode = 1 << 28 // CLK_DIS Cleanly disable the PCM clock
pcmDecimation32 pcmMode = 1 << 27 // PDMN; 0 is factor 16, 1 is factor 32
pcmRXPDMFilter pcmMode = 1 << 26 // PDME Enable input CIC filter on PDM input
pcmRXMerge pcmMode = 1 << 25 // FRXP Merge both channels as single FIFO entry
pcmTXMerge pcmMode = 1 << 24 // FTXP Merge both channels as singe FIFO entry
pcmClockSlave pcmMode = 1 << 23 // CLKM PCM CLK is input
pcmClockInverted pcmMode = 1 << 22 // CLKI Inverse clock signal
pcmFSSlave pcmMode = 1 << 21 // FSM PCM FS is input
pcmFSInverted pcmMode = 1 << 20 // FSI Invese FS signal
pcmFrameLengthShift = 10 //
pcmFrameLenghtMask pcmMode = 0x3F << pcmFrameLengthShift // FLEN Frame length + 1
pcmFSLenghtMask pcmMode = 0x3F << 0 // FSLEN FS pulse clock width
)
type pcmRX uint32
// Page 131-132
const (
pcmRX1Width pcmRX = 1 << 31 // CH1WEX Legacy
pcmRX1Enable pcmRX = 1 << 30 // CH1EN
pcmRX1PosShift = 20
pcmRX1PosMask pcmRX = 0x3F << pcmRX1PosShift // CH1POS Clock delay
pcmRX1Channel16 pcmRX = 8 << 16 // CH1WID (Arbitrary width between 8 and 16 is supported)
pcmRX2Width pcmRX = 1 << 15 // CH2WEX Legacy
pcmRX2Enable pcmRX = 1 << 14 // CH2EN
pcmRX2PosShift = 4
pcmRX2PosMask pcmRX = 0x3F << pcmRX2PosShift // CH2POS Clock delay
pcmRX2Channel16 pcmRX = 8 << 0 // CH2WID (Arbitrary width between 8 and 16 is supported)
)
type pcmTX uint32
// Page 133-134
const (
pcmTX1Width pcmTX = 1 << 31 // CH1WX Legacy
pcmTX1Enable pcmTX = 1 << 30 // CH1EN Enable channel 1
pcmTX1PosShift = 20
pcmTX1PosMask pcmTX = 0x3F << pcmTX1PosShift // CH1POS Clock delay
pcmTX1Channel16 pcmTX = 8 << 16 // CH1WID (Arbitrary width between 8 and 16 is supported)
pcmTX2Width pcmTX = 1 << 15 // CH2WEX Legacy
pcmTX2Enable pcmTX = 1 << 14 // CH2EN
pcmTX2PosShift = 4
pcmTX2PosMask pcmTX = 0x3F << pcmTX2PosShift // CH2POS Clock delay
pcmTX2Channel16 pcmTX = 8 << 0 // CH2WID (Arbitrary width between 8 and 16 is supported)
)
type pcmDreq uint32
// Page 134-135
const (
// 31 reserved
pcmDreqTXPanicShift = 24
pcmDreqTXPanicMask pcmDreq = 0x7F << pcmDreqTXPanicShift // TX_PANIC Panic level
// 23 reserved
pcmDreqRXPanicShift = 16
pcmDreqRXPanicMask pcmDreq = 0x7F << pcmDreqRXPanicShift // RX_PANIC Panic level
// 15 reserved
pcmDreqTXLevelShift = 8
pcmDreqTXLevelMask pcmDreq = 0x7F << pcmDreqTXPanicShift // TX Request Level
// 7 reserved
pcmDreqRXLevelShift = 0
pcmDreqRXLevelMask pcmDreq = 0x7F << pcmDreqRXPanicShift // RX Request Level
)
type pcmInterrupt uint32
// Page 135
const (
// 31:4 reserved
pcmIntRXErr pcmInterrupt = 1 << 3 // RXERR RX error interrupt enable
pcmIntTXErr pcmInterrupt = 1 << 2 // TXERR TX error interrupt enable
pcmIntRXEnable pcmInterrupt = 1 << 1 // RXR RX Read interrupt enable
pcmIntTXEnable pcmInterrupt = 1 << 0 // TXW TX Write interrupt enable
)
type pcmIntStatus uint32
// Page 135-136
const (
// 31:4 reserved
pcmIntStatRXErr pcmIntStatus = 1 << 3 // RXERR RX error occurred / clear
pcmIntStatTXErr pcmIntStatus = 1 << 2 // TXERR TX error occurred / clear
pcmIntStatRXEnable pcmIntStatus = 1 << 1 // RXR RX Read interrupt occurred / clear
pcmIntStatTXEnable pcmIntStatus = 1 << 0 // TXW TX Write interrupt occurred / clear
pcmIntStatusClear pcmIntStatus = 0xF
)
// pcmGray puts it into a special data/strobe mode that is under 'best effort'
// contract.
type pcmGray uint32
// Page 136-137
const (
// 31:22 reserved
pcmGrayRXFIFOLevelShift = 16
pcmGrayRXFIFOLevelMask pcmGray = 0x3F << pcmGrayRXFIFOLevelShift // RXFIFOLEVEL How many words in RXFIFO
pcmGrayFlushShift = 10
pcmGrayFlushMask = 0x3F << pcmGrayFlushShift // FLUSHED How many bits were valid when flush occurred
pcmGrayRXLevelShift = 4
pcmGrayRXLevelMask pcmGray = 0x3F << pcmGrayRXLevelShift // RXLEVEL How many GRAY coded bits received
pcmGrayFlush pcmGray = 1 << 2 // FLUSH
pcmGrayClear pcmGray = 1 << 1 // CLR
pcmGrayEnable pcmGray = 1 << 0 // EN
)
// Page 119
type pcmMap struct {
cs pcmCS // CS_A Control Status
fifo uint32 // FIFO_A FIFO register
mode pcmMode // MODE_A Operation mode
rxc pcmRX // RXC_A RX control
txc pcmTX // TXC_A TX control
dreq pcmDreq // DREQ_A DMA control
inten pcmInterrupt // INTEN_A Interrupt enable
intstc pcmIntStatus // INTSTC_A Interrupt status
gray pcmGray // GRAY Gray mode input processing
}
func (p *pcmMap) GoString() string {
return fmt.Sprintf(
"{\n cs: 0x%x,\n mode: 0x%x,\n rxc: 0x%x,\n txc: 0x%x,\n dreq: 0x%x,\n inten: 0x%x,\n intstc: 0x%x,\n gray: 0x%x,\n}",
p.cs, p.mode, p.rxc, p.txc, p.dreq, p.inten, p.intstc, p.gray)
}
func (p *pcmMap) reset() {
p.cs = 0
// In theory need to wait the equivalent of 2 PCM clocks.
// TODO(maruel): Use pcmSync busy loop to synchronize.
Nanospin(time.Microsecond)
// Hard reset
p.fifo = 0
p.mode = 0
p.rxc = 0
p.txc = 0
p.dreq = 0
p.inten = 0
p.intstc = pcmIntStatusClear
p.gray = 0
// Clear pcmStandby / pcm
}
// set initializes 8 bits stream via DMA with no delay and no FS.
func (p *pcmMap) set() {
p.cs |= pcmEnable
p.txc = pcmTX1Width | pcmTX1Channel16 | pcmTX1Enable // 32bit TX
p.mode = (32 - 1) << pcmFrameLengthShift
p.cs |= pcmTXClear | pcmRXClear
// In theory need to wait the equivalent of 2 PCM clocks.
// TODO(maruel): Use pcmSync busy loop to synchronize.
Nanospin(time.Microsecond)
p.dreq = 0x10<<pcmDreqTXPanicShift | 0x30<<pcmDreqTXLevelShift
p.cs |= pcmDMAEnable
// pcmTXThresholdOne ?
p.cs |= pcmTXEnable
}
// setPCMClockSource sets the PCM clock.
//
// It may select an higher frequency than the one requested.
//
// Other potentially good clock sources are PWM, SPI and UART.
func setPCMClockSource(f physic.Frequency) (physic.Frequency, uint32, error) {
if drvDMA.pcmMemory == nil {
return 0, 0, errors.New("subsystem PCM not initialized")
}
if drvDMA.clockMemory == nil {
return 0, 0, errors.New("subsystem Clock not initialized")
}
actual, divs, err := drvDMA.clockMemory.pcm.set(f, 1)
if err == nil {
drvDMA.pcmMemory.cs = 0
}
// Convert divisor into wait cycles.
return actual, divs, err
}

272
vendor/periph.io/x/periph/host/bcm283x/pwm.go generated vendored Normal file
View File

@ -0,0 +1,272 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package bcm283x
import (
"errors"
"fmt"
"time"
"periph.io/x/periph/conn/physic"
)
// PWENi is used to enable/disable the corresponding channel. Setting this bit
// to 1 enables the channel and transmitter state machine. All registers and
// FIFO is writable without setting this bit.
//
// MODEi bit is used to determine mode of operation. Setting this bit to 0
// enables PWM mode. In this mode data stored in either PWM_DATi or FIFO is
// transmitted by pulse width modulation within the range defined by PWM_RNGi.
// When this mode is used MSENi defines whether to use PWM algorithm. Setting
// MODEi to 1 enables serial mode, in which data stored in either PWM_DATi or
// FIFO is transmitted serially within the range defined by PWM_RNGi. Data is
// transmitted MSB first and truncated or zeropadded depending on PWM_RNGi.
// Default mode is PWM.
//
// RPTLi is used to enable/disable repeating of the last data available in the
// FIFO just before it empties. When this bit is 1 and FIFO is used, the last
// available data in the FIFO is repeatedly sent. This may be useful in PWM
// mode to avoid duty cycle gaps. If the FIFO is not used this bit does not
// have any effect. Default operation is do-notrepeat.
//
// SBITi defines the state of the output when no transmission takes place. It
// also defines the zero polarity for the zero padding in serialiser mode. This
// bit is padded between two consecutive transfers as well as tail of the data
// when PWM_RNGi is larger than bit depth of data being transferred. this bit
// is zero by default.
//
// POLAi is used to configure the polarity of the output bit. When set to high
// the final output is inverted. Default operation is no inversion.
//
// USEFi bit is used to enable/disable FIFO transfer. When this bit is high
// data stored in the FIFO is used for transmission. When it is low, data
// written to PWM_DATi is transferred. This bit is 0 as default.
//
// CLRF is used to clear the FIFO. Writing a 1 to this bit clears the FIFO.
// Writing 0 has no effect. This is a single shot operation and reading the bit
// always returns 0.
//
// MSENi is used to determine whether to use PWM algorithm or simple M/S ratio
// transmission. When this bit is high M/S transmission is used. This bit is
// zero as default. When MODEi is 1, this configuration bit has no effect.
//
// See page 139-140 for the description of the PWM and M/S ratio algorithms.
const (
// 31:16 reserved
pwm2MS pwmControl = 1 << 15 // MSEN2; 0: PWM algorithm is used; 1: M/S transmission is used
// 14 reserved
pwm2UseFIFO pwmControl = 1 << 13 // USEF2; 0: Data register is transmitted; 1: Fifo is used for transmission
pwm2Polarity pwmControl = 1 << 12 // POLA2; 0: 0=low 1=high; 1: 1=low 0=high
pwm2SilenceHigh pwmControl = 1 << 11 // SBIT2; Defines the state of the output when no transmission takes place
pwm2RepeatLastData pwmControl = 1 << 10 // RPTL2; 0: Transmission interrupts when FIFO is empty; 1: Last data in FIFO is transmitted repetedly until FIFO is not empty
pwm2Serialiser pwmControl = 1 << 9 // MODE2; 0: PWM mode; 1: Serialiser mode
pwm2Enable pwmControl = 1 << 8 // PWEN2; Enable channel 2
pwm2Mask pwmControl = pwm2MS | pwm2UseFIFO | pwm2Polarity | pwm2SilenceHigh | pwm2RepeatLastData | pwm2Serialiser | pwm2Enable
pwm1MS pwmControl = 1 << 7 // MSEN1; 0: PWM algorithm is used; 1: M/S transmission is used
pwmClearFIFO pwmControl = 1 << 6 // CLRF1; Clear the fifo
pwm1UseFIFO pwmControl = 1 << 5 // USEF1; 0: Data register is transmitted; 1: Fifo is used for transmission
pwm1Polarity pwmControl = 1 << 4 // POLA1; 0: 0=low 1=high; 1: 1=low 0=high
pwm1SilenceHigh pwmControl = 1 << 3 // SBIT1; Defines the state of the output when no transmission takes place
pwm1RepeatLastData pwmControl = 1 << 2 // RPTL1; 0: Transmission interrupts when FIFO is empty; 1: Last data in FIFO is transmitted repetedly until FIFO is not empty
pwm1Serialiser pwmControl = 1 << 1 // MODE1; 0: PWM mode; 1: Serialiser mode
pwm1Enable pwmControl = 1 << 0 // PWEN1; Enable channel 1
pwm1Mask pwmControl = pwm1MS | pwm1UseFIFO | pwm1Polarity | pwm1SilenceHigh | pwm1RepeatLastData | pwm1Serialiser | pwm1Enable
)
// Pages 141-143.
type pwmControl uint32
const (
// 31:13 reserved
// STAi bit indicates the current state of the channel which is useful for
// debugging purposes. The bit set means the channel is currently
// transmitting data.
pwmSta4 pwmStatus = 1 << 12 // STA4
pwmSta3 pwmStatus = 1 << 11 // STA3
pwmSta2 pwmStatus = 1 << 10 // STA2
pwmSta1 pwmStatus = 1 << 9 // STA1
// BERR sets to high when an error has occurred while writing to registers
// via APB. This may happen if the bus tries to write successively to same
// set of registers faster than the synchroniser block can cope with.
// Multiple switching may occur and contaminate the data during
// synchronisation. Software should clear this bit by writing 1. Writing 0
// to this bit has no effect.
pwmBusErr pwmStatus = 1 << 8 // BERR Bus Error flag
// GAPOi. bit indicates that there has been a gap between transmission of two
// consecutive data from FIFO. This may happen when FIFO gets empty after
// state machine has sent a word and waits for the next. If control bit RPTLi
// is set to high this event will not occur. Software must clear this bit by
// writing 1. Writing 0 to this bit has no effect.
pwmGapo4 pwmStatus = 1 << 7 // GAPO4 Channel 4 Gap Occurred flag
pwmGapo3 pwmStatus = 1 << 6 // GAPO3 Channel 3 Gap Occurred flag
pwmGapo2 pwmStatus = 1 << 5 // GAPO2 Channel 2 Gap Occurred flag
pwmGapo1 pwmStatus = 1 << 4 // GAPO1 Channel 1 Gap Occurred flag
// RERR1 bit sets to high when a read when empty error occurs. Software must
// clear this bit by writing 1. Writing 0 to this bit has no effect.
pwmRerr1 pwmStatus = 1 << 3 // RERR1
// WERR1 bit sets to high when a write when full error occurs. Software must
// clear this bit by writing 1. Writing 0 to this bit has no effect.
pwmWerr1 pwmStatus = 1 << 2 // WERR1
// EMPT1 bit indicates the empty status of the FIFO. If this bit is high FIFO
// is empty.
pwmEmpt1 pwmStatus = 1 << 1 // EMPT1
// FULL1 bit indicates the full status of the FIFO. If this bit is high FIFO
// is full.
pwmFull1 pwmStatus = 1 << 0 // FULL1
pwmStatusMask = pwmSta4 | pwmSta3 | pwmSta2 | pwmSta1 | pwmBusErr | pwmGapo4 | pwmGapo3 | pwmGapo2 | pwmGapo1 | pwmRerr1 | pwmWerr1 | pwmEmpt1 | pwmFull1
)
// Pages 144-145.
type pwmStatus uint32
const (
pwmDMAEnable pwmDMACfg = 1 << 31 // ENAB
// 30:16 reserved
pwmPanicShift = 16
pwmPanicMask pwmDMACfg = 0xFF << pwmPanicShift // PANIC Default is 7
pwmDreqMask pwmDMACfg = 0xFF // DREQ Default is 7
)
// Page 145.
type pwmDMACfg uint32
// pwmMap is the block to control the PWM generator.
//
// Note that pins are named PWM0 and PWM1 but the mapping uses channel numbers
// 1 and 2.
// - PWM0: GPIO12, GPIO18, GPIO40, GPIO52.
// - PWM1: GPIO13, GPIO19, GPIO41, GPIO45, GPIO53.
//
// Each channel works independently. They can either output a bitstream or a
// serialised version of up to eight 32 bits words.
//
// The default base PWM frequency is 100Mhz.
//
// Description at page 138-139.
//
// Page 140-141.
type pwmMap struct {
ctl pwmControl // CTL
status pwmStatus // STA
dmaCfg pwmDMACfg // DMAC
// This register is used to define the range for the corresponding channel.
// In PWM mode evenly distributed pulses are sent within a period of length
// defined by this register. In serial mode serialised data is transmitted
// within the same period. If the value in PWM_RNGi is less than 32, only the
// first PWM_RNGi bits are sent resulting in a truncation. If it is larger
// than 32 excess zero bits are padded at the end of data. Default value for
// this register is 32.
dummy1 uint32 // Padding
rng1 uint32 // RNG1
// This register stores the 32 bit data to be sent by the PWM Controller when
// USEFi is 0. In PWM mode data is sent by pulse width modulation: the value
// of this register defines the number of pulses which is sent within the
// period defined by PWM_RNGi. In serialiser mode data stored in this
// register is serialised and transmitted.
dat1 uint32 // DAT1
// This register is the FIFO input for the all channels. Data written to this
// address is stored in channel FIFO and if USEFi is enabled for the channel
// i it is used as data to be sent. This register is write only, and reading
// this register will always return bus default return value, pwm0.
// When more than one channel is enabled for FIFO usage, the data written
// into the FIFO is shared between these channels in turn. For example if the
// word series A B C D E F G H I .. is written to FIFO and two channels are
// active and configured to use FIFO then channel 1 will transmit words A C E
// G I .. and channel 2 will transmit words B D F H .. . Note that
// requesting data from the FIFO is in locked-step manner and therefore
// requires tight coupling of state machines of the channels. If any of the
// channel range (period) value is different than the others this will cause
// the channels with small range values to wait between words hence resulting
// in gaps between words. To avoid that, each channel sharing the FIFO should
// be configured to use the same range value. Also note that RPTLi are not
// meaningful when the FIFO is shared between channels as there is no defined
// channel to own the last data in the FIFO. Therefore sharing channels must
// have their RPTLi set to zero.
//
// If the set of channels to share the FIFO has been modified after a
// configuration change, FIFO should be cleared before writing new data.
fifo uint32 // FIF1
dummy2 uint32 // Padding
rng2 uint32 // RNG2 Equivalent of rng1 for channel 2
dat2 uint32 // DAT2 Equivalent of dat1 for channel 2
}
// reset stops the PWM.
func (p *pwmMap) reset() {
p.dmaCfg = 0
p.ctl |= pwmClearFIFO
p.ctl &^= pwm1Enable | pwm2Enable
Nanospin(100 * time.Microsecond) // Cargo cult copied. Probably not necessary.
p.status = pwmBusErr | pwmGapo1 | pwmGapo2 | pwmGapo3 | pwmGapo4 | pwmRerr1 | pwmWerr1
Nanospin(100 * time.Microsecond)
// Use the full 32 bits of DATi.
p.rng1 = 32
p.rng2 = 32
}
// setPWMClockSource sets the PWM clock for use by the DMA controller for
// pacing.
//
// It may select an higher frequency than the one requested.
//
// Other potentially good clock sources are PCM, SPI and UART.
func setPWMClockSource() (physic.Frequency, error) {
if drvDMA.pwmMemory == nil {
return 0, errors.New("subsystem PWM not initialized")
}
if drvDMA.clockMemory == nil {
return 0, errors.New("subsystem Clock not initialized")
}
if drvDMA.pwmDMACh != nil {
// Already initialized
return drvDMA.pwmDMAFreq, nil
}
// divs * div must fit in rng1 registor.
div := uint32(drvDMA.pwmBaseFreq / drvDMA.pwmDMAFreq)
actual, divs, err := drvDMA.clockMemory.pwm.set(drvDMA.pwmBaseFreq, div)
if err != nil {
return 0, err
}
if e := actual / physic.Frequency(divs*div); drvDMA.pwmDMAFreq != e {
return 0, fmt.Errorf("Unexpected DMA frequency %s != %s (%d/%d/%d)", drvDMA.pwmDMAFreq, e, actual, divs, div)
}
// It acts as a clock multiplier, since this amount of data is sent per
// clock tick.
drvDMA.pwmMemory.rng1 = divs * div
Nanospin(10 * time.Microsecond)
// Periph data (?)
// Use low priority.
drvDMA.pwmMemory.dmaCfg = pwmDMAEnable | pwmDMACfg(15<<pwmPanicShift|15)
Nanospin(10 * time.Microsecond)
drvDMA.pwmMemory.ctl |= pwmClearFIFO
Nanospin(10 * time.Microsecond)
old := drvDMA.pwmMemory.ctl
drvDMA.pwmMemory.ctl = (old & ^pwmControl(0xff)) | pwm1UseFIFO | pwm1Enable
// Start DMA
if drvDMA.pwmDMACh, drvDMA.pwmDMABuf, err = dmaWritePWMFIFO(); err != nil {
return 0, err
}
return drvDMA.pwmDMAFreq, nil
}
func resetPWMClockSource() error {
if drvDMA.pwmDMACh != nil {
drvDMA.pwmDMACh.reset()
drvDMA.pwmDMACh = nil
}
if drvDMA.pwmDMABuf != nil {
if err := drvDMA.pwmDMABuf.Close(); err != nil {
return err
}
drvDMA.pwmDMABuf = nil
}
_, _, err := drvDMA.clockMemory.pwm.set(0, 0)
return err
}

134
vendor/periph.io/x/periph/host/bcm283x/streams.go generated vendored Normal file
View File

@ -0,0 +1,134 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package bcm283x
import (
"encoding/binary"
"errors"
"fmt"
"periph.io/x/periph/conn/gpio/gpiostream"
)
// uint32ToBitLSBF packs a bit offset found on slice `d` (that is actually
// uint32) back into a densely packed Bits stream.
func uint32ToBitLSBF(w []byte, d []uint8, bit uint8, skip int) {
// Little endian.
x := bit / 8
d = d[x:]
bit -= 8 * x
mask := uint8(1) << bit
for i := range w {
w[i] = ((d[0]&mask)>>bit<<0 |
(d[skip*1]&mask)>>bit<<1 |
(d[skip*2]&mask)>>bit<<2 |
(d[skip*3]&mask)>>bit<<3 |
(d[skip*4]&mask)>>bit<<4 |
(d[skip*5]&mask)>>bit<<5 |
(d[skip*6]&mask)>>bit<<6 |
(d[skip*7]&mask)>>bit<<7)
d = d[skip*8:]
}
}
func getBit(b byte, index int, msb bool) byte {
var shift uint
if msb {
shift = uint(7 - index)
} else {
shift = uint(index)
}
return (b >> shift) & 1
}
func raster32Bits(s gpiostream.Stream, skip int, clear, set []uint32, mask uint32) error {
var msb bool
var bits []byte
switch b := s.(type) {
case *gpiostream.BitStream:
msb = !b.LSBF
bits = b.Bits
default:
return fmt.Errorf("Unsupported type %T", b)
}
m := len(clear) / 8
if n := len(bits); n < m {
m = n
}
index := 0
for i := 0; i < m; i++ {
for j := 0; j < 8; j++ {
if getBit(bits[i], j, msb) != 0 {
for k := 0; k < skip; k++ {
set[index] |= mask
index++
}
} else {
for k := 0; k < skip; k++ {
clear[index] |= mask
index++
}
}
}
}
return nil
}
// raster32 rasters the stream into a uint32 stream with the specified masks to
// put in the correctly slice when the bit is set and when it is clear.
//
// `s` must be one of the types in this package.
func raster32(s gpiostream.Stream, skip int, clear, set []uint32, mask uint32) error {
if mask == 0 {
return errors.New("bcm283x: mask is 0")
}
if len(clear) == 0 {
return errors.New("bcm283x: clear buffer is empty")
}
if len(set) == 0 {
return errors.New("bcm283x: set buffer is empty")
}
if len(clear) != len(set) {
return errors.New("bcm283x: clear and set buffers have different length")
}
switch x := s.(type) {
case *gpiostream.BitStream:
// TODO
return raster32Bits(x, skip, clear, set, mask)
case *gpiostream.EdgeStream:
return errors.New("bcm283x: EdgeStream is not supported yet")
case *gpiostream.Program:
return errors.New("bcm283x: Program is not supported yet")
default:
return errors.New("bcm283x: unknown stream type")
}
}
// PCM/PWM DMA buf is encoded as little-endian and MSB first.
func copyStreamToDMABuf(w gpiostream.Stream, dst []uint32) error {
switch v := w.(type) {
case *gpiostream.BitStream:
if v.LSBF {
return errors.New("TODO(simokawa): handle BitStream.LSBF")
}
// This is big-endian and MSB first.
i := 0
for ; i < len(v.Bits)/4; i++ {
dst[i] = binary.BigEndian.Uint32(v.Bits[i*4:])
}
last := uint32(0)
if mod := len(v.Bits) % 4; mod > 0 {
for j := 0; j < mod; j++ {
last |= (uint32(v.Bits[i*4+j])) << uint32(8*(3-j))
}
dst[i] = last
}
return nil
case *gpiostream.EdgeStream:
return errors.New("TODO(simokawa): handle EdgeStream")
default:
return errors.New("Unsupported Stream type")
}
}

60
vendor/periph.io/x/periph/host/bcm283x/timer.go generated vendored Normal file
View File

@ -0,0 +1,60 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package bcm283x
import (
"time"
"periph.io/x/periph/host/cpu"
)
// ReadTime returns the time on a monotonic 1Mhz clock (1µs resolution).
//
// It only works if bcm283x-dma successfully loaded. Otherwise it returns 0.
func ReadTime() time.Duration {
if drvDMA.timerMemory == nil {
return 0
}
return (time.Duration(drvDMA.timerMemory.high)<<32 | time.Duration(drvDMA.timerMemory.low)) * time.Microsecond
}
// Nanospin spins the CPU without calling into the kernel code if possible.
func Nanospin(t time.Duration) {
start := ReadTime()
if start == 0 {
// Use the slow generic version.
cpu.Nanospin(t)
return
}
// TODO(maruel): Optimize code path for sub-1µs duration.
for ReadTime()-start < t {
}
}
//
const (
// 31:4 reserved
timerM3 = 1 << 3 // M3
timerM2 = 1 << 2 // M2
timerM1 = 1 << 1 // M1
timerM0 = 1 << 0 // M0
)
// Page 173
type timerCtl uint32
// timerMap represents the registers to access the 1Mhz timer.
//
// Page 172
type timerMap struct {
ctl timerCtl // CS
low uint32 // CLO
high uint32 // CHI
c0 uint32 // 0
c1 uint32 // C1
c2 uint32 // C2
c3 uint32 // C3
}

34
vendor/periph.io/x/periph/host/beagle/black/black.go generated vendored Normal file
View File

@ -0,0 +1,34 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package black implements headers for the BeagleBone Black and BeagleBone
// Black Wireless micro-computers.
//
// Reference
//
// https://beagleboard.org/black
//
// Datasheet
//
// https://elinux.org/Beagleboard:BeagleBoneBlack
//
// https://github.com/CircuitCo/BeagleBone-Black/blob/rev_b/BBB_SRM.pdf
//
// https://elinux.org/Beagleboard:Cape_Expansion_Headers
package black
import (
"strings"
"periph.io/x/periph/host/distro"
)
// Present returns true if the host is a BeagleBone Black or BeagleBone Black
// Wireless.
func Present() bool {
if isArm {
return strings.HasPrefix(distro.DTModel(), "TI AM335x BeagleBone Black")
}
return false
}

View File

@ -0,0 +1,7 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package black
const isArm = true

View File

@ -0,0 +1,9 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build !arm
package black
const isArm = false

318
vendor/periph.io/x/periph/host/beagle/bone/bone.go generated vendored Normal file
View File

@ -0,0 +1,318 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package bone implements headers J1, P8 and P9 found on many (but not all)
// BeagleBone micro-computer.
//
// In particular, the headers are found on the models using a TI AM335x
// processor: BeagleBone Black, Black Wireless, Green and Green Wireless.
//
// Reference
//
// http://beagleboard.org/Support/bone101/#hardware
package bone
import (
"errors"
"periph.io/x/periph"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/pin"
"periph.io/x/periph/conn/pin/pinreg"
"periph.io/x/periph/host/beagle/black"
"periph.io/x/periph/host/beagle/green"
"periph.io/x/periph/host/sysfs"
)
// TODO(maruel): Use specialized am335x or pru implementation once available.
// Common pin types on BeagleBones.
var (
PWR_BUT = &pin.BasicPin{N: "PWR_BUT"} //
RESET_OUT = &pin.BasicPin{N: "RESET_OUT"} // SYS_RESETn
VADC = &pin.BasicPin{N: "VADC"} // VDD_ADC
AIN4 = &pin.BasicPin{N: "AIN4"} // AIN4
AGND = &pin.BasicPin{N: "AGND"} // GNDA_ADC
AIN6 = &pin.BasicPin{N: "AIN6"} // AIN6
AIN5 = &pin.BasicPin{N: "AIN5"} // AIN5
AIN2 = &pin.BasicPin{N: "AIN2"} // AIN2
AIN3 = &pin.BasicPin{N: "AIN3"} // AIN3
AIN0 = &pin.BasicPin{N: "AIN0"} // AIN0
AIN1 = &pin.BasicPin{N: "AIN1"} // AIN1
)
// Headers found on BeagleBones.
var (
// Port J1 is the UART port where the default terminal is connected to.
J1_1 pin.Pin = pin.GROUND
J1_2 pin.Pin = pin.INVALID
J1_3 pin.Pin = pin.INVALID
J1_4 gpio.PinIO = gpio.INVALID // GPIO42, UART0_RX
J1_5 gpio.PinIO = gpio.INVALID // GPIO43, UART0_TX
J1_6 pin.Pin = pin.INVALID
P8_1 pin.Pin = pin.GROUND
P8_2 pin.Pin = pin.GROUND
P8_3 gpio.PinIO = gpio.INVALID // GPIO38, MMC1_DAT6
P8_4 gpio.PinIO = gpio.INVALID // GPIO39, MMC1_DAT7
P8_5 gpio.PinIO = gpio.INVALID // GPIO34, MMC1_DAT2
P8_6 gpio.PinIO = gpio.INVALID // GPIO35, MMC1_DAT3
P8_7 gpio.PinIO = gpio.INVALID // GPIO66, Timer4
P8_8 gpio.PinIO = gpio.INVALID // GPIO67, Timer7
P8_9 gpio.PinIO = gpio.INVALID // GPIO69, Timer5
P8_10 gpio.PinIO = gpio.INVALID // GPIO68, Timer6
P8_11 gpio.PinIO = gpio.INVALID // GPIO45,
P8_12 gpio.PinIO = gpio.INVALID // GPIO44,
P8_13 gpio.PinIO = gpio.INVALID // GPIO23, EHRPWM2B
P8_14 gpio.PinIO = gpio.INVALID // GPIO26,
P8_15 gpio.PinIO = gpio.INVALID // GPIO47,
P8_16 gpio.PinIO = gpio.INVALID // GPIO46,
P8_17 gpio.PinIO = gpio.INVALID // GPIO27,
P8_18 gpio.PinIO = gpio.INVALID // GPIO65,
P8_19 gpio.PinIO = gpio.INVALID // GPIO22, EHRPWM2A
P8_20 gpio.PinIO = gpio.INVALID // GPIO63, MMC1_CMD
P8_21 gpio.PinIO = gpio.INVALID // GPIO62, MMC1_CLK
P8_22 gpio.PinIO = gpio.INVALID // GPIO37, MMC1_DAT5
P8_23 gpio.PinIO = gpio.INVALID // GPIO36, MMC1_DAT4
P8_24 gpio.PinIO = gpio.INVALID // GPIO33, MMC1_DAT1
P8_25 gpio.PinIO = gpio.INVALID // GPIO32, MMC1_DAT0
P8_26 gpio.PinIO = gpio.INVALID // GPIO61,
P8_27 gpio.PinIO = gpio.INVALID // GPIO86, LCD_VSYNC
P8_28 gpio.PinIO = gpio.INVALID // GPIO88, LCD_PCLK
P8_29 gpio.PinIO = gpio.INVALID // GPIO87, LCD_HSYNC
P8_30 gpio.PinIO = gpio.INVALID // GPIO89, LCD_AC_BIAS_E
P8_31 gpio.PinIO = gpio.INVALID // GPIO10, LCD_DATA14, UART4_CTS
P8_32 gpio.PinIO = gpio.INVALID // GPIO11, LCD_DATA15, UART5_RTS
P8_33 gpio.PinIO = gpio.INVALID // GPIO9, LCD_DATA13, UART4_RTS
P8_34 gpio.PinIO = gpio.INVALID // GPIO81, LCD_DATA11, EHRPWM1B, UART3_RTS
P8_35 gpio.PinIO = gpio.INVALID // GPIO8, LCD_DATA12, UART4_CTS
P8_36 gpio.PinIO = gpio.INVALID // GPIO80, LCD_DATA10, EHRPWM1A, UART3_CTS
P8_37 gpio.PinIO = gpio.INVALID // GPIO78, LCD_DATA8, UART5_TX
P8_38 gpio.PinIO = gpio.INVALID // GPIO79, LCD_DATA9, UART5_RX
P8_39 gpio.PinIO = gpio.INVALID // GPIO76, LCD_DATA6
P8_40 gpio.PinIO = gpio.INVALID // GPIO77, LCD_DATA7
P8_41 gpio.PinIO = gpio.INVALID // GPIO74, LCD_DATA4
P8_42 gpio.PinIO = gpio.INVALID // GPIO75, LCD_DATA5
P8_43 gpio.PinIO = gpio.INVALID // GPIO72, LCD_DATA2
P8_44 gpio.PinIO = gpio.INVALID // GPIO73, LCD_DATA3
P8_45 gpio.PinIO = gpio.INVALID // GPIO70, LCD_DATA0, EHRPWM2A
P8_46 gpio.PinIO = gpio.INVALID // GPIO71, LCD_DATA1, EHRPWM2B
P9_1 pin.Pin = pin.GROUND
P9_2 pin.Pin = pin.GROUND
P9_3 pin.Pin = pin.V3_3
P9_4 pin.Pin = pin.V3_3
P9_5 pin.Pin = pin.V5
P9_6 pin.Pin = pin.V5
P9_7 pin.Pin = pin.V5
P9_8 pin.Pin = pin.V5
P9_9 pin.Pin = PWR_BUT // PWR_BUT
P9_10 pin.Pin = RESET_OUT // SYS_RESETn
P9_11 gpio.PinIO = gpio.INVALID // GPIO30, UART4_RX
P9_12 gpio.PinIO = gpio.INVALID // GPIO60
P9_13 gpio.PinIO = gpio.INVALID // GPIO31, UART4_TX
P9_14 gpio.PinIO = gpio.INVALID // GPIO50, EHRPWM1A
P9_15 gpio.PinIO = gpio.INVALID // GPIO48
P9_16 gpio.PinIO = gpio.INVALID // GPIO51, EHRPWM1B
P9_17 gpio.PinIO = gpio.INVALID // GPIO5, I2C1_SCL, SPI0_CS0
P9_18 gpio.PinIO = gpio.INVALID // GPIO4, I2C1_SDA, SPI0_MISO
P9_19 gpio.PinIO = gpio.INVALID // GPIO13, I2C2_SCL, UART1_RTS, SPI1_CS1
P9_20 gpio.PinIO = gpio.INVALID // GPIO12, I2C2_SDA, UART1_CTS, SPI1_CS0
P9_21 gpio.PinIO = gpio.INVALID // GPIO3, EHRPWM0B, I2C2_SCL, UART2_TX, SPI0_MOSI
P9_22 gpio.PinIO = gpio.INVALID // GPIO2, EHRPWM0A, I2C2_SDA, UART2_RX, SPI0_CLK
P9_23 gpio.PinIO = gpio.INVALID // GPIO49
P9_24 gpio.PinIO = gpio.INVALID // GPIO15, I2C1_SCL, UART1_TX
P9_25 gpio.PinIO = gpio.INVALID // GPIO117
P9_26 gpio.PinIO = gpio.INVALID // GPIO14, I2C1_SDA, UART1_RX
P9_27 gpio.PinIO = gpio.INVALID // GPIO115
P9_28 gpio.PinIO = gpio.INVALID // GPIO113, ECAPPWM2, SPI1_CS0
P9_29 gpio.PinIO = gpio.INVALID // GPIO111, EHRPWM0B, SPI1_MOSI
P9_30 gpio.PinIO = gpio.INVALID // GPIO112, SPI1_MISO
P9_31 gpio.PinIO = gpio.INVALID // GPIO110, EHRPWM0A, SPI1_CLK
P9_32 pin.Pin = VADC // VDD_ADC
P9_33 pin.Pin = AIN4 // AIN4
P9_34 pin.Pin = AGND // GNDA_ADC
P9_35 pin.Pin = AIN6 // AIN6
P9_36 pin.Pin = AIN5 // AIN5
P9_37 pin.Pin = AIN2 // AIN2
P9_38 pin.Pin = AIN3 // AIN3
P9_39 pin.Pin = AIN0 // AIN0
P9_40 pin.Pin = AIN1 // AIN1
P9_41 gpio.PinIO = gpio.INVALID // GPIO20
P9_42 gpio.PinIO = gpio.INVALID // GPIO7, ECAPPWM0, UART3_TX, SPI1_CS1
P9_43 pin.Pin = pin.GROUND
P9_44 pin.Pin = pin.GROUND
P9_45 pin.Pin = pin.GROUND
P9_46 pin.Pin = pin.GROUND
)
// Present returns true if the host is a BeagleBone Black/Green or their
// Wireless version.
func Present() bool {
return black.Present() || green.Present()
}
// driver implements periph.Driver.
type driver struct {
}
func (d *driver) String() string {
return "beaglebone"
}
func (d *driver) Prerequisites() []string {
return []string{"am335x"}
}
func (d *driver) After() []string {
return nil
}
func (d *driver) Init() (bool, error) {
if !Present() {
return false, errors.New("BeagleBone board not detected")
}
J1_4 = sysfs.Pins[42]
J1_5 = sysfs.Pins[43]
P8_3 = sysfs.Pins[38]
P8_4 = sysfs.Pins[39]
P8_5 = sysfs.Pins[34]
P8_6 = sysfs.Pins[35]
P8_7 = sysfs.Pins[66]
P8_8 = sysfs.Pins[67]
P8_9 = sysfs.Pins[69]
P8_10 = sysfs.Pins[68]
P8_11 = sysfs.Pins[45]
P8_12 = sysfs.Pins[44]
P8_13 = sysfs.Pins[23]
P8_14 = sysfs.Pins[26]
P8_15 = sysfs.Pins[47]
P8_16 = sysfs.Pins[46]
P8_17 = sysfs.Pins[27]
P8_18 = sysfs.Pins[65]
P8_19 = sysfs.Pins[22]
P8_20 = sysfs.Pins[63]
P8_21 = sysfs.Pins[62]
P8_22 = sysfs.Pins[37]
P8_23 = sysfs.Pins[36]
P8_24 = sysfs.Pins[33]
P8_25 = sysfs.Pins[32]
P8_26 = sysfs.Pins[61]
P8_27 = sysfs.Pins[86]
P8_28 = sysfs.Pins[88]
P8_29 = sysfs.Pins[87]
P8_30 = sysfs.Pins[89]
P8_31 = sysfs.Pins[10]
P8_32 = sysfs.Pins[11]
P8_33 = sysfs.Pins[9]
P8_34 = sysfs.Pins[81]
P8_35 = sysfs.Pins[8]
P8_36 = sysfs.Pins[80]
P8_37 = sysfs.Pins[78]
P8_38 = sysfs.Pins[79]
P8_39 = sysfs.Pins[76]
P8_40 = sysfs.Pins[77]
P8_41 = sysfs.Pins[74]
P8_42 = sysfs.Pins[75]
P8_43 = sysfs.Pins[72]
P8_44 = sysfs.Pins[73]
P8_45 = sysfs.Pins[70]
P8_46 = sysfs.Pins[71]
P9_11 = sysfs.Pins[30]
P9_12 = sysfs.Pins[60]
P9_13 = sysfs.Pins[31]
P9_14 = sysfs.Pins[50]
P9_15 = sysfs.Pins[48]
P9_16 = sysfs.Pins[51]
P9_17 = sysfs.Pins[5]
P9_18 = sysfs.Pins[4]
P9_19 = sysfs.Pins[13]
P9_20 = sysfs.Pins[12]
P9_21 = sysfs.Pins[3]
P9_22 = sysfs.Pins[2]
P9_23 = sysfs.Pins[49]
P9_24 = sysfs.Pins[15]
P9_25 = sysfs.Pins[117]
P9_26 = sysfs.Pins[14]
P9_27 = sysfs.Pins[115]
P9_28 = sysfs.Pins[113]
P9_29 = sysfs.Pins[111]
P9_30 = sysfs.Pins[112]
P9_31 = sysfs.Pins[110]
P9_41 = sysfs.Pins[20]
P9_42 = sysfs.Pins[7]
hdr := [][]pin.Pin{{J1_1}, {J1_2}, {J1_3}, {J1_4}, {J1_5}, {J1_6}}
if err := pinreg.Register("J1", hdr); err != nil {
return true, err
}
hdr = [][]pin.Pin{
{P8_1, P8_2},
{P8_3, P8_4},
{P8_5, P8_6},
{P8_7, P8_8},
{P8_9, P8_10},
{P8_11, P8_12},
{P8_13, P8_14},
{P8_15, P8_16},
{P8_17, P8_18},
{P8_19, P8_20},
{P8_21, P8_22},
{P8_23, P8_24},
{P8_25, P8_26},
{P8_27, P8_28},
{P8_29, P8_30},
{P8_31, P8_32},
{P8_33, P8_34},
{P8_35, P8_36},
{P8_37, P8_38},
{P8_39, P8_40},
{P8_41, P8_42},
{P8_43, P8_44},
{P8_45, P8_46},
}
if err := pinreg.Register("P8", hdr); err != nil {
return true, err
}
hdr = [][]pin.Pin{
{P9_1, P9_2},
{P9_3, P9_4},
{P9_5, P9_6},
{P9_7, P9_8},
{P9_9, P9_10},
{P9_11, P9_12},
{P9_13, P9_14},
{P9_15, P9_16},
{P9_17, P9_18},
{P9_19, P9_20},
{P9_21, P9_22},
{P9_23, P9_24},
{P9_25, P9_26},
{P9_27, P9_28},
{P9_29, P9_30},
{P9_31, P9_32},
{P9_33, P9_34},
{P9_35, P9_36},
{P9_37, P9_38},
{P9_39, P9_40},
{P9_41, P9_42},
{P9_43, P9_44},
{P9_45, P9_46},
}
err := pinreg.Register("P9", hdr)
return true, err
}
func init() {
if isArm {
periph.MustRegister(&drv)
}
}
var drv driver

View File

@ -0,0 +1,7 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package bone
const isArm = true

View File

@ -0,0 +1,9 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build !arm
package bone
const isArm = false

95
vendor/periph.io/x/periph/host/beagle/green/green.go generated vendored Normal file
View File

@ -0,0 +1,95 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package green implements headers for the BeagleBone Green and BeagleBone
// Green Wireless micro-computers.
//
// Reference
//
// https://beagleboard.org/green
//
// https://beagleboard.org/green-wireless
//
// Datasheet
//
// http://wiki.seeedstudio.com/BeagleBone_Green/
package green
import (
"errors"
"strings"
"periph.io/x/periph"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/pin"
"periph.io/x/periph/conn/pin/pinreg"
"periph.io/x/periph/host/distro"
"periph.io/x/periph/host/sysfs"
)
// Headers found on BeagleBone Green.
var (
// I2C Groove port.
I2C_SCL gpio.PinIO = gpio.INVALID // GPIO13, I2C2_SCL, UART1_RTS, SPI1_CS1
I2C_SDA gpio.PinIO = gpio.INVALID // GPIO12, I2C2_SDA, UART1_CTS, SPI1_CS0
// UART Groove port connected to UART2.
UART_TX gpio.PinIO = gpio.INVALID // GPIO3, EHRPWM0B, I2C2_SCL, UART2_TX, SPI0_MISO
UART_RX gpio.PinIO = gpio.INVALID // GPIO2, EHRPWM0A, I2C2_SDA, UART2_RX, SPI0_CLK
)
// Present returns true if the host is a BeagleBone Green or BeagleBone Green
// Wireless.
func Present() bool {
if isArm {
return strings.HasPrefix(distro.DTModel(), "TI AM335x BeagleBone Green")
}
return false
}
// driver implements periph.Driver.
type driver struct {
}
func (d *driver) String() string {
return "beaglebone-green"
}
func (d *driver) Prerequisites() []string {
return []string{"am335x"}
}
func (d *driver) After() []string {
return nil
}
func (d *driver) Init() (bool, error) {
if !Present() {
return false, errors.New("BeagleBone Green board not detected")
}
I2C_SDA = sysfs.Pins[12]
I2C_SCL = sysfs.Pins[13]
hdr := [][]pin.Pin{{pin.GROUND}, {pin.V3_3}, {I2C_SDA}, {I2C_SCL}}
if err := pinreg.Register("I2C", hdr); err != nil {
return true, err
}
UART_TX = sysfs.Pins[3]
UART_RX = sysfs.Pins[2]
hdr = [][]pin.Pin{{pin.GROUND}, {pin.V3_3}, {UART_TX}, {UART_RX}}
if err := pinreg.Register("UART", hdr); err != nil {
return true, err
}
return true, nil
}
func init() {
if isArm {
periph.MustRegister(&drv)
}
}
var drv driver

View File

@ -0,0 +1,7 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package green
const isArm = true

View File

@ -0,0 +1,9 @@
// Copyright 2018 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build !arm
package green
const isArm = false

358
vendor/periph.io/x/periph/host/chip/chip.go generated vendored Normal file
View File

@ -0,0 +1,358 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package chip
import (
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
"periph.io/x/periph"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/gpio/gpioreg"
"periph.io/x/periph/conn/pin"
"periph.io/x/periph/conn/pin/pinreg"
"periph.io/x/periph/host/allwinner"
"periph.io/x/periph/host/distro"
"periph.io/x/periph/host/fs"
)
// C.H.I.P. hardware pins.
var (
TEMP_SENSOR = &pin.BasicPin{N: "TEMP_SENSOR"}
PWR_SWITCH = &pin.BasicPin{N: "PWR_SWITCH"}
// XIO "gpio" pins attached to the pcf8574 I²C port extender.
XIO0, XIO1, XIO2, XIO3, XIO4, XIO5, XIO6, XIO7 gpio.PinIO
)
// The U13 header is opposite the power LED.
//
// The alternate pin functionality is described at pages 322-323 of
// https://github.com/NextThingCo/CHIP-Hardware/raw/master/CHIP%5Bv1_0%5D/CHIPv1_0-BOM-Datasheets/Allwinner%20R8%20User%20Manual%20V1.1.pdf
var (
U13_1 = pin.GROUND //
U13_2 = pin.DC_IN //
U13_3 = pin.V5 // (filtered)
U13_4 = pin.GROUND //
U13_5 = pin.V3_3 //
U13_6 = TEMP_SENSOR // Analog temp sensor input
U13_7 = pin.V1_8 //
U13_8 = pin.BAT_PLUS // External LiPo battery
U13_9 = allwinner.PB16 // I2C1_SDA
U13_10 = PWR_SWITCH // Power button
U13_11 = allwinner.PB15 // I2C1_SCL
U13_12 = pin.GROUND //
U13_13 = allwinner.X1 // Touch screen X1
U13_14 = allwinner.X2 // Touch screen X2
U13_15 = allwinner.Y1 // Touch screen Y1
U13_16 = allwinner.Y2 // Touch screen Y2
U13_17 = allwinner.PD2 // LCD-D2; UART2_TX firmware probe for 1-wire to detect DIP at boot; http://docs.getchip.com/dip.html#dip-identification
U13_18 = allwinner.PB2 // PWM0; EINT16
U13_19 = allwinner.PD4 // LCD-D4; UART2_CTS
U13_20 = allwinner.PD3 // LCD-D3; UART2_RX
U13_21 = allwinner.PD6 // LCD-D6
U13_22 = allwinner.PD5 // LCD-D5
U13_23 = allwinner.PD10 // LCD-D10
U13_24 = allwinner.PD7 // LCD-D7
U13_25 = allwinner.PD12 // LCD-D12
U13_26 = allwinner.PD11 // LCD-D11
U13_27 = allwinner.PD14 // LCD-D14
U13_28 = allwinner.PD13 // LCD-D13
U13_29 = allwinner.PD18 // LCD-D18
U13_30 = allwinner.PD15 // LCD-D15
U13_31 = allwinner.PD20 // LCD-D20
U13_32 = allwinner.PD19 // LCD-D19
U13_33 = allwinner.PD22 // LCD-D22
U13_34 = allwinner.PD21 // LCD-D21
U13_35 = allwinner.PD24 // LCD-CLK
U13_36 = allwinner.PD23 // LCD-D23
U13_37 = allwinner.PD26 // LCD-VSYNC
U13_38 = allwinner.PD27 // LCD-HSYNC
U13_39 = pin.GROUND //
U13_40 = allwinner.PD25 // LCD-DE: RGB666 data
)
// The U14 header is right next to the power LED.
var (
U14_1 = pin.GROUND //
U14_2 = pin.V5 // (filtered)
U14_3 = allwinner.PG3 // UART1_TX; EINT3
U14_4 = allwinner.HP_LEFT // Headphone left output
U14_5 = allwinner.PG4 // UART1_RX; EINT4
U14_6 = allwinner.HP_COM // Headphone amp out
U14_7 = allwinner.FEL // Boot mode selection
U14_8 = allwinner.HP_RIGHT // Headphone right output
U14_9 = pin.V3_3 //
U14_10 = allwinner.MIC_GND // Microphone ground
U14_11 = allwinner.KEY_ADC // LRADC Low res analog to digital
U14_12 = allwinner.MIC_IN // Microphone input
U14_13 = XIO0 // gpio via I²C controller
U14_14 = XIO1 // gpio via I²C controller
U14_15 = XIO2 // gpio via I²C controller
U14_16 = XIO3 // gpio via I²C controller
U14_17 = XIO4 // gpio via I²C controller
U14_18 = XIO5 // gpio via I²C controller
U14_19 = XIO6 // gpio via I²C controller
U14_20 = XIO7 // gpio via I²C controller
U14_21 = pin.GROUND //
U14_22 = pin.GROUND //
U14_23 = allwinner.PG1 // GPS_CLK; AP-EINT1
U14_24 = allwinner.PB3 // IR_TX; AP-EINT3 (EINT17)
U14_25 = allwinner.PB18 // I2C2_SDA
U14_26 = allwinner.PB17 // I2C2_SCL
U14_27 = allwinner.PE0 // CSIPCK: CMOS serial interface; SPI2_CS0; EINT14
U14_28 = allwinner.PE1 // CSICK: CMOS serial interface; SPI2_CLK; EINT15
U14_29 = allwinner.PE2 // CSIHSYNC; SPI2_MOSI
U14_30 = allwinner.PE3 // CSIVSYNC; SPI2_MISO
U14_31 = allwinner.PE4 // CSID0
U14_32 = allwinner.PE5 // CSID1
U14_33 = allwinner.PE6 // CSID2
U14_34 = allwinner.PE7 // CSID3
U14_35 = allwinner.PE8 // CSID4
U14_36 = allwinner.PE9 // CSID5
U14_37 = allwinner.PE10 // CSID6; UART1_RX
U14_38 = allwinner.PE11 // CSID7; UART1_TX
U14_39 = pin.GROUND //
U14_40 = pin.GROUND //
)
// Present returns true if running on a NextThing Co's C.H.I.P. board.
//
// It looks for "C.H.I.P" in the device tree. The following information is
// expected in the device dtree:
// root@chip2:/proc/device-tree# od -c compatible
// 0000000 n e x t t h i n g , c h i p \0 a
// 0000020 l l w i n n e r , s u n 5 i - r
// 0000040 8 \0
// root@chip2:/proc/device-tree# od -c model
// 0000000 N e x t T h i n g C . H . I .
// 0000020 P . \0
func Present() bool {
return strings.Contains(distro.DTModel(), "C.H.I.P")
}
//
// aliases is a list of aliases for the various gpio pins, this allows users to
// refer to pins using the documented and labeled names instead of some GPIOnnn
// name. The map key is the alias and the value is the real pin name.
var aliases = map[string]string{
"AP-EINT1": "PG1",
"AP-EINT3": "PB3",
"CSIPCK": "PE0",
"CSIHSYNC": "PE2",
"CSID0": "PE4",
"CSID2": "PE6",
"CSID4": "PE8",
"CSID6": "PE10",
"CSICK": "PE1",
"CSIVSYNC": "PE3",
"CSID1": "PE5",
"CSID3": "PE7",
"CSID5": "PE9",
"CSID7": "PE11",
"LCD-CLK": "PD24",
"LCD-D10": "PD10",
"LCD-D11": "PD11",
"LCD-D12": "PD12",
"LCD-D13": "PD13",
"LCD-D14": "PD14",
"LCD-D15": "PD15",
"LCD-D18": "PD18",
"LCD-D19": "PD19",
"LCD-D2": "PD2",
"LCD-D20": "PD20",
"LCD-D21": "PD21",
"LCD-D22": "PD22",
"LCD-D23": "PD23",
"LCD-D3": "PD3",
"LCD-D4": "PD4",
"LCD-D5": "PD5",
"LCD-D6": "PD6",
"LCD-D7": "PD7",
"LCD-DE": "PD25",
"LCD-HSYNC": "PD27",
"LCD-VSYNC": "PD26",
"TWI1-SCK": "PB15",
"TWI1-SDA": "PB16",
"TWI2-SCK": "PB17",
"TWI2-SDA": "PB18",
"UART1-RX": "PG4",
"UART1-TX": "PG3",
}
func init() {
// These are initialized later by the driver.
XIO0 = gpio.INVALID
XIO1 = gpio.INVALID
XIO2 = gpio.INVALID
XIO3 = gpio.INVALID
XIO4 = gpio.INVALID
XIO5 = gpio.INVALID
XIO6 = gpio.INVALID
XIO7 = gpio.INVALID
// These must be reinitialized.
U14_13 = XIO0
U14_14 = XIO1
U14_15 = XIO2
U14_16 = XIO3
U14_17 = XIO4
U14_18 = XIO5
U14_19 = XIO6
U14_20 = XIO7
}
// findXIOBase calculates the base of the XIO-P? gpio pins as explained in
// http://docs.getchip.com/chip.html#kernel-4-3-vs-4-4-gpio-how-to-tell-the-difference
//
// The XIO-P? sysfs mapped pin number changed in kernel 4.3, 4.4.11 and again
// in 4.4.13 so it is better to query sysfs.
func findXIOBase() int {
chips, err := filepath.Glob("/sys/class/gpio/gpiochip*/label")
if err != nil {
return -1
}
for _, item := range chips {
f, err := fs.Open(item, os.O_RDONLY)
if err != nil {
continue
}
b, err := ioutil.ReadAll(f)
if err1 := f.Close(); err == nil {
err = err1
}
if err != nil {
continue
}
if string(b) == "pcf8574a\n" {
id, err := strconv.Atoi(filepath.Base(filepath.Dir(item))[8:])
if err != nil {
return -1
}
return id
}
}
return -1
}
// driver implements drivers.Driver.
type driver struct {
}
func (d *driver) String() string {
return "chip"
}
func (d *driver) Prerequisites() []string {
return nil
}
func (d *driver) After() []string {
// has allwinner cpu, needs sysfs for XIO0-XIO7 "gpio" pins
return []string{"allwinner-gpio", "sysfs-gpio"}
}
func (d *driver) Init() (bool, error) {
if !Present() {
return false, errors.New("NextThing Co. CHIP board not detected")
}
base := findXIOBase()
if base == -1 {
return true, errors.New("couldn't find XIO pins base number")
}
for i := 0; i < 8; i++ {
aliases[fmt.Sprintf("XIO-P%d", i)] = fmt.Sprintf("GPIO%d", base+i)
}
// At this point the sysfs driver has initialized and discovered its pins,
// we can now hook-up the appropriate CHIP pins to sysfs gpio pins.
for alias, real := range aliases {
if err := gpioreg.RegisterAlias(alias, real); err != nil {
return true, err
}
}
// These must be explicitly initialized.
XIO0 = gpioreg.ByName("XIO-P0")
XIO1 = gpioreg.ByName("XIO-P1")
XIO2 = gpioreg.ByName("XIO-P2")
XIO3 = gpioreg.ByName("XIO-P3")
XIO4 = gpioreg.ByName("XIO-P4")
XIO5 = gpioreg.ByName("XIO-P5")
XIO6 = gpioreg.ByName("XIO-P6")
XIO7 = gpioreg.ByName("XIO-P7")
U14_13 = XIO0
U14_14 = XIO1
U14_15 = XIO2
U14_16 = XIO3
U14_17 = XIO4
U14_18 = XIO5
U14_19 = XIO6
U14_20 = XIO7
// U13 is one of the 20x2 connectors.
U13 := [][]pin.Pin{
{U13_1, U13_2},
{U13_3, U13_4},
{U13_5, U13_6},
{U13_7, U13_8},
{gpioreg.ByName("TWI1-SDA"), U13_10},
{gpioreg.ByName("TWI1-SCK"), U13_12},
{U13_13, U13_14},
{U13_15, U13_16},
{gpioreg.ByName("LCD-D2"), gpioreg.ByName("PWM0")},
{gpioreg.ByName("LCD-D4"), gpioreg.ByName("LCD-D3")},
{gpioreg.ByName("LCD-D6"), gpioreg.ByName("LCD-D5")},
{gpioreg.ByName("LCD-D10"), gpioreg.ByName("LCD-D7")},
{gpioreg.ByName("LCD-D12"), gpioreg.ByName("LCD-D11")},
{gpioreg.ByName("LCD-D14"), gpioreg.ByName("LCD-D13")},
{gpioreg.ByName("LCD-D18"), gpioreg.ByName("LCD-D15")},
{gpioreg.ByName("LCD-D20"), gpioreg.ByName("LCD-D19")},
{gpioreg.ByName("LCD-D22"), gpioreg.ByName("LCD-D21")},
{gpioreg.ByName("LCD-CLK"), gpioreg.ByName("LCD-D23")},
{gpioreg.ByName("LCD-VSYNC"), gpioreg.ByName("LCD-HSYNC")},
{U13_39, gpioreg.ByName("LCD-DE")},
}
if err := pinreg.Register("U13", U13); err != nil {
return true, err
}
// U14 is one of the 20x2 connectors.
U14 := [][]pin.Pin{
{U14_1, U14_2},
{gpioreg.ByName("UART1-TX"), U14_4},
{gpioreg.ByName("UART1-RX"), U14_6},
{U14_7, U14_8},
{U14_9, U14_10},
{U14_11, U14_12}, // TODO(maruel): switch to LRADC once analog support is added
{U14_13, U14_14},
{U14_15, U14_16},
{U14_17, U14_18},
{U14_19, U14_20},
{U14_21, U14_22},
{gpioreg.ByName("AP-EINT1"), gpioreg.ByName("AP-EINT3")},
{gpioreg.ByName("TWI2-SDA"), gpioreg.ByName("TWI2-SCK")},
{gpioreg.ByName("CSIPCK"), gpioreg.ByName("CSICK")},
{gpioreg.ByName("CSIHSYNC"), gpioreg.ByName("CSIVSYNC")},
{gpioreg.ByName("CSID0"), gpioreg.ByName("CSID1")},
{gpioreg.ByName("CSID2"), gpioreg.ByName("CSID3")},
{gpioreg.ByName("CSID4"), gpioreg.ByName("CSID5")},
{gpioreg.ByName("CSID6"), gpioreg.ByName("CSID7")},
{U14_39, U14_40},
}
return true, pinreg.Register("U14", U14)
}
func init() {
if isArm {
periph.MustRegister(&drv)
}
}
var drv driver

7
vendor/periph.io/x/periph/host/chip/chip_arm.go generated vendored Normal file
View File

@ -0,0 +1,7 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package chip
const isArm = true

9
vendor/periph.io/x/periph/host/chip/chip_other.go generated vendored Normal file
View File

@ -0,0 +1,9 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build !arm
package chip
const isArm = false

30
vendor/periph.io/x/periph/host/chip/doc.go generated vendored Normal file
View File

@ -0,0 +1,30 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package chip contains header definitions for NextThing Co's C.H.I.P. board.
//
// CHIP uses the Allwinner R8 processor and thus the allwinner host package is
// automatically imported.
//
// This package exports the U13 header, which is opposite the power LED, and
// U14, which is right next to the power LED. Most of the pins are usable as
// GPIO and are directly to the processor. These can use memory-mapped GPIO,
// which is very fast. The XIO-P0 through XIO-P7 pins are attached to a pcf8574
// I²C expander which has the result that all accesses to these pins have to go
// through the kernel and the I²C bus protocol, i.e., they're slow.
//
// GPIO edge detection (using interrupts) is only supported on a few of the
// processor's pins: AP-EINT1, AP-EINT3, CSIPCK, and CSICK. Edge detection is
// also supported on the XIO pins, but this feature is rather limited due to
// the device and the driver (for example, the driver interrupts on all edges).
//
// References
//
// http://www.chip-community.org/index.php/Hardware_Information
//
// http://docs.getchip.com/chip.html#chip-hardware
//
// A graphical view of the board headers is available at:
// http://docs.getchip.com/chip.html#pin-headers
package chip

83
vendor/periph.io/x/periph/host/cpu/cpu.go generated vendored Normal file
View File

@ -0,0 +1,83 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package cpu
import (
"io"
"io/ioutil"
"os"
"strconv"
"strings"
"sync"
"time"
"periph.io/x/periph/host/fs"
)
// MaxSpeed returns the processor maximum speed in Hz.
//
// Returns 0 if it couldn't be calculated.
func MaxSpeed() int64 {
if isLinux {
return getMaxSpeedLinux()
}
return 0
}
// Nanospin spins for a short amount of time doing a busy loop.
//
// This function should be called with durations of 10µs or less.
func Nanospin(d time.Duration) {
// TODO(maruel): Use runtime.LockOSThread()?
if isLinux {
nanospinLinux(d)
} else {
nanospinTime(d)
}
}
//
var (
mu sync.Mutex
maxSpeed int64 = -1
openFile = openFileOrig
)
func openFileOrig(path string, flag int) (io.ReadCloser, error) {
f, err := fs.Open(path, flag)
if err != nil {
return nil, err
}
return f, nil
}
func getMaxSpeedLinux() int64 {
mu.Lock()
defer mu.Unlock()
if maxSpeed == -1 {
maxSpeed = 0
if f, err := openFile("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", os.O_RDONLY); err == nil {
defer f.Close()
if b, err := ioutil.ReadAll(f); err == nil {
s := strings.TrimSpace(string(b))
if i, err := strconv.ParseInt(s, 10, 64); err == nil {
// Weirdly, the speed is listed as khz. :(
maxSpeed = i * 1000
}
}
}
}
return maxSpeed
}
func nanospinTime(d time.Duration) {
// TODO(maruel): That's not optimal; it's actually pretty bad.
// time.Sleep() sleeps for really too long, calling it repeatedly with
// minimal value will give the caller a wake rate of 5KHz or so, depending on
// the host. This makes it useless for bitbanging protocol implementations.
for start := time.Now(); time.Since(start) < d; {
}
}

22
vendor/periph.io/x/periph/host/cpu/cpu_linux.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package cpu
import (
"syscall"
"time"
)
const isLinux = true
func nanospinLinux(d time.Duration) {
// runtime.nanotime() is not exported so it cannot be used to busy loop for
// very short sleep (10µs or less).
time := syscall.NsecToTimespec(d.Nanoseconds())
leftover := syscall.Timespec{}
for syscall.Nanosleep(&time, &leftover) != nil {
time = leftover
}
}

14
vendor/periph.io/x/periph/host/cpu/cpu_other.go generated vendored Normal file
View File

@ -0,0 +1,14 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build !linux
package cpu
import "time"
const isLinux = false
func nanospinLinux(d time.Duration) {
}

6
vendor/periph.io/x/periph/host/cpu/doc.go generated vendored Normal file
View File

@ -0,0 +1,6 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package cpu implements functions relating to the host CPU itself.
package cpu

61
vendor/periph.io/x/periph/host/distro/devtree.go generated vendored Normal file
View File

@ -0,0 +1,61 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package distro
// DTModel returns platform model info from the Linux device tree (/proc/device-tree/model), and
// returns "unknown" on non-linux systems or if the file is missing.
func DTModel() string {
mu.Lock()
defer mu.Unlock()
if dtModel == "" {
dtModel = "<unknown>"
if isLinux {
dtModel = makeDTModelLinux()
}
}
return dtModel
}
// DTCompatible returns platform compatibility info from the Linux device tree
// (/proc/device-tree/compatible), and returns []{"unknown"} on non-linux systems or if the file is
// missing.
func DTCompatible() []string {
mu.Lock()
defer mu.Unlock()
if dtCompatible == nil {
dtCompatible = []string{}
if isLinux {
dtCompatible = makeDTCompatible()
}
}
return dtCompatible
}
//
var (
dtModel string // cached /proc/device-tree/model
dtCompatible []string // cached /proc/device-tree/compatible
)
func makeDTModelLinux() string {
// Read model from device tree.
if bytes, err := readFile("/proc/device-tree/model"); err == nil {
if model := splitNull(bytes); len(model) > 0 {
return model[0]
}
}
return "<unknown>"
}
func makeDTCompatible() []string {
// Read compatible from device tree.
if bytes, err := readFile("/proc/device-tree/compatible"); err == nil {
return splitNull(bytes)
}
return []string{}
}

189
vendor/periph.io/x/periph/host/distro/distro.go generated vendored Normal file
View File

@ -0,0 +1,189 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package distro implements common functionality to auto-detect features on
// the host; generally about linux distributions.
//
// Most of the functions exported as in the form IsFoo() where Foo is a linux
// distribution.
package distro
import (
"io/ioutil"
"os"
"strconv"
"strings"
"sync"
"unicode"
)
// IsArmbian returns true if running on a Armbian distribution.
//
// http://www.armbian.com/
func IsArmbian() bool {
if isArm && isLinux {
// Armbian presents itself as debian in /etc/os-release so OSRelease()
// cannot be used..
_, err := os.Stat("/etc/armbian.txt")
return err == nil
}
return false
}
// IsDebian returns true if running on an Debian derived distribution.
//
// This function returns true on both Armbian, Raspbian and Ubuntu.
//
// https://debian.org/
func IsDebian() bool {
if isLinux {
// http://0pointer.de/public/systemd-man/os-release.html#ID_LIKE=
if OSRelease()["ID"] == "debian" {
return true
}
for _, part := range strings.Split(OSRelease()["ID_LIKE"], " ") {
if part == "debian" {
return true
}
}
}
return false
}
// IsRaspbian returns true if running on a Raspbian distribution.
//
// https://raspbian.org/
func IsRaspbian() bool {
if isArm && isLinux {
return OSRelease()["ID"] == "raspbian"
}
return false
}
// IsUbuntu returns true if running on an Ubuntu derived distribution.
//
// https://ubuntu.com/
func IsUbuntu() bool {
if isLinux {
return OSRelease()["ID"] == "ubuntu"
}
return false
}
// OSRelease returns parsed data from /etc/os-release.
//
// For more information, see
// http://0pointer.de/public/systemd-man/os-release.html
func OSRelease() map[string]string {
if isLinux {
return makeOSReleaseLinux()
}
return osRelease
}
// CPU
// CPUInfo returns parsed data from /proc/cpuinfo.
func CPUInfo() map[string]string {
if isLinux {
return makeCPUInfoLinux()
}
return cpuInfo
}
//
var (
mu sync.Mutex
cpuInfo map[string]string
osRelease map[string]string
readFile = ioutil.ReadFile
)
func splitSemiColon(content string) map[string]string {
// Strictly speaking this format isn't ok, there can be multiple group.
out := map[string]string{}
for _, line := range strings.Split(content, "\n") {
parts := strings.SplitN(line, ":", 2)
if len(parts) != 2 {
continue
}
// This format may have space around the ':'.
key := strings.TrimRightFunc(parts[0], unicode.IsSpace)
if len(key) == 0 || key[0] == '#' {
continue
}
// Ignore duplicate keys.
// TODO(maruel): Keep them all.
if _, ok := out[key]; !ok {
// Trim on both side, trailing space was observed on "Features" value.
out[key] = strings.TrimFunc(parts[1], unicode.IsSpace)
}
}
return out
}
func splitStrict(content string) map[string]string {
out := map[string]string{}
for _, line := range strings.Split(content, "\n") {
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
key := parts[0]
if len(key) == 0 || key[0] == '#' {
continue
}
// Overwrite previous key.
value := parts[1]
if len(value) > 2 && value[0] == '"' && value[len(value)-1] == '"' {
// Not exactly 100% right but #closeenough. See for more details
// https://www.freedesktop.org/software/systemd/man/os-release.html
var err error
value, err = strconv.Unquote(value)
if err != nil {
continue
}
}
out[key] = value
}
return out
}
// splitNull returns the null-terminated strings in the data
func splitNull(data []byte) []string {
ss := strings.Split(string(data), "\x00")
// The last string is typically null-terminated, so remove empty string
// from end of array.
if len(ss) > 0 && len(ss[len(ss)-1]) == 0 {
ss = ss[:len(ss)-1]
}
return ss
}
func makeCPUInfoLinux() map[string]string {
mu.Lock()
defer mu.Unlock()
if cpuInfo == nil {
cpuInfo = map[string]string{}
if bytes, err := readFile("/proc/cpuinfo"); err == nil {
cpuInfo = splitSemiColon(string(bytes))
}
}
return cpuInfo
}
func makeOSReleaseLinux() map[string]string {
mu.Lock()
defer mu.Unlock()
if osRelease == nil {
// This file may not exist on older distros. Send a PR if you want to have
// a specific fallback.
osRelease = map[string]string{}
if bytes, err := readFile("/etc/os-release"); err == nil {
osRelease = splitStrict(string(bytes))
}
}
return osRelease
}

7
vendor/periph.io/x/periph/host/distro/distro_arm.go generated vendored Normal file
View File

@ -0,0 +1,7 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package distro
const isArm = true

View File

@ -0,0 +1,9 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build arm64
package distro
const isArm = true

View File

@ -0,0 +1,7 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package distro
const isLinux = true

View File

@ -0,0 +1,9 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build !arm,!arm64
package distro
const isArm = false

View File

@ -0,0 +1,9 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// +build !linux
package distro
const isLinux = false

10
vendor/periph.io/x/periph/host/doc.go generated vendored Normal file
View File

@ -0,0 +1,10 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package host defines the host itself.
//
// The host is the machine where this code is running.
//
// Subpackages contain the drivers that are loaded automatically.
package host

130
vendor/periph.io/x/periph/host/fs/fs.go generated vendored Normal file
View File

@ -0,0 +1,130 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package fs provides access to the file system on the host.
//
// It exposes ioctl syscall and epoll in an OS agnostic way and permits
// completely disabling file access to lock down unit tests.
package fs
import (
"errors"
"os"
"sync"
)
// Ioctler is a file handle that supports ioctl calls.
type Ioctler interface {
// Ioctl sends a linux ioctl on the file handle. op is effectively a uint32.
//
// The op is expected to be encoded in the format on x64. ARM happens to
// share the same format.
Ioctl(op uint, data uintptr) error
}
// Open opens a file.
//
// Returns an error if Inhibit() was called.
func Open(path string, flag int) (*File, error) {
mu.Lock()
if inhibited {
mu.Unlock()
return nil, errors.New("file I/O is inhibited")
}
used = true
mu.Unlock()
f, err := os.OpenFile(path, flag, 0600)
if err != nil {
return nil, err
}
return &File{f}, nil
}
// Inhibit inhibits any future file I/O. It panics if any file was opened up to
// now.
//
// It should only be called in unit tests.
func Inhibit() {
mu.Lock()
inhibited = true
if used {
panic("calling Inhibit() while files were already opened")
}
mu.Unlock()
}
// File is a superset of os.File.
type File struct {
*os.File
}
// Ioctl sends an ioctl to the file handle.
func (f *File) Ioctl(op uint, data uintptr) error {
if isMIPS {
var err error
if op, err = translateOpMIPS(op); err != nil {
return err
}
}
return ioctl(f.Fd(), op, data)
}
// Event is a file system event.
type Event struct {
event
}
// MakeEvent initializes an epoll *edge* triggered event on linux.
//
// An edge triggered event is basically an "auto-reset" event, where waiting on
// the edge resets it. A level triggered event requires manual resetting; this
// could be done via a Read() call but there's no need to require the user to
// call Read(). This is particularly useless in the case of gpio.RisingEdge and
// gpio.FallingEdge.
//
// As per the official doc, edge triggers is still remembered even when no
// epoll_wait() call is running, so no edge is missed. Two edges will be
// coallesced into one if the user mode process can't keep up. There's no
// accumulation of edges.
func (e *Event) MakeEvent(fd uintptr) error {
return e.event.makeEvent(fd)
}
// Wait waits for an event or the specified amount of time.
func (e *Event) Wait(timeoutms int) (int, error) {
return e.event.wait(timeoutms)
}
//
var (
mu sync.Mutex
inhibited bool
used bool
)
func translateOpMIPS(op uint) (uint, error) {
// Decode the arm/x64 encoding and reencode as MIPS specific linux ioctl.
// arm/x64: DIR(2), SIZE(14), TYPE(8), NR(8)
// mips: DIR(3), SIZE(13), TYPE(8), NR(8)
// Check for size overflow.
if (op & (1 << (13 + 8 + 8))) != 0 {
return 0, errors.New("fs: op code size is too large")
}
const mask = (1 << (13 + 8 + 8)) - 1
out := op & mask
// Convert dir.
switch op >> (14 + 8 + 8) {
case 0: // none
out |= 1 << (13 + 8 + 8)
case 1: // write
out |= 4 << (13 + 8 + 8)
case 2: // read
out |= 2 << (13 + 8 + 8)
default:
return 0, errors.New("fs: op code dir is invalid")
}
return out, nil
}

57
vendor/periph.io/x/periph/host/fs/fs_linux.go generated vendored Normal file
View File

@ -0,0 +1,57 @@
// Copyright 2017 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package fs
import "syscall"
const isLinux = true
func ioctl(f uintptr, op uint, arg uintptr) error {
if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, f, uintptr(op), arg); errno != 0 {
return syscall.Errno(errno)
}
return nil
}
const (
epollET = 1 << 31
epollPRI = 2
epollCTLAdd = 1
epollCTLDel = 2
epollCTLMod = 3
)
type event struct {
event [1]syscall.EpollEvent
epollFd int
fd int
}
// makeEvent creates an epoll *edge* triggered event.
//
// References:
// behavior and flags: http://man7.org/linux/man-pages/man7/epoll.7.html
// syscall.EpollCreate: http://man7.org/linux/man-pages/man2/epoll_create.2.html
// syscall.EpollCtl: http://man7.org/linux/man-pages/man2/epoll_ctl.2.html
func (e *event) makeEvent(fd uintptr) error {
epollFd, err := syscall.EpollCreate(1)
if err != nil {
return err
}
e.epollFd = epollFd
e.fd = int(fd)
// EPOLLWAKEUP could be used to force the system to not go do sleep while
// waiting for an edge. This is generally a bad idea, as we'd instead have
// the system to *wake up* when an edge is triggered. Achieving this is
// outside the scope of this interface.
e.event[0].Events = epollPRI | epollET
e.event[0].Fd = int32(e.fd)
return syscall.EpollCtl(e.epollFd, epollCTLAdd, e.fd, &e.event[0])
}
func (e *event) wait(timeoutms int) (int, error) {
// http://man7.org/linux/man-pages/man2/epoll_wait.2.html
return syscall.EpollWait(e.epollFd, e.event[:], timeoutms)
}

Some files were not shown because too many files have changed in this diff Show More