Compare commits

..

1 commit

Author SHA1 Message Date
83bb953842 Experiment with headphones 2024-07-09 18:45:33 +02:00
10 changed files with 555 additions and 495 deletions

1
.gitignore vendored
View file

@ -1,3 +1,2 @@
/build/
/grc/*.py
/.cache/

View file

@ -32,4 +32,4 @@ See the [blog post](https://blog.porucha.net/2024/pico-sdr/) for more informatio
4. Open `grc/PicoSDR-WBFM.grc` in GNU Radio Companion, adjust carrier frequency to match your favorite FM radio station and press `F6`.
5. Alternatively [gqrx](https://www.gqrx.dk/) works fine with `rtl_tcp` input mode. Maximum sample rate seem to be 400 ksps, above that the samples are dropped. Make sure to adjust LNA gain to +30 dB. It's not accurate, but it does control bias strength which in turn does affect analog gain.
5. Alternatively [gqrx](https://www.gqrx.dk/) works fine with `rtl_tcp` input mode. Maximum sample rate seem to be 400 ksps, above that the samples are dropped.

View file

@ -49,7 +49,7 @@ blocks:
id: variable
parameters:
comment: ''
value: '200_000'
value: '192_000'
states:
bus_sink: false
bus_source: false
@ -78,7 +78,7 @@ blocks:
parameters:
affinity: ''
alias: ''
audio_decimation: '8'
audio_decimation: '4'
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 // 8
samp_rate: samp_rate // 4
states:
bus_sink: false
bus_source: false
@ -150,15 +150,15 @@ blocks:
alias: ''
beta: '6.76'
comment: ''
cutoff_freq: samp_rate / 16
decim: '8'
cutoff_freq: samp_rate / 8
decim: '4'
gain: '1'
interp: '1'
maxoutbuf: '0'
minoutbuf: '0'
samp_rate: samp_rate
type: fir_filter_fff
width: samp_rate / 16
width: samp_rate / 8
win: window.WIN_HAMMING
states:
bus_sink: false
@ -205,7 +205,7 @@ blocks:
ant8: ''
ant9: ''
args: '"rtl_tcp"'
bb_gain0: '0'
bb_gain0: '20'
bb_gain1: '20'
bb_gain10: '20'
bb_gain11: '20'
@ -374,7 +374,7 @@ blocks:
freq7: 100e6
freq8: 100e6
freq9: 100e6
gain0: '0'
gain0: '10'
gain1: '10'
gain10: '10'
gain11: '10'
@ -438,7 +438,7 @@ blocks:
gain_mode7: 'False'
gain_mode8: 'False'
gain_mode9: 'False'
if_gain0: '0'
if_gain0: '20'
if_gain1: '20'
if_gain10: '20'
if_gain11: '20'
@ -677,7 +677,7 @@ blocks:
name: '"FM Demodulation"'
nconnections: '1'
size: '512'
srate: samp_rate // 8
srate: samp_rate // (2 ** 3)
stemplot: 'False'
style1: '1'
style10: '1'
@ -856,4 +856,4 @@ connections:
metadata:
file_format: 1
grc_version: 3.10.11.0
grc_version: 3.10.9.2

View file

@ -37,7 +37,7 @@ blocks:
id: variable
parameters:
comment: ''
value: 169.5e6
value: '40_680_000'
states:
bus_sink: false
bus_source: false
@ -45,60 +45,16 @@ blocks:
coordinate: [168, 8.0]
rotation: 0
state: enabled
- name: decimation
id: variable
parameters:
comment: ''
value: '16'
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [368, 8.0]
rotation: 0
state: enabled
- name: rf_rate
id: variable
parameters:
comment: ''
value: '400_000'
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [280, 8.0]
rotation: 0
state: enabled
- name: samp_rate
id: variable
parameters:
comment: ''
value: rf_rate // decimation
value: '50_000'
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [472, 8.0]
rotation: 0
state: enabled
- name: analog_agc_xx_0
id: analog_agc_xx
parameters:
affinity: ''
alias: ''
comment: ''
gain: '1.0'
max_gain: '1'
maxoutbuf: '0'
minoutbuf: '0'
rate: 1e-4
reference: '0.707'
type: complex
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [632, 312.0]
coordinate: [264, 8.0]
rotation: 0
state: enabled
- name: analog_quadrature_demod_cf_0
@ -114,26 +70,9 @@ blocks:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [912, 616.0]
coordinate: [640, 536.0]
rotation: 0
state: true
- name: blocks_freqshift_cc_0
id: blocks_freqshift_cc
parameters:
affinity: ''
alias: ''
comment: ''
freq: '0'
maxoutbuf: '0'
minoutbuf: '0'
sample_rate: rf_rate
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [256, 328.0]
rotation: 0
state: enabled
- name: blocks_message_debug_0
id: blocks_message_debug
parameters:
@ -146,7 +85,7 @@ blocks:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [1200, 112.0]
coordinate: [928, 32.0]
rotation: 0
state: true
- name: blocks_probe_rate_0
@ -166,7 +105,7 @@ blocks:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [912, 120.0]
coordinate: [640, 40.0]
rotation: 0
state: true
- name: digital_costas_loop_cc_0
@ -179,38 +118,14 @@ blocks:
minoutbuf: '0'
order: '2'
use_snr: 'False'
w: math.pi / 100
w: 2 * math.pi / 100
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [912, 424.0]
coordinate: [640, 344.0]
rotation: 0
state: true
- name: low_pass_filter_0
id: low_pass_filter
parameters:
affinity: ''
alias: ''
beta: '6.76'
comment: ''
cutoff_freq: samp_rate / 4
decim: decimation
gain: '1'
interp: '1'
maxoutbuf: '0'
minoutbuf: '0'
samp_rate: rf_rate
type: fir_filter_ccf
width: samp_rate / 4
win: window.WIN_HAMMING
states:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [440, 284.0]
rotation: 0
state: enabled
- name: osmosdr_source_0
id: osmosdr_source
parameters:
@ -249,7 +164,7 @@ blocks:
ant8: ''
ant9: ''
args: '"rtl_tcp"'
bb_gain0: '0'
bb_gain0: '20'
bb_gain1: '20'
bb_gain10: '20'
bb_gain11: '20'
@ -418,7 +333,7 @@ blocks:
freq7: 100e6
freq8: 100e6
freq9: 100e6
gain0: '0'
gain0: '10'
gain1: '10'
gain10: '10'
gain11: '10'
@ -482,7 +397,7 @@ blocks:
gain_mode7: 'False'
gain_mode8: 'False'
gain_mode9: 'False'
if_gain0: '0'
if_gain0: '20'
if_gain1: '20'
if_gain10: '20'
if_gain11: '20'
@ -550,7 +465,7 @@ blocks:
minoutbuf: '0'
nchan: '1'
num_mboards: '1'
sample_rate: rf_rate
sample_rate: samp_rate
sync: sync
time_source0: ''
time_source1: ''
@ -565,7 +480,7 @@ blocks:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [8, 244.0]
coordinate: [152, 164.0]
rotation: 0
state: enabled
- name: qtgui_const_sink_x_0
@ -657,7 +572,7 @@ blocks:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [1200, 408.0]
coordinate: [928, 328.0]
rotation: 0
state: true
- name: qtgui_time_sink_x_0
@ -717,7 +632,7 @@ blocks:
nconnections: '1'
size: '256'
srate: samp_rate
stemplot: 'True'
stemplot: 'False'
style1: '1'
style10: '1'
style2: '1'
@ -754,7 +669,7 @@ blocks:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [912, 312.0]
coordinate: [640, 232.0]
rotation: 0
state: true
- name: qtgui_time_sink_x_0_0
@ -814,7 +729,7 @@ blocks:
nconnections: '1'
size: '256'
srate: samp_rate
stemplot: 'True'
stemplot: 'False'
style1: '1'
style10: '1'
style2: '1'
@ -833,7 +748,7 @@ blocks:
tr_tag: '""'
type: float
update_time: 1/30
width1: '2'
width1: '1'
width10: '1'
width2: '1'
width3: '1'
@ -851,7 +766,7 @@ blocks:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [1200, 592.0]
coordinate: [928, 512.0]
rotation: 0
state: true
- name: qtgui_time_sink_x_0_1
@ -911,7 +826,7 @@ blocks:
nconnections: '1'
size: '256'
srate: samp_rate
stemplot: 'True'
stemplot: 'False'
style1: '1'
style10: '1'
style2: '1'
@ -930,9 +845,9 @@ blocks:
tr_tag: '""'
type: complex
update_time: 1/30
width1: '2'
width1: '1'
width10: '1'
width2: '2'
width2: '1'
width3: '1'
width4: '1'
width5: '1'
@ -948,7 +863,7 @@ blocks:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [1200, 480.0]
coordinate: [928, 400.0]
rotation: 0
state: true
- name: qtgui_waterfall_sink_x_0_0
@ -1009,24 +924,21 @@ blocks:
bus_sink: false
bus_source: false
bus_structure: null
coordinate: [912, 208.0]
coordinate: [640, 128.0]
rotation: 0
state: true
connections:
- [analog_agc_xx_0, '0', analog_quadrature_demod_cf_0, '0']
- [analog_agc_xx_0, '0', blocks_probe_rate_0, '0']
- [analog_agc_xx_0, '0', digital_costas_loop_cc_0, '0']
- [analog_agc_xx_0, '0', qtgui_time_sink_x_0, '0']
- [analog_agc_xx_0, '0', qtgui_waterfall_sink_x_0_0, '0']
- [analog_quadrature_demod_cf_0, '0', qtgui_time_sink_x_0_0, '0']
- [blocks_freqshift_cc_0, '0', low_pass_filter_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', analog_agc_xx_0, '0']
- [osmosdr_source_0, '0', blocks_freqshift_cc_0, '0']
- [osmosdr_source_0, '0', analog_quadrature_demod_cf_0, '0']
- [osmosdr_source_0, '0', blocks_probe_rate_0, '0']
- [osmosdr_source_0, '0', digital_costas_loop_cc_0, '0']
- [osmosdr_source_0, '0', qtgui_time_sink_x_0, '0']
- [osmosdr_source_0, '0', qtgui_waterfall_sink_x_0_0, '0']
metadata:
file_format: 1
grc_version: 3.10.11.0
grc_version: 3.10.9.2

View file

@ -1,2 +0,0 @@
CompileFlags:
CompilationDatabase: ../build

View file

@ -1,5 +1,4 @@
cmake_minimum_required(VERSION 3.21)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include($ENV{PICO_SDK_PATH}/pico_sdk_init.cmake)

50
src/cordic.h Normal file
View file

@ -0,0 +1,50 @@
#pragma once
/*
* Copyright (c) 2020 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* https://opensource.org/licenses/BSD-3-Clause
*/
#define CORDIC_MAXITER 9
#define CORDIC_PI 0x10000000
static int CORDIC_ZTBL[] = { 0x04000000, 0x025C80A4, 0x013F670B, 0x00A2223B, 0x005161A8, 0x0028BAFC,
0x00145EC4, 0x000A2F8B, 0x000517CA, 0x00028BE6, 0x000145F3, 0x0000A2FA,
0x0000517D, 0x000028BE, 0x0000145F, 0x00000A30 };
inline static __attribute__((__unused__)) int fast_atan2(int y, int x)
{
int k, tx, z = 0, fl = 0;
if (x < 0) {
fl = ((y > 0) ? +1 : -1);
x = -x;
y = -y;
}
for (k = 0; k < CORDIC_MAXITER; k++) {
tx = x;
if (y <= 0) {
x -= (y >> k);
y += (tx >> k);
z -= CORDIC_ZTBL[k];
} else {
x += (y >> k);
y -= (tx >> k);
z += CORDIC_ZTBL[k];
}
}
if (fl != 0) {
z += fl * CORDIC_PI;
}
return z;
}

