예제 #1
0
async def streaming():
    sdr = RtlSdr()
    # configure device
    Fs = 2.4e6  # Hz
    sdr.sample_rate = Fs  # Hz
    sdr.center_freq = 98e6  # Hz
    sdr.freq_correction = 60  # PPM
    sdr.gain = 'auto'
    # Sampling for 1 sec
    t_sampling = 1
    N_samples = round(Fs * t_sampling)
    samples = sdr.read_samples(N_samples)

    fig = plt.figure(1)
    plt.xlabel('Frequency (MHz)')
    plt.ylabel('Relative power (dB)')
    fig.show()

    async for samples in sdr.stream():

        plt.psd(samples,
                NFFT=1024,
                Fs=sdr.sample_rate / 1e6,
                Fc=sdr.center_freq / 1e6)
        plt.title("Dynamic Plot")
        plt.draw()
        plt.pause(0.1)
        fig.clear()

    # to stop streaming:
    await sdr.stop()

    # done
    sdr.close()
예제 #2
0
def check_rtl_device(device):
    try:
        sdr = RtlSdr(device_index = device)
        sdr.close()
        print("rtlsdr device", device, "ready")
    except:
        print("rtlsdr device", device, "not found")
예제 #3
0
def main():
    sdr = RtlSdr()

    print 'Configuring SDR...'
    sdr.rs = 2.4e6
    sdr.fc = 100e6
    sdr.gain = 10
    print '  sample rate: %0.6f MHz' % (sdr.rs/1e6)
    print '  center frequency %0.6f MHz' % (sdr.fc/1e6)
    print '  gain: %d dB' % sdr.gain

    print 'Reading samples...'
    samples = sdr.read_samples(256*1024)
    print '  signal mean:', sum(samples)/len(samples)

    print 'Testing callback...'
    sdr.read_samples_async(test_callback, 256*1024)

    try:
        import pylab as mpl

        print 'Testing spectrum plotting...'
        mpl.figure()
        mpl.psd(samples, NFFT=1024, Fc=sdr.fc/1e6, Fs=sdr.rs/1e6)

        mpl.show()
    except:
        # matplotlib not installed/working
        pass

    print 'Done\n'
    sdr.close()
