Skip to content
Open

2.2.3 #170

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ccfc3e5
draft: decimation filter
Dec 9, 2025
7ba6169
draft: decimation filter q15
Dec 10, 2025
fc44bde
draft: fix coefficients
Dec 10, 2025
4d1884b
draft: f32 for stereo
Dec 10, 2025
7681806
draft: cascaded decimator
Dec 10, 2025
ab87053
draft: enable downsampling make configurable via App
Dec 10, 2025
a63d37d
draft: no decimator option
Dec 10, 2025
089ea92
fix decimation factor 1
Dec 11, 2025
a6da0bd
src/audio/audio_datapath.c: stop micro correctly
Dec 11, 2025
c870162
fix: sd card crash at the end of the recording
Dec 16, 2025
7644454
fix: add mutex to decimator to prevent crash at end of recording
Dec 22, 2025
405a46c
src/SD_Card/SDLogger/SDLogger.cpp: reset signal state properly
DennisMoschina Jan 30, 2026
a9a35d5
src/audio/audio_datapath.c: removed k_poll_signal_check to avoid dead…
DennisMoschina Jan 30, 2026
f4259d8
src/SensorManager/Microphone.cpp: fixed printing mic sampling rate wr…
DennisMoschina Jan 30, 2026
f642a94
src/SD_Card/SDLogger.cpp: make sure the logger event is reset correctly
DennisMoschina Feb 4, 2026
e287241
src/SD_Card/SDLogger.cpp: allow writing multiple blocks at once, only…
DennisMoschina Feb 4, 2026
8e4ceff
feat(version): introduce automatic semantic versioning
DennisMoschina Mar 4, 2026
f4d892a
enable audio streaming
o-bagge Jan 30, 2026
8fdc81e
remove no streaming comment
o-bagge Feb 2, 2026
7e0331c
fix(sensor): enhance GATT notification handling with context management
DennisMoschina Apr 21, 2026
6f021cf
fix(sensor): improve notification context management with spinlock pr…
DennisMoschina Apr 21, 2026
2c2b0db
chore(VERSION): updated patch level
DennisMoschina Apr 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
VERSION_MAJOR = 2
VERSION_MINOR = 2
PATCHLEVEL = 2
PATCHLEVEL = 3
VERSION_TWEAK = 0
EXTRAVERSION =
8 changes: 4 additions & 4 deletions src/ParseInfo/DefaultSensors.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,11 @@ SensorScheme defaultSensors[SENSOR_COUNT] = {
.groupCount = MICRO_GROUP_COUNT,
.groups = microGroups,
.configOptions = {
.availableOptions = DATA_STORAGE | FREQUENCIES_DEFINED, // no streaming
.availableOptions = DATA_STREAMING | DATA_STORAGE | FREQUENCIES_DEFINED,
.frequencyOptions = {
.frequencyCount = sizeof(Microphone::sample_rates.reg_vals),
.defaultFrequencyIndex = 1,
.maxBleFrequencyIndex = 1,
.defaultFrequencyIndex = 0,
.maxBleFrequencyIndex = 0,
.frequencies = Microphone::sample_rates.sample_rates,
},
},
Expand All @@ -159,7 +159,7 @@ SensorScheme defaultSensors[SENSOR_COUNT] = {
.availableOptions = DATA_STREAMING | DATA_STORAGE | FREQUENCIES_DEFINED,
.frequencyOptions = {
.frequencyCount = sizeof(PPG::sample_rates.reg_vals),
.defaultFrequencyIndex = 2,
.defaultFrequencyIndex = 1,
.maxBleFrequencyIndex = 12,
.frequencies = PPG::sample_rates.sample_rates,
},
Expand Down
25 changes: 15 additions & 10 deletions src/SD_Card/SDLogger/SDLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ void sd_listener_callback(const struct zbus_channel *chan)
}
}

inline void reset_logger_signal() {
k_poll_signal_reset(&logger_sig);
logger_evt.state = K_POLL_STATE_NOT_READY;
}

