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

The Hitec servo wire on a programming port: the OPEN, transaction, POWER and CLOSE states. More...

#include "hitec_port.h"
#include <stddef.h>
#include <string.h>
#include "hitec_pre.h"

Macros

#define COUNT_MAX   0x0FFFu
 The transaction count stops at this value (12 bits).
#define ST(p, reg)

Functions

static uint32_t st32 (const hitec_port_t *p, unsigned lo)
 Read the 32-bit staged value at write offset lo, low word first.
static bool supply_view (const hitec_port_t *p, supply_port_view_t *v)
 Read the supply's view of the port into v.
static void supply_off (hitec_port_t *p)
 Ask the supply off, when the build has a supply to switch.
static void op_begin (hitec_port_t *p, link_hitec_op_t op)
 Start an operation: record its code and set the result to RUNNING.
static void go_free (hitec_port_t *p)
 Back to free: the line closed, the pin the generator's.
static void finish (hitec_port_t *p)
 The capture is in: decode it as the transaction asked.
static void cut (hitec_port_t *p)
 Cut the running transaction; its capture comes at the next poll.
static void start (hitec_port_t *p, const hitec_xfer_t *x, uint8_t keyed)
 Start x on the line: BUSY, or OPEN with LINK_HITEC_RESULT_START.
static void on_stop (hitec_port_t *p)
 Apply a stop to the port, by its state.
static bool decoder_ok (const hitec_port_t *p, link_hitec_op_t op)
 The decoder the staged registers ask for, checked against the family.
static bool staged_xfer (const hitec_port_t *p, link_hitec_op_t op, hitec_xfer_t *x)
 The transaction the staged registers say for op; false when it is not one the line runs.
static bool power_range_ok (const supply_port_view_t *v, uint16_t mv, uint16_t ma, uint16_t off_ms)
 Whether the PD mini gives the servo mv and ma: inside the POWER bounds, and under the input with the module's cap.
static link_hitec_refusal_t open_port (hitec_port_t *p, uint8_t port, const uint16_t *in, uint32_t now_ms)
 Start OPEN on port: take the staged line and the port's pin, and enter STOPPING.
static link_hitec_refusal_t close_port (hitec_port_t *p, uint8_t port)
 Start CLOSE on port: cut what runs, close the line and free the port.
static void abort_op (hitec_port_t *p)
 Cut what runs: a STOPPING port is freed, a BUSY port is cut, and a POWER in its off time ends.
static link_hitec_refusal_t power (hitec_port_t *p, const hitec_xfer_t *x, uint32_t now_ms)
 Start POWER: check the supply and the set points, then ask the supply off.
static bool puts_byte_out (link_hitec_op_t op, const hitec_xfer_t *x)
 Whether a transaction puts a byte on the wire.
static link_hitec_refusal_t transaction (hitec_port_t *p, link_hitec_op_t op, uint8_t port, const uint16_t *in, uint32_t now_ms)
 SEND, LISTEN, LEVEL and POWER.
static link_hitec_refusal_t dispatch (hitec_port_t *p, link_hitec_op_t op, uint8_t port, const uint16_t *in, uint32_t now_ms)
 Route one command to its operation.
static uint8_t command (hitec_port_t *p, const uint16_t *in, uint32_t now_ms)
 Handle the command frame, registers 0 to 3.
uint8_t hitec_port_write (hitec_port_t *p, uint8_t off, uint8_t n, const uint16_t *in, uint32_t now_ms)
 A write of the page: 0, or the LINK_NACK_* reason with nothing changed.
static void put32 (uint16_t *at, uint32_t v)
 Store a 32-bit value in two registers, low word first.
static uint16_t state_reg (const hitec_port_t *p)
 The STATE register: the state, the port and the flags.
static void data_regs (const hitec_port_t *p, uint16_t *all)
 Registers 16 to 31 of all, as VIEW selects.
void hitec_port_read (const hitec_port_t *p, uint8_t off, uint8_t n, uint16_t *out)
 A read of the page, LINK_HT_*.
static void step_busy (hitec_port_t *p, uint32_t now_ms)
 The pass of a BUSY port: take the capture, or cut a precharge line or a run past its time.
static void step_power (hitec_port_t *p, uint32_t now_ms)
 The pass of a POWER port: wait for the supply to read off, its off time, then the ON and the listen.