예제 #4
0
def read_frequency(fq):
    sdr = RtlSdr()

    # Set parameters
    sampling_rate = 2400000
    center_freq = fq * 1.000e6
    # print(sdr.valid_gains_db)
    gain = 40.2

    sdr.set_sample_rate(sampling_rate)
    sdr.set_center_freq(center_freq)
    sdr.set_gain(gain)

    time_duration = 1  # if noisy plot try longer duration
    N_Samples = sampling_rate * time_duration
    y = sdr.read_samples(N_Samples)  # comment out after collecting data
    # y = np.load(str(int(center_freq)) + ".npy")	# uncomment after collecting data
    sdr.close()

    interval = 2048
    chunks = N_Samples // interval
    N = interval * chunks

    y = y[:N]
    # np.save(str(int(center_freq)), y)	# comment out after collecting data

    # Calculate average power spectrum
    y = y[:len(y // interval * interval)]
    y = y.reshape(N // interval, interval)
    y_windowed = y * np.kaiser(interval, 6)
    Y = fftshift(fft(y_windowed, axis=1), axes=1)

    Pspect = mean(abs(Y) * abs(Y), axis=0)
    return Pspect
예제 #5
0
def main():
    sdr = RtlSdr()

    print 'Configuring SDR...'
    sdr.rs = 2.4e6
    sdr.fc = 100e6
    sdr.gain = 10
    print '  sample rate: %0.6f MHz' % (sdr.rs / 1e6)
    print '  center frequency %0.6f MHz' % (sdr.fc / 1e6)
    print '  gain: %d dB' % sdr.gain

    print 'Reading samples...'
    samples = sdr.read_samples(256 * 1024)
    print '  signal mean:', sum(samples) / len(samples)

    print 'Testing callback...'
    sdr.read_samples_async(test_callback, 256 * 1024)

    try:
        import pylab as mpl

        print 'Testing spectrum plotting...'
        mpl.figure()
        mpl.psd(samples, NFFT=1024, Fc=sdr.fc / 1e6, Fs=sdr.rs / 1e6)

        mpl.show()
    except:
        # matplotlib not installed/working
        pass

    print 'Done\n'
    sdr.close()
예제 #6
0
async def streaming():
    sdr = RtlSdr()
    sdr.sample_rate = 1.2e6
    sdr.center_freq = 91.8e6

    prev = None

    device.write(np.array([0] * 100000).astype('int16'))

    async for samples in sdr.stream():
        samples = np.array(samples).astype('complex64')
        samples = signal.decimate(samples, int(1.2e6 / 200e3))

        if prev is not None:
            samples = np.insert(samples, 0, prev)
        prev = samples[-1]
        samples = np.angle(samples[1:] * np.conj(samples[:-1]))

        x = np.exp(-1 / (200e3 * 75e-6))
        samples = signal.lfilter([1 - x], [1, -x], samples)

        samples = signal.decimate(samples, int(200e3 / 50e3))
        samples *= 10000

        device.write(samples.astype('int16'))

    await sdr.stop()
    sdr.close()
예제 #7
0
async def main():
    import math

    sdr = RtlSdr()

    print('Configuring SDR...')
    sdr.rs = 2.4e6
    sdr.fc = 100e6
    sdr.gain = 10
    print('  sample rate: %0.6f MHz' % (sdr.rs / 1e6))
    print('  center frequency %0.6f MHz' % (sdr.fc / 1e6))
    print('  gain: %d dB' % sdr.gain)

    print('Streaming samples...')

    i = 0
    async for samples in sdr.stream():
        power = sum(abs(s)**2 for s in samples) / len(samples)
        print('Relative power:', 10 * math.log10(power), 'dB')

        i += 1

        if i > 100:
            sdr.stop()
            break

    print('Done')

    sdr.close()
예제 #8
0
class Rtl_threading(threading.Thread):
	def __init__(self, addr, fc, fs, size, corr):
		'''Add one more augument, corr'''
		threading.Thread.__init__(self)
		self.sdr = RtlSdr(addr)
		# configure device
		self.sdr.sample_rate = fs;  # Hz
		self.sdr.center_freq = fc;     # Hz
		# self.freq_correction = corr;   # PPM
		if addr==1:
			self.sdr.gain = 32.8
		else: #0
			self.sdr.gain = 32.8
		# init param
		self.addr = addr;
		self.size = size
		self.counter = 0;

#0.0 0.9 1.4 2.7 3.7 7.7 8.7 12.5 14.4 15.7 16.6 19.7 20.7 22.9 25.4 28.0 29.7 32.8 33.8 36.4 37.2 38.6 40.2 42.1 43.4 43.9 44.5 48.0 49.6

	def run(self):
		# start lock to avoid reading the same data
		global event, output; #init the synchronization
		if event.isSet():
			event.clear()
			event.wait()
		else:
			event.set()
		output[self.addr] = self.sdr.read_samples(self.size);
	def close(self):
		self.sdr.close();
예제 #9
0
async def main():
    import math

    sdr = RtlSdr()

    print('Configuring SDR...')
    sdr.rs = 2.4e6
    sdr.fc = 100e6
    sdr.gain = 10
    print('  sample rate: %0.6f MHz' % (sdr.rs/1e6))
    print('  center frequency %0.6f MHz' % (sdr.fc/1e6))
    print('  gain: %d dB' % sdr.gain)

    print('Streaming samples...')

    i = 0
    async for samples in sdr.stream():
        power = sum(abs(s)**2 for s in samples) / len(samples)
        print('Relative power:', 10*math.log10(power), 'dB')

        i += 1

        if i > 100:
            sdr.stop()
            break

    print('Done')

    sdr.close()
예제 #10
0
async def streaming():
    size = 256
    x_vec = np.linspace(0, 5, size + 1)[0:-1]
    y_vec = np.random.randn(len(x_vec))
    line1 = []
    sdr = RtlSdr()
    sdr.sample_rate = 2.048e6  # Hz
    sdr.center_freq = 101e6  # Hz
    sdr.freq_correction = 60  # PPM
    sdr.gain = 4
    i = 0

    async for samples in sdr.stream(256):
        i = i + 1
        print("{i} sample")
        print(samples)
        for sample in samples:
            rand_val = sample * 10000
            y_vec[-1] = rand_val
            line1 = live_plotter(x_vec, y_vec, line1)
            y_vec = np.append(y_vec[1:], 0.0)
            print(rand_val)

    # to stop streaming:
    await sdr.stop()

    # done
    sdr.close()
def collectSignal(freq, freq_file_path, mag_file_path):
    # Define function for writing signal data into file
    def write_data(data_points, magnitudeData, frequencyData, mag_file,
                   freq_file):
        i = 0
        mag_file.write('[')
        freq_file.write('[')
        while i < data_points - 1:
            mag_file.write("%s, " % magnitudeData[i])
            freq_file.write("%s, " % frequencyData[i])
            i += 1
        mag_file.write('%s]\n' % magnitudeData[i])
        freq_file.write('%s]\n' % frequencyData[i])

    sdr = RtlSdr()

    # Configure SDR
    sdr.sample_rate = 2.4e6  # Hz
    sdr.center_freq = freq  # Hz
    sdr.freq_correction = 60  # PPM
    sdr.gain = 4  # 'auto'

    # Initialize
    data_points = 1024
    samples = sdr.read_samples(256 * data_points)
    mag_file_path = mag_file_path + "magdata.txt"
    freq_file_path = freq_file_path + "freqdata.txt"

    ### *** IMPORTANT *** (for later, when optimizing)
    ### I'm not sure if we should leave this outside of the function
    ### and move it to the end of the main code, after the flight path
    ### ends. Idk the impact of leaving the SDR open/on for an extended
    ### period of time. If we move sdr.close() outside, we have to
    ### remember to also move the above code outside as well.
    ### Leaving this line within this function should be fine for now.
    sdr.close()

    # PSD plot data
    psddata = psd(samples,
                  NFFT=data_points,
                  Fs=sdr.sample_rate / 1e6,
                  Fc=sdr.center_freq / 1e6)

    # Extracting pertinent information from the PSD plot calculation
    magnitudeData = psddata[0]
    frequencyData = psddata[1]

    # Check for .txt file and write data
    # Magnitude has not been converted to dB yet. To convert, 10*log(magnitude). This comment is for Ron.
    if Path(mag_file_path).is_file() and Path(freq_file_path).is_file():
        with open(mag_file_path, 'a') as mag_file, open(freq_file_path,
                                                        'a') as freq_file:
            write_data(data_points, magnitudeData, frequencyData, mag_file,
                       freq_file)
    else:
        with open(mag_file_path, 'w') as mag_file, open(freq_file_path,
                                                        'w') as freq_file:
            write_data(data_points, magnitudeData, frequencyData, mag_file,
                       freq_file)
예제 #12
0
 def capture_samples(self):
     sdr = RtlSdr()
     sdr.sample_rate = self.sample_rate
     sdr.center_freq = self.freq - self.dc_offset
     sdr.gain = 'auto'
     self.samples = sdr.read_samples(self.sample_count)
     self.samples_to_np()
     sdr.close()
예제 #13
0
 def get_info_from_device_index(self, device_index):
     self.device_index = device_index
     if self.device_serial is None:
         self.device_serial = RtlSdr.get_device_serial_addresses(
         )[device_index]
     sdr = RtlSdr(device_index)
     self._get_info_from_device(sdr)
     sdr.close()
예제 #14
0
 def get_info_from_device_serial(self, device_serial):
     self.device_serial = device_serial
     if self.device_index is None:
         self.device_index = RtlSdr.get_device_index_by_serial(
             device_serial)
     sdr = RtlSdr(device_serial=device_serial)
     self._get_info_from_device(sdr)
     sdr.close()
예제 #15
0
def main():
    sdr = RtlSdr()

    # some defaults
    sdr.rs = 2.4e6
    sdr.fc = 146e6
    sdr.gain = 50

    noiseWindowLength = 20
    noiseWindow = []

    rampWindowLength = 5
    rampWindow = []
    rampPercent = 1.2

    backgroundNoise = False
    pulseFound = False

    results = []

    # Loop enough times to collect 3 seconds of data
    sampleLoops = int(sdr.rs * 3 / 1024)

    for i in range(0, sampleLoops):
        samples = sdr.read_samples(1024)
        curMag, freqs = magnitude_spectrum(samples, Fs=sdr.rs)
        maxSignal = max(curMag)

        noiseWindow.append(maxSignal)
        if len(noiseWindow) > noiseWindowLength:
            noiseWindow.pop(0)
            backgroundNoise = sum(noiseWindow) / noiseWindowLength
            rampWindow.append(backgroundNoise)

            if len(rampWindow) > rampWindowLength:
                rampWindow.pop(0)

                if rampWindow[rampWindowLength -
                              1] > rampWindow[0] * rampPercent:
                    pulseFound = True
                else:
                    pulseFound = False

        results.append([maxSignal, backgroundNoise, pulseFound])

    sdr.close()

    f = open("data.csv", "w")
    for result in results:
        f.write(str(result[0]))
        f.write(",")
        f.write(str(result[1]))
        f.write(",")
        f.write(str(result[2]))
        f.write("\n")
    f.close()
예제 #16
0
class SDRThread(QThread):
    signal = pyqtSignal(object)

    def __init__(self,
                 sample_rate=2.4e6,
                 center_freq=100.0e6,
                 freq_correction=60,
                 gain=33.8,
                 chunks=1024):
        QThread.__init__(self)

        # configure device
        try:
            self.sdr = RtlSdr()
        except LibUSBError:
            print("No Hardware Detected")
            self.isRunning = False

        else:
            self.sdr.sample_rate = sample_rate  # Hz
            self.sdr.center_freq = center_freq  # Hz
            self.sdr.freq_correction = freq_correction  # PPM
            self.sdr.gain = gain  # dB
            self.isRunning = True

        self.CHUNK = chunks

    def __del__(self):
        if self.isRunning:
            self.wait()

    def stop_thread(self):
        self.isRunning = False
        self.sdr.cancel_read_async()
        self.sdr.close()

    def sdr_tune(self, cf):
        self.sdr.center_freq = cf  # Hz

    def sdr_gain(self, gain=33.8):
        self.sdr.gain = gain

    def run(self):
        if self.isRunning:
            self.sdr.read_samples_async(self.sdr_async_callback, self.CHUNK,
                                        None)

    def sdr_async_callback(self, iq, ctx):
        power, _ = mlab.psd(iq,
                            NFFT=self.CHUNK,
                            Fs=self.sdr.sample_rate,
                            scale_by_freq=False)
        self.signal.emit(np.sqrt(power))
예제 #17
0
def main():
    sdr = RtlSdr()

    # some defaults
    sdr.rs = 2.4e6
    sdr.fc = 146e6
    sdr.gain = 50

    noiseWindowLength = 20
    noiseWindow = []

    rampWindowLength = 5
    rampWindow = []
    rampPercent = 1.2

    backgroundNoise = False
    pulseFound = False

    sampleCount = int(sdr.rs * 3 / 1024)

    f = open("data.csv", "w")

    for i in range(0, sampleCount):
        samples = sdr.read_samples(1024)
        curMag, freqs = magnitude_spectrum(samples, Fs=sdr.rs)
        maxSignal = max(curMag)

        noiseWindow.append(maxSignal)
        if len(noiseWindow) > noiseWindowLength:
            noiseWindow.pop(0)
            backgroundNoise = sum(noiseWindow) / noiseWindowLength
            rampWindow.append(backgroundNoise)

            if len(rampWindow) > rampWindowLength:
                rampWindow.pop(0)

                if rampWindow[rampWindowLength -
                              1] > rampWindow[0] * rampPercent:
                    pulseFound = True
                else:
                    pulseFound = False

        f.write(str(maxSignal))
        f.write(",")
        f.write(str(backgroundNoise))
        f.write(",")
        f.write(str(pulseFound))
        f.write("\n")

    f.close()

    # cleanup
    sdr.close()
예제 #18
0
def main():
    sdr = RtlSdr()
    wf = Waterfall(sdr)

    # some defaults
    sdr.rs = 2.4e6
    sdr.fc = 100e6
    sdr.gain = 10

    wf.start()

    # cleanup
    sdr.close()
예제 #19
0
def main():
    sdr = RtlSdr()
    wf = Waterfall(sdr)

    # some defaults
    sdr.rs = 2.4e6
    sdr.fc = 100e6
    sdr.gain = 10

    wf.start()

    # cleanup
    sdr.close()
예제 #20
0
class SDR:
    def __init__(self,freq):
        self.sample_rate = 1e6

        self.center_freq = freq
        self.gain = 36

        self.sdr =  RtlSdr()
        self.sdr.direct_sampling = 1
        self.sdr.sample_rate = self.sample_rate
        self.sdr.center_freq = self.center_freq
        self.sdr.gain = self.gain
    def __del__(self):
        self.sdr.close()
예제 #21
0
def main():
    sdr = RtlSdr()
    wf = Waterfall(sdr)

    # some defaults
    # Sample rate
    sdr.rs = 1e6
    sdr.set_direct_sampling('q')

    sdr.fc = 0
    sdr.gain = 10

    wf.start()

    # cleanup
    sdr.close()
예제 #22
0
def main():
    sdr = RtlSdr()
    wf = Waterfall(sdr)

    # some defaults
    # Sample rate
    sdr.rs = 1e6
    sdr.set_direct_sampling('q')

    sdr.fc = 0
    sdr.gain = 10

    wf.start()

    # cleanup
    sdr.close()
예제 #23
0
def main():
    sdr = RtlSdr()
    wf = Waterfall(sdr)

    # some defaults
    sdr.rs = 2.4e6
    sdr.fc = 100e6
    #sdr.gain = 10
    sdr.gain = 'auto'

    ### setting up TCP server
    t1 = threading.Thread(target=server_run, args=(q2,))
    t1.start()
    wf.start()

    # cleanup
    sdr.close()
예제 #24
0
파일: lab3_1.py 프로젝트: viyer/ham_qam
def transmit_and_capture(data, outfile, length, title='Captured Data', verbose=False, fs_audio=48000, fs_sdr=240000, fc0=443.650e6,  plot=False):
    """Transmit and receive a signal.
    length seconds
    """
    sdr = RtlSdr()          # Create an RtlSdr object
    p = pyaudio.PyAudio()   # Create a PyAudio object
    Nsamples=256000*length
    fc = fc0*(1.0-85e-6)

    # Get device numbers
    din, dout, dusb = audio_dev_numbers(p, in_name='USB', out_name='default', debug=verbose)

    # Create SDR capture thread as daemon
    capture = threading.Thread(target=sdr_record, args=(sdr, outfile, Nsamples, fc, fs_sdr))
    capture.daemon = True

    # Create play thread as daemon
    play = threading.Thread(target=play_audio, args=(data, p, fs_audio, dusb))
    play.daemon = True

    # Start both threads
    capture.start()
    play.start()

    time.sleep(length+2)

    try:
        if plot:
            print 'Loading data...'
            y = np.load(outfile)
            print 'Generating plot...'
            tt,ff,xmf = myspectrogram_hann_ovlp(y, 256, fs_sdr, fc)
            plt.title(title)
            plt.show()
        else:
            print 'Captured data saved to ' + outfile
    except IOError:
        type, value, traceback = sys.exc_info()
        print('Error loading %s: %s' % (value.filename, value.strerror))
    except Exception as e:
        print 'Error: '+str(e)
    finally:
        print 'Cleaning up...'
        sdr.close()
        p.terminate()
        print 'Closed SDR and PyAudio'
예제 #25
0
def main():

    now = datetime.datetime.now()

    current_time = now.strftime("%H:%M:%S.%f")
    print("Current Time =", current_time)
    #aquire location

    #start calibration process (needed?)

    #start syc process

    sdr = RtlSdr()  # rtl-sdr instance
    # configure device
    timeToSample = 1  # in sec
    sampleRate = 2.4e6  # in Mhz
    sdr.sample_rate = sampleRate
    sdr.center_freq = 433e6  # in Mhz
    sdr.gain = 30  # in dB
    print("gain set to:", sdr.get_gain())
    print(now)

    numberOfSamples = sampleRate * timeToSample
    fig = figure()
    ax = fig.add_subplot(111, projection='3d')  # used for 3d IQ/time plot
    samples = sdr.read_samples(numberOfSamples)  # aquire samples
    sdr.close()
    # I/Q seperation
    real = samples.real
    imag = samples.imag
    samp = np.arange(0, numberOfSamples, 1)  # used as an axis
    #ax.scatter(samp[0:-1:100],real[0:-1:100],imag[0:-1:100],marker='^',s=2)#used for pumba slack

    simulateRecivers(real, sampleRate)  # used to simulation
    #plt.subplot(3, 1, 2)
    # xlabel('Real axis')#used for pumba slack
    # ylabel('img axis')#used for pumba slack
    '''
    pxx,farr=psd(samples, NFFT=1024, Fs=sampleRate / 1e6, Fc=sdr.center_freq / 1e6)
    plt.subplot(2, 1, 1)
    plt.plot(samp, imag)
    plt.subplot(2, 1, 2)
    plt.plot(farr,pxx)
    '''
    show()
예제 #26
0
 def find_devices() -> str:
     devices = ""
     # could do with a call that returns the valid device_index's
     max_device = 10
     for device in range(max_device):
         try:
             sdr = RtlSdr(device_index=device)
             type_of_tuner = sdr.get_tuner_type()
             # index = sdr.get_device_index_by_serial('0000001')  # permissions required
             # addresses = sdr.get_device_serial_addresses() # permissions required
             sdr.close()
             devices += f"device {device}, type {type_of_tuner} {allowed_tuner_types[type_of_tuner]}\n"
         except Exception:
             pass
     if devices == "":
         devices = f"No rtlsdr devices found, scanned 0 to {max_device-1}"
     print(devices)
     return devices
예제 #27
0
def main():

    sdr = RtlSdr(1)

    wf = Waterfall(sdr)

    # some defaults

    sdr.rs = 1.024e6

    sdr.fc = 89.3e6

    sdr.gain = 'auto'

    wf.start()

    # cleanup

    sdr.close()
예제 #28
0
def main():
    sdr = RtlSdr()

    print 'Configuring SDR...'
    sdr.rs = 2.4e6
    sdr.fc = 70e6
    sdr.gain = 4
    print '  sample rate: %0.6f MHz' % (sdr.rs / 1e6)
    print '  center frequency %0.6f MHz' % (sdr.fc / 1e6)
    print '  gain: %d dB' % sdr.gain

    print 'Reading samples...'
    samples = sdr.read_samples(1024)
    print '  signal mean:', sum(samples) / len(samples)

    print 'Testing callback...'
    sdr.read_samples_async(test_callback)

    sdr.close()
예제 #29
0
def main():
    sdr = RtlSdr()

    print 'Configuring SDR...'
    sdr.rs = 2.4e6
    sdr.fc = 70e6
    sdr.gain = 4
    print '  sample rate: %0.6f MHz' % (sdr.rs/1e6)
    print '  center frequency %0.6f MHz' % (sdr.fc/1e6)
    print '  gain: %d dB' % sdr.gain

    print 'Reading samples...'
    samples = sdr.read_samples(1024)
    print '  signal mean:', sum(samples)/len(samples)

    print 'Testing callback...'
    sdr.read_samples_async(test_callback)

    sdr.close()
def read_n_plot():
    sdr = RtlSdr()
    # configure device
    sdr.sample_rate = 2.4e6
    sdr.center_freq = 90e6
    sdr.gain = 4
    samples = sdr.read_samples(12000 * 1024)
    sdr.close()
    demod_result = demodulate(samples)

    write_to_txt(demod_result)
    write_to_audio(demod_result, "recmusic.wav")
    plot_t(demod_result)

    # use matplotlib to estimate and plot the PSD
    psd(samples, NFFT=1024, Fs=sdr.sample_rate / 1e6, Fc=sdr.center_freq / 1e6)
    xlabel('Frequency (MHz)')
    ylabel('Relative power (dB)')
    show()
예제 #31
0
def capture(freq, label, range_freq, range_gain):
    for freq_var in range_freq:
        for gain_var in range_gain:
            # Configure device (freq in herz, freq_correction is PPM)
            sdr = RtlSdr()
            sdr.sample_rate = 250000
            sdr.center_freq = freq + freq_var
            sdr.freq_correction = 60
            sdr.gain = gain_var
            # Read 10 seconds of 250k sampled data
            samples = sdr.read_samples(10 * 256 * 1024)
            sdr.close()

            # Use matplotlib to estimate and plot the PSD
            psd(samples[:65536],
                NFFT=1024,
                Fs=sdr.sample_rate / 1e6,
                Fc=sdr.center_freq / 1e6)
            #print(psd)
            xlabel('Frequency (MHz)')
            ylabel('Relative power (dB)')
            # Show and save a pic
            #show()
            file_name = 'data-' + label + '-' + str(
                double(freq + freq_var)) + '-g-' + str(gain_var)
            print("Saving " + file_name)
            savefig(file_name + '.png')

            # Save samples to file
            fh = open(file_name + '.iq', "wb")
            x = samples
            x = x[:5000000]

            for sample in x:
                ba = bytearray(struct.pack("f", numpy.float32(sample.real)))
                for b in ba:
                    fh.write(bytearray([b]))

                ba = bytearray(struct.pack("f", numpy.float32(sample.imag)))
                for b in ba:
                    fh.write(bytearray([b]))
            fh.close()
            clf()
예제 #32
0
def find_powerfull_FM():
    sdr = RtlSdr()
    # configure device
    Fs = 2e6  # Hz
    sdr.sample_rate = Fs  # Hz
    sdr.freq_correction = 60  # PPM
    sdr.gain = 'auto'

    FM_band_min = 87.5
    FM_band_max = 109

    powe = np.ndarray(0)
    freq = np.ndarray(0)

    t_sampling = 0.1  # Sampling for 100 ms
    N_samples = round(Fs * t_sampling)

    for i in np.arange(FM_band_min, FM_band_max, Fs / 1e6):
        sdr.center_freq = i * 1e6  # Hz
        counter = 0
        prev_int = 0
        while 1:
            counter = counter + 1
            samples = sdr.read_samples(N_samples)
            ###################################################################################
            power, psd_freq = plt.psd(samples,
                                      NFFT=1024,
                                      Fs=sdr.sample_rate / 1e6,
                                      Fc=sdr.center_freq / 1e6)
            #####################################################################################
            ind_pow = np.argmax(power)
            freq_ind = round(psd_freq[ind_pow], 1)
            if freq_ind == prev_int and counter >= 3:
                powe = np.append(powe, ind_pow)
                freq = np.append(freq, freq_ind)
                break
            prev_int = freq_ind
    # done
    sdr.close()
    max_fm_station_power = np.argmax(powe)
    max_fm_station_freq = freq[max_fm_station_power]
    return max_fm_station_freq
예제 #33
0
def main():

    gin = sys.argv[1]
    ppm = sys.argv[2]
    chn = sys.argv[3]
    if ppm == '0': ppm = '1'
    if chn == 'a': frc = 161.975e6
    if chn == 'b': frc = 162.025e6

    sdr = RtlSdr()
    wf = Waterfall(sdr)

    # some defaults
    sdr.rs = 1e6
    sdr.fc = frc
    sdr.gain = float(gin)
    sdr.freq_correction = int(float(ppm))

    wf.start()

    # cleanup
    sdr.close()
예제 #34
0
def main():

    gin=sys.argv[1]
    ppm=sys.argv[2]
    chn=sys.argv[3]
    if ppm=='0': ppm='1'
    if chn=='a': frc=161.975e6
    if chn=='b': frc=162.025e6

    sdr = RtlSdr()
    wf = Waterfall(sdr)

    # some defaults
    sdr.rs = 1e6
    sdr.fc = frc
    sdr.gain = float(gin)
    sdr.freq_correction = int(float(ppm))

    wf.start()

    # cleanup
    sdr.close()
예제 #35
0
async def streaming(sample_processor: Callable[[SampleStream, RtlSdr], None],
                    center_freq=100300000,
                    sample_rate=2.048e6):
    """SDR streaming function
    :param sample_processor: Function that is used to process the samples, must
        take an array of floats as the first argument and an sdr object
        (for metadata) as the second
    :param sample_rate: The sample rate to obtain samples at in Hz
    :param center_freq int: The center frequency for capturing in Hz
    """
    sdr = RtlSdr()
    sdr.sample_rate=sample_rate
    sdr.center_freq = center_freq
    sdr.freq_correction = 60
    sdr.gain = 'auto'

    async for samples in sdr.stream():
        sample_processor(samples, sdr)

    await sdr.stop()

    sdr.close()
def storing_stream_with_windows(l, device_number, folder, subfolders, center_frequency, samplerate, gain, nsamples, freq_correction,
                   user_hash):
    l.acquire()
    print(device_number, center_frequency, samplerate, gain, nsamples, freq_correction)
    # configure device
    sdr = RtlSdr(device_index=device_number)
    sdr.center_freq = center_frequency
    sdr.sample_rate = samplerate
    if freq_correction:
        sdr.freq_correction = freq_correction   # PPM
    sdr.gain = gain
    print('hello world')
    timestamp = time.mktime(time.gmtime())
    samples = sdr.read_bytes(nsamples*2)
    sdr.close()
    l.release()

    print("save")
    basename = "{hash}_{freq}_{time:0.0f}".format(hash=user_hash, freq=center_frequency, time=timestamp)
    filename = path.join(folder, subfolders[0], "tmp_" + basename)
    # np.savez_compressed(filename, samples) # storing by numpy and copressing it
    '''np.save(filename, samples)
    os.rename(filename + ".npy",
              path.join(folder, subfolders[0], basename + ".npy"))'''

    f = open(filename, 'wb')
    f.write(samples)
    f.close()
    os.rename(filename,
              path.join(folder, subfolders[0], basename + ".dat"))

    del samples

    filename = path.join(folder, subfolders[1], basename + ".npy")
    sdrmeta(filename, device_number, folder, subfolders, center_frequency,
            samplerate, gain, nsamples, freq_correction, user_hash)

    return filename
예제 #37
0
def main():
    sdr = RtlSdr()
    wf = Waterfall(sdr)

    # some defaults
    sdr.rs = 1e6
    sdr.fc = 103.4e6
    sdr.gain = 10

    # mqtt client

    client.on_connect = on_connect
    client.username_pw_set("slip","slip")
    client.connect("ec2-35-180-123-52.eu-west-3.compute.amazonaws.com",1883)
   
    
    #client.loop_start()
    #client.publish("laverie/1","102.5,0")
    #client.disconnect()
#client.loop_stop()
    wf.start()
    # cleanup
    sdr.close()
예제 #38
0
    def from_rtl(self, freq=93.3e6, rate=256000, samples=8192000):
        try:
            sdr = RtlSdr()

            # configure device
            # in Hz
            sdr.sample_rate = int(rate)
            sdr.center_freq = freq
            sdr.gain = 'auto'

            # Read samples
            samples = sdr.read_samples(samples)
            # Clean up the SDR device
            sdr.close()
            del (sdr)

            self.data = np.array(samples).astype('complex64')
            self.dtype = self.data.dtype
            self.rate = rate * u.Hz
            self.center_freq = freq * u.Hz
            self.nitems = len(self.data)
            self.exptime = (self.nitems / self.rate)
        except:
            raise IOError("Could not read from RTLSDR")
예제 #39
0
def storing_stream_with_windows(lock, rs, cf, gain, ns, device, path_storing):

    if 0==0:#librtlsdr.rtlsdr_get_device_count() > 0:
        lock.acquire(timeout=ns/rs*1.1)
        print("locked")
        sdr = RtlSdr(device_index = device)

        # some defaults
        sdr.rs = rs
        sdr.fc = cf
        sdr.gain = gain

        timestamp = time.time()
        samples = sdr.read_bytes(ns * 2)
        sdr.close()

        lock.release()
    #print("print")

        filename = get_groundstationid() + "_f" + str(cf) + "_d" + str(device) + "_t" + str(int(timestamp))
        f = open(path_storing + filename + ".tmp", 'wb')
        f.write(samples)
        f.close()
        os.rename(path_storing + filename + ".tmp", path_storing + filename + ".dat")
예제 #40
0
class FMRadio:

     # num samplesmust be multiple of 256


    def __init__(self,freq,N_samples):

        self.sample_rate = 1e6
        self.decim_r1 = 1e6/2e5 # for wideband fm
        self.decim_r2 = 2e5/44100 # for baseband recovery
        self.center_freq = freq+250e3
        self.gain = 36

        self.N_samples = N_samples

        self.sdr =  RtlSdr()
        self.sdr.direct_sampling = 1
        self.sdr.sample_rate = self.sample_rate
        self.sdr.center_freq = self.center_freq
        self.sdr.gain = 'auto' #self.gain

        self.pa = pyaudio.PyAudio()
        self.stream = self.pa.open( format = pyaudio.paFloat32,
                                    channels = 2,
                                    rate = 44100,
                                    output = True)

        adj = 0
        hamming = 10*signal.hamming(self.N_samples*.10 + adj)
        lpf = np.append( np.zeros(self.N_samples*.45),hamming)
        self.lpf = np.roll(np.fft.fftshift(np.append(lpf,np.zeros(self.N_samples*.45))),int(-.25*self.N_samples))

    def __del__(self):
        print "sdr closed"
        self.sdr.close()
        print "pyaudio terminated"
        self.pa.terminate()

    def getSamples(self):
        #N_samples = self.N_samples # 1/24.4 seconds   ~46336 #approximately a blocksize amount's time
        return self.sdr.read_samples(self.N_samples)


#    def demodulate_threaded(self,samples):
#        async_demodulation = self.pool.apply_async(self.demodulate, samples, callback=self.play)


    def demodulate(self,samples):
        # DEMODULATION CODE
        #samples = #self.sample_buffer.get()
        # LIMITER goes here

        # low pass & down sampling via fft

        spectrum = np.fft.fft(samples)*self.lpf

        toplot = False
        if(toplot):
            fig = plt.figure()
            plt.plot(np.abs(spectrum))
            plt.show()

# Decimate in two rounds. One to 200k, another to 44.1k
        # DECIMATE HERE. Note that we're looking at 1MHz bandwidth.
        n_s = spectrum.size

        channel_spectrum = spectrum[int(n_s*.75-.5*n_s/self.decim_r1):int(.75*n_s+.5*n_s/self.decim_r1)] #np.append(spectrum[0:int(n_s/self.decim_r1*.5)],spectrum[n_s-int(n_s/self.decim_r1*.5):n_s])

        #radio_spectrum -= np.mean(radio_spectrum) #attempt to remove dc bias
        #print channel_spectrum.size
        toplot = False
        if(toplot):
            fig = plt.figure()
            plt.plot(np.abs(np.fft.ifftshift(channel_spectrum)))
            plt.show()


        lp_samples = np.fft.ifft(np.fft.ifftshift(channel_spectrum))


        power = np.abs(self.rms(lp_samples))
        lp_samples /= power
        #lp_samples = self.lowpass_filter(lp_samples,4)

    # polar discriminator

        A = lp_samples[1:lp_samples.size]
        B = lp_samples[0:lp_samples.size-1]

        dphase = ( A * np.conj(B) )

#dpm = np.mean(np.abs(dphase))
        # normalize
        #       dphase /= dpm
        dphase.resize(dphase.size+1)
        dphase[dphase.size-1] = dphase[dphase.size-2]

        rebuilt = signal.medfilt(np.angle(dphase)/np.pi,21) #  np.cos(dphase)

        #phase = np.sin(rebuilt)
        #phase = self.lowpass_filter(phase,8)

        #rebuilt= self.lowpass_filter(rebuilt,8)

        toplot = False
        if toplot:
            fig = plt.figure()
            ax = fig.add_subplot(111)
            ax.plot(rebuilt)

            plt.show()

        modulated = rebuilt * np.sin(2*np.pi*38000/2e5*np.r_[0:rebuilt.size])

        spectrum = np.fft.fft(rebuilt)
        mod_spectrum = np.fft.fft(modulated) #* self.lpf2



        n_z = spectrum.size
        #base_spectrum = np.append(spectrum[0:1024],spectrum[n_z-1024:n_z])
        base_spectrum = np.append(spectrum[0:int(n_z/self.decim_r2*.5)],spectrum[n_z-int(n_z/self.decim_r2*.5):n_s])
        stereo_spectrum = np.append(mod_spectrum[0:int(n_z/self.decim_r2*.5)],mod_spectrum[n_z-int(n_z/self.decim_r2*.5):n_s])
        stereo_spectrum *= np.fft.ifftshift(np.hamming(stereo_spectrum.size))

        toplot = False
        if(toplot):
            fig = plt.figure()
            plt.plot(np.linspace(-22050,22050,stereo_spectrum.size),np.abs(np.fft.fftshift(stereo_spectrum)),
                     np.linspace(-22050,22050,base_spectrum.size),.05*np.abs(np.fft.fftshift(base_spectrum)))
            plt.show()


        output = np.fft.ifft(base_spectrum)
        diff =np.fft.ifft(stereo_spectrum)
        #check: should be 1807 or very close to it. it is!!

        #output = self.lowpass_filter(np.real(output),8) #[12:8204]
        stereo = np.zeros(output.size*2,dtype='complex')
        left = output + 10*diff
        right = output - 10* diff
        stereo[0:stereo.size:2] = left
        stereo[1:stereo.size:2] = right
        #print 1e6/n_s / 44100 * output.size
        return np.real(stereo)


    def demodulate2(self,samples):
        # DEMODULATION CODE

        # LIMITER goes here

        # low pass & down sampling
        lp_samples = signal.decimate(self.lowpass_filter(samples,16),int(self.decim_r1))


    # polar discriminator

        A = lp_samples[1:lp_samples.size]
        B = lp_samples[0:lp_samples.size-1]

        dphase = ( A * np.conj(B) )

        dphase.resize(dphase.size+1)
        dphase[dphase.size-1] = dphase[dphase.size-2]

        rebuilt = signal.medfilt(np.angle(dphase)/np.pi,15) #  np.cos(dphase)

        output = signal.decimate(rebuilt,int(self.decim_r2))

        return np.real(output)

    def lowpass_filter(self,x,width):
        #wndw = np.sinc(np.r_[-15:16]/np.pi)/np.pi
        wndw = np.kaiser(width,6)
        wndw /= np.sum(wndw)
        new_array = signal.fftconvolve(x, wndw)

        return new_array[int(width/2):x.size+int(width/2)]

   # calculate rms for power #
    def rms(self,samples):
        meansq = np.mean(np.square(samples))
        return np.sqrt(meansq)

    def play(self,samples):
        self.stream.write( samples.astype(np.float32).tostring() )

    def start(self):
        while True:
            self.play(self.demodulate(self.getSamples()))
예제 #41
0
class FMRadio:

    sample_buffer = Queue.Queue(maxsize=100)
    base_spectrum = np.ones(5780)

    def __init__(self,freq,N_samples):

        self.sample_rate = 1e6
        self.decim_r1 = 1e6/2e5 # for wideband fm
        self.decim_r2 = 2e5/44100 # for baseband recovery
        self.center_freq = freq+250e3
        self.gain = 36

        self.N_samples = N_samples
        self.is_sampling = False

        self.sdr =  RtlSdr()
        self.sdr.direct_sampling = 1
        self.sdr.sample_rate = self.sample_rate
        self.sdr.center_freq = self.center_freq
        self.sdr.gain = self.gain

        self.pa = pyaudio.PyAudio()
        self.stream = self.pa.open( format = pyaudio.paFloat32,
                                    channels = 1,
                                    rate = 44100,
                                    output = True)

        adj = 0
        hamming = 10*signal.hamming(self.N_samples*.10 + adj)
        lpf = np.append( np.zeros(self.N_samples*.45),hamming)
        self.lpf = np.roll(np.fft.fftshift(np.append(lpf,np.zeros(self.N_samples*.45))),int(-.25*self.N_samples))

    def __del__(self):
        print "sdr closed"
        self.sdr.close()
        print "pyaudio terminated"
        self.pa.terminate()

    def getSamples(self):
        #N_samples = self.N_samples # 1/24.4 seconds   ~46336 #approximately a 2048/44100 amount's time
        return self.sdr.read_samples(self.N_samples)

    def getSamplesAsync(self):
        #Asynchronous call. Meant to be put in a loop w/ a calback fn
        #print 'gonna sample'
        self.is_sampling = True
        samples = self.sdr.read_samples_async(self.sampleCallback,self.N_samples,context=self)

    def sampleCallback(self,samples,sself):

        self.is_sampling = False
        self.sample_buffer.put(samples)
        #print 'put some samples in the jar'

        # recursive loop
        #sself.getSamplesAsync()

    def demodulate_th(self):
        while(1):

            try:
                samples = self.sample_buffer.get()
                #samples2 = self.sample_buffer.get()
              #  print 'gottum'
            except:
                print "wtf idk no samples?"
                break

            out1 = self.demodulate(samples)
            self.sample_buffer.task_done()
            #out2 = self.demodulate(samples2)
            #self.sample_buffer.task_done()

            audio_out = out1 #np.append(out1,out2)

            self.play(audio_out)

        print 'gonna try to finish off the to-do list'
        sample_buffer.join()


    def demodulate(self,samples):
        # DEMODULATION CODE
        #samples = #self.sample_buffer.get()
        # LIMITER goes here

        # low pass & down sampling via fft


        spectrum = np.fft.fft(samples)*self.lpf

        toplot = False
        if(toplot):
            fig = plt.figure()
            plt.plot(np.abs(spectrum))
            plt.show()

# Decimate in two rounds. One to 200k, another to 44.1k
        # DECIMATE HERE. Note that we're looking at 1MHz bandwidth.
        n_s = spectrum.size

        channel_spectrum = spectrum[int(n_s*.75-.5*n_s/self.decim_r1):int(.75*n_s+.5*n_s/self.decim_r1)] #np.append(spectrum[0:int(n_s/self.decim_r1*.5)],spectrum[n_s-int(n_s/self.decim_r1*.5):n_s])

        #radio_spectrum -= np.mean(radio_spectrum) #attempt to remove dc bias
        #print channel_spectrum.size
        toplot = False
        if(toplot):
            fig = plt.figure()
            plt.plot(np.abs(np.fft.ifftshift(channel_spectrum)))
            plt.show()


        lp_samples = np.fft.ifft(np.fft.ifftshift(channel_spectrum))

        #lp_samples = self.lowpass_filter(lp_samples,4)
        power = np.abs(self.rms(lp_samples))
        lp_samples /= power
        #print np.abs(self.rms(lp_samples))

    # polar discriminator
        dphase = np.zeros(lp_samples.size)

        A = lp_samples[1:lp_samples.size]
        B = lp_samples[0:lp_samples.size-1]

        dphase = ( A * np.conj(B) )

#dpm = np.mean(np.abs(dphase))
        # normalize
        #       dphase /= dpm
        #dphase.resize(dphase.size+1)
        dphase[dphase.size-1] = dphase[dphase.size-2]

        rebuilt = signal.medfilt(np.angle(dphase)/np.pi,21) #  np.cos(dphase)

        #phase = np.sin(rebuilt)
        #phase = self.lowpass_filter(phase,8)

        #rebuilt= self.lowpass_filter(rebuilt,8)

        toplot = False
        if toplot:
            fig = plt.figure()
            ax = fig.add_subplot(111)
            ax.plot(rebuilt)

            plt.show()


        spectrum = np.fft.fft(rebuilt) #* self.lpf2

        n_z = spectrum.size
        #base_spectrum = np.append(spectrum[0:1024],spectrum[n_z-1024:n_z])
        self.base_spectrum = np.append(spectrum[0:int(n_z/self.decim_r2*.5)],spectrum[n_z-int(n_z/self.decim_r2*.5):n_s])

        output = np.fft.ifft(self.base_spectrum)

        output = self.lowpass_filter(np.real(output),8) # just the tip (kills the 19k pilot)

#         toplot = False
#         if(toplot):
#             fig = plt.figure()
#             plt.plot(np.real(output))
#             plt.show()

        return np.real(output)

    def updateimg(self,base_spectrum):
        spectralimg = np.zeros((base_spectrum.size/20,base_spectrum.size/10))
        for i in np.r_[0:base_spectrum.size/10]:
            spectralimg[np.abs(np.fft.fftshift(base_spectrum)[i*10]/10),i] = 1
        cv2.imshow('spectrum',spectralimg)

    def demodulate2(self,samples):
        # DEMODULATION CODE

        # LIMITER goes here

        # low pass & down sampling
        lp_samples = signal.decimate(self.lowpass_filter(samples,16),int(self.decim_r1))


    # polar discriminator

        A = lp_samples[1:lp_samples.size]
        B = lp_samples[0:lp_samples.size-1]

        dphase = ( A * np.conj(B) )

        dphase.resize(dphase.size+1)
        dphase[dphase.size-1] = dphase[dphase.size-2]

        rebuilt = signal.medfilt(np.angle(dphase)/np.pi,15) #  np.cos(dphase)

        output = signal.decimate(rebuilt,int(self.decim_r2))

        return np.real(output)

# utility functions #

    def lowpass_filter(self,x,width):
        #wndw = np.sinc(np.r_[-15:16]/np.pi)/np.pi
        wndw = np.kaiser(width,6)
        #wndw /= np.sum(wndw)
        new_array = signal.fftconvolve(x, wndw)

        return new_array[int(width/2):x.size+int(width/2)]

    # calculate mean average deviation #
    def mad(self,samples):
        ave = np.mean(samples)
        return np.mean(np.abs(samples-ave))

    # calculate rms for power #
    def rms(self,samples):
        meansq = np.mean(np.square(samples))
        return np.sqrt(meansq)

    def play(self,samples):
        self.stream.write( samples.astype(np.float32).tostring() )



    def start(self):
        streamer = MakeDaemon(self.demodulate_th) # run demodulation in the 'background'
        streamer.start()
        self.count = 0
        while(1):
            if not self.is_sampling:
                self.getSamplesAsync() # sampler loop
예제 #42
0
class Demod:
  SAMP_RATE = 256000.
  SAMP_WINDOW = 1024*40

  def __init__(self):
    self.sdr = RtlSdr()
    # Sampling rate
    self.sdr.rs = Demod.SAMP_RATE
    # Pins 1 and 2
    self.sdr.set_direct_sampling(1)
    # I don't think this is used?
    self.sdr.gain = 1

  def run(self, limit=None, callback=lambda x: print(x),
                carrier=32000, bw=1000, sps=8, 
                codes=manchester, mod=Mods.MAGNITUDE, 
                header=HEADER, footer=FOOTER, pktlen=PKTBYTES):
    # Center frequency
    self.sdr.fc = carrier

    self.mod = mod
    self.header = header
    self.footer = footer
    self.pktlen = 8*pktlen + len(footer)

    self.rxcallback = callback

    decim = Demod.SAMP_RATE/bw/sps
    assert decim == int(decim)
    self.decim = int(decim)
    assert Demod.SAMP_WINDOW % self.decim == 0

    self.sampchips = Demod.SAMP_WINDOW / self.decim 
    self.corr = codes2corr(codes, sps)
    self.codelen = len(self.corr[0])

    self.last = np.zeros(Demod.SAMP_WINDOW)
    self.index = 0

    self.tocheck = [None] * self.codelen
    for i in range(self.codelen):
      self.tocheck[i] = dict()
      self.tocheck[i]['last'] = ''.join(range(0))
      self.tocheck[i]['pkts'] = range(0)

    if limit is None:
      def byte_callback(samp, sdr):
        if select.select([sys.stdin], [], [], 0)[0]:
          sdr.cancel_read_async()
        self.ddc(samp, sdr)
    else:
      @limit_calls(limit)
      def byte_callback(samp, sdr):
        if select.select([sys.stdin], [], [], 0)[0]:
          sdr.cancel_read_async()
        self.ddc(samp, sdr)

    self.sdr.read_bytes_async(byte_callback, Demod.SAMP_WINDOW*2)
    print (self.index, "samples read")
    sys.stdout.flush()
    sys.stdin.readline()

  def bb2c(self, baseband):
    mag = np.abs(baseband)
    phase = np.angle(baseband)
    dp = np.mod(np.ediff1d(phase)+np.pi, 2*np.pi)-np.pi
    return mag[1:], phase[1:], dp

  def decode(self, chips):
    corrs = []
    for c in self.corr:
      corrs.append(np.correlate(chips, c))
    # Vector correlations
    if np.iscomplex(corrs).any():
      corrs = np.abs(corrs)
    maxes = np.max(np.array(corrs), 0)
    codes = np.argmax(np.array(corrs), 0)
    return maxes, codes

  def debounce(self, i, l, rxstr):
    try:
      if i != self.debounce_i or abs(l - self.debounce_l) > 1:
        self.rxcallback(rxstr)
    except AttributeError:
      self.rxcallback(rxstr)
    self.debounce_i = i
    self.debounce_l = l

  def extract(self, nc):
    for codeoffset in range(self.codelen):
      pkts = []
      codestr = "".join(map(repr, map(int, nc[codeoffset::self.codelen])))

      for p in self.tocheck[codeoffset]['pkts']:
        pkt = p + codestr[0:self.pktlen-len(p)]
        if len(pkt) < self.pktlen:
          pkts.append(pkt)
        elif len(self.footer) == 0 or pkt[-len(self.footer):] == self.footer:
          str = ""
          for j in range(0,len(pkt)-1,8):
            str += chr(int(pkt[j:j+8][::-1], 2))
          self.debounce(self.index, -len(p), str)
          sys.stdout.flush()

      codestr = self.tocheck[codeoffset]['last'] + codestr
      for ind in find_all(codestr, self.header):
        pkt = codestr[ind+len(self.header):ind+len(self.header)+self.pktlen]
        if len(pkt) < self.pktlen:
          pkts.append(pkt)
        elif len(self.footer) == 0 or pkt[-len(self.footer):] == self.footer:
          str = ""
          for j in range(0,len(pkt)-1,8):
            str += chr(int(pkt[j:j+8][::-1], 2))
          self.debounce(self.index, ind, str)
          sys.stdout.flush()
      self.tocheck[codeoffset]['pkts'] = [] + pkts
      self.tocheck[codeoffset]['last'] = "" + codestr[-len(self.header)+1:]

  def ddc(self, samp, sdr):
    s = np.asarray(samp)
    i, q = s[::2], s[1::2]
    i = np.mean(i.reshape(-1,self.decim), 1) # poor man's decimation
    q = np.mean(q.reshape(-1,self.decim), 1) # poor man's decimation
    iq = np.empty(len(i), 'complex')
    iq.real, iq.imag = i, q
    iq /= (255/2)
    iq -= (1 + 1j)

    baseband = np.concatenate((self.last, iq))
    self.last = iq
    mag, phase, dp  = self.bb2c(baseband)
    if self.mod == Mods.MAGNITUDE:
      sig = mag
    elif self.mod == Mods.PHASE:
      sig = phase
    elif self.mod == Mods.DPHASE:
      sig = dp
    else:
      sig = baseband
    corrs, codes = self.decode(sig)

    nc = codes[self.codelen:self.codelen+self.sampchips]
    self.extract(nc)

    self.index += 1

  def end(self):
    self.sdr.close()

  def plot(self):
    plt.ion()
    fig = plt.figure()
    ax1 = fig.add_subplot(311)
    ax1.plot(self.chips)
    ax2 = fig.add_subplot(312, sharex=ax1)
    ax2.plot(self.corrs)
    ax3 = fig.add_subplot(313, sharex=ax1)
    ax3.plot(self.demod)
    plt.show()

  def checkdemod(self, index, demod=None, packetlen=5):
    if demod is None:
      demod = self.demod
    l = packetlen*8+6+7
    b = self.demod[index:index+l*self.codelen:self.codelen]
    return chipsToString(np.concatenate(([1,0], b, [0])))

  def findstring(self, demod = None, packetlen=5):
    if demod is None:
      demod = self.demod
    find = []
    for i in range(len(demod)):
      s, c = self.checkdemod(i, demod, packetlen)
      if len(s) and s[0] == 'a' and s[-1] == 'x':
        find.append((i, s[1:-1]))
    return find
예제 #43
0
class FMRadio(QtGui.QMainWindow,Ui_MainWindow):
    sample_buffer = Queue.Queue(maxsize=10)
    base_spectrum = np.ones(5780)

    plotOverall = True
    plotChannel = False
    plotPlaying = False
    plotWaveform = False
    useStereo = False
    stereoWidth = 10
    useMedianFilt = True
    useLPFilt = True
    demodFiltSize = 100000
    useAudioFilter = True
    audioFilterSize = 16
    toDraw = True
    demodMain = True
    demodSub1 = False
    demodSub2 = False
    toDrawWaterfalls = True
    toDrawPlots = False

    prevCutoff = 0
    prevSpec1 = np.zeros(128)
    prevSpec2 = np.zeros(128)
    prevSpec3 = np.zeros(128)
    prevConvo1 = np.zeros(128)
    prevConvo2 = np.zeros(128,dtype='complex')

    limiterMax = np.zeros(32)

    toPlot = (np.cumsum(np.ones(5780)),np.cumsum(np.ones(5780)))

    def __init__(self,freq,N_samples):
        self.spectrogram = np.zeros((512,400))
        self.chspectrogram = np.zeros((512,400))
        self.plspectrogram = np.zeros((256,400))
        self.cur_spectrogram = self.spectrogram


        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.createQtConnections()
        ftxt = "%.1f MHz" % (freq/1e6)
        self.ui.curFreq.setText(ftxt)

        self.sample_rate = 2.4e5 # tried 1.024e6 - not so great
        self.decim_r1 = 1 # 1.024e6/2.4e5 # for wideband fm down from sample_rate
        self.decim_r2 = 2.4e5/48000 # for baseband recovery
        self.center_freq = freq #+250e3
        self.gain = 16

        self.N_samples = N_samples
        self.is_sampling = False



        self.sdr =  RtlSdr()
        #self.sdr.direct_sampling = 1
        self.sdr.sample_rate = self.sample_rate
        self.sdr.center_freq = self.center_freq
        self.sdr.gain = self.gain

        self.pa = pyaudio.PyAudio()
        self.stream = self.pa.open( format = pyaudio.paFloat32,
                                    channels = 2,
                                    rate = 48000,
                                    output = True)

        self.PLL = PhaseLockedLoop(self.N_samples,19000,self.sample_rate)

        self.initOpenCV()

        self.noisefilt = np.ones(6554)
        b,a = signal.butter(1, 2122/48000*2*np.pi, btype='low')
        self.demph_zf = signal.lfilter_zi(b, a)

        adj = 0
        hamming = np.kaiser(self.N_samples/4 + adj,1)
        lpf = np.append( np.zeros(self.N_samples*3/8),hamming)
        self.lpf = np.fft.fftshift(np.append(lpf,np.zeros(self.N_samples*3/8))) #,int(-.25*self.N_samples))

        hamming = 10*signal.hamming(self.N_samples/16)
        lpf = np.append(np.zeros(self.N_samples*15/32),hamming)
        self.lpf_s1 = (np.append(lpf,np.zeros(int(self.N_samples*15/32))))
        #self.lpf_s1 = np.roll(temp,int(.5*self.N_samples*67/120))
        #self.lpf_s1 += np.roll(temp,int(-.5*self.N_samples*67/120))
        self.lpf_s1 = np.fft.fftshift(self.lpf_s1)
        #self.lpf_s1 += np.fft.fftshift(self.lpf_s1)

#         fig = plt.figure()
#         ax = fig.add_subplot(111)
#         ax.plot(range(self.lpf_s1.size),self.lpf_s1)
#         fig.show()

        hamming = 10*signal.hamming(self.N_samples/32)
        lpf = np.append(np.zeros(self.N_samples*31/64),hamming)
        self.lpf_s2 = (np.append(lpf,np.zeros(int(self.N_samples*31/64))))
        #self.lpf_s2 = np.roll(temp,int(.5*self.N_samples*92/120))
        #self.lpf_s2 += np.roll(temp,int(-.5*self.N_samples*92/120))
        self.lpf_s2 = np.fft.fftshift(self.lpf_s2)

    # Not currently used
    def getSamples(self):
        return self.sdr.read_samples(self.N_samples);

    def getSamplesAsync(self):
        #Asynchronous call. Initiates a continuous loop with the callback fn
        self.is_sampling = True
        samples = self.sdr.read_samples_async(self.sampleCallback,self.N_samples,context=self)
    def sampleCallback(self,samples,sself):

        self.is_sampling = False
        self.sample_buffer.put(samples)
        #print 'put some samples in the jar'

        # recursive loop
        #sself.getSamplesAsync()

    def demodulate_th(self):
        # Initiates a loop to process all the incoming blocks of samples from the Queue
        # This should be run in its own thread, or the program will become unresponsive
        while(1):

            try:
                samples = self.sample_buffer.get()
                #samples2 = self.sample_buffer.get()
            except:
                #print "wtf idk no samples?"  # even though this can't happen... (although I'm not sure why not)
                #print 'gonna try to finish off the to-do list'
                #self.sample_buffer.join()
                break

            out1 = self.demodulate(samples)
            self.sample_buffer.task_done()
            #out2 = self.demodulate(samples2)
            #self.sample_buffer.task_done()

            audio_out = out1 #np.append(out1,out2)
            self.play(audio_out)

    def gen_spectrogram(self,x,m,prevSpec):
        itsreal = np.isreal(x[0])

        m = int(m)
        lx = x.size
        nt = (lx) // m
        #NT = (lx +m -1)//m
        #padsize = NT*m -lx
        cutsize = lx -nt*m
        padsize = int(cutsize + m/2)


        if not prevSpec.size == padsize:
            prevSpec = np.zeros(padsize)

        xp = np.append(x[cutsize:],prevSpec)
        prevSpec = x[:(padsize)]

        xh = np.zeros((m,nt*2), dtype='complex')
        for n in range(int(nt*2)):
            block = xp[m*n//2:m*(n+2)//2]

            xh[:,n] = block*np.hanning(block.size)


        #if self.prevSpec.size == padsize:
        #    xb = np.append(self.prevSpec[:prevSpec.size-m/2],x)
        #    xc = np.append(self.prevSpec,x[:lx-m/2])
        #    self.prevSpec = x[lx-m/2:]
        #else:

        #    xb = np.append(x,np.zeros(-lx+nt*m))
        #    xc = np.append(x[m/2:],np.zeros(nt*m - lx + m/2))


        #xr = np.reshape(xb, (m,nt), order='F') * np.outer(np.hanning(m),np.ones(nt))
        #xs = np.reshape(xc, (m,nt), order='F') * np.outer(np.hanning(m),np.ones(nt))

        #xm = np.zeros((m,2*nt),dtype='complex')
        #xm[:,::2] = xr
        #xm[:,1::2] = xs

        if itsreal:
            spec = np.fft.fft(xh,m,axis=0)
            spec = spec[:m//2,:]
        else:
            spec = np.fft.fftshift(np.fft.fft(xh,m,axis=0))
        #mx = np.max(spec)

        pwr = np.log(np.abs(spec) + 1e-6)

        return (np.real(pwr),prevSpec)

    def initOpenCV(self):
        cv2.namedWindow("Spectrogram")

    def demodulate(self,samples):
        # DEMODULATION CODE - And the core function
        # samples must be passed in by the caller
        self.count += 1

        #spectral_window = signal.hanning

        #spectrum = np.fft.fftshift(np.fft.fft(samples*spectral_window(samples.size)))

        self.spectrogram = np.roll(self.spectrogram, 16,axis=1)
        stft,self.prevSpec1 = self.gen_spectrogram(samples,samples.size//8,self.prevSpec1)
        self.spectrogram[:,:16] = stft[::8,:]     # np.log(np.abs(spectrum[::100]))

        if(self.plotOverall): # and self.count % 10 == 9):
            #self.drawSpectrum()
            self.cur_spectrogram = self.spectrogram
            self.drawCurSpectrum()

#         cutoff = self.demodFiltSize
#         h = signal.firwin(128, cutoff,nyq=self.sample_rate/2)
#         lp = signal.fftconvolve(samples[::self.decim_r1],h,mode='full')
#         lps = lp.size
#         hs = h.size
#         prev = lp[lps-hs:]
#         lp[:hs/2] += self.prevConvo2[hs/2:]
#         lp = np.append(self.prevConvo2[:hs/2],lp)
#         self.prevConvo2 = prev
#         lp_samples = lp[:lps-hs+1]
        lp_samples = samples

        power = np.abs(self.mad(lp_samples))
        self.ui.signalMeter.setValue(20*(np.log10(power)))


    # polar discriminator

        dphase = np.zeros(lp_samples.size, dtype='complex')

        A = lp_samples[1:lp_samples.size]
        B = lp_samples[0:lp_samples.size-1]

        dphase[1:] = ( A * np.conj(B) )

        dphase[0] = lp_samples[0] * np.conj(self.prevCutoff) #dphase[dphase.size-2]
        self.prevCutoff = lp_samples[lp_samples.size-1]

    # limiting

        dphase /= np.abs(dphase)

#         if self.useMedianFilt:
#             rebuilt = signal.medfilt(np.angle(dphase)/np.pi,self.demodFiltSize) #  np.cos(dphase)
#         else:
#             rebuilt = self.lowpass(np.angle(dphase),self.demodFiltSize)

        rebuilt = np.real(np.angle(dphase) / np.pi)



        demodMain = False
        demodSub1 = False
        demodSub2 = False
        isStereo = False
        if self.demodMain:
            demodMain = True
            if self.useStereo:
                isStereo = True
        elif self.demodSub1:
            demodSub1 = True
        elif self.demodSub2:
            demodSub2 = True

        #spectrum = np.fft.fft(rebuilt* spectral_window(rebuilt.size))
        #print rebuilt.size/8
        self.chspectrogram = np.roll(self.chspectrogram, 16,axis=1)
        stft,self.prevSpec2 = self.gen_spectrogram(rebuilt,rebuilt.size/8,self.prevSpec2)
        self.chspectrogram[:,:16] = stft[::-4,:]                          # np.log(np.abs(spectrum[spectrum.size/2:spectrum.size:50]))
        if(self.plotChannel):# and self.count % 10 == 9):
            self.cur_spectrogram = self.chspectrogram
            self.drawCurSpectrum()
             #plotspectrum = np.abs(channel_spectrum[::100])
             #self.toPlot = (np.linspace(-np.pi,np.pi,plotspectrum.size),plotspectrum)
             #self.replot()


        n_z = rebuilt.size
        if demodMain:

            h = signal.firwin(128,16000,nyq=1.2e5)
            output = signal.fftconvolve(rebuilt,h,mode='full')
            outputa = output    # could be done in place but I'm not concerned with memory

            outputa[:h.size/2] += self.prevConvo1[h.size/2:]   #add the latter half of tail end of the previous convolution
            outputa = np.append(self.prevConvo1[:h.size/2], outputa) # also delayed by half size of h so append the first half

            self.prevConvo1 = output[output.size-h.size:]   # set the tail for next iteration

            output = outputa[:output.size-h.size:self.decim_r2]  # chop off the tail and decimate


            #stereo_spectrum = spectrum
            if isStereo:

                #pilot = rebuilt * np.cos(2*np.pi*19/240*(np.r_[0:rebuilt.size]))
                h = signal.firwin(512,[18000,20000],pass_zero=False,nyq=1.2e5)
                pilot_actual = signal.fftconvolve(rebuilt,h,mode='same')
                self.PLL.adjust(pilot_actual)


                moddif = rebuilt * np.real(np.square(self.PLL.pll)) #np.cos(2*np.pi*38/240*(np.r_[0:ss] - phase_shift))
                h = signal.firwin(128,16000,nyq=1.2e5)
                moddif = signal.fftconvolve(moddif,h,mode='same')

                h = signal.firwin(64,16000,nyq=48000/2)
                diff = signal.fftconvolve(moddif[::self.decim_r2],h,mode='same')
                diff = np.real(diff)
#                 rdbs = rebuilt * np.power(self.PLL.pll,3)
#                 h = signal.hanning(1024)
#                 rdbs = signal.fftconvolve(rdbs,h)
#                 if np.mean(rdbs) > 0:
#                     # bit ONE
#                 else:
#                     # bit ZERO

        elif demodSub1:


            demod = rebuilt * np.exp(-2j*np.pi*67650/2.4e5*np.r_[0:rebuilt.size])

            h = signal.firwin(128,7500,nyq=2.4e5/2)
            lp_demod = signal.fftconvolve(demod,h,mode='same')
            decim = lp_demod[::self.decim_r2]


            dphase = np.zeros(decim.size, dtype='complex')
#
            A = decim[1:decim.size]
            B = decim[0:decim.size-1]
#
            dphase[1:] = np.real(np.angle( A * np.conj(B) ))
            h = signal.firwin(128,7500,nyq=24000)
            output = signal.fftconvolve(dphase,h,mode='same')


        elif demodSub2:
            demod = rebuilt * np.exp(-2j*np.pi*92000/2.4e5*np.r_[0:rebuilt.size])

            h = signal.firwin(128,7500,nyq=2.4e5/2)
            lp_demod = signal.fftconvolve(demod,h,mode='same')
            decim = lp_demod[::self.decim_r2]


            dphase = np.zeros(decim.size, dtype='complex')
#
            A = decim[1:decim.size]
            B = decim[0:decim.size-1]
#
            dphase[1:] = np.real(np.angle( A * np.conj(B) ))
            h = signal.firwin(128,7500,nyq=24000)
            output = signal.fftconvolve(dphase,h,mode='same')

        # DC block filter, lol, srsly
        output = np.real(output) - np.mean(np.real(output))

        if np.isnan(output[0]):
            #print "error" # for some reason, output is NaN for the first 2 loops
            return np.zeros(6554)

        # deemphasis - # 2122/samplerate*2 *pi  - butterworth filter
        b,a = signal.butter(1, 2122/48000*2*np.pi, btype='low')
        output, zf = signal.lfilter(b, a, output,zi=self.demph_zf)
        self.demph_zf = zf

        stereo = np.zeros(output.size*2)
        if (isStereo):

            diff = signal.lfilter(b,a,diff)
            w = self.stereoWidth  # adjust to change stereo wideness
            left = output + w/10 * diff
            right = output - w/10 * diff

            if(self.useAudioFilter):
                left = self.lowpass(left,self.audioFilterSize)
                right = self.lowpass(right,self.audioFilterSize)

            stereo[0:stereo.size:2] = left
            stereo[1:stereo.size:2] = right
        else:
            if self.useAudioFilter:
                output = self.lowpass(output,self.audioFilterSize) # just the tip (kills the 19k pilot)
            stereo[0:stereo.size:2] = output
            stereo[1:stereo.size:2] = output

        #normalize to avoid any possible clipping when playing
        stereo /= 2*np.max(stereo)
        #spectrum = np.fft.fft(stereo[::2])
        output = .5*(stereo[::2]+stereo[1::2])

        #spectrum = np.fft.fft(.5*(stereo[::2]+stereo[1::2])*spectral_window(output.size))
        self.plspectrogram = np.roll(self.plspectrogram, 24,axis=1)
        stft,self.prevSpec3 = self.gen_spectrogram(output,512,self.prevSpec3)
        self.plspectrogram[:,:24] = stft[::-1,:]  # np.log(np.abs(spectrum[spectrum.size/2:spectrum.size:20]))
        if(self.plotPlaying): # and self.count % 2 == 0):
            #if self.toDrawWaterfalls:
            self.cur_spectrogram = self.plspectrogram
            self.drawCurSpectrum(invert=True)

                #self.drawPlspectrum()
            #else:

            #    sm = np.abs(np.fft.fftshift(spectrum[::20]))
            #    toPlot = (np.linspace(-2.4e4,2.4e4,sm.size),sm)
            #    self.replot(toPlot)


        #if(self.toDraw and self.plotWaveform):
        #    if self.toDrawWaterfalls:
        #        sm = np.real(output[::20])
        #        toPlot = (np.linspace(0,output.size/48000,sm.size),sm)
        #        self.replot(toPlot)
        #    else:
        #        sm = np.real(self.PLL.pll[::200])
        #        toPlot = (np.linspace(0,output.size/48000,sm.size),sm)
        #        self.replot(toPlot)

        return np.real(stereo)


    # Alternate demodulator. Not used, but extremely simple
    def demodulate2(self,samples):
        # DEMODULATION CODE

        # LIMITER goes here

        # low pass & down sampling
        h = signal.firwin(128,80000,nyq=1.2e5)
        lp_samples = signal.fftconvolve(samples, h)

    # polar discriminator

        A = lp_samples[1:lp_samples.size]
        B = lp_samples[0:lp_samples.size-1]

        dphase = ( A * np.conj(B) ) / np.pi

        dphase.resize(dphase.size+1)
        dphase[dphase.size-1] = dphase[dphase.size-2]

        h = signal.firwin(128,16000,nyq=1.2e5)
        rebuilt = signal.fftconvolve(dphase,h)

        output = rebuilt[::self.decim_r2]

        output = self.lowpass(output, self.audioFilterSize)

        return np.real(output)

# utility functions #

    def lowpass(self,x,width):
        #wndw = np.sinc(np.r_[-15:16]/np.pi)/np.pi
        #wndw = np.kaiser(width,6)
        wndw = signal.firwin(16,width*999,nyq=24000)
        #wndw /= np.sum(wndw)
        new_array = signal.fftconvolve(x, wndw, mode='same')

        return new_array

    # calculate mean average deviation #
    def mad(self,samples):
        ave = np.mean(samples)
        return np.mean(np.abs(samples-ave))

    # calculate rms for power #
    def rms(self,samples):
        meansq = np.mean(np.square(samples))
        return np.sqrt(meansq)

    def play(self,samples):
        self.stream.write( samples.astype(np.float32).tostring() )


    # starting point
    def start(self):
        # Initiates running things
        self.streamer = MakeDaemon(self.demodulate_th) # run demodulation in the 'background'
        self.streamer.start()
        self.count = 0
        self.sampler_t = threading.Thread(target=self.getSamplesAsync) # sampler loop
        self.sampler_t.start()


    def createQtConnections(self):

        QtCore.QObject.connect(self.ui.freqSelect, QtCore.SIGNAL(_fromUtf8("valueChanged(int)")), self.setFreq)
        QtCore.QObject.connect(self.ui.checkBox, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.setUseStereo)
        QtCore.QObject.connect(self.ui.mainchannel, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDemodMain)
        QtCore.QObject.connect(self.ui.subband1, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDemodSub1)
        QtCore.QObject.connect(self.ui.subband2, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDemodSub2)
        QtCore.QObject.connect(self.ui.stereoWidthSlider, QtCore.SIGNAL(_fromUtf8("sliderMoved(int)")), self.setStereoWidth)
        QtCore.QObject.connect(self.ui.spectrum_overall, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setSpectrumOverall)
        QtCore.QObject.connect(self.ui.spectrum_channel, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setSpectrumChannel)
        QtCore.QObject.connect(self.ui.spectrum_playing, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setSpectrumPlaying)
        QtCore.QObject.connect(self.ui.spectrum_waveform, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setSpectrumWaveform)
        QtCore.QObject.connect(self.ui.demodFiltMedian, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDemodFiltMedian)
        QtCore.QObject.connect(self.ui.demodFiltLP, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDemodFiltLP)
        QtCore.QObject.connect(self.ui.demodFilterSize, QtCore.SIGNAL(_fromUtf8("sliderMoved(int)")), self.setDemodFiltSize)
        QtCore.QObject.connect(self.ui.audioFilterActive, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setAudioFiltUse)
        QtCore.QObject.connect(self.ui.audioFilterSizeSlider, QtCore.SIGNAL(_fromUtf8("sliderMoved(int)")), self.setAudioFiltSize)
        QtCore.QObject.connect(self.ui.exitButton, QtCore.SIGNAL(_fromUtf8("clicked()")), self.terminate)
        QtCore.QObject.connect(self.ui.drawPlot, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDrawSpec)
        QtCore.QObject.connect(self.ui.waterfallButton, QtCore.SIGNAL(_fromUtf8('toggled(bool)')), self.setDrawWaterfalls)
      #  QtCore.QObject.connect(self.ui.plotButton, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDrawPlot)

        self.bindPlot()


    def bindPlot(self):
        self.dpi = 100
        self.fig = Figure((4.31,2.0), dpi=self.dpi)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.ui.plotFrame)

        self.initplot()


    def initplot(self):
        self.axes = self.fig.add_subplot(111, aspect=200/431)
        self.axes.xaxis.set_major_locator(ticker.NullLocator())
        self.axes.yaxis.set_major_locator(ticker.NullLocator())
        self.fig.tight_layout()
        #self.axes.invert_yaxis()

        #self.anim = animation.FuncAnimation(self.fig,self.drawCurSpectrum,interval=750)


    def replot(self,toPlot):
        self.axes.clear()
        self.axes.plot(toPlot[0],toPlot[1])
        self.axes.set_aspect('auto',anchor='C')
        self.canvas.draw()

    def setDrawSpec(self,s):
        self.toDraw = s

    def drawCurSpectrum(self,invert=False):
        #self.axes.clear()
        #self.axes.imshow(self.cur_spectrogram, cmap='spectral')
        #self.axes.xaxis.set_major_locator(ticker.NullLocator())
        #self.axes.yaxis.set_major_locator(ticker.NullLocator())
        #self.axes.set_aspect('auto',adjustable='box',anchor='NW')
        #self.canvas.draw()
        mx = np.max(self.cur_spectrogram)
        mn = np.min(self.cur_spectrogram)
        if invert:
            self.cur_spectrogram = -cv2.convertScaleAbs(self.cur_spectrogram,alpha=255 / (mx))
        else:
            self.cur_spectrogram = cv2.convertScaleAbs(self.cur_spectrogram,alpha=255 / (mn))
        self.cur_spectrogram = cv2.GaussianBlur(self.cur_spectrogram,(5,5),.6)
        cmapped =cv2.applyColorMap(self.cur_spectrogram,cv2.COLORMAP_JET)
        cv2.imshow('Spectrogram',cmapped)
        cv2.waitKey(1);

    def drawSpectrum(self):
        self.axes.clear()
        self.axes.imshow(self.spectrogram, cmap='spectral')
        self.axes.xaxis.set_major_locator(ticker.NullLocator())
        self.axes.yaxis.set_major_locator(ticker.NullLocator())
        self.axes.set_aspect('auto',adjustable='box',anchor='NW')
        self.canvas.draw()

    def drawChspectrum(self):
        self.axes.clear()
        self.axes.imshow(self.chspectrogram, cmap='spectral')
        self.axes.xaxis.set_major_locator(ticker.NullLocator())
        self.axes.yaxis.set_major_locator(ticker.NullLocator())
        self.axes.set_aspect('auto',adjustable='box',anchor='NW')
        self.canvas.draw()

    def drawPlspectrum(self):
        self.axes.clear()
        self.axes.imshow(self.plspectrogram, cmap='spectral')
        self.axes.xaxis.set_major_locator(ticker.NullLocator())
        self.axes.yaxis.set_major_locator(ticker.NullLocator())
        self.axes.set_aspect('auto',adjustable='box',anchor='NW')
        self.canvas.draw()

    def setDrawPlots(self,s):

        self.toDrawPlots = s
        self.toDrawWaterfalls = not s

    def setDrawWaterfalls(self,s):

        self.toDrawWaterfalls = s
        self.toDrawPlots = not s

    def setFreq(self,freq):
        if freq % 2 == 0:
            freq += 1
        freq /= 10.0
        text = "%.1f MHz" % freq
        self.ui.curFreq.setText(text)
        self.center_freq = freq*1e6 #+ 250e3
        setf_t = threading.Thread(target=self.setF_th, args=[self.center_freq,])
        setf_t.start()
        setf_t.join()



    # This function is what is used to adjust the tuner on the RTL
    # Currently, it causes the program to crash if used after an unspecified period of inactivity
    #     commented lines are attempts that didn't work
    def setF_th(self,f):
        while(self.is_sampling == True):
            pass
        #self.sdr.cancel_read_async()
        time.sleep(.1)
        self.sdr.center_freq = f
        #self.getSamplesAsync()

    def setUseStereo(self,u):
        self.useStereo = u
    def setStereoWidth(self,w):
        self.stereoWidth = w/5

    def setDemodMain(self,s):
        self.demodMain = s
        self.demodSub1 = not s
        self.demodSub2 = not s
        #self.useStereo = True
    def setDemodSub1(self,s):
        self.demodMain = not s
        self.demodSub1 = s
        self.demodSub2 = not s
        #self.useStereo = False
    def setDemodSub2(self,s):
        self.demodMain = not s
        self.demodSub1 = not s
        self.demodSub2 = s
        #self.useStereo = False

    def setSpectrumOverall(self,s):
        #self.initplot()
        #self.cur_spectrogram = self.spectrogram
        self.plotOverall = s
        self.plotChannel = not s
        self.plotPlaying = not s
        self.plotWaveform = not s
    def setSpectrumChannel(self,s):
        #self.initplot()
        self.plotChannel = s
        self.plotOverall = not s
        self.plotPlaying = not s
        self.plotWaveform = not s
    def setSpectrumPlaying(self,s):
        #self.initplot()
        self.plotPlaying = s
        self.plotChannel = not s
        self.plotOverall= not s
        self.plotWaveform = not s
    def setSpectrumWaveform(self,s):
        self.plotWaveform = s
        self.plotPlaying = not s
        self.plotChannel = not s
        self.plotOverall= not s

    def setDemodFiltMedian(self,s):
        self.useMedianFilt = s
        self.useLPFilt = not s
    def setDemodFiltLP(self,s):
        self.useLPFilt = s
        self.useMedianFilt = not s
    def setDemodFiltSize(self,s):
        #if(s % 2 == 0):
        #    s+=1
        self.demodFiltSize = s

    def setAudioFiltUse(self,s):
        self.useAudioFilter = s
    def setAudioFiltSize(self,s):
        self.audioFilterSize = s

    def terminate(self):
        self.__del__()

    # Destructor - also used to exit the program when user clicks "Quit"
    def __del__(self):

        # Program will continue running in the background unless the RTL is told to stop sampling
        self.sdr.cancel_read_async()
        print "sdr closed"
        self.sdr.close()
        print "pyaudio terminated"
        self.pa.terminate()
        cv2.destroyAllWindows()
예제 #44
0
class WSHandler(tornado.websocket.WebSocketHandler):    
    def check_origin(self, origin):
        return True

    def open(self):        
        self.siggen = SigGen()
        self.sdr = RtlSdr()    
        self.scan = Scan(self.sdr)
        self.rotor = Rotor()
        self.callback = PeriodicCallback(self.send_values, timeInterval)
        

    def send_values(self):
        print "::WS: Begin scanning...."
        scan_vals = self.scan.scan()
        
        print "::WS: Detecting Signal Peaks...."
        peaks = detect_peaks(scan_vals)
        
        print "::WS: Sending peak vals to WS...."
        self.write_message("++")
        self.write_message(json_encode(peaks))

    def on_message(self, message):

        print ":: Recvd message: %s" % message
        
        if (message.startswith("==Frequency:")):
                
                str = message.split("|");
                freq = str[0].split(" ")[1]
                rxgain = str[1].split(" ")[1]
                
                print "::WS: Setting Tx Freq:" + freq
                self.siggen.setTxFreq(freq)
                
                print "::WS: Setting Rx Freq:" + freq + "| RxGain: " + rxgain
                self.scan.setFreqGain(freq, rxgain)
                
                print "::WS: Initializing Callback function..."
                self.callback.start()			
                
        elif (message.startswith("==TxOff")):
                print "::WS: Resetting Callback"
                self.callback.stop()
                
                print "::WS: Setting Tx Off"			
                self.siggen.setTxOff()
                
                print "::WS: Closing SDR instance"
                #self.sdr.close()
				
        elif (message.startswith("==Rotor:")):   # ==Rotor: R|2000
			
                str = message.split("|");
                dir = str[0].split(" ")[1]
                deg = str[1]
                self.rotor.setRotor(dir,deg)
        
                        

    def on_close(self):
        print "::WS: Resetting Callback"
        self.callback.stop()
                
        print "::WS: Setting Tx Off"			
        self.siggen.setTxOff()
        
        print "::WS: Closing SDR instance"
        self.sdr.close()
        self.rotor.close();
        self.siggen.close();
def main():
    print("you are using", platform.system(), platform.release(), os.name)

    # creating the central shared dgsn-node-data for all programs on the nodes
    #######################################
    pathname = os.path.abspath(os.path.dirname(sys.argv[0]))
    pathname_all = ""
    for i in range(len(pathname.split(path_separator))-2): # creating the folders two folder levels above
        pathname_all = pathname_all + pathname.split(path_separator)[i] + path_separator
    pathname_save = pathname_all + "dgsn-node-data"
    pathname_config = pathname_all + "dgsn-hub-ops"

    # creating the dump folder for files and the needed data folders
    #######################################
    if not os.path.exists(pathname_save):
        os.makedirs(pathname_save)

    folder = pathname_save + path_separator + "rec"
    subfolders = ["iq", "sdr", "gapped", "coded", "monitor"]
    if not os.path.exists(folder):
        os.makedirs(folder)

    if os.path.exists(folder):
        for i in range(len(subfolders)):
            if not os.path.exists(folder + path_separator + subfolders[i]):
                os.makedirs(folder + path_separator + subfolders[i])

    if not os.path.exists(pathname_config):
        os.makedirs(pathname_config)

    pathname_config = pathname_config + path_separator + "io-radio"

    if not os.path.exists(pathname_config):
        os.makedirs(pathname_config)

    # setting the rtlsdr before the gain finding
    #####################################

    # getting one file to each node very simple via github, or via a local file copy
    data = loading_config_file(pathname_config)

    # getting the specific settings for the node itself. perhaps it cannot be as fast as others
    with open(pathname + path_separator +'node-config.json') as data_file:
        data_node = json.load(data_file)

    device_number = data["device_number"]
    center_frequency = data["center_frequency"]
    samplerate = data["samplerate"]

    # this will be necessary in case a full fledged pc is a node or in case a micro pc is used with less RAM
    secondsofrecording = min(data["secondsofrecording"], data_node["secondsofrecording_maximum"])
    print("record seconds commanded", data["secondsofrecording"], "record seconds maximum",
          data_node["secondsofrecording_maximum"], "and it is", secondsofrecording)

    nsamples = secondsofrecording * samplerate
    freq_correction = data["freq_correction"]
    user_hash = get_groundstationid()

    dt = datetime.datetime(data["recording_start"]["year"], data["recording_start"]["month"], data["recording_start"]["day"],
                           data["recording_start"]["hour"], data["recording_start"]["minute"], data["recording_start"]["second"])
    recording_start = time.mktime(dt.timetuple())

    dt = datetime.datetime(data["recording_end"]["year"], data["recording_end"]["month"], data["recording_end"]["day"],
                           data["recording_end"]["hour"], data["recording_end"]["minute"], data["recording_end"]["second"])
    recording_stop = time.mktime(dt.timetuple())

    # getting the data for calibration
    calibration_start = data["calibration_start"]
    gain_start = data["gain_start"]
    gain_end = data["gain_end"]
    gain_step = data["gain_step"]
    signal_threshold = data["signal_threshold"]
    print("gg", gain_start, gain_end)

    ##################################
    print("starting the fun...")

    if platform.system() == "Windows":
        print("detecting a windows")
        ##############
        device_count = librtlsdr.rtlsdr_get_device_count()
        print("number of rtl-sdr devices:", device_count)

        if device_count > 0:
            lock = Lock()
            jobs = []
            gain = 0
            calibration_finished = 0 # 1 means calibration is done

            while time.mktime(time.gmtime()) <= recording_start or calibration_finished == 0:
                # waiting for the time to be right :)
                time.sleep(10)
                print("still to wait", recording_start - time.mktime(time.gmtime()), "to record and",
                  recording_start - time.mktime(time.gmtime())- calibration_start, "to calibration")

                if time.mktime(time.gmtime()) > recording_start - calibration_start and calibration_finished == 0:
                    sdr = RtlSdr(device_index=device_number)
                    sdr.center_freq = center_frequency
                    sdr.sample_rate = samplerate
                    # sdr.freq_correction = 1   # PPM

                    # calibrating the dongle
                    if gain_start >= gain_end or gain_start >= 49.0:
                        print("fixed gain")
                        if gain_start==0 or gain_start > 49.0:
                            print("autogain")
                            gain = 'auto'
                        else:
                            gain = gain_start

                    else:
                        print("calibrated gain")
                        gain = calibrating_gain_with_windows(sdr, samplerate, gain_step, gain_start,
                                                             gain_end, signal_threshold)

                    print("used gain", gain)
                    sdr.gain = gain

                    sdr.close()
                    calibration_finished = 1

            utctime = time.mktime(time.gmtime())
            if utctime >= recording_start and utctime <= recording_stop:
                print("recording starts now...")
                for recs in range(2):
                    p = Process(target=storing_stream_with_windows, args=(lock, device_number, folder, subfolders,
                                                                          center_frequency, samplerate, gain, nsamples,
                                                                          freq_correction, user_hash))
                    jobs.append(p)
                    p.start()
                print("end")

                while time.mktime(time.gmtime()) <= recording_stop:
                    time.sleep(2)
                    for n, p in enumerate(jobs):
                        if not p.is_alive() and time.mktime(time.gmtime()) <= recording_stop:
                            jobs.pop(n)
                            recs += 1
                            p = Process(target=storing_stream_with_windows, args=(lock, device_number, folder,
                                                                                  subfolders, center_frequency,
                                                                                  samplerate, gain, nsamples,
                                                                                  freq_correction, user_hash))
                            jobs.append(p)
                            p.start()
                            print("rec number", recs, 'added')

            for job in jobs:
                job.join()

    elif platform.system() == "Linux" or platform.system() == "Linux2":
        print("detecting a linux")

        # getNumber_of_rtlsdrs_with_linux()

        gain = 0
        calibration_finished = 0

        while time.mktime(time.gmtime()) <= recording_start or calibration_finished == 0:
            # waiting for the time to be right :)
            time.sleep(10)
            print("still to wait", recording_start - time.mktime(time.gmtime()), "to record and",
                  recording_start - time.mktime(time.gmtime())- calibration_start, "to calibration")

            if time.mktime(time.gmtime()) > recording_start - calibration_start and calibration_finished == 0:
                if gain_start >= gain_end or gain_start >= 49.0:
                    print("fixed gain")
                    if gain_start==0 or gain_start > 49.0:
                        print("autogain")
                        gain = 0
                    else:
                        gain = gain_start

                else:
                    print("calibrated gain")
                    gain = calibrating_gain_with_linux(device_number, center_frequency, samplerate, gain_step,
                                                       gain_start, gain_end, signal_threshold)
                print("used gain", gain)
                calibration_finished = 1

        utctime = time.mktime(time.gmtime())
        if utctime >= recording_start and utctime <= recording_stop:
            print("recording starts now...")

            rtl_sdr_exe = "rtl_sdr"
            sdr = Popen([rtl_sdr_exe, "-d", str(device_number), "-f", str(center_frequency), "-s", str(samplerate),
                         "-g", str(gain), "-p", str(freq_correction), "-"],
                        stdout=PIPE, stderr=None)

            while time.mktime(time.gmtime()) <= recording_stop:
                stream_data = sdr.stdout.read(nsamples*2)
                storing_stream_with_linux(stream_data, device_number, folder, subfolders, center_frequency, samplerate,
                                          gain, nsamples, freq_correction, user_hash)

            sdr.kill()
    print("it's done. thank you, please come back again!")
예제 #46
0
class FMRadio(QtGui.QMainWindow,Ui_MainWindow):
    sample_buffer = Queue.Queue(maxsize=10)
    base_spectrum = np.ones(5780)

    plotOverall = True
    plotChannel = False
    plotPlaying = False
    plotWaveform = False
    useStereo = False
    stereoWidth = 10
    useMedianFilt = True
    useLPFilt = False
    demodFiltSize = 11
    useAudioFilter = True
    audioFilterSize = 16
    toDraw = True
    demodMain = True
    demodSub1 = False
    demodSub2 = False
    toDrawWaterfalls = True
    toDrawPlots = False

    prevCutoff = 0

    toPlot = (np.cumsum(np.ones(5780)),np.cumsum(np.ones(5780)))

    def __init__(self,freq,N_samples):

        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.createQtConnections()


        self.sample_rate = 2.4e5 ###1e6
        #self.decim_r1 = 1e6/2e5 # for wideband fm
        self.decim_r2 = 2.4e5/48000 # for baseband recovery
        self.center_freq = freq #+250e3
        self.gain = 38

        self.N_samples = N_samples
        self.is_sampling = False

        self.spectrogram = np.zeros((328,200))
        self.chspectrogram = np.zeros((328,200))
        self.plspectrogram = np.zeros((164,200))

        self.sdr =  RtlSdr()
        #self.sdr.direct_sampling = 1
        self.sdr.sample_rate = self.sample_rate
        self.sdr.center_freq = self.center_freq
        self.sdr.gain = self.gain

        self.pa = pyaudio.PyAudio()
        self.stream = self.pa.open( format = pyaudio.paFloat32,
                                    channels = 2,
                                    rate = 48000,
                                    output = True)

        adj = 0
        hamming = np.kaiser(self.N_samples/4 + adj,1)
        lpf = np.append( np.zeros(self.N_samples*3/8),hamming)
        self.lpf = np.fft.fftshift(np.append(lpf,np.zeros(self.N_samples*3/8))) #,int(-.25*self.N_samples))

        hamming = 10*signal.hamming(self.N_samples/16)
        lpf = np.append(np.zeros(self.N_samples*15/32),hamming)
        self.lpf_s1 = (np.append(lpf,np.zeros(int(self.N_samples*15/32))))
        #self.lpf_s1 = np.roll(temp,int(.5*self.N_samples*67/120))
        #self.lpf_s1 += np.roll(temp,int(-.5*self.N_samples*67/120))
        self.lpf_s1 = np.fft.fftshift(self.lpf_s1)
        #self.lpf_s1 += np.fft.fftshift(self.lpf_s1)

#         fig = plt.figure()
#         ax = fig.add_subplot(111)
#         ax.plot(range(self.lpf_s1.size),self.lpf_s1)
#         fig.show()

        hamming = 10*signal.hamming(self.N_samples/32)
        lpf = np.append(np.zeros(self.N_samples*31/64),hamming)
        self.lpf_s2 = (np.append(lpf,np.zeros(int(self.N_samples*31/64))))
        #self.lpf_s2 = np.roll(temp,int(.5*self.N_samples*92/120))
        #self.lpf_s2 += np.roll(temp,int(-.5*self.N_samples*92/120))
        self.lpf_s2 = np.fft.fftshift(self.lpf_s2)

    def createQtConnections(self):
        QtCore.QObject.connect(self.ui.freqSelect, QtCore.SIGNAL(_fromUtf8("valueChanged(int)")), self.setFreq)
        QtCore.QObject.connect(self.ui.checkBox, QtCore.SIGNAL(_fromUtf8("toggled(bool)")), self.setUseStereo)
        QtCore.QObject.connect(self.ui.mainchannel, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDemodMain)
        QtCore.QObject.connect(self.ui.subband1, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDemodSub1)
        QtCore.QObject.connect(self.ui.subband2, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDemodSub2)
        QtCore.QObject.connect(self.ui.stereoWidthSlider, QtCore.SIGNAL(_fromUtf8("sliderMoved(int)")), self.setStereoWidth)
        QtCore.QObject.connect(self.ui.spectrum_overall, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setSpectrumOverall)
        QtCore.QObject.connect(self.ui.spectrum_channel, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setSpectrumChannel)
        QtCore.QObject.connect(self.ui.spectrum_playing, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setSpectrumPlaying)
        QtCore.QObject.connect(self.ui.spectrum_waveform, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setSpectrumWaveform)
        QtCore.QObject.connect(self.ui.demodFiltMedian, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDemodFiltMedian)
        QtCore.QObject.connect(self.ui.demodFiltLP, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDemodFiltLP)
        QtCore.QObject.connect(self.ui.demodFilterSize, QtCore.SIGNAL(_fromUtf8("sliderMoved(int)")), self.setDemodFiltSize)
        QtCore.QObject.connect(self.ui.audioFilterActive, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setAudioFiltUse)
        QtCore.QObject.connect(self.ui.audioFilterSizeSlider, QtCore.SIGNAL(_fromUtf8("sliderMoved(int)")), self.setAudioFiltSize)
        QtCore.QObject.connect(self.ui.exitButton, QtCore.SIGNAL(_fromUtf8("clicked()")), self.terminate)
        QtCore.QObject.connect(self.ui.drawPlot, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDrawSpec)
        QtCore.QObject.connect(self.ui.waterfallButton, QtCore.SIGNAL(_fromUtf8('toggled(bool)')), self.setDrawWaterfalls)
      #  QtCore.QObject.connect(self.ui.plotButton, QtCore.SIGNAL(_fromUtf8("clicked(bool)")), self.setDrawPlot)

        self.bindPlot()


    def bindPlot(self):
        self.dpi = 100
        self.fig = Figure((4.31,2.0), dpi=self.dpi)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.ui.plotFrame)

        self.initplot()

        #self.anim = animation.FuncAnimation(self.fig,self.replot,interval=2000,blit=False)
        #self.canvas.mpl_connect('click_event',self.on_click_plot)


#         self.curve = QwtPlotCurve("Frequencies")
#         self.curve.setData(self.toPlot[0],self.toPlot[1]) #np.r_[-5e5:5e5:1e6/self.toPlot.size],np.abs(self.toPlot))
#         self.curve.attach(self.ui.spectrumPlot)
#         self.ui.spectrumPlot.replot()
#         #threading.Timer(1,self.replot).start()

    def initplot(self):
        self.axes = self.fig.add_subplot(111, aspect=200/431)
        self.axes.xaxis.set_major_locator(ticker.NullLocator())
        self.axes.yaxis.set_major_locator(ticker.NullLocator())
        #self.axes.invert_yaxis()

    def replot(self):
       self.axes.clear()
       #self.axes.set_s
       self.axes.plot(self.toPlot[0],self.toPlot[1])
       self.axes.set_aspect('auto',anchor='C')
       self.canvas.draw()

    def setDrawSpec(self,s):
        self.toDraw = s

    def drawSpectrum(self):
        self.axes.clear()
        self.axes.imshow(self.spectrogram, cmap='spectral')
        self.axes.xaxis.set_major_locator(ticker.NullLocator())
        self.axes.yaxis.set_major_locator(ticker.NullLocator())
        self.axes.set_aspect('auto',adjustable='box',anchor='NW')
        self.canvas.draw()

    def drawChspectrum(self):
        self.axes.clear()
        self.axes.imshow(self.chspectrogram, cmap='spectral')
        self.axes.xaxis.set_major_locator(ticker.NullLocator())
        self.axes.yaxis.set_major_locator(ticker.NullLocator())
        self.axes.set_aspect('auto',adjustable='box',anchor='NW')
        self.canvas.draw()

    def drawPlspectrum(self):
        self.axes.clear()
        self.axes.imshow(self.plspectrogram, cmap='spectral')
        self.axes.xaxis.set_major_locator(ticker.NullLocator())
        self.axes.yaxis.set_major_locator(ticker.NullLocator())
        self.axes.set_aspect('auto',adjustable='box',anchor='NW')
        self.canvas.draw()

    def setDrawPlots(self,s):
        self.toDrawPlots = s
        self.toDrawWaterfalls = not s

    def setDrawWaterfalls(self,s):
        self.toDrawWaterfalls = s
        self.toDrawPlots = not s

    def setFreq(self,freq):
        freq /= 10.0
        text = "%.1f MHz" % freq
        self.ui.curFreq.setText(text)
        self.center_freq = freq*1e6 #+ 250e3
        setf_t = threading.Thread(target=self.setF_th, args=[self.center_freq,])
        setf_t.start()
        setf_t.join()

    def setF_th(self,f):
        while(self.is_sampling == True):
            pass
        self.sdr.center_freq = f

    def setUseStereo(self,u):
        self.useStereo = u
    def setStereoWidth(self,w):
        self.stereoWidth = np.sqrt(10*w)

    def setDemodMain(self,s):
        self.demodMain = s
        self.demodSub1 = not s
        self.demodSub2 = not s
        #self.useStereo = True
    def setDemodSub1(self,s):
        self.demodMain = not s
        self.demodSub1 = s
        self.demodSub2 = not s
        #self.useStereo = False
    def setDemodSub2(self,s):
        self.demodMain = not s
        self.demodSub1 = not s
        self.demodSub2 = s
        #self.useStereo = False

    def setSpectrumOverall(self,s):
        #self.initplot()
        self.plotOverall = s
        self.plotChannel = not s
        self.plotPlaying = not s
        self.plotWaveform = not s
    def setSpectrumChannel(self,s):
        #self.initplot()
        self.plotChannel = s
        self.plotOverall = not s
        self.plotPlaying = not s
        self.plotWaveform = not s
    def setSpectrumPlaying(self,s):
        #self.initplot()
        self.plotPlaying = s
        self.plotChannel = not s
        self.plotOverall= not s
        self.plotWaveform = not s
    def setSpectrumWaveform(self,s):
        self.plotWaveform = s
        self.plotPlaying = not s
        self.plotChannel = not s
        self.plotOverall= not s

    def setDemodFiltMedian(self,s):
        self.useMedianFilt = s
        self.useLPFilt = not s
    def setDemodFiltLP(self,s):
        self.useLPFilt = s
        self.useMedianFilt = not s
    def setDemodFiltSize(self,s):
        if(s % 2 == 0):
            s+=1
        self.demodFiltSize = s

    def setAudioFiltUse(self,s):
        self.useAudioFilter = s
    def setAudioFiltSize(self,s):
        self.audioFilterSize = s

    def terminate(self):
        self.__del__()

    def __del__(self):
        #QtGui.QMainWindow.__del__()
        #Ui_MainWindow.__del__()
        #self.streamer.stop()
        #self.sampler_t.stop()
        print "sdr closed"
        self.sdr.close()
        print "pyaudio terminated"
        self.pa.terminate()
        sys.exit()

    def getSamples(self):
        #N_samples = self.N_samples # 1/24.4 seconds   ~46336 #approximately a 2048/44100 amount's time
        return self.sdr.read_samples(self.N_samples)

    def getSamplesAsync(self):
        #Asynchronous call. Meant to be put in a loop w/ a calback fn
        #print 'gonna sample'
        self.is_sampling = True
        samples = self.sdr.read_samples_async(self.sampleCallback,self.N_samples,context=self)

    def sampleCallback(self,samples,sself):

        self.is_sampling = False
        self.sample_buffer.put(samples)
        #print 'put some samples in the jar'

        # recursive loop
        #sself.getSamplesAsync()

    def demodulate_th(self):
        while(1):

            try:
                samples = self.sample_buffer.get()
                #samples2 = self.sample_buffer.get()
              #  print 'gottum'
            except:
                print "wtf idk no samples?"
                break

            out1 = self.demodulate(samples)
            self.sample_buffer.task_done()
            #out2 = self.demodulate(samples2)
            #self.sample_buffer.task_done()

            audio_out = out1 #np.append(out1,out2)

            self.play(audio_out)

        print 'gonna try to finish off the to-do list'
        sample_buffer.join()


    def demodulate(self,samples):
        # DEMODULATION CODE
        #samples = #self.sample_buffer.get()
        # LIMITER goes here

        # low pass & down sampling via fft


        spectrum = np.fft.fftshift(np.fft.fft(samples))

        self.spectrogram = np.roll(self.spectrogram, 1,axis=1)
        self.spectrogram[:,0] = np.log(np.abs(spectrum[::100]))


        if(self.toDraw and self.plotOverall and self.count % 10 == 9):

#             self.toPlot = (np.linspace(-5e5,5e5,spectrum.size),np.abs(spectrum))
#             self.replot()
            self.drawSpectrum()

        self.count += 1



            #fig = plt.figure()
            #plt.plot(np.abs(spectrum))
            #plt.show()
#
#         spectrum *= self.lpf
# # Decimate in two rounds. One to 200k, another to 44.1k
#         # DECIMATE HERE. Note that we're looking at 1MHz bandwidth.
#         n_s = spectrum.size
#
#         channel_spectrum = spectrum #.25*spectrum[int(n_s*.75-.5*n_s/self.decim_r1):int(.75*n_s+.5*n_s/self.decim_r1)] #np.append(spectrum[0:int(n_s/self.decim_r1*.5)],spectrum[n_s-int(n_s/self.decim_r1*.5):n_s])
#
#         #radio_spectrum -= np.mean(radio_spectrum) #attempt to remove dc bias
#         #print channel_spectrum.size

# #             fig = plt.figure()
# #             plt.plot(np.abs(np.fft.ifftshift(channel_spectrum)))
# #             plt.show()
#             #self.fig.plot(np.fft.ifftshift(channel_spectrum))
#
#
#         lp_samples = np.fft.ifft(np.fft.ifftshift(channel_spectrum))
#
        lp_samples = samples



      #  lp_samples /= power


    # polar discriminator



        dphase = np.zeros(lp_samples.size, dtype='complex')

        A = lp_samples[1:lp_samples.size]
        B = lp_samples[0:lp_samples.size-1]

        dphase[1:] = ( A * np.conj(B) )

        dphase[0] = lp_samples[0] * np.conj(self.prevCutoff) #dphase[dphase.size-2]
        self.prevCutoff = lp_samples[lp_samples.size-1]

#         if self.useMedianFilt:
#             rebuilt = signal.medfilt(np.angle(dphase)/np.pi,self.demodFiltSize) #  np.cos(dphase)
#         else:
#             rebuilt = self.lowpass(np.angle(dphase),self.demodFiltSize)
        rebuilt = np.angle(dphase) / np.pi
#         toplot = False
#         if toplot:
#             fig = plt.figure()
#             ax = fig.add_subplot(111)
#             ax.plot(rebuilt)

        power = np.abs(self.mad(lp_samples))
        self.ui.signalMeter.setValue(20*(np.log10(power)))

        demodMain = False
        demodSub1 = False
        demodSub2 = False
        if self.demodMain:
            demodMain = True

           # lp_samples = samples
        elif self.demodSub1:
            demodSub1 = True

            #lp_samples = samples * np.exp(-1j*2*np.pi*67650/2.4e5*np.r_[0:samples.size])
        elif self.demodSub2:
            demodSub2 = True
            #lp_samples = samples * np.exp(-1j*2*np.pi*92000/2.4e5*np.r_[0:samples.size])


        spectrum = np.fft.fft(rebuilt)


         #toplot = self.plotChannel
        self.chspectrogram = np.roll(self.chspectrogram, 1,axis=1)
        self.chspectrogram[:,0] = np.log(np.abs(spectrum[spectrum.size/2:spectrum.size:50]))
        if(self.toDraw and self.plotChannel and self.count % 10 == 9):
            self.drawChspectrum()
             #plotspectrum = np.abs(channel_spectrum[::100])
             #self.toPlot = (np.linspace(-np.pi,np.pi,plotspectrum.size),plotspectrum)
             #self.replot()


        isStereo = False
        #demodSub1 = False
        #demodSub2 = False
        n_z = rebuilt.size
        if demodMain:

            #stereo_spectrum = spectrum
            if self.useStereo:
                isStereo = True
                #modulated = rebuilt * np.exp(-2j*np.pi*38000/2.4e5*np.r_[0:rebuilt.size])
                #h = signal.firwin(128,22000,nyq=1.2e5)
                #lp_mod = signal.fftconvolve(modulated,h,mode='same')
                #decim = lp_mod[::self.decim_r2]
                #dphase = np.zeros(decim.size, dtype='complex')
#
#                A = decim[1:decim.size]
#                B = decim[0:decim.size-1]
#
#                dphase[1:] = np.angle( A * np.conj(B) )
                #h = signal.firwin(128,22000,nyq=24000)

                #diff = dphase# [::self.decim_r2]
                mod_spectrum = np.roll(spectrum,int(.5*n_z*38000/120000))
                mod_spectrum += np.roll(spectrum,int(-.5*n_z*38000/120000)) #np.fft.fft(modulated)
                mod_spectrum *= self.lpf #np.fft.ifftshift(np.hamming(stereo_spectrum.size))
                stereo_spectrum = np.append(mod_spectrum[0:np.ceil(n_z/self.decim_r2*.5)],mod_spectrum[n_z-np.ceil(n_z/self.decim_r2*.5):n_z])
                diff = np.fft.ifft(stereo_spectrum)
            #self.base_spectrum = np.append(spectrum[0:int(n_z/self.decim_r2*.5)],spectrum[n_z-int(n_z/self.decim_r2*.5):n_z])
            #output = np.fft.ifft(self.base_spectrum)
            h = signal.firwin(128,16000,nyq=1.2e5)
            output = signal.fftconvolve(rebuilt,h,mode='same')
            output = rebuilt[::self.decim_r2]
#             h = signal.firwin(128,16000,nyq=2.4e4)
#             output = signal.fftconvolve(output,h,mode='same')
        elif demodSub1:

            demod = rebuilt * np.exp(-2j*np.pi*67650/2.4e5*np.r_[0:rebuilt.size])
         #   spectrum = np.fft.fft(demod)*self.lpf_s1
            h = signal.firwin(128,7500,nyq=2.4e5/2)
            lp_demod = signal.fftconvolve(demod,h,mode='same')
            decim = lp_demod[::self.decim_r2]
        #    base_spectrum = np.append(spectrum[0:int(.5*n_z*7500/2.4e5)],spectrum[n_z-int(.5*n_z*7500/2.4e5):n_z])
        #    decim = np.fft.ifft(base_spectrum)

            dphase = np.zeros(decim.size, dtype='complex')
#
            A = decim[1:decim.size]
            B = decim[0:decim.size-1]
#
            dphase[1:] = np.angle( A * np.conj(B) )
            h = signal.firwin(128,7500,nyq=24000)
            output = signal.fftconvolve(dphase,h,mode='same')

            #retoutput)

        elif demodSub2:
            demod = rebuilt * np.exp(-2j*np.pi*92000/2.4e5*np.r_[0:rebuilt.size])
          #  spectrum = np.fft.fft(demod)*self.lpf_s2
            h = signal.firwin(128,7500,nyq=2.4e5/2)
            lp_demod = signal.fftconvolve(demod,h,mode='same')
            decim = lp_demod[::self.decim_r2]
          #  base_spectrum = np.append(spectrum[0:int(.5*n_z*7500/2.4e5)],spectrum[n_z-int(.5*n_z*7500/2.4e5):n_z])
          #  decim = np.fft.ifft(base_spectrum)

            dphase = np.zeros(decim.size, dtype='complex')
#
            A = decim[1:decim.size]
            B = decim[0:decim.size-1]
#
            dphase[1:] = np.angle( A * np.conj(B) )
            h = signal.firwin(128,7500,nyq=24000)
            output = signal.fftconvolve(dphase,h,mode='same')

            #return np.real(output)

        output -= np.mean(output)

        stereo = np.zeros(output.size*2, dtype='complex')
        if (isStereo):
            #diff = np.fft.ifft(stereo_spectrum)
            w = self.stereoWidth  # adjust to change stereo wideness
         #print w
            left = output + w/10 * diff
            right = output - w/10 * diff

            if(self.useAudioFilter):
                left = self.lowpass(left,self.audioFilterSize)
                right = self.lowpass(right,self.audioFilterSize)

            stereo[0:stereo.size:2] = left
            stereo[1:stereo.size:2] = right
        else:
            if self.useAudioFilter:
                output = self.lowpass(output,self.audioFilterSize) # just the tip (kills the 19k pilot)
            stereo[0:stereo.size:2] = output
            stereo[1:stereo.size:2] = output


        spectrum = np.fft.fft(stereo[::2])
        self.plspectrogram = np.roll(self.plspectrogram, 1,axis=1)
        self.plspectrogram[:,0] = np.log(np.abs(spectrum[spectrum.size/2:spectrum.size:20]))
        if(self.toDraw and self.plotPlaying): # and self.count % 2 == 0):
            if self.toDrawWaterfalls:
                self.drawPlspectrum()
            else:
                sm = np.abs(np.fft.fftshift(spectrum[::20]))
                self.toPlot = (np.linspace(-2.4e4,2.4e4,sm.size),sm)
                self.replot()


        if(self.toDraw and self.plotWaveform):
            sm = np.real(stereo[::20])
            self.toPlot = (np.linspace(0,output.size/48000,sm.size),sm)
            self.replot()


        return np.real(stereo)


#     def updateimg(self,base_spectrum):
#         spectralimg = np.zeros((base_spectrum.size/20,base_spectrum.size/10))
#         for i in np.r_[0:base_spectrum.size/10]:
#             spectralimg[np.abs(np.fft.fftshift(base_spectrum)[i*10]/10),i] = 1
#         cv2.imshow('spectrum',spectralimg)

    def demodulate2(self,samples):
        # DEMODULATION CODE

        # LIMITER goes here

        # low pass & down sampling
        lp_samples = signal.decimate(self.lowpass_filter(samples,16),int(self.decim_r1))


    # polar discriminator

        A = lp_samples[1:lp_samples.size]
        B = lp_samples[0:lp_samples.size-1]

        dphase = ( A * np.conj(B) )

        dphase.resize(dphase.size+1)
        dphase[dphase.size-1] = dphase[dphase.size-2]

        rebuilt = signal.medfilt(np.angle(dphase)/np.pi,15) #  np.cos(dphase)

        output = signal.decimate(rebuilt,int(self.decim_r2))

        return np.real(.5*output)

# utility functions #

    def lowpass(self,x,width):
        #wndw = np.sinc(np.r_[-15:16]/np.pi)/np.pi
        #wndw = np.kaiser(width,6)
        wndw = signal.firwin(16,width*990,nyq=24000)
        #wndw /= np.sum(wndw)
        new_array = signal.fftconvolve(x, wndw, mode='same')

        return new_array

    # calculate mean average deviation #
    def mad(self,samples):
        ave = np.mean(samples)
        return np.mean(np.abs(samples-ave))

    # calculate rms for power #
    def rms(self,samples):
        meansq = np.mean(np.square(samples))
        return np.sqrt(meansq)

    def play(self,samples):
        self.stream.write( samples.astype(np.float32).tostring() )



    def start(self):
        self.streamer = MakeDaemon(self.demodulate_th) # run demodulation in the 'background'
        self.streamer.start()
        self.count = 0
        self.sampler_t = threading.Thread(target=self.getSamplesAsync) # sampler loop
        self.sampler_t.start()
예제 #47
0
class Sampler(QtCore.QObject):
    samplerError = QtCore.pyqtSignal(object)
    dataAcquired = QtCore.pyqtSignal(object)

    def __init__(self, gain, sampRate, freqs, numSamples, parent=None):
        super(Sampler, self).__init__(parent)
        self.gain = gain
        self.sampRate = sampRate
        self.freqs = freqs
        self.numSamples = numSamples
        self.offset = 0
        self.sdr = None
        self.errorMsg = None

        self.WORKING = True
        self.BREAK = False
        self.MEASURE = False

        try:
            self.sdr = RtlSdr()
            self.sdr.set_manual_gain_enabled(1)
            self.sdr.gain = self.gain
            self.sdr.sample_rate = self.sampRate
        except IOError:
            self.WORKING = False
            print "Failed to initiate device. Please reconnect."
            self.errorMsg = "Failed to initiate device. Please reconnect."
            self.samplerError.emit(self.errorMsg)

    def sampling(self):
        print 'Starting sampler...'
        while self.WORKING:
            prev = 0
            counter = 0
            gain = self.gain
            numSamples = self.numSamples
            self.BREAK = False
            self.sdr.gain = gain
            start = time.time()
            #print self.sdr.get_gain()
            for i in range(len(self.freqs)):
                if self.BREAK:
                    break
                else:
                    centerFreq = self.freqs[i]
                    #print "frequency: " + str(center_freq/1e6) + "MHz"
                    if centerFreq != prev:
                        try:
                            self.sdr.set_center_freq(centerFreq)
                        except:
                            self.WORKING = False
                            print "Device failure while setting center frequency"
                            self.errorMsg = "Device failure while setting center frequency"
                            self.samplerError.emit(self.errorMsg)
                            break
                        prev = centerFreq
                    else:
                        pass

                    #time.sleep(0.01)
                    try:
                        x = self.sdr.read_samples(2048)
                        data = self.sdr.read_samples(numSamples)

                    except:
                        self.WORKING = False
                        print "Device failure while getting samples"
                        self.errorMsg = "Device failure while getting samples"
                        self.samplerError.emit(self.errorMsg)
                        break

                    if self.MEASURE:
                        self.offset = np.mean(data)

                    counter += 1
                    self.dataAcquired.emit([i, centerFreq, data])

        if self.errorMsg is not None:
            self.samplerError.emit(self.errorMsg)
        if self.sdr is not None:
            self.sdr.close()
예제 #48
0
from rtlsdr import RtlSdr
import numpy as np
from pylab import psd

sdr = RtlSdr()

sdr.sample_rate = 2.4e6
sdr.center_freq = 105e6
sdr.gain = 4

passes = 1000
fftbins = 1024
samples = sdr.read_samples(passes * fftbins)
sdr.close()

print(samples[0])

spectra = psd(samples,
              NFFT=fftbins,
              Fs=sdr.sample_rate / 1e6,
              Fc=sdr.center_freq / 1e6)
print(spectra[0])
print(spectra[1])
예제 #49
0
class FMRadio:

     # multiple of 256


    def __init__(self,freq,N_samples):

        self.sample_rate = 1e6
        self.decim_r1 = 1e6/2e5 # for wideband fm
        self.decim_r2 = 2e5/44100 # for baseband recovery
        self.center_freq = freq
        self.gain = 36

        self.N_samples = N_samples

        self.sdr =  RtlSdr()
        self.sdr.direct_sampling = 1
        self.sdr.sample_rate = self.sample_rate
        self.sdr.center_freq = self.center_freq
        self.sdr.gain = self.gain

        self.pa = pyaudio.PyAudio()
        self.stream = self.pa.open( format = pyaudio.paFloat32,
                                    channels = 1,
                                    rate = 44100,
                                    output = True)

        hamming = 10*signal.hamming(self.N_samples*.10 )
        lpf = np.append( np.zeros(self.N_samples*.45),hamming)
        self.lpf = np.fft.fftshift(np.append(lpf,np.zeros(self.N_samples*.45)))

    def __del__(self):
        print "sdr closed"
        self.sdr.close()
        print "pyaudio terminated"
        self.pa.terminate()

    def getSamples(self):
        #N_samples = self.N_samples # 1/24.4 seconds   ~46336 #approximately a blocksize amount's time
        return self.sdr.read_samples(self.N_samples)


#    def demodulate_threaded(self,samples):
#        async_demodulation = self.pool.apply_async(self.demodulate, samples, callback=self.play)


    def demodulate(self,samples):
        # DEMODULATION CODE
        #samples = #self.sample_buffer.get()
        # LIMITER goes here

        # low pass & down sampling via fft

        spectrum = np.fft.fft(samples) * (self.lpf)

#         toplot = False
#         if(toplot):
#             fig = plt.figure()
#             plt.plot(np.abs(spectrum))
#             plt.show()

# Decimate in two rounds. One to 200k, another to 44.1k
        # DECIMATE HERE. Note that we're looking at 1MHz bandwidth.
        n_s = spectrum.size
        channel_spectrum = np.append(spectrum[0:n_s/self.decim_r1*.5],spectrum[n_s-n_s/self.decim_r1*.5:n_s])

        #radio_spectrum -= np.mean(radio_spectrum) #attempt to remove dc bias

#         toplot = False
#         if(toplot):
#             fig = plt.figure()
#             plt.plot(np.abs(channel_spectrum))
#             plt.show()


        lp_samples = np.fft.ifft(channel_spectrum)

        #lp_samples = self.lowpass_filter(lp_samples,4)

    # polar discriminator

        A = lp_samples[1:lp_samples.size]
        B = lp_samples[0:lp_samples.size-1]

        dphase = ( A * np.conj(B) )

#dpm = np.mean(np.abs(dphase))
        # normalize
        #       dphase /= dpm
        dphase.resize(dphase.size+1)
        dphase[dphase.size-1] = dphase[dphase.size-2]

        rebuilt = signal.medfilt(np.angle(dphase)/np.pi,15) #  np.cos(dphase)

        #phase = np.sin(rebuilt)
        #phase = self.lowpass_filter(phase,8)

        #rebuilt= self.lowpass_filter(rebuilt,8)

#         toplot = False
#         if toplot:
#             fig = plt.figure()
#             ax = fig.add_subplot(111)
#             ax.plot(rebuilt)
#             ax.plot(phase)
#             plt.show()


        spectrum = np.fft.fft(rebuilt) #* self.lpf2
        n_s = spectrum.size
        base_spectrum = np.append(spectrum[0:n_s/self.decim_r2*.5],spectrum[n_s-n_s/self.decim_r2*.5:n_s])
        output = np.fft.ifft(base_spectrum)
        #check: should be 1807 or very close to it. it is!!

       # output = self.lowpass_filter(np.real(output),16) #[12:8204]

#         toplot = False
#         if(toplot):
#             fig = plt.figure()
#             plt.plot(np.real(output))
#             plt.show()


        return np.real(output)


    def demodulate2(self,samples):
        # DEMODULATION CODE

        # LIMITER goes here

        # low pass & down sampling
        lp_samples = signal.decimate(self.lowpass_filter(samples,16),int(self.decim_r1))


    # polar discriminator

        A = lp_samples[1:lp_samples.size]
        B = lp_samples[0:lp_samples.size-1]

        dphase = ( A * np.conj(B) )

        dphase.resize(dphase.size+1)
        dphase[dphase.size-1] = dphase[dphase.size-2]

        rebuilt = signal.medfilt(np.angle(dphase)/np.pi,15) #  np.cos(dphase)

        output = signal.decimate(rebuilt,int(self.decim_r2))

        return np.real(output)

    def lowpass_filter(self,x,width):
        #wndw = np.sinc(np.r_[-15:16]/np.pi)/np.pi
        wndw = np.kaiser(width,6)
        wndw /= np.sum(wndw)
        new_array = signal.fftconvolve(x, wndw)

        return new_array[int(width/2):x.size+int(width/2)]



    def play(self,samples):
        self.stream.write( samples.astype(np.float32).tostring() )

    def start(self):
        while True:
            self.play(self.demodulate(self.getSamples()))