raw_samples.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
  2. * See the LICENSE file for information about the license. */
  3. #include <inttypes.h>
  4. #include <furi/core/string.h>
  5. #include <furi.h>
  6. #include <furi_hal.h>
  7. #include "raw_samples.h"
  8. /* Allocate and initialize a samples buffer. */
  9. RawSamplesBuffer* raw_samples_alloc(void) {
  10. RawSamplesBuffer* buf = malloc(sizeof(*buf));
  11. buf->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  12. raw_samples_reset(buf);
  13. return buf;
  14. }
  15. /* Free a sample buffer. Should be called when the mutex is released. */
  16. void raw_samples_free(RawSamplesBuffer* s) {
  17. furi_mutex_free(s->mutex);
  18. free(s);
  19. }
  20. /* This just set all the samples to zero and also resets the internal
  21. * index. There is no need to call it after raw_samples_alloc(), but only
  22. * when one wants to reset the whole buffer of samples. */
  23. void raw_samples_reset(RawSamplesBuffer* s) {
  24. furi_mutex_acquire(s->mutex, FuriWaitForever);
  25. s->total = RAW_SAMPLES_NUM;
  26. s->idx = 0;
  27. s->short_pulse_dur = 0;
  28. memset(s->samples, 0, sizeof(s->samples));
  29. furi_mutex_release(s->mutex);
  30. }
  31. /* Set the raw sample internal index so that what is currently at
  32. * offset 'offset', will appear to be at 0 index. */
  33. void raw_samples_center(RawSamplesBuffer* s, uint32_t offset) {
  34. s->idx = (s->idx + offset) % RAW_SAMPLES_NUM;
  35. }
  36. /* Add the specified sample in the circular buffer. */
  37. void raw_samples_add(RawSamplesBuffer* s, bool level, uint32_t dur) {
  38. furi_mutex_acquire(s->mutex, FuriWaitForever);
  39. s->samples[s->idx].level = level;
  40. s->samples[s->idx].dur = dur;
  41. s->idx = (s->idx + 1) % RAW_SAMPLES_NUM;
  42. furi_mutex_release(s->mutex);
  43. }
  44. /* This is like raw_samples_add(), however in case a sample of the
  45. * same level of the previous one is added, the duration of the last
  46. * sample is updated instead. Needed mainly for the decoders build_message()
  47. * methods: it is simpler to write an encoder of a signal like that,
  48. * just creating messages piece by piece.
  49. *
  50. * This function is a bit slower so the internal data sampling should
  51. * be performed with raw_samples_add(). */
  52. void raw_samples_add_or_update(RawSamplesBuffer* s, bool level, uint32_t dur) {
  53. furi_mutex_acquire(s->mutex, FuriWaitForever);
  54. uint32_t previdx = (s->idx - 1) % RAW_SAMPLES_NUM;
  55. if(s->samples[previdx].level == level && s->samples[previdx].dur != 0) {
  56. /* Update the last sample: it has the same level. */
  57. s->samples[previdx].dur += dur;
  58. } else {
  59. /* Add a new sample. */
  60. s->samples[s->idx].level = level;
  61. s->samples[s->idx].dur = dur;
  62. s->idx = (s->idx + 1) % RAW_SAMPLES_NUM;
  63. }
  64. furi_mutex_release(s->mutex);
  65. }
  66. /* Get the sample from the buffer. It is possible to use out of range indexes
  67. * as 'idx' because the modulo operation will rewind back from the start. */
  68. void raw_samples_get(RawSamplesBuffer* s, uint32_t idx, bool* level, uint32_t* dur) {
  69. furi_mutex_acquire(s->mutex, FuriWaitForever);
  70. idx = (s->idx + idx) % RAW_SAMPLES_NUM;
  71. *level = s->samples[idx].level;
  72. *dur = s->samples[idx].dur;
  73. furi_mutex_release(s->mutex);
  74. }
  75. /* Copy one buffer to the other, including current index. */
  76. void raw_samples_copy(RawSamplesBuffer* dst, RawSamplesBuffer* src) {
  77. furi_mutex_acquire(src->mutex, FuriWaitForever);
  78. furi_mutex_acquire(dst->mutex, FuriWaitForever);
  79. dst->idx = src->idx;
  80. dst->short_pulse_dur = src->short_pulse_dur;
  81. memcpy(dst->samples, src->samples, sizeof(dst->samples));
  82. furi_mutex_release(src->mutex);
  83. furi_mutex_release(dst->mutex);
  84. }