rcbench
Servo and ESC test bench: panel, IOmcu and shared C
Loading...
Searching...
No Matches
esc_profile.h File Reference

ESC (electronic speed controller) programming profiles: how to enter an ESC's throttle-stick programming menu, how it sounds a number, and what the menu holds. More...

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

Go to the source code of this file.

Data Structures

struct  esc_model_t
 One model the profile lists, with its battery and input limits. More...
struct  esc_value_t
 One value an item can take, with the moves that program it. More...
struct  esc_item_t
 One menu item: its name, sounded number and values. More...
struct  esc_manual_t
 A step a person does at the ESC besides the throttle and the power: fit or pull a jumper, press a button. More...
struct  esc_profile_t
 One ESC programming profile: its family, menu and steps. More...

Macros

#define ESC_PROFILE_SCHEMA   1u
 The schema version of the JSON this reads.
#define ESC_PROFILE_MAX_BYTES   65536u
 The largest file the parser takes, in bytes.
#define ESC_PROFILE_MAX_OVERRIDES   32u
 How many profiles the card may add or replace.
#define ESC_MAKER_MODELS_MAX   512u
 The most models one maker may list across its profiles, built in and from the card: what the ESC STICK list holds for one maker.
#define ESC_AFTER_MAX   4u
 The most stick moves a value asks for after its selection.
#define ESC_MANUAL_ACTION_MAX   120u
 The longest manual step's text, in bytes: two lines of a pop-up.
#define ESC_MANUAL_MAX   4u
 The most manual steps one profile holds.

Enumerations

enum  esc_scheme_t {
  ESC_SCHEME_COUNT = 0 , ESC_SCHEME_SHORT_LONG , ESC_SCHEME_MELODY_GROUPS , ESC_SCHEME_YES_NO ,
  ESC_SCHEME_STICK_POSITION , ESC_SCHEME_OTHER
}
 How the menu as a whole is driven. More...
enum  esc_encoding_t { ESC_ENC_COUNT = 0 , ESC_ENC_SHORT_LONG , ESC_ENC_MELODY , ESC_ENC_YES_NO }
 How one number is sounded.
enum  esc_auto_t { ESC_AUTO_FULL = 0 , ESC_AUTO_ASSISTED , ESC_AUTO_NONE }
 Who can run the sequence. More...
enum  esc_throttle_t { ESC_THR_MIN = 0 , ESC_THR_MID , ESC_THR_MAX , ESC_THR_NONE }
 Throttle stick position that a step uses. More...
enum  esc_announce_t { ESC_ANNOUNCE_ITEM = 0 , ESC_ANNOUNCE_VALUE , ESC_ANNOUNCE_ITEM_THEN_VALUE }
 What the ESC announces before a selection.
enum  esc_manual_when_t {
  ESC_MANUAL_BEFORE_POWER = 0 , ESC_MANUAL_AT_POWER_UP , ESC_MANUAL_BEFORE_MENU , ESC_MANUAL_DURING_MENU ,
  ESC_MANUAL_BEFORE_POWER_OFF , ESC_MANUAL_AFTER_PROGRAMMING
}
 When an operator's step at the ESC is due, in the order of a run. More...

Functions

bool esc_profile_parse (const char *json, size_t len, esc_profile_t *out, void **block, char *err, size_t err_size)
 Parse one profile file.
bool esc_profile_file_is (const char *file_name, const char *id)
 Whether file_name is the name the profile id belongs in: the id with ".json" after it, letters compared without regard to case, since a card written on another computer may change them.
bool esc_profiles_override (const esc_profile_t *p, void *block)
 Add a parsed profile from the card.
bool esc_profiles_override_why (const esc_profile_t *p, void *block, const char **why)
 esc_profiles_override(), with why it refused in why (a static string; may be NULL): "no profile", "more than 32 on the card", or "its maker would list more than 512 models" – the maker's models across every profile, built in and from the card, with this one in place of any it replaces, makers compared with the letters A to Z folded.
bool esc_brand_same (const char *a, const char *b)
 Whether a and b name one maker: the letters A to Z folded, every other byte itself, as the list groups them.
void esc_profiles_clear_overrides (void)
 Drop every card profile; the built-in ones remain.
size_t esc_profiles_override_count (void)
 Card profiles held, for a status line.
size_t esc_profiles_count (void)
 Every profile the bench offers: the built-in ones with card files in their place, then card profiles with new ids.
const esc_profile_t * esc_profiles_at (size_t i)
 The profile at index i of the list the bench offers.
const esc_profile_t * esc_profiles_find (const char *id)
 NULL when no profile has this id.
bool esc_profiles_is_override (const esc_profile_t *p)
 Whether the profile at p came from the card.
bool esc_text_matches (const char *text, const char *pattern)
 Whether pattern is found in text.
