|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The KST programming protocol on a programming port, and its link page (0x32). More...
#include <stdbool.h>#include <stdint.h>#include "kst_session.h"#include "link_pages.h"#include "outputs.h"#include "supply_page.h"Go to the source code of this file.
Data Structures | |
| struct | kst_port_hw_t |
| What the port needs from the hardware. More... | |
| struct | kst_port_t |
| The state of one KST port: the hardware, the session, the staged registers and the running or last operation. More... | |
Macros | |
| #define | KST_PORT_STOP_MS 50u |
| The port renders no pulse this long before the generator gives up the pin: 2 frames at 40Hz, the lowest PWM rate. | |
| #define | KST_PORT_LOW_MS 100u |
| The driver holds the pin low this long before the session starts. | |
| #define | KST_PORT_RAIL_OFF_MS 2000u |
| The servo's supply stays off this long, counted from the read that shows it off. | |
| #define | KST_PORT_RAIL_WAIT_MS 1000u |
| And the servo has this long to start, counted from the read that shows the supply on. The owner's value; not measured. | |
| #define | KST_PORT_SUPPLY_MS 3000u |
| The PD mini has this long to read as asked after a switch. | |
| #define | KST_PORT_SUPPLY_MAX_MV 8400u |
| The highest supply voltage ENTER takes: the highest servo rail of the IO board (hardware/docs/IOBoard.md). | |
| #define | KST_PORT_SUPPLY_MIN_MV 4800u |
| The lowest supply voltage a session runs at: an ENTER whose voltage, or the lower voltage of an output that is on, is under it is refused with LINK_KST_REF_SUPPLY_LOW. | |
Functions | |
| bool | kst_port_init (kst_port_t *p, const kst_port_hw_t *hw) |
| Prepare a port in LINK_KST_PWM. | |
| uint8_t | kst_port_write (kst_port_t *p, uint8_t off, uint8_t n, const uint16_t *in, uint32_t now_ms) |
| A write of the page: 0, or the LINK_NACK_* reason with nothing changed. | |
| void | kst_port_read (const kst_port_t *p, uint8_t off, uint8_t n, uint16_t *out) |
| A read of the page, LINK_KS_*. | |
| void | kst_port_step (kst_port_t *p, bool safe, bool stop, uint32_t now_ms) |
| One pass. | |
| link_kst_state_t | kst_port_state (const kst_port_t *p) |
| Where the port is. | |
| uint8_t | kst_port_quiet_mask (const kst_port_t *p) |
| Bit n: programming port n renders no PWM pulse. | |
| bool | kst_port_frame_out (const kst_port_t *p) |
| An operation of the session runs: a frame may be on the wire. | |
| void | kst_port_bench_armed (kst_port_t *p, bool armed) |
| Whether the bank is armed. | |
| void | kst_port_other_mask (kst_port_t *p, uint8_t mask) |
| Bit n: the HITEC page holds programming port n (hitec_port_quiet_mask()). | |
| uint8_t | kst_port_pin_mask (const kst_port_t *p) |
| Bit n: programming port n's pin is the wire driver's, not the PWM generator's. | |
The KST programming protocol on a programming port, and its link page (0x32).
Whether a KST or Chaservo servo in programming mode follows PWM (pulse-width modulation) pulses is not measured; the port is built for one that does. The port takes the pin of one programming port (prog_port.h) from the PWM generator, hands it to the wire driver and runs the session of protocols/kst on it. A port is in PWM or in PROGRAMMING, never both. A port the HITEC page holds (hitec_port.h) takes no ENTER and no REBOOT from PWM: both are refused with LINK_KST_REF_BUSY. A standard servo port is no programming port: a command that names an output channel is refused.
The servo's supply is the PD mini of the SUPPLY page, reached through kst_port_hw_t.supply. With no PD mini answering the port touches no supply and the user switches the servo's power.
The way out of PWM, started by the operation ENTER:
STOPPING KST_PORT_STOP_MS: the port renders no pulse, so a pulse that runs ends and no other starts. LOW the generator gives up the pin and the driver holds it low for KST_PORT_LOW_MS at least. The supply is set here:
The way back:
A read that does not come within KST_PORT_SUPPLY_MS ends the cycle with LINK_KST_RESULT_SUPPLY. Not read off: a port that was in PROGRAMMING is there again with LINK_KS_F_IN_MODE kept, because the servo may have had power throughout. Not read on: the supply is asked off and the port is in PWM.
The supply ends off whenever nobody is there to switch it off. The SUPPLY page switches the PD mini off when the heartbeat is lost or the link is silent. A port in PROGRAMMING that finds the supply it started under off or asked off (by that, by the panel, by the PD mini's own protection) ends the operation, keeps the supply off for KST_PORT_RAIL_OFF_MS and returns to PWM with LINK_KS_F_IN_MODE clear and the result KST_SES_ERR_ABORTED: a servo without power is in no mode. In RAIL_OFF the supply is switched on again only while the heartbeat is trusted; in RAIL_WAIT a supply found asked off ends the cycle the same way. The operation ABORT ends a cycle off as well: in RAIL_OFF nothing is switched on afterwards, in RAIL_WAIT the supply is switched off.
KST_PORT_RAIL_OFF_MS and KST_PORT_RAIL_WAIT_MS are the owner's values. The time a KST servo needs without power to leave programming mode, the time it needs to start, and the supply voltage it accepts in programming mode are not measured.
While the port is out of PWM the caller keeps the pulse off the pin: kst_port_quiet_mask() names the programming port that renders none and kst_port_pin_mask() the one whose pin is the wire driver's. The servo tester's commands end at the port's channel, so none reaches the pin.
A stop is the heartbeat lost, the link silent or the bank disarmed. On a stop the running operation is aborted: a frame on the wire is finished, which takes at most 12ms, and no other starts. The pin is low or an input afterwards. LINK_KS_F_MUST_READ is set, and until a read of all registers has succeeded the port takes ENTER, READ_ALL, ABORT, POWER_CYCLED and REBOOT only. The operation ABORT does the same to an operation of the session. While the heartbeat is not trusted or the link is silent no frame starts and every operation but ABORT and POWER_CYCLED is refused. A disarm alone leaves the supply as it is.
A write to the servo (WRITE, RESTORE, RELEASE) is refused unless the command carries LINK_KST_WRITE_KEY. The plan is built here, from the image this session read and the staged registers, with the planner and the limits of protocols/kst; the panel sends no register write.
The session plans a WRITE and a RESTORE itself and runs its own plan (kst_session_edit(), kst_session_restore()). The command's frame checks the request and prepares the job: a target the planner refuses without a search (register 0x00, pairing, a hard rule) is refused there, with LINK_KST_REF_PLAN_R00, _PAIRING or _RULES, and no operation starts. Every other request starts the operation, and each pass then does one slice of the planner, KST_PLAN_SLICE_UNITS (100) to 109 units of work, and nothing else of the session. While it plans, LINK_KS_F_BUSY is set, LINK_KS_RESULT's low byte is LINK_KST_RESULT_PLANNING and no frame goes out. The planning ends after KST_PLAN_WORK_CAP (216,000) units at most, 2,161 passes:
A slice is 892us or less and the frame's part 64us on a Cortex-M33 at 150MHz, computed from the instructions executed (docs/Performance.md); not measured on hardware. A RELEASE has one write at most and no search.
A stop, an ABORT, a POWER_CYCLED, a REBOOT and a supply found off end an operation that plans as they end one that sends: at the next pass, with KST_SES_ERR_ABORTED, nothing sent and the session not locked. The rest is what the paragraphs above say for PROGRAMMING, LINK_KS_F_MUST_READ included. A command while it plans is refused with LINK_KST_REF_BUSY.
Commands: registers 0 to 3 of a write, one frame. SEQ is LINK_KS_SEQ plus 1; the frame just taken, sent again, is acknowledged and does nothing; any other SEQ is refused with LINK_NACK_BAD_VALUE. A command that is taken is acknowledged, and what became of it is on the page: LINK_KS_RESULT's high byte says why it started nothing, or 0.
Nothing here is kept over a restart of the IOmcu: after one the port is in PWM with LINK_KS_F_IN_MODE clear, whatever mode the servo is in, and the SUPPLY page starts with the PD mini asked off.
Pure logic: the pin, the driver and the supply are behind kst_port_hw_t.
SPDX-License-Identifier: MIT
| #define KST_PORT_RAIL_OFF_MS 2000u |
The servo's supply stays off this long, counted from the read that shows it off.
The owner's value; what a KST servo needs is not measured.
| #define KST_PORT_SUPPLY_MAX_MV 8400u |
The highest supply voltage ENTER takes: the highest servo rail of the IO board (hardware/docs/IOBoard.md).
What a KST servo accepts in programming mode is not measured.
| #define KST_PORT_SUPPLY_MIN_MV 4800u |
The lowest supply voltage a session runs at: an ENTER whose voltage, or the lower voltage of an output that is on, is under it is refused with LINK_KST_REF_SUPPLY_LOW.
The voltage a KST or Chaservo servo needs to store a register is not measured.
| void kst_port_bench_armed | ( | kst_port_t * | p, |
| bool | armed ) |
Whether the bank is armed.
An ENTER is refused with LINK_KST_REF_BUSY while it is; the caller arms no output while kst_port_quiet_mask() is not 0.
| p | The port, or NULL; a NULL p is ignored. |
| armed | true when the bank is armed. |
| bool kst_port_frame_out | ( | const kst_port_t * | p | ) |
An operation of the session runs: a frame may be on the wire.
False from the pass in which an operation, or its cut, has ended.
| p | The port, or NULL. |
| bool kst_port_init | ( | kst_port_t * | p, |
| const kst_port_hw_t * | hw ) |
Prepare a port in LINK_KST_PWM.
False when hw names no port, lacks a function other than the supply's two, or has one of those two.
| p | The port to prepare. |
| hw | The hardware hooks, copied into the port. |
| void kst_port_other_mask | ( | kst_port_t * | p, |
| uint8_t | mask ) |
Bit n: the HITEC page holds programming port n (hitec_port_quiet_mask()).
An ENTER on it, and a REBOOT taken in PWM, are refused with LINK_KST_REF_BUSY.
| p | The port, or NULL; a NULL p is ignored. |
| mask | Bit n: the HITEC page holds programming port n. |
| uint8_t kst_port_pin_mask | ( | const kst_port_t * | p | ) |
Bit n: programming port n's pin is the wire driver's, not the PWM generator's.
The held port from LINK_KST_LOW until it is back in LINK_KST_PWM; never for a REBOOT taken in PWM.
| p | The port, or NULL. |
| uint8_t kst_port_quiet_mask | ( | const kst_port_t * | p | ) |
Bit n: programming port n renders no PWM pulse.
The held port in every state but LINK_KST_PWM.
| p | The port, or NULL. |
| void kst_port_read | ( | const kst_port_t * | p, |
| uint8_t | off, | ||
| uint8_t | n, | ||
| uint16_t * | out ) |
A read of the page, LINK_KS_*.
| p | The port. |
| 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 past LINK_KS_COUNT. |
| link_kst_state_t kst_port_state | ( | const kst_port_t * | p | ) |
Where the port is.
| p | The port, or NULL. |
| void kst_port_step | ( | kst_port_t * | p, |
| bool | safe, | ||
| bool | stop, | ||
| uint32_t | now_ms ) |
One pass.
safe: the heartbeat is trusted and the link is not silent. stop: the bank was switched off or disarmed since the last pass. Steps the session and the port's timers; a pass every 1ms or faster keeps the session's pacing. A pass does one slice of planning at most and never a whole search.
| p | The port. |
| safe | true when the heartbeat is trusted and the link is not silent. |
| stop | true when the bank was switched off or disarmed since the last pass. |
| now_ms | Current time in milliseconds. |
| uint8_t kst_port_write | ( | kst_port_t * | p, |
| uint8_t | off, | ||
| uint8_t | n, | ||
| const uint16_t * | in, | ||
| uint32_t | now_ms ) |
A write of the page: 0, or the LINK_NACK_* reason with nothing changed.
A window that starts in registers 0 to 3 is a command and has to be exactly those 4. Registers 4 to 28 are taken in any windows; 29 and up are LINK_NACK_READ_ONLY.
| p | The port. |
| off | First register of the window. |
| n | Number of registers in the window. |
| in | The n register values to write. |
| now_ms | Current time in milliseconds. |