ref_app_breathing.c
Go to the documentation of this file.
1 // Copyright (c) Acconeer AB, 2023
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 <math.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <string.h>
11
12 #include "acc_alg_basic_utils.h"
13 #include "acc_algorithm.h"
14 #include "acc_definitions_a121.h"
15 #include "acc_definitions_common.h"
16 #include "acc_detector_presence.h"
17 #include "acc_hal_definitions_a121.h"
18 #include "acc_hal_integration_a121.h"
19 #include "acc_integration.h"
20 #include "acc_processing.h"
21 #include "acc_rss_a121.h"
22 #include "acc_sensor.h"
23 #include "acc_version.h"
24
25
26 typedef enum
27 {
28 BREATHING_PRESET_NONE,
29 BREATHING_PRESET_SITTING,
30 BREATHING_PRESET_INFANT,
31 } breathing_preset_t;
32
33 #define SENSOR_ID (1U)
34 #define SENSOR_TIMEOUT_MS (1000U)
35
36 #define ACC_ALGORITHM_APPROX_BASE_STEP_LENGTH_M (2.5e-3f)
37
38 #define DEFAULT_PRESET_CONFIG BREATHING_PRESET_SITTING
39
40 #define B_STATIC_LENGTH (3U)
41 #define A_STATIC_LENGTH (2U)
42 #define B_ANGLE_LENGTH (5U)
43 #define A_ANGLE_LENGTH (4U)
44
45 /**
46 * @brief Breathing application config container
47 */
48 typedef struct
49 {
50 /**
51 * Length of time series
52 */
53 uint16_t time_series_length_s;
54 /**
55 * Lowest anticipated breathing rate (breaths per minute)
56 */
57 uint16_t lowest_breathing_rate;
58 /**
59 * Highest anticipated breathing rate (breaths per minute)
60 */
61 uint16_t highest_breathing_rate;
62 /**
63 * Number of distance to analyze in breathing
64 */
65 uint16_t num_dists_to_analyze;
66 /**
67 * Use presence detector to determine distance to motion
68 */
69 bool use_presence_processor;
70 /**
71 * Time to determine distance to presence
72 */
73 uint16_t distance_determination_duration_s;
74 /**
75 * Presence config
76 */
77 acc_detector_presence_config_t *presence_config;
78 } acc_breathing_config_t;
79
80 typedef enum
81 {
82 ACC_BREATHING_APP_STATE_INIT,
83 ACC_BREATHING_APP_STATE_NO_PRESENCE,
84 ACC_BREATHING_APP_STATE_INTRA_PRESENCE,
85 ACC_BREATHING_APP_STATE_DETERMINE_DISTANCE,
86 ACC_BREATHING_APP_STATE_ESTIMATE_BREATHING_RATE,
87 } acc_breathing_app_state_t;
88
89
90 /**
91 * @brief Breathing application context handle
92 */
93 typedef struct
94 {
95 acc_sensor_t *sensor;
96 acc_cal_result_t sensor_cal_result;
97 acc_detector_presence_handle_t *presence_handle;
98 void *buffer;
99 uint32_t buffer_size;
100
101 float start_m;
102 float step_length_m;
103 int32_t start_point;
104 uint16_t num_points_to_analyze_half_width;
105 uint16_t num_points_to_analyze;
106 uint16_t end_point;
107 float frame_rate;
108 float lowest_freq;
109 float highest_freq;
110 uint16_t use_presence_processor;
111 uint16_t distance_determination_count;
112 uint16_t time_series_length_s;
113 uint16_t time_series_length;
114 uint16_t padded_time_series_length_shift;
115 uint16_t padded_time_series_length;
116 uint16_t num_points;
117 uint16_t sweeps_per_frame;
118 float intra_detection_threshold;
119
120 acc_breathing_app_state_t app_state;
121 acc_breathing_app_state_t prev_app_state;
122
123 float presence_sf;
124 float breathing_sf;
125
126 float b_static[B_STATIC_LENGTH];
127 float a_static[A_STATIC_LENGTH];
128 float b_angle[B_ANGLE_LENGTH];
129 float a_angle[A_ANGLE_LENGTH];
130
131 float complex *mean_sweep;
132 float complex *sparse_iq_buffer;
133 float complex *filt_sparse_iq_buffer;
134 float complex *filt_sparse_iq;
135 float *angle;
136 float *prev_angle;
137 float *lp_filt_ampl;
138 float *unwrapped_angle;
139 float *angle_buffer;
140 float *filt_angle_buffer;
141 float *breathing_motion_buffer;
142 float *hamming_window;
143 float *windowed_breathing_motion_buffer;
144 float complex *rfft_output;
145 uint16_t rfft_output_length;
146 float *weighted_psd;
147 float freq_delta;
148
149 uint16_t distance_determination_counter;
150 bool presence_init;
151 float presence_distance;
152 bool base_presence_dist;
153 float base_presence_distance;
154 float presence_distance_threshold;
155 bool first;
156 uint16_t init_count;
157 uint16_t count;
158 bool initialized;
159 uint16_t count_limit;
160 } acc_breathing_handle_t;
161
162
163 /**
164 * @brief Breathing application results container
165 */
166 typedef struct
167 {
168 /**
169 * Indication when a new breathing rate result is produced
170 */
171 bool result_ready;
172 /**
173 * Breathing rate in BPM
174 */
175 float breathing_rate;
176 } acc_breathing_result_t;
177
178
179 static void cleanup(acc_breathing_handle_t *handle, acc_breathing_config_t *config);
180
181
182 static void set_config(acc_breathing_config_t *config, breathing_preset_t preset);
183
184
185 static bool validate_config(acc_breathing_config_t *config);
186
187
188 static bool init_handle(acc_breathing_handle_t *handle, acc_breathing_config_t *config);
189
190
191 static bool init_sensor_resources(acc_breathing_handle_t *handle, acc_breathing_config_t *config);
192
193
194 static bool sensor_calibration(acc_breathing_handle_t *handle);
195
196
197 static bool reinit_breathing(acc_breathing_handle_t *handle, uint16_t start_point, uint16_t end_point);
198
199
200 static bool measure(acc_breathing_handle_t *handle, acc_detector_presence_result_t *presence_result);
201
202
203 static bool enter_hibernate(acc_sensor_t *sensor);
204
205
206 static bool exit_hibernate(acc_sensor_t *sensor);
207
208
209 static void determine_state(acc_breathing_handle_t *handle, acc_detector_presence_result_t *presence_result);
210
211
212 static void update_presence_distance(acc_breathing_handle_t *handle, float presence_distance);
213
214
215 static bool perform_action_based_on_state(acc_breathing_handle_t *handle, acc_int16_complex_t *frame, acc_breathing_result_t *result);
216
217
218 static bool process_breathing(acc_breathing_handle_t *handle, acc_int16_complex_t *frame, acc_breathing_result_t *result);
219
220
221 static void print_app_state(acc_breathing_handle_t *handle);
222
223
224 static void print_result(acc_breathing_result_t *result);
225
226
227 static bool check_indications(acc_breathing_handle_t *handle, acc_breathing_config_t *config, acc_detector_presence_result_t *presence_result,
228 bool *recalibration_done);
229
230
231 int acconeer_main(int argc, char *argv[]);
232
233
234 int acconeer_main(int argc, char *argv[])
235 {
236 (void)argc;
237 (void)argv;
238 acc_breathing_config_t config = { 0 };
239 acc_breathing_handle_t handle = { 0 };
240
241 printf("Acconeer software version %s\n", acc_version_get());
242
243 const acc_hal_a121_t *hal = acc_hal_rss_integration_get_implementation();
244
245 if (!acc_rss_hal_register(hal))
246 {
247 return EXIT_FAILURE;
248 }
249
250 config.presence_config = acc_detector_presence_config_create();
251 if (config.presence_config == NULL)
252 {
253 printf("acc_config_create() failed\n");
254 cleanup(&handle, &config);
255 return EXIT_FAILURE;
256 }
257
258 set_config(&config, DEFAULT_PRESET_CONFIG);
259
260 if (!validate_config(&config))
261 {
262 printf("Failed to validate config\n");
263 cleanup(&handle, &config);
264 return EXIT_FAILURE;
265 }
266
267 if (!init_handle(&handle, &config))
268 {
269 printf("Failed to initialize handle\n");
270 cleanup(&handle, &config);
271 return EXIT_FAILURE;
272 }
273
274 uint32_t sleep_time_ms = (uint32_t)(1000.0f / handle.frame_rate);
275 acc_integration_set_periodic_wakeup(sleep_time_ms);
276
277 if (!init_sensor_resources(&handle, &config))
278 {
279 printf("Failed to initialize sensor resources\n");
280 cleanup(&handle, &config);
281 return EXIT_FAILURE;
282 }
283
284 acc_breathing_result_t result = { 0 };
285 acc_detector_presence_result_t presence_result = { 0 };
286 bool recalibration_done = false;
287
288 if (!enter_hibernate(handle.sensor))
289 {
290 printf("enter_hibernate failed\n");
291 cleanup(&handle, &config);
292 return EXIT_FAILURE;
293 }
294
295 while (true)
296 {
297 if (!measure(&handle, &presence_result))
298 {
299 cleanup(&handle, &config);
300 return EXIT_FAILURE;
301 }
302
303 if (!check_indications(&handle, &config, &presence_result, &recalibration_done))
304 {
305 cleanup(&handle, &config);
306 return EXIT_FAILURE;
307 }
308
309 if (recalibration_done)
310 {
311 recalibration_done = false;
312 handle.base_presence_dist = false;
313 handle.base_presence_distance = 0.0f;
314 }
315 else
316 {
317 determine_state(&handle, &presence_result);
318
319 update_presence_distance(&handle, presence_result.presence_distance);
320
321 if (!perform_action_based_on_state(&handle, presence_result.processing_result.frame, &result))
322 {
323 cleanup(&handle, &config);
324 return EXIT_FAILURE;
325 }
326
327 if (handle.prev_app_state != handle.app_state)
328 {
329 print_app_state(&handle);
330 }
331
332 print_result(&result);
333 }
334
335 handle.prev_app_state = handle.app_state;
336
337 acc_integration_sleep_until_periodic_wakeup();
338 }
339
340 cleanup(&handle, &config);
341
342 printf("Application finished OK\n");
343
344 return EXIT_SUCCESS;
345 }
346
347
348 static void cleanup(acc_breathing_handle_t *handle, acc_breathing_config_t *config)
349 {
350 acc_sensor_hibernate_off(handle->sensor);
351 acc_hal_integration_sensor_disable(SENSOR_ID);
352 acc_hal_integration_sensor_supply_off(SENSOR_ID);
353
354 if (config->presence_config != NULL)
355 {
356 acc_detector_presence_config_destroy(config->presence_config);
357 }
358
359 if (handle->sensor != NULL)
360 {
361 acc_sensor_destroy(handle->sensor);
362 }
363
364 if (handle->presence_handle != NULL)
365 {
366 acc_detector_presence_destroy(handle->presence_handle);
367 }
368
369 if (handle->buffer != NULL)
370 {
371 acc_integration_mem_free(handle->buffer);
372 }
373
374 if (handle->mean_sweep != NULL)
375 {
376 acc_integration_mem_free(handle->mean_sweep);
377 }
378
379 if (handle->filt_sparse_iq != NULL)
380 {
381 acc_integration_mem_free(handle->filt_sparse_iq);
382 }
383
384 if (handle->sparse_iq_buffer != NULL)
385 {
386 acc_integration_mem_free(handle->sparse_iq_buffer);
387 }
388
389 if (handle->filt_sparse_iq_buffer != NULL)
390 {
391 acc_integration_mem_free(handle->filt_sparse_iq_buffer);
392 }
393
394 if (handle->angle != NULL)
395 {
396 acc_integration_mem_free(handle->angle);
397 }
398
399 if (handle->prev_angle != NULL)
400 {
401 acc_integration_mem_free(handle->prev_angle);
402 }
403
404 if (handle->lp_filt_ampl != NULL)
405 {
406 acc_integration_mem_free(handle->lp_filt_ampl);
407 }
408
409 if (handle->unwrapped_angle != NULL)
410 {
411 acc_integration_mem_free(handle->unwrapped_angle);
412 }
413
414 if (handle->angle_buffer != NULL)
415 {
416 acc_integration_mem_free(handle->angle_buffer);
417 }
418
419 if (handle->filt_angle_buffer != NULL)
420 {
421 acc_integration_mem_free(handle->filt_angle_buffer);
422 }
423
424 if (handle->breathing_motion_buffer != NULL)
425 {
426 acc_integration_mem_free(handle->breathing_motion_buffer);
427 }
428
429 if (handle->hamming_window != NULL)
430 {
431 acc_integration_mem_free(handle->hamming_window);
432 }
433
434 if (handle->windowed_breathing_motion_buffer != NULL)
435 {
436 acc_integration_mem_free(handle->windowed_breathing_motion_buffer);
437 }
438
439 if (handle->rfft_output != NULL)
440 {
441 acc_integration_mem_free(handle->rfft_output);
442 }
443
444 if (handle->weighted_psd != NULL)
445 {
446 acc_integration_mem_free(handle->weighted_psd);
447 }
448 }
449
450
451 static void set_config(acc_breathing_config_t *config, breathing_preset_t preset)
452 {
453 config->time_series_length_s = 20U;
454 config->lowest_breathing_rate = 6U;
455 config->highest_breathing_rate = 60U;
456 config->num_dists_to_analyze = 3U;
457 config->use_presence_processor = true;
458 config->distance_determination_duration_s = 5U;
459
460 acc_detector_presence_config_t *presence_config = config->presence_config;
461
462 acc_detector_presence_config_start_set(presence_config, 0.3f);
463 acc_detector_presence_config_hwaas_set(presence_config, 32U);
464 acc_detector_presence_config_frame_rate_set(presence_config, 10.0f);
465 acc_detector_presence_config_sweeps_per_frame_set(presence_config, 16U);
466 acc_detector_presence_config_auto_profile_set(presence_config, false);
467 acc_detector_presence_config_profile_set(presence_config, ACC_CONFIG_PROFILE_3);
468 acc_detector_presence_config_auto_step_length_set(presence_config, false);
469 acc_detector_presence_config_step_length_set(presence_config, 24U);
470 acc_detector_presence_config_inter_frame_presence_timeout_set(presence_config, 0U);
471 acc_detector_presence_config_inter_frame_fast_cutoff_set(presence_config, 20.0f);
472 acc_detector_presence_config_intra_output_time_const_set(presence_config, 0.5f);
473 acc_detector_presence_config_inter_output_time_const_set(presence_config, 5.0f);
474
475 switch (preset)
476 {
477 case BREATHING_PRESET_NONE:
478 // Add custom configuration of the reference application here
479 break;
480 case BREATHING_PRESET_SITTING:
481 acc_detector_presence_config_end_set(presence_config, 1.5f);
482 acc_detector_presence_config_intra_detection_threshold_set(presence_config, 6.0f);
483 break;
484 case BREATHING_PRESET_INFANT:
485 acc_detector_presence_config_end_set(presence_config, 1.0f);
486 acc_detector_presence_config_intra_detection_threshold_set(presence_config, 4.0f);
487 break;
488 }
489
490 acc_detector_presence_config_frame_rate_app_driven_set(presence_config, true);
491 }
492
493
494 static bool validate_config(acc_breathing_config_t *config)
495 {
496 float frame_rate = acc_detector_presence_config_frame_rate_get(config->presence_config);
497
498 bool status = true;
499
500 if (frame_rate == 0.0f)
501 {
502 printf("Frame rate must be set, i.e. > 0.0\n");
503 status = false;
504 }
505
506 if (config->lowest_breathing_rate >= config->highest_breathing_rate)
507 {
508 printf("Lowest breathing rate must be lower than highest breathing rate\n");
509 status = false;
510 }
511
512 if (config->num_dists_to_analyze < 1U)
513 {
514 printf("Number of distances to analyze must be higher than 1");
515 status = false;
516 }
517
518 return status;
519 }
520
521
522 static bool init_handle(acc_breathing_handle_t *handle, acc_breathing_config_t *config)
523 {
524 handle->frame_rate = acc_detector_presence_config_frame_rate_get(config->presence_config);
525 handle->sweeps_per_frame = acc_detector_presence_config_sweeps_per_frame_get(config->presence_config);
526 handle->intra_detection_threshold = acc_detector_presence_config_intra_detection_threshold_get(config->presence_config);
527
528 acc_detector_presence_metadata_t presence_metadata;
529
530 handle->presence_handle = acc_detector_presence_create(config->presence_config, &presence_metadata);
531
532 if (handle->presence_handle == NULL)
533 {
534 printf("acc_detector_presence_create() failed\n");
535 return false;
536 }
537
538 handle->start_m = presence_metadata.start_m;
539 handle->step_length_m = presence_metadata.step_length_m;
540 handle->num_points = presence_metadata.num_points;
541
542 handle->lowest_freq = (float)config->lowest_breathing_rate / 60.0f;
543 handle->highest_freq = (float)config->highest_breathing_rate / 60.0f;
544 handle->use_presence_processor = config->use_presence_processor;
545 handle->time_series_length_s = config->time_series_length_s;
546 handle->distance_determination_count = config->distance_determination_duration_s * handle->frame_rate;
547 handle->num_points_to_analyze_half_width = config->num_dists_to_analyze / 2U;
548 handle->num_points_to_analyze = config->use_presence_processor ? handle->num_points_to_analyze_half_width * 2U +
549 1U : handle->num_points;
550
551 acc_detector_presence_get_buffer_size(handle->presence_handle, &handle->buffer_size);
552
553 handle->time_series_length = handle->time_series_length_s * handle->frame_rate;
554 handle->padded_time_series_length_shift = 0U;
555 handle->padded_time_series_length = 1U << handle->padded_time_series_length_shift;
556
557 while (handle->padded_time_series_length < handle->time_series_length)
558 {
559 handle->padded_time_series_length_shift++;
560 handle->padded_time_series_length = 1U << handle->padded_time_series_length_shift;
561 }
562
563 handle->rfft_output_length = (handle->padded_time_series_length / 2U) + 1U;
564 handle->distance_determination_counter = 0U;
565 handle->presence_init = false;
566 handle->presence_distance = 0.0f;
567 handle->base_presence_dist = false;
568 handle->base_presence_distance = 0.0f;
569 handle->presence_distance_threshold = acc_algorithm_get_fwhm(acc_detector_presence_config_profile_get(config->presence_config)) *
570 2.0f;
571 handle->first = true;
572 handle->init_count = 0U;
573 handle->count = 0U;
574 handle->initialized = false;
575 handle->presence_sf = acc_algorithm_exp_smoothing_coefficient(handle->frame_rate,
576 (float)config->distance_determination_duration_s / 4.0f);
577 handle->breathing_sf = acc_algorithm_exp_smoothing_coefficient(handle->frame_rate, handle->time_series_length_s / 2.0f);
578
579 handle->app_state = ACC_BREATHING_APP_STATE_INIT;
580 handle->prev_app_state = ACC_BREATHING_APP_STATE_INIT;
581
582 handle->count_limit = handle->time_series_length / 2U;
583
584 acc_algorithm_butter_lowpass(handle->lowest_freq, handle->frame_rate, handle->b_static, handle->a_static);
585 acc_algorithm_butter_bandpass(handle->lowest_freq, handle->highest_freq, handle->frame_rate,
586 handle->b_angle, handle->a_angle);
587
588 handle->buffer = acc_integration_mem_alloc(handle->buffer_size);
589 handle->mean_sweep = acc_integration_mem_alloc(handle->num_points_to_analyze * sizeof(*handle->mean_sweep));
590 handle->filt_sparse_iq = acc_integration_mem_alloc(handle->num_points_to_analyze * sizeof(*handle->filt_sparse_iq));
591 handle->sparse_iq_buffer =
592 acc_integration_mem_alloc(B_STATIC_LENGTH * handle->num_points_to_analyze * sizeof(*handle->sparse_iq_buffer));
593 handle->filt_sparse_iq_buffer = acc_integration_mem_alloc(A_STATIC_LENGTH * handle->num_points_to_analyze *
594 sizeof(*handle->filt_sparse_iq_buffer));
595 handle->angle = acc_integration_mem_alloc(handle->num_points_to_analyze * sizeof(*handle->angle));
596 handle->prev_angle = acc_integration_mem_alloc(handle->num_points_to_analyze * sizeof(*handle->prev_angle));
597 handle->lp_filt_ampl = acc_integration_mem_alloc(handle->num_points_to_analyze * sizeof(*handle->lp_filt_ampl));
598 handle->unwrapped_angle = acc_integration_mem_alloc(handle->num_points_to_analyze * sizeof(*handle->unwrapped_angle));
599 handle->angle_buffer = acc_integration_mem_alloc(B_ANGLE_LENGTH * handle->num_points_to_analyze * sizeof(*handle->angle_buffer));
600 handle->filt_angle_buffer = acc_integration_mem_alloc(
601 A_ANGLE_LENGTH * handle->num_points_to_analyze * sizeof(*handle->filt_angle_buffer));
602 handle->breathing_motion_buffer =
603 acc_integration_mem_alloc(handle->time_series_length * handle->num_points_to_analyze * sizeof(*handle->breathing_motion_buffer));
604 handle->hamming_window = acc_integration_mem_alloc(handle->time_series_length * sizeof(*handle->hamming_window));
605 handle->windowed_breathing_motion_buffer =
606 acc_integration_mem_alloc(handle->time_series_length * handle->num_points_to_analyze *
607 sizeof(*handle->windowed_breathing_motion_buffer));
608 handle->rfft_output = acc_integration_mem_alloc(handle->rfft_output_length * handle->num_points_to_analyze * sizeof(*handle->rfft_output));
609 handle->weighted_psd = acc_integration_mem_alloc(handle->rfft_output_length * sizeof(*handle->weighted_psd));
610
611 bool status = handle->buffer != NULL && handle->mean_sweep != NULL && handle->filt_sparse_iq != NULL &&
612 handle->sparse_iq_buffer != NULL && handle->filt_sparse_iq_buffer != NULL && handle->angle != NULL &&
613 handle->prev_angle != NULL && handle->lp_filt_ampl != NULL && handle->unwrapped_angle != NULL && handle->angle_buffer != NULL &&
614 handle->filt_angle_buffer != NULL && handle->breathing_motion_buffer != NULL && handle->hamming_window != NULL &&
615 handle->windowed_breathing_motion_buffer != NULL && handle->rfft_output != NULL && handle->weighted_psd != NULL;
616
617 if (status)
618 {
619 handle->freq_delta = acc_algorithm_fftfreq_delta(handle->padded_time_series_length, 1.0f / handle->frame_rate);
620 acc_algorithm_hamming(handle->time_series_length, handle->hamming_window);
621 }
622
623 return status;
624 }
625
626
627 static bool init_sensor_resources(acc_breathing_handle_t *handle, acc_breathing_config_t *config)
628 {
629 acc_hal_integration_sensor_supply_on(SENSOR_ID);
630 acc_hal_integration_sensor_enable(SENSOR_ID);
631
632 handle->sensor = acc_sensor_create(SENSOR_ID);
633 if (handle->sensor == NULL)
634 {
635 printf("acc_sensor_create() failed\n");
636 return false;
637 }
638
639 if (!sensor_calibration(handle))
640 {
641 printf("Sensor calibration failed\n");
642 return false;
643 }
644
645 if (!acc_detector_presence_prepare(handle->presence_handle, config->presence_config, handle->sensor, &handle->sensor_cal_result,
646 handle->buffer,
647 handle->buffer_size))
648 {
649 printf("acc_detector_presence_prepare() failed\n");
650 return false;
651 }
652
653 return true;
654 }
655
656
657 static bool sensor_calibration(acc_breathing_handle_t *handle)
658 {
659 bool status = false;
660 bool cal_complete = false;
661 const uint16_t calibration_retries = 1U;
662
663 // Random disturbances may cause the calibration to fail. At failure, retry at least once.
664 for (uint16_t i = 0; !status && (i <= calibration_retries); i++)
665 {
666 // Reset sensor before calibration by disabling/enabling it
667 acc_hal_integration_sensor_disable(SENSOR_ID);
668 acc_hal_integration_sensor_enable(SENSOR_ID);
669
670 do
671 {
672 status = acc_sensor_calibrate(handle->sensor, &cal_complete, &handle->sensor_cal_result, handle->buffer, handle->buffer_size);
673
674 if (status && !cal_complete)
675 {
676 status = acc_hal_integration_wait_for_sensor_interrupt(SENSOR_ID, SENSOR_TIMEOUT_MS);
677 }
678 } while (status && !cal_complete);
679 }
680
681 if (status)
682 {
683 /* Reset sensor after calibration by disabling/enabling it */
684 acc_hal_integration_sensor_disable(SENSOR_ID);
685 acc_hal_integration_sensor_enable(SENSOR_ID);
686 }
687 else
688 {
689 printf("acc_sensor_calibrate() failed\n");
690 acc_sensor_status(handle->sensor);
691 }
692
693 return status;
694 }
695
696
697 static bool reinit_breathing(acc_breathing_handle_t *handle, uint16_t start_point, uint16_t end_point)
698 {
699 handle->start_point = start_point;
700 handle->end_point = end_point;
701 handle->num_points_to_analyze = end_point - start_point;
702
703 handle->first = true;
704 handle->init_count = 0U;
705 handle->count = 0U;
706 handle->initialized = false;
707
708 memset(handle->sparse_iq_buffer, 0, B_STATIC_LENGTH * handle->num_points_to_analyze * sizeof(*handle->sparse_iq_buffer));
709 memset(handle->filt_sparse_iq_buffer, 0, A_STATIC_LENGTH * handle->num_points_to_analyze * sizeof(*handle->filt_sparse_iq_buffer));
710 memset(handle->prev_angle, 0, handle->num_points_to_analyze * sizeof(*handle->prev_angle));
711 memset(handle->lp_filt_ampl, 0, handle->num_points_to_analyze * sizeof(*handle->lp_filt_ampl));
712 memset(handle->unwrapped_angle, 0, handle->num_points_to_analyze * sizeof(*handle->unwrapped_angle));
713 memset(handle->angle_buffer, 0, B_ANGLE_LENGTH * handle->num_points_to_analyze * sizeof(*handle->angle_buffer));
714 memset(handle->filt_angle_buffer, 0, A_ANGLE_LENGTH * handle->num_points_to_analyze * sizeof(*handle->filt_angle_buffer));
715 memset(handle->breathing_motion_buffer, 0,
716 handle->time_series_length * handle->num_points_to_analyze * sizeof(*handle->breathing_motion_buffer));
717
718 return true;
719 }
720
721
722 static bool measure(acc_breathing_handle_t *handle, acc_detector_presence_result_t *presence_result)
723 {
724 if (!exit_hibernate(handle->sensor))
725 {
726 printf("exit_hibernate failed\n");
727 return EXIT_FAILURE;
728 }
729
730 if (!acc_sensor_measure(handle->sensor))
731 {
732 printf("acc_sensor_measure failed\n");
733 acc_sensor_status(handle->sensor);
734 return false;
735 }
736
737 if (!acc_hal_integration_wait_for_sensor_interrupt(SENSOR_ID, SENSOR_TIMEOUT_MS))
738 {
739 printf("Sensor interrupt timeout\n");
740 acc_sensor_status(handle->sensor);
741 return false;
742 }
743
744 if (!acc_sensor_read(handle->sensor, handle->buffer, handle->buffer_size))
745 {
746 printf("acc_sensor_read() failed\n");
747 acc_sensor_status(handle->sensor);
748 return false;
749 }
750
751 if (!enter_hibernate(handle->sensor))
752 {
753 printf("enter_hibernate failed\n");
754 return EXIT_FAILURE;
755 }
756
757 if (!acc_detector_presence_process(handle->presence_handle, handle->buffer, presence_result))
758 {
759 printf("acc_detector_presence_process() failed\n");
760 return false;
761 }
762
763 return true;
764 }
765
766
767 static bool enter_hibernate(acc_sensor_t *sensor)
768 {
769 bool status = true;
770
771 if (!acc_sensor_hibernate_on(sensor))
772 {
773 printf("acc_sensor_hibernate_on failed\n");
774 acc_sensor_status(sensor);
775 status = false;
776 }
777
778 acc_hal_integration_sensor_disable(SENSOR_ID);
779 return status;
780 }
781
782
783 static bool exit_hibernate(acc_sensor_t *sensor)
784 {
785 bool status = true;
786
787 acc_hal_integration_sensor_enable(SENSOR_ID);
788 if (!acc_sensor_hibernate_off(sensor))
789 {
790 printf("acc_sensor_hibernate_off failed\n");
791 acc_sensor_status(sensor);
792 status = false;
793 }
794
795 return status;
796 }
797
798
799 static void determine_state(acc_breathing_handle_t *handle, acc_detector_presence_result_t *presence_result)
800 {
801 if (!presence_result->presence_detected)
802 {
803 handle->app_state = ACC_BREATHING_APP_STATE_NO_PRESENCE;
804 }
805 else if (handle->intra_detection_threshold < presence_result->intra_presence_score)
806 {
807 handle->app_state = ACC_BREATHING_APP_STATE_INTRA_PRESENCE;
808 }
809 else if (!handle->base_presence_dist && handle->use_presence_processor)
810 {
811 handle->app_state = ACC_BREATHING_APP_STATE_DETERMINE_DISTANCE;
812 }
813 else if (!handle->use_presence_processor || handle->distance_determination_count <= handle->distance_determination_counter)
814 {
815 handle->app_state = ACC_BREATHING_APP_STATE_ESTIMATE_BREATHING_RATE;
816 }
817 else
818 {
819 // Do nothing
820 }
821 }
822
823
824 static void update_presence_distance(acc_breathing_handle_t *handle, float presence_distance)
825 {
826 if (!handle->presence_init)
827 {
828 handle->presence_init = true;
829 handle->presence_distance = presence_distance;
830 }
831
832 handle->presence_distance = handle->presence_distance * handle->presence_sf + presence_distance * (1.0f - handle->presence_sf);
833
834 if (handle->base_presence_dist && handle->presence_distance_threshold < fabsf(handle->base_presence_distance - handle->presence_distance))
835 {
836 handle->base_presence_dist = false;
837 handle->base_presence_distance = 0.0f;
838 }
839 }
840
841
842 static bool perform_action_based_on_state(acc_breathing_handle_t *handle, acc_int16_complex_t *frame, acc_breathing_result_t *result)
843 {
844 bool status = true;
845
846 result->result_ready = false;
847
848 switch (handle->app_state)
849 {
850 case ACC_BREATHING_APP_STATE_INIT:
851 // Do nothing
852 break;
853 // No presence and intra presence require the same action
854 case ACC_BREATHING_APP_STATE_NO_PRESENCE:
855 case ACC_BREATHING_APP_STATE_INTRA_PRESENCE:
856 handle->base_presence_dist = false;
857 handle->base_presence_distance = 0.0f;
858 break;
859 case ACC_BREATHING_APP_STATE_DETERMINE_DISTANCE:
860 if (handle->app_state != handle->prev_app_state)
861 {
862 handle->distance_determination_counter = 0U;
863 }
864 else
865 {
866 handle->distance_determination_counter++;
867 handle->base_presence_dist = true;
868 handle->base_presence_distance = handle->presence_distance;
869 }
870
871 break;
872 case ACC_BREATHING_APP_STATE_ESTIMATE_BREATHING_RATE:
873 if (handle->app_state != handle->prev_app_state)
874 {
875 uint16_t start_p;
876 uint16_t end_p;
877
878 if (handle->use_presence_processor)
879 {
880 uint16_t center_idx =
881 (uint16_t)(((handle->base_presence_distance - handle->start_m) / handle->step_length_m) + 0.5f);
882 start_p = center_idx >=
883 handle->num_points_to_analyze_half_width ? (uint16_t)(center_idx -
884 handle->num_points_to_analyze_half_width) : 0U;
885 end_p = (center_idx + handle->num_points_to_analyze_half_width + 1U) <=
886 handle->num_points ? (center_idx + handle->num_points_to_analyze_half_width +
887 1U) : handle->num_points;
888 }
889 else
890 {
891 start_p = 0U;
892 end_p = handle->num_points;
893 }
894
895 reinit_breathing(handle, start_p, end_p);
896 }
897
898 status = process_breathing(handle, frame, result);
899 break;
900 default:
901 // Should never happen
902 break;
903 }
904
905 return status;
906 }
907
908
909 static bool process_breathing(acc_breathing_handle_t *handle, acc_int16_complex_t *frame, acc_breathing_result_t *result)
910 {
911 acc_algorithm_mean_sweep(frame, handle->num_points, handle->sweeps_per_frame, handle->start_point, handle->end_point,
912 handle->mean_sweep);
913
914 acc_algorithm_roll_and_push_f32_complex_matrix(handle->sparse_iq_buffer, B_STATIC_LENGTH, handle->num_points_to_analyze,
915 handle->mean_sweep,
916 true);
917
918 acc_algorithm_apply_filter_complex(handle->a_static, handle->filt_sparse_iq_buffer, A_STATIC_LENGTH, handle->num_points_to_analyze,
919 handle->b_static, handle->sparse_iq_buffer, B_STATIC_LENGTH, handle->num_points_to_analyze,
920 handle->filt_sparse_iq, handle->num_points_to_analyze);
921
922 acc_algorithm_roll_and_push_f32_complex_matrix(handle->filt_sparse_iq_buffer, A_STATIC_LENGTH, handle->num_points_to_analyze,
923 handle->filt_sparse_iq, true);
924
925 for (uint16_t i = 0U; i < handle->num_points_to_analyze; i++)
926 {
927 handle->mean_sweep[i] = handle->mean_sweep[i] - handle->filt_sparse_iq[i];
928 handle->angle[i] = cargf(handle->mean_sweep[i]);
929 }
930
931 if (handle->first)
932 {
933 for (uint16_t i = 0U; i < handle->num_points_to_analyze; i++)
934 {
935 handle->prev_angle[i] = handle->angle[i];
936 handle->lp_filt_ampl[i] = cabsf(handle->mean_sweep[i]);
937 }
938
939 handle->first = false;
940 }
941
942 for (uint16_t i = 0U; i < handle->num_points_to_analyze; i++)
943 {
944 handle->lp_filt_ampl[i] = handle->breathing_sf * handle->lp_filt_ampl[i] + (1.0f - handle->breathing_sf) *
945 cabsf(handle->mean_sweep[i]);
946 }
947
948 for (uint16_t i = 0U; i < handle->num_points_to_analyze; i++)
949 {
950 float angle_diff = handle->angle[i] - handle->prev_angle[i];
951 handle->prev_angle[i] = handle->angle[i];
952
953 if ((float)M_PI < angle_diff)
954 {
955 angle_diff -= 2.0f * (float)M_PI;
956 }
957 else if (angle_diff < -(float)M_PI)
958 {
959 angle_diff += 2.0f * (float)M_PI;
960 }
961
962 handle->unwrapped_angle[i] += angle_diff;
963 }
964
965 acc_algorithm_roll_and_push_f32_matrix(handle->angle_buffer, B_ANGLE_LENGTH, handle->num_points_to_analyze, handle->unwrapped_angle,
966 true);
967
968 acc_algorithm_apply_filter(handle->a_angle, handle->filt_angle_buffer, A_ANGLE_LENGTH, handle->num_points_to_analyze, handle->b_angle,
969 handle->angle_buffer, B_ANGLE_LENGTH, handle->num_points_to_analyze, handle->angle,
970 handle->num_points_to_analyze);
971
972 acc_algorithm_roll_and_push_f32_matrix(handle->filt_angle_buffer, A_ANGLE_LENGTH, handle->num_points_to_analyze, handle->angle, true);
973
974 acc_algorithm_roll_and_push_f32_matrix(handle->breathing_motion_buffer, handle->time_series_length, handle->num_points_to_analyze,
975 handle->angle,
976 false);
977
978 if (handle->init_count > handle->time_series_length)
979 {
980 handle->initialized = true;
981 }
982 else
983 {
984 handle->init_count++;
985 }
986
987 if (handle->time_series_length - handle->count_limit <= handle->count)
988 {
989 handle->count = 0;
990
991 if (handle->initialized)
992 {
993 float lp_filt_ampl_sum = 0U;
994
995 for (uint16_t r = 0U; r < handle->time_series_length; r++)
996 {
997 for (uint16_t c = 0U; c < handle->num_points_to_analyze; c++)
998 {
999 handle->windowed_breathing_motion_buffer[r * handle->num_points_to_analyze +
1000 c] =
1001 handle->breathing_motion_buffer[r * handle->num_points_to_analyze + c] *
1002 handle->hamming_window[r];
1003 lp_filt_ampl_sum += handle->lp_filt_ampl[c];
1004 }
1005 }
1006
1007 acc_algorithm_rfft_matrix(handle->windowed_breathing_motion_buffer, handle->time_series_length,
1008 handle->num_points_to_analyze, handle->padded_time_series_length_shift,
1009 handle->rfft_output, 0U);
1010
1011 for (uint16_t r = 0U; r < handle->rfft_output_length; r++)
1012 {
1013 float sum_psd = 0U;
1014
1015 for (uint16_t c = 0U; c < handle->num_points_to_analyze; c++)
1016 {
1017 sum_psd += cabsf(handle->rfft_output[r * handle->num_points_to_analyze + c]) * handle->lp_filt_ampl[c];
1018 }
1019
1020 handle->weighted_psd[r] = sum_psd / lp_filt_ampl_sum;
1021 }
1022
1023 uint16_t peak_loc = acc_algorithm_argmax(handle->weighted_psd, handle->rfft_output_length);
1024
1025 if (peak_loc > 0U)
1026 {
1027 float freq = acc_algorithm_interpolate_peaks_equidistant(handle->weighted_psd, 0.0f, handle->freq_delta, peak_loc);
1028 result->result_ready = true;
1029 result->breathing_rate = freq * 60.0f;
1030 }
1031 }
1032 }
1033 else
1034 {
1035 handle->count++;
1036 }
1037
1038 return true;
1039 }
1040
1041
1042 static void print_app_state(acc_breathing_handle_t *handle)
1043 {
1044 switch (handle->app_state)
1045 {
1046 case ACC_BREATHING_APP_STATE_INIT:
1047 break;
1048 case ACC_BREATHING_APP_STATE_NO_PRESENCE:
1049 printf("NO_PRESENCE_DETECTED\n");
1050 break;
1051 case ACC_BREATHING_APP_STATE_INTRA_PRESENCE:
1052 printf("INTRA_PRESENCE_DETECTED\n");
1053 break;
1054 case ACC_BREATHING_APP_STATE_DETERMINE_DISTANCE:
1055 printf("DETERMINE_DISTANCE_ESTIMATE\n");
1056 break;
1057 case ACC_BREATHING_APP_STATE_ESTIMATE_BREATHING_RATE:
1058 printf("ESTIMATE_BREATHING_RATE\n");
1059 break;
1060 default:
1061 break;
1062 }
1063 }
1064
1065
1066 static void print_result(acc_breathing_result_t *result)
1067 {
1068 if (result->result_ready)
1069 {
1070 printf("Breaths: %" PRIu16 " bpm\n", (uint16_t)result->breathing_rate);
1071 }
1072 }
1073
1074
1075 static bool check_indications(acc_breathing_handle_t *handle, acc_breathing_config_t *config, acc_detector_presence_result_t *presence_result,
1076 bool *recalibration_done)
1077 {
1078 if (presence_result->processing_result.data_saturated)
1079 {
1080 printf("Data saturated. The detector result is not reliable.\n");
1081 }
1082
1083 if (presence_result->processing_result.frame_delayed)
1084 {
1085 printf("Frame delayed. Could not read data fast enough.\n");
1086 printf("Try lowering the frame rate or call 'acc_sensor_read' more frequently.\n");
1087 }
1088
1089 if (presence_result->processing_result.calibration_needed)
1090 {
1091 printf("Sensor recalibration needed ... \n");
1092
1093 if (!sensor_calibration(handle))
1094 {
1095 printf("Sensor calibration failed\n");
1096 return false;
1097 }
1098
1099 printf("Sensor recalibration done!\n");
1100
1101 // Before measuring again, the sensor needs to be prepared through the detector
1102 if (!acc_detector_presence_prepare(handle->presence_handle, config->presence_config, handle->sensor, &handle->sensor_cal_result,
1103 handle->buffer,
1104 handle->buffer_size))
1105 {
1106 printf("acc_detector_presence_prepare() failed\n");
1107 return false;
1108 }
1109
1110 *recalibration_done = true;
1111 }
1112
1113 return true;
1114 }
acc_breathing_handle_t::angle_buffer
float * angle_buffer
Definition: ref_app_breathing.c:139
acc_breathing_config_t::distance_determination_duration_s
uint16_t distance_determination_duration_s
Definition: ref_app_breathing.c:73
process_breathing
static bool process_breathing(acc_breathing_handle_t *handle, acc_int16_complex_t *frame, acc_breathing_result_t *result)
Definition: ref_app_breathing.c:909
acc_breathing_handle_t::app_state
acc_breathing_app_state_t app_state
Definition: ref_app_breathing.c:120
acc_breathing_handle_t::first
bool first
Definition: ref_app_breathing.c:155
acc_breathing_handle_t::rfft_output_length
uint16_t rfft_output_length
Definition: ref_app_breathing.c:145
acc_breathing_handle_t::buffer
void * buffer
Definition: ref_app_breathing.c:98
acc_breathing_handle_t::buffer_size
uint32_t buffer_size
Definition: ref_app_breathing.c:99
acc_detector_presence_config_sweeps_per_frame_set
void acc_detector_presence_config_sweeps_per_frame_set(acc_detector_presence_config_t *presence_config, uint16_t sweeps_per_frame)
Set the number of sweeps per frame.
ACC_BREATHING_APP_STATE_INIT
@ ACC_BREATHING_APP_STATE_INIT
Definition: ref_app_breathing.c:82
acc_breathing_handle_t::base_presence_distance
float base_presence_distance
Definition: ref_app_breathing.c:153
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:113
acc_algorithm_exp_smoothing_coefficient
float acc_algorithm_exp_smoothing_coefficient(float fs, float tc)
Calculate exponential smoothing coefficient.
Definition: acc_algorithm.c:577
acc_rss_a121.h
BREATHING_PRESET_INFANT
@ BREATHING_PRESET_INFANT
Definition: ref_app_breathing.c:30
acc_detector_presence_prepare
bool acc_detector_presence_prepare(acc_detector_presence_handle_t *presence_handle, acc_detector_presence_config_t *presence_config, acc_sensor_t *sensor, const acc_cal_result_t *cal_result, void *buffer, uint32_t buffer_size)
Prepare the detector to do a measurement.
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:107
acc_detector_presence_destroy
void acc_detector_presence_destroy(acc_detector_presence_handle_t *presence_handle)
Destroy a presence detector identified with the provided handle.
acc_detector_presence_config_hwaas_set
void acc_detector_presence_config_hwaas_set(acc_detector_presence_config_t *presence_config, uint16_t hwaas)
Set the hardware accelerated average samples (HWAAS)
ACC_BREATHING_APP_STATE_DETERMINE_DISTANCE
@ ACC_BREATHING_APP_STATE_DETERMINE_DISTANCE
Definition: ref_app_breathing.c:85
acc_breathing_handle_t::distance_determination_counter
uint16_t distance_determination_counter
Definition: ref_app_breathing.c:149
acc_breathing_config_t::lowest_breathing_rate
uint16_t lowest_breathing_rate
Definition: ref_app_breathing.c:57
acc_breathing_config_t
Breathing application config container.
Definition: ref_app_breathing.c:48
acc_sensor_read
bool acc_sensor_read(const acc_sensor_t *sensor, void *buffer, uint32_t buffer_size)
Read out radar data.
ACC_BREATHING_APP_STATE_ESTIMATE_BREATHING_RATE
@ ACC_BREATHING_APP_STATE_ESTIMATE_BREATHING_RATE
Definition: ref_app_breathing.c:86
acc_version.h
acc_detector_presence_metadata_t::step_length_m
float step_length_m
Definition: acc_detector_presence.h:106
acc_breathing_handle_t::sweeps_per_frame
uint16_t sweeps_per_frame
Definition: ref_app_breathing.c:117
acc_detector_presence_config_auto_profile_set
void acc_detector_presence_config_auto_profile_set(acc_detector_presence_config_t *presence_config, bool enable)
Enable automatic selection of profile based on start point of measurement.
presence_distance
static float presence_distance
Definition: i2c_presence_detector.c:49
acc_breathing_handle_t::b_static
float b_static[(3U)]
Definition: ref_app_breathing.c:126
acc_breathing_handle_t::filt_angle_buffer
float * filt_angle_buffer
Definition: ref_app_breathing.c:140
acc_breathing_handle_t::start_m
float start_m
Definition: ref_app_breathing.c:101
acc_alg_basic_utils.h
acc_int16_complex_t
Data type for interger-based representation of complex numbers.
Definition: acc_definitions_common.h:43
acc_breathing_handle_t::angle
float * angle
Definition: ref_app_breathing.c:135
acc_breathing_handle_t::time_series_length
uint16_t time_series_length
Definition: ref_app_breathing.c:113
acc_breathing_handle_t::filt_sparse_iq_buffer
float complex * filt_sparse_iq_buffer
Definition: ref_app_breathing.c:133
acc_algorithm_interpolate_peaks_equidistant
float acc_algorithm_interpolate_peaks_equidistant(const float *y, float x_start, float x_delta, uint16_t peak_idx)
Interpolate equidistant peaks.
Definition: acc_algorithm.c:255
print_app_state
static void print_app_state(acc_breathing_handle_t *handle)
Definition: ref_app_breathing.c:1042
acc_detector_presence_result_t::processing_result
acc_processing_result_t processing_result
Definition: acc_detector_presence.h:86
acc_cal_result_t
Definition: acc_definitions_a121.h:19
DEFAULT_PRESET_CONFIG
#define DEFAULT_PRESET_CONFIG
Definition: ref_app_breathing.c:38
acc_detector_presence_config_frame_rate_set
void acc_detector_presence_config_frame_rate_set(acc_detector_presence_config_t *presence_config, float frame_rate)
Set the frame rate.
ACC_BREATHING_APP_STATE_INTRA_PRESENCE
@ ACC_BREATHING_APP_STATE_INTRA_PRESENCE
Definition: ref_app_breathing.c:84
acc_breathing_result_t
Breathing application results container.
Definition: ref_app_breathing.c:166
breathing_preset_t
breathing_preset_t
Definition: ref_app_breathing.c:26
set_config
static void set_config(acc_breathing_config_t *config, breathing_preset_t preset)
Definition: ref_app_breathing.c:451
acc_breathing_handle_t::step_length_m
float step_length_m
Definition: ref_app_breathing.c:102
acc_detector_presence_metadata_t::start_m
float start_m
Definition: acc_detector_presence.h:100
BREATHING_PRESET_SITTING
@ BREATHING_PRESET_SITTING
Definition: ref_app_breathing.c:29
acc_breathing_handle_t::num_points
uint16_t num_points
Definition: ref_app_breathing.c:116
determine_state
static void determine_state(acc_breathing_handle_t *handle, acc_detector_presence_result_t *presence_result)
Definition: ref_app_breathing.c:799
ACC_BREATHING_APP_STATE_NO_PRESENCE
@ ACC_BREATHING_APP_STATE_NO_PRESENCE
Definition: ref_app_breathing.c:83
acc_integration.h
acc_breathing_handle_t::presence_distance_threshold
float presence_distance_threshold
Definition: ref_app_breathing.c:154
acc_detector_presence_get_buffer_size
bool acc_detector_presence_get_buffer_size(const acc_detector_presence_handle_t *presence_handle, uint32_t *buffer_size)
Get the buffer size needed for the provided presence detector handle.
acc_breathing_handle_t::init_count
uint16_t init_count
Definition: ref_app_breathing.c:156
enter_hibernate
static bool enter_hibernate(acc_sensor_t *sensor)
Definition: ref_app_breathing.c:767
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:166
acc_detector_presence_result_t::presence_detected
bool presence_detected
Definition: acc_detector_presence.h:55
acc_detector_presence_config_intra_detection_threshold_set
void acc_detector_presence_config_intra_detection_threshold_set(acc_detector_presence_config_t *presence_config, float intra_detection_threshold)
Set the detection threshold for the intra-frame presence detection.
acc_breathing_handle_t::frame_rate
float frame_rate
Definition: ref_app_breathing.c:107
acc_breathing_handle_t::hamming_window
float * hamming_window
Definition: ref_app_breathing.c:142
acc_integration_mem_alloc
void * acc_integration_mem_alloc(size_t size)
Allocate dynamic memory.
Definition: acc_integration_stm32.c:632
acc_breathing_handle_t::padded_time_series_length
uint16_t padded_time_series_length
Definition: ref_app_breathing.c:115
reinit_breathing
static bool reinit_breathing(acc_breathing_handle_t *handle, uint16_t start_point, uint16_t end_point)
Definition: ref_app_breathing.c:697
acc_hal_a121_t
Definition: acc_hal_definitions_a121.h:82
acc_rss_hal_register
bool acc_rss_hal_register(const acc_hal_a121_t *hal)
Register an integration.
acconeer_main
int acconeer_main(int argc, char *argv[])
Assembly test example.
Definition: ref_app_breathing.c:234
acc_integration_set_periodic_wakeup
void acc_integration_set_periodic_wakeup(uint32_t time_msec)
Set up a periodic timer used to wake up the system from sleep.
Definition: acc_integration_stm32.c:531
acc_sensor.h
acc_detector_presence_result_t
Presence detector results container.
Definition: acc_detector_presence.h:50
measure
static bool measure(acc_breathing_handle_t *handle, acc_detector_presence_result_t *presence_result)
Definition: ref_app_breathing.c:722
acc_detector_presence_config_inter_frame_presence_timeout_set
void acc_detector_presence_config_inter_frame_presence_timeout_set(acc_detector_presence_config_t *presence_config, uint16_t inter_frame_presence_timeout)
Set the inter-frame presence timeout in seconds.
acc_algorithm_butter_lowpass
void acc_algorithm_butter_lowpass(float freq, float fs, float *b, float *a)
Design a 2nd order digital Butterworth lowpass filter.
Definition: acc_algorithm.c:263
acc_detector_presence_metadata_t::num_points
uint16_t num_points
Definition: acc_detector_presence.h:113
acc_algorithm_argmax
uint16_t acc_algorithm_argmax(const float *data, uint16_t data_length)
Find index of largest element in the array.
Definition: acc_algorithm.c:227
acc_breathing_handle_t::sensor_cal_result
acc_cal_result_t sensor_cal_result
Definition: ref_app_breathing.c:96
acc_breathing_handle_t::sensor
acc_sensor_t * sensor
Definition: ref_app_breathing.c:95
acc_breathing_handle_t::weighted_psd
float * weighted_psd
Definition: ref_app_breathing.c:146
acc_breathing_handle_t::initialized
bool initialized
Definition: ref_app_breathing.c:158
acc_detector_presence_config_destroy
void acc_detector_presence_config_destroy(acc_detector_presence_config_t *presence_config)
Destroy a presence detector configuration.
acc_detector_presence_metadata_t
Definition: acc_detector_presence.h:93
acc_breathing_handle_t::count
uint16_t count
Definition: ref_app_breathing.c:157
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:142
acc_algorithm_rfft_matrix
void acc_algorithm_rfft_matrix(const float *data, uint16_t rows, uint16_t cols, uint16_t length_shift, float complex *output, uint16_t axis)
1D Fast Fourier Transform for real input matrix
Definition: acc_algorithm.c:474
acc_hal_integration_a121.h
acc_detector_presence_config_end_set
void acc_detector_presence_config_end_set(acc_detector_presence_config_t *presence_config, float end)
Set the end point of measurement interval in meters.
acc_detector_presence_config_intra_output_time_const_set
void acc_detector_presence_config_intra_output_time_const_set(acc_detector_presence_config_t *presence_config, float intra_output_time_const)
Set the time constant for the output in the intra-frame part.
acc_breathing_handle_t::base_presence_dist
bool base_presence_dist
Definition: ref_app_breathing.c:152
acc_sensor_hibernate_off
bool acc_sensor_hibernate_off(const acc_sensor_t *sensor)
Restore sensor after exiting hibernation.
acc_breathing_handle_t::a_static
float a_static[(2U)]
Definition: ref_app_breathing.c:127
acc_version_get
const char * acc_version_get(void)
Get the version of the Acconeer software.
A_ANGLE_LENGTH
#define A_ANGLE_LENGTH
Definition: ref_app_breathing.c:43
printf
#define printf
Definition: printf.h:60
acc_breathing_config_t::time_series_length_s
uint16_t time_series_length_s
Definition: ref_app_breathing.c:53
acc_detector_presence_result_t::intra_presence_score
float intra_presence_score
Definition: acc_detector_presence.h:59
acc_breathing_config_t::use_presence_processor
bool use_presence_processor
Definition: ref_app_breathing.c:69
M_PI
#define M_PI
Definition: acc_alg_basic_utils.h:14
acc_breathing_handle_t::use_presence_processor
uint16_t use_presence_processor
Definition: ref_app_breathing.c:110
validate_config
static bool validate_config(acc_breathing_config_t *config)
Definition: ref_app_breathing.c:494
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:119
acc_hal_definitions_a121.h
acc_breathing_handle_t::prev_app_state
acc_breathing_app_state_t prev_app_state
Definition: ref_app_breathing.c:121
acc_detector_presence_process
bool acc_detector_presence_process(acc_detector_presence_handle_t *presence_handle, void *buffer, acc_detector_presence_result_t *result)
Process the data according to the configuration used in acc_detector_presence_config_create.
acc_detector_presence_config_inter_output_time_const_set
void acc_detector_presence_config_inter_output_time_const_set(acc_detector_presence_config_t *presence_config, float inter_output_time_const)
Set the time constant for the output in the inter-frame part.
acc_breathing_handle_t::presence_sf
float presence_sf
Definition: ref_app_breathing.c:123
B_ANGLE_LENGTH
#define B_ANGLE_LENGTH
Definition: ref_app_breathing.c:42
acc_algorithm_mean_sweep
void acc_algorithm_mean_sweep(const acc_int16_complex_t *frame, uint16_t num_points, uint16_t sweeps_per_frame, uint16_t start_point, uint16_t end_point, float complex *sweep)
Calculate mean sweep of a frame from start_point to end_point.
Definition: acc_algorithm.c:441
acc_breathing_handle_t::breathing_sf
float breathing_sf
Definition: ref_app_breathing.c:124
acc_breathing_handle_t
Breathing application context handle.
Definition: ref_app_breathing.c:93
acc_algorithm_apply_filter
void acc_algorithm_apply_filter(const float *a, const float *filt_data, uint16_t filt_rows, uint16_t filt_cols, const float *b, const float *data, uint16_t data_rows, uint16_t data_cols, float *output, uint16_t output_length)
Apply filter coefficients to filtered data matrix and data matrix.
Definition: acc_algorithm.c:395
acc_algorithm_fftfreq_delta
float acc_algorithm_fftfreq_delta(uint16_t n, float d)
Calculate delta between frequency bins in rfft.
Definition: acc_algorithm.c:532
acc_breathing_handle_t::count_limit
uint16_t count_limit
Definition: ref_app_breathing.c:159
acc_breathing_handle_t::a_angle
float a_angle[(4U)]
Definition: ref_app_breathing.c:129
acc_processing_result_t::frame_delayed
bool frame_delayed
Definition: acc_processing.h:80
acc_processing_result_t::frame
acc_int16_complex_t * frame
Definition: acc_processing.h:91
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:130
B_STATIC_LENGTH
#define B_STATIC_LENGTH
Definition: ref_app_breathing.c:40
acc_breathing_handle_t::filt_sparse_iq
float complex * filt_sparse_iq
Definition: ref_app_breathing.c:134
acc_breathing_handle_t::presence_distance
float presence_distance
Definition: ref_app_breathing.c:151
acc_detector_presence_config_t
struct acc_detector_presence_config acc_detector_presence_config_t
Definition: acc_detector_presence.h:44
acc_breathing_handle_t::presence_handle
acc_detector_presence_handle_t * presence_handle
Definition: ref_app_breathing.c:97
acc_breathing_handle_t::highest_freq
float highest_freq
Definition: ref_app_breathing.c:109
acc_detector_presence_config_sweeps_per_frame_get
uint16_t acc_detector_presence_config_sweeps_per_frame_get(const acc_detector_presence_config_t *presence_config)
Get the number of sweeps per frame.
init_handle
static bool init_handle(acc_breathing_handle_t *handle, acc_breathing_config_t *config)
Definition: ref_app_breathing.c:522
acc_breathing_handle_t::windowed_breathing_motion_buffer
float * windowed_breathing_motion_buffer
Definition: ref_app_breathing.c:143
sensor_calibration
static bool sensor_calibration(acc_breathing_handle_t *handle)
Definition: ref_app_breathing.c:657
acc_sensor_hibernate_on
bool acc_sensor_hibernate_on(acc_sensor_t *sensor)
Prepare sensor for entering hibernation.
acc_breathing_handle_t::rfft_output
float complex * rfft_output
Definition: ref_app_breathing.c:144
acc_breathing_handle_t::sparse_iq_buffer
float complex * sparse_iq_buffer
Definition: ref_app_breathing.c:132
acc_breathing_handle_t::lowest_freq
float lowest_freq
Definition: ref_app_breathing.c:108
acc_breathing_handle_t::end_point
uint16_t end_point
Definition: ref_app_breathing.c:106
acc_sensor_status
void acc_sensor_status(const acc_sensor_t *sensor)
Check the status of the sensor.
acc_breathing_handle_t::unwrapped_angle
float * unwrapped_angle
Definition: ref_app_breathing.c:138
acc_breathing_handle_t::num_points_to_analyze
uint16_t num_points_to_analyze
Definition: ref_app_breathing.c:105
acc_algorithm_roll_and_push_f32_matrix
void acc_algorithm_roll_and_push_f32_matrix(float *data, uint16_t rows, uint16_t cols, const float *column, bool pos_shift)
Roll row elements and push a new column.
Definition: acc_algorithm.c:133
acc_breathing_result_t::breathing_rate
float breathing_rate
Definition: ref_app_breathing.c:175
acc_breathing_handle_t::padded_time_series_length_shift
uint16_t padded_time_series_length_shift
Definition: ref_app_breathing.c:114
acc_algorithm.h
acc_breathing_handle_t::breathing_motion_buffer
float * breathing_motion_buffer
Definition: ref_app_breathing.c:141
acc_breathing_handle_t::time_series_length_s
uint16_t time_series_length_s
Definition: ref_app_breathing.c:112
acc_breathing_handle_t::start_point
int32_t start_point
Definition: ref_app_breathing.c:103
acc_breathing_handle_t::num_points_to_analyze_half_width
uint16_t num_points_to_analyze_half_width
Definition: ref_app_breathing.c:104
acc_detector_presence_config_frame_rate_get
float acc_detector_presence_config_frame_rate_get(const acc_detector_presence_config_t *presence_config)
Get the frame rate.
acc_detector_presence_config_profile_set
void acc_detector_presence_config_profile_set(acc_detector_presence_config_t *presence_config, acc_config_profile_t profile)
Set a profile.
acc_algorithm_get_fwhm
float acc_algorithm_get_fwhm(acc_config_profile_t profile)
Get the envelope Full Width Half Maximum in meters given a profile.
Definition: acc_algorithm.c:632
acc_detector_presence_result_t::presence_distance
float presence_distance
Definition: acc_detector_presence.h:67
acc_integration_mem_free
void acc_integration_mem_free(void *ptr)
Free dynamic memory.
Definition: acc_integration_stm32.c:644
acc_integration_sleep_until_periodic_wakeup
void acc_integration_sleep_until_periodic_wakeup(void)
Put the system in sleep until the periodic timer triggers.
Definition: acc_integration_stm32.c:590
acc_definitions_common.h
acc_detector_presence_create
acc_detector_presence_handle_t * acc_detector_presence_create(acc_detector_presence_config_t *presence_config, acc_detector_presence_metadata_t *metadata)
Create a presence detector with the provided configuration.
acc_detector_presence_config_intra_detection_threshold_get
float acc_detector_presence_config_intra_detection_threshold_get(const acc_detector_presence_config_t *presence_config)
Get the detection threshold for the intra-frame presence detection.
acc_detector_presence_config_profile_get
acc_config_profile_t acc_detector_presence_config_profile_get(const acc_detector_presence_config_t *presence_config)
Get the currently set profile.
acc_algorithm_butter_bandpass
void acc_algorithm_butter_bandpass(float min_freq, float max_freq, float fs, float *b, float *a)
Design a 2nd order digital Butterworth bandpass filter.
Definition: acc_algorithm.c:306
acc_breathing_handle_t::mean_sweep
float complex * mean_sweep
Definition: ref_app_breathing.c:131
acc_processing_result_t::data_saturated
bool data_saturated
Definition: acc_processing.h:76
BREATHING_PRESET_NONE
@ BREATHING_PRESET_NONE
Definition: ref_app_breathing.c:28
acc_detector_presence_handle_t
struct acc_detector_presence_handle acc_detector_presence_handle_t
Definition: acc_detector_presence.h:36
init_sensor_resources
static bool init_sensor_resources(acc_breathing_handle_t *handle, acc_breathing_config_t *config)
Definition: ref_app_breathing.c:627
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.
check_indications
static bool check_indications(acc_breathing_handle_t *handle, acc_breathing_config_t *config, acc_detector_presence_result_t *presence_result, bool *recalibration_done)
Definition: ref_app_breathing.c:1075
acc_breathing_handle_t::lp_filt_ampl
float * lp_filt_ampl
Definition: ref_app_breathing.c:137
acc_detector_presence_config_create
acc_detector_presence_config_t * acc_detector_presence_config_create(void)
Create a configuration for a presence detector.
acc_breathing_config_t::highest_breathing_rate
uint16_t highest_breathing_rate
Definition: ref_app_breathing.c:61
acc_breathing_handle_t::presence_init
bool presence_init
Definition: ref_app_breathing.c:150
acc_detector_presence_config_start_set
void acc_detector_presence_config_start_set(acc_detector_presence_config_t *presence_config, float start)
Set the start point of measurement interval in meters.
ACC_CONFIG_PROFILE_3
@ ACC_CONFIG_PROFILE_3
Definition: acc_definitions_a121.h:44
acc_processing_result_t::calibration_needed
bool calibration_needed
Definition: acc_processing.h:84
acc_breathing_handle_t::b_angle
float b_angle[(5U)]
Definition: ref_app_breathing.c:128
acc_detector_presence.h
acc_breathing_handle_t::distance_determination_count
uint16_t distance_determination_count
Definition: ref_app_breathing.c:111
acc_breathing_handle_t::freq_delta
float freq_delta
Definition: ref_app_breathing.c:147
acc_algorithm_roll_and_push_f32_complex_matrix
void acc_algorithm_roll_and_push_f32_complex_matrix(float complex *data, uint16_t rows, uint16_t cols, const float complex *column, bool pos_shift)
Roll row elements and push a new column.
Definition: acc_algorithm.c:168
acc_sensor_measure
bool acc_sensor_measure(acc_sensor_t *sensor)
Start a radar measurement with previously prepared configuration.
acc_detector_presence_config_auto_step_length_set
void acc_detector_presence_config_auto_step_length_set(acc_detector_presence_config_t *presence_config, bool enable)
Enable automatic selection of step length based on the profile.
acc_breathing_handle_t::intra_detection_threshold
float intra_detection_threshold
Definition: ref_app_breathing.c:118
acc_algorithm_hamming
void acc_algorithm_hamming(uint16_t n, float *window)
Calculate hamming window for a specified number of points.
Definition: acc_algorithm.c:606
acc_algorithm_apply_filter_complex
void acc_algorithm_apply_filter_complex(const float *a, const float complex *filt_data, uint16_t filt_rows, uint16_t filt_cols, const float *b, const float complex *data, uint16_t data_rows, uint16_t data_cols, float complex *output, uint16_t output_length)
Apply filter coefficients to filtered data matrix and data matrix.
Definition: acc_algorithm.c:415
print_result
static void print_result(acc_breathing_result_t *result)
Definition: ref_app_breathing.c:1066
acc_breathing_config_t::num_dists_to_analyze
uint16_t num_dists_to_analyze
Definition: ref_app_breathing.c:65
update_presence_distance
static void update_presence_distance(acc_breathing_handle_t *handle, float presence_distance)
Definition: ref_app_breathing.c:824
exit_hibernate
static bool exit_hibernate(acc_sensor_t *sensor)
Definition: ref_app_breathing.c:783
acc_breathing_handle_t::prev_angle
float * prev_angle
Definition: ref_app_breathing.c:136
acc_breathing_app_state_t
acc_breathing_app_state_t
Definition: ref_app_breathing.c:80
acc_processing.h
acc_sensor_t
struct acc_sensor acc_sensor_t
Definition: acc_sensor.h:31
cleanup
static void cleanup(acc_breathing_handle_t *handle, acc_breathing_config_t *config)
Definition: ref_app_breathing.c:348
acc_detector_presence_config_step_length_set
void acc_detector_presence_config_step_length_set(acc_detector_presence_config_t *presence_config, uint16_t step_length)
Set the step length in points.
SENSOR_ID
#define SENSOR_ID
Definition: ref_app_breathing.c:33
acc_sensor_destroy
void acc_sensor_destroy(acc_sensor_t *sensor)
Destroy a sensor instance freeing any resources allocated.
SENSOR_TIMEOUT_MS
#define SENSOR_TIMEOUT_MS
Definition: ref_app_breathing.c:34
acc_breathing_config_t::presence_config
acc_detector_presence_config_t * presence_config
Definition: ref_app_breathing.c:77
acc_definitions_a121.h
acc_detector_presence_config_frame_rate_app_driven_set
void acc_detector_presence_config_frame_rate_app_driven_set(acc_detector_presence_config_t *presence_config, bool enable)
Set if the application should maintain the requested frame rate.
A_STATIC_LENGTH
#define A_STATIC_LENGTH
Definition: ref_app_breathing.c:41
acc_detector_presence_config_inter_frame_fast_cutoff_set
void acc_detector_presence_config_inter_frame_fast_cutoff_set(acc_detector_presence_config_t *presence_config, float inter_frame_fast_cutoff)
Set the cutoff frequency of the low pass filter for the fast filtered absolute sweep mean.
acc_breathing_result_t::result_ready
bool result_ready
Definition: ref_app_breathing.c:171
perform_action_based_on_state
static bool perform_action_based_on_state(acc_breathing_handle_t *handle, acc_int16_complex_t *frame, acc_breathing_result_t *result)
Definition: ref_app_breathing.c:842
acc_sensor_create
acc_sensor_t * acc_sensor_create(acc_sensor_id_t sensor_id)
Create a sensor instance.