From 4b9f377bb0a8b6242d0ae4ec4dda1f1d3aa638d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Hamal=20Dvo=C5=99=C3=A1k?= Date: Sat, 30 Aug 2025 20:33:37 +0200 Subject: [PATCH] Fix DC offset removal, simplify... --- src/main.c | 203 ++++++++++++++++++++--------------------------------- 1 file changed, 76 insertions(+), 127 deletions(-) diff --git a/src/main.c b/src/main.c index 39fe9fc..ecd6b43 100644 --- a/src/main.c +++ b/src/main.c @@ -21,43 +21,43 @@ #include #include -#define VREG_VOLTAGE VREG_VOLTAGE_1_20 -#define CLK_SYS_HZ (320 * MHZ) +#define VREG_VOLTAGE VREG_VOLTAGE_1_30 +#define CLK_SYS_HZ (300 * MHZ) -#define RX_PIN 10 -#define FB_PIN 6 +#define RX_PIN 10 +#define FB_PIN 6 #define PSU_PIN 23 -#define PIO pio0 -#define SM_RX 0 +#define PIO pio0 +#define SM_RX 0 #define SM_BIAS 1 -#define SM_COS 2 -#define SM_SIN 3 +#define SM_COS 2 +#define SM_SIN 3 -#define IQ_SAMPLES 32 +#define IQ_SAMPLES 32 #define IQ_BLOCK_LEN (2 * IQ_SAMPLES) #define IQ_QUEUE_LEN 16 -#define XOR_ADDR 0x1000 -#define LO_BITS_DEPTH 15 -#define LO_WORDS (1 << (LO_BITS_DEPTH - 2)) +#define XOR_ADDR 0x1000 +#define LO_BITS_DEPTH 15 +#define LO_WORDS (1 << (LO_BITS_DEPTH - 2)) #define LO_COS_ACCUMULATOR (&PIO->sm[SM_COS].pinctrl) #define LO_SIN_ACCUMULATOR (&PIO->sm[SM_SIN].pinctrl) -#define SIN_PHASE (0u) -#define COS_PHASE (3u << 30) +#define SIN_PHASE (0u) +#define COS_PHASE (3u << 30) static uint32_t lo_cos[LO_WORDS] __attribute__((__aligned__(1 << LO_BITS_DEPTH))); static uint32_t lo_sin[LO_WORDS] __attribute__((__aligned__(1 << LO_BITS_DEPTH))); #define INIT_SAMPLE_RATE 100000 -#define INIT_FREQ 94600000 +#define INIT_FREQ 94600000 static int frequency = INIT_FREQ; static int sample_rate = INIT_SAMPLE_RATE; -#define BASE_GAIN (1 << 15) -#define ATTN_BITS 12 -#define DECIMATE 4 +#define ATTN_BITS 16 +#define BASE_GAIN (1 << 23) +#define DC_OFFSET (int)(127.4 * (1 << ATTN_BITS)) static int gain = BASE_GAIN / (CLK_SYS_HZ / INIT_SAMPLE_RATE); @@ -108,7 +108,7 @@ static void init_rx() pio_gpio_init(PIO, RX_PIN); const uint16_t insn[] = { - pio_encode_in(pio_pins, 1) | pio_encode_delay(0), + pio_encode_in(pio_pins, 1), }; pio_program_t prog = { @@ -143,16 +143,8 @@ static void init_bias() gpio_set_slew_rate(FB_PIN, GPIO_SLEW_RATE_SLOW); const uint16_t insn[] = { - pio_encode_mov(pio_isr, pio_null), - pio_encode_in(pio_y, 4), - pio_encode_in(pio_pins, 1) | pio_encode_delay(15), - pio_encode_in(pio_pins, 1) | pio_encode_delay(15), - - pio_encode_mov(pio_y, pio_isr), - pio_encode_mov(pio_x, pio_isr), - - pio_encode_jmp_x_dec(6), - pio_encode_mov_not(pio_pins, pio_pins) | pio_encode_sideset(1, 1), + pio_encode_mov_not(pio_pins, pio_pins) | pio_encode_sideset(1, 1) | + pio_encode_delay(0), }; pio_program_t prog = { @@ -286,7 +278,7 @@ static void rf_rx_start() channel_config_set_write_increment(&dma_conf, false); channel_config_set_chain_to(&dma_conf, dma_ch_cos); dma_channel_configure(dma_ch_cp, &dma_conf, LO_SIN_ACCUMULATOR, LO_COS_ACCUMULATOR, 1, - false); + false); /* Read lo_cos into accumulator I with XOR. */ dma_conf = dma_channel_get_default_config(dma_ch_cos); @@ -296,7 +288,7 @@ static void rf_rx_start() channel_config_set_ring(&dma_conf, false, LO_BITS_DEPTH); channel_config_set_chain_to(&dma_conf, dma_ch_sin); dma_channel_configure(dma_ch_cos, &dma_conf, LO_COS_ACCUMULATOR + XOR_ADDR / 4, lo_cos, 1, - false); + false); /* Read lo_sin into accumulator Q with XOR. */ dma_conf = dma_channel_get_default_config(dma_ch_sin); @@ -306,7 +298,7 @@ static void rf_rx_start() channel_config_set_ring(&dma_conf, false, LO_BITS_DEPTH); channel_config_set_chain_to(&dma_conf, dma_ch_pio_cos); dma_channel_configure(dma_ch_sin, &dma_conf, LO_SIN_ACCUMULATOR + XOR_ADDR / 4, lo_sin, 1, - false); + false); /* Copy mixed I accumulator to PIO adder I. */ dma_conf = dma_channel_get_default_config(dma_ch_pio_cos); @@ -316,7 +308,7 @@ static void rf_rx_start() channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, SM_COS, true)); channel_config_set_chain_to(&dma_conf, dma_ch_pio_sin); dma_channel_configure(dma_ch_pio_cos, &dma_conf, &PIO->txf[SM_COS], LO_COS_ACCUMULATOR, 1, - false); + false); /* Copy mixed Q accumulator to PIO adder Q. */ dma_conf = dma_channel_get_default_config(dma_ch_pio_sin); @@ -326,7 +318,7 @@ static void rf_rx_start() channel_config_set_dreq(&dma_conf, pio_get_dreq(PIO, SM_SIN, true)); channel_config_set_chain_to(&dma_conf, dma_ch_rx); dma_channel_configure(dma_ch_pio_sin, &dma_conf, &PIO->txf[SM_SIN], LO_SIN_ACCUMULATOR, 1, - false); + false); /* Trigger I accumulator values push. */ dma_conf = dma_channel_get_default_config(dma_ch_samp_cos); @@ -337,7 +329,7 @@ static void rf_rx_start() channel_config_set_high_priority(&dma_conf, true); channel_config_set_chain_to(&dma_conf, dma_ch_samp_sin); dma_channel_configure(dma_ch_samp_cos, &dma_conf, &PIO->sm[SM_COS].instr, &samp_insn, 1, - false); + false); /* Trigger Q accumulator values push. */ dma_conf = dma_channel_get_default_config(dma_ch_samp_sin); @@ -347,7 +339,7 @@ static void rf_rx_start() channel_config_set_high_priority(&dma_conf, true); channel_config_set_chain_to(&dma_conf, dma_ch_samp_cos); dma_channel_configure(dma_ch_samp_sin, &dma_conf, &PIO->sm[SM_SIN].instr, &samp_insn, 1, - false); + false); init_bias(); init_adder(); @@ -426,92 +418,50 @@ inline static void led_set(bool on) gpio_put(PICO_DEFAULT_LED_PIN, on); } -inline static uint32_t pio_sm_get_blocking_unsafe(pio_hw_t *pio, int sm) -{ - while (pio->fstat & (1u << (PIO_FSTAT_RXEMPTY_LSB + sm))) - asm volatile("nop"); - - return pio->rxf[sm]; -} - -static int Ia1, Ia2, Ia3; -static int Ib1, Ib2, Ib3; - -static int Qa1, Qa2, Qa3; -static int Qb1, Qb2, Qb3; - -inline static void accI() -{ - static uint16_t py, px; - - uint32_t yx = pio_sm_get_blocking_unsafe(PIO, SM_COS); - uint16_t y = yx >> 16; - uint16_t x = yx; - - uint16_t ny = py - y; - uint16_t nx = px - x; - - py = y; - px = x; - - uint32_t s = (ny << 1) + nx; - - Ia1 += s; - Ia2 += Ia1; - Ia3 += Ia2; -} - -inline static void accQ() -{ - static uint16_t py, px; - - uint32_t yx = pio_sm_get_blocking_unsafe(PIO, SM_SIN); - uint16_t y = yx >> 16; - uint16_t x = yx; - - uint16_t ny = py - y; - uint16_t nx = px - x; - - py = y; - px = x; - - uint32_t s = (ny << 1) + nx; - - Qa1 += s; - Qa2 += Qa1; - Qa3 += Qa2; -} - inline static int getI() { - uint32_t c1, c2, c3; + static uint16_t py, px; - c3 = Ia3 - Ib3; - Ib3 = Ia3; + uint32_t yx = pio_sm_get_blocking(PIO, SM_COS); + uint16_t y = yx >> 16; + uint16_t x = yx; - c2 = c3 - Ib2; - Ib2 = c3; + uint16_t ny = py - y; + uint16_t nx = px - x; - c1 = c2 - Ib1; - Ib1 = c2; + py = y; + px = x; - return (int)c1; + int s = ((ny << 1) + nx) * gain; + + static int dc; + dc += (s - dc) >> ATTN_BITS; + s -= dc; + + return (s + DC_OFFSET) >> ATTN_BITS; } inline static int getQ() { - uint32_t c1, c2, c3; + static uint16_t py, px; - c3 = Qa3 - Qb3; - Qb3 = Qa3; + uint32_t yx = pio_sm_get_blocking(PIO, SM_SIN); + uint16_t y = yx >> 16; + uint16_t x = yx; - c2 = c3 - Qb2; - Qb2 = c3; + uint16_t ny = py - y; + uint16_t nx = px - x; - c1 = c2 - Qb1; - Qb1 = c2; + py = y; + px = x; - return (int)c1; + int s = ((ny << 1) + nx) * gain; + + static int dc; + dc += (s - dc) >> ATTN_BITS; + s -= dc; + + return (s + DC_OFFSET) >> ATTN_BITS; } static void rf_rx(void) @@ -527,19 +477,21 @@ static void rf_rx(void) uint8_t *blockptr = block; for (int i = 0; i < IQ_SAMPLES; i++) { - for (int d = 0; d < DECIMATE; d++) { - accI(); - accQ(); - } + int I = getI(); + int Q = getQ(); - int I = getI() * gain; - int Q = getQ() * gain; + if (I < 0) + I = 0; + else if (I > 255) + I = 255; - I >>= ATTN_BITS; - *blockptr++ = I + 128; + if (Q < 0) + Q = 0; + else if (Q > 255) + Q = 255; - Q >>= ATTN_BITS; - *blockptr++ = Q + 128; + *blockptr++ = I; + *blockptr++ = Q; } if (queue_try_add(&iq_queue, &block)) { @@ -561,7 +513,7 @@ static void run_command(uint8_t cmd, uint32_t arg) /* Set the rate at which IQ sample pairs are sent */ sample_rate = arg; gain = BASE_GAIN / (CLK_SYS_HZ / sample_rate); - dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE)); + dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / sample_rate); rx_lo_init(frequency); } } @@ -613,10 +565,7 @@ static void do_rx() fwrite(block, IQ_BLOCK_LEN, 1, stdout); fflush(stdout); } else { - int wait = xorshift() >> (32 - 15); - - for (int i = 0; i < wait; i++) - asm volatile("nop"); + sleep_us(1); } } @@ -634,7 +583,7 @@ int main() vreg_set_voltage(VREG_VOLTAGE); set_sys_clock_khz(CLK_SYS_HZ / KHZ, true); clock_configure(clk_peri, 0, CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, CLK_SYS_HZ, - CLK_SYS_HZ); + CLK_SYS_HZ); /* Enable PSU PWM mode. */ gpio_init(PSU_PIN); @@ -657,13 +606,13 @@ int main() /* We need to have the sampling timer ready. */ dma_t_samp = dma_claim_unused_timer(true); - dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE)); + dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / sample_rate); while (true) { if (check_command() > 0) { static const uint32_t header[3] = { __builtin_bswap32(0x52544c30), - __builtin_bswap32(5), - __builtin_bswap32(29) }; + __builtin_bswap32(5), + __builtin_bswap32(29) }; fwrite(header, sizeof header, 1, stdout); fflush(stdout);