Go to the documentation of this file.
26 #define SENSOR_ID (1U)
29 #define SENSOR_TIMEOUT_MS (1000U)
103 #define DEFAULT_PRESET ACC_TOUCHLESS_BUTTON_PRESET_CLOSE
185 static bool check_count(uint16_t *count, uint16_t check_offset, uint16_t check_length);
189 static bool get_detection(
bool current_detection, uint16_t sig_count, uint16_t non_sig_count, uint16_t patience);
206 handle.double_buffer_filter_buffer = NULL;
207 handle.frame_variance = NULL;
213 handle.dynamic_background = NULL;
214 handle.dynamic_background_guard = NULL;
215 handle.threshold_check_count = NULL;
227 if (
handle.config.sensor_config == NULL)
229 printf(
"acc_config_create() failed\n");
246 printf(
"Failed to init handle\n");
253 printf(
"Failed to init sensor\n");
262 printf(
"Failed to measure\n");
267 if (
handle.proc_result.data_saturated)
269 printf(
"Data saturated. The detector result is not reliable.\n");
272 if (
handle.proc_result.frame_delayed)
274 printf(
"Frame delayed. Could not read data fast enough.\n");
275 printf(
"Try lowering the frame rate or call 'acc_sensor_read' more frequently.\n");
278 if (
handle.proc_result.calibration_needed)
280 printf(
"The current calibration is not valid for the current temperature.\n");
281 printf(
"The sensor needs to be re-calibrated.\n");
285 printf(
"do_sensor_calibration_and_prepare() failed\n");
293 printf(
"The sensor was successfully re-calibrated.\n");
301 printf(
"Failed to process sensor result\n");
312 printf(
"Application finished OK\n");
322 if (
handle->config.sensor_config != NULL)
327 if (
handle->sensor != NULL)
332 if (
handle->processing != NULL)
337 if (
handle->buffer != NULL)
342 if (
handle->double_buffer_filter_buffer != NULL)
347 if (
handle->frame_variance != NULL)
352 if (
handle->arg_norm != NULL)
357 if (
handle->ampl_mean != NULL)
362 if (
handle->ampl_std != NULL)
367 if (
handle->phase_mean != NULL)
372 if (
handle->phase_std != NULL)
377 if (
handle->dynamic_background != NULL)
382 if (
handle->dynamic_background_guard != NULL)
387 if (
handle->threshold_check_count != NULL)
413 config->sensitivity_close = 1.9f;
414 config->patience_close = 2U;
415 config->calibration_duration_s = 0.6f;
416 config->calibration_interval_s = 20.0f;
433 config->sensitivity_far = 2.0f;
434 config->patience_far = 2U;
435 config->calibration_duration_s = 0.6f;
436 config->calibration_interval_s = 20.0f;
462 config->sensitivity_close = 1.9f;
463 config->patience_close = 2U;
464 config->sensitivity_far = 2.0f;
465 config->patience_far = 2U;
466 config->calibration_duration_s = 0.6f;
467 config->calibration_interval_s = 20.0f;
479 printf(
"Number of subsweeps must be 2 for 'close and far'\n");
486 printf(
"Number of subsweeps must be 1 for 'close' and 'far'\n");
493 if (sweep_rate == 0.0f)
495 printf(
"Sweep rate must be set\n");
500 if (spf > (
config->calibration_duration_s * sweep_rate))
502 float calibration_limit = (float)spf / sweep_rate;
514 float sensitivity_close =
config->sensitivity_close;
515 uint16_t patience_close =
config->patience_close;
516 float sensitivity_far =
config->sensitivity_far;
517 uint16_t patience_far =
config->patience_far;
518 float calibration_duration_s =
config->calibration_duration_s;
519 float calibration_interval_s =
config->calibration_interval_s;
522 printf(
"Reference application Touchless Button config\n");
527 printf(
"patience close: %" PRIu16
"\n", patience_close);
533 printf(
"patience far: %" PRIu16
"\n", patience_far);
539 char *measurement_type_str =
"";
541 switch (measurement_type)
544 measurement_type_str =
"close";
547 measurement_type_str =
"far";
550 measurement_type_str =
"close and far";
554 printf(
"measurement type: %s\n", measurement_type_str);
556 printf(
"Sensor config\n");
566 printf(
"acc_rss_get_buffer_size() failed\n");
577 float frame_rate = sweep_rate / (float)spf;
579 handle->cal_interval_frames = (uint16_t)((frame_rate *
handle->config.calibration_interval_s) + 0.5f);
580 handle->cal_sweeps = (uint16_t)((sweep_rate *
handle->config.calibration_duration_s) + 0.5f);
581 uint16_t num_points =
handle->proc_metadata.sweep_data_length;
591 handle->dynamic_background_guard =
595 status = (
handle->processing != NULL &&
handle->buffer != NULL &&
handle->double_buffer_filter_buffer != NULL &&
596 handle->frame_variance != NULL &&
handle->arg_norm != NULL &&
handle->ampl_mean != NULL &&
handle->ampl_std != NULL &&
597 handle->phase_mean != NULL &&
handle->phase_std != NULL &&
handle->dynamic_background != NULL &&
598 handle->dynamic_background_guard != NULL &&
handle->threshold_check_count != NULL);
617 handle->close_signal = 0U;
619 handle->close_non_signal =
handle->config.patience_close + 1U;
620 handle->far_non_signal =
handle->config.patience_far + 1U;
621 handle->close_detection =
false;
622 handle->far_detection =
false;
630 return (1.0f / sensitivity) * 10.0f;
635 handle->frames_since_last_cal = 0U;
638 uint16_t num_points =
handle->proc_metadata.sweep_data_length;
640 memset(
handle->dynamic_background, 0,
handle->cal_sweeps * num_points *
sizeof(*
handle->dynamic_background));
641 handle->rows_in_dynamic_background = 0U;
642 memset(
handle->dynamic_background_guard, 0, spf * num_points *
sizeof(*
handle->dynamic_background_guard));
643 handle->update_background =
false;
653 if (
handle->sensor == NULL)
669 bool cal_complete =
false;
671 const uint16_t calibration_retries = 1U;
674 for (uint16_t i = 0; !status && (i <= calibration_retries); i++)
684 if (status && !cal_complete)
688 }
while (status && !cal_complete);
707 printf(
"acc_sensor_measure failed\n");
714 printf(
"Sensor interrupt timeout\n");
721 printf(
"acc_sensor_read failed\n");
733 uint16_t sweep_data_length =
handle->proc_metadata.sweep_data_length;
741 for (uint16_t c = 0U; c < sweep_data_length; c++)
743 float abs_mean = 0.0f;
744 float abs_sq_term = 0.0f;
745 float phase_mean = 0.0f;
746 float phase_sq_term = 0.0f;
747 for (uint16_t r = 0U; r <
handle->cal_sweeps; r++)
749 float ac =
handle->dynamic_background[r * sweep_data_length + c].real * crealf(
handle->arg_norm[c]);
750 float bd =
handle->dynamic_background[r * sweep_data_length + c].imag * cimagf(
handle->arg_norm[c]);
751 float ad =
handle->dynamic_background[r * sweep_data_length + c].real * cimagf(
handle->arg_norm[c]);
752 float bc =
handle->dynamic_background[r * sweep_data_length + c].imag * crealf(
handle->arg_norm[c]);
753 float complex element = (ac - bd) + I * (ad + bc);
755 float delta = cabsf(element) - abs_mean;
756 uint16_t div = (r == 0U) ? 1U : r;
757 abs_mean += (delta / (float)div);
758 abs_sq_term += delta * (cabsf(element) - abs_mean);
760 delta = cargf(element) - phase_mean;
761 phase_mean += (delta / (float)div);
762 phase_sq_term += delta * (cargf(element) - phase_mean);
765 handle->ampl_mean[c] = abs_mean;
766 handle->ampl_std[c] = sqrtf(abs_sq_term /
handle->cal_sweeps);
767 handle->phase_mean[c] = phase_mean;
768 handle->phase_std[c] = sqrtf(phase_sq_term /
handle->cal_sweeps);
773 for (uint16_t r = 0U; r < spf; r++)
775 for (uint16_t c = 0U; c < sweep_data_length; c++)
777 float ac =
handle->proc_result.frame[r * sweep_data_length + c].real * crealf(
handle->arg_norm[c]);
778 float bd =
handle->proc_result.frame[r * sweep_data_length + c].imag * cimagf(
handle->arg_norm[c]);
779 float ad =
handle->proc_result.frame[r * sweep_data_length + c].real * cimagf(
handle->arg_norm[c]);
780 float bc =
handle->proc_result.frame[r * sweep_data_length + c].imag * crealf(
handle->arg_norm[c]);
781 float complex element = (ac - bd) + I * (ad + bc);
782 float a = (cabsf(element) -
handle->ampl_mean[c]) /
handle->ampl_std[c];
783 float b = (cargf(element) -
handle->phase_mean[c]) /
handle->phase_std[c];
785 handle->frame_variance[r * sweep_data_length + c] = sqrtf(powf(a, 2.0f) + powf(b, 2.0f));
790 static bool check_count(uint16_t *count, uint16_t check_offset, uint16_t check_length)
792 bool success =
false;
794 for (uint16_t i = 0U; i < check_length; i++)
796 if (count[check_offset + i] > 1U)
811 handle->proc_metadata.sweep_data_length,
812 handle->dynamic_background_guard,
816 handle->rows_in_dynamic_background += spf;
817 handle->rows_in_dynamic_background =
819 handle->frames_since_last_cal = 0U;
822 static bool get_detection(
bool current_detection, uint16_t sig_count, uint16_t non_sig_count, uint16_t patience)
824 bool new_detection = !current_detection && sig_count >= patience;
825 bool keep_detection = current_detection && non_sig_count <= patience;
827 return new_detection || keep_detection;
837 handle->double_buffer_filter_buffer);
840 memset(
handle->frame_variance, 0,
handle->proc_metadata.frame_data_length *
sizeof(*
handle->frame_variance));
842 if (
handle->frames_since_last_cal >
handle->cal_interval_frames)
846 else if (
handle->rows_in_dynamic_background ==
handle->cal_sweeps)
851 uint16_t threshold_check_offset = 0U;
857 handle->proc_metadata.sweep_data_length,
859 handle->threshold_check_count,
860 threshold_check_offset,
864 threshold_check_offset =
handle->close_num_points;
871 handle->proc_metadata.sweep_data_length,
873 handle->threshold_check_count,
874 threshold_check_offset,
881 uint16_t close_offset = 0U;
882 uint16_t far_offset =
handle->close_num_points;
889 handle->close_non_signal = 0U;
893 handle->close_signal = 0U;
894 handle->close_non_signal++;
903 handle->far_non_signal = 0U;
912 handle->update_background =
false;
913 memset(
handle->dynamic_background_guard, 0,
handle->proc_metadata.frame_data_length *
sizeof(*
handle->dynamic_background_guard));
914 handle->frames_since_last_cal++;
918 handle->close_signal = 0U;
920 handle->close_non_signal++;
923 if (
handle->update_background)
928 memcpy(
handle->dynamic_background_guard,
929 handle->proc_result.frame,
930 handle->proc_metadata.frame_data_length *
sizeof(*
handle->dynamic_background_guard));
931 handle->update_background =
true;
void acc_config_start_point_set(acc_config_t *config, int32_t start_point)
Set the starting point of the sweep.
void acc_config_inter_frame_idle_state_set(acc_config_t *config, acc_config_idle_state_t idle_state)
Set inter frame idle state.
void acc_hal_integration_sensor_supply_off(acc_sensor_id_t sensor_id)
Power off sensor supply.
void acc_processing_destroy(acc_processing_t *handle)
Destroy a processing instance identified with the provided processing handle.
uint16_t acc_config_subsweep_num_points_get(const acc_config_t *config, uint8_t index)
Get the number of data points to measure.
void acc_hal_integration_sensor_supply_on(acc_sensor_id_t sensor_id)
Power on sensor supply.
Result provided by the processing module.
bool acc_sensor_read(const acc_sensor_t *sensor, void *buffer, uint32_t buffer_size)
Read out radar data.
uint8_t acc_config_num_subsweeps_get(const acc_config_t *config)
Get the number of subsweeps to use.
void acc_algorithm_normalize_f32_complex(float complex *data, uint16_t data_length)
Normalize all elements in an array individually.
void acc_config_profile_set(acc_config_t *config, acc_config_profile_t profile)
Set a profile.
Data type for interger-based representation of complex numbers.
void acc_algorithm_double_buffering_frame_filter(acc_int16_complex_t *frame, const uint16_t sweeps_per_frame, const uint16_t num_points, int32_t *work_buffer)
Double buffering frame filter.
void acc_config_sweeps_per_frame_set(acc_config_t *config, uint16_t sweeps)
Set sweeps per frame.
void acc_config_destroy(acc_config_t *config)
Destroy a configuration freeing any resources allocated.
The result from a completed calibration.
void acc_processing_execute(acc_processing_t *handle, void *buffer, acc_processing_result_t *result)
Process the data according to the configuration used in create.
void acc_config_inter_sweep_idle_state_set(acc_config_t *config, acc_config_idle_state_t idle_state)
Set inter sweep idle state.
acc_config_t * acc_config_create(void)
Create a configuration.
const acc_hal_a121_t * acc_hal_rss_integration_get_implementation(void)
Get hal implementation reference.
void * acc_integration_mem_alloc(size_t size)
Allocate dynamic memory.
void acc_config_double_buffering_set(acc_config_t *config, bool enable)
Enable or disable double buffering.
void acc_algorithm_mean_matrix_i16_complex(const acc_int16_complex_t *matrix, uint16_t rows, uint16_t cols, float complex *out, uint16_t axis)
Calculate mean array of a matrix.
void acc_config_hwaas_set(acc_config_t *config, uint16_t hwaas)
Set the hardware accelerated average samples (HWAAS)
uint16_t acc_config_sweeps_per_frame_get(const acc_config_t *config)
Get the number of sweeps per frame.
bool acc_hal_integration_wait_for_sensor_interrupt(acc_sensor_id_t sensor_id, uint32_t timeout_ms)
Wait for a sensor interrupt.
@ ACC_CONFIG_IDLE_STATE_READY
const char * acc_version_get(void)
Get the version of the Acconeer software.
struct acc_config acc_config_t
void acc_config_num_subsweeps_set(acc_config_t *config, uint8_t num_subsweeps)
Set the number of subsweeps to use.
void acc_hal_integration_sensor_enable(acc_sensor_id_t sensor_id)
Enable sensor.
void acc_config_step_length_set(acc_config_t *config, uint16_t step_length)
Set the step length in a sweep.
void acc_config_num_points_set(acc_config_t *config, uint16_t num_points)
Set the number of data points to measure.
void acc_config_subsweep_start_point_set(acc_config_t *config, int32_t start_point, uint8_t index)
Set the starting point of the sweep.
void acc_config_sweep_rate_set(acc_config_t *config, float sweep_rate)
Set the sweep rate.
void acc_config_subsweep_profile_set(acc_config_t *config, acc_config_profile_t profile, uint8_t index)
Set a profile.
void acc_algorithm_conj_f32(float complex *data, uint16_t data_length)
Inline calculate conjugate of all elements in an array.
void acc_hal_integration_sensor_disable(acc_sensor_id_t sensor_id)
Disable sensor.
struct acc_processing_handle acc_processing_t
#define ACC_LOG_FLOAT_TO_INTEGER(a)
void acc_config_continuous_sweep_mode_set(acc_config_t *config, bool enabled)
Set continuous sweep mode.
void acc_sensor_status(const acc_sensor_t *sensor)
Check the status of the sensor.
void acc_config_subsweep_receiver_gain_set(acc_config_t *config, uint8_t gain, uint8_t index)
Set receiver gain setting.
bool acc_sensor_prepare(acc_sensor_t *sensor, const acc_config_t *config, const acc_cal_result_t *cal_result, void *buffer, uint32_t buffer_size)
Prepare a sensor to do a measurement.
void acc_integration_mem_free(void *ptr)
Free dynamic memory.
bool acc_config_double_buffering_get(const acc_config_t *config)
Get the double buffering configuration.
void acc_config_subsweep_hwaas_set(acc_config_t *config, uint16_t hwaas, uint8_t index)
Set the hardware accelerated average samples (HWAAS)
void acc_config_receiver_gain_set(acc_config_t *config, uint8_t gain)
Set receiver gain setting.
void acc_config_log(const acc_config_t *config)
Print a configuration to the log.
void acc_config_subsweep_step_length_set(acc_config_t *config, uint16_t step_length, uint8_t index)
Set the step length in a sweep.
float acc_config_sweep_rate_get(const acc_config_t *config)
Get the sweep rate.
bool acc_sensor_calibrate(acc_sensor_t *sensor, bool *cal_complete, acc_cal_result_t *cal_result, void *buffer, uint32_t buffer_size)
Calibrate a sensor.
void acc_config_subsweep_num_points_set(acc_config_t *config, uint16_t num_points, uint8_t index)
Set the number of data points to measure.
uint16_t acc_config_num_points_get(const acc_config_t *config)
Get the number of data points to measure.
#define PRIfloat
Specifier for printing float type using integers.
bool acc_sensor_measure(acc_sensor_t *sensor)
Start a radar measurement with previously prepared configuration.
void acc_algorithm_count_points_above_threshold(const float *matrix, uint16_t rows, uint16_t cols, const float threshold, uint16_t *count, uint16_t offset, uint16_t threshold_check_length, uint16_t axis)
Count points in matrix above threshold row-wise or col-wise.
acc_processing_t * acc_processing_create(const acc_config_t *config, acc_processing_metadata_t *processing_metadata)
Create a processing instance with the provided configuration.
void acc_algorithm_roll_and_push_mult_matrix_i16_complex(acc_int16_complex_t *data, uint16_t data_rows, uint16_t cols, const acc_int16_complex_t *matrix, uint16_t matrix_rows, bool pos_shift)
Roll row elements and push multiple columns.
struct acc_sensor acc_sensor_t
void acc_sensor_destroy(acc_sensor_t *sensor)
Destroy a sensor instance freeing any resources allocated.
acc_sensor_t * acc_sensor_create(acc_sensor_id_t sensor_id)
Create a sensor instance.