ref_app_touchless_button.c
Go to the documentation of this file.
1 // Copyright (c) Acconeer AB, 2023-2024
2 // All rights reserved
3 // This file is subject to the terms and conditions defined in the file
4 // 'LICENSES/license_acconeer.txt', (BSD 3-Clause License) which is part
5 // of this source code package.
6
7 #include <complex.h>
8 #include <math.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <string.h>
13
14 #include "acc_algorithm.h"
15 #include "acc_config.h"
16 #include "acc_definitions_common.h"
17 #include "acc_hal_definitions_a121.h"
18 #include "acc_hal_integration_a121.h"
19 #include "acc_integration.h"
20 #include "acc_integration_log.h"
21 #include "acc_processing.h"
22 #include "acc_rss_a121.h"
23 #include "acc_sensor.h"
24 #include "acc_version.h"
25
26 #define SENSOR_ID (1U)
27 // The time to measure for the application presets should be well below 1s.
28 // If timeouts occurs, try increasing the number.
29 #define SENSOR_TIMEOUT_MS (1000U)
30
31 /**
32 * @brief Application measurement type
33 */
34 typedef enum
35 {
36 /**
37 * Corresponds to a range of approximate 0 cm - 5 cm
38 */
39 ACC_TOUCHLESS_BUTTON_CLOSE_RANGE,
40 /**
41 * Corresponds to a range of approximate 0 cm - 24 cm
42 */
43 ACC_TOUCHLESS_BUTTON_FAR_RANGE,
44 /**
45 * Gives two detection outputs, one for each range
46 */
47 ACC_TOUCHLESS_BUTTON_CLOSE_AND_FAR_RANGE,
48 } acc_touchless_button_measurement_type_t;
49
50 /**
51 * @brief Touchless button application config
52 */
53 typedef struct
54 {
55 /**
56 * Sensitivity for close range detection. High sensitivity equals low
57 * detection threshold, low sensitivity equals high detection threshold
58 */
59 float sensitivity_close;
60 /**
61 * Number of frames in a row above threshold to count as a new close range detection,
62 * also number of frames in a row below threshold to count as end of detection
63 */
64 uint16_t patience_close;
65 /**
66 * Sensitivity for far range detection. High sensitivity equals low
67 * detection threshold, low sensitivity equals high detection threshold
68 */
69 float sensitivity_far;
70 /**
71 * Number of frames in a row above threshold to count as a new close range detection,
72 * also number of frames in a row below threshold to count as end of detection
73 */
74 uint16_t patience_far;
75 /**
76 * Calibration duration in seconds
77 */
78 float calibration_duration_s;
79 /**
80 * Interval between calibrations in seconds. When reached a new calibration is made.
81 * Should not be set lower than the longest estimated continuous detection event
82 */
83 float calibration_interval_s;
84 /**
85 * The measurement type
86 * See @ref acc_touchless_button_measurement_type_t for more information
87 */
88 acc_touchless_button_measurement_type_t measurement_type;
89 /**
90 * The sensor configuration
91 */
92 acc_config_t *sensor_config;
93 } acc_touchless_button_config_t;
94
95 typedef enum
96 {
97 ACC_TOUCHLESS_BUTTON_PRESET_NONE,
98 ACC_TOUCHLESS_BUTTON_PRESET_CLOSE,
99 ACC_TOUCHLESS_BUTTON_PRESET_FAR,
100 ACC_TOUCHLESS_BUTTON_PRESET_CLOSE_AND_FAR,
101 } acc_touchless_button_preset_t;
102
103 #define DEFAULT_PRESET ACC_TOUCHLESS_BUTTON_PRESET_CLOSE
104
105 /**
106 * @brief Touchless button application handle
107 */
108 typedef struct
109 {
110 acc_touchless_button_config_t config;
111 acc_sensor_t *sensor;
112 acc_processing_t *processing;
113 acc_processing_metadata_t proc_metadata;
114 acc_processing_result_t proc_result;
115 void *buffer;
116 uint32_t buffer_size;
117 int32_t *double_buffer_filter_buffer;
118 float *frame_variance;
119 float complex *arg_norm;
120 float *ampl_mean;
121 float *ampl_std;
122 float *phase_mean;
123 float *phase_std;
124 uint16_t cal_interval_frames;
125 uint16_t cal_sweeps;
126 acc_int16_complex_t *dynamic_background;
127 uint16_t rows_in_dynamic_background;
128 acc_int16_complex_t *dynamic_background_guard;
129 bool update_background;
130 uint16_t frames_since_last_cal;
131 float close_threshold;
132 float far_threshold;
133 uint16_t *threshold_check_count;
134 bool run_close;
135 bool run_far;
136 uint16_t close_num_points;
137 uint16_t far_num_points;
138 uint16_t close_signal;
139 uint16_t far_signal;
140 uint16_t close_non_signal;
141 uint16_t far_non_signal;
142 bool close_detection;
143 bool far_detection;
144 } acc_touchless_button_handle_t;
145
146 /**
147 * @brief Touchless button range result
148 */
149 typedef enum
150 {
151 ACC_TOUCHLESS_BUTTON_RANGE_NOT_USED,
152 ACC_TOUCHLESS_BUTTON_RANGE_NO_DETECTION,
153 ACC_TOUCHLESS_BUTTON_RANGE_DETECTION,
154 } acc_touchless_button_range_result_t;
155
156 /**
157 * @brief Touchless button application result
158 */
159 typedef struct
160 {
161 acc_touchless_button_range_result_t close_result;
162 acc_touchless_button_range_result_t far_result;
163 } acc_touchless_button_result_t;
164
165 static void cleanup(acc_touchless_button_handle_t *handle);
166
167 static void set_config(acc_touchless_button_config_t *config, acc_touchless_button_preset_t preset);
168
169 static bool validate_config(acc_touchless_button_config_t *config);
170
171 static void config_log(acc_touchless_button_config_t *config);
172
173 static bool init_handle(acc_touchless_button_handle_t *handle);
174
175 static float get_threshold(float sensitivity);
176
177 static void reset_background(acc_touchless_button_handle_t *handle);
178
179 static bool init_sensor(acc_touchless_button_handle_t *handle);
180
181 static bool do_sensor_calibration_and_prepare(acc_touchless_button_handle_t *handle);
182
183 static bool measure(acc_touchless_button_handle_t *handle);
184
185 static bool check_count(uint16_t *count, uint16_t check_offset, uint16_t check_length);
186
187 static void update_background(acc_touchless_button_handle_t *handle);
188
189 static bool get_detection(bool current_detection, uint16_t sig_count, uint16_t non_sig_count, uint16_t patience);
190
191 static bool process(acc_touchless_button_handle_t *handle, acc_touchless_button_result_t *result);
192
193 static void print_result(acc_touchless_button_result_t *result);
194
195 int acconeer_main(int argc, char *argv[]);
196
197 int acconeer_main(int argc, char *argv[])
198 {
199 (void)argc;
200 (void)argv;
201
202 acc_touchless_button_handle_t handle;
203 handle.sensor = NULL;
204 handle.processing = NULL;
205 handle.buffer = NULL;
206 handle.double_buffer_filter_buffer = NULL;
207 handle.frame_variance = NULL;
208 handle.arg_norm = NULL;
209 handle.ampl_mean = NULL;
210 handle.ampl_std = NULL;
211 handle.phase_mean = NULL;
212 handle.phase_std = NULL;
213 handle.dynamic_background = NULL;
214 handle.dynamic_background_guard = NULL;
215 handle.threshold_check_count = NULL;
216
217 printf("Acconeer software version %s\n", acc_version_get());
218
219 const acc_hal_a121_t *hal = acc_hal_rss_integration_get_implementation();
220
221 if (!acc_rss_hal_register(hal))
222 {
223 return EXIT_FAILURE;
224 }
225
226 handle.config.sensor_config = acc_config_create();
227 if (handle.config.sensor_config == NULL)
228 {
229 printf("acc_config_create() failed\n");
230 cleanup(&handle);
231 return EXIT_FAILURE;
232 }
233
234 set_config(&handle.config, DEFAULT_PRESET);
235
236 if (!validate_config(&handle.config))
237 {
238 cleanup(&handle);
239 return EXIT_FAILURE;
240 }
241
242 config_log(&handle.config);
243
244 if (!init_handle(&handle))
245 {
246 printf("Failed to init handle\n");
247 cleanup(&handle);
248 return EXIT_FAILURE;
249 }
250
251 if (!init_sensor(&handle))
252 {
253 printf("Failed to init sensor\n");
254 cleanup(&handle);
255 return EXIT_FAILURE;
256 }
257
258 while (true)
259 {
260 if (!measure(&handle))
261 {
262 printf("Failed to measure\n");
263 cleanup(&handle);
264 return EXIT_FAILURE;
265 }
266
267 if (handle.proc_result.data_saturated)
268 {
269 printf("Data saturated. The detector result is not reliable.\n");
270 }
271
272 if (handle.proc_result.frame_delayed)
273 {
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");
276 }
277
278 if (handle.proc_result.calibration_needed)
279 {
280 printf("The current calibration is not valid for the current temperature.\n");
281 printf("The sensor needs to be re-calibrated.\n");
282
283 if (!do_sensor_calibration_and_prepare(&handle))
284 {
285 printf("do_sensor_calibration_and_prepare() failed\n");
286 acc_sensor_status(handle.sensor);
287 cleanup(&handle);
288 return EXIT_FAILURE;
289 }
290
291 reset_background(&handle);
292
293 printf("The sensor was successfully re-calibrated.\n");
294 }
295 else
296 {
297 acc_touchless_button_result_t result = {0};
298
299 if (!process(&handle, &result))
300 {
301 printf("Failed to process sensor result\n");
302 cleanup(&handle);
303 return EXIT_FAILURE;
304 }
305
306 print_result(&result);
307 }
308 }
309
310 cleanup(&handle);
311
312 printf("Application finished OK\n");
313
314 return EXIT_SUCCESS;
315 }
316
317 static void cleanup(acc_touchless_button_handle_t *handle)
318 {
319 acc_hal_integration_sensor_disable(SENSOR_ID);
320 acc_hal_integration_sensor_supply_off(SENSOR_ID);
321
322 if (handle->config.sensor_config != NULL)
323 {
324 acc_config_destroy(handle->config.sensor_config);
325 }
326
327 if (handle->sensor != NULL)
328 {
329 acc_sensor_destroy(handle->sensor);
330 }
331
332 if (handle->processing != NULL)
333 {
334 acc_processing_destroy(handle->processing);
335 }
336
337 if (handle->buffer != NULL)
338 {
339 acc_integration_mem_free(handle->buffer);
340 }
341
342 if (handle->double_buffer_filter_buffer != NULL)
343 {
344 acc_integration_mem_free(handle->double_buffer_filter_buffer);
345 }
346
347 if (handle->frame_variance != NULL)
348 {
349 acc_integration_mem_free(handle->frame_variance);
350 }
351
352 if (handle->arg_norm != NULL)
353 {
354 acc_integration_mem_free(handle->arg_norm);
355 }
356
357 if (handle->ampl_mean != NULL)
358 {
359 acc_integration_mem_free(handle->ampl_mean);
360 }
361
362 if (handle->ampl_std != NULL)
363 {
364 acc_integration_mem_free(handle->ampl_std);
365 }
366
367 if (handle->phase_mean != NULL)
368 {
369 acc_integration_mem_free(handle->phase_mean);
370 }
371
372 if (handle->phase_std != NULL)
373 {
374 acc_integration_mem_free(handle->phase_std);
375 }
376
377 if (handle->dynamic_background != NULL)
378 {
379 acc_integration_mem_free(handle->dynamic_background);
380 }
381
382 if (handle->dynamic_background_guard != NULL)
383 {
384 acc_integration_mem_free(handle->dynamic_background_guard);
385 }
386
387 if (handle->threshold_check_count != NULL)
388 {
389 acc_integration_mem_free(handle->threshold_check_count);
390 }
391 }
392
393 static void set_config(acc_touchless_button_config_t *config, acc_touchless_button_preset_t preset)
394 {
395 switch (preset)
396 {
397 case ACC_TOUCHLESS_BUTTON_PRESET_NONE:
398 break;
399 case ACC_TOUCHLESS_BUTTON_PRESET_CLOSE:
400 acc_config_sweeps_per_frame_set(config->sensor_config, 16U);
401 acc_config_sweep_rate_set(config->sensor_config, 320U);
402 acc_config_continuous_sweep_mode_set(config->sensor_config, true);
403 acc_config_double_buffering_set(config->sensor_config, true);
404 acc_config_inter_sweep_idle_state_set(config->sensor_config, ACC_CONFIG_IDLE_STATE_READY);
405 acc_config_inter_frame_idle_state_set(config->sensor_config, ACC_CONFIG_IDLE_STATE_READY);
406 acc_config_num_points_set(config->sensor_config, 3U);
407 acc_config_profile_set(config->sensor_config, ACC_CONFIG_PROFILE_1);
408 acc_config_receiver_gain_set(config->sensor_config, 0U);
409 acc_config_hwaas_set(config->sensor_config, 40U);
410 acc_config_start_point_set(config->sensor_config, 0U);
411 acc_config_step_length_set(config->sensor_config, 6U);
412
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;
417 config->measurement_type = ACC_TOUCHLESS_BUTTON_CLOSE_RANGE;
418 break;
419 case ACC_TOUCHLESS_BUTTON_PRESET_FAR:
420 acc_config_sweeps_per_frame_set(config->sensor_config, 16U);
421 acc_config_sweep_rate_set(config->sensor_config, 320U);
422 acc_config_continuous_sweep_mode_set(config->sensor_config, true);
423 acc_config_double_buffering_set(config->sensor_config, true);
424 acc_config_inter_sweep_idle_state_set(config->sensor_config, ACC_CONFIG_IDLE_STATE_READY);
425 acc_config_inter_frame_idle_state_set(config->sensor_config, ACC_CONFIG_IDLE_STATE_READY);
426 acc_config_num_points_set(config->sensor_config, 3U);
427 acc_config_profile_set(config->sensor_config, ACC_CONFIG_PROFILE_3);
428 acc_config_receiver_gain_set(config->sensor_config, 5U);
429 acc_config_hwaas_set(config->sensor_config, 60U);
430 acc_config_start_point_set(config->sensor_config, 0U);
431 acc_config_step_length_set(config->sensor_config, 24U);
432
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;
437 config->measurement_type = ACC_TOUCHLESS_BUTTON_FAR_RANGE;
438 break;
439 case ACC_TOUCHLESS_BUTTON_PRESET_CLOSE_AND_FAR:
440 acc_config_num_subsweeps_set(config->sensor_config, 2U);
441 acc_config_sweeps_per_frame_set(config->sensor_config, 16U);
442 acc_config_sweep_rate_set(config->sensor_config, 320U);
443 acc_config_continuous_sweep_mode_set(config->sensor_config, true);
444 acc_config_double_buffering_set(config->sensor_config, true);
445 acc_config_inter_sweep_idle_state_set(config->sensor_config, ACC_CONFIG_IDLE_STATE_READY);
446 acc_config_inter_frame_idle_state_set(config->sensor_config, ACC_CONFIG_IDLE_STATE_READY);
447
448 acc_config_subsweep_num_points_set(config->sensor_config, 3U, 0U);
449 acc_config_subsweep_profile_set(config->sensor_config, ACC_CONFIG_PROFILE_1, 0U);
450 acc_config_subsweep_receiver_gain_set(config->sensor_config, 0U, 0U);
451 acc_config_subsweep_hwaas_set(config->sensor_config, 40U, 0U);
452 acc_config_subsweep_start_point_set(config->sensor_config, 0U, 0U);
453 acc_config_subsweep_step_length_set(config->sensor_config, 6U, 0U);
454
455 acc_config_subsweep_num_points_set(config->sensor_config, 3U, 1U);
456 acc_config_subsweep_profile_set(config->sensor_config, ACC_CONFIG_PROFILE_3, 1U);
457 acc_config_subsweep_receiver_gain_set(config->sensor_config, 5U, 1U);
458 acc_config_subsweep_hwaas_set(config->sensor_config, 60U, 1U);
459 acc_config_subsweep_start_point_set(config->sensor_config, 0U, 1U);
460 acc_config_subsweep_step_length_set(config->sensor_config, 24U, 1U);
461
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;
468 config->measurement_type = ACC_TOUCHLESS_BUTTON_CLOSE_AND_FAR_RANGE;
469 break;
470 }
471 }
472
473 static bool validate_config(acc_touchless_button_config_t *config)
474 {
475 bool status = true;
476
477 if (acc_config_num_subsweeps_get(config->sensor_config) != 2U && config->measurement_type == ACC_TOUCHLESS_BUTTON_CLOSE_AND_FAR_RANGE)
478 {
479 printf("Number of subsweeps must be 2 for 'close and far'\n");
480 status = false;
481 }
482
483 if (acc_config_num_subsweeps_get(config->sensor_config) != 1U &&
484 (config->measurement_type == ACC_TOUCHLESS_BUTTON_CLOSE_RANGE || config->measurement_type == ACC_TOUCHLESS_BUTTON_FAR_RANGE))
485 {
486 printf("Number of subsweeps must be 1 for 'close' and 'far'\n");
487 status = false;
488 }
489
490 float sweep_rate = acc_config_sweep_rate_get(config->sensor_config);
491 uint16_t spf = acc_config_sweeps_per_frame_get(config->sensor_config);
492
493 if (sweep_rate == 0.0f)
494 {
495 printf("Sweep rate must be set\n");
496 status = false;
497 }
498 else
499 {
500 if (spf > (config->calibration_duration_s * sweep_rate))
501 {
502 float calibration_limit = (float)spf / sweep_rate;
503
504 printf("Calibration duration must be at least %" PRIfloat " s\n", ACC_LOG_FLOAT_TO_INTEGER(calibration_limit));
505 status = false;
506 }
507 }
508
509 return status;
510 }
511
512 static void config_log(acc_touchless_button_config_t *config)
513 {
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;
520 acc_touchless_button_measurement_type_t measurement_type = config->measurement_type;
521
522 printf("Reference application Touchless Button config\n");
523
524 if (measurement_type == ACC_TOUCHLESS_BUTTON_CLOSE_RANGE || measurement_type == ACC_TOUCHLESS_BUTTON_CLOSE_AND_FAR_RANGE)
525 {
526 printf("sensitivity close: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(sensitivity_close));
527 printf("patience close: %" PRIu16 "\n", patience_close);
528 }
529
530 if (measurement_type == ACC_TOUCHLESS_BUTTON_FAR_RANGE || measurement_type == ACC_TOUCHLESS_BUTTON_CLOSE_AND_FAR_RANGE)
531 {
532 printf("sensitivity far: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(sensitivity_far));
533 printf("patience far: %" PRIu16 "\n", patience_far);
534 }
535
536 printf("calibration duration: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(calibration_duration_s));
537 printf("calibration interval: %" PRIfloat "\n", ACC_LOG_FLOAT_TO_INTEGER(calibration_interval_s));
538
539 char *measurement_type_str = "";
540
541 switch (measurement_type)
542 {
543 case ACC_TOUCHLESS_BUTTON_CLOSE_RANGE:
544 measurement_type_str = "close";
545 break;
546 case ACC_TOUCHLESS_BUTTON_FAR_RANGE:
547 measurement_type_str = "far";
548 break;
549 case ACC_TOUCHLESS_BUTTON_CLOSE_AND_FAR_RANGE:
550 measurement_type_str = "close and far";
551 break;
552 }
553
554 printf("measurement type: %s\n", measurement_type_str);
555
556 printf("Sensor config\n");
557 acc_config_log(config->sensor_config);
558 }
559
560 static bool init_handle(acc_touchless_button_handle_t *handle)
561 {
562 bool status = true;
563
564 if (!acc_rss_get_buffer_size(handle->config.sensor_config, &handle->buffer_size))
565 {
566 printf("acc_rss_get_buffer_size() failed\n");
567 status = false;
568 }
569
570 if (status)
571 {
572 handle->processing = acc_processing_create(handle->config.sensor_config, &handle->proc_metadata);
573 handle->buffer = acc_integration_mem_alloc(handle->buffer_size);
574
575 uint16_t spf = acc_config_sweeps_per_frame_get(handle->config.sensor_config);
576 float sweep_rate = acc_config_sweep_rate_get(handle->config.sensor_config);
577 float frame_rate = sweep_rate / (float)spf;
578
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;
582
583 handle->double_buffer_filter_buffer = acc_integration_mem_alloc((spf - 2U) * sizeof(*handle->double_buffer_filter_buffer));
584 handle->frame_variance = acc_integration_mem_alloc(handle->proc_metadata.frame_data_length * sizeof(*handle->frame_variance));
585 handle->arg_norm = acc_integration_mem_alloc(handle->proc_metadata.sweep_data_length * sizeof(*handle->arg_norm));
586 handle->ampl_mean = acc_integration_mem_alloc(handle->proc_metadata.sweep_data_length * sizeof(*handle->ampl_mean));
587 handle->ampl_std = acc_integration_mem_alloc(handle->proc_metadata.sweep_data_length * sizeof(*handle->ampl_std));
588 handle->phase_mean = acc_integration_mem_alloc(handle->proc_metadata.sweep_data_length * sizeof(*handle->phase_mean));
589 handle->phase_std = acc_integration_mem_alloc(handle->proc_metadata.sweep_data_length * sizeof(*handle->phase_std));
590 handle->dynamic_background = acc_integration_mem_alloc(handle->cal_sweeps * num_points * sizeof(*handle->dynamic_background));
591 handle->dynamic_background_guard =
592 acc_integration_mem_alloc(handle->proc_metadata.frame_data_length * sizeof(*handle->dynamic_background_guard));
593 handle->threshold_check_count = acc_integration_mem_alloc(handle->proc_metadata.sweep_data_length * sizeof(*handle->threshold_check_count));
594
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);
599 }
600
601 if (status)
602 {
603 reset_background(handle);
604
605 handle->run_close = handle->config.measurement_type == ACC_TOUCHLESS_BUTTON_CLOSE_RANGE ||
606 handle->config.measurement_type == ACC_TOUCHLESS_BUTTON_CLOSE_AND_FAR_RANGE;
607 handle->run_far = handle->config.measurement_type == ACC_TOUCHLESS_BUTTON_FAR_RANGE ||
608 handle->config.measurement_type == ACC_TOUCHLESS_BUTTON_CLOSE_AND_FAR_RANGE;
609 handle->close_num_points = handle->run_close ? acc_config_subsweep_num_points_get(handle->config.sensor_config, 0U) : 0U;
610 handle->far_num_points = handle->run_far ? (handle->run_close ? acc_config_subsweep_num_points_get(handle->config.sensor_config, 1U)
611 : acc_config_num_points_get(handle->config.sensor_config))
612 : 0U;
613
614 handle->close_threshold = get_threshold(handle->config.sensitivity_close);
615 handle->far_threshold = get_threshold(handle->config.sensitivity_far);
616
617 handle->close_signal = 0U;
618 handle->far_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;
623 }
624
625 return status;
626 }
627
628 static float get_threshold(float sensitivity)
629 {
630 return (1.0f / sensitivity) * 10.0f;
631 }
632
633 static void reset_background(acc_touchless_button_handle_t *handle)
634 {
635 handle->frames_since_last_cal = 0U;
636
637 uint16_t spf = acc_config_sweeps_per_frame_get(handle->config.sensor_config);
638 uint16_t num_points = handle->proc_metadata.sweep_data_length;
639
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;
644 }
645
646 static bool init_sensor(acc_touchless_button_handle_t *handle)
647 {
648 acc_hal_integration_sensor_supply_on(SENSOR_ID);
649 acc_hal_integration_sensor_enable(SENSOR_ID);
650
651 handle->sensor = acc_sensor_create(SENSOR_ID);
652
653 if (handle->sensor == NULL)
654 {
655 return false;
656 }
657
658 if (!do_sensor_calibration_and_prepare(handle))
659 {
660 return false;
661 }
662
663 return true;
664 }
665
666 static bool do_sensor_calibration_and_prepare(acc_touchless_button_handle_t *handle)
667 {
668 bool status = false;
669 bool cal_complete = false;
670 acc_cal_result_t cal_result;
671 const uint16_t calibration_retries = 1U;
672
673 // Random disturbances may cause the calibration to fail. At failure, retry at least once.
674 for (uint16_t i = 0; !status && (i <= calibration_retries); i++)
675 {
676 // Reset sensor before calibration by disabling/enabling it
677 acc_hal_integration_sensor_disable(SENSOR_ID);
678 acc_hal_integration_sensor_enable(SENSOR_ID);
679
680 do
681 {
682 status = acc_sensor_calibrate(handle->sensor, &cal_complete, &cal_result, handle->buffer, handle->buffer_size);
683
684 if (status && !cal_complete)
685 {
686 status = acc_hal_integration_wait_for_sensor_interrupt(SENSOR_ID, SENSOR_TIMEOUT_MS);
687 }
688 } while (status && !cal_complete);
689 }
690
691 if (status)
692 {
693 // Reset sensor after calibration by disabling/enabling it
694 acc_hal_integration_sensor_disable(SENSOR_ID);
695 acc_hal_integration_sensor_enable(SENSOR_ID);
696
697 status = acc_sensor_prepare(handle->sensor, handle->config.sensor_config, &cal_result, handle->buffer, handle->buffer_size);
698 }
699
700 return status;
701 }
702
703 static bool measure(acc_touchless_button_handle_t *handle)
704 {
705 if (!acc_sensor_measure(handle->sensor))
706 {
707 printf("acc_sensor_measure failed\n");
708 acc_sensor_status(handle->sensor);
709 return false;
710 }
711
712 if (!acc_hal_integration_wait_for_sensor_interrupt(SENSOR_ID, SENSOR_TIMEOUT_MS))
713 {
714 printf("Sensor interrupt timeout\n");
715 acc_sensor_status(handle->sensor);
716 return false;
717 }
718
719 if (!acc_sensor_read(handle->sensor, handle->buffer, handle->buffer_size))
720 {
721 printf("acc_sensor_read failed\n");
722 acc_sensor_status(handle->sensor);
723 return false;
724 }
725
726 acc_processing_execute(handle->processing, handle->buffer, &handle->proc_result);
727
728 return true;
729 }
730
731 static void calc_variance(acc_touchless_button_handle_t *handle)
732 {
733 uint16_t sweep_data_length = handle->proc_metadata.sweep_data_length;
734
735 acc_algorithm_mean_matrix_i16_complex(handle->dynamic_background, handle->cal_sweeps, sweep_data_length, handle->arg_norm, 0U);
736
737 acc_algorithm_conj_f32(handle->arg_norm, sweep_data_length);
738
739 acc_algorithm_normalize_f32_complex(handle->arg_norm, sweep_data_length);
740
741 for (uint16_t c = 0U; c < sweep_data_length; c++)
742 {
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++)
748 {
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);
754
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);
759
760 delta = cargf(element) - phase_mean;
761 phase_mean += (delta / (float)div);
762 phase_sq_term += delta * (cargf(element) - phase_mean);
763 }
764
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);
769 }
770
771 uint16_t spf = acc_config_sweeps_per_frame_get(handle->config.sensor_config);
772
773 for (uint16_t r = 0U; r < spf; r++)
774 {
775 for (uint16_t c = 0U; c < sweep_data_length; c++)
776 {
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];
784
785 handle->frame_variance[r * sweep_data_length + c] = sqrtf(powf(a, 2.0f) + powf(b, 2.0f));
786 }
787 }
788 }
789
790 static bool check_count(uint16_t *count, uint16_t check_offset, uint16_t check_length)
791 {
792 bool success = false;
793
794 for (uint16_t i = 0U; i < check_length; i++)
795 {
796 if (count[check_offset + i] > 1U)
797 {
798 success = true;
799 }
800 }
801
802 return success;
803 }
804
805 static void update_background(acc_touchless_button_handle_t *handle)
806 {
807 uint16_t spf = acc_config_sweeps_per_frame_get(handle->config.sensor_config);
808
809 acc_algorithm_roll_and_push_mult_matrix_i16_complex(handle->dynamic_background,
810 handle->cal_sweeps,
811 handle->proc_metadata.sweep_data_length,
812 handle->dynamic_background_guard,
813 acc_config_sweeps_per_frame_get(handle->config.sensor_config),
814 false);
815
816 handle->rows_in_dynamic_background += spf;
817 handle->rows_in_dynamic_background =
818 handle->rows_in_dynamic_background > handle->cal_sweeps ? handle->cal_sweeps : handle->rows_in_dynamic_background;
819 handle->frames_since_last_cal = 0U;
820 }
821
822 static bool get_detection(bool current_detection, uint16_t sig_count, uint16_t non_sig_count, uint16_t patience)
823 {
824 bool new_detection = !current_detection && sig_count >= patience;
825 bool keep_detection = current_detection && non_sig_count <= patience;
826
827 return new_detection || keep_detection;
828 }
829
830 static bool process(acc_touchless_button_handle_t *handle, acc_touchless_button_result_t *result)
831 {
832 if (acc_config_double_buffering_get(handle->config.sensor_config))
833 {
834 acc_algorithm_double_buffering_frame_filter(handle->proc_result.frame,
835 acc_config_sweeps_per_frame_get(handle->config.sensor_config),
836 acc_config_num_points_get(handle->config.sensor_config),
837 handle->double_buffer_filter_buffer);
838 }
839
840 memset(handle->frame_variance, 0, handle->proc_metadata.frame_data_length * sizeof(*handle->frame_variance));
841
842 if (handle->frames_since_last_cal > handle->cal_interval_frames)
843 {
844 reset_background(handle);
845 }
846 else if (handle->rows_in_dynamic_background == handle->cal_sweeps)
847 {
848 calc_variance(handle);
849 }
850
851 uint16_t threshold_check_offset = 0U;
852
853 if (handle->run_close)
854 {
855 acc_algorithm_count_points_above_threshold(handle->frame_variance,
856 acc_config_sweeps_per_frame_get(handle->config.sensor_config),
857 handle->proc_metadata.sweep_data_length,
858 handle->close_threshold,
859 handle->threshold_check_count,
860 threshold_check_offset,
861 handle->close_num_points,
862 1U);
863
864 threshold_check_offset = handle->close_num_points;
865 }
866
867 if (handle->run_far)
868 {
869 acc_algorithm_count_points_above_threshold(handle->frame_variance,
870 acc_config_sweeps_per_frame_get(handle->config.sensor_config),
871 handle->proc_metadata.sweep_data_length,
872 handle->far_threshold,
873 handle->threshold_check_count,
874 threshold_check_offset,
875 handle->far_num_points,
876 1U);
877 }
878
879 if (check_count(handle->threshold_check_count, 0U, handle->proc_metadata.sweep_data_length))
880 {
881 uint16_t close_offset = 0U;
882 uint16_t far_offset = handle->close_num_points;
883
884 if (handle->run_close)
885 {
886 if (check_count(handle->threshold_check_count, close_offset, handle->close_num_points))
887 {
888 handle->close_signal++;
889 handle->close_non_signal = 0U;
890 }
891 else
892 {
893 handle->close_signal = 0U;
894 handle->close_non_signal++;
895 }
896 }
897
898 if (handle->run_far)
899 {
900 if (check_count(handle->threshold_check_count, far_offset, handle->far_num_points))
901 {
902 handle->far_signal++;
903 handle->far_non_signal = 0U;
904 }
905 else
906 {
907 handle->far_signal = 0U;
908 handle->far_non_signal++;
909 }
910 }
911
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++;
915 }
916 else
917 {
918 handle->close_signal = 0U;
919 handle->far_signal = 0U;
920 handle->close_non_signal++;
921 handle->far_non_signal++;
922
923 if (handle->update_background)
924 {
925 update_background(handle);
926 }
927
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;
932 }
933
934 memset(result, 0, sizeof(*result));
935
936 result->close_result = ACC_TOUCHLESS_BUTTON_RANGE_NOT_USED;
937 result->far_result = ACC_TOUCHLESS_BUTTON_RANGE_NOT_USED;
938
939 if (handle->run_close)
940 {
941 handle->close_detection =
942 get_detection(handle->close_detection, handle->close_signal, handle->close_non_signal, handle->config.patience_close);
943 result->close_result = handle->close_detection ? ACC_TOUCHLESS_BUTTON_RANGE_DETECTION : ACC_TOUCHLESS_BUTTON_RANGE_NO_DETECTION;
944 }
945
946 if (handle->run_far)
947 {
948 handle->far_detection = get_detection(handle->far_detection, handle->far_signal, handle->far_non_signal, handle->config.patience_far);
949 result->far_result = handle->far_detection ? ACC_TOUCHLESS_BUTTON_RANGE_DETECTION : ACC_TOUCHLESS_BUTTON_RANGE_NO_DETECTION;
950 }
951
952 return true;
953 }
954
955 static void print_result(acc_touchless_button_result_t *result)
956 {
957 if (result->close_result != ACC_TOUCHLESS_BUTTON_RANGE_NOT_USED)
958 {
959 printf("Close detection: %s\n", result->close_result == ACC_TOUCHLESS_BUTTON_RANGE_DETECTION ? "True" : "False");
960 }
961
962 if (result->far_result != ACC_TOUCHLESS_BUTTON_RANGE_NOT_USED)
963 {
964 printf("Far detection: %s\n", result->far_result == ACC_TOUCHLESS_BUTTON_RANGE_DETECTION ? "True" : "False");
965 }
966 }
acc_touchless_button_result_t
Touchless button application result.
Definition: ref_app_touchless_button.c:159
acc_touchless_button_handle_t::proc_result
acc_processing_result_t proc_result
Definition: ref_app_touchless_button.c:114
acc_config_start_point_set
void acc_config_start_point_set(acc_config_t *config, int32_t start_point)
Set the starting point of the sweep.
acc_touchless_button_handle_t::buffer
void * buffer
Definition: ref_app_touchless_button.c:115
acc_config_inter_frame_idle_state_set
void acc_config_inter_frame_idle_state_set(acc_config_t *config, acc_config_idle_state_t idle_state)
Set inter frame idle state.
acc_touchless_button_handle_t::config
acc_touchless_button_config_t config
Definition: ref_app_touchless_button.c:110
acc_hal_integration_sensor_supply_off
void acc_hal_integration_sensor_supply_off(acc_sensor_id_t sensor_id)
Power off sensor supply.
Definition: acc_hal_integration_stm32cube_xm.c:104
acc_rss_a121.h
acc_touchless_button_handle_t::far_threshold
float far_threshold
Definition: ref_app_touchless_button.c:132
acc_processing_destroy
void acc_processing_destroy(acc_processing_t *handle)
Destroy a processing instance identified with the provided processing handle.
acc_config_subsweep_num_points_get
uint16_t acc_config_subsweep_num_points_get(const acc_config_t *config, uint8_t index)
Get the number of data points to measure.
acc_hal_integration_sensor_supply_on
void acc_hal_integration_sensor_supply_on(acc_sensor_id_t sensor_id)
Power on sensor supply.
Definition: acc_hal_integration_stm32cube_xm.c:99
get_detection
static bool get_detection(bool current_detection, uint16_t sig_count, uint16_t non_sig_count, uint16_t patience)
Definition: ref_app_touchless_button.c:822
ACC_TOUCHLESS_BUTTON_PRESET_NONE
@ ACC_TOUCHLESS_BUTTON_PRESET_NONE
Definition: ref_app_touchless_button.c:97
acc_processing_result_t
Result provided by the processing module.
Definition: acc_processing.h:71
acc_touchless_button_handle_t::close_signal
uint16_t close_signal
Definition: ref_app_touchless_button.c:138
init_handle
static bool init_handle(acc_touchless_button_handle_t *handle)
Definition: ref_app_touchless_button.c:560
acc_touchless_button_handle_t::far_non_signal
uint16_t far_non_signal
Definition: ref_app_touchless_button.c:141
ACC_TOUCHLESS_BUTTON_RANGE_DETECTION
@ ACC_TOUCHLESS_BUTTON_RANGE_DETECTION
Definition: ref_app_touchless_button.c:153
acc_sensor_read
bool acc_sensor_read(const acc_sensor_t *sensor, void *buffer, uint32_t buffer_size)
Read out radar data.
SENSOR_TIMEOUT_MS
#define SENSOR_TIMEOUT_MS
Definition: ref_app_touchless_button.c:29
acc_touchless_button_handle_t::sensor
acc_sensor_t * sensor
Definition: ref_app_touchless_button.c:111
acc_version.h
acc_touchless_button_handle_t::proc_metadata
acc_processing_metadata_t proc_metadata
Definition: ref_app_touchless_button.c:113
acc_rss_get_buffer_size
bool acc_rss_get_buffer_size(const acc_config_t *config, uint32_t *buffer_size)
Get the buffer size needed for the specified config.
acc_config_num_subsweeps_get
uint8_t acc_config_num_subsweeps_get(const acc_config_t *config)
Get the number of subsweeps to use.
acc_algorithm_normalize_f32_complex
void acc_algorithm_normalize_f32_complex(float complex *data, uint16_t data_length)
Normalize all elements in an array individually.
Definition: acc_algorithm.c:584
acc_touchless_button_config_t::patience_far
uint16_t patience_far
Definition: ref_app_touchless_button.c:74
acc_touchless_button_config_t::sensor_config
acc_config_t * sensor_config
Definition: ref_app_touchless_button.c:92
acc_config_profile_set
void acc_config_profile_set(acc_config_t *config, acc_config_profile_t profile)
Set a profile.
init_sensor
static bool init_sensor(acc_touchless_button_handle_t *handle)
Definition: ref_app_touchless_button.c:646
acc_int16_complex_t
Data type for interger-based representation of complex numbers.
Definition: acc_definitions_common.h:40
acc_algorithm_double_buffering_frame_filter
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.
Definition: acc_algorithm.c:774
acc_config_sweeps_per_frame_set
void acc_config_sweeps_per_frame_set(acc_config_t *config, uint16_t sweeps)
Set sweeps per frame.
acc_config_destroy
void acc_config_destroy(acc_config_t *config)
Destroy a configuration freeing any resources allocated.
ACC_TOUCHLESS_BUTTON_RANGE_NO_DETECTION
@ ACC_TOUCHLESS_BUTTON_RANGE_NO_DETECTION
Definition: ref_app_touchless_button.c:152
acc_touchless_button_handle_t::run_far
bool run_far
Definition: ref_app_touchless_button.c:135
acc_cal_result_t
The result from a completed calibration.
Definition: acc_definitions_a121.h:30
acc_touchless_button_handle_t::close_non_signal
uint16_t close_non_signal
Definition: ref_app_touchless_button.c:140
acc_touchless_button_handle_t::close_detection
bool close_detection
Definition: ref_app_touchless_button.c:142
acc_processing_execute
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.
ACC_TOUCHLESS_BUTTON_FAR_RANGE
@ ACC_TOUCHLESS_BUTTON_FAR_RANGE
Definition: ref_app_touchless_button.c:43
get_threshold
static float get_threshold(float sensitivity)
Definition: ref_app_touchless_button.c:628
acc_config_inter_sweep_idle_state_set
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_touchless_button_handle_t::update_background
bool update_background
Definition: ref_app_touchless_button.c:129
acc_config_create
acc_config_t * acc_config_create(void)
Create a configuration.
update_background
static void update_background(acc_touchless_button_handle_t *handle)
Definition: ref_app_touchless_button.c:805
ACC_TOUCHLESS_BUTTON_PRESET_CLOSE_AND_FAR
@ ACC_TOUCHLESS_BUTTON_PRESET_CLOSE_AND_FAR
Definition: ref_app_touchless_button.c:100
acc_touchless_button_preset_t
acc_touchless_button_preset_t
Definition: ref_app_touchless_button.c:95
acc_integration.h
config
cargo_config_t config
Definition: i2c_example_cargo.c:34
acc_touchless_button_config_t::calibration_duration_s
float calibration_duration_s
Definition: ref_app_touchless_button.c:78
acc_hal_rss_integration_get_implementation
const acc_hal_a121_t * acc_hal_rss_integration_get_implementation(void)
Get hal implementation reference.
Definition: acc_hal_integration_stm32cube_xm.c:152
acc_integration_mem_alloc
void * acc_integration_mem_alloc(size_t size)
Allocate dynamic memory.
Definition: acc_integration_stm32.c:592
acc_processing_metadata_t
Metadata that will be populated by the processing module during creation.
Definition: acc_processing.h:36
acc_hal_a121_t
Definition: acc_hal_definitions_a121.h:82
acc_touchless_button_measurement_type_t
acc_touchless_button_measurement_type_t
Application measurement type.
Definition: ref_app_touchless_button.c:34
acc_rss_hal_register
bool acc_rss_hal_register(const acc_hal_a121_t *hal)
Register an integration.
acc_sensor.h
acc_touchless_button_handle_t::far_detection
bool far_detection
Definition: ref_app_touchless_button.c:143
acc_config_double_buffering_set
void acc_config_double_buffering_set(acc_config_t *config, bool enable)
Enable or disable double buffering.
acc_algorithm_mean_matrix_i16_complex
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.
Definition: acc_algorithm.c:554
acc_config_hwaas_set
void acc_config_hwaas_set(acc_config_t *config, uint16_t hwaas)
Set the hardware accelerated average samples (HWAAS)
acc_config_sweeps_per_frame_get
uint16_t acc_config_sweeps_per_frame_get(const acc_config_t *config)
Get the number of sweeps per frame.
acc_touchless_button_handle_t
Touchless button application handle.
Definition: ref_app_touchless_button.c:108
SENSOR_ID
#define SENSOR_ID
Definition: ref_app_touchless_button.c:26
acc_touchless_button_handle_t::ampl_std
float * ampl_std
Definition: ref_app_touchless_button.c:121
acc_touchless_button_handle_t::close_threshold
float close_threshold
Definition: ref_app_touchless_button.c:131
ACC_TOUCHLESS_BUTTON_CLOSE_RANGE
@ ACC_TOUCHLESS_BUTTON_CLOSE_RANGE
Definition: ref_app_touchless_button.c:39
acc_hal_integration_wait_for_sensor_interrupt
bool acc_hal_integration_wait_for_sensor_interrupt(acc_sensor_id_t sensor_id, uint32_t timeout_ms)
Wait for a sensor interrupt.
Definition: acc_hal_integration_stm32cube_xm.c:130
acc_touchless_button_handle_t::rows_in_dynamic_background
uint16_t rows_in_dynamic_background
Definition: ref_app_touchless_button.c:127
acc_touchless_button_config_t::sensitivity_far
float sensitivity_far
Definition: ref_app_touchless_button.c:69
acc_hal_integration_a121.h
cleanup
static void cleanup(acc_touchless_button_handle_t *handle)
Definition: ref_app_touchless_button.c:317
handle
cargo_handle_t * handle
Definition: i2c_example_cargo.c:35
ACC_CONFIG_IDLE_STATE_READY
@ ACC_CONFIG_IDLE_STATE_READY
Definition: acc_definitions_a121.h:76
result
cargo_result_t result
Definition: i2c_example_cargo.c:43
acc_version_get
const char * acc_version_get(void)
Get the version of the Acconeer software.
acc_config_t
struct acc_config acc_config_t
Definition: acc_config.h:24
printf
#define printf
Definition: printf.h:60
acc_touchless_button_handle_t::phase_std
float * phase_std
Definition: ref_app_touchless_button.c:123
ACC_TOUCHLESS_BUTTON_RANGE_NOT_USED
@ ACC_TOUCHLESS_BUTTON_RANGE_NOT_USED
Definition: ref_app_touchless_button.c:151
acc_touchless_button_handle_t::dynamic_background
acc_int16_complex_t * dynamic_background
Definition: ref_app_touchless_button.c:126
acc_config_num_subsweeps_set
void acc_config_num_subsweeps_set(acc_config_t *config, uint8_t num_subsweeps)
Set the number of subsweeps to use.
acc_hal_integration_sensor_enable
void acc_hal_integration_sensor_enable(acc_sensor_id_t sensor_id)
Enable sensor.
Definition: acc_hal_integration_stm32cube_xm.c:109
acc_touchless_button_handle_t::cal_sweeps
uint16_t cal_sweeps
Definition: ref_app_touchless_button.c:125
acc_config_step_length_set
void acc_config_step_length_set(acc_config_t *config, uint16_t step_length)
Set the step length in a sweep.
acc_config_num_points_set
void acc_config_num_points_set(acc_config_t *config, uint16_t num_points)
Set the number of data points to measure.
acc_config_subsweep_start_point_set
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.
acc_touchless_button_handle_t::buffer_size
uint32_t buffer_size
Definition: ref_app_touchless_button.c:116
acc_hal_definitions_a121.h
acc_touchless_button_handle_t::close_num_points
uint16_t close_num_points
Definition: ref_app_touchless_button.c:136
acconeer_main
int acconeer_main(int argc, char *argv[])
Assembly test example.
Definition: ref_app_touchless_button.c:197
acc_config_sweep_rate_set
void acc_config_sweep_rate_set(acc_config_t *config, float sweep_rate)
Set the sweep rate.
acc_config_subsweep_profile_set
void acc_config_subsweep_profile_set(acc_config_t *config, acc_config_profile_t profile, uint8_t index)
Set a profile.
acc_touchless_button_result_t::far_result
acc_touchless_button_range_result_t far_result
Definition: ref_app_touchless_button.c:162
acc_touchless_button_handle_t::frame_variance
float * frame_variance
Definition: ref_app_touchless_button.c:118
acc_touchless_button_handle_t::far_num_points
uint16_t far_num_points
Definition: ref_app_touchless_button.c:137
acc_algorithm_conj_f32
void acc_algorithm_conj_f32(float complex *data, uint16_t data_length)
Inline calculate conjugate of all elements in an array.
Definition: acc_algorithm.c:576
acc_touchless_button_range_result_t
acc_touchless_button_range_result_t
Touchless button range result.
Definition: ref_app_touchless_button.c:149
acc_hal_integration_sensor_disable
void acc_hal_integration_sensor_disable(acc_sensor_id_t sensor_id)
Disable sensor.
Definition: acc_hal_integration_stm32cube_xm.c:119
acc_touchless_button_result_t::close_result
acc_touchless_button_range_result_t close_result
Definition: ref_app_touchless_button.c:161
acc_touchless_button_config_t::measurement_type
acc_touchless_button_measurement_type_t measurement_type
Definition: ref_app_touchless_button.c:88
acc_processing_t
struct acc_processing_handle acc_processing_t
Definition: acc_processing.h:30
validate_config
static bool validate_config(acc_touchless_button_config_t *config)
Definition: ref_app_touchless_button.c:473
acc_integration_log.h
acc_touchless_button_handle_t::double_buffer_filter_buffer
int32_t * double_buffer_filter_buffer
Definition: ref_app_touchless_button.c:117
ACC_LOG_FLOAT_TO_INTEGER
#define ACC_LOG_FLOAT_TO_INTEGER(a)
Definition: acc_integration_log.h:26
acc_touchless_button_config_t::patience_close
uint16_t patience_close
Definition: ref_app_touchless_button.c:64
reset_background
static void reset_background(acc_touchless_button_handle_t *handle)
Definition: ref_app_touchless_button.c:633
acc_touchless_button_handle_t::run_close
bool run_close
Definition: ref_app_touchless_button.c:134
acc_config_continuous_sweep_mode_set
void acc_config_continuous_sweep_mode_set(acc_config_t *config, bool enabled)
Set continuous sweep mode.
process
static bool process(acc_touchless_button_handle_t *handle, acc_touchless_button_result_t *result)
Definition: ref_app_touchless_button.c:830
acc_sensor_status
void acc_sensor_status(const acc_sensor_t *sensor)
Check the status of the sensor.
acc_touchless_button_handle_t::dynamic_background_guard
acc_int16_complex_t * dynamic_background_guard
Definition: ref_app_touchless_button.c:128
acc_touchless_button_handle_t::processing
acc_processing_t * processing
Definition: ref_app_touchless_button.c:112
acc_config_subsweep_receiver_gain_set
void acc_config_subsweep_receiver_gain_set(acc_config_t *config, uint8_t gain, uint8_t index)
Set receiver gain setting.
acc_algorithm.h
acc_touchless_button_handle_t::ampl_mean
float * ampl_mean
Definition: ref_app_touchless_button.c:120
acc_touchless_button_handle_t::threshold_check_count
uint16_t * threshold_check_count
Definition: ref_app_touchless_button.c:133
calc_variance
static void calc_variance(acc_touchless_button_handle_t *handle)
Definition: ref_app_touchless_button.c:731
acc_sensor_prepare
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.
ACC_TOUCHLESS_BUTTON_PRESET_FAR
@ ACC_TOUCHLESS_BUTTON_PRESET_FAR
Definition: ref_app_touchless_button.c:99
acc_integration_mem_free
void acc_integration_mem_free(void *ptr)
Free dynamic memory.
Definition: acc_integration_stm32.c:602
acc_config_double_buffering_get
bool acc_config_double_buffering_get(const acc_config_t *config)
Get the double buffering configuration.
acc_definitions_common.h
acc_config_subsweep_hwaas_set
void acc_config_subsweep_hwaas_set(acc_config_t *config, uint16_t hwaas, uint8_t index)
Set the hardware accelerated average samples (HWAAS)
acc_config_receiver_gain_set
void acc_config_receiver_gain_set(acc_config_t *config, uint8_t gain)
Set receiver gain setting.
acc_config_log
void acc_config_log(const acc_config_t *config)
Print a configuration to the log.
acc_config_subsweep_step_length_set
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.
check_count
static bool check_count(uint16_t *count, uint16_t check_offset, uint16_t check_length)
Definition: ref_app_touchless_button.c:790
acc_config.h
DEFAULT_PRESET
#define DEFAULT_PRESET
Definition: ref_app_touchless_button.c:103
acc_config_sweep_rate_get
float acc_config_sweep_rate_get(const acc_config_t *config)
Get the sweep rate.
ACC_TOUCHLESS_BUTTON_CLOSE_AND_FAR_RANGE
@ ACC_TOUCHLESS_BUTTON_CLOSE_AND_FAR_RANGE
Definition: ref_app_touchless_button.c:47
acc_touchless_button_handle_t::frames_since_last_cal
uint16_t frames_since_last_cal
Definition: ref_app_touchless_button.c:130
acc_sensor_calibrate
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.
acc_config_subsweep_num_points_set
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.
acc_config_num_points_get
uint16_t acc_config_num_points_get(const acc_config_t *config)
Get the number of data points to measure.
PRIfloat
#define PRIfloat
Specifier for printing float type using integers.
Definition: acc_integration_log.h:31
ACC_TOUCHLESS_BUTTON_PRESET_CLOSE
@ ACC_TOUCHLESS_BUTTON_PRESET_CLOSE
Definition: ref_app_touchless_button.c:98
ACC_CONFIG_PROFILE_1
@ ACC_CONFIG_PROFILE_1
Definition: acc_definitions_a121.h:52
acc_touchless_button_config_t::calibration_interval_s
float calibration_interval_s
Definition: ref_app_touchless_button.c:83
acc_sensor_measure
bool acc_sensor_measure(acc_sensor_t *sensor)
Start a radar measurement with previously prepared configuration.
acc_algorithm_count_points_above_threshold
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.
Definition: acc_algorithm.c:1281
acc_touchless_button_handle_t::arg_norm
float complex * arg_norm
Definition: ref_app_touchless_button.c:119
acc_processing_create
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.
measure
static bool measure(acc_touchless_button_handle_t *handle)
Definition: ref_app_touchless_button.c:703
acc_touchless_button_config_t
Touchless button application config.
Definition: ref_app_touchless_button.c:53
acc_algorithm_roll_and_push_mult_matrix_i16_complex
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.
Definition: acc_algorithm.c:237
acc_touchless_button_handle_t::phase_mean
float * phase_mean
Definition: ref_app_touchless_button.c:122
acc_processing.h
acc_sensor_t
struct acc_sensor acc_sensor_t
Definition: acc_sensor.h:31
ACC_CONFIG_PROFILE_3
@ ACC_CONFIG_PROFILE_3
Definition: acc_definitions_a121.h:54
acc_touchless_button_config_t::sensitivity_close
float sensitivity_close
Definition: ref_app_touchless_button.c:59
acc_touchless_button_handle_t::far_signal
uint16_t far_signal
Definition: ref_app_touchless_button.c:139
do_sensor_calibration_and_prepare
static bool do_sensor_calibration_and_prepare(acc_touchless_button_handle_t *handle)
Definition: ref_app_touchless_button.c:666
acc_sensor_destroy
void acc_sensor_destroy(acc_sensor_t *sensor)
Destroy a sensor instance freeing any resources allocated.
print_result
static void print_result(acc_touchless_button_result_t *result)
Definition: ref_app_touchless_button.c:955
config_log
static void config_log(acc_touchless_button_config_t *config)
Definition: ref_app_touchless_button.c:512
set_config
static void set_config(acc_touchless_button_config_t *config, acc_touchless_button_preset_t preset)
Definition: ref_app_touchless_button.c:393
acc_sensor_create
acc_sensor_t * acc_sensor_create(acc_sensor_id_t sensor_id)
Create a sensor instance.
acc_touchless_button_handle_t::cal_interval_frames
uint16_t cal_interval_frames
Definition: ref_app_touchless_button.c:124