void hitec_port_step (hitec_port_t *p, bool safe, bool stop, uint32_t now_ms)
 One pass.
bool hitec_port_init (hitec_port_t *p, const hitec_port_hw_t *hw)
 Prepare a free port.
link_hitec_state_t hitec_port_state (const hitec_port_t *p)
 Where the port is.
uint8_t hitec_port_quiet_mask (const hitec_port_t *p)
 Bit n: programming port n renders no PWM pulse.
uint8_t hitec_port_pin_mask (const hitec_port_t *p)
 Bit n: programming port n's pin is the wire driver's.
void hitec_port_bench_armed (hitec_port_t *p, bool armed)
 Whether the bank is armed: OPEN is refused while it is.
void hitec_port_other_mask (hitec_port_t *p, uint8_t mask)
 Bit n: the KST page holds programming port n (kst_port_quiet_mask()). OPEN on it is refused with LINK_HITEC_REF_HELD.
bool hitec_port_supply_hold (const hitec_port_t *p)
 The port holds the SUPPLY page (supply_page_hold()): every state but LINK_HITEC_FREE, from OPEN to CLOSE.
bool hitec_port_frame_out (const hitec_port_t *p, uint32_t now_ms)
 A byte may be on the wire: a SEND from its start until the lead and the bytes have had their time, counted in whole ms; a LISTEN or a POWER that answers, while it runs.

Detailed Description

The Hitec servo wire on a programming port: the OPEN, transaction, POWER and CLOSE states.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ ST

#define ST ( p,
reg )
Value:
((p)->staged[(reg) - LINK_HT_W_LINE])

Function Documentation

◆ abort_op()

void abort_op ( hitec_port_t * p)
static

Cut what runs: a STOPPING port is freed, a BUSY port is cut, and a POWER in its off time ends.

Parameters
pThe port.

◆ close_port()

link_hitec_refusal_t close_port ( hitec_port_t * p,
uint8_t port )
static

Start CLOSE on port: cut what runs, close the line and free the port.

Parameters
pThe port.
portProgramming port index.
Returns
LINK_HITEC_REF_NONE when CLOSE runs; otherwise the refusal.

◆ command()

uint8_t command ( hitec_port_t * p,
const uint16_t * in,
uint32_t now_ms )
static

Handle the command frame, registers 0 to 3.

Parameters
pThe port.
inThe command frame's four registers.
now_msCurrent time in milliseconds.
Returns
0 when the frame is acknowledged; LINK_NACK_BAD_VALUE for a bad frame or SEQ.

◆ cut()

void cut ( hitec_port_t * p)
static

Cut the running transaction; its capture comes at the next poll.

Parameters
pThe port.

◆ data_regs()

void data_regs ( const hitec_port_t * p,
uint16_t * all )
static

Registers 16 to 31 of all, as VIEW selects.

Parameters
pThe port.
allThe register image, LINK_HT_COUNT entries, filled in place.

◆ decoder_ok()

bool decoder_ok ( const hitec_port_t * p,
link_hitec_op_t op )
static

The decoder the staged registers ask for, checked against the family.

Parameters
pThe port.
opThe operation the registers were staged for.
Returns
true when the staged decoder fits the operation and the family.

◆ dispatch()

link_hitec_refusal_t dispatch ( hitec_port_t * p,
link_hitec_op_t op,
uint8_t port,
const uint16_t * in,
uint32_t now_ms )
static

Route one command to its operation.

Parameters
pThe port.
opThe operation.
portProgramming port index.
inThe command frame's registers.
now_msCurrent time in milliseconds.
Returns
LINK_HITEC_REF_NONE when the operation is taken; otherwise the refusal.

◆ finish()

void finish ( hitec_port_t * p)
static

The capture is in: decode it as the transaction asked.

Parameters
pThe port.

◆ go_free()

void go_free ( hitec_port_t * p)
static

Back to free: the line closed, the pin the generator's.

Parameters
pThe port.

◆ hitec_port_bench_armed()

void hitec_port_bench_armed ( hitec_port_t * p,
bool armed )

Whether the bank is armed: OPEN is refused while it is.

Parameters
pThe port, or NULL; a NULL p is ignored.
armedtrue when the bank is armed.

◆ hitec_port_frame_out()

bool hitec_port_frame_out ( const hitec_port_t * p,
uint32_t now_ms )

