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

The Hitec wire on one RP2350 pin. More...

#include "hitec_line.h"
#include <stdint.h>
#include <string.h>
#include "hardware/clocks.h"
#include "hardware/dma.h"
#include "hardware/gpio.h"
#include "hardware/pio.h"
#include "hardware/structs/io_bank0.h"
#include "hardware/structs/pads_bank0.h"
#include "hardware/timer.h"
#include "pico.h"
#include "hitec_line.pio.h"

Macros

#define DMA_COUNT_MASK   0x0FFFFFFFu
 A transfer count's low 28 bits are the count; the rest is the mode.
#define RX_SETTLE_SPINS   64u
 Reads of the receive FIFO a poll or an abort makes at most while the channel takes the words still in it: 4 words, each a few system clock cycles.

Functions

static PIO line_pio (const hitec_line_t *l)
 Get the PIO block of a line.
static void set_pull (unsigned pin, uint8_t family)
 The family's pull: classic down, the D series up.
static bool line_idle (const hitec_line_t *l)
 The state machine waits for a stream: it stalls on the first out, the FIFO is empty and the channel has handed over every word.
static void line_ready (PIO pio, uint sm, uint offset)
 Run the program's drain on the stopped machine and put it on the out it stalls on between transactions: the output shift register is empty, whatever a restart left in it, and line_idle() holds from the moment the machine runs again.
static void line_restart (hitec_line_t *l)
 Put the state machine at idle with the pad released, whatever it was doing.
static bool answer_due (const hitec_line_t *l, unsigned n)
 Whether the answer is still to go out with n bytes received: a restart now cuts it.
static unsigned rx_count (const hitec_line_t *l)
 Bytes the receive channel has written.
static bool rx_settled (const hitec_line_t *l)
 The receive channel has every word the machine pushed, or all it takes.
static void rx_settle (const hitec_line_t *l)
 Wait up to RX_SETTLE_SPINS FIFO reads for the channel to take the words still in the receive FIFO.
static unsigned rx_stop_count (hitec_line_t *l)
 Stop the machine and count the bytes it received.
static uint32_t pre_words_us (const hitec_line_t *l, uint32_t words)
 The longest words sample words take, in us, rounded up.
static void pre_take (hitec_line_t *l)
 The pad to the sampler, and the sampler started: the pin's control and pad registers kept, the pin in the sampler's block with no input override, 2mA and slow slew, the samples to the line object.
static uint32_t pre_words_in (const hitec_line_t *l)
 Sample words written so far: the channel's write address moves after each write.
static bool pre_rx_stalled (const hitec_line_t *l)
 Whether the sampler's receive FIFO has run full since its start.
static bool pre_give (hitec_line_t *l)
 The sampler stopped with the pad released and the pin's two registers back as they were.
static void pre_sample (hitec_line_t *l)
 The sampler from the start of a LISTEN, or once the request is out.
static bool pre_poll (hitec_line_t *l, hitec_capture_t *out)
 poll() of a transaction the sampler receives.
void hitec_line_init (hitec_line_t *line)
 Mark line closed.
hitec_line_err_t hitec_line_open (hitec_line_t *line, unsigned pin, uint8_t family, uint8_t drive)
 Claim the resources and take pin for family (hitec_family_t) with drive (hitec_drive_t): from the return on the pad is a released input with the family's pull.
static pio_program_t pre_program (const hitec_line_t *l)
 The sampler's program as the SDK takes it.
static hitec_line_err_t pre_claim (hitec_line_t *l, unsigned pin)
 Claim the sampler's state machine, program and DMA channel for pin.
static void pre_unclaim (hitec_line_t *l)
 Give back the sampler state machine, its program and its DMA channel.
hitec_line_err_t hitec_line_open_rx (hitec_line_t *line, unsigned pin, uint8_t family, uint8_t drive, uint8_t rx_mode)
 hitec_line_open() with the receive mode rx (hitec_rx_mode_t).
