rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
out_ppm.c File Reference

PPM out: a PIO state machine and a self-restarting pair of DMA channels. More...

#include "out_ppm.h"
#include <string.h>
#include "hardware/dma.h"
#include "hardware/gpio.h"
#include "hardware/pio.h"
#include "ppm.h"
#include "ppm.pio.h"

Data Structures

struct  ppm_out_t
 State of one PPM output: its pin, PIO state machine and DMA channels. More...

Macros

#define RUN_TO_COUNT(us)
 The program renders a run of N microseconds as a one-cycle out and N-1 cycles of loop, so the count in the FIFO (first in first out) is two less than the duration. ppm_frame() refuses a run shorter than the mark, and the mark is 300us, so this cannot go negative.

Functions

static ppm_out_t * find (uint8_t pin)
 Find the bound entry for a pin.
static void set_enabled (ppm_out_t *s, bool on)
 Erratum RP2350-E5: a channel that is aborted while it or a channel chained to it is still enabled can be retriggered by the abort itself.
static void halt (ppm_out_t *s)
 Stop the frame and hold the pin low.
static void teardown (ppm_out_t *s)
 Halt an output and give back its DMA channels, PIO state machine and program.
static ppm_cfg_t cfg_of (uint16_t frame_us)
 Build the frame timing for a frame period, with the default mark and sync gap.
bool out_ppm_bind (uint8_t pin, uint8_t channels, uint16_t rate_hz)
 Take pin for channels channels at rate_hz frames a second.
void out_ppm_release (uint8_t pin)
 Give the pin, the state machine and both DMA channels back.
void out_ppm_stop (uint8_t pin)
 Stop emitting; the pin is left low.
bool out_ppm_write (uint8_t pin, const uint16_t *channel_us, uint8_t channels)
 Lay channels pulse widths into the frame and keep sending it.

Variables

static ppm_out_t s_out [OUT_PPM_MAX_PINS]
 One per pin that can be bound.

Detailed Description

PPM out: a PIO state machine and a self-restarting pair of DMA channels.

See out_ppm.h.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ RUN_TO_COUNT

#define RUN_TO_COUNT ( us)
Value:
((uint32_t)(us) - 2u)

The program renders a run of N microseconds as a one-cycle out and N-1 cycles of loop, so the count in the FIFO (first in first out) is two less than the duration. ppm_frame() refuses a run shorter than the mark, and the mark is 300us, so this cannot go negative.

Function Documentation

◆ find()

ppm_out_t * find ( uint8_t pin)
static

Find the bound entry for a pin.

Returns NULL when the pin is not bound.

◆ halt()

void halt ( ppm_out_t * s)
static

Stop the frame and hold the pin low.

Does nothing when the output has no DMA channels.

◆ out_ppm_bind()

bool out_ppm_bind ( uint8_t pin,
uint8_t channels,
uint16_t rate_hz )

Take pin for channels channels at rate_hz frames a second.

Refuses a frame rate that cannot carry that many channels at their widest (see ppm_min_frame_us), a pin no PIO block can reach alongside its other programs, and a shortage of state machines or DMA channels. Nothing is emitted until the first out_ppm_write().

A pin that is already bound with the same channel count and frame period stays as it is and the call returns true. With a different count or period it returns false and the old binding keeps running; release the pin first to change it.

Parameters
pinGPIO number.
channelsNumber of channels.
rate_hzFrames per second; refused when rate_hz is 0 or the frame period is below 2us or above 65535us.
Returns
true when the pin is bound with these parameters, false otherwise.

◆ out_ppm_release()

void out_ppm_release ( uint8_t pin)

Give the pin, the state machine and both DMA channels back.

Parameters
pinGPIO number. A pin that is not bound is ignored.

◆ out_ppm_stop()

void out_ppm_stop ( uint8_t pin)

Stop emitting; the pin is left low.

The next write starts it again.

Parameters
pinGPIO number. A pin that is not running is ignored.

◆ out_ppm_write()

bool out_ppm_write ( uint8_t pin,
const uint16_t * channel_us,
uint8_t channels )

Lay channels pulse widths into the frame and keep sending it.

Returns false, and stops the output, for a set of widths that cannot be laid out in the frame this pin was bound with. A refused frame is not half-written: ppm_frame() builds it whole or not at all.

Parameters
pinGPIO number.
channel_usPulse width of each channel, in us.
channelsNumber of channels, which must match the binding.
Returns
true when the frame is sent, false otherwise.

◆ set_enabled()

void set_enabled ( ppm_out_t * s,
bool on )
static

Erratum RP2350-E5: a channel that is aborted while it or a channel chained to it is still enabled can be retriggered by the abort itself.

Both are therefore disabled first, and the enable bit is put back when the frame is started again.

◆ teardown()

void teardown ( ppm_out_t * s)
static

Halt an output and give back its DMA channels, PIO state machine and program.

The pin is left as an input.

Variable Documentation

◆ s_out

ppm_out_t s_out[OUT_PPM_MAX_PINS]
static

One per pin that can be bound.

DMA channels run out before these do.