|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
Binding a protocol to pins: what the operator chooses, and the OUTPUTS page that comes out of it. More...
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. | |
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
| enum 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 |
| enum 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. |
| 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.
| id | Identity the IOmcu reports, an outbind_board_id_t value or a learned identity. |
id. OUTBIND_BOARD_UNKNOWN always returns NULL. | const outbind_board_t * outbind_board_at | ( | uint8_t | index | ) |
The board at index in the table, or NULL past the end.
| index | Position in the table, 0 to outbind_board_count() - 1. |
index is past the end. | 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.
| 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.
| board | The board to render, or NULL for a page of zeroes. |
| regs | LINK_CAT_COUNT registers to write. NULL does nothing. |
| 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.
| b | The selection. |
| index | Catalogue index of the pin. |
| uint8_t outbind_channels_used | ( | const outbind_t * | b | ) |
Channels the chosen pins render, across every protocol.
| b | The selection. |
| uint8_t outbind_chosen | ( | const outbind_t * | b | ) |
How many pins the protocol being edited has chosen.
| b | The selection. |
| 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.
| b | The selection. |
| 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.
| 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.
| b | Receives the selection. Cleared on refusal. |
| board | Identity of the board the page was read from. |
| regs | LINK_OS_COUNT registers of the OUTPUTS page. |
| chan_cfg | LINK_CC_COUNT registers of the CHAN_CFG page, or NULL. |
board; false when it is refused and b is cleared. | 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.
| b | The selection. |
| index | Catalogue index of the pin. |
b is NULL. | 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.
| board | Identity of the board, as for outbind_board(). |
| gpio | GPIO number to look up. |
gpio. The board's count when it is not listed, and 0 for a board this build does not know. | void outbind_init | ( | outbind_t * | b | ) |
Empty, and belonging to no board: nothing can be chosen until one is set.
| b | The selection to clear. NULL does nothing. |
| 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.
| id | Identity the catalogue page came from. Must not be OUTBIND_BOARD_UNKNOWN or an identity in the compiled table. |
| regs | LINK_CAT_COUNT registers of the catalogue page. NULL is refused. |
| 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.
| id | Identity of the learned board. Must equal the learned board's identity. |
| regs | LINK_PAD_COUNT registers of the pad page. NULL is refused. |
| 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.
| id | Identity of the learned board. Must equal the learned board's identity. |
| regs | LINK_SH_COUNT registers of the shape page. NULL is refused. |
| 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.
| board | Identity of the board, as for outbind_board(). |
| 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.
| shape | The outline to place the pad on. |
| pad | Pad number, 1 to twice shape's per_side. |
| x_cmm | Receives the x coordinate of the pad centre. |
| y_cmm | Receives the y coordinate of the pad centre. |
| 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.
| board | Identity of the board, as for outbind_board(). |
| void outbind_pads_to_regs | ( | const outbind_board_t * | board, |
| uint16_t * | regs ) |
Render them into LINK_PAD_COUNT registers, or leave them zero.
| board | The board whose pads to render, or NULL for a page of zeroes. |
| regs | LINK_PAD_COUNT registers to write. NULL does nothing. |
| 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.
| board | Identity of the board, as for outbind_board(). |
| 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.
| board | The board whose catalogue index indexes. |
| index | Catalogue index, 0 to the board's count - 1. |
| 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.
| board | Identity of the board, as for outbind_board(). |
| const outbind_proto_t * outbind_protos | ( | void | ) |
The protocol table, indexed by protocol number; entry 0 is OFF.
| 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:
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.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.
| b | The selection. |
| index | Catalogue index of the pin being checked. |
| prog_gpio | GPIO of the programming port's pin, or OUTBIND_NO_GPIO. |
| with | Receives the GPIO clashed with, or NULL to skip it. |
| 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()).
| b | The selection. |
| index | Catalogue index of the pin being checked. |
| ports | GPIOs of the programming ports, or NULL. |
| count | Number of entries in ports. |
| with | Receives the GPIO clashed with, or NULL to skip it. |
| 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.
| board | Identity of the board, as for outbind_board(). |
| 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.
| regs | LINK_OS_COUNT registers of the OUTPUTS page. |
| chan_cfg | LINK_CC_COUNT registers of the CHAN_CFG page. |
| role | The role to look for. |
| 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.
| b | The selection. NULL does nothing. |
| board | Identity of the board the selection is now for. |
| 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.
| b | The selection. NULL does nothing. |
| proto | Protocol number, an index into outbind_protos(). A value of OUTBIND_PROTOS or more does nothing. |
| 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.
| board | The board whose shape to render, or NULL for a page of zeroes. |
| regs | LINK_SH_COUNT registers to write. NULL does nothing. |
| 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.
| b | The selection. NULL leaves regs at the defaults. |
| regs | LINK_CC_COUNT registers to write. NULL does nothing. |
| min_us | Low endpoint of the throttle channels, in microseconds. |
| max_us | High endpoint of the throttle channels, in microseconds. |
| 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.
| b | The selection. NULL leaves regs with the default slots. |
| regs | LINK_OS_COUNT registers to write. NULL does nothing. |
| 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.
| b | The selection, changed on success. |
| index | Catalogue index of the pin. |
| 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.
| b | The selection, trimmed in place. NULL does nothing. |
| 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.
| b | The selection. |
b is NULL.