A new package tinyio (working title) is proposed to solve the cyclic dependency problem between the tinygo and drivers packages detailed in #487. Additional benefits:
Single source of truth for I/O interfaces:
Validating whether a target has a peripheral implementation (I2C). This is valuable for automatic documentation generation and compile-time validation, preventing bad implementations from making it into the tinygo package
No more discussion on whether it's a good idea to have interfaces defined in tinygo package. This is a fine line to tread as there are some interfaces that have been defined in the tinygo package like USB and UART interfaces.
Opens TinyGo to the wider Go community
tinyio becomes the defacto standard for low level I/O since it is a pure native Go implementation
The transition to the tinyio package would not be immediate. The goal I propose is to decide on tinyio as being the goal to which the Go community strives for the future.
Example of `tinyio/tinyio.go` contents:
```go
package drivers
import (
"image/color"
"io"
"net"
"time"
)
// Pin type is not needed today, but may be useful to define here for types like PWMer.
// Guarded by build tag `tinygo`
type Pin = machine.Pin
// Guarded by `!tinygo` build tag.
type Pin uint8
// UART represents a UART connection. It is implemented by the machine.UART type.
type UART interface {
io.Reader
io.Writer
Buffered() int
}
// SPI represents a SPI bus. It is implemented by the machine.SPI type.
type SPI interface {
// Tx transmits the given buffer w and receives at the same time the buffer r.
// The two buffers must be the same length. The only exception is when w or r are nil,
// in which case Tx only transmits (without receiving) or only receives (while sending 0 bytes).
Tx(w, r []byte) error
// Transfer writes a single byte out on the SPI bus and receives a byte at the same time.
// If you want to transfer multiple bytes, it is more efficient to use Tx instead.
Transfer(b byte) (byte, error)
}
// I2C represents an I2C bus. It is notably implemented by the machine.I2C type.
type I2C interface {
// Excludes WriteRegister and ReadRegister since these are rarely implemented
// as hardware-level functions and more commonly use the contents of
// machine/i2c.go. They should instead be implemented as tinyio top level
// package functions.
Tx(addr uint16, w, r []byte) error
}
type Displayer interface {
// Size returns the current size of the display.
Size() (x, y int16)
// SetPizel modifies the internal buffer.
SetPixel(x, y int16, c color.RGBA)
// Display sends the buffer (if any) to the screen.
Display() error
}
// A Netdever is a network device driver for Tinygo; Tinygo's network device
// driver model.
type Netdever interface {
// Probe initializes the network device and maintains the connection to
// the network. For example, Probe will maintain the connection to the
// Wifi access point for a Wifi network device.
Probe() error
// GetHostByName returns the IP address of either a hostname or IPv4
// address in standard dot notation.
GetHostByName(name string) (net.IP, error)
// Socketer is Berkely Sockets-like interface
Socketer
}
type AddressFamily int
type SockType int
type Protocol int
type SockAddr struct {
port [2]byte // Network byte order
ip [4]byte // Network byte order
}
type SockFlags int
type SockOpt int
type SockOptLevel int
type Sockfd int
// Berkely Sockets-like interface. See man page for socket(2), etc.
type Socketer interface {
Socket(family AddressFamily, sockType SockType, protocol Protocol) (Sockfd, error)
Bind(sockfd Sockfd, myaddr SockAddr) error
Connect(sockfd Sockfd, servaddr SockAddr) error
Listen(sockfd Sockfd, backlog int) error
Accept(sockfd Sockfd, peer SockAddr) error
Send(sockfd Sockfd, buff []byte, flags SockFlags, timeout time.Duration) (int, error)
SendTo(sockfd Sockfd, buff []byte, flags SockFlags, to SockAddr,
timeout time.Duration) (int, error)
Recv(sockfd Sockfd, buff []byte, flags SockFlags, timeout time.Duration) (int, error)
RecvFrom(sockfd Sockfd, buff []byte, flags SockFlags, from SockAddr,
timeout time.Duration) (int, error)
Close(sockfd Sockfd) error
SetSockOpt(sockfd Sockfd, level SockOptLevel, opt SockOpt, value interface{}) error
}
```
A new package
tinyio
(working title) is proposed to solve the cyclic dependency problem between thetinygo
anddrivers
packages detailed in #487. Additional benefits:tinyio
becomes the defacto standard for low level I/O since it is a pure native Go implementationThe transition to the
tinyio
package would not be immediate. The goal I propose is to decide on tinyio as being the goal to which the Go community strives for the future.Example of `tinyio/tinyio.go` contents:
```go package drivers import ( "image/color" "io" "net" "time" ) // Pin type is not needed today, but may be useful to define here for types like PWMer. // Guarded by build tag `tinygo` type Pin = machine.Pin // Guarded by `!tinygo` build tag. type Pin uint8 // UART represents a UART connection. It is implemented by the machine.UART type. type UART interface { io.Reader io.Writer Buffered() int } // SPI represents a SPI bus. It is implemented by the machine.SPI type. type SPI interface { // Tx transmits the given buffer w and receives at the same time the buffer r. // The two buffers must be the same length. The only exception is when w or r are nil, // in which case Tx only transmits (without receiving) or only receives (while sending 0 bytes). Tx(w, r []byte) error // Transfer writes a single byte out on the SPI bus and receives a byte at the same time. // If you want to transfer multiple bytes, it is more efficient to use Tx instead. Transfer(b byte) (byte, error) } // I2C represents an I2C bus. It is notably implemented by the machine.I2C type. type I2C interface { // Excludes WriteRegister and ReadRegister since these are rarely implemented // as hardware-level functions and more commonly use the contents of // machine/i2c.go. They should instead be implemented as tinyio top level // package functions. Tx(addr uint16, w, r []byte) error } type Displayer interface { // Size returns the current size of the display. Size() (x, y int16) // SetPizel modifies the internal buffer. SetPixel(x, y int16, c color.RGBA) // Display sends the buffer (if any) to the screen. Display() error } // A Netdever is a network device driver for Tinygo; Tinygo's network device // driver model. type Netdever interface { // Probe initializes the network device and maintains the connection to // the network. For example, Probe will maintain the connection to the // Wifi access point for a Wifi network device. Probe() error // GetHostByName returns the IP address of either a hostname or IPv4 // address in standard dot notation. GetHostByName(name string) (net.IP, error) // Socketer is Berkely Sockets-like interface Socketer } type AddressFamily int type SockType int type Protocol int type SockAddr struct { port [2]byte // Network byte order ip [4]byte // Network byte order } type SockFlags int type SockOpt int type SockOptLevel int type Sockfd int // Berkely Sockets-like interface. See man page for socket(2), etc. type Socketer interface { Socket(family AddressFamily, sockType SockType, protocol Protocol) (Sockfd, error) Bind(sockfd Sockfd, myaddr SockAddr) error Connect(sockfd Sockfd, servaddr SockAddr) error Listen(sockfd Sockfd, backlog int) error Accept(sockfd Sockfd, peer SockAddr) error Send(sockfd Sockfd, buff []byte, flags SockFlags, timeout time.Duration) (int, error) SendTo(sockfd Sockfd, buff []byte, flags SockFlags, to SockAddr, timeout time.Duration) (int, error) Recv(sockfd Sockfd, buff []byte, flags SockFlags, timeout time.Duration) (int, error) RecvFrom(sockfd Sockfd, buff []byte, flags SockFlags, from SockAddr, timeout time.Duration) (int, error) Close(sockfd Sockfd) error SetSockOpt(sockfd Sockfd, level SockOptLevel, opt SockOpt, value interface{}) error } ```