Skip to content

Driver design API

Ayke edited this page Jan 28, 2019 · 7 revisions

This is a strawman proposal for TinyGo drivers.

Drivers vary greatly in their complexity. Here is a WIP proposal for an API.

Design goals

  • Let drivers implement an interface that is very close to the sensor hardware.
  • Avoid the need for internal state in drivers as much as possible.
  • Make an interface that is easy to use for higher level libraries, like sensor fusion.

Sensors / actuators

Simple sensors

type TemperatureSensor interface {
    // ReadTemperature returns the current temperature in milli-degrees
    // Celsius. For example, 25°C is returned as 25000.
    ReadTemperature() (int32, error)
}

type RelativeHumiditySensor interface {
    // ReadRelativeHumidity returns the current humidity (0%-100%) in
    // promilles.
    // Rationale: even very precise humidity sensors rarely go below 1%
    // accuracy so providing more accuracy isn't very useful.
    ReadRelativeHumidity() (int16, error)
}

More complex sensors

type AccelerationSensor interface {
    // ReadAcceleration returns the current acceleration in µm/s².
    // Note: this is more precise than returning gravity, because gravity
    // varies by location.
    // The unit µm/s² is used because it captures the precision of most
    // sensors, unlike mm/s².
    ReadAcceleration() (x int32, y int32, z int32, err error)
}

type RotationSensor interface {
    // TODO
    ReadRotation() (x int32, y int32, z int32, err error)
}

Displays

type Display interface {
    Dimensions() image.Point
    Density() (dpi int) // estimate of the real density in DPI
    Write([]byte) (int, error)
    ColorModel() image.ColorModel
}

Graphics library

A graphics library takes a display and adds support for all kinds of graphics animations using an internal buffer. For example, it could look like this:

type Gfx struct {
    display Display
    buffer []byte
}

// Set a single pixel.
func (g *Gfx) SetPixel(coord image.Point, color ...) {}

// Set an area to the given color.
func (g *Gfx) SetArea(area image.Rectangle, color ...) {}

// Overwrite a part of the image.
func (g *Gfx) Draw(dstRect image.Rectangle, src image.Image, srcPts image.Point) error {}

// Write buffered image to the display.
func (g *Gfx) Display()

Such a graphics library should make it unnecessary for a driver to use an internal buffer

Example use, moving a pixel over a screen:

func main() {
    display := mydisplaydriver.New(spi)
    g := gfx.New(display)
    x := 10
    for {
        g.Clear() // set to black
        g.SetPixel(image.Point{x, 30}, <color>)
        g.Display() // write to screen
        time.Sleep(...)

        x++ // move pixel
        if x > 90 {
            // start from the beginning
            x = 10
        }
    }
}

Sensor fusion

A sensor fusion algorithm takes an accelerometer, a gyroscope, and possibly a magnetometer and/or barometer and fuses their readings together to get a good estimate of the position of the object.

type SensorFusionAlgorithm interface {
    UpdateAcceleration(x, y, z int32)
    UpdateRotation(x, y, z int32)

    // Orientation returns the current rotation quaternion.
    Orientation() (x, y, z, w int32)
}