|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The control task: touch, STOP, arming, the outputs, the link and the heartbeat. More...
#include <math.h>#include <stdatomic.h>#include <string.h>#include "driver/gpio.h"#include "driver/temperature_sensor.h"#include "esp_log.h"#include "freertos/FreeRTOS.h"#include "freertos/queue.h"#include "freertos/task.h"#include "arming.h"#include "board_pins.h"#include "frame_watch.h"#include "gfx.h"#include "heartbeat.h"#include "outputs.h"#include "panel.h"#include "panel_main.h"#include "panel_trial.h"#include "servo_link.h"#include "telemetry_sim.h"#include "touch.h"#include "touch_loss.h"#include "ui_band.h"#include "ui_text.h"Functions | |
| void | heartbeat_init (void) |
| Set the heartbeat's pin up as an output, low. | |
| void | tsens_init (void) |
| Start the die temperature sensor. | |
| static void | tsens_read (void) |
| Reads the MCU's own die temperature into s_mcu_c. | |
| static void | beat (bool alive) |
| Steps the heartbeat generator and drives PANEL_HEARTBEAT_PIN with its level. | |
| static void | render_watch (void) |
| The render loop, watched while the bench is ARMED or the supply's output is on (frame_watch.h). | |
| static bool | touch_q_put (const touch_event_t *evt, bool lost) |
| Offer one item to s_touch_q, numbered. Returns whether the queue holds it. | |
| static void | drv_lost (uint32_t n) |
The driver's stream lost n events. Found on the event after the gap, before that event goes through the STOP branch, or at the end of a drain against the number the driver last published. | |
| void | control_pump (void) |
| Drains the touch driver's queue, answers sequence gaps, applies a STOP at its press and passes the events on to the render loop. | |
| void | control_task (void *arg) |
| The control task; app_main creates it on core 1. | |
Variables | |
| static const char * | TAG = "rcbench" |
| Log tag. | |
| static heartbeat_gen_t | s_beat |
| Driven from the loop that reads touch and draws STOP. The line asserts that the processor owning the STOP button is running its loop, which a level cannot assert and a crashed panel cannot fake. | |
| static temperature_sensor_handle_t | s_tsens |
| The panel's own die, not the IOmcu's. The two boards sit in different air and run different loads, and this is the one the ESP32-P4 can measure without a wire. Read once a second; the sensor is slow and nothing on the screen changes faster. | |
| float | s_mcu_c = NAN |
| Read and published by the control task; app_main takes it from the snapshot with everything else that crosses between the two. | |
| atomic_bool | s_stop_live |
| Whether a STOP is drawn to press, from the render loop to the control task's hit test. | |
| static touch_seq_rx_t | s_drv_rx = { .next = 1u } |
| static uint32_t | s_tq_seq |
| S_touch_q's numbers, this task's alone; see s_tq_published, main.c. | |
| static frame_watch_t | s_frame_watch |
| The render loop's watchdog, this task's alone; see render_watch(). | |
The control task: touch, STOP, arming, the outputs, the link and the heartbeat.
The task runs at a fixed CONTROL_PERIOD_MS on the core the renderer does not use. control_pump() is the part of it with a deadline; it also runs inside every link exchange's wait. The heartbeat's pin and the die temperature are this task's too. app_main (main.c) creates it.
SPDX-License-Identifier: MIT
| void control_task | ( | void * | arg | ) |
The control task; app_main creates it on core 1.
| arg | Unused. |
|
static |
The driver's stream lost n events. Found on the event after the gap, before that event goes through the STOP branch, or at the end of a drain against the number the driver last published.
The render loop is told by an item in s_touch_q, ahead of the events that followed the gap, so it drops the screens' gestures before it handles any of them.
A STOP press needs nothing here: it stopped the bench at its DOWN, and its release does nothing. Losses in s_touch_q itself cannot lose a STOP either: this task evicts from that queue only after the event has been through the STOP branch.
|
static |
The render loop, watched while the bench is ARMED or the supply's output is on (frame_watch.h).
A render loop that has stopped leaves STOP working, through this task's own hit test, and nothing else: DISARM, the throttle slider, the servo dial and OUTPUT OFF are the loop's, and the outputs hold their last command. A counter that has stood still for FRAME_WATCH_MS is answered as a STOP of the bench's own, the way an arm the watch undoes is: arming_stop() drops the heartbeat in this pass, the IOmcu fails safe within HEARTBEAT_MAX_GAP_MS (150ms), supply_pump() switches the output off in this pass, and service_arming() lets go of the rest. Nothing here arms or switches anything on, so a loop that comes back finds the latch as a STOP leaves it. The alert shows when the loop draws again.
Called from control_pump(), here and inside every exchange's wait, before the supply's pump.
|
static |
Offer one item to s_touch_q, numbered. Returns whether the queue holds it.
The consumer is behind when the send fails. The oldest entry is dropped and the newest kept, which is what the GT911's own event queue and the command queue do – but which of the two is lost is not what makes this safe, and no choice is safe on its own: a release that never arrives leaves a screen holding a press, a DOWN that never arrives orphans the release after it, and the MOVE where a finger leaves ARM is what abandons the hold. What makes it safe is that the dropped entry's number is missing from what the render loop takes, and it drops the gesture before it handles the next event (touch_loss.h). Nothing is counted here.
The retry runs whether or not the receive took anything: the render loop can empty the queue between the failed send and the receive, and then there is room without anything having been evicted.
|
static |
Driven from the loop that reads touch and draws STOP. The line asserts that the processor owning the STOP button is running its loop, which a level cannot assert and a crashed panel cannot fake.
The monostable the line gates is on no board: the edges reach a header pin of the panel (PANEL_HEARTBEAT_PIN) and the IOmcu's monitor. They are emitted regardless, at one GPIO (general-purpose input/output) write per pass, so the line is running and can be scoped.
|
static |