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

Binding a protocol to pins: what the operator chooses, and the OUTPUTS page that comes out of it. More...

#include <stdbool.h>
#include <stdint.h>
#include "outputs.h"

Go to the source code of this file.

Data Structures

struct  outbind_pin_t
 One pin of a board's catalogue. More...
struct  outbind_shape_t
 Where a board's pads are: two rows on one pitch, which is every 0.1-inch header board. More...
struct  outbind_pad_t
 A pad that is not a pin: a ground, a rail, or neither. More...
struct  outbind_board_t
 One board: its identity, catalogue, outline and pads. More...
struct  outbind_proto_t
 What can be bound, as an operator names it. More...
struct  outbind_t
 The selection: which board, the protocol being edited, and each protocol's pins. More...

Macros

#define OUTBIND_PINS   26u
 The most pins any board in this build brings out.
#define OUTBIND_PROTOS   8u
 Entries in the protocol table, OFF included.
#define OUTBIND_NO_GPIO   0xFFu
 No programming port pin, for outbind_pwm_clash().
#define OUTBIND_PROTO_MIXED   0xFFu
 outbind_role_proto(): the role's slots are bound as several entries.

Enumerations

enum  outbind_board_id_t { OUTBIND_BOARD_UNKNOWN = 0 , OUTBIND_BOARD_PICO_HEADER = 1 }
 Which IOmcu is on the other end. More...
enum  outbind_clash_t { OUTBIND_CLASH_NONE = 0 , OUTBIND_CLASH_PROG_SLICE , OUTBIND_CLASH_COMPARE }
 Why the PWM generator cannot take a pin, as outbind_pwm_clash() says. More...

Functions

const outbind_board_t * outbind_board (uint16_t id)
 The board with this identity, or NULL when nothing here describes it.
void outbind_board_to_regs (const outbind_board_t *board, uint16_t *regs)
 Render a board's catalogue into LINK_CAT_COUNT registers for the wire.
bool outbind_learn_board (uint16_t id, const uint16_t *regs)
 Learn the board a catalogue page describes, replacing any previous one.
void outbind_shape_to_regs (const outbind_board_t *board, uint16_t *regs)
 Render a board's shape into LINK_SH_COUNT registers, or leave them zero when it has none.
bool outbind_learn_shape (uint16_t id, const uint16_t *regs)
 Give the learned board a shape from a shape page.
bool outbind_pad_xy (const outbind_shape_t *shape, uint8_t pad, uint16_t *x_cmm, uint16_t *y_cmm)
 Where a pad's centre is, in hundredths of a millimetre from the top-left of the outline.
const outbind_pad_t * outbind_pads (uint16_t board)
 The pads that are not pins, and how many.
uint8_t outbind_pad_count (uint16_t board)
 How many pads that are not pins the board has, or 0 for a board nothing here describes that way.
void outbind_pads_to_regs (const outbind_board_t *board, uint16_t *regs)
 Render them into LINK_PAD_COUNT registers, or leave them zero.
bool outbind_learn_pads (uint16_t id, const uint16_t *regs)
 Give the learned board its grounds and rails.
void outbind_forget_learned (void)
 Forget it.
uint8_t outbind_board_count (void)
 The table itself, so a caller can walk every board rather than guess at a range of identities. outbind_board_at() returns NULL past the end.
const outbind_board_t * outbind_board_at (uint8_t index)
 The board at index in the table, or NULL past the end.
bool outbind_pin_selectable (const outbind_board_t *board, uint8_t index)
 Whether index may be added to a selection on board.
const outbind_pin_t * outbind_pins (uint16_t board)
 Its catalogue and how long it is.
uint8_t outbind_pin_count (uint16_t board)
 How many pins the board's catalogue lists, or 0 for a board this build does not know.
uint8_t outbind_index_of (uint16_t board, uint8_t gpio)
 Index of gpio in that board's catalogue, or its count when the board does not bring that pin out.
uint64_t outbind_reserved_mask (uint16_t board)
 Every pin of a board that no output and no PD mini pin may take, one bit per GPIO (0 to 63).
const outbind_proto_t * outbind_protos (void)
 The protocol table, indexed by protocol number; entry 0 is OFF.
