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

The panel's half of the HITEC link page. More...

#include "hitec_link.h"
#include <stddef.h>
#include <string.h>

Macros

#define STAGE_WINDOWS   5u
 The staged registers and VIEW go out in 5 windows: 4 whole ones and one of 3.
#define STAGE_W   4u
 Registers of a whole window: one CAN frame.
#define SG(l, reg)
 A staged register of l by its write offset reg.
#define STATUS_N   ((unsigned)LINK_HT_DATA)
 Registers 0 to 15: the status and the capture.
#define RUN_N   ((unsigned)LINK_HT_COUNT)
 Registers 0 to 31: the read of the run, with VIEW and the capture in the same read.
#define FLAG_MASK   0x0FF8u
 LINK_HT_STATE's flag bits.

Enumerations

enum  {
  X_NONE = 0 , X_STATUS , X_STAGE , X_CMD ,
  X_RUN
}

Functions

static bool op_transaction (uint8_t op)
 Whether op is a transaction, one that leaves a capture.
static void ses_of (uint8_t result, const uint16_t *end, hitec_ses_result_t *out)
 The step's result for the session from how a request ended.
static void capture_of (const hitec_link_t *l, hitec_link_outcome_t *o)
 The capture of a step's end into the outcome.
static uint16_t run_reg (const uint16_t *run, unsigned reg)
 A register of VIEW 2 from a read of registers 16 to 31.
static uint32_t run32 (const uint16_t *run, unsigned lo)
 A 32-bit value of VIEW 2, low half first.
static void finish (hitec_link_t *l, hitec_link_outcome_kind_t kind, uint8_t nack, const uint16_t *run)
 The request on its way ends here, as kind.
void hitec_link_init (hitec_link_t *l)
 Sets up the module: no IOmcu, nothing owed.
void hitec_link_lost (hitec_link_t *l)
 The link went: a request on its way ends as HITEC_LINK_OUT_NO_ANSWER and nothing is read or written until it comes up again.
void hitec_link_came_up (hitec_link_t *l, uint16_t minor)
 An IOmcu answered with protocol minor minor.
bool hitec_link_has_page (const hitec_link_t *l)
 Whether the IOmcu has the page.
static hitec_link_start_t ready (const hitec_link_t *l)
 Whether a request is taken now.
static void begin (hitec_link_t *l, link_hitec_op_t op, uint8_t port, uint32_t id, uint16_t key, bool staged)
 Put a request on its way.
static void stage_clear (hitec_link_t *l)
 Clear the staged registers and set VIEW to the run.
static void stage32 (hitec_link_t *l, unsigned lo, uint32_t v)
 Store a 32-bit value in two staged registers, low half first.
hitec_link_start_t hitec_link_open (hitec_link_t *l, uint8_t port, uint8_t family, uint8_t drive, uint32_t id)
 OPEN port for family and drive.
static hitec_link_start_t bare (hitec_link_t *l, link_hitec_op_t op, uint8_t port, uint32_t id)
 A request with no staged registers: CLOSE or CLEAR.
hitec_link_start_t hitec_link_close (hitec_link_t *l, uint8_t port, uint32_t id)
 CLOSE port: any port the page holds, one another writer opened included. The supply is left as it is.
hitec_link_start_t hitec_link_clear (hitec_link_t *l, uint8_t port, uint32_t id)
 CLEAR the STOPPED flag of port.
static bool step_op (const hitec_ses_step_t *st, link_hitec_op_t *op)
 The operation that runs a step, and whether the step is one.
hitec_link_start_t hitec_link_step (hitec_link_t *l, uint8_t port, const hitec_ses_step_t *st, uint16_t mv, uint16_t ma, uint32_t id)
 Run one session step on port: an XFER as SEND, LISTEN or LEVEL by its kind, or a POWER at mv and ma with the step's off time and its LISTEN.
static void cmd_in_doubt (hitec_link_t *l, bool abort)
 The command went and no answer came: it is not sent again.
void hitec_link_abort (hitec_link_t *l)
 STOP, or the operator's cancel.
static bool ask (hitec_link_t *l, hitec_link_xfer_t *x, uint8_t kind, bool write, unsigned off, unsigned n, const uint16_t *regs)
 Sets up one exchange with the page.