void hitec_line_close (hitec_line_t *line)
 Stop the state machine, give back what the open claimed and leave the pad an input with the family's pull and no input override.
bool hitec_line_is_open (const hitec_line_t *line)
 Check whether a line is open.
bool hitec_line_busy (const hitec_line_t *line)
 A transaction runs: between a start() that returned true and the poll() that returns true.
uint8_t hitec_line_rx_mode (const hitec_line_t *line)
 The receive mode of the open line; HITEC_RX_PULL_UP while closed.
uint32_t hitec_line_bit_ns (const hitec_line_t *line)
 The bit time the system clock gives, in ns; 0 on a closed line.
void hitec_line_abort (hitec_line_t *line)
 Cut the running transaction: the pad is released at once, and the next poll() returns the bytes so far with the capture marked aborted.
static bool line_start (hitec_line_t *l, const hitec_xfer_t *xfer)
 Start a transaction on the line's own state machine.
bool hitec_line_start (void *ctx, const hitec_xfer_t *xfer)
 The three functions of hitec_driver_t; ctx is the hitec_line_t.
bool hitec_line_poll (void *ctx, hitec_capture_t *out)
 Poll a transaction; the second of the three driver functions.
uint32_t hitec_line_now_us (void *ctx)
 Read the microsecond clock; the third of the three driver functions.
hitec_driver_t hitec_line_driver (hitec_line_t *line)
 The driver for line.

Detailed Description

The Hitec wire on one RP2350 pin.

See hitec_line.h.

SPDX-License-Identifier: MIT

Function Documentation

◆ hitec_line_abort()

void hitec_line_abort ( hitec_line_t * line)

Cut the running transaction: the pad is released at once, and the next poll() returns the bytes so far with the capture marked aborted.

Does nothing when no transaction runs.

Parameters
lineLine object.

◆ hitec_line_bit_ns()

uint32_t hitec_line_bit_ns ( const hitec_line_t * line)

The bit time the system clock gives, in ns; 0 on a closed line.

Parameters
lineLine object.
Returns
The bit time in ns; 0 on a closed line.

◆ hitec_line_busy()

bool hitec_line_busy ( const hitec_line_t * line)

A transaction runs: between a start() that returned true and the poll() that returns true.

Parameters
lineLine object.
Returns
true between a start that returned true and the poll that returns true.

◆ hitec_line_close()

void hitec_line_close ( hitec_line_t * line)

Stop the state machine, give back what the open claimed and leave the pad an input with the family's pull and no input override.

A transaction on the wire is cut. Safe on a closed line.

Parameters
lineLine object.

◆ hitec_line_driver()

hitec_driver_t hitec_line_driver ( hitec_line_t * line)

The driver for line.

Parameters
lineLine object.
Returns
The hitec_driver_t for the line.

◆ hitec_line_init()

void hitec_line_init ( hitec_line_t * line)

Mark line closed.

Call once, before the first open.

Parameters
lineLine object to mark closed.

◆ hitec_line_is_open()

bool hitec_line_is_open ( const hitec_line_t * line)

Check whether a line is open.

Parameters
lineLine object.
Returns
true when the line is open.

◆ hitec_line_now_us()

uint32_t hitec_line_now_us ( void * ctx)

Read the microsecond clock; the third of the three driver functions.

Parameters
ctxThe hitec_line_t.
Returns
The microsecond clock.

◆ hitec_line_open()

hitec_line_err_t hitec_line_open ( hitec_line_t * line,
unsigned pin,
uint8_t family,
uint8_t drive )

Claim the resources and take pin for family (hitec_family_t) with drive (hitec_drive_t): from the return on the pad is a released input with the family's pull.

The caller has stopped every other use of the pin. On an error nothing stays claimed and the pin is not touched. An open line is closed first.