void outbind_init (outbind_t *b)
 Empty, and belonging to no board: nothing can be chosen until one is set.
uint8_t outbind_group_of (const outbind_t *b, uint8_t index)
 Which protocol holds index, or 0 (OFF) when nothing does.
uint8_t outbind_chosen_total (const outbind_t *b)
 Pins chosen across every protocol, and the channels they render.
uint8_t outbind_channels_used (const outbind_t *b)
 Channels the chosen pins render, across every protocol.
void outbind_trim (outbind_t *b)
 Drop anything a selection cannot mean on its board.
void outbind_set_board (outbind_t *b, uint16_t board)
 Say which board this binding is for.
uint8_t outbind_chosen (const outbind_t *b)
 How many pins the protocol being edited has chosen.
uint8_t outbind_wire_proto (const outbind_t *b)
 The protocol a page rendered from this selection reads back as: the lowest-numbered one holding a pin, or OFF when nothing does.
bool outbind_toggle (outbind_t *b, uint8_t index)
 Add or remove a pin, in the protocol being edited.
void outbind_set_proto (outbind_t *b, uint8_t proto)
 Choose which protocol is being edited.
bool outbind_can_add (const outbind_t *b, uint8_t index)
 True when this pin may still be added to the protocol being edited, for a screen drawing it.
outbind_clash_t outbind_pwm_clash (const outbind_t *b, uint8_t index, uint8_t prog_gpio, uint8_t *with)
 Whether the IOmcu refuses catalogue entry index for the protocol being edited, beside prog_gpio and the pins b binds as PWM.
outbind_clash_t outbind_pwm_clash_ports (const outbind_t *b, uint8_t index, const uint8_t *ports, uint8_t count, uint8_t *with)
 outbind_pwm_clash() beside every programming port's pin: count pins from ports (NULL or 0 for none), each OUTBIND_NO_GPIO for a port without one.
uint8_t outbind_to_slots (const outbind_t *b, uint16_t *regs)
 Render the selection into the OUTPUTS page.
bool outbind_from_slots (outbind_t *b, uint16_t board, const uint16_t *regs, const uint16_t *chan_cfg)
 Read a selection back out of an OUTPUTS page.
uint8_t outbind_role_proto (const uint16_t *regs, const uint16_t *chan_cfg, out_role_t role)
 The entry the slots of role are bound as, an index into outbind_protos(), read from an OUTPUTS page and the CHAN_CFG page that came back with it: what MOTOR & ESC's TARGET row names before the throttle's pins.
void outbind_to_chan_cfg (const outbind_t *b, uint16_t *regs, uint16_t min_us, uint16_t max_us)
 Render the channel configuration to match.

Detailed Description

Binding a protocol to pins: what the operator chooses, and the OUTPUTS page that comes out of it.

A set of pins for each protocol, rather than eight independent slots. A bench is wired a protocol at a time – four servo leads, then one ESC (electronic speed controller) – and asking for the protocol and then for its pins is the shape of that job. The sets stand together: a pin belongs to at most one of them, and choosing a protocol says which set is being edited rather than retargeting the pins already chosen for another.

Each chosen pin becomes one slot on the OUTPUTS page, in pin order across every protocol, taking channels from zero upward. So the lowest chosen pin is channel 0 whichever protocol holds it, and a bench wired to one protocol writes the page it always wrote.

The pin catalogue is the IOmcu's header, not its silicon. A GPIO (general-purpose input/output) the module does not bring out to a pad cannot be wired to anything, so it is not offered; GP23 to GP25 are absent for that reason rather than because anything reserves them.

Reserved pins are offered but cannot be chosen. Hiding them would leave an operator hunting for GP10 and finding a gap; showing them greyed says the pin exists and what already has it.

Nothing here talks to the wire. It produces register arrays, and the panel writes them.

SPDX-License-Identifier: MIT

Enumeration Type Documentation

◆ outbind_board_id_t

Which IOmcu is on the other end.

There is one today and there will be more: a custom board carries its outputs on pins that are soldered, not chosen, and knows a different set of them. The panel is told which by the identity page rather than assuming, because the two things that must never happen are showing a pin map for a board that is not there and applying a binding made for one board to another.