static bool ask_status (hitec_link_t *l, hitec_link_xfer_t *x)
 Sets up a read of registers 0 to 15.
static bool due (const hitec_link_t *l, uint32_t period)
 Whether a periodic read is due.
static bool ask_cmd (hitec_link_t *l, hitec_link_xfer_t *x)
 Sets up the write of the command on its way.
static bool next_request (hitec_link_t *l, hitec_link_xfer_t *x)
 The next exchange of a request on its way out or being fetched.
bool hitec_link_next (hitec_link_t *l, uint32_t now_ms, hitec_link_xfer_t *x)
 The next exchange owed at now_ms, into x; false for none.
static bool page_fits_cmd (const hitec_link_t *l, const uint16_t *regs)
 Whether the page regs is in a state the request's command leaves, against the status read before it (l->status).
static bool page_took_cmd (const hitec_link_t *l, const uint16_t *regs)
 Whether the page regs took the command that was not sent again.
static bool op_went_back (const hitec_link_t *l, const uint16_t *regs)
 Whether the page regs started again since the status last read: it names no operation after a read that named one.
static void port_look (hitec_link_t *l, const uint16_t *regs)
 A free port in the read regs is no longer this module's.
static void on_running (hitec_link_t *l, const uint16_t *regs)
 A request that runs: whether the read regs ends it, and how.
static void on_verdict (hitec_link_t *l, const uint16_t *regs)
 The command's verdict: refused, done at once, or running.
static void on_status (hitec_link_t *l, const uint16_t *regs)
 Takes a read of registers 0 to 15 into the state.
static void on_refused (hitec_link_t *l, uint8_t kind, uint8_t nack)
 Handles an exchange the page refused.
static void on_silence (hitec_link_t *l, uint8_t kind)
 An exchange went without an answer.
static void on_run (hitec_link_t *l, const uint16_t *regs)
 Takes the read of registers 0 to 31 that ends a request.
void hitec_link_done (hitec_link_t *l, int result, const uint16_t *regs)
 How the exchange hitec_link_next() gave went.
unsigned hitec_link_service (hitec_link_t *l, uint32_t now_ms, hitec_link_xchg_fn xchg, void *ctx)
 Up to HITEC_LINK_PASS_MAX exchanges through xchg: one pass.
hitec_link_phase_t hitec_link_phase (const hitec_link_t *l)
 Where the module is.
bool hitec_link_outcome (hitec_link_t *l, hitec_link_outcome_t *out)
 How the last request went, once.
void hitec_link_readout (const hitec_link_t *l, hitec_link_readout_t *r)
 The screen's copy of the page.

Detailed Description

The panel's half of the HITEC link page.

See hitec_link.h.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ SG

#define SG ( l,
reg )
Value:
((l)->staged[(unsigned)(reg) - (unsigned)LINK_HT_W_LINE])

A staged register of l by its write offset reg.

Function Documentation

◆ ask()

bool ask ( hitec_link_t * l,
hitec_link_xfer_t * x,
uint8_t kind,
bool write,
unsigned off,
unsigned n,
const uint16_t * regs )
static

Sets up one exchange with the page.

Parameters
lThe module.
xReceives the exchange.
kindThe exchange kind.
writetrue for a write.
offThe first register.
nThe number of registers.
regsThe registers to write, or NULL for a read.
Returns
Always true.

◆ ask_cmd()

bool ask_cmd ( hitec_link_t * l,
hitec_link_xfer_t * x )
static

Sets up the write of the command on its way.

Parameters
lThe module.
xReceives the exchange.
Returns
Always true.

◆ ask_status()

bool ask_status ( hitec_link_t * l,
hitec_link_xfer_t * x )
static

Sets up a read of registers 0 to 15.

Parameters
lThe module.
xReceives the exchange.
Returns
Always true.

◆ bare()

hitec_link_start_t bare ( hitec_link_t * l,
link_hitec_op_t op,
uint8_t port,
uint32_t id )
static

A request with no staged registers: CLOSE or CLEAR.

Parameters
lThe module.
opThe operation.
portThe port.
idThe caller's number of it.
Returns
As hitec_link_open().

◆ begin()

void begin ( hitec_link_t * l,
link_hitec_op_t op,
uint8_t port,
uint32_t id,
uint16_t key,
bool staged )
static

Put a request on its way.

