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

The panel's half of the throttle's pulse endpoints, Idle pulse and Full pulse, on the CHAN_CFG (0x23) link page: when a debt is paid, what each outcome of paying it leaves, and whether a switch to ARMED may go on. More...

#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>

Go to the source code of this file.

Data Structures

struct  endpoints_debt_t
 The debt. More...

Macros

#define ENDPOINTS_SETTLE_MS   300u
 An edit rests this long before the pair is written.

Enumerations

enum  endpoints_next_t { ENDPOINTS_PAID = 0 , ENDPOINTS_WAIT_DISARM , ENDPOINTS_WAIT_SETTLE , ENDPOINTS_PAY }
 What the debt asks of this pass, endpoints_next(). More...
enum  endpoints_outcome_t {
  ENDPOINTS_NO_ANSWER = 0 , ENDPOINTS_READ_REFUSED , ENDPOINTS_ORDER , ENDPOINTS_HELD ,
  ENDPOINTS_TAKEN , ENDPOINTS_WRITE_REFUSED , ENDPOINTS_DIFFERS
}
 How paying a debt went. More...
enum  endpoints_block_t {
  ENDPOINTS_BLOCK_NONE = 0 , ENDPOINTS_BLOCK_OWED , ENDPOINTS_BLOCK_UNKNOWN , ENDPOINTS_BLOCK_ORDER ,
  ENDPOINTS_BLOCK_REFUSED , ENDPOINTS_BLOCK_DIFFERS
}
 Why a switch to ARMED is refused for the pair, endpoints_block(). More...

Functions

endpoints_next_t endpoints_next (bool owed, bool far_disarmed, uint32_t edit_ms, uint32_t now_ms)
 What a debt asks of a pass at now_ms.
bool endpoints_page_holds (const uint16_t *page, uint16_t min_us, uint16_t max_us)
 Whether every throttle channel of a CHAN_CFG page page (LINK_CC_COUNT registers) holds min_us and max_us.
bool endpoints_owed_after (endpoints_outcome_t outcome)
 Whether the debt stands after an attempt that ended in outcome: true only for ENDPOINTS_NO_ANSWER, and for a value outside the enum.
void endpoints_publish (endpoints_debt_t *d, uint16_t min_us, uint16_t max_us, uint32_t now_ms)
 An edit of Idle pulse or Full pulse at now_ms, from any task: the pair, then the time, then the flag, so a payment that sees the flag sees the pair and the rest it starts from.
void endpoints_link_up (endpoints_debt_t *d)
 A link-up edge: the pair is owed again and the far end held disarmed until it is paid.
bool endpoints_owed (const endpoints_debt_t *d)
 Whether a pair is owed: true refuses a switch to ARMED with the link up.
void endpoints_recheck (endpoints_debt_t *d)
 A binding was written: the throttle channels may have moved, so the pair is owed again, due at the next poll once its edit has rested.
endpoints_block_t endpoints_block (const endpoints_debt_t *d)
 Why a switch to ARMED with the link up is refused for the pair: ENDPOINTS_BLOCK_OWED while owed, else what the last answered payment left.
bool endpoints_blocked (const endpoints_debt_t *d)
 endpoints_block() is not ENDPOINTS_BLOCK_NONE.
bool endpoints_held (const endpoints_debt_t *d)
 Whether the far end is held disarmed for the debt.
uint16_t endpoints_min (const endpoints_debt_t *d)
 The pair as last published, in us; 0 for NULL.
uint16_t endpoints_max (const endpoints_debt_t *d)
 The Full pulse as last published, in us; 0 for NULL.
endpoints_next_t endpoints_take (endpoints_debt_t *d, bool far_disarmed, uint32_t now_ms)
 The debt at a poll, on the control task: what endpoints_next() finds.
void endpoints_paid (endpoints_debt_t *d, endpoints_outcome_t outcome)
 The end of a payment endpoints_take() handed out: owed again on a missing answer, the hold and the block kept with it; otherwise paid, the hold ended, and the block set from outcome – none for ENDPOINTS_HELD and ENDPOINTS_TAKEN.

Detailed Description

The panel's half of the throttle's pulse endpoints, Idle pulse and Full pulse, on the CHAN_CFG (0x23) link page: when a debt is paid, what each outcome of paying it leaves, and whether a switch to ARMED may go on.

An edit of either setting, a link-up edge and the panel's start owe the IOmcu the pair. The debt is paid at a poll whose control write put ARM = 0 at the IOmcu and was acknowledged, once ENDPOINTS_SETTLE_MS (300ms) have passed since the last edit: a key held on + or - steps the value every few hundred milliseconds, and each write of CHAN_CFG is a flash save at the IOmcu. Paying it reads the page, puts the pair on the throttle channels and writes the page when it differs.