bool esc_profile_matches (const esc_profile_t *p, const char *pattern)
 Whether pattern (as esc_text_matches()) is found in the profile's manufacturer and name read as one text, "brand family", or in its manufacturer and one of its models' names, "brand model": a family such as "JAZZ / MINIJAZZ" names its sizes only in its models ("JAZZ 55 LV").
bool esc_model_matches (const esc_profile_t *p, unsigned model, const char *pattern)
 Whether pattern finds model model of p: in the maker and the family read as one text, which every model of the family shares, or in the maker and the model's own name, as esc_profile_matches() reads them.
bool esc_item_applies (const esc_profile_t *p, unsigned item, int model)
 Whether item item of p is on model model: an item without applies_to is on every model; one with it only on the models it names.
unsigned esc_profile_manual_count (const esc_profile_t *p, esc_manual_when_t when)
 How many of the profile's manual steps are due at when.

Variables

const esc_profile_t esc_profiles_builtin []
 The profiles compiled in, sorted by id.
const size_t esc_profiles_builtin_count

Detailed Description

ESC (electronic speed controller) programming profiles: how to enter an ESC's throttle-stick programming menu, how it sounds a number, and what the menu holds.

One profile describes one family: a set of models that share one entry gesture and one menu. The profiles of record are the JSON files in shared/esc/profiles/, described in docs/EscProfiles.md. tools/gen_esc_profiles.py compiles them into esc_profiles_gen.c, so every panel carries them without a card. A file in BENCH/ESC/CONF on the SD card (CARD_ESC_CONF, card_tree.h) is parsed by esc_profile_parse() and replaces the built-in profile of the same id, or adds one when the id is new.

Boundaries of this module:

  • No file access. The caller reads the card and hands over bytes, so the host suite feeds the parser truncated and hostile input with no card at all.
  • No beep timing. The manuals give none; every time field is 0 until a bench recording supplies one, and 0 means "not known", never "none".
  • Text the bench does not act on (sources, notes, unknowns, the scheme description) stays in the JSON. The firmware carries names, numbers and the operator steps a person has to perform.

SPDX-License-Identifier: MIT

Macro Definition Documentation

◆ ESC_MAKER_MODELS_MAX

#define ESC_MAKER_MODELS_MAX   512u

The most models one maker may list across its profiles, built in and from the card: what the ESC STICK list holds for one maker.

A card profile that would take its maker past it is refused at load.

◆ ESC_PROFILE_MAX_BYTES

#define ESC_PROFILE_MAX_BYTES   65536u

The largest file the parser takes, in bytes.

The largest profile of record is about 21KiB.

Enumeration Type Documentation

◆ esc_auto_t

enum esc_auto_t

Who can run the sequence.

Enumerator
ESC_AUTO_FULL 

throttle signal and power alone

ESC_AUTO_ASSISTED 

a person sets a jumper, presses a button or reads an LED

ESC_AUTO_NONE 

the manual gives no usable procedure

◆ esc_manual_when_t

When an operator's step at the ESC is due, in the order of a run.

Enumerator
ESC_MANUAL_BEFORE_POWER 

before the supply comes on

ESC_MANUAL_AT_POWER_UP 

begun before, held while it comes on

ESC_MANUAL_BEFORE_MENU 

powered, after the entry, before the menu sounds

ESC_MANUAL_DURING_MENU 

while the menu sounds

ESC_MANUAL_BEFORE_POWER_OFF 

powered, after the value is stored, before the supply goes off: hands off, the operator watches the ESC

ESC_MANUAL_AFTER_PROGRAMMING 

once the run is over

◆ esc_scheme_t

How the menu as a whole is driven.

Enumerator
ESC_SCHEME_COUNT 

N beeps say item or value N

ESC_SCHEME_SHORT_LONG 

long beeps count several short ones

ESC_SCHEME_MELODY_GROUPS 

a melody per group, repeated

ESC_SCHEME_YES_NO 

each value asked, full = yes, low = no

ESC_SCHEME_STICK_POSITION 

the stick's position is the value

◆ esc_throttle_t

Throttle stick position that a step uses.

Enumerator
ESC_THR_NONE 

no throttle move does this

Function Documentation

◆ esc_brand_same()

bool esc_brand_same ( const char * a,
const char * b )

Whether a and b name one maker: the letters A to Z folded, every other byte itself, as the list groups them.

Parameters
aA maker name, or NULL.
bA maker name, or NULL.
Returns
true when the names are equal with A to Z folded. Two NULL names are equal; a NULL name and a name are not.

◆ esc_item_applies()

bool esc_item_applies ( const esc_profile_t * p,
unsigned item,
int model )

Whether item item of p is on model model: an item without applies_to is on every model; one with it only on the models it names.

For -1 – the family, no model picked – only an item on every model, as the one item the ESC is sure to have.

Parameters
pThe profile.
itemIndex into the profile's items.
modelIndex into the profile's models, or -1 for none picked.
Returns
true when the item applies

◆ esc_model_matches()

