|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The SERVO link page at the IOmcu: the frame rate of the tester's target and the sweep that drives it through a curve. More...
Go to the source code of this file.
Data Structures | |
| struct | servo_page_t |
| The SERVO page state: its registers, the sweep, and the hold. More... | |
| struct | servo_phase_t |
| The far end's sweep phase as the host times it, from the acknowledgements of the writes that start, hold and resume it: when the curve's phase 0 is on the host's clock, and the phase a hold kept. More... | |
Enumerations | |
| enum | servo_resume_t { SERVO_RESUME_CURVE , SERVO_RESUME_WRITE , SERVO_RESUME_TOO_OLD , SERVO_RESUME_REFUSED , SERVO_RESUME_UNTIMED } |
| What a host writes to carry on a sweep it asked to be resumed. More... | |
Functions | |
| void | servo_page_init (servo_page_t *p) |
| Set the page to its start: no sweep, no hold, the standard servo ports as target. | |
| uint8_t | servo_page_write (servo_page_t *p, uint8_t off, uint8_t n, const uint16_t *in, outputs_t *o, uint32_t now_ms) |
A write to the page, validated whole against the bank o before any of it is stored. | |
| void | servo_page_read (servo_page_t *p, uint8_t off, uint8_t n, uint16_t *out) |
| The page as a read sees it: the sweep register 0 once the sweep has stopped, and the ends it reached as of the last servo_page_step(). | |
| bool | servo_page_step (servo_page_t *p, outputs_t *o, uint32_t now_ms) |
| One pass: stop a sweep the bank's surfaces are no longer armed for, one not written for OUT_DEFAULT_TIMEOUT_MS or one that has made its movements, and command every surface along a sweep that runs. | |
| void | servo_page_ports (servo_page_t *p, uint16_t channels, uint16_t sliced) |
The programming ports as a rate for a port target is judged, bit n for bank channel n: channels the ports whose pulse is on, whose endpoints the rate must fit, and sliced the ports whose pin shares a PWM slice with another port's pin, which run at PROG_PORT_RATE_HZ only. | |
| uint16_t | servo_page_hz (const servo_page_t *p) |
| The frame rate register: the target's rate, 0 for its own. | |
| uint16_t | servo_page_slots_hz (const servo_page_t *p) |
| The rate the slots take, for outputs_slot_rates() and the OUTPUTS and CHAN_CFG checks: the register with the standard servo ports as target, 0 with a programming port. | |
| bool | servo_page_target (servo_page_t *p, outputs_t *o, uint8_t first, uint8_t count) |
Name the channels the sweep and the hold command: count channels of the bank from first, or with count 0 the standard servo ports (channels 0 to LINK_OUT_CHANNELS - 1), which is what a page starts with. | |
| servo_resume_t | servo_page_resume_plan (bool asked, bool held, bool timed, uint16_t proto_minor, bool refused) |
The host's choice for a sweep command: asked a resume of the sweep held, held a hold at the far end, timed its phase known here (false for a HOLD that went unanswered and was not yet acknowledged, which may or may not have reached the far end), proto_minor its protocol minor, and refused the RESUME just written was refused. | |
| void | servo_phase_started (servo_phase_t *ph, uint32_t ack_ms) |
A sweep started, from its beginning, when acknowledged at ack_ms. | |
| uint32_t | servo_phase_held (servo_phase_t *ph, uint32_t ack_ms) |
A running sweep held at ack_ms: its phase is kept; returned. | |
| void | servo_phase_stopped (servo_phase_t *ph) |
| The sweep stopped, or the far end restarted: nothing is held to resume. | |
| bool | servo_phase_resumable (const servo_phase_t *ph) |
| Whether a hold of a running sweep stands to be resumed. | |
| bool | servo_phase_resumed (servo_phase_t *ph, uint32_t ack_ms, uint32_t *start_ms) |
A held sweep resumed at ack_ms: its phase 0 moves on by the hold, into start_ms. | |
The SERVO link page at the IOmcu: the frame rate of the tester's target and the sweep that drives it through a curve.
Register 0 is the target's frame rate (protocol 4.19). With the standard servo ports as target it is every PWM slot whose first channel is a surface (outputs_servo_rate_check()); with a programming port it is that port's pin alone, and the slots run at their own rates. The other programming ports run at PROG_PORT_RATE_HZ, 50Hz. A change of target returns the register to 0. Registers 1 to 4 are a sweep – curve, speed, amplitude, dwell – and fit one CAN frame, so a start is whole. Register 5 is how many ends a sweep started after it reaches before it stops; register 6 reads how many the sweep has reached.
A sweep runs only while the bench is armed for the surfaces (OUT_ROLE_SURFACE), and only while the panel keeps writing it: one that hears nothing for OUT_DEFAULT_TIMEOUT_MS stops, the rule a channel command already keeps, so a panel that goes quiet leaves no servo moving. A write that repeats the sweep in force keeps it going without restarting the curve; one that changes it starts the new curve from its beginning. A disarm stops it. A sweep that has made its movements stays stopped while the same curve is written again, so a panel still repeating it does not start it over; 0 or another curve clears that.
A hold (LINK_SV_HOLD) freezes the surfaces where their outputs are, and a sweep running when it began keeps its phase; a resume (LINK_SV_RESUME, protocol 4.6) carries that sweep on from there. Whatever ends the hold – 0, a curve written over it, a disarm, silence – forgets the phase. A hold of a sweep that has made its movements keeps the centre it ended on.
Every write is judged against the page as a servo_page_step() at the same moment leaves it, so a write served ahead of the pass finds a sweep that has run out already ended.
While it runs it commands every channel the bank marks a surface, each pass, and the CHANNELS page is not what drives them.
Nothing on the page is kept across a restart. Host-tested; the IOmcu is wiring.
SPDX-License-Identifier: MIT
| enum servo_resume_t |
What a host writes to carry on a sweep it asked to be resumed.
| uint16_t servo_page_hz | ( | const servo_page_t * | p | ) |
The frame rate register: the target's rate, 0 for its own.
| p | The page state. |
| void servo_page_init | ( | servo_page_t * | p | ) |
Set the page to its start: no sweep, no hold, the standard servo ports as target.
Nothing is done when p is NULL.
| p | The page state, overwritten. |
| void servo_page_ports | ( | servo_page_t * | p, |
| uint16_t | channels, | ||
| uint16_t | sliced ) |
The programming ports as a rate for a port target is judged, bit n for bank channel n: channels the ports whose pulse is on, whose endpoints the rate must fit, and sliced the ports whose pin shares a PWM slice with another port's pin, which run at PROG_PORT_RATE_HZ only.
Both 0 after servo_page_init().
| p | The page state. Nothing is done when NULL. |
| channels | Bit n set for a bank channel whose pulse is on. |
| sliced | Bit n set for a bank channel that runs at PROG_PORT_RATE_HZ. |
| void servo_page_read | ( | servo_page_t * | p, |
| uint8_t | off, | ||
| uint8_t | n, | ||
| uint16_t * | out ) |
The page as a read sees it: the sweep register 0 once the sweep has stopped, and the ends it reached as of the last servo_page_step().
Nothing is done when p or out is NULL, or when off and n reach past LINK_SV_COUNT.
| p | The page state. The sweep register is cleared when the sweep has stopped. |
| off | First register, 0 to LINK_SV_COUNT - 1. |
| n | Number of registers to read. |
| out | Receives the n register values. |
| servo_resume_t servo_page_resume_plan | ( | bool | asked, |
| bool | held, | ||
| bool | timed, | ||
| uint16_t | proto_minor, | ||
| bool | refused ) |
The host's choice for a sweep command: asked a resume of the sweep held, held a hold at the far end, timed its phase known here (false for a HOLD that went unanswered and was not yet acknowledged, which may or may not have reached the far end), proto_minor its protocol minor, and refused the RESUME just written was refused.
A resume is written only for a hold in force, so a repeat of the resumed sweep is the curve; the two fallbacks start the curve over – a stop, then the curve whole, since a RESUME whose acknowledgement was lost leaves the far end running and a repeat of its curve would carry it on – and are for saying so.
| asked | Whether a resume of the held sweep was asked. |
| held | Whether a hold is in force at the far end. |
| timed | Whether the phase of the hold is known on the host. |
| proto_minor | The IOmcu's protocol minor. Below 6 has no resume. |
| refused | Whether the RESUME just written was refused. |
refused, and SERVO_RESUME_WRITE otherwise. | uint16_t servo_page_slots_hz | ( | const servo_page_t * | p | ) |
The rate the slots take, for outputs_slot_rates() and the OUTPUTS and CHAN_CFG checks: the register with the standard servo ports as target, 0 with a programming port.
| p | The page state. |
| bool servo_page_step | ( | servo_page_t * | p, |
| outputs_t * | o, | ||
| uint32_t | now_ms ) |
One pass: stop a sweep the bank's surfaces are no longer armed for, one not written for OUT_DEFAULT_TIMEOUT_MS or one that has made its movements, and command every surface along a sweep that runs.
True while it runs.
| p | The page state. Nothing is done when NULL. |
| o | The outputs bank whose surfaces are commanded. |
| now_ms | Current time in milliseconds. |
p or o is NULL. | bool servo_page_target | ( | servo_page_t * | p, |
| outputs_t * | o, | ||
| uint8_t | first, | ||
| uint8_t | count ) |
Name the channels the sweep and the hold command: count channels of the bank from first, or with count 0 the standard servo ports (channels 0 to LINK_OUT_CHANNELS - 1), which is what a page starts with.
A programming port is such a range of 1 channel.
A change ends a running or held sweep as a SWEEP of 0 does: the surfaces it moved stay where their outputs are. It also returns the frame rate register to 0, so a change of target never raises a rate under pulses meant for a slower one (protocol 4.19). False, with nothing changed, for a range that runs off the bank.
| p | The page state. |
| o | The outputs bank, for the surfaces a running sweep stops on. |
| first | First channel of the target. |
| count | Number of channels; 0 selects the standard servo ports. |
p or o, or a range past OUT_MAX_CHANNELS. | uint8_t servo_page_write | ( | servo_page_t * | p, |
| uint8_t | off, | ||
| uint8_t | n, | ||
| const uint16_t * | in, | ||
| outputs_t * | o, | ||
| uint32_t | now_ms ) |
A write to the page, validated whole against the bank o before any of it is stored.
A stop holds each surface where its output has got to. Refused: off the page (BAD_RANGE); register 6 (READ_ONLY); a frame rate the target cannot take (BAD_VALUE): for the standard servo ports one outputs_servo_rate_check() refuses or one under which a bound PWM output would carry a pulse longer than its frame (outputs_pulse_check(), protocol 4.16); for a programming port one outside the PWM driver's 40 to 560Hz, one other than PROG_PORT_RATE_HZ for a port servo_page_ports() names as sharing its slice, or one whose frame is shorter than the endpoint of a port it names as pulsing (protocol 4.19). Refused too: a sweep sweep_cfg_valid() refuses, or a sweep started or changed by a write that does not carry all four of its registers, or a resume with no phase kept or with a curve that has changed since the hold (BAD_VALUE); a sweep, a hold or a resume while the bank is not armed for the surfaces, an arm for the throttle alone among them (NOT_ARMED).
| p | The page state, changed only when the write is taken. |
| off | First register, 0 to LINK_SV_COUNT - 1. |
| n | Number of registers to write. 0 is taken with no change. |
| in | The n new register values. |
| o | The outputs bank, judged and driven by the sweep and the hold. |
| now_ms | Current time in milliseconds, on the same clock as the passes. |
| uint32_t servo_phase_held | ( | servo_phase_t * | ph, |
| uint32_t | ack_ms ) |
A running sweep held at ack_ms: its phase is kept; returned.
| ph | The phase record. Nothing is changed when NULL. |
| ack_ms | Host time of the hold's acknowledgement, in milliseconds. |
ack_ms minus the start. 0 for NULL. | bool servo_phase_resumable | ( | const servo_phase_t * | ph | ) |
Whether a hold of a running sweep stands to be resumed.
| ph | The phase record. |
| bool servo_phase_resumed | ( | servo_phase_t * | ph, |
| uint32_t | ack_ms, | ||
| uint32_t * | start_ms ) |
A held sweep resumed at ack_ms: its phase 0 moves on by the hold, into start_ms.
False, and nothing changes, with no phase kept.
| ph | The phase record. Its kept phase is cleared on success. |
| ack_ms | Host time of the resume's acknowledgement, in milliseconds. |
| start_ms | Receives the new phase 0 on the host's clock. May be NULL. |
| void servo_phase_started | ( | servo_phase_t * | ph, |
| uint32_t | ack_ms ) |
A sweep started, from its beginning, when acknowledged at ack_ms.
Nothing is done when ph is NULL.
| ph | The phase record, set to the start and no kept phase. |
| ack_ms | Host time of the acknowledgement, in milliseconds. |
| void servo_phase_stopped | ( | servo_phase_t * | ph | ) |
The sweep stopped, or the far end restarted: nothing is held to resume.
Nothing is done when ph is NULL.
| ph | The phase record. Its kept phase is cleared. |