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 15:06:27 +01:00
parent 8d97a5d33f
commit 480baa97fa
2 changed files with 117 additions and 102 deletions

View File

@@ -13,24 +13,25 @@ int main(void)
ir_packet_t test_packet = {0};
/* 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(100);
k_msleep(1000);
LOG_INF("Sending noisy packet with high jitter...");
test_packet.data.fields.id = 255;
ir_sim_error_t ext_error = {
.noise_flips_per_8 = 1, /* 2 von 8 Samples pro Block sind falsch */
.jitter_mark = 1, /* Mark schwankt zwischen 6 und 10 Samples */
.jitter_space_0 = 1, /* Space0 schwankt zwischen 4 und 12 Samples */
.jitter_space_1 = 1 /* Space1 schwankt zwischen 14 und 18 Samples */
.noise_flips_per_8 = 2, /* 2 von 8 Samples pro Block sind falsch */
.jitter_mark = 2, /* Mark schwankt zwischen 6 und 10 Samples */
.jitter_space_0 = 4, /* Space0 schwankt zwischen 4 und 12 Samples */
.jitter_space_1 = 2 /* Space1 schwankt zwischen 14 und 18 Samples */
};
ir_recv_sim_send_packet(&test_packet, &ext_error);
ir_recv_sim_send_packet(&test_packet, NULL);//&ext_error);
return 0;
}

View File

