|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
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). | |
| #define REG | ( | port, | |
| r ) |
|
static |
The channel of port as the page describes it.
| p | The port model. |
| o | The outputs model whose port channel is set. |
| port | Port index. |
|
static |
The 64-bit mask with only bit pin set.
| pin | The pin number, used as a shift count. |
pin set.
|
static |
Whether the window off, n carries register r.
| off | First register of the window. |
| n | Number of registers in the window. |
| r | Register index. |
r lies in the window.
|
static |
The function a port starts with on a board that has stored none: the servo pulse on port 0, nothing on the others.
| port | Port index. |
|
static |
Whether the port's function is DShot (4.28): a PIO state machine renders it from the port's channel, a throttle.
| regs | The page's registers, LINK_PG_REGS entries. |
| port | Port index. |
|
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.
| word | The kept function word, 4 bits per port. |
| port | Port index. |
|
static |
Port port's function as regs hold it.
| regs | The page's registers, LINK_PG_REGS entries. |
| port | Port index. |
|
static |
Whether the port's function is the servo pulse, which the PWM generator renders and which the PWM-pin and slice rules hold.
| regs | The page's registers, LINK_PG_REGS entries. |
| port | Port index. |
|
static |
Whether port port holds the pin its register names.
| p | The port model. |
| port | Port index. |
|
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.
| o | The outputs model, for its reservations and slots. |
| pin | The pin to test. |
| pwm | true for a SERVO PWM port. |
| ours | Bit n: pins the ports hold now. |
| taken | Bit n: pins other holders have. |
|
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.
| target | The TARGET register: 1 + the port index, or 0 for none. |
| hz | The SERVO page's rate in Hz, 0 for none. |
| port | Port index. |
|
static |
Two port pins that cannot both be held: one pin, or two servo pulses on one compare register of the generator.
| a | The pin of one port. |
| a_pwm | true when that port is a SERVO PWM port. |
| b | The pin of the other port. |
| b_pwm | true when that port is a SERVO PWM port. |
| 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.
| p | The port model. |
| mask | 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_channel | ( | uint8_t | port | ) |
The bank channel of port.
| port | Port index. |
| uint8_t prog_port_count | ( | const prog_port_t * | p | ) |
The number of ports the model holds.
| p | The port model, or NULL. |
| 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.
| kept | Receives PROG_PORT_KEPT_COUNT kept registers, written in place. |
| pin0 | The pin of port 0, or LINK_PG_PIN_NONE for none. |
| 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.
| p | The port model. |
| 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.
| p | The port model, or NULL. |
| port | Port index, 0 to LINK_PG_PORTS_MAX - 1. |
| 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.
| p | The port model to set up. |
| count | Ports the build has, 0 to LINK_PG_PORTS_MAX; a larger value is clamped. |
| 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.
| p | The port model, or NULL. |
| port | Port index, 0 to LINK_PG_PORTS_MAX - 1. |
| void prog_port_kept | ( | const prog_port_t * | p, |
| uint16_t * | kept ) |
The kept registers as they stand, PROG_PORT_KEPT_COUNT of them.
| p | The port model. |
| kept | Receives PROG_PORT_KEPT_COUNT registers, written in place. |
| 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.
| p | The port model. |
| 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.
| p | The port model. |
| uint8_t prog_port_pin | ( | const prog_port_t * | p, |
| uint8_t | port ) |
The pin port port holds, or PROG_PORT_NO_PIN.
| p | The port model, or NULL. |
| port | Port index. |
| uint64_t prog_port_pins | ( | const prog_port_t * | p | ) |
Every pin the ports hold, one bit per pin.
| p | The port model, or NULL. |
| 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.
| p | The port model, or NULL. |
| port | Port index. |
| uint8_t prog_port_pwm | ( | const prog_port_t * | p | ) |
Bit n: port n's pulse is switched on.
| p | The port model, or NULL. |
| 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.
| p | The port model, or NULL. |
| 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.
| p | The port model. |
| 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.
| p | The port model, or NULL; a NULL p is ignored. |
| hz | The SERVO page's frame rate in Hz, 0 for none. |
| 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.
| p | The port model. |
| off | First register of the window. |
| n | Number of registers to read. |
| out | Receives n register values; left unchanged for a NULL p or out, or a window beyond LINK_PG_REGS. |
| 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.
| p | The port model to restore into. |
| kept | PROG_PORT_KEPT_COUNT kept registers, as prog_port_kept() wrote them. |
| o | The outputs model whose port channels are set. |
| taken | Bit n: pin n is held by another holder beyond the slots and the bank's reservation. |
| 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.
| p | The port model to restore into. |
| kept | PROG_PORT_KEPT_COUNT kept registers, as prog_port_kept() wrote them. |
| func_word | The kept function word, as prog_port_kept_func() wrote it. |
| o | The outputs model whose port channels are set. |
| taken | Bit n: pin n is held by another holder beyond the slots and the bank's reservation. |
| 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.
| p | The port model, overwritten with was. |
| was | The port model as it stood before the write that failed. |
| o | The outputs model whose port channels are set. |
| 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.
| p | The port model, or NULL. |
| 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).
| p | The port model, or NULL. |
| slots | The OUTPUTS slot registers, LINK_OUT_SLOTS slots of LINK_OS_STRIDE registers each. |
| 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.
| slots | The 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. |
| uint8_t prog_port_target | ( | const prog_port_t * | p | ) |
0 for the standard servo ports, 1 + n for port n.
| p | The port model, or NULL. |
| 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.
| p | The port model, or NULL. |
| port | Port index, 0 to LINK_PG_PORTS_MAX - 1. |
| bound | Bit n for port n: the port's pin is held by the IOmcu (outputs_hw_ports_bound()). |
| 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.
| p | The port model, updated when the write is applied. |
| off | First register of the window; below LINK_PG_PWM is read-only. |
| n | Number of registers in the window; 0 applies nothing. |
| in | The n register values to write. |
| o | The outputs model whose port channels are set. |
| taken | Bit n: pin n is held by another holder beyond the slots and the bank's reservation. |
| locked | True refuses every PIN and FUNC change. |
| now_ms | Current time in milliseconds, passed on for a CMD write. |
|
static |
Whether a bound slot's channels reach a port's bank channel.
| r | The slot's register words. |
|
static |
Whether us lies in the endpoint range.
| us | The endpoint in microseconds. |
us lies between LINK_CC_FLOOR_US and LINK_CC_CEILING_US, both included.