Update AFBR to 1.4.4. Remove changing measurement modes. Add parameters. Default to Long range mode"

This commit is contained in:
AlexKlimaj
2023-04-05 11:21:24 -06:00
committed by Daniel Agar
parent 6d71224cdb
commit 7ff00db9c5
39 changed files with 6383 additions and 2957 deletions
@@ -33,6 +33,7 @@
/* Include Files */
#include "AFBRS50.hpp"
#include "argus_hal_test.h"
#include <lib/drivers/device/Device.hpp>
@@ -42,9 +43,6 @@
/*! Define the SPI baud rate (to be used in the SPI module). */
#define SPI_BAUD_RATE 5000000
#define LONG_RANGE_MODE_HZ 25
#define SHORT_RANGE_MODE_HZ 50
#include "s2pi.h"
#include "timer.h"
#include "argus_hal_test.h"
@@ -52,6 +50,7 @@
AFBRS50 *g_dev{nullptr};
AFBRS50::AFBRS50(uint8_t device_orientation):
ModuleParams(nullptr),
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::hp_default),
_px4_rangefinder(0, device_orientation)
{
@@ -61,6 +60,7 @@ AFBRS50::AFBRS50(uint8_t device_orientation):
device_id.devid_s.devtype = DRV_DIST_DEVTYPE_AFBRS50;
_px4_rangefinder.set_device_id(device_id.devid);
_px4_rangefinder.set_device_type(distance_sensor_s::MAV_DISTANCE_SENSOR_LASER);
}
AFBRS50::~AFBRS50()
@@ -70,12 +70,12 @@ AFBRS50::~AFBRS50()
perf_free(_sample_perf);
}
status_t AFBRS50::measurement_ready_callback(status_t status, void *data)
status_t AFBRS50::measurement_ready_callback(status_t status, argus_hnd_t *hnd)
{
if (!up_interrupt_context()) {
if (status == STATUS_OK) {
if (g_dev) {
g_dev->ProcessMeasurement(data);
g_dev->ProcessMeasurement(hnd);
}
} else {
@@ -86,35 +86,33 @@ status_t AFBRS50::measurement_ready_callback(status_t status, void *data)
return status;
}
void AFBRS50::ProcessMeasurement(void *data)
void AFBRS50::ProcessMeasurement(argus_hnd_t *hnd)
{
if (data != nullptr) {
perf_count(_sample_perf);
perf_count(_sample_perf);
argus_results_t res{};
status_t evaluate_status = Argus_EvaluateData(_hnd, &res, data);
argus_results_t res{};
status_t evaluate_status = Argus_EvaluateData(hnd, &res);
if ((evaluate_status == STATUS_OK) && (res.Status == STATUS_OK)) {
uint32_t result_mm = res.Bin.Range / (Q9_22_ONE / 1000);
float result_m = static_cast<float>(result_mm) / 1000.f;
int8_t quality = res.Bin.SignalQuality;
if ((evaluate_status == STATUS_OK) && (res.Status == STATUS_OK)) {
uint32_t result_mm = res.Bin.Range / (Q9_22_ONE / 1000);
float result_m = static_cast<float>(result_mm) / 1000.f;
int8_t quality = res.Bin.SignalQuality;
// Signal quality indicates 100% for good signals, 50% and lower for weak signals.
// 1% is an errored signal (not reliable). Signal Quality of 0% is unknown.
if (quality == 1) {
quality = 0;
}
// distance quality check
if (result_m > _max_distance) {
result_m = 0.0;
quality = 0;
}
_current_distance = result_m;
_current_quality = quality;
_px4_rangefinder.update(((res.TimeStamp.sec * 1000000ULL) + res.TimeStamp.usec), result_m, quality);
// Signal quality indicates 100% for good signals, 50% and lower for weak signals.
// 1% is an errored signal (not reliable). Signal Quality of 0% is unknown.
if (quality == 1) {
quality = 0;
}
// distance quality check
if (result_m > _max_distance) {
result_m = 0.0;
quality = 0;
}
_current_distance = result_m;
_current_quality = quality;
_px4_rangefinder.update(((res.TimeStamp.sec * 1000000ULL) + res.TimeStamp.usec), result_m, quality);
}
}
@@ -137,7 +135,37 @@ int AFBRS50::init()
// Initialize the S2PI hardware required by the API.
S2PI_Init(BROADCOM_AFBR_S50_S2PI_SPI_BUS, SPI_BAUD_RATE);
status_t status = Argus_Init(_hnd, BROADCOM_AFBR_S50_S2PI_SPI_BUS);
int32_t mode_param = _p_sens_afbr_mode.get();
if (mode_param < 0 || mode_param > 3) {
PX4_ERR("Invalid mode parameter: %li", mode_param);
return PX4_ERROR;
}
argus_mode_t mode = ARGUS_MODE_LONG_RANGE;
switch (mode_param) {
case 0:
mode = ARGUS_MODE_SHORT_RANGE;
break;
case 1:
mode = ARGUS_MODE_LONG_RANGE;
break;
case 2:
mode = ARGUS_MODE_HIGH_SPEED_SHORT_RANGE;
break;
case 3:
mode = ARGUS_MODE_HIGH_SPEED_LONG_RANGE;
break;
default:
break;
}
status_t status = Argus_InitMode(_hnd, BROADCOM_AFBR_S50_S2PI_SPI_BUS, mode);
if (status == STATUS_OK) {
uint32_t id = Argus_GetChipID(_hnd);
@@ -148,7 +176,6 @@ int AFBRS50::init()
PX4_INFO_RAW("AFBR-S50 Chip ID: %u, API Version: %u v%d.%d.%d\n", (uint)id, (uint)value, a, b, c);
argus_module_version_t mv = Argus_GetModuleVersion(_hnd);
argus_laser_type_t lt = Argus_GetLaserType(_hnd);
switch (mv) {
case AFBR_S50MV85G_V1:
@@ -168,19 +195,20 @@ int AFBRS50::init()
case AFBR_S50LV85D_V1:
_min_distance = 0.08f;
if (lt == LASER_H_V2X) {
_max_distance = 50.f;
PX4_INFO_RAW("AFBR-S50LX85D (v2)\n");
} else {
_max_distance = 30.f;
PX4_INFO_RAW("AFBR-S50LV85D (v1)\n");
}
_max_distance = 30.f;
_px4_rangefinder.set_min_distance(_min_distance);
_px4_rangefinder.set_max_distance(_max_distance);
_px4_rangefinder.set_fov(math::radians(6.f));
PX4_INFO_RAW("AFBR-S50LV85D\n");
break;
case AFBR_S50LX85D_V1:
_min_distance = 0.08f;
_max_distance = 50.f;
_px4_rangefinder.set_min_distance(_min_distance);
_px4_rangefinder.set_max_distance(_max_distance);
_px4_rangefinder.set_fov(math::radians(6.f));
PX4_INFO_RAW("AFBR-S50LX85D\n");
break;
case AFBR_S50MV68B_V1:
@@ -223,6 +251,9 @@ int AFBRS50::init()
ScheduleDelayed(_measure_interval);
return PX4_OK;
} else {
PX4_ERR("Argus_InitMode failed: %ld", status);
}
return PX4_ERROR;
@@ -230,6 +261,15 @@ int AFBRS50::init()
void AFBRS50::Run()
{
if (_parameter_update_sub.updated()) {
// clear update
parameter_update_s param_update;
_parameter_update_sub.copy(&param_update);
// update parameters from storage
ModuleParams::updateParams();
}
switch (_state) {
case STATE::TEST: {
if (_testing) {
@@ -243,7 +283,8 @@ void AFBRS50::Run()
break;
case STATE::CONFIGURE: {
status_t status = set_rate(SHORT_RANGE_MODE_HZ);
_current_rate = (uint32_t)_p_sens_afbr_s_rate.get();
status_t status = set_rate(_current_rate);
if (status != STATUS_OK) {
PX4_ERR("CONFIGURE status not okay: %i", (int)status);
@@ -251,24 +292,18 @@ void AFBRS50::Run()
ScheduleNow();
}
status = Argus_SetConfigurationDFMMode(_hnd, ARGUS_MODE_B, DFM_MODE_8X);
status = Argus_SetConfigurationDFMMode(_hnd, DFM_MODE_8X);
if (status != STATUS_OK) {
PX4_ERR("Argus_SetConfigurationDFMMode status not okay: %i", (int)status);
_state = STATE::STOP;
ScheduleNow();
}
status = Argus_SetConfigurationDFMMode(_hnd, ARGUS_MODE_A, DFM_MODE_8X);
status = Argus_SetConfigurationSmartPowerSaveEnabled(_hnd, false);
if (status != STATUS_OK) {
PX4_ERR("Argus_SetConfigurationDFMMode status not okay: %i", (int)status);
}
// start in short range mode
_mode = ARGUS_MODE_B;
set_mode(_mode);
if (status != STATUS_OK) {
PX4_ERR("CONFIGURE status not okay: %i", (int)status);
PX4_ERR("Argus_SetConfigurationSmartPowerSaveEnabled status not okay: %i", (int)status);
ScheduleNow();
} else {
@@ -288,7 +323,7 @@ void AFBRS50::Run()
}
}
UpdateMode();
Evaluate_rate();
}
break;
@@ -306,49 +341,41 @@ void AFBRS50::Run()
ScheduleDelayed(_measure_interval);
}
void AFBRS50::UpdateMode()
void AFBRS50::Evaluate_rate()
{
// only update mode if _current_distance is a valid measurement
if ((_current_distance > 0) && (_current_quality > 0)) {
// only update mode if _current_distance is a valid measurement and if the last rate switch was more than 1 second ago
if ((_current_distance > 0) && (_current_quality > 0) && ((hrt_absolute_time() - _last_rate_switch) > 1_s)) {
if ((_current_distance >= _long_range_threshold) && (_mode != ARGUS_MODE_A)) {
// change to long range mode
argus_mode_t mode = ARGUS_MODE_A;
status_t status = set_mode(mode);
status_t status = STATUS_OK;
if (status != STATUS_OK) {
PX4_ERR("set_mode status not okay: %i", (int)status);
}
if ((_current_distance >= (_p_sens_afbr_thresh.get() + _p_sens_afbr_hyster.get()))
&& (_current_rate != (uint32_t)_p_sens_afbr_l_rate.get())) {
status = set_rate(LONG_RANGE_MODE_HZ);
_current_rate = (uint32_t)_p_sens_afbr_l_rate.get();
status = set_rate(_current_rate);
if (status != STATUS_OK) {
PX4_ERR("set_rate status not okay: %i", (int)status);
} else {
PX4_INFO("switched to long range rate: %i", (int)_current_rate);
_last_rate_switch = hrt_absolute_time();
}
status = set_rate(LONG_RANGE_MODE_HZ);
} else if ((_current_distance <= (_p_sens_afbr_thresh.get() - _p_sens_afbr_hyster.get()))
&& (_current_rate != (uint32_t)_p_sens_afbr_s_rate.get())) {
_current_rate = (uint32_t)_p_sens_afbr_s_rate.get();
status = set_rate(_current_rate);
if (status != STATUS_OK) {
PX4_ERR("set_rate status not okay: %i", (int)status);
}
} else if ((_current_distance <= _short_range_threshold) && (_mode != ARGUS_MODE_B)) {
// change to short range mode
argus_mode_t mode = ARGUS_MODE_B;
status_t status = set_mode(mode);
if (status != STATUS_OK) {
PX4_ERR("set_mode status not okay: %i", (int)status);
}
status = set_rate(SHORT_RANGE_MODE_HZ);
if (status != STATUS_OK) {
PX4_ERR("set_rate status not okay: %i", (int)status);
} else {
PX4_INFO("switched to short range rate: %i", (int)_current_rate);
_last_rate_switch = hrt_absolute_time();
}
}
ScheduleDelayed(1000_ms); // don't switch again for at least 1 second
}
}
@@ -373,33 +400,6 @@ void AFBRS50::print_info()
get_info();
}
status_t AFBRS50::set_mode(argus_mode_t mode)
{
while (Argus_GetStatus(_hnd) != STATUS_IDLE) {
px4_usleep(1_ms);
}
status_t status = Argus_SetConfigurationMeasurementMode(_hnd, mode);
if (status != STATUS_OK) {
PX4_ERR("Argus_SetConfigurationMeasurementMode status not okay: %i", (int)status);
return status;
}
argus_mode_t current_mode;
status = Argus_GetConfigurationMeasurementMode(_hnd, &current_mode);
if (status != STATUS_OK) {
PX4_ERR("Argus_GetConfigurationMeasurementMode status not okay: %i", (int)status);
return status;
} else {
_mode = current_mode;
}
return status;
}
status_t AFBRS50::set_rate(uint32_t rate_hz)
{
while (Argus_GetStatus(_hnd) != STATUS_IDLE) {
@@ -429,13 +429,10 @@ status_t AFBRS50::set_rate(uint32_t rate_hz)
void AFBRS50::get_info()
{
argus_mode_t current_mode;
argus_dfm_mode_t dfm_mode;
Argus_GetConfigurationMeasurementMode(_hnd, &current_mode);
Argus_GetConfigurationDFMMode(_hnd, current_mode, &dfm_mode);
Argus_GetConfigurationDFMMode(_hnd, &dfm_mode);
PX4_INFO_RAW("distance: %.3fm\n", (double)_current_distance);
PX4_INFO_RAW("mode: %d\n", current_mode);
PX4_INFO_RAW("dfm mode: %d\n", dfm_mode);
PX4_INFO_RAW("rate: %u Hz\n", (uint)(1000000 / _measure_interval));
}
@@ -44,13 +44,16 @@
#include <drivers/drv_hrt.h>
#include <lib/drivers/rangefinder/PX4Rangefinder.hpp>
#include <lib/perf/perf_counter.h>
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/defines.h>
#include <px4_platform_common/module_params.h>
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/topics/parameter_update.h>
using namespace time_literals;
class AFBRS50 : public px4::ScheduledWorkItem
class AFBRS50 : public ModuleParams, public px4::ScheduledWorkItem
{
public:
AFBRS50(const uint8_t device_orientation = distance_sensor_s::ROTATION_DOWNWARD_FACING);
@@ -75,18 +78,16 @@ public:
private:
void Run() override;
void UpdateMode();
void Evaluate_rate();
void ProcessMeasurement(void *data);
void ProcessMeasurement(argus_hnd_t *hnd);
static status_t measurement_ready_callback(status_t status, void *data);
static status_t measurement_ready_callback(status_t status, argus_hnd_t *hnd);
void get_info();
status_t set_mode(argus_mode_t mode);
status_t set_rate(uint32_t rate_hz);
argus_hnd_t *_hnd{nullptr};
argus_mode_t _mode{ARGUS_MODE_B}; // Short-Range
enum class STATE : uint8_t {
TEST,
@@ -98,14 +99,24 @@ private:
PX4Rangefinder _px4_rangefinder;
hrt_abstime _measurement_time{0};
hrt_abstime _last_rate_switch{0};
perf_counter_t _sample_perf{perf_alloc(PC_INTERVAL, MODULE_NAME": sample interval")};
uint32_t _measure_interval{1000000 / 50}; // 50Hz
float _current_distance{0};
int8_t _current_quality{0};
const float _short_range_threshold = 4.0; //meters
const float _long_range_threshold = 6.0; //meters
float _max_distance;
float _min_distance;
uint32_t _current_rate{0};
uORB::Subscription _parameter_update_sub{ORB_ID(parameter_update)};
DEFINE_PARAMETERS(
(ParamInt<px4::params::SENS_AFBR_MODE>) _p_sens_afbr_mode,
(ParamInt<px4::params::SENS_AFBR_S_RATE>) _p_sens_afbr_s_rate,
(ParamInt<px4::params::SENS_AFBR_L_RATE>) _p_sens_afbr_l_rate,
(ParamInt<px4::params::SENS_AFBR_THRESH>) _p_sens_afbr_thresh,
(ParamInt<px4::params::SENS_AFBR_HYSTER>) _p_sens_afbr_hyster
);
};
@@ -85,6 +85,8 @@ static int gpio_falling_edge(int irq, void *context, void *arg)
status_t S2PI_Init(s2pi_slave_t defaultSlave, uint32_t baudRate_Bps)
{
(void)defaultSlave;
px4_arch_configgpio(BROADCOM_AFBR_S50_S2PI_CS);
s2pi_.spidev = px4_spibus_initialize(BROADCOM_AFBR_S50_S2PI_SPI_BUS);
@@ -107,11 +109,24 @@ status_t S2PI_Init(s2pi_slave_t defaultSlave, uint32_t baudRate_Bps)
* - #STATUS_BUSY: An SPI transfer is in progress.
* - #STATUS_S2PI_GPIO_MODE: The module is in GPIO mode.
*****************************************************************************/
status_t S2PI_GetStatus(void)
status_t S2PI_GetStatus(s2pi_slave_t slave)
{
(void)slave;
return s2pi_.Status;
}
status_t S2PI_TryGetMutex(s2pi_slave_t slave)
{
(void) slave;
return STATUS_OK;
}
void S2PI_ReleaseMutex(s2pi_slave_t slave)
{
(void) slave;
}
/*!***************************************************************************
* @brief Sets the SPI baud rate in bps.
* @param baudRate_Bps The default SPI baud rate in bauds-per-second.
@@ -135,8 +150,10 @@ status_t S2PI_SetBaudRate(uint32_t baudRate_Bps)
* switch back to ordinary SPI functionality.
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
*****************************************************************************/
status_t S2PI_CaptureGpioControl(void)
status_t S2PI_CaptureGpioControl(s2pi_slave_t slave)
{
(void)slave;
/* Check if something is ongoing. */
IRQ_LOCK();
status_t status = s2pi_.Status;
@@ -165,8 +182,10 @@ status_t S2PI_CaptureGpioControl(void)
* the #S2PI_CaptureGpioControl function.
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
*****************************************************************************/
status_t S2PI_ReleaseGpioControl(void)
status_t S2PI_ReleaseGpioControl(s2pi_slave_t slave)
{
(void)slave;
/* Check if something is ongoing. */
IRQ_LOCK();
status_t status = s2pi_.Status;
@@ -202,6 +221,8 @@ status_t S2PI_ReleaseGpioControl(void)
*****************************************************************************/
status_t S2PI_WriteGpioPin(s2pi_slave_t slave, s2pi_pin_t pin, uint32_t value)
{
(void)slave;
/* Check if pin is valid. */
if (pin > S2PI_IRQ || value > 1) {
return ERROR_INVALID_ARGUMENT;
@@ -228,6 +249,8 @@ status_t S2PI_WriteGpioPin(s2pi_slave_t slave, s2pi_pin_t pin, uint32_t value)
*****************************************************************************/
status_t S2PI_ReadGpioPin(s2pi_slave_t slave, s2pi_pin_t pin, uint32_t *value)
{
(void)slave;
/* Check if pin is valid. */
if (pin > S2PI_IRQ || !value) {
return ERROR_INVALID_ARGUMENT;
@@ -255,6 +278,8 @@ status_t S2PI_ReadGpioPin(s2pi_slave_t slave, s2pi_pin_t pin, uint32_t *value)
*****************************************************************************/
status_t S2PI_CycleCsPin(s2pi_slave_t slave)
{
(void)slave;
/* Check the driver status. */
IRQ_LOCK();
status_t status = s2pi_.Status;
@@ -372,8 +397,10 @@ status_t S2PI_TransferFrame(s2pi_slave_t spi_slave, uint8_t const *txData, uint8
* invoked with the #ERROR_ABORTED error byte.
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
*****************************************************************************/
status_t S2PI_Abort(void)
status_t S2PI_Abort(s2pi_slave_t slave)
{
(void)slave;
status_t status = s2pi_.Status;
/* Check if something is ongoing. */
@@ -405,6 +432,8 @@ status_t S2PI_Abort(void)
*****************************************************************************/
status_t S2PI_SetIrqCallback(s2pi_slave_t slave, s2pi_irq_callback_t callback, void *callbackData)
{
(void)slave;
s2pi_.IrqCallback = callback;
s2pi_.IrqCallbackData = callbackData;
@@ -430,5 +459,7 @@ status_t S2PI_SetIrqCallback(s2pi_slave_t slave, s2pi_irq_callback_t callback, v
*****************************************************************************/
uint32_t S2PI_ReadIrqPin(s2pi_slave_t slave)
{
(void)slave;
return px4_arch_gpioread(s2pi_.GPIOs[S2PI_IRQ]);
}
File diff suppressed because it is too large Load Diff
@@ -1,12 +1,12 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Defines the dynamic configuration adaption (DCA) setup parameters
* and data structure.
* @brief This file is part of the AFBR-S50 API.
* @details Defines the dynamic configuration adaption (DCA) setup parameters
* and data structure.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,34 +37,37 @@
#ifndef ARGUS_DCA_H
#define ARGUS_DCA_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup argusdca Dynamic Configuration Adaption
* @ingroup argusapi
* @defgroup argus_dca Dynamic Configuration Adaption
* @ingroup argus_api
*
* @brief Dynamic Configuration Adaption (DCA) parameter definitions and API functions.
* @brief Dynamic Configuration Adaption (DCA) parameter definitions and API functions.
*
* @details The DCA contains an algorithms that detect ambient conditions
* and adopt the device configuration to the changing parameters
* dynamically while operating the sensor. This is achieved by
* rating the currently received signal quality and changing the
* device configuration accordingly to the gathered information
* from the current measurement frame results before the next
* integration cycle starts.
* @details The DCA contains an algorithms that detect ambient conditions
* and adopt the device configuration to the changing parameters
* dynamically while operating the sensor. This is achieved by
* rating the currently received signal quality and changing the
* device configuration accordingly to the gathered information
* from the current measurement frame results before the next
* integration cycle starts.
*
* The DCA consists of the following features:
* - Static or Dynamic mode. The first is utilizing the nominal
* values while the latter is dynamically adopting between min.
* and max. value and starting from the nominal values.
* - Analog Integration Depth Adaption (from multiple patterns down to single pulses)
* - Optical Output Power Adaption
* - Pixel Input Gain Adaption (w/ ambient light rejection)
* - ADC Sensitivity (i.e. ADC Range) Adaption
* - Power Saving Ratio (to decrease the average output power and thus the current consumption)
* - All that features are heeding the Laser Safety limits.
* .
* The DCA consists of the following features:
* - Static or Dynamic mode. The first is utilizing the nominal
* values while the latter is dynamically adopting between min.
* and max. value and starting from the nominal values.
* - Analog Integration Depth Adaption (from multiple patterns down to single pulses)
* - Optical Output Power Adaption
* - Pixel Input Gain Adaption (w/ ambient light rejection)
* - ADC Sensitivity (i.e. ADC Range) Adaption
* - Power Saving Ratio (to decrease the average output power and thus the current consumption)
* - All that features are heeding the Laser Safety limits.
* .
*
* @addtogroup argusdca
* @addtogroup argus_dca
* @{
*****************************************************************************/
@@ -73,39 +76,26 @@
/*! The minimum amplitude threshold value. */
#define ARGUS_CFG_DCA_ATH_MIN (1U << 6U)
#define ARGUS_CFG_DCA_ATH_MIN (1U << 6U)
/*! The maximum amplitude threshold value. */
#define ARGUS_CFG_DCA_ATH_MAX (0xFFFFU)
#define ARGUS_CFG_DCA_ATH_MAX (0xFFFFU)
/*! The minimum saturated pixel threshold value. */
#define ARGUS_CFG_DCA_PXTH_MIN (1U)
#define ARGUS_CFG_DCA_PXTH_MIN (1U)
/*! The maximum saturated pixel threshold value. */
#define ARGUS_CFG_DCA_PXTH_MAX (33U)
#define ARGUS_CFG_DCA_PXTH_MAX (33U)
/*! The maximum analog integration depth in UQ10.6 format,
* i.e. the maximum pattern count per sample. */
#define ARGUS_CFG_DCA_DEPTH_MAX ((uq10_6_t)(ADS_SEQCT_N_MASK << (6U - ADS_SEQCT_N_SHIFT)))
#define ARGUS_CFG_DCA_DEPTH_MAX ((uq10_6_t)(0xFFC0U))
/*! The minimum analog integration depth in UQ10.6 format,
* i.e. the minimum pattern count per sample. */
#define ARGUS_CFG_DCA_DEPTH_MIN ((uq10_6_t)(1U)) // 1/64, i.e. 1/2 nibble
/*! The maximum optical output power, i.e. the maximum VCSEL high current in LSB. */
#define ARGUS_CFG_DCA_POWER_MAX_LSB (ADS_LASET_VCSEL_HC1_MASK >> ADS_LASET_VCSEL_HC1_SHIFT)
/*! The minimum optical output power, i.e. the minimum VCSEL high current in mA. */
#define ARGUS_CFG_DCA_POWER_MIN_LSB (1)
/*! The maximum optical output power, i.e. the maximum VCSEL high current in LSB. */
#define ARGUS_CFG_DCA_POWER_MAX (ADS0032_HIGH_CURRENT_LSB2MA(ARGUS_CFG_DCA_POWER_MAX_LSB + 1))
/*! The minimum optical output power, i.e. the minimum VCSEL high current in mA. */
#define ARGUS_CFG_DCA_POWER_MIN (1)
#define ARGUS_CFG_DCA_DEPTH_MIN ((uq10_6_t)(1U)) // 1/64, i.e. 1/2 nibble
/*! The dynamic configuration algorithm Pixel Input Gain stage count. */
@@ -139,9 +129,9 @@
/*!***************************************************************************
* @brief The dynamic configuration algorithm enable flags.
* @brief The dynamic configuration algorithm enable flags.
*****************************************************************************/
typedef enum {
typedef enum argus_dca_enable_t {
/*! @internal
*
* DCA is disabled and will be completely skipped.
@@ -160,9 +150,9 @@ typedef enum {
} argus_dca_enable_t;
/*!***************************************************************************
* @brief The DCA amplitude evaluation method.
* @brief The DCA amplitude evaluation method.
*****************************************************************************/
typedef enum {
typedef enum argus_dca_amplitude_mode_t {
/*! Evaluate the DCA amplitude as the maximum of all valid amplitudes. */
DCA_AMPLITUDE_MAX = 1U,
@@ -172,9 +162,9 @@ typedef enum {
} argus_dca_amplitude_mode_t;
/*!***************************************************************************
* @brief The dynamic configuration algorithm Optical Output Power stages enumerator.
* @brief The dynamic configuration algorithm Optical Output Power stages enumerator.
*****************************************************************************/
typedef enum {
typedef enum argus_dca_power_t {
/*! Use low output power stage. */
DCA_POWER_LOW = 0,
@@ -187,9 +177,9 @@ typedef enum {
} argus_dca_power_t;
/*!***************************************************************************
* @brief The dynamic configuration algorithm Pixel Input Gain stages enumerator.
* @brief The dynamic configuration algorithm Pixel Input Gain stages enumerator.
*****************************************************************************/
typedef enum {
typedef enum argus_dca_gain_t {
/*! Low gain stage. */
DCA_GAIN_LOW = 0,
@@ -206,113 +196,113 @@ typedef enum {
/*!***************************************************************************
* @brief State flags for the current frame.
* @details State flags determine the current state of the measurement frame:
* - [0]: #ARGUS_STATE_MEASUREMENT_MODE
* - [1]: #ARGUS_STATE_DUAL_FREQ_MODE
* - [2]: #ARGUS_STATE_MEASUREMENT_FREQ
* - [3]: #ARGUS_STATE_DEBUG_MODE
* - [4]: #ARGUS_STATE_WEAK_SIGNAL
* - [5]: #ARGUS_STATE_BGL_WARNING
* - [6]: #ARGUS_STATE_BGL_ERROR
* - [7]: #ARGUS_STATE_PLL_LOCKED
* - [8]: #ARGUS_STATE_LASER_WARNING
* - [9]: #ARGUS_STATE_LASER_ERROR
* - [10]: #ARGUS_STATE_HAS_DATA
* - [11]: #ARGUS_STATE_HAS_AUX_DATA
* - [12]: #ARGUS_STATE_DCA_MAX
* - [13]: DCA Power Stage
* - [14-15]: DCA Gain Stages
* .
* @brief State flags for the current frame.
* @details State flags determine the current state of the measurement frame:
* - [0]: #ARGUS_STATE_XTALK_MONITOR_ACTIVE
* - [1]: #ARGUS_STATE_DUAL_FREQ_MODE
* - [2]: #ARGUS_STATE_MEASUREMENT_FREQ
* - [3]: #ARGUS_STATE_DEBUG_MODE
* - [4]: #ARGUS_STATE_WEAK_SIGNAL
* - [5]: #ARGUS_STATE_BGL_WARNING
* - [6]: #ARGUS_STATE_BGL_ERROR
* - [7]: #ARGUS_STATE_PLL_LOCKED
* - [8]: #ARGUS_STATE_LASER_WARNING
* - [9]: #ARGUS_STATE_LASER_ERROR
* - [10]: #ARGUS_STATE_HAS_DATA
* - [11]: #ARGUS_STATE_HAS_AUX_DATA
* - [12]: #ARGUS_STATE_DCA_MAX
* - [13]: DCA Power Stage
* - [14-15]: DCA Gain Stages
* .
*****************************************************************************/
typedef enum {
typedef enum argus_state_t {
/*! No state flag set. */
ARGUS_STATE_NONE = 0,
/*! 0x0001: Measurement Mode.
* - 0: Mode A: Long Range / Medium Precision
* - 1: Mode B: Short Range / High Precision */
ARGUS_STATE_MEASUREMENT_MODE = 1U << 0U,
/*! 0x0001: Crosstalk Monitor is enabled and updating.
* - 0: Inactive: crosstalk monitor values are not updated,
* - 1: Active: crosstalk monitor values are updated. */
ARGUS_STATE_XTALK_MONITOR_ACTIVE = 1U << 0U,
/*! 0x0002: Dual Frequency Mode Enabled.
* - 0: Disabled: measurements with base frequency,
* - 1: Enabled: measurement with detuned frequency. */
* - 0: Disabled: measurements with base frequency,
* - 1: Enabled: measurement with detuned frequency. */
ARGUS_STATE_DUAL_FREQ_MODE = 1U << 1U,
/*! 0x0004: Measurement Frequency for Dual Frequency Mode
* (only if #ARGUS_STATE_DUAL_FREQ_MODE flag is set).
* - 0: A-Frame w/ detuned frequency,
* - 1: B-Frame w/ detuned frequency */
* - 0: A-Frame w/ detuned frequency,
* - 1: B-Frame w/ detuned frequency */
ARGUS_STATE_MEASUREMENT_FREQ = 1U << 2U,
/*! 0x0008: Debug Mode. If set, the range value of erroneous pixels
* are not cleared or reset.
* - 0: Disabled (default).
* - 1: Enabled. */
* are not cleared or reset.
* - 0: Disabled (default).
* - 1: Enabled. */
ARGUS_STATE_DEBUG_MODE = 1U << 3U,
/*! 0x0010: Weak Signal Flag.
* Set whenever the Pixel Binning Algorithm is detecting a
* weak signal, i.e. if the amplitude dies not reach its
* (absolute) threshold. If the Golden Pixel is enabled,
* this also indicates that the Pixel Binning Algorithm
* falls back to the Golden Pixel.
* - 0: Normal Signal.
* - 1: Weak Signal or Golden Pixel Mode. */
* Set whenever the Pixel Binning Algorithm is detecting a
* weak signal, i.e. if the amplitude dies not reach its
* (absolute) threshold. If the Golden Pixel is enabled,
* this also indicates that the Pixel Binning Algorithm
* falls back to the Golden Pixel.
* - 0: Normal Signal.
* - 1: Weak Signal or Golden Pixel Mode. */
ARGUS_STATE_WEAK_SIGNAL = 1U << 4U,
/*! 0x0020: Background Light Warning Flag.
* Set whenever the background light is very high and the
* measurement data might be unreliable.
* - 0: No Warning: Background Light is within valid range.
* - 1: Warning: Background Light is very high. */
* Set whenever the background light is very high and the
* measurement data might be unreliable.
* - 0: No Warning: Background Light is within valid range.
* - 1: Warning: Background Light is very high. */
ARGUS_STATE_BGL_WARNING = 1U << 5U,
/*! 0x0040: Background Light Error Flag.
* Set whenever the background light is too high and the
* measurement data is unreliable or invalid.
* - 0: No Error: Background Light is within valid range.
* - 1: Error: Background Light is too high. */
* Set whenever the background light is too high and the
* measurement data is unreliable or invalid.
* - 0: No Error: Background Light is within valid range.
* - 1: Error: Background Light is too high. */
ARGUS_STATE_BGL_ERROR = 1U << 6U,
/*! 0x0080: PLL_LOCKED bit.
* - 0: PLL not locked at start of integration.
* - 1: PLL locked at start of integration. */
* - 0: PLL not locked at start of integration.
* - 1: PLL locked at start of integration. */
ARGUS_STATE_PLL_LOCKED = 1U << 7U,
/*! 0x0100: Laser Failure Warning Flag.
* Set whenever the an invalid system condition is detected.
* (i.e. DCA at max state but no amplitude on any (incl. reference)
* pixel, not amplitude but any saturated pixel).
* - 0: No Warning: Laser is operating properly.
* - 1: Warning: Invalid laser conditions detected. If the invalid
* condition stays, a laser malfunction error is raised. */
* Set whenever the an invalid system condition is detected.
* (i.e. DCA at max state but no amplitude on any (incl. reference)
* pixel, not amplitude but any saturated pixel).
* - 0: No Warning: Laser is operating properly.
* - 1: Warning: Invalid laser conditions detected. If the invalid
* condition stays, a laser malfunction error is raised. */
ARGUS_STATE_LASER_WARNING = 1U << 8U,
/*! 0x0200: Laser Failure Error Flag.
* Set whenever a laser malfunction error is raised and the
* system is put into a safe state.
* - 0: No Error: Laser is operating properly.
* - 1: Error: Invalid laser conditions are detected for a certain
* soak time and the system is put into a safe state. */
* Set whenever a laser malfunction error is raised and the
* system is put into a safe state.
* - 0: No Error: Laser is operating properly.
* - 1: Error: Invalid laser conditions are detected for a certain
* soak time and the system is put into a safe state. */
ARGUS_STATE_LASER_ERROR = 1U << 9U,
/*! 0x0400: Set if current frame has distance measurement data available.
* - 0: No measurement data available, all values are 0 or stalled.
* - 1: Measurement data is available and correctly evaluated. */
* - 0: No measurement data available, all values are 0 or stalled.
* - 1: Measurement data is available and correctly evaluated. */
ARGUS_STATE_HAS_DATA = 1U << 10U,
/*! 0x0800: Set if current frame has auxiliary measurement data available.
* - 0: No auxiliary data available, all values are 0 or stalled.
* - 1: Auxiliary data is available and correctly evaluated. */
* - 0: No auxiliary data available, all values are 0 or stalled.
* - 1: Auxiliary data is available and correctly evaluated. */
ARGUS_STATE_HAS_AUX_DATA = 1U << 11U,
/*! 0x1000: DCA Maximum State Flag.
* Set whenever the DCA has extended all its parameters to their
* maximum values and can not increase the integration energy any
* further.
* - 0: DCA has not yet reached its maximum state.
* - 1: DCA has reached its maximum state and can not increase any further. */
* Set whenever the DCA has extended all its parameters to their
* maximum values and can not increase the integration energy any
* further.
* - 0: DCA has not yet reached its maximum state.
* - 1: DCA has reached its maximum state and can not increase any further. */
ARGUS_STATE_DCA_MAX = 1U << 12U,
/*! 0x2000: DCA is in high Optical Output Power stage. */
@@ -333,20 +323,20 @@ typedef enum {
} argus_state_t;
/*!***************************************************************************
* @brief Dynamic Configuration Adaption (DCA) Parameters.
* @details DCA contains:
* - Static or dynamic mode. The first is utilizing the nominal values
* while the latter is dynamically adopting between min. and max.
* value and starting form the nominal values.
* - Analog Integration Depth Adaption down to single pulses.
* - Optical Output Power Adaption
* - Pixel Input Gain Adaption
* - Digital Integration Depth Adaption
* - Dynamic Global Phase Shift Injection.
* - All that features are heeding the Laser Safety limits.
* .
* @brief Dynamic Configuration Adaption (DCA) Parameters.
* @details DCA contains:
* - Static or dynamic mode. The first is utilizing the nominal values
* while the latter is dynamically adopting between min. and max.
* value and starting form the nominal values.
* - Analog Integration Depth Adaption down to single pulses.
* - Optical Output Power Adaption
* - Pixel Input Gain Adaption
* - Digital Integration Depth Adaption
* - Dynamic Global Phase Shift Injection.
* - All that features are heeding the Laser Safety limits.
* .
*****************************************************************************/
typedef struct {
typedef struct argus_cfg_dca_t {
/*! Enables the automatic configuration adaption features.
* Enables the dynamic part if #DCA_ENABLE_DYNAMIC and the static only if
* #DCA_ENABLE_STATIC. */
@@ -494,4 +484,7 @@ typedef struct {
} argus_cfg_dca_t;
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_DCA_H */
@@ -1,12 +1,12 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 hardware API.
* @details This file provides generic definitions belonging to all
* devices from the AFBR-S50 product family.
* @brief This file is part of the AFBR-S50 hardware API.
* @details This file provides generic definitions belonging to all
* devices from the AFBR-S50 product family.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,9 @@
#ifndef ARGUS_DEF_H
#define ARGUS_DEF_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* Include files
@@ -52,36 +55,41 @@
#include <string.h>
/*!***************************************************************************
* @addtogroup argusapi
* @addtogroup argus_api
* @{
*****************************************************************************/
/*!***************************************************************************
* @brief Maximum number of phases per measurement cycle.
* @details The actual phase number is defined in the register configuration.
* However the software does only support a fixed value of 4 yet.
* @brief Maximum number of phases per measurement cycle.
* @details The actual phase number is defined in the register configuration.
* However the software does only support a fixed value of 4 yet.
*****************************************************************************/
#define ARGUS_PHASECOUNT 4U
#define ARGUS_PHASECOUNT 4
/*!***************************************************************************
* @brief The device pixel field size in x direction (long edge).
* @brief The device pixel field size in x direction (long edge).
*****************************************************************************/
#define ARGUS_PIXELS_X 8U
#define ARGUS_PIXELS_X 8
/*!***************************************************************************
* @brief The device pixel field size in y direction (short edge).
* @brief The device pixel field size in y direction (short edge).
*****************************************************************************/
#define ARGUS_PIXELS_Y 4U
#define ARGUS_PIXELS_Y 4
/*!***************************************************************************
* @brief The total device pixel count.
* @brief The total device pixel count.
*****************************************************************************/
#define ARGUS_PIXELS ((ARGUS_PIXELS_X)*(ARGUS_PIXELS_Y))
#define ARGUS_PIXELS ((ARGUS_PIXELS_X)*(ARGUS_PIXELS_Y))
/*!***************************************************************************
* @brief The AFBR-S50 module types.
* @brief A flag indicating that the device is a extended range device.
*****************************************************************************/
typedef enum {
#define MODULE_EXTENDED_FLAG (0x40U)
/*!***************************************************************************
* @brief The AFBR-S50 module types.
*****************************************************************************/
typedef enum argus_module_version_t {
/*! No device connected or not recognized. */
MODULE_NONE = 0,
@@ -89,54 +97,80 @@ typedef enum {
* w/ 4x8 pixel matrix and infra-red, 850 nm, laser source for
* medium range 3D applications.
* Version 1 - legacy version! */
AFBR_S50MV85G_V1 = 1,
AFBR_S50MV85G_V1 = 0x01,
/*! AFBR-S50MV85G: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and infra-red, 850 nm, laser source for
* medium range 3D applications.
* Version 2 - legacy version! */
AFBR_S50MV85G_V2 = 2,
/*! AFBR-S50MV85G: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and infra-red, 850 nm, laser source for
* medium range 3D applications.
* Version 7 - current version! */
AFBR_S50MV85G_V3 = 7,
AFBR_S50MV85G_V2 = 0x02,
/*! AFBR-S50LV85D: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and infra-red, 850 nm, laser source for
* long range 1D applications.
* Version 1 - current version! */
AFBR_S50LV85D_V1 = 3,
AFBR_S50LV85D_V1 = 0x03,
/*! AFBR-S50MV68B: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and red, 680 nm, laser source for
* medium range 1D applications.
* Version 1 - current version! */
AFBR_S50MV68B_V1 = 4,
AFBR_S50MV68B_V1 = 0x04,
/*! AFBR-S50MV85I: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and infra-red, 850 nm, laser source for
* medium range 3D applications.
* Version 1 - current version! */
AFBR_S50MV85I_V1 = 5,
AFBR_S50MV85I_V1 = 0x05,
/*! AFBR-S50MV85G: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and infra-red, 850 nm, laser source for
* short range 3D applications.
* Version 1 - current version! */
AFBR_S50SV85K_V1 = 6,
AFBR_S50SV85K_V1 = 0x06,
/*! AFBR-S50MV85G: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and infra-red, 850 nm, laser source for
* medium range 3D applications.
* Version 3 - current version! */
AFBR_S50MV85G_V3 = 0x07,
/*! Reserved for future extensions. */
Reserved = 0x3F
/*! AFBR-S50LX85D: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and infra-red, 850 nm, laser source for
* extended long range 1D applications.
* Version 1 - current version! */
AFBR_S50LX85D_V1 = AFBR_S50LV85D_V1 | MODULE_EXTENDED_FLAG,
/*! AFBR-S50MX68B: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and red, 680 nm, laser source for
* extended medium range 1D applications.
* Version 1 - current version! */
AFBR_S50MX68B_V1 = AFBR_S50MV68B_V1 | MODULE_EXTENDED_FLAG,
/*! AFBR-S50MX85I: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and infra-red, 850 nm, laser source for
* extended medium range 3D applications.
* Version 1 - current version! */
AFBR_S50MX85I_V1 = AFBR_S50MV85I_V1 | MODULE_EXTENDED_FLAG,
/*! AFBR-S50MX85G: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and infra-red, 850 nm, laser source for
* extended short range 3D applications.
* Version 1 - current version! */
AFBR_S50SX85K_V1 = AFBR_S50SV85K_V1 | MODULE_EXTENDED_FLAG,
/*! AFBR-S50MX85G: an ADS0032 based multi-pixel range finder device
* w/ 4x8 pixel matrix and infra-red, 850 nm, laser source for
* extended medium range 3D applications.
* Version 1 - current version! */
AFBR_S50MX85G_V1 = AFBR_S50MV85G_V3 | MODULE_EXTENDED_FLAG,
} argus_module_version_t;
/*!***************************************************************************
* @brief The AFBR-S50 laser configurations.
* @brief The AFBR-S50 laser configurations.
*****************************************************************************/
typedef enum {
typedef enum argus_laser_type_t {
/*! No laser connected. */
LASER_NONE = 0,
@@ -152,12 +186,15 @@ typedef enum {
/*! 850nm Infra-Red VCSEL v2 /w extended mode. */
LASER_H_V2X = 4,
/*! 680nm Red VCSEL v1 w/ extended mode. */
LASER_R_V1X = 5,
} argus_laser_type_t;
/*!***************************************************************************
* @brief The AFBR-S50 chip versions.
* @brief The AFBR-S50 chip versions.
*****************************************************************************/
typedef enum {
typedef enum argus_chip_version_t {
/*! No device connected or not recognized. */
ADS0032_NONE = 0,
@@ -178,37 +215,102 @@ typedef enum {
} argus_chip_version_t;
/*!***************************************************************************
* @brief The number of measurement modes with distinct configuration and
* calibration records.
*****************************************************************************/
#define ARGUS_MODE_COUNT (2)
/*!***************************************************************************
* @brief The measurement modes.
* @brief The measurement mode flags.
* @details The measurement mode flags that can be combined to a measurement
* mode, e.g. high speed short range mode. See #argus_mode_t for
* a complete list of available measurement modes.
*
* - Bit 0: Short Range Mode
* - Bit 1: Long Range Mode
* - Bit 2: High Speed Mode
*
* Note that the Long and Short Range Flags are mutual exclusive but
* any of those 2 must be set. Thus the value 0 is invalid!
* All other flags enhance the base configurations, e.g. the High
* Speed flag create the high speed mode of the selected base
* measurement mode.
*****************************************************************************/
typedef enum {
/*! Measurement Mode A: Long Range Mode. */
ARGUS_MODE_A = 1,
typedef enum argus_mode_flags_t {
/*! Measurement Mode Flag for Short Range Base Mode. */
ARGUS_MODE_FLAG_SHORT_RANGE = 0x01 << 0,
/*! Measurement Mode B: Short Range Mode. */
ARGUS_MODE_B = 2,
/*! Measurement Mode Flag for Long Range Base Mode. */
ARGUS_MODE_FLAG_LONG_RANGE = 0x01 << 1,
/*! Measurement Mode Flag for High Speed Mode. */
ARGUS_MODE_FLAG_HIGH_SPEED = 0x01 << 2
} argus_mode_flags_t;
/*!***************************************************************************
* @brief The measurement modes.
* @details The measurement modes are composed in binary from of the flags
* define in #argus_mode_flags_t, i.e. each bit has a special meaning:
*
* - Bit 0: Short Range Mode
* - Bit 1: Long Range Mode
* - Bit 2: High Speed Mode
*
* Note that the Long and Short Range Bits are mutual exclusive but any
* of those 2 must be set. Thus the value 0 is invalid!
*****************************************************************************/
typedef enum argus_mode_t {
/*! Measurement Mode: Short Range Mode. */
ARGUS_MODE_SHORT_RANGE = // = 0x01 = 0b0001
ARGUS_MODE_FLAG_SHORT_RANGE,
/*! Measurement Mode: Long Range Mode. */
ARGUS_MODE_LONG_RANGE = // = 0x02 = 0b0010
ARGUS_MODE_FLAG_LONG_RANGE,
/*! Measurement Mode: High Speed Short Range Mode. */
ARGUS_MODE_HIGH_SPEED_SHORT_RANGE = // = 0x05 = 0b0101
ARGUS_MODE_FLAG_SHORT_RANGE | ARGUS_MODE_FLAG_HIGH_SPEED,
/*! Measurement Mode: High Speed Long Range Mode. */
ARGUS_MODE_HIGH_SPEED_LONG_RANGE = // = 0x06 = 0b0110
ARGUS_MODE_FLAG_LONG_RANGE | ARGUS_MODE_FLAG_HIGH_SPEED,
} argus_mode_t;
/*! The data structure for the API representing a AFBR-S50 device instance. */
typedef struct argus_hnd_t argus_hnd_t;
/*!***************************************************************************
* @brief Generic API callback function.
* @details Invoked by the API. The content of the abstract data pointer
* depends upon the context.
* @param status The module status that caused the callback. #STATUS_OK if
* everything was as expected.
* @param data An abstract pointer to an user defined data. This will usually
* be passed to the function that also takes the callback as an
* parameter. Otherwise it has a special meaning such as
* configuration or calibration data.
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
* @brief Measurement Ready API callback function.
*
* @details Invoked by the API whenever a measurement cycle is finished and
* new data is ready to be evaluated via the #Argus_EvaluateData API
* function.
* The callback is passed to the API via the #Argus_TriggerMeasurement
* or #Argus_StartMeasurementTimer API functions.
* The API passes the status of the currently finished measurement
* cycle to the callback as first parameters. The second parameter is
* a pointer the API handle structure. The latter is used to identify
* the calling instance of the API in case of multiple devices.
* Further it can be passed to the #Argus_EvaluateData function.
*
* @warning Since the callback is called from an interrupt context, the
* callback execution must return as fast as possible. The usual task
* in the callback is to post an event to the main thread to inform it
* about the new data and that is must call the #Argus_EvaluateData
* function.
*
* @param status The module status that caused the callback. #STATUS_OK if
* everything was as expected.
*
* @param hnd The API handle pointer to the calling instance. Identifies the
* instance of the API that was invoking the callback and thus the
* instance that must call the #Argus_EvaluateData for.
*
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
*****************************************************************************/
typedef status_t (*argus_callback_t)(status_t status, void *data);
typedef status_t (*argus_measurement_ready_callback_t)(status_t status, argus_hnd_t *hnd);
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_DEF_H */
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Defines the dual frequency mode (DFM) setup parameters.
* @brief This file is part of the AFBR-S50 API.
* @details Defines the dual frequency mode (DFM) setup parameters.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,24 +36,27 @@
#ifndef ARGUS_DFM_H
#define ARGUS_DFM_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup argusdfm Dual Frequency Mode
* @ingroup argusapi
* @defgroup argus_dfm Dual Frequency Mode
* @ingroup argus_api
*
* @brief Dual Frequency Mode (DFM) parameter definitions and API functions.
* @brief Dual Frequency Mode (DFM) parameter definitions and API functions.
*
* @details The DFM is an algorithm to extend the unambiguous range of the
* sensor by utilizing two detuned measurement frequencies.
* @details The DFM is an algorithm to extend the unambiguous range of the
* sensor by utilizing two detuned measurement frequencies.
*
* The AFBR-S50 API provides three measurement modes:
* - 1X: Single Frequency Measurement
* - 4X: Dual Frequency Measurement w/ 4 times the unambiguous
* range of the Single Frequency Measurement
* - 8X: Dual Frequency Measurement w/ 8 times the unambiguous
* range of the Single Frequency Measurement
* The AFBR-S50 API provides three measurement modes:
* - 1X: Single Frequency Measurement
* - 4X: Dual Frequency Measurement w/ 4 times the unambiguous
* range of the Single Frequency Measurement
* - 8X: Dual Frequency Measurement w/ 8 times the unambiguous
* range of the Single Frequency Measurement
*
* @addtogroup argusdfm
* @addtogroup argus_dfm
* @{
*****************************************************************************/
@@ -61,10 +64,10 @@
#define ARGUS_DFM_FRAME_COUNT (2U)
/*! The Dual Frequency Mode measurement modes count. Excluding the disabled mode. */
#define ARGUS_DFM_MODE_COUNT (2U) // expect off-mode!
#define ARGUS_DFM_MODE_COUNT (2U) // except off-mode!
/*! The Dual Frequency Mode measurement modes enumeration. */
typedef enum {
typedef enum argus_dfm_mode_t {
/*! Single Frequency Measurement Mode (w/ 1x Unambiguous Range). */
DFM_MODE_OFF = 0U,
@@ -78,4 +81,7 @@ typedef enum {
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_DFM_H */
File diff suppressed because it is too large Load Diff
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 hardware API.
* @details Defines the generic measurement parameters and data structures.
* @brief This file is part of the AFBR-S50 hardware API.
* @details Defines the generic measurement parameters and data structures.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,17 +36,20 @@
#ifndef ARGUS_MEAS_H
#define ARGUS_MEAS_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup argusmeas Measurement/Device Control
* @ingroup argusapi
* @defgroup argus_meas Measurement/Device Control
* @ingroup argus_api
*
* @brief Measurement/Device control module
* @brief Measurement/Device control module
*
* @details This module contains measurement and device control specific
* definitions and methods.
* @details This module contains measurement and device control specific
* definitions and methods.
*
* @addtogroup argusmeas
* @addtogroup argus_meas
* @{
*****************************************************************************/
@@ -66,11 +69,11 @@
#define ARGUS_AUX_DATA_SIZE (3U * ARGUS_AUX_CHANNEL_COUNT) // 3 bytes * x channels * 1 phase
/*!***************************************************************************
* @brief The device measurement configuration structure.
* @details The portion of the configuration data that belongs to the
* measurement cycle. I.e. the data that defines a measurement frame.
* @brief The device measurement configuration structure.
* @details The portion of the configuration data that belongs to the
* measurement cycle. I.e. the data that defines a measurement frame.
*****************************************************************************/
typedef struct {
typedef struct argus_meas_frame_t {
/*! Frame integration time in microseconds.
* The integration time determines the measured time between
* the start signal and the IRQ. Note that this value will be
@@ -82,13 +85,13 @@ typedef struct {
/*! Pixel enabled mask for the 32 pixels sorted
* by x-y-indices.
* See [pixel mapping](@ref argusmap) for more
* See [pixel mapping](@ref argus_map) for more
* details on the pixel mask. */
uint32_t PxEnMask;
/*! ADS channel enabled mask for the remaining
* channels 31 .. 63 (miscellaneous values).
* See [pixel mapping](@ref argusmap) for more
* See [pixel mapping](@ref argus_map) for more
* details on the ADC channel mask. */
uint32_t ChEnMask;
@@ -113,9 +116,6 @@ typedef struct {
* Determines the optical output power. */
uq12_4_t OutputPower;
/*! The amplitude that is evaluated and used in the DCA module. */
uq12_4_t DCAAmplitude;
/*! Laser Bias Current Settings in LSB. */
uint8_t BiasCurrent;
@@ -133,4 +133,7 @@ typedef struct {
} argus_meas_frame_t;
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_MEAS_H */
@@ -0,0 +1,59 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 hardware API.
* @details Defines the generic device calibration API.
*
* @copyright
*
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef ARGUS_OFFSET_H
#define ARGUS_OFFSET_H
/*!***************************************************************************
* @addtogroup argus_cal
* @{
*****************************************************************************/
#include "argus_def.h"
/*!***************************************************************************
* @brief Pixel Range Offset Table.
* @details Contains pixel range offset values for all 32 active pixels.
*****************************************************************************/
typedef struct argus_cal_offset_table_t {
/*! The offset values per pixel in meter and Q0.15 format. */
q0_15_t Table[ARGUS_PIXELS_X][ARGUS_PIXELS_Y];
} argus_cal_offset_table_t;
/*! @} */
#endif /* ARGUS_OFFSET_T */
@@ -1,12 +1,12 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Defines the pixel binning algorithm (PBA) setup parameters and
* data structure.
* @brief This file is part of the AFBR-S50 API.
* @details Defines the pixel binning algorithm (PBA) setup parameters and
* data structure.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -37,86 +37,98 @@
#ifndef ARGUS_PBA_H
#define ARGUS_PBA_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup arguspba Pixel Binning Algorithm
* @ingroup argusapi
* @defgroup argus_pba Pixel Binning Algorithm
* @ingroup argus_api
*
* @brief Pixel Binning Algorithm (PBA) parameter definitions and API functions.
* @brief Pixel Binning Algorithm (PBA) parameter definitions and API functions.
*
* @details Defines the generic pixel binning algorithm (PBA) setup parameters
* and data structure.
* @details Defines the generic Pixel Binning Algorithm (PBA) setup parameters
* and data structure.
*
* The PBA module contains filter algorithms that determine the
* pixels with the best signal quality and extract an 1d distance
* information from the filtered pixels.
* The PBA module contains filter algorithms that determine the
* pixels with the best signal quality and extract an 1D distance
* information from the filtered pixels by averaging them in a
* specified way.
*
* The pixel filter algorithm is a three-stage filter with a
* fallback value:
* The Pixel Binning Algorithm is a three-stage filter with a
* fallback value:
*
* -# A fixed pre-filter mask is applied to statically disable
* specified pixels.
* -# A relative and absolute amplitude filter is applied in the
* second stage. The relative filter is determined by a ratio
* of the maximum amplitude off all available (i.e. not filtered
* in stage 1) pixels. Pixels that have an amplitude below the
* relative threshold are dismissed. The same holds true for
* the absolute amplitude threshold. All pixel with smaller
* amplitude are dismissed.\n
* The relative threshold is useful to setup a distance
* measurement scenario. All well illuminated pixels are
* selected and considered for the final 1d distance. The
* absolute threshold is used to dismiss pixels that are below
* the noise level. The latter would be considered for the 1d
* result if the maximum amplitude is already very low.
* -# A distance filter is used to distinguish pixels that target
* the actual object from pixels that see the brighter background,
* e.g. white walls. Thus, the pixel with the minimum distance
* is referenced and all pixel that have a distance between
* the minimum and the given minimum distance scope are selected
* for the 1d distance result. The minimum distance scope is
* determined by an relative (to the current minimum distance)
* and an absolute value. The larger scope value is the
* relevant one, i.e. the relative distance scope can be used
* to heed the increasing noise at larger distances.
* -# If all of the above filters fail to determine a single valid
* pixel, the golden pixel is used as a fallback value. The
* golden pixel is the pixel that sits right at the focus point
* of the optics at large distances.
* .
* -# A fixed pre-filter mask is applied to statically disable
* specified pixels.
* -# A relative and absolute amplitude filter is applied in the
* second stage. The relative filter is determined by a ratio
* of the maximum amplitude off all available (i.e. not filtered
* in stage 1) pixels. Pixels that have an amplitude below the
* relative threshold are dismissed. The same holds true for
* the absolute amplitude threshold. All pixel with smaller
* amplitude are dismissed.\n
* Note that the absolute amplitude threshold is disabled if
* the Golden Pixel (see below) is also disabled in order to
* prevent invalid filtering for multi-pixel devices.\n
* The relative threshold is useful to setup a distance
* measurement scenario. All well illuminated pixels are
* selected and considered for the final 1D distance. The
* absolute threshold is used to dismiss pixels that are below
* the noise level. The latter would be considered for the 1D
* result if the maximum amplitude is already very low.
* -# An absolute minimum distance filter is applied in addition
* to the amplitude filter. This removes all pixel that have
* a lower distance than the specified threshold. This is used
* to remove invalid pixels that can be detected by a physically
* not correct negative distance.
* -# A distance filter is used to distinguish pixels that target
* the actual object from pixels that see the brighter background,
* e.g. white walls. Thus, the pixel with the minimum distance
* is referenced and all pixel that have a distance between
* the minimum and the given minimum distance scope are selected
* for the 1D distance result. The minimum distance scope is
* determined by an relative (to the current minimum distance)
* and an absolute value. The larger scope value is the
* relevant one, i.e. the relative distance scope can be used
* to heed the increasing noise at larger distances.
* -# If all of the above filters fail to determine a single valid
* pixel, the Golden Pixel is used as a fallback value. The
* Golden Pixel is the pixel that sits right at the focus point
* of the optics at large distances.
* .
*
* After filtering is done, there may be more than a single pixel
* left to determine the 1d signal. Therefore several averaging
* methods are implemented to obtain the best 1d result from many
* pixels. See #argus_pba_averaging_mode_t for details.
* After filtering is done, there may be more than a single pixel
* left to determine the 1D signal. Therefore several averaging
* methods are implemented to obtain the best 1D result from many
* pixels. See #argus_pba_averaging_mode_t for details.
*
*
* @addtogroup arguspba
* @addtogroup argus_pba
* @{
*****************************************************************************/
#include "argus_def.h"
/*!***************************************************************************
* @brief Enable flags for the pixel binning algorithm.
* @brief Enable flags for the pixel binning algorithm.
*
* @details Determines the pixel binning algorithm feature enable status.
* - [0]: #PBA_ENABLE: Enables the pixel binning feature.
* - [1]: reserved
* - [2]: reserved
* - [3]: reserved
* - [4]: reserved
* - [5]: #PBA_ENABLE_GOLDPX: Enables the golden pixel feature.
* - [6]: #PBA_ENABLE_MIN_DIST_SCOPE: Enables the minimum distance scope
* feature.
* - [7]: reserved
* .
* - [0]: #PBA_ENABLE: Enables the pixel binning feature.
* - [1]: reserved
* - [2]: reserved
* - [3]: reserved
* - [4]: reserved
* - [5]: #PBA_ENABLE_GOLDPX: Enables the Golden Pixel feature.
* - [6]: #PBA_ENABLE_MIN_DIST_SCOPE: Enables the minimum distance scope
* feature.
* - [7]: reserved
* .
*****************************************************************************/
typedef enum {
typedef enum argus_pba_flags_t {
/*! Enables the pixel binning feature. */
PBA_ENABLE = 1U << 0U,
/*! Enables the golden pixel. */
/*! Enables the Golden Pixel. */
PBA_ENABLE_GOLDPX = 1U << 5U,
/*! Enables the minimum distance scope filter. */
@@ -125,9 +137,9 @@ typedef enum {
} argus_pba_flags_t;
/*!***************************************************************************
* @brief The averaging modes for the pixel binning algorithm.
* @brief The averaging modes for the pixel binning algorithm.
*****************************************************************************/
typedef enum {
typedef enum argus_pba_averaging_mode_t {
/*! Evaluate the 1D range from all available pixels using
* a simple average. */
PBA_SIMPLE_AVG = 1U,
@@ -140,11 +152,12 @@ typedef enum {
} argus_pba_averaging_mode_t;
/*!***************************************************************************
* @brief The pixel binning algorithm settings data structure.
* @details Describes the pixel binning algorithm settings.
* @brief The pixel binning algorithm settings data structure.
* @details Describes the pixel binning algorithm settings.
*****************************************************************************/
typedef struct {
/*! Enables the pixel binning features.
/*! Enables the Pixel Binning Algorithm.
*
* Each bit may enable a different feature. See #argus_pba_flags_t
* for details about the enabled flags. */
argus_pba_flags_t Enabled;
@@ -156,6 +169,7 @@ typedef struct {
argus_pba_averaging_mode_t AveragingMode;
/*! The Relative amplitude threshold value (in %) of the max. amplitude.
*
* Pixels with amplitude below this threshold value are dismissed.
*
* All available values from the 8-bit representation are valid.
@@ -165,22 +179,27 @@ typedef struct {
uq0_8_t RelAmplThreshold;
/*! The relative minimum distance scope value in %.
* Pixels that have a range value within [x0, x0 + dx] are considered
* for the pixel binning, where x0 is the minimum distance of all
* amplitude picked pixels and dx is the minimum distance scope value.
* The minimum distance scope value will be the maximum of relative
* and absolute value.
*
* Pixels that have a range value within [x0, x0 + dx] are considered
* for the pixel binning, where x0 is the minimum distance of all
* amplitude picked pixels and dx is the minimum distance scope value.
* The minimum distance scope value will be the maximum of relative
* and absolute value.
*
* All available values from the 8-bit representation are valid.
* The actual percentage value is determined by 100%/256*x.
*
* Special values:
* Special values:
* - 0: Use 0 for absolute value only or to choose the pixel with the
* minimum distance only (of also the absolute value is 0)! */
* minimum distance only (of also the absolute value is 0)! */
uq0_8_t RelMinDistanceScope;
/*! The Absolute amplitude threshold value in LSB.
* Pixels with amplitude below this threshold value are dismissed.
/*! The absolute amplitude threshold value in LSB.
*
* Pixels with amplitude below this threshold value are dismissed.
*
* The absolute amplitude threshold is only valid if the Golden Pixel
* mode is enabled. Otherwise, the threshold is set to 0 LSB internally.
*
* All available values from the 16-bit representation are valid.
* The actual LSB value is determined by x/16.
@@ -189,33 +208,42 @@ typedef struct {
uq12_4_t AbsAmplThreshold;
/*! The absolute minimum distance scope value in m.
* Pixels that have a range value within [x0, x0 + dx] are considered
* for the pixel binning, where x0 is the minimum distance of all
* amplitude picked pixels and dx is the minimum distance scope value.
* The minimum distance scope value will be the maximum of relative
* and absolute value.
*
* Pixels that have a range value within [x0, x0 + dx] are considered
* for the pixel binning, where x0 is the minimum distance of all
* amplitude picked pixels and dx is the minimum distance scope value.
* The minimum distance scope value will be the maximum of relative
* and absolute value.
*
* All available values from the 16-bit representation are valid.
* The actual LSB value is determined by x/2^15.
*
* Special values:
* Special values:
* - 0: Use 0 for relative value only or to choose the pixel with the
* minimum distance only (of also the relative value is 0)! */
* minimum distance only (of also the relative value is 0)! */
uq1_15_t AbsMinDistanceScope;
/*! The pre-filter pixel mask determines the pixel channels that are
* statically excluded from the pixel binning (i.e. 1D distance) result.
/*! The absolute minimum distance threshold value in m.
*
* The pixel enabled mask is an 32-bit mask that determines the
* device internal channel number. It is recommended to use the
* - #PIXELXY_ISENABLED(msk, x, y)
* - #PIXELXY_ENABLE(msk, x, y)
* - #PIXELXY_DISABLE(msk, x, y)
* .
* macros to work with the pixel enable masks. */
* Pixels with distance below this threshold value are dismissed. */
q9_22_t AbsMinDistanceThreshold;
/*! The pre-filter pixel mask determines the pixel channels that are
* statically excluded from the pixel binning (i.e. 1D distance) result.
*
* The pixel enabled mask is an 32-bit mask that determines the
* device internal channel number. It is recommended to use the
* - #PIXELXY_ISENABLED(msk, x, y)
* - #PIXELXY_ENABLE(msk, x, y)
* - #PIXELXY_DISABLE(msk, x, y)
* .
* macros to work with the pixel enable masks. */
uint32_t PrefilterMask;
} argus_cfg_pba_t;
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_PBA_H */
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Defines the device pixel measurement results data structure.
* @brief This file is part of the AFBR-S50 API.
* @details Defines the device pixel measurement results data structure.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,34 +36,40 @@
#ifndef ARGUS_PX_H
#define ARGUS_PX_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @addtogroup argusres
* @addtogroup argus_res
* @{
*****************************************************************************/
#include "argus_def.h"
/*! Maximum amplitude value in UQ12.4 format. */
#define ARGUS_AMPLITUDE_MAX (0xFFF0U)
#define ARGUS_AMPLITUDE_MAX (0xFFF0U)
/*! Maximum range value in Q9.22 format.
* Also used as a special value to determine no object detected or infinity range. */
#define ARGUS_RANGE_MAX (Q9_22_MAX)
/*!***************************************************************************
* @brief Status flags for the evaluated pixel structure.
* @brief Status flags for the evaluated pixel structure.
*
* @details Determines the pixel status. 0 means OK (#PIXEL_OK).
* - [0]: #PIXEL_OFF: Pixel was disabled and not read from the device.
* - [1]: #PIXEL_SAT: The pixel was saturated.
* - [2]: #PIXEL_BIN_EXCL: The pixel was excluded from the 1D result.
* - [3]: #PIXEL_AMPL_MIN: The pixel amplitude has evaluated to 0.
* - [4]: #PIXEL_PREFILTERED: The was pre-filtered by static mask.
* - [5]: #PIXEL_NO_SIGNAL: The pixel has no valid signal.
* - [6]: #PIXEL_OUT_OF_SYNC: The pixel has lost signal trace.
* - [7]: #PIXEL_STALLED: The pixel value is stalled due to errors.
* .
* - [0]: #PIXEL_OFF: Pixel was disabled and not read from the device.
* - [1]: #PIXEL_SAT: The pixel was saturated.
* - [2]: #PIXEL_BIN_EXCL: The pixel was excluded from the 1D result.
* - [3]: #PIXEL_INVALID: The pixel data is invalid.
* - [4]: #PIXEL_PREFILTERED: The was pre-filtered by static mask.
* - [5]: #PIXEL_NO_SIGNAL: The pixel has no valid signal.
* - [6]: #PIXEL_OUT_OF_SYNC: The pixel has lost signal trace.
* - [7]: #PIXEL_STALLED: The pixel value is stalled due to errors.
* .
*****************************************************************************/
typedef enum {
typedef enum argus_px_status_t {
/*! 0x00: Pixel status OK. */
PIXEL_OK = 0,
@@ -77,43 +83,45 @@ typedef enum {
/*! 0x04: Pixel is excluded from the pixel binning (1d) result. */
PIXEL_BIN_EXCL = 1U << 2U,
/*! 0x08: Pixel amplitude minimum underrun
* (i.e. the amplitude calculation yields 0). */
PIXEL_AMPL_MIN = 1U << 3U,
/*! 0x08: Pixel has invalid data due to miscellaneous reasons, e.g.
* - Amplitude calculates to 0 (i.e. division by 0)
* - Golden Pixel is invalid due to other saturated pixel.
* - Range/distance is negative. */
PIXEL_INVALID = 1U << 3U,
/*! 0x10: Pixel is pre-filtered by the static pixel binning pre-filter mask,
* i.e. the pixel is disabled by software. */
* i.e. the pixel is disabled by software. */
PIXEL_PREFILTERED = 1U << 4U,
/*! 0x20: Pixel amplitude is below its threshold value. The received signal
* strength is too low to evaluate a valid signal. The range value is
* set to the maximum possible value (approx. 512 m). */
* strength is too low to evaluate a valid signal. The range value is
* set to the maximum possible value (approx. 512 m). */
PIXEL_NO_SIGNAL = 1U << 5U,
/*! 0x40: Pixel is not in sync with respect to the dual frequency algorithm.
* I.e. the pixel may have a correct value but is estimated into the
* wrong unambiguous window. */
* I.e. the pixel may have a correct value but is estimated into the
* wrong unambiguous window. */
PIXEL_OUT_OF_SYNC = 1U << 6U,
/*! 0x80: Pixel is stalled due to one of the following reasons:
* - #PIXEL_SAT
* - #PIXEL_AMPL_MIN
* - #PIXEL_OUT_OF_SYNC
* - Global Measurement Error
* .
* A stalled pixel does not update its measurement data and keeps the
* previous values. If the issue is resolved, the stall disappears and
* the pixel is updating again. */
* - #PIXEL_SAT
* - #PIXEL_INVALID
* - #PIXEL_OUT_OF_SYNC
* - Global Measurement Error
* .
* A stalled pixel does not update its measurement data and keeps the
* previous values. If the issue is resolved, the stall disappears and
* the pixel is updating again. */
PIXEL_STALLED = 1U << 7U
} argus_px_status_t;
/*!***************************************************************************
* @brief The evaluated measurement results per pixel.
* @details This structure contains the evaluated data for a single pixel.\n
* If the amplitude is 0, the pixel is turned off or has invalid data.
* @brief The evaluated measurement results per pixel.
* @details This structure contains the evaluated data for a single pixel.\n
* If the amplitude is 0, the pixel is turned off or has invalid data.
*****************************************************************************/
typedef struct {
typedef struct argus_pixel_t {
/*! Range Values from the device in meter. It is the actual distance before
* software adjustments/calibrations. */
q9_22_t Range;
@@ -141,14 +149,23 @@ typedef struct {
/*!***************************************************************************
* @brief Representation of a correlation vector containing sine/cosine components.
*****************************************************************************/
typedef struct {
/*! The sine component. */
q15_16_t S;
typedef struct argus_vector_t {
union {
/*! The sine [0] and cosine [1] components. */
q15_16_t SC[2];
/*! The cosine component. */
q15_16_t C;
struct {
/*! The sine component. */
q15_16_t S;
/*! The cosine component. */
q15_16_t C;
};
};
} argus_vector_t;
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_PX_H */
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Defines the generic measurement results data structure.
* @brief This file is part of the AFBR-S50 API.
* @details Defines the generic measurement results data structure.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,35 +36,39 @@
#ifndef ARGUS_RES_H
#define ARGUS_RES_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup argusres Measurement Data
* @ingroup argusapi
* @defgroup argus_res Measurement Data
* @ingroup argus_api
*
* @brief Measurement results data structures.
* @brief Measurement results data structures.
*
* @details The interface defines all data structures that correspond to
* the AFBR-S50 measurement results, e.g.
* - 1D distance and amplitude values,
* - 3D distance and amplitude values (i.e. per pixel),
* - Auxiliary channel measurement results (VDD, IAPD, temperature, ...)
* - Device and result status
* - ...
* .
* @details The interface defines all data structures that correspond to
* the AFBR-S50 measurement results, e.g.
* - 1D distance and amplitude values,
* - 3D distance and amplitude values (i.e. per pixel),
* - Auxiliary channel measurement results (VDD, IAPD, temperature, ...)
* - Device and result status
* - ...
* .
*
* @addtogroup argusres
* @addtogroup argus_res
* @{
*****************************************************************************/
#include "argus_def.h"
#include "argus_px.h"
#include "argus_def.h"
#include "argus_meas.h"
#include "argus_xtalk.h"
/*!***************************************************************************
* @brief The 1d measurement results data structure.
* @brief The 1d measurement results data structure.
* @details The 1d measurement results obtained by the Pixel Binning Algorithm.
*****************************************************************************/
typedef struct {
typedef struct argus_results_bin_t {
/*! Raw 1D range value in meter (Q9.22 format). The distance obtained by
* the Pixel Binning Algorithm from the current measurement frame. */
q9_22_t Range;
@@ -83,11 +87,11 @@ typedef struct {
} argus_results_bin_t;
/*!***************************************************************************
* @brief The auxiliary measurement results data structure.
* @details The auxiliary measurement results obtained by the auxiliary task.\n
* Special values, i.e. 0xFFFFU, indicate no readout value available.
* @brief The auxiliary measurement results data structure.
* @details The auxiliary measurement results obtained by the auxiliary task.\n
* Special values, i.e. 0xFFFFU, indicate no readout value available.
*****************************************************************************/
typedef struct {
typedef struct argus_results_aux_t {
/*! VDD ADC channel readout value.\n
* Special Value if no value has been measured:\n
* Invalid/NotAvailable = 0xFFFFU (UQ12_4_MAX) */
@@ -129,32 +133,66 @@ typedef struct {
} argus_results_aux_t;
/*!***************************************************************************
* @brief The measurement results data structure.
* @brief The debug data of measurement results data structure.
* @details This data structure will be filled with API internal data for
* debugging purposes.
*****************************************************************************/
typedef struct argus_results_debug_t {
/*! The amplitude that is evaluated and used in the DCA module. */
uq12_4_t DCAAmplitude;
/*! Raw x-y-sorted ADC results from the device.\n
* Data is arranged as 32-bit values in following order:
* index > phase; where index is pixel number n and auxiliary ADC channel.\n
* Note that disabled pixels are skipped.\n
* e.g. [n=0,p=0][n=0,p=1]..[n=0,p=3][n=1,p=0]...[n=1,p=3]...[n=31,p=3] */
uint32_t Data[ARGUS_RAW_DATA_VALUES];
/*! The current crosstalk correction values as determined by the
* crosstalk predictor algorithm. This is basically the temperature
* dependent portion of the crosstalk correction.\n
* Note that there are two values for the upper and lower two rows
* respectively. */
xtalk_t XtalkPredictor[ARGUS_PIXELS_Y / 2U];
/*! The current crosstalk correction values as determined by the
* crosstalk monitor algorithm. This is a dynamic portion of the
* crosstalk correction that is determined by monitoring passive
* pixels.\n
* Note that the values are valid row-wise. */
xtalk_t XtalkMonitor[ARGUS_PIXELS_Y];
} argus_results_debug_t;
/*!***************************************************************************
* @brief The measurement results data structure.
* @details This structure contains all information obtained by a single
* distance measurement on the device:
* - The measurement status can be read from the #Status.
* - A timing information is given via the #TimeStamp.
* - Information about the frame state is in the #Frame structure.
* - The 1D distance results are gathered under #Bin.
* - The 3D distance results for each pixel is at #Pixels or #Pixel.
* - Auxiliary values such as temperature can be found at #Auxiliary.
* - Raw data from the device is stored in the #Data array.
* .
* distance measurement on the device:
* - The measurement status can be read from the #Status.
* - A timing information is given via the #TimeStamp.
* - Information about the frame state is in the #Frame structure.
* - The 1D distance results are gathered under #Bin.
* - The 3D distance results for each pixel is at #Pixels or #Pixel.
* - Auxiliary values such as temperature can be found at #Auxiliary.
* - Raw data and debug information from the device and API is stored
* in the optional #Debug data structure. Note that this points to
* an optional structure and can be null!
* .
*
* The pixel x-y orientation is sketched in the following graph. Note that
* the laser source would be on the right side beyond the reference pixel.
* See also \link argusmap ADC Channel Mapping\endlink
* The pixel x-y orientation is sketched in the following graph. Note that
* the laser source would be on the right side beyond the reference pixel.
* See also \link argus_map ADC Channel Mapping\endlink
* @code
* // Pixel Field: Pixel[x][y]
* //
* // 0 -----------> x
* // | O O O O O O O O
* // | O O O O O O O O
* // | O O O O O O O O O (ref. Px)
* // y O O O O O O O O
* // Pixel Field: Pixel[x][y]
* //
* // 0 -----------> x
* // | O O O O O O O O
* // | O O O O O O O O
* // | O O O O O O O O O (ref. Px)
* // y O O O O O O O O
* @endcode
*****************************************************************************/
typedef struct {
typedef struct argus_results_t {
/*! The \link #status_t status\endlink of the current measurement frame.
* - 0 (i.e. #STATUS_OK) for a good measurement signal.
* - > 0 for warnings and weak measurement signal.
@@ -168,13 +206,6 @@ typedef struct {
/*! The configuration for the current measurement frame. */
argus_meas_frame_t Frame;
/*! Raw x-y-sorted ADC results from the device.\n
* Data is arranged as 32-bit values in following order:
* index > phase; where index is pixel number n and auxiliary ADC channel.\n
* Note that disabled pixels are skipped.\n
* e.g. [n=0,p=0][n=0,p=1]..[n=0,p=3][n=1,p=0]...[n=1,p=3]...[n=31,p=3] */
uint32_t Data[ARGUS_RAW_DATA_VALUES];
union {
/*! Pixel data indexed by channel number n.\n
* Contains calibrated range, amplitude and pixel status among others.
@@ -183,14 +214,14 @@ typedef struct {
* - 0..31: active pixels
* - 32: reference pixel
*
* See also \link argusmap ADC Channel Mapping\endlink */
* See also \link argus_map ADC Channel Mapping\endlink */
argus_pixel_t Pixels[ARGUS_PIXELS + 1U];
struct {
/*! Pixel data indexed by x-y-indices.\n
* The pixels are ordered in a two dimensional array that represent
* the x and y indices of the pixel.\n
* See also \link argusmap ADC Channel Mapping\endlink
* See also \link argus_map ADC Channel Mapping\endlink
*
* Contains calibrated range, amplitude and pixel status among others. */
argus_pixel_t Pixel[ARGUS_PIXELS_X][ARGUS_PIXELS_Y];
@@ -213,8 +244,17 @@ typedef struct {
/*! The auxiliary ADC channel data, e.g. sensor temperature. */
argus_results_aux_t Auxiliary;
/*! Optional Debug Data.
* If the pointer is set to a #argus_results_debug_t data structure before
* passing it to the #Argus_EvaluateData function, the data structure is
* filled with internal parameters for debugging purposes. */
argus_results_debug_t *Debug;
} argus_results_t;
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_RES_H */
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Defines the Shot Noise Monitor (SNM) setup parameters.
* @brief This file is part of the AFBR-S50 API.
* @details Defines the Shot Noise Monitor (SNM) setup parameters.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,30 +36,33 @@
#ifndef ARGUS_SNM_H
#define ARGUS_SNM_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup argussnm Shot Noise Monitor
* @ingroup argusapi
* @defgroup argus_snm Shot Noise Monitor
* @ingroup argus_api
*
* @brief Shot Noise Monitor (SNM) parameter definitions and API functions.
* @brief Shot Noise Monitor (SNM) parameter definitions and API functions.
*
* @details The SNM is an algorithm to monitor and react on shot noise
* induced by harsh environment conditions like high ambient
* light.
* @details The SNM is an algorithm to monitor and react on shot noise
* induced by harsh environment conditions like high ambient
* light.
*
* The AFBR-S50 API provides three modes:
* - Dynamic: Automatic mode, automatically adopts to current
* ambient conditions.
* - Static (Outdoor): Static mode, optimized for outdoor applications.
* - Static (Indoor): Static mode, optimized for indoor applications.
* .
* The AFBR-S50 API provides three modes:
* - Dynamic: Automatic mode, automatically adopts to current
* ambient conditions.
* - Static (Outdoor): Static mode, optimized for outdoor applications.
* - Static (Indoor): Static mode, optimized for indoor applications.
* .
*
* @addtogroup argussnm
* @addtogroup argus_snm
* @{
*****************************************************************************/
/*! The Shot Noise Monitor modes enumeration. */
typedef enum {
typedef enum argus_snm_mode_t {
/*! Static Shot Noise Monitoring Mode, optimized for indoor applications.
* Assumes the best case scenario, i.e. no bad influence from ambient conditions.
* Thus it uses a fixed setting that will result in the best performance.
@@ -79,4 +82,7 @@ typedef enum {
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_SNM_H */
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Provides status codes for the AFBR-S50 API.
* @brief This file is part of the AFBR-S50 API.
* @details Provides status codes for the AFBR-S50 API.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,25 +36,32 @@
#ifndef ARGUS_STATUS_H
#define ARGUS_STATUS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/*!***************************************************************************
* @defgroup status Status Codes
* @defgroup argus_status Status Codes
* @ingroup argus
*
* @brief Status and Error Code Definitions
*
* @details Defines status and error codes for function return values.
* Basic status number structure:
* - 0 is OK or no error.
* - negative values determine errors.
* - positive values determine warnings or status information.
* .
* @addtogroup status
*
* @addtogroup argus_status
* @{
*****************************************************************************/
/*!***************************************************************************
* @brief Type used for all status and error return values.
* @details Basic status number structure:
* @brief Type used for all status and error return values.
* @details Basic status number structure:
* - 0 is OK or no error.
* - negative values determine errors.
* - positive values determine warnings or status information.
@@ -138,8 +145,8 @@ enum Status {
********** NVM / Flash Layer Status *********************************************************
*********************************************************************************************/
/*! -98: Flash Error: The version of the settings in the flash memory is not compatible. */
ERROR_NVM_INVALID_FILE_VERSION = -98,
/*! -98: Flash Error: The read memory block was not written previously and contains no data. */
ERROR_NVM_EMPTY = -98,
/*! -99: Flash Error: The memory is out of range. */
ERROR_NVM_OUT_OF_RANGE = -99,
@@ -183,6 +190,13 @@ enum Status {
/*! -102: AFBR-S50 Error: Inconsistent configuration parameters. */
ERROR_ARGUS_INVALID_CFG = -102,
/*! -103: AFBR-S50 Error: The evaluation function has been called but no
* raw data is available yet.
* See also #Argus_EvaluateData for more information. */
ERROR_ARGUS_BUFFER_EMPTY = -103,
/*! -104: AFBR-S50 Error: Invalid slave identifier is passed to the module. */
ERROR_ARGUS_INVALID_SLAVE = -104,
/*! -105: AFBR-S50 Error: Invalid measurement mode configuration parameter. */
ERROR_ARGUS_INVALID_MODE = -105,
@@ -191,7 +205,6 @@ enum Status {
* The current measurement data set is invalid! */
ERROR_ARGUS_BIAS_VOLTAGE_REINIT = -107,
/*! -109: AFBR-S50 Error: The EEPROM readout has failed. The failure is detected
* by three distinct read attempts, each resulting in invalid data.
* Note: this state differs from that #STATUS_ARGUS_EEPROM_BIT_ERROR
@@ -224,7 +237,6 @@ enum Status {
* requested command. */
ERROR_ARGUS_BUSY = -191,
/*! -199: AFBR-S50 Error: Unknown module number. */
ERROR_ARGUS_UNKNOWN_MODULE = -199,
@@ -235,24 +247,22 @@ enum Status {
ERROR_ARGUS_UNKNOWN_LASER = -197,
/*! 191: AFBR-S50 Status (internal): The device is currently busy with testing the
* SPI connection to the device. */
STATUS_ARGUS_BUSY_TEST = 191,
/*! 193: AFBR-S50 Status (internal): The device is currently busy with updating the
* configuration (i.e. with writing register values). */
STATUS_ARGUS_BUSY_CFG_UPDATE = 193,
/*! 194: AFBR-S50 Status (internal): The device is currently busy with updating the
* calibration data (i.e. writing to register values). */
STATUS_ARGUS_BUSY_CAL_UPDATE = 194,
/*! 192: AFBR-S50 Status (internal): The device is currently busy with updating the
* settings parameter (i.e. with writing register values). */
STATUS_ARGUS_BUSY_UPDATE = 192,
/*! 195: AFBR-S50 Status (internal): The device is currently executing a calibration
* sequence. */
* sequence. */
STATUS_ARGUS_BUSY_CAL_SEQ = 195,
/*! 196: AFBR-S50 Status (internal): The device is currently executing a measurement
* cycle. */
STATUS_ARGUS_BUSY_MEAS = 196,
/*! 100: AFBR-S50 Status (internal): The ASIC is initializing a new measurement, i.e.
* a register value is written that starts an integration cycle on the ASIC. */
STATUS_ARGUS_STARTING = 100,
@@ -260,9 +270,10 @@ enum Status {
/*! 103: AFBR-S50 Status (internal): The ASIC is performing an integration cycle. */
STATUS_ARGUS_ACTIVE = 103,
};
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_STATUS_H */
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details This file contains the current API version number.
* @brief This file is part of the AFBR-S50 API.
* @details This file contains the current API version number.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,16 +36,19 @@
#ifndef ARGUS_VERSION_H
#define ARGUS_VERSION_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup version API Version
* @ingroup argusapi
* @defgroup argus_version API Version
* @ingroup argus_api
*
* @brief API and library core version number
* @brief API and library core version number
*
* @details Contains the AFBR-S50 API and Library Core Version Number.
* @details Contains the AFBR-S50 API and Library Core Version Number.
*
* @addtogroup version
* @addtogroup argus_version
* @{
*****************************************************************************/
@@ -53,13 +56,13 @@
#define ARGUS_API_VERSION_MAJOR 1
/*! Minor version number of the AFBR-S50 API. */
#define ARGUS_API_VERSION_MINOR 3
#define ARGUS_API_VERSION_MINOR 4
/*! Bugfix version number of the AFBR-S50 API. */
#define ARGUS_API_VERSION_BUGFIX 5
#define ARGUS_API_VERSION_BUGFIX 4
/*! Build version nunber of the AFBR-S50 API. */
#define ARGUS_API_VERSION_BUILD "20210812171515"
/*! Build version number of the AFBR-S50 API. */
#define ARGUS_API_VERSION_BUILD "20230327150535"
/*****************************************************************************/
@@ -73,4 +76,7 @@
(ARGUS_API_VERSION_BUGFIX))
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_VERSION_H */
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 hardware API.
* @details Defines the generic device calibration API.
* @brief This file is part of the AFBR-S50 hardware API.
* @details Defines the generic device calibration API.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,44 +36,71 @@
#ifndef ARGUS_XTALK_H
#define ARGUS_XTALK_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @addtogroup arguscal
* @addtogroup argus_cal
* @{
*****************************************************************************/
#include "api/argus_def.h"
#include "argus_def.h"
#include "argus_dfm.h"
/*!***************************************************************************
* @brief Pixel Crosstalk Compensation Vector.
* @details Contains calibration data (per pixel) that belongs to the
* RX-TX-Crosstalk compensation feature.
* @brief Pixel Crosstalk Compensation Vector.
* @details Contains calibration data (per pixel) that belongs to the
* RX-TX-Crosstalk compensation feature.
* The crosstalk vector consists of a Sine and Cosine component in LSB.
*****************************************************************************/
/*! Pixel Crosstalk Vector */
typedef struct {
typedef struct xtalk_t {
/*! Crosstalk Vector - Sine component.
* Units: LSB
* Special Value: Q11_4_MIN == not available */
q11_4_t dS;
/*! Crosstalk Vector - Cosine component.
* Units: LSB
* Special Value: Q11_4_MIN == not available */
q11_4_t dC;
} xtalk_t;
/*!***************************************************************************
* @brief Pixel-To-Pixel Crosstalk Compensation Parameters.
* @details Contains calibration data that belongs to the pixel-to-pixel
* crosstalk compensation feature.
* @brief Pixel Crosstalk Vector Table.
* @details Contains crosstalk vector values for all 32 active pixels,
* separated for A/B-Frames.
*****************************************************************************/
typedef struct {
typedef struct argus_cal_xtalk_table_t {
union {
struct {
/*! The crosstalk vector table for A-Frames. */
xtalk_t FrameA[ARGUS_PIXELS_X][ARGUS_PIXELS_Y];
/*! The crosstalk vector table for B-Frames. */
xtalk_t FrameB[ARGUS_PIXELS_X][ARGUS_PIXELS_Y];
};
/*! The crosstalk vector table for A/B-Frames of all 32 pixels.*/
xtalk_t Table[ARGUS_DFM_FRAME_COUNT][ARGUS_PIXELS_X][ARGUS_PIXELS_Y];
};
} argus_cal_xtalk_table_t;
/*!***************************************************************************
* @brief Pixel-To-Pixel Crosstalk Compensation Parameters.
* @details Contains calibration data that belongs to the pixel-to-pixel
* crosstalk compensation feature.
*****************************************************************************/
typedef struct argus_cal_p2pxtalk_t {
/*! Pixel-To-Pixel Compensation on/off. */
bool Enabled;
/*! The relative threshold determines when the compensation is active for
* each individual pixel. The value determines the ratio of the individual
* pixel signal is with respect to the overall average signal. If the
* pixel signal with respect to the overall average signal. If the
* ratio is smaller than the value, the compensation is active. Absolute
* and relative conditions are connected with AND logic. */
uq0_8_t RelativeThreshold;
@@ -111,4 +138,7 @@ typedef struct {
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_XTALK_H */
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details This file the main header of the AFBR-S50 API.
* @brief This file is part of the AFBR-S50 API.
* @details This file the main header of the AFBR-S50 API.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,6 @@
#ifndef ARGUS_H
#define ARGUS_H
#ifdef __cplusplus
extern "C" {
#endif
@@ -44,7 +43,6 @@ extern "C" {
#include "api/argus_api.h"
#ifdef __cplusplus
}
} // extern "C"
#endif
#endif /* ARGUS_H */
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details This file provides an interface for enabling/disabling interrupts.
* @brief This file is part of the AFBR-S50 API.
* @details This file provides an interface for enabling/disabling interrupts.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,96 +36,94 @@
#ifndef ARGUS_IRQ_H
#define ARGUS_IRQ_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup argus_irq IRQ: Global Interrupt Control Layer
* @ingroup argus_platform
* @defgroup argus_irq IRQ: Global Interrupt Control Layer
* @ingroup argus_hal
*
* @brief Global Interrupt Control Layer
* @brief Global Interrupt Control Layer
*
* @details This module provides functionality to globally enable/disable
* interrupts in a nested way.
* @details This module provides functionality to globally enable/disable
* interrupts in a nested way.
*
* Here is a simple example implementation using the CMSIS functions
* "__enable_irq()" and "__disable_irq()". An integer counter is
* used to achieve nested interrupt disabling:
* Here is a simple example implementation using the CMSIS functions
* "__enable_irq()" and "__disable_irq()". An integer counter is
* used to achieve nested interrupt disabling:
*
* @code
* @code
*
* // Global lock level counter value.
* static volatile int g_irq_lock_ct;
* // Global lock level counter value.
* static volatile int g_irq_lock_ct;
*
* // Global unlock all interrupts using CMSIS function "__enable_irq()".
* void IRQ_UNLOCK(void)
* {
* assert(g_irq_lock_ct > 0);
* if (--g_irq_lock_ct <= 0)
* {
* g_irq_lock_ct = 0;
* __enable_irq();
* }
* }
* // Global unlock all interrupts using CMSIS function "__enable_irq()".
* void IRQ_UNLOCK(void)
* {
* assert(g_irq_lock_ct > 0);
* if (--g_irq_lock_ct <= 0)
* {
* g_irq_lock_ct = 0;
* __enable_irq();
* }
* }
*
* // Global lock all interrupts using CMSIS function "__disable_irq()".
* void IRQ_LOCK(void)
* {
* __disable_irq();
* g_irq_lock_ct++;
* }
* // Global lock all interrupts using CMSIS function "__disable_irq()".
* void IRQ_LOCK(void)
* {
* __disable_irq();
* g_irq_lock_ct++;
* }
*
* @endcode
* @endcode
*
* @note The IRQ locking mechanism is used to create atomic sections
* (within the scope of the AFBR-S50 API) that are very few processor
* instruction only. It does NOT lock interrupts for considerable
* amounts of time.
* @note The IRQ locking mechanism is used to create atomic sections
* (within the scope of the AFBR-S50 API) that are very few processor
* instruction only. It does NOT lock interrupts for considerable
* amounts of time.
*
* @note The IRQ_LOCK might get called multiple times. Therefore, the
* API expects that the IRQ_UNLOCK must be called as many times as
* the IRQ_LOCK was called before the interrupts are enabled.
* @note The IRQ_LOCK might get called multiple times. Therefore, the
* API expects that the IRQ_UNLOCK must be called as many times as
* the IRQ_LOCK was called before the interrupts are enabled.
*
* @note The interrupts utilized by the AFBR-S50 API can be interrupted
* by other, higher prioritized interrupts, e.g. some system
* critical interrupts. In this case, the IRQ_LOCK/IRQ_UNLOCK
* mechanism can be implemented such that only the interrupts
* required for the AFBR-S50 API are locked. The above example is
* dedicated to a ARM Corex-M0 architecture, where interrupts
* can only disabled at a global scope. Other architectures like
* ARM Cortex-M4 allow selective disabling of interrupts.
* @note The interrupts utilized by the AFBR-S50 API can be interrupted
* by other, higher prioritized interrupts, e.g. some system
* critical interrupts. In this case, the IRQ_LOCK/IRQ_UNLOCK
* mechanism can be implemented such that only the interrupts
* required for the AFBR-S50 API are locked. The above example is
* dedicated to a ARM Corex-M0 architecture, where interrupts
* can only disabled at a global scope. Other architectures like
* ARM Cortex-M4 allow selective disabling of interrupts.
*
* @addtogroup argus_irq
* @addtogroup argus_irq
* @{
*****************************************************************************/
/*!***************************************************************************
* @brief Enable IRQ Interrupts
* @brief Enable IRQ Interrupts
*
* @details Enables IRQ interrupts and enters an atomic or critical section.
* @details Enables IRQ interrupts and enters an atomic or critical section.
*
* @note The IRQ_LOCK might get called multiple times. Therefore, the
* API expects that the IRQ_UNLOCK must be called as many times as
* the IRQ_LOCK was called before the interrupts are enabled.
* @note The IRQ_LOCK might get called multiple times. Therefore, the
* API expects that the IRQ_UNLOCK must be called as many times as
* the IRQ_LOCK was called before the interrupts are enabled.
*****************************************************************************/
void IRQ_UNLOCK(void);
/*!***************************************************************************
* @brief Disable IRQ Interrupts
* @brief Disable IRQ Interrupts
*
* @details Disables IRQ interrupts and leaves the atomic or critical section.
* @details Disables IRQ interrupts and leaves the atomic or critical section.
*
* @note The IRQ_LOCK might get called multiple times. Therefore, the
* API expects that the IRQ_UNLOCK must be called as many times as
* the IRQ_LOCK was called before the interrupts are enabled.
* @note The IRQ_LOCK might get called multiple times. Therefore, the
* API expects that the IRQ_UNLOCK must be called as many times as
* the IRQ_LOCK was called before the interrupts are enabled.
*****************************************************************************/
void IRQ_LOCK(void);
#ifdef __cplusplus
}
#endif
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ARGUS_IRQ_H
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details This file provides an interface for the optional non-volatile memory.
* @brief This file is part of the AFBR-S50 API.
* @details This file provides an interface for the optional non-volatile memory.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,99 +36,113 @@
#ifndef ARGUS_NVM_H
#define ARGUS_NVM_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup argus_nvm NVM: Non-Volatile Memory Layer
* @ingroup argus_platform
* @defgroup argus_nvm NVM: Non-Volatile Memory Layer
* @ingroup argus_hal
*
* @brief Non-Volatile Memory Layer
* @brief Non-Volatile Memory Layer
*
* @details This module provides functionality to access the non-volatile
* memory (e.g. flash) on the underlying platform.
* @details This module provides functionality to access the non-volatile
* memory (e.g. flash) on the underlying platform.
*
* This module is optional and only required if calibration data
* needs to be stored within the API.
* This module is optional and only required if calibration data
* needs to be stored within the API.
*
* @note The implementation of this module is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that disables the NVM feature.
* @note The implementation of this module is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that disables the NVM feature.
*
* @addtogroup argus_nvm
* @addtogroup argus_nvm
* @{
*****************************************************************************/
#include "argus.h"
#include "api/argus_def.h"
/*! The NVM block size in the non-volatile memory. */
#define ARGUS_NVM_BLOCK_SIZE 0x300 // 768 bytes
/*!***************************************************************************
* @brief Initializes the non-volatile memory unit and reserves a chunk of memory.
* @brief Write a block of data to the non-volatile memory.
*
* @details The function is called upon API initialization sequence. If available,
* the non-volatile memory module reserves a chunk of memory with the
* provides number of bytes (size) and returns with #STATUS_OK.
* @details The function is called whenever the API wants to write data into
* non-volatile memory, e.g. flash. Later, the API reads the written
* data via the #NVM_ReadBlock function.
*
* If not implemented, the function should return #ERROR_NOT_IMPLEMENTED
* in oder to inform the API to not use the NVM module.
* The data shall be written to a specified memory block that is
* uniquely dedicated to each individual device. The /p id parameter
* is passed to the function that identifies the device. The /p id
* is composed of the device ID and module type, i.e. it is unique
* among all devices. If only a single device is used anyway, the
* /p id parameter can be ignored.
*
* After initialization, the API calls the #NVM_Write and #NVM_Read
* methods to write within the reserved chunk of memory.
* If no NVM module is available, the function can return with error
* #ERROR_NOT_IMPLEMENTED and the API ignores the NVM.
*
* @note The implementation of this function is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that disables the NVM feature.
* If write fails, e.g. due to lack of memory, a negative status
* must be returned, e.g. #ERROR_NVM_OUT_OF_RANGE.
*
* @param size The required size of NVM to store all parameters.
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
* The block size is fixed for a single device. The actual block size
* is defined with #ARGUS_NVM_BLOCK_SIZE.
*
* @note The implementation of this function is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that disables the NVM feature.
*
* @param id The 32-bit ID number to identify the corresponding memory block.
* @param block_size The number of bytes to be written. Note that this value
* is fixed, i.e. the API always writes the same data size.
* The size is defined here: #ARGUS_NVM_BLOCK_SIZE.
* @param buf The pointer to the data buffer of size /p block_size that needs
* to be written to the NVM.
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
*****************************************************************************/
status_t NVM_Init(uint32_t size);
status_t NVM_WriteBlock(uint32_t id, uint32_t block_size, uint8_t const *buf);
/*!***************************************************************************
* @brief Write a block of data to the non-volatile memory.
* @brief Reads a block of data from the non-volatile memory.
*
* @details The function is called whenever the API wants to write data into
* the previously reserved (#NVM_Init) memory block. The data shall
* be written at a given offset and with a given size.
* @details The function is called whenever the API wants to read data from
* non-volatile memory, e.g. flash. The data will be previously
* stored using the #NVM_WriteBlock function. Otherwise, the function
* must return a corresponding error code, namely #ERROR_NVM_EMPTY.
*
* If no NVM module is available, the function can return with error
* #ERROR_NOT_IMPLEMENTED.
* The data shall be read from a specified memory block that is
* uniquely dedicated to each individual device. The /p id parameter
* is passed to the function that identifies the device. The /p id
* is composed of the device ID and module type, i.e. it is unique
* among all devices. If only a single device is used anyway, the
* /p id parameter can be ignored.
*
* @note The implementation of this function is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that disables the NVM feature.
* If no NVM module is available, the function can return with error
* #ERROR_NOT_IMPLEMENTED and the API ignores the NVM.
*
* @param offset The index offset where the first byte needs to be written.
* @param size The number of bytes to be written.
* @param buf The pointer to the data buffer with the data to be written.
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
* If read fails, e.g. if data has not been written previously,
* a negative status must be returned, e.g. #ERROR_NVM_EMPTY if no
* data has been written yet or any other negative error else-wise.
*
* The block size is fixed for a single device. The actual block size
* is defined with #ARGUS_NVM_BLOCK_SIZE.
*
* @note The implementation of this function is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that disables the NVM feature.
*
* @param id The 32-bit ID number to identify the corresponding memory block.
* @param block_size The number of bytes to be read. Note that this value
* is fixed, i.e. the API always reads the same data size.
* The size is defined here: #ARGUS_NVM_BLOCK_SIZE.
* @param buf The pointer to the data buffer of size /p block_size to copy
* the data to.
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
*****************************************************************************/
status_t NVM_Write(uint32_t offset, uint32_t size, uint8_t const *buf);
/*!***************************************************************************
* @brief Reads a block of data from the non-volatile memory.
*
* @details The function is called whenever the API wants to read data from
* the previously reserved (#NVM_Init) memory block. The data shall
* be read at a given offset and with a given size.
*
* If no NVM module is available, the function can return with error
* #ERROR_NOT_IMPLEMENTED.
*
* @note The implementation of this function is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that disables the NVM feature.
*
* @param offset The index offset where the first byte needs to be read.
* @param size The number of bytes to be read.
* @param buf The pointer to the data buffer to copy the data to.
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
*****************************************************************************/
status_t NVM_Read(uint32_t offset, uint32_t size, uint8_t *buf);
#ifdef __cplusplus
}
#endif
status_t NVM_ReadBlock(uint32_t id, uint32_t block_size, uint8_t *buf);
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ARGUS_NVM_H
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details This file provides an interface for the optional debug module.
* @brief This file is part of the AFBR-S50 API.
* @details This file provides an interface for the optional debug module.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,48 +36,55 @@
#ifndef ARGUS_PRINT_H
#define ARGUS_PRINT_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup argus_log Debug: Logging Interface
* @ingroup argus_platform
* @defgroup argus_log Debug: Logging Interface
* @ingroup argus_hal
*
* @brief Logging interface for the AFBR-S50 API.
* @brief Logging interface for the AFBR-S50 API.
*
* @details This interface provides logging utility functions.
* Defines a printf-like function that is used to print error and
* log messages.
* @details This interface provides logging utility functions.
* Defines a printf-like function that is used to print error and
* log messages.
*
* @addtogroup argus_log
* @addtogroup argus_log
* @{
*****************************************************************************/
#include "api/argus_def.h"
/*!***************************************************************************
* @brief A printf-like function to print formatted data to an debugging interface.
* @brief A printf-like function to print formatted data to an debugging interface.
*
* @details Writes the C string pointed by fmt_t to an output. If format
* includes format specifiers (subsequences beginning with %), the
* additional arguments following fmt_t are formatted and inserted in
* the resulting string replacing their respective specifiers.
* includes format specifiers (subsequences beginning with %), the
* additional arguments following fmt_t are formatted and inserted in
* the resulting string replacing their respective specifiers.
*
* To enable the print functionality, an implementation of the function
* must be provided that maps the output to an interface like UART or
* a debugging console, e.g. by forwarding to standard printf() method.
* To enable the print functionality, an implementation of the function
* must be provided that maps the output to an interface like UART or
* a debugging console, e.g. by forwarding to standard printf() method.
*
* @note The implementation of this function is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that does nothing. This will improve
* the performance but no error messages are logged.
* @note The implementation of this function is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that does nothing. This will improve
* the performance but no error messages are logged.
*
* @note The naming is different from the standard printf() on purpose to
* prevent builtin compiler optimizations.
* @note The naming is different from the standard printf() on purpose to
* prevent builtin compiler optimizations.
*
* @param fmt_s The usual print() format string.
* @param ... The usual print() parameters. *
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
* @param fmt_s The usual print() format string.
* @param ... The usual print() parameters.
*
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
*****************************************************************************/
status_t print(const char *fmt_s, ...);
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_PRINT_H */
File diff suppressed because it is too large Load Diff
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details This file provides an interface for the required timer modules.
* @brief This file is part of the AFBR-S50 API.
* @details This file provides an interface for the required timer modules.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,118 +36,117 @@
#ifndef ARGUS_TIMER_H
#define ARGUS_TIMER_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup argus_timer Timer: Hardware Timer Interface
* @ingroup argus_platform
* @defgroup argus_timer Timer: Hardware Timer Interface
* @ingroup argus_hal
*
* @brief Timer implementations for lifetime counting as well as periodic
* callback.
* @brief Timer implementations for lifetime counting as well as periodic
* callback.
*
* @details The module provides an interface to the timing utilities that
* are required by the AFBR-S50 time-of-flight sensor API.
* @details The module provides an interface to the timing utilities that
* are required by the AFBR-S50 time-of-flight sensor API.
*
* Two essential features have to be provided by the user code:
* 1. Time Measurement Capability: In order to keep track of outgoing
* signals, the API needs to measure elapsed time. In order to
* provide optimum device performance, the granularity should be
* around 10 to 100 microseconds.
* 2. Periodic Callback: The API provides an automatic starting of
* measurement cycles at a fixed frame rate via a periodic
* interrupt timer. If this feature is not used, implementation
* of the periodic interrupts can be skipped. An weak default
* implementation is provide in the API.
* .
* Two essential features have to be provided by the user code:
* 1. Time Measurement Capability: In order to keep track of outgoing
* signals, the API needs to measure elapsed time. In order to
* provide optimum device performance, the granularity should be
* around 10 to 100 microseconds.
* 2. Periodic Callback: The API provides an automatic starting of
* measurement cycles at a fixed frame rate via a periodic
* interrupt timer. If this feature is not used, implementation
* of the periodic interrupts can be skipped. An weak default
* implementation is provide in the API.
* .
*
* The time measurement feature is simply implemented by the function
* #Timer_GetCounterValue. Whenever the function is called, the
* provided counter values must be written with the values obtained
* by the current time.
* The time measurement feature is simply implemented by the function
* #Timer_GetCounterValue. Whenever the function is called, the
* provided counter values must be written with the values obtained
* by the current time.
*
* The periodic interrupt timer is a simple callback interface.
* After installing the callback function pointer via #Timer_SetCallback,
* the timer can be started by setting interval via #Timer_SetInterval.
* From then, the callback is invoked periodically as the corresponding
* interval may specify. The timer is stopped by setting the interval
* to 0 using the #Timer_SetInterval function. The interval can be
* updated at any time by updating the interval via the #Timer_SetInterval
* function. To any of these functions, an abstract parameter pointer
* must be passed. This parameter is passed back to the callback any
* time it is invoked.
* The periodic interrupt timer is a simple callback interface.
* After installing the callback function pointer via #Timer_SetCallback,
* the timer can be started by setting interval via #Timer_SetInterval.
* From then, the callback is invoked periodically as the corresponding
* interval may specify. The timer is stopped by setting the interval
* to 0 using the #Timer_SetInterval function. The interval can be
* updated at any time by updating the interval via the #Timer_SetInterval
* function. To any of these functions, an abstract parameter pointer
* must be passed. This parameter is passed back to the callback any
* time it is invoked.
*
* In order to provide the usage of multiple devices, an mechanism is
* introduced to allow the installation of multiple callback interval
* at the same time. Therefore, the abstract parameter pointer is used
* to identify the corresponding callback interval. For example, there
* are two callbacks for two intervals, t1 and t2, required. The user
* can start two timers by calling the #Timer_SetInterval method twice,
* but with an individual parameter pointer, ptr1 and ptr2, each:
* \code
* Timer_SetInterval(100000, ptr1); // 10 ms callback w/ parameter ptr1
* Timer_SetInterval(200000, ptr2); // 20 ms callback w/ parameter ptr1
* \endcode
* In order to provide the usage of multiple devices, an mechanism is
* introduced to allow the installation of multiple callback interval
* at the same time. Therefore, the abstract parameter pointer is used
* to identify the corresponding callback interval. For example, there
* are two callbacks for two intervals, t1 and t2, required. The user
* can start two timers by calling the #Timer_SetInterval method twice,
* but with an individual parameter pointer, ptr1 and ptr2, each:
* \code
* Timer_SetInterval(100000, ptr1); // 10 ms callback w/ parameter ptr1
* Timer_SetInterval(200000, ptr2); // 20 ms callback w/ parameter ptr1
* \endcode
*
* Note that the implemented timer module must therefore support
* as many different intervals as instances of the AFBR-S50 device are
* used.
* Note that the implemented timer module must therefore support
* as many different intervals as instances of the AFBR-S50 device are
* used.
*
* @addtogroup argus_timer
* @addtogroup argus_timer
* @{
*****************************************************************************/
#include "api/argus_def.h"
#include "utility/status.h"
/*******************************************************************************
* Lifetime Counter Timer Interface
******************************************************************************/
/*!***************************************************************************
* @brief Obtains the lifetime counter value from the timers.
* @brief Obtains the lifetime counter value from the timers.
*
* @details The function is required to get the current time relative to any
* point in time, e.g. the startup time. The returned values \p hct and
* \p lct are given in seconds and microseconds respectively. The current
* elapsed time since the reference time is then calculated from:
* point in time, e.g. the startup time. The returned values \p hct and
* \p lct are given in seconds and microseconds respectively. The current
* elapsed time since the reference time is then calculated from:
*
* t_now [µsec] = hct * 1000000 µsec + lct * 1 µsec
* t_now [µsec] = hct * 1000000 µsec + lct * 1 µsec
*
* Note that the accuracy/granularity of the lifetime counter does
* not need to be 1 µsec. Usually, a granularity of approximately
* 100 µsec is sufficient. However, in case of very high frame rates
* (above 1000 frames per second), it is recommended to implement
* an even lower granularity (somewhere in the 10 µsec regime).
* Note that the accuracy/granularity of the lifetime counter does
* not need to be 1 µsec. Usually, a granularity of approximately
* 100 µsec is sufficient. However, in case of very high frame rates
* (above 1000 frames per second), it is recommended to implement
* an even lower granularity (somewhere in the 10 µsec regime).
*
* It must be guaranteed, that each call of the #Timer_GetCounterValue
* function must provide a value that is greater or equal, but never lower,
* than the value returned from the previous call.
* It must be guaranteed, that each call of the #Timer_GetCounterValue
* function must provide a value that is greater or equal, but never lower,
* than the value returned from the previous call.
*
* A hardware based implementation of the lifetime counter functionality
* would be to chain two distinct timers such that counter 2 increases
* its value when counter 1 wraps to 0. The easiest way is to setup
* counter 1 to wrap exactly every second. Counter 1 would than count
* the sub-seconds (i.e. µsec) value (\p lct) and counter 2 the seconds
* (\p hct) value. A 16-bit counter is sufficient in case of counter 1
* while counter 2 must be a 32-bit version.
* A hardware based implementation of the lifetime counter functionality
* would be to chain two distinct timers such that counter 2 increases
* its value when counter 1 wraps to 0. The easiest way is to setup
* counter 1 to wrap exactly every second. Counter 1 would than count
* the sub-seconds (i.e. µsec) value (\p lct) and counter 2 the seconds
* (\p hct) value. A 16-bit counter is sufficient in case of counter 1
* while counter 2 must be a 32-bit version.
*
* In case of a lack of available hardware timers, a software solution
* can be used that requires only a 16-bit timer. In a simple scenario,
* the timer is configured to wrap around every second and increase
* a software counter value in its interrupt service routine (triggered
* with the wrap around event) every time the wrap around occurs.
* In case of a lack of available hardware timers, a software solution
* can be used that requires only a 16-bit timer. In a simple scenario,
* the timer is configured to wrap around every second and increase
* a software counter value in its interrupt service routine (triggered
* with the wrap around event) every time the wrap around occurs.
*
*
* @note The implementation of this function is mandatory for the correct
* execution of the API.
* @note The implementation of this function is mandatory for the correct
* execution of the API.
*
* @param hct A pointer to the high counter value bits representing current
* time in seconds.
* @param hct A pointer to the high counter value bits representing current
* time in seconds.
*
* @param lct A pointer to the low counter value bits representing current
* time in microseconds. Range: 0, .., 999999 µsec
* @param lct A pointer to the low counter value bits representing current
* time in microseconds. Range: 0, .., 999999 µsec
*****************************************************************************/
void Timer_GetCounterValue(uint32_t *hct, uint32_t *lct);
@@ -156,68 +155,70 @@ void Timer_GetCounterValue(uint32_t *hct, uint32_t *lct);
******************************************************************************/
/*!***************************************************************************
* @brief The callback function type for periodic interrupt timer.
* @brief The callback function type for periodic interrupt timer.
*
* @details The function that is invoked every time a specified interval elapses.
* An abstract parameter is passed to the function whenever it is called.
* @details The function that is invoked every time a specified interval elapses.
* An abstract parameter is passed to the function whenever it is called.
*
* @param param An abstract parameter to be passed to the callback. This is
* also the identifier of the given interval.
* @param param An abstract parameter to be passed to the callback. This is
* also the identifier of the given interval.
*****************************************************************************/
typedef void (*timer_cb_t)(void *param);
/*!***************************************************************************
* @brief Installs an periodic timer callback function.
* @brief Installs an periodic timer callback function.
*
* @details Installs an periodic timer callback function that is invoked whenever
* an interval elapses. The callback is the same for any interval,
* however, the single intervals can be identified by the passed
* parameter.
* Passing a zero-pointer removes and disables the callback.
* @details Installs an periodic timer callback function that is invoked whenever
* an interval elapses. The callback is the same for any interval,
* however, the single intervals can be identified by the passed
* parameter.
* Passing a zero-pointer removes and disables the callback.
*
* @note The implementation of this function is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that disable the periodic timer callback
* and thus the automatic starting of measurements from the background.
* @note The implementation of this function is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that disable the periodic timer callback
* and thus the automatic starting of measurements from the background.
*
* @param f The timer callback function.
* @param f The timer callback function.
*
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
*****************************************************************************/
status_t Timer_SetCallback(timer_cb_t f);
/*!***************************************************************************
* @brief Sets the timer interval for a specified callback parameter.
* @brief Sets the timer interval for a specified callback parameter.
*
* @details Sets the callback interval for the specified parameter and starts
* the timer with a new interval. If there is already an interval with
* the given parameter, the timer is restarted with the given interval.
* If the same time interval as already set is passed, nothing happens.
* Passing a interval of 0 disables the timer.
* @details Sets the callback interval for the specified parameter and starts
* the timer with a new interval. If there is already an interval with
* the given parameter, the timer is restarted with the given interval.
* If the same time interval as already set is passed, nothing happens.
* Passing a interval of 0 disables the timer.
*
* Note that a microsecond granularity for the timer interrupt period is
* not required. Usually a microseconds granularity is sufficient.
* The required granularity depends on the targeted frame rate, e.g. in
* case of more than 1 kHz measurement rate, a granularity of less than
* a microsecond is required to achieve the given frame rate.
* When enabling the timer (or resetting by applying another interval),
* the first timer interrupt must happen after the specified interval.
*
* @note The implementation of this function is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that disable the periodic timer callback
* and thus the automatic starting of measurements from the background.
* Note that a microsecond granularity for the timer interrupt period is
* not required. Usually a milliseconds granularity is sufficient.
* The required granularity depends on the targeted frame rate, e.g. in
* case of more than 1 kHz measurement rate, a granularity of less than
* a millisecond is required to achieve the given frame rate.
*
* @param dt_microseconds The callback interval in microseconds.
* @note The implementation of this function is optional for the correct
* execution of the API. If not implemented, a weak implementation
* within the API will be used that disable the periodic timer callback
* and thus the automatic starting of measurements from the background.
*
* @param param An abstract parameter to be passed to the callback. This is
* also the identifier of the given interval.
* @param dt_microseconds The callback interval in microseconds.
*
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
* @param param An abstract parameter to be passed to the callback. This is
* also the identifier of the given interval.
*
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
*****************************************************************************/
status_t Timer_SetInterval(uint32_t dt_microseconds, void *param);
#ifdef __cplusplus
}
#endif
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_TIMER_H */
@@ -1,11 +1,11 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Provides definitions and basic macros for fixed point data types.
* @brief This file is part of the AFBR-S50 API.
* @details Provides definitions and basic macros for fixed point data types.
*
* @copyright
*
* Copyright (c) 2021, Broadcom Inc
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,23 +36,30 @@
#ifndef FP_DEF_H
#define FP_DEF_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @defgroup fixedpoint Fixed Point Math
* @ingroup argusutil
* @brief A basic math library for fixed point number in the Qx.y fomat.
* @details This module contains common fixed point type definitions as
* well as some basic math algorithms. All types are based on
* integer types. The number are defined with the Q number format.
* @defgroup argus_fp Fixed Point Math
* @ingroup argus_util
*
* - For a description of the Q number format refer to:
* https://en.wikipedia.org/wiki/Q_(number_format)
* - Another resource for fixed point math in C might be found at
* http://www.eetimes.com/author.asp?section_id=36&doc_id=1287491
* .
* @warning This definitions are not portable and work only with
* little-endian systems!
* @addtogroup fixedpoint
* @brief A basic math library for fixed point number in the Qx.y fomat.
*
* @details This module contains common fixed point type definitions as
* well as some basic math algorithms. All types are based on
* integer types. The number are defined with the Q number format.
*
* - For a description of the Q number format refer to:
* https://en.wikipedia.org/wiki/Q_(number_format)
* - Another resource for fixed point math in C might be found at
* http://www.eetimes.com/author.asp?section_id=36&doc_id=1287491
* .
*
* @warning This definitions are not portable and work only with
* little-endian systems!
*
* @addtogroup argus_fp
* @{
*****************************************************************************/
@@ -66,11 +73,11 @@
***** UQ6.2
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ6.2
* @details An unsigned fixed point number format based on the 8-bit unsigned
* integer type with 6 integer and 2 fractional bits.
* - Range: 0 .. 63.75
* - Granularity: 0.25
* @brief Unsigned fixed point number: UQ6.2
* @details An unsigned fixed point number format based on the 8-bit unsigned
* integer type with 6 integer and 2 fractional bits.
* - Range: 0 .. 63.75
* - Granularity: 0.25
*****************************************************************************/
typedef uint8_t uq6_2_t;
@@ -86,11 +93,11 @@ typedef uint8_t uq6_2_t;
***** UQ4.4
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ4.4
* @details An unsigned fixed point number format based on the 8-bit unsigned
* integer type with 4 integer and 4 fractional bits.
* - Range: 0 .. 15.9375
* - Granularity: 0.0625
* @brief Unsigned fixed point number: UQ4.4
* @details An unsigned fixed point number format based on the 8-bit unsigned
* integer type with 4 integer and 4 fractional bits.
* - Range: 0 .. 15.9375
* - Granularity: 0.0625
*****************************************************************************/
typedef uint8_t uq4_4_t;
@@ -106,11 +113,11 @@ typedef uint8_t uq4_4_t;
***** UQ2.6
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ2.6
* @details An unsigned fixed point number format based on the 8-bit unsigned
* integer type with 2 integer and 6 fractional bits.
* - Range: 0 .. 3.984375
* - Granularity: 0.015625
* @brief Unsigned fixed point number: UQ2.6
* @details An unsigned fixed point number format based on the 8-bit unsigned
* integer type with 2 integer and 6 fractional bits.
* - Range: 0 .. 3.984375
* - Granularity: 0.015625
*****************************************************************************/
typedef uint8_t uq2_6_t;
@@ -126,11 +133,11 @@ typedef uint8_t uq2_6_t;
***** UQ1.7
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ1.7
* @details An unsigned fixed point number format based on the 8-bit unsigned
* integer type with 1 integer and 7 fractional bits.
* - Range: 0 .. 1.9921875
* - Granularity: 0.0078125
* @brief Unsigned fixed point number: UQ1.7
* @details An unsigned fixed point number format based on the 8-bit unsigned
* integer type with 1 integer and 7 fractional bits.
* - Range: 0 .. 1.9921875
* - Granularity: 0.0078125
*****************************************************************************/
typedef uint8_t uq1_7_t;
@@ -146,11 +153,11 @@ typedef uint8_t uq1_7_t;
***** UQ0.8
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ0.8
* @details An unsigned fixed point number format based on the 8-bit unsigned
* integer type with 1 integer and 7 fractional bits.
* - Range: 0 .. 0.99609375
* - Granularity: 0.00390625
* @brief Unsigned fixed point number: UQ0.8
* @details An unsigned fixed point number format based on the 8-bit unsigned
* integer type with 1 integer and 7 fractional bits.
* - Range: 0 .. 0.99609375
* - Granularity: 0.00390625
*****************************************************************************/
typedef uint8_t uq0_8_t;
@@ -167,11 +174,11 @@ typedef uint8_t uq0_8_t;
***** Q3.4
******************************************************************************/
/*!***************************************************************************
* @brief Signed fixed point number: Q3.4
* @details A signed fixed point number format based on the 8-bit signed
* integer type with 3 integer and 4 fractional bits.
* - Range: -8 ... 7.9375
* - Granularity: 0.0625
* @brief Signed fixed point number: Q3.4
* @details A signed fixed point number format based on the 8-bit signed
* integer type with 3 integer and 4 fractional bits.
* - Range: -8 ... 7.9375
* - Granularity: 0.0625
*****************************************************************************/
typedef int8_t q3_4_t;
@@ -189,11 +196,11 @@ typedef int8_t q3_4_t;
***** Q1.6
******************************************************************************/
/*!***************************************************************************
* @brief Signed fixed point number: Q1.6
* @details A signed fixed point number format based on the 8-bit signed
* integer type with 1 integer and 6 fractional bits.
* - Range: -2 ... 1.984375
* - Granularity: 0.015625
* @brief Signed fixed point number: Q1.6
* @details A signed fixed point number format based on the 8-bit signed
* integer type with 1 integer and 6 fractional bits.
* - Range: -2 ... 1.984375
* - Granularity: 0.015625
*****************************************************************************/
typedef int8_t q1_6_t;
@@ -215,11 +222,11 @@ typedef int8_t q1_6_t;
***** UQ12.4
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ12.4
* @details An unsigned fixed point number format based on the 16-bit unsigned
* integer type with 12 integer and 4 fractional bits.
* - Range: 0 ... 4095.9375
* - Granularity: 0.0625
* @brief Unsigned fixed point number: UQ12.4
* @details An unsigned fixed point number format based on the 16-bit unsigned
* integer type with 12 integer and 4 fractional bits.
* - Range: 0 ... 4095.9375
* - Granularity: 0.0625
*****************************************************************************/
typedef uint16_t uq12_4_t;
@@ -235,11 +242,11 @@ typedef uint16_t uq12_4_t;
***** UQ10.6
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ10.6
* @details An unsigned fixed point number format based on the 16-bit unsigned
* integer type with 10 integer and 6 fractional bits.
* - Range: 0 ... 1023.984375
* - Granularity: 0.015625
* @brief Unsigned fixed point number: UQ10.6
* @details An unsigned fixed point number format based on the 16-bit unsigned
* integer type with 10 integer and 6 fractional bits.
* - Range: 0 ... 1023.984375
* - Granularity: 0.015625
*****************************************************************************/
typedef uint16_t uq10_6_t;
@@ -255,11 +262,11 @@ typedef uint16_t uq10_6_t;
***** UQ1.15
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ1.15
* @details An unsigned fixed point number format based on the 16-bit unsigned
* integer type with 1 integer and 15 fractional bits.
* - Range: 0 .. 1.999969
* - Granularity: 0.000031
* @brief Unsigned fixed point number: UQ1.15
* @details An unsigned fixed point number format based on the 16-bit unsigned
* integer type with 1 integer and 15 fractional bits.
* - Range: 0 .. 1.999969
* - Granularity: 0.000031
*****************************************************************************/
typedef uint16_t uq1_15_t;
@@ -275,11 +282,11 @@ typedef uint16_t uq1_15_t;
***** UQ0.16
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ0.16
* @details An unsigned fixed point number format based on the 16-bit unsigned
* integer type with 0 integer and 16 fractional bits.
* - Range: 0 .. 0.9999847412109375
* - Granularity: 1.52587890625e-5
* @brief Unsigned fixed point number: UQ0.16
* @details An unsigned fixed point number format based on the 16-bit unsigned
* integer type with 0 integer and 16 fractional bits.
* - Range: 0 .. 0.9999847412109375
* - Granularity: 1.52587890625e-5
*****************************************************************************/
typedef uint16_t uq0_16_t;
@@ -296,11 +303,11 @@ typedef uint16_t uq0_16_t;
***** Q11.4
******************************************************************************/
/*!***************************************************************************
* @brief Signed fixed point number: Q11.4
* @details A signed fixed point number format based on the 16-bit signed
* integer type with 11 integer and 4 fractional bits.
* - Range: -2048 ... 2047.9375
* - Granularity: 0.0625
* @brief Signed fixed point number: Q11.4
* @details A signed fixed point number format based on the 16-bit signed
* integer type with 11 integer and 4 fractional bits.
* - Range: -2048 ... 2047.9375
* - Granularity: 0.0625
*****************************************************************************/
typedef int16_t q11_4_t;
@@ -319,11 +326,11 @@ typedef int16_t q11_4_t;
***** Q7.8
******************************************************************************/
/*!***************************************************************************
* @brief Signed fixed point number: Q7.8
* @details A signed fixed point number format based on the 16-bit signed
* integer type with 7 integer and 8 fractional bits.
* - Range: -128 .. 127.99609375
* - Granularity: 0.00390625
* @brief Signed fixed point number: Q7.8
* @details A signed fixed point number format based on the 16-bit signed
* integer type with 7 integer and 8 fractional bits.
* - Range: -128 .. 127.99609375
* - Granularity: 0.00390625
*****************************************************************************/
typedef int16_t q7_8_t;
@@ -342,11 +349,11 @@ typedef int16_t q7_8_t;
***** Q3.12
******************************************************************************/
/*!***************************************************************************
* @brief Signed fixed point number: Q3.12
* @details A signed fixed point number format based on the 16-bit integer
* type with 3 integer and 12 fractional bits.
* - Range: -8 .. 7.99975586
* - Granularity: 0.00024414
* @brief Signed fixed point number: Q3.12
* @details A signed fixed point number format based on the 16-bit integer
* type with 3 integer and 12 fractional bits.
* - Range: -8 .. 7.99975586
* - Granularity: 0.00024414
*****************************************************************************/
typedef int16_t q3_12_t;
@@ -365,11 +372,11 @@ typedef int16_t q3_12_t;
***** Q0.15
******************************************************************************/
/*!***************************************************************************
* @brief Signed fixed point number: Q0.15
* @details A signed fixed point number format based on the 16-bit integer
* type with 0 integer and 15 fractional bits.
* - Range: -1 .. 0.999969482
* - Granularity: 0.000030518
* @brief Signed fixed point number: Q0.15
* @details A signed fixed point number format based on the 16-bit integer
* type with 0 integer and 15 fractional bits.
* - Range: -1 .. 0.999969482
* - Granularity: 0.000030518
*****************************************************************************/
typedef int16_t q0_15_t;
@@ -389,11 +396,11 @@ typedef int16_t q0_15_t;
***** UQ28.4
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ28.4
* @details An unsigned fixed point number format based on the 32-bit unsigned
* integer type with 28 integer and 4 fractional bits.
* - Range: 0 ... 268435455.9375
* - Granularity: 0.0625
* @brief Unsigned fixed point number: UQ28.4
* @details An unsigned fixed point number format based on the 32-bit unsigned
* integer type with 28 integer and 4 fractional bits.
* - Range: 0 ... 268435455.9375
* - Granularity: 0.0625
*****************************************************************************/
typedef uint32_t uq28_4_t;
@@ -409,11 +416,11 @@ typedef uint32_t uq28_4_t;
***** UQ16.16
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ16.16
* @details An unsigned fixed point number format based on the 32-bit unsigned
* integer type with 16 integer and 16 fractional bits.
* - Range: 0 ... 65535.999984741
* - Granularity: 0.000015259
* @brief Unsigned fixed point number: UQ16.16
* @details An unsigned fixed point number format based on the 32-bit unsigned
* integer type with 16 integer and 16 fractional bits.
* - Range: 0 ... 65535.999984741
* - Granularity: 0.000015259
*****************************************************************************/
typedef uint32_t uq16_16_t;
@@ -432,11 +439,11 @@ typedef uint32_t uq16_16_t;
***** UQ10.22
******************************************************************************/
/*!***************************************************************************
* @brief Unsigned fixed point number: UQ10.22
* @details An unsigned fixed point number format based on the 32-bit unsigned
* integer type with 10 integer and 22 fractional bits.
* - Range: 0 ... 1023.99999976158
* - Granularity: 2.38418579101562E-07
* @brief Unsigned fixed point number: UQ10.22
* @details An unsigned fixed point number format based on the 32-bit unsigned
* integer type with 10 integer and 22 fractional bits.
* - Range: 0 ... 1023.99999976158
* - Granularity: 2.38418579101562E-07
*****************************************************************************/
typedef uint32_t uq10_22_t;
@@ -456,11 +463,11 @@ typedef uint32_t uq10_22_t;
***** Q27.4
******************************************************************************/
/*!***************************************************************************
* @brief Signed fixed point number: Q27.4
* @details A signed fixed point number format based on the 32-bit signed
* integer type with 27 integer and 4 fractional bits.
* - Range: -134217728 ... 134217727.9375
* - Granularity: 0.0625
* @brief Signed fixed point number: Q27.4
* @details A signed fixed point number format based on the 32-bit signed
* integer type with 27 integer and 4 fractional bits.
* - Range: -134217728 ... 134217727.9375
* - Granularity: 0.0625
*****************************************************************************/
typedef int32_t q27_4_t;
@@ -475,15 +482,35 @@ typedef int32_t q27_4_t;
/*******************************************************************************
***** Q16.15
******************************************************************************/
/*!***************************************************************************
* @brief Signed fixed point number: Q16.15
* @details A signed fixed point number format based on the 32-bit integer
* type with 16 integer and 15 fractional bits.
* - Range: -65536 .. 65536.999969482
* - Granularity: 0.000030518
*****************************************************************************/
typedef int32_t q16_15_t;
/*! Minimum value of Q16.15 number format. */
#define Q16_15_MIN ((q16_15_t)INT32_MIN)
/*! Maximum value of Q16.15 number format. */
#define Q16_15_MAX ((q16_15_t)INT32_MAX)
/*******************************************************************************
***** Q15.16
******************************************************************************/
/*!***************************************************************************
* @brief Signed fixed point number: Q15.16
* @details A signed fixed point number format based on the 32-bit integer
* type with 15 integer and 16 fractional bits.
* - Range: -32768 .. 32767.99998
* - Granularity: 1.52588E-05
* @brief Signed fixed point number: Q15.16
* @details A signed fixed point number format based on the 32-bit integer
* type with 15 integer and 16 fractional bits.
* - Range: -32768 .. 32767.99998
* - Granularity: 1.52588E-05
*****************************************************************************/
typedef int32_t q15_16_t;
@@ -502,11 +529,11 @@ typedef int32_t q15_16_t;
***** Q9.22
******************************************************************************/
/*!***************************************************************************
* @brief Signed fixed point number: Q9.22
* @details A signed fixed point number format based on the 32-bit integer
* type with 9 integer and 22 fractional bits.
* - Range: -512 ... 511.9999998
* - Granularity: 2.38418579101562E-07
* @brief Signed fixed point number: Q9.22
* @details A signed fixed point number format based on the 32-bit integer
* type with 9 integer and 22 fractional bits.
* - Range: -512 ... 511.9999998
* - Granularity: 2.38418579101562E-07
*****************************************************************************/
typedef int32_t q9_22_t;
@@ -522,4 +549,7 @@ typedef int32_t q9_22_t;
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* FP_DEF_H */
@@ -0,0 +1,173 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Provides definitions and basic macros for fixed point data types.
*
* @copyright
*
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef FP_DIV_H
#define FP_DIV_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @addtogroup argus_fp
* @{
*****************************************************************************/
#include "fp_def.h"
#include "int_math.h"
/*!***************************************************************************
* Set to use hardware division (Cortex-M3/4) over software division (Cortex-M0/1).
*****************************************************************************/
#ifndef USE_HW_DIV
#define USE_HW_DIV 0
#endif
/*!***************************************************************************
* @brief 32-bit implementation of an Q15.16 division.
*
* @details Algorithm to evaluate a/b, where b is in Q15.16 format, on a 32-bit
* architecture with maximum precision.
* The result is correctly rounded and given as the input format.
* Division by 0 yields max. values determined by signa of numerator.
* Too high/low results are truncated to max/min values.
*
* Depending on the architecture, the division is implemented with a 64-bit
* division and shifting (Cortex-M3/4) or as a fast software algorithm
* (Cortex-M0/1) wich runs fast on processors without hardware division.
*
* @see https://code.google.com/archive/p/libfixmath
*
* @param a Numerator in any Qx.y format
* @param b Denominator in Q15.16 format
* @return Result = a/b in the same Qx.y format as the input parameter a.
*****************************************************************************/
inline int32_t fp_div16(int32_t a, q15_16_t b)
{
//assert(b);
if (b == 0) { return a < 0 ? INT32_MIN : INT32_MAX; }
#if USE_HW_DIV
// Tested on Cortex-M4, it takes approx. 75% of the
// software algorithm below.
int64_t c = ((int64_t) a) << 30U;
if ((uint32_t)(a ^ b) & 0x80000000U) {
c = (((-c) / b) + (1 << 13U)) >> 14U;
if (c > 0x80000000U) { return INT32_MIN; }
return -c;
} else {
c = ((c / b) + (1 << 13U)) >> 14U;
if (c > (int64_t)INT32_MAX) { return INT32_MAX; }
return c;
}
#else
// This uses the basic binary restoring division algorithm.
// It appears to be faster to do the whole division manually than
// trying to compose a 64-bit divide out of 32-bit divisions on
// platforms without hardware divide.
// Tested on Cortex-M0, it takes approx. 33% of the time of the
// 64-bit version above.
uint32_t remainder = absval(a);
uint32_t divider = absval(b);
uint32_t quotient = 0;
uint32_t bit = 0x10000U;
/* The algorithm requires D >= R */
while (divider < remainder) {
divider <<= 1U;
bit <<= 1U;
}
if (!bit) {
if ((uint32_t)(a ^ b) & 0x80000000U) { // return truncated values
return INT32_MIN;
} else {
return INT32_MAX;
}
}
if (divider & 0x80000000U) {
// Perform one step manually to avoid overflows later.
// We know that divider's bottom bit is 0 here.
if (remainder >= divider) {
quotient |= bit;
remainder -= divider;
}
divider >>= 1U;
bit >>= 1U;
}
/* Main division loop */
while (bit && remainder) {
if (remainder >= divider) {
quotient |= bit;
remainder -= divider;
}
remainder <<= 1U;
bit >>= 1U;
}
if (remainder >= divider) {
quotient++;
}
uint32_t result = quotient;
/* Figure out the sign of result */
if ((uint32_t)(a ^ b) & 0x80000000U) {
result = -result;
}
return (int32_t)result;
#endif
}
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* FP_DIV_H */
@@ -0,0 +1,204 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Provides averaging algorithms for fixed point data types.
*
* @copyright
*
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef FP_EMA_H
#define FP_EMA_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @addtogroup argus_fp
* @{
*****************************************************************************/
#include "fp_def.h"
#include "utility/fp_rnd.h"
#include "utility/fp_mul.h"
/*!***************************************************************************
* @brief Circular exponentially weighted moving average using UQ1.15 format.
*
* @details Evaluates the moving average (exponentially weighted) for circular
* data in UQ1.15 format.
* Circular data is that MAX_VALUE + 1 == MIN_VALUE. For example the
* usual phase information.
*
* Problem: Due to circularity of phase values, i.e. 0+x and 2PI+x are
* the same, the usual EMA has issues with the wrap around effect.
* Especially for vectors with phase around 0 (or 2PI), two values
* like 0 + x and PI - y are averaged to something around PI instead
* of 0 which would be more correct.
*
* Solution: Assume that phase jumps of more than PI are not allowed
* or possible. If a deviation of the new value to the smoothed signal
* occurs, it is clear that this stems from the wrap around effect and
* can be caught and correctly handled by the smoothing algorithm.
*
* Caution: If a target comes immediately into the field of view, phase
* jumps of > PI are indeed possible and volitional. However, the
* averaging break there anyway since the smoothed signal approaches
* only with delay to the correct values. The error made here is, that
* the smoothed signal approaches from the opposite direction. However,
* is approaches even faster since it always takes the shortest
* direction.
*
* @param mean The previous mean value in UQ1.15 format.
* @param x The current value to be added to the average UQ1.15 format.
* @param weight The EMA weight in UQ0.7 format.
* @return The new mean value in UQ1.15 format.
*****************************************************************************/
inline uq1_15_t fp_ema15c(uq1_15_t mean, uq1_15_t x, uq0_8_t weight)
{
if (weight == 0) { return x; }
// Heeds the wrap around effect by casting dx to int16:
const int16_t dx = (int16_t)(x - mean);
const int32_t diff = weight * dx;
return (uq1_15_t)fp_rnds((mean << 8U) + diff, 8U);
}
/*!***************************************************************************
* @brief Exponentially weighted moving average using the Q11.4 format.
*
* @details Evaluates the moving average (exponentially weighted) for data in
* Q11.4 format.
*
* @param mean The previous mean value in Q11.4 format.
* @param x The current value to be added to the average Q11.4 format.
* @param weight The EMA weight in UQ0.7 format.
* @return The new mean value in Q11.4 format.
*****************************************************************************/
inline q11_4_t fp_ema4(q11_4_t mean, q11_4_t x, uq0_8_t weight)
{
if (weight == 0) { return x; }
const int32_t dx = x - mean;
const int32_t diff = weight * dx;
return (q11_4_t)fp_rnds((mean << 8U) + diff, 8U);
}
/*!***************************************************************************
* @brief Exponentially weighted moving average using the Q7.8 format.
*
* @details Evaluates the moving average (exponentially weighted) for data in
* Q7.8 format.
*
* @param mean The previous mean value in Q7.8 format.
* @param x The current value to be added to the average Q7.8 format.
* @param weight The EMA weight in UQ0.7 format.
* @return The new mean value in Q7.8 format.
*****************************************************************************/
inline q7_8_t fp_ema8(q7_8_t mean, q7_8_t x, uq0_8_t weight)
{
return (q7_8_t)fp_ema4(mean, x, weight);
}
/*!***************************************************************************
* @brief Exponentially weighted moving average using the Q15.16 format.
*
* @details Evaluates the moving average (exponentially weighted) for data in
* Q15.16 format.
*
* @param mean The previous mean value in Q15.16 format.
* @param x The current value to be added to the average Q15.16 format.
* @param weight The EMA weight in UQ0.7 format.
* @return The new mean value in Q15.16 format.
*****************************************************************************/
inline uint32_t uint_ema32(uint32_t mean, uint32_t x, uq0_8_t weight)
{
if (weight == 0) { return x; }
if (x > mean) {
const uint32_t dx = x - mean;
const uint32_t diff = fp_mulu(weight, dx, 8U);
return mean + diff;
} else {
const uint32_t dx = mean - x;
const uint32_t diff = fp_mulu(weight, dx, 8U);
return mean - diff;
}
}
/*!***************************************************************************
* @brief Exponentially weighted moving average using the Q15.16 format.
*
* @details Evaluates the moving average (exponentially weighted) for data in
* Q15.16 format.
*
* @param mean The previous mean value in Q15.16 format.
* @param x The current value to be added to the average Q15.16 format.
* @param weight The EMA weight in UQ0.7 format.
* @return The new mean value in Q15.16 format.
*****************************************************************************/
inline int32_t int_ema32(int32_t mean, int32_t x, uq0_8_t weight)
{
if (weight == 0) { return x; }
if (x > mean) {
const uint32_t dx = x - mean;
const uint32_t diff = fp_mulu(weight, dx, 8U);
return mean + diff;
} else {
const uint32_t dx = mean - x;
const uint32_t diff = fp_mulu(weight, dx, 8U);
return mean - diff;
}
}
/*!***************************************************************************
* @brief Exponentially weighted moving average using the Q15.16 format.
*
* @details Evaluates the moving average (exponentially weighted) for data in
* Q15.16 format.
*
* @param mean The previous mean value in Q15.16 format.
* @param x The current value to be added to the average Q15.16 format.
* @param weight The EMA weight in UQ0.7 format.
* @return The new mean value in Q15.16 format.
*****************************************************************************/
inline q15_16_t fp_ema16(q15_16_t mean, q15_16_t x, uq0_8_t weight)
{
return (q15_16_t)int_ema32(mean, x, weight);
}
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* FP_EMA_H */
@@ -0,0 +1,69 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details This file provides an exponential function for fixed point type.
*
* @copyright
*
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef FP_EXP_H
#define FP_EXP_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @addtogroup argus_fp
* @{
*****************************************************************************/
#include "fp_def.h"
/*!***************************************************************************
* @brief Calculates the exponential of an fixed point number Q15.16 format.
*
* @details Calculates y = exp(x) in fixed point representation.
*
* Note that the result might not be 100 % accurate and might contain
* a small error!
*
* @see https://www.quinapalus.com/efunc.html
*
* @param x The input parameter in unsigned fixed point format Q15.16.
* @return Result y = exp(x) in the UQ16.16 format.
*****************************************************************************/
uq16_16_t fp_exp16(q15_16_t x);
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* FP_DIV_H */
@@ -0,0 +1,69 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details This file provides an logarithm function for fixed point type.
*
* @copyright
*
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef FP_LOG_H
#define FP_LOG_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @addtogroup argus_fp
* @{
*****************************************************************************/
#include "fp_def.h"
/*!***************************************************************************
* @brief Calculates the natural logarithm (base e) of an fixed point number.
*
* @details Calculates y = ln(x) = log_e(x) in fixed point representation.
*
* Note that the result might not be 100 % accurate and might contain
* a small error!
*
* @see https://www.quinapalus.com/efunc.html
*
* @param x The input parameter in unsigned fixed point format Q15.16.
* @return Result y = ln(x) in the UQ16.16 format.
*****************************************************************************/
q15_16_t fp_log16(uq16_16_t x);
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* FP_DIV_H */
@@ -0,0 +1,235 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Provides definitions and basic macros for fixed point data types.
*
* @copyright
*
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef FP_MUL_H
#define FP_MUL_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @addtogroup argus_fp
* @{
*****************************************************************************/
#include "fp_def.h"
#include "utility/fp_rnd.h"
/*!***************************************************************************
* Set to use hardware division (Cortex-M3/4) over software division (Cortex-M0/1).
*****************************************************************************/
#ifndef USE_64BIT_MUL
#define USE_64BIT_MUL 0
#endif
#if !USE_64BIT_MUL
/*!***************************************************************************
* @brief Long multiplication of two unsigned 32-bit into an 64-bit value on
* 32-bit architecture.
*
* @details w (two words) gets the product of u and v (one word each).
* w[0] is the most significant word of the result, w[1] the least.
* (The words are in big-endian order).
* It is Knuth's Algorithm M from [Knu2] section 4.3.1.
* *
* @see http://www.hackersdelight.org/hdcodetxt/muldwu.c.txt
*
* @param w The result (u * v) value given as two unsigned 32-bit numbers:
* w[0] is the most significant word of the result, w[1] the least.
* (The words are in big-endian order).
* @param u Left hand side of the multiplication.
* @param v Right hand side of the multiplication.
*****************************************************************************/
inline void muldwu(uint32_t w[], uint32_t u, uint32_t v)
{
const uint32_t u0 = u >> 16U;
const uint32_t u1 = u & 0xFFFFU;
const uint32_t v0 = v >> 16U;
const uint32_t v1 = v & 0xFFFFU;
uint32_t t = u1 * v1;
const uint32_t w3 = t & 0xFFFFU;
uint32_t k = t >> 16U;
t = u0 * v1 + k;
const uint32_t w2 = t & 0xFFFFU;
const uint32_t w1 = t >> 16U;
t = u1 * v0 + w2;
k = t >> 16U;
w[0] = u0 * v0 + w1 + k;
w[1] = (t << 16U) + w3;
}
#endif
/*!***************************************************************************
* @brief 64-bit implementation of an unsigned multiplication with fixed point format.
*
* @details Algorithm to evaluate a*b, where a and b are arbitrary fixed point
* number of 32-bit width. The multiplication is done in 64-bit and
* the result is shifted down by the passed shift parameter in order
* to return a 32-bit value.
* The shift is executed with correct rounding.
*
* Note that the result must fit into the 32-bit value. An assertion
* error occurs otherwise (or undefined behavior of no assert available).
*
* @param u The left parameter in UQx1.y1 format
* @param v The right parameter in UQx2.y2 format
* @param shift The final right shift (rounding) value.
* @return Result = (a*b)>>shift in UQx.(y1+y2-shift) format.
*****************************************************************************/
inline uint32_t fp_mulu(uint32_t u, uint32_t v, uint_fast8_t shift)
{
assert(shift <= 32);
#if USE_64BIT_MUL
const uint64_t w = (uint64_t)u * (uint64_t)v;
return (w >> shift) + ((w >> (shift - 1)) & 1U);
#else
uint32_t tmp[2] = { 0 };
muldwu(tmp, u, v);
assert(shift ? tmp[0] <= (UINT32_MAX >> (32 - shift)) : tmp[0] == 0);
if (32 - shift) {
return ((tmp[0] << (32 - shift)) + fp_rndu(tmp[1], shift));
} else {
return tmp[1] > (UINT32_MAX >> 1) ? tmp[0] + 1 : tmp[0];
}
#endif
}
/*!***************************************************************************
* @brief 64-bit implementation of a signed multiplication with fixed point format.
*
* @details Algorithm to evaluate a*b, where a and b are arbitrary fixed point
* number of 32-bit width. The multiplication is done in 64-bit and
* the result is shifted down by the passed shift parameter in order
* to return a 32-bit value.
* The shift is executed with correct rounding.
*
* Note that the result must fit into the 32-bit value. An assertion
* error occurs otherwise (or undefined behavior of no assert available).
*
* @param u The left parameter in Qx1.y1 format
* @param v The right parameter in Qx2.y2 format
* @param shift The final right shift (rounding) value.
* @return Result = (a*b)>>shift in Qx.(y1+y2-shift) format.
*****************************************************************************/
inline int32_t fp_muls(int32_t u, int32_t v, uint_fast8_t shift)
{
int_fast8_t sign = 1;
uint32_t u2, v2;
if (u < 0) { u2 = -u; sign = -sign; } else { u2 = u; }
if (v < 0) { v2 = -v; sign = -sign; } else { v2 = v; }
const uint32_t res = fp_mulu(u2, v2, shift);
assert(sign > 0 ? res <= 0x7FFFFFFFU : res <= 0x80000000U);
return sign > 0 ? res : -res;
}
/*!***************************************************************************
* @brief 48-bit implementation of a unsigned multiplication with fixed point format.
*
* @details Algorithm to evaluate a*b, where a and b are arbitrary fixed point
* numbers with 32-bit unsigned and 16-bit unsigned format respectively.
* The multiplication is done in two 16x16-bit operations and the
* result is shifted down by the passed shift parameter in order to
* return a 32-bit value.
*
* Note that the result must fit into the 32-bit value. An assertion
* error occurs otherwise (or undefined behavior of no assert available).
*
* @param u The left parameter in Qx1.y1 format
* @param v The right parameter in Qx2.y2 format
* @param shift The final right shift (rounding) value.
* @return Result = (a*b)>>shift in Qx.(y1+y2-shift) format.
*****************************************************************************/
inline uint32_t fp_mul_u32_u16(uint32_t u, uint16_t v, uint_fast8_t shift)
{
assert(shift <= 48);
if (shift > 16) {
uint32_t msk = 0xFFFFU;
uint32_t a = (u >> 16U) * v;
uint32_t b = (msk & u) * v;
return fp_rndu(a, shift - 16) + fp_rndu(b, shift);
} else {
uint32_t msk = ~(0xFFFFFFFFU << shift);
uint32_t a = (u >> shift) * v;
uint32_t b = fp_rndu((msk & u) * v, shift);
return a + b;
}
}
/*!***************************************************************************
* @brief 48-bit implementation of an unsigned/signed multiplication with fixed point format.
*
* @details Algorithm to evaluate a*b, where a and b are arbitrary fixed point
* numbers with 32-bit signed and 16-bit unsigned format respectively.
* The multiplication is done in two 16x16-bit operations and the
* result is shifted down by the passed shift parameter in order to
* return a 32-bit value.
* The shift is executed with correct rounding.
*
* Note that the result must fit into the 32-bit value. An assertion
* error occurs otherwise (or undefined behavior of no assert available).
*
* @param u The left parameter in Qx1.y1 format
* @param v The right parameter in Qx2.y2 format
* @param shift The final right shift (rounding) value.
* @return Result = (a*b)>>shift in Qx.(y1+y2-shift) format.
*****************************************************************************/
inline int32_t fp_mul_s32_u16(int32_t u, uint16_t v, uint_fast8_t shift)
{
return u >= 0 ? fp_mul_u32_u16(u, v, shift) : - fp_mul_u32_u16(-u, v, shift);
}
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* FP_MUL_H */
@@ -0,0 +1,118 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Provides definitions and basic macros for fixed point data types.
*
* @copyright
*
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef FP_RND_H
#define FP_RND_H
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @addtogroup argus_fp
* @{
*****************************************************************************/
#include "fp_def.h"
#include <assert.h>
/*!***************************************************************************
* @brief Converting with rounding from UQx.n1 to UQx.n2.
* @details Equivalent to dividing by 2^n with correct rounding to unsigned
* integer values.
* @param Q The number in (U)Qx.n1 fixed point format to be rounded.
* @param n The number of bits to be rounded,
* e.g. UQ8.8 -> UQ12.4 => n = 8 - 4 = 4.
* @return The rounded value in (U)Qx.n2 format.
*****************************************************************************/
inline uint32_t fp_rndu(uint32_t Q, uint_fast8_t n)
{
if (n == 0) { return Q; }
else if (n > 32U) { return 0; }
// Shift by n>=32 yields undefined behavior! Thus, this extra first
// step is essential to prevent issues.
Q >>= n - 1;
return (Q >> 1) + (Q & 1U);
}
/*!***************************************************************************
* @brief Converting with rounding from Qx.n1 to Qx.n2.
* @details Equivalent to dividing by 2^n with correct rounding to integer
* values.
* @param Q The number in (U)Qx.n1 fixed point format to be rounded.
* @param n The number of bits to be rounded,
* e.g. Q7.8 -> Q11.4 => n = 8 - 4 = 4.
* @return The rounded value in (U)Qx.n2 format.
*****************************************************************************/
inline int32_t fp_rnds(int32_t Q, uint_fast8_t n)
{
return (Q < 0) ? -fp_rndu(-Q, n) : fp_rndu(Q, n);
}
/*!***************************************************************************
* @brief Converting with truncation from UQx.n1 to UQx.n2.
* @details Equivalent to dividing by 2^n with truncating (throw away) the
* fractional part, resulting in an unsigned integer/fixed-point value.
* @param Q The number in (U)Qx.n1 fixed point format to be truncated.
* @param n The number of bits to be truncated,
* e.g. UQ8.8 -> UQ12.4 => n = 8 - 4 = 4.
* @return The truncated value in (U)Qx.n2 format.
*****************************************************************************/
inline uint32_t fp_truncu(uint32_t Q, uint_fast8_t n)
{
return (n < 32U) ? (Q >> n) : 0;
}
/*!***************************************************************************
* @brief Converting with truncation from Qx.n1 to Qx.n2.
* @details Equivalent to dividing by 2^n with truncating (throw away) the
* fractional part, resulting in a signed integer/fixed-point value.
* @param Q The number in (U)Qx.n1 fixed point format to be truncated.
* @param n The number of bits to be truncated,
* e.g. Q7.8 -> Q11.4 => n = 8 - 4 = 4.
* @return The truncated value in (U)Qx.n2 format.
*****************************************************************************/
inline int32_t fp_truncs(int32_t Q, uint_fast8_t n)
{
return (Q < 0) ? -fp_truncu(-Q, n) : fp_truncu(Q, n);
}
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* FP_RND_H */
@@ -0,0 +1,281 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details Provides algorithms applied to integer values.
*
* @copyright
*
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef INT_MATH
#define INT_MATH
#ifdef __cplusplus
extern "C" {
#endif
/*!***************************************************************************
* @addtogroup argus_misc
* @{
*****************************************************************************/
#include <stdint.h>
#include <assert.h>
/*! Enables the integer square root function. */
#ifndef INT_SQRT
#define INT_SQRT 0
#endif
/*!***************************************************************************
* @brief Integer Base-2 Logarithm.
*
* @details Calculates the base-2 logarithm for unsigned integer values. The
* result is the integer equivalent of floor(log2(x)).
*
* @param x Input parameter.
* @return The floor of the base-2 logarithm.
*****************************************************************************/
inline uint32_t log2i(uint32_t x)
{
assert(x != 0);
#if 1
return 31 - __builtin_clz(x);
#else
#define S(k) if (x >= (1 << k)) { i += k; x >>= k; }
int i = 0; S(16); S(8); S(4); S(2); S(1); return i;
#undef S
#endif
}
/*!***************************************************************************
* @brief Integer Base-2 Logarithm with rounded result.
*
* @details Calculates the base-2 logarithm for unsigned integer values and
* returns the rounded result. The result is the integer equivalent
* of round(log2(x)).
*
* It is finding the nearest power-of-two value s.t. |x - 2^n| becomes
* minimum for all n.
*
* @param x Input parameter.
* @return The rounded value of the base-2 logarithm.
*****************************************************************************/
inline uint32_t log2_round(uint32_t x)
{
assert(x != 0);
#if 0
const uint32_t y = x;
const uint32_t i = 0;
while (y >>= 1) { i++; }
#else
const uint32_t i = log2i(x);
#endif
return (i + ((x >> (i - 1U)) == 3U));
}
/*!***************************************************************************
* @brief Finding the nearest power-of-two value.
*
* @details Implemented s.t. |x - 2^n| becomes minimum for all n.
* Special case 0: returns 0;
* Maximum input: 3037000499; higher number result in overflow! (returns 0)
*
* @param x Input parameter.
* @return Nearest power-of-two number, i.e. 2^n.
*****************************************************************************/
inline uint32_t binary_round(uint32_t x)
{
assert(x != 0);
const uint32_t shift = log2_round(x);
return (shift > 31U) ? 0 : 1U << shift;
}
/*!***************************************************************************
* @brief Counting bits set in a 32-bit unsigned integer.
*
* @details @see http://graphics.stanford.edu/~seander/bithacks.html
*
* @param x Input parameter.
* @return Number of bits set in input value.
*****************************************************************************/
inline uint32_t popcount(uint32_t x)
{
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
x = x - ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
return (((x + (x >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
}
/*!***************************************************************************
* @brief Determining if an integer is a power of 2
*
* @details @see http://graphics.stanford.edu/~seander/bithacks.html
*
* @param x Input parameter.
* @return True if integer is power of 2.
*****************************************************************************/
inline uint32_t ispowoftwo(uint32_t x)
{
return x && !(x & (x - 1));
}
/*!***************************************************************************
* @brief Calculates the absolute value.
*
* @param x Input parameter.
* @return The absolute value of x.
*****************************************************************************/
inline uint32_t absval(int32_t x)
{
// Note: special case of INT32_MIN must be handled correctly:
return x < 0 ? ((~(uint32_t)(x)) + 1) : (uint32_t)x;
/* alternative with equal performance:*/
// int32_t y = x >> 31;
// return (x ^ y) - y;
/* wrong implementation:
* does not correctly return abs(INT32_MIN) on 32-bit platform */
// return x < 0 ? (uint32_t)(-x) : (uint32_t)x;
}
/*!***************************************************************************
* @brief Calculates the floor division by a factor of 2: floor(x / 2^n).
*
* @param x Input parameter.
* @param n The shift value, maximum is 31.
* @return The floor division by 2^n result.
*****************************************************************************/
inline uint32_t floor2(uint32_t x, uint_fast8_t n)
{
assert(n < 32);
return x >> n;
}
/*!***************************************************************************
* @brief Calculates the ceildiv division by a factor of 2: ceildiv(x / 2^n).
*
* @param x Input parameter.
* @param n The shift value, maximum is 31.
* @return The ceildiv division by 2^n result.
*****************************************************************************/
inline uint32_t ceiling2(uint32_t x, uint_fast8_t n)
{
assert(n < 32);
return x ? (1 + ((x - 1) >> n)) : 0;
}
/*!***************************************************************************
* @brief Calculates the ceildiv division: ceildiv(x / y).
*
* @param x Numerator
* @param y Denominator
* @return The result of the ceildiv division ceildiv(x / y).
*****************************************************************************/
inline uint32_t ceildiv(uint32_t x, uint32_t y)
{
assert(y != 0);
return x ? (1 + ((x - 1) / y)) : 0;
}
/*!***************************************************************************
* @brief Calculates the maximum of two values.
*
* @param a Input parameter.
* @param b Input parameter.
* @return The maximum value of the input parameters.
*****************************************************************************/
#define MAX(a, b) ((a) > (b) ? (a) : (b))
/*!***************************************************************************
* @brief Calculates the minimum of two values.
*
* @param a Input parameter.
* @param b Input parameter.
* @return The minimum value of the input parameters.
*****************************************************************************/
#define MIN(a, b) ((a) < (b) ? (a) : (b))
/*!***************************************************************************
* @brief Clamps a value between a minimum and maximum boundary.
*
* @details Clamps the values such that the condition min <= x <= max is true.
*
* @note The condition \p min <= \p max must hold!!!
*
* @param x The input parameter to be clamped.
* @param min The minimum or lower boundary.
* @param max The maximum or upper boundary.
* @return The clamped value of the input parameter within [min,max].
*****************************************************************************/
#define CLAMP(x, min, max) (MIN(MAX((x), (min)), (max)))
#if INT_SQRT
/*!***************************************************************************
* @brief Calculates the integer square root of x.
*
* @details The integer square root is defined as:
* isqrt(x) = (int)sqrt(x)
*
* @see https://en.wikipedia.org/wiki/Integer_square_root
* @see https://github.com/chmike/fpsqrt/blob/master/fpsqrt.c
*
* @param x Input parameter.
* @return isqrt(x)
*****************************************************************************/
inline uint32_t isqrt(uint32_t v)
{
unsigned t, q, b, r;
r = v; // r = v - x²
b = 0x40000000; // a²
q = 0; // 2ax
while (b > 0) {
t = q + b; // t = 2ax + a²
q >>= 1; // if a' = a/2, then q' = q/2
if (r >= t) { // if (v - x²) >= 2ax + a²
r -= t; // r' = (v - x²) - (2ax + a²)
q += b; // if x' = (x + a) then ax' = ax + a², thus q' = q' + b
}
b >>= 2; // if a' = a/2, then b' = b / 4
}
return q;
}
#endif // INT_SQRT
/*! @} */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* INT_MATH */
@@ -0,0 +1,49 @@
/*************************************************************************//**
* @file
* @brief This file is part of the AFBR-S50 API.
* @details This file contains status codes for all platform specific
* functions.
*
* @copyright
*
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#ifndef STATUS_H
#define STATUS_H
#ifdef __cplusplus
extern "C" {
#endif
#include "api/argus_status.h"
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* STATUS_H */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,10 +1,10 @@
/*************************************************************************//**
* @file argus_hal_test.c
* @brief Tests for the AFBR-S50 API hardware abstraction layer.
* @file
* @brief Tests for the AFBR-S50 API hardware abstraction layer.
*
* @copyright
*
* Copyright (c) 2021, Broadcom, Inc.
* Copyright (c) 2023, Broadcom Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,147 +41,192 @@
extern "C" {
#endif
/*!***************************************************************************
* @defgroup argustest HAL Self Test
* @defgroup argus_test HAL Self Test
* @ingroup argus
*
* @brief A test module to verify implementation of the HAL.
* @brief A test module to verify implementation of the HAL.
*
* @details A series of automated tests that can be executed on the target
* platform in order to verify the implementation of the HAL that
* are required by the API.
* @details A series of automated tests that can be executed on the target
* platform in order to verify the implementation of the HAL that
* are required by the API.
*
* @addtogroup argustest
* See #Argus_VerifyHALImplementation for a detailed documentation.
*
* @addtogroup argus_test
* @{
*****************************************************************************/
#include "argus.h"
/*!***************************************************************************
* @brief Version number of the HAL Self Test.
* @brief Version number of the HAL Self Test.
*
* @details Changes:
* * v1.0:
* - Initial release.
* * v1.1:
* - Added additional print output.
* - Increased tolerance for timer test to 3%.
* - Fixed callback issue by disabling it after IRQ test.
* * v1.1:
* - Added PIT test cases.
* * v1.0:
* - Initial release.
* * v1.1:
* - Added additional print output.
* - Increased tolerance for timer test to 3%.
* - Fixed callback issue by disabling it after IRQ test.
* * v1.2:
* - Added PIT test cases.
* * v1.3:
* - Added test case for SPI maximum data transfer size.
* - Added tests for SPI transfers invoked from all IRQ callbacks.
* - Added verification of first PIT event occurrence.
* - Relaxed PIT pass conditions (0.1% -> 0.5%)
* * v1.4:
* - Adopted to new multi-device HAL interface of API v1.4.4 release.
* - Added verification of SPI callback invocation.
* - Updated GPIO interrupt test to verify if delayed interrupt
* pending states can be detected via #S2PI_ReadIrqPin.
*
*****************************************************************************/
#define HAL_TEST_VERSION "v1.2"
#define HAL_TEST_VERSION "v1.4"
/*!***************************************************************************
* @brief Executes a series of tests in order to verify the HAL implementation.
* @brief Executes a series of tests in order to verify the HAL implementation.
*
* @details A series of automated tests are executed on the target platform in
* order to verify the implementation of the HAL that are required by
* the API.
* order to verify the implementation of the HAL that are required by
* the API.
*
* Each test will write an error description via the print (i.e. UART)
* function that shows what went wrong. Also an corresponding status is
* returned in case no print functionality is available.
* Each test will write an error description via the print (i.e. UART)
* function that shows what went wrong. Also an corresponding status is
* returned in case no print functionality is available.
*
* The following tests are executed:
* The following tests are executed:
*
* **1) Timer Plausibility Test:**
* **1) Timer Plausibility Test:**
*
* Rudimentary tests of the lifetime counter (LTC) implementation.
* This verifies that the LTC is running by checking if the returned
* values of two consecutive calls to the #Timer_GetCounterValue
* function are ascending. An artificial delay using the NOP operation
* is induced such that the timer is not read to fast.
* Rudimentary tests of the lifetime counter (LTC) implementation.
* This verifies that the LTC is running by checking if the returned
* values of two consecutive calls to the #Timer_GetCounterValue
* function are ascending. An artificial delay using the NOP operation
* is induced such that the timer is not read to fast.
*
* **2) Timer Wraparound Test:**
* **2) Timer Wraparound Test:**
*
* The LTC values must wrap from 999999 µs to 0 µs and increase the
* seconds counter accordingly. This test verifies the correct wrapping
* by consecutively calling the #Timer_GetCounterValue function until
* at least 2 wraparound events have been occurred.
* The LTC values must wrap from 999999 µs to 0 µs and increase the
* seconds counter accordingly. This test verifies the correct wrapping
* by consecutively calling the #Timer_GetCounterValue function until
* at least 2 wraparound events have been occurred.
*
* **3) SPI Connection Test:**
* **3) SPI Connection Test:**
*
* This test verifies the basic functionality of the SPI interface.
* The test utilizes the devices laser pattern register, which can
* be freely programmed by any 128-bit pattern. Thus, it writes a byte
* sequence and reads back the written values on the consecutive SPI
* access.
* This test verifies the basic functionality of the SPI interface.
* The test utilizes the devices laser pattern register, which can
* be freely programmed by any 128-bit pattern. Thus, it writes a byte
* sequence and reads back the written values on the consecutive SPI
* access.
*
* **4) SPI Interrupt Test:**
* **4) SPI Maximum Data Length Test**:
*
* This test verifies the correct implementation of the device
* integration finished interrupt callback. Therefore it configures
* the device with a minimal setup to run a pseudo measurement that
* does not emit any laser light.
* This test verifies the maximum data transfer length of the SPI
* interface. The test sends and receives up to 396 data bytes plus
* a single address byte over the SPI interface and verifies that no
* data get lost.
*
* Note that this test does verify the GPIO interrupt that occurs
* whenever the device has finished the integration/measurement and
* new data is waiting to be read from the device. This does not test
* the interrupt that is triggered when the SPI transfer has finished.
* **5) SPI Interrupt Test:**
*
* The data ready interrupt implies two S2PI layer functions that
* are tested in this test: The #S2PI_SetIrqCallback function installs
* a callback function that is invoked whenever the IRQ occurs.
* The IRQ can be delayed due to higher priority task, e.g. from the
* user code. It is essential for the laser safety timeout algorithm
* to determine the device ready signal as fast as possible, another
* method is implemented to read if the IRQ is pending but the
* callback has not been reset yet. This is what the #S2PI_ReadIrqPin
* function is for.
* This test verifies the correct implementation of the device
* integration finished interrupt callback. Therefore it configures
* the device with a minimal setup to run a pseudo measurement that
* does not emit any laser light.
*
* **5) GPIO Mode Test:**
* Note that this test does verify the GPIO interrupt that occurs
* whenever the device has finished the integration/measurement and
* new data is waiting to be read from the device. This does not test
* the interrupt that is triggered when the SPI transfer has finished.
*
* This test verifies the GPIO mode of the S2PI HAL module. This is
* done by leveraging the EEPROM readout sequence that accesses the
* devices EEPROM via a software protocol that depends on the GPIO
* mode.
* The data ready interrupt implies two S2PI layer functions that
* are tested in this test: The #S2PI_SetIrqCallback function installs
* a callback function that is invoked whenever the IRQ occurs.
* The IRQ can be delayed due to higher priority task, e.g. from the
* user code. It is essential for the laser safety timeout algorithm
* to determine the device ready signal as fast as possible, another
* method is implemented to read if the IRQ is pending but the
* callback has not been reset yet. This is what the #S2PI_ReadIrqPin
* function is for.
*
* This the requires several steps, most of them are already verified
* in previous tests:
* **6) GPIO Mode Test:**
*
* - Basic device configuration and enable EEPROM.
* - Read EERPOM via GPIO mode and apply Hamming weight.
* - Repeat several times (to eliminate random readout issues).
* - Decode the EEPROM (using EEPROM_Decode in argus_cal_eeprom.c).
* - Check if Module Number and Chip ID is not 0.
* This test verifies the GPIO mode of the S2PI HAL module. This is
* done by leveraging the EEPROM readout sequence that accesses the
* devices EEPROM via a software protocol that depends on the GPIO
* mode.
*
* **6) Timer Test for Lifetime Counter:**
* This the requires several steps, most of them are already verified
* in previous tests:
*
* The test verifies the lifetime counter timer HAL implementation by
* comparing the timings to the AFBR-S50 device as a reference.
* Therefore several measurement are executed on the device, each with
* a different averaging sample count. The elapsed time increases
* linearly with the number of averaging samples. In order to remove
* the time for software/setup, a linear regression fit is applied to
* the measurement results and only the slope is considered for the
* result. A delta of 102.4 microseconds per sample is expected.
* If the measured delta per sample is within an specified error range,
* the timer implementation is considered correct.
* - Basic device configuration and enable EEPROM.
* - Read EERPOM via GPIO mode and apply Hamming weight.
* - Repeat several times (to eliminate random readout issues).
* - Decode the EEPROM (using EEPROM_Decode in argus_cal_eeprom.c).
* - Check if Module Number and Chip ID is not 0.
*
* **7) Timer Test for Periodic Interrupt Timer:**
* **7) Timer Test for Lifetime Counter:**
*
* The test verifies the correct implementation of the periodic
* interrupt timer (PIT). It sets different intervals and waits for
* a certain number of interrupts to happen. Each interrupt event
* is counted and the time between the first and the last interrupt
* is measured. Finally, the measured interval is compared to the
* expectations.
* The test verifies the lifetime counter timer HAL implementation by
* comparing the timings to the AFBR-S50 device as a reference.
* Therefore several measurement are executed on the device, each with
* a different averaging sample count. The elapsed time increases
* linearly with the number of averaging samples. In order to remove
* the time for software/setup, a linear regression fit is applied to
* the measurement results and only the slope is considered for the
* result. A delta of 102.4 microseconds per sample is expected.
* If the measured delta per sample is within an specified error range,
* the timer implementation is considered correct.
*
* **8) Timer Test for Periodic Interrupt Timer (optional):**
*
* @param spi_slave The SPI hardware slave, i.e. the specified CS and IRQ
* lines. This is actually just a number that is passed
* to the SPI interface to distinct for multiple SPI slave
* devices. Note that the slave must be not equal to 0,
* since is reserved for error handling.
* The test verifies the correct implementation of the periodic
* interrupt timer (PIT). It sets different intervals and waits for
* a certain number of interrupts to happen. Each interrupt event
* is counted and the time between the first and the last interrupt
* is measured. Finally, the measured interval is compared to the
* expectations.
*
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
* Note that this test is only executed if the PIT is actually
* implemented. Otherwise, the test is skipped.
*
* **9) SPI Transfer from Interrupt Callback Test:**
*
* The test verifies that the #S2PI_TransferFrame method of the
* S2PI layer can be invoked from a interrupt callback function too.
* Thus, it repeats the S2PI Connection Test but this time from
* different interrupt callback functions:
*
* - SPI Callback: The first transfer is invoked from thread level,
* the second transfer is invoke from the SPI interrupt callback
* function.
*
* - GPIO Callback: The device is setup to trigger an GPIO interrupt
* (see also the SPI Interrupt Test). The corresponding GPIO
* interrupt callback function will trigger the first transfer while
* the second one is triggered from the SPI callback function.
*
* - PIT Callback (optional): This test is only executed optional if
* the PIT interface is implemented. The test sequence is the same
* as for the GPIO callback, but the first transfer is triggered
* from the PIT callback function.
*
* @note See #HAL_TEST_VERSION for a version history and change log of
* the HAL self tests.
*
* @param spi_slave The SPI hardware slave, i.e. the specified CS and IRQ
* lines. This is actually just a number that is passed
* to the SPI interface to distinct for multiple SPI slave
* devices. Note that the slave must be not equal to 0,
* since is reserved for error handling.
*
* @return Returns the \link #status_t status\endlink (#STATUS_OK on success).
*****************************************************************************/
status_t Argus_VerifyHALImplementation(s2pi_slave_t spi_slave);
#ifdef __cplusplus
}
#endif
/*! @} */
#endif /* ARGUS_CAL_API_H */
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* ARGUS_HAL_TEST_H */
@@ -0,0 +1,102 @@
/****************************************************************************
*
* Copyright (c) 2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* AFBR Rangefinder Mode
*
* This parameter defines the mode of the AFBR Rangefinder.
*
* @reboot_required true
* @min 0
* @max 3
* @group Sensors
*
* @value 0 Short Range Mode
* @value 1 Long Range Mode
* @value 2 High Speed Short Range Mode
* @value 3 High Speed Long Range Mode
*/
PARAM_DEFINE_INT32(SENS_AFBR_MODE, 1);
/**
* AFBR Rangefinder Short Range Rate
*
* This parameter defines measurement rate of the AFBR Rangefinder in short range mode.
*
* @min 1
* @max 100
* @group Sensors
*
*/
PARAM_DEFINE_INT32(SENS_AFBR_S_RATE, 50);
/**
* AFBR Rangefinder Long Range Rate
*
* This parameter defines measurement rate of the AFBR Rangefinder in long range mode.
*
* @min 1
* @max 100
* @group Sensors
*
*/
PARAM_DEFINE_INT32(SENS_AFBR_L_RATE, 25);
/**
* AFBR Rangefinder Short/Long Range Threshold
*
* This parameter defines the threshold for switching between short and long range mode.
* The mode will switch from short to long range when the distance is greater than the threshold plus the hysteresis.
* The mode will switch from long to short range when the distance is less than the threshold minus the hysteresis.
*
* @unit m
* @min 1
* @max 50
* @group Sensors
*
*/
PARAM_DEFINE_INT32(SENS_AFBR_THRESH, 5);
/**
* AFBR Rangefinder Short/Long Range Threshold Hysteresis
*
* This parameter defines the hysteresis for switching between short and long range mode.
*
* @unit m
* @min 1
* @max 10
* @group Sensors
*
*/
PARAM_DEFINE_INT32(SENS_AFBR_HYSTER, 1);
+7 -8
View File
@@ -108,14 +108,13 @@ void UavcanRangefinderBridge::range_sub_cb(const
_inited = true;
}
/*
* FIXME HACK
* This code used to rely on msg.getMonotonicTimestamp().toUSec() instead of HRT.
* It stopped working when the time sync feature has been introduced, because it caused libuavcan
* to use an independent time source (based on hardware TIM5) instead of HRT.
* The proper solution is to be developed.
*/
rangefinder->update(hrt_absolute_time(), msg.range);
int8_t quality = -1;
if (msg.reading_type == uavcan::equipment::range_sensor::Measurement::READING_TYPE_VALID_RANGE) {
quality = 100;
}
rangefinder->update(hrt_absolute_time(), msg.range, quality);
}
int UavcanRangefinderBridge::init_driver(uavcan_bridge::Channel *channel)