A byte may be on the wire: a SEND from its start until the lead and the bytes have had their time, counted in whole ms; a LISTEN or a POWER that answers, while it runs.

Parameters
pThe port, or NULL.
now_msCurrent time in milliseconds.
Returns
true while a byte may be on the wire; false for a NULL p or a port that is not BUSY.

◆ hitec_port_init()

bool hitec_port_init ( hitec_port_t * p,
const hitec_port_hw_t * hw )

Prepare a free port.

False when hw names no port or lacks a function other than run and the supply's two, or has one of those two.

Parameters
pThe port to prepare; zeroed first.
hwThe hardware hooks, copied into the port.
Returns
true when the port is prepared; false for a NULL p, or for a hw that fails the checks above.

◆ hitec_port_other_mask()

void hitec_port_other_mask ( hitec_port_t * p,
uint8_t mask )

Bit n: the KST page holds programming port n (kst_port_quiet_mask()). OPEN on it is refused with LINK_HITEC_REF_HELD.

Parameters
pThe port, or NULL; a NULL p is ignored.
maskBit n: the KST page holds programming port n.

◆ hitec_port_pin_mask()

uint8_t hitec_port_pin_mask ( const hitec_port_t * p)

Bit n: programming port n's pin is the wire driver's.

From the take until CLOSE.

Parameters
pThe port, or NULL.
Returns
Bit n set for port n while the wire driver holds its pin; 0 for a NULL p.

◆ hitec_port_quiet_mask()

uint8_t hitec_port_quiet_mask ( const hitec_port_t * p)

Bit n: programming port n renders no PWM pulse.

The held port in every state but LINK_HITEC_FREE.

Parameters
pThe port, or NULL.
Returns
Bit n set for port n while the port is held and not free; 0 for a NULL p.

◆ hitec_port_read()

void hitec_port_read ( const hitec_port_t * p,
uint8_t off,
uint8_t n,
uint16_t * out )

A read of the page, LINK_HT_*.

Parameters
pThe port.
offFirst register of the window.
nNumber of registers to read.
outReceives n register values; left unchanged for a NULL p or out, or a window past LINK_HT_COUNT.

◆ hitec_port_state()

link_hitec_state_t hitec_port_state ( const hitec_port_t * p)

Where the port is.

Parameters
pThe port, or NULL.
Returns
The state of the port; LINK_HITEC_FREE for a NULL p.

◆ hitec_port_step()

void hitec_port_step ( hitec_port_t * p,
bool safe,
bool stop,
uint32_t now_ms )

One pass.

safe: the heartbeat is trusted and the link is not silent. stop: the bank was switched off or disarmed since the last pass.

Parameters
pThe port.
safetrue when the heartbeat is trusted and the link is not silent.
stoptrue when the bank was switched off or disarmed since the last pass.
now_msCurrent time in milliseconds.

◆ hitec_port_supply_hold()

bool hitec_port_supply_hold ( const hitec_port_t * p)

The port holds the SUPPLY page (supply_page_hold()): every state but LINK_HITEC_FREE, from OPEN to CLOSE.

Parameters
pThe port, or NULL.
Returns
true while the port is held, a stopped one included; false for a free port and for a NULL p.

◆ hitec_port_write()

uint8_t hitec_port_write ( hitec_port_t * p,
uint8_t off,
uint8_t n,
const uint16_t * in,
uint32_t now_ms )

A write of the page: 0, or the LINK_NACK_* reason with nothing changed.

A window that starts in registers 0 to 3 is a command and has to be exactly those 4. Registers 4 to 23 are taken in any windows; 24 and up are LINK_NACK_READ_ONLY. A VIEW or an RX_MODE above the last is LINK_NACK_BAD_VALUE.

Parameters
pThe port.
offFirst register of the window.
nNumber of registers in the window; 0 is refused.
inThe n register values to write.
now_msCurrent time in milliseconds.
Returns
0 when the write is applied or the command is acknowledged; otherwise LINK_NACK_BAD_RANGE, LINK_NACK_READ_ONLY or LINK_NACK_BAD_VALUE.

◆ on_stop()

void on_stop ( hitec_port_t * p)
static

Apply a stop to the port, by its state.

Parameters
pThe port.

◆ op_begin()

void op_begin ( hitec_port_t * p,
link_hitec_op_t op )
static

Start an operation: record its code and set the result to RUNNING.

Parameters
pThe port.
opThe operation to record.

◆ open_port()

