|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The SERVO link page. More...
#include "servo_page.h"#include <stddef.h>#include <string.h>#include "link_msg.h"#include "out_pwm_map.h"#include "outputs_pages.h"#include "prog_port.h"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. | |
| static sweep_cfg_t | cfg_of (const uint16_t *r) |
| The sweep curve the page's registers describe. | |
| static bool | same_curve (const sweep_cfg_t *a, const sweep_cfg_t *b) |
| Whether two sweeps trace the same curve; the movement count is not the curve, and it applies to the next start. | |
| static uint8_t | target_first (const servo_page_t *p) |
| The channels the sweep and the hold command: the standard servo ports, or the range servo_page_target() named. | |
| static uint8_t | target_end (const servo_page_t *p) |
| One past the last channel the sweep and the hold command. | |
| static void | command_surfaces (const servo_page_t *p, outputs_t *o, uint16_t cmd, uint32_t now_ms) |
Every surface of the target commanded to cmd. | |
| static void | freeze_surfaces (const servo_page_t *p, outputs_t *o) |
| Every surface held where its output has got to. | |
| static bool | resumable (const servo_page_t *p, const uint16_t *next) |
| Whether a RESUME can carry on the sweep held now: a phase kept by a hold still in force and a page that still describes that sweep. | |
| static uint8_t | rate_check (const servo_page_t *p, const outputs_t *o, uint16_t hz) |
Whether the frame rate hz may be the target's. | |
| 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. | |
| 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. | |
| 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. | |
| 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. | |
| 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. | |
| 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. | |
| 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. | |
|
static |
The sweep curve the page's registers describe.
| r | The page registers, LINK_SV_COUNT of them. |
|
static |
Every surface of the target commanded to cmd.
| p | The page state, for the target range. |
| o | The outputs bank. Only channels with role OUT_ROLE_SURFACE change. |
| cmd | The command for each surface. |
| now_ms | Current time in milliseconds, passed to outputs_set(). |
|
static |
Every surface held where its output has got to.
The last command a sweep left would otherwise be slewed towards for as long again as the channel's own timeout, past the moment the sweep stopped. The channel's clock is left alone, so it rests when it would have.
| p | The page state, for the target range. |
| o | The outputs bank. Each surface's command becomes its actual value. |
|
static |
Whether the frame rate hz may be the target's.
The standard servo ports: every PWM slot whose first channel is a surface, judged against the slices it shares (outputs_servo_rate_check()) and against every PWM slot's endpoints at the rate it runs at, 0 sending the surfaces back to their own. A programming port: its own pin alone, which shares no slice with a slot; a pin that shares its slice with another port's stays at PROG_PORT_RATE_HZ, and a port whose pulse is on takes no rate its endpoints do not fit. 0 always fits: the port goes back to 50Hz, whose 19999us frame holds every endpoint the pages take.
| p | The page state, for the target and the port masks. |
| o | The outputs bank, for the slots and the channels' endpoints. |
| hz | The frame rate in Hz to judge. |
hz fits. Otherwise the refusal of outputs_servo_rate_check() or outputs_pulse_check() for the standard servo ports, or LINK_NACK_BAD_VALUE for a programming port whose range or endpoints do not fit hz.
|
static |
Whether a RESUME can carry on the sweep held now: a phase kept by a hold still in force and a page that still describes that sweep.
A curve changed while held is a new sweep, which starts only whole.
| p | The page state. |
| next | The page registers as the write would leave them. |
|
static |
Whether two sweeps trace the same curve; the movement count is not the curve, and it applies to the next start.
| a | The first sweep. |
| b | The second sweep. |
| 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. |
|
static |
One past the last channel the sweep and the hold command.
| p | The page state. |
|
static |
The channels the sweep and the hold command: the standard servo ports, or the range servo_page_target() named.
| p | The page state. |