Parameters
lineLine object.
pinGPIO number.
familyhitec_family_t value.
drivehitec_drive_t value.
Returns
HITEC_LINE_OK, or the error that refused the open.

◆ hitec_line_open_rx()

hitec_line_err_t hitec_line_open_rx ( hitec_line_t * line,
unsigned pin,
uint8_t family,
uint8_t drive,
uint8_t rx )

hitec_line_open() with the receive mode rx (hitec_rx_mode_t).

HITEC_RX_PULL_UP is hitec_line_open(). HITEC_RX_PRECHARGE takes the D series only (HITEC_LINE_ERR_ARG for classic) and claims the sampler as well; on an error nothing stays claimed and the pin is not touched.

Parameters
lineLine object.
pinGPIO number.
familyhitec_family_t value.
drivehitec_drive_t value.
rxhitec_rx_mode_t value.
Returns
HITEC_LINE_OK, or the error that refused the open.

◆ hitec_line_poll()

bool hitec_line_poll ( void * ctx,
hitec_capture_t * out )

Poll a transaction; the second of the three driver functions.

Parameters
ctxThe hitec_line_t.
outReceives the capture when the transaction has ended.
Returns
true once, when the transaction has ended.

◆ hitec_line_rx_mode()

uint8_t hitec_line_rx_mode ( const hitec_line_t * line)

The receive mode of the open line; HITEC_RX_PULL_UP while closed.

Parameters
lineLine object.
Returns
The receive mode of the open line; HITEC_RX_PULL_UP while closed.

◆ hitec_line_start()

bool hitec_line_start ( void * ctx,
const hitec_xfer_t * xfer )

The three functions of hitec_driver_t; ctx is the hitec_line_t.

Parameters
ctxThe hitec_line_t.
xferTransaction to run.
Returns
true when the transaction started.

◆ line_idle()

bool line_idle ( const hitec_line_t * l)
static

The state machine waits for a stream: it stalls on the first out, the FIFO is empty and the channel has handed over every word.

A stream is 3 words or more and the program reads all of them before the receiver starts, so this is false from the start of a transfer to the end of the transaction.

◆ line_ready()

void line_ready ( PIO pio,
uint sm,
uint offset )
static

Run the program's drain on the stopped machine and put it on the out it stalls on between transactions: the output shift register is empty, whatever a restart left in it, and line_idle() holds from the moment the machine runs again.

The transmit FIFO is empty, so autopull takes nothing.

◆ line_start()

bool line_start ( hitec_line_t * l,
const hitec_xfer_t * xfer )
static

Start a transaction on the line's own state machine.

A transaction on the line's own state machine.

◆ pre_claim()

hitec_line_err_t pre_claim ( hitec_line_t * l,
unsigned pin )
static

Claim the sampler's state machine, program and DMA channel for pin.

Touches no pin; on false nothing stays claimed.

◆ pre_give()

bool pre_give ( hitec_line_t * l)
static

The sampler stopped with the pad released and the pin's two registers back as they were.

True when samples went missing: the receive FIFO ran full while the channel still had words to take. Once the channel has every word, the state machine runs on until this stops it and fills the FIFO in 8 words, 278us at 150MHz; that stall loses nothing.

◆ rx_settle()

void rx_settle ( const hitec_line_t * l)
static

Wait up to RX_SETTLE_SPINS FIFO reads for the channel to take the words still in the receive FIFO.

The caller has made sure the machine pushes nothing more.

◆ rx_stop_count()

unsigned rx_stop_count ( hitec_line_t * l)
static

Stop the machine and count the bytes it received.

Stopped first, so it pushes nothing more; then the channel takes what is still in the receive FIFO, and only then is the count read. A byte pushed just before the stop is counted, not cleared by the restart that follows. The machine stays stopped at its address, so answer_due() reads where it stopped.

Parameters
lThe line, busy on its own state machine.
Returns
The bytes the receive channel has written; 0 for a run that receives none.