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

The programming ports and the PROG link page. More...

#include "prog_port.h"
#include <stddef.h>
#include <string.h>
#include "link_msg.h"
#include "out_pwm_map.h"
#include "outputs_pages.h"

Macros

#define REG(port, r)

Functions

static uint64_t bit64 (uint16_t pin)
 The 64-bit mask with only bit pin set.
static uint16_t fn_of (const uint16_t *regs, unsigned port)
 Port port's function as regs hold it.
static bool fn_pwm (const uint16_t *regs, unsigned port)
 Whether the port's function is the servo pulse, which the PWM generator renders and which the PWM-pin and slice rules hold.
static bool fn_dshot (const uint16_t *regs, unsigned port)
 Whether the port's function is DShot (4.28): a PIO state machine renders it from the port's channel, a throttle.
static uint16_t fn_default (unsigned port)
 The function a port starts with on a board that has stored none: the servo pulse on port 0, nothing on the others.
static bool holds (const prog_port_t *p, unsigned port)
 Whether port port holds the pin its register names.
static bool ports_clash (uint16_t a, bool a_pwm, uint16_t b, bool b_pwm)
 Two port pins that cannot both be held: one pin, or two servo pulses on one compare register of the generator.
static bool pin_ok (const outputs_t *o, uint16_t pin, bool pwm, uint64_t ours, uint64_t taken)
 Whether pin may be a port's beside the bank: a header pin, not reserved unless it is one the ports hold now (ours), not in taken and no slot's.
static bool us_ok (uint16_t us)
 Whether us lies in the endpoint range.
static void apply_cfg (const prog_port_t *p, outputs_t *o, unsigned port)
 The channel of port as the page describes it.
void prog_port_init (prog_port_t *p, uint8_t count)
 count ports, 0 to LINK_PG_PORTS_MAX, none with a pin, all at PROG_PORT_RATE_HZ.
void prog_port_defaults (uint16_t *kept, uint16_t pin0)
 The kept registers of a board that has stored none: port 0 on pin0 (LINK_PG_PIN_NONE for none), the others without a pin, slew 0, LINK_CC_DEFAULT_MIN to LINK_CC_DEFAULT_MAX.
void prog_port_restore (prog_port_t *p, const uint16_t *kept, outputs_t *o, uint64_t taken)
 Take the kept registers at start, after the slots and the other pin holders are restored.
static uint16_t fn_from_word (uint16_t word, unsigned port)
 Port port's function from the kept word word: the nibble's value less 1, or the port's default for 0 or a value no write would take.
void prog_port_restore_fn (prog_port_t *p, const uint16_t *kept, uint16_t func_word, outputs_t *o, uint64_t taken)
 As prog_port_restore(), with each port's function from the kept word func_word (prog_port_kept_func()): bits 4n to 4n + 3 hold 1 + port n's FUNC; 0, or a value no write would take, is the port's default.
void prog_port_kept (const prog_port_t *p, uint16_t *kept)
 The kept registers as they stand, PROG_PORT_KEPT_COUNT of them.
uint16_t prog_port_kept_func (const prog_port_t *p)
 The functions as they stand, as the kept word: bits 4n to 4n + 3 hold 1 + port n's FUNC, never 0.
static uint16_t port_hz (uint16_t target, uint16_t hz, unsigned port)
 The rate port port runs at with target as TARGET and the SERVO rate hz: hz for the target port, PROG_PORT_RATE_HZ otherwise.
static bool carries (uint8_t off, uint8_t n, unsigned r)
 Whether the window off, n carries register r.
uint8_t prog_port_write (prog_port_t *p, uint8_t off, uint8_t n, const uint16_t *in, outputs_t *o, uint64_t taken, bool locked, uint32_t now_ms)
 A write of the page: 0, or the LINK_NACK_* reason with nothing changed.
void prog_port_read (const prog_port_t *p, uint8_t off, uint8_t n, uint16_t *out)
 Read a window of the PROG page's registers into out.
void prog_port_revert (prog_port_t *p, const prog_port_t *was, outputs_t *o)
 Undo a write the silicon could not follow: the page as was, and each port's channel in o with the slew and endpoints of that page.
void prog_port_bound (prog_port_t *p, uint8_t mask)
 Tell the page which ports' pins are held by their function, bit n for port n: bound to the generator for SERVO PWM, parked for NONE, or held by a wire page.
