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

The sensor bus on the RP2350's I2C block. More...

#include "sense_i2c.h"
#include "hardware/gpio.h"
#include "hardware/i2c.h"
#include "hardware/sync.h"
#include "pico/stdlib.h"
#include "link_pages.h"

Functions

static void block_init (void)
 The block reset and set up again: a transaction that failed leaves it part way through one, and restart_on_next as that one left it.
static bool lines_high (void)
 Tells whether SDA and SCL both read high.
static bool lines_rise (uint32_t us)
 Both lines high within us: the pull-ups have the bus.
bool sense_i2c_open (uint8_t sda, uint8_t scl)
 The block on sda and scl.
static void release (uint8_t pin)
 Returns a pin to a plain input with its pull-down, as at reset.
void sense_i2c_close (void)
 The block reset and its pins back to plain inputs, pulled down as at reset.
static sense_err_t idle_low (void)
 Lines that stay low at idle, told apart: held by a part, or held by nothing on a bus without pull-ups – pins nothing is wired to.
static sense_err_t lines_idle (void)
 Both lines high within SENSE_I2C_IDLE_US, as a transaction needs them: SENSE_OK, or what idle_low() makes of them.
static sense_err_t classify (int rc, size_t want)
 A pico-sdk result as the bus sees it: want bytes was success.
static sense_err_t done (sense_err_t e, uint32_t irq)
 The end of every transaction: a failed one leaves the block reset.
sense_err_t sense_i2c_read (void *ctx, uint8_t addr, uint8_t reg, uint8_t *buf, size_t n)
 sense_i2c_t's read: the register pointer, a repeated START and n bytes, most significant first.
sense_err_t sense_i2c_write (void *ctx, uint8_t addr, uint8_t reg, const uint8_t *buf, size_t n)
 sense_i2c_t's write: the register pointer and n bytes.
sense_err_t sense_i2c_ask (uint8_t addr)
 Whether addr acknowledges: the address and one byte read.
static void line (uint8_t pin, bool high)
 Open drain by hand: low is the pin driven 0, high is the pin let go to its pull-up.
static void scl_release (void)
 SCL let go, and given SENSE_I2C_CLEAR_STRETCH_US to rise: a part may hold it low a while.
void sense_i2c_recover (void)
 The bus clear: the block reset, SCL clocked 9 times as an open-drain GPIO, so a part that was sending a byte when the bus stopped finishes it and lets SDA go; then a STOP (SDA rising while SCL is high); then the block set up again on its pins (NXP UM10204 ยง3.1.16).

Variables

static i2c_inst_t * s_i2c
static uint8_t s_sda
static uint8_t s_scl
static bool s_open

Detailed Description

The sensor bus on the RP2350's I2C block.

See sense_i2c.h.

SPDX-License-Identifier: MIT

Function Documentation

◆ classify()

sense_err_t classify ( int rc,
size_t want )
static

A pico-sdk result as the bus sees it: want bytes was success.

The SDK reports a NACK of the address, an arbitration lost and any other abort as one PICO_ERROR_GENERIC, so the lines tell them apart: back high is a NACK on a working bus, held low is a part holding it, and low with nothing holding them is a NACK on a bus without pull-ups.

Parameters
rcThe pico-sdk result: a byte count, or a negative error.
wantThe byte count that is success.
Returns
SENSE_OK, SENSE_TIMEOUT, SENSE_NACK, or what lines_idle() returns.

◆ done()

sense_err_t done ( sense_err_t e,
uint32_t irq )
static

The end of every transaction: a failed one leaves the block reset.

Parameters
eThe transaction's result.
irqInterrupt state to restore.
Returns
The value of e.

◆ idle_low()

sense_err_t idle_low ( void )
static

Lines that stay low at idle, told apart: held by a part, or held by nothing on a bus without pull-ups – pins nothing is wired to.

The pads' own pull-ups are switched on for at most SENSE_I2C_PROBE_US: a line nothing holds rises on them, and one a part drives low does not. They go off again either way. SENSE_NACK for lines that rose: nothing answers there, and no recovery is owed. SENSE_BUS_LOW otherwise.

Returns
SENSE_NACK when the lines rose, SENSE_BUS_LOW otherwise.

◆ line()

void line ( uint8_t pin,
bool high )
static

Open drain by hand: low is the pin driven 0, high is the pin let go to its pull-up.

Parameters
pinGPIO number.
highTrue to let the line go high, false to drive it low.

◆ lines_high()

bool lines_high ( void )
static

Tells whether SDA and SCL both read high.

Returns
True when both lines are high.

◆ lines_idle()

sense_err_t lines_idle ( void )
static

Both lines high within SENSE_I2C_IDLE_US, as a transaction needs them: SENSE_OK, or what idle_low() makes of them.

Returns
SENSE_OK when both lines are high within SENSE_I2C_IDLE_US, or what idle_low() returns.

◆ lines_rise()

bool lines_rise ( uint32_t us)
static

Both lines high within us: the pull-ups have the bus.

Parameters
usTime to wait, in microseconds.
Returns
True when both lines are high within us.

◆ release()

void release ( uint8_t pin)
static

Returns a pin to a plain input with its pull-down, as at reset.

Parameters
pinGPIO number.

◆ sense_i2c_ask()

sense_err_t sense_i2c_ask ( uint8_t addr)

Whether addr acknowledges: the address and one byte read.

Parameters
addrI2C address of the device.
Returns
SENSE_OK when the device acknowledges, or the error the transaction came to.

◆ sense_i2c_close()

void sense_i2c_close ( void )

The block reset and its pins back to plain inputs, pulled down as at reset.

Nothing when closed.

◆ sense_i2c_open()

bool sense_i2c_open ( uint8_t sda,
uint8_t scl )

The block on sda and scl.

False, and nothing touched, when they are not one block's pair on this package. Opening again closes first.

Parameters
sdaGPIO number of SDA.
sclGPIO number of SCL.
Returns
True when the pins are one block's pair on this package.

◆ sense_i2c_read()

sense_err_t sense_i2c_read ( void * ctx,
uint8_t addr,
uint8_t reg,
uint8_t * buf,
size_t n )

sense_i2c_t's read: the register pointer, a repeated START and n bytes, most significant first.

Parameters
ctxUnused.
addrI2C address of the device.
regRegister pointer, sent before the repeated START.
bufReceives n bytes.
nNumber of bytes to read. Zero is refused with SENSE_BAD_ARG.
Returns
SENSE_OK, or the error the transaction came to.

◆ sense_i2c_write()

sense_err_t sense_i2c_write ( void * ctx,
uint8_t addr,
uint8_t reg,
const uint8_t * buf,
size_t n )

sense_i2c_t's write: the register pointer and n bytes.

Parameters
ctxUnused.
addrI2C address of the device.
regRegister pointer, sent before the bytes.
bufThe bytes to write.
nNumber of bytes, 1 to 4. Other counts are refused with SENSE_BAD_ARG.
Returns
SENSE_OK, or the error the transaction came to.