Chipinterface API#

@file

A common communication interface API for interfacing signal processing libraries provided by Novelda to the X4 and X7 hardware sensors.

The chipinterface API is meant to simplify the integration of Novelda products into custom environments and is limited to general read/write transactions as well as 2 IO pins - one output for enabling the sensor and one input to detect interrupt events. Although it supports both I2C and SPI, only one variant is usually used per project. Therefore, integrators may focus on one interface for one specific sensor.

The proposed workflow is as follows:

  1. Add the provided high-level sensor library provided by Novelda into your project. You should see linker errors due to missing chipinterface functions.

  2. Find the missing functions below and implement them based upon the available documentation. Demo chipinterface implementations are available for the Zephyr OS and may serve as a blueprint.

  3. Always hook up a logic analyzer to the bus when testing your code.

type chipinterface_error_t#

Status code returned by most of the chipinterface functions.

static const chipinterface_error_t CHIPINTERFACE_SUCCESS#

The function call succeeded.

static const chipinterface_error_t CHIPINTERFACE_FAILURE#

The function call failed due to an error.

static const chipinterface_error_t CHIPINTERFACE_TIMEOUT#

The function timed out.

@see chipinterface_wait_us @see chipinterface_wait_for_interrupt

static const uint32_t CHIPINTERFACE_WAIT_FOREVER#

Represents an infinite wait time.

@see chipinterface_wait_us @see chipinterface_wait_for_interrupt

enum chipinterface_interrupt_state_t#

The current level of the interrupt line

The interrupt line can either be asserted or deasserted. Asserted usually means “high” while deasserted means “low”.

@see chipinterface_get_interrupt_state

enumerator chipinterface_interrupt_asserted#

The interrupt line is asserted

enumerator chipinterface_interrupt_deasserted#

The interrupt line is deasserted

enum chipinterface_polarity_t#

Clock polarity (CPOL) for SPI communication.

enumerator chipinterface_polarity_low#

The clock signal idles at the logical low voltage (CPOL = 0).

enumerator chipinterface_polarity_high#

The clock signal idles at the logical high voltage (CPOL = 1).

enum chipinterface_phase_t#

Clock phase (CPHA) for SPI communication.

enumerator chipinterface_phase_leading#

The first data bit is outputted immediately when CS activates. Subsequent bits are outputted when SCLK transitions to its idle voltage level. Sampling occurs when SCLK transitions from its idle voltage level (CPHA = 0).

enumerator chipinterface_phase_trailing#

The first data bit is outputted on SCLK’s first clock edge after CS activates. Subsequent bits are outputted when SCLK transitions from its idle voltage level. Sampling occurs when SCLK transitions to its idle voltage level (CPHA = 1).

enum chipinterface_bitorder_t#

Bit order for SPI communication.

enumerator chipinterface_bitorder_msb#

The most significant bit (MSB) is outputted first on the bus.

enumerator chipinterface_bitorder_lsb#

The least significant bit (LSB) is first outputted to the bus.

struct chipinterface_spi_config_t#

SPI clock configuration to be used for the connection. Novelda X4 and X7 sensors require a different SPI clock configuration. Novelda provides default values for their sensors.

@see chipinterface_default_x4_spi_config @see chipinterface_default_x7_spi_config

chipinterface_polarity_t clock_polarity#

Clock polarity

chipinterface_phase_t clock_phase#

Clock phase

chipinterface_bitorder_t bit_order#

Bit order

static const chipinterface_spi_config_t chipinterface_default_x4_spi_config#

SPI configuration to be used for communication to X4 sensors.

static const chipinterface_spi_config_t chipinterface_default_x7_spi_config#

SPI configuration to be used for communication to X7 sensors.

chipinterface_error_t chipinterface_set_chip_enabled(bool enabled)#

Enables and disables the sensor.

On the X4 this function controls the Enable pin. On the X7 this function controls the Reset pin. On both ICs the signal goes high when the sensor is enabled/running and low when the sensor is disabled/reset.

@param enabled true if the sensor should be enabled, otherwise false @return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_wait_us(uint32_t microseconds)#

Waits for a specified period in microseconds.

This function is called whenever the X4/7 drivers need to wait for the sensor. The underlying implementation is free to do whatever while waiting. It may yield the current thread or bring the whole system into a sleep mode or just busy-wait.

The actual time may not exactly match the desired period, but it must be at least as long as specified. Longer wait times will prolong the firmware upload, but the sensor will still work. Most of the time, this function is called with rather small values below 1000 microseconds. For wait times below the available tick resolution, consider to implement a busy-wait loop.

@param microseconds the timespan to wait in microseconds @return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_get_time_microseconds(uint32_t *microseconds)#

Determines the elapsed time in microseconds

In order to achieve a correct frame rate and when no interrupt is used, the elapsed time must be monitored. This function writes a monotonic increasing counter value into the output parameter @p microseconds. The timestamps may wrap around.

