whatcanGOwrong

This commit is contained in:
2024-09-19 21:38:24 -04:00
commit d0ae4d841d
17908 changed files with 4096831 additions and 0 deletions
@@ -0,0 +1,177 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux
// +build linux
package spi
import (
"fmt"
"os"
"syscall"
"unsafe"
"golang.org/x/exp/io/spi/driver"
)
const (
devfs_MAGIC = 107
devfs_NRBITS = 8
devfs_TYPEBITS = 8
devfs_SIZEBITS = 13
devfs_DIRBITS = 3
devfs_NRSHIFT = 0
devfs_TYPESHIFT = devfs_NRSHIFT + devfs_NRBITS
devfs_SIZESHIFT = devfs_TYPESHIFT + devfs_TYPEBITS
devfs_DIRSHIFT = devfs_SIZESHIFT + devfs_SIZEBITS
devfs_READ = 2
devfs_WRITE = 4
)
type payload struct {
tx uint64
rx uint64
length uint32
speed uint32
delay uint16
bits uint8
csChange uint8
txNBits uint8
rxNBits uint8
pad uint16
}
// Devfs is an SPI driver that works against the devfs.
// You need to have loaded the "spidev" Linux module to use this driver.
type Devfs struct {
// Dev is the device to be opened.
// Device name is usually in the /dev/spidev<bus>.<chip> format.
// Required.
Dev string
// Mode is the SPI mode. SPI mode is a combination of polarity and phases.
// CPOL is the high order bit, CPHA is the low order. Pre-computed mode
// values are Mode0, Mode1, Mode2 and Mode3. The value of the mode argument
// can be overridden by the device's driver.
// Required.
Mode Mode
// MaxSpeed is the max clock speed (Hz) and can be overridden by the device's driver.
// Required.
MaxSpeed int64
}
// Open opens the provided device with the specified options
// and returns a connection.
func (d *Devfs) Open() (driver.Conn, error) {
f, err := os.OpenFile(d.Dev, os.O_RDWR, os.ModeDevice)
if err != nil {
return nil, err
}
conn := &devfsConn{f: f}
if err := conn.Configure(driver.Mode, int(d.Mode)); err != nil {
conn.Close()
return nil, err
}
if err := conn.Configure(driver.MaxSpeed, int(d.MaxSpeed)); err != nil {
conn.Close()
return nil, err
}
return conn, nil
}
type devfsConn struct {
f *os.File
mode uint8
speed uint32
bits uint8
delay uint16
csChange uint8
}
func (c *devfsConn) Configure(k, v int) error {
switch k {
case driver.Mode:
m := uint8(v)
if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 1, 1), uintptr(unsafe.Pointer(&m))); err != nil {
return fmt.Errorf("error setting mode to %v: %v", m, err)
}
c.mode = m
case driver.Bits:
b := uint8(v)
if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 3, 1), uintptr(unsafe.Pointer(&b))); err != nil {
return fmt.Errorf("error setting bits per word to %v: %v", b, err)
}
c.bits = b
case driver.MaxSpeed:
s := uint32(v)
if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 4, 4), uintptr(unsafe.Pointer(&s))); err != nil {
return fmt.Errorf("error setting speed to %v: %v", s, err)
}
c.speed = s
case driver.Order:
o := uint8(v)
if err := c.ioctl(requestCode(devfs_WRITE, devfs_MAGIC, 2, 1), uintptr(unsafe.Pointer(&o))); err != nil {
return fmt.Errorf("error setting bit order to %v: %v", o, err)
}
case driver.Delay:
c.delay = uint16(v)
case driver.CSChange:
c.csChange = uint8(v)
default:
return fmt.Errorf("unknown key: %v", k)
}
return nil
}
func (c *devfsConn) Tx(w, r []byte) error {
if r == nil {
r = make([]byte, len(w))
}
// TODO(jbd): len(w) == len(r)?
// TODO(jbd): Allow nil w.
p := payload{
tx: uint64(uintptr(unsafe.Pointer(&w[0]))),
rx: uint64(uintptr(unsafe.Pointer(&r[0]))),
length: uint32(len(w)),
speed: c.speed,
delay: c.delay,
bits: c.bits,
csChange: c.csChange,
}
// TODO(jbd): Read from the device and fill rx.
return c.ioctl(msgRequestCode(1), uintptr(unsafe.Pointer(&p)))
}
func (c *devfsConn) Close() error {
return c.f.Close()
}
// requestCode returns the device specific request code for the specified direction,
// type, number and size to be used in the ioctl call.
func requestCode(dir, typ, nr, size uintptr) uintptr {
return (dir << devfs_DIRSHIFT) | (typ << devfs_TYPESHIFT) | (nr << devfs_NRSHIFT) | (size << devfs_SIZESHIFT)
}
// msgRequestCode returns the device specific value for the SPI
// message payload to be used in the ioctl call.
// n represents the number of messages.
func msgRequestCode(n uint32) uintptr {
return uintptr(0x40006B00 + (n * 0x200000))
}
// ioctl makes an IOCTL on the open device file descriptor.
func (c *devfsConn) ioctl(a1, a2 uintptr) error {
_, _, errno := syscall.Syscall(
syscall.SYS_IOCTL, c.f.Fd(), a1, a2,
)
if errno != 0 {
return syscall.Errno(errno)
}
return nil
}
@@ -0,0 +1,40 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !linux
// +build !linux
package spi
import (
"errors"
"golang.org/x/exp/io/spi/driver"
)
// Devfs is a no-implementation of an SPI driver that works against the devfs.
// You need to have loaded the Linux "spidev" module to use this driver.
type Devfs struct {
// Dev is the device to be opened.
// Device name is usually in the /dev/spidev<bus>.<chip> format.
// Required.
Dev string
// Mode is the SPI mode. SPI mode is a combination of polarity and phases.
// CPOL is the high order bit, CPHA is the low order. Pre-computed mode
// values are Mode0, Mode1, Mode2 and Mode3. The value of the mode argument
// can be overridden by the device's driver.
// Required.
Mode Mode
// MaxSpeed is the max clock speed (Hz) and can be overridden by the device's driver.
// Required.
MaxSpeed int64
}
// Open opens the provided device with the speicifed options
// and returns a connection.
func (d *Devfs) Open() (driver.Conn, error) {
return nil, errors.New("not implemented on this platform")
}
@@ -0,0 +1,50 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package driver contains interfaces to be implemented by various SPI implementations.
package driver // import "golang.org/x/exp/io/spi/driver"
const (
Mode = iota
Bits
MaxSpeed
Order
Delay
CSChange
)
// Opener is an interface to be implemented by the SPI driver to open
// a connection to an SPI device.
type Opener interface {
Open() (Conn, error)
}
// Conn is a connection to an SPI device.
// TODO(jbd): Extend the interface to query configuration values.
type Conn interface {
// Configure configures the SPI device.
//
// Available configuration keys are:
// - Mode, the SPI mode (valid values are 0, 1, 2 and 3).
// - Bits, bits per word (default is 8-bit per word).
// - Speed, the max clock speed (in Hz).
// - Order, bit order to be used in transfers. Zero value represents
// the MSB-first, non-zero values represent LSB-first encoding.
// - Delay, the pause time between frames (in usecs).
// Some SPI devices require a minimum amount of wait time after
// each frame write. If set, Delay amount of usecs are inserted after
// each write.
// - CSChange, whether to leave the device's chipselect active after a Tx.
//
// SPI devices can override these values.
Configure(k, v int) error
// Tx performs a SPI transaction: w is written if not nil, the result is
// put into r if not nil. len(w) must be equal to len(r), otherwise the
// driver should return an error.
Tx(w, r []byte) error
// Close frees the underlying resources and closes the connection.
Close() error
}
@@ -0,0 +1,38 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package spi_test
import "golang.org/x/exp/io/spi"
// Example illustrates a program that drives an APA-102 LED strip.
func Example() {
dev, err := spi.Open(&spi.Devfs{
Dev: "/dev/spidev0.1",
Mode: spi.Mode3,
MaxSpeed: 500000,
})
if err != nil {
panic(err)
}
defer dev.Close()
if err := dev.Tx([]byte{
0, 0, 0, 0,
0xff, 200, 0, 200,
0xff, 200, 0, 200,
0xe0, 200, 0, 200,
0xff, 200, 0, 200,
0xff, 8, 50, 0,
0xff, 200, 0, 0,
0xff, 0, 0, 0,
0xff, 200, 0, 200,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
}, nil); err != nil {
panic(err)
}
}
@@ -0,0 +1,107 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package spi allows users to read from and write to an SPI device.
//
// # Deprecated
//
// This package is not maintained anymore. An actively supported cross-platform
// alternative is https://periph.io/.
package spi // import "golang.org/x/exp/io/spi"
import (
"time"
"golang.org/x/exp/io/spi/driver"
)
// Mode represents the SPI mode number where clock parity (CPOL)
// is the high order and clock edge (CPHA) is the low order bit.
type Mode int
const (
Mode0 = Mode(0)
Mode1 = Mode(1)
Mode2 = Mode(2)
Mode3 = Mode(3)
)
// Order is the bit justification to be used while transferring
// words to the SPI device. MSB-first encoding is more popular
// than LSB-first.
type Order int
const (
MSBFirst = Order(0)
LSBFirst = Order(1)
)
type Device struct {
conn driver.Conn
}
// SetMode sets the SPI mode. SPI mode is a combination of polarity and phases.
// CPOL is the high order bit, CPHA is the low order. Pre-computed mode
// values are Mode0, Mode1, Mode2 and Mode3.
// The value can be changed by SPI device's driver.
func (d *Device) SetMode(mode Mode) error {
return d.conn.Configure(driver.Mode, int(mode))
}
// SetMaxSpeed sets the maximum clock speed in Hz.
// The value can be overridden by SPI device's driver.
func (d *Device) SetMaxSpeed(speed int) error {
return d.conn.Configure(driver.MaxSpeed, speed)
}
// SetBitsPerWord sets how many bits it takes to represent a word, e.g. 8 represents 8-bit words.
// The default is 8 bits per word.
func (d *Device) SetBitsPerWord(bits int) error {
return d.conn.Configure(driver.Bits, bits)
}
// SetBitOrder sets the bit justification used to transfer SPI words.
// Valid values are MSBFirst and LSBFirst.
func (d *Device) SetBitOrder(o Order) error {
return d.conn.Configure(driver.Order, int(o))
}
// SetDelay sets the amount of pause will be added after each frame write.
func (d *Device) SetDelay(t time.Duration) error {
return d.conn.Configure(driver.Delay, int(t.Nanoseconds()/1000))
}
// SetCSChange sets whether to leave the chipselect enabled after a Tx.
func (d *Device) SetCSChange(leaveEnabled bool) error {
v := 0
if leaveEnabled {
v = 1
}
return d.conn.Configure(driver.CSChange, v)
}
// Tx performs a duplex transmission to write w to the SPI device
// and read len(r) bytes to r.
// User should not mutate the w and r until this call returns.
func (d *Device) Tx(w, r []byte) error {
// TODO(jbd): Allow nil w.
return d.conn.Tx(w, r)
}
// Open opens a device with the specified bus and chip select
// by using the given driver. If a nil driver is provided,
// the default driver (devfs) is used.
func Open(o driver.Opener) (*Device, error) {
conn, err := o.Open()
if err != nil {
return nil, err
}
return &Device{conn: conn}, nil
}
// Close closes the SPI device and releases the related resources.
func (d *Device) Close() error {
return d.conn.Close()
}