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

The SERVO screen's drawing. More...

#include "servo_screen.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
#include "sensors_rows.h"
#include "settings.h"
#include "supply_screen.h"
#include "ui_plot.h"
#include "ui_slider.h"
#include "ui_text.h"
#include "ui_theme.h"
#include "ui_widgets.h"
#include "gfx_subpixel.h"
#include "servo_screen_core_int.h"

Macros

#define HORN_TIP_REACH   36.0f
 How far a horn reaches from its tip, px: the outer ring's 33px radius, its 1px half width, its blended edge and a pixel more.
#define HORN_SHAFT_REACH   27.0f
 And from the shaft: the boss's 25px disc, its edge and a pixel.

Functions

static gfx_rect_t sup_row_rect (void)
 Gives the rectangle of the supply row on the rail.
static void at_f (float deg, float r, float *x, float *y)
 The point r px from the shaft at deg, in fractions of a pixel.
static void at (float deg, int r, int *x, int *y)
 The same on whole pixels: the dial's ticks and labels, which stand still.
static void draw_body (gfx_canvas_t *c)
 The case, its tabs and its boss. Drawn per framebuffer, not per frame: thing on this card that moves is the horn.
static float ring_gap_deg (float r, float half_w, float dark_px)
 Where a ring of radius r has to stop so that a constant band of dark card shows between its end and the arm.
static void draw_horn (gfx_canvas_t *c, float deg, gfx_color_t col)
 The horn at deg in col: the arm, its holes, its rings and the boss, placed in fractions of a pixel, so that a horn turning by a tenth of a degree moves by a sixth of a pixel rather than standing still and then jumping one.
static void draw_dial (gfx_canvas_t *c)
 Draws the dial: the ring, the scale, the labels and the horn.
int wrap_text (gfx_canvas_t *c, int x, int y, int pitch, const char *text, int cells, gfx_color_t ink, const gfx_font_t *f)
 text in lines of at most cells cells of face f, from (x, y) down by pitch px, each broken at the last double space that keeps it within them, or else at the last single space.
static void draw_readings (gfx_canvas_t *c)
 LIVE's three readings along the bottom of the card: COMMANDED in microseconds, MEASURED in degrees and CURRENT in amps, each its label and unit over its numerals.
static bool ghost_shown (void)
 Whether the commanded horn is drawn behind the one shown: while the two are more than a degree apart.
static void draw_left (gfx_canvas_t *c)
 LIVE's card: the dial, the case, the horn, the horn's angle, why the dial takes no press, the three readings and a run's box.
static gfx_color_t arm_fill (void)
 The same fill as MOTOR & ESC's ARM, from the same widget: armed is the danger red the press fades towards, and the flash is the whole button.
static void draw_arm (gfx_canvas_t *c)
 ARM, or DISARM while armed, across the column.
static gfx_rect_t power_rect (void)
 Gives the rectangle of the power readout on the rail.
static void fixed_text (char *out, size_t n, int32_t q, int places, const char *unit)
 q, a signed count of 10^-places of unit, as text: the sign kept, and a reading that rounds to nothing drawn without one. An empty unit leaves the number alone.
static void draw_power (gfx_canvas_t *c)
 The servo rail's voltage, current and power, read and plotted, under the name of its meter: the supply, or the INA3221 channel that watches the tester's target, "INA 0x41 CH2", while that is the meter.
static void hero_text (gfx_canvas_t *c, int x, int y, int w, const char *t, gfx_color_t col)
 A reading's numerals at (x, y), left aligned in w px: in SV_FONT_NUM, or where they are wider than that – a reading held at +-1000000.00A is 12 cells – in SV_FONT_HEAD, or in SV_FONT_LABEL.
static gfx_rect_t cur_val_rect (void)
 The CURRENT reading's numerals on LIVE's card.
static void cur_value (gfx_canvas_t *c)
 The rail's current as its meter reads it, signed, in hundredths of an amp; in the warning colour from a clipped window.
static void draw_cur_value (gfx_canvas_t *c)
 The same over its own background: the row's repaint between two repaints of the card.
static gfx_color_t out_fill (void)
 OUTPUT ON and OFF in SUPPLY's colours: off is the green the hold fades from, on the danger red it fades to.
static void draw_sup_row (gfx_canvas_t *c)
 SET, the two set points, and the output switch.
static gfx_rect_t tag_rect (void)
 Gives the rectangle of the telemetry tag on the rail.
static void draw_tag (gfx_canvas_t *c)
 The profile in force, its frame rate and its pulse range in microseconds, in the danger colour when it is one that can destroy a servo not made for it.