The numbers are a contract, like a page number: nothing is renumbered, and a new board appends. Zero means nothing answered, or answered with an identity this build has never heard of – and both are the same thing to a panel: it does not know this board, so it offers nothing.

Enumerator
OUTBIND_BOARD_UNKNOWN 

nothing answered, or unknown identity

OUTBIND_BOARD_PICO_HEADER 

Pico form factor, wired by hand

◆ outbind_clash_t

Why the PWM generator cannot take a pin, as outbind_pwm_clash() says.

Enumerator
OUTBIND_CLASH_PROG_SLICE 

The pin's slice is the programming port's pin's slice.

OUTBIND_CLASH_COMPARE 

The pin's compare register drives a pin already bound as PWM.

Function Documentation

◆ outbind_board()

const outbind_board_t * outbind_board ( uint16_t id)

The board with this identity, or NULL when nothing here describes it.

The table compiled into this build first, then a board learned over the link. A build that ships a catalogue for a board uses its own: the compiled one has been read by somebody, names the exact signal holding each reserved pin, and cannot change under a running bench.

Parameters
idIdentity the IOmcu reports, an outbind_board_id_t value or a learned identity.
Returns
The board, or NULL when neither the table nor the learned board has id. OUTBIND_BOARD_UNKNOWN always returns NULL.

◆ outbind_board_at()

const outbind_board_t * outbind_board_at ( uint8_t index)

The board at index in the table, or NULL past the end.

Parameters
indexPosition in the table, 0 to outbind_board_count() - 1.
Returns
The board, or NULL when index is past the end.

◆ outbind_board_count()

uint8_t outbind_board_count ( void )

The table itself, so a caller can walk every board rather than guess at a range of identities. outbind_board_at() returns NULL past the end.

Returns
The number of boards in the compiled table.

◆ outbind_board_to_regs()

void outbind_board_to_regs ( const outbind_board_t * board,
uint16_t * regs )

Render a board's catalogue into LINK_CAT_COUNT registers for the wire.

Slots past the board's own pins are left with a pad number of zero, which is how the page says there is no pin there.

Parameters
boardThe board to render, or NULL for a page of zeroes.
regsLINK_CAT_COUNT registers to write. NULL does nothing.

◆ outbind_can_add()

bool outbind_can_add ( const outbind_t * b,
uint8_t index )

True when this pin may still be added to the protocol being edited, for a screen drawing it.

Includes the compare-register rule of outbind_pwm_clash(), which needs no programming port: a PWM protocol is not offered the partner of a pin bound as PWM. The slice rule needs the port's pin, which this binding does not carry, so a screen asks outbind_pwm_clash() for it.

Parameters
bThe selection.
indexCatalogue index of the pin.
Returns
true when the pin may be added; false otherwise.

◆ outbind_channels_used()

uint8_t outbind_channels_used ( const outbind_t * b)

Channels the chosen pins render, across every protocol.

Parameters
bThe selection.
Returns
The sum of each chosen pin's channels, capped at 255. 0 for NULL.

◆ outbind_chosen()

uint8_t outbind_chosen ( const outbind_t * b)

How many pins the protocol being edited has chosen.

Parameters
bThe selection.
Returns
The count of pins in the edited protocol. 0 for NULL.

◆ outbind_chosen_total()

uint8_t outbind_chosen_total ( const outbind_t * b)

Pins chosen across every protocol, and the channels they render.

Both are budgets shared by all of them: LINK_OUT_SLOTS and LINK_OUT_CHANNELS.

Parameters
bThe selection.
Returns
The number of pins chosen in protocols 1 and up. 0 for NULL.

◆ outbind_forget_learned()

void outbind_forget_learned ( void )

Forget it.

Not needed when the link drops. The slot is keyed by identity and is returned for that identity alone, so a board that has been unplugged cannot be reached by the one that replaces it – and keeping it means the screen still knows the pins of a board whose link merely blinked, which is what a compiled-in catalogue already gives a board this build knows.

◆ outbind_from_slots()

