|
| 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.
|
| 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.
|
| 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.
|
| void | prog_port_kept (const prog_port_t *p, uint16_t *kept) |
| | The kept registers as they stand, PROG_PORT_KEPT_COUNT of them.
|
| 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_count (const prog_port_t *p) |
| | The number of ports the model holds.
|
| 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_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.
|
| 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.
|
| 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.
|
| 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.
|
| 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).
|
| 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.
|
The programming ports and their link page (0x33).
A programming port is an output of its own kind. It has its own pin, is no slot of the OUTPUTS page and holds no channel of the CHANNELS page. Its pin carries the port's function (FUNC, protocol 4.26) while no wire page holds the port, or that page's wire protocol:
SERVO PWM a servo pulse from the PWM (pulse-width modulation) generator, rendered while the bank is armed and the port's bit in LINK_PG_PWM is set. The pulse is a channel of the bank (prog_port_channel()), so arming, clamping, slew, the 500ms command timeout and the endpoints are the bank's. NONE no driver: the pin is held for the port, parked as an input with its pull-down, and renders nothing. Any free header pin; no PWM-pin or slice rule. DSHOT150, DSHOT300, DSHOT600 (4.28) plain DShot at 150, 300 or 600kbit/s from a PIO state machine of its own, rendered from the port's channel as a motor slot is: the channel's role is THROTTLE, so ARM THROTTLE arms it and the CONTROL page's throttle commands it. Any free header pin; no PWM-pin or slice rule. The page's CMD register is refused on such a port. PROGRAMMING the wire protocol of the KST or HITEC page (kst_port.h, hitec_port.h), which takes the pin from the function and gives it back.
A FUNC write is refused, as a PIN write is, while the bank is armed, a wire page holds a port, the port's pulse is on or the port is the TARGET. The pulse and the TARGET name SERVO PWM ports only, so the servo tester never drives a NONE or DShot port. Port 0 starts as SERVO PWM, the others as NONE.
The servo tester reaches a port three ways: LINK_PG_CMD is the manual command, LINK_PG_TARGET points the SERVO page's sweep and hold at the port (servo_page_target()), and a capture of the SERVO_SENSE page names the port with LINK_SS_ARM_PORT.
Pins. A port's pin and a slot's pin are never the same: a PIN write refuses a slot's pin, and prog_port_slots_check() refuses a slot on a port's pin. A SERVO PWM port's pin shares no PWM slice and no compare register with a PWM slot's pin either, so neither can change the other's frame rate. Two SERVO PWM ports may share a slice; both then run at PROG_PORT_RATE_HZ. A NONE or DShot port's pin is under none of the PWM rules.
Rates. Every port runs at PROG_PORT_RATE_HZ, 50Hz, except the TARGET port while the SERVO page names a rate: that port alone runs at it (protocol 4.19). A slice counts against one wrap register, so a port whose pin shares its slice with another port's pin takes no rate but 50Hz (servo_page_write()), and no pin moves onto the slice of a TARGET port that runs at another rate.
The model holds LINK_PG_PORTS_MAX ports; a build names how many it has.
Pure logic: binding a pin to the generator is the caller's.
SPDX-License-Identifier: MIT
| uint8_t prog_port_write |
( |
prog_port_t * | p, |
|
|
uint8_t | off, |
|
|
uint8_t | n, |
|
|
const uint16_t * | in, |
|
|
outputs_t * | o, |
|
|
uint64_t | taken, |
|
|
bool | locked, |
|
|
uint32_t | now_ms ) |
A write of the page: 0, or the LINK_NACK_* reason with nothing changed.
taken: the pins other holders have beyond the slots and the bank's reservation. locked: no PIN or FUNC may change now (the bank is armed or asked to arm, or a wire page holds a port). A PIN or FUNC change is also refused for a port whose PWM bit is set or that is the TARGET, before or after the frame. A FUNC above LINK_PG_FN_NONE, and any register of a port the build does not have, is BAD_VALUE. A PIN is judged under the FUNC the frame leaves its port with.
PWM and TARGET name only SERVO PWM ports whose pin the generator has (prog_port_bound()), and not a port whose PIN or FUNC the same frame changes.
No port whose PWM bit the write leaves set may have an endpoint longer than its frame carries: MIN_US and MAX_US at most out_pwm_pulse_max() of the rate the write leaves the port at (prog_port_port_hz()), 1784us at 560Hz (BAD_VALUE, protocol 4.16). This covers a range written to a pulsing port and a pulse switched on under a range that does not fit.
A TARGET change returns the SERVO rate to 0 (servo_page_target()), so every port is judged at PROG_PORT_RATE_HZ after one, and the write sets the rate prog_port_rate() last named to 0 as well: prog_port_port_hz() then names the rate each port runs at once the write is in force, before the SERVO page has followed the TARGET. Refused as well (BAD_VALUE, protocol 4.19): a TARGET change away from the standard servo ports while they run at a SERVO rate, when a PWM slot back at its own rate would carry a pulse longer than its frame (outputs_pulse_check()); and a PIN that puts a port on the PWM slice of the TARGET port while that port runs at a rate other than PROG_PORT_RATE_HZ.
- Parameters
-
| 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. |
- Returns
- 0 when the write is applied; otherwise the LINK_NACK_* reason: LINK_NACK_BAD_RANGE for a NULL argument or a window beyond LINK_PG_REGS, LINK_NACK_READ_ONLY for a window below LINK_PG_PWM, LINK_NACK_BAD_VALUE for a value refused as described above.