uint8_t prog_port_func (const prog_port_t *p, uint8_t port)
 Port port's function, a link_pg_func_t; NONE for a port the model does not hold.
uint8_t prog_port_pwm_ports (const prog_port_t *p)
 The SERVO PWM ports whose pin the generator has, bit n for port n: the ports a pulse bit and the TARGET may name.
uint8_t prog_port_parked (const prog_port_t *p)
 The NONE ports that hold a pin, bit n for port n: the pins the caller parks as inputs.
uint8_t prog_port_dshot (const prog_port_t *p)
 The DShot ports that hold a pin (FUNC DSHOT150 to DSHOT600, 4.28), bit n for port n: the pins the caller binds to a DShot state machine.
uint16_t prog_port_kbit (const prog_port_t *p, uint8_t port)
 Port port's DShot bit rate in kbit/s, 0 for another function.
uint8_t prog_port_count (const prog_port_t *p)
 The number of ports the model holds.
uint8_t prog_port_pin (const prog_port_t *p, uint8_t port)
 The pin port port holds, or PROG_PORT_NO_PIN.
uint8_t prog_port_wire_pin (const prog_port_t *p, uint8_t port, uint8_t bound)
 The pin a wire page (KST, HITEC) may take for a session on port port: the port's pin while the IOmcu holds it (bound, bit n, as outputs_hw_ports_bound() says), PROG_PORT_NO_PIN otherwise and for a DShot port, whose lead goes to an ESC.
uint64_t prog_port_pins (const prog_port_t *p)
 Every pin the ports hold, one bit per pin.
uint8_t prog_port_pwm (const prog_port_t *p)
 Bit n: port n's pulse is switched on.
uint16_t prog_port_pwm_channels (const prog_port_t *p)
 The bank channels of the ports whose pulse is switched on, bit c for channel c: what servo_page_ports() is told.
void prog_port_rate (prog_port_t *p, uint16_t hz)
 The SERVO page's frame rate, 0 while it names none.
uint16_t prog_port_port_hz (const prog_port_t *p, uint8_t port)
 The frame rate port port runs at: the SERVO page's rate for the TARGET port while it names one, PROG_PORT_RATE_HZ otherwise.
uint16_t prog_port_sliced_channels (const prog_port_t *p)
 The bank channels of the ports whose pin shares a PWM slice with another port's pin, bit c for channel c: what servo_page_ports() is told as held at PROG_PORT_RATE_HZ.
uint8_t prog_port_target (const prog_port_t *p)
 0 for the standard servo ports, 1 + n for port n.
uint8_t prog_port_channel (uint8_t port)
 The bank channel of port.
static bool slot_on_port_channel (const uint16_t *r)
 Whether a bound slot's channels reach a port's bank channel.
unsigned prog_port_slots_free (uint16_t *slots)
 Unbinds every slot of slots whose channel range reaches a port's bank channel, for a stored page read at start.
uint8_t prog_port_slots_check (const prog_port_t *p, const uint16_t *slots)
 Whether the OUTPUTS page slots may be taken beside the ports: 0, or LINK_NACK_BAD_VALUE for a slot on a port's pin, a PWM slot on a SERVO PWM port pin's slice, or a bound slot whose channel range reaches a port's bank channel (PROG_PORT_CHANNEL0 to PROG_PORT_CHANNEL0 + LINK_PG_PORTS_MAX - 1).

Detailed Description

The programming ports and the PROG link page.

See prog_port.h.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ REG

#define REG ( port,
r )
Value:
LINK_PG_REG(port, r)

Function Documentation

◆ apply_cfg()

void apply_cfg ( const prog_port_t * p,
outputs_t * o,
unsigned port )
static

The channel of port as the page describes it.

Parameters
pThe port model.
oThe outputs model whose port channel is set.
portPort index.

◆ bit64()

uint64_t bit64 ( uint16_t pin)
static

The 64-bit mask with only bit pin set.

Parameters
pinThe pin number, used as a shift count.
Returns
A mask with bit pin set.

◆ carries()

bool carries ( uint8_t off,
uint8_t n,
unsigned r )
static

Whether the window off, n carries register r.

Parameters
offFirst register of the window.
nNumber of registers in the window.
rRegister index.
Returns
true when r lies in the window.

◆ fn_default()

uint16_t fn_default ( unsigned port)
static

The function a port starts with on a board that has stored none: the servo pulse on port 0, nothing on the others.

