gpiostream

package
v3.6.8+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 24, 2021 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package gpiostream defines digital streams.

Warning

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

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BitStream

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.

Example
package main

import (
	"fmt"

	"periph.io/x/periph/conn/gpio"
	"periph.io/x/periph/conn/gpio/gpiostream"
	"periph.io/x/periph/conn/physic"
)

func main() {
	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

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

Duration implements Stream.

func (*BitStream) Frequency

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

Frequency implements Stream.

func (*BitStream) GoString

func (b *BitStream) GoString() string

GoString implements fmt.GoStringer.

type EdgeStream

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

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

Duration implements Stream.

func (*EdgeStream) Frequency

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

Frequency implements Stream.

type PinIn

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.

Example
package main

import (
	"fmt"
	"log"

	"periph.io/x/periph/conn/gpio"
	"periph.io/x/periph/conn/gpio/gpioreg"
	"periph.io/x/periph/conn/gpio/gpiostream"
	"periph.io/x/periph/conn/physic"
	"periph.io/x/periph/host"
)

func main() {
	// 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")
		}
	}
}
Output:

type PinOut

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.

Example
package main

import (
	"log"

	"periph.io/x/periph/conn/gpio/gpioreg"
	"periph.io/x/periph/conn/gpio/gpiostream"
	"periph.io/x/periph/conn/physic"
	"periph.io/x/periph/host"
)

func main() {
	// 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)
	}
}
Output:

type Program

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

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

Duration implements Stream.

func (*Program) Frequency

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

Frequency implements Stream.

type Stream

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

Path Synopsis
Package gpiostreamtest enables testing device driver using gpiostream.PinIn or PinOut.
Package gpiostreamtest enables testing device driver using gpiostream.PinIn or PinOut.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL