gpiostream

package
Version: 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: 79

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.

Source Files

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