diff --git a/grc/PicoSDR-WBFM.grc b/grc/PicoSDR-WBFM.grc index c9d33cc..6be09c4 100644 --- a/grc/PicoSDR-WBFM.grc +++ b/grc/PicoSDR-WBFM.grc @@ -37,7 +37,7 @@ blocks: id: variable parameters: comment: '' - value: '94_600_000' + value: '88_200_000' states: bus_sink: false bus_source: false @@ -49,7 +49,7 @@ blocks: id: variable parameters: comment: '' - value: '192_000' + value: '200_000' states: bus_sink: false bus_source: false @@ -78,7 +78,7 @@ blocks: parameters: affinity: '' alias: '' - audio_decimation: '4' + audio_decimation: '8' comment: '' deemph_tau: 75e-6 maxoutbuf: '0' @@ -100,7 +100,7 @@ blocks: device_name: '' num_inputs: '2' ok_to_block: 'True' - samp_rate: samp_rate // 4 + samp_rate: samp_rate // 8 states: bus_sink: false bus_source: false @@ -150,15 +150,15 @@ blocks: alias: '' beta: '6.76' comment: '' - cutoff_freq: samp_rate / 8 - decim: '4' + cutoff_freq: samp_rate / 16 + decim: '8' gain: '1' interp: '1' maxoutbuf: '0' minoutbuf: '0' samp_rate: samp_rate type: fir_filter_fff - width: samp_rate / 8 + width: samp_rate / 16 win: window.WIN_HAMMING states: bus_sink: false @@ -677,7 +677,7 @@ blocks: name: '"FM Demodulation"' nconnections: '1' size: '512' - srate: samp_rate // (2 ** 3) + srate: samp_rate // 8 stemplot: 'False' style1: '1' style10: '1' @@ -856,4 +856,4 @@ connections: metadata: file_format: 1 - grc_version: 3.10.9.2 + grc_version: 3.10.11.0 diff --git a/src/main.c b/src/main.c index b654e0f..8fcbf11 100644 --- a/src/main.c +++ b/src/main.c @@ -53,27 +53,28 @@ static uint32_t lo_sin[LO_WORDS] __attribute__((__aligned__(1 << LO_BITS_DEPTH)) #define INIT_SAMPLE_RATE 100000 #define INIT_FREQ 94600000 -#define INIT_GAIN 127 -#define NUM_GAINS 29 -static int gains[NUM_GAINS] = { 0, 9, 14, 27, 37, 77, 87, 125, 144, 157, - 166, 197, 207, 229, 254, 280, 297, 328, 338, 364, - 372, 386, 402, 421, 434, 439, 445, 480, 496 }; +#define BASE_GAIN (1 << 15) +#define ATTN_BITS 8 + static int sample_rate = INIT_SAMPLE_RATE; -static int max_amplitude = CLK_SYS_HZ / INIT_SAMPLE_RATE / 2; -static int gain = INIT_GAIN; +static int gain = BASE_GAIN / (CLK_SYS_HZ / INIT_SAMPLE_RATE / 2); static int frequency = INIT_FREQ; static queue_t iq_queue; static uint8_t iq_queue_buffer[IQ_QUEUE_LEN][IQ_BLOCK_LEN]; static size_t iq_queue_pos = 0; -static uint32_t rnd = 0; +static uint32_t xorshift_seed; -inline static __unused uint32_t rnd_next() +static inline __unused uint32_t xorshift(void) { - rnd = rnd * 0x41c64e6d + 12345; - return rnd; + uint32_t x = xorshift_seed; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + xorshift_seed = x; + return x; } static void dma_channel_clear_chain_to(int ch) @@ -187,6 +188,7 @@ static const uint32_t samp_insn = 16; static void init_adder() { const uint16_t insn[] = { + /* y has weight of 2, x has weight of 1 */ pio_encode_out(pio_pc, 4), // 0000 +0 pio_encode_jmp_x_dec(0), // 0001 +1 pio_encode_jmp_x_dec(0), // 0010 +1 @@ -428,6 +430,11 @@ static void rf_rx_stop(void) dma_ch_samp_sin = -1; } +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))) @@ -438,12 +445,18 @@ inline static uint32_t pio_sm_get_blocking_unsafe(pio_hw_t *pio, int sm) inline static int nextI() { - static int prevI = 0; + static int prevI2, prevI1, prevI; - int sI = 0; - sI -= 2 * pio_sm_get_blocking_unsafe(PIO, SM_COS); - sI -= pio_sm_get_blocking_unsafe(PIO, SM_COS); + int sI2 = pio_sm_get_blocking_unsafe(PIO, SM_COS); + int I2 = sI2 - prevI2; + prevI2 = sI2; + + int sI1 = pio_sm_get_blocking_unsafe(PIO, SM_COS); + int I1 = sI1 - prevI1; + prevI1 = sI1; + + int sI = I2 + I2 + I1; int I = sI - prevI; prevI = sI; @@ -452,12 +465,18 @@ inline static int nextI() inline static int nextQ() { - static int prevQ = 0; + static int prevQ2, prevQ1, prevQ; - int sQ = 0; - sQ -= 2 * pio_sm_get_blocking_unsafe(PIO, SM_SIN); - sQ -= pio_sm_get_blocking_unsafe(PIO, SM_SIN); + int sQ2 = pio_sm_get_blocking_unsafe(PIO, SM_SIN); + int Q2 = sQ2 - prevQ2; + prevQ2 = sQ2; + + int sQ1 = pio_sm_get_blocking_unsafe(PIO, SM_SIN); + int Q1 = sQ1 - prevQ1; + prevQ1 = sQ1; + + int sQ = Q2 + Q2 + Q1; int Q = sQ - prevQ; prevQ = sQ; @@ -492,28 +511,21 @@ static void rf_rx(void) Q -= nextI(); I *= gain; - I /= max_amplitude; + I >>= ATTN_BITS; - if (I > 127) - I = 127; - else if (I < -128) - I = -128; - - *blockptr++ = (uint8_t)I + 128; + *blockptr++ = I + 128; Q *= gain; - Q /= max_amplitude; + Q >>= ATTN_BITS; - if (Q > 127) - Q = 127; - else if (Q < -128) - Q = -128; - - *blockptr++ = (uint8_t)Q + 128; + *blockptr++ = Q + 128; } if (queue_try_add(&iq_queue, &block)) { - iq_queue_pos = (iq_queue_pos + 1) & (IQ_QUEUE_LEN - 1); + iq_queue_pos = (iq_queue_pos + 1) % IQ_QUEUE_LEN; + led_set(0); + } else { + led_set(1); } } } @@ -527,16 +539,9 @@ static void run_command(uint8_t cmd, uint32_t arg) } else if (0x02 == cmd) { /* Set the rate at which IQ sample pairs are sent */ sample_rate = arg; - max_amplitude = CLK_SYS_HZ / sample_rate / 2; + gain = BASE_GAIN / (CLK_SYS_HZ / sample_rate / 2); dma_timer_set_fraction(dma_t_samp, 1, CLK_SYS_HZ / (sample_rate * DECIMATE)); rx_lo_init(frequency + sample_rate, true); - } else if (0x04 == cmd) { - /* Set the tuner gain level */ - gain = INIT_GAIN * pow(10.0, arg / 200.0); - } else if (0x0d == cmd) { - /* Set tuner gain by the tuner's gain index */ - if (arg <= NUM_GAINS) - gain = INIT_GAIN * pow(10.0, gains[arg] / 200.0); } } @@ -587,7 +592,7 @@ static void do_rx() fwrite(block, IQ_BLOCK_LEN, 1, stdout); fflush(stdout); } else { - int wait = rnd_next() & 0x1fff; + int wait = xorshift() >> (32 - 15); for (int i = 0; i < wait; i++) asm volatile("nop"); @@ -615,6 +620,10 @@ int main() gpio_set_dir(PSU_PIN, GPIO_OUT); gpio_put(PSU_PIN, 1); + gpio_init(PICO_DEFAULT_LED_PIN); + gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); + gpio_put(PICO_DEFAULT_LED_PIN, 0); + /* Prioritize DMA over CPU. */ bus_ctrl_hw->priority |= BUSCTRL_BUS_PRIORITY_DMA_W_BITS | BUSCTRL_BUS_PRIORITY_DMA_R_BITS; @@ -633,7 +642,7 @@ int main() if (check_command() > 0) { static const uint32_t header[3] = { __builtin_bswap32(0x52544c30), __builtin_bswap32(5), - __builtin_bswap32(NUM_GAINS) }; + __builtin_bswap32(29) }; fwrite(header, sizeof header, 1, stdout); fflush(stdout);