From 9d44d520177a8e67ac76ce40b9e5777608b0031e Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Sat, 26 May 2018 13:16:24 +0300 Subject: Fix signal processing, use files --- talk.slides.html | 82 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 28 deletions(-) (limited to 'talk.slides.html') diff --git a/talk.slides.html b/talk.slides.html index 31d711f..e00e354 100644 --- a/talk.slides.html +++ b/talk.slides.html @@ -11915,7 +11915,6 @@ a.anchor-link {

Yuval Adam

@@ -11930,7 +11929,7 @@ a.anchor-link {

This talk

@@ -11941,10 +11940,8 @@ a.anchor-link {
-

Agenda

+

Radio Waves

static/dipole.gif

+

Source: https://en.wikipedia.org/wiki/Antenna_(radio)

@@ -11953,17 +11950,16 @@ a.anchor-link {
-

Radio Waves

static/dipole.gif

-

Source: https://en.wikipedia.org/wiki/Antenna_(radio)

+

Hardware Radio

static/radio.jpg

- +
-

Hardware Radio

static/radio.jpg

+

Hardware Radio

static/gsm.jpg

@@ -12047,6 +12043,14 @@ a.anchor-link {

Modulations

static/amfm2.gif

Source: http://mriquestions.com/signal-squiggles.html

+
+ +
+
+
+
+
+

GQRX

@@ -12064,10 +12068,8 @@ a.anchor-link { sdr.center_freq = 91.8e6 # 91,800,00 Hz frequency for the radio station sdr.gain = 'auto' # tune the gain (AKA "volume") automatically -samples = sdr.read_samples(1.2e6 * 8) # collect samples during 8 seconds +samples = sdr.read_samples(1.2e6 * 10) sdr.close() - -print(samples[:5]) @@ -12077,14 +12079,18 @@ a.anchor-link {
-
In [ ]:
+
In [1]:
-
# Load the samples into a numpy array
+
# Alternatively, load previously captured samples from rtl_sdr
+# and convert them from unsigned 8-bit samples to a complex IQ array
 
 import numpy as np
 
-samples = np.array(samples).astype('complex64')
+raw = np.fromfile('/tmp/samples.in', np.uint8).astype(np.float64)
+raw += -127
+raw /= 2**7
+samples = (raw[0::2] + 1j * raw[1::2]).astype(np.complex64)
 
@@ -12094,7 +12100,7 @@ a.anchor-link {
-
In [ ]:
+
In [2]:
# We captured too many samples so we need to apply a low pass filter
@@ -12103,7 +12109,7 @@ a.anchor-link {
 import scipy.signal as signal
 
 BANDWIDTH = 200e3
-DECIMATION_RATE = int(1.2e6 / BANDWIDTH)
+DECIMATION_RATE = int(1.2e6 / BANDWIDTH)  # Decimation factor of 6
 
 samples = signal.decimate(samples, DECIMATION_RATE)
 
@@ -12115,10 +12121,11 @@ a.anchor-link {
-
In [ ]:
+
In [3]:
-
# Apply the demodulation, we use a polar discriminator
+
# Apply the Frequency DEmodulation
+# We use something called a polar discriminator
 
 samples = np.angle(samples[1:] * np.conj(samples[:-1]))
 
@@ -12130,10 +12137,12 @@ a.anchor-link {
-
In [ ]:
+
In [4]:
-
# De-emphasis filter - too "sciency"
+
# De-emphasis filter
+# Even I'm not sure how/why this works
+
 # MAKE THINGS SOUND BETTER
 
 d = BANDWIDTH * 75e-6
@@ -12149,31 +12158,45 @@ a.anchor-link {
 
-
In [ ]:
+
In [5]:
# Decimate the signal down to something an audio driver can handle
 # We only catch the mono part of the signal
 
 AUDIO_RATE = 50e3
-DECIMATION_RATE = int(1.2e6 / BANDWIDTH / AUDIO_RATE)
+DECIMATION_RATE = int(BANDWIDTH / AUDIO_RATE)  # Decimation factor of 4
 
 samples = signal.decimate(samples, DECIMATION_RATE)
+
+# Amplify the signal volume
+samples *= 10000
+samples = samples.astype('int16')
 
-
+
-
In [ ]:
+
In [6]:
# HIT IT
 
-whatever.play(samples)
+import alsaaudio
+
+device = alsaaudio.PCM(alsaaudio.PCM_PLAYBACK, device='default')
+device.setchannels(1)
+device.setrate(50000)
+device.setformat(alsaaudio.PCM_FORMAT_S16_LE)
+device.setperiodsize(120)
+
+# Write data in chunks
+for s in np.array_split(samples, 120):
+    device.write(s)
 
@@ -12187,7 +12210,10 @@ a.anchor-link {

Caveats

  • Python, NumPy and SciPy are very good at doing fast processing of static data
  • -
  • When handling real-time data, buffering becomes a serious issue
  • +
  • When handling real-time data, buffering becomes a serious issue
      +
    • How do you synchronize different input/ouput sample rates on the same flow?
    • +
    +
  • GNU Radio
    • top-notch signal processing framework
    • implemented many DSP primivites
    • -- cgit v1.3.1