bool outbind_from_slots ( outbind_t * b,
uint16_t board,
const uint16_t * regs,
const uint16_t * chan_cfg )

Read a selection back out of an OUTPUTS page.

The IOmcu holds the configuration, so the panel asks it what is driving rather than remembering: a binding is a description of wiring, and a panel that reapplied a remembered one would be applying it to whatever is on the bench now.

Slots on different protocols are the ordinary case; slots on the same driver and rate are one protocol's set, because that pair is what names a set. The protocol left being edited is the lowest-numbered one the page uses, so a page with anything on it opens on something.

Returns false for a page this shape cannot describe – a rate no entry uses, a pin not on the header, a channel run that does not follow the slot order – and leaves b cleared. The screen then shows nothing chosen rather than a selection that disagrees with the page it came from.

chan_cfg is the CHAN_CFG page that came back with regs, and it is what separates two entries the slots page cannot: SERVO PWM and MOTOR PWM are one driver at one rate, and only the role of the slot's first channel says which was chosen. NULL takes the first entry that matches driver and rate, which on this catalogue reads a motor back as a servo and rests it at half throttle, so pass the page whenever there is one.

Parameters
bReceives the selection. Cleared on refusal.
boardIdentity of the board the page was read from.
regsLINK_OS_COUNT registers of the OUTPUTS page.
chan_cfgLINK_CC_COUNT registers of the CHAN_CFG page, or NULL.
Returns
true when the page reads back to itself as a selection on board; false when it is refused and b is cleared.

◆ outbind_group_of()

uint8_t outbind_group_of ( const outbind_t * b,
uint8_t index )

Which protocol holds index, or 0 (OFF) when nothing does.

A pin refused because another protocol holds it is a different fact from one the IOmcu reserves: the first is a choice the operator can undo by going to that protocol, the second is the wiring. A screen that drew them alike would offer to free the heartbeat line.

Parameters
bThe selection.
indexCatalogue index of the pin.
Returns
The protocol number holding the pin, or 0 when none does or b is NULL.

◆ outbind_index_of()

uint8_t outbind_index_of ( uint16_t board,
uint8_t gpio )

Index of gpio in that board's catalogue, or its count when the board does not bring that pin out.

Parameters
boardIdentity of the board, as for outbind_board().
gpioGPIO number to look up.
Returns
Catalogue index of gpio. The board's count when it is not listed, and 0 for a board this build does not know.

◆ outbind_init()

void outbind_init ( outbind_t * b)

Empty, and belonging to no board: nothing can be chosen until one is set.

Parameters
bThe selection to clear. NULL does nothing.

◆ outbind_learn_board()

bool outbind_learn_board ( uint16_t id,
const uint16_t * regs )

Learn the board a catalogue page describes, replacing any previous one.

There is room for exactly one: the panel talks to one IOmcu, and a second learned board would be a pin map for hardware that is not on the bench. Refuses a page that cannot be a board – no pins, a GPIO past OUT_MAX_PIN, pins out of GPIO order, or the same GPIO twice – and learns nothing rather than half of it, because a catalogue half read is a pin map that disagrees with the board sending it.

Refuses an identity the compiled table already has: that board is described here already, and letting the wire replace it would let an IOmcu rename the pin holding the safety line.

Parameters
idIdentity the catalogue page came from. Must not be OUTBIND_BOARD_UNKNOWN or an identity in the compiled table.
regsLINK_CAT_COUNT registers of the catalogue page. NULL is refused.
Returns
true when the board was learned, false when it was refused and the previous learned board, if any, is unchanged.

◆ outbind_learn_pads()

bool outbind_learn_pads ( uint16_t id,
const uint16_t * regs )

Give the learned board its grounds and rails.

Refuses a list that cannot belong to the board: a pad of zero, a kind that is not one, pads out of order or repeated, or a pad the catalogue already calls a pin – one pad cannot be both a GPIO and a ground, and a page saying so is describing something other than this board. Refusing costs the marks and nothing else.

Parameters
idIdentity of the learned board. Must equal the learned board's identity.
regsLINK_PAD_COUNT registers of the pad page. NULL is refused.
Returns
true when the pads were learned, false when the page was refused.

