chore: bump periph.io dependencies
This commit is contained in:
parent
0b8d2218c1
commit
c1ec63fcc1
5
go.mod
5
go.mod
@ -8,8 +8,8 @@ require (
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.5
|
||||
github.com/golang/protobuf v1.5.2
|
||||
go.uber.org/zap v1.19.1
|
||||
periph.io/x/conn/v3 v3.6.8
|
||||
periph.io/x/host/v3 v3.7.0
|
||||
periph.io/x/conn/v3 v3.6.10
|
||||
periph.io/x/host/v3 v3.7.2
|
||||
)
|
||||
|
||||
require (
|
||||
@ -18,5 +18,4 @@ require (
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
periph.io/x/d2xx v0.0.3 // indirect
|
||||
)
|
||||
|
14
go.sum
14
go.sum
@ -48,6 +48,8 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
|
||||
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@ -159,10 +161,8 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v0.0.0-20181223230014-1083505acf35/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
periph.io/x/conn/v3 v3.6.8 h1:fnNSwSoKPzpoLOSxml70EInaP6YrrqcucP3KDfNxpmU=
|
||||
periph.io/x/conn/v3 v3.6.8/go.mod h1:3OD27w9YVa5DS97VsUxsPGzD9Qrm5Ny7cF5b6xMMIWg=
|
||||
periph.io/x/d2xx v0.0.1/go.mod h1:38Euaaj+s6l0faIRHh32a+PrjXvxFTFkPBEQI0TKg34=
|
||||
periph.io/x/d2xx v0.0.3 h1:BE8XcIdxabu9ZzAr1UXxSz88T9Txki6Xyo8aJ1qZvks=
|
||||
periph.io/x/d2xx v0.0.3/go.mod h1:38Euaaj+s6l0faIRHh32a+PrjXvxFTFkPBEQI0TKg34=
|
||||
periph.io/x/host/v3 v3.7.0 h1:9CP/j0FcJmR+PRHlNzAmhV6Mt3GXoWnPmRhknJlQhnE=
|
||||
periph.io/x/host/v3 v3.7.0/go.mod h1:okb5m0yUYLTM/dnMYWMBX47w4owTzyCPLpZUQb35nhs=
|
||||
periph.io/x/conn/v3 v3.6.10 h1:gwU4ssmZkq1D/uz8hU91i/COo2c9DrRaS4PJZBbCd+c=
|
||||
periph.io/x/conn/v3 v3.6.10/go.mod h1:UqWNaPMosWmNCwtufoTSTTYhB2wXWsMRAJyo1PlxO4Q=
|
||||
periph.io/x/d2xx v0.0.4/go.mod h1:38Euaaj+s6l0faIRHh32a+PrjXvxFTFkPBEQI0TKg34=
|
||||
periph.io/x/host/v3 v3.7.2 h1:rCAUxkzy2xrzh18HP2AoVwTL/fEKqmcJ1icsZQGM58Q=
|
||||
periph.io/x/host/v3 v3.7.2/go.mod h1:nHMlzkPwmnHyP9Tn0I8FV+e0N3K7TjFXLZkIWzAicog=
|
||||
|
8
vendor/modules.txt
vendored
8
vendor/modules.txt
vendored
@ -65,7 +65,7 @@ google.golang.org/protobuf/runtime/protoiface
|
||||
google.golang.org/protobuf/runtime/protoimpl
|
||||
google.golang.org/protobuf/types/descriptorpb
|
||||
google.golang.org/protobuf/types/known/timestamppb
|
||||
# periph.io/x/conn/v3 v3.6.8
|
||||
# periph.io/x/conn/v3 v3.6.10
|
||||
## explicit; go 1.13
|
||||
periph.io/x/conn/v3
|
||||
periph.io/x/conn/v3/driver
|
||||
@ -80,10 +80,7 @@ periph.io/x/conn/v3/pin
|
||||
periph.io/x/conn/v3/pin/pinreg
|
||||
periph.io/x/conn/v3/spi
|
||||
periph.io/x/conn/v3/spi/spireg
|
||||
# periph.io/x/d2xx v0.0.3
|
||||
## explicit; go 1.13
|
||||
periph.io/x/d2xx
|
||||
# periph.io/x/host/v3 v3.7.0
|
||||
# periph.io/x/host/v3 v3.7.2
|
||||
## explicit; go 1.13
|
||||
periph.io/x/host/v3
|
||||
periph.io/x/host/v3/allwinner
|
||||
@ -96,7 +93,6 @@ periph.io/x/host/v3/chip
|
||||
periph.io/x/host/v3/cpu
|
||||
periph.io/x/host/v3/distro
|
||||
periph.io/x/host/v3/fs
|
||||
periph.io/x/host/v3/ftdi
|
||||
periph.io/x/host/v3/odroidc1
|
||||
periph.io/x/host/v3/pine64
|
||||
periph.io/x/host/v3/pmem
|
||||
|
380
vendor/periph.io/x/conn/v3/.gohci.yml
generated
vendored
380
vendor/periph.io/x/conn/v3/.gohci.yml
generated
vendored
@ -17,62 +17,87 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: host
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -81,7 +106,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -111,62 +135,87 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: host
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -176,7 +225,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -219,62 +267,87 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: host
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -284,7 +357,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -343,62 +415,87 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: host
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -408,7 +505,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -433,62 +529,87 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: host
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../host
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/conn/v3=../conn
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/conn/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -498,7 +619,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
|
3
vendor/periph.io/x/conn/v3/README.md
generated
vendored
3
vendor/periph.io/x/conn/v3/README.md
generated
vendored
@ -9,8 +9,7 @@ get an [invite here](https://invite.slack.golangbridge.org/).
|
||||
[](https://periph.io/)
|
||||
|
||||
[](https://pkg.go.dev/periph.io/x/conn/v3)
|
||||
[](https://codecov.io/gh/periph/conn)
|
||||
[](https://codecov.io/gh/periph/conn)
|
||||
|
||||
|
||||
## Example
|
||||
|
18
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_parallel.go
generated
vendored
18
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_parallel.go
generated
vendored
@ -5,6 +5,7 @@
|
||||
// This file contains the parallelized driver loading logic. It is meant to be
|
||||
// load the drivers as fast as possible by parallelising work.
|
||||
|
||||
//go:build !tinygo
|
||||
// +build !tinygo
|
||||
|
||||
package driverreg
|
||||
@ -50,9 +51,11 @@ func initImpl() (*State, error) {
|
||||
if err != nil {
|
||||
return state, err
|
||||
}
|
||||
loaded := make(map[string]struct{}, len(byName))
|
||||
loaded := sync.Map{}
|
||||
for _, s := range stages {
|
||||
s.loadParallel(loaded, cD, cS, cE)
|
||||
// It's very important that each of the stage is fully completed before the
|
||||
// next one is attempted.
|
||||
s.loadParallel(&loaded, cD, cS, cE)
|
||||
}
|
||||
close(cD)
|
||||
close(cS)
|
||||
@ -61,10 +64,9 @@ func initImpl() (*State, error) {
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// loadParallel loads all the drivers for this stage in parallel.
|
||||
//
|
||||
// Updates loaded in a safe way.
|
||||
func (s *stage) loadParallel(loaded map[string]struct{}, cD chan<- driver.Impl, cS, cE chan<- DriverFailure) {
|
||||
// loadParallel loads all the drivers for this stage in parallel and returns
|
||||
// once they are all loaded.
|
||||
func (s *stage) loadParallel(loaded *sync.Map, cD chan<- driver.Impl, cS, cE chan<- DriverFailure) {
|
||||
success := make(chan string)
|
||||
go func() {
|
||||
defer close(success)
|
||||
@ -73,7 +75,7 @@ func (s *stage) loadParallel(loaded map[string]struct{}, cD chan<- driver.Impl,
|
||||
for name, drv := range s.drvs {
|
||||
// Intentionally do not look at After(), only Prerequisites().
|
||||
for _, dep := range drv.Prerequisites() {
|
||||
if _, ok := loaded[dep]; !ok {
|
||||
if _, ok := loaded.Load(dep); !ok {
|
||||
cS <- DriverFailure{drv, errors.New("dependency not loaded: " + strconv.Quote(dep))}
|
||||
continue loop
|
||||
}
|
||||
@ -98,6 +100,6 @@ func (s *stage) loadParallel(loaded map[string]struct{}, cD chan<- driver.Impl,
|
||||
wg.Wait()
|
||||
}()
|
||||
for s := range success {
|
||||
loaded[s] = struct{}{}
|
||||
loaded.Store(s, nil)
|
||||
}
|
||||
}
|
||||
|
1
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_serial.go
generated
vendored
1
vendor/periph.io/x/conn/v3/driver/driverreg/driverreg_serial.go
generated
vendored
@ -5,6 +5,7 @@
|
||||
// This file contains the single threaded driver loading code, to be used on
|
||||
// low performance cores.
|
||||
|
||||
//go:build tinygo
|
||||
// +build tinygo
|
||||
|
||||
package driverreg
|
||||
|
48
vendor/periph.io/x/d2xx/.gohci.yml
generated
vendored
48
vendor/periph.io/x/d2xx/.gohci.yml
generated
vendored
@ -1,48 +0,0 @@
|
||||
# Copyright 2021 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.
|
||||
|
||||
# See https://github.com/periph/gohci
|
||||
version: 1
|
||||
workers:
|
||||
- checks:
|
||||
- cmd:
|
||||
- go
|
||||
- test
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/host
|
||||
dir: ..
|
||||
- cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/d2xx@${GIT_SHA}
|
||||
dir: ../host
|
||||
- cmd:
|
||||
- go
|
||||
- test
|
||||
- ./...
|
||||
dir: ../host
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/d2xx@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- go
|
||||
- test
|
||||
- ./...
|
||||
dir: ../cmd
|
202
vendor/periph.io/x/d2xx/LICENSE
generated
vendored
202
vendor/periph.io/x/d2xx/LICENSE
generated
vendored
@ -1,202 +0,0 @@
|
||||
|
||||
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.
|
44
vendor/periph.io/x/d2xx/README.md
generated
vendored
44
vendor/periph.io/x/d2xx/README.md
generated
vendored
@ -1,44 +0,0 @@
|
||||
# d2xx
|
||||
|
||||
Package d2xx is a thin Go wrapper for the Future Technology "D2XX" driver at
|
||||
https://ftdichip.com/drivers/d2xx-drivers/.
|
||||
|
||||
This package is not Go idiomatic. You will want to use
|
||||
https://periph.io/x/host/v3/ftdi (or later) instead.
|
||||
|
||||
But if you really want, here it goes:
|
||||
[](https://pkg.go.dev/periph.io/x/d2xx)
|
||||
|
||||
This Go package includes third party software. See
|
||||
[third_party/README.md](third_party/README.md).
|
||||
|
||||
## Configuration
|
||||
|
||||
See https://periph.io/device/ftdi/ to configure the host to be able to use this
|
||||
driver.
|
||||
|
||||
## Availability
|
||||
|
||||
On darwin_amd64, linux_amd64 linux_arm (v6, v7 compatible) and linux_arm64 (v8),
|
||||
cgo is required. If cgo is disabled (via `CGO_ENABLED=0`), all functions in this
|
||||
driver return error [NoCGO](https://periph.io/x/d2xx#NoCGO).
|
||||
|
||||
On Windows, cgo is not required. If the dynamic library is not found at runtime,
|
||||
[Missing](https://periph.io/x/d2xx#Missing) is returned.
|
||||
|
||||
## bcm2385
|
||||
|
||||
On linux_arm (v6), hard-float is required. For cross compilation, this
|
||||
means arm-linux-gnueabihf-gcc is preferred to arm-linux-gnueabi-gcc. Using
|
||||
hardfloat causes a segfault on Raspberry Pi 1, Zero and Zero Wireless. It is
|
||||
recommended to disable this driver if targeting these hosts, see below.
|
||||
|
||||
## Disabling
|
||||
|
||||
To disable this driver, build with tag `no_d2xx`, e.g.
|
||||
|
||||
```
|
||||
go install -tags no_d2xx periph.io/x/cmd/gpio-list@latest
|
||||
```
|
||||
|
||||
This will behave has if cgo was disabled, even on Windows.
|
145
vendor/periph.io/x/d2xx/d2xx.go
generated
vendored
145
vendor/periph.io/x/d2xx/d2xx.go
generated
vendored
@ -1,145 +0,0 @@
|
||||
// Copyright 2021 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 d2xx
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Err is the error type returned by d2xx functions.
|
||||
type Err int
|
||||
|
||||
// These are additional synthetic error codes.
|
||||
const (
|
||||
// NoCGO is returned when the package was compiled without cgo, thus the d2xx
|
||||
// library is unavailable or the library was disabled via the `no_d2xx` build
|
||||
// tag.
|
||||
NoCGO Err = -2
|
||||
// Missing is returned when the dynamic library is not available.
|
||||
Missing Err = -1
|
||||
)
|
||||
|
||||
// String converts a error integer to a string representation of the error.
|
||||
func (e Err) String() string {
|
||||
switch e {
|
||||
case Missing:
|
||||
// when the library d2xx couldn't be loaded at runtime.
|
||||
return "couldn't load driver; visit https://periph.io/device/ftdi/ for help"
|
||||
case NoCGO:
|
||||
return "can't be used without cgo"
|
||||
case 0: // FT_OK
|
||||
return ""
|
||||
case 1: // FT_INVALID_HANDLE
|
||||
return "invalid handle"
|
||||
case 2: // FT_DEVICE_NOT_FOUND
|
||||
return "device not found; see https://periph.io/device/ftdi/ for help"
|
||||
case 3: // FT_DEVICE_NOT_OPENED
|
||||
return "device busy; see https://periph.io/device/ftdi/ for help"
|
||||
case 4: // FT_IO_ERROR
|
||||
return "I/O error"
|
||||
case 5: // FT_INSUFFICIENT_RESOURCES
|
||||
return "insufficient resources"
|
||||
case 6: // FT_INVALID_PARAMETER
|
||||
return "invalid parameter"
|
||||
case 7: // FT_INVALID_BAUD_RATE
|
||||
return "invalid baud rate"
|
||||
case 8: // FT_DEVICE_NOT_OPENED_FOR_ERASE
|
||||
return "device not opened for erase"
|
||||
case 9: // FT_DEVICE_NOT_OPENED_FOR_WRITE
|
||||
return "device not opened for write"
|
||||
case 10: // FT_FAILED_TO_WRITE_DEVICE
|
||||
return "failed to write device"
|
||||
case 11: // FT_EEPROM_READ_FAILED
|
||||
return "eeprom read failed"
|
||||
case 12: // FT_EEPROM_WRITE_FAILED
|
||||
return "eeprom write failed"
|
||||
case 13: // FT_EEPROM_ERASE_FAILED
|
||||
return "eeprom erase failed"
|
||||
case 14: // FT_EEPROM_NOT_PRESENT
|
||||
return "eeprom not present"
|
||||
case 15: // FT_EEPROM_NOT_PROGRAMMED
|
||||
return "eeprom not programmed"
|
||||
case 16: // FT_INVALID_ARGS
|
||||
return "invalid argument"
|
||||
case 17: // FT_NOT_SUPPORTED
|
||||
return "not supported"
|
||||
case 18: // FT_OTHER_ERROR
|
||||
return "other error"
|
||||
case 19: // FT_DEVICE_LIST_NOT_READY
|
||||
return "device list not ready"
|
||||
default:
|
||||
return "unknown status " + strconv.Itoa(int(e))
|
||||
}
|
||||
}
|
||||
|
||||
// unknown is a forward declaration of ftdi.DevType.
|
||||
const unknown = 3
|
||||
|
||||
// handle is a d2xx handle.
|
||||
//
|
||||
// This is the base type which each OS specific implementation adds methods to.
|
||||
type handle uintptr
|
||||
|
||||
// Handle is d2xx device handle.
|
||||
type Handle interface {
|
||||
Close() Err
|
||||
// ResetDevice takes >1.2ms
|
||||
ResetDevice() Err
|
||||
GetDeviceInfo() (uint32, uint16, uint16, Err)
|
||||
EEPROMRead(devType uint32, e *EEPROM) Err
|
||||
EEPROMProgram(e *EEPROM) Err
|
||||
EraseEE() Err
|
||||
WriteEE(offset uint8, value uint16) Err
|
||||
EEUASize() (int, Err)
|
||||
EEUARead(ua []byte) Err
|
||||
EEUAWrite(ua []byte) Err
|
||||
SetChars(eventChar byte, eventEn bool, errorChar byte, errorEn bool) Err
|
||||
SetUSBParameters(in, out int) Err
|
||||
SetFlowControl() Err
|
||||
SetTimeouts(readMS, writeMS int) Err
|
||||
SetLatencyTimer(delayMS uint8) Err
|
||||
SetBaudRate(hz uint32) Err
|
||||
// GetQueueStatus takes >60µs
|
||||
GetQueueStatus() (uint32, Err)
|
||||
// Read takes <5µs if GetQueueStatus was called just before,
|
||||
// 300µs~800µs otherwise (!)
|
||||
Read(b []byte) (int, Err)
|
||||
// Write takes >0.1ms
|
||||
Write(b []byte) (int, Err)
|
||||
GetBitMode() (byte, Err)
|
||||
// SetBitMode takes >0.1ms
|
||||
SetBitMode(mask, mode byte) Err
|
||||
}
|
||||
|
||||
var _ Handle = handle(0)
|
||||
|
||||
// Version returns the library's version.
|
||||
//
|
||||
// 0, 0, 0 is returned if the library is unavailable.
|
||||
func Version() (uint8, uint8, uint8) {
|
||||
return version()
|
||||
}
|
||||
|
||||
// CreateDeviceInfoList discovers the currently found devices.
|
||||
//
|
||||
// If the driver is disabled via build tag `no_d2xx`, or on posix
|
||||
// `CGO_ENABLED=0` environment variable, NoCGO is returned.
|
||||
//
|
||||
// On Windows, Missing is returned if the dynamic library is not found at
|
||||
// runtime.
|
||||
func CreateDeviceInfoList() (int, Err) {
|
||||
return createDeviceInfoList()
|
||||
}
|
||||
|
||||
// Open opens the ith device discovered.
|
||||
//
|
||||
// If the driver is disabled via build tag `no_d2xx`, or on posix
|
||||
// `CGO_ENABLED=0` environment variable, NoCGO is returned.
|
||||
//
|
||||
// On Windows, Missing is returned if the dynamic library is not found at
|
||||
// runtime.
|
||||
func Open(i int) (Handle, Err) {
|
||||
return open(i)
|
||||
}
|
13
vendor/periph.io/x/d2xx/d2xx_darwin_amd64.go
generated
vendored
13
vendor/periph.io/x/d2xx/d2xx_darwin_amd64.go
generated
vendored
@ -1,13 +0,0 @@
|
||||
// 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 cgo
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -framework CoreFoundation -framework IOKit ${SRCDIR}/third_party/libftd2xx_darwin_amd64_v1.4.4.a
|
||||
*/
|
||||
import "C"
|
13
vendor/periph.io/x/d2xx/d2xx_linux_amd64.go
generated
vendored
13
vendor/periph.io/x/d2xx/d2xx_linux_amd64.go
generated
vendored
@ -1,13 +0,0 @@
|
||||
// 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 cgo
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: ${SRCDIR}/third_party/libftd2xx_linux_amd64_v1.4.24.a
|
||||
*/
|
||||
import "C"
|
16
vendor/periph.io/x/d2xx/d2xx_linux_arm.go
generated
vendored
16
vendor/periph.io/x/d2xx/d2xx_linux_arm.go
generated
vendored
@ -1,16 +0,0 @@
|
||||
// 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 cgo
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
// TODO(maruel): https://github.com/golang/go/issues/7211 would help target the
|
||||
// optimal ARM architecture.
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: ${SRCDIR}/third_party/libftd2xx_linux_arm6hf_v1.4.24.a
|
||||
*/
|
||||
import "C"
|
13
vendor/periph.io/x/d2xx/d2xx_linux_arm64.go
generated
vendored
13
vendor/periph.io/x/d2xx/d2xx_linux_arm64.go
generated
vendored
@ -1,13 +0,0 @@
|
||||
// Copyright 2021 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 cgo
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: ${SRCDIR}/third_party/libftd2xx_linux_arm64_v1.4.24.a
|
||||
*/
|
||||
import "C"
|
219
vendor/periph.io/x/d2xx/d2xx_posix.go
generated
vendored
219
vendor/periph.io/x/d2xx/d2xx_posix.go
generated
vendored
@ -1,219 +0,0 @@
|
||||
// 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 cgo
|
||||
// +build !windows
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
/*
|
||||
#include "third_party/ftd2xx.h"
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Available is true if the library is available on this system.
|
||||
const Available = true
|
||||
|
||||
// Library functions.
|
||||
|
||||
func version() (uint8, uint8, uint8) {
|
||||
var v C.DWORD
|
||||
C.FT_GetLibraryVersion(&v)
|
||||
return uint8(v >> 16), uint8(v >> 8), uint8(v)
|
||||
}
|
||||
|
||||
func createDeviceInfoList() (int, Err) {
|
||||
var num C.DWORD
|
||||
e := C.FT_CreateDeviceInfoList(&num)
|
||||
return int(num), Err(e)
|
||||
}
|
||||
|
||||
func open(i int) (Handle, Err) {
|
||||
var h C.FT_HANDLE
|
||||
e := C.FT_Open(C.int(i), &h)
|
||||
if uintptr(h) == 0 && e == 0 {
|
||||
// 18 means FT_OTHER_ERROR. Kind of a hack but better than panic.
|
||||
e = 18
|
||||
}
|
||||
return handle(h), Err(e)
|
||||
}
|
||||
|
||||
func (h handle) Close() Err {
|
||||
return Err(C.FT_Close(h.toH()))
|
||||
}
|
||||
|
||||
func (h handle) ResetDevice() Err {
|
||||
return Err(C.FT_ResetDevice(h.toH()))
|
||||
}
|
||||
|
||||
func (h handle) GetDeviceInfo() (uint32, uint16, uint16, Err) {
|
||||
var dev C.FT_DEVICE
|
||||
var id C.DWORD
|
||||
if e := C.FT_GetDeviceInfo(h.toH(), &dev, &id, nil, nil, nil); e != 0 {
|
||||
return unknown, 0, 0, Err(e)
|
||||
}
|
||||
return uint32(dev), uint16(id >> 16), uint16(id), 0
|
||||
}
|
||||
|
||||
func (h handle) EEPROMRead(devType uint32, ee *EEPROM) Err {
|
||||
var manufacturer [64]C.char
|
||||
var manufacturerID [64]C.char
|
||||
var desc [64]C.char
|
||||
var serial [64]C.char
|
||||
eepromVoid := unsafe.Pointer(&ee.Raw[0])
|
||||
hdr := ee.asHeader()
|
||||
|
||||
// There something odd going on here.
|
||||
//
|
||||
// On a ft232h, we observed that hdr.DeviceType MUST NOT be set, but on a
|
||||
// ft232r, it MUST be set. Since we can't know in advance what we must use,
|
||||
// just try both. ¯\_(ツ)_/¯
|
||||
hdr.DeviceType = devType
|
||||
if e := C.FT_EEPROM_Read(h.toH(), eepromVoid, C.DWORD(len(ee.Raw)), &manufacturer[0], &manufacturerID[0], &desc[0], &serial[0]); e != 0 {
|
||||
// FT_INVALID_PARAMETER
|
||||
if e == 6 {
|
||||
hdr.DeviceType = 0
|
||||
e = C.FT_EEPROM_Read(h.toH(), eepromVoid, C.DWORD(len(ee.Raw)), &manufacturer[0], &manufacturerID[0], &desc[0], &serial[0])
|
||||
}
|
||||
if e != 0 {
|
||||
return Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
ee.Manufacturer = C.GoString(&manufacturer[0])
|
||||
ee.ManufacturerID = C.GoString(&manufacturerID[0])
|
||||
ee.Desc = C.GoString(&desc[0])
|
||||
ee.Serial = C.GoString(&serial[0])
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h handle) EEPROMProgram(ee *EEPROM) Err {
|
||||
// len(manufacturer) + len(desc) <= 40.
|
||||
/*
|
||||
var cmanu [64]byte
|
||||
copy(cmanu[:], ee.manufacturer)
|
||||
var cmanuID [64]byte
|
||||
copy(cmanuID[:], ee.manufacturerID)
|
||||
var cdesc [64]byte
|
||||
copy(cdesc[:], ee.desc)
|
||||
var cserial [64]byte
|
||||
copy(cserial[:], ee.serial)
|
||||
*/
|
||||
cmanu := C.CString(ee.Manufacturer)
|
||||
defer C.free(unsafe.Pointer(cmanu))
|
||||
cmanuID := C.CString(ee.ManufacturerID)
|
||||
defer C.free(unsafe.Pointer(cmanuID))
|
||||
cdesc := C.CString(ee.Desc)
|
||||
defer C.free(unsafe.Pointer(cdesc))
|
||||
cserial := C.CString(ee.Serial)
|
||||
defer C.free(unsafe.Pointer(cserial))
|
||||
|
||||
if len(ee.Raw) == 0 {
|
||||
return Err(C.FT_EEPROM_Program(h.toH(), unsafe.Pointer(uintptr(0)), 0, cmanu, cmanuID, cdesc, cserial))
|
||||
}
|
||||
return Err(C.FT_EEPROM_Program(h.toH(), unsafe.Pointer(&ee.Raw[0]), C.DWORD(len(ee.Raw)), cmanu, cmanuID, cdesc, cserial))
|
||||
}
|
||||
|
||||
func (h handle) EraseEE() Err {
|
||||
return Err(C.FT_EraseEE(h.toH()))
|
||||
}
|
||||
|
||||
func (h handle) WriteEE(offset uint8, value uint16) Err {
|
||||
return Err(C.FT_WriteEE(h.toH(), C.DWORD(offset), C.WORD(value)))
|
||||
}
|
||||
|
||||
func (h handle) EEUASize() (int, Err) {
|
||||
var size C.DWORD
|
||||
if e := C.FT_EE_UASize(h.toH(), &size); e != 0 {
|
||||
return 0, Err(e)
|
||||
}
|
||||
return int(size), 0
|
||||
}
|
||||
|
||||
func (h handle) EEUARead(ua []byte) Err {
|
||||
var size C.DWORD
|
||||
if e := C.FT_EE_UARead(h.toH(), (*C.UCHAR)(unsafe.Pointer(&ua[0])), C.DWORD(len(ua)), &size); e != 0 {
|
||||
return Err(e)
|
||||
}
|
||||
if int(size) != len(ua) {
|
||||
return 6 // FT_INVALID_PARAMETER
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h handle) EEUAWrite(ua []byte) Err {
|
||||
if e := C.FT_EE_UAWrite(h.toH(), (*C.UCHAR)(&ua[0]), C.DWORD(len(ua))); e != 0 {
|
||||
return Err(e)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h handle) SetChars(eventChar byte, eventEn bool, errorChar byte, errorEn bool) Err {
|
||||
v := C.UCHAR(0)
|
||||
if eventEn {
|
||||
v = 1
|
||||
}
|
||||
w := C.UCHAR(0)
|
||||
if errorEn {
|
||||
w = 1
|
||||
}
|
||||
return Err(C.FT_SetChars(h.toH(), C.UCHAR(eventChar), v, C.UCHAR(errorChar), w))
|
||||
}
|
||||
|
||||
func (h handle) SetUSBParameters(in, out int) Err {
|
||||
return Err(C.FT_SetUSBParameters(h.toH(), C.DWORD(in), C.DWORD(out)))
|
||||
}
|
||||
|
||||
func (h handle) SetFlowControl() Err {
|
||||
return Err(C.FT_SetFlowControl(h.toH(), C.FT_FLOW_RTS_CTS, 0, 0))
|
||||
}
|
||||
|
||||
func (h handle) SetTimeouts(readMS, writeMS int) Err {
|
||||
return Err(C.FT_SetTimeouts(h.toH(), C.DWORD(readMS), C.DWORD(writeMS)))
|
||||
}
|
||||
|
||||
func (h handle) SetLatencyTimer(delayMS uint8) Err {
|
||||
return Err(C.FT_SetLatencyTimer(h.toH(), C.UCHAR(delayMS)))
|
||||
}
|
||||
|
||||
func (h handle) SetBaudRate(hz uint32) Err {
|
||||
return Err(C.FT_SetBaudRate(h.toH(), C.DWORD(hz)))
|
||||
}
|
||||
|
||||
func (h handle) GetQueueStatus() (uint32, Err) {
|
||||
var v C.DWORD
|
||||
e := C.FT_GetQueueStatus(h.toH(), &v)
|
||||
return uint32(v), Err(e)
|
||||
}
|
||||
|
||||
func (h handle) Read(b []byte) (int, Err) {
|
||||
var bytesRead C.DWORD
|
||||
e := C.FT_Read(h.toH(), C.LPVOID(unsafe.Pointer(&b[0])), C.DWORD(len(b)), &bytesRead)
|
||||
return int(bytesRead), Err(e)
|
||||
}
|
||||
|
||||
func (h handle) Write(b []byte) (int, Err) {
|
||||
var bytesSent C.DWORD
|
||||
e := C.FT_Write(h.toH(), C.LPVOID(unsafe.Pointer(&b[0])), C.DWORD(len(b)), &bytesSent)
|
||||
return int(bytesSent), Err(e)
|
||||
}
|
||||
|
||||
func (h handle) GetBitMode() (byte, Err) {
|
||||
var s C.UCHAR
|
||||
e := C.FT_GetBitMode(h.toH(), &s)
|
||||
return uint8(s), Err(e)
|
||||
}
|
||||
|
||||
func (h handle) SetBitMode(mask, mode byte) Err {
|
||||
return Err(C.FT_SetBitMode(h.toH(), C.UCHAR(mask), C.UCHAR(mode)))
|
||||
}
|
||||
|
||||
func (h handle) toH() C.FT_HANDLE {
|
||||
return C.FT_HANDLE(h)
|
||||
}
|
109
vendor/periph.io/x/d2xx/d2xx_posix_no_cgo.go
generated
vendored
109
vendor/periph.io/x/d2xx/d2xx_posix_no_cgo.go
generated
vendored
@ -1,109 +0,0 @@
|
||||
// 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 !cgo no_d2xx
|
||||
// +build !windows no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
// Available is true if the library is available on this system.
|
||||
const Available = false
|
||||
|
||||
// Library functions.
|
||||
|
||||
func version() (uint8, uint8, uint8) {
|
||||
return 0, 0, 0
|
||||
}
|
||||
|
||||
func createDeviceInfoList() (int, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func open(i int) (Handle, Err) {
|
||||
return handle(0), NoCGO
|
||||
}
|
||||
|
||||
func (h handle) Close() Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) ResetDevice() Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) GetDeviceInfo() (uint32, uint16, uint16, Err) {
|
||||
return unknown, 0, 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EEPROMRead(devType uint32, ee *EEPROM) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EEPROMProgram(e *EEPROM) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EraseEE() Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) WriteEE(offset uint8, value uint16) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EEUASize() (int, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EEUARead(ua []byte) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) EEUAWrite(ua []byte) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetChars(eventChar byte, eventEn bool, errorChar byte, errorEn bool) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetUSBParameters(in, out int) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetFlowControl() Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetTimeouts(readMS, writeMS int) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetLatencyTimer(delayMS uint8) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetBaudRate(hz uint32) Err {
|
||||
return NoCGO
|
||||
}
|
||||
|
||||
func (h handle) GetQueueStatus() (uint32, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) Read(b []byte) (int, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) Write(b []byte) (int, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) GetBitMode() (byte, Err) {
|
||||
return 0, NoCGO
|
||||
}
|
||||
|
||||
func (h handle) SetBitMode(mask, mode byte) Err {
|
||||
return NoCGO
|
||||
}
|
19
vendor/periph.io/x/d2xx/d2xx_posix_other.go
generated
vendored
19
vendor/periph.io/x/d2xx/d2xx_posix_other.go
generated
vendored
@ -1,19 +0,0 @@
|
||||
// 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 cgo
|
||||
// +build !darwin,!amd64
|
||||
// +build !linux,!amd64
|
||||
// +build !linux,!arm
|
||||
// +build !windows
|
||||
// +build !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
// This assumes the library is installed and available for linking.
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -lftd2xx
|
||||
*/
|
||||
import "C"
|
281
vendor/periph.io/x/d2xx/d2xx_windows.go
generated
vendored
281
vendor/periph.io/x/d2xx/d2xx_windows.go
generated
vendored
@ -1,281 +0,0 @@
|
||||
// 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 !no_d2xx
|
||||
|
||||
package d2xx
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Available is true if the library is available on this system.
|
||||
var Available = false
|
||||
|
||||
func version() (uint8, uint8, uint8) {
|
||||
var v uint32
|
||||
if pGetLibraryVersion != nil {
|
||||
_, _, _ = pGetLibraryVersion.Call(uintptr(unsafe.Pointer(&v)))
|
||||
}
|
||||
return uint8(v >> 16), uint8(v >> 8), uint8(v)
|
||||
}
|
||||
|
||||
func createDeviceInfoList() (int, Err) {
|
||||
if pCreateDeviceInfoList != nil {
|
||||
var num uint32
|
||||
r1, _, _ := pCreateDeviceInfoList.Call(uintptr(unsafe.Pointer(&num)))
|
||||
return int(num), Err(r1)
|
||||
}
|
||||
return 0, Missing
|
||||
}
|
||||
|
||||
func open(i int) (Handle, Err) {
|
||||
var h handle
|
||||
if pOpen != nil {
|
||||
r1, _, _ := pOpen.Call(uintptr(i), uintptr(unsafe.Pointer(&h)))
|
||||
return h, Err(r1)
|
||||
}
|
||||
return h, Missing
|
||||
}
|
||||
|
||||
func (h handle) Close() Err {
|
||||
r1, _, _ := pClose.Call(h.toH())
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) ResetDevice() Err {
|
||||
r1, _, _ := pResetDevice.Call(h.toH())
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) GetDeviceInfo() (uint32, uint16, uint16, Err) {
|
||||
var d uint32
|
||||
var id uint32
|
||||
if r1, _, _ := pGetDeviceInfo.Call(h.toH(), uintptr(unsafe.Pointer(&d)), uintptr(unsafe.Pointer(&id)), 0, 0, 0); r1 != 0 {
|
||||
return unknown, 0, 0, Err(r1)
|
||||
}
|
||||
return d, uint16(id >> 16), uint16(id), 0
|
||||
}
|
||||
|
||||
func (h handle) EEPROMRead(devType uint32, ee *EEPROM) Err {
|
||||
var manufacturer [64]byte
|
||||
var manufacturerID [64]byte
|
||||
var desc [64]byte
|
||||
var serial [64]byte
|
||||
// Shortcuts.
|
||||
m := uintptr(unsafe.Pointer(&manufacturer[0]))
|
||||
mi := uintptr(unsafe.Pointer(&manufacturerID[0]))
|
||||
de := uintptr(unsafe.Pointer(&desc[0]))
|
||||
s := uintptr(unsafe.Pointer(&serial[0]))
|
||||
|
||||
eepromVoid := unsafe.Pointer(&ee.Raw[0])
|
||||
hdr := ee.asHeader()
|
||||
// It MUST be set here. This is not always the case on posix.
|
||||
hdr.DeviceType = devType
|
||||
if r1, _, _ := pEEPROMRead.Call(h.toH(), uintptr(eepromVoid), uintptr(len(ee.Raw)), m, mi, de, s); r1 != 0 {
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
ee.Manufacturer = toStr(manufacturer[:])
|
||||
ee.ManufacturerID = toStr(manufacturerID[:])
|
||||
ee.Desc = toStr(desc[:])
|
||||
ee.Serial = toStr(serial[:])
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h handle) EEPROMProgram(ee *EEPROM) Err {
|
||||
var cmanu [64]byte
|
||||
copy(cmanu[:], ee.Manufacturer)
|
||||
var cmanuID [64]byte
|
||||
copy(cmanuID[:], ee.ManufacturerID)
|
||||
var cdesc [64]byte
|
||||
copy(cdesc[:], ee.Desc)
|
||||
var cserial [64]byte
|
||||
copy(cserial[:], ee.Serial)
|
||||
r1, _, _ := pEEPROMProgram.Call(h.toH(), uintptr(unsafe.Pointer(&ee.Raw[0])), uintptr(len(ee.Raw)), uintptr(unsafe.Pointer(&cmanu[0])), uintptr(unsafe.Pointer(&cmanuID[0])), uintptr(unsafe.Pointer(&cdesc[0])), uintptr(unsafe.Pointer(&cserial[0])))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) EraseEE() Err {
|
||||
r1, _, _ := pEraseEE.Call(h.toH())
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) WriteEE(offset uint8, value uint16) Err {
|
||||
r1, _, _ := pWriteEE.Call(h.toH(), uintptr(offset), uintptr(value))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) EEUASize() (int, Err) {
|
||||
var size uint32
|
||||
if r1, _, _ := pEEUASize.Call(h.toH(), uintptr(unsafe.Pointer(&size))); r1 != 0 {
|
||||
return 0, Err(r1)
|
||||
}
|
||||
return int(size), 0
|
||||
}
|
||||
|
||||
func (h handle) EEUARead(ua []byte) Err {
|
||||
var size uint32
|
||||
if r1, _, _ := pEEUARead.Call(h.toH(), uintptr(unsafe.Pointer(&ua[0])), uintptr(len(ua)), uintptr(unsafe.Pointer(&size))); r1 != 0 {
|
||||
return Err(r1)
|
||||
}
|
||||
if int(size) != len(ua) {
|
||||
return 6 // FT_INVALID_PARAMETER
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h handle) EEUAWrite(ua []byte) Err {
|
||||
r1, _, _ := pEEUAWrite.Call(h.toH(), uintptr(unsafe.Pointer(&ua[0])), uintptr(len(ua)))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetChars(eventChar byte, eventEn bool, errorChar byte, errorEn bool) Err {
|
||||
v := uintptr(0)
|
||||
if eventEn {
|
||||
v = 1
|
||||
}
|
||||
w := uintptr(0)
|
||||
if errorEn {
|
||||
w = 1
|
||||
}
|
||||
r1, _, _ := pSetChars.Call(h.toH(), uintptr(eventChar), v, uintptr(errorChar), w)
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetUSBParameters(in, out int) Err {
|
||||
r1, _, _ := pSetUSBParameters.Call(h.toH(), uintptr(in), uintptr(out))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetFlowControl() Err {
|
||||
// FT_FLOW_RTS_CTS
|
||||
r1, _, _ := pSetFlowControl.Call(h.toH(), 0x0100, 0, 0)
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetTimeouts(readMS, writeMS int) Err {
|
||||
r1, _, _ := pSetTimeouts.Call(h.toH(), uintptr(readMS), uintptr(writeMS))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetLatencyTimer(delayMS uint8) Err {
|
||||
r1, _, _ := pSetLatencyTimer.Call(h.toH(), uintptr(delayMS))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetBaudRate(hz uint32) Err {
|
||||
r1, _, _ := pSetBaudRate.Call(h.toH(), uintptr(hz))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) GetQueueStatus() (uint32, Err) {
|
||||
var v uint32
|
||||
r1, _, _ := pGetQueueStatus.Call(h.toH(), uintptr(unsafe.Pointer(&v)))
|
||||
return v, Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) Read(b []byte) (int, Err) {
|
||||
var bytesRead uint32
|
||||
r1, _, _ := pRead.Call(h.toH(), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(unsafe.Pointer(&bytesRead)))
|
||||
return int(bytesRead), Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) Write(b []byte) (int, Err) {
|
||||
var bytesSent uint32
|
||||
r1, _, _ := pWrite.Call(h.toH(), uintptr(unsafe.Pointer(&b[0])), uintptr(len(b)), uintptr(unsafe.Pointer(&bytesSent)))
|
||||
return int(bytesSent), Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) GetBitMode() (byte, Err) {
|
||||
var s uint8
|
||||
r1, _, _ := pGetBitMode.Call(h.toH(), uintptr(unsafe.Pointer(&s)))
|
||||
return s, Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) SetBitMode(mask, mode byte) Err {
|
||||
r1, _, _ := pSetBitMode.Call(h.toH(), uintptr(mask), uintptr(mode))
|
||||
return Err(r1)
|
||||
}
|
||||
|
||||
func (h handle) toH() uintptr {
|
||||
return uintptr(h)
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var (
|
||||
pClose *syscall.Proc
|
||||
pCreateDeviceInfoList *syscall.Proc
|
||||
pEEPROMRead *syscall.Proc
|
||||
pEEPROMProgram *syscall.Proc
|
||||
pEraseEE *syscall.Proc
|
||||
pWriteEE *syscall.Proc
|
||||
pEEUASize *syscall.Proc
|
||||
pEEUARead *syscall.Proc
|
||||
pEEUAWrite *syscall.Proc
|
||||
pGetBitMode *syscall.Proc
|
||||
pGetDeviceInfo *syscall.Proc
|
||||
pGetLibraryVersion *syscall.Proc
|
||||
pGetQueueStatus *syscall.Proc
|
||||
pOpen *syscall.Proc
|
||||
pRead *syscall.Proc
|
||||
pResetDevice *syscall.Proc
|
||||
pSetBaudRate *syscall.Proc
|
||||
pSetBitMode *syscall.Proc
|
||||
pSetChars *syscall.Proc
|
||||
pSetFlowControl *syscall.Proc
|
||||
pSetLatencyTimer *syscall.Proc
|
||||
pSetTimeouts *syscall.Proc
|
||||
pSetUSBParameters *syscall.Proc
|
||||
pWrite *syscall.Proc
|
||||
)
|
||||
|
||||
func init() {
|
||||
if dll, _ := syscall.LoadDLL("ftd2xx.dll"); dll != nil {
|
||||
// If any function is not found, disable the support.
|
||||
Available = true
|
||||
find := func(n string) *syscall.Proc {
|
||||
s, _ := dll.FindProc(n)
|
||||
if s == nil {
|
||||
Available = false
|
||||
}
|
||||
return s
|
||||
}
|
||||
pClose = find("FT_Close")
|
||||
pCreateDeviceInfoList = find("FT_CreateDeviceInfoList")
|
||||
pEEPROMRead = find("FT_EEPROM_Read")
|
||||
pEEPROMProgram = find("FT_EEPROM_Program")
|
||||
pEraseEE = find("FT_EraseEE")
|
||||
pWriteEE = find("FT_WriteEE")
|
||||
pEEUASize = find("FT_EE_UASize")
|
||||
pEEUARead = find("FT_EE_UARead")
|
||||
pEEUAWrite = find("FT_EE_UAWrite")
|
||||
pGetBitMode = find("FT_GetBitMode")
|
||||
pGetDeviceInfo = find("FT_GetDeviceInfo")
|
||||
pGetLibraryVersion = find("FT_GetLibraryVersion")
|
||||
pGetQueueStatus = find("FT_GetQueueStatus")
|
||||
pOpen = find("FT_Open")
|
||||
pRead = find("FT_Read")
|
||||
pResetDevice = find("FT_ResetDevice")
|
||||
pSetBaudRate = find("FT_SetBaudRate")
|
||||
pSetBitMode = find("FT_SetBitMode")
|
||||
pSetChars = find("FT_SetChars")
|
||||
pSetFlowControl = find("FT_SetFlowControl")
|
||||
pSetLatencyTimer = find("FT_SetLatencyTimer")
|
||||
pSetTimeouts = find("FT_SetTimeouts")
|
||||
pSetUSBParameters = find("FT_SetUSBParameters")
|
||||
pWrite = find("FT_Write")
|
||||
}
|
||||
}
|
||||
|
||||
func toStr(c []byte) string {
|
||||
i := bytes.IndexByte(c, 0)
|
||||
if i != -1 {
|
||||
return string(c[:i])
|
||||
}
|
||||
return string(c)
|
||||
}
|
18
vendor/periph.io/x/d2xx/doc.go
generated
vendored
18
vendor/periph.io/x/d2xx/doc.go
generated
vendored
@ -1,18 +0,0 @@
|
||||
// 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 d2xx is a thin Go wrapper for the Future Technology "D2XX" driver.
|
||||
//
|
||||
// This package is not Go idiomatic. You want to use
|
||||
// https://periph.io/x/host/v3/ftdi (or later) instead.
|
||||
//
|
||||
// A static library of the d2xx driver is included for linux and macOS. They are
|
||||
// from https://ftdichip.com/drivers/d2xx-drivers/. See third_party/README.md
|
||||
// for more details.
|
||||
//
|
||||
// Configuration
|
||||
//
|
||||
// See https://periph.io/device/ftdi/ for more details, and how to configure
|
||||
// the host to be able to use this driver.
|
||||
package d2xx
|
39
vendor/periph.io/x/d2xx/eeprom.go
generated
vendored
39
vendor/periph.io/x/d2xx/eeprom.go
generated
vendored
@ -1,39 +0,0 @@
|
||||
// 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 d2xx
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// EEPROM is the unprocessed EEPROM content.
|
||||
//
|
||||
// The EEPROM is in 3 parts: the defined struct, the 4 strings and the rest
|
||||
// which is used as an 'user area'. The size of the user area depends on the
|
||||
// length of the strings. The user area content is not included in this struct.
|
||||
type EEPROM struct {
|
||||
// Raw is the raw EEPROM content. It excludes the strings.
|
||||
Raw []byte
|
||||
|
||||
// The following condition must be true: len(Manufacturer) + len(Desc) <= 40.
|
||||
Manufacturer string
|
||||
ManufacturerID string
|
||||
Desc string
|
||||
Serial string
|
||||
}
|
||||
|
||||
func (e *EEPROM) asHeader() *eepromHeader {
|
||||
// sizeof(EEPROMHeader)
|
||||
if len(e.Raw) < 16 {
|
||||
return nil
|
||||
}
|
||||
return (*eepromHeader)(unsafe.Pointer(&e.Raw[0]))
|
||||
}
|
||||
|
||||
// eepromHeader is the common 16 bytes header.
|
||||
type eepromHeader struct {
|
||||
DeviceType uint32
|
||||
// The rest is not necessary here so it is skipped.
|
||||
}
|
43
vendor/periph.io/x/d2xx/test.sh
generated
vendored
43
vendor/periph.io/x/d2xx/test.sh
generated
vendored
@ -1,43 +0,0 @@
|
||||
#!/bin/bash
|
||||
# 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.
|
||||
|
||||
# Builds the package on multiple OSes to confirm it builds fine.
|
||||
|
||||
set -eu
|
||||
|
||||
cd `dirname $0`
|
||||
|
||||
OPT=$*
|
||||
|
||||
# Do not set CGO_ENABLED, as we want the default behavior when cross compiling,
|
||||
# which is different from when CGO_ENABLED=1.
|
||||
export -n CGO_ENABLED
|
||||
|
||||
# Cleanup.
|
||||
export -n GOOS
|
||||
export -n GOARCH
|
||||
|
||||
function build {
|
||||
export GOOS=$1
|
||||
export GOARCH=$2
|
||||
echo "Building on $GOOS/$GOARCH"
|
||||
go build $OPT
|
||||
echo "Building on $GOOS/$GOARCH - no_d2xx"
|
||||
go build -tags no_d2xx $OPT
|
||||
echo "Building on $GOOS/$GOARCH - no cgo"
|
||||
CGO_ENABLED=0 go build $OPT
|
||||
echo "Building on $GOOS/$GOARCH - no cgo, no_d2xx"
|
||||
CGO_ENABLED=0 go build -tags no_d2xx $OPT
|
||||
}
|
||||
|
||||
CGO_ENABLED=1 CC=x86_64-linux-gnu-gcc build linux amd64
|
||||
# Requires: sudo apt install gcc-arm-linux-gnueabihf
|
||||
CGO_ENABLED=1 CC=arm-linux-gnueabihf-gcc build linux arm
|
||||
# Requires: sudo apt install gcc-aarch64-linux-gnu
|
||||
CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc build linux arm64
|
||||
|
||||
build linux 386
|
||||
build windows amd64
|
||||
build darwin amd64
|
285
vendor/periph.io/x/host/v3/.gohci.yml
generated
vendored
285
vendor/periph.io/x/host/v3/.gohci.yml
generated
vendored
@ -17,44 +17,61 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -63,7 +80,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -93,44 +109,61 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -140,7 +173,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -183,44 +215,61 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -230,7 +279,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -277,6 +325,11 @@ workers:
|
||||
- periph-smoketest
|
||||
- bcm283x
|
||||
- -quick
|
||||
- cmd:
|
||||
- periph-smoketest
|
||||
- ftdi
|
||||
- -type
|
||||
- ft232h
|
||||
|
||||
# Old MacBook Pro on 10.9.
|
||||
- name: mbp
|
||||
@ -289,44 +342,61 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -336,7 +406,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -349,11 +418,11 @@ workers:
|
||||
- i2c-list
|
||||
- cmd:
|
||||
- spi-list
|
||||
# - cmd:
|
||||
# - periph-smoketest
|
||||
# - ftdi
|
||||
# - -type
|
||||
# - ft232r
|
||||
- cmd:
|
||||
- periph-smoketest
|
||||
- ftdi
|
||||
- -type
|
||||
- ft232r
|
||||
|
||||
# Laptop on Windows 10.
|
||||
- name: win10
|
||||
@ -366,44 +435,61 @@ workers:
|
||||
- -benchtime=1000ms
|
||||
- -benchmem
|
||||
- ./...
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: devices
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/devices
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../devices
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../devices
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../devices
|
||||
# Test in advance.
|
||||
- cmd:
|
||||
# Test in advance: cmd
|
||||
- dir: ..
|
||||
cmd:
|
||||
- git
|
||||
- clone
|
||||
- --depth
|
||||
- 1
|
||||
- https://github.com/periph/cmd
|
||||
dir: ..
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- mod
|
||||
- edit
|
||||
- -replace=periph.io/x/host/v3=../host
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- get
|
||||
- periph.io/x/host/v3@${GIT_SHA}
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- -t
|
||||
- ./...
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- test
|
||||
- -short
|
||||
- ./...
|
||||
dir: ../cmd
|
||||
# Test commands.
|
||||
- cmd:
|
||||
- dir: ../cmd
|
||||
cmd:
|
||||
- go
|
||||
- install
|
||||
- -v
|
||||
@ -413,7 +499,6 @@ workers:
|
||||
- ./periph-info
|
||||
- ./periph-smoketest
|
||||
- ./spi-list
|
||||
dir: ../cmd
|
||||
- cmd:
|
||||
- periph-info
|
||||
- cmd:
|
||||
@ -426,8 +511,8 @@ workers:
|
||||
- i2c-list
|
||||
- cmd:
|
||||
- spi-list
|
||||
# - cmd:
|
||||
# - periph-smoketest
|
||||
# - ftdi
|
||||
# - -type
|
||||
# - ft232h
|
||||
- cmd:
|
||||
- periph-smoketest
|
||||
- ftdi
|
||||
- -type
|
||||
- ft232h
|
||||
|
3
vendor/periph.io/x/host/v3/README.md
generated
vendored
3
vendor/periph.io/x/host/v3/README.md
generated
vendored
@ -9,8 +9,7 @@ get an [invite here](https://invite.slack.golangbridge.org/).
|
||||
[](https://periph.io/)
|
||||
|
||||
[](https://pkg.go.dev/periph.io/x/host/v3)
|
||||
[](https://codecov.io/gh/periph/host)
|
||||
[](https://codecov.io/gh/periph/host)
|
||||
|
||||
|
||||
## Example
|
||||
|
1
vendor/periph.io/x/host/v3/allwinner/allwinner_arm64.go
generated
vendored
1
vendor/periph.io/x/host/v3/allwinner/allwinner_arm64.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package allwinner
|
||||
|
1
vendor/periph.io/x/host/v3/allwinner/allwinner_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/allwinner/allwinner_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm && !arm64
|
||||
// +build !arm,!arm64
|
||||
|
||||
package allwinner
|
||||
|
1
vendor/periph.io/x/host/v3/am335x/am335x_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/am335x/am335x_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package am335x
|
||||
|
1
vendor/periph.io/x/host/v3/bcm283x/bcm283x_arm64.go
generated
vendored
1
vendor/periph.io/x/host/v3/bcm283x/bcm283x_arm64.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package bcm283x
|
||||
|
1
vendor/periph.io/x/host/v3/bcm283x/bcm283x_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/bcm283x/bcm283x_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm && !arm64
|
||||
// +build !arm,!arm64
|
||||
|
||||
package bcm283x
|
||||
|
14
vendor/periph.io/x/host/v3/bcm283x/gpio.go
generated
vendored
14
vendor/periph.io/x/host/v3/bcm283x/gpio.go
generated
vendored
@ -406,8 +406,8 @@ func (p *Pin) In(pull gpio.Pull, edge gpio.Edge) error {
|
||||
// https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
|
||||
// page 101.
|
||||
// However, BCM2711 uses a simpler way of setting pull resistors, reference at
|
||||
// https://github.com/raspberrypi/documentation/blob/master/hardware/raspberrypi/bcm2711/rpi_DATA_2711_1p0.pdf
|
||||
// page 84 and 95 ~ 98.
|
||||
// https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf
|
||||
// page 65 and 73 ~ 76.
|
||||
|
||||
// If we are running on a newer chip such as BCM2711, set Pull directly.
|
||||
if !drvGPIO.useLegacyPull {
|
||||
@ -431,7 +431,10 @@ func (p *Pin) In(pull gpio.Pull, edge gpio.Edge) error {
|
||||
case gpio.Float:
|
||||
pullState = 0
|
||||
}
|
||||
drvGPIO.gpioMemory.pullRegister[offset] = pullState << uint((p.number%16)<<1)
|
||||
|
||||
bitOffset := 2 * uint(p.number%16)
|
||||
previous := drvGPIO.gpioMemory.pullRegister[offset] & ^(3 << bitOffset)
|
||||
drvGPIO.gpioMemory.pullRegister[offset] = previous | (pullState << bitOffset)
|
||||
} else {
|
||||
// Set Pull
|
||||
switch pull {
|
||||
@ -1024,9 +1027,8 @@ type function uint8
|
||||
// Mapping as
|
||||
// https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
|
||||
// pages 90-91.
|
||||
// And
|
||||
// https://github.com/raspberrypi/documentation/blob/master/hardware/raspberrypi/bcm2711/rpi_DATA_2711_1p0.pdf
|
||||
// pages 83-84.
|
||||
// And https://datasheets.raspberrypi.org/bcm2711/bcm2711-peripherals.pdf pages
|
||||
// 65 and 73 ~ 76.
|
||||
type gpioMap struct {
|
||||
// 0x00 RW GPIO Function Select 0 (GPIO0-9)
|
||||
// 0x04 RW GPIO Function Select 1 (GPIO10-19)
|
||||
|
1
vendor/periph.io/x/host/v3/beagle/black/black_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/beagle/black/black_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package black
|
||||
|
1
vendor/periph.io/x/host/v3/beagle/bone/bone_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/beagle/bone/bone_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package bone
|
||||
|
1
vendor/periph.io/x/host/v3/beagle/green/green_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/beagle/green/green_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package green
|
||||
|
1
vendor/periph.io/x/host/v3/chip/chip_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/chip/chip_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package chip
|
||||
|
1
vendor/periph.io/x/host/v3/cpu/cpu_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/cpu/cpu_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package cpu
|
||||
|
1
vendor/periph.io/x/host/v3/distro/distro_arm64.go
generated
vendored
1
vendor/periph.io/x/host/v3/distro/distro_arm64.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package distro
|
||||
|
1
vendor/periph.io/x/host/v3/distro/distro_nonarm.go
generated
vendored
1
vendor/periph.io/x/host/v3/distro/distro_nonarm.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm && !arm64
|
||||
// +build !arm,!arm64
|
||||
|
||||
package distro
|
||||
|
1
vendor/periph.io/x/host/v3/distro/distro_nonlinux.go
generated
vendored
1
vendor/periph.io/x/host/v3/distro/distro_nonlinux.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package distro
|
||||
|
1
vendor/periph.io/x/host/v3/fs/fs_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/fs/fs_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package fs
|
||||
|
1
vendor/periph.io/x/host/v3/fs/ioctl_mips_like.go
generated
vendored
1
vendor/periph.io/x/host/v3/fs/ioctl_mips_like.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build mips || mipsle
|
||||
// +build mips mipsle
|
||||
|
||||
package fs
|
||||
|
1
vendor/periph.io/x/host/v3/fs/ioctl_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/fs/ioctl_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !mips && !mipsle
|
||||
// +build !mips,!mipsle
|
||||
|
||||
package fs
|
||||
|
878
vendor/periph.io/x/host/v3/ftdi/dev.go
generated
vendored
878
vendor/periph.io/x/host/v3/ftdi/dev.go
generated
vendored
@ -1,878 +0,0 @@
|
||||
// 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 ftdi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"periph.io/x/conn/v3"
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/i2c"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
"periph.io/x/conn/v3/spi"
|
||||
)
|
||||
|
||||
// Info is the information gathered about the connected FTDI device.
|
||||
//
|
||||
// The data is gathered from the USB descriptor.
|
||||
type Info struct {
|
||||
// Opened is true if the device was successfully opened.
|
||||
Opened bool
|
||||
// Type is the FTDI device type.
|
||||
//
|
||||
// The value can be "FT232H", "FT232R", etc.
|
||||
//
|
||||
// An empty string means the type is unknown.
|
||||
Type string
|
||||
// VenID is the vendor ID from the USB descriptor information. It is expected
|
||||
// to be 0x0403 (FTDI).
|
||||
VenID uint16
|
||||
// DevID is the product ID from the USB descriptor information. It is
|
||||
// expected to be one of 0x6001, 0x6006, 0x6010, 0x6014.
|
||||
DevID uint16
|
||||
}
|
||||
|
||||
// Dev represents one FTDI device.
|
||||
//
|
||||
// There can be multiple FTDI devices connected to a host.
|
||||
//
|
||||
// The device may also export one or multiple of I²C, SPI buses. You need to
|
||||
// either cast into the right hardware, but more simply use the i2creg / spireg
|
||||
// bus/port registries.
|
||||
type Dev interface {
|
||||
// conn.Resource
|
||||
String() string
|
||||
Halt() error
|
||||
|
||||
// Info returns information about an opened device.
|
||||
Info(i *Info)
|
||||
|
||||
// Header returns the GPIO pins exposed on the chip.
|
||||
Header() []gpio.PinIO
|
||||
|
||||
// SetSpeed sets the base clock for all I/O transactions.
|
||||
//
|
||||
// The device defaults to its fastest speed.
|
||||
SetSpeed(f physic.Frequency) error
|
||||
|
||||
// EEPROM returns the EEPROM content.
|
||||
EEPROM(ee *EEPROM) error
|
||||
// WriteEEPROM updates the EEPROM. Must be used carefully.
|
||||
WriteEEPROM(ee *EEPROM) error
|
||||
// EraseEEPROM erases the EEPROM. Must be used carefully.
|
||||
EraseEEPROM() error
|
||||
// UserArea reads and return the EEPROM part that can be used to stored user
|
||||
// defined values.
|
||||
UserArea() ([]byte, error)
|
||||
// WriteUserArea updates the user area in the EEPROM.
|
||||
//
|
||||
// If the length of ua is less than the available space, is it zero extended.
|
||||
WriteUserArea(ua []byte) error
|
||||
}
|
||||
|
||||
// broken represents a device that couldn't be opened correctly.
|
||||
//
|
||||
// It returns an error message to help the user diagnose issues.
|
||||
type broken struct {
|
||||
index int
|
||||
err error
|
||||
name string
|
||||
}
|
||||
|
||||
func (b *broken) String() string {
|
||||
return b.name
|
||||
}
|
||||
|
||||
func (b *broken) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *broken) Info(i *Info) {
|
||||
i.Opened = false
|
||||
}
|
||||
|
||||
func (b *broken) Header() []gpio.PinIO {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *broken) SetSpeed(f physic.Frequency) error {
|
||||
return b.err
|
||||
}
|
||||
|
||||
func (b *broken) EEPROM(ee *EEPROM) error {
|
||||
return b.err
|
||||
}
|
||||
|
||||
func (b *broken) WriteEEPROM(ee *EEPROM) error {
|
||||
return b.err
|
||||
}
|
||||
|
||||
func (b *broken) EraseEEPROM() error {
|
||||
return b.err
|
||||
}
|
||||
|
||||
func (b *broken) UserArea() ([]byte, error) {
|
||||
return nil, b.err
|
||||
}
|
||||
|
||||
func (b *broken) WriteUserArea(ua []byte) error {
|
||||
return b.err
|
||||
}
|
||||
|
||||
// generic represents a generic FTDI device.
|
||||
//
|
||||
// It is used for the models that this package doesn't fully support yet.
|
||||
type generic struct {
|
||||
// Immutable after initialization.
|
||||
index int
|
||||
h *handle
|
||||
name string
|
||||
}
|
||||
|
||||
func (f *generic) String() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
// Halt implements conn.Resource.
|
||||
//
|
||||
// This halts all operations going through this device.
|
||||
func (f *generic) Halt() error {
|
||||
return f.h.Reset()
|
||||
}
|
||||
|
||||
// Info returns information about an opened device.
|
||||
func (f *generic) Info(i *Info) {
|
||||
i.Opened = true
|
||||
i.Type = f.h.t.String()
|
||||
i.VenID = f.h.venID
|
||||
i.DevID = f.h.devID
|
||||
}
|
||||
|
||||
// Header returns the GPIO pins exposed on the chip.
|
||||
func (f *generic) Header() []gpio.PinIO {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *generic) SetSpeed(freq physic.Frequency) error {
|
||||
// TODO(maruel): Doc says the actual speed is 16x, confirm.
|
||||
return f.h.SetBaudRate(freq)
|
||||
}
|
||||
|
||||
func (f *generic) EEPROM(ee *EEPROM) error {
|
||||
return f.h.ReadEEPROM(ee)
|
||||
/*
|
||||
if f.ee.Raw == nil {
|
||||
if err := f.h.readEEPROM(&f.ee); err != nil {
|
||||
return nil
|
||||
}
|
||||
if f.ee.Raw == nil {
|
||||
// It's a fresh new device. Devices bought via Adafruit already have
|
||||
// their EEPROM programmed with Adafruit branding but devices sold by
|
||||
// CJMCU are not. Since d2xxGetDeviceInfo() above succeeded, we know the
|
||||
// device type via the USB descriptor, which is sufficient to load the
|
||||
// driver, which permits to program the EEPROM to "bootstrap" it.
|
||||
f.ee.Raw = []byte{}
|
||||
}
|
||||
}
|
||||
*ee = f.ee
|
||||
return nil
|
||||
*/
|
||||
}
|
||||
|
||||
func (f *generic) WriteEEPROM(ee *EEPROM) error {
|
||||
// TODO(maruel): Compare with the cached EEPROM, and only update the
|
||||
// different values if needed so reduce the EEPROM wear.
|
||||
// f.h.h.d2xxWriteEE()
|
||||
return f.h.WriteEEPROM(ee)
|
||||
}
|
||||
|
||||
func (f *generic) EraseEEPROM() error {
|
||||
return f.h.EraseEEPROM()
|
||||
}
|
||||
|
||||
func (f *generic) UserArea() ([]byte, error) {
|
||||
return f.h.ReadUA()
|
||||
}
|
||||
|
||||
func (f *generic) WriteUserArea(ua []byte) error {
|
||||
return f.h.WriteUA(ua)
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func newFT232H(g generic) (*FT232H, error) {
|
||||
f := &FT232H{
|
||||
generic: g,
|
||||
cbus: gpiosMPSSE{h: g.h, cbus: true},
|
||||
dbus: gpiosMPSSE{h: g.h},
|
||||
c8: invalidPin{num: 16, n: g.name + ".C8"}, // , dp: gpio.PullUp
|
||||
c9: invalidPin{num: 17, n: g.name + ".C9"}, // , dp: gpio.PullUp
|
||||
}
|
||||
f.cbus.init(f.name)
|
||||
f.dbus.init(f.name)
|
||||
|
||||
for i := range f.dbus.pins {
|
||||
f.hdr[i] = &f.dbus.pins[i]
|
||||
}
|
||||
for i := range f.cbus.pins {
|
||||
f.hdr[i+8] = &f.cbus.pins[i]
|
||||
}
|
||||
// TODO(maruel): C8 and C9 can be used when their mux in the EEPROM is set to
|
||||
// ft232hCBusIOMode.
|
||||
f.hdr[16] = &f.c8
|
||||
f.hdr[17] = &f.c9
|
||||
f.D0 = f.hdr[0]
|
||||
f.D1 = f.hdr[1]
|
||||
f.D2 = f.hdr[2]
|
||||
f.D3 = f.hdr[3]
|
||||
f.D4 = f.hdr[4]
|
||||
f.D5 = f.hdr[5]
|
||||
f.D6 = f.hdr[6]
|
||||
f.D7 = f.hdr[7]
|
||||
f.C0 = f.hdr[8]
|
||||
f.C1 = f.hdr[9]
|
||||
f.C2 = f.hdr[10]
|
||||
f.C3 = f.hdr[11]
|
||||
f.C4 = f.hdr[12]
|
||||
f.C5 = f.hdr[13]
|
||||
f.C6 = f.hdr[14]
|
||||
f.C7 = f.hdr[15]
|
||||
f.C8 = f.hdr[16]
|
||||
f.C9 = f.hdr[17]
|
||||
|
||||
// This function forces all pins as inputs.
|
||||
if err := f.h.InitMPSSE(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.s.c.f = f
|
||||
f.i.f = f
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// FT232H represents a FT232H device.
|
||||
//
|
||||
// It implements Dev.
|
||||
//
|
||||
// The FT232H has 1024 bytes output buffer and 1024 bytes input buffer. It
|
||||
// supports 512 bytes USB packets.
|
||||
//
|
||||
// The device can be used in a few different modes, two modes are supported:
|
||||
//
|
||||
// - D0~D3 as a serial protocol (MPSEE), supporting I²C and SPI (and eventually
|
||||
// UART), In this mode, D4~D7 and C0~C7 can be used as synchronized GPIO.
|
||||
//
|
||||
// - D0~D7 as a synchronous 8 bits bit-bang port. In this mode, only a few pins
|
||||
// on CBus are usable in slow mode.
|
||||
//
|
||||
// Each group of pins D0~D7 and C0~C7 can be changed at once in one pass via
|
||||
// DBus() or CBus().
|
||||
//
|
||||
// This enables usage as an 8 bit parallel port.
|
||||
//
|
||||
// Pins C8 and C9 can only be used in 'slow' mode via EEPROM and are currently
|
||||
// not implemented.
|
||||
//
|
||||
// Datasheet
|
||||
//
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232H.pdf
|
||||
type FT232H struct {
|
||||
generic
|
||||
|
||||
D0 gpio.PinIO // Clock output
|
||||
D1 gpio.PinIO // Data out
|
||||
D2 gpio.PinIO // Data in
|
||||
D3 gpio.PinIO // Chip select
|
||||
D4 gpio.PinIO
|
||||
D5 gpio.PinIO
|
||||
D6 gpio.PinIO
|
||||
D7 gpio.PinIO
|
||||
C0 gpio.PinIO
|
||||
C1 gpio.PinIO
|
||||
C2 gpio.PinIO
|
||||
C3 gpio.PinIO
|
||||
C4 gpio.PinIO
|
||||
C5 gpio.PinIO
|
||||
C6 gpio.PinIO
|
||||
C7 gpio.PinIO
|
||||
C8 gpio.PinIO // Not implemented
|
||||
C9 gpio.PinIO // Not implemented
|
||||
|
||||
hdr [18]gpio.PinIO
|
||||
cbus gpiosMPSSE
|
||||
dbus gpiosMPSSE
|
||||
c8 invalidPin // gpio.PullUp
|
||||
c9 invalidPin // gpio.PullUp
|
||||
|
||||
mu sync.Mutex
|
||||
usingI2C bool
|
||||
usingSPI bool
|
||||
i i2cBus
|
||||
s spiMPSEEPort
|
||||
// TODO(maruel): Technically speaking, a SPI port could be hacked up too in
|
||||
// sync bit-bang but there's less point when MPSEE is available.
|
||||
}
|
||||
|
||||
// Header returns the GPIO pins exposed on the chip.
|
||||
func (f *FT232H) Header() []gpio.PinIO {
|
||||
out := make([]gpio.PinIO, len(f.hdr))
|
||||
copy(out, f.hdr[:])
|
||||
return out
|
||||
}
|
||||
|
||||
func (f *FT232H) SetSpeed(freq physic.Frequency) error {
|
||||
// TODO(maruel): When using MPSEE, use the MPSEE command. If using sync
|
||||
// bit-bang, use SetBaudRate().
|
||||
|
||||
// TODO(maruel): Doc says the actual speed is 16x, confirm.
|
||||
return f.h.SetBaudRate(freq)
|
||||
}
|
||||
|
||||
// CBus sets the values of C0 to C7 in the specified direction and value.
|
||||
//
|
||||
// 0 direction means input, 1 means output.
|
||||
func (f *FT232H) CBus(direction, value byte) error {
|
||||
return f.h.MPSSECBus(direction, value)
|
||||
}
|
||||
|
||||
// DBus sets the values of D0 to d7 in the specified direction and value.
|
||||
//
|
||||
// 0 direction means input, 1 means output.
|
||||
//
|
||||
// This function must be used to set Clock idle level.
|
||||
func (f *FT232H) DBus(direction, value byte) error {
|
||||
return f.h.MPSSEDBus(direction, value)
|
||||
}
|
||||
|
||||
// CBusRead reads the values of C0 to C7.
|
||||
func (f *FT232H) CBusRead() (byte, error) {
|
||||
return f.h.MPSSECBusRead()
|
||||
}
|
||||
|
||||
// DBusRead reads the values of D0 to D7.
|
||||
func (f *FT232H) DBusRead() (byte, error) {
|
||||
return f.h.MPSSEDBusRead()
|
||||
}
|
||||
|
||||
// I2C returns an I²C bus over the AD bus.
|
||||
//
|
||||
// pull can be either gpio.PullUp or gpio.Float. The recommended pull up
|
||||
// resistors are 10kΩ for 100kHz and 2kΩ for 400kHz when using Float. The
|
||||
// GPIO's pull up is 75kΩ, which may require using a lower speed for signal
|
||||
// reliability. Optimal pull up resistor calculation depends on the capacitance.
|
||||
//
|
||||
// It uses D0, D1 and D2.
|
||||
//
|
||||
// D0 is SCL. It must to be pulled up externally.
|
||||
//
|
||||
// D1 and D2 are used for SDA. D1 is the output using open drain, D2 is the
|
||||
// input. D1 and D2 must be wired together and must be pulled up externally.
|
||||
//
|
||||
// It is recommended to set the mode to ‘245 FIFO’ in the EEPROM of the FT232H.
|
||||
//
|
||||
// The FIFO mode is recommended because it allows the ADbus lines to start as
|
||||
// tristate. If the chip starts in the default UART mode, then the ADbus lines
|
||||
// will be in the default UART idle states until the application opens the port
|
||||
// and configures it as MPSSE. Care should also be taken that the RD# input on
|
||||
// ACBUS is not asserted in this initial state as this can cause the FIFO lines
|
||||
// to drive out.
|
||||
func (f *FT232H) I2C(pull gpio.Pull) (i2c.BusCloser, error) {
|
||||
if pull != gpio.PullUp && pull != gpio.Float {
|
||||
return nil, errors.New("d2xx: I²C pull can only be PullUp or Float")
|
||||
}
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingI2C {
|
||||
return nil, errors.New("d2xx: already using I²C")
|
||||
}
|
||||
if f.usingSPI {
|
||||
return nil, errors.New("d2xx: already using SPI")
|
||||
}
|
||||
if err := f.i.setupI2C(pull == gpio.PullUp); err != nil {
|
||||
_ = f.i.stopI2C()
|
||||
return nil, err
|
||||
}
|
||||
return &f.i, nil
|
||||
}
|
||||
|
||||
// SPI returns a SPI port over the AD bus.
|
||||
//
|
||||
// It uses D0, D1, D2 and D3. D0 is the clock, D1 the output (MOSI), D2 is the
|
||||
// input (MISO) and D3 is CS line.
|
||||
func (f *FT232H) SPI() (spi.PortCloser, error) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingI2C {
|
||||
return nil, errors.New("d2xx: already using I²C")
|
||||
}
|
||||
if f.usingSPI {
|
||||
return nil, errors.New("d2xx: already using SPI")
|
||||
}
|
||||
// Don't mark it as being used yet. It only become used once Connect() is
|
||||
// called.
|
||||
return &f.s, nil
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func newFT232R(g generic) (*FT232R, error) {
|
||||
f := &FT232R{
|
||||
generic: g,
|
||||
dbus: [...]dbusPinSync{{num: 0}, {num: 1}, {num: 2}, {num: 3}, {num: 4}, {num: 5}, {num: 6}, {num: 7}},
|
||||
cbus: [...]cbusPin{{num: 8, p: gpio.PullUp}, {num: 9, p: gpio.PullUp}, {num: 10, p: gpio.PullUp}, {num: 11, p: gpio.Float}},
|
||||
}
|
||||
// Use the UART names, as this is how all FT232R boards are marked.
|
||||
dnames := [...]string{"TX", "RX", "RTS", "CTS", "DTR", "DSR", "DCD", "RI"}
|
||||
for i := range f.dbus {
|
||||
f.dbus[i].n = f.name + "." + dnames[i]
|
||||
f.dbus[i].bus = f
|
||||
f.hdr[i] = &f.dbus[i]
|
||||
}
|
||||
for i := range f.cbus {
|
||||
f.cbus[i].n = f.name + ".C" + strconv.Itoa(i)
|
||||
f.cbus[i].bus = f
|
||||
f.hdr[i+8] = &f.cbus[i]
|
||||
}
|
||||
f.D0 = f.hdr[0]
|
||||
f.D1 = f.hdr[1]
|
||||
f.D2 = f.hdr[2]
|
||||
f.D3 = f.hdr[3]
|
||||
f.D4 = f.hdr[4]
|
||||
f.D5 = f.hdr[5]
|
||||
f.D6 = f.hdr[6]
|
||||
f.D7 = f.hdr[7]
|
||||
f.TX = f.hdr[0]
|
||||
f.RX = f.hdr[1]
|
||||
f.RTS = f.hdr[2]
|
||||
f.CTS = f.hdr[3]
|
||||
f.DTR = f.hdr[4]
|
||||
f.DSR = f.hdr[5]
|
||||
f.DCD = f.hdr[6]
|
||||
f.RI = f.hdr[7]
|
||||
f.C0 = f.hdr[8]
|
||||
f.C1 = f.hdr[9]
|
||||
f.C2 = f.hdr[10]
|
||||
f.C3 = f.hdr[11]
|
||||
|
||||
// Default to 3MHz.
|
||||
if err := f.h.SetBaudRate(3 * physic.MegaHertz); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set all CBus pins as input.
|
||||
if err := f.h.SetBitMode(0, bitModeCbusBitbang); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// And read their value.
|
||||
// TODO(maruel): Sadly this is impossible to know which pin is input or
|
||||
// output, but we could try to guess, as the call above may generate noise on
|
||||
// the line which could interfere with the device connected.
|
||||
var err error
|
||||
if f.cbusnibble, err = f.h.GetBitMode(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Set all DBus as asynchronous bitbang, everything as input.
|
||||
if err := f.h.SetBitMode(0, bitModeAsyncBitbang); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// And read their value.
|
||||
var b [1]byte
|
||||
if _, err := f.h.ReadAll(context.Background(), b[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.dvalue = b[0]
|
||||
f.s.c.f = f
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// FT232R represents a FT232RL/FT232RQ device.
|
||||
//
|
||||
// It implements Dev.
|
||||
//
|
||||
// Not all pins may be physically connected on the header!
|
||||
//
|
||||
// Adafruit's version only has the following pins connected: RX, TX, RTS and
|
||||
// CTS.
|
||||
//
|
||||
// SparkFun's version exports all pins *except* (inexplicably) the CBus ones.
|
||||
//
|
||||
// The FT232R has 128 bytes output buffer and 256 bytes input buffer.
|
||||
//
|
||||
// Pin C4 can only be used in 'slow' mode via EEPROM and is currently not
|
||||
// implemented.
|
||||
//
|
||||
// Datasheet
|
||||
//
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232R.pdf
|
||||
type FT232R struct {
|
||||
generic
|
||||
|
||||
// Pin and their alias to the Dn pins for user convenience. Each pair points
|
||||
// to the exact same pin.
|
||||
D0, TX gpio.PinIO // Transmit; SPI_MOSI
|
||||
D1, RX gpio.PinIO // Receive; SPI_MISO
|
||||
D2, RTS gpio.PinIO // Request To Send Control Output / Handshake signal; SPI_CLK
|
||||
D3, CTS gpio.PinIO // Clear to Send Control input / Handshake signal; SPI_CS
|
||||
D4, DTR gpio.PinIO // Data Terminal Ready Control Output / Handshake signal
|
||||
D5, DSR gpio.PinIO // Data Set Ready Control Input / Handshake signal
|
||||
D6, DCD gpio.PinIO // Data Carrier Detect Control input
|
||||
D7, RI gpio.PinIO // Ring Indicator Control Input. When remote wake up is enabled in the internal EEPROM taking RI# low can be used to resume the PC USB host controller from suspend.
|
||||
|
||||
// The CBus pins are slower to use, but can drive an high load, like a LED.
|
||||
C0 gpio.PinIO
|
||||
C1 gpio.PinIO
|
||||
C2 gpio.PinIO
|
||||
C3 gpio.PinIO
|
||||
|
||||
dbus [8]dbusPinSync
|
||||
cbus [4]cbusPin
|
||||
hdr [12]gpio.PinIO
|
||||
|
||||
// Mutable.
|
||||
mu sync.Mutex
|
||||
usingSPI bool
|
||||
usingCBus bool
|
||||
s spiSyncPort
|
||||
dmask uint8 // 0 input, 1 output
|
||||
dvalue uint8
|
||||
cbusnibble uint8 // upper nibble is I/O control, lower nibble is values.
|
||||
}
|
||||
|
||||
// Header returns the GPIO pins exposed on the chip.
|
||||
func (f *FT232R) Header() []gpio.PinIO {
|
||||
out := make([]gpio.PinIO, len(f.hdr))
|
||||
copy(out, f.hdr[:])
|
||||
return out
|
||||
}
|
||||
|
||||
// SetDBusMask sets all D0~D7 input or output mode at once.
|
||||
//
|
||||
// mask is the input/output pins to use. A bit value of 0 sets the
|
||||
// corresponding pin to an input, a bit value of 1 sets the corresponding pin
|
||||
// to an output.
|
||||
//
|
||||
// It should be called before calling Tx().
|
||||
func (f *FT232R) SetDBusMask(mask uint8) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingSPI {
|
||||
return errors.New("d2xx: already using SPI")
|
||||
}
|
||||
return f.setDBusMaskLocked(mask)
|
||||
}
|
||||
|
||||
// Tx does synchronized read-then-write on all the D0~D7 GPIOs.
|
||||
//
|
||||
// SetSpeed() determines the pace at which the I/O is done.
|
||||
//
|
||||
// SetDBusMask() determines which bits are interpreted in the w and r byte
|
||||
// slice. w has its significant value masked by 'mask' and r has its
|
||||
// significant value masked by '^mask'.
|
||||
//
|
||||
// Input sample is done *before* updating outputs. So r[0] is sampled before
|
||||
// w[0] is used. The last w byte should be duplicated if an addition read is
|
||||
// desired.
|
||||
//
|
||||
// On the Adafruit cable, only the first 4 bits D0(TX), D1(RX), D2(RTS) and
|
||||
// D3(CTS) are connected. This is just enough to create a full duplex SPI bus!
|
||||
func (f *FT232R) Tx(w, r []byte) error {
|
||||
if len(w) != 0 {
|
||||
if len(r) != 0 && len(w) != len(r) {
|
||||
return errors.New("d2xx: length of buffer w and r must match")
|
||||
}
|
||||
} else if len(r) == 0 {
|
||||
return errors.New("d2xx: at least one of w or r must be passed")
|
||||
}
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingSPI {
|
||||
return errors.New("d2xx: already using SPI")
|
||||
}
|
||||
return f.txLocked(w, r)
|
||||
}
|
||||
|
||||
// SPI returns a SPI port over the first 4 pins.
|
||||
//
|
||||
// It uses D0(TX), D1(RX), D2(RTS) and D3(CTS). D2(RTS) is the clock, D0(TX)
|
||||
// the output (MOSI), D1(RX) is the input (MISO) and D3(CTS) is CS line.
|
||||
func (f *FT232R) SPI() (spi.PortCloser, error) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingSPI {
|
||||
return nil, errors.New("d2xx: already using SPI")
|
||||
}
|
||||
// Don't mark it as being used yet. It only become used once Connect() is
|
||||
// called.
|
||||
return &f.s, nil
|
||||
}
|
||||
|
||||
// setDBusMaskLocked is the locked version of SetDBusMask.
|
||||
func (f *FT232R) setDBusMaskLocked(mask uint8) error {
|
||||
if mask != f.dmask {
|
||||
if err := f.h.SetBitMode(mask, bitModeAsyncBitbang); err != nil {
|
||||
return err
|
||||
}
|
||||
f.dmask = mask
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FT232R) txLocked(w, r []byte) error {
|
||||
// Investigate FT232R clock issue:
|
||||
// http://developer.intra2net.com/mailarchive/html/libftdi/2010/msg00240.html
|
||||
|
||||
// The FT232R has 128 bytes TX buffer and 256 bytes RX buffer. Chunk into 64
|
||||
// bytes chunks. That's half the buffer size of the TX buffer and permits
|
||||
// pipelining and removes the risk of buffer overrun. This is important
|
||||
// otherwise there's huge gaps due to the USB transmit overhead.
|
||||
// TODO(maruel): Determine what's optimal via experimentation.
|
||||
chunk := 64
|
||||
var scratch [128]byte
|
||||
if len(w) == 0 {
|
||||
// Read only.
|
||||
for i := range scratch {
|
||||
scratch[i] = f.dvalue
|
||||
}
|
||||
for len(r) != 0 {
|
||||
// TODO(maruel): Optimize.
|
||||
c := len(r)
|
||||
if c > chunk {
|
||||
c = chunk
|
||||
}
|
||||
if _, err := f.h.Write(scratch[:c]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := f.h.ReadAll(context.Background(), r[:c]); err != nil {
|
||||
return err
|
||||
}
|
||||
r = r[c:]
|
||||
}
|
||||
} else if len(r) == 0 {
|
||||
// Write only.
|
||||
// The first write is 128 bytes to fill the buffer.
|
||||
chunk = 128
|
||||
for len(w) != 0 {
|
||||
c := len(w)
|
||||
if c > chunk {
|
||||
c = chunk
|
||||
}
|
||||
if _, err := f.h.Write(w[:c]); err != nil {
|
||||
return err
|
||||
}
|
||||
w = w[c:]
|
||||
chunk = 64
|
||||
}
|
||||
/*
|
||||
// Let the USB drive pace it.
|
||||
if _, err := f.h.Write(w); err != nil {
|
||||
return err
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
// R/W.
|
||||
// Always write one 'w' ahead.
|
||||
// The first write is 128 bytes to fill the buffer.
|
||||
chunk = 128
|
||||
cw := len(w)
|
||||
if cw > chunk {
|
||||
cw = chunk
|
||||
}
|
||||
if _, err := f.h.Write(w[:cw]); err != nil {
|
||||
return err
|
||||
}
|
||||
w = w[cw:]
|
||||
chunk = 64
|
||||
for len(r) != 0 {
|
||||
// Read then write.
|
||||
cr := len(r)
|
||||
if cr > chunk {
|
||||
cr = chunk
|
||||
}
|
||||
if _, err := f.h.ReadAll(context.Background(), r[:cr]); err != nil {
|
||||
return err
|
||||
}
|
||||
r = r[cr:]
|
||||
|
||||
cw = len(w)
|
||||
if cw > chunk {
|
||||
cw = chunk
|
||||
}
|
||||
if cw != 0 {
|
||||
if _, err := f.h.Write(w[:cw]); err != nil {
|
||||
return err
|
||||
}
|
||||
w = w[cw:]
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// dbusSyncGPIOFunc implements dbusSync. It returns the function of a GPIO
|
||||
// pin.
|
||||
func (f *FT232R) dbusSyncGPIOFunc(n int) string {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.usingSPI {
|
||||
switch n {
|
||||
case 0:
|
||||
return "SPI_MOSI" // TX
|
||||
case 1:
|
||||
return "SPI_MISO" // RX
|
||||
case 2:
|
||||
return "SPI_CLK" // RTS
|
||||
case 3:
|
||||
return "SPI_CS" // CTS
|
||||
}
|
||||
}
|
||||
mask := uint8(1 << uint(n))
|
||||
if f.dmask&mask != 0 {
|
||||
return "Out/" + gpio.Level(f.dvalue&mask != 0).String()
|
||||
}
|
||||
return "In/" + f.dbusSyncReadLocked(n).String()
|
||||
}
|
||||
|
||||
// dbusSyncGPIOIn implements dbusSync.
|
||||
func (f *FT232R) dbusSyncGPIOIn(n int) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
// TODO(maruel): if f.usingSPI && n < 4.
|
||||
mask := uint8(1 << uint(n))
|
||||
if f.dmask&mask == 0 {
|
||||
// Already input.
|
||||
return nil
|
||||
}
|
||||
v := f.dmask &^ mask
|
||||
if err := f.h.SetBitMode(v, bitModeAsyncBitbang); err != nil {
|
||||
return err
|
||||
}
|
||||
f.dmask = v
|
||||
return nil
|
||||
}
|
||||
|
||||
// dbusSyncGPIORead implements dbusSync.
|
||||
func (f *FT232R) dbusSyncGPIORead(n int) gpio.Level {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.dbusSyncReadLocked(n)
|
||||
}
|
||||
|
||||
func (f *FT232R) dbusSyncReadLocked(n int) gpio.Level {
|
||||
// In synchronous mode, to read we must write first to for a sample.
|
||||
b := [1]byte{f.dvalue}
|
||||
if _, err := f.h.Write(b[:]); err != nil {
|
||||
return gpio.Low
|
||||
}
|
||||
mask := uint8(1 << uint(n))
|
||||
if _, err := f.h.ReadAll(context.Background(), b[:]); err != nil {
|
||||
return gpio.Low
|
||||
}
|
||||
f.dvalue = b[0]
|
||||
return f.dvalue&mask != 0
|
||||
}
|
||||
|
||||
// dbusSyncGPIOOut implements dbusSync.
|
||||
func (f *FT232R) dbusSyncGPIOOut(n int, l gpio.Level) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
mask := uint8(1 << uint(n))
|
||||
if f.dmask&mask != 1 {
|
||||
// Was input.
|
||||
v := f.dmask | mask
|
||||
if err := f.h.SetBitMode(v, bitModeAsyncBitbang); err != nil {
|
||||
return err
|
||||
}
|
||||
f.dmask = v
|
||||
}
|
||||
return f.dbusSyncGPIOOutLocked(n, l)
|
||||
}
|
||||
|
||||
func (f *FT232R) dbusSyncGPIOOutLocked(n int, l gpio.Level) error {
|
||||
b := [1]byte{f.dvalue}
|
||||
if _, err := f.h.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
f.dvalue = b[0]
|
||||
// In synchronous mode, we must read after writing to flush the buffer.
|
||||
if _, err := f.h.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// cBusGPIOFunc implements cBusGPIO.
|
||||
func (f *FT232R) cBusGPIOFunc(n int) string {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
fmask := uint8(0x10 << uint(n))
|
||||
vmask := uint8(1 << uint(n))
|
||||
if f.cbusnibble&fmask != 0 {
|
||||
return "Out/" + gpio.Level(f.cbusnibble&vmask != 0).String()
|
||||
}
|
||||
return "In/" + f.cBusReadLocked(n).String()
|
||||
}
|
||||
|
||||
// cBusGPIOIn implements cBusGPIO.
|
||||
func (f *FT232R) cBusGPIOIn(n int) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
fmask := uint8(0x10 << uint(n))
|
||||
if f.cbusnibble&fmask == 0 {
|
||||
// Already input.
|
||||
return nil
|
||||
}
|
||||
v := f.cbusnibble &^ fmask
|
||||
if err := f.h.SetBitMode(v, bitModeCbusBitbang); err != nil {
|
||||
return err
|
||||
}
|
||||
f.cbusnibble = v
|
||||
return nil
|
||||
}
|
||||
|
||||
// cBusGPIORead implements cBusGPIO.
|
||||
func (f *FT232R) cBusGPIORead(n int) gpio.Level {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
return f.cBusReadLocked(n)
|
||||
}
|
||||
|
||||
func (f *FT232R) cBusReadLocked(n int) gpio.Level {
|
||||
v, err := f.h.GetBitMode()
|
||||
if err != nil {
|
||||
return gpio.Low
|
||||
}
|
||||
f.cbusnibble = v
|
||||
vmask := uint8(1 << uint(n))
|
||||
return f.cbusnibble&vmask != 0
|
||||
}
|
||||
|
||||
// cBusGPIOOut implements cBusGPIO.
|
||||
func (f *FT232R) cBusGPIOOut(n int, l gpio.Level) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
fmask := uint8(0x10 << uint(n))
|
||||
vmask := uint8(1 << uint(n))
|
||||
v := f.cbusnibble | fmask
|
||||
if l {
|
||||
v |= vmask
|
||||
} else {
|
||||
v &^= vmask
|
||||
}
|
||||
if f.cbusnibble == v {
|
||||
// Was already in the right mode.
|
||||
return nil
|
||||
}
|
||||
if err := f.h.SetBitMode(v, bitModeCbusBitbang); err != nil {
|
||||
return err
|
||||
}
|
||||
f.cbusnibble = v
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
var _ conn.Resource = Dev(nil)
|
20
vendor/periph.io/x/host/v3/ftdi/doc.go
generated
vendored
20
vendor/periph.io/x/host/v3/ftdi/doc.go
generated
vendored
@ -1,20 +0,0 @@
|
||||
// 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 ftdi implements support for popular FTDI devices.
|
||||
//
|
||||
// The supported devices (FT232h/FT232r) implement support for various
|
||||
// protocols like the GPIO, I²C, SPI, UART, JTAG.
|
||||
//
|
||||
// More details
|
||||
//
|
||||
// See https://periph.io/device/ftdi/ for more details, and how to configure
|
||||
// the host to be able to use this driver.
|
||||
//
|
||||
// Datasheets
|
||||
//
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232R.pdf
|
||||
//
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232H.pdf
|
||||
package ftdi
|
213
vendor/periph.io/x/host/v3/ftdi/driver.go
generated
vendored
213
vendor/periph.io/x/host/v3/ftdi/driver.go
generated
vendored
@ -1,213 +0,0 @@
|
||||
// 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 ftdi
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"periph.io/x/conn/v3/driver/driverreg"
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/gpio/gpioreg"
|
||||
"periph.io/x/conn/v3/i2c"
|
||||
"periph.io/x/conn/v3/i2c/i2creg"
|
||||
"periph.io/x/conn/v3/pin"
|
||||
"periph.io/x/conn/v3/pin/pinreg"
|
||||
"periph.io/x/conn/v3/spi/spireg"
|
||||
"periph.io/x/d2xx"
|
||||
)
|
||||
|
||||
// All enumerates all the connected FTDI devices.
|
||||
func All() []Dev {
|
||||
drv.mu.Lock()
|
||||
defer drv.mu.Unlock()
|
||||
out := make([]Dev, len(drv.all))
|
||||
copy(out, drv.all)
|
||||
return out
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// open opens a FTDI device.
|
||||
//
|
||||
// Must be called with mu held.
|
||||
func open(opener func(i int) (d2xx.Handle, d2xx.Err), i int) (Dev, error) {
|
||||
h, err := openHandle(opener, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := h.Init(); err != nil {
|
||||
// setupCommon() takes the device in its previous state. It could be in an
|
||||
// unexpected state, so try resetting it first.
|
||||
if err := h.Reset(); err != nil {
|
||||
_ = h.Close()
|
||||
return nil, err
|
||||
}
|
||||
if err := h.Init(); err != nil {
|
||||
_ = h.Close()
|
||||
return nil, err
|
||||
}
|
||||
// The second attempt worked.
|
||||
}
|
||||
// Makes a copy of the handle.
|
||||
g := generic{index: i, h: h, name: h.t.String()}
|
||||
if i > 0 {
|
||||
// When more than one device is present, add "(index)" suffix.
|
||||
// TODO(maruel): Using the serial number would be nicer than a number.
|
||||
g.name += "(" + strconv.Itoa(i) + ")"
|
||||
}
|
||||
// Makes a copy of the generic instance.
|
||||
switch g.h.t {
|
||||
case DevTypeFT232H:
|
||||
f, err := newFT232H(g)
|
||||
if err != nil {
|
||||
_ = h.Close()
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
case DevTypeFT2232H:
|
||||
f, err := newFT232H(g)
|
||||
if err != nil {
|
||||
_ = h.Close()
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
case DevTypeFT232R:
|
||||
f, err := newFT232R(g)
|
||||
if err != nil {
|
||||
_ = h.Close()
|
||||
return nil, err
|
||||
}
|
||||
return f, nil
|
||||
default:
|
||||
return &g, nil
|
||||
}
|
||||
}
|
||||
|
||||
// registerDev registers the header and supported buses and ports in the
|
||||
// relevant registries.
|
||||
func registerDev(d Dev, multi bool) error {
|
||||
name := d.String()
|
||||
hdr := d.Header()
|
||||
|
||||
// Register the GPIOs.
|
||||
for _, p := range hdr {
|
||||
if err := gpioreg.Register(p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if !multi {
|
||||
// Register shorthands.
|
||||
// The "." used here vs the "_" used in pinreg is unfortunate. Investigate
|
||||
// a better way.
|
||||
prefix := len(name) + 1
|
||||
for _, p := range hdr {
|
||||
n := p.Name()
|
||||
if err := gpioreg.RegisterAlias(n[prefix:], n); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register the header.
|
||||
raw := make([][]pin.Pin, len(hdr))
|
||||
for i := range hdr {
|
||||
raw[i] = []pin.Pin{hdr[i]}
|
||||
}
|
||||
if err := pinreg.Register(name, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
switch t := d.(type) {
|
||||
case *FT232H:
|
||||
// Register I²C without pull up.
|
||||
if err := i2creg.Register(name, nil, -1, func() (i2c.BusCloser, error) { return t.I2C(gpio.Float) }); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := spireg.Register(name, nil, -1, t.SPI); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(maruel): UART
|
||||
case *FT232R:
|
||||
// TODO(maruel): SPI, UART
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// driver implements driver.Impl.
|
||||
type driver struct {
|
||||
mu sync.Mutex
|
||||
all []Dev
|
||||
d2xxOpen func(i int) (d2xx.Handle, d2xx.Err)
|
||||
numDevices func() (int, error)
|
||||
}
|
||||
|
||||
func (d *driver) String() string {
|
||||
return "ftdi"
|
||||
}
|
||||
|
||||
func (d *driver) Prerequisites() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) After() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *driver) Init() (bool, error) {
|
||||
num, err := d.numDevices()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
multi := num > 1
|
||||
for i := 0; i < num; i++ {
|
||||
// TODO(maruel): Close the device one day. :)
|
||||
if dev, err1 := open(d.d2xxOpen, i); err1 == nil {
|
||||
d.all = append(d.all, dev)
|
||||
if err = registerDev(dev, multi); err != nil {
|
||||
return true, err
|
||||
}
|
||||
} else {
|
||||
// Create a shallow broken handle, so the user can learn how to fix the
|
||||
// problem.
|
||||
//
|
||||
// TODO(maruel): On macOS with a FT232R, calling two processes in a row
|
||||
// often results in a broken device on the second process. Figure out why
|
||||
// and make it more resilient.
|
||||
err = err1
|
||||
// The serial number is not available so what can be listed is limited.
|
||||
// TODO(maruel): Add VID/PID?
|
||||
name := "broken#" + strconv.Itoa(i) + ": " + err.Error()
|
||||
d.all = append(d.all, &broken{index: i, err: err, name: name})
|
||||
}
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
|
||||
func (d *driver) reset() {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
d.all = nil
|
||||
// open is mocked in tests.
|
||||
d.d2xxOpen = d2xx.Open
|
||||
// numDevices is mocked in tests.
|
||||
d.numDevices = numDevices
|
||||
|
||||
// The d2xx can hang for up to the timeout under certain circumstances and the
|
||||
// Go profiler is not very useful to find the source, so use manual logging
|
||||
// to see where time it spent.
|
||||
//d.d2xxOpen = func(i int) (d2xx.Handle, int) {
|
||||
// h, e := d2xxOpen(i)
|
||||
// return &d2xxLoggingHandle{h}, e
|
||||
//}
|
||||
}
|
||||
|
||||
func init() {
|
||||
if d2xx.Available {
|
||||
drv.reset()
|
||||
driverreg.MustRegister(&drv)
|
||||
}
|
||||
}
|
||||
|
||||
var drv driver
|
368
vendor/periph.io/x/host/v3/ftdi/eeprom.go
generated
vendored
368
vendor/periph.io/x/host/v3/ftdi/eeprom.go
generated
vendored
@ -1,368 +0,0 @@
|
||||
// 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 ftdi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// EEPROM is the unprocessed EEPROM content.
|
||||
//
|
||||
// The EEPROM is in 3 parts: the defined struct, the 4 strings and the rest
|
||||
// which is used as an 'user area'. The size of the user area depends on the
|
||||
// length of the strings. The user area content is not included in this struct.
|
||||
type EEPROM struct {
|
||||
// Raw is the raw EEPROM content. It excludes the strings.
|
||||
Raw []byte
|
||||
|
||||
// The following condition must be true: len(Manufacturer) + len(Desc) <= 40.
|
||||
Manufacturer string
|
||||
ManufacturerID string
|
||||
Desc string
|
||||
Serial string
|
||||
}
|
||||
|
||||
// Validate checks that the data is good.
|
||||
func (e *EEPROM) Validate() error {
|
||||
// Verify that the values are set correctly.
|
||||
if len(e.Manufacturer) > 40 {
|
||||
return errors.New("ftdi: Manufacturer is too long")
|
||||
}
|
||||
if len(e.ManufacturerID) > 40 {
|
||||
return errors.New("ftdi: ManufacturerID is too long")
|
||||
}
|
||||
if len(e.Desc) > 40 {
|
||||
return errors.New("ftdi: Desc is too long")
|
||||
}
|
||||
if len(e.Serial) > 40 {
|
||||
return errors.New("ftdi: Serial is too long")
|
||||
}
|
||||
if len(e.Manufacturer)+len(e.Desc) > 40 {
|
||||
return errors.New("ftdi: length of Manufacturer plus Desc is too long")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EEPROM) AsHeader() *EEPROMHeader {
|
||||
// sizeof(EEPROMHeader)
|
||||
if len(e.Raw) < 16 {
|
||||
return nil
|
||||
}
|
||||
return (*EEPROMHeader)(unsafe.Pointer(&e.Raw[0]))
|
||||
}
|
||||
|
||||
// AsFT232H returns the Raw data aliased as EEPROMFT232H.
|
||||
func (e *EEPROM) AsFT232H() *EEPROMFT232H {
|
||||
// sizeof(EEPROMFT232H)
|
||||
if len(e.Raw) < 44 {
|
||||
return nil
|
||||
}
|
||||
return (*EEPROMFT232H)(unsafe.Pointer(&e.Raw[0]))
|
||||
}
|
||||
|
||||
// AsFT2232H returns the Raw data aliased as EEPROMFT2232H.
|
||||
func (e *EEPROM) AsFT2232H() *EEPROMFT2232H {
|
||||
// sizeof(EEPROMFT2232H)
|
||||
if len(e.Raw) < 40 {
|
||||
return nil
|
||||
}
|
||||
return (*EEPROMFT2232H)(unsafe.Pointer(&e.Raw[0]))
|
||||
}
|
||||
|
||||
// AsFT232R returns the Raw data aliased as EEPROMFT232R.
|
||||
func (e *EEPROM) AsFT232R() *EEPROMFT232R {
|
||||
// sizeof(EEPROMFT232R)
|
||||
if len(e.Raw) < 32 {
|
||||
return nil
|
||||
}
|
||||
return (*EEPROMFT232R)(unsafe.Pointer(&e.Raw[0]))
|
||||
}
|
||||
|
||||
// FT232hCBusMux is stored in the FT232H EEPROM to control each CBus pin.
|
||||
type FT232hCBusMux uint8
|
||||
|
||||
const (
|
||||
// TriSt-PU; Sets in Tristate (pull up) (C0~C6, C8, C9) on 75kΩ.
|
||||
FT232hCBusTristatePullUp FT232hCBusMux = 0x00
|
||||
// TXLED#; Pulses low when transmitting data (C0~C6, C8, C9).
|
||||
FT232hCBusTxLED FT232hCBusMux = 0x01
|
||||
// RXLED#; Pulses low when receiving data (C0~C6, C8, C9).
|
||||
FT232hCBusRxLED FT232hCBusMux = 0x02
|
||||
// TX&RXLED#; Pulses low when either receiving or transmitting data (C0~C6,
|
||||
// C8, C9).
|
||||
FT232hCBusTxRxLED FT232hCBusMux = 0x03
|
||||
// PWREN#; Output is low after the device has been configured by USB, then
|
||||
// high during USB suspend mode (C0~C6, C8, C9).
|
||||
//
|
||||
// Must be used with an external 10kΩ pull up.
|
||||
FT232hCBusPwrEnable FT232hCBusMux = 0x04
|
||||
// SLEEP#; Goes low during USB suspend mode (C0~C6, C8, C9).
|
||||
FT232hCBusSleep FT232hCBusMux = 0x05
|
||||
// DRIVE1; Drives pin to logic 0 (C0~C6, C8, C9).
|
||||
FT232hCBusDrive0 FT232hCBusMux = 0x06
|
||||
// DRIVE1; Drives pin to logic 1 (C0, C5, C6, C8, C9).
|
||||
FT232hCBusDrive1 FT232hCBusMux = 0x07
|
||||
// I/O Mode; CBus bit-bang mode option (C5, C6, C8, C9).
|
||||
FT232hCBusIOMode FT232hCBusMux = 0x08
|
||||
// TXDEN; Tx Data Enable. Used with RS485 level converters to enable the line
|
||||
// driver during data transmit. It is active one bit time before the start
|
||||
// bit up to until the end of the stop bit (C0~C6, C8, C9).
|
||||
FT232hCBusTxdEnable FT232hCBusMux = 0x09
|
||||
// CLK30 30MHz clock output (C0, C5, C6, C8, C9).
|
||||
FT232hCBusClk30 FT232hCBusMux = 0x0A
|
||||
// CLK15 15MHz clock output (C0, C5, C6, C8, C9).
|
||||
FT232hCBusClk15 FT232hCBusMux = 0x0B
|
||||
// CLK7.5 7.5MHz clock output (C0, C5, C6, C8, C9).
|
||||
FT232hCBusClk7_5 FT232hCBusMux = 0x0C
|
||||
)
|
||||
|
||||
const ft232hCBusMuxName = "FT232hCBusTristatePullUpFT232hCBusTxLEDFT232hCBusRxLEDFT232hCBusTxRxLEDFT232hCBusPwrEnableFT232hCBusSleepFT232hCBusDrive0FT232hCBusDrive1FT232hCBusIOModeFT232hCBusTxdEnableFT232hCBusClk30FT232hCBusClk15FT232hCBusClk7_5"
|
||||
|
||||
var fr232hCBusMuxIndex = [...]uint8{0, 24, 39, 54, 71, 90, 105, 121, 137, 153, 172, 187, 202, 218}
|
||||
|
||||
func (f FT232hCBusMux) String() string {
|
||||
if f >= FT232hCBusMux(len(fr232hCBusMuxIndex)-1) {
|
||||
return fmt.Sprintf("FT232hCBusMux(%d)", f)
|
||||
}
|
||||
return ft232hCBusMuxName[fr232hCBusMuxIndex[f]:fr232hCBusMuxIndex[f+1]]
|
||||
}
|
||||
|
||||
// FT232rCBusMux is stored in the FT232R EEPROM to control each CBus pin.
|
||||
type FT232rCBusMux uint8
|
||||
|
||||
const (
|
||||
// TXDEN; Tx Data Enable. Used with RS485 level converters to enable the line
|
||||
// driver during data transmit. It is active one bit time before the start
|
||||
// bit up to until the end of the stop bit (C0~C4).
|
||||
FT232rCBusTxdEnable FT232rCBusMux = 0x00
|
||||
// PWREN#; Output is low after the device has been configured by USB, then
|
||||
// high during USB suspend mode (C0~C4).
|
||||
//
|
||||
// Must be used with an external 10kΩ pull up.
|
||||
FT232rCBusPwrEnable FT232rCBusMux = 0x01
|
||||
// RXLED#; Pulses low when receiving data (C0~C4).
|
||||
FT232rCBusRxLED FT232rCBusMux = 0x02
|
||||
// TXLED#; Pulses low when transmitting data (C0~C4).
|
||||
FT232rCBusTxLED FT232rCBusMux = 0x03
|
||||
// TX&RXLED#; Pulses low when either receiving or transmitting data (C0~C4).
|
||||
FT232rCBusTxRxLED FT232rCBusMux = 0x04
|
||||
// SLEEP# Goes low during USB suspend mode (C0~C4).
|
||||
FT232rCBusSleep FT232rCBusMux = 0x05
|
||||
// CLK48 48Mhz +/-0.7% clock output (C0~C4).
|
||||
FT232rCBusClk48 FT232rCBusMux = 0x06
|
||||
// CLK24 24Mhz clock output (C0~C4).
|
||||
FT232rCBusClk24 FT232rCBusMux = 0x07
|
||||
// CLK12 12Mhz clock output (C0~C4).
|
||||
FT232rCBusClk12 FT232rCBusMux = 0x08
|
||||
// CLK6 6Mhz +/-0.7% clock output (C0~C4).
|
||||
FT232rCBusClk6 FT232rCBusMux = 0x09
|
||||
// CBitBangI/O; CBus bit-bang mode option (C0~C3).
|
||||
FT232rCBusIOMode FT232rCBusMux = 0x0A
|
||||
// BitBangWRn; CBus WR# strobe output (C0~C3).
|
||||
FT232rCBusBitBangWR FT232rCBusMux = 0x0B
|
||||
// BitBangRDn; CBus RD# strobe output (C0~C3).
|
||||
FT232rCBusBitBangRD FT232rCBusMux = 0x0C
|
||||
)
|
||||
|
||||
const ft232rCBusMuxName = "FT232rCBusTxdEnableFT232rCBusPwrEnableFT232rCBusRxLEDFT232rCBusTxLEDFT232rCBusTxRxLEDFT232rCBusSleepFT232rCBusClk48FT232rCBusClk24FT232rCBusClk12FT232rCBusClk6FT232rCBusIOModeFT232rCBusBitBangWRFT232rCBusBitBangRD"
|
||||
|
||||
var ft232rCBusMuxIndex = [...]uint8{0, 19, 38, 53, 68, 85, 100, 115, 130, 145, 159, 175, 194, 213}
|
||||
|
||||
func (f FT232rCBusMux) String() string {
|
||||
if f >= FT232rCBusMux(len(ft232rCBusMuxIndex)-1) {
|
||||
return fmt.Sprintf("FT232rCBusMux(%d)", f)
|
||||
}
|
||||
return ft232rCBusMuxName[ft232rCBusMuxIndex[f]:ft232rCBusMuxIndex[f+1]]
|
||||
}
|
||||
|
||||
// EEPROMHeader is the common header found on FTDI devices.
|
||||
//
|
||||
// It is 16 bytes long.
|
||||
type EEPROMHeader struct {
|
||||
DeviceType DevType // 0x00 FTxxxx device type to be programmed
|
||||
VendorID uint16 // 0x04 Defaults to 0x0403; can be changed
|
||||
ProductID uint16 // 0x06 Defaults to 0x6001 for FT232R, 0x6014 for FT232H, relevant value
|
||||
SerNumEnable uint8 // 0x07 bool Non-zero if serial number to be used
|
||||
Unused0 uint8 // 0x08 For alignment.
|
||||
MaxPower uint16 // 0x0A 0mA < MaxPower <= 500mA
|
||||
SelfPowered uint8 // 0x0C bool 0 = bus powered, 1 = self powered
|
||||
RemoteWakeup uint8 // 0x0D bool 0 = not capable, 1 = capable; RI# low will wake host in 20ms.
|
||||
PullDownEnable uint8 // 0x0E bool Non zero if pull down in suspend enabled
|
||||
Unused1 uint8 // 0x0F For alignment.
|
||||
}
|
||||
|
||||
// EEPROMFT232H is the EEPROM layout of a FT232H device.
|
||||
//
|
||||
// It is 44 bytes long.
|
||||
type EEPROMFT232H struct {
|
||||
EEPROMHeader
|
||||
|
||||
// FT232H specific.
|
||||
ACSlowSlew uint8 // 0x10 bool Non-zero if AC bus pins have slow slew
|
||||
ACSchmittInput uint8 // 0x11 bool Non-zero if AC bus pins are Schmitt input
|
||||
ACDriveCurrent uint8 // 0x12 Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
ADSlowSlew uint8 // 0x13 bool Non-zero if AD bus pins have slow slew
|
||||
ADSchmittInput uint8 // 0x14 bool Non-zero if AD bus pins are Schmitt input
|
||||
ADDriveCurrent uint8 // 0x15 Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
Cbus0 FT232hCBusMux // 0x16
|
||||
Cbus1 FT232hCBusMux // 0x17
|
||||
Cbus2 FT232hCBusMux // 0x18
|
||||
Cbus3 FT232hCBusMux // 0x19
|
||||
Cbus4 FT232hCBusMux // 0x1A
|
||||
Cbus5 FT232hCBusMux // 0x1B
|
||||
Cbus6 FT232hCBusMux // 0x1C
|
||||
Cbus7 FT232hCBusMux // 0x1D C7 is limited a sit can only do 'suspend on C7 low'. Defaults pull down.
|
||||
Cbus8 FT232hCBusMux // 0x1E
|
||||
Cbus9 FT232hCBusMux // 0x1F
|
||||
FT1248Cpol uint8 // 0x20 bool FT1248 clock polarity - clock idle high (true) or clock idle low (false)
|
||||
FT1248Lsb uint8 // 0x21 bool FT1248 data is LSB (true), or MSB (false)
|
||||
FT1248FlowControl uint8 // 0x22 bool FT1248 flow control enable
|
||||
IsFifo uint8 // 0x23 bool Non-zero if Interface is 245 FIFO
|
||||
IsFifoTar uint8 // 0x24 bool Non-zero if Interface is 245 FIFO CPU target
|
||||
IsFastSer uint8 // 0x25 bool Non-zero if Interface is Fast serial
|
||||
IsFT1248 uint8 // 0x26 bool Non-zero if Interface is FT1248
|
||||
PowerSaveEnable uint8 // 0x27 bool Suspect on ACBus7 low.
|
||||
DriverType uint8 // 0x28 bool 0 is D2XX, 1 is VCP
|
||||
Unused2 uint8 // 0x29
|
||||
Unused3 uint16 // 0x30
|
||||
}
|
||||
|
||||
func (e *EEPROMFT232H) Defaults() {
|
||||
// As found on Adafruit device.
|
||||
e.ACDriveCurrent = 4
|
||||
e.ADDriveCurrent = 4
|
||||
e.Cbus0 = FT232hCBusTristatePullUp
|
||||
e.Cbus1 = FT232hCBusTristatePullUp
|
||||
e.Cbus2 = FT232hCBusTristatePullUp
|
||||
e.Cbus3 = FT232hCBusTristatePullUp
|
||||
e.Cbus4 = FT232hCBusTristatePullUp
|
||||
e.Cbus5 = FT232hCBusTristatePullUp
|
||||
e.Cbus6 = FT232hCBusTristatePullUp
|
||||
e.Cbus7 = FT232hCBusTristatePullUp
|
||||
e.Cbus8 = FT232hCBusDrive1
|
||||
e.Cbus9 = FT232hCBusDrive0
|
||||
}
|
||||
|
||||
// EEPROMFT2232H is the EEPROM layout of a FT2232H device.
|
||||
//
|
||||
// It is 40 bytes long.
|
||||
type EEPROMFT2232H struct {
|
||||
EEPROMHeader
|
||||
|
||||
// FT232H specific.
|
||||
ALSlowSlew uint8 // 0x10 bool non-zero if AL pins have slow slew
|
||||
ALSchmittInput uint8 // 0x11 bool non-zero if AL pins are Schmitt input
|
||||
ALDriveCurrent uint8 // 0x12 Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
AHSlowSlew uint8 // 0x13 bool non-zero if AH pins have slow slew
|
||||
AHSchmittInput uint8 // 0x14 bool non-zero if AH pins are Schmitt input
|
||||
AHDriveCurrent uint8 // 0x15 Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
BLSlowSlew uint8 // 0x16 bool non-zero if BL pins have slow slew
|
||||
BLSchmittInput uint8 // 0x17 bool non-zero if BL pins are Schmitt input
|
||||
BLDriveCurrent uint8 // 0x18 Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
BHSlowSlew uint8 // 0x19 bool non-zero if BH pins have slow slew
|
||||
BHSchmittInput uint8 // 0x1A bool non-zero if BH pins are Schmitt input
|
||||
BHDriveCurrent uint8 // 0x1B Valid values are 4mA, 8mA, 12mA, 16mA in 2mA units
|
||||
AIsFifo uint8 // 0x1C bool non-zero if interface is 245 FIFO
|
||||
AIsFifoTar uint8 // 0x1D bool non-zero if interface is 245 FIFO CPU target
|
||||
AIsFastSer uint8 // 0x1E bool non-zero if interface is Fast serial
|
||||
BIsFifo uint8 // 0x1F bool non-zero if interface is 245 FIFO
|
||||
BIsFifoTar uint8 // 0x20 bool non-zero if interface is 245 FIFO CPU target
|
||||
BIsFastSer uint8 // 0x21 bool non-zero if interface is Fast serial
|
||||
PowerSaveEnable uint8 // 0x22 bool non-zero if using BCBUS7 to save power for self-powered designs
|
||||
ADriverType uint8 // 0x23 bool
|
||||
BDriverType uint8 // 0x24 bool
|
||||
Unused2 uint8 // 0x25
|
||||
Unused3 uint16 // 0x26
|
||||
}
|
||||
|
||||
// EEPROMFT232R is the EEPROM layout of a FT232R device.
|
||||
//
|
||||
// It is 32 bytes long.
|
||||
type EEPROMFT232R struct {
|
||||
EEPROMHeader
|
||||
|
||||
// FT232R specific.
|
||||
IsHighCurrent uint8 // 0x10 bool High Drive I/Os; 3mA instead of 1mA (@3.3V)
|
||||
UseExtOsc uint8 // 0x11 bool Use external oscillator
|
||||
InvertTXD uint8 // 0x12 bool
|
||||
InvertRXD uint8 // 0x13 bool
|
||||
InvertRTS uint8 // 0x14 bool
|
||||
InvertCTS uint8 // 0x15 bool
|
||||
InvertDTR uint8 // 0x16 bool
|
||||
InvertDSR uint8 // 0x17 bool
|
||||
InvertDCD uint8 // 0x18 bool
|
||||
InvertRI uint8 // 0x19 bool
|
||||
Cbus0 FT232rCBusMux // 0x1A Default ft232rCBusTxLED
|
||||
Cbus1 FT232rCBusMux // 0x1B Default ft232rCBusRxLED
|
||||
Cbus2 FT232rCBusMux // 0x1C Default ft232rCBusTxdEnable
|
||||
Cbus3 FT232rCBusMux // 0x1D Default ft232rCBusPwrEnable
|
||||
Cbus4 FT232rCBusMux // 0x1E Default ft232rCBusSleep
|
||||
DriverType uint8 // 0x1F bool 0 is D2XX, 1 is VCP
|
||||
}
|
||||
|
||||
func (e *EEPROMFT232R) Defaults() {
|
||||
// As found on Adafruit device.
|
||||
e.Cbus0 = FT232rCBusTxLED
|
||||
e.Cbus1 = FT232rCBusRxLED
|
||||
e.Cbus2 = FT232rCBusTxdEnable
|
||||
e.Cbus3 = FT232rCBusPwrEnable
|
||||
e.Cbus4 = FT232rCBusSleep
|
||||
e.DriverType = 1
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// DevType is the FTDI device type.
|
||||
type DevType uint32
|
||||
|
||||
const (
|
||||
DevTypeFTBM DevType = iota // 0
|
||||
DevTypeFTAM
|
||||
DevTypeFT100AX
|
||||
DevTypeUnknown // 3
|
||||
DevTypeFT2232C
|
||||
DevTypeFT232R // 5
|
||||
DevTypeFT2232H
|
||||
DevTypeFT4232H
|
||||
DevTypeFT232H // 8
|
||||
DevTypeFTXSeries
|
||||
DevTypeFT4222H0
|
||||
DevTypeFT4222H1_2
|
||||
DevTypeFT4222H3
|
||||
DevTypeFT4222Prog
|
||||
DevTypeFT900
|
||||
DevTypeFT930
|
||||
DevTypeFTUMFTPD3A
|
||||
)
|
||||
|
||||
// EEPROMSize returns the size of the EEPROM for this device.
|
||||
func (d DevType) EEPROMSize() int {
|
||||
switch d {
|
||||
case DevTypeFT232H:
|
||||
// sizeof(EEPROMFT232H)
|
||||
return 44
|
||||
case DevTypeFT2232H:
|
||||
// sizeof(EEPROMFT2232H)
|
||||
return 40
|
||||
case DevTypeFT232R:
|
||||
// sizeof(EEPROMFT232R)
|
||||
return 32
|
||||
default:
|
||||
return 256
|
||||
}
|
||||
}
|
||||
|
||||
const devTypeName = "FTBMFTAMFT100AXUnknownFT2232CFT232RFT2232HFT4232HFT232HFTXSeriesFT4222H0FT4222H1/2FT4222H3FT4222ProgFT900FT930FTUMFTPD3A"
|
||||
|
||||
var devTypeIndex = [...]uint8{0, 4, 8, 15, 22, 29, 35, 42, 49, 55, 64, 72, 82, 90, 100, 105, 110, 120}
|
||||
|
||||
func (d DevType) String() string {
|
||||
if d >= DevType(len(devTypeIndex)-1) {
|
||||
d = DevTypeUnknown
|
||||
}
|
||||
return devTypeName[devTypeIndex[d]:devTypeIndex[d+1]]
|
||||
}
|
5
vendor/periph.io/x/host/v3/ftdi/ftdi.go
generated
vendored
5
vendor/periph.io/x/host/v3/ftdi/ftdi.go
generated
vendored
@ -1,5 +0,0 @@
|
||||
// Copyright 2021 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 ftdi
|
241
vendor/periph.io/x/host/v3/ftdi/gpio.go
generated
vendored
241
vendor/periph.io/x/host/v3/ftdi/gpio.go
generated
vendored
@ -1,241 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Emulate independent GPIOs.
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
)
|
||||
|
||||
// dbusSync is the handler of a synchronous bitbang on DBus.
|
||||
//
|
||||
// More details at:
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_232R-01_Bit_Bang_Mode_Available_For_FT232R_and_Ft245R.pdf
|
||||
type dbusSync interface {
|
||||
dbusSyncGPIOFunc(n int) string
|
||||
dbusSyncGPIOIn(n int) error
|
||||
dbusSyncGPIORead(n int) gpio.Level
|
||||
dbusSyncGPIOOut(n int, l gpio.Level) error
|
||||
}
|
||||
|
||||
// dbusPinSync represents a GPIO on a synchronous bitbang DBus.
|
||||
//
|
||||
// It is immutable and stateless.
|
||||
type dbusPinSync struct {
|
||||
n string
|
||||
num int
|
||||
bus dbusSync
|
||||
}
|
||||
|
||||
// String implements conn.Resource.
|
||||
func (s *dbusPinSync) String() string {
|
||||
return s.n
|
||||
}
|
||||
|
||||
// Halt implements conn.Resource.
|
||||
func (s *dbusPinSync) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Name implements pin.Pin.
|
||||
func (s *dbusPinSync) Name() string {
|
||||
return s.n
|
||||
}
|
||||
|
||||
// Number implements pin.Pin.
|
||||
func (s *dbusPinSync) Number() int {
|
||||
return s.num
|
||||
}
|
||||
|
||||
// Function implements pin.Pin.
|
||||
func (s *dbusPinSync) Function() string {
|
||||
return s.bus.dbusSyncGPIOFunc(s.num)
|
||||
}
|
||||
|
||||
// In implements gpio.PinIn.
|
||||
func (s *dbusPinSync) In(pull gpio.Pull, e gpio.Edge) error {
|
||||
if e != gpio.NoEdge {
|
||||
// We could support it on D5.
|
||||
return errors.New("d2xx: edge triggering is not supported")
|
||||
}
|
||||
if pull != gpio.PullUp && pull != gpio.PullNoChange {
|
||||
// EEPROM has a PullDownEnable flag.
|
||||
return errors.New("d2xx: pull is not supported")
|
||||
}
|
||||
return s.bus.dbusSyncGPIOIn(s.num)
|
||||
}
|
||||
|
||||
// Read implements gpio.PinIn.
|
||||
func (s *dbusPinSync) Read() gpio.Level {
|
||||
return s.bus.dbusSyncGPIORead(s.num)
|
||||
}
|
||||
|
||||
// WaitForEdge implements gpio.PinIn.
|
||||
func (s *dbusPinSync) WaitForEdge(t time.Duration) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// DefaultPull implements gpio.PinIn.
|
||||
func (s *dbusPinSync) DefaultPull() gpio.Pull {
|
||||
// 200kΩ
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232R.pdf
|
||||
// p. 24
|
||||
return gpio.PullUp
|
||||
}
|
||||
|
||||
// Pull implements gpio.PinIn.
|
||||
func (s *dbusPinSync) Pull() gpio.Pull {
|
||||
return gpio.PullUp
|
||||
}
|
||||
|
||||
// Out implements gpio.PinOut.
|
||||
func (s *dbusPinSync) Out(l gpio.Level) error {
|
||||
return s.bus.dbusSyncGPIOOut(s.num, l)
|
||||
}
|
||||
|
||||
// PWM implements gpio.PinOut.
|
||||
func (s *dbusPinSync) PWM(d gpio.Duty, f physic.Frequency) error {
|
||||
return errors.New("d2xx: not implemented")
|
||||
}
|
||||
|
||||
/*
|
||||
func (s *dbusPinSync) Drive() physic.ElectricCurrent {
|
||||
// optionally 3
|
||||
//return s.bus.ee.DDriveCurrent * physic.MilliAmpere
|
||||
return physic.MilliAmpere
|
||||
}
|
||||
|
||||
func (s *dbusPinSync) SlewLimit() bool {
|
||||
//return s.bus.ee.DSlowSlew
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *dbusPinSync) Hysteresis() bool {
|
||||
//return s.bus.ee.DSchmittInput
|
||||
return true
|
||||
}
|
||||
*/
|
||||
|
||||
//
|
||||
|
||||
// cBusGPIO is the handler of a CBus bitbang bus.
|
||||
//
|
||||
// This is an asynchronous mode.
|
||||
//
|
||||
// More details at:
|
||||
// http://www.ftdichip.com/Support/Knowledgebase/index.html?cbusbitbangmode.htm
|
||||
type cBusGPIO interface {
|
||||
cBusGPIOFunc(n int) string
|
||||
cBusGPIOIn(n int) error
|
||||
cBusGPIORead(n int) gpio.Level
|
||||
cBusGPIOOut(n int, l gpio.Level) error
|
||||
}
|
||||
|
||||
// cbusPin represents a GPIO on a CBus bitbang bus.
|
||||
//
|
||||
// It is immutable and stateless.
|
||||
type cbusPin struct {
|
||||
n string
|
||||
num int
|
||||
p gpio.Pull
|
||||
bus cBusGPIO
|
||||
}
|
||||
|
||||
// String implements conn.Resource.
|
||||
func (c *cbusPin) String() string {
|
||||
return c.n
|
||||
}
|
||||
|
||||
// Halt implements conn.Resource.
|
||||
func (c *cbusPin) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Name implements pin.Pin.
|
||||
func (c *cbusPin) Name() string {
|
||||
return c.n
|
||||
}
|
||||
|
||||
// Number implements pin.Pin.
|
||||
func (c *cbusPin) Number() int {
|
||||
return c.num
|
||||
}
|
||||
|
||||
// Function implements pin.Pin.
|
||||
func (c *cbusPin) Function() string {
|
||||
return c.bus.cBusGPIOFunc(c.num)
|
||||
}
|
||||
|
||||
// In implements gpio.PinIn.
|
||||
func (c *cbusPin) In(pull gpio.Pull, e gpio.Edge) error {
|
||||
if e != gpio.NoEdge {
|
||||
// We could support it on D5.
|
||||
return errors.New("d2xx: edge triggering is not supported")
|
||||
}
|
||||
if pull != c.p && pull != gpio.PullNoChange {
|
||||
// EEPROM has a PullDownEnable flag.
|
||||
return errors.New("d2xx: pull is not supported")
|
||||
}
|
||||
return c.bus.cBusGPIOIn(c.num)
|
||||
}
|
||||
|
||||
// Read implements gpio.PinIn.
|
||||
func (c *cbusPin) Read() gpio.Level {
|
||||
return c.bus.cBusGPIORead(c.num)
|
||||
}
|
||||
|
||||
// WaitForEdge implements gpio.PinIn.
|
||||
func (c *cbusPin) WaitForEdge(t time.Duration) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// DefaultPull implements gpio.PinIn.
|
||||
func (c *cbusPin) DefaultPull() gpio.Pull {
|
||||
// 200kΩ
|
||||
// http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT232R.pdf
|
||||
// p. 24
|
||||
return c.p
|
||||
}
|
||||
|
||||
// Pull implements gpio.PinIn.
|
||||
func (c *cbusPin) Pull() gpio.Pull {
|
||||
return c.p
|
||||
}
|
||||
|
||||
// Out implements gpio.PinOut.
|
||||
func (c *cbusPin) Out(l gpio.Level) error {
|
||||
return c.bus.cBusGPIOOut(c.num, l)
|
||||
}
|
||||
|
||||
// PWM implements gpio.PinOut.
|
||||
func (c *cbusPin) PWM(d gpio.Duty, f physic.Frequency) error {
|
||||
return errors.New("d2xx: not implemented")
|
||||
}
|
||||
|
||||
/*
|
||||
func (c *cbusPin) Drive() physic.ElectricCurrent {
|
||||
// optionally 3
|
||||
//return c.bus.ee.CDriveCurrent * physic.MilliAmpere
|
||||
return physic.MilliAmpere
|
||||
}
|
||||
|
||||
func (c *cbusPin) SlewLimit() bool {
|
||||
//return c.bus.ee.CSlowSlew
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *cbusPin) Hysteresis() bool {
|
||||
//return c.bus.ee.CSchmittInput
|
||||
return true
|
||||
}
|
||||
*/
|
||||
|
||||
var _ gpio.PinIO = &dbusPinSync{}
|
||||
var _ gpio.PinIO = &cbusPin{}
|
382
vendor/periph.io/x/host/v3/ftdi/handle.go
generated
vendored
382
vendor/periph.io/x/host/v3/ftdi/handle.go
generated
vendored
@ -1,382 +0,0 @@
|
||||
// Copyright 2021 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 ftdi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"periph.io/x/conn/v3/physic"
|
||||
"periph.io/x/d2xx"
|
||||
)
|
||||
|
||||
//
|
||||
|
||||
// bitMode is used by SetBitMode to change the chip behavior.
|
||||
type bitMode uint8
|
||||
|
||||
const (
|
||||
// Resets all Pins to their default value
|
||||
bitModeReset bitMode = 0x00
|
||||
// Sets the DBus to asynchronous bit-bang.
|
||||
bitModeAsyncBitbang bitMode = 0x01
|
||||
// Switch to MPSSE mode (FT2232, FT2232H, FT4232H and FT232H).
|
||||
bitModeMpsse bitMode = 0x02
|
||||
// Sets the DBus to synchronous bit-bang (FT232R, FT245R, FT2232, FT2232H,
|
||||
// FT4232H and FT232H).
|
||||
bitModeSyncBitbang bitMode = 0x04
|
||||
// Switch to MCU host bus emulation (FT2232, FT2232H, FT4232H and FT232H).
|
||||
bitModeMcuHost bitMode = 0x08
|
||||
// Switch to fast opto-isolated serial mode (FT2232, FT2232H, FT4232H and
|
||||
// FT232H).
|
||||
bitModeFastSerial bitMode = 0x10
|
||||
// Sets the CBus in 4 bits bit-bang mode (FT232R and FT232H)
|
||||
// In this case, upper nibble controls which pin is output/input, lower
|
||||
// controls which of outputs are high and low.
|
||||
bitModeCbusBitbang bitMode = 0x20
|
||||
// Single Channel Synchronous 245 FIFO mode (FT2232H and FT232H).
|
||||
bitModeSyncFifo bitMode = 0x40
|
||||
)
|
||||
|
||||
// numDevices returns the number of detected devices.
|
||||
func numDevices() (int, error) {
|
||||
num, e := d2xx.CreateDeviceInfoList()
|
||||
if e != 0 {
|
||||
return 0, toErr("GetNumDevices initialization failed", e)
|
||||
}
|
||||
return num, nil
|
||||
}
|
||||
|
||||
func openHandle(opener func(i int) (d2xx.Handle, d2xx.Err), i int) (*handle, error) {
|
||||
h, e := opener(i)
|
||||
if e != 0 {
|
||||
return nil, toErr("Open", e)
|
||||
}
|
||||
d := &handle{h: h}
|
||||
t, vid, did, e := h.GetDeviceInfo()
|
||||
if e != 0 {
|
||||
_ = d.Close()
|
||||
return nil, toErr("GetDeviceInfo", e)
|
||||
}
|
||||
d.t = DevType(t)
|
||||
d.venID = vid
|
||||
d.devID = did
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// handle is a thin wrapper around the low level d2xx device handle to make it
|
||||
// more go-idiomatic.
|
||||
//
|
||||
// It also implements many utility functions to help with initialization and
|
||||
// device management.
|
||||
type handle struct {
|
||||
// It is just above 'handle' which directly maps to D2XX function calls.
|
||||
//
|
||||
// Dev converts the int error type into Go native error and handles higher
|
||||
// level functionality like reading and writing to the USB connection.
|
||||
//
|
||||
// The content of the struct is immutable after initialization.
|
||||
h d2xx.Handle
|
||||
t DevType
|
||||
venID uint16
|
||||
devID uint16
|
||||
}
|
||||
|
||||
func (h *handle) Close() error {
|
||||
// Not yet called.
|
||||
return toErr("Close", h.h.Close())
|
||||
}
|
||||
|
||||
// Init is the general setup for common devices.
|
||||
//
|
||||
// It tries first the 'happy path' which doesn't reset the device. By doing so,
|
||||
// the goal is to reduce the amount of glitches on the GPIO pins, on a best
|
||||
// effort basis. On all devices, the GPIOs are still reset as inputs, since
|
||||
// there is no way to determine if each GPIO is an input or output.
|
||||
func (h *handle) Init() error {
|
||||
// Driver: maximum packet size. Note that this clears any data in the buffer,
|
||||
// so it is good to do it immediately after a reset. The 'out' parameter is
|
||||
// ignored.
|
||||
// TODO(maruel): The FT232H doc claims a 512 byte packets support in hi-speed
|
||||
// mode, which means that this would likely be better to use this value.
|
||||
if e := h.h.SetUSBParameters(65536, 0); e != 0 {
|
||||
return toErr("SetUSBParameters", e)
|
||||
}
|
||||
// Driver: Set I/O timeouts to 15 sec. The reason is that we want the
|
||||
// timeouts to be very visible, at least as the driver is being developed.
|
||||
if e := h.h.SetTimeouts(15000, 15000); e != 0 {
|
||||
return toErr("SetTimeouts", e)
|
||||
}
|
||||
// Not sure: Disable event/error characters.
|
||||
if e := h.h.SetChars(0, false, 0, false); e != 0 {
|
||||
return toErr("SetChars", e)
|
||||
}
|
||||
// Not sure: Latency timer at 1ms.
|
||||
if e := h.h.SetLatencyTimer(1); e != 0 {
|
||||
return toErr("SetLatencyTimer", e)
|
||||
}
|
||||
// Not sure: Turn on flow control to synchronize IN requests.
|
||||
if e := h.h.SetFlowControl(); e != 0 {
|
||||
return toErr("SetFlowControl", e)
|
||||
}
|
||||
// Just in case. It's a very small cost.
|
||||
return h.Flush()
|
||||
}
|
||||
|
||||
// Reset resets the device.
|
||||
func (h *handle) Reset() error {
|
||||
if e := h.h.ResetDevice(); e != 0 {
|
||||
return toErr("Reset", e)
|
||||
}
|
||||
if err := h.SetBitMode(0, bitModeReset); err != nil {
|
||||
return err
|
||||
}
|
||||
// USB/driver: Flush any pending read buffer that had been sent by the device
|
||||
// before it reset. Do not return any error there, as the device may spew a
|
||||
// read error right after being initialized.
|
||||
_ = h.Flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBitMode returns the current bit mode.
|
||||
//
|
||||
// This is device-dependent.
|
||||
func (h *handle) GetBitMode() (byte, error) {
|
||||
l, e := h.h.GetBitMode()
|
||||
if e != 0 {
|
||||
return 0, toErr("GetBitMode", e)
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// SetBitMode change the mode of operation of the device.
|
||||
//
|
||||
// mask sets which pins are inputs and outputs for bitModeCbusBitbang.
|
||||
func (h *handle) SetBitMode(mask byte, mode bitMode) error {
|
||||
return toErr("SetBitMode", h.h.SetBitMode(mask, byte(mode)))
|
||||
}
|
||||
|
||||
// Flush flushes any data left in the read buffer.
|
||||
func (h *handle) Flush() error {
|
||||
var buf [128]byte
|
||||
for {
|
||||
p, err := h.Read(buf[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if p == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read returns as much as available in the read buffer without blocking.
|
||||
func (h *handle) Read(b []byte) (int, error) {
|
||||
// GetQueueStatus() 60µs is relatively slow compared to Read() 4µs,
|
||||
// but surprisingly if GetQueueStatus() is *not* called, Read()
|
||||
// becomes largely slower (800µs).
|
||||
//
|
||||
// TODO(maruel): This asks for more perf testing before settling on the best
|
||||
// solution.
|
||||
// TODO(maruel): Investigate FT_GetStatus().
|
||||
p, e := h.h.GetQueueStatus()
|
||||
if p == 0 || e != 0 {
|
||||
return int(p), toErr("Read/GetQueueStatus", e)
|
||||
}
|
||||
v := int(p)
|
||||
if v > len(b) {
|
||||
v = len(b)
|
||||
}
|
||||
n, e := h.h.Read(b[:v])
|
||||
return n, toErr("Read", e)
|
||||
}
|
||||
|
||||
// ReadAll blocks to return all the data.
|
||||
//
|
||||
// Similar to ioutil.ReadAll() except that it will stop if the context is
|
||||
// canceled.
|
||||
func (h *handle) ReadAll(ctx context.Context, b []byte) (int, error) {
|
||||
// TODO(maruel): Use FT_SetEventNotification() instead of looping when
|
||||
// waiting for bytes.
|
||||
for offset := 0; offset != len(b); {
|
||||
if ctx.Err() != nil {
|
||||
return offset, io.EOF
|
||||
}
|
||||
chunk := len(b) - offset
|
||||
if chunk > 4096 {
|
||||
chunk = 4096
|
||||
}
|
||||
n, err := h.Read(b[offset : offset+chunk])
|
||||
if offset += n; err != nil {
|
||||
return offset, err
|
||||
}
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// WriteFast writes to the USB device.
|
||||
//
|
||||
// In practice this takes at least 0.1ms, which limits the effective rate.
|
||||
//
|
||||
// There's no guarantee that the data is all written, so it is important to
|
||||
// check the return value.
|
||||
func (h *handle) WriteFast(b []byte) (int, error) {
|
||||
n, e := h.h.Write(b)
|
||||
return n, toErr("Write", e)
|
||||
}
|
||||
|
||||
// Write blocks until all data is written.
|
||||
func (h *handle) Write(b []byte) (int, error) {
|
||||
for offset := 0; offset != len(b); {
|
||||
chunk := len(b) - offset
|
||||
if chunk > 4096 {
|
||||
chunk = 4096
|
||||
}
|
||||
p, err := h.WriteFast(b[offset : offset+chunk])
|
||||
if err != nil {
|
||||
return offset + p, err
|
||||
}
|
||||
if p != 0 {
|
||||
offset += p
|
||||
}
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
// ReadEEPROM reads the EEPROM.
|
||||
func (h *handle) ReadEEPROM(ee *EEPROM) error {
|
||||
// The raw data size must be exactly what the device contains.
|
||||
eepromSize := h.t.EEPROMSize()
|
||||
if len(ee.Raw) < eepromSize {
|
||||
ee.Raw = make([]byte, eepromSize)
|
||||
} else if len(ee.Raw) > eepromSize {
|
||||
ee.Raw = ee.Raw[:eepromSize]
|
||||
}
|
||||
ee2 := d2xx.EEPROM{Raw: ee.Raw}
|
||||
e := h.h.EEPROMRead(uint32(h.t), &ee2)
|
||||
ee.Manufacturer = ee2.Manufacturer
|
||||
ee.ManufacturerID = ee2.ManufacturerID
|
||||
ee.Desc = ee2.Desc
|
||||
ee.Serial = ee2.Serial
|
||||
if e != 0 {
|
||||
// 15 == FT_EEPROM_NOT_PROGRAMMED
|
||||
if e != 15 {
|
||||
return toErr("EEPROMRead", e)
|
||||
}
|
||||
// It's a fresh new device. Devices bought via Adafruit already have
|
||||
// their EEPROM programmed with Adafruit branding but fake devices sold by
|
||||
// CJMCU are not. Since GetDeviceInfo() above succeeded, we know the
|
||||
// device type via the USB descriptor, which is sufficient to load the
|
||||
// driver, which permits to program the EEPROM to "bootstrap" it.
|
||||
//
|
||||
// Fill it with an empty yet valid EEPROM content. We don't want to set
|
||||
// VenID or DevID to 0! Nobody would do that, right?
|
||||
ee.Raw = make([]byte, h.t.EEPROMSize())
|
||||
hdr := ee.AsHeader()
|
||||
hdr.DeviceType = h.t
|
||||
hdr.VendorID = h.venID
|
||||
hdr.ProductID = h.devID
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteEEPROM programs the EEPROM.
|
||||
func (h *handle) WriteEEPROM(ee *EEPROM) error {
|
||||
if err := ee.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(ee.Raw) != 0 {
|
||||
hdr := ee.AsHeader()
|
||||
if hdr == nil {
|
||||
return errors.New("ftdi: unexpected EEPROM header size")
|
||||
}
|
||||
if hdr.DeviceType != h.t {
|
||||
return errors.New("ftdi: unexpected device type set while programming EEPROM")
|
||||
}
|
||||
if hdr.VendorID != h.venID {
|
||||
return errors.New("ftdi: unexpected VenID set while programming EEPROM")
|
||||
}
|
||||
if hdr.ProductID != h.devID {
|
||||
return errors.New("ftdi: unexpected DevID set while programming EEPROM")
|
||||
}
|
||||
}
|
||||
ee2 := d2xx.EEPROM{
|
||||
Raw: ee.Raw,
|
||||
Manufacturer: ee.Manufacturer,
|
||||
ManufacturerID: ee.ManufacturerID,
|
||||
Desc: ee.Desc,
|
||||
Serial: ee.Serial,
|
||||
}
|
||||
return toErr("EEPROMWrite", h.h.EEPROMProgram(&ee2))
|
||||
}
|
||||
|
||||
// EraseEEPROM erases all the EEPROM.
|
||||
//
|
||||
// Will fail on FT232R and FT245R.
|
||||
func (h *handle) EraseEEPROM() error {
|
||||
return toErr("EraseEE", h.h.EraseEE())
|
||||
}
|
||||
|
||||
// ReadUA reads the EEPROM user area.
|
||||
//
|
||||
// May return nil when there's nothing programmed yet.
|
||||
func (h *handle) ReadUA() ([]byte, error) {
|
||||
size, e := h.h.EEUASize()
|
||||
if e != 0 {
|
||||
return nil, toErr("EEUASize", e)
|
||||
}
|
||||
if size == 0 {
|
||||
// Happens on uninitialized EEPROM.
|
||||
return nil, nil
|
||||
}
|
||||
b := make([]byte, size)
|
||||
if e := h.h.EEUARead(b); e != 0 {
|
||||
return nil, toErr("EEUARead", e)
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// WriteUA writes to the EEPROM user area.
|
||||
func (h *handle) WriteUA(ua []byte) error {
|
||||
size, e := h.h.EEUASize()
|
||||
if e != 0 {
|
||||
return toErr("EEUASize", e)
|
||||
}
|
||||
if size == 0 {
|
||||
return errors.New("ftdi: please program EEPROM first")
|
||||
}
|
||||
if size < len(ua) {
|
||||
return fmt.Errorf("ftdi: maximum user area size is %d bytes", size)
|
||||
}
|
||||
if size != len(ua) {
|
||||
b := make([]byte, size)
|
||||
copy(b, ua)
|
||||
ua = b
|
||||
}
|
||||
if e := h.h.EEUAWrite(ua); e != 0 {
|
||||
return toErr("EEUAWrite", e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetBaudRate sets the baud rate.
|
||||
func (h *handle) SetBaudRate(f physic.Frequency) error {
|
||||
if f >= physic.GigaHertz {
|
||||
return errors.New("ftdi: baud rate too high")
|
||||
}
|
||||
v := uint32(f / physic.Hertz)
|
||||
return toErr("SetBaudRate", h.h.SetBaudRate(v))
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func toErr(s string, e d2xx.Err) error {
|
||||
if e == 0 {
|
||||
return nil
|
||||
}
|
||||
return errors.New("ftdi: " + s + ": " + e.String())
|
||||
}
|
295
vendor/periph.io/x/host/v3/ftdi/i2c.go
generated
vendored
295
vendor/periph.io/x/host/v3/ftdi/i2c.go
generated
vendored
@ -1,295 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// This functionality requires MPSSE.
|
||||
//
|
||||
// Interfacing I²C:
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_113_FTDI_Hi_Speed_USB_To_I2C_Example.pdf
|
||||
//
|
||||
// Implementation based on
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_255_USB%20to%20I2C%20Example%20using%20the%20FT232H%20and%20FT201X%20devices.pdf
|
||||
//
|
||||
// Page 18: MPSSE does not automatically support clock stretching for I²C.
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"periph.io/x/conn/v3"
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/i2c"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
)
|
||||
|
||||
const i2cSCL = 1 // D0
|
||||
const i2cSDAOut = 2 // D1
|
||||
const i2cSDAIn = 4 // D2
|
||||
|
||||
type i2cBus struct {
|
||||
f *FT232H
|
||||
pullUp bool
|
||||
}
|
||||
|
||||
// Close stops I²C mode, returns to high speed mode, disable tri-state.
|
||||
func (d *i2cBus) Close() error {
|
||||
d.f.mu.Lock()
|
||||
err := d.stopI2C()
|
||||
d.f.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// Duplex implements conn.Conn.
|
||||
func (d *i2cBus) Duplex() conn.Duplex {
|
||||
return conn.Half
|
||||
}
|
||||
|
||||
func (d *i2cBus) String() string {
|
||||
return d.f.String()
|
||||
}
|
||||
|
||||
// SetSpeed implements i2c.Bus.
|
||||
func (d *i2cBus) SetSpeed(f physic.Frequency) error {
|
||||
if f > 10*physic.MegaHertz {
|
||||
return fmt.Errorf("d2xx: invalid speed %s; maximum supported clock is 10MHz", f)
|
||||
}
|
||||
if f < 100*physic.Hertz {
|
||||
return fmt.Errorf("d2xx: invalid speed %s; minimum supported clock is 100Hz; did you forget to multiply by physic.KiloHertz?", f)
|
||||
}
|
||||
d.f.mu.Lock()
|
||||
defer d.f.mu.Unlock()
|
||||
_, err := d.f.h.MPSSEClock(f * 2 / 3)
|
||||
return err
|
||||
}
|
||||
|
||||
// Tx implements i2c.Bus.
|
||||
func (d *i2cBus) Tx(addr uint16, w, r []byte) error {
|
||||
d.f.mu.Lock()
|
||||
defer d.f.mu.Unlock()
|
||||
if err := d.setI2CStart(); err != nil {
|
||||
return err
|
||||
}
|
||||
a := [1]byte{byte(addr)}
|
||||
if err := d.writeBytes(a[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(w) != 0 {
|
||||
if err := d.writeBytes(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(r) != 0 {
|
||||
if err := d.readBytes(r); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := d.setI2CStop(); err != nil {
|
||||
return err
|
||||
}
|
||||
return d.setI2CLinesIdle()
|
||||
}
|
||||
|
||||
// SCL implements i2c.Pins.
|
||||
func (d *i2cBus) SCL() gpio.PinIO {
|
||||
return d.f.D0
|
||||
}
|
||||
|
||||
// SDA implements i2c.Pins.
|
||||
func (d *i2cBus) SDA() gpio.PinIO {
|
||||
return d.f.D1
|
||||
}
|
||||
|
||||
// setupI2C initializes the MPSSE to the state to run an I²C transaction.
|
||||
//
|
||||
// Defaults to 400kHz.
|
||||
//
|
||||
// When pullUp is true; output alternates between Out(Low) and In(PullUp).
|
||||
//
|
||||
// when pullUp is false; pins are set in Tristate so Out(High) becomes float
|
||||
// instead of drive High. Low still drives low. That's called open collector.
|
||||
func (d *i2cBus) setupI2C(pullUp bool) error {
|
||||
if pullUp {
|
||||
return errors.New("d2xx: PullUp will soon be implemented")
|
||||
}
|
||||
// TODO(maruel): We could set these only *during* the I²C operation, which
|
||||
// would make more sense.
|
||||
f := 400 * physic.KiloHertz
|
||||
clk := ((30 * physic.MegaHertz / f) - 1) * 2 / 3
|
||||
|
||||
buf := [4 + 3]byte{
|
||||
clock3Phase,
|
||||
clock30MHz, byte(clk), byte(clk >> 8),
|
||||
}
|
||||
cmd := buf[:4]
|
||||
if !d.pullUp {
|
||||
// TODO(maruel): Do not mess with other GPIOs tristate.
|
||||
cmd = append(cmd, dataTristate, 7, 0)
|
||||
}
|
||||
if _, err := d.f.h.Write(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
d.f.usingI2C = true
|
||||
d.pullUp = pullUp
|
||||
return d.setI2CLinesIdle()
|
||||
}
|
||||
|
||||
// stopI2C resets the MPSSE to a more "normal" state.
|
||||
func (d *i2cBus) stopI2C() error {
|
||||
// Resets to 30MHz.
|
||||
buf := [4 + 3]byte{
|
||||
clock2Phase,
|
||||
clock30MHz, 0, 0,
|
||||
}
|
||||
cmd := buf[:4]
|
||||
if !d.pullUp {
|
||||
// TODO(maruel): Do not mess with other GPIOs tristate.
|
||||
cmd = append(cmd, dataTristate, 0, 0)
|
||||
}
|
||||
_, err := d.f.h.Write(cmd)
|
||||
d.f.usingI2C = false
|
||||
return err
|
||||
}
|
||||
|
||||
// setI2CLinesIdle sets all D0 and D1 lines high.
|
||||
//
|
||||
// Does not touch D3~D7.
|
||||
func (d *i2cBus) setI2CLinesIdle() error {
|
||||
const mask = 0xFF &^ (i2cSCL | i2cSDAOut | i2cSDAIn)
|
||||
// TODO(maruel): d.pullUp
|
||||
d.f.dbus.direction = d.f.dbus.direction&mask | i2cSCL | i2cSDAOut
|
||||
d.f.dbus.value = d.f.dbus.value & mask
|
||||
cmd := [...]byte{gpioSetD, d.f.dbus.value | i2cSCL | i2cSDAOut, d.f.dbus.direction}
|
||||
_, err := d.f.h.Write(cmd[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// setI2CStart starts an I²C transaction.
|
||||
//
|
||||
// Does not touch D3~D7.
|
||||
func (d *i2cBus) setI2CStart() error {
|
||||
// TODO(maruel): d.pullUp
|
||||
dir := d.f.dbus.direction
|
||||
v := d.f.dbus.value
|
||||
// Assumes last setup was d.setI2CLinesIdle(), e.g. D0 and D1 are high, so
|
||||
// skip this.
|
||||
//
|
||||
// Runs the command 4 times as a way to delay execution.
|
||||
cmd := [...]byte{
|
||||
// SCL high, SDA low for 600ns
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
// SCL low, SDA low
|
||||
gpioSetD, v, dir,
|
||||
gpioSetD, v, dir,
|
||||
gpioSetD, v, dir,
|
||||
}
|
||||
_, err := d.f.h.Write(cmd[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// setI2CStop completes an I²C transaction.
|
||||
//
|
||||
// Does not touch D3~D7.
|
||||
func (d *i2cBus) setI2CStop() error {
|
||||
// TODO(maruel): d.pullUp
|
||||
dir := d.f.dbus.direction
|
||||
v := d.f.dbus.value
|
||||
// Runs the command 4 times as a way to delay execution.
|
||||
cmd := [...]byte{
|
||||
// SCL low, SDA low
|
||||
gpioSetD, v, dir,
|
||||
gpioSetD, v, dir,
|
||||
gpioSetD, v, dir,
|
||||
gpioSetD, v, dir,
|
||||
// SCL high, SDA low
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
gpioSetD, v | i2cSCL, dir,
|
||||
// SCL high, SDA high
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
}
|
||||
_, err := d.f.h.Write(cmd[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// writeBytes writes multiple bytes within an I²C transaction.
|
||||
//
|
||||
// Does not touch D3~D7.
|
||||
func (d *i2cBus) writeBytes(w []byte) error {
|
||||
// TODO(maruel): d.pullUp
|
||||
dir := d.f.dbus.direction
|
||||
v := d.f.dbus.value
|
||||
// TODO(maruel): WAT?
|
||||
if err := d.f.h.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(maruel): Implement both with and without NAK check.
|
||||
var r [1]byte
|
||||
cmd := [...]byte{
|
||||
// Data out, the 0 will be replaced with the byte.
|
||||
dataOut | dataOutFall, 0, 0, 0,
|
||||
// Set back to idle.
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
// Read ACK/NAK.
|
||||
dataIn | dataBit, 0,
|
||||
flush,
|
||||
}
|
||||
for _, c := range w {
|
||||
cmd[3] = c
|
||||
if _, err := d.f.h.Write(cmd[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := d.f.h.ReadAll(context.Background(), r[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if r[0]&1 == 0 {
|
||||
return errors.New("got NAK")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readBytes reads multiple bytes within an I²C transaction.
|
||||
//
|
||||
// Does not touch D3~D7.
|
||||
func (d *i2cBus) readBytes(r []byte) error {
|
||||
// TODO(maruel): d.pullUp
|
||||
dir := d.f.dbus.direction
|
||||
v := d.f.dbus.value
|
||||
|
||||
cmd := [...]byte{
|
||||
// Read 8 bits.
|
||||
dataIn | dataBit, 7,
|
||||
// Send ACK/NAK.
|
||||
dataOut | dataOutFall | dataBit, 0, 0,
|
||||
// Set back to idle.
|
||||
gpioSetD, v | i2cSCL | i2cSDAOut, dir,
|
||||
// Force read buffer flush. This is only necessary if NAK are not ignored.
|
||||
flush,
|
||||
}
|
||||
for i := range r {
|
||||
if i == len(r)-1 {
|
||||
// NAK.
|
||||
cmd[4] = 0x80
|
||||
}
|
||||
if _, err := d.f.h.Write(cmd[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := d.f.h.ReadAll(context.Background(), r[i:1]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ i2c.BusCloser = &i2cBus{}
|
||||
var _ i2c.Pins = &i2cBus{}
|
452
vendor/periph.io/x/host/v3/ftdi/mpsse.go
generated
vendored
452
vendor/periph.io/x/host/v3/ftdi/mpsse.go
generated
vendored
@ -1,452 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// MPSSE is Multi-Protocol Synchronous Serial Engine
|
||||
//
|
||||
// MPSSE basics:
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_135_MPSSE_Basics.pdf
|
||||
//
|
||||
// MPSSE and MCU emulation modes:
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
)
|
||||
|
||||
const (
|
||||
// TDI/TDO serial operation synchronised on clock edges.
|
||||
//
|
||||
// Long streams (default):
|
||||
// - [1, 65536] bytes (length is sent minus one, requires 8 bits multiple)
|
||||
// <op>, <LengthLow-1>, <LengthHigh-1>, <byte0>, ..., <byteN>
|
||||
//
|
||||
// Short streams (dataBit is specified):
|
||||
// - [1, 8] bits
|
||||
// <op>, <Length-1>, <byte>
|
||||
//
|
||||
// When both dataOut and dataIn are specified, one of dataOutFall or
|
||||
// dataInFall should be specified, at least for most sane protocols.
|
||||
//
|
||||
// Flags:
|
||||
dataOut byte = 0x10 // Enable output, default on +VE (Rise)
|
||||
dataIn byte = 0x20 // Enable input, default on +VE (Rise)
|
||||
dataOutFall byte = 0x01 // instead of Rise
|
||||
dataInFall byte = 0x04 // instead of Rise
|
||||
dataLSBF byte = 0x08 // instead of MSBF
|
||||
dataBit byte = 0x02 // instead of Byte
|
||||
|
||||
// Data line drives low when the data is 0 and tristates on data 1. This is
|
||||
// used with I²C.
|
||||
// <op>, <ADBus pins>, <ACBus pins>
|
||||
dataTristate byte = 0x9E
|
||||
|
||||
// TSM operation (for JTAG).
|
||||
//
|
||||
// - Send bits 6 to 0 to the TMS pin using LSB or MSB.
|
||||
// - Bit 7 is passed to TDI/DO before the first clock of TMS and is held
|
||||
// static for the duration of TMS clocking.
|
||||
//
|
||||
// <op>, <Length>, <byte>
|
||||
tmsOutLSBFRise byte = 0x4A
|
||||
tmsOutLSBFFall byte = 0x4B
|
||||
tmsIOLSBInRise byte = 0x6A
|
||||
tmsIOLSBInFall byte = 0x6B
|
||||
// Unclear: 0x6E and 0x6F
|
||||
|
||||
// GPIO operation.
|
||||
//
|
||||
// - Operates on 8 GPIOs at a time, e.g. C0~C7 or D0~D7.
|
||||
// - Direction 1 means output, 0 means input.
|
||||
//
|
||||
// <op>, <value>, <direction>
|
||||
gpioSetD byte = 0x80
|
||||
gpioSetC byte = 0x82
|
||||
// <op>, returns <value>
|
||||
gpioReadD byte = 0x81
|
||||
gpioReadC byte = 0x83
|
||||
|
||||
// Internal loopback.
|
||||
//
|
||||
// Connects TDI and TDO together.
|
||||
internalLoopbackEnable byte = 0x84
|
||||
internalLoopbackDisable byte = 0x85
|
||||
|
||||
// Clock.
|
||||
//
|
||||
// The TCK/SK has a 50% duty cycle.
|
||||
//
|
||||
// The inactive clock state can be set via the gpioSetD command and control
|
||||
// bit 0.
|
||||
//
|
||||
// By default, the base clock is 6MHz via a 5x divisor. On
|
||||
// FT232H/FT2232H/FT4232H, the 5x divisor can be disabled.
|
||||
clock30MHz byte = 0x8A
|
||||
clock6MHz byte = 0x8B
|
||||
// Sets clock divisor.
|
||||
//
|
||||
// The effective value depends if clock30MHz was sent or not.
|
||||
//
|
||||
// - 0(1) 6MHz / 30MHz
|
||||
// - 1(2) 3MHz / 15MHz
|
||||
// - 2(3) 2MHz / 10MHz
|
||||
// - 3(4) 1.5MHz / 7.5MHz
|
||||
// - 4(5) 1.25MHz / 6MHz
|
||||
// - ...
|
||||
// - 0xFFFF(65536) 91.553Hz / 457.763Hz
|
||||
//
|
||||
// <op>, <valueL-1>, <valueH-1>
|
||||
clockSetDivisor byte = 0x86
|
||||
// Uses 3 phases data clocking: data is valid on both clock edges. Needed
|
||||
// for I²C.
|
||||
clock3Phase byte = 0x8C
|
||||
// Uses normal 2 phases data clocking.
|
||||
clock2Phase byte = 0x8D
|
||||
// Enables clock even while not doing any operation. Used with JTAG.
|
||||
// Enables the clock between [1, 8] pulses.
|
||||
// <op>, <length-1>
|
||||
clockOnShort byte = 0x8E
|
||||
// Enables the clock between [8, 524288] pulses in 8 multiples.
|
||||
// <op>, <lengthL-1>, <lengthH-1>
|
||||
clockOnLong byte = 0x8F
|
||||
// Enables clock until D5 is high or low. Used with JTAG.
|
||||
clockUntilHigh byte = 0x94
|
||||
clockUntilLow byte = 0x95
|
||||
// <op>, <lengthL-1>, <lengthH-1> in 8 multiples.
|
||||
clockUntilHighLong byte = 0x9C
|
||||
clockUntilLowLong byte = 0x9D
|
||||
// Enables adaptive clocking. Used with JTAG.
|
||||
//
|
||||
// This causes the controller to wait for D7 signal state as an ACK.
|
||||
clockAdaptive byte = 0x96
|
||||
// Disables adaptive clocking.
|
||||
clockNormal byte = 0x97
|
||||
|
||||
// CPU mode.
|
||||
//
|
||||
// Access the device registers like a memory mapped device.
|
||||
//
|
||||
// <op>, <addrLow>
|
||||
cpuReadShort byte = 0x90
|
||||
// <op>, <addrHi>, <addrLow>
|
||||
cpuReadFar byte = 0x91
|
||||
// <op>, <addrLow>, <data>
|
||||
cpuWriteShort byte = 0x92
|
||||
// <op>, <addrHi>, <addrLow>, <data>
|
||||
cpuWriteFar byte = 0x91
|
||||
|
||||
// Buffer operations.
|
||||
//
|
||||
// Flush the buffer back to the host.
|
||||
flush byte = 0x87
|
||||
// Wait until D5 (JTAG) or I/O1 (CPU) is high. Once it is detected as
|
||||
// high, the MPSSE engine moves on to process the next instruction.
|
||||
waitHigh byte = 0x88
|
||||
waitLow byte = 0x89
|
||||
)
|
||||
|
||||
// InitMPSSE sets the device into MPSSE mode.
|
||||
//
|
||||
// This requires a f232h, ft2232, ft2232h or a ft4232h.
|
||||
//
|
||||
// Use only one of Init or InitMPSSE.
|
||||
func (h *handle) InitMPSSE() error {
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_255_USB%20to%20I2C%20Example%20using%20the%20FT232H%20and%20FT201X%20devices.pdf
|
||||
// Pre-state:
|
||||
// - Write EEPROM i.IsFifo = true so the device DBus is started in tristate.
|
||||
|
||||
// Try to verify the MPSSE controller without initializing it first. This is
|
||||
// the 'happy path', which enables reusing the device is its current state
|
||||
// without affecting current GPIO state.
|
||||
if h.mpsseVerify() != nil {
|
||||
// Do a full reset. Just trying to set the MPSSE controller will
|
||||
// likely not work. That's a layering violation (since the retry with reset
|
||||
// is done in driver.go) but we've survived worse things...
|
||||
//
|
||||
// TODO(maruel): This is not helping in practice, this need to be fine
|
||||
// tuned.
|
||||
if err := h.Reset(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.SetBitMode(0, bitModeMpsse); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := h.mpsseVerify(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize MPSSE to a known state.
|
||||
// Reset the clock since it is impossible to read back the current clock rate.
|
||||
// Reset all the GPIOs are inputs since it is impossible to read back the
|
||||
// state of each GPIO (if they are input or output).
|
||||
cmd := []byte{
|
||||
clock30MHz, clockNormal, clock2Phase, internalLoopbackDisable,
|
||||
gpioSetC, 0x00, 0x00,
|
||||
gpioSetD, 0x00, 0x00,
|
||||
}
|
||||
if _, err := h.Write(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
// Success!!
|
||||
return nil
|
||||
}
|
||||
|
||||
// mpsseVerify sends an invalid MPSSE command and verifies the returned value
|
||||
// is incorrect.
|
||||
//
|
||||
// In practice this takes around 2ms.
|
||||
func (h *handle) mpsseVerify() error {
|
||||
var b [16]byte
|
||||
for _, v := range []byte{0xAA, 0xAB} {
|
||||
// Write a bad command and ensure it returned correctly.
|
||||
// Unlike what the application note proposes, include a flush op right
|
||||
// after. Without the flush, the device will only flush after the delay
|
||||
// specified to SetLatencyTimer. The flush removes this unneeded wait,
|
||||
// which enables increasing the delay specified to SetLatencyTimer.
|
||||
b[0] = v
|
||||
b[1] = flush
|
||||
if _, err := h.Write(b[:2]); err != nil {
|
||||
return fmt.Errorf("d2xx: mpsseVerify: %v", err)
|
||||
}
|
||||
// Sometimes, especially right after a reset, the device spews a few bytes.
|
||||
// Discard them. This significantly increases the odds of a successful
|
||||
// initialization.
|
||||
p, e := h.h.GetQueueStatus()
|
||||
if e != 0 {
|
||||
return toErr("Read/GetQueueStatus", e)
|
||||
}
|
||||
for p > 2 {
|
||||
l := int(p) - 2
|
||||
if l > len(b) {
|
||||
l = len(b)
|
||||
}
|
||||
// Discard the overflow bytes.
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
if _, err := h.ReadAll(ctx, b[:l]); err != nil {
|
||||
return fmt.Errorf("d2xx: mpsseVerify: %v", err)
|
||||
}
|
||||
p -= uint32(l)
|
||||
}
|
||||
// Custom implementation, as we want to flush any stray byte.
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
if _, err := h.ReadAll(ctx, b[:2]); err != nil {
|
||||
return fmt.Errorf("d2xx: mpsseVerify: %v", err)
|
||||
}
|
||||
// 0xFA means invalid command, 0xAA is the command echoed back.
|
||||
if b[0] != 0xFA || b[1] != v {
|
||||
return fmt.Errorf("d2xx: mpsseVerify: failed test for byte %#x: %#x", v, b)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// MPSSERegRead reads the memory mapped registers from the device.
|
||||
func (h *handle) MPSSERegRead(addr uint16) (byte, error) {
|
||||
// Unlike most other operations, the uint16 byte order is <hi>, <lo>.
|
||||
b := [...]byte{cpuReadFar, byte(addr >> 8), byte(addr), flush}
|
||||
if _, err := h.Write(b[:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
_, err := h.ReadAll(ctx, b[:1])
|
||||
return b[0], err
|
||||
}
|
||||
|
||||
// MPSSEClock sets the clock at the closest value and returns it.
|
||||
func (h *handle) MPSSEClock(f physic.Frequency) (physic.Frequency, error) {
|
||||
// TODO(maruel): Memory clock and skip if the same value.
|
||||
clk := clock30MHz
|
||||
base := 30 * physic.MegaHertz
|
||||
div := base / f
|
||||
if div >= 65536 {
|
||||
clk = clock6MHz
|
||||
base /= 5
|
||||
div = base / f
|
||||
if div >= 65536 {
|
||||
return 0, errors.New("d2xx: clock frequency is too low")
|
||||
}
|
||||
}
|
||||
b := [...]byte{clk, clockSetDivisor, byte(div - 1), byte((div - 1) >> 8)}
|
||||
_, err := h.Write(b[:])
|
||||
return base / div, err
|
||||
}
|
||||
|
||||
// mpsseTxOp returns the right MPSSE command byte for the stream.
|
||||
func mpsseTxOp(w, r bool, ew, er gpio.Edge, lsbf bool) byte {
|
||||
op := byte(0)
|
||||
if lsbf {
|
||||
op |= dataLSBF
|
||||
}
|
||||
if w {
|
||||
op |= dataOut
|
||||
if ew == gpio.FallingEdge {
|
||||
op |= dataOutFall
|
||||
}
|
||||
}
|
||||
if r {
|
||||
op |= dataIn
|
||||
if er == gpio.FallingEdge {
|
||||
op |= dataInFall
|
||||
}
|
||||
}
|
||||
return op
|
||||
}
|
||||
|
||||
// MPSSETx runs a transaction on the clock on pins D0, D1 and D2.
|
||||
//
|
||||
// It can only do it on a multiple of 8 bits.
|
||||
func (h *handle) MPSSETx(w, r []byte, ew, er gpio.Edge, lsbf bool) error {
|
||||
l := len(w)
|
||||
if len(w) != 0 {
|
||||
// TODO(maruel): This is easy to fix by daisy chaining operations.
|
||||
if len(w) > 65536 {
|
||||
return errors.New("d2xx: write buffer too long; max 65536")
|
||||
}
|
||||
}
|
||||
if len(r) != 0 {
|
||||
if len(r) > 65536 {
|
||||
return errors.New("d2xx: read buffer too long; max 65536")
|
||||
}
|
||||
if l != 0 && len(r) != l {
|
||||
return errors.New("d2xx: mismatched buffer lengths")
|
||||
}
|
||||
l = len(r)
|
||||
}
|
||||
// The FT232H has 1Kb Tx and Rx buffers. So partial writes should be done.
|
||||
// TODO(maruel): Test.
|
||||
|
||||
// Flush can be useful if rbits != 0.
|
||||
op := mpsseTxOp(len(w) != 0, len(r) != 0, ew, er, lsbf)
|
||||
cmd := []byte{op, byte(l - 1), byte((l - 1) >> 8)}
|
||||
cmd = append(cmd, w...)
|
||||
if len(r) != 0 {
|
||||
cmd = append(cmd, flush)
|
||||
}
|
||||
if _, err := h.Write(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(r) != 0 {
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
_, err := h.ReadAll(ctx, r)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MPSSETxShort runs a transaction on the clock pins D0, D1 and D2 for a byte
|
||||
// or less: between 1 and 8 bits.
|
||||
func (h *handle) MPSSETxShort(w byte, wbits, rbits int, ew, er gpio.Edge, lsbf bool) (byte, error) {
|
||||
op := byte(dataBit)
|
||||
if lsbf {
|
||||
op |= dataLSBF
|
||||
}
|
||||
l := wbits
|
||||
if wbits != 0 {
|
||||
if wbits > 8 {
|
||||
return 0, errors.New("d2xx: write buffer too long; max 8")
|
||||
}
|
||||
op |= dataOut
|
||||
if ew == gpio.FallingEdge {
|
||||
op |= dataOutFall
|
||||
}
|
||||
}
|
||||
if rbits != 0 {
|
||||
if rbits > 8 {
|
||||
return 0, errors.New("d2xx: read buffer too long; max 8")
|
||||
}
|
||||
op |= dataIn
|
||||
if er == gpio.FallingEdge {
|
||||
op |= dataInFall
|
||||
}
|
||||
if l != 0 && rbits != l {
|
||||
return 0, errors.New("d2xx: mismatched buffer lengths")
|
||||
}
|
||||
l = rbits
|
||||
}
|
||||
b := [3]byte{op, byte(l - 1)}
|
||||
cmd := b[:2]
|
||||
if wbits != 0 {
|
||||
cmd = append(cmd, w)
|
||||
}
|
||||
if rbits != 0 {
|
||||
cmd = append(cmd, flush)
|
||||
}
|
||||
if _, err := h.Write(cmd); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if rbits != 0 {
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
_, err := h.ReadAll(ctx, b[:1])
|
||||
return b[0], err
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// MPSSECBus operates on 8 GPIOs at a time C0~C7.
|
||||
//
|
||||
// Direction 1 means output, 0 means input.
|
||||
func (h *handle) MPSSECBus(mask, value byte) error {
|
||||
b := [...]byte{gpioSetC, value, mask}
|
||||
_, err := h.Write(b[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// MPSSEDBus operates on 8 GPIOs at a time D0~D7.
|
||||
//
|
||||
// Direction 1 means output, 0 means input.
|
||||
func (h *handle) MPSSEDBus(mask, value byte) error {
|
||||
b := [...]byte{gpioSetD, value, mask}
|
||||
_, err := h.Write(b[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// MPSSECBusRead reads all the CBus pins C0~C7.
|
||||
func (h *handle) MPSSECBusRead() (byte, error) {
|
||||
b := [...]byte{gpioReadC, flush}
|
||||
if _, err := h.Write(b[:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
if _, err := h.ReadAll(ctx, b[:1]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return b[0], nil
|
||||
}
|
||||
|
||||
// MPSSEDBusRead reads all the DBus pins D0~D7.
|
||||
func (h *handle) MPSSEDBusRead() (byte, error) {
|
||||
b := [...]byte{gpioReadD, flush}
|
||||
if _, err := h.Write(b[:]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
ctx, cancel := context200ms()
|
||||
defer cancel()
|
||||
if _, err := h.ReadAll(ctx, b[:1]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return b[0], nil
|
||||
}
|
||||
|
||||
func context200ms() (context.Context, func()) {
|
||||
return context.WithTimeout(context.Background(), 200*time.Millisecond)
|
||||
}
|
205
vendor/periph.io/x/host/v3/ftdi/mpsse_gpio.go
generated
vendored
205
vendor/periph.io/x/host/v3/ftdi/mpsse_gpio.go
generated
vendored
@ -1,205 +0,0 @@
|
||||
// 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 ftdi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
)
|
||||
|
||||
// gpiosMPSSE is a slice of 8 GPIO pins driven via MPSSE.
|
||||
//
|
||||
// This permits keeping a cache.
|
||||
type gpiosMPSSE struct {
|
||||
// Immutable.
|
||||
h *handle
|
||||
cbus bool // false if D bus
|
||||
pins [8]gpioMPSSE
|
||||
|
||||
// Cache of values
|
||||
direction byte
|
||||
value byte
|
||||
}
|
||||
|
||||
func (g *gpiosMPSSE) init(name string) {
|
||||
s := "D"
|
||||
if g.cbus {
|
||||
s = "C"
|
||||
}
|
||||
// Configure pulls; pull ups are 75kΩ.
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_184%20FTDI%20Device%20Input%20Output%20Pin%20States.pdf
|
||||
// has a good table.
|
||||
// D0, D2 and D4 go in high impedance before going into pull up.
|
||||
// TODO(maruel): The pull on CBus depends on EEPROM!
|
||||
for i := range g.pins {
|
||||
g.pins[i].a = g
|
||||
g.pins[i].n = name + "." + s + strconv.Itoa(i)
|
||||
g.pins[i].num = i
|
||||
g.pins[i].dp = gpio.PullUp
|
||||
}
|
||||
if g.cbus {
|
||||
// That's just the default EEPROM value.
|
||||
g.pins[7].dp = gpio.PullDown
|
||||
}
|
||||
}
|
||||
|
||||
func (g *gpiosMPSSE) in(n int) error {
|
||||
if g.h == nil {
|
||||
return errors.New("d2xx: device not open")
|
||||
}
|
||||
g.direction = g.direction & ^(1 << uint(n))
|
||||
if g.cbus {
|
||||
return g.h.MPSSECBus(g.direction, g.value)
|
||||
}
|
||||
return g.h.MPSSEDBus(g.direction, g.value)
|
||||
}
|
||||
|
||||
func (g *gpiosMPSSE) read() (byte, error) {
|
||||
if g.h == nil {
|
||||
return 0, errors.New("d2xx: device not open")
|
||||
}
|
||||
var err error
|
||||
if g.cbus {
|
||||
g.value, err = g.h.MPSSECBusRead()
|
||||
} else {
|
||||
g.value, err = g.h.MPSSEDBusRead()
|
||||
}
|
||||
return g.value, err
|
||||
}
|
||||
|
||||
func (g *gpiosMPSSE) out(n int, l gpio.Level) error {
|
||||
if g.h == nil {
|
||||
return errors.New("d2xx: device not open")
|
||||
}
|
||||
g.direction = g.direction | (1 << uint(n))
|
||||
if l {
|
||||
g.value |= 1 << uint(n)
|
||||
} else {
|
||||
g.value &^= 1 << uint(n)
|
||||
}
|
||||
if g.cbus {
|
||||
return g.h.MPSSECBus(g.direction, g.value)
|
||||
}
|
||||
return g.h.MPSSEDBus(g.direction, g.value)
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// gpioMPSSE is a GPIO pin on a FTDI device driven via MPSSE.
|
||||
//
|
||||
// gpioMPSSE implements gpio.PinIO.
|
||||
//
|
||||
// It is immutable and stateless.
|
||||
type gpioMPSSE struct {
|
||||
a *gpiosMPSSE
|
||||
n string
|
||||
num int
|
||||
dp gpio.Pull
|
||||
}
|
||||
|
||||
// String implements pin.Pin.
|
||||
func (g *gpioMPSSE) String() string {
|
||||
return g.n
|
||||
}
|
||||
|
||||
// Name implements pin.Pin.
|
||||
func (g *gpioMPSSE) Name() string {
|
||||
return g.n
|
||||
}
|
||||
|
||||
// Number implements pin.Pin.
|
||||
func (g *gpioMPSSE) Number() int {
|
||||
return g.num
|
||||
}
|
||||
|
||||
// Function implements pin.Pin.
|
||||
func (g *gpioMPSSE) Function() string {
|
||||
s := "Out/"
|
||||
m := byte(1 << uint(g.num))
|
||||
if g.a.direction&m == 0 {
|
||||
s = "In/"
|
||||
_, _ = g.a.read()
|
||||
}
|
||||
return s + gpio.Level(g.a.value&m != 0).String()
|
||||
}
|
||||
|
||||
// Halt implements gpio.PinIO.
|
||||
func (g *gpioMPSSE) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// In implements gpio.PinIn.
|
||||
func (g *gpioMPSSE) In(pull gpio.Pull, e gpio.Edge) error {
|
||||
if e != gpio.NoEdge {
|
||||
// We could support it on D5.
|
||||
return errors.New("d2xx: edge triggering is not supported")
|
||||
}
|
||||
if pull != g.dp && pull != gpio.PullNoChange {
|
||||
// TODO(maruel): This needs to be redone:
|
||||
// - EEPROM values FT232hCBusTristatePullUp and FT232hCBusPwrEnable can be
|
||||
// used to control individual CBus pins.
|
||||
// - dataTristate enables gpio.Float when set to output High, but I don't
|
||||
// know if it will enable reading the value (?). This needs to be
|
||||
// confirmed.
|
||||
return fmt.Errorf("d2xx: pull %s is not supported; try %s", pull, g.dp)
|
||||
}
|
||||
return g.a.in(g.num)
|
||||
}
|
||||
|
||||
// Read implements gpio.PinIn.
|
||||
func (g *gpioMPSSE) Read() gpio.Level {
|
||||
v, _ := g.a.read()
|
||||
return gpio.Level(v&(1<<uint(g.num)) != 0)
|
||||
}
|
||||
|
||||
// WaitForEdge implements gpio.PinIn.
|
||||
func (g *gpioMPSSE) WaitForEdge(t time.Duration) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// DefaultPull implements gpio.PinIn.
|
||||
func (g *gpioMPSSE) DefaultPull() gpio.Pull {
|
||||
return g.dp
|
||||
}
|
||||
|
||||
// Pull implements gpio.PinIn. The resistor is 75kΩ.
|
||||
func (g *gpioMPSSE) Pull() gpio.Pull {
|
||||
// See In() for the challenges.
|
||||
return g.dp
|
||||
}
|
||||
|
||||
// Out implements gpio.PinOut.
|
||||
func (g *gpioMPSSE) Out(l gpio.Level) error {
|
||||
return g.a.out(g.num, l)
|
||||
}
|
||||
|
||||
// PWM implements gpio.PinOut.
|
||||
func (g *gpioMPSSE) PWM(d gpio.Duty, f physic.Frequency) error {
|
||||
return errors.New("d2xx: not implemented")
|
||||
}
|
||||
|
||||
/*
|
||||
func (g *gpioMPSSE) Drive() physic.ElectricCurrent {
|
||||
//return g.a.ee.CDriveCurrent * physic.MilliAmpere
|
||||
return 2 * physic.MilliAmpere
|
||||
}
|
||||
|
||||
func (g *gpioMPSSE) SlewLimit() bool {
|
||||
//return g.a.ee.CSlowSlew
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *gpioMPSSE) Hysteresis() bool {
|
||||
//return g.a.ee.DSchmittInput
|
||||
return true
|
||||
}
|
||||
*/
|
||||
|
||||
var _ gpio.PinIO = &gpioMPSSE{}
|
85
vendor/periph.io/x/host/v3/ftdi/pin.go
generated
vendored
85
vendor/periph.io/x/host/v3/ftdi/pin.go
generated
vendored
@ -1,85 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// Emulate independent GPIOs.
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
)
|
||||
|
||||
// invalidPin is a non-working (not implemented) pin on a FTDI device.
|
||||
//
|
||||
// invalidPin implements gpio.PinIO.
|
||||
type invalidPin struct {
|
||||
n string
|
||||
num int
|
||||
}
|
||||
|
||||
// String implements pin.Pin.
|
||||
func (p *invalidPin) String() string {
|
||||
return p.n
|
||||
}
|
||||
|
||||
// Name implements pin.Pin.
|
||||
func (p *invalidPin) Name() string {
|
||||
return p.n
|
||||
}
|
||||
|
||||
// Number implements pin.Pin.
|
||||
func (p *invalidPin) Number() int {
|
||||
return p.num
|
||||
}
|
||||
|
||||
// Function implements pin.Pin.
|
||||
func (p *invalidPin) Function() string {
|
||||
return "N/A"
|
||||
}
|
||||
|
||||
// Halt implements gpio.PinIO.
|
||||
func (p *invalidPin) Halt() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// In implements gpio.PinIn.
|
||||
func (p *invalidPin) In(pull gpio.Pull, e gpio.Edge) error {
|
||||
return errors.New("d2xx: to be implemented")
|
||||
}
|
||||
|
||||
// Read implements gpio.PinIn.
|
||||
func (p *invalidPin) Read() gpio.Level {
|
||||
return gpio.Low
|
||||
}
|
||||
|
||||
// WaitForEdge implements gpio.PinIn.
|
||||
func (p *invalidPin) WaitForEdge(t time.Duration) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Pull implements gpio.PinIn.
|
||||
func (p *invalidPin) Pull() gpio.Pull {
|
||||
return gpio.PullNoChange
|
||||
}
|
||||
|
||||
// DefaultPull implements gpio.PinIn.
|
||||
func (p *invalidPin) DefaultPull() gpio.Pull {
|
||||
return gpio.PullNoChange
|
||||
}
|
||||
|
||||
// Out implements gpio.PinOut.
|
||||
func (p *invalidPin) Out(l gpio.Level) error {
|
||||
return errors.New("d2xx: to be implemented")
|
||||
}
|
||||
|
||||
// PWM implements gpio.PinOut.
|
||||
func (p *invalidPin) PWM(d gpio.Duty, f physic.Frequency) error {
|
||||
return errors.New("d2xx: to be implemented")
|
||||
}
|
||||
|
||||
var _ gpio.PinIO = &invalidPin{}
|
697
vendor/periph.io/x/host/v3/ftdi/spi.go
generated
vendored
697
vendor/periph.io/x/host/v3/ftdi/spi.go
generated
vendored
@ -1,697 +0,0 @@
|
||||
// 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.
|
||||
|
||||
// This functionality requires MPSSE.
|
||||
//
|
||||
// Interfacing SPI:
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_114_FTDI_Hi_Speed_USB_To_SPI_Example.pdf
|
||||
//
|
||||
// Implementation based on
|
||||
// http://www.ftdichip.com/Support/Documents/AppNotes/AN_180_FT232H%20MPSSE%20Example%20-%20USB%20Current%20Meter%20using%20the%20SPI%20interface.pdf
|
||||
|
||||
package ftdi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"periph.io/x/conn/v3"
|
||||
"periph.io/x/conn/v3/gpio"
|
||||
"periph.io/x/conn/v3/physic"
|
||||
"periph.io/x/conn/v3/spi"
|
||||
)
|
||||
|
||||
// spiMPSEEPort is an SPI port over a FTDI device in MPSSE mode using the data
|
||||
// command on the AD bus.
|
||||
type spiMPSEEPort struct {
|
||||
c spiMPSEEConn
|
||||
|
||||
// Mutable.
|
||||
maxFreq physic.Frequency
|
||||
}
|
||||
|
||||
func (s *spiMPSEEPort) Close() error {
|
||||
s.c.f.mu.Lock()
|
||||
s.c.f.usingSPI = false
|
||||
s.maxFreq = 0
|
||||
s.c.edgeInvert = false
|
||||
s.c.clkActiveLow = false
|
||||
s.c.noCS = false
|
||||
s.c.lsbFirst = false
|
||||
s.c.halfDuplex = false
|
||||
s.c.f.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *spiMPSEEPort) String() string {
|
||||
return s.c.f.String()
|
||||
}
|
||||
|
||||
// Connect implements spi.Port.
|
||||
func (s *spiMPSEEPort) Connect(f physic.Frequency, m spi.Mode, bits int) (spi.Conn, error) {
|
||||
if f > physic.GigaHertz {
|
||||
return nil, fmt.Errorf("d2xx: invalid speed %s; maximum supported clock is 30MHz", f)
|
||||
}
|
||||
if f > 30*physic.MegaHertz {
|
||||
// TODO(maruel): Figure out a way to communicate that the speed was lowered.
|
||||
// https://github.com/google/periph/issues/255
|
||||
f = 30 * physic.MegaHertz
|
||||
}
|
||||
if f < 100*physic.Hertz {
|
||||
return nil, fmt.Errorf("d2xx: invalid speed %s; minimum supported clock is 100Hz; did you forget to multiply by physic.MegaHertz?", f)
|
||||
}
|
||||
if bits&7 != 0 {
|
||||
return nil, errors.New("d2xx: bits must be multiple of 8")
|
||||
}
|
||||
if bits != 8 {
|
||||
return nil, errors.New("d2xx: implement bits per word above 8")
|
||||
}
|
||||
|
||||
s.c.f.mu.Lock()
|
||||
defer s.c.f.mu.Unlock()
|
||||
s.c.noCS = m&spi.NoCS != 0
|
||||
s.c.halfDuplex = m&spi.HalfDuplex != 0
|
||||
s.c.lsbFirst = m&spi.LSBFirst != 0
|
||||
m &^= spi.NoCS | spi.HalfDuplex | spi.LSBFirst
|
||||
if s.c.halfDuplex {
|
||||
return nil, errors.New("d2xx: spi.HalfDuplex is not yet supported (implementing wouldn't be too hard, please submit a PR")
|
||||
}
|
||||
if m < 0 || m > 3 {
|
||||
return nil, errors.New("d2xx: unknown spi mode")
|
||||
}
|
||||
s.c.edgeInvert = m&1 != 0
|
||||
s.c.clkActiveLow = m&2 != 0
|
||||
if s.maxFreq == 0 || f < s.maxFreq {
|
||||
// TODO(maruel): We could set these only *during* the SPI operation, which
|
||||
// would make more sense.
|
||||
if _, err := s.c.f.h.MPSSEClock(f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.maxFreq = f
|
||||
}
|
||||
s.c.resetIdle()
|
||||
if err := s.c.f.h.MPSSEDBus(s.c.f.dbus.direction, s.c.f.dbus.value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.c.f.usingSPI = true
|
||||
return &s.c, nil
|
||||
}
|
||||
|
||||
// LimitSpeed implements spi.Port.
|
||||
func (s *spiMPSEEPort) LimitSpeed(f physic.Frequency) error {
|
||||
if f > physic.GigaHertz {
|
||||
return fmt.Errorf("d2xx: invalid speed %s; maximum supported clock is 30MHz", f)
|
||||
}
|
||||
if f > 30*physic.MegaHertz {
|
||||
f = 30 * physic.MegaHertz
|
||||
}
|
||||
if f < 100*physic.Hertz {
|
||||
return errors.New("d2xx: minimum supported clock is 100Hz; did you forget to multiply by physic.MegaHertz?")
|
||||
}
|
||||
s.c.f.mu.Lock()
|
||||
defer s.c.f.mu.Unlock()
|
||||
if s.maxFreq != 0 && s.maxFreq <= f {
|
||||
return nil
|
||||
}
|
||||
s.maxFreq = f
|
||||
// TODO(maruel): We could set these only *during* the SPI operation, which
|
||||
// would make more sense.
|
||||
_, err := s.c.f.h.MPSSEClock(s.maxFreq)
|
||||
return err
|
||||
}
|
||||
|
||||
// CLK returns the SCK (clock) pin.
|
||||
func (s *spiMPSEEPort) CLK() gpio.PinOut {
|
||||
return s.c.CLK()
|
||||
}
|
||||
|
||||
// MOSI returns the SDO (master out, slave in) pin.
|
||||
func (s *spiMPSEEPort) MOSI() gpio.PinOut {
|
||||
return s.c.MOSI()
|
||||
}
|
||||
|
||||
// MISO returns the SDI (master in, slave out) pin.
|
||||
func (s *spiMPSEEPort) MISO() gpio.PinIn {
|
||||
return s.c.MISO()
|
||||
}
|
||||
|
||||
// CS returns the CSN (chip select) pin.
|
||||
func (s *spiMPSEEPort) CS() gpio.PinOut {
|
||||
return s.c.CS()
|
||||
}
|
||||
|
||||
type spiMPSEEConn struct {
|
||||
// Immutable.
|
||||
f *FT232H
|
||||
|
||||
// Initialized at Connect().
|
||||
edgeInvert bool // CPHA=1
|
||||
clkActiveLow bool // CPOL=1
|
||||
noCS bool // CS line is not changed
|
||||
lsbFirst bool // Default is MSB first
|
||||
halfDuplex bool // 3 wire mode
|
||||
}
|
||||
|
||||
func (s *spiMPSEEConn) String() string {
|
||||
return s.f.String()
|
||||
}
|
||||
|
||||
func (s *spiMPSEEConn) Tx(w, r []byte) error {
|
||||
var p = [1]spi.Packet{{W: w, R: r}}
|
||||
return s.TxPackets(p[:])
|
||||
}
|
||||
|
||||
func (s *spiMPSEEConn) Duplex() conn.Duplex {
|
||||
// TODO(maruel): Support half if there's a need.
|
||||
return conn.Full
|
||||
}
|
||||
|
||||
func (s *spiMPSEEConn) TxPackets(pkts []spi.Packet) error {
|
||||
// Verification.
|
||||
for _, p := range pkts {
|
||||
if p.KeepCS {
|
||||
return errors.New("d2xx: implement spi.Packet.KeepCS")
|
||||
}
|
||||
if p.BitsPerWord&7 != 0 {
|
||||
return errors.New("d2xx: bits must be a multiple of 8")
|
||||
}
|
||||
if p.BitsPerWord != 0 && p.BitsPerWord != 8 {
|
||||
return errors.New("d2xx: implement spi.Packet.BitsPerWord")
|
||||
}
|
||||
if err := verifyBuffers(p.W, p.R); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
s.f.mu.Lock()
|
||||
defer s.f.mu.Unlock()
|
||||
const clk = byte(1) << 0
|
||||
const mosi = byte(1) << 1
|
||||
const miso = byte(1) << 2
|
||||
const cs = byte(1) << 3
|
||||
s.resetIdle()
|
||||
idle := s.f.dbus.value
|
||||
start1 := idle
|
||||
if !s.noCS {
|
||||
start1 &^= cs
|
||||
}
|
||||
// In mode 0 and 2, start2 is not needed.
|
||||
start2 := start1
|
||||
stop := idle
|
||||
if s.edgeInvert {
|
||||
// This is needed to 'prime' the clock.
|
||||
start2 ^= clk
|
||||
// With mode 1 and 3, keep the clock steady while CS is being deasserted to
|
||||
// not create a spurious clock.
|
||||
stop ^= clk
|
||||
}
|
||||
ew := gpio.FallingEdge
|
||||
er := gpio.RisingEdge
|
||||
if s.edgeInvert {
|
||||
ew, er = er, ew
|
||||
}
|
||||
if s.clkActiveLow {
|
||||
// TODO(maruel): Not sure.
|
||||
ew, er = er, ew
|
||||
}
|
||||
|
||||
// FT232H claims 512 USB packet support, so to reduce the chatter over USB,
|
||||
// try to make all I/O be aligned on this amount. This also removes the need
|
||||
// for heap usage. The idea is to always trail reads by one buffer. This is
|
||||
// fine as the device has 1024 byte read buffer. Operations look like this:
|
||||
// W, W, R, W, R, W, R, R
|
||||
// This enables reducing the I/O gaps between USB packets as the device is
|
||||
// always busy with operations.
|
||||
var buf [512]byte
|
||||
cmd := buf[:0]
|
||||
keptCS := false
|
||||
|
||||
// Loop, without increasing the index.
|
||||
for _, p := range pkts {
|
||||
if len(p.W) == 0 && len(p.R) == 0 {
|
||||
continue
|
||||
}
|
||||
// TODO(maruel): s.halfDuplex.
|
||||
|
||||
if !keptCS {
|
||||
for i := 0; i < 5; i++ {
|
||||
cmd = append(cmd, gpioSetD, idle, s.f.dbus.direction)
|
||||
}
|
||||
for i := 0; i < 5; i++ {
|
||||
cmd = append(cmd, gpioSetD, start1, s.f.dbus.direction)
|
||||
}
|
||||
}
|
||||
if s.edgeInvert {
|
||||
// This is needed to 'prime' the clock.
|
||||
for i := 0; i < 5; i++ {
|
||||
cmd = append(cmd, gpioSetD, start2, s.f.dbus.direction)
|
||||
}
|
||||
}
|
||||
op := mpsseTxOp(len(p.W) != 0, len(p.R) != 0, ew, er, s.lsbFirst)
|
||||
|
||||
// Do an I/O loop. We can mutate p here because it is a copy.
|
||||
// TODO(maruel): Have the pipeline cross the packet boundary.
|
||||
if len(p.W) == 0 {
|
||||
// Have the write buffer point to the read one. This saves from
|
||||
// allocating memory. The side effect is that it will write whatever
|
||||
// happened to be in the read buffer.
|
||||
p.W = p.R[:]
|
||||
}
|
||||
pendingRead := 0
|
||||
for len(p.W) != 0 {
|
||||
// op, sizelo, sizehi.
|
||||
chunk := len(buf) - 3 - len(cmd)
|
||||
if l := len(p.W); chunk > l {
|
||||
chunk = l
|
||||
}
|
||||
cmd = append(cmd, op, byte(chunk-1), byte((chunk-1)>>8))
|
||||
cmd = append(cmd, p.W[:chunk]...)
|
||||
p.W = p.W[chunk:]
|
||||
if _, err := s.f.h.WriteFast(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
cmd = buf[:0]
|
||||
|
||||
// TODO(maruel): Read 62 bytes at a time?
|
||||
// Delay reading by 512 bytes.
|
||||
if pendingRead >= 512 {
|
||||
if len(p.R) != 0 {
|
||||
// Align reads on 512 bytes exactly, aligned on USB packet size.
|
||||
if _, err := s.f.h.ReadAll(context.Background(), p.R[:512]); err != nil {
|
||||
return err
|
||||
}
|
||||
p.R = p.R[512:]
|
||||
pendingRead -= 512
|
||||
}
|
||||
}
|
||||
pendingRead += chunk
|
||||
}
|
||||
// Do not forget to read whatever is pending.
|
||||
// TODO(maruel): Investigate if a flush helps.
|
||||
if len(p.R) != 0 {
|
||||
// Send a flush to not wait for data.
|
||||
cmd = append(cmd, flush)
|
||||
if _, err := s.f.h.WriteFast(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
cmd = buf[:0]
|
||||
if _, err := s.f.h.ReadAll(context.Background(), p.R); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// TODO(maruel): Inject this in the write if it fits (it will generally
|
||||
// do). That will save one USB I/O, which is not insignificant.
|
||||
keptCS = p.KeepCS
|
||||
if !keptCS {
|
||||
cmd = append(cmd, flush)
|
||||
for i := 0; i < 5; i++ {
|
||||
cmd = append(cmd, gpioSetD, stop, s.f.dbus.direction)
|
||||
}
|
||||
for i := 0; i < 5; i++ {
|
||||
cmd = append(cmd, gpioSetD, idle, s.f.dbus.direction)
|
||||
}
|
||||
if _, err := s.f.h.WriteFast(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
cmd = buf[:0]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CLK returns the SCK (clock) pin.
|
||||
func (s *spiMPSEEConn) CLK() gpio.PinOut {
|
||||
return s.f.D0
|
||||
}
|
||||
|
||||
// MOSI returns the SDO (master out, slave in) pin.
|
||||
func (s *spiMPSEEConn) MOSI() gpio.PinOut {
|
||||
return s.f.D1
|
||||
}
|
||||
|
||||
// MISO returns the SDI (master in, slave out) pin.
|
||||
func (s *spiMPSEEConn) MISO() gpio.PinIn {
|
||||
return s.f.D2
|
||||
}
|
||||
|
||||
// CS returns the CSN (chip select) pin.
|
||||
func (s *spiMPSEEConn) CS() gpio.PinOut {
|
||||
return s.f.D3
|
||||
}
|
||||
|
||||
// resetIdle sets D0~D3. D0, D1 and D3 are output but only touch D3 is CS is
|
||||
// used.
|
||||
func (s *spiMPSEEConn) resetIdle() {
|
||||
const clk = byte(1) << 0
|
||||
const mosi = byte(1) << 1
|
||||
const miso = byte(1) << 2
|
||||
const cs = byte(1) << 3
|
||||
if !s.noCS {
|
||||
s.f.dbus.direction &= 0xF0
|
||||
s.f.dbus.direction |= cs
|
||||
s.f.dbus.value &= 0xF0
|
||||
s.f.dbus.value |= cs
|
||||
} else {
|
||||
s.f.dbus.value &= 0xF8
|
||||
s.f.dbus.direction &= 0xF8
|
||||
}
|
||||
s.f.dbus.direction |= mosi | clk
|
||||
if s.clkActiveLow {
|
||||
// Clock idles high.
|
||||
s.f.dbus.value |= clk
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// spiSyncPort is an SPI port over a FTDI device in synchronous bit-bang mode.
|
||||
type spiSyncPort struct {
|
||||
c spiSyncConn
|
||||
|
||||
// Mutable.
|
||||
maxFreq physic.Frequency
|
||||
}
|
||||
|
||||
func (s *spiSyncPort) Close() error {
|
||||
s.c.f.mu.Lock()
|
||||
s.c.f.usingSPI = false
|
||||
s.maxFreq = 0
|
||||
s.c.edgeInvert = false
|
||||
s.c.clkActiveLow = false
|
||||
s.c.noCS = false
|
||||
s.c.lsbFirst = false
|
||||
s.c.halfDuplex = false
|
||||
s.c.f.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *spiSyncPort) String() string {
|
||||
return s.c.f.String()
|
||||
}
|
||||
|
||||
const ft232rMaxSpeed = 3 * physic.MegaHertz
|
||||
|
||||
// Connect implements spi.Port.
|
||||
func (s *spiSyncPort) Connect(f physic.Frequency, m spi.Mode, bits int) (spi.Conn, error) {
|
||||
if f > physic.GigaHertz {
|
||||
return nil, fmt.Errorf("d2xx: invalid speed %s; maximum supported clock is 1.5MHz", f)
|
||||
}
|
||||
if f > ft232rMaxSpeed/2 {
|
||||
// TODO(maruel): Figure out a way to communicate that the speed was lowered.
|
||||
// https://github.com/google/periph/issues/255
|
||||
f = ft232rMaxSpeed / 2
|
||||
}
|
||||
if f < 100*physic.Hertz {
|
||||
return nil, fmt.Errorf("d2xx: invalid speed %s; minimum supported clock is 100Hz; did you forget to multiply by physic.MegaHertz?", f)
|
||||
}
|
||||
if bits&7 != 0 {
|
||||
return nil, errors.New("d2xx: bits must be multiple of 8")
|
||||
}
|
||||
if bits != 8 {
|
||||
return nil, errors.New("d2xx: implement bits per word above 8")
|
||||
}
|
||||
|
||||
s.c.f.mu.Lock()
|
||||
defer s.c.f.mu.Unlock()
|
||||
s.c.noCS = m&spi.NoCS != 0
|
||||
s.c.halfDuplex = m&spi.HalfDuplex != 0
|
||||
s.c.lsbFirst = m&spi.LSBFirst != 0
|
||||
m &^= spi.NoCS | spi.HalfDuplex | spi.LSBFirst
|
||||
if s.c.halfDuplex {
|
||||
return nil, errors.New("d2xx: spi.HalfDuplex is not yet supported (implementing wouldn't be too hard, please submit a PR")
|
||||
}
|
||||
if m < 0 || m > 3 {
|
||||
return nil, errors.New("d2xx: unknown spi mode")
|
||||
}
|
||||
s.c.edgeInvert = m&1 != 0
|
||||
s.c.clkActiveLow = m&2 != 0
|
||||
if s.maxFreq == 0 || f < s.maxFreq {
|
||||
if err := s.c.f.SetSpeed(f * 2); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s.maxFreq = f
|
||||
}
|
||||
// D0, D2 and D3 are output. D4~D7 are kept as-is.
|
||||
const mosi = byte(1) << 0 // TX
|
||||
const miso = byte(1) << 1 // RX
|
||||
const clk = byte(1) << 2 // RTS
|
||||
const cs = byte(1) << 3 // CTS
|
||||
mask := mosi | clk | cs | (s.c.f.dmask & 0xF0)
|
||||
if err := s.c.f.setDBusMaskLocked(mask); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO(maruel): Combine both following calls if possible. We'd shave off a
|
||||
// few ms.
|
||||
if !s.c.noCS {
|
||||
// CTS/SPI_CS is active low.
|
||||
if err := s.c.f.dbusSyncGPIOOutLocked(3, gpio.High); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if s.c.clkActiveLow {
|
||||
// RTS/SPI_CLK is active low.
|
||||
if err := s.c.f.dbusSyncGPIOOutLocked(2, gpio.High); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
s.c.f.usingSPI = true
|
||||
return &s.c, nil
|
||||
}
|
||||
|
||||
// LimitSpeed implements spi.Port.
|
||||
func (s *spiSyncPort) LimitSpeed(f physic.Frequency) error {
|
||||
if f > physic.GigaHertz {
|
||||
return fmt.Errorf("d2xx: invalid speed %s; maximum supported clock is 1.5MHz", f)
|
||||
}
|
||||
if f < 100*physic.Hertz {
|
||||
return fmt.Errorf("d2xx: invalid speed %s; minimum supported clock is 100Hz; did you forget to multiply by physic.MegaHertz?", f)
|
||||
}
|
||||
s.c.f.mu.Lock()
|
||||
defer s.c.f.mu.Unlock()
|
||||
if s.maxFreq != 0 && s.maxFreq <= f {
|
||||
return nil
|
||||
}
|
||||
if err := s.c.f.SetSpeed(f * 2); err == nil {
|
||||
s.maxFreq = f
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CLK returns the SCK (clock) pin.
|
||||
func (s *spiSyncPort) CLK() gpio.PinOut {
|
||||
return s.c.CLK()
|
||||
}
|
||||
|
||||
// MOSI returns the SDO (master out, slave in) pin.
|
||||
func (s *spiSyncPort) MOSI() gpio.PinOut {
|
||||
return s.c.MOSI()
|
||||
}
|
||||
|
||||
// MISO returns the SDI (master in, slave out) pin.
|
||||
func (s *spiSyncPort) MISO() gpio.PinIn {
|
||||
return s.c.MISO()
|
||||
}
|
||||
|
||||
// CS returns the CSN (chip select) pin.
|
||||
func (s *spiSyncPort) CS() gpio.PinOut {
|
||||
return s.c.CS()
|
||||
}
|
||||
|
||||
type spiSyncConn struct {
|
||||
// Immutable.
|
||||
f *FT232R
|
||||
|
||||
// Initialized at Connect().
|
||||
edgeInvert bool // CPHA=1
|
||||
clkActiveLow bool // CPOL=1
|
||||
noCS bool // CS line is not changed
|
||||
lsbFirst bool // Default is MSB first
|
||||
halfDuplex bool // 3 wire mode
|
||||
}
|
||||
|
||||
func (s *spiSyncConn) String() string {
|
||||
return s.f.String()
|
||||
}
|
||||
|
||||
func (s *spiSyncConn) Tx(w, r []byte) error {
|
||||
var p = [1]spi.Packet{{W: w, R: r}}
|
||||
return s.TxPackets(p[:])
|
||||
}
|
||||
|
||||
func (s *spiSyncConn) Duplex() conn.Duplex {
|
||||
// TODO(maruel): Support half if there's a need.
|
||||
return conn.Full
|
||||
}
|
||||
|
||||
func (s *spiSyncConn) TxPackets(pkts []spi.Packet) error {
|
||||
// We need to 'expand' each bit 2 times * 8 bits, which leads
|
||||
// to a 16x memory usage increase. Adds 5 samples before and after.
|
||||
totalW := 0
|
||||
totalR := 0
|
||||
for _, p := range pkts {
|
||||
if p.KeepCS {
|
||||
return errors.New("d2xx: implement spi.Packet.KeepCS")
|
||||
}
|
||||
if p.BitsPerWord&7 != 0 {
|
||||
return errors.New("d2xx: bits must be a multiple of 8")
|
||||
}
|
||||
if p.BitsPerWord != 0 && p.BitsPerWord != 8 {
|
||||
return errors.New("d2xx: implement spi.Packet.BitsPerWord")
|
||||
}
|
||||
if err := verifyBuffers(p.W, p.R); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(maruel): Correctly calculate offsets.
|
||||
if len(p.W) != 0 {
|
||||
totalW += 2 * 8 * len(p.W)
|
||||
}
|
||||
if len(p.R) != 0 {
|
||||
totalR += 2 * 8 * len(p.R)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a large, single chunk.
|
||||
var we, re []byte
|
||||
if totalW != 0 {
|
||||
totalW += 10
|
||||
we = make([]byte, 0, totalW)
|
||||
}
|
||||
if totalR != 0 {
|
||||
totalR += 10
|
||||
re = make([]byte, totalR)
|
||||
}
|
||||
const mosi = byte(1) << 0 // TX
|
||||
const miso = byte(1) << 1 // RX
|
||||
const clk = byte(1) << 2 // RTS
|
||||
const cs = byte(1) << 3 // CTS
|
||||
|
||||
s.f.mu.Lock()
|
||||
defer s.f.mu.Unlock()
|
||||
|
||||
// https://en.wikipedia.org/wiki/Serial_Peripheral_Interface#Data_transmission
|
||||
|
||||
csActive := s.f.dvalue & s.f.dmask & 0xF0
|
||||
csIdle := csActive
|
||||
if !s.noCS {
|
||||
csIdle = csActive | cs
|
||||
}
|
||||
clkIdle := csActive
|
||||
clkActive := clkIdle | clk
|
||||
if s.clkActiveLow {
|
||||
clkActive, clkIdle = clkIdle, clkActive
|
||||
csIdle |= clk
|
||||
}
|
||||
// Start of tx; assert CS if needed.
|
||||
we = append(we, csIdle, clkIdle, clkIdle, clkIdle, clkIdle)
|
||||
for _, p := range pkts {
|
||||
if len(p.W) == 0 && len(p.R) == 0 {
|
||||
continue
|
||||
}
|
||||
// TODO(maruel): s.halfDuplex.
|
||||
for _, b := range p.W {
|
||||
for j := uint(0); j < 8; j++ {
|
||||
// For each bit, handle clock phase and data phase.
|
||||
bit := byte(0)
|
||||
if !s.lsbFirst {
|
||||
// MSBF
|
||||
if b&(0x80>>j) != 0 {
|
||||
bit = mosi
|
||||
}
|
||||
} else {
|
||||
// LSBF
|
||||
if b&(1<<j) != 0 {
|
||||
bit = mosi
|
||||
}
|
||||
}
|
||||
if !s.edgeInvert {
|
||||
// Mode0/2; CPHA=0
|
||||
we = append(we, clkIdle|bit, clkActive|bit)
|
||||
} else {
|
||||
// Mode1/3; CPHA=1
|
||||
we = append(we, clkActive|bit, clkIdle|bit)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// End of tx; deassert CS.
|
||||
we = append(we, clkIdle, clkIdle, clkIdle, clkIdle, csIdle)
|
||||
|
||||
if err := s.f.txLocked(we, re); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Extract data from re into r.
|
||||
for _, p := range pkts {
|
||||
// TODO(maruel): Correctly calculate offsets.
|
||||
if len(p.W) == 0 && len(p.R) == 0 {
|
||||
continue
|
||||
}
|
||||
// TODO(maruel): halfDuplex.
|
||||
for i := range p.R {
|
||||
// For each bit, read at the right data phase.
|
||||
b := byte(0)
|
||||
for j := 0; j < 8; j++ {
|
||||
if re[5+i*8*2+j*2+1]&byte(1)<<1 != 0 {
|
||||
if !s.lsbFirst {
|
||||
// MSBF
|
||||
b |= 0x80 >> uint(j)
|
||||
} else {
|
||||
// LSBF
|
||||
b |= 1 << uint(j)
|
||||
}
|
||||
}
|
||||
}
|
||||
p.R[i] = b
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CLK returns the SCK (clock) pin.
|
||||
func (s *spiSyncConn) CLK() gpio.PinOut {
|
||||
return s.f.D2 // RTS
|
||||
}
|
||||
|
||||
// MOSI returns the SDO (master out, slave in) pin.
|
||||
func (s *spiSyncConn) MOSI() gpio.PinOut {
|
||||
return s.f.D0 // TX
|
||||
}
|
||||
|
||||
// MISO returns the SDI (master in, slave out) pin.
|
||||
func (s *spiSyncConn) MISO() gpio.PinIn {
|
||||
return s.f.D1 // RX
|
||||
}
|
||||
|
||||
// CS returns the CSN (chip select) pin.
|
||||
func (s *spiSyncConn) CS() gpio.PinOut {
|
||||
return s.f.D3 // CTS
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
func verifyBuffers(w, r []byte) error {
|
||||
if len(w) != 0 {
|
||||
if len(r) != 0 {
|
||||
if len(w) != len(r) {
|
||||
return errors.New("d2xx: both buffers must have the same size")
|
||||
}
|
||||
}
|
||||
// TODO(maruel): When the buffer is >64Kb, cut it in parts and do not
|
||||
// request a flush. Still try to read though.
|
||||
if len(w) > 65536 {
|
||||
return errors.New("d2xx: maximum buffer size is 64Kb")
|
||||
}
|
||||
} else if len(r) != 0 {
|
||||
// TODO(maruel): Remove, this is not a problem.
|
||||
if len(r) > 65536 {
|
||||
return errors.New("d2xx: maximum buffer size is 64Kb")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var _ spi.PortCloser = &spiMPSEEPort{}
|
||||
var _ spi.Conn = &spiMPSEEConn{}
|
||||
var _ spi.PortCloser = &spiSyncPort{}
|
||||
var _ spi.Conn = &spiSyncConn{}
|
4
vendor/periph.io/x/host/v3/host.go
generated
vendored
4
vendor/periph.io/x/host/v3/host.go
generated
vendored
@ -6,7 +6,9 @@ package host
|
||||
|
||||
import (
|
||||
"periph.io/x/conn/v3/driver/driverreg"
|
||||
_ "periph.io/x/host/v3/ftdi"
|
||||
// TODO(maruel): For now do not include ftdi by default. It's not stable
|
||||
// enough to warrant being included.
|
||||
// _ "periph.io/x/host/v3/ftdi"
|
||||
)
|
||||
|
||||
// Init calls driverreg.Init() and returns it as-is.
|
||||
|
1
vendor/periph.io/x/host/v3/odroidc1/odroidc1_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/odroidc1/odroidc1_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm
|
||||
// +build !arm
|
||||
|
||||
package odroidc1
|
||||
|
1
vendor/periph.io/x/host/v3/pine64/pine64_arm64.go
generated
vendored
1
vendor/periph.io/x/host/v3/pine64/pine64_arm64.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package pine64
|
||||
|
1
vendor/periph.io/x/host/v3/pine64/pine64_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/pine64/pine64_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm && !arm64
|
||||
// +build !arm,!arm64
|
||||
|
||||
package pine64
|
||||
|
1
vendor/periph.io/x/host/v3/pmem/mem_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/pmem/mem_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package pmem
|
||||
|
12
vendor/periph.io/x/host/v3/rpi/rpi.go
generated
vendored
12
vendor/periph.io/x/host/v3/rpi/rpi.go
generated
vendored
@ -384,6 +384,7 @@ const (
|
||||
memory1GB revisionCode = 2 << memoryShift
|
||||
memory2GB revisionCode = 3 << memoryShift
|
||||
memory4GB revisionCode = 4 << memoryShift
|
||||
memory8GB revisionCode = 5 << memoryShift
|
||||
|
||||
sonyUK revisionCode = 0 << manufacturerShift
|
||||
egoman revisionCode = 1 << manufacturerShift
|
||||
@ -413,6 +414,9 @@ const (
|
||||
boardReserved revisionCode = 0xf << boardShift
|
||||
boardCM3Plus revisionCode = 0x10 << boardShift
|
||||
board4B revisionCode = 0x11 << boardShift
|
||||
boardZero2W revisionCode = 0x12 << boardShift
|
||||
board400 revisionCode = 0x13 << boardShift
|
||||
boardCM4 revisionCode = 0x14 << boardShift
|
||||
)
|
||||
|
||||
// features represents the different features on various Raspberry Pi boards.
|
||||
@ -502,6 +506,14 @@ func (f *features) init(v uint32) error {
|
||||
f.hdrAudio = true
|
||||
f.audioLeft41 = true
|
||||
f.hdrHDMI = true
|
||||
case boardZero2W:
|
||||
f.hdrP1P40 = true
|
||||
f.hdrHDMI = true
|
||||
case board400:
|
||||
f.hdrP1P40 = true
|
||||
f.hdrHDMI = true
|
||||
case boardCM4:
|
||||
// Compute Module does not have a SODIMM header.
|
||||
default:
|
||||
return fmt.Errorf("rpi: unknown hardware version: 0x%x", r)
|
||||
}
|
||||
|
1
vendor/periph.io/x/host/v3/rpi/rpi_arm64.go
generated
vendored
1
vendor/periph.io/x/host/v3/rpi/rpi_arm64.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package rpi
|
||||
|
1
vendor/periph.io/x/host/v3/rpi/rpi_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/rpi/rpi_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !arm && !arm64
|
||||
// +build !arm,!arm64
|
||||
|
||||
package rpi
|
||||
|
1
vendor/periph.io/x/host/v3/sysfs/fs_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/sysfs/fs_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package sysfs
|
||||
|
1
vendor/periph.io/x/host/v3/sysfs/sysfs_other.go
generated
vendored
1
vendor/periph.io/x/host/v3/sysfs/sysfs_other.go
generated
vendored
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed under the Apache License, Version 2.0
|
||||
// that can be found in the LICENSE file.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package sysfs
|
||||
|
Loading…
x
Reference in New Issue
Block a user