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

The IOmcu application's own state, shared by the files it is cut into. More...

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "hardware/gpio.h"
#include "heartbeat.h"
#include "hitec_line.h"
#include "hitec_port.h"
#include "iomcu_pins.h"
#include "kst_line.h"
#include "kst_port.h"
#include "link_dev.h"
#include "link_pages.h"
#include "out_stage.h"
#include "out_store.h"
#include "outputs.h"
#include "outputs_hw.h"
#include "pdmini.h"
#include "prog_port.h"
#include "safety_gate.h"
#include "sense_core1.h"
#include "sense_page.h"
#include "servo_page.h"
#include "supply_page.h"
#include "tone_page.h"

Go to the source code of this file.

Data Structures

struct  iomcu_state_t
 Register images of the pages the IOmcu holds, one array per page. More...

Macros

#define IOMCU_CAPABILITIES   ((uint16_t)(LINK_CAP_SERVO_PWM | LINK_CAP_ESC_DRIVE | LINK_CAP_ESC_TELEM))
 What the output drivers make true, whatever is connected; see main().
#define IOMCU_PROG_PORTS   4u
 The programming ports this build has; the model holds LINK_PG_PORTS_MAX.
#define CH_THROTTLE   LINK_OUT_CHANNELS

Functions

void identity_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the IDENTITY page.
void control_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the CONTROL page.
uint8_t control_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the CONTROL page.
void status_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the STATUS page.
void bench_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the BENCH page.
void channels_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the CHANNELS page.
uint8_t channels_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the CHANNELS page.
void chan_cfg_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the CHAN_CFG page.
uint8_t chan_cfg_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the CHAN_CFG page.
void slots_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the OUTPUTS page.
uint8_t slots_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the OUTPUTS page.
void servo_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the SERVO page.
uint8_t servo_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the SERVO page.
void prog_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the PROG page.
uint8_t prog_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the PROG page.
void kst_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the KST page.
uint8_t kst_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the KST page.
void hitec_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the HITEC page.
uint8_t hitec_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the HITEC page.
void supply_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the SUPPLY page.
uint8_t supply_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the SUPPLY page.
void sense_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the SENSE page.
uint8_t sense_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the SENSE page.
void servo_sense_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the SERVO_SENSE page.
uint8_t servo_sense_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the SERVO_SENSE page.
void servo_win_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the SERVO_WIN page.
void sense_map_rd (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the SENSE_MAP page.
uint8_t sense_map_wr (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the SENSE_MAP page.
void sense_win_a_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the SENSE_WIN_A page.
void sense_win_b_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the SENSE_WIN_B page.
void sense_limit_rd (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the SENSE_LIMIT page.
uint8_t sense_limit_wr (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the SENSE_LIMIT page.
void tone_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the TONE page.
uint8_t tone_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the TONE page.
void bind_cfg_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the BIND_CFG page.
uint8_t bind_cfg_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the BIND_CFG page.
void bind_out_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the BIND_OUT page.
uint8_t bind_out_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the BIND_OUT page.
void bind_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the BIND page.
uint8_t bind_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the BIND page.
void catalogue_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the CATALOGUE page.
void shape_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the SHAPE page.
void artwork_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the ARTWORK page.
void art_data_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the ART_DATA page.
uint8_t art_data_write (void *ctx, uint8_t off, uint8_t n, const uint16_t *in)
 Writes the ART_DATA page.
void pads_read (void *ctx, uint8_t off, uint8_t n, uint16_t *out)
 Reads the PADS page.
void save_outputs (const iomcu_state_t *s)
 Asks for the output configuration to be saved.
void ports_apply (void)
 Makes the programming ports' pins agree with the PROG page.
void hw_apply_only (uint8_t may_bind)
 Makes the silicon agree with the bank, binding only the slots in may_bind.
void hw_apply (void)
 Makes the silicon agree with the bank, binding every slot.
uint8_t chan_cfg_take (iomcu_state_t *s, const uint16_t *next, const uint16_t *slots, bool save)
 Takes a whole CHAN_CFG page into force, when it passes the checks.
uint8_t slots_take (iomcu_state_t *s, const uint16_t *next, bool save)
 Takes a whole OUTPUTS page (slots) into force, when it passes the checks.
uint8_t kst_hw_pin (void *ctx, uint8_t port)
 Returns the pin of a programming port for the KST wire driver.
bool kst_hw_take (void *ctx, uint8_t port, uint8_t pin)
 Takes the programming port's pin for the KST wire driver.
void kst_hw_give (void *ctx)
 Gives the programming port's pin back from the KST wire driver.
void kst_hw_supply (void *ctx, supply_port_view_t *out)
 Fills the supply view of the KST port.
bool kst_hw_supply_set (void *ctx, bool on, uint16_t mv, uint16_t ma)
 Sets the supply of the KST port.
bool hitec_hw_take (void *ctx, uint8_t port, uint8_t pin, uint8_t family, uint8_t drive, uint8_t rx)
 Takes the programming port's pin for the HITEC wire driver.
void hitec_hw_give (void *ctx)
 Gives the programming port's pin back from the HITEC wire driver.
void hitec_hw_abort (void *ctx)
 Aborts the HITEC operation in progress.
void hitec_hw_run (void *ctx, hitec_port_run_t *out)
 Reports the timing of the last HITEC run.
void capabilities_update (void)
 Refreshes the IDENTITY page's capability word.
bool supply_rewire (void)
 Rebinds the supply's PD mini UART to the wiring in force.
uint8_t supply_take (uint8_t off, uint8_t n, const uint16_t *in, bool checked)
 Takes a SUPPLY write into the supply's wiring and output state.
uint64_t tone_taken (void)
 Returns the pins the phase tap may not take now.
bool tone_rewire (void)
 Makes the phase tap's capture agree with the TONE page's pin.
void heartbeat_init (void)
 Sets up the heartbeat input.
void can_start (void)
 Brings up the CAN controller at IOMCU_CAN_BITRATE.
void can_service (uint32_t now)
 Empties the CAN receive buffers and answers each frame.
void can_report (uint32_t now)
 Prints the console report when 3s have passed.
void reset_start (void)
 Reads why this start happened, once at boot, and prints it.
static void status_gate (iomcu_state_t *s)
 STATUS's state and fault registers.
static uint8_t bound_slots (void)
 The slots the silicon has bound, one bit each.
static bool heartbeat_edge (void)
 Sample the line; returns whether its level changed since the last sample.
static uint8_t ports_quiet (void)
 The programming ports out of PWM: held by the KST page or the HITEC page, in any state but PWM and free.
static uint8_t ports_wire (void)
 The programming ports whose pin a wire driver holds.
static void ports_exclusive (void)
 Each wire page told which ports the other holds: neither takes a port the other has.
static bool ports_hold_supply (void)
 A wire page holds the SUPPLY page: the KST port out of PWM, or the HITEC port held, from its OPEN to its CLOSE.
static uint8_t ports_pulsing (void)
 The ports that render their pulse while the bank drives: bound, switched on, and not out of PWM for a wire protocol or a supply cycle.
static void reserve_held (void)
 What no output may have: the board's own pins, and the ones the supply, the sensor bus and the phase tap hold now – the pages', and the ones core 1 has not let go of yet.
static void sense_build (sense_cmd_t *cmd)
 Core 1's order, from the page as it stands, the run and the edge.
static void sense_order (void)
 Sent whenever something in it changes; core 1 takes it at its next tick.
static void sense_sync (void)
 Core 1's newest snapshot into the pages, when there is one.

Variables

iomcu_state_t s_state
 The register images of the pages in iomcu_state_t.
servo_page_t s_servo
 The SERVO page: the PWM target's frame rate and the sweep.
supply_page_t s_supply
 The SUPPLY page and the PD mini it drives on a PIO UART.
pdmini_t s_pd
bool s_pd_open
uint8_t s_pd_rate
bool s_supply_unsaved
 Wiring taken and not yet in flash: no ON until it is, so a restart in the run finds the wiring that drives the module and can switch it off.
bool s_supply_attach
 New wiring taken, the UART to attach once it is saved.
sense_page_t s_sense
 The SENSE and SERVO_SENSE pages: the current monitors' set-up, kept, and the pins it holds.
tone_page_t s_tone
 The TONE page: the phase tap's set-up, kept, and the beeps core 1 hears on it.
sense_snap_t s_sense_snap
 Core 1's last snapshot.
sense_cmd_t s_sense_cmd
uint16_t s_run_gen
 Moves on each edge of the bank into driving: core 1 starts the run's peaks and the INA228's totals on it.
bool s_edge_set
 The capture's PWM edge, stamped by outputs_hw for capture order s_edge_gen.
uint16_t s_edge_gen
uint64_t s_edge_us
uint64_t s_base_reserved
 What the board and this application hold, before the supply and the sensor bus take their pins.
prog_port_t s_prog
 The PROG page: the programming ports, outputs of their own kind with their own pins (shared/outputs/prog_port.h).
kst_port_t s_kst
 The KST page: the wire protocol for KST and Chaservo servos on a programming port (shared/outputs/kst_port.h) and the wire driver the port's pin is handed to (protocols/kst/rp2350).
kst_line_t s_kst_line
hitec_port_t s_hitec
 The HITEC page: raw transactions of the Hitec wire on a programming port (shared/outputs/hitec_port.h) and the wire driver the port's pin is handed to (protocols/hitec/rp2350).
hitec_line_t s_hitec_line
link_dev_t s_dev
outputs_t s_outputs
 Every output, behind one set of rules.
heartbeat_mon_t s_beat
 The panel's safety line, as judged in firmware.
uint32_t s_frames
 Requests this end has answered, published on the STATUS page.
uint32_t s_refused
 CAN frames received and refused since power-up, published on the STATUS page (LINK_ST_REFUSED_LO and _HI).
uint32_t s_now_ms
 The pass's clock, used by everything the pass reaches – including the page callbacks, which run inside can_service() and have no now of their own.
bool s_beat_level
 The heartbeat line's level at the last sample; see iomcu_can.c.
bool s_can_up
 The CAN controller, its echoes and its receive overruns; see iomcu_can.c.
uint32_t s_can_echoes
uint32_t s_can_overflows
uint32_t s_last_rx_ms
 When a frame was last taken out of the controller; see iomcu_can.c.
out_stage_t s_stage
 The binding BIND_CFG and BIND_OUT hold prepared; see iomcu_bind.c.

Detailed Description

The IOmcu application's own state, shared by the files it is cut into.

Private to firmware/iomcu/src: nothing under shared/ or protocols/ includes it.

main.c boot, the main loop and the page table; defines most of the state declared below iomcu_report.c the console report every 3s, and why this start iomcu_pages.c IDENTITY, STATUS, CONTROL, BENCH, CHANNELS, CHAN_CFG, OUTPUTS, SERVO and PROG, and the glue that binds the outputs iomcu_kst.c the KST page and the port's hardware iomcu_hitec.c the HITEC page and the port's hardware iomcu_sense.c SUPPLY, SENSE, SERVO_SENSE, SERVO_WIN, SENSE_MAP, SENSE_WIN_A, SENSE_WIN_B and SENSE_LIMIT iomcu_tone.c the TONE page and the phase tap's capture iomcu_bind.c BIND, BIND_CFG, BIND_OUT and the board's own pages iomcu_can.c the heartbeat's input and the CAN bus

The helpers at the end are static inline, so the main loop and each page handler that calls one carry their own inlined copy.

SPDX-License-Identifier: MIT

Function Documentation

◆ art_data_read()

void art_data_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the ART_DATA page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ art_data_write()

uint8_t art_data_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the ART_DATA page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ artwork_read()

void artwork_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the ARTWORK page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ bench_read()

void bench_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the BENCH page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ bind_cfg_read()

void bind_cfg_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the BIND_CFG page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ bind_cfg_write()

uint8_t bind_cfg_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the BIND_CFG page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ bind_out_read()

void bind_out_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the BIND_OUT page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ bind_out_write()

uint8_t bind_out_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the BIND_OUT page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ bind_read()

void bind_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the BIND page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ bind_write()

uint8_t bind_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the BIND page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ bound_slots()

uint8_t bound_slots ( void )
inlinestatic

The slots the silicon has bound, one bit each.

Returns
One bit per slot: bit i is set when slot i is bound.

◆ can_report()

void can_report ( uint32_t now)

Prints the console report when 3s have passed.

Parameters
nowThe pass's clock in ms.

◆ can_service()

void can_service ( uint32_t now)

Empties the CAN receive buffers and answers each frame.

Parameters
nowThe pass's clock in ms, stamped on each frame received and passed to the link dispatcher.

◆ can_start()

void can_start ( void )

Brings up the CAN controller at IOMCU_CAN_BITRATE.

A failure is not fatal: it is reported on the USB serial port, and s_can_up stays false.

◆ catalogue_read()

void catalogue_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the CATALOGUE page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ chan_cfg_read()

void chan_cfg_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the CHAN_CFG page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ chan_cfg_take()

uint8_t chan_cfg_take ( iomcu_state_t * s,
const uint16_t * next,
const uint16_t * slots,
bool save )

Takes a whole CHAN_CFG page into force, when it passes the checks.

Parameters
sThe state to update.
nextThe new CHAN_CFG register values.
slotsThe OUTPUTS page prepared beside next by a BIND commit, or NULL for a CHAN_CFG write.
saveTrue to save the configuration to flash.
Returns
0 to accept, or a link_nack_t to refuse. A refused page leaves the page in force unchanged.

◆ chan_cfg_write()

uint8_t chan_cfg_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the CHAN_CFG page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ channels_read()

void channels_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the CHANNELS page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ channels_write()

uint8_t channels_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the CHANNELS page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ control_read()

void control_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the CONTROL page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ control_write()

uint8_t control_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the CONTROL page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ heartbeat_edge()

bool heartbeat_edge ( void )
inlinestatic

Sample the line; returns whether its level changed since the last sample.

safety_gate_step() hands the edge to the monitor.

Returns
True when the level changed since the last sample.

◆ heartbeat_init()

void heartbeat_init ( void )

Sets up the heartbeat input.

Set the heartbeat's pin up as an output, low.

◆ hitec_hw_abort()

void hitec_hw_abort ( void * ctx)

Aborts the HITEC operation in progress.

Parameters
ctxUnused.

◆ hitec_hw_give()

void hitec_hw_give ( void * ctx)

Gives the programming port's pin back from the HITEC wire driver.

Parameters
ctxUnused.

◆ hitec_hw_run()

void hitec_hw_run ( void * ctx,
hitec_port_run_t * out )

Reports the timing of the last HITEC run.

Parameters
ctxUnused.
outReceives the lead time, span and bit time of the run.

◆ hitec_hw_take()

bool hitec_hw_take ( void * ctx,
uint8_t port,
uint8_t pin,
uint8_t family,
uint8_t drive,
uint8_t rx )

Takes the programming port's pin for the HITEC wire driver.

Parameters
ctxUnused.
portIndex of the programming port. Not used here.
pinGPIO number to take.
familyHitec protocol family the line is opened for.
driveDrive setting of the pin.
rxNonzero to claim the sampler as well, for PRECHARGE.
Returns
True when the HITEC line opened on the pin.

◆ hitec_read()

void hitec_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the HITEC page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ hitec_write()

uint8_t hitec_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the HITEC page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ hw_apply_only()

void hw_apply_only ( uint8_t may_bind)

Makes the silicon agree with the bank, binding only the slots in may_bind.

Parameters
may_bindBit mask of the slots that may be bound. The others are released and left unbound.

◆ identity_read()

void identity_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the IDENTITY page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ kst_hw_give()

void kst_hw_give ( void * ctx)

Gives the programming port's pin back from the KST wire driver.

Parameters
ctxUnused.

◆ kst_hw_pin()

uint8_t kst_hw_pin ( void * ctx,
uint8_t port )

Returns the pin of a programming port for the KST wire driver.

Parameters
ctxUnused.
portIndex of the programming port.
Returns
The GPIO number, or the value prog_port_wire_pin() gives for a port with no pin.

◆ kst_hw_supply()

void kst_hw_supply ( void * ctx,
supply_port_view_t * out )

Fills the supply view of the KST port.

Parameters
ctxUnused.
outReceives the port's supply view.

◆ kst_hw_supply_set()

bool kst_hw_supply_set ( void * ctx,
bool on,
uint16_t mv,
uint16_t ma )

Sets the supply of the KST port.

No ON while the supply's wiring is not in flash, as the SUPPLY page refuses one: a restart in the run could not switch the module off.

Parameters
ctxUnused.
onTrue to switch the supply on.
mvSet voltage in millivolts, for ON.
maSet current in milliamps, for ON.
Returns
False for an ON while the wiring is not saved; otherwise what supply_page_port_set() returns.

◆ kst_hw_take()

bool kst_hw_take ( void * ctx,
uint8_t port,
uint8_t pin )

Takes the programming port's pin for the KST wire driver.

Parameters
ctxUnused.
portIndex of the programming port. Not used here.
pinGPIO number to take.
Returns
True when the KST line opened on the pin.

◆ kst_read()

void kst_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the KST page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ kst_write()

uint8_t kst_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the KST page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ pads_read()

void pads_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the PADS page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ ports_exclusive()

void ports_exclusive ( void )
inlinestatic

Each wire page told which ports the other holds: neither takes a port the other has.

Called after a write of either and once a pass.

◆ ports_hold_supply()

bool ports_hold_supply ( void )
inlinestatic

A wire page holds the SUPPLY page: the KST port out of PWM, or the HITEC port held, from its OPEN to its CLOSE.

Returns
True when the SUPPLY page is held.

◆ ports_pulsing()

uint8_t ports_pulsing ( void )
inlinestatic

The ports that render their pulse while the bank drives: bound, switched on, and not out of PWM for a wire protocol or a supply cycle.

Returns
One bit per programming port.

◆ ports_quiet()

uint8_t ports_quiet ( void )
inlinestatic

The programming ports out of PWM: held by the KST page or the HITEC page, in any state but PWM and free.

Returns
One bit per programming port.

◆ ports_wire()

uint8_t ports_wire ( void )
inlinestatic

The programming ports whose pin a wire driver holds.

Returns
One bit per programming port.

◆ prog_read()

void prog_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the PROG page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ prog_write()

uint8_t prog_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the PROG page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ reset_start()

void reset_start ( void )

Reads why this start happened, once at boot, and prints it.

Reads POWMAN CHIP_RESET, WATCHDOG REASON, SCRATCH2 and SCRATCH3 and the boot ROM's boot info, then zeroes SCRATCH2 and SCRATCH3 (reset_cause.h). The SDK's start-up code writes none of them. can_report() repeats the line every 3s.

◆ save_outputs()

void save_outputs ( const iomcu_state_t * s)

Asks for the output configuration to be saved.

Parameters
sThe state whose output configuration is saved.

◆ sense_build()

void sense_build ( sense_cmd_t * cmd)
inlinestatic

Core 1's order, from the page as it stands, the run and the edge.

Parameters
cmdReceives the order. It is zeroed first.

◆ sense_limit_rd()

void sense_limit_rd ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the SENSE_LIMIT page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ sense_limit_wr()

uint8_t sense_limit_wr ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the SENSE_LIMIT page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ sense_map_rd()

void sense_map_rd ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the SENSE_MAP page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ sense_map_wr()

uint8_t sense_map_wr ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the SENSE_MAP page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ sense_order()

void sense_order ( void )
inlinestatic

Sent whenever something in it changes; core 1 takes it at its next tick.

A copy under a lock, about a microsecond. The order, 136 bytes with the 12 channels' shunts and limits, is built in s_sense_cmd rather than on core 0's 4kB stack: core 0 alone builds it, from its main loop.

◆ sense_read()

void sense_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the SENSE page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ sense_sync()

void sense_sync ( void )
inlinestatic

Core 1's newest snapshot into the pages, when there is one.

Called where its contents are needed – a read of either page, the 50Hz sample, a capture ending – rather than every pass, so a pass with nothing to publish costs one load.

◆ sense_win_a_read()

void sense_win_a_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the SENSE_WIN_A page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ sense_win_b_read()

void sense_win_b_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the SENSE_WIN_B page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ sense_write()

uint8_t sense_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the SENSE page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ servo_read()

void servo_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the SERVO page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ servo_sense_read()

void servo_sense_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the SERVO_SENSE page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ servo_sense_write()

uint8_t servo_sense_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the SERVO_SENSE page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ servo_win_read()

void servo_win_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the SERVO_WIN page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ servo_write()

uint8_t servo_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the SERVO page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ shape_read()

void shape_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the SHAPE page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ slots_read()

void slots_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the OUTPUTS page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ slots_take()

uint8_t slots_take ( iomcu_state_t * s,
const uint16_t * next,
bool save )

Takes a whole OUTPUTS page (slots) into force, when it passes the checks.

Parameters
sThe state to update.
nextThe new slot register values.
saveTrue to save the configuration to flash.
Returns
0 to accept, or a link_nack_t to refuse.

◆ slots_write()

uint8_t slots_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the OUTPUTS page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ status_gate()

void status_gate ( iomcu_state_t * s)
inlinestatic

STATUS's state and fault registers.

The state and the link and heartbeat bits are the gate's (safety_gate_status()); the arm latch is on neither.

Parameters
sThe state whose STATUS registers are updated.

◆ status_read()

void status_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the STATUS page.

Parameters
ctxThe iomcu_state_t the page reads or writes.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ supply_read()

void supply_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the SUPPLY page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ supply_rewire()

bool supply_rewire ( void )

Rebinds the supply's PD mini UART to the wiring in force.

Returns
True when the supply is disabled or its UART is attached. False when no PIO block can reach the pins or has room.

◆ supply_take()

uint8_t supply_take ( uint8_t off,
uint8_t n,
const uint16_t * in,
bool checked )

Takes a SUPPLY write into the supply's wiring and output state.

Parameters
offFirst register of the write.
nNumber of registers in the write.
inThe n register values.
checkedTrue for the wiring change a state read has shown the module off for (supply_page_wire_ready()); false for a write from the link.
Returns
0 to accept, or a link_nack_t to refuse.

◆ supply_write()

uint8_t supply_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the SUPPLY page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

◆ tone_read()

void tone_read ( void * ctx,
uint8_t off,
uint8_t n,
uint16_t * out )

Reads the TONE page.

Parameters
ctxUnused.
offFirst register to read.
nNumber of registers to read.
outReceives the n register values.

◆ tone_rewire()

bool tone_rewire ( void )

Makes the phase tap's capture agree with the TONE page's pin.

Returns
True when the capture agrees with the page. False when the wiring could not take the pin, or core 1 was still in a pass.

◆ tone_taken()

uint64_t tone_taken ( void )

Returns the pins the phase tap may not take now.

Returns
One bit per GPIO: the supply's pins, the programming ports' pins and the sensor bus's pins, including those core 1 has not let go of yet.

◆ tone_write()

uint8_t tone_write ( void * ctx,
uint8_t off,
uint8_t n,
const uint16_t * in )

Writes the TONE page.

Parameters
ctxUnused.
offFirst register to write.
nNumber of registers to write.
inThe n register values to write.
Returns
0 to accept, or a link_nack_t to refuse.

Variable Documentation

◆ s_beat

heartbeat_mon_t s_beat
extern

The panel's safety line, as judged in firmware.

The control page consults it before it arms; see heartbeat_init() in iomcu_can.c.

◆ s_beat_level

bool s_beat_level
extern

The heartbeat line's level at the last sample; see iomcu_can.c.

The panel's safety line, watched in firmware as well as in hardware.

The heartbeat line's level at the last sample; see iomcu_can.c.

No board carries the retriggerable monostable that would gate the output enable in hardware (docs/Safety.md), so this monitor is the whole check. A ringing line, a short to a clock or a floating input next to a switching supply look like edges. heartbeat_mon_t knows the expected period and rejects what cannot be the panel's control task edging every 20ms.

The pin is sampled in the main loop rather than by an interrupt. A pass that turns over faster than HEARTBEAT_MIN_GAP_MS (4ms) cannot miss an edge the monitor would accept. The pass time is not measured: a printf every 3s goes to USB (Universal Serial Bus) stdio, and the supply's UART send blocks while its PIO FIFO is full. An ISR (interrupt service routine) would notice edges faster than the floor, which the monitor rejects anyway.

◆ s_can_up

bool s_can_up
extern

The CAN controller, its echoes and its receive overruns; see iomcu_can.c.

Tried at boot, and not fatal if it fails.

The CAN controller, its echoes and its receive overruns; see iomcu_can.c.

The controller either answers on SPI (Serial Peripheral Interface) or it does not, and the datasheet guarantees the mode it wakes in, so this distinguishes "no module fitted" and "SPI miswired" from anything on the CAN (Controller Area Network) bus itself.

The echo responder runs unconditionally. It costs one register read per loop, answers only frames addressed to a page the map does not use, and runs at the lowest priority on the bus, so it stays in every build.

◆ s_hitec

hitec_port_t s_hitec
extern

The HITEC page: raw transactions of the Hitec wire on a programming port (shared/outputs/hitec_port.h) and the wire driver the port's pin is handed to (protocols/hitec/rp2350).

A port is free, the KST page's or this page's, never two of them. Not kept: a restart finds the port free.

◆ s_kst

kst_port_t s_kst
extern

The KST page: the wire protocol for KST and Chaservo servos on a programming port (shared/outputs/kst_port.h) and the wire driver the port's pin is handed to (protocols/kst/rp2350).

Not kept: a restart finds the port in PWM (pulse-width modulation) with no session.

◆ s_last_rx_ms

uint32_t s_last_rx_ms
extern

When a frame was last taken out of the controller; see iomcu_can.c.

When a frame was last taken out of the controller.

When a frame was last taken out of the controller; see iomcu_can.c.

can_service() empties both receive buffers every pass, so where this is read it is the age of the last frame on the bus rather than of the last one collected. The flash windows are opened against it: this core answers nothing while it writes, and the two buffers hold 260us of frames. Zero until the first frame, so a board that has heard nothing since boot reads as a quiet bus, which is what it has.

◆ s_now_ms

uint32_t s_now_ms
extern

The pass's clock, used by everything the pass reaches – including the page callbacks, which run inside can_service() and have no now of their own.

Read at the top of the loop and once more before its tail, and nowhere else. The second read is there because two things in a pass can stop this core for longer than a pass lasts: a flash window, and a printf to a USB host. See the loop for why that matters to what is measured after them.

Every timeout in this application is a wrap-safe unsigned subtraction of two timestamps. A second reading of the clock inside a pass can be a millisecond ahead of the pass's own, and a stamp ahead of the now it is later compared against subtracts to 4,294,967,295ms – past every timeout there is. A CHANNELS write stamped that way reads as stale in the same pass and is put back to rest; a save stamped that way skips the settle and the quiet-bus wait and takes its flash window inside the request burst it was meant to wait out.

◆ s_outputs

outputs_t s_outputs
extern

Every output, behind one set of rules.

The pages above are the wire format; the rules (arming, clamping, slew and the silence timeout) live in shared/outputs and nowhere else, so this end and the panel cannot answer them differently.

The output pages address bank channels 0..LINK_OUT_CHANNELS-1 directly. The throttle lives above that range, so the control page commands it without colliding with a CHANNELS-page write, and a motor command keeps the control page's priority on the wire.

◆ s_pd_rate

uint8_t s_pd_rate
extern

the rate it runs at, 0..6

◆ s_prog

prog_port_t s_prog
extern

The PROG page: the programming ports, outputs of their own kind with their own pins (shared/outputs/prog_port.h).

Pin, slew, endpoints and function are kept; the pulse's switch and the tester's target are not.

◆ s_refused

uint32_t s_refused
extern

CAN frames received and refused since power-up, published on the STATUS page (LINK_ST_REFUSED_LO and _HI).

Counted in two places, both shared code: a receive buffer with no frame the link carries in it (mcp2515_recv_next()) and a frame link_can_decode() refuses (link_can_decode_counted()). Wraps at 2^32.

◆ s_sense

sense_page_t s_sense
extern

The SENSE and SERVO_SENSE pages: the current monitors' set-up, kept, and the pins it holds.

Core 1 reads the parts (sense_core1.h); this core gives it its orders and publishes what it hands back.

◆ s_sense_snap

sense_snap_t s_sense_snap
extern

Core 1's last snapshot.

The pins it said it still holds are the page's (sense_page_held()): a bus moved or closed keeps its old pins from the outputs until core 1 has let them go, about 1ms.

◆ s_servo

servo_page_t s_servo
extern

The SERVO page: the PWM target's frame rate and the sweep.

Not kept.

◆ s_stage

out_stage_t s_stage
extern

The binding BIND_CFG and BIND_OUT hold prepared; see iomcu_bind.c.

A binding prepared and taken whole (protocol 4.10): BIND_CFG and BIND_OUT hold a CHAN_CFG and an OUTPUTS page that are not in force, and a write of BIND's COMMIT that names their CRC (cyclic redundancy check) puts both in force or neither.

The binding BIND_CFG and BIND_OUT hold prepared; see iomcu_bind.c.

shared/outputs/out_stage.c decides; this is the glue to the two pages' own rules in iomcu_pages.c. Not kept in flash: it starts as the pages in force at boot.

◆ s_state

iomcu_state_t s_state
extern

The register images of the pages in iomcu_state_t.

What iomcu.h declares and describes.

The register images of the pages in iomcu_state_t.

◆ s_supply

supply_page_t s_supply
extern

The SUPPLY page and the PD mini it drives on a PIO UART.

Not kept.

◆ s_tone

tone_page_t s_tone
extern

The TONE page: the phase tap's set-up, kept, and the beeps core 1 hears on it.

Core 0 owns the PIO state machine and the DMA ring (tone_cap.c in protocols/phase_tap/rp2350); core 1 reads and detects (tone_core1.c).