It is enough if the underlying implementation to provide a resolution of 1 ms, but it should not be less.

@param microseconds the current time stamp in microseconds @return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_create_i2c(uint32_t frequencyHz, uint8_t slave_address)#

Initializes the interface for I2C communication

This function initializes the hardware interface and gets it ready for communication. When using I2C this is the first function called by the Novelda driver and should be used to initialize other required hardware drivers.

@param frequencyHz the I2C clock frequency @param slave_address the address of the X4/X7 chip

@return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_delete_i2c()#

Deinitializes the chipinterface

This function should free up any resources acquired by chipinterface_create_i2c.

@return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_read_i2c(uint8_t *data, size_t size)#

Reads data from the sensor via I2C

This function reads data from the sensor hardware via I2C and stores to the buffer pointed to by @p data. That buffer is guaranteed to be @p size bytes large. The IO configuration has been set in chipinterface_create_i2c.

The implementation may read from the sensor in chunks.

@param data pointer to the internal buffer @param size number of bytes to read @return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_write_i2c(const uint8_t *data, size_t size)#

Writes data to the sensor via I2C

This function writes @p size bytes provided in the @p data buffer to the sensor hardware via I2C. The actual write may happen in chunks. The IO configuration has been set in chipinterface_create_i2c.

@param data pointer to the buffer containing the data to write @param size number of bytes to write @return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_create_spi(uint32_t frequencyHz, const chipinterface_spi_config_t *configuration)#

Initializes the interface for SPI communication

This function initializes the hardware interface and gets it ready for communication. When using SPI this is the first function called by the Novelda driver and should be used to initialize other required hardware drivers.

@param frequencyHz the SPI clock frequency @param configuration a pointer to a valid clock configuration object

The configuration object is a temporary argument. When needed by the chip interface implementation beyond this function call, the implementation must store an internal copy of the object.

The chip interface implementation may be tailored towards either X4 or X7 and is thus free to ignore frequencyHz and configuration entirely.

@see chipinterface_default_x4_spi_config @see chipinterface_default_x7_spi_config

@return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_delete_spi()#

Deinitializes the chipinterface

This function should free up any resources acquired by chipinterface_create_spi.

@return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_set_clock_frequency(uint32_t frequencyHz)#

Sets the SPI/I2C clock frequency

This function sets the SPI/I2C clock frequency at run-time to the specified value.

This function is only needed for X7 sensors.

@param frequencyHz the desired SPI/I2C clock frequency @return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_transfer_spi(const uint8_t *wdata, size_t wlength, uint8_t *rdata, size_t rlength)#

Transfers data from and to the sensor via SPI.

This function writes and reads data to and from the sensor using the SPI bus. The hardware must first send @p wlength bytes and then read in @p rlength bytes. So the resulting transaction on the bus is @p wlength + @p rlength bytes long.

@param wdata pointer to the buffer containing data to write @param wlength number of bytes to write @param rdata pointer to the buffer where incoming data should be stored @param rlength number of bytes to read @return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_get_interrupt_state(chipinterface_interrupt_state_t *state)#

Reads the current state of the interrupt line.

@param state Pointer to where the current state is written to @return CHIPINTERFACE_SUCCESS on success

chipinterface_error_t chipinterface_wait_for_interrupt(uint32_t microseconds)#

Waits up to a specified period for an interrupt

This function blocks and waits for an interrupt for @p microseconds time. If the interrupt line is already asserted, the function returns immediately. If @p microseconds is @p CHIPINTERFACE_WAIT_FOREVER, the function waits forever. While waiting, the underlying implementation may put the system into a low-power state or use busy-wait.

It is enough if the underlying implementation to provide a resolution of 1 ms.

@param microseconds The time to wait or @p CHIPINTERFACE_WAIT_FOREVER @return CHIPINTERFACE_SUCCESS on interrupts,

otherwise CHIPINTERFACE_TIMEOUT

uint32_t reverse_bits(uint32_t n)#

Reverse the bits per byte.

@param n The 32-bit integer whose bits are to be reversed. @return The 32-bit integer with reversed bits.

void reverse_bits_per_byte_buffer_u32(uint32_t *buf, size_t numElements)#

Reverse the bits for each individual byte in a buffer of specified length.

@param buf Pointer to the buffer. @param numElements Number of uint32_t elements in the buffer.

void reverse_bits_per_byte_buffer_u8(uint8_t *buf, size_t numElements)#

Reverse the bits for each individual byte in a buffer of specified length.

@param buf Pointer to the buffer. @param numElements Number of uint8_t elements in the buffer.

@note This is a wrapper around reverse_bits_per_byte(uint32_t n) which

operates on a single 32-bit word at a time. Thus the buffer is assumed to have a length and alignment matching that of uint32_t.