Post Go back to editing

The adxl367 uses fifo, non-interruptible mode

Thread Summary

The user is experiencing an issue where the FIFO of the ADXL367 accelerometer is always full (513 data points) when polled once per second, despite configuring it to store only 64 sets of three-axis data. The final answer suggests checking the FIFO configuration and ensuring the FIFO is being cleared after each read. The ADXL367 is configured in stream mode with a FIFO_SAMPLES register set to 64 and an ODR of 400Hz.
AI Generated Content

My intended purpose is to read the latest 64*2 sets of three-axis data from the FIFO, as configured in my setup: I have configured the FIFO in stream mode, set the FIFO_SAMPLES register to 64, and set the ODR to 400Hz. Of course, I'm not using interrupts but polling once per second to read data.

I believed that when reading from the FIFO via I2C, there should be 64*2 sets of three-axis data, with older data being discarded; however, in practice, I observe that the FIFO is always full (513 data points) when I read it, which is confusing to me. Could you help explain this?

My requirement is to poll the FIFO once per second to read data, and I expect the FIFO to keep only the latest 64 sets of data in the FIFO.

Here is my detailed code.

#include <stdlib.h>
#include "adxl367.h"
#include "nrf_drv_twi.h"
#include "sample_mode.h"
#include "nrf_delay.h"

static const nrf_drv_twi_t * p_twi;

uint32_t adxl367_set_register_value(uint8_t register_value, uint8_t register_address)
{
	uint8_t buffer[2] = {0};
	buffer[0] = register_address;
	buffer[1] = register_value;

	return nrf_drv_twi_tx(p_twi, I2C_AXI_ADDR, buffer, 2, false);
}

uint32_t adxl367_get_register_value(uint8_t* read_data, uint8_t register_address, uint8_t register_nb)
{
	int ret = 1;
	uint8_t buffer[64] = {0};
	
	if (register_address > ADXL367_REG_STATUS_2)
		return ret;
	
	ret = nrf_drv_twi_tx(p_twi, I2C_AXI_ADDR, &register_address, 1, false);
	if (ret)
		return ret;
	
	ret = nrf_drv_twi_rx(p_twi, I2C_AXI_ADDR, buffer, register_nb);
	if (ret)
		return ret;
	
	for(int index = 0; index < register_nb; index++)
		read_data[index] = buffer[index];

	return 0;
}

int adx1367_get_raw_xyz(uint16_t* x, uint16_t* y, uint16_t* z)
{
	uint8_t xyz_values[3] = {0};
	uint8_t reg_data = 0;

	adxl367_get_register_value(&reg_data, ADXL367_REG_STATUS, 1);
	if(reg_data & 1){
		adxl367_get_register_value(xyz_values, ADXL367_REG_XDATA, 3);	
		*x = xyz_values[0] << 6;	
		*y = xyz_values[1] << 6;	
		*z = xyz_values[2] << 6;

		if(*x & 0x2000){
			*x |= 0xC000;
		}

		if(*y & 0x2000){
			*y |= 0xC000;
		}

		if(*z & 0x2000){
			*z |= 0xC000;
		}
	}
	else{
		*x = 0;
		*y = 0;
		*z = 0;
	}
	return 0;
}

uint16_t adx1367_get_fifo_xyz(uint16_t *buff)
{
	uint8_t data_buff[512 * 2] = {0};
	uint16_t fifo_entries = 0;
	uint8_t reg_val[2] = {0};

	adxl367_get_register_value(&reg_val[0], ADXL367_REG_STATUS, 1);
	if(reg_val[0] & 1 << 2){
		adxl367_get_register_value(reg_val, ADXL367_REG_FIFO_ENTRIES_L, 2);
		fifo_entries = ((reg_val[1] & 0x03) << 8) | reg_val[0];
		if((0 == fifo_entries)){
			return 0;
		}
		
		adxl367_get_register_value(data_buff, ADXL367_REG_I2C_FIFO_DATA, fifo_entries);
		fifo_entries = (fifo_entries > SAMPLE_DEFAULT_AXI_HZ*6 ? SAMPLE_DEFAULT_AXI_HZ*6:fifo_entries);
		for(int index = 0; index < fifo_entries; index++){
			buff[index] = (data_buff[index * 2] << 6) + (data_buff[index*2 + 1] >> 2);
		}
		return fifo_entries;
	}
	
	return 0;
}

void adxl367_fifo_setup(void)
{
	sample_mode_info_t *p_sample = NULL;
	uint8_t reg_value = 0;

	p_sample = sample_config_get();
	
	// Set fifo stream mode
	adxl367_get_register_value(&reg_value, ADXL367_REG_FIFO_CONTROL, 1);
	reg_value &= ~(3);
	reg_value |= ADXL367_STREAM_MODE;

	// Set fifo sample x,y,z
	reg_value &= ~(0x0F << 3);

	// set fifo sample 64
	reg_value &= ~(1 << 2);
	adxl367_set_register_value(reg_value, ADXL367_REG_FIFO_CONTROL);


	// set fifo sample 64
	reg_value = 0;
	adxl367_get_register_value(&reg_value, ADXL367_REG_FIFO_SAMPLES, 1);
	reg_value = p_sample->sample_axi_hz;
	adxl367_set_register_value(reg_value, ADXL367_REG_FIFO_SAMPLES);
}

int adxl367_start(void)
{
	int status = 0;
	uint8_t reg_value = 0;

	//adxl367_fifo_setup();
	
	// set measure mode
	adxl367_get_register_value(&reg_value, ADXL367_REG_POWER_CTL, 1);
	reg_value &= ~(3);
	reg_value |= 2;
	
	status = adxl367_set_register_value(reg_value, ADXL367_REG_POWER_CTL);
	if (status)
		return -1;

	nrf_delay_ms(100);
	return 0;
}

int adxl367_stop(void)
{
	int status;
	uint8_t reg_value = 0;
	reg_value = 0;
	adxl367_get_register_value(&reg_value, ADXL367_REG_POWER_CTL, 1);

	// set standby mode
	reg_value &= ~(3);
	status = adxl367_set_register_value(reg_value, ADXL367_REG_POWER_CTL);
	if (status)
		return -1;

	nrf_delay_ms(50);
	return 0;
}

int ADXl367_Init(nrf_drv_twi_t *hi2c)
{
	int status;
	uint8_t reg_value = 0;
	
	p_twi = NULL;
	if(NULL == hi2c)
		return -1;

	p_twi = hi2c;
	
	/* Perform soft reset */
	status = adxl367_set_register_value(ADXL367_RESET_KEY, ADXL367_REG_SOFT_RESET);
	if (status)
		return -1;

	nrf_delay_ms(20);

	// check device id
	adxl367_get_register_value(&reg_value, ADXL367_REG_DEVID_AD, 1);
	if (reg_value != ADXL367_DEVICE_AD)
		return -1;

	adxl367_get_register_value(&reg_value, ADXL367_REG_PARTID, 1);
	if (reg_value != ADXL367_PART_ID)
		return -1;
	
	// set device output speed 200Hz and range to 4G
	reg_value = 0;
	adxl367_get_register_value(&reg_value, ADXL367_REG_FILTER_CTL, 1);
	reg_value &= ~(3 << 6);
	reg_value |= (1 << 6);
	reg_value &= ~7;
	reg_value |= 4;
	status = adxl367_set_register_value(reg_value, ADXL367_REG_FILTER_CTL);
	if (status)
		return -1;

	return 0;
}