Parameters
lThe module.
opThe operation.
portThe port.
idThe caller's number of it.
keyLINK_HT_W_KEY of its command.
stagedtrue when the staged registers go out first.

◆ capture_of()

void capture_of ( const hitec_link_t * l,
hitec_link_outcome_t * o )
static

The capture of a step's end into the outcome.

Parameters
lThe module.
oThe outcome.

◆ cmd_in_doubt()

void cmd_in_doubt ( hitec_link_t * l,
bool abort )
static

The command went and no answer came: it is not sent again.

Whether the page took it, the next status read says (on_status()). That read has HITEC_LINK_RETRIES tries of its own.

Parameters
lThe module.
aborttrue when an abort asked for it.

◆ due()

bool due ( const hitec_link_t * l,
uint32_t period )
static

Whether a periodic read is due.

Parameters
lThe module.
periodThe period, ms.
Returns
true when no read was made yet or period has passed since the last one.

◆ finish()

void finish ( hitec_link_t * l,
hitec_link_outcome_kind_t kind,
uint8_t nack,
const uint16_t * run )
static

The request on its way ends here, as kind.

Parameters
lThe module.
kindThe outcome kind.
nackThe NACK reason of the last answer, or 0.
runRegisters 16 to 31 of the step, or NULL.

◆ hitec_link_abort()

void hitec_link_abort ( hitec_link_t * l)

STOP, or the operator's cancel.

A request whose command has not gone is dropped (HITEC_LINK_OUT_DROPPED). A command that went without an answer is not sent again: a read of registers 0 to 15 follows, and a page at the SEQ before the command did not take it, which drops the request too. The command ABORT is sent as soon as the page is known; a request that runs ends with LINK_HITEC_RESULT_CUT, a step's capture marked aborted. An ABORT refused with LINK_NACK_BAD_VALUE goes again after a read of the page, with its SEQ.

Parameters
lThe module.

◆ hitec_link_came_up()

void hitec_link_came_up ( hitec_link_t * l,
uint16_t minor )

An IOmcu answered with protocol minor minor.

Below HITEC_LINK_MINOR it has no page and nothing is sent to it.

Parameters
lThe module.
minorThe IOmcu's protocol minor.

◆ hitec_link_clear()

hitec_link_start_t hitec_link_clear ( hitec_link_t * l,
uint8_t port,
uint32_t id )

CLEAR the STOPPED flag of port.

The page refuses it with LINK_HITEC_REF_UNSAFE while its heartbeat is not trusted or its link is silent.

Parameters
lThe module.
portThe programming port, 0 to LINK_PG_PORTS_MAX - 1.
idThe caller's number of the request.
Returns
As hitec_link_open().

◆ hitec_link_close()

hitec_link_start_t hitec_link_close ( hitec_link_t * l,
uint8_t port,
uint32_t id )

CLOSE port: any port the page holds, one another writer opened included. The supply is left as it is.

Parameters
lThe module.
portThe programming port, 0 to LINK_PG_PORTS_MAX - 1.
idThe caller's number of the request.
Returns
As hitec_link_open().

◆ hitec_link_done()

void hitec_link_done ( hitec_link_t * l,
int result,
const uint16_t * regs )

How the exchange hitec_link_next() gave went.

Parameters
lThe module.
resultHITEC_LINK_ACK, a NACK's reason or HITEC_LINK_NO_ANSWER.
regsA read's registers, x.n of them; NULL for a write.

◆ hitec_link_has_page()

bool hitec_link_has_page ( const hitec_link_t * l)

Whether the IOmcu has the page.

Parameters
lThe module.
Returns
true while an IOmcu answers and has the page.

◆ hitec_link_init()

void hitec_link_init ( hitec_link_t * l)

Sets up the module: no IOmcu, nothing owed.

Parameters
lThe module.

◆ hitec_link_lost()

void hitec_link_lost ( hitec_link_t * l)

The link went: a request on its way ends as HITEC_LINK_OUT_NO_ANSWER and nothing is read or written until it comes up again.

The page's port, when held, is no longer this module's (ours).

Parameters
lThe module.

◆ hitec_link_next()

bool hitec_link_next ( hitec_link_t * l,
uint32_t now_ms,
hitec_link_xfer_t * x )

The next exchange owed at now_ms, into x; false for none.

