|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
KST servo programming protocol: a servo configuration as a text file. More...
#include <stdbool.h>#include <stddef.h>#include <stdint.h>#include "kst_limits.h"#include "kst_reg.h"Go to the source code of this file.
Data Structures | |
| struct | kst_file_t |
| A text as read. More... | |
| struct | kst_file_load_t |
| What loading a file into a servo does. More... | |
Macros | |
| #define | KST_FILE_FORMAT 1u |
| The format version kst_file_format() writes and kst_file_parse() reads. | |
| #define | KST_FILE_LINE_MAX 64u |
| Characters kst_file_format() puts in a line at most, the line end not counted. | |
| #define | KST_FILE_LINES_MAX ((unsigned)KST_F_COUNT + 8u) |
| Lines kst_file_format() writes at most: one per field, the header, the type, the register count, 4 register lines and the checksum. | |
| #define | KST_FILE_MAX ((size_t)KST_FILE_LINES_MAX * (KST_FILE_LINE_MAX + 2u)) |
| Bytes in a file at most: 3432. kst_file_parse() refuses a longer text. kst_file_format() writes fewer than 1024 bytes with this field table, so a buffer of this size holds every written file with either line end and leaves more than 2300 bytes for a person's comments. | |
Enumerations | |
| enum | kst_file_err_t { KST_FILE_OK = 0 , KST_FILE_ERR_ARG = 1 , KST_FILE_ERR_OVERSIZED = 2 , KST_FILE_ERR_NOT_KST = 3 , KST_FILE_ERR_VERSION = 4 , KST_FILE_ERR_NEWER = 5 , KST_FILE_ERR_TRUNCATED = 6 , KST_FILE_ERR_LINE_END = 7 , KST_FILE_ERR_MALFORMED = 8 , KST_FILE_ERR_REG_COUNT = 9 , KST_FILE_ERR_CHECKSUM = 10 , KST_FILE_ERR_TRAILING = 11 , KST_FILE_ERR_NAME = 12 , KST_FILE_ERR_DUPLICATE = 13 , KST_FILE_ERR_VALUE = 14 , KST_FILE_ERR_TYPE = 15 } |
| Why a text is refused. More... | |
| enum | kst_file_kind_t { KST_FILE_VERIFIED = 0 , KST_FILE_EDITED_TYPED = 1 , KST_FILE_EDITED_UNTYPED = 2 } |
| What a text is. More... | |
| enum | kst_file_verdict_t { KST_FILE_LOAD_OK = 0 , KST_FILE_LOAD_TYPE_MISMATCH = 1 , KST_FILE_LOAD_HARD_LIMIT = 2 , KST_FILE_LOAD_ARG = 3 } |
| Whether a file loads. More... | |
Functions | |
| size_t | kst_file_format (const kst_image_t *img, char *out, size_t out_size) |
Write the text of img into out. | |
| kst_file_err_t | kst_file_parse (const char *text, size_t len, kst_file_t *out, unsigned *line) |
Read len bytes of text. | |
| kst_file_verdict_t | kst_file_load (const kst_file_t *file, const kst_image_t *servo, const kst_image_t *backup, kst_file_load_t *out) |
| Hold a file against the image read from the connected servo. | |
KST servo programming protocol: a servo configuration as a text file.
Implements the programming protocol of KST and Chaservo servos. KST and Chaservo are names or trademarks of their respective owners; they are used here only to say which servos this module works with (README.md, "Legal notice and disclaimer").
kst_file_format() writes the 32 registers of a servo as text a person reads. kst_file_parse() reads such a text back, and reads a text a person wrote or changed. kst_file_load() holds what was read against the connected servo: its type, the access classes and the limits. All three work on buffers the caller holds. There is no file access, no heap and no stdio here.
The text kst_file_format() writes, format version 1:
line 1 "KST servo configuration, format 1" line 2 "Type: V6" or "Type: V8", the servo type as kst_type() gives it for the registers 27 lines one per named field of the field table, in table order: "<name> = <value>", the value as kst_field_display() gives it with its unit; a field no load writes carries " [not loaded]" 1 line "registers 32" 4 lines "00: xx xx xx xx xx xx xx xx", 8 registers each, the address of the first one in front, 2 upper-case hexadecimal digits per register last line "checksum xxxxxxxx", 8 upper-case hexadecimal digits
The characters are ASCII (American Standard Code for Information Interchange) 0x20 to 0x7E, a line holds at most KST_FILE_LINE_MAX of them, and every line, the last one included, ends with LF (line feed, 0x0A). kst_file_format() writes exactly this.
The checksum is CRC-32 (cyclic redundancy check, polynomial 0x04C11DB7 reflected, start 0xFFFFFFFF, final inversion: the one of IEEE 802.3) over every line before the checksum line, each with its line end counted as one LF.
A text is read as one of 3 kinds (kst_file_kind_t). A line whose first word is "checksum" decides between them.
With a checksum line the file is VERIFIED or refused. The 4 register lines are the image. The type line has to state the type of that image. The field lines are not interpreted: the checksum covers them. The file has LF on every line or CR LF (carriage return, 0x0D, then LF) on every line; because the checksum counts a line end as one LF, a transfer that converts every line end keeps the file valid. Both kinds in one file, a CR at any other place and a lower-case hexadecimal digit refuse it. Behind the checksum line, lines of spaces and tabs or of nothing pass and any other byte refuses the file. The checksum line is taken without its line end when it holds its 17 characters.
Without a checksum line the file is EDITED: a person's input.
Both kinds take the 3 bytes EF BB BF (the byte order mark of UTF-8, 8-bit Unicode Transformation Format) in front of the header; they are not part of the checksum.
The last line of an edited file may lack its line end when the line shows its own end: a unit, a "[...]", a comment, a type line, a register line. A text that ends in the digits of a number, in a name or inside the register block is refused as truncated, so a cut file never gives a shortened number. A file cut between two lines reads as an edited file with fewer lines; kst_file_load() states how many of the 27 fields it gives (named of fields).
SPDX-License-Identifier: MIT
| #define KST_FILE_LINE_MAX 64u |
Characters kst_file_format() puts in a line at most, the line end not counted.
A line of an edited file may be longer.
| enum kst_file_err_t |
Why a text is refused.
The numbers are stable.
| enum kst_file_kind_t |
What a text is.
| Enumerator | |
|---|---|
| KST_FILE_VERIFIED | the checksum fits: the registers are what kst_file_format() wrote |
| KST_FILE_EDITED_TYPED | no checksum; a register block or a type line states the servo type |
| KST_FILE_EDITED_UNTYPED | no checksum, no register block and no type line: the file states no servo type |
| enum kst_file_verdict_t |
Whether a file loads.
The numbers are stable.
| size_t kst_file_format | ( | const kst_image_t * | img, |
| char * | out, | ||
| size_t | out_size ) |
Write the text of img into out.
Returns the number of bytes written. No terminator is written. Returns 0, with out in an unspecified state, for a NULL argument and for an out_size the text does not fit; KST_FILE_MAX always fits.
Every image is written, also one that breaks the layout fingerprint or a limit: the file states what a servo holds.
| img | Image to write. |
| out | Buffer that receives the text. |
| out_size | Size of out, in bytes. |
| kst_file_verdict_t kst_file_load | ( | const kst_file_t * | file, |
| const kst_image_t * | servo, | ||
| const kst_image_t * | backup, | ||
| kst_file_load_t * | out ) |
Hold a file against the image read from the connected servo.
servo is the servo's image as read last. backup is the image the limits compare with, as the caller passes it to kst_limits_edit() for an edit made by hand; a caller without a separate backup passes servo.
skipped, and the load goes on: the protection block, Servo / Gyro Servo, Lock and the pairing value never deny a load. An edited file's register block gives the raw value of an editable field whose line reads as the block shows, and no other value.backup, target, no unlock set), the check an edit made by hand goes through. A broken hard rule refuses the whole file. Soft rules are returned.The caller passes the target of KST_FILE_LOAD_OK to kst_plan_edit() as it does with an edit made by hand; nothing here replaces that check.
Returns the verdict. out is untouched for KST_FILE_LOAD_ARG.
| file | The file as read. |
| servo | The servo image as read last. |
| backup | The image the limits compare with. |
| out | Receives the load result. |
| kst_file_err_t kst_file_parse | ( | const char * | text, |
| size_t | len, | ||
| kst_file_t * | out, | ||
| unsigned * | line ) |
Read len bytes of text.
out is written on KST_FILE_OK and on no other result. line, when not NULL, receives the number of the line the refusal is at, counted from 1, and 0 for a result that belongs to no line (KST_FILE_OK, KST_FILE_ERR_ARG, KST_FILE_ERR_OVERSIZED).
Nothing is checked against the fingerprint, an access class or a limit here; kst_file_load() does that against a servo.
| text | Text to read. |
| len | Length of text, in bytes. |
| out | Receives the file on KST_FILE_OK. |
| line | Receives the line of a refusal; may be NULL. |