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()
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()
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))
def run(self): # Read 128ms of data at a time (must be a multiple of a power of two) blkSize = SAMPLE_RATE_KHZ()*128; blockLoc = np.zeros(1,dtype=np.uint64); sdr = RtlSdr(); # configure device sdr.sample_rate = SAMPLE_RATE_KHZ()*1e3 # Hz sdr.center_freq = 1575420000 # Hz sdr.gain = 29; sdrQueue.put((sdr,blockLoc,blkSize/SAMPLE_RATE_KHZ(),1)); sdr.read_samples_async(sdrCallback, blkSize, context=sdrQueue);
def run(self): # Read 128ms of data at a time (must be a multiple of a power of two) blkSize = SAMPLE_RATE_KHZ() * 128 blockLoc = np.zeros(1, dtype=np.uint64) sdr = RtlSdr() # configure device sdr.sample_rate = SAMPLE_RATE_KHZ() * 1e3 # Hz sdr.center_freq = 1575420000 # Hz sdr.gain = 29 sdrQueue.put((sdr, blockLoc, blkSize / SAMPLE_RATE_KHZ(), 1)) sdr.read_samples_async(sdrCallback, blkSize, context=sdrQueue)
def main(): from rtlsdr import RtlSdr sdr = RtlSdr() print 'Configuring SDR...' sdr.rs = 1e6 sdr.fc = 70e6 sdr.gain = 5 print ' sample rate: %0.6f MHz' % (sdr.rs / 1e6) print ' center ferquency %0.6f MHz' % (sdr.fc / 1e6) print ' gain: %d dB' % sdr.gain print 'Testing callback...' sdr.read_samples_async(test_callback)
def main(): from rtlsdr import RtlSdr sdr = RtlSdr() print 'Configuring SDR...' sdr.rs = 1e6 sdr.fc = 70e6 sdr.gain = 5 print ' sample rate: %0.6f MHz' % (sdr.rs/1e6) print ' center ferquency %0.6f MHz' % (sdr.fc/1e6) print ' gain: %d dB' % sdr.gain print 'Testing callback...' sdr.read_samples_async(test_callback)
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 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 main(): @limit_time(0.01) @limit_calls(20) def read_callback(buffer, rtlsdr_obj): print('In callback') print(' signal mean:', sum(buffer)/len(buffer)) from rtlsdr import RtlSdr sdr = RtlSdr() print('Configuring SDR...') sdr.rs = 1e6 sdr.fc = 70e6 sdr.gain = 5 print(' sample rate: %0.6f MHz' % (sdr.rs/1e6)) print(' center ferquency %0.6f MHz' % (sdr.fc/1e6)) print(' gain: %d dB' % sdr.gain) print('Testing callback...') sdr.read_samples_async(read_callback)
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
return (num,den); fmDemod = FMDemod(); fileRead = FileReader(); audioPlay = AudioPlay(); dataQueue = Queue.Queue([1]); audioQueue = Queue.Queue([1]); sdr = RtlSdr(); # configure device sdr.sample_rate = 250e3; # Hz numSampsRead = 1024*600; freq = raw_input('Choose a station frequency: '); try: freq = float(freq); sdr.center_freq = freq; sdr.gain = 'auto'; #fileRead.start(); fmDemod.start(); audioPlay.start(); sdr.read_samples_async(sdrCallback, numSampsRead); except ValueError: print("Invalid number");
bitstr += "0" else: bitstr += "1" if (bitCount < 6): scancode += (1 << bitCount) bitCount += 1 bitValue = 0 if (bitCount > 10): bitCount = 0 state = 0 # fin demod except: exit(0) if __name__ == "__main__": q = Queue() p = Process(target=AsyncWelchProcess, args=(q, )) p.start() def on_sample(buf, queue): queue.put(list(buf)) from rtlsdr import RtlSdr sdr = RtlSdr() # configure device sdr.sample_rate = SAMPLE_RATE # sample rate sdr.center_freq = FREQ sdr.gain = 'auto' sdr.read_samples_async(on_sample, 2048, context=q)
process(samples, rtl_sdr_obj) parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('--ppm', type=int, default=0, help='ppm error correction') parser.add_argument('--gain', type=int, default=20, help='RF gain level') parser.add_argument('--freq', type=int, default=92900000, help='frequency to listen to, in Hertz') parser.add_argument('--verbose', action='store_true', help='mute audio output') args = parser.parse_args() sdr = RtlSdr() sdr.rs = 1024000 sdr.fc = args.freq sdr.gain = args.gain sdr.err_ppm = args.ppm sdr.read_samples_async(read_callback, int(sdr.get_sample_rate()) // 16)
class RtlReader(object): def __init__(self, **kwargs): super(RtlReader, self).__init__() self.signal_buffer = [] self.sdr = RtlSdr() self.sdr.sample_rate = modes_sample_rate self.sdr.center_freq = modes_frequency self.sdr.gain = "auto" # sdr.freq_correction = 75 self.debug = kwargs.get("debug", False) self.raw_pipe_in = None self.stop_flag = False def _process_buffer(self): messages = [] # signal_array = np.array(self.signal_buffer) # pulses_array = np.where(np.array(self.signal_buffer) < th_amp, 0, 1) # pulses = "".join(str(x) for x in pulses_array) buffer_length = len(self.signal_buffer) i = 0 while i < buffer_length: if self.signal_buffer[i] < th_amp: i += 1 continue # if pulses[i : i + pbits * 2] == preamble: if self._check_preamble(self.signal_buffer[i : i + pbits * 2]): frame_start = i + pbits * 2 frame_end = i + pbits * 2 + (fbits + 1) * 2 frame_length = (fbits + 1) * 2 frame_pulses = self.signal_buffer[frame_start:frame_end] msgbin = "" for j in range(0, frame_length, 2): p2 = frame_pulses[j : j + 2] if len(p2) < 2: break if p2[0] < th_amp and p2[1] < th_amp: break elif p2[0] >= p2[1]: c = "1" elif p2[0] < p2[1]: c = "0" else: msgbin = "" break msgbin += c # advance i with a jump i = frame_start + j if len(msgbin) > 0: msghex = pms.bin2hex(msgbin) if self._check_msg(msghex): messages.append([msghex, time.time()]) if self.debug: self._debug_msg(msghex) elif i > buffer_length - 500: # save some for next process break else: i += 1 # keep reminder of buffer for next iteration self.signal_buffer = self.signal_buffer[i:] return messages def _check_preamble(self, pulses): if len(pulses) != 16: return False for i in range(16): if abs(pulses[i] - preamble[i]) > th_amp_diff: return False return True def _check_msg(self, msg): df = pms.df(msg) msglen = len(msg) if df == 17 and msglen == 28: if pms.crc(msg) == 0: return True elif df in [20, 21] and msglen == 28: return True elif df in [4, 5, 11] and msglen == 14: return True def _debug_msg(self, msg): df = pms.df(msg) msglen = len(msg) if df == 17 and msglen == 28: print(msg, pms.icao(msg), pms.crc(msg)) elif df in [20, 21] and msglen == 28: print(msg, pms.icao(msg)) elif df in [4, 5, 11] and msglen == 14: print(msg, pms.icao(msg)) else: # print("[*]", msg) pass def _read_callback(self, data, rtlsdr_obj): # scaling signal (imporatant) amp = np.absolute(data) amp_norm = np.interp(amp, (amp.min(), amp.max()), (0, 1)) self.signal_buffer.extend(amp_norm.tolist()) if len(self.signal_buffer) >= buffer_size: messages = self._process_buffer() self.handle_messages(messages) def handle_messages(self, messages): """re-implement this method to handle the messages""" for msg, t in messages: # print("%15.9f %s" % (t, msg)) pass def stop(self, *args, **kwargs): self.sdr.cancel_read_async() def run(self, raw_pipe_in=None, stop_flag=None): self.raw_pipe_in = raw_pipe_in self.stop_flag = stop_flag self.sdr.read_samples_async(self._read_callback, read_size)
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()
den = np.array([1, -2*gain*np.cos(freq), (2*gain-1)]); return (num,den); fmDemod = FMDemod(); fileRead = FileReader(); audioPlay = AudioPlay(); dataQueue = Queue.Queue([1]); audioQueue = Queue.Queue([1]); sdr = RtlSdr(); # configure device sdr.sample_rate = 250e3; # Hz numSampsRead = 1024*600; freq = raw_input('Choose a station frequency: '); try: freq = float(freq); sdr.center_freq = freq; sdr.gain = 'auto'; #fileRead.start(); fmDemod.start(); audioPlay.start(); sdr.read_samples_async(sdrCallback, numSampsRead); except ValueError: print("Invalid number");
queue = mp.Queue(queue_max_size) print("Creating multiprocessing process") p = mp.Process(target=process_samples, args=(queue, )) p.start() # This code helps the decoder determine frequency offsets, etc. decoder.first_samples(samples, doppler=doppler) context_dict = { 'sdr': sdr, 'observer': obs, 'sat': sat, 'sat_name': sat_name, } sdr.read_samples_async(rtlsdr_callback, num_samples_per_recording, context_dict) print("Ending async RTLSDR processing") queue.close() queue.join_thread() p.join() if should_finish: break else: # If no satellite is overhead, find the next one that will be sat_detected = False for minute in range(0, 60 * 12): obs.date = ephem.now() + minute * ephem.minute for sat_name in active_orbcomm_satellites:
sdr.center_freq = center_freq sdr.gain = 10 ## get samples samples = [] def callback(ss, obj): samples.append(ss) #obj.cancel_read_async() print('Ready to record!') raw_input("Press Enter to record...") print('recording...') N_samples = sample_rate*0.5 # approximately seconds sdr.read_samples_async(limit_time(record_len)(callback), N_samples) # get samples print('recorded!') sdr_samples = np.hstack(samples) print('demodulating...') ss = smart_demod(sdr_samples, sample_rate, freq_offset) #del sdr_samples' print('finding packets...') packets = findPackets(ss)[0] print('error correcting packets...') decodes = map(lambda p: util.correct(decodePacket(p)), packets)
def stream_radio(): sdr = RtlSdr() sdr.sample_rate = 2.4e6 sdr.center_freq = 90e6 sdr.gain = 4 sdr.read_samples_async(async_callback)
class Receiver: def __init__(self, sampleRate, carrierFreq, symbolLength, frameSize): self.sampleRate = sampleRate self.carrierFreq = carrierFreq self.symbolLength = symbolLength self.frameSizeInBits = frameSize * 8 / 2 self.headerStart = [ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0 ] self.headerEnd = [ 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1 ] self.rtl = RtlSdr() self.rtl.sample_rate = self.sampleRate self.rtl.center_freq = self.carrierFreq self.demodulator = Demodulator(self.carrierFreq, self.symbolLength, self.sampleRate) self.modulator = Modulator(self.carrierFreq, self.symbolLength, self.sampleRate) self.frameSync = FrameSynchronization( self.modulator.modulate(self.headerStart), self.modulator.modulate(self.headerEnd), self.symbolLength, self.sampleRate) self.timeRecover = TimingRecovery(self.symbolLength) self.rtlSamples = Queue() self.frames = Queue() self.previousData = Queue(1) self.previousData.put([0]) self.data = Queue() self.threads = [] self.threads.append(threading.Thread(target=self.receive)) self.threads.append(threading.Thread(target=self.findFrame)) self.threads.append(threading.Thread(target=self.processData)) self.threads.append(threading.Thread(target=self.playSound)) for th in self.threads: th.start() def receive(self): def rtl_callback(samples, rtlsdr_obj): self.rtlSamples.put(samples) self.rtl.read_samples_async(rtl_callback, self.sampleRate / 10) def findFrame(self): currentData = self.rtlSamples.get() prevData = self.previousData.get() data = np.append(prevData, currentData) dataPosition = self.frameSync.synchronizeStartHeader(data) dataEndPosition = self.frameSync.synchronizeStopHeader( data[dataPosition:]) if abs(dataEndPosition - self.frameSizeInBits) <= self.frameSizeInBits / 10: print("Frame found. Size = " + str(dataEndPosition)) self.previousData.put(data[dataPosition + dataEndPosition:]) self.frames.put(data[dataPosition:dataPosition + dataEndPosition]) else: self.previousData.put(currentData) def processData(self): data = self.frames.get() data = self.frameSync.correctFreqAndPhase(data) data = self.timeRecover.synchronizeTiming(data) data = self.demodulator.demodulate(data) self.data.put(data) def playSound(self): dataToPlay = self.data.get() #TODO: write func return
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()
def run_total_power_int(num_samp, gain, rate, fc, t_int): ''' Implement a total-power radiometer. Raw, uncalibrated power values. Inputs: num_samp: Number of elements to sample from the SDR IQ timeseries per call gain: Requested SDR gain (dB) rate: SDR sample rate, intrinsically tied to bandwidth in SDRs (Hz) fc: Bandpass center frequency (Hz) t_int: Total integration time (s) Returns: p_tot: Time-averaged power in the signal from the sdr, in uncalibrated units ''' import rtlsdr.helpers as helpers # Start the RtlSdr instance print('Initializing rtl-sdr with pyrtlsdr:') sdr = RtlSdr() try: sdr.rs = rate sdr.fc = fc sdr.gain = gain print(' sample rate: {} MHz'.format(sdr.rs / 1e6)) print(' center frequency {} MHz'.format(sdr.fc / 1e6)) print(' gain: {} dB'.format(sdr.gain)) print(' num samples per call: {}'.format(num_samp)) print(' requested integration time: {}s'.format(t_int)) # For Nyquist sampling of the passband dv over an integration time # tau, we must collect N = 2 * dv * tau real samples. # https://www.cv.nrao.edu/~sransom/web/A1.html#S3 # Because the SDR collects complex samples at a rate rs = dv, we can # Nyquist sample a signal of band-limited noise dv with only rs * tau # complex samples. # The phase content of IQ samples allows the bandlimited signal to be # Nyquist sampled at a data rate of rs = dv complex samples per second # rather than the 2* dv required of real samples. N = int(sdr.rs * t_int) print(' => num samples to collect: {}'.format(N)) print(' => est. num of calls: {}'.format(int(N / num_samp))) global p_tot global cnt p_tot = 0.0 cnt = 0 # Set the baseline time start_time = time.time() print('Integration began at {}'.format( time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime(start_time)))) # Time integration loop @helpers.limit_calls(N / num_samp) def p_tot_callback(iq, context): # The below is a total power measurement equivalent to summing # P = V^2 / R = (sqrt(I^2 + Q^2))^2 = (I^2 + Q^2) global p_tot p_tot += np.sum(np.real(iq * np.conj(iq))) global cnt cnt += 1 sdr.read_samples_async(p_tot_callback, num_samples=num_samp) end_time = time.time() print('Integration ended at {} after {} seconds.'.format( time.strftime('%a, %d %b %Y %H:%M:%S'), end_time - start_time)) print('{} calls were made to SDR.'.format(cnt)) print('{} samples were measured at {} MHz'.format( cnt * num_samp, fc / 1e6)) print('for an effective integration time of {:.2f}s'.format( (num_samp * cnt) / rate)) # Compute the average power value based on the number of measurements # we actually did p_avg = p_tot / (num_samp * cnt) # nice and tidy sdr.close() except OSError as err: print("OS error: {0}".format(err)) raise (err) except: print('Unexpected error:', sys.exc_info()[0]) raise finally: sdr.close() return p_avg
class RtlReceiver(Process): """Set up and receive data from RTLSDR. """ def __init__(self, sample_rate, center_freq, gain, ppm, sdr_out_A, sdr_out_B, decimate, satellite=False): super(RtlReceiver, self).__init__() self.sample_rate = sample_rate self.center_freq = center_freq self.gain = gain self.freq_correction = ppm self.async_sample_size = 1024 * 24 #default 1024 self.sdr_out_A = sdr_out_A self.sdr_out_B = sdr_out_B self.decimate = decimate if satellite: # Channel 75 self.freq_shift_A = self.center_freq - 156.775 * 1e6 # Channel 76 self.freq_shift_B = self.center_freq - 156.825 * 1e6 else: # Channel 88B self.freq_shift_A = self.center_freq - 162.025 * 1e6 # Channel 87B self.freq_shift_B = self.center_freq - 161.975 * 1e6 print("Frequency shift A: {}MHz".format(self.freq_shift_A / 1e6)) print("Frequency shift B: {}MHz".format(self.freq_shift_B / 1e6)) self.fc1_A = np.exp(1.0j * 2.0 * np.pi * self.freq_shift_A / self.sample_rate * np.arange(self.async_sample_size)) self.fc1_B = np.exp(1.0j * 2.0 * np.pi * self.freq_shift_B / self.sample_rate * np.arange(self.async_sample_size)) def send_samples(self, samples, rtl): #shift frequency, filter, detect phase, and send if len(samples) == self.async_sample_size: pass else: pad = np.zeros(self.async_sample_size - len(samples)) samples = np.append(samples, pad) print("Samples padded: {}".format(len(pad))) #Frequency shift shifted_A = samples * self.fc1_A shifted_B = samples * self.fc1_B self.sdr_out_A.send(shifted_A) self.sdr_out_B.send(shifted_B) def run(self): #Import here so that a working RtlSdr isn't required to work with recordings from rtlsdr import RtlSdr, RtlSdrTcpClient self.sdr = RtlSdr() #self.sdr = RtlSdrTcpClient(hostname='192.168.0.6', port=1234) # configure device self.sdr.center_freq = self.center_freq self.sdr.sample_rate = self.sample_rate self.sdr.gain = self.gain if self.freq_correction != 0: self.sdr.freq_correction = self.freq_correction #try for some extra filtering try: #self.sdr.bandwidth = (.350 * 1e6) pass except IOError: print("No bandwidth adjustment availible.") print("SDR Frequency: {}MHz".format(self.sdr.get_center_freq() / 1e6)) print("SDR Sample Rate: {}MS/s".format(self.sdr.get_sample_rate() / 1e6)) self.sdr.read_samples_async(self.send_samples, self.async_sample_size) print("Radio closing...")
bitstr += "0" else: bitstr += "1" if bitCount < 6: scancode += 1 << bitCount bitCount += 1 bitValue = 0 if bitCount > 10: bitCount = 0 state = 0 # fin demod except: exit(0) if __name__ == "__main__": q = Queue() p = Process(target=AsyncWelchProcess, args=(q,)) p.start() def on_sample(buf, queue): queue.put(list(buf)) from rtlsdr import RtlSdr sdr = RtlSdr() # configure device sdr.sample_rate = SAMPLE_RATE # sample rate sdr.center_freq = FREQ sdr.gain = "auto" sdr.read_samples_async(on_sample, 2048, context=q)
print "Number of loops =", numberofloops #s.close(); global book_index global chart global sheet1 chart.add_series({ 'name': '=Sheet1!$B$1', 'categories': '=Sheet1!$E$2:$E$120', 'values': '=Sheet1!$B$2:$B$120', }) # Set an Excel chart style. Colors with white outline and shadow. chart.set_style(10) # Insert the chart into the worksheet (with an offset). sheet1.insert_chart('G2', chart, {'x_offset': 25, 'y_offset': 10}) sys.exit(0) signal.signal(signal.SIGINT, signal_handler) # - - - - - - - - - - - Calling the sending function - - - - - - -# sdr.read_samples_async(process_send) ############################################################################################ time.sleep(3600) for key, mask in mysel.select(timeout=1): callback = key.data callback(key.fileobj, mask) print('shutting down') mysel.close()
class RadioReceiver: def __init__(self, center_freq=446.1e6, sample_rate=250e3, freq_correction=0, buffer_size=2048, device_index=0): self._registeredQueueList = list() self._registeredQueueListLock = threading.Lock() self._sdr = RtlSdr(device_index) self._sdr.sample_rate = sample_rate self._sdr.center_freq = center_freq if self._sdr.freq_correction != freq_correction: self._sdr.freq_correction = freq_correction self._thread = threading.Thread(target=self._read_thread, args=(buffer_size, )) self._thread.start() @property def sample_rate(self): return self._sdr.sample_rate @sample_rate.setter def sample_rate(self, value): self._sdr.sample_rate = value @property def center_freq(self): return self._sdr.center_freq @center_freq.setter def center_freq(self, value): self._sdr.center_freq = value @property def freq_correction(self): return self._sdr.sample_rate @freq_correction.setter def freq_correction(self, value): if self._sdr.freq_correction != value: self._sdr.freq_correction = value def registerQueue(self, q: queue): with self._registeredQueueListLock: self._registeredQueueList.append(q) def unregisterQueue(self, q: queue): with self._registeredQueueListLock: if q in self._registeredQueueList: self._registeredQueueList.remove(q) @staticmethod def _read_samples_callback(buffer, self): with self._registeredQueueListLock: for q in self._registeredQueueList: if q.full(): q.get_nowait() q.put_nowait(buffer) def _read_thread(self, buffer_size): try: self._sdr.read_samples_async(RadioReceiver._read_samples_callback, buffer_size, self) except IOError: #IOError is raised when read_async is canceled pass def close(self): self._sdr.cancel_read_async() self._thread.join() with self._registeredQueueListLock: for q in self._registeredQueueList: if q.full(): q.get_nowait() q.put_nowait(None)