link_hitec_refusal_t open_port ( hitec_port_t * p,
uint8_t port,
const uint16_t * in,
uint32_t now_ms )
static

Start OPEN on port: take the staged line and the port's pin, and enter STOPPING.

Parameters
pThe port.
portProgramming port index.
inThe command frame's registers.
now_msCurrent time in milliseconds.
Returns
LINK_HITEC_REF_NONE when OPEN starts; otherwise the refusal.

◆ power()

link_hitec_refusal_t power ( hitec_port_t * p,
const hitec_xfer_t * x,
uint32_t now_ms )
static

Start POWER: check the supply and the set points, then ask the supply off.

Parameters
pThe port.
xThe listen the POWER runs after the ON.
now_msCurrent time in milliseconds.
Returns
LINK_HITEC_REF_NONE when POWER starts; otherwise the refusal.

◆ power_range_ok()

bool power_range_ok ( const supply_port_view_t * v,
uint16_t mv,
uint16_t ma,
uint16_t off_ms )
static

Whether the PD mini gives the servo mv and ma: inside the POWER bounds, and under the input with the module's cap.

Parameters
vThe supply's view.
mvThe supply set point in mV.
maThe supply current limit in mA.
off_msThe off time in milliseconds.
Returns
true when the set points and the off time are in range and the input is unknown or holds the module's cap above mv.

◆ put32()

void put32 ( uint16_t * at,
uint32_t v )
static

Store a 32-bit value in two registers, low word first.

Parameters
atThe first of two registers.
vThe value.

◆ puts_byte_out()

bool puts_byte_out ( link_hitec_op_t op,
const hitec_xfer_t * x )
static

Whether a transaction puts a byte on the wire.

Parameters
opThe operation.
xThe transaction.
Returns
true for a SEND, or a transaction that answers.

◆ st32()

uint32_t st32 ( const hitec_port_t * p,
unsigned lo )
static

Read the 32-bit staged value at write offset lo, low word first.

Parameters
pThe port.
loWrite offset of the low 16-bit register.
Returns
The registers lo and lo + 1 joined, lo in the low half.

◆ staged_xfer()

bool staged_xfer ( const hitec_port_t * p,
link_hitec_op_t op,
hitec_xfer_t * x )
static

The transaction the staged registers say for op; false when it is not one the line runs.

Parameters
pThe port.
opThe operation the registers were staged for.
xReceives the transaction the staged registers describe.
Returns
true when the transaction is valid; false when it is not one the line runs.

◆ start()

void start ( hitec_port_t * p,
const hitec_xfer_t * x,
uint8_t keyed )
static

Start x on the line: BUSY, or OPEN with LINK_HITEC_RESULT_START.

Parameters
pThe port.
xThe transaction to start.
keyed1 when the transaction puts a byte out, else 0.

◆ state_reg()

uint16_t state_reg ( const hitec_port_t * p)
static

The STATE register: the state, the port and the flags.

Parameters
pThe port.
Returns
The STATE register value.

◆ step_busy()

void step_busy ( hitec_port_t * p,
uint32_t now_ms )
static

The pass of a BUSY port: take the capture, or cut a precharge line or a run past its time.

Parameters
pThe port.
now_msCurrent time in milliseconds.

◆ step_power()

void step_power ( hitec_port_t * p,
uint32_t now_ms )
static

The pass of a POWER port: wait for the supply to read off, its off time, then the ON and the listen.

Parameters
pThe port.
now_msCurrent time in milliseconds.

◆ supply_off()

void supply_off ( hitec_port_t * p)
static

Ask the supply off, when the build has a supply to switch.

Parameters
pThe port.

◆ supply_view()

bool supply_view ( const hitec_port_t * p,
supply_port_view_t * v )
static

Read the supply's view of the port into v.

Parameters
pThe port.
vReceives the view; zeroed first.
Returns
true when the supply is online; false when the build has no supply.

◆ transaction()

link_hitec_refusal_t transaction ( hitec_port_t * p,
link_hitec_op_t op,
uint8_t port,
const uint16_t * in,
uint32_t now_ms )
static

SEND, LISTEN, LEVEL and POWER.

Parameters
pThe port.
opThe operation.
portProgramming port index.
inThe command frame's registers.
now_msCurrent time in milliseconds.
Returns
LINK_HITEC_REF_NONE when the operation starts; otherwise the refusal.