diff --git a/firmware/apps/_samples/ir_recv_sim/prj.conf b/firmware/apps/_samples/ir_recv_sim/prj.conf index fa27183..672bb38 100644 --- a/firmware/apps/_samples/ir_recv_sim/prj.conf +++ b/firmware/apps/_samples/ir_recv_sim/prj.conf @@ -11,6 +11,15 @@ CONFIG_SHELL_BACKEND_SERIAL=y # Lasertag-spezifische Konfiguration CONFIG_LASERTAG_UTILS=y CONFIG_IR_RECV=y -CONFIG_IR_RECV_LOG_LEVEL_DBG=y +CONFIG_IR_RECV_LOG_LEVEL_INF=y CONFIG_IR_RECV_SIMULATOR=y +# Thread Analyzer aktivieren +CONFIG_THREAD_ANALYZER=y +CONFIG_THREAD_ANALYZER_AUTO=y +CONFIG_THREAD_ANALYZER_AUTO_INTERVAL=5 + +# CPU-Laufzeit-Statistiken aktivieren +CONFIG_THREAD_RUNTIME_STATS=y +CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS=y + diff --git a/firmware/apps/_samples/ir_recv_sim/src/main.c b/firmware/apps/_samples/ir_recv_sim/src/main.c index bfed647..8fb2df7 100644 --- a/firmware/apps/_samples/ir_recv_sim/src/main.c +++ b/firmware/apps/_samples/ir_recv_sim/src/main.c @@ -16,44 +16,16 @@ int main(void) /* Test 1: Perfektes Signal */ LOG_INF("Sending perfect packet..."); test_packet.data.fields.type = 1; - test_packet.data.fields.id = 42; test_packet.data.fields.value = 15; - ir_recv_sim_send_packet(&test_packet, NULL); - - k_msleep(500); - LOG_INF("Sending 1. noisy packet with high jitter..."); - test_packet.data.fields.id = 255; - - ir_sim_error_t ext_error = { - .noise_flips_per_8 = 1, /* Maximal 1 Fehl-Sample pro Block (meist im Space) */ - .jitter_mark = 1, /* Mark: 7 bis 9 Samples */ - .jitter_space_0 = 2, /* Space 0: 6 bis 10 Samples */ - .jitter_space_1 = 2 /* Space 1: 14 bis 18 Samples */ - }; - ir_recv_sim_send_packet(&test_packet, &ext_error); + uint8_t id = 0; - k_msleep(500); - - LOG_INF("Sending 2. noisy packet with high jitter..."); - test_packet.data.fields.id = 255; - - ext_error.noise_flips_per_8 = 2; - ext_error.jitter_mark = 1; - ext_error.jitter_space_0 = 2; - ext_error.jitter_space_1 = 2; - ir_recv_sim_send_packet(&test_packet, &ext_error); - - k_msleep(500); - - LOG_INF("Sending 3. noisy packet with high jitter..."); - test_packet.data.fields.id = 255; - - ext_error.noise_flips_per_8 = 1; - ext_error.jitter_mark = 2; - ext_error.jitter_space_0 = 2; - ext_error.jitter_space_1 = 4; - ir_recv_sim_send_packet(&test_packet, &ext_error); + for(;;) + { + test_packet.data.fields.id = id++; + ir_recv_sim_send_packet(&test_packet, NULL); + k_sleep(K_MSEC(300)); + } return 0; } \ No newline at end of file diff --git a/firmware/libs/ir/recv/src/ir_recv.c b/firmware/libs/ir/recv/src/ir_recv.c index 9131be5..6c44863 100644 --- a/firmware/libs/ir/recv/src/ir_recv.c +++ b/firmware/libs/ir/recv/src/ir_recv.c @@ -25,6 +25,8 @@ static struct k_sem adc_sem; #ifdef CONFIG_IR_RECV_SIMULATOR #include +K_SEM_DEFINE(sim_start_sem, 0, 1); + #define SIM_MAX_SAMPLES 1000 static bool sim_buffer[SIM_MAX_SAMPLES]; static uint32_t sim_total_samples = 0; @@ -114,6 +116,10 @@ void ir_recv_sim_send_packet(ir_packet_t *packet, ir_sim_error_t *err) sim_sample_pos = 0; sim_trigger = true; + sim_sample_pos = 0; + sim_trigger = true; + k_sem_give(&sim_start_sem); + LOG_DBG("Simulator: Queued (Type: %u, CRC: 0x%02X), Total Samples: %u", pkt.data.fields.type, pkt.data.fields.crc, sim_total_samples); } @@ -122,6 +128,11 @@ void ir_recv_sim_thread(void *p1, void *p2, void *p3) { while (1) { + if (!sim_trigger) + { + k_sem_take(&sim_start_sem, K_FOREVER); + } + k_usleep(75 * SAMPLES_PER_BUFFER); if (!sim_trigger) continue; @@ -152,7 +163,75 @@ void ir_recv_sim_thread(void *p1, void *p2, void *p3) } } K_THREAD_DEFINE(sim_tid, 1024, ir_recv_sim_thread, NULL, NULL, NULL, 5, 0, 0); -#endif +#endif // CONFIG_IR_RECV_SIMULATOR + +#ifndef CONFIG_IR_RECV_SIMULATOR +#include + +/* ADC-Kanäle dynamisch aus dem DeviceTree (zephyr,user) laden */ +static const struct adc_dt_spec adc_channels[] = { + ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 0), + ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 1), + ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 2), + ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 3) +}; + +static void hw_adc_setup(void) +{ + for (int i = 0; i < ARRAY_SIZE(adc_channels); i++) { + if (!adc_is_ready_dt(&adc_channels[i])) { + LOG_ERR("ADC controller for channel %d not ready", i); + return; + } + int err = adc_channel_setup_dt(&adc_channels[i]); + if (err < 0) { + LOG_ERR("Could not setup channel %d (err: %d)", i, err); + return; + } + } + LOG_INF("Hardware ADC configured via DeviceTree (EasyDMA Mode)."); +} + +void hw_adc_thread(void *p1, void *p2, void *p3) +{ + hw_adc_setup(); + + struct adc_sequence_options options = { + .extra_samplings = SAMPLES_PER_BUFFER - 1, + .interval_us = 0, /* Kontinuierliches Sampling ohne Pause */ + }; + + struct adc_sequence sequence = { + .options = &options, + /* Dynamische Maske aus den geladenen DeviceTree-Spezifikationen */ + .channels = BIT(adc_channels[0].channel_id) | + BIT(adc_channels[1].channel_id) | + BIT(adc_channels[2].channel_id) | + BIT(adc_channels[3].channel_id), + .buffer_size = SAMPLES_PER_BUFFER * ADC_CHANNELS * sizeof(int16_t), + .resolution = adc_channels[0].resolution, + .oversampling = 0, + .calibrate = false, + }; + + while (1) { + sequence.buffer = adc_buffers[write_idx]; + + /* Der Pointer adc_channels[0].dev zeigt auf den Haupt-ADC-Controller */ + int err = adc_read(adc_channels[0].dev, &sequence); + if (err < 0) { + LOG_ERR("ADC read error: %d", err); + k_msleep(10); + continue; + } + + write_idx = (write_idx + 1) % BUFFER_COUNT; + k_sem_give(&adc_sem); + } +} +K_THREAD_DEFINE(hw_adc_tid, 1024, hw_adc_thread, NULL, NULL, NULL, 5, 0, 0); + +#endif // !CONFIG_IR_RECV_SIMULATOR typedef enum {