The caller makes it and reports with hitec_link_done().

Parameters
lThe module.
now_msThe time, ms.
xReceives the exchange.
Returns
true when an exchange is owed.

◆ hitec_link_open()

hitec_link_start_t hitec_link_open ( hitec_link_t * l,
uint8_t port,
uint8_t family,
uint8_t drive,
uint32_t id )

OPEN port for family and drive.

The outcome comes when the page has left STOPPING: result DONE with the port in OPEN, NO_LINE, or CUT by a stop. The line's pin is read then.

Parameters
lThe module.
portThe programming port, 0 to LINK_PG_PORTS_MAX - 1.
familyhitec_family_t.
drivehitec_drive_t.
idThe caller's number of the request.
Returns
HITEC_LINK_START_OK when the request is on its way, else why not; nothing is sent then.

◆ hitec_link_outcome()

bool hitec_link_outcome ( hitec_link_t * l,
hitec_link_outcome_t * out )

How the last request went, once.

Parameters
lThe module.
outReceives the outcome.
Returns
true when a new outcome was written to out.

◆ hitec_link_phase()

hitec_link_phase_t hitec_link_phase ( const hitec_link_t * l)

Where the module is.

Parameters
lThe module.
Returns
The phase; HITEC_LINK_DOWN for NULL.

◆ hitec_link_readout()

void hitec_link_readout ( const hitec_link_t * l,
hitec_link_readout_t * r )

The screen's copy of the page.

Parameters
lThe module.
rReceives the copy.

◆ hitec_link_service()

unsigned hitec_link_service ( hitec_link_t * l,
uint32_t now_ms,
hitec_link_xchg_fn xchg,
void * ctx )

Up to HITEC_LINK_PASS_MAX exchanges through xchg: one pass.

Stops after an exchange without an answer.

Parameters
lThe module.
now_msThe time, ms.
xchgThe caller's exchange.
ctxIts context.
Returns
The exchanges made.

◆ hitec_link_step()

hitec_link_start_t hitec_link_step ( hitec_link_t * l,
uint8_t port,
const hitec_ses_step_t * st,
uint16_t mv,
uint16_t ma,
uint32_t id )

Run one session step on port: an XFER as SEND, LISTEN or LEVEL by its kind, or a POWER at mv and ma with the step's off time and its LISTEN.

The step's decoder and its argument go to the page. The key goes with every SEND and with a LISTEN or POWER that answers. The set points and the off time are not checked here: the page refuses them with LINK_HITEC_REF_SUPPLY_RANGE.

Parameters
lThe module.
portThe programming port, 0 to LINK_PG_PORTS_MAX - 1.
stThe step, XFER or POWER; its transaction valid (hitec_xfer_valid()), a POWER's a LISTEN.
mvPOWER: the supply voltage, mV.
maPOWER: its current limit, mA.
idThe caller's number of the request.
Returns
As hitec_link_open().

◆ next_request()

bool next_request ( hitec_link_t * l,
hitec_link_xfer_t * x )
static

The next exchange of a request on its way out or being fetched.

Parameters
lThe module.
xReceives the exchange.
Returns
true when one is owed.

◆ on_refused()

void on_refused ( hitec_link_t * l,
uint8_t kind,
uint8_t nack )
static

Handles an exchange the page refused.

Parameters
lThe module.
kindThe exchange kind.
nackThe NACK reason.

◆ on_run()

void on_run ( hitec_link_t * l,
const uint16_t * regs )
static

Takes the read of registers 0 to 31 that ends a request.

VIEW is written without a command, so another writer can change it without a new SEQ. Registers 16 to 31 are the run's when the same read shows VIEW at LINK_HITEC_VIEW_RUN and the SEQ, the operation with its count and the capture of the read that ended the request; otherwise the outcome carries no run and the line read before stays. The step's result is that of the read that ended the request either way.

Parameters
lThe module.
regsRegisters 0 to 31 as read.

◆ on_running()

void on_running ( hitec_link_t * l,
const uint16_t * regs )
static

A request that runs: whether the read regs ends it, and how.

Parameters
lThe module.
regsRegisters 0 to 15 as read.

◆ on_silence()

void on_silence ( hitec_link_t * l,
uint8_t kind )
static

An exchange went without an answer.

Parameters
lThe module.
kindThe exchange kind.