void SDLogger::sensor_sd_task() {
int ret;
Expand All @@ -112,7 +116,7 @@ void SDLogger::sensor_sd_task() {

// If a close/flush is in progress, do not write concurrently.
if (atomic_get(&g_stop_writing)) {
k_poll_signal_reset(&logger_sig);
reset_logger_signal();
continue;
}

Expand All @@ -122,7 +126,7 @@ void SDLogger::sensor_sd_task() {
ring_buf_reset(&ring_buffer);
k_mutex_unlock(&ring_mutex);
sdlogger.is_open = false;
k_poll_signal_reset(&logger_sig);
reset_logger_signal();
continue;
}

Expand All @@ -143,12 +147,12 @@ void SDLogger::sensor_sd_task() {

// Claim up to one SD block from the ring buffer under lock.
k_mutex_lock(&ring_mutex, K_FOREVER);
uint32_t claimed = ring_buf_get_claim(&ring_buffer, &data, SD_BLOCK_SIZE);
uint32_t claimed = ring_buf_get_claim(&ring_buffer, &data, fill - (fill % SD_BLOCK_SIZE));
k_mutex_unlock(&ring_mutex);

if (claimed == 0 || data == nullptr) {
// Nothing to write right now.
k_poll_signal_reset(&logger_sig);
reset_logger_signal();
continue;
}

Expand All @@ -165,7 +169,7 @@ void SDLogger::sensor_sd_task() {

// Do not advance the ring buffer on error.
// Wakeups will continue; user can call end().
k_poll_signal_reset(&logger_sig);
reset_logger_signal();
continue;
}

Expand All @@ -177,7 +181,7 @@ void SDLogger::sensor_sd_task() {
k_yield();
}

k_poll_signal_reset(&logger_sig);
reset_logger_signal();

STACK_USAGE_PRINT("sensor_msg_thread", &sdlogger.thread_data);
}
Expand Down Expand Up @@ -354,7 +358,9 @@ int SDLogger::write_sensor_data(const void* const* data_blocks, const size_t* le

k_mutex_unlock(&ring_mutex);

k_poll_signal_raise(&logger_sig, 0);
if (ring_buf_size_get(&ring_buffer) >= SD_BLOCK_SIZE) {
k_poll_signal_raise(&logger_sig, 0);
}
return 0;
}

Expand Down Expand Up @@ -422,7 +428,6 @@ int SDLogger::end() {
}

if (!sd_card->is_mounted()) {
//k_poll_signal_reset(&logger_sig);
is_open = false;
return -ENODEV;
}
Expand All @@ -445,13 +450,13 @@ int SDLogger::end() {
ret = sd_card->close_file();
k_mutex_unlock(&file_mutex);
if (ret < 0) {
k_poll_signal_reset(&logger_sig);
reset_logger_signal();
return ret;
}

is_open = false;

k_poll_signal_reset(&logger_sig);
reset_logger_signal();
atomic_clear(&g_stop_writing);
atomic_clear(&g_sd_removed);

Expand Down
20 changes: 13 additions & 7 deletions src/SensorManager/Microphone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,18 @@ extern void empty_fifo();
#endif

#include <zephyr/logging/log.h>
//LOG_MODULE_DECLARE(BMX160);
LOG_MODULE_REGISTER(microphone, CONFIG_LOG_DEFAULT_LEVEL);

extern struct data_fifo fifo_rx;

Microphone Microphone::sensor;

const SampleRateSetting<1> Microphone::sample_rates = {
{ 0 },
const SampleRateSetting<9> Microphone::sample_rates = {
{ 1, 2, 3, 4, 6, 8, 12, 16, 24 },

{ 48000 },
{ 48000, 24000, 16000, 12000, 8000, 6000, 4000, 3000, 2000 },

{ 48000.0 }
{ 48000.0, 24000.0, 16000.0, 12000.0, 8000.0, 6000.0, 4000.0, 3000.0, 2000.0 }
};

bool Microphone::init(struct k_msgq * queue) {
Expand All @@ -55,16 +54,21 @@ bool Microphone::init(struct k_msgq * queue) {
}

void Microphone::start(int sample_rate_idx) {
ARG_UNUSED(sample_rate_idx);
//ARG_UNUSED(sample_rate_idx);

int ret;

if (!_active) return;

record_to_sd(true);
LOG_INF("Starting Microphone at %f Hz", sample_rates.sample_rates[sample_rate_idx]);
record_to_sd(_sd_logging);

audio_datapath_aquire(&fifo_rx);

audio_datapath_decimator_init(sample_rates.reg_vals[sample_rate_idx]);

record_to_sd(true);

_running = true;
}

Expand All @@ -78,5 +82,7 @@ void Microphone::stop() {

audio_datapath_release();

//audio_datapath_decimator_cleanup();

_running = false;
}
2 changes: 1 addition & 1 deletion src/SensorManager/Microphone.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Microphone : public EdgeMlSensor {
void start(int sample_rate_idx) override;
void stop() override;

const static SampleRateSetting<1> sample_rates;
const static SampleRateSetting<9> sample_rates;
private:
bool _active = false;
};
Expand Down
6 changes: 6 additions & 0 deletions src/SensorManager/SensorManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <string>
#include <set>

#include "audio_datapath.h"

#include <sensor_service.h>

#include <zephyr/logging/log.h>
Expand Down Expand Up @@ -128,6 +130,10 @@ void stop_sensor_manager() {

LOG_DBG("Stopping sensor manager");

// Stop audio recording/processing first to prevent race condition
//extern "C" void audio_datapath_stop_recording(void);
audio_datapath_stop_recording();

Baro::sensor.stop();
IMU::sensor.stop();
PPG::sensor.stop();
Expand Down
2 changes: 2 additions & 0 deletions src/audio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ target_sources(app PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/audio_datapath.c
${CMAKE_CURRENT_SOURCE_DIR}/sw_codec_select.c
${CMAKE_CURRENT_SOURCE_DIR}/le_audio_rx.c
${CMAKE_CURRENT_SOURCE_DIR}/decimation_filter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/audio_datapath_decimator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sdlogger_wrapper.cpp
# ${CMAKE_CURRENT_SOURCE_DIR}/rx_publish.c
# ${CMAKE_CURRENT_SOURCE_DIR}/pdm_mic.c
Expand Down
66 changes: 45 additions & 21 deletions src/audio/audio_datapath.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

#include "Equalizer.h"
#include "sdlogger_wrapper.h"
#include "decimation_filter.h"
#include "arm_math.h"

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(audio_datapath, CONFIG_AUDIO_DATAPATH_LOG_LEVEL);
Expand Down Expand Up @@ -193,6 +195,9 @@ int _count = 0;
extern struct k_poll_signal encoder_sig;
extern struct k_poll_event logger_sig;

/* Decimation buffer for SD card logging */
static int16_t decimated_audio[BLOCK_SIZE_BYTES / sizeof(int16_t) / 4]; /* /4 for decimation factor 4 */

// Funktion für den neuen Thread
static void data_thread(void *arg1, void *arg2, void *arg3)
{
Expand All @@ -219,36 +224,47 @@ static void data_thread(void *arg1, void *arg2, void *arg3)

data_fifo_block_free(ctrl_blk.in.fifo, tmp_pcm_raw_data[i]);

unsigned int logger_signaled;

if (_record_to_sd) {
/* Decimate audio data from 48kHz to the desired sampling rate */
int16_t *audio_block = (int16_t *)(audio_item.data + (i * BLOCK_SIZE_BYTES));
uint32_t num_frames = BLOCK_SIZE_BYTES / sizeof(int16_t) / 2; /* stereo frames */

int decimated_frames = audio_datapath_decimator_process(audio_block, decimated_audio, num_frames);

// If decimator returns 0 frames (e.g. during cleanup), skip processing
if (decimated_frames <= 0) {
continue;
}

struct sensor_msg audio_msg;

audio_msg.sd = true;
audio_msg.stream = false;

audio_msg.data.id = ID_MICRO;
audio_msg.data.size = BLOCK_SIZE_BYTES; // SENQUEUE_FRAME_SIZE;
audio_msg.data.time = time_stamp;

/*k_mutex_lock(&write_mutex, K_FOREVER);

uint32_t data_size = sizeof(audio_msg.data.id) + sizeof(audio_msg.data.size) + sizeof(audio_msg.data.time); // + audio_msg.data.size;
audio_msg.data.size = decimated_frames * 2 * sizeof(int16_t);

uint32_t bytes_written = ring_buf_put(&ring_buffer, (uint8_t *) &audio_msg.data, data_size);
bytes_written += ring_buf_put(&ring_buffer, audio_item.data + (i * BLOCK_SIZE_BYTES), BLOCK_SIZE_BYTES);

k_mutex_unlock(&write_mutex);*/

uint32_t data_size[2] = {sizeof(audio_msg.data.id) + sizeof(audio_msg.data.size) + sizeof(audio_msg.data.time), BLOCK_SIZE_BYTES};
uint32_t data_size[2] = {
sizeof(audio_msg.data.id) + sizeof(audio_msg.data.size) + sizeof(audio_msg.data.time),
audio_msg.data.size
};

const void *data_ptrs[2] = {
void *data_ptrs[2] = {
&audio_msg.data,
audio_item.data + (i * BLOCK_SIZE_BYTES)
decimated_audio
};

sdlogger_write_data(&data_ptrs, data_size, 2);

//sdlogger_write_data(&audio_msg.data, data_size);
//sdlogger_write_data(audio_item.data + (i * BLOCK_SIZE_BYTES), BLOCK_SIZE_BYTES);
if (decimated_frames == num_frames) {
data_ptrs[1] = audio_block;
}

if (decimated_frames > 0) {
sdlogger_write_data(&data_ptrs, data_size, 2);
}
}

k_yield();
Expand All @@ -266,11 +282,6 @@ static void data_thread(void *arg1, void *arg2, void *arg3)
}
}

/*void set_ring_buffer(struct ring_buf *buf)
{
ring_buffer = buf;
}*/

void set_sensor_queue(struct k_msgq *queue)
{
sensor_queue = queue;
Expand All @@ -281,6 +292,13 @@ void record_to_sd(bool active) {
_record_to_sd = active;
}

void audio_datapath_stop_recording(void) {
// Stop SD recording
_record_to_sd = false;

LOG_DBG("Audio recording stopped safely");
}

// Funktion, um den neuen Thread zu starten
void start_data_thread(void)
{
Expand Down Expand Up @@ -634,6 +652,9 @@ static void tone_stop_worker(struct k_work *work)
tone_active = false;
memset(test_tone_buf, 0, sizeof(test_tone_buf));
LOG_DBG("Tone stopped");

struct sensor_config mic = {ID_MICRO, 0, 0};
config_sensor(&mic);
}

K_WORK_DEFINE(tone_stop_work, tone_stop_worker);
Expand Down Expand Up @@ -1202,6 +1223,9 @@ int audio_datapath_stop(void)

data_fifo_empty(ctrl_blk.in.fifo);

/* Cleanup CascadedDecimator on stop */
audio_datapath_decimator_cleanup();

return 0;
} else {
return -EALREADY;
Expand Down
Loading
Loading