The IOmcu applies a CHAN_CFG write to its outputs before it acknowledges it, and the acknowledgement carries what it stored. A read that already holds the pair, or an ACK whose stored throttle channels hold it, is the pair in force; a read or a write nobody answered leaves the debt owed.

Any other answer ends the debt and blocks the switch to ARMED (endpoints_block()): the read refused, Idle pulse not below Full pulse, the write refused, or an ACK whose throttle channels hold another pair. The same request refused once is refused every time, so the debt is not sent again by itself. A new edit, a new binding (endpoints_recheck()) or a link-up edge, an IOmcu restart or update included, owes the pair again, and the payment that follows decides afresh.

The frame that switches to ARMED carries no CHAN_CFG. While the pair is not in force – owed or blocked – with the link up, a switch to ARMED is refused (arming_hs_facts_t.endpoints_blocked): one that went on would run the throttle on whatever range the IOmcu holds.

The debt crosses two tasks: the settings screen publishes an edit (endpoints_publish()) and the control task, which owns the link, pays it (endpoints_service()) and asks it before a switch to ARMED (endpoints_owed()). The pair and the time travel in atomics beside the flag, the pair in one word, min in the high half, so a payment never pairs one edit's minimum with another's maximum.

No link of its own: the caller's pay function makes the exchanges and reports how they went.

SPDX-License-Identifier: MIT

Enumeration Type Documentation

◆ endpoints_block_t

Why a switch to ARMED is refused for the pair, endpoints_block().

Enumerator
ENDPOINTS_BLOCK_NONE 

The pair is in force, or nothing was ever owed.

ENDPOINTS_BLOCK_OWED 

Owed: an edit, a binding or a link-up not yet paid.

ENDPOINTS_BLOCK_UNKNOWN 

The IOmcu refused the read: its range is not known.

ENDPOINTS_BLOCK_ORDER 

Idle pulse is not below Full pulse: nothing was sent.

ENDPOINTS_BLOCK_REFUSED 

The IOmcu refused the write.

ENDPOINTS_BLOCK_DIFFERS 

The IOmcu acknowledged and stored another pair.

◆ endpoints_next_t

What the debt asks of this pass, endpoints_next().

Enumerator
ENDPOINTS_PAID 

Nothing owed.

ENDPOINTS_WAIT_DISARM 

Owed, and this pass did not put ARM = 0 at the IOmcu.

ENDPOINTS_WAIT_SETTLE 

Owed, and the last edit is younger than ENDPOINTS_SETTLE_MS.

ENDPOINTS_PAY 

Owed and due: read the page now.

◆ endpoints_outcome_t

How paying a debt went.

Enumerator
ENDPOINTS_NO_ANSWER 

The read or the write ended unanswered.

ENDPOINTS_READ_REFUSED 

The read came back refused: the range in force is not known.

ENDPOINTS_ORDER 

Idle pulse is not below Full pulse: nothing sent.

ENDPOINTS_HELD 

The page already holds the pair: nothing written.

ENDPOINTS_TAKEN 

The write came back acknowledged: the pair is in force.

ENDPOINTS_WRITE_REFUSED 

The write came back refused: the IOmcu keeps the pair it held, or the frames of the page before the refused one.

ENDPOINTS_DIFFERS 

The write came back acknowledged, and what the IOmcu stored on a throttle channel is not the pair.

Function Documentation

◆ endpoints_block()

endpoints_block_t endpoints_block ( const endpoints_debt_t * d)

Why a switch to ARMED with the link up is refused for the pair: ENDPOINTS_BLOCK_OWED while owed, else what the last answered payment left.

ENDPOINTS_BLOCK_NONE for NULL.

Parameters
dThe debt to read.
Returns
The block reason; ENDPOINTS_BLOCK_NONE for NULL.

◆ endpoints_blocked()

bool endpoints_blocked ( const endpoints_debt_t * d)

endpoints_block() is not ENDPOINTS_BLOCK_NONE.

Parameters
dThe debt to read.
Returns
true when endpoints_block() is not ENDPOINTS_BLOCK_NONE.

◆ endpoints_held()

bool endpoints_held ( const endpoints_debt_t * d)

Whether the far end is held disarmed for the debt.

False for NULL.

Parameters
dThe debt to read.
Returns
true when the far end is held disarmed.

◆ endpoints_link_up()

void endpoints_link_up ( endpoints_debt_t * d)

