|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
Binding a protocol to pins. More...
#include "out_bind.h"#include <stddef.h>#include <string.h>#include "link_pages.h"#include "out_pwm_map.h"#include "outputs_pages.h"Functions | |
| const outbind_board_t * | outbind_board (uint16_t id) |
| The board with this identity, or NULL when nothing here describes it. | |
| static const char * | hold_name (uint8_t hold) |
| The panel's words for what the wire can only number. The panel shows them through ui_pin_holder(), in the language showing. | |
| 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. | |
| 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_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. | |
| 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. | |
| static uint32_t | board_mask (const outbind_board_t *bd) |
| Which bits of a selection can mean anything on this board. | |
| 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. | |
| void | outbind_set_board (outbind_t *b, uint16_t board) |
| Say which board this binding is for. | |
| static uint8_t | count_pins (uint32_t pins, uint8_t width) |
| How many bits are set in one protocol's pin set. | |
| static uint8_t | cap_of (const outbind_proto_t *p) |
| What a protocol may take: its own cap, and never more slots than the page has. | |
| 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. | |
| 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. | |
| uint8_t | outbind_group_of (const outbind_t *b, uint8_t index) |
Which protocol holds index, or 0 (OFF) when nothing does. | |
| void | outbind_trim (outbind_t *b) |
| Drop anything a selection cannot mean on its board. | |
| 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. | |
| 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. | |
| uint8_t | outbind_to_slots (const outbind_t *b, uint16_t *regs) |
| Render the selection into the OUTPUTS page. | |
| static out_role_t | role_of_slot (const uint16_t *chan_cfg, const uint16_t *r) |
| What the CHAN_CFG page says the channels of this slot are for. | |
| 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. | |
| 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. | |
| 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. | |
Variables | |
| static const outbind_pin_t | k_pico_pins [OUTBIND_PINS] |
| The header, in GPIO order. | |
| static const outbind_shape_t | k_pico_shape |
| The Pico form factor: 51.00 x 21.00mm, forty pads on 2.54mm, twenty a side, pad 1 at the bottom left with the numbers running away from it. | |
| static const outbind_pad_t | k_pico_pads [] |
| The pads that are not pins, in pad order. | |
| static const outbind_board_t | k_boards [] |
| Every board this build knows. | |
| static outbind_pin_t | s_learned_pins [LINK_CAT_PINS] |
| One board learned over the link, for an IOmcu this build ships no catalogue for. | |
| static outbind_pad_t | s_learned_pads [LINK_PAD_SLOTS] |
| static outbind_shape_t | s_learned_shape |
| static char | s_learned_name [16] |
| static outbind_board_t | s_learned |
| static bool | s_have_learned |
| static const outbind_proto_t | k_protos [OUTBIND_PROTOS] |
| PWM runs at 50Hz, which every analogue and digital servo takes. | |
|
static |
Which bits of a selection can mean anything on this board.
| bd | The board, or NULL. |
|
static |
What a protocol may take: its own cap, and never more slots than the page has.
| p | The protocol entry. |
p's max_pins and OUT_MAX_SLOTS.
|
static |
How many bits are set in one protocol's pin set.
| pins | The pin set, one bit per catalogue index. |
| width | How many low bits to count, 0 to 32. |
width.
|
static |
The panel's words for what the wire can only number. The panel shows them through ui_pin_holder(), in the language showing.
| hold | A LINK_PIN_* value from the catalogue page. |
hold, or "in use" for any other value. | 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.
|
static |
What the CHAN_CFG page says the channels of this slot are for.
The slot's first channel answers for the run: outbind_to_chan_cfg() writes one role across every channel a slot renders, so no page this end produced can disagree with itself. A page that does – which nothing here writes – is read by its first channel rather than refused, and a first channel past the page reads as a surface, which is where an unconfigured channel already rests.
| chan_cfg | The CHAN_CFG page, or NULL. |
| r | The slot's OUTPUTS registers. |
|
static |
Every board this build knows.
A second one appends a row here and a catalogue above it; nothing else in this file is per-board.
|
static |
The pads that are not pins, in pad order.
VSYS carries no voltage here because it does not have one: it is the input rail and follows whatever feeds it, which on the bring-up module is USB and on a bench could be anything. A number that is only sometimes true is worse on this screen than no number.
|
static |
The header, in GPIO order.
GP23 to GP25 and GP29 are missing because the Pico form factor does not bring them out: on the module GP23 is the MODE pin of the MP28164 power converter, GP24 senses VBUS, GP25 drives LED1 and GP29 senses VSYS. outbind_reserved_mask() reserves every pin the catalogue leaves out, so those four and every number from GP30 up are refused. The pad numbers are the ones printed on the board so an operator counting pads and an operator reading GPIOs arrive at the same pin.
The reserved six are the IOmcu's: GP3 carries the safety heartbeat in from the panel, and GP8 to GP12 are the CAN (Controller Area Network) controller's interrupt and its SPI (Serial Peripheral Interface) bus. firmware/iomcu/include/iomcu_pins.h assigns the same pins for the drivers that use them; the IOmcu reserves the union of both, so the two disagreeing costs a pin rather than the safety line.
|
static |
The Pico form factor: 51.00 x 21.00mm, forty pads on 2.54mm, twenty a side, pad 1 at the bottom left with the numbers running away from it.
The outline's own numbers. The board drawing the IOmcu serves places its pads on the same grid, and the picker refuses a drawing that does not (board_drawing_agrees()).
|
static |
PWM runs at 50Hz, which every analogue and digital servo takes.
PPM runs at 40Hz because eight channels do not fit in a 50Hz frame. A channel is at most OUT_CEILING_US (2500us), and the frame also carries the mark and a sync gap of at least PPM_SYNC_MIN_US, so eight of them need 8 x 2500 + 300 + 3000 = 23,300us and 50Hz gives 20,000. The IOmcu refuses the bind and leaves the slot unbound, having acknowledged the page that asked for it, so the screen shows a binding the bench does not have. 40Hz gives 25,000us and binds.
The DShot rates are bit rates and the two bidirectional entries are the same wire asking for telemetry back.
SERVO PWM and MOTOR PWM are the same signal at the same rate and differ only in what the channel is for. A servo centres when nothing commands it; a motor stops. Nothing in the pulse says which is on the pin, so the two are separate entries and the operator picks the one that is wired.
|
static |
One board learned over the link, for an IOmcu this build ships no catalogue for.
The name is formatted rather than carried: a name is a string and the page is registers, and the identity is what the operator needs to match against the board in front of them.