sync during ir_recv dev
All checks were successful
Deploy Docs / build-and-deploy (push) Successful in 12s

This commit is contained in:
2026-02-16 17:09:15 +01:00
parent 2a4d007805
commit f012ce9fe0
12 changed files with 83 additions and 38 deletions

View File

@@ -1,5 +1,6 @@
if(CONFIG_IR_RECV)
zephyr_library()
zephyr_sources(src/ir_recv.c)
zephyr_library_sources(src/ir_recv.c)
zephyr_include_directories(include)
zephyr_library_link_libraries_ifdef(CONFIG_NRFX nrfx)
endif()

View File

@@ -1,11 +1,19 @@
menuconfig IR_RECV
bool "IR Receiver"
select ADC
select DMA
help
Enable support for receiving IR signals using the ADC and DMA.
if IR_RECV
config IR_RECV_HW_DEPENDENCIES
bool
default y if !IR_RECV_SIMULATOR
select ADC
select NRFX_GPPI
select NRFX_TIMER
select NRFX_TIMER1
select NRFX_PPI
select NRFX_SAADC
config IR_RECV_SIMULATOR
bool "Enable IR receiver simulator"
select ENTROPY_GENERATOR
@@ -36,4 +44,4 @@ if IR_RECV
module = IR_RECV
module-str = ir_recv
source "subsys/logging/Kconfig.template.log_config"
endif
endif

View File

@@ -167,6 +167,9 @@ K_THREAD_DEFINE(sim_tid, 1024, ir_recv_sim_thread, NULL, NULL, NULL, 5, 0, 0);
#ifndef CONFIG_IR_RECV_SIMULATOR
#include <zephyr/drivers/adc.h>
#include <nrfx_timer.h>
#include <helpers/nrfx_gppi.h>
#include <hal/nrf_saadc.h>
/* ADC-Kanäle dynamisch aus dem DeviceTree (zephyr,user) laden */
static const struct adc_dt_spec adc_channels[] = {
@@ -176,34 +179,61 @@ static const struct adc_dt_spec adc_channels[] = {
ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 3)
};
static void hw_adc_setup(void)
static int hw_adc_setup(void)
{
int err;
for (int i = 0; i < ARRAY_SIZE(adc_channels); i++) {
if (!adc_is_ready_dt(&adc_channels[i])) {
if (err) {
LOG_ERR("ADC controller for channel %d not ready", i);
return;
return err;
}
int err = adc_channel_setup_dt(&adc_channels[i]);
if (err < 0) {
err = adc_channel_setup_dt(&adc_channels[i]);
if (err) {
LOG_ERR("Could not setup channel %d (err: %d)", i, err);
return;
return err;
}
}
LOG_INF("Hardware ADC configured via DeviceTree (EasyDMA Mode).");
LOG_DBG("Hardware ADC configured via DeviceTree (EasyDMA Mode).");
return 0;
}
/* Wir reservieren uns Timer 1 für den ADC-Takt */
static nrfx_timer_t adc_timer = NRFX_TIMER_INSTANCE(1);
void hw_adc_thread(void *p1, void *p2, void *p3)
{
hw_adc_setup();
/* 1. Hardware Timer auf 1 MHz einstellen */
nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG(NRF_TIMER_FREQ_1MHz);
timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
nrfx_timer_init(&adc_timer, &timer_cfg, NULL);
/* Compare-Event bei exakt 75 µs auslösen und Timer danach automatisch nullen */
nrfx_timer_extended_compare(&adc_timer, NRF_TIMER_CC_CHANNEL0, 75,
NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
/* 2. PPI: Verbinde das Timer-Event direkt in Hardware mit dem ADC-Sample-Trigger */
nrfx_gppi_handle_t ppi_handle;
int err = nrfx_gppi_conn_alloc(
nrfx_timer_event_address_get(&adc_timer, NRF_TIMER_EVENT_COMPARE0),
nrf_saadc_task_address_get(NRF_SAADC, NRF_SAADC_TASK_SAMPLE),
&ppi_handle);
if (err != 0) {
LOG_ERR("GPPI connection alloc failed: %d", err);
return;
}
/* Alles einschalten */
nrfx_gppi_conn_enable(ppi_handle);
nrfx_timer_enable(&adc_timer);
/* 3. Zephyr ADC-Sequenz (Ohne Software-Intervall!) */
struct adc_sequence_options options = {
.extra_samplings = SAMPLES_PER_BUFFER - 1,
.interval_us = 0, /* Kontinuierliches Sampling ohne Pause */
.interval_us = 0,
};
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) |
@@ -217,8 +247,11 @@ void hw_adc_thread(void *p1, void *p2, void *p3)
while (1) {
sequence.buffer = adc_buffers[write_idx];
/* Der Pointer adc_channels[0].dev zeigt auf den Haupt-ADC-Controller */
/* Zephyr setzt den DMA-Speicher auf und wartet auf das Ende der 32 Samples.
* Den Startschuss für jedes einzelne Sample feuert ab sofort im Hintergrund
* das PPI-Modul exakt alle 75µs ab. Die CPU schläft hier tief und fest! */
int err = adc_read(adc_channels[0].dev, &sequence);
if (err < 0) {
LOG_ERR("ADC read error: %d", err);
k_msleep(10);
@@ -432,6 +465,14 @@ int ir_recv_init(void)
{
channels[i].state = IR_STATE_IDLE;
}
#ifndef CONFIG_IR_RECV_SIMULATOR
int err = hw_adc_setup();
if (err) {
return err;
}
#endif
LOG_DBG("IR Receiver initialized. Mode: %s",
IS_ENABLED(CONFIG_IR_RECV_SIMULATOR) ? "Simulator" : "Hardware");

View File

@@ -1,5 +1,5 @@
if(CONFIG_IR_SEND)
zephyr_library()
zephyr_sources(src/ir_send.c)
zephyr_library_sources(src/ir_send.c)
zephyr_include_directories(include)
endif()