@@ -34,107 +34,122 @@ static uint32_t sim_sample_pos = 0;
/* Hilfsfunktion für den Jitter: Liefert einen Zufallswert zwischen -max und +max */
static int get_jitter(uint8_t max_jitter)
{
if (max_jitter == 0) return 0;
return (int)(sys_rand32_get() % (max_jitter * 2 + 1)) - max_jitter;
if (max_jitter == 0)
return 0;
return (int)(sys_rand32_get() % (max_jitter * 2 + 1)) - max_jitter;
}
void ir_recv_sim_send_packet(ir_packet_t *packet, ir_sim_error_t *err)
{
/* Blockieren, bis vorheriges Paket abgearbeitet ist */
while (sim_trigger) {
k_msleep(5);
}
/* Blockieren, bis vorheriges Paket abgearbeitet ist */
while (sim_trigger)
{
k_msleep(5);
}
ir_packet_t pkt;
memcpy(&pkt, packet, sizeof(ir_packet_t));
pkt.data.fields.crc = lastertag_crc8(pkt.data.bytes, 2);
ir_packet_t pkt;
memcpy(&pkt, packet, sizeof(ir_packet_t));
pkt.data.fields.crc = lastertag_crc8(pkt.data.bytes, 2);
ir_sim_error_t default_err = {0};
if (err == NULL) {
err = &default_err;
}
ir_sim_error_t default_err = {0};
if (err == NULL)
{
err = &default_err;
}
sim_total_samples = 0;
sim_total_samples = 0;
/* 1. Header Mark */
int m_len = 32 + get_jitter(err->jitter_mark);
for (int i = 0; i < m_len && sim_total_samples < SIM_MAX_SAMPLES; i++) {
sim_buffer[sim_total_samples++] = 1;
}
/* 1. Header Mark */
int m_len = 32 + get_jitter(err->jitter_mark);
for (int i = 0; i < m_len && sim_total_samples < SIM_MAX_SAMPLES; i++)
{
sim_buffer[sim_total_samples++] = 1;
}
/* 2. Header Gap */
int g_len = 8 + get_jitter(err->jitter_space_0);
for (int i = 0; i < g_len && sim_total_samples < SIM_MAX_SAMPLES; i++) {
sim_buffer[sim_total_samples++] = 0;
}
/* 2. Header Gap */
int g_len = 8 + get_jitter(err->jitter_space_0);
for (int i = 0; i < g_len && sim_total_samples < SIM_MAX_SAMPLES; i++)
{
sim_buffer[sim_total_samples++] = 0;
}
/* 3. Payload Bits (24 Bit) */
for (int i = 0; i < 24; i++) {
bool bit = (pkt.data.bytes[i / 8] >> (i % 8)) & 1;
/* Space Phase */
int s_base = bit ? 16 : 8;
int s_jit = bit ? get_jitter(err->jitter_space_1) : get_jitter(err->jitter_space_0);
int s_len = s_base + s_jit;
for (int j = 0; j < s_len && sim_total_samples < SIM_MAX_SAMPLES; j++) {
sim_buffer[sim_total_samples++] = 0;
}
/* Mark Phase */
int bm_len = 8 + get_jitter(err->jitter_mark);
for (int j = 0; j < bm_len && sim_total_samples < SIM_MAX_SAMPLES; j++) {
sim_buffer[sim_total_samples++] = 1;
}
}
/* 3. Payload Bits (24 Bit) */
for (int i = 0; i < 24; i++)
{
bool bit = (pkt.data.bytes[i / 8] >> (i % 8)) & 1;
/* 4. Rauschen injizieren (Bit Flips) */
if (err->noise_flips_per_8 > 0) {
for (uint32_t i = 0; i < sim_total_samples; i += 8) {
for (int f = 0; f < err->noise_flips_per_8; f++) {
uint32_t flip_idx = i + (sys_rand32_get() % 8);
if (flip_idx < sim_total_samples) {
sim_buffer[flip_idx] = !sim_buffer[flip_idx]; /* Bit kippen */
}
}
}
}
/* Space Phase */
int s_base = bit ? 16 : 8;
int s_jit = bit ? get_jitter(err->jitter_space_1) : get_jitter(err->jitter_space_0);
int s_len = s_base + s_jit;
for (int j = 0; j < s_len && sim_total_samples < SIM_MAX_SAMPLES; j++)
{
sim_buffer[sim_total_samples++] = 0;
}
sim_sample_pos = 0;
sim_trigger = true;
/* Mark Phase */
int bm_len = 8 + get_jitter(err->jitter_mark);
for (int j = 0; j < bm_len && sim_total_samples < SIM_MAX_SAMPLES; j++)
{
sim_buffer[sim_total_samples++] = 1;
}
}
LOG_DBG("Simulator: Queued (Type: %u, CRC: 0x%02X), Total Samples: %u",
pkt.data.fields.type, pkt.data.fields.crc, sim_total_samples);
/* 4. Rauschen injizieren (Bit Flips) */
if (err->noise_flips_per_8 > 0)
{
for (uint32_t i = 0; i < sim_total_samples; i += 8)
{
for (int f = 0; f < err->noise_flips_per_8; f++)
{
uint32_t flip_idx = i + (sys_rand32_get() % 8);
if (flip_idx < sim_total_samples)
{
sim_buffer[flip_idx] = !sim_buffer[flip_idx]; /* Bit kippen */
}
}
}
}
sim_sample_pos = 0;
sim_trigger = true;
LOG_DBG("Simulator: Queued (Type: %u, CRC: 0x%02X), Total Samples: %u",
pkt.data.fields.type, pkt.data.fields.crc, sim_total_samples);
}
void ir_recv_sim_thread(void *p1, void *p2, void *p3)
{
while (1)
{
k_usleep(75 * SAMPLES_PER_BUFFER);
if (!sim_trigger) continue;
while (1)
{
k_usleep(75 * SAMPLES_PER_BUFFER);
if (!sim_trigger)
continue;
int16_t *buf = adc_buffers[write_idx];
for (int i = 0; i < SAMPLES_PER_BUFFER; i++)
{
bool level = 0;
if (sim_sample_pos < sim_total_samples) {
level = sim_buffer[sim_sample_pos++];
}
bool active = IS_ENABLED(CONFIG_IR_RECV_INVERT_SIGNAL) ? !level : level;
buf[i * ADC_CHANNELS] = active ? 0x0FFF : 0x0000;
buf[i * ADC_CHANNELS + 3] = 2400; // VBat Dummy
}
write_idx = (write_idx + 1) % BUFFER_COUNT;
k_sem_give(&adc_sem);
int16_t *buf = adc_buffers[write_idx];
for (int i = 0; i < SAMPLES_PER_BUFFER; i++)
{
bool level = 0;
if (sim_sample_pos < sim_total_samples)
{
level = sim_buffer[sim_sample_pos];
}
sim_sample_pos++; /* Unbedingtes Inkrement */
/* Nach dem Puffer noch eine kurze Pause einhalten, um das Paket abzuschließen */
if (sim_sample_pos >= sim_total_samples + 50)
{
sim_trigger = false;
LOG_INF("Simulation sequence finished.");
}
}
bool active = IS_ENABLED(CONFIG_IR_RECV_INVERT_SIGNAL) ? !level : level;
buf[i * ADC_CHANNELS] = active ? 0x0FFF : 0x0000;
buf[i * ADC_CHANNELS + 3] = 2400; // VBat Dummy
}
write_idx = (write_idx + 1) % BUFFER_COUNT;
k_sem_give(&adc_sem);
/* Nach dem Puffer noch eine kurze Pause einhalten, um das Paket abzuschließen */
if (sim_sample_pos >= sim_total_samples + 50)
{
sim_trigger = false;
LOG_INF("Simulation sequence finished.");
}
}
}
K_THREAD_DEFINE(sim_tid, 1024, ir_recv_sim_thread, NULL, NULL, NULL, 5, 0, 0);
#endif
@@ -175,7 +190,7 @@ static void process_ir_sample(ir_ctx_t *ctx, int16_t raw)
/* Energie über 32 Samples (Header) und 8 Samples (Bits) berechnen */
uint8_t energy_32 = __builtin_popcount(ctx->sample_window);
uint8_t energy_8 = __builtin_popcount(ctx->sample_window & 0xFF);
uint8_t energy_8 = __builtin_popcount(ctx->sample_window & 0xFF);
switch (ctx->state)
{
@@ -206,7 +221,7 @@ static void process_ir_sample(ir_ctx_t *ctx, int16_t raw)
case IR_STATE_FIND_MARK:
ctx->timer++;
if (energy_8 >= 4)
{
ctx->state = IR_STATE_SYNC_MARK;
@@ -232,13 +247,13 @@ static void process_ir_sample(ir_ctx_t *ctx, int16_t raw)
if (ctx->sync_window >= 10)
{
if (ctx->max_energy >= 6)
if (ctx->max_energy >= 6)
{
bool bit = (ctx->timer_at_max >= 20);
bool bit = (ctx->timer_at_max >= 20);
ctx->bit_acc = (ctx->bit_acc >> 1) | (bit ? (1 << 23) : 0);
LOG_DBG("Bit %u: %d (T_Max:%u, E_Max:%u)",
LOG_DBG("Bit %u: %d (T_Max:%u, E_Max:%u)",
ctx->bit_count, bit, ctx->timer_at_max, ctx->max_energy);
if (++ctx->bit_count >= 24)
@@ -248,7 +263,6 @@ static void process_ir_sample(ir_ctx_t *ctx, int16_t raw)
else
{
ctx->state = IR_STATE_FIND_MARK;
ctx->timer = ctx->timer - ctx->timer_at_max;
}
@@ -268,12 +282,12 @@ static void process_ir_sample(ir_ctx_t *ctx, int16_t raw)
p.data.bytes[2] = (ctx->bit_acc >> 16) & 0xFF;
if (lastertag_crc8(p.data.bytes, 2) == p.data.fields.crc)
{
LOG_INF("VALID: Type %u, ID %u, Val %u",
p.data.fields.type,
p.data.fields.id,
p.data.fields.value);
}
{
LOG_INF("VALID: Type %u, ID %u, Val %u",
p.data.fields.type,
p.data.fields.id,
p.data.fields.value);
}
else
{
LOG_WRN("CRC Error! Acc: 0x%06X", ctx->bit_acc);