static void draw_right (gfx_canvas_t *c, bool power)
 The output card. The power plot only when power: a repaint for anything else leaves the plot, which its own samples repaint, clipped.
static void clipped (gfx_canvas_t *c, gfx_rect_t box, void(*fn)(gfx_canvas_t *))
 Draw fn clipped to box.
static void clipped_session (gfx_canvas_t *c, gfx_rect_t box, const prog_page_set_t *ps)
 The same for a session, drawn through its own function (PROG_CALLS).
static gfx_rect_t rect_union (gfx_rect_t a, gfx_rect_t b)
 The smallest rectangle holding a and b, neither empty.
static gfx_rect_t horn_box (float deg)
 Every pixel a horn at deg draws: the shaft's disc and the tip's rings, which hold the arm between them.
static gfx_rect_t angle_box (float deg)
 The horn's angle deg in the bench's numerals and deg after them, as draw_left() writes it, and never narrower than -888.8.
static bool dial_on_its_own (bool cover)
 Whether the dial's changes are repainted on their own: LIVE's card shown with nothing over it. A box of a run or a limit run over the card, or any other page, repaints whole for them.
static void dial_drawn (int buf)
 Note what buffer buf now shows of the dial.
static void draw_dial_part (gfx_canvas_t *c, int buf)
 The dial's change repainted in buffer buf: LIVE's card, clipped to the boxes of the horns as this buffer last drew them and as they are now, to the angle's numerals and to COMMANDED and MEASURED. Each buffer keeps its own last angles, so both end up with the horn where it is, whichever frames each was drawn in.
void svs_render (gfx_canvas_t *c, int buffer_index)
 The frame: what changed since buffer_index was last drawn.

Variables

static const uint8_t k_line_w [2][PS_COUNT]
 The widths of the three readings on the line over the plot, in px of 10px cells.

Detailed Description

The SERVO screen's drawing.

The SERVO screen's drawing: the servo on the dial, the left card, the right card with its readings, plot, set points and controls, and the frame, which repaints what changed. The state and the seam are servo_screen_int.h and servo_screen_core_int.h.

SPDX-License-Identifier: MIT

Function Documentation

◆ angle_box()

gfx_rect_t angle_box ( float deg)
static

The horn's angle deg in the bench's numerals and deg after them, as draw_left() writes it, and never narrower than -888.8.

Parameters
degthe angle, degrees
Returns
the box draw_left() draws them in

◆ at()

void at ( float deg,
int r,
int * x,
int * y )
static

The same on whole pixels: the dial's ticks and labels, which stand still.

Parameters
degthe angle, degrees
rthe distance from the shaft, px
xthe column, px
ythe row, px

◆ at_f()

void at_f ( float deg,
float r,
float * x,
float * y )
static

The point r px from the shaft at deg, in fractions of a pixel.

Parameters
degthe angle, degrees
rthe distance from the shaft, px
xthe column, px
ythe row, px

◆ cur_val_rect()

gfx_rect_t cur_val_rect ( void )
static

The CURRENT reading's numerals on LIVE's card.

Returns
the box draw_cur_value() repaints

◆ cur_value()

void cur_value ( gfx_canvas_t * c)
static

The rail's current as its meter reads it, signed, in hundredths of an amp; in the warning colour from a clipped window.

Parameters
cthe canvas

◆ dial_drawn()

void dial_drawn ( int buf)
static

Note what buffer buf now shows of the dial.

Parameters
bufthe buffer, 0 or 1

◆ dial_on_its_own()

bool dial_on_its_own ( bool cover)
static

Whether the dial's changes are repainted on their own: LIVE's card shown with nothing over it. A box of a run or a limit run over the card, or any other page, repaints whole for them.

Parameters
covera panel or a session is over the left column
Returns
true when they are

◆ draw_arm()

void draw_arm ( gfx_canvas_t * c)
static

ARM, or DISARM while armed, across the column.

Parameters
cthe canvas

◆ draw_dial_part()

void draw_dial_part ( gfx_canvas_t * c,
int buf )
static

The dial's change repainted in buffer buf: LIVE's card, clipped to the boxes of the horns as this buffer last drew them and as they are now, to the angle's numerals and to COMMANDED and MEASURED. Each buffer keeps its own last angles, so both end up with the horn where it is, whichever frames each was drawn in.

Parameters
cthe canvas
bufthe buffer, 0 or 1

◆ draw_horn()

void draw_horn ( gfx_canvas_t * c,
float deg,
gfx_color_t col )
static

The horn at deg in col: the arm, its holes, its rings and the boss, placed in fractions of a pixel, so that a horn turning by a tenth of a degree moves by a sixth of a pixel rather than standing still and then jumping one.

Parameters
cthe canvas
degthe angle, degrees
colthe arm's colour

◆ draw_left()

void draw_left ( gfx_canvas_t * c)
static

LIVE's card: the dial, the case, the horn, the horn's angle, why the dial takes no press, the three readings and a run's box.

Parameters
cthe canvas

◆ draw_readings()

void draw_readings ( gfx_canvas_t * c)
static

LIVE's three readings along the bottom of the card: COMMANDED in microseconds, MEASURED in degrees and CURRENT in amps, each its label and unit over its numerals.

MEASURED is the horn's angle from the encoder where one reads; with the encoder off in SETUP, from the feedback; with it on and not reading, the dashes: the pulse position is not the horn's angle then.

Parameters
cthe canvas

◆ draw_right()

void draw_right ( gfx_canvas_t * c,
bool power )
static

The output card. The power plot only when power: a repaint for anything else leaves the plot, which its own samples repaint, clipped.

Parameters
cthe canvas
powerwhether the plot is drawn too

◆ draw_tag()

void draw_tag ( gfx_canvas_t * c)
static

The profile in force, its frame rate and its pulse range in microseconds, in the danger colour when it is one that can destroy a servo not made for it.

The longest, a 13-character type, 560Hz and two 4-digit ends, is 32 of the pill's 35 cells.

Parameters
cthe canvas

◆ fixed_text()

void fixed_text ( char * out,
size_t n,
int32_t q,
int places,
const char * unit )
static

q, a signed count of 10^-places of unit, as text: the sign kept, and a reading that rounds to nothing drawn without one. An empty unit leaves the number alone.

Parameters
outthe text
nits size
qthe count
places1 or 2
unitthe unit right after the number, or ""

◆ ghost_shown()

bool ghost_shown ( void )
static

Whether the commanded horn is drawn behind the one shown: while the two are more than a degree apart.

Returns
true when it is

◆ hero_text()

void hero_text ( gfx_canvas_t * c,
int x,
int y,
int w,
const char * t,
gfx_color_t col )
static

A reading's numerals at (x, y), left aligned in w px: in SV_FONT_NUM, or where they are wider than that – a reading held at +-1000000.00A is 12 cells – in SV_FONT_HEAD, or in SV_FONT_LABEL.

Parameters
cthe canvas
xthe column's left edge, px
ythe numerals' top, px
wthe column's width, px
tthe numerals
coltheir colour

◆ horn_box()

gfx_rect_t horn_box ( float deg)
static

Every pixel a horn at deg draws: the shaft's disc and the tip's rings, which hold the arm between them.

Parameters
degthe horn's angle, degrees
Returns
the box, whole pixels

◆ rect_union()

gfx_rect_t rect_union ( gfx_rect_t a,
gfx_rect_t b )
static

The smallest rectangle holding a and b, neither empty.

Parameters
aone rectangle
bthe other
Returns
the rectangle holding both

◆ ring_gap_deg()

float ring_gap_deg ( float r,
float half_w,
float dark_px )
static

Where a ring of radius r has to stop so that a constant band of dark card shows between its end and the arm.

A fixed angle does not do it: the arm is the same width at every radius, so it subtends less angle further out, and two rings sharing one angular gap leave the outer one further clear of the arm than the inner. The outer ring is therefore the longer of the two.

◆ svs_render()

void svs_render ( gfx_canvas_t * c,
int buffer_index )

The frame: what changed since buffer_index was last drawn.

Parameters
cthe canvas
buffer_indexthe frame buffer drawn into

◆ wrap_text()

int wrap_text ( gfx_canvas_t * c,
int x,
int y,
int pitch,
const char * text,
int cells,
gfx_color_t ink,
const gfx_font_t * f )

text in lines of at most cells cells of face f, from (x, y) down by pitch px, each broken at the last double space that keeps it within them, or else at the last single space.

Parameters
cthe canvas, or NULL to count the lines only
xthe lines' left edge, px
ythe first line's top, px
pitchfrom line to line, px
textthe text
cellsthe cells a line holds
inkthe text's colour
fthe face
Returns
the lines it takes

Variable Documentation

◆ k_line_w

const uint8_t k_line_w[2][PS_COUNT]
static
Initial value:
= {
{ 88, 88, 90 },
{ 64, 84, 74 },
}

The widths of the three readings on the line over the plot, in px of 10px cells.

Beside PD MINI 88, 88 and 90, the rest of the column. Beside an INA3221 channel's 12-cell name, "INA 0x41 CH2", 64, 84 and 74, which hold the widest reading of the part's registers: a voltage of 6 cells, 9.99V or 65.5V, -32.77A, and a power of 7 cells, -99.9W or -2147W.