|
|
|
@@ -36,6 +36,7 @@
|
|
|
|
|
#include "app_raw.h"
|
|
|
|
|
#include "inv_imu_extfunc.h"
|
|
|
|
|
#include "inv_imu_driver.h"
|
|
|
|
|
#include "inv_imu_transport.h"
|
|
|
|
|
#include "ble_nus.h"
|
|
|
|
|
#include "nrf_log.h"
|
|
|
|
|
#include "nrf_log_ctrl.h"
|
|
|
|
@@ -45,6 +46,7 @@
|
|
|
|
|
#include "main.h"
|
|
|
|
|
#include "debug_print.h"
|
|
|
|
|
#include "nrf_delay.h"
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@@ -168,9 +170,9 @@ int configure_imu_device(void)
|
|
|
|
|
/* High-resolution FIFO mode: 20-bit data, FSR locked to 16g/2000dps */
|
|
|
|
|
rc |= inv_imu_enable_high_resolution_fifo(&icm_driver);
|
|
|
|
|
} else {
|
|
|
|
|
/* Standard mode: accel +/-4g, gyro +/-2000dps FSR */
|
|
|
|
|
/* Standard mode: accel +/-4g, gyro +/-500dps FSR */
|
|
|
|
|
rc |= inv_imu_set_accel_fsr(&icm_driver, ACCEL_CONFIG0_FS_SEL_4g);
|
|
|
|
|
rc |= inv_imu_set_gyro_fsr(&icm_driver, GYRO_CONFIG0_FS_SEL_2000dps);
|
|
|
|
|
rc |= inv_imu_set_gyro_fsr(&icm_driver, GYRO_CONFIG0_FS_SEL_500dps);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (USE_LOW_NOISE_MODE) {
|
|
|
|
@@ -580,3 +582,423 @@ int imu_read_direct(void)
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------
|
|
|
|
|
* mtb? FIFO capture support
|
|
|
|
|
*
|
|
|
|
|
* Uses the ICM42670P internal FIFO at 25 Hz. The FIFO is started when mtb?
|
|
|
|
|
* begins, then drained after piezo raa: completion and sent as rim: packets.
|
|
|
|
|
* rim payload: u16 BE total_sample_count, then per sample accel(6B)+gyro(6B) from each 16B FIFO record.
|
|
|
|
|
*
|
|
|
|
|
* Timing (tune for MTB latency vs BLE reliability):
|
|
|
|
|
* - IMU_FIFO_ENABLE_SETTLE_MS: after accel/gyro on, before 2nd FIFO flush (first start only).
|
|
|
|
|
* - IMU_FIFO_RIM_POST_TX_MS: gap between rim notifications only (not after final packet).
|
|
|
|
|
* -------------------------------------------------------------------------------------- */
|
|
|
|
|
#define IMU_FIFO_PACKET_SIZE_BYTES FIFO_16BYTES_PACKET_SIZE
|
|
|
|
|
#define IMU_FIFO_MAX_PACKET_COUNT 258
|
|
|
|
|
#define IMU_FIFO_READ_RECORDS_PER_BURST 14
|
|
|
|
|
#define IMU_FIFO_ACCEL_OFFSET 1
|
|
|
|
|
#define IMU_FIFO_GYRO_OFFSET 7
|
|
|
|
|
#define IMU_FIFO_ENABLE_SETTLE_MS 35U
|
|
|
|
|
#define IMU_FIFO_RIM_POST_TX_MS 8U
|
|
|
|
|
#define RIM_SAMPLE_SIZE_BYTES 12
|
|
|
|
|
#define RIM_PACKET_HEADER_BYTES 6 /* "rim:" + u16 BE total_sample_count */
|
|
|
|
|
#define RIM_MAX_SAMPLE_BYTES (BLE_NUS_MAX_DATA_LEN - 2 - RIM_PACKET_HEADER_BYTES)
|
|
|
|
|
#define RIM_SAMPLES_PER_PACKET (RIM_MAX_SAMPLE_BYTES / RIM_SAMPLE_SIZE_BYTES)
|
|
|
|
|
|
|
|
|
|
static bool s_fifo_capture_active = false;
|
|
|
|
|
|
|
|
|
|
static void imu_serif_make(struct inv_imu_serif *serif)
|
|
|
|
|
{
|
|
|
|
|
serif->context = 0;
|
|
|
|
|
serif->read_reg = inv_io_hal_read_reg;
|
|
|
|
|
serif->write_reg = inv_io_hal_write_reg;
|
|
|
|
|
serif->max_read = 1024 * 32;
|
|
|
|
|
serif->max_write = 1024 * 32;
|
|
|
|
|
serif->serif_type = SERIF_TYPE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int imu_fifo_driver_prepare(void)
|
|
|
|
|
{
|
|
|
|
|
struct inv_imu_serif icm_serif;
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] prepare: TWI reinit + setup_imu_device\r\n");
|
|
|
|
|
inv_i2c_master_uninitialize();
|
|
|
|
|
inv_i2c_master_initialize();
|
|
|
|
|
|
|
|
|
|
imu_serif_make(&icm_serif);
|
|
|
|
|
rc = setup_imu_device(&icm_serif);
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] prepare: setup_imu_device rc=%d\r\n", rc);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void imu_fifo_power_off(void)
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] power_off: disable gyro/accel, FIFO off, active=0\r\n");
|
|
|
|
|
(void)inv_imu_disable_gyro(&icm_driver);
|
|
|
|
|
(void)inv_imu_disable_accel(&icm_driver);
|
|
|
|
|
(void)inv_imu_configure_fifo(&icm_driver, INV_IMU_FIFO_DISABLED);
|
|
|
|
|
s_fifo_capture_active = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int imu_fifo_capture_start(void)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] capture_start: enter active=%u\r\n", (unsigned)s_fifo_capture_active);
|
|
|
|
|
|
|
|
|
|
if (s_fifo_capture_active)
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] capture_start: skip (already active)\r\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc = imu_fifo_driver_prepare();
|
|
|
|
|
if (rc != 0)
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] prepare fail %d\r\n", rc);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] capture_start: FSR/ODR/FIFO stream, settle %ums\r\n",
|
|
|
|
|
(unsigned)IMU_FIFO_ENABLE_SETTLE_MS);
|
|
|
|
|
rc |= inv_imu_set_accel_fsr(&icm_driver, ACCEL_CONFIG0_FS_SEL_4g);
|
|
|
|
|
rc |= inv_imu_set_gyro_fsr(&icm_driver, GYRO_CONFIG0_FS_SEL_500dps);
|
|
|
|
|
rc |= inv_imu_set_accel_frequency(&icm_driver, ACCEL_CONFIG0_ODR_25_HZ);
|
|
|
|
|
rc |= inv_imu_set_gyro_frequency(&icm_driver, GYRO_CONFIG0_ODR_25_HZ);
|
|
|
|
|
rc |= inv_imu_set_accel_ln_bw(&icm_driver, IMU_FIFO_MTB_ACCEL_LN_BW);
|
|
|
|
|
rc |= inv_imu_set_gyro_ln_bw(&icm_driver, IMU_FIFO_MTB_GYRO_LN_BW);
|
|
|
|
|
rc |= inv_imu_disable_high_resolution_fifo(&icm_driver);
|
|
|
|
|
rc |= inv_imu_configure_fifo(&icm_driver, INV_IMU_FIFO_ENABLED);
|
|
|
|
|
{
|
|
|
|
|
uint8_t fifo_cfg1;
|
|
|
|
|
rc |= inv_imu_read_reg(&icm_driver, FIFO_CONFIG1, 1, &fifo_cfg1);
|
|
|
|
|
fifo_cfg1 &= ~FIFO_CONFIG1_FIFO_MODE_MASK;
|
|
|
|
|
fifo_cfg1 |= FIFO_CONFIG1_FIFO_MODE_STREAM;
|
|
|
|
|
rc |= inv_imu_write_reg(&icm_driver, FIFO_CONFIG1, 1, &fifo_cfg1);
|
|
|
|
|
}
|
|
|
|
|
rc |= inv_imu_reset_fifo(&icm_driver);
|
|
|
|
|
rc |= inv_imu_enable_accel_low_noise_mode(&icm_driver);
|
|
|
|
|
rc |= inv_imu_enable_gyro_low_noise_mode(&icm_driver);
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] capture_start: delay %ums\r\n", (unsigned)IMU_FIFO_ENABLE_SETTLE_MS);
|
|
|
|
|
dr_sd_delay_ms(IMU_FIFO_ENABLE_SETTLE_MS);
|
|
|
|
|
rc |= inv_imu_reset_fifo(&icm_driver);
|
|
|
|
|
|
|
|
|
|
if (rc != 0)
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] start fail %d\r\n", rc);
|
|
|
|
|
imu_fifo_power_off();
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s_fifo_capture_active = true;
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] capture_start: OK active=1 rc_accum=%d\r\n", rc);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void imu_fifo_send_rim_packets(uint16_t total_sample_count)
|
|
|
|
|
{
|
|
|
|
|
static uint8_t rim_buf[BLE_NUS_MAX_DATA_LEN];
|
|
|
|
|
uint16_t record_idx = 0;
|
|
|
|
|
uint16_t pkt = 0;
|
|
|
|
|
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] rim_send: total_samples=%u max_per_pkt=%u\r\n",
|
|
|
|
|
(unsigned)total_sample_count, (unsigned)RIM_SAMPLES_PER_PACKET);
|
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
uint16_t sample_count = total_sample_count - record_idx;
|
|
|
|
|
uint16_t dst_idx = RIM_PACKET_HEADER_BYTES;
|
|
|
|
|
uint16_t i;
|
|
|
|
|
|
|
|
|
|
if (sample_count > RIM_SAMPLES_PER_PACKET)
|
|
|
|
|
{
|
|
|
|
|
sample_count = RIM_SAMPLES_PER_PACKET;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rim_buf[0] = 'r'; rim_buf[1] = 'i'; rim_buf[2] = 'm'; rim_buf[3] = ':';
|
|
|
|
|
rim_buf[4] = (uint8_t)(total_sample_count >> 8);
|
|
|
|
|
rim_buf[5] = (uint8_t)(total_sample_count & 0xFF);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < sample_count; i++)
|
|
|
|
|
{
|
|
|
|
|
const uint8_t *record = &icm_driver.fifo_data[(record_idx + i) * IMU_FIFO_PACKET_SIZE_BYTES];
|
|
|
|
|
memcpy(&rim_buf[dst_idx], &record[IMU_FIFO_ACCEL_OFFSET], 6);
|
|
|
|
|
dst_idx += 6;
|
|
|
|
|
memcpy(&rim_buf[dst_idx], &record[IMU_FIFO_GYRO_OFFSET], 6);
|
|
|
|
|
dst_idx += 6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] rim_send: pkt=%u samples=%u bytes=%u words=%u\r\n",
|
|
|
|
|
(unsigned)pkt, (unsigned)sample_count, (unsigned)dst_idx, (unsigned)(dst_idx / 2));
|
|
|
|
|
dr_binary_tx_safe(rim_buf, dst_idx / 2);
|
|
|
|
|
record_idx += sample_count;
|
|
|
|
|
pkt++;
|
|
|
|
|
if (record_idx < total_sample_count)
|
|
|
|
|
{
|
|
|
|
|
dr_sd_delay_ms(IMU_FIFO_RIM_POST_TX_MS);
|
|
|
|
|
}
|
|
|
|
|
} while (record_idx < total_sample_count);
|
|
|
|
|
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] rim_send: done packets=%u\r\n", (unsigned)pkt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int imu_fifo_read_records(uint16_t record_count)
|
|
|
|
|
{
|
|
|
|
|
int rc = 0;
|
|
|
|
|
uint16_t record_idx = 0;
|
|
|
|
|
uint16_t burst_n = 0;
|
|
|
|
|
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] fifo_read: records=%u burst_max=%u\r\n",
|
|
|
|
|
(unsigned)record_count, (unsigned)IMU_FIFO_READ_RECORDS_PER_BURST);
|
|
|
|
|
|
|
|
|
|
while ((record_idx < record_count) && (rc == 0))
|
|
|
|
|
{
|
|
|
|
|
uint16_t burst_records = record_count - record_idx;
|
|
|
|
|
uint16_t burst_bytes;
|
|
|
|
|
|
|
|
|
|
if (burst_records > IMU_FIFO_READ_RECORDS_PER_BURST)
|
|
|
|
|
{
|
|
|
|
|
burst_records = IMU_FIFO_READ_RECORDS_PER_BURST;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
burst_bytes = burst_records * IMU_FIFO_PACKET_SIZE_BYTES;
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] fifo_read: burst=%u idx=%u n=%u bytes=%u\r\n",
|
|
|
|
|
(unsigned)burst_n, (unsigned)record_idx, (unsigned)burst_records, (unsigned)burst_bytes);
|
|
|
|
|
rc |= inv_imu_read_reg(&icm_driver,
|
|
|
|
|
FIFO_DATA,
|
|
|
|
|
burst_bytes,
|
|
|
|
|
&icm_driver.fifo_data[record_idx * IMU_FIFO_PACKET_SIZE_BYTES]);
|
|
|
|
|
|
|
|
|
|
record_idx += burst_records;
|
|
|
|
|
burst_n++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] fifo_read: done bursts=%u rc=%d\r\n", (unsigned)burst_n, rc);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Invensense inv_imu_get_data_from_fifo(): header 0x80 with all payload bytes zero = invalid placeholder. */
|
|
|
|
|
static bool imu_fifo_record_is_invalid_placeholder(const uint8_t *rec)
|
|
|
|
|
{
|
|
|
|
|
uint16_t i;
|
|
|
|
|
|
|
|
|
|
if (rec[0] != 0x80u)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
for (i = 1u; i < IMU_FIFO_PACKET_SIZE_BYTES; i++)
|
|
|
|
|
{
|
|
|
|
|
if (rec[i] != 0u)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint16_t imu_fifo_compact_placeholder_records(uint8_t *fifo, uint16_t record_count)
|
|
|
|
|
{
|
|
|
|
|
uint16_t w;
|
|
|
|
|
uint16_t r;
|
|
|
|
|
const uint16_t sz = IMU_FIFO_PACKET_SIZE_BYTES;
|
|
|
|
|
|
|
|
|
|
for (r = 0, w = 0; r < record_count; r++)
|
|
|
|
|
{
|
|
|
|
|
uint8_t *rec = fifo + (r * sz);
|
|
|
|
|
|
|
|
|
|
if (imu_fifo_record_is_invalid_placeholder(rec))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (w != r)
|
|
|
|
|
{
|
|
|
|
|
memcpy(fifo + (w * sz), rec, sz);
|
|
|
|
|
}
|
|
|
|
|
w++;
|
|
|
|
|
}
|
|
|
|
|
return w;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int16_t imu_fifo_record_gyro_axis(const uint8_t *rec, uint8_t axis)
|
|
|
|
|
{
|
|
|
|
|
const uint8_t *p = &rec[IMU_FIFO_GYRO_OFFSET + ((uint16_t)axis * 2u)];
|
|
|
|
|
|
|
|
|
|
if (icm_driver.endianness_data == INTF_CONFIG0_DATA_BIG_ENDIAN)
|
|
|
|
|
{
|
|
|
|
|
return (int16_t)((uint16_t)p[0] << 8 | p[1]);
|
|
|
|
|
}
|
|
|
|
|
return (int16_t)((uint16_t)p[1] << 8 | p[0]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Invensense: gyro axis == INVALID_VALUE_FIFO (0x8000) when not valid in this FIFO record. */
|
|
|
|
|
static bool imu_fifo_record_is_invalid_gyro(const uint8_t *rec)
|
|
|
|
|
{
|
|
|
|
|
uint8_t axis;
|
|
|
|
|
|
|
|
|
|
for (axis = 0; axis < 3u; axis++)
|
|
|
|
|
{
|
|
|
|
|
if (imu_fifo_record_gyro_axis(rec, axis) != INVALID_VALUE_FIFO)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint16_t imu_fifo_compact_invalid_gyro_records(uint8_t *fifo, uint16_t record_count)
|
|
|
|
|
{
|
|
|
|
|
uint16_t w;
|
|
|
|
|
uint16_t r;
|
|
|
|
|
const uint16_t sz = IMU_FIFO_PACKET_SIZE_BYTES;
|
|
|
|
|
|
|
|
|
|
for (r = 0, w = 0; r < record_count; r++)
|
|
|
|
|
{
|
|
|
|
|
uint8_t *rec = fifo + (r * sz);
|
|
|
|
|
|
|
|
|
|
if (imu_fifo_record_is_invalid_gyro(rec))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (w != r)
|
|
|
|
|
{
|
|
|
|
|
memcpy(fifo + (w * sz), rec, sz);
|
|
|
|
|
}
|
|
|
|
|
w++;
|
|
|
|
|
}
|
|
|
|
|
return w;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint16_t imu_fifo_normalize_for_rim(uint8_t *fifo, uint16_t n)
|
|
|
|
|
{
|
|
|
|
|
const uint16_t sz = IMU_FIFO_PACKET_SIZE_BYTES;
|
|
|
|
|
|
|
|
|
|
#if (IMU_FIFO_RIM_TARGET_SAMPLES > 0)
|
|
|
|
|
if (n > (uint16_t)IMU_FIFO_RIM_TARGET_SAMPLES)
|
|
|
|
|
{
|
|
|
|
|
const uint16_t drop = (uint16_t)(n - (uint16_t)IMU_FIFO_RIM_TARGET_SAMPLES);
|
|
|
|
|
|
|
|
|
|
memmove(fifo, fifo + ((uint32_t)drop * sz), (uint32_t)IMU_FIFO_RIM_TARGET_SAMPLES * sz);
|
|
|
|
|
n = (uint16_t)IMU_FIFO_RIM_TARGET_SAMPLES;
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] normalize: capped to newest %u samples\r\n",
|
|
|
|
|
(unsigned)IMU_FIFO_RIM_TARGET_SAMPLES);
|
|
|
|
|
}
|
|
|
|
|
(void)sz;
|
|
|
|
|
#elif (IMU_FIFO_RIM_MIN_SAMPLES > 0)
|
|
|
|
|
if (n < (uint16_t)IMU_FIFO_RIM_MIN_SAMPLES)
|
|
|
|
|
{
|
|
|
|
|
while (n < (uint16_t)IMU_FIFO_RIM_MIN_SAMPLES && n < IMU_FIFO_MAX_PACKET_COUNT)
|
|
|
|
|
{
|
|
|
|
|
memset(fifo + ((uint32_t)n * sz), 0, sz);
|
|
|
|
|
n++;
|
|
|
|
|
}
|
|
|
|
|
if (n < (uint16_t)IMU_FIFO_RIM_MIN_SAMPLES)
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] normalize: MIN=%u unreachable, using %u\r\n",
|
|
|
|
|
(unsigned)IMU_FIFO_RIM_MIN_SAMPLES, (unsigned)n);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
(void)sz;
|
|
|
|
|
#endif
|
|
|
|
|
return n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int imu_fifo_capture_stop_and_send_rim(void)
|
|
|
|
|
{
|
|
|
|
|
int rc = 0;
|
|
|
|
|
uint8_t count_raw[2] = {0};
|
|
|
|
|
uint16_t packet_count;
|
|
|
|
|
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: enter active=%u\r\n", (unsigned)s_fifo_capture_active);
|
|
|
|
|
|
|
|
|
|
if (!s_fifo_capture_active)
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: not active -> empty rim\r\n");
|
|
|
|
|
imu_fifo_send_rim_packets(0);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc |= inv_imu_switch_on_mclk(&icm_driver);
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: mclk on rc=%d\r\n", rc);
|
|
|
|
|
|
|
|
|
|
rc |= inv_imu_read_reg(&icm_driver, FIFO_COUNTH, 2, count_raw);
|
|
|
|
|
packet_count = (uint16_t)count_raw[0] | ((uint16_t)count_raw[1] << 8);
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: FIFO_COUNT raw[0]=0x%02X [1]=0x%02X -> records=%u\r\n",
|
|
|
|
|
count_raw[0], count_raw[1], (unsigned)packet_count);
|
|
|
|
|
|
|
|
|
|
if (packet_count > IMU_FIFO_MAX_PACKET_COUNT)
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: clamp %u -> %u\r\n",
|
|
|
|
|
(unsigned)packet_count, (unsigned)IMU_FIFO_MAX_PACKET_COUNT);
|
|
|
|
|
packet_count = IMU_FIFO_MAX_PACKET_COUNT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((rc == 0) && (packet_count > 0))
|
|
|
|
|
{
|
|
|
|
|
uint16_t before_count = packet_count;
|
|
|
|
|
|
|
|
|
|
rc |= imu_fifo_read_records(packet_count);
|
|
|
|
|
if (rc == 0)
|
|
|
|
|
{
|
|
|
|
|
packet_count = imu_fifo_compact_placeholder_records(icm_driver.fifo_data, packet_count);
|
|
|
|
|
if (before_count != packet_count)
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: dropped %u invalid FIFO placeholder record(s)\r\n",
|
|
|
|
|
(unsigned)(before_count - packet_count));
|
|
|
|
|
}
|
|
|
|
|
before_count = packet_count;
|
|
|
|
|
packet_count = imu_fifo_compact_invalid_gyro_records(icm_driver.fifo_data, packet_count);
|
|
|
|
|
if (before_count != packet_count)
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: dropped %u invalid-gyro FIFO record(s)\r\n",
|
|
|
|
|
(unsigned)(before_count - packet_count));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: skip read (rc=%d count=%u)\r\n", rc, (unsigned)packet_count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((rc == 0) && (IMU_FIFO_RIM_DROP_LEADING_SAMPLES > 0U) && (packet_count > 0U))
|
|
|
|
|
{
|
|
|
|
|
const uint16_t drop_req = (uint16_t)IMU_FIFO_RIM_DROP_LEADING_SAMPLES;
|
|
|
|
|
const uint16_t drop = (drop_req < packet_count) ? drop_req : packet_count;
|
|
|
|
|
const uint16_t sz = IMU_FIFO_PACKET_SIZE_BYTES;
|
|
|
|
|
uint8_t *const fifo = icm_driver.fifo_data;
|
|
|
|
|
|
|
|
|
|
packet_count = (uint16_t)(packet_count - drop);
|
|
|
|
|
memmove(fifo, fifo + ((uint32_t)drop * sz), (uint32_t)packet_count * sz);
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: dropped %u leading sample(s), remain=%u\r\n",
|
|
|
|
|
(unsigned)drop, (unsigned)packet_count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rc == 0)
|
|
|
|
|
{
|
|
|
|
|
const uint16_t after_norm = imu_fifo_normalize_for_rim(icm_driver.fifo_data, packet_count);
|
|
|
|
|
|
|
|
|
|
if (after_norm != packet_count)
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: normalize %u -> %u samples (TARGET/MIN)\r\n",
|
|
|
|
|
(unsigned)packet_count, (unsigned)after_norm);
|
|
|
|
|
}
|
|
|
|
|
packet_count = after_norm;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rc |= inv_imu_switch_off_mclk(&icm_driver);
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: mclk off rc=%d\r\n", rc);
|
|
|
|
|
|
|
|
|
|
if (rc != 0)
|
|
|
|
|
{
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] drain fail %d\r\n", rc);
|
|
|
|
|
imu_fifo_send_rim_packets(0);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: rim TX records=%u\r\n", (unsigned)packet_count);
|
|
|
|
|
imu_fifo_send_rim_packets(packet_count);
|
|
|
|
|
DBG_PRINTF("[IMU FIFO] stop_send: OK\r\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|