periph: periph.io/x/periph/conn/gpio/gpiostream Index | Examples | Files | Directories

package gpiostream

import "periph.io/x/periph/conn/gpio/gpiostream"

Package gpiostream defines digital streams.

Warning

This package is still in flux as development is on-going.

Index

Examples

Package Files

gpiostream.go

type BitStream Uses

type BitStream struct {
    // Bits is a densely packed bitstream.
    //
    // The stream is required to be a multiple of 8 samples.
    Bits []byte
    // Freq is the rate at each the bit (not byte) stream should be processed.
    Freq physic.Frequency
    // LSBF when true means than Bits is in LSB-first. When false, the data is
    // MSB-first.
    //
    // With MSBF, the first bit processed is the most significant one (0x80). For
    // example, I²C, I2S PCM and SPI use MSB-first at the word level. This
    // requires to pack words correctly.
    //
    // With LSBF, the first bit processed is the least significant one (0x01).
    // For example, Ethernet uses LSB-first at the byte level and MSB-first at
    // the word level.
    LSBF bool
}

BitStream is a stream of bits to be written or read.

Code:

fmt.Printf("Format is LSB-first; least significant bit first:\n")
stream := gpiostream.BitStream{
    Bits: []byte{0x80, 0x01, 0xAA, 0x55},
    Freq: physic.MegaHertz,
    LSBF: true,
}
for _, l := range stream.Bits {
    fmt.Printf("0x%02X: ", l)
    for j := 0; j < 8; j++ {
        mask := byte(1) << uint(j)
        fmt.Printf("%4s,", gpio.Level(l&mask != 0))
        if j != 7 {
            fmt.Printf(" ")
        }
    }
    fmt.Printf("\n")
}
fmt.Printf("\n")

fmt.Printf("Format is MSB-first; most significant bit first:\n")
stream = gpiostream.BitStream{
    Bits: []byte{0x80, 0x01, 0xAA, 0x55},
    Freq: physic.MegaHertz,
    LSBF: false,
}
for _, l := range stream.Bits {
    fmt.Printf("0x%02X: ", l)
    for j := 7; j >= 0; j-- {
        mask := byte(1) << uint(j)
        fmt.Printf("%4s,", gpio.Level(l&mask != 0))
        if j != 0 {
            fmt.Printf(" ")
        }
    }
    fmt.Printf("\n")
}

Output:

Format is LSB-first; least significant bit first:
0x80:  Low,  Low,  Low,  Low,  Low,  Low,  Low, High,
0x01: High,  Low,  Low,  Low,  Low,  Low,  Low,  Low,
0xAA:  Low, High,  Low, High,  Low, High,  Low, High,
0x55: High,  Low, High,  Low, High,  Low, High,  Low,

Format is MSB-first; most significant bit first:
0x80: High,  Low,  Low,  Low,  Low,  Low,  Low,  Low,
0x01:  Low,  Low,  Low,  Low,  Low,  Low,  Low, High,
0xAA: High,  Low, High,  Low, High,  Low, High,  Low,
0x55:  Low, High,  Low, High,  Low, High,  Low, High,

func (*BitStream) Duration Uses

func (b *BitStream) Duration() time.Duration

Duration implements Stream.

func (*BitStream) Frequency Uses

func (b *BitStream) Frequency() physic.Frequency

Frequency implements Stream.

func (*BitStream) GoString Uses

func (b *BitStream) GoString() string

GoString implements fmt.GoStringer.

type EdgeStream Uses

type EdgeStream struct {
    // Edges is the list of Level change. It is assumed that the signal starts
    // with gpio.High. Use a duration of 0 for Edges[0] to start with a Low
    // instead of the default High.
    //
    // The value is a multiple of Res. Use a 0 value to 'extend' a continuous
    // signal that lasts more than "2^16-1*Res" duration by skipping a pulse.
    Edges []uint16
    // Res is the minimum resolution at which the edges should be
    // rasterized.
    //
    // The lower the value, the more memory shall be used when rasterized.
    Freq physic.Frequency
}

EdgeStream is a stream of edges to be written.