◆ outbind_learn_shape()

bool outbind_learn_shape ( uint16_t id,
const uint16_t * regs )

Give the learned board a shape from a shape page.

Refuses one that cannot be a board: no pads in a row, a corner that is not one, no pitch, or an outline too small to hold the row it claims. Refuses one whose rows cannot hold the catalogue's pins, since the two pages describe the same board and a pad with nowhere to sit would be drawn off the outline. A board with no shape is used and not drawn, so refusing costs the picture and nothing else.

Parameters
idIdentity of the learned board. Must equal the learned board's identity.
regsLINK_SH_COUNT registers of the shape page. NULL is refused.
Returns
true when the shape was learned, false when it was refused.

◆ outbind_pad_count()

uint8_t outbind_pad_count ( uint16_t board)

How many pads that are not pins the board has, or 0 for a board nothing here describes that way.

Parameters
boardIdentity of the board, as for outbind_board().
Returns
The number of entries in outbind_pads(), or 0.

◆ outbind_pad_xy()

bool outbind_pad_xy ( const outbind_shape_t * shape,
uint8_t pad,
uint16_t * x_cmm,
uint16_t * y_cmm )

Where a pad's centre is, in hundredths of a millimetre from the top-left of the outline.

False for a pad the shape does not place: pads are numbered from one, up to twice the row length.

Parameters
shapeThe outline to place the pad on.
padPad number, 1 to twice shape's per_side.
x_cmmReceives the x coordinate of the pad centre.
y_cmmReceives the y coordinate of the pad centre.
Returns
true when the pad is placed and both outputs are written; false for a NULL argument, a shape with no pads per side, or a pad outside the range above.

◆ outbind_pads()

const outbind_pad_t * outbind_pads ( uint16_t board)

The pads that are not pins, and how many.

NULL and 0 for a board nothing here describes that way.

Parameters
boardIdentity of the board, as for outbind_board().
Returns
The pad table, or NULL. The count is outbind_pad_count().

◆ outbind_pads_to_regs()

void outbind_pads_to_regs ( const outbind_board_t * board,
uint16_t * regs )

Render them into LINK_PAD_COUNT registers, or leave them zero.

Parameters
boardThe board whose pads to render, or NULL for a page of zeroes.
regsLINK_PAD_COUNT registers to write. NULL does nothing.

◆ outbind_pin_count()

uint8_t outbind_pin_count ( uint16_t board)

How many pins the board's catalogue lists, or 0 for a board this build does not know.

Parameters
boardIdentity of the board, as for outbind_board().
Returns
The number of entries in outbind_pins(), or 0.

◆ outbind_pin_selectable()

bool outbind_pin_selectable ( const outbind_board_t * board,
uint8_t index )

Whether index may be added to a selection on board.

Takes the board rather than reading it from the table, so the rule can be held against a board this build does not yet contain – a soldered one, for instance, which refuses every pin because there is nothing there to choose.

Parameters
boardThe board whose catalogue index indexes.
indexCatalogue index, 0 to the board's count - 1.
Returns
true when the pin is in range, the board is not soldered and the pin is not reserved; false otherwise.

◆ outbind_pins()

const outbind_pin_t * outbind_pins ( uint16_t board)

Its catalogue and how long it is.

NULL and 0 for a board this build does not know, so a caller that forgets to check offers nothing rather than offering the wrong thing.

Parameters
boardIdentity of the board, as for outbind_board().
Returns
The catalogue, in GPIO order, or NULL. The length is outbind_pin_count().

◆ outbind_protos()

const outbind_proto_t * outbind_protos ( void )

The protocol table, indexed by protocol number; entry 0 is OFF.

Returns
The table of OUTBIND_PROTOS entries.

◆ outbind_pwm_clash()

outbind_clash_t outbind_pwm_clash ( const outbind_t * b,
uint8_t index,
uint8_t prog_gpio,
uint8_t * with )

Whether the IOmcu refuses catalogue entry index for the protocol being edited, beside prog_gpio and the pins b binds as PWM.

