|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
Hitec session: entry, reads, write plans and leave, handed out as steps. More...
Macros | |
| #define | C_FIRST_P1 0x00u |
| The first command's first byte, as the HPP-21 Plus sends it. | |
| #define | C_FIRST_P2 0x00u |
| The first command's second byte, as the HPP-21 Plus sends it. | |
| #define | SET_BITS (HITEC_SES_SET_BYTES * 8u) |
| Bits of an address set. | |
Enumerations | |
| enum | { OP_NONE = 0 , OP_ENTER , OP_READ , OP_WRITE , OP_LEAVE } |
| Operation the session runs. | |
| enum | { PH_C_POWER = 0 , PH_C_NEXT , PH_C_FIRST , PH_D_POWER , PH_READ , PH_WRITE , PH_LEAVE } |
| The step an operation is at. | |
Functions | |
| bool | hitec_ses_in_set (const uint8_t *set, uint8_t addr) |
True when address addr is in the set set. | |
| static void | set_add (uint8_t *set, uint8_t addr) |
Put addr into set. | |
| static void | set_drop (uint8_t *set, uint8_t addr) |
Take addr out of set. | |
| static bool | set_first (const uint8_t *set, uint8_t *out) |
The lowest address in set. | |
| static uint16_t | set_count (const uint8_t *set) |
Addresses in set. | |
| static void | set_full_read (uint8_t series, uint8_t *set) |
Put the series' full read into set. | |
| static uint32_t | ticks (const hitec_session_t *s, uint32_t ms) |
ms in ticks of the session's clock. | |
| static void | gap_from (hitec_session_t *s, uint32_t now, uint32_t ms) |
Start the gap of ms before the next step, from now. | |
| static uint32_t | series_gap (const hitec_session_t *s) |
| The gap after a transaction of the session's series. | |
| static uint32_t | step_gap (const hitec_session_t *s) |
| The wait the step that is out asks for once its result comes, whether it ran, was cut or was lost. | |
| static bool | read_back (const hitec_session_t *s, uint8_t addr) |
True when the read-back of the running write has read addr. | |
| static void | forget_unsure (hitec_session_t *s) |
| After a write that failed: mark every address the servo may have changed and the read-back has not read as not known. | |
| static hitec_ses_t | finish (hitec_session_t *s, hitec_ses_t res) |
End the operation with res; an abort asked for ends it with HITEC_SES_ERR_ABORTED. A write that ends with an error after a step was handed out and its result fed forgets what the servo may have changed. | |
| static void | begin (hitec_session_t *s, uint8_t op, uint8_t phase) |
Begin operation op at phase. | |
| static void | begin_read (hitec_session_t *s) |
| Go to a read of the addresses in todo. | |
| static hitec_ses_t | may_start (const hitec_session_t *s, bool in_mode) |
| The common refusals of an operation. | |
| bool | hitec_session_init (hitec_session_t *s, uint8_t series, uint8_t clock) |
| Prepare a session for one series. | |
| hitec_ses_t | hitec_session_enter (hitec_session_t *s, bool power, uint16_t off_ms) |
| Enter programming mode. | |
| hitec_ses_t | hitec_session_read_all (hitec_session_t *s) |
| Read the series' full set: hitec_d_read_list() or hitec_c_read_ranges(). | |
| hitec_ses_t | hitec_session_read_set (hitec_session_t *s, const uint8_t *addrs, uint16_t n) |
Read n addresses into the image, which keeps the rest. | |
| static bool | plan_fits (const hitec_session_t *s, const hitec_plan_t *plan) |
True when every step of plan is one the session runs on its series. | |
| static hitec_ses_t | start_plan (hitec_session_t *s, bool compare) |
Start the plan in s->plan; the read-back compares with target when compare. | |
| hitec_ses_t | hitec_session_write (hitec_session_t *s, const hitec_image_t *target) |
Write the servo from the image to target, then read it back. | |
| hitec_ses_t | hitec_session_run_plan (hitec_session_t *s, const hitec_plan_t *plan, const hitec_image_t *expect) |
| Run a plan the caller built, such as hitec_d_factory_plan(), then read back as hitec_session_write() does. | |
| hitec_ses_t | hitec_session_leave (hitec_session_t *s) |
| Leave programming mode. | |
| bool | hitec_session_abort (hitec_session_t *s) |
| End the running operation with HITEC_SES_ERR_ABORTED. | |
| hitec_ses_t | hitec_session_result (const hitec_session_t *s) |
| The running operation's state. | |
| static void | power_step (const hitec_session_t *s, hitec_ses_step_t *st, uint32_t window_us, bool answer) |
A POWER step whose LISTEN waits window_us. | |
| static void | build (hitec_session_t *s) |
| Build the step of the operation's phase into s->step. | |
| hitec_ses_kind_t | hitec_session_next (hitec_session_t *s, uint32_t now, hitec_ses_step_t *out) |
The step to run at now. | |
| static bool | compare (hitec_session_t *s) |
| True when the image holds what target holds at every address the read-back checks; diff names the others. | |
| static hitec_ses_t | fail (hitec_session_t *s, uint8_t rx) |
| The end of a failed transaction with no tries left, or with none at all. | |
| static hitec_ses_t | read_took (hitec_session_t *s, uint16_t value) |
The read of s->addr took value: store it, then the next address or the operation's end. The gap is the one feed started. | |
| static hitec_ses_t | write_took (hitec_session_t *s, uint32_t now) |
| The write of plan.step[step_index] took: count it, start its wait, then the next write or the read-back. | |
| static hitec_ses_t | decoded (hitec_session_t *s, uint32_t now, uint8_t rx, uint16_t value) |
A decoded transaction ended with rx. | |
| hitec_ses_t | hitec_session_feed (hitec_session_t *s, uint32_t now, const hitec_ses_result_t *r) |
| Take the result of the step that is out. | |
Hitec session: entry, reads, write plans and leave, handed out as steps.
SPDX-License-Identifier: MIT
|
static |
Begin operation op at phase.
| s | Session. |
| op | Operation. |
| phase | Its first step. |
|
static |
Go to a read of the addresses in todo.
| s | Session. |
|
static |
Build the step of the operation's phase into s->step.
| s | Session. |
|
static |
True when the image holds what target holds at every address the read-back checks; diff names the others.
| s | Session. |
|
static |
A decoded transaction ended with rx.
| s | Session. |
| now | The clock. |
| rx | hitec_rx_t. |
| value | The decoded value. |
|
static |
The end of a failed transaction with no tries left, or with none at all.
| s | Session. |
| rx | The last try's hitec_rx_t. |
|
static |
End the operation with res; an abort asked for ends it with HITEC_SES_ERR_ABORTED. A write that ends with an error after a step was handed out and its result fed forgets what the servo may have changed.
| s | Session. |
| res | Result. |
|
static |
After a write that failed: mark every address the servo may have changed and the read-back has not read as not known.
D series: every register of the full read and every register the plan names; a save, a reboot or a factory reset may change any of them. Classic: the cell of the step that ran with no + +, and the balance.
| s | Session. |
|
static |
Start the gap of ms before the next step, from now.
| s | Session. |
| now | The clock. |
| ms | Gap, ms; 0 for none. |
| bool hitec_ses_in_set | ( | const uint8_t * | set, |
| uint8_t | addr ) |
True when address addr is in the set set.
| set | HITEC_SES_SET_BYTES bytes, bit a % 8 of byte a / 8. |
| addr | Address. |
| bool hitec_session_abort | ( | hitec_session_t * | s | ) |
End the running operation with HITEC_SES_ERR_ABORTED.
With no step out it ends at once. With a step out it ends when that step's result comes: the caller cuts the step and feeds its result, which the session stores as far as it went. Until then hitec_session_next() gives the same step.
| s | Session. |
| hitec_ses_t hitec_session_enter | ( | hitec_session_t * | s, |
| bool | power, | ||
| uint16_t | off_ms ) |
Enter programming mode.
Classic: POWER (off off_ms, on, a LISTEN of HITEC_SES_C_ENTRY_WINDOW_US that answers the servo's + with +), a LISTEN of HITEC_SES_C_NEXT_WINDOW_US for the servo's next +, then the first command 67 00 00 99, whose reply's value is the version. A listen that gets no + ends the entry; the first command has HITEC_SES_TRIES tries. Classic entry always cycles the supply.
D series: with power, POWER (off off_ms, on, a LISTEN of HITEC_SES_POWER_WINDOW_US that waits for nothing) and HITEC_SES_D_ENTRY_WAIT_MS; without it, on the supply as it is. Then a read of register 0x00, the model, with HITEC_SES_TRIES tries.
The image starts empty and holds the version or the model. The off time is kept for the leave.
| s | Session. |
| power | D series: cycle the supply first; classic: ignored. |
| off_ms | Supply off time, 0 to HITEC_SES_OFF_MS_MAX. |
| hitec_ses_t hitec_session_feed | ( | hitec_session_t * | s, |
| uint32_t | now, | ||
| const hitec_ses_result_t * | r ) |
Take the result of the step that is out.
CUT ends the operation with HITEC_SES_ERR_CUT, FAILED with HITEC_SES_ERR_LINK. A step with a decoder: HITEC_RX_OK goes on; HITEC_RX_ERR_ARG ends it with HITEC_SES_ERR_STEP; HITEC_RX_ERR_ABORTED with HITEC_SES_ERR_CUT; every other code is a failed try. A failed try of a classic entry LISTEN ends the entry. A transaction with tries left goes again after its gap; one with none ends the operation with HITEC_SES_ERR_NO_SERVO when the last try was HITEC_RX_ERR_SILENT, else with the operation's error: ENTRY, READ or WRITE.
Every result starts the gap of the step that ended before anything else, a cut or lost step's included, since its frame may have reached the servo: the series gap, a plan step's longer wait, the D series entry's 1000ms, the 1000ms after a D series leave. An abort, an error or the end of the operation keeps it; the next operation waits it out.
| s | Session. |
| now | The clock when the step ended. |
| r | The result. |
| bool hitec_session_init | ( | hitec_session_t * | s, |
| uint8_t | series, | ||
| uint8_t | clock ) |
Prepare a session for one series.
No operation runs, no step is due, not in mode; off time HITEC_SES_OFF_MS.
| s | Session. |
| series | hitec_family_t, chosen by the operator. |
| clock | hitec_ses_clock_t of the now the caller passes. |
| hitec_ses_t hitec_session_leave | ( | hitec_session_t * | s | ) |
Leave programming mode.
Classic: POWER (off off_ms, on, a LISTEN of HITEC_SES_POWER_WINDOW_US with no answer). D series: the reboot, 0x46 = 1, then HITEC_D_REBOOT_WAIT_MS before the next step of any operation. in_mode is 0 from the start of the leave. Taken in or out of mode.
| s | Session. |
| hitec_ses_kind_t hitec_session_next | ( | hitec_session_t * | s, |
| uint32_t | now, | ||
| hitec_ses_step_t * | out ) |
The step to run at now.
A step stays out, and this call gives it again, until its result is fed. WAIT while the gap before the next transaction runs; DONE when no operation runs.
| s | Session. |
| now | The clock. |
| out | Receives the step; NULL takes the kind only. |
| hitec_ses_t hitec_session_read_all | ( | hitec_session_t * | s | ) |
Read the series' full set: hitec_d_read_list() or hitec_c_read_ranges().
The image starts empty, the classic version kept. Addresses go in ascending order, each with HITEC_SES_TRIES tries; one that fails on every try ends the read, and the image keeps what was read before it.
| s | Session. |
| hitec_ses_t hitec_session_read_set | ( | hitec_session_t * | s, |
| const uint8_t * | addrs, | ||
| uint16_t | n ) |
Read n addresses into the image, which keeps the rest.
As hitec_session_read_all(), in ascending order, each address once.
| s | Session. |
| addrs | Cells, or even D series registers. |
| n | Count, 1 to 256. |
| hitec_ses_t hitec_session_result | ( | const hitec_session_t * | s | ) |
The running operation's state.
| s | Session. |
| hitec_ses_t hitec_session_run_plan | ( | hitec_session_t * | s, |
| const hitec_plan_t * | plan, | ||
| const hitec_image_t * | expect ) |
Run a plan the caller built, such as hitec_d_factory_plan(), then read back as hitec_session_write() does.
| s | Session. |
| plan | The plan, copied; steps of the session's series only. |
| expect | The image the read-back must hold, copied; NULL reads back and compares nothing. |
| hitec_ses_t hitec_session_write | ( | hitec_session_t * | s, |
| const hitec_image_t * | target ) |
Write the servo from the image to target, then read it back.
The plan is hitec_plan(image, target), kept in plan. An empty plan ends with HITEC_SES_OK and sends nothing.
Classic: each cell and each balance (0x1C) as 62 cell value sum, with HITEC_SES_TRIES tries for its + +, HITEC_SES_C_GAP_MS apart. Then a read of cells 0x00 to 0x23.
D series: each write, the save and the reboot as a write frame with no answer, each followed by its plan wait (20ms, 100ms, 1000ms), at least HITEC_SES_D_GAP_MS. Then a read of the full set.
The read-back must hold every writable address (hitec_writable()) and the classic balance as target holds it, where target knows it; diff names the ones that differ. step_index counts the plan's writes that went out.
The image holds only what the servo confirmed. A classic write answered + + goes into it. A D series write has no answer and does not change it; the read-back puts the register there.
A write that ends with anything but HITEC_SES_OK once a plan step was handed out and its result fed (RAN, CUT or FAILED: a cut or lost step may have reached the servo) marks as not known (hitec_image_forget()) every address the servo may have changed and this write's read-back has not read: D series, every register of the full read and every register of the plan, since a save, a reboot or a factory reset may change registers the plan does not name; classic, the cell of a write whose last try got no + + (a cut or lost try included) and the balance 0x1C. hitec_plan() then refuses with HITEC_PLAN_ERR_UNKNOWN (HITEC_SES_ERR_PLAN): the caller reads the servo before it writes again. A write refused or aborted before a step's result was fed, and one whose read-back ended with HITEC_SES_ERR_VERIFY, forget nothing.
| s | Session. |
| target | The draft, copied. |
|
static |
The common refusals of an operation.
| s | Session. |
| in_mode | true when the operation needs a successful entry. |
|
static |
True when every step of plan is one the session runs on its series.
| s | Session. |
| plan | Plan. |
|
static |
A POWER step whose LISTEN waits window_us.
| s | Session. |
| st | Receives the step. |
| window_us | The LISTEN's window, us. |
| answer | true to answer the first byte with +. |
|
static |
True when the read-back of the running write has read addr.
| s | Session. |
| addr | Address. |
|
static |
The read of s->addr took value: store it, then the next address or the operation's end. The gap is the one feed started.
| s | Session. |
| value | The decoded value. |
|
static |
The gap after a transaction of the session's series.
| s | Session. |
|
static |
Put addr into set.
| set | Address set. |
| addr | Address. |
|
static |
Addresses in set.
| set | Address set. |
|
static |
Take addr out of set.
| set | Address set. |
| addr | Address. |
|
static |
The lowest address in set.
| set | Address set. |
| out | Receives the address. |
|
static |
Put the series' full read into set.
| series | hitec_family_t. |
| set | Address set, emptied first. |
|
static |
Start the plan in s->plan; the read-back compares with target when compare.
| s | Session. |
| compare | true to compare the read-back with target. |
|
static |
The wait the step that is out asks for once its result comes, whether it ran, was cut or was lost.
| s | Session. |
|
static |
ms in ticks of the session's clock.
| s | Session. |
| ms | Time, ms. |
|
static |
The write of plan.step[step_index] took: count it, start its wait, then the next write or the read-back.
A classic write answered + + goes into the image. A D series write has no answer and leaves the image alone: the read-back puts the value the servo holds there.
| s | Session. |
| now | The clock. |