This struct is more efficient than BitStream for short repetitive pulses, like controlling a servo. A PWM can be created by specifying a slice of twice the same resolution and make it looping via a Program.

func (*EdgeStream) Duration Uses

func (e *EdgeStream) Duration() time.Duration

Duration implements Stream.

func (*EdgeStream) Frequency Uses

func (e *EdgeStream) Frequency() physic.Frequency

Frequency implements Stream.

type PinIn Uses

type PinIn interface {
    pin.Pin
    // StreamIn reads for the pin at the specified resolution to fill the
    // provided buffer.
    //
    // May only support a subset of the structs implementing Stream.
    StreamIn(p gpio.Pull, b Stream) error
}

PinIn allows to read a bit stream from a pin.

Caveat

This interface doesn't enable sampling multiple pins in a synchronized way or reading in a continuous uninterrupted way. As such, it should be considered experimental.

Code:

// Make sure periph is initialized.
if _, err := host.Init(); err != nil {
    log.Fatal(err)
}

// Read one second of sample at 1ms resolution and print the values read.
p := gpioreg.ByName("GPIO3")
r, ok := p.(gpiostream.PinIn)
if !ok {
    log.Fatalf("pin streaming is not supported on pin %s", p)
}
b := gpiostream.BitStream{Freq: physic.KiloHertz, Bits: make([]byte, 1000/8)}
if err := r.StreamIn(gpio.PullNoChange, &b); err != nil {
    log.Fatal(err)
}
for i, l := range b.Bits {
    // Bits format is in MSB; the most significant bit is streamed first.
    for j := 7; j >= 0; j-- {
        mask := byte(1) << uint(j)
        fmt.Printf("%4s, ", gpio.Level(l&mask != 0))
    }
    if i&1 == 1 {
        fmt.Printf("\n")
    }
}

type PinOut Uses

type PinOut interface {
    pin.Pin
    StreamOut(s Stream) error
}

PinOut allows to stream to a pin.

The Stream may be a Program, a BitStream or an EdgeStream. If it is a Program that is an infinite loop, a separate goroutine can be used to cancel the program. In this case StreamOut() returns without an error.

Caveat

This interface doesn't enable streaming to multiple pins in a synchronized way or reading in a continuous uninterrupted way. As such, it should be considered experimental.

Code:

// Make sure periph is initialized.
if _, err := host.Init(); err != nil {
    log.Fatal(err)
}

// Generates a 25% duty cycle PWM at 1kHz for 5 seconds with a precision of
// 1µs.
p := gpioreg.ByName("GPIO3")
r, ok := p.(gpiostream.PinOut)
if !ok {
    log.Fatalf("pin streaming is not supported on pin %s", p)
}
b := gpiostream.Program{
    Parts: []gpiostream.Stream{
        &gpiostream.EdgeStream{
            Freq:  physic.MegaHertz,
            Edges: []uint16{250, 750},
        },
    },
    Loops: 5000,
}
if err := r.StreamOut(&b); err != nil {
    log.Fatal(err)
}

type Program Uses

type Program struct {
    Parts []Stream // Each part must be a BitStream, EdgeStream or Program
    Loops int      // Set to -1 to create an infinite loop
}

Program is a loop of streams.

This is itself a stream, it can be used to reduce memory usage when repeated patterns are used.

func (*Program) Duration Uses

func (p *Program) Duration() time.Duration

Duration implements Stream.

func (*Program) Frequency Uses

func (p *Program) Frequency() physic.Frequency

Frequency implements Stream.

type Stream Uses

type Stream interface {
    // Frequency is the minimum data rate at which the binary stream is usable.
    //
    // For example, a bit stream may have a 10kHz data rate.
    Frequency() physic.Frequency
    // Duration of the binary stream. For infinitely looping streams, it is the
    // duration of the non-looping part.
    Duration() time.Duration
}

Stream is the interface to define a generic stream.

Directories

PathSynopsis
gpiostreamtestPackage gpiostreamtest enables testing device driver using gpiostream.PinIn or PinOut.

Package gpiostream imports 5 packages (graph) and is imported by 10 packages. Updated 2019-08-09. Refresh now. Tools for package owners.