A link-up edge: the pair is owed again and the far end held disarmed until it is paid.

Control task only.

Parameters
dThe debt to update.

◆ endpoints_max()

uint16_t endpoints_max ( const endpoints_debt_t * d)

The Full pulse as last published, in us; 0 for NULL.

Parameters
dThe debt to read.
Returns
The Full pulse in us; 0 for NULL.

◆ endpoints_min()

uint16_t endpoints_min ( const endpoints_debt_t * d)

The pair as last published, in us; 0 for NULL.

Parameters
dThe debt to read.
Returns
The Idle pulse in us; 0 for NULL.

◆ endpoints_next()

endpoints_next_t endpoints_next ( bool owed,
bool far_disarmed,
uint32_t edit_ms,
uint32_t now_ms )

What a debt asks of a pass at now_ms.

owed: a pair is owed. far_disarmed: the control write of this pass put ARM = 0 at the far end and was acknowledged. edit_ms: the time of the last edit.

Due once now_ms - edit_ms, taken modulo 2^32, reaches ENDPOINTS_SETTLE_MS: 299ms after an edit waits, 300ms pays.

Parameters
owedtrue while a pair is owed.
far_disarmedtrue when the control write of this pass put ARM = 0 at the far end and it was acknowledged.
edit_msThe time of the last edit, in ms.
now_msThe time of this pass, in ms.
Returns
What the pass asks for, as endpoints_next_t.

◆ endpoints_owed()

bool endpoints_owed ( const endpoints_debt_t * d)

Whether a pair is owed: true refuses a switch to ARMED with the link up.

False for NULL.

Parameters
dThe debt to read.
Returns
true when a pair is owed.

◆ endpoints_owed_after()

bool endpoints_owed_after ( endpoints_outcome_t outcome)

Whether the debt stands after an attempt that ended in outcome: true only for ENDPOINTS_NO_ANSWER, and for a value outside the enum.

Parameters
outcomeThe outcome of the attempt.
Returns
true when the debt stands.

◆ endpoints_page_holds()

bool endpoints_page_holds ( const uint16_t * page,
uint16_t min_us,
uint16_t max_us )

Whether every throttle channel of a CHAN_CFG page page (LINK_CC_COUNT registers) holds min_us and max_us.

A page with no throttle channel holds any pair. False for NULL.

Parameters
pageThe CHAN_CFG page, LINK_CC_COUNT registers.
min_usThe Idle pulse, in us.
max_usThe Full pulse, in us.
Returns
true when every throttle channel holds the pair; false for NULL.

◆ endpoints_paid()

void endpoints_paid ( endpoints_debt_t * d,
endpoints_outcome_t outcome )

The end of a payment endpoints_take() handed out: owed again on a missing answer, the hold and the block kept with it; otherwise paid, the hold ended, and the block set from outcome – none for ENDPOINTS_HELD and ENDPOINTS_TAKEN.

Parameters
dThe debt, or NULL.
outcomeThe result of the payment.

◆ endpoints_publish()

void endpoints_publish ( endpoints_debt_t * d,
uint16_t min_us,
uint16_t max_us,
uint32_t now_ms )

An edit of Idle pulse or Full pulse at now_ms, from any task: the pair, then the time, then the flag, so a payment that sees the flag sees the pair and the rest it starts from.

Parameters
dThe debt to update.
min_usThe Idle pulse, in us.
max_usThe Full pulse, in us.
now_msThe time of the edit, in ms.

◆ endpoints_recheck()

void endpoints_recheck ( endpoints_debt_t * d)

A binding was written: the throttle channels may have moved, so the pair is owed again, due at the next poll once its edit has rested.

Control task only.

Parameters
dThe debt to update.

◆ endpoints_take()

endpoints_next_t endpoints_take ( endpoints_debt_t * d,
bool far_disarmed,
uint32_t now_ms )

The debt at a poll, on the control task: what endpoints_next() finds.

On ENDPOINTS_PAY the flag has been taken, and the caller pays the pair endpoints_min() and endpoints_max() read now and ends the payment with endpoints_paid(). The flag is taken before the exchanges and given back by a missing answer, so an edit published while they run stays owed. A switch to ARMED asks endpoints_owed() on the same task, so never between the taking and the outcome.

On ENDPOINTS_PAID the hold ends. A NULL d changes nothing and returns ENDPOINTS_WAIT_DISARM.

Parameters
dThe debt, or NULL.
far_disarmedtrue when the far end is disarmed.
now_msThe time of the poll, in ms.
Returns
What endpoints_next() finds at this poll.