Parameters
portPort index.
Returns
LINK_PG_FN_SERVO_PWM for port 0, LINK_PG_FN_NONE otherwise.

◆ fn_dshot()

bool fn_dshot ( const uint16_t * regs,
unsigned port )
static

Whether the port's function is DShot (4.28): a PIO state machine renders it from the port's channel, a throttle.

Parameters
regsThe page's registers, LINK_PG_REGS entries.
portPort index.
Returns
true when the port's function is DShot (DSHOT150 to DSHOT600).

◆ fn_from_word()

uint16_t fn_from_word ( uint16_t word,
unsigned port )
static

Port port's function from the kept word word: the nibble's value less 1, or the port's default for 0 or a value no write would take.

Parameters
wordThe kept function word, 4 bits per port.
portPort index.
Returns
The FUNC value of the port.

◆ fn_of()

uint16_t fn_of ( const uint16_t * regs,
unsigned port )
static

Port port's function as regs hold it.

Parameters
regsThe page's registers, LINK_PG_REGS entries.
portPort index.
Returns
The FUNC register of the port.

◆ fn_pwm()

bool fn_pwm ( const uint16_t * regs,
unsigned port )
static

Whether the port's function is the servo pulse, which the PWM generator renders and which the PWM-pin and slice rules hold.

Parameters
regsThe page's registers, LINK_PG_REGS entries.
portPort index.
Returns
true when the port's function is the servo pulse.

◆ holds()

bool holds ( const prog_port_t * p,
unsigned port )
static

Whether port port holds the pin its register names.

Parameters
pThe port model.
portPort index.
Returns
true when the port index is below the count, its PIN register is not LINK_PG_PIN_NONE and the port is not blocked.

◆ pin_ok()

bool pin_ok ( const outputs_t * o,
uint16_t pin,
bool pwm,
uint64_t ours,
uint64_t taken )
static

Whether pin may be a port's beside the bank: a header pin, not reserved unless it is one the ports hold now (ours), not in taken and no slot's.

For the servo pulse (pwm) also a pin of the PWM generator beside no PWM slot's in the silicon.

Parameters
oThe outputs model, for its reservations and slots.
pinThe pin to test.
pwmtrue for a SERVO PWM port.
oursBit n: pins the ports hold now.
takenBit n: pins other holders have.
Returns
true when the pin may be a port's pin.

◆ port_hz()

uint16_t port_hz ( uint16_t target,
uint16_t hz,
unsigned port )
static

The rate port port runs at with target as TARGET and the SERVO rate hz: hz for the target port, PROG_PORT_RATE_HZ otherwise.

Parameters
targetThe TARGET register: 1 + the port index, or 0 for none.
hzThe SERVO page's rate in Hz, 0 for none.
portPort index.
Returns
The frame rate of the port in Hz.

◆ ports_clash()

bool ports_clash ( uint16_t a,
bool a_pwm,
uint16_t b,
bool b_pwm )
static

Two port pins that cannot both be held: one pin, or two servo pulses on one compare register of the generator.

Parameters
aThe pin of one port.
a_pwmtrue when that port is a SERVO PWM port.
bThe pin of the other port.
b_pwmtrue when that port is a SERVO PWM port.
Returns
true when the two pins cannot both be held.

◆ prog_port_bound()

void prog_port_bound ( prog_port_t * p,
uint8_t mask )

Tell the page which ports' pins are held by their function, bit n for port n: bound to the generator for SERVO PWM, parked for NONE, or held by a wire page.

A port that loses its pin loses its PWM bit and, if it was the TARGET, the target returns to the standard servo ports.

Parameters
pThe port model.
maskBit n for port n: bound to the generator for SERVO PWM, parked for NONE, or held by a wire page.

◆ prog_port_channel()

uint8_t prog_port_channel ( uint8_t port)

The bank channel of port.

Parameters
portPort index.
Returns
The bank channel of the port, PROG_PORT_CHANNEL0 + port.

◆ prog_port_count()

uint8_t prog_port_count ( const prog_port_t * p)

The number of ports the model holds.

Parameters
pThe port model, or NULL.
Returns
The port count; 0 for a NULL p.

◆ prog_port_defaults()

void prog_port_defaults ( uint16_t * kept,
uint16_t pin0 )

The kept registers of a board that has stored none: port 0 on pin0 (LINK_PG_PIN_NONE for none), the others without a pin, slew 0, LINK_CC_DEFAULT_MIN to LINK_CC_DEFAULT_MAX.

