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

The Hitec wire on one RP2350 pin: a hitec_driver_t made of one PIO (programmable input/output) state machine (hitec_line.pio) and two DMA (direct memory access) channels, one for the words of a transaction and one for the received bytes. More...

#include <stdbool.h>
#include <stdint.h>
#include "hitec_pio.h"
#include "hitec_pre.h"
#include "hitec_wire.h"

Go to the source code of this file.

Data Structures

struct  hitec_line_t
 One line. More...

Macros

#define HITEC_LINE_GRACE_US   1000u
 The driver ends a transaction whose state machine still runs this long after the time the transaction can take.

Enumerations

enum  hitec_line_err_t {
  HITEC_LINE_OK = 0 , HITEC_LINE_ERR_ARG , HITEC_LINE_ERR_CLOCK , HITEC_LINE_ERR_PIO ,
  HITEC_LINE_ERR_DMA
}

Functions

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.
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).
uint8_t hitec_line_rx_mode (const hitec_line_t *line)
 The receive mode of the open line; HITEC_RX_PULL_UP while closed.
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.
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.
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: a hitec_driver_t made of one PIO (programmable input/output) state machine (hitec_line.pio) and two DMA (direct memory access) channels, one for the words of a transaction and one for the received bytes.

A D series line opened to receive by PRECHARGE (hitec_pre.h) adds a second state machine, the sampler, and a third DMA channel for its samples.

Implements the signal-wire programming protocols of Hitec servos. Hitec is a name or trademark of its owner; it is used here only to say which servos this module works with (README.md, "Legal notice and disclaimer").

Resources. hitec_line_open() claims 1 state machine, 30 words of program space in a PIO block that reaches the pin, and 2 DMA channels; hitec_line_close() gives all of them back. Every open line loads its own copy of the program, so a block of 32 words holds 1 line and the RP2350's 3 blocks hold up to 3. No interrupt and no PIO interrupt flag is used. PRECHARGE claims 1 more state machine with the sampler's program, 7 words at 150MHz (hitec_pre_program()), in a block with room for it, and 1 more DMA channel, at the open; the close gives them back.

Clock. The divider is computed from clock_get_hz(clk_sys) at the open, 16 state machine cycles a bit. The open is refused when the divider would be below 4 or the bit time more than 0.05% off. The system clock must not change while the line is open.

Pad. Open and outside a transaction the pad is an input: classic with its pull-down on, the D series with its pull-up on and the input inverted. The internal pulls are 50 to 80kOhm; the D series needs a pull-up on the board. In a transaction the pad drives as the stream says and is released at the end of the transmit, at the end of the answer, at the end of the window, at an abort and at a restart. The close leaves the pad an input with the family's pull and the input override off.

PRECHARGE. A SEND with a receive window goes out with no receiver (hitec_pre_tx_xfer()). The first poll() that finds the request ended hands the pad to the sampler: the pin's control and pad registers are kept, the pin goes to the sampler's PIO block with no input override, 2mA drive and slow slew, and a DMA channel writes the samples to the line object. Each poll() decodes the words written since the last one (hitec_pre_step()). At the decoder's end, at the last word, at an abort and at the close the sampler stops with the pad released, and the pin's two registers are written back as they were. A LISTEN samples from its start; one that answers is refused, and so is a window above HITEC_PRE_WINDOW_MAX_US. A transaction with no window and a LEVEL run as in PULL-UP. The bytes' times carry the sampler's start, read off the microsecond timer: within 1us.

Every function is called from one context. hitec_line_poll() ends a transaction whose state machine still runs HITEC_LINE_GRACE_US after the time the transaction can take: the state machine is stopped, the receive channel takes the words still in the FIFO, the bytes are counted, and then the machine is restarted with the pad released. The capture holds every byte pushed before the stop and is marked as overflowed.

Not measured: no byte of this driver has been on a pin.

SPDX-License-Identifier: MIT

Enumeration Type Documentation

◆ hitec_line_err_t

Enumerator
HITEC_LINE_ERR_ARG 

No line object, a pin the chip does not have, an unknown family or drive, or push-pull for classic.

HITEC_LINE_ERR_CLOCK 

The system clock gives no divider (hitec_pio.h), or PRECHARGE no cycle counts (hitec_pre_timing()).

HITEC_LINE_ERR_PIO 

No state machine or no program space; for PRECHARGE, none for the sampler.

HITEC_LINE_ERR_DMA 

Fewer than 2 free DMA channels, 3 for PRECHARGE.

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.