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