Applies to a protocol on OUT_DRIVER_PWM and a pin that is not reserved and that no protocol holds; any other pin or protocol is OUTBIND_CLASH_NONE. Two refusals, in this order:

  • OUTBIND_CLASH_PROG_SLICE: the pin shares a slice with prog_gpio, the programming port's pin (prog_port_slots_check()). Only while no protocol holds prog_gpio: a slot on that pin leaves the port without one. OUTBIND_NO_GPIO, or any GPIO past OUT_MAX_PIN, is no port.
  • OUTBIND_CLASH_COMPARE: the pin shares a compare register with a pin a PWM protocol holds (out_pwm_bind() in the IOmcu).

Both are out_pwm_same_slice() and out_pwm_same_compare(), the helpers the IOmcu decides with. with, when not NULL, gets the GPIO the pin clashes with, or OUTBIND_NO_GPIO for OUTBIND_CLASH_NONE.

Parameters
bThe selection.
indexCatalogue index of the pin being checked.
prog_gpioGPIO of the programming port's pin, or OUTBIND_NO_GPIO.
withReceives the GPIO clashed with, or NULL to skip it.
Returns
The refusal, or OUTBIND_CLASH_NONE.

◆ outbind_pwm_clash_ports()

outbind_clash_t outbind_pwm_clash_ports ( const outbind_t * b,
uint8_t index,
const uint8_t * ports,
uint8_t count,
uint8_t * with )

outbind_pwm_clash() beside every programming port's pin: count pins from ports (NULL or 0 for none), each OUTBIND_NO_GPIO for a port without one.

The slice rule is checked against each in order, the first clash named; then the compare rule. The IOmcu checks a slot against every port it has (prog_port_slots_check()).

Parameters
bThe selection.
indexCatalogue index of the pin being checked.
portsGPIOs of the programming ports, or NULL.
countNumber of entries in ports.
withReceives the GPIO clashed with, or NULL to skip it.
Returns
The first refusal found, or OUTBIND_CLASH_NONE.

◆ outbind_reserved_mask()

uint64_t outbind_reserved_mask ( uint16_t board)

Every pin of a board that no output and no PD mini pin may take, one bit per GPIO (0 to 63).

That is the catalogue's reserved pins, plus every pin the catalogue does not list: the pins the board uses without bringing them out and the numbers the part does not have. The IOmcu hands this mask to outputs_reserve_pins(), which the OUTPUTS and SUPPLY pages both consult, and the panel greys the catalogue's reserved pins, so the two ends cannot disagree about which pins exist to be given away. An unknown board reserves everything: a build that cannot say which pins are safe must not hand any of them out.

Parameters
boardIdentity of the board, as for outbind_board().
Returns
Bit n is set when GPIO n is reserved. All 64 bits are set for an unknown board.

◆ outbind_role_proto()

uint8_t outbind_role_proto ( const uint16_t * regs,
const uint16_t * chan_cfg,
out_role_t role )

The entry the slots of role are bound as, an index into outbind_protos(), read from an OUTPUTS page and the CHAN_CFG page that came back with it: what MOTOR & ESC's TARGET row names before the throttle's pins.

A slot is the role's when its first channel carries the role on chan_cfg, as outbind_from_slots() reads it; its entry is the one of that role with the slot's driver and rate. Returns 0 when no slot is the role's, when a page is NULL, or when the role's one slot set matches no entry, and OUTBIND_PROTO_MIXED when the role's slots match two entries or one matches none beside one that does.

Parameters
regsLINK_OS_COUNT registers of the OUTPUTS page.
chan_cfgLINK_CC_COUNT registers of the CHAN_CFG page.
roleThe role to look for.
Returns
The entry index, 0, or OUTBIND_PROTO_MIXED as above.

◆ outbind_set_board()

void outbind_set_board ( outbind_t * b,
uint16_t board )

Say which board this binding is for.

Clears the selection whenever the board changes, and that is the point: a bit in pins is an index into one board's catalogue and means a different pin – or no pin – in another's. Carrying a selection across would bind whatever happened to sit at that index on the board now in front of the operator.

Parameters
bThe selection. NULL does nothing.
boardIdentity of the board the selection is now for.

◆ outbind_set_proto()

