mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-12-23 19:23:09 +00:00
93 lines
3.5 KiB
C
93 lines
3.5 KiB
C
/* 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);
|
|
}
|