|
rcbench
Servo and ESC test bench: panel, IOmcu and shared C
|
The panel's half of the SENSE (0x2B), SERVO_SENSE (0x2C) and SERVO_WIN (0x31) link pages: what is written to SENSE, in what order, what is read from the three pages and how often, and what a read means for the operator. More...
Go to the source code of this file.
Data Structures | |
| struct | sense_setup_t |
| The set-up as SETUP INTERFACES has it. More... | |
| struct | sense_link_op_t |
| One exchange the SENSE link asks the caller to make. More... | |
| struct | sense_link_win_t |
| One 50ms window of INA3221 CH1, as SERVO_WIN carries it. More... | |
| struct | sense_link_meter_t |
| What the servo rail's meter is chosen from (servo_source.h), as of the last exchange. More... | |
| struct | sense_link_t |
| The panel's state of the SENSE link page. More... | |
| struct | sense_link_enc_t |
| The output encoder's angle as last read. More... | |
Macros | |
| #define | SENSE_LINK_MINOR 7u |
| The protocol minor that has SENSE and SERVO_SENSE. | |
| #define | SENSE_LINK_ENC_MINOR 9u |
| The protocol minor that has SENSE's output encoder. | |
| #define | SENSE_LINK_WIN_MINOR LINK_MINOR_SERVO_WIN |
| The protocol minor that has SERVO_WIN and SENSE's RESETS. | |
| #define | SENSE_LINK_SETTLE_MS 500u |
| How long a set-up rests after its last edit before it is written: a held + or - on SETUP steps a value about 30 times a second, and each write is a flash save at the IOmcu. | |
| #define | SENSE_LINK_READ_MS 40u |
| SENSE's read-only registers are due this long after the last read, while a part is enabled: under the 50ms poll, so every BENCH poll reads them – 20Hz – however its exchanges move it, and a bench sample has the ESC's figures and the INA228's totals of the same poll. | |
| #define | SENSE_LINK_TOTALS_MS 100u |
| The INA228's totals from a SENSE read younger than this are used over BENCH's: two polls, so one read that went unanswered does not drop the count back to BENCH's 1mAh and 0.1Wh rounding for a sample. | |
| #define | SENSE_LINK_SERVO_MS 40u |
| SERVO_SENSE's windows and channel flags are due this long after the last read while the INA3221 is enabled: under the 50ms poll, so every poll reads them and every 50ms window is seen – its mean the filter, its highest current and lowest voltage the spikes. | |
| #define | SENSE_LINK_WIN_MS 40u |
| SERVO_WIN's header and two newest windows are due this long after the last read while the INA3221 is enabled with CH1: under the 50ms poll, so every poll reads them. | |
| #define | SENSE_LINK_WIN_HEAD ((unsigned)LINK_SW_ENTRY(2, 0)) |
| The registers of that read, and the windows they carry. | |
| #define | SENSE_LINK_WIN_HEAD_WINDOWS 2u |
| #define | SENSE_LINK_WIN_ALL_MS 100u |
| The whole page is read instead once this long has passed since a read last left no window owed: two windows, after which a third can have closed. | |
| #define | SENSE_LINK_GRACE_MS 2500u |
| A part enabled and not online this long after its set-up was taken, or first read, is said not to answer: the IOmcu scans the bus again every 1000ms while a part is missing. | |
| #define | SENSE_LINK_BUS_RETRY_MS 5000u |
| A bus frame refused on pins something else holds is offered again this often: freeing the pin on OUTPUTS or SUPPLY lets it through. | |
| #define | SENSE_LINK_STALE_MS 500u |
| A SENSE read older than this gives no ESC figures. | |
| #define | SENSE_LINK_STATUS_COUNT ((unsigned)LINK_SN_COUNT - (unsigned)LINK_SN_FLAGS) |
| The registers read from SENSE: FLAGS to the last, AS5600_STILL_MS's neighbour; and without the encoder FLAGS to ESC_FLAGS. | |
| #define | SENSE_LINK_STATUS_COUNT_V48 ((unsigned)LINK_SN_COUNT_V48 - (unsigned)LINK_SN_FLAGS) |
| #define | SENSE_LINK_SERVO_COUNT ((unsigned)LINK_SS_CH_FLAGS + 1u) |
| And from SERVO_SENSE: the three channels' windows, WINDOW and CH_FLAGS. | |
| #define | SENSE_LINK_NO_ANSWER (-1) |
| What came of an exchange: ACK or DATA, a NACK's reason, or none. | |
| #define | SENSE_LINK_ACK 0 |
| #define | SENSE_LINK_EV_SETUP |
| The events about the set-up asked, which sense_link_event_stands() judges: what ends them is an edit on SETUP and a write the page takes. | |
| #define | SENSE_LINK_WINDOW_MS 50u |
| One window of the IOmcu's, in ms: SENSE_WINDOW_MS. | |
| #define | SENSE_LINK_EVENT_GAP_MS 5000u |
| How long an event handed out by sense_link_event() has the alert band before the next one is handed out. | |
Enumerations | |
| enum | sense_link_part_t { SENSE_LINK_INA228 = 0 , SENSE_LINK_INA3221 = 1 } |
| The two parts, for the accessors. | |
| enum | { SENSE_LINK_EV_NO_PAGE = 0x0001 , SENSE_LINK_EV_PINS_UNSET = 0x0002 , SENSE_LINK_EV_SAME_ADDR = 0x0004 , SENSE_LINK_EV_BUS_REFUSED = 0x0008 , SENSE_LINK_EV_I228_REFUSED = 0x0010 , SENSE_LINK_EV_I3221_REFUSED = 0x0020 , SENSE_LINK_EV_I228_SILENT = 0x0040 , SENSE_LINK_EV_I3221_SILENT = 0x0080 , SENSE_LINK_EV_I228_WRONG = 0x0100 , SENSE_LINK_EV_I3221_WRONG = 0x0200 , SENSE_LINK_EV_STUCK = 0x0400 , SENSE_LINK_EV_I228_CLIPPED = 0x0800 , SENSE_LINK_EV_I3221_CLIPPED = 0x1000 , SENSE_LINK_EV_STORE_OFF = 0x2000 , SENSE_LINK_EV_ENC_OLD = 0x4000 , SENSE_LINK_EV_ENC_SILENT = 0x8000 , SENSE_LINK_EV_ENC_MAGNET = 0x10000 } |
| Things the caller tells the operator about, each once. More... | |
| enum | sense_link_op_kind_t { SENSE_LINK_OP_NONE = 0 , SENSE_LINK_OP_READ_SETUP , SENSE_LINK_OP_OFF , SENSE_LINK_OP_I228 , SENSE_LINK_OP_I3221 , SENSE_LINK_OP_BUS , SENSE_LINK_OP_IDENTITY , SENSE_LINK_OP_STATUS , SENSE_LINK_OP_SERVO , SENSE_LINK_OP_WIN , SENSE_LINK_OP_WIN_ALL } |
| The exchange sense_link_next() asks for. More... | |
| enum | { SENSE_LINK_ROW_I228 = 0x0001 , SENSE_LINK_ROW_I3221 = 0x0002 , SENSE_LINK_ROW_ENC = 0x0004 , SENSE_LINK_ROW_PINS = 0x0008 , SENSE_LINK_ROW_I228_ADDR = 0x0010 , SENSE_LINK_ROW_I228_SHUNT = 0x0020 , SENSE_LINK_ROW_I228_MAX = 0x0040 , SENSE_LINK_ROW_I3221_ADDR = 0x0080 , SENSE_LINK_ROW_I3221_SHUNT = 0x0100 , SENSE_LINK_ROW_I3221_CH = 0x0200 } |
| The rows of SETUP INTERFACES, for sense_link_unheld(). More... | |
Functions | |
| void | sense_link_init (sense_link_t *s) |
| Sets up the SENSE link state. | |
| void | sense_link_lost (sense_link_t *s) |
| The link went: nothing on the page is known, and nothing is read or written until it comes up again. | |
| void | sense_link_came_up (sense_link_t *s, uint16_t minor, uint32_t now_ms) |
An IOmcu answered with protocol minor minor. | |
| void | sense_link_want (sense_link_t *s, const sense_setup_t *w, uint32_t now_ms) |
| The set-up SETUP names now. | |
| bool | sense_link_next (sense_link_t *s, uint32_t now_ms, bool idle, sense_link_op_t *op) |
The next exchange owed at now_ms, into op; false for none. | |
| void | sense_link_done (sense_link_t *s, int result, const uint16_t *regs, uint32_t now_ms) |
How the exchange sense_link_next() gave went: SENSE_LINK_ACK with the registers read (regs, op.n of them; NULL for a write), a NACK reason, or SENSE_LINK_NO_ANSWER. | |
| void | sense_link_faults (sense_link_t *s, uint16_t faults) |
| STATUS's faults word, as the caller last read it. | |
| uint32_t | sense_link_events (sense_link_t *s) |
| The events since the last call, SENSE_LINK_EV_*, and cleared. | |
| uint32_t | sense_link_event (sense_link_t *s, uint32_t now_ms) |
| One event for the alert band, which shows one line and replaces it with the next: the most pressing waiting – no page, a set-up not sent or refused, a stuck bus, a part not answering, another identity, a clipped reading, the store off – cleared, and the rest kept. | |
| bool | sense_link_event_stands (const sense_link_t *s, uint32_t ev) |
Whether what ev, one SENSE_LINK_EV_* bit, says still holds now. | |
| void | sense_link_event_back (sense_link_t *s, uint32_t ev) |
| Put back an event sense_link_event() handed out that never reached the band – another alert replaced it first – with what it was raised with, so it is handed out again after the gap. | |
| bool | sense_link_settled (const sense_link_t *s) |
| Whether nothing is owed: the page holds the set-up asked, less the frames it refused. | |
| 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. | |
| uint16_t | sense_link_flags (const sense_link_t *s) |
| FLAGS as last read, 0 before any read. | |
| bool | sense_link_win_on (const sense_link_t *s) |
| Whether the INA3221's windows come from SERVO_WIN: the IOmcu has the page and its SENSE page enables the INA3221 with CH1. | |
| 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. | |
| 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. | |
| 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. | |
| 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. | |
| 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 (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. | |
| bool | sense_link_enc_on (const sense_link_t *s) |
| Whether the encoder is set up on the page: enabled there, and 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. | |
| 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_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. | |
| 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. | |
| 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. | |
The panel's half of the SENSE (0x2B), SERVO_SENSE (0x2C) and SERVO_WIN (0x31) link pages: what is written to SENSE, in what order, what is read from the three pages and how often, and what a read means for the operator.
The IOmcu reads the two current monitors and the output encoder (an AS5600 angle sensor); the panel sets them up from SETUP INTERFACES and reads what they measured. An IOmcu whose protocol minor is below SENSE_LINK_MINOR has neither page, and nothing is sent to it: not a write and not a read. One below SENSE_LINK_ENC_MINOR has no encoder: ENABLE bit 2 is not written, SENSE 26 to 31 are not read, and an encoder enabled on SETUP raises SENSE_LINK_EV_ENC_OLD. One below SENSE_LINK_WIN_MINOR has no SERVO_WIN and no RESETS: nothing is sent to SERVO_WIN, and the INA3221's windows are SERVO_SENSE's last one per read.
The set-up is three frames of four registers: the bus (ENABLE to KHZ), the INA228 (4 to 7) and the INA3221 (8 to 11). The page judges every frame against the whole set-up it would leave, so the order is fixed:
Writes go out only while the caller says the bank is idle – the page refuses any change while it drives – and only once the set-up has rested SENSE_LINK_SETTLE_MS since its last edit, because the IOmcu keeps each change in flash. A frame the page refuses is not written again until the set-up changes – except a bus frame whose SDA and SCL are one I2C block's pair, refused for pins something else holds, which is offered again every SENSE_LINK_BUS_RETRY_MS and said once. Two set-ups are not written at all, and said once per edit: a part enabled with SDA or SCL unset, and both parts enabled on one address; neither part is enabled on the page then.
After a write is taken, the identity page is read again: its capability bits 3 and 4 say what the SENSE set-up enables, and change only with a SENSE write.
While the page enables a part, SENSE 12 to 25 – to 31 with the encoder – are read every SENSE_LINK_READ_MS and, while it enables the INA3221, SERVO_SENSE 0 to 13 every SENSE_LINK_SERVO_MS. From those reads come the events the caller tells the operator about, each once: a part enabled and not answering, a part that answers with another identity, the bus stuck, and a reading clipped at the top of its range.
The window ring. While the page of a 4.11 IOmcu enables the INA3221 with CH1, SERVO_WIN's registers 0 to 15 – the header and the two newest windows – are read every SENSE_LINK_WIN_MS, and SENSE's status read goes to register 31 for RESETS, as it does with the encoder. Each CH1 window number is handed over once, oldest first (sense_link_take_win()):
Pure C, no link of its own: the caller makes each exchange and reports how it went. Control task only.
SPDX-License-Identifier: MIT
| #define SENSE_LINK_EV_SETUP |
The events about the set-up asked, which sense_link_event_stands() judges: what ends them is an edit on SETUP and a write the page takes.
| anonymous enum |
Things the caller tells the operator about, each once.
| Enumerator | |
|---|---|
| SENSE_LINK_EV_NO_PAGE | A part is enabled and the IOmcu has no SENSE page. |
| SENSE_LINK_EV_PINS_UNSET | A part is enabled with SDA or SCL unset: none is enabled. |
| SENSE_LINK_EV_SAME_ADDR | Both parts enabled on one address: neither is. |
| SENSE_LINK_EV_BUS_REFUSED | The page refused the bus frame: the pins, as a rule. |
| SENSE_LINK_EV_I228_REFUSED | The page refused the INA228's frame: its shunt and range. |
| SENSE_LINK_EV_I3221_REFUSED | The page refused the INA3221's frame. |
| SENSE_LINK_EV_I228_SILENT | The INA228 is enabled and does not answer at its address. |
| SENSE_LINK_EV_I228_WRONG | Something answers at the INA228's address with another identity. |
| SENSE_LINK_EV_STUCK | SDA held low; the IOmcu clocks it free. |
| SENSE_LINK_EV_I228_CLIPPED | The INA228's current read at the end of its range. |
| SENSE_LINK_EV_I3221_CLIPPED | An INA3221 channel read 163.8mV across its shunt; see sense_link_clipped_channel(). |
| SENSE_LINK_EV_STORE_OFF | STATUS fault bit 6: the IOmcu saves nothing this boot. |
| SENSE_LINK_EV_ENC_OLD | The encoder is enabled and the IOmcu is older than 4.9. |
| SENSE_LINK_EV_ENC_SILENT | The encoder is enabled and does not answer at 0x36, or something answers there that is not an AS5600. |
| SENSE_LINK_EV_ENC_MAGNET | The encoder answers and its magnet is missing, too weak or too strong; see sense_link_enc_magnet(). Said once while the magnet bits (MD, ML, MH) stay as they were said, across the set-ups an edit on SETUP writes; said again when a bit changes – a weak magnet that goes missing, a missing one that comes back weak, a weak one that reads strong – when the field read right in between, after the encoder was said not to answer, after a set-up that switches it off, and after a link-up. |
| anonymous enum |
The rows of SETUP INTERFACES, for sense_link_unheld().
| Enumerator | |
|---|---|
| SENSE_LINK_ROW_I228 | INA228 on or off |
| SENSE_LINK_ROW_I3221 | INA3221 on or off |
| SENSE_LINK_ROW_ENC | AS5600 on or off |
| SENSE_LINK_ROW_PINS | Sensor SDA and SCL |
| enum sense_link_op_kind_t |
The exchange sense_link_next() asks for.
| 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.
| s | The link state. |
| part | The part. |
| void sense_link_came_up | ( | sense_link_t * | s, |
| uint16_t | minor, | ||
| uint32_t | now_ms ) |
An IOmcu answered with protocol minor minor.
Below SENSE_LINK_MINOR it has neither page and nothing is sent to it, and a part enabled on SETUP raises SENSE_LINK_EV_NO_PAGE.
| s | The link state. |
| minor | The IOmcu's protocol minor version. |
| now_ms | The time, in ms. |
| 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.
| s | The link state. |
| void sense_link_done | ( | sense_link_t * | s, |
| int | result, | ||
| const uint16_t * | regs, | ||
| uint32_t | now_ms ) |
How the exchange sense_link_next() gave went: SENSE_LINK_ACK with the registers read (regs, op.n of them; NULL for a write), a NACK reason, or SENSE_LINK_NO_ANSWER.
| s | The link state. |
| result | The result: an acknowledgement, a NACK's reason or SENSE_LINK_NO_ANSWER. |
| regs | The registers read, or NULL for a write. |
| now_ms | The time, in ms. |
| 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.
| s | The link state. |
| now_ms | The time, in ms. |
| out | Receives the angle. |
| 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.
| s | The link state. |
| 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.
| s | The link state. |
| now_ms | The time, in ms. |
| bool sense_link_enc_on | ( | const sense_link_t * | s | ) |
Whether the encoder is set up on the page: enabled there, and read.
| s | The link state. |
| 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.
| s | The link state. |
| now_ms | The time, in ms. |
| v_ok | Receives the valid bit of the voltage. |
| volts | Receives the voltage, in V. |
| i_ok | Receives the valid bit of the current. |
| amps | Receives the current, in A. |
| uint32_t sense_link_event | ( | sense_link_t * | s, |
| uint32_t | now_ms ) |
One event for the alert band, which shows one line and replaces it with the next: the most pressing waiting – no page, a set-up not sent or refused, a stuck bus, a part not answering, another identity, a clipped reading, the store off – cleared, and the rest kept.
0 while none waits or while the last one handed out is younger than SENSE_LINK_EVENT_GAP_MS at now_ms.
| s | The link state. |
| now_ms | The time, in ms. |
| void sense_link_event_back | ( | sense_link_t * | s, |
| uint32_t | ev ) |
Put back an event sense_link_event() handed out that never reached the band – another alert replaced it first – with what it was raised with, so it is handed out again after the gap.
A clipped event takes its channel back. An event about an IOmcu is not put back once the link has gone.
| s | The link state. |
| ev | The event to put back. |
| 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.
| s | The link state. |
| part | The part. |
| 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.
| s | The link state. |
| part | The part. |
| bool sense_link_event_stands | ( | const sense_link_t * | s, |
| uint32_t | ev ) |
Whether what ev, one SENSE_LINK_EV_* bit, says still holds now.
For the events about the set-up asked: SENSE_LINK_EV_PINS_UNSET and SENSE_LINK_EV_SAME_ADDR while the settings ask it; a refusal – SENSE_LINK_EV_BUS_REFUSED, _I228_REFUSED, _I3221_REFUSED – until the page is known to hold the frame as asked: not refused, and written and taken. A refused value stepped back on SETUP ends it once the IOmcu takes the frame; the rest and the write take SENSE_LINK_SETTLE_MS and a poll. With no IOmcu answering a refusal stands. True for every other event: what a read raised ends with the band's own time.
The caller takes back an alert it showed for such an event once this is false; sense_link_event() drops one waiting that is over.
| s | The link state. |
| ev | One SENSE_LINK_EV_* bit. |
| uint32_t sense_link_events | ( | sense_link_t * | s | ) |
The events since the last call, SENSE_LINK_EV_*, and cleared.
| s | The link state. |
| void sense_link_faults | ( | sense_link_t * | s, |
| uint16_t | faults ) |
STATUS's faults word, as the caller last read it.
| s | The link state. |
| faults | The STATUS faults word. |
| uint16_t sense_link_flags | ( | const sense_link_t * | s | ) |
FLAGS as last read, 0 before any read.
| s | The link state. |
| 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.
| s | The link state. |
| part | The part. |
| 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.
| s | The link state. |
| sda | Receives the SDA pin, or -1; may be NULL. |
| scl | Receives the SCL pin, or -1; may be NULL. |
| 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.
| s | The link state. |
| uint16_t sense_link_i3221_dmohm | ( | const sense_link_t * | s | ) |
The INA3221's shunt on the page, 0.1mOhm.
| s | The link state. |
| 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).
| s | The link state. |
| part | The part. |
| void sense_link_init | ( | sense_link_t * | s | ) |
Sets up the SENSE link state.
| s | The link state to set up. |
| void sense_link_lost | ( | sense_link_t * | s | ) |
The link went: nothing on the page is known, and nothing is read or written until it comes up again.
| s | The link state. |
| 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.
| s | The link state. |
| out | Receives the meter's choice. |
| bool sense_link_next | ( | sense_link_t * | s, |
| uint32_t | now_ms, | ||
| bool | idle, | ||
| sense_link_op_t * | op ) |
The next exchange owed at now_ms, into op; false for none.
Writes only while idle: the bank is disarmed here and at the far end. The caller makes the exchange and reports with sense_link_done().
| s | The link state. |
| now_ms | The time, in ms. |
| idle | true while the bank is disarmed here and at the far end. |
| op | Receives the exchange owed. |
| 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.
| s | The link state. |
| 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.
| s | The link state. |
| int sense_link_scl | ( | const sense_link_t * | s | ) |
The SCL pin asked, -1 for unset.
| s | The link state. |
| int sense_link_sda | ( | const sense_link_t * | s | ) |
The pins asked, -1 for unset: what SENSE_LINK_EV_BUS_REFUSED names.
| s | The link state. |
| 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.
| s | The link state. |
| map | true when the INA3221 parts go by SENSE_MAP. |
| 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.
| s | The link state. |
| held | true while SENSE_MAP holds the map SETUP asks. |
| bool sense_link_settled | ( | const sense_link_t * | s | ) |
Whether nothing is owed: the page holds the set-up asked, less the frames it refused.
| s | The link state. |
| 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.
| s | The link state. |
| caps | Receives the capability bits. |
| 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.
| s | The link state. |
| out | Receives the 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.
| s | The link state. |
| b | Receives the window for the log. |
| 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.
| s | The link state. |
| now_ms | The time, in ms. |
| charge_cmah | Receives the charge, in 0.01mAh. |
| energy_cwh | Receives the energy, in 0.01Wh. |
| 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.
| s | The link state. |
| void sense_link_want | ( | sense_link_t * | s, |
| const sense_setup_t * | w, | ||
| uint32_t | now_ms ) |
The set-up SETUP names now.
A part enabled while an IOmcu without the page answers raises SENSE_LINK_EV_NO_PAGE. A set-up with a value outside the page's range – a zeroed snapshot – is ignored: nothing is asked, and nothing is written for it.
| s | The link state. |
| w | The set-up SETUP names. |
| now_ms | The time, in ms. |
| 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.
| s | The link state. |
| w | The ring window. |
| b | Receives the log fields. |
| 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.
| s | The link state. |
| bool sense_link_win_on | ( | const sense_link_t * | s | ) |
Whether the INA3221's windows come from SERVO_WIN: the IOmcu has the page and its SENSE page enables the INA3221 with CH1.
| s | The link state. |
| 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.
| s | The link state. |