From 2995f19e9bc269c5b21487828b0dd88d8d72cfa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Hamal=20Dvo=C5=99=C3=A1k?= Date: Wed, 6 Mar 2024 00:01:57 +0100 Subject: [PATCH] Go to 300 MHz for FM receiver --- grc/PicoSDR-WBFM.grc | 348 ++++++++++++++++--------------------------- src/main.c | 23 ++- 2 files changed, 145 insertions(+), 226 deletions(-) diff --git a/grc/PicoSDR-WBFM.grc b/grc/PicoSDR-WBFM.grc index 3cad223..5c3136d 100644 --- a/grc/PicoSDR-WBFM.grc +++ b/grc/PicoSDR-WBFM.grc @@ -77,7 +77,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [712, 480.0] + coordinate: [704, 296.0] rotation: 0 state: true - name: analog_wfm_rcv_pll_0 @@ -85,7 +85,7 @@ blocks: parameters: affinity: '' alias: '' - audio_decimation: '4' + audio_decimation: '1' comment: '' deemph_tau: 75e-6 maxoutbuf: '0' @@ -95,7 +95,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [704, 552.0] + coordinate: [456, 408.0] rotation: 0 state: true - name: audio_sink_0 @@ -112,7 +112,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1000, 560.0] + coordinate: [992, 384.0] rotation: 0 state: true - name: blocks_add_xx_0 @@ -130,7 +130,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1000, 632.0] + coordinate: [992, 456.0] rotation: 0 state: true - name: blocks_interleaved_short_to_complex_0 @@ -184,24 +184,6 @@ blocks: coordinate: [704, 16.0] rotation: 0 state: true -- name: digital_costas_loop_cc_0 - id: digital_costas_loop_cc - parameters: - affinity: '' - alias: '' - comment: '' - maxoutbuf: '0' - minoutbuf: '0' - order: '2' - use_snr: 'False' - w: 2 * math.pi / 100 - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [704, 296.0] - rotation: 0 - state: true - name: import_0 id: import parameters: @@ -215,6 +197,54 @@ blocks: coordinate: [440, 8.0] rotation: 0 state: true +- name: low_pass_filter_0 + id: low_pass_filter + parameters: + affinity: '' + alias: '' + beta: '6.76' + comment: '' + cutoff_freq: '22_000' + decim: '4' + gain: '1' + interp: '1' + maxoutbuf: '0' + minoutbuf: '0' + samp_rate: samp_rate + type: fir_filter_fff + width: '2_000' + win: window.WIN_HAMMING + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [704, 356.0] + rotation: 0 + state: true +- name: low_pass_filter_0_0 + id: low_pass_filter + parameters: + affinity: '' + alias: '' + beta: '6.76' + comment: '' + cutoff_freq: '22_000' + decim: '4' + gain: '1' + interp: '1' + maxoutbuf: '0' + minoutbuf: '0' + samp_rate: samp_rate + type: fir_filter_fff + width: '2_000' + win: window.WIN_HAMMING + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [704, 516.0] + rotation: 0 + state: true - name: network_tcp_source_0 id: network_tcp_source parameters: @@ -235,98 +265,6 @@ blocks: coordinate: [48, 200.0] rotation: 0 state: true -- name: qtgui_const_sink_x_0 - id: qtgui_const_sink_x - parameters: - affinity: '' - alias: '' - alpha1: '1.0' - alpha10: '1.0' - alpha2: '1.0' - alpha3: '1.0' - alpha4: '1.0' - alpha5: '1.0' - alpha6: '1.0' - alpha7: '1.0' - alpha8: '1.0' - alpha9: '1.0' - autoscale: 'False' - axislabels: 'True' - color1: '"blue"' - color10: '"red"' - color2: '"red"' - color3: '"red"' - color4: '"red"' - color5: '"red"' - color6: '"red"' - color7: '"red"' - color8: '"red"' - color9: '"red"' - comment: '' - grid: 'True' - gui_hint: (2, 1, 1, 1) - label1: '' - label10: '' - label2: '' - label3: '' - label4: '' - label5: '' - label6: '' - label7: '' - label8: '' - label9: '' - legend: 'False' - marker1: '0' - marker10: '0' - marker2: '0' - marker3: '0' - marker4: '0' - marker5: '0' - marker6: '0' - marker7: '0' - marker8: '0' - marker9: '0' - name: '""' - nconnections: '1' - size: min(int(samp_rate // 30), 512) - style1: '0' - style10: '0' - style2: '0' - style3: '0' - style4: '0' - style5: '0' - style6: '0' - style7: '0' - style8: '0' - style9: '0' - tr_chan: '0' - tr_level: '0.0' - tr_mode: qtgui.TRIG_MODE_FREE - tr_slope: qtgui.TRIG_SLOPE_POS - tr_tag: '""' - type: complex - update_time: 1/30 - width1: '1' - width10: '1' - width2: '1' - width3: '1' - width4: '1' - width5: '1' - width6: '1' - width7: '1' - width8: '1' - width9: '1' - xmax: '1' - xmin: '-1' - ymax: '1' - ymin: '-1' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [1000, 280.0] - rotation: 0 - state: true - name: qtgui_time_sink_x_0 id: qtgui_time_sink_x parameters: @@ -518,104 +456,7 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1000, 456.0] - rotation: 0 - state: true -- name: qtgui_time_sink_x_0_1 - id: qtgui_time_sink_x - parameters: - affinity: '' - alias: '' - alpha1: '1.0' - alpha10: '1.0' - alpha2: '1.0' - alpha3: '1.0' - alpha4: '1.0' - alpha5: '1.0' - alpha6: '1.0' - alpha7: '1.0' - alpha8: '1.0' - alpha9: '1.0' - autoscale: 'False' - axislabels: 'True' - color1: blue - color10: dark blue - color2: red - color3: green - color4: black - color5: cyan - color6: magenta - color7: yellow - color8: dark red - color9: dark green - comment: '' - ctrlpanel: 'False' - entags: 'False' - grid: 'True' - gui_hint: (2, 0, 1, 1) - label1: I - label10: Signal 10 - label2: Q - label3: Signal 3 - label4: Signal 4 - label5: Signal 5 - label6: Signal 6 - label7: Signal 7 - label8: Signal 8 - label9: Signal 9 - legend: 'False' - marker1: '-1' - marker10: '-1' - marker2: '-1' - marker3: '-1' - marker4: '-1' - marker5: '-1' - marker6: '-1' - marker7: '-1' - marker8: '-1' - marker9: '-1' - name: '"IQ / Loop"' - nconnections: '1' - size: min(int(samp_rate // 30), 512) - srate: samp_rate - stemplot: 'False' - style1: '1' - style10: '1' - style2: '1' - style3: '1' - style4: '1' - style5: '1' - style6: '1' - style7: '1' - style8: '1' - style9: '1' - tr_chan: '0' - tr_delay: '0' - tr_level: '0.0' - tr_mode: qtgui.TRIG_MODE_FREE - tr_slope: qtgui.TRIG_SLOPE_POS - tr_tag: '""' - type: complex - update_time: 1/30 - width1: '1' - width10: '1' - width2: '1' - width3: '1' - width4: '1' - width5: '1' - width6: '1' - width7: '1' - width8: '1' - width9: '1' - ylabel: Amplitude - ymax: '1' - ymin: '-1' - yunit: '""' - states: - bus_sink: false - bus_source: false - bus_structure: null - coordinate: [1000, 352.0] + coordinate: [992, 272.0] rotation: 0 state: true - name: qtgui_waterfall_sink_x_0_0 @@ -711,9 +552,9 @@ blocks: fftsize: '1024' freqhalf: 'True' grid: 'True' - gui_hint: (3, 0, 1, 2) + gui_hint: (4, 0, 1, 2) int_max: '0' - int_min: '-90' + int_min: 10 * math.log10(1 / ((2 ** 15 - 1) ** 2)) label1: '' label10: '' label2: '' @@ -737,26 +578,87 @@ blocks: bus_sink: false bus_source: false bus_structure: null - coordinate: [1144, 616.0] + coordinate: [1152, 440.0] + rotation: 0 + state: true +- name: qtgui_waterfall_sink_x_0_0_0_0 + id: qtgui_waterfall_sink_x + parameters: + affinity: '' + alias: '' + alpha1: '1.0' + alpha10: '1.0' + alpha2: '1.0' + alpha3: '1.0' + alpha4: '1.0' + alpha5: '1.0' + alpha6: '1.0' + alpha7: '1.0' + alpha8: '1.0' + alpha9: '1.0' + axislabels: 'True' + bw: samp_rate + color1: '0' + color10: '0' + color2: '0' + color3: '0' + color4: '0' + color5: '0' + color6: '0' + color7: '0' + color8: '0' + color9: '0' + comment: '' + fc: '0' + fftsize: '1024' + freqhalf: 'True' + grid: 'True' + gui_hint: (3, 0, 1, 2) + int_max: '0' + int_min: 10 * math.log10(1 / ((2 ** 15 - 1) ** 2)) + label1: '' + label10: '' + label2: '' + label3: '' + label4: '' + label5: '' + label6: '' + label7: '' + label8: '' + label9: '' + legend: 'True' + maxoutbuf: '0' + minoutbuf: '0' + name: '"FM Demodulation"' + nconnections: '1' + showports: 'False' + type: float + update_time: 1/30 + wintype: window.WIN_BLACKMAN_hARRIS + states: + bus_sink: false + bus_source: false + bus_structure: null + coordinate: [992, 168.0] rotation: 0 state: true connections: - [analog_quadrature_demod_cf_0, '0', qtgui_time_sink_x_0_0, '0'] -- [analog_wfm_rcv_pll_0, '0', audio_sink_0, '0'] -- [analog_wfm_rcv_pll_0, '0', blocks_add_xx_0, '0'] -- [analog_wfm_rcv_pll_0, '1', audio_sink_0, '1'] -- [analog_wfm_rcv_pll_0, '1', blocks_add_xx_0, '1'] +- [analog_quadrature_demod_cf_0, '0', qtgui_waterfall_sink_x_0_0_0_0, '0'] +- [analog_wfm_rcv_pll_0, '0', low_pass_filter_0, '0'] +- [analog_wfm_rcv_pll_0, '1', low_pass_filter_0_0, '0'] - [blocks_add_xx_0, '0', qtgui_waterfall_sink_x_0_0_0, '0'] - [blocks_interleaved_short_to_complex_0, '0', analog_quadrature_demod_cf_0, '0'] - [blocks_interleaved_short_to_complex_0, '0', analog_wfm_rcv_pll_0, '0'] - [blocks_interleaved_short_to_complex_0, '0', blocks_probe_rate_0, '0'] -- [blocks_interleaved_short_to_complex_0, '0', digital_costas_loop_cc_0, '0'] - [blocks_interleaved_short_to_complex_0, '0', qtgui_time_sink_x_0, '0'] - [blocks_interleaved_short_to_complex_0, '0', qtgui_waterfall_sink_x_0_0, '0'] - [blocks_probe_rate_0, rate, blocks_message_debug_0, print] -- [digital_costas_loop_cc_0, '0', qtgui_const_sink_x_0, '0'] -- [digital_costas_loop_cc_0, '0', qtgui_time_sink_x_0_1, '0'] +- [low_pass_filter_0, '0', audio_sink_0, '0'] +- [low_pass_filter_0, '0', blocks_add_xx_0, '0'] +- [low_pass_filter_0_0, '0', audio_sink_0, '1'] +- [low_pass_filter_0_0, '0', blocks_add_xx_0, '1'] - [network_tcp_source_0, '0', blocks_interleaved_short_to_complex_0, '0'] metadata: diff --git a/src/main.c b/src/main.c index 538934d..d85f44d 100644 --- a/src/main.c +++ b/src/main.c @@ -40,10 +40,10 @@ /* FM Radio */ #if 1 #define VREG_VOLTAGE VREG_VOLTAGE_1_20 -#define CLK_SYS_HZ (266 * MHZ) +#define CLK_SYS_HZ (300 * MHZ) #define BANDWIDTH 1536000 #define DECIMATION_BITS 3 -#define LPF_ORDER 3 +#define LPF_ORDER 4 #define AGC_DECAY_BITS 20 #define BIAS_STRENGTH 0 #endif @@ -64,7 +64,7 @@ #define DECIMATION (1 << DECIMATION_BITS) static_assert(RX_SLEEP_US > 0, "RX_SLEEP_US must be positive"); -static_assert(LPF_ORDER <= 3, "LPF_ORDER must be 0-3"); +static_assert(LPF_ORDER <= 4, "LPF_ORDER must be 0-4"); static_assert(BIAS_STRENGTH >= 0 && BIAS_STRENGTH <= 9, "BIAS_STRENGTH must be 0-9"); #define XOR_ADDR 0x1000 @@ -636,6 +636,13 @@ static void rf_rx(void) int lpQa3 = 0; #endif +#if LPF_ORDER >= 4 + static int lpIh4[DECIMATION]; + static int lpQh4[DECIMATION]; + int lpIa4 = 0; + int lpQa4 = 0; +#endif + int64_t dcI = 0, dcQ = 0; while (true) { @@ -685,6 +692,11 @@ static void rf_rx(void) lpIa3 += I - lpIh3[d]; lpIh3[d] = I; I = lpIa3 / DECIMATION; +#endif +#if LPF_ORDER >= 4 + lpIa4 += I - lpIh4[d]; + lpIh4[d] = I; + I = lpIa4 / DECIMATION; #endif dI += I; } @@ -720,6 +732,11 @@ static void rf_rx(void) lpQa3 += Q - lpQh3[d]; lpQh3[d] = Q; Q = lpQa3 / DECIMATION; +#endif +#if LPF_ORDER >= 4 + lpQa4 += Q - lpQh4[d]; + lpQh4[d] = Q; + Q = lpQa4 / DECIMATION; #endif dQ += Q; }