bool esc_model_matches ( const esc_profile_t * p,
unsigned model,
const char * pattern )

Whether pattern finds model model of p: in the maker and the family read as one text, which every model of the family shares, or in the maker and the model's own name, as esc_profile_matches() reads them.

Parameters
pThe profile.
modelIndex into the profile's models.
patternThe pattern, with "*" as a wildcard.
Returns
true when the pattern finds the model

◆ esc_profile_file_is()

bool esc_profile_file_is ( const char * file_name,
const char * id )

Whether file_name is the name the profile id belongs in: the id with ".json" after it, letters compared without regard to case, since a card written on another computer may change them.

A card file whose name and id differ is refused, as tools/gen_esc_profiles.py refuses one in the repository: a renamed copy would otherwise replace a profile its name does not mention.

Parameters
file_nameThe file name as found on the card.
idThe profile id to compare against.
Returns
true when the names match

◆ esc_profile_manual_count()

unsigned esc_profile_manual_count ( const esc_profile_t * p,
esc_manual_when_t when )

How many of the profile's manual steps are due at when.

Parameters
pThe profile.
whenThe point in a run to count for.
Returns
The number of manual steps due at when.

◆ esc_profile_matches()

bool esc_profile_matches ( const esc_profile_t * p,
const char * pattern )

Whether pattern (as esc_text_matches()) is found in the profile's manufacturer and name read as one text, "brand family", or in its manufacturer and one of its models' names, "brand model": a family such as "JAZZ / MINIJAZZ" names its sizes only in its models ("JAZZ 55 LV").

Parameters
pThe profile to search.
patternThe pattern, with "*" as a wildcard.
Returns
true when the pattern is found

◆ esc_profile_parse()

bool esc_profile_parse ( const char * json,
size_t len,
esc_profile_t * out,
void ** block,
char * err,
size_t err_size )

Parse one profile file.

Everything the profile points at – strings, models, items, values – is placed in one block from malloc(); *block receives it and free(*block) releases the lot. On failure nothing is allocated and err (when not NULL) holds a line for the operator, e.g. "items[2].values: empty".

Parameters
jsonThe file's bytes.
lenLength of json in bytes.
outReceives the parsed profile.
blockReceives the malloc() block that holds the profile.
errMessage for the operator, or NULL.
err_sizeSize of err in bytes.
Returns
true when out is a usable profile

◆ esc_profiles_at()

const esc_profile_t * esc_profiles_at ( size_t i)

The profile at index i of the list the bench offers.

Parameters
iIndex into the list, from 0.
Returns
The profile at i, or NULL when i is past the last profile.

◆ esc_profiles_count()

size_t esc_profiles_count ( void )

Every profile the bench offers: the built-in ones with card files in their place, then card profiles with new ids.

Returns
The number of profiles the bench offers.

◆ esc_profiles_find()

const esc_profile_t * esc_profiles_find ( const char * id)

NULL when no profile has this id.

Parameters
idThe profile id.
Returns
The card profile with this id if there is one, else the built-in profile, or NULL when id is NULL or no profile has it.

◆ esc_profiles_is_override()

bool esc_profiles_is_override ( const esc_profile_t * p)

Whether the profile at p came from the card.

Parameters
pThe profile.
Returns
true when p is one of the card profiles.

◆ esc_profiles_override()

bool esc_profiles_override ( const esc_profile_t * p,
void * block )

Add a parsed profile from the card.

Ownership of block passes to the registry. A second file with the same id replaces the first.

Parameters
pThe parsed profile.
blockThe malloc() block that holds p.
Returns
false when the registry is full; block is freed then too

◆ esc_profiles_override_count()

size_t esc_profiles_override_count ( void )

Card profiles held, for a status line.

Returns
The number of card profiles held.

◆ esc_profiles_override_why()

bool esc_profiles_override_why ( const esc_profile_t * p,
void * block,
const char ** why )

esc_profiles_override(), with why it refused in why (a static string; may be NULL): "no profile", "more than 32 on the card", or "its maker would list more than 512 models" – the maker's models across every profile, built in and from the card, with this one in place of any it replaces, makers compared with the letters A to Z folded.

Parameters
pThe parsed profile.
blockThe malloc() block that holds p; freed when the profile is refused.
whyReceives a static reason string when refused, or NULL.
Returns
true when p is registered, false when it is refused.

◆ esc_text_matches()

bool esc_text_matches ( const char * text,
const char * pattern )

Whether pattern is found in text.

Letters A to Z match without regard to case; every other byte matches itself, so "Ü" does not match "ü". "*" stands for any run of characters, none included, and the pattern is found anywhere in the text: "sky*v2" is in "Skywalker V2". An empty pattern, or one of "*" only, is found in every text. A NULL pattern counts as empty and a NULL text as "".

Parameters
textThe text to search.
patternThe pattern, with "*" as a wildcard.
Returns
true when the pattern is found