Parameters
keptReceives PROG_PORT_KEPT_COUNT kept registers, written in place.
pin0The pin of port 0, or LINK_PG_PIN_NONE for none.

◆ prog_port_dshot()

uint8_t prog_port_dshot ( const prog_port_t * p)

The DShot ports that hold a pin (FUNC DSHOT150 to DSHOT600, 4.28), bit n for port n: the pins the caller binds to a DShot state machine.

Parameters
pThe port model.
Returns
Bit n set for port n when it is a DShot port that holds a pin; 0 for a NULL p.

◆ prog_port_func()

uint8_t prog_port_func ( const prog_port_t * p,
uint8_t port )

Port port's function, a link_pg_func_t; NONE for a port the model does not hold.

Parameters
pThe port model, or NULL.
portPort index, 0 to LINK_PG_PORTS_MAX - 1.
Returns
The function, a link_pg_func_t value; LINK_PG_FN_NONE for a NULL p or a port of LINK_PG_PORTS_MAX or more.

◆ prog_port_init()

void prog_port_init ( prog_port_t * p,
uint8_t count )

count ports, 0 to LINK_PG_PORTS_MAX, none with a pin, all at PROG_PORT_RATE_HZ.

Parameters
pThe port model to set up.
countPorts the build has, 0 to LINK_PG_PORTS_MAX; a larger value is clamped.

◆ prog_port_kbit()

uint16_t prog_port_kbit ( const prog_port_t * p,
uint8_t port )

Port port's DShot bit rate in kbit/s, 0 for another function.

Parameters
pThe port model, or NULL.
portPort index, 0 to LINK_PG_PORTS_MAX - 1.
Returns
The bit rate in kbit/s; 0 for a NULL p, a port of LINK_PG_PORTS_MAX or more, or a function that is not DShot.

◆ prog_port_kept()

void prog_port_kept ( const prog_port_t * p,
uint16_t * kept )

The kept registers as they stand, PROG_PORT_KEPT_COUNT of them.

Parameters
pThe port model.
keptReceives PROG_PORT_KEPT_COUNT registers, written in place.

◆ prog_port_kept_func()

uint16_t prog_port_kept_func ( const prog_port_t * p)

The functions as they stand, as the kept word: bits 4n to 4n + 3 hold 1 + port n's FUNC, never 0.

Parameters
pThe port model.
Returns
The kept function word; PROG_PORT_FUNC_UNSTORED for a NULL p.

◆ prog_port_parked()

uint8_t prog_port_parked ( const prog_port_t * p)

The NONE ports that hold a pin, bit n for port n: the pins the caller parks as inputs.

Parameters
pThe port model.
Returns
Bit n set for port n when it is a NONE port that holds a pin; 0 for a NULL p.

◆ prog_port_pin()

uint8_t prog_port_pin ( const prog_port_t * p,
uint8_t port )

The pin port port holds, or PROG_PORT_NO_PIN.

Parameters
pThe port model, or NULL.
portPort index.
Returns
The pin the port holds, or PROG_PORT_NO_PIN for a NULL p or a port that holds no pin.

◆ prog_port_pins()

uint64_t prog_port_pins ( const prog_port_t * p)

Every pin the ports hold, one bit per pin.

Parameters
pThe port model, or NULL.
Returns
One bit per pin the ports hold; 0 for a NULL p.

◆ prog_port_port_hz()

uint16_t prog_port_port_hz ( const prog_port_t * p,
uint8_t port )

The frame rate port port runs at: the SERVO page's rate for the TARGET port while it names one, PROG_PORT_RATE_HZ otherwise.

Parameters
pThe port model, or NULL.
portPort index.
Returns
The frame rate of the port in Hz; PROG_PORT_RATE_HZ for a NULL p.

◆ prog_port_pwm()

uint8_t prog_port_pwm ( const prog_port_t * p)

Bit n: port n's pulse is switched on.

Parameters
pThe port model, or NULL.
Returns
The pulse bits, bit n for port n; 0 for a NULL p.

◆ prog_port_pwm_channels()

uint16_t prog_port_pwm_channels ( const prog_port_t * p)

The bank channels of the ports whose pulse is switched on, bit c for channel c: what servo_page_ports() is told.

Parameters
pThe port model, or NULL.
Returns
Bit c set for each bank channel c of a port whose pulse is on; 0 for a NULL p.

◆ prog_port_pwm_ports()