◆ on_status()

void on_status ( hitec_link_t * l,
const uint16_t * regs )
static

Takes a read of registers 0 to 15 into the state.

Parameters
lThe module.
regsRegisters 0 to 15 as read.

◆ on_verdict()

void on_verdict ( hitec_link_t * l,
const uint16_t * regs )
static

The command's verdict: refused, done at once, or running.

Parameters
lThe module.
regsRegisters 0 to 15 as read.

◆ op_transaction()

bool op_transaction ( uint8_t op)
static

Whether op is a transaction, one that leaves a capture.

Parameters
opThe operation.
Returns
true for SEND, LISTEN, LEVEL and POWER.

◆ op_went_back()

bool op_went_back ( const hitec_link_t * l,
const uint16_t * regs )
static

Whether the page regs started again since the status last read: it names no operation after a read that named one.

Parameters
lThe module.
regsRegisters 0 to 15 as read.
Returns
true when LINK_HT_OP went back to NONE.

◆ page_fits_cmd()

bool page_fits_cmd ( const hitec_link_t * l,
const uint16_t * regs )
static

Whether the page regs is in a state the request's command leaves, against the status read before it (l->status).

The SEQ alone does not name the writer: another writer's command at the same SEQ, ahead of a try of this one, leaves it too. A refusal fits: the outcome is REFUSED and claims no run. CLOSE leaves the port free or another port held; CLEAR leaves the port held with STOPPED clear. An operation that starts names itself in LINK_HT_OP on the request's port and changes the page: the operation, the transaction count, the state or the result differ from the read before. A transaction the driver refused that repeats the operation and result before it does not fit; the request ends FAILED either way.

Parameters
lThe module.
regsRegisters 0 to 15 as read.
Returns
true when the state fits the request's command.

◆ page_took_cmd()

bool page_took_cmd ( const hitec_link_t * l,
const uint16_t * regs )
static

Whether the page regs took the command that was not sent again.

A command taken leaves its SEQ. A page that started again reads SEQ 0, operation NONE and no refusal: at SEQ 0, the command after 0xFFFF, the SEQ alone does not tell the two apart, and such a page counts as one that started again.

Parameters
lThe module.
regsRegisters 0 to 15 as read.
Returns
true when the page shows the command's SEQ, is no fresh page and is in a state the command leaves (page_fits_cmd()).

◆ port_look()

void port_look ( hitec_link_t * l,
const uint16_t * regs )
static

A free port in the read regs is no longer this module's.

Another port held, or the same one taken again, comes with another SEQ, which on_status() takes as a restart.

Parameters
lThe module.
regsRegisters 0 to 15 as read.

◆ ready()

hitec_link_start_t ready ( const hitec_link_t * l)
static

Whether a request is taken now.

Parameters
lThe module.
Returns
HITEC_LINK_START_OK when it is, else the reason it is not.

◆ run32()

uint32_t run32 ( const uint16_t * run,
unsigned lo )
static

A 32-bit value of VIEW 2, low half first.

Parameters
runThe registers read.
loThe register of the low half, LINK_HT_I_*.
Returns
The value.

◆ run_reg()

uint16_t run_reg ( const uint16_t * run,
unsigned reg )
static

A register of VIEW 2 from a read of registers 16 to 31.

Parameters
runThe registers read.
regThe register, LINK_HT_I_*.
Returns
Its value.

◆ ses_of()

void ses_of ( uint8_t result,
const uint16_t * end,
hitec_ses_result_t * out )
static

The step's result for the session from how a request ended.

Parameters
resultlink_hitec_result_t the page gave.
endRegisters 0 to 15 as the request ended.
outReceives the result.

◆ stage32()

void stage32 ( hitec_link_t * l,
unsigned lo,
uint32_t v )
static

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

Parameters
lThe module.
loThe write offset of the low half.
vThe value.

◆ stage_clear()

void stage_clear ( hitec_link_t * l)
static

Clear the staged registers and set VIEW to the run.

Parameters
lThe module.

◆ step_op()

bool step_op ( const hitec_ses_step_t * st,
link_hitec_op_t * op )
static

The operation that runs a step, and whether the step is one.

Parameters
stThe step.
opReceives the operation.
Returns
true for an XFER or a POWER whose transaction the page can carry.