File diff suppressed because it is too large Load diff

@ -1 +1 @@
Subproject commit ed4858dda407ec66626aade9b7c6ad6016539f4c
Subproject commit b6b09e34b844326a156bc6734146a88111138473

View file

@ -1,15 +1,8 @@
#!/usr/bin/env python
import struct
from socket import (
AF_INET6,
MSG_DONTWAIT,
SO_REUSEADDR,
SO_SNDBUF,
SOCK_STREAM,
SOL_SOCKET,
socket,
)
from socket import (AF_INET, MSG_DONTWAIT, SO_REUSEADDR, SO_SNDBUF,
SOCK_STREAM, SOL_SOCKET, socket)
import click
import serial
@ -44,12 +37,12 @@ def describe(cmd: int, arg: int):
@click.option("-f", "--frequency", default=88200000, help="Frequency to tune to")
@click.option("-d", "--device", default="/dev/ttyACM0", help="Serial port device")
def bridge(frequency, device):
sock = socket(AF_INET6, SOCK_STREAM)
sock = socket(AF_INET, SOCK_STREAM)
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
sock.setsockopt(SOL_SOCKET, SO_SNDBUF, 1024 * 100)
print("Posing as rtl_tcp at tcp://localhost:1234")
sock.bind(("::", 1234))
print("Posing as rtl_tcp at tcp://127.0.0.1:1234")
sock.bind(("127.0.0.1", 1234))
sock.listen(3)
while True: