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

The panel's half of the SENSE, SERVO_SENSE and SERVO_WIN link pages: what the last reads hold, handed to the screens, the log and the band – the servo windows, the meter, the ESC figures and totals, the encoder and the parts' addresses and identities – and the rows of SETUP the page does not hold. More...

#include "sense_link.h"
#include "sense_link_int.h"
#include <stddef.h>
#include <string.h>

Functions

static uint8_t servo_ok (const sense_link_t *s)
 SERVO_SENSE's last read: the channels whose window holds readings, bit n-1 for CHn.
static bool servo_window_new (const sense_link_t *s)
 Whether SERVO_SENSE's last read holds a window not taken yet.
unsigned sense_link_windows (const sense_link_t *s)
 How many windows sense_link_take_window() hands over now: the ring's waiting ones, or without the ring 1 while SERVO_SENSE's last read holds a window not taken yet.
static void servo_channel (const sense_link_t *s, size_t i, bench_state_t *b)
 Channel index i of SERVO_SENSE's last read into b.
void sense_link_win_bench (const sense_link_t *s, const sense_link_win_t *w, bench_state_t *b)
 A ring window into b's log fields: servo_new set, its number, CH1's mean and highest current and lowest bus voltage with servo_ok bit 0 set while the window holds samples, servo_no_current and servo_no_voltage bit 0 for the quantity it holds no sample of, and CH2's and CH3's figures from SERVO_SENSE's last read when that read shows the same window number.
bool sense_link_take_window (sense_link_t *s, bench_state_t *b)
 The INA3221's next window into b for the log, once per window; true and servo_new set, false and b untouched otherwise.
static bool held_as_asked (const sense_link_t *s)
 Whether the page holds what the panel asks of it.
void sense_link_meter (const sense_link_t *s, sense_link_meter_t *out)
 What the servo rail's meter is chosen from, into out.
uint16_t sense_link_flags (const sense_link_t *s)
 FLAGS as last read, 0 before any read.
uint32_t sense_link_reads (const sense_link_t *s)
 SENSE reads answered since init: a caller that compares two counts can tell a read made in between.
bool sense_link_esc (const sense_link_t *s, uint32_t now_ms, bool *v_ok, float *volts, bool *i_ok, float *amps)
 The ESC's own telemetry voltage and current, from the last SENSE read if it is younger than SENSE_LINK_STALE_MS, each with its valid bit.
bool sense_link_totals (const sense_link_t *s, uint32_t now_ms, int32_t *charge_cmah, uint32_t *energy_cwh)
 The INA228's charge in 0.01mAh and energy in 0.01Wh as last read, 0 while they are not the run's totals.
bool sense_link_enc_on (const sense_link_t *s)
 Whether the encoder is set up on the page: enabled there, and read.
static bool enc_read (const sense_link_t *s, uint32_t now_ms, uint16_t *flags)
 Whether the last SENSE read is fresh at now_ms and holds a reading of the encoder's registers from a part that answers; its flags into flags.
bool sense_link_enc (const sense_link_t *s, uint32_t now_ms, sense_link_enc_t *out)
 The encoder's last angle into out: true when the page enables it, the last SENSE read is younger than SENSE_LINK_STALE_MS at now_ms, the part was online in it, the angle holds a reading of this set-up and that reading's STATUS has MD set: a magnet is detected, and RAW ANGLE is a position.
bool sense_link_enc_no_magnet (const sense_link_t *s, uint32_t now_ms)
 Whether sense_link_enc() gives no angle at now_ms because the part answers and sees no magnet: every condition of sense_link_enc() but MD holds.
uint16_t sense_link_enc_magnet (const sense_link_t *s)
 The magnet bits SENSE_LINK_EV_ENC_MAGNET was raised with: LINK_SN_ENC_MD, _ML and _MH, as read.
uint8_t sense_link_addr (const sense_link_t *s, sense_link_part_t part)
 The address part is set up at on the page, 0 while not known.
uint16_t sense_link_id (const sense_link_t *s, sense_link_part_t part)
 The ID part gave, as last read (DEVICE_ID, the die ID).
uint8_t sense_link_found (const sense_link_t *s, sense_link_part_t part)
 Another address that answered the last scan where part could be: an INA228 at 0x40 to 0x4F, an INA3221 at 0x40 to 0x43, neither at the other part's address while that one is enabled.
uint16_t sense_link_event_id (const sense_link_t *s, sense_link_part_t part)
 What an event was raised with, kept for when the band shows it: the ID part gave for SENSE_LINK_EV_*_WRONG, and the address the scan found for SENSE_LINK_EV_*_SILENT (0 none).
uint8_t sense_link_event_found (const sense_link_t *s, sense_link_part_t part)
 The address a scan found for the event's part, or 0 for none.
uint8_t sense_link_clipped_channel (const sense_link_t *s)
 The INA3221 channel SENSE_LINK_EV_I3221_CLIPPED names, 1 to 3: the one sense_link_event() last handed out.
uint16_t sense_link_i3221_dmohm (const sense_link_t *s)
 The INA3221's shunt on the page, 0.1mOhm.
uint8_t sense_link_i3221_addr (const sense_link_t *s)
 The INA3221's address on the page, the part SERVO_SENSE reads: 0x40 to 0x43; 0 before the page is read.
int sense_link_sda (const sense_link_t *s)
 The pins asked, -1 for unset: what SENSE_LINK_EV_BUS_REFUSED names.
int sense_link_scl (const sense_link_t *s)
 The SCL pin asked, -1 for unset.
uint16_t sense_link_unheld (const sense_link_t *s)
 The rows whose value as asked is not the one the page holds, SENSE_LINK_ROW_*: a set-up not written yet – it rests SENSE_LINK_SETTLE_MS and waits for an idle bank – one the page refused, and a part that is on in the settings and off on the page because its frame was refused, its pins are unset, both monitors share an address or the IOmcu is older than the part.
void sense_link_set_map (sense_link_t *s, bool map)
 Whether the INA3221 parts go by SENSE_MAP (sense_map_link_page()): then ENABLE bit 1 and the INA3221's frame are the IOmcu's mirror of the map, kept as read and never written, and refuse nothing.
void sense_link_set_map_held (sense_link_t *s, bool held)
 Whether SENSE_MAP holds the map SETUP asks (sense_map_link_held()): with the map in force the meter is held only then.
void sense_link_reread (sense_link_t *s)
 Read SENSE's set-up again, and the identity after it: a SENSE_MAP write was taken, and the mirror registers moved with it.
bool sense_link_take_caps (sense_link_t *s, uint16_t *caps)
 The capability bits an identity read since the last call brought, into caps; false if none did.
bool sense_link_take_win (sense_link_t *s, sense_link_win_t *out)
 The next CH1 window of the ring into out, oldest first, each number once: false when none waits, out untouched.
uint32_t sense_link_win_lost (const sense_link_t *s)
 Window numbers that left the ring before a read took them, since init, modulo 2^32: the windows lost, and with them any number the IOmcu skipped that was out of the ring by the read.
bool sense_link_held_pins (const sense_link_t *s, int *sda, int *scl)
 The sensor bus's pins the page holds by its last read or write, as the IOmcu reserves them (sense_page_pins()): SDA and SCL while ENABLE has a part on, -1 and -1 while it has none or the IOmcu has no SENSE page.

Detailed Description

The panel's half of the SENSE, SERVO_SENSE and SERVO_WIN link pages: what the last reads hold, handed to the screens, the log and the band – the servo windows, the meter, the ESC figures and totals, the encoder and the parts' addresses and identities – and the rows of SETUP the page does not hold.

The state machine that decides what is read and written is in sense_link.c. See sense_link.h.

SPDX-License-Identifier: MIT

Function Documentation

◆ enc_read()

bool enc_read ( const sense_link_t * s,
uint32_t now_ms,
uint16_t * flags )
static

Whether the last SENSE read is fresh at now_ms and holds a reading of the encoder's registers from a part that answers; its flags into flags.

Parameters
sThe link state.
now_msThe time, in ms.
flagsReceives the encoder flags.
Returns
true when the reading is fresh and from a part that answers.

◆ held_as_asked()

bool held_as_asked ( const sense_link_t * s)
static

Whether the page holds what the panel asks of it.

With the map in force the INA3221's enable bit and frame are the map's mirror, which the panel does not ask: they are left out.

Parameters
sThe link state.
Returns
true when the page holds the set-up asked.

◆ sense_link_addr()

uint8_t sense_link_addr ( const sense_link_t * s,
sense_link_part_t part )

The address part is set up at on the page, 0 while not known.

Parameters
sThe link state.
partThe part.
Returns
The address, or 0 while not known.

◆ sense_link_clipped_channel()

uint8_t sense_link_clipped_channel ( const sense_link_t * s)

The INA3221 channel SENSE_LINK_EV_I3221_CLIPPED names, 1 to 3: the one sense_link_event() last handed out.

Channels that clip together are handed out one each, the event standing until the last.

Parameters
sThe link state.
Returns
The INA3221 channel, 1 to 3.

◆ sense_link_enc()

bool sense_link_enc ( const sense_link_t * s,
uint32_t now_ms,
sense_link_enc_t * out )

The encoder's last angle into out: true when the page enables it, the last SENSE read is younger than SENSE_LINK_STALE_MS at now_ms, the part was online in it, the angle holds a reading of this set-up and that reading's STATUS has MD set: a magnet is detected, and RAW ANGLE is a position.

False, out untouched, otherwise. This is the one place an angle leaves the link, so no caller has an angle read without a magnet.

Parameters
sThe link state.
now_msThe time, in ms.
outReceives the angle.
Returns
true when an angle is given.

◆ sense_link_enc_magnet()

uint16_t sense_link_enc_magnet ( const sense_link_t * s)

The magnet bits SENSE_LINK_EV_ENC_MAGNET was raised with: LINK_SN_ENC_MD, _ML and _MH, as read.

Parameters
sThe link state.
Returns
The magnet bits, as read.

◆ sense_link_enc_no_magnet()

bool sense_link_enc_no_magnet ( const sense_link_t * s,
uint32_t now_ms )

Whether sense_link_enc() gives no angle at now_ms because the part answers and sees no magnet: every condition of sense_link_enc() but MD holds.

Parameters
sThe link state.
now_msThe time, in ms.
Returns
true when the encoder answers and sees no magnet.

◆ sense_link_enc_on()

bool sense_link_enc_on ( const sense_link_t * s)

Whether the encoder is set up on the page: enabled there, and read.

Parameters
sThe link state.
Returns
true when the encoder is set up on the page.

◆ sense_link_esc()

bool sense_link_esc ( const sense_link_t * s,
uint32_t now_ms,
bool * v_ok,
float * volts,
bool * i_ok,
float * amps )

The ESC's own telemetry voltage and current, from the last SENSE read if it is younger than SENSE_LINK_STALE_MS, each with its valid bit.

False, both bits clear, otherwise.

Parameters
sThe link state.
now_msThe time, in ms.
v_okReceives the valid bit of the voltage.
voltsReceives the voltage, in V.
i_okReceives the valid bit of the current.
ampsReceives the current, in A.
Returns
true when the telemetry is available.

◆ sense_link_event_found()

uint8_t sense_link_event_found ( const sense_link_t * s,
sense_link_part_t part )

The address a scan found for the event's part, or 0 for none.

Parameters
sThe link state.
partThe part.
Returns
The address a scan found for the event.

◆ sense_link_event_id()

uint16_t sense_link_event_id ( const sense_link_t * s,
sense_link_part_t part )

What an event was raised with, kept for when the band shows it: the ID part gave for SENSE_LINK_EV_*_WRONG, and the address the scan found for SENSE_LINK_EV_*_SILENT (0 none).

A later read can show another; a part that answers as itself before the band shows either drops it.

Parameters
sThe link state.
partThe part.
Returns
The ID the part gave for a WRONG event.

◆ sense_link_flags()

uint16_t sense_link_flags ( const sense_link_t * s)

FLAGS as last read, 0 before any read.

Parameters
sThe link state.
Returns
FLAGS as last read.

◆ sense_link_found()

uint8_t sense_link_found ( const sense_link_t * s,
sense_link_part_t part )

Another address that answered the last scan where part could be: an INA228 at 0x40 to 0x4F, an INA3221 at 0x40 to 0x43, neither at the other part's address while that one is enabled.

The lowest; 0 for none.

Parameters
sThe link state.
partThe part.
Returns
The lowest other address that answered, or 0 for none.

◆ sense_link_held_pins()

bool sense_link_held_pins ( const sense_link_t * s,
int * sda,
int * scl )

The sensor bus's pins the page holds by its last read or write, as the IOmcu reserves them (sense_page_pins()): SDA and SCL while ENABLE has a part on, -1 and -1 while it has none or the IOmcu has no SENSE page.

False, both -1, while that is not known: no link, or no read yet. sda and scl may be NULL.

Parameters
sThe link state.
sdaReceives the SDA pin, or -1; may be NULL.
sclReceives the SCL pin, or -1; may be NULL.
Returns
true when the held pins are known.

◆ sense_link_i3221_addr()

uint8_t sense_link_i3221_addr ( const sense_link_t * s)

The INA3221's address on the page, the part SERVO_SENSE reads: 0x40 to 0x43; 0 before the page is read.

Parameters
sThe link state.
Returns
The INA3221's address, 0x40 to 0x43, or 0 before the page is read.

◆ sense_link_i3221_dmohm()

uint16_t sense_link_i3221_dmohm ( const sense_link_t * s)

The INA3221's shunt on the page, 0.1mOhm.

Parameters
sThe link state.
Returns
The INA3221's shunt on the page, in 0.1mOhm.

◆ sense_link_id()

uint16_t sense_link_id ( const sense_link_t * s,
sense_link_part_t part )

The ID part gave, as last read (DEVICE_ID, the die ID).

Parameters
sThe link state.
partThe part.
Returns
The ID the part gave.

◆ sense_link_meter()

void sense_link_meter ( const sense_link_t * s,
sense_link_meter_t * out )

What the servo rail's meter is chosen from, into out.

Parameters
sThe link state.
outReceives the meter's choice.

◆ sense_link_reads()

uint32_t sense_link_reads ( const sense_link_t * s)

SENSE reads answered since init: a caller that compares two counts can tell a read made in between.

Parameters
sThe link state.
Returns
The SENSE reads answered since init.

◆ sense_link_reread()

void sense_link_reread ( sense_link_t * s)

Read SENSE's set-up again, and the identity after it: a SENSE_MAP write was taken, and the mirror registers moved with it.

Parameters
sThe link state.

◆ sense_link_scl()

int sense_link_scl ( const sense_link_t * s)

The SCL pin asked, -1 for unset.

Parameters
sThe link state.
Returns
The SCL pin asked, or -1 for unset.

◆ sense_link_sda()

int sense_link_sda ( const sense_link_t * s)

The pins asked, -1 for unset: what SENSE_LINK_EV_BUS_REFUSED names.

Parameters
sThe link state.
Returns
The SDA pin asked, or -1 for unset.

◆ sense_link_set_map()

void sense_link_set_map ( sense_link_t * s,
bool map )

Whether the INA3221 parts go by SENSE_MAP (sense_map_link_page()): then ENABLE bit 1 and the INA3221's frame are the IOmcu's mirror of the map, kept as read and never written, and refuse nothing.

Parameters
sThe link state.
maptrue when the INA3221 parts go by SENSE_MAP.

◆ sense_link_set_map_held()

void sense_link_set_map_held ( sense_link_t * s,
bool held )

Whether SENSE_MAP holds the map SETUP asks (sense_map_link_held()): with the map in force the meter is held only then.

Parameters
sThe link state.
heldtrue while SENSE_MAP holds the map SETUP asks.

◆ sense_link_take_caps()

bool sense_link_take_caps ( sense_link_t * s,
uint16_t * caps )

The capability bits an identity read since the last call brought, into caps; false if none did.

Parameters
sThe link state.
capsReceives the capability bits.
Returns
true when an identity read since the last call brought bits.

◆ sense_link_take_win()

bool sense_link_take_win ( sense_link_t * s,
sense_link_win_t * out )

The next CH1 window of the ring into out, oldest first, each number once: false when none waits, out untouched.

Parameters
sThe link state.
outReceives the window.
Returns
true when a window was taken.

◆ sense_link_take_window()

bool sense_link_take_window ( sense_link_t * s,
bench_state_t * b )

The INA3221's next window into b for the log, once per window; true and servo_new set, false and b untouched otherwise.

With the ring (sense_link_win_on()): the next CH1 window, as sense_link_take_win() and sense_link_win_bench() give it. Call until false: a poll brings up to LINK_SW_RING windows.

Without it: SERVO_SENSE's last read, when it holds a window with readings whose number has not been taken before.

Parameters
sThe link state.
bReceives the window for the log.
Returns
true when a window was taken.

◆ sense_link_totals()

bool sense_link_totals ( const sense_link_t * s,
uint32_t now_ms,
int32_t * charge_cmah,
uint32_t * energy_cwh )

The INA228's charge in 0.01mAh and energy in 0.01Wh as last read, 0 while they are not the run's totals.

False before any read and for a read older than SENSE_LINK_TOTALS_MS at now_ms.

Parameters
sThe link state.
now_msThe time, in ms.
charge_cmahReceives the charge, in 0.01mAh.
energy_cwhReceives the energy, in 0.01Wh.
Returns
true when the totals are valid.

◆ sense_link_unheld()

uint16_t sense_link_unheld ( const sense_link_t * s)

The rows whose value as asked is not the one the page holds, SENSE_LINK_ROW_*: a set-up not written yet – it rests SENSE_LINK_SETTLE_MS and waits for an idle bank – one the page refused, and a part that is on in the settings and off on the page because its frame was refused, its pins are unset, both monitors share an address or the IOmcu is older than the part.

The comparison is want against held, the two this module writes from. 0 while no IOmcu answers and before the page has been read: nothing is known to compare with. An IOmcu without the page holds no part, and the parts that are on are named.

Parameters
sThe link state.
Returns
The SENSE_LINK_ROW_* bits of the rows not held as asked.

◆ sense_link_win_bench()

void sense_link_win_bench ( const sense_link_t * s,
const sense_link_win_t * w,
bench_state_t * b )

A ring window into b's log fields: servo_new set, its number, CH1's mean and highest current and lowest bus voltage with servo_ok bit 0 set while the window holds samples, servo_no_current and servo_no_voltage bit 0 for the quantity it holds no sample of, and CH2's and CH3's figures from SERVO_SENSE's last read when that read shows the same window number.

Parameters
sThe link state.
wThe ring window.
bReceives the log fields.

◆ sense_link_win_lost()

uint32_t sense_link_win_lost ( const sense_link_t * s)

Window numbers that left the ring before a read took them, since init, modulo 2^32: the windows lost, and with them any number the IOmcu skipped that was out of the ring by the read.

A caller that compares two counts has those of the time in between.

Parameters
sThe link state.
Returns
The windows lost since init, modulo 2^32.

◆ sense_link_windows()

unsigned sense_link_windows ( const sense_link_t * s)

How many windows sense_link_take_window() hands over now: the ring's waiting ones, or without the ring 1 while SERVO_SENSE's last read holds a window not taken yet.

Parameters
sThe link state.
Returns
The number of windows sense_link_take_window() hands over now.

◆ servo_channel()

void servo_channel ( const sense_link_t * s,
size_t i,
bench_state_t * b )
static

Channel index i of SERVO_SENSE's last read into b.

Parameters
sThe link state.
iThe channel index, from 0.
bReceives the channel figures.

◆ servo_ok()

uint8_t servo_ok ( const sense_link_t * s)
static

SERVO_SENSE's last read: the channels whose window holds readings, bit n-1 for CHn.

Parameters
sThe link state.
Returns
Bit n-1 set for CHn with readings.

◆ servo_window_new()

bool servo_window_new ( const sense_link_t * s)
static

Whether SERVO_SENSE's last read holds a window not taken yet.

Parameters
sThe link state.
Returns
true when such a window is waiting.