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

The panel's half of the HITEC (0x34) link page, protocol 4.23 on: one step of a session with a servo by Hitec turned into page frames, and the page's answer turned back into its result. More...

#include <stdbool.h>
#include <stdint.h>
#include "hitec_session.h"
#include "hitec_wire.h"
#include "link_pages.h"

Go to the source code of this file.

Data Structures

 The outcome of a request that ended. More...
 The screen's copy of the page: a plain value. More...
 One exchange for the caller to make. More...
 The state of the HITEC link module. More...

Macros

#define HITEC_LINK_MINOR   LINK_MINOR_HITEC
 The protocol minor whose IOmcu has the HITEC page.
#define HITEC_LINK_POLL_MS   5u
 Registers 0 to 15 are due this long after the last read while a request runs: one 5ms pass of the panel's control task.
#define HITEC_LINK_HELD_MS   100u
 And this long after it while the page holds a port.
#define HITEC_LINK_IDLE_MS   500u
 And this long after it while the page holds none.
#define HITEC_LINK_RETRIES   3u
 Exchanges without an answer, in a row, after which a request is given up.
#define HITEC_LINK_PASS_MAX   4u
 Exchanges one hitec_link_service() call makes at most.
#define HITEC_LINK_RUN_MAX_MS   25000u
 A request still running this long after its command was taken is aborted, ms.
#define HITEC_LINK_NO_PIN   0xFFFFu
 LINK_HT_I_PIN while the driver holds no pin.
#define HITEC_LINK_NO_ANSWER   (-1)
 An exchange without an answer.
#define HITEC_LINK_ACK   0
 An exchange answered with ACK or DATA; a NACK's reason is above 0.
#define HITEC_LINK_STAGED   (LINK_HT_W_STAGED + 1u)
 Staged registers 4 to 21 and VIEW, as they go out.

Typedefs

typedef int(*) hitec_link_xchg_fn(void *ctx, const hitec_link_xfer_t *x, uint16_t *regs)
 The caller's exchange: makes x and fills regs with the x->n registers of a read that was answered with DATA.

Enumerations

enum  hitec_link_phase_t {
  HITEC_LINK_DOWN = 0 , HITEC_LINK_NO_PAGE , HITEC_LINK_SYNC , HITEC_LINK_READY ,
  HITEC_LINK_SENDING , HITEC_LINK_RUNNING , HITEC_LINK_FETCHING
}
 Where the module is. More...
enum  hitec_link_start_t {
  HITEC_LINK_START_OK = 0 , HITEC_LINK_START_DOWN , HITEC_LINK_START_NO_PAGE , HITEC_LINK_START_BUSY ,
  HITEC_LINK_START_ARG
}
 What a request answers. More...
enum  hitec_link_outcome_kind_t {
  HITEC_LINK_OUT_NONE = 0 , HITEC_LINK_OUT_DONE , HITEC_LINK_OUT_REFUSED , HITEC_LINK_OUT_NACK ,
  HITEC_LINK_OUT_NO_ANSWER , HITEC_LINK_OUT_RESTARTED , HITEC_LINK_OUT_DROPPED
}
 How a request went. More...

Functions

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.
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.
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.
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.
void hitec_link_abort (hitec_link_t *l)
 STOP, or the operator's cancel.
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.
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 (0x34) link page, protocol 4.23 on: one step of a session with a servo by Hitec turned into page frames, and the page's answer turned back into its result.

Hitec is a name or trademark of its owner; it is used here only to say which servos this module works with.

The session runs on the panel (protocols/hitec/include/hitec_session.h). The page holds no session: it runs one raw transaction at a time (shared/outputs/hitec_port.h). This module takes one request at a time:

