|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The panel's side of the programming ports' page (0x33). More...
Go to the source code of this file.
Data Structures | |
| struct | prog_link_t |
| The panel's side of the programming ports' page. More... | |
| struct | prog_link_write_t |
| One register to write. More... | |
| struct | prog_link_port_t |
| A port as the page holds it, for the OUTPUTS entry and PICK A PIN. More... | |
| struct | prog_link_drive_t |
| What the tester drives: the target, and with a port its pin and pulse. More... | |
Macros | |
| #define | PROG_LINK_POLL_MS 500u |
| The page is read this often, in ms, and at once while it is unknown. | |
| #define | PROG_LINK_NO_PIN 0xFFu |
| What prog_link_pin() returns for a port without a pin. | |
| #define | PROG_LINK_TARGET_UNKNOWN 0xFEu |
| prog_link_drive()'s target while the page is there and not known: where the commands would go is not known, and the tester sends none. | |
| #define | PROG_LINK_TARGET_NO_LINK 0xFFu |
| prog_link_drive()'s target with no IOmcu answering. | |
| #define | PROG_LINK_CFG_REGS 3u |
| The registers prog_link_cfg() fills: SLEW, MIN_US, MAX_US of a port. | |
| #define | PROG_LINK_SEEN_NONE 0xFFu |
| prog_link_t's seen while no TARGET is known. | |
| #define | PROG_LINK_COUNT_UNKNOWN 0xFFu |
| prog_link_count() while the ports are not known. | |
Enumerations | |
| enum | prog_link_rate_t { PROG_LINK_RATE_KEPT = 0 , PROG_LINK_RATE_RESET , PROG_LINK_RATE_UNKNOWN } |
| What became of the SERVO rate the panel last wrote (prog_link_rate()). More... | |
| enum | prog_link_ask_kind_t { PROG_LINK_ASK_PIN = 0 , PROG_LINK_ASK_FUNC } |
| What a prog_link_ask() asks: a port's PIN or its FUNC. | |
| enum | prog_link_ask_state_t { PROG_LINK_ASK_IDLE = 0 , PROG_LINK_ASK_WAITING , PROG_LINK_ASK_DONE , PROG_LINK_ASK_REFUSED , PROG_LINK_ASK_LOST } |
| Where the last prog_link_ask() stands. More... | |
Functions | |
| void | prog_link_init (prog_link_t *p) |
| No link, no page, nothing wanted. | |
| void | prog_link_came_up (prog_link_t *p, uint16_t minor) |
An IOmcu answered with protocol minor minor. | |
| void | prog_link_lost (prog_link_t *p) |
| The link is down: no page, no link. | |
| void | prog_link_want (prog_link_t *p, uint8_t target, bool pwm) |
What the screen wants: target 0 for the standard outputs or 1 + n for port n, and whether that port renders its pulse. | |
| void | prog_link_hold (prog_link_t *p, bool held) |
| Whether the servo programmer has a port (kst_prog_port_taken()). | |
| bool | prog_link_held (const prog_link_t *p) |
| Whether the servo programmer holds a port. | |
| uint8_t | prog_link_regs (const prog_link_t *p) |
| The registers a read of the page asks for: LINK_PG_REGS from 4.26, LINK_PG_REGS_V424 before. | |
| bool | prog_link_has_func (const prog_link_t *p) |
| Whether the IOmcu takes a FUNC: protocol 4.26 or later. | |
| bool | prog_link_has_dshot (const prog_link_t *p) |
| Whether the IOmcu takes FUNC DSHOT150 to DSHOT600: protocol 4.28 or later. | |
| bool | prog_link_ask (prog_link_t *p, uint8_t port, prog_link_ask_kind_t kind, uint16_t value) |
Ask for port port's PIN (value a GPIO, or LINK_PG_PIN_NONE) or FUNC (a link_pg_func_t) to be written. | |
| prog_link_ask_state_t | prog_link_ask_state (const prog_link_t *p, uint8_t *port, uint8_t *kind, uint16_t *value) |
Where the last ask stands, and what it was (port, kind, value may be NULL). | |
| bool | prog_link_read_due (const prog_link_t *p, uint32_t now_ms) |
| Whether the page is to be read now: it is unknown, or PROG_LINK_POLL_MS have passed. | |
| bool | prog_link_hitec_due (const prog_link_t *p) |
| The HITEC page beside the PROG page (protocol 4.23): a session the bench console opens holds a port the panel's rows must leave alone. | |
| void | prog_link_hitec_read (prog_link_t *p, const uint16_t *state) |
The HITEC STATE register as read, state NULL for a read nobody answered: the port it names is held from STOPPING on, free at FREE. | |
| uint8_t | prog_link_hitec_held (const prog_link_t *p) |
| Bit n: the HITEC page holds port n, as last read; 0 with no link, no page or nothing read since the link came up. | |
| void | prog_link_read (prog_link_t *p, const uint16_t *regs, uint32_t now_ms) |
| The page as read, prog_link_regs() registers, or NULL for a read that was not answered: the page is unknown then. | |
| void | prog_link_stale (prog_link_t *p) |
| The page is unknown until it is read again. | |
| bool | prog_link_next (const prog_link_t *p, bool quiet, prog_link_write_t *w) |
The write that is due, into w. | |
| uint8_t | prog_link_pulse_on (const prog_link_t *p, const prog_link_write_t *w) |
The port w switches its pulse on for, as 1 + n, or 0 for a write that switches none on. | |
| void | prog_link_written (prog_link_t *p, const prog_link_write_t *w, bool ack) |
What became of w: acknowledged, or not (refused or unanswered), which makes the page unknown. | |
| uint8_t | prog_link_wanted (const prog_link_t *p) |
| The target the screen can have: what is wanted, or 0 when the page has no such port, the port has no pin bound to the PWM generator – the IOmcu refuses such a target – or an ask for that port waits. | |
| bool | prog_link_ready (const prog_link_t *p) |
| Whether prog_link_target() is the IOmcu's: there is no page, or the page is read. | |
| uint8_t | prog_link_target (const prog_link_t *p) |
| The target as the IOmcu holds it; 0 without a page or a read. | |
| bool | prog_link_pending (const prog_link_t *p) |
| Whether a target change waits: the page is known and its target is not the one prog_link_wanted() names. | |
| bool | prog_link_settled (const prog_link_t *p) |
| Whether the tester may command: there is no page, or the page is known and its target is the one wanted. | |
| bool | prog_link_command (const prog_link_t *p, bool release) |
Whether the tester sends a command now, a release for release. | |
| prog_link_rate_t | prog_link_rate (prog_link_t *p) |
| What the reads and writes since the last call did to the SERVO rate, and forgets it. | |
| bool | prog_link_pwm (const prog_link_t *p) |
| Whether the target port renders its pulse, as the page holds it. | |
| uint8_t | prog_link_count (const prog_link_t *p) |
| The ports the IOmcu's page reports (register COUNT), at most LINK_PG_PORTS_MAX: 0 for an IOmcu without the page (protocol older than 4.13), PROG_LINK_COUNT_UNKNOWN with no link or before the page's first read since the link came up, a write not acknowledged, or a read not answered (prog_link_stale()). | |
| uint8_t | prog_link_pin (const prog_link_t *p, uint8_t port) |
The GPIO port port is bound to, or PROG_LINK_NO_PIN: no page, no read, no such port, no pin, or a pin the IOmcu refused. | |
| bool | prog_link_port (const prog_link_t *p, uint8_t port, prog_link_port_t *out) |
Port port as the page holds it into out. | |
| bool | prog_link_no_drive (const prog_link_t *p) |
| Whether the screen wants a port the page cannot make the target: one the IOmcu does not have, one without a pin the PWM generator holds (none, refused, or FUNCTION NONE), or one an ask waits on. | |
| prog_link_drive_t | prog_link_drive (const prog_link_t *p) |
| Where the tester's commands go now, for the SERVO screen's TARGET row. | |
| void | prog_link_cfg (const uint16_t *cc, uint16_t *out) |
| A channel's configuration as the CHAN_CFG page takes it (LINK_CC_STRIDE registers) as a port takes it from LINK_PG_SLEW on: SLEW, MIN_US, MAX_US. | |
The panel's side of the programming ports' page (0x33).
The SERVO screen's tester drives one of two things: the standard servo outputs, or a programming port. Which one is a register of the IOmcu (LINK_PG_TARGET), and whether the port renders a pulse is another (its bit in LINK_PG_PWM). This module holds what the page last read, what the screen wants, and names the one write that brings the page to it.
Rules:
An IOmcu older than protocol 4.13 has no page: nothing is read or written and the target is the standard outputs.
From protocol 4.19 the SERVO page's frame rate is the target's, and a TARGET change returns it to 0. prog_link_rate() says what the reads and writes since it was last asked mean for the rate the panel last wrote.
A port's PIN and, from protocol 4.26, its FUNC are the IOmcu's, kept in its flash with the outputs' binding: the panel writes one only when the operator asks (prog_link_ask()), never from a stored setting. An ask waits for a bench at rest as a TARGET change does; a port that is the TARGET is first let go (TARGET 0, its pulse off first), and the target wanted comes back after the write. An IOmcu older than 4.26 has 24 registers and no FUNC: every port reads SERVO PWM and a FUNC ask is refused before anything is sent.
Pure logic, no I/O. Nothing here has run on hardware.
SPDX-License-Identifier: MIT
Where the last prog_link_ask() stands.
| enum prog_link_rate_t |
What became of the SERVO rate the panel last wrote (prog_link_rate()).
| Enumerator | |
|---|---|
| PROG_LINK_RATE_KEPT | no TARGET change seen |
| PROG_LINK_RATE_RESET | the TARGET changed: the rate is 0 |
| PROG_LINK_RATE_UNKNOWN | a TARGET write went unacknowledged |
| bool prog_link_ask | ( | prog_link_t * | p, |
| uint8_t | port, | ||
| prog_link_ask_kind_t | kind, | ||
| uint16_t | value ) |
Ask for port port's PIN (value a GPIO, or LINK_PG_PIN_NONE) or FUNC (a link_pg_func_t) to be written.
True when taken: the page is there, the port is one it has, and for FUNC the IOmcu has the register and value is SERVO PWM or NONE, or from 4.28 DSHOT150, DSHOT300 or DSHOT600. A later ask replaces one still waiting. prog_link_next() writes it on a bench at rest.
| p | The link state. |
| port | The port. |
| kind | PIN or FUNC. |
| value | The GPIO, or the link_pg_func_t. |
| prog_link_ask_state_t prog_link_ask_state | ( | const prog_link_t * | p, |
| uint8_t * | port, | ||
| uint8_t * | kind, | ||
| uint16_t * | value ) |
Where the last ask stands, and what it was (port, kind, value may be NULL).
| p | The link state. |
| port | Receives the port, or NULL. |
| kind | Receives the kind, or NULL. |
| value | Receives the value, or NULL. |
| void prog_link_came_up | ( | prog_link_t * | p, |
| uint16_t | minor ) |
An IOmcu answered with protocol minor minor.
What is wanted stays; the page is unknown.
| p | The link state. |
| minor | The IOmcu's protocol minor version. |
| void prog_link_cfg | ( | const uint16_t * | cc, |
| uint16_t * | out ) |
A channel's configuration as the CHAN_CFG page takes it (LINK_CC_STRIDE registers) as a port takes it from LINK_PG_SLEW on: SLEW, MIN_US, MAX_US.
| cc | The channel's CHAN_CFG registers, LINK_CC_STRIDE of them. |
| out | Receives SLEW, MIN_US and MAX_US. |
| bool prog_link_command | ( | const prog_link_t * | p, |
| bool | release ) |
Whether the tester sends a command now, a release for release.
Not before the page is read (prog_link_ready()); not to a port while the programmer has one, a release neither – it stays owed; and a command that is not a release only once the target is the one wanted (prog_link_settled()) and the screen wants one that can be driven (prog_link_no_drive()).
| p | The link state. |
| release | true for a release command. |
| uint8_t prog_link_count | ( | const prog_link_t * | p | ) |
The ports the IOmcu's page reports (register COUNT), at most LINK_PG_PORTS_MAX: 0 for an IOmcu without the page (protocol older than 4.13), PROG_LINK_COUNT_UNKNOWN with no link or before the page's first read since the link came up, a write not acknowledged, or a read not answered (prog_link_stale()).
| p | The link state. |
| prog_link_drive_t prog_link_drive | ( | const prog_link_t * | p | ) |
Where the tester's commands go now, for the SERVO screen's TARGET row.
PROG_LINK_TARGET_NO_LINK with no IOmcu answering (before the first prog_link_came_up() and after prog_link_lost()), PROG_LINK_TARGET_UNKNOWN while the page is there and not known (not read yet, a read not answered, a write not acknowledged). The tester sends no command in either: nothing crosses a link that is down, and prog_link_command() is false while the page is not known. An IOmcu without the page has target 0.
While the servo programmer holds the port (prog_link_hold(true)) the target is unchanged: the line keeps naming the target the IOmcu holds, a port or the standard outputs. The programmer drives the port and the tester sends nothing.
Otherwise the target is prog_link_target(), the one the commands use; the pin is the target port's GPIO, or PROG_LINK_NO_PIN with the standard outputs as target or a port without a usable pin (none, refused, or a port the page does not have); pwm is prog_link_pwm(), false with target
| p | The link state. |
| bool prog_link_has_dshot | ( | const prog_link_t * | p | ) |
Whether the IOmcu takes FUNC DSHOT150 to DSHOT600: protocol 4.28 or later.
| p | The link state. |
| bool prog_link_has_func | ( | const prog_link_t * | p | ) |
Whether the IOmcu takes a FUNC: protocol 4.26 or later.
| p | The link state. |
| bool prog_link_held | ( | const prog_link_t * | p | ) |
Whether the servo programmer holds a port.
| p | The link state. |
| bool prog_link_hitec_due | ( | const prog_link_t * | p | ) |
The HITEC page beside the PROG page (protocol 4.23): a session the bench console opens holds a port the panel's rows must leave alone.
Whether its STATE register is read with the PROG page: an IOmcu answers that has the page.
| p | The link state. |
| uint8_t prog_link_hitec_held | ( | const prog_link_t * | p | ) |
Bit n: the HITEC page holds port n, as last read; 0 with no link, no page or nothing read since the link came up.
| p | The link state. |
| void prog_link_hitec_read | ( | prog_link_t * | p, |
| const uint16_t * | state ) |
The HITEC STATE register as read, state NULL for a read nobody answered: the port it names is held from STOPPING on, free at FREE.
A read not answered keeps what was known.
| p | The link state. |
| state | The STATE register as read, or NULL for a read nobody answered. |
| void prog_link_hold | ( | prog_link_t * | p, |
| bool | held ) |
Whether the servo programmer has a port (kst_prog_port_taken()).
While it has, the page is read and not written: prog_link_want() changes nothing, prog_link_next() names no write – not a pulse switched off either – prog_link_pending() is false and prog_link_command() takes no command for a port. What is wanted afterwards is what prog_link_want() says after the hold.
| p | The link state. |
| held | true while the servo programmer has a port. |
| void prog_link_init | ( | prog_link_t * | p | ) |
No link, no page, nothing wanted.
| p | The link state to set up. |
| void prog_link_lost | ( | prog_link_t * | p | ) |
The link is down: no page, no link.
| p | The link state. |
| bool prog_link_next | ( | const prog_link_t * | p, |
| bool | quiet, | ||
| prog_link_write_t * | w ) |
The write that is due, into w.
quiet says the bank is disarmed and no surface holds a position this panel wrote. False for none: no page, the page unknown, nothing differs, or what differs waits for quiet. The pulse is switched off before the target changes and on after. An ask (prog_link_ask()) is written on a bench at rest once its port is neither the target nor pulsing, before the pulse goes back on.
| p | The link state. |
| quiet | true when the bank is disarmed and no surface holds a position this panel wrote. |
| w | Receives the write that is due. |
| bool prog_link_no_drive | ( | const prog_link_t * | p | ) |
Whether the screen wants a port the page cannot make the target: one the IOmcu does not have, one without a pin the PWM generator holds (none, refused, or FUNCTION NONE), or one an ask waits on.
prog_link_wanted() is then 0, so the IOmcu's target is the standard outputs; the tester drives nothing in their place (prog_link_command() takes no command but a release). False before the page is read and with an IOmcu without the page, whose target is the standard outputs.
| p | The link state. |
| bool prog_link_pending | ( | const prog_link_t * | p | ) |
Whether a target change waits: the page is known and its target is not the one prog_link_wanted() names.
| p | The link state. |
| uint8_t prog_link_pin | ( | const prog_link_t * | p, |
| uint8_t | port ) |
The GPIO port port is bound to, or PROG_LINK_NO_PIN: no page, no read, no such port, no pin, or a pin the IOmcu refused.
| p | The link state. |
| port | The port. |
| bool prog_link_port | ( | const prog_link_t * | p, |
| uint8_t | port, | ||
| prog_link_port_t * | out ) |
Port port as the page holds it into out.
False, and out untouched, with no page, no read or no such port.
| p | The link state. |
| port | The port. |
| out | Receives the port as the page holds it. |
| uint8_t prog_link_pulse_on | ( | const prog_link_t * | p, |
| const prog_link_write_t * | w ) |
The port w switches its pulse on for, as 1 + n, or 0 for a write that switches none on.
An IOmcu from protocol 4.16 refuses that write while the port's range is longer than the frame it runs at (1784us at 560Hz), so the panel states the range the screen names to the port first: a range kept from an earlier profile would keep it refused.
| p | The link state. |
| w | The write. |
| bool prog_link_pwm | ( | const prog_link_t * | p | ) |
Whether the target port renders its pulse, as the page holds it.
False with the standard outputs as target.
| p | The link state. |
| prog_link_rate_t prog_link_rate | ( | prog_link_t * | p | ) |
What the reads and writes since the last call did to the SERVO rate, and forgets it.
From 4.19: PROG_LINK_RATE_RESET once a read or an acknowledged write shows a TARGET other than the one known before, and PROG_LINK_RATE_UNKNOWN once a TARGET write went unacknowledged, which may or may not have changed it; the stronger of the two when both happened. Always PROG_LINK_RATE_KEPT below 4.19, where the rate does not follow the target, and for the first TARGET known after a link-up.
| p | The link state. |
| void prog_link_read | ( | prog_link_t * | p, |
| const uint16_t * | regs, | ||
| uint32_t | now_ms ) |
The page as read, prog_link_regs() registers, or NULL for a read that was not answered: the page is unknown then.
Below 4.26 every port's FUNC is taken as SERVO PWM.
| p | The link state. |
| regs | The page as read, or NULL for a read not answered. |
| now_ms | The time, in ms. |
| bool prog_link_read_due | ( | const prog_link_t * | p, |
| uint32_t | now_ms ) |
Whether the page is to be read now: it is unknown, or PROG_LINK_POLL_MS have passed.
| p | The link state. |
| now_ms | The time, in ms. |
| bool prog_link_ready | ( | const prog_link_t * | p | ) |
Whether prog_link_target() is the IOmcu's: there is no page, or the page is read.
A release goes to the target that holds the pulse, so it waits for this and not for prog_link_settled().
| p | The link state. |
| uint8_t prog_link_regs | ( | const prog_link_t * | p | ) |
The registers a read of the page asks for: LINK_PG_REGS from 4.26, LINK_PG_REGS_V424 before.
| p | The link state. |
| bool prog_link_settled | ( | const prog_link_t * | p | ) |
Whether the tester may command: there is no page, or the page is known and its target is the one wanted.
The pulse bit is not part of it.
| p | The link state. |
| void prog_link_stale | ( | prog_link_t * | p | ) |
The page is unknown until it is read again.
| p | The link state. |
| uint8_t prog_link_target | ( | const prog_link_t * | p | ) |
The target as the IOmcu holds it; 0 without a page or a read.
| p | The link state. |
| void prog_link_want | ( | prog_link_t * | p, |
| uint8_t | target, | ||
| bool | pwm ) |
What the screen wants: target 0 for the standard outputs or 1 + n for port n, and whether that port renders its pulse.
A target above LINK_PG_PORTS_MAX is taken as 0.
| p | The link state. |
| target | 0 for the standard outputs, or 1 + n for port n. |
| pwm | true when that port renders its pulse. |
| uint8_t prog_link_wanted | ( | const prog_link_t * | p | ) |
The target the screen can have: what is wanted, or 0 when the page has no such port, the port has no pin bound to the PWM generator – the IOmcu refuses such a target – or an ask for that port waits.
0 while the page is unknown or absent.
| p | The link state. |
| void prog_link_written | ( | prog_link_t * | p, |
| const prog_link_write_t * | w, | ||
| bool | ack ) |
What became of w: acknowledged, or not (refused or unanswered), which makes the page unknown.
| p | The link state. |
| w | The write. |
| ack | true when the write was acknowledged. |