void outbind_set_proto ( outbind_t * b,
uint8_t proto )

Choose which protocol is being edited.

Nothing is dropped. The pins chosen for the protocol being left stay bound and appear as held on the grid, and the pins of the one arrived at come back as they were: a selector that retargeted the current pins would make binding a second protocol mean unbinding the first.

The whole selection is trimmed here, since this is every screen's way in to a binding that came from outside.

Parameters
bThe selection. NULL does nothing.
protoProtocol number, an index into outbind_protos(). A value of OUTBIND_PROTOS or more does nothing.

◆ outbind_shape_to_regs()

void outbind_shape_to_regs ( const outbind_board_t * board,
uint16_t * regs )

Render a board's shape into LINK_SH_COUNT registers, or leave them zero when it has none.

Parameters
boardThe board whose shape to render, or NULL for a page of zeroes.
regsLINK_SH_COUNT registers to write. NULL does nothing.

◆ outbind_to_chan_cfg()

void outbind_to_chan_cfg ( const outbind_t * b,
uint16_t * regs,
uint16_t min_us,
uint16_t max_us )

Render the channel configuration to match.

Each entry says what its channels are for, and that is what decides where a channel rests when it stops being commanded – stopped, or centred. With more than one protocol bound the roles are mixed, and each channel takes the role of the protocol whose pin renders it. Channels the selection does not use keep the schema's defaults.

min_us and max_us go to the throttle channels only, through outputs_chan_cfg_set_throttle_range(); every surface channel keeps the schema's 1000 to 2000us. Endpoints that page would refuse are not written at all.

Parameters
bThe selection. NULL leaves regs at the defaults.
regsLINK_CC_COUNT registers to write. NULL does nothing.
min_usLow endpoint of the throttle channels, in microseconds.
max_usHigh endpoint of the throttle channels, in microseconds.

◆ outbind_to_slots()

uint8_t outbind_to_slots ( const outbind_t * b,
uint16_t * regs )

Render the selection into the OUTPUTS page.

regs is LINK_OS_COUNT registers, cleared and rebuilt: every slot the selection does not use is set to no driver, so a page written from this is the whole truth rather than a change to what was there.

Slots are filled in pin order across every protocol and take channels from zero upward, so the lowest chosen pin is channel 0 whichever protocol holds it. Filling stops at LINK_OUT_SLOTS slots or LINK_OUT_CHANNELS channels, whichever comes first. Returns how many slots were used.

Parameters
bThe selection. NULL leaves regs with the default slots.
regsLINK_OS_COUNT registers to write. NULL does nothing.
Returns
The number of slots used, 0 for NULL arguments.

◆ outbind_toggle()

bool outbind_toggle ( outbind_t * b,
uint8_t index )

Add or remove a pin, in the protocol being edited.

Refuses a reserved pin, an index off the end, one more pin than the protocol can take – PPM's second pin is not a second output, it is a mistake – and a pin another protocol holds, which is that protocol's to give up. Removing a pin this protocol holds always succeeds, because an operator must always be able to undo what they just did.

Parameters
bThe selection, changed on success.
indexCatalogue index of the pin.
Returns
true when the pin was toggled; false when it was refused, and the selection is unchanged.

◆ outbind_trim()

void outbind_trim ( outbind_t * b)

Drop anything a selection cannot mean on its board.

Bits above the catalogue's width, and pins past what a protocol takes. outbind_t is a plain struct and one arrives from outside – read off the wire, or restored – so it is trimmed before it is shown rather than trusted.

Parameters
bThe selection, trimmed in place. NULL does nothing.

◆ outbind_wire_proto()

uint8_t outbind_wire_proto ( const outbind_t * b)

The protocol a page rendered from this selection reads back as: the lowest-numbered one holding a pin, or OFF when nothing does.

Which protocol is being edited is not on the wire. A page carries pins, and outbind_from_slots() has to name a protocol from them, so it names this one. A screen that has just been handed a binding uses this to tell the two apart: a protocol equal to it says only what the pins already said, and any other is somebody's choice.

Parameters
bThe selection.
Returns
The protocol number, or 0 (OFF) when no pin is chosen or b is NULL.