A request goes out in this order:

  1. OPEN and a step: the staged registers 4 to 21 and VIEW (register 22, always LINK_HITEC_VIEW_RUN), 5 frames of 4, 4, 4, 4 and 3 registers;
  2. the command, registers 0 to 3, one frame, with SEQ one above the page's, the CRC of the staged registers and, for a step that puts a byte on the wire, LINK_HITEC_WRITE_KEY. A command without an answer is sent again as it was, up to HITEC_LINK_RETRIES times; the page takes it once. After the last try registers 0 to 15 are read: the page's SEQ, and a state the command leaves, tell whether it took the command. A SEQ whose state does not fit is another writer's command: HITEC_LINK_OUT_RESTARTED;
  3. registers 0 to 15 are read: the command started the operation or the page says why not (LINK_HT_RESULT's high byte);
  4. registers 0 to 15 are read every HITEC_LINK_POLL_MS until the page is out of STOPPING, BUSY and POWER_OFF. The last read holds the capture: STATE, RESULT, CAP, DEC, VALUE and the 16 bytes;
  5. registers 0 to 31 are read once: registers 16 to 31 are the run's (the decoder's delay, the times, the line and the pin) when the same read shows VIEW at LINK_HITEC_VIEW_RUN and the SEQ, the operation and the capture of step 4; otherwise the outcome has no run.

hitec_link_outcome() then hands out how it went, once.

A step that runs HITEC_LINK_RUN_MAX_MS after its command was taken is aborted from here: longer than the longest POWER the page runs, 3000ms for the supply to read off, 10,000ms off and 10,000ms of a transaction.

hitec_link_abort() is for STOP and for the operator's cancel: a request whose command has not gone is dropped, and the command ABORT follows whenever the page is known. A command sent without an answer is never sent again after it; the page's SEQ tells whether it was taken.

Between requests registers 0 to 15 are read every HITEC_LINK_HELD_MS while the page holds a port and every HITEC_LINK_IDLE_MS while it holds none. An IOmcu whose protocol minor is below HITEC_LINK_MINOR has no HITEC page and is sent nothing.

Pure C, no link of its own: the caller makes each exchange and reports how it went (hitec_link_next() and hitec_link_done(), or hitec_link_service() with the caller's exchange function). One caller only.

SPDX-License-Identifier: MIT

Typedef Documentation

◆ hitec_link_xchg_fn

typedef int(*) hitec_link_xchg_fn(void *ctx, const hitec_link_xfer_t *x, uint16_t *regs)

The caller's exchange: makes x and fills regs with the x->n registers of a read that was answered with DATA.

Parameters
ctxThe caller's context.
xThe exchange to make.
regsReceives a read's registers, 32 at most; NULL for a write.
Returns
HITEC_LINK_ACK, a NACK's reason (LINK_NACK_*), or HITEC_LINK_NO_ANSWER.

Enumeration Type Documentation

◆ hitec_link_outcome_kind_t

How a request went.

Enumerator
HITEC_LINK_OUT_DONE 

it ran; result says how it ended

HITEC_LINK_OUT_REFUSED 

the page took the command and started nothing; refusal says why

HITEC_LINK_OUT_NACK 

the page refused a frame; nack says why

HITEC_LINK_OUT_NO_ANSWER 

HITEC_LINK_RETRIES exchanges unanswered, or the link went

HITEC_LINK_OUT_RESTARTED 

the page's SEQ is not the panel's, or its operation went back to NONE: the IOmcu started again, or another writer sent a command

HITEC_LINK_OUT_DROPPED 

hitec_link_abort() before the page took the command; nothing of it ran

◆ hitec_link_phase_t

Where the module is.

Enumerator
HITEC_LINK_DOWN 

no IOmcu answers

HITEC_LINK_NO_PAGE 

the IOmcu has no HITEC page

HITEC_LINK_SYNC 

the page has not been read yet

HITEC_LINK_READY 

a request is taken

HITEC_LINK_SENDING 

the staged registers and the command go out

HITEC_LINK_RUNNING 

the page runs the request

HITEC_LINK_FETCHING 

registers 0 to 31 are read

◆ hitec_link_start_t

What a request answers.

Enumerator
HITEC_LINK_START_DOWN 

no IOmcu answers

HITEC_LINK_START_NO_PAGE 

the IOmcu has no HITEC page

HITEC_LINK_START_BUSY 

the phase is not HITEC_LINK_READY, or an exchange is still out

HITEC_LINK_START_ARG 

no such port, family, drive or step

Function Documentation

◆ 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().