uint8_t prog_port_pwm_ports ( const prog_port_t * p)

The SERVO PWM ports whose pin the generator has, bit n for port n: the ports a pulse bit and the TARGET may name.

Parameters
pThe port model.
Returns
Bit n set for port n when it is a SERVO PWM port whose pin is bound; 0 for a NULL p.

◆ prog_port_rate()

void prog_port_rate ( prog_port_t * p,
uint16_t hz )

The SERVO page's frame rate, 0 while it names none.

It reaches the TARGET port only; a write is judged against it.

Parameters
pThe port model, or NULL; a NULL p is ignored.
hzThe SERVO page's frame rate in Hz, 0 for none.

◆ prog_port_read()

void prog_port_read ( const prog_port_t * p,
uint8_t off,
uint8_t n,
uint16_t * out )

Read a window of the PROG page's registers into out.

Parameters
pThe port model.
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 beyond LINK_PG_REGS.

◆ prog_port_restore()

void prog_port_restore ( prog_port_t * p,
const uint16_t * kept,
outputs_t * o,
uint64_t taken )

Take the kept registers at start, after the slots and the other pin holders are restored.

A value no write would take becomes its default, except a slew above LINK_CC_SLEW_MAX, which becomes LINK_CC_SLEW_MAX. A pin that is taken (a slot's, one in taken, reserved in o, or beside a PWM slot in the silicon) stays on the page and is not held: LINK_PG_FLAGS says refused until another pin is written. Sets the role, slew and endpoints of each port's channel in o.

Parameters
pThe port model to restore into.
keptPROG_PORT_KEPT_COUNT kept registers, as prog_port_kept() wrote them.
oThe outputs model whose port channels are set.
takenBit n: pin n is held by another holder beyond the slots and the bank's reservation.

◆ prog_port_restore_fn()

void prog_port_restore_fn ( prog_port_t * p,
const uint16_t * kept,
uint16_t func_word,
outputs_t * o,
uint64_t taken )

As prog_port_restore(), with each port's function from the kept word func_word (prog_port_kept_func()): bits 4n to 4n + 3 hold 1 + port n's FUNC; 0, or a value no write would take, is the port's default.

A kept pin is judged under its port's function: a SERVO PWM port's pin must be a pin of the generator.

Parameters
pThe port model to restore into.
keptPROG_PORT_KEPT_COUNT kept registers, as prog_port_kept() wrote them.
func_wordThe kept function word, as prog_port_kept_func() wrote it.
oThe outputs model whose port channels are set.
takenBit n: pin n is held by another holder beyond the slots and the bank's reservation.

◆ prog_port_revert()

void prog_port_revert ( prog_port_t * p,
const prog_port_t * was,
outputs_t * o )

Undo a write the silicon could not follow: the page as was, and each port's channel in o with the slew and endpoints of that page.

A command the write carried stays commanded.

Parameters
pThe port model, overwritten with was.
wasThe port model as it stood before the write that failed.
oThe outputs model whose port channels are set.

◆ prog_port_sliced_channels()

uint16_t prog_port_sliced_channels ( const prog_port_t * p)

The bank channels of the ports whose pin shares a PWM slice with another port's pin, bit c for channel c: what servo_page_ports() is told as held at PROG_PORT_RATE_HZ.

Parameters
pThe port model, or NULL.
Returns
Bit c set for each bank channel c of a port whose pin shares a PWM slice with another port's pin; 0 for a NULL p.

◆ prog_port_slots_check()

uint8_t prog_port_slots_check ( const prog_port_t * p,
const uint16_t * slots )

Whether the OUTPUTS page slots may be taken beside the ports: 0, or LINK_NACK_BAD_VALUE for a slot on a port's pin, a PWM slot on a SERVO PWM port pin's slice, or a bound slot whose channel range reaches a port's bank channel (PROG_PORT_CHANNEL0 to PROG_PORT_CHANNEL0 + LINK_PG_PORTS_MAX - 1).

Parameters
pThe port model, or NULL.
slotsThe OUTPUTS slot registers, LINK_OUT_SLOTS slots of LINK_OS_STRIDE registers each.
Returns
0 when the slots may be taken; LINK_NACK_BAD_VALUE for a NULL slots or a refused slot (see above). 0 for a NULL p.

◆ prog_port_slots_free()

unsigned prog_port_slots_free ( uint16_t * slots)

Unbinds every slot of slots whose channel range reaches a port's bank channel, for a stored page read at start.

Returns how many.

Parameters
slotsThe OUTPUTS slot registers, LINK_OUT_SLOTS slots of LINK_OS_STRIDE registers each; a slot on a port's channel has its driver cleared in place.
Returns
The number of slots unbound; 0 for NULL slots.

◆ prog_port_target()

uint8_t prog_port_target ( const prog_port_t * p)

0 for the standard servo ports, 1 + n for port n.

Parameters
pThe port model, or NULL.
Returns
1 + n for the TARGET port n, 0 for the standard servo ports; 0 for a NULL p.

◆ prog_port_wire_pin()

uint8_t prog_port_wire_pin ( const prog_port_t * p,
uint8_t port,
uint8_t bound )

The pin a wire page (KST, HITEC) may take for a session on port port: the port's pin while the IOmcu holds it (bound, bit n, as outputs_hw_ports_bound() says), PROG_PORT_NO_PIN otherwise and for a DShot port, whose lead goes to an ESC.

Parameters
pThe port model, or NULL.
portPort index, 0 to LINK_PG_PORTS_MAX - 1.
boundBit n for port n: the port's pin is held by the IOmcu (outputs_hw_ports_bound()).
Returns
The pin for the wire page, or PROG_PORT_NO_PIN (see above).

◆ prog_port_write()

uint8_t prog_port_write ( prog_port_t * p,
uint8_t off,
uint8_t n,
const uint16_t * in,
outputs_t * o,
uint64_t taken,
bool locked,
uint32_t now_ms )

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

taken: the pins other holders have beyond the slots and the bank's reservation. locked: no PIN or FUNC may change now (the bank is armed or asked to arm, or a wire page holds a port). A PIN or FUNC change is also refused for a port whose PWM bit is set or that is the TARGET, before or after the frame. A FUNC above LINK_PG_FN_NONE, and any register of a port the build does not have, is BAD_VALUE. A PIN is judged under the FUNC the frame leaves its port with.

PWM and TARGET name only SERVO PWM ports whose pin the generator has (prog_port_bound()), and not a port whose PIN or FUNC the same frame changes.

No port whose PWM bit the write leaves set may have an endpoint longer than its frame carries: MIN_US and MAX_US at most out_pwm_pulse_max() of the rate the write leaves the port at (prog_port_port_hz()), 1784us at 560Hz (BAD_VALUE, protocol 4.16). This covers a range written to a pulsing port and a pulse switched on under a range that does not fit.

A TARGET change returns the SERVO rate to 0 (servo_page_target()), so every port is judged at PROG_PORT_RATE_HZ after one, and the write sets the rate prog_port_rate() last named to 0 as well: prog_port_port_hz() then names the rate each port runs at once the write is in force, before the SERVO page has followed the TARGET. Refused as well (BAD_VALUE, protocol 4.19): a TARGET change away from the standard servo ports while they run at a SERVO rate, when a PWM slot back at its own rate would carry a pulse longer than its frame (outputs_pulse_check()); and a PIN that puts a port on the PWM slice of the TARGET port while that port runs at a rate other than PROG_PORT_RATE_HZ.

Parameters
pThe port model, updated when the write is applied.
offFirst register of the window; below LINK_PG_PWM is read-only.
nNumber of registers in the window; 0 applies nothing.
inThe n register values to write.
oThe outputs model whose port channels are set.
takenBit n: pin n is held by another holder beyond the slots and the bank's reservation.
lockedTrue refuses every PIN and FUNC change.
now_msCurrent time in milliseconds, passed on for a CMD write.
Returns
0 when the write is applied; otherwise the LINK_NACK_* reason: LINK_NACK_BAD_RANGE for a NULL argument or a window beyond LINK_PG_REGS, LINK_NACK_READ_ONLY for a window below LINK_PG_PWM, LINK_NACK_BAD_VALUE for a value refused as described above.

◆ slot_on_port_channel()

bool slot_on_port_channel ( const uint16_t * r)
static

Whether a bound slot's channels reach a port's bank channel.

Parameters
rThe slot's register words.
Returns
true when the slot drives and its channel range reaches a port's bank channel.

◆ us_ok()

bool us_ok ( uint16_t us)
static

Whether us lies in the endpoint range.

Parameters
usThe endpoint in microseconds.
Returns
true when us lies between LINK_CC_FLOOR_US and LINK_CC_CEILING_US, both included.