#!/usr/bin/env python # -*- coding: UTF-8 -*- # generated by wxGlade 0.3.5.1 on Fri Jun 10 10:32:01 2005 from gnuradio import gr, gru, eng_notation, optfir from gnuradio import audio_oss as audio from gnuradio import usrp, blks, tv_rx, window # from gnuradio import blks # from gnuradio import tv_rx from gnuradio.eng_option import eng_option from gnuradio.wxgui import slider, powermate from gnuradio.wxgui import stdgui, fftsink from optparse import OptionParser import sys, time import math import wx, usrp_dbid ID_EXIT = wx.NewId() ID_OPEN_FILE = wx.NewId() ID_CLOSE_FILE = wx.NewId() ID_SLIDER_1 = wx.NewId() ID_SLIDER_2 = wx.NewId() ID_SLIDER_3 = wx.NewId() ID_SLIDER_4 = wx.NewId() ID_RADIO_FREQ = wx.NewId() ID_RADIO_VOL = wx.NewId() ID_SPINBUTTON_1 = wx.NewId() ID_BUTTON_1 = wx.NewId() ID_STATION_1 = wx.NewId() ID_STATION_2 = wx.NewId() ID_STATION_3 = wx.NewId() ID_STATION_4 = wx.NewId() ID_STATION_5 = wx.NewId() ID_STATION_6 = wx.NewId() ID_STATION_7 = wx.NewId() ID_STATION_8 = wx.NewId() ID_STATION_9 = wx.NewId() ID_STATION_10 = wx.NewId() class MyFrame(wx.Frame): def __init__(self, *args, **kwds): # begin wxGlade: MyFrame.__init__ kwds["style"] = wx.DEFAULT_FRAME_STYLE wx.Frame.__init__(self, *args, **kwds) # Menu Bar self.frame_1_menubar = wx.MenuBar() self.SetMenuBar(self.frame_1_menubar) wxglade_tmp_menu = wx.Menu() wxglade_tmp_menu.Append(ID_OPEN_FILE, "Save to file", "Open", wx.ITEM_NORMAL) wxglade_tmp_menu.Append(ID_CLOSE_FILE, "Close file", "Close file", wx.ITEM_NORMAL) wxglade_tmp_menu.AppendSeparator() wxglade_tmp_menu.Append(ID_EXIT, "Exit", "Exit", wx.ITEM_NORMAL) self.frame_1_menubar.Append(wxglade_tmp_menu, "File") # Menu Bar end self.button_1 = wx.ToggleButton(self, ID_BUTTON_1, "Set", size=(40,25)) self.text_ctrl_1 = wx.TextCtrl(self, -1, "",size=(50,25)) self.button_2 = wx.Button(self, ID_STATION_1, "Station 1") self.text_ctrl_6 = wx.TextCtrl(self, -1, "",size=(50,25)) self.button_7 = wx.Button(self, ID_STATION_6, "Station 6") self.text_ctrl_2 = wx.TextCtrl(self, -1, "",size=(50,25)) self.button_3 = wx.Button(self, ID_STATION_2, "Station 2") self.text_ctrl_7 = wx.TextCtrl(self, -1, "",size=(50,25)) self.button_8 = wx.Button(self, ID_STATION_7, "Station 7") self.text_ctrl_3 = wx.TextCtrl(self, -1, "",size=(50,25)) self.button_4 = wx.Button(self, ID_STATION_3, "Station 3") self.text_ctrl_8 = wx.TextCtrl(self, -1, "",size=(50,25)) self.button_9 = wx.Button(self, ID_STATION_8, "Station 8") self.text_ctrl_4 = wx.TextCtrl(self, -1, "",size=(50,25)) self.button_5 = wx.Button(self, ID_STATION_4, "Station 4") self.text_ctrl_9 = wx.TextCtrl(self, -1, "",size=(50,25)) self.button_10 = wx.Button(self, ID_STATION_9, "Station 9") self.text_ctrl_5 = wx.TextCtrl(self, -1, "",size=(50,25)) self.button_6 = wx.Button(self, ID_STATION_5, "Station 5") self.text_ctrl_10 = wx.TextCtrl(self, -1, "",size=(50,25)) self.button_11 = wx.Button(self, ID_STATION_10, "Station 10") self.gauge_=[] for i in range(2,34): self.gauge_.append(wx.Gauge(self, -1, 300, style=wx.GA_VERTICAL)) self.label_2 = wx.StaticText(self, -1, " Frequency") self.bitmap_1 = wx.StaticBitmap(self, -1, wx.Bitmap("./fancydigitalgreen/1.bmp", wx.BITMAP_TYPE_ANY)) self.bitmap_2 = wx.StaticBitmap(self, -1, wx.Bitmap("./fancydigitalgreen/0.bmp", wx.BITMAP_TYPE_ANY)) self.bitmap_3 = wx.StaticBitmap(self, -1, wx.Bitmap("./fancydigitalgreen/2.bmp", wx.BITMAP_TYPE_ANY)) self.bitmap_4 = wx.StaticBitmap(self, -1, wx.Bitmap("./fancydigitalgreen/7.bmp", wx.BITMAP_TYPE_ANY)) self.radio_btn_1 = wx.RadioButton(self, ID_RADIO_FREQ, "frequency", style=wx.RB_GROUP) self.spin_button_1 = wx.SpinButton(self, ID_SPINBUTTON_1 ) self.label_3 = wx.StaticText(self, -1, " Volume") self.slider_4 = wx.Slider(self, ID_SLIDER_4, 0, 0, 2000) self.radio_btn_2 = wx.RadioButton(self, ID_RADIO_VOL, "volume") self.panel_2 = wx.Panel(self, -1) self.label_1 = wx.StaticText(self, -1, " RF Gain ") self.slider_1 = wx.Slider(self, ID_SLIDER_1, 0, 0, 115) self.label_4 = wx.StaticText(self, -1, " Stereo Adjust") self.slider_2 = wx.Slider(self, ID_SLIDER_2, 0, 0, 260) self.panel_4 = wx.Panel(self, -1) self.label_5 = wx.StaticText(self, -1, " Pilot power ") self.slider_3 = wx.Slider(self, ID_SLIDER_3, 0, 0, 100) self.gauge_34 = wx.Gauge(self, -1, 100, style=wx.GA_VERTICAL) self.panel_5 = wx.Panel(self, -1) # end wxGlade # wxpython gui events wx.EVT_MENU(self, ID_EXIT, self.MenuExit) wx.EVT_MENU(self, ID_OPEN_FILE, self.MenuOpenFile) wx.EVT_MENU(self, ID_CLOSE_FILE, self.MenuCloseFile) wx.EVT_SLIDER(self, ID_SLIDER_1, self.set_gain) wx.EVT_SLIDER(self, ID_SLIDER_2, self.set_adv) wx.EVT_SLIDER(self, ID_SLIDER_3, self.set_power) wx.EVT_SLIDER(self, ID_SLIDER_4, self.volume) wx.EVT_RADIOBUTTON(self, ID_RADIO_FREQ, self.radio_button) wx.EVT_RADIOBUTTON(self, ID_RADIO_VOL, self.radio_button) wx.EVT_SPIN(self, ID_SPINBUTTON_1, self.spin_button) wx.EVT_BUTTON(self, ID_STATION_1, self.station) wx.EVT_BUTTON(self, ID_STATION_2, self.station) wx.EVT_BUTTON(self, ID_STATION_3, self.station) wx.EVT_BUTTON(self, ID_STATION_4, self.station) wx.EVT_BUTTON(self, ID_STATION_5, self.station) wx.EVT_BUTTON(self, ID_STATION_6, self.station) wx.EVT_BUTTON(self, ID_STATION_7, self.station) wx.EVT_BUTTON(self, ID_STATION_8, self.station) wx.EVT_BUTTON(self, ID_STATION_9, self.station) wx.EVT_BUTTON(self, ID_STATION_10, self.station) self.s1 = 88.5 self.text_ctrl_1.SetValue("88.5") self.s2 = 94.5 self.text_ctrl_2.SetValue("94.5") self.s3 = 99.9 self.text_ctrl_3.SetValue("99.9") self.s4 = 100.9 self.text_ctrl_4.SetValue("100.9") self.s5 = 102.7 self.text_ctrl_5.SetValue("102.7") self.s6 = 105.1 self.text_ctrl_6.SetValue("105.1") self.s7 = 107.3 self.text_ctrl_7.SetValue("107.3") self.s8 = 88.1 self.text_ctrl_8.SetValue("88.1") self.s9 = 88.1 self.text_ctrl_9.SetValue("88.1") self.s10 = 88.1 self.text_ctrl_10.SetValue("88.1") # blocks needed for save to file # This creates a signed-word 2-channel (stereo) file at 32000 hz # convert to wav file with: sox -c 2 -r 32000 hfx_out.sw hfx_out.wav self.FILEOPEN = False self.stereo = gr.interleave(gr.sizeof_short) self.sc1 = gr.multiply_const_ff(378000) self.sc2 = gr.multiply_const_ff(378000) self.f2s1 = gr.float_to_short() self.f2s2 = gr.float_to_short() # load pretty green numerals self.n_ = [] for i in range(0, 10): fname = "./fancydigitalgreen/"+str(i)+".bmp" self.n_.append(wx.Bitmap(fname, wx.BITMAP_TYPE_ANY)) # radio from tvrx_wfm_rcv_gui_pm.py self.fg = gr.flow_graph() self.vol = .5 self.state = "FREQ" adc_rate = 64e6 usrp_decim = 250 self.quad_rate = adc_rate / usrp_decim # 256000 audio_decimation = 8 self.audio_rate = self.quad_rate / audio_decimation # 32 kHz # usrp is data source src = usrp.source_c (0, usrp_decim) self.src = src rx_subdev_spec = pick_subdevice(self.src) self.src.set_mux(usrp.determine_rx_mux_value(self.src, rx_subdev_spec)) self.subdev = usrp.selected_subdev(self.src, rx_subdev_spec) print "Using RX d'board %s" % (self.subdev.side_and_name(),) # set up frontend self.set_freq(102.7) # from Achilleas stereo FM # Demodulation of the MUX signal-->input: complex; output: float peak_composite = 1.0 fm_demod_gain = 1.0 / (2 * math.pi * 75e3 / peak_composite / self.quad_rate) print "FM demodulator gain =", fm_demod_gain volume = 2.0 fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain) # L+R processing: LPF + decimation # compute FIR filter taps for audio filter width = 1e3 # the 0.5 gain compensates for (L+R)+(L-R)=2L audio_coefs = gr.firdes.low_pass (0.5, self.quad_rate, 15e3, width, gr.firdes.WIN_HAMMING) audio_filter_lpr = gr.fir_filter_fff (audio_decimation, audio_coefs) # Pilot extraction: BPF, squarer # compute FIR filter taps for pilot filter # FIX ME: we need a power-meter/AGC to adjust the pilot amplitude Ap=math.sqrt(0.00012) * fm_demod_gain / (2200.0/32768.0) # this seems to work fine, but why? print "Pilot power = ", Ap*Ap/2 p_width = 1e3 pilot_coefs = gr.firdes.band_pass (2/Ap, self.quad_rate, 19e3-p_width/2, 19e3+p_width/2, p_width, gr.firdes.WIN_HAMMING) f0=19e3 d1 = find_arg(pilot_coefs,self.quad_rate,f0) print "Delay of Pilot BPF @", f0, " = ", d1 pilot_filter = gr.fir_filter_fff(1, pilot_coefs) self.p_adjust = gr.multiply_const_ff(.5) self.p_meter = gr.probe_avg_mag_sqrd_f(1,.01) # square the pilot to get the 38KHz local carrier (should result in a unit amplitude carrier @ 38KHz --- effect of DC term is removed later) square = gr.multiply_ff() # L-R processing: BPF, L-R demod, LPF, decimation # compute FIR filter taps for bandpass L-R filter width = 1e3 band_coefs = gr.firdes.band_pass (1.0,self.quad_rate, 23e3, 53e3, width, gr.firdes.WIN_HAMMING) f0 = 38e3+0e3 d2 = find_arg(band_coefs,self.quad_rate,f0) print "Delay of BPF @", f0 , " = ", d2 band_filter = gr.fir_filter_fff (1, band_coefs) # calc total advance required # adv = math.fmod(d1 - d2 , 1/38e3) self.adv = 12e-6 print "Required Advance = ", self.adv # design the interpolation filter self.degree = 1 a_coefs = build_advance_interpolator(self.quad_rate,self.adv,self.degree,False,sinc) print a_coefs self.a_filter = gr.fir_filter_fff (1, a_coefs) # demodulation of L-R demod_lmr = gr.multiply_ff() audio_filter_lmr = gr.fir_filter_fff (audio_decimation, audio_coefs) # DEMUX of L and R channels and deemphasis Left = gr.add_ff() Right = gr.sub_ff() fs = self.quad_rate tau=75e-6 w_p = 1/tau w_pp = math.tan (w_p / (fs * 2)) # prewarped analog freq a1 = (w_pp - 1)/(w_pp + 1) b0 = w_pp/(1 + w_pp) b1 = b0 btaps = [b0, b1] ataps = [1, a1] self.deemphl = gr.iir_filter_ffd(btaps, ataps) self.deemphr = gr.iir_filter_ffd(btaps, ataps) self.volume_control_l = gr.multiply_const_ff(self.vol) self.volume_control_r = gr.multiply_const_ff(self.vol) combine = gr.add_ff() self.audio_sink = audio.sink (int (self.audio_rate)) # Wire it self.fg.connect (src, fm_demod) # head self.fg.connect (fm_demod, audio_filter_lpr) self.fg.connect (fm_demod, pilot_filter) self.fg.connect (pilot_filter,self.p_adjust,self.p_meter) self.fg.connect (self.p_adjust,(square,0)) self.fg.connect (fm_demod,band_filter) self.fg.connect (self.p_adjust,(square,1)) self.fg.connect (band_filter,(demod_lmr,0)) self.fg.connect (square,self.a_filter) self.fg.connect (self.a_filter,(demod_lmr,1)) self.fg.connect (demod_lmr, audio_filter_lmr) self.fg.connect (audio_filter_lpr,(Left,0)) self.fg.connect (audio_filter_lmr,(Left,1)) self.fg.connect (audio_filter_lpr,(Right,0)) self.fg.connect (audio_filter_lmr,(Right,1)) self.fg.connect (Left,self.deemphl,self.volume_control_l,(self.audio_sink,0)) self.fg.connect (Right,self.deemphr,self.volume_control_r,(self.audio_sink,1)) self.fg.connect (Left,(combine,0)) self.fg.connect (Right,(combine,1)) self.slider_1.SetValue(55) self.set_gain(ID_SLIDER_1) self.slider_4.SetValue(int(self.vol*200)) self.slider_3.SetValue(25) fft_size = 64 scale4display = gr.multiply_const_ff(2) hilbert = gr.hilbert_fc(197) s2v = gr.stream_to_vector (gr.sizeof_gr_complex, fft_size) mywindow = window.blackmanharris(fft_size) fft = gr.fft_vcc (fft_size,True,mywindow) # size, fwd, window v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) s2ss = gr.stream_to_streams (gr.sizeof_gr_complex, fft_size) self.fg.connect(combine,scale4display,hilbert,s2v,fft,v2s,s2ss) alpha = .01 self.L=[] for i in range(0,32): self.L.append(gr.probe_avg_mag_sqrd_c(1,alpha)) sink = gr.null_sink(gr.sizeof_gr_complex) self.fg.connect((s2ss,0),sink) for i in range(0,32): # sink = gr.null_sink(gr.sizeof_gr_complex) self.fg.connect((s2ss,i+1),self.L[i]) # ,sink) for i in range(33,64): sink = gr.null_sink(gr.sizeof_gr_complex) self.fg.connect((s2ss,i),sink) # time for updating gauges every 30 mSec self.timer = UpdateTimer(self, 30) POWERMATE = True try: self.knob = powermate.powermate(self) self.rot = 0 powermate.EVT_POWERMATE_ROTATE (self, self.on_rotate) powermate.EVT_POWERMATE_BUTTON (self, self.on_button) except: print "No Powermate or Contour Knob found" POWERMATE = False self.brightness = 128 self.pulse_speed = 0 if POWERMATE: self.knob.set_led_state(self.brightness, self.pulse_speed) self.__set_properties() self.__do_layout() self.fg.start() def __set_properties(self): # begin wxGlade: MyFrame.__set_properties self.SetTitle("GNU Radio Rocks !") for i in range(0,32): self.gauge_[i].SetSize((12, 150)) self.gauge_[i].SetBackgroundColour(wx.Colour(0, 255, 0)) self.label_2.SetSize((100, 17)) self.label_3.SetSize((100, 17)) self.slider_4.SetSize((110, 19)) self.label_1.SetSize((110, 25)) self.slider_1.SetSize((200, 60)) self.label_4.SetSize((110, 25)) self.slider_2.SetSize((200, 60)) self.label_5.SetSize((110, 25)) self.slider_3.SetSize((200, 60)) self.gauge_34.SetSize((10, 100)) # end wxGlade self.spin_button_1.SetRange(881,1081) self.spin_button_1.SetValue(1027) self.slider_2.SetValue(self.adv*1e7) def __do_layout(self): # begin wxGlade: MyFrame.__do_layout grid_sizer_1 = wx.FlexGridSizer(6, 1, 0, 0) sizer_4 = wx.BoxSizer(wx.HORIZONTAL) sizer_2 = wx.BoxSizer(wx.HORIZONTAL) sizer_1 = wx.BoxSizer(wx.HORIZONTAL) grid_sizer_2 = wx.FlexGridSizer(2, 4, 0, 0) sizer_3 = wx.BoxSizer(wx.HORIZONTAL) grid_sizer_3 = wx.FlexGridSizer(1, 32, 0, 0) sizer_5 = wx.BoxSizer(wx.HORIZONTAL) grid_sizer_4 = wx.GridSizer(5, 4, 0, 0) sizer_5.Add(self.button_1, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.text_ctrl_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.button_2, 0, wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.text_ctrl_6, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.button_7, 0, wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.text_ctrl_2, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.button_3, 0, wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.text_ctrl_7, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.button_8, 0, wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.text_ctrl_3, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.button_4, 0, wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.text_ctrl_8, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.button_9, 0, wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.text_ctrl_4, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.button_5, 0, wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.text_ctrl_9, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.button_10, 0, wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.text_ctrl_5, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.button_6, 0, wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.text_ctrl_10, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.button_11, 0, wx.FIXED_MINSIZE, 0) sizer_5.Add(grid_sizer_4, 1, wx.EXPAND, 0) grid_sizer_1.Add(sizer_5, 1, wx.EXPAND, 0) for i in range(0,32): grid_sizer_3.Add(self.gauge_[i], 0, wx.FIXED_MINSIZE, 0) grid_sizer_1.Add(grid_sizer_3, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.label_2, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) sizer_3.Add(self.bitmap_1, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) sizer_3.Add(self.bitmap_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) sizer_3.Add(self.bitmap_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) sizer_3.Add(self.bitmap_4, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(sizer_3, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.radio_btn_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.spin_button_1, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.label_3, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.slider_4, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.radio_btn_2, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.panel_2, 1, wx.EXPAND, 0) grid_sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0) sizer_1.Add(self.label_1, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) sizer_1.Add(self.slider_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_1.Add(sizer_1, 1, wx.EXPAND, 0) sizer_2.Add(self.label_4, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) sizer_2.Add(self.slider_2, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) sizer_2.Add(self.panel_4, 1, wx.EXPAND, 0) grid_sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) sizer_4.Add(self.label_5, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) sizer_4.Add(self.slider_3, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) sizer_4.Add(self.gauge_34, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) sizer_4.Add(self.panel_5, 1, wx.EXPAND, 0) grid_sizer_1.Add(sizer_4, 1, wx.EXPAND, 0) self.SetAutoLayout(True) self.SetSizer(grid_sizer_1) grid_sizer_1.Fit(self) grid_sizer_1.SetSizeHints(self) self.Layout() # end wxGlade def MenuExit(self, event): self.fg.stop() self.Close() def set_gain (self,event): gain = self.slider_1.GetValue() self.subdev.set_gain(gain) def spin_button (self, event): id = event.GetId() if id == ID_SPINBUTTON_1: self.set_freq(self.spin_button_1.GetValue()/10.) self.update_display(self.station) def on_rotate (self, event): self.rot += event.delta if (self.state == "FREQ"): if self.rot >= 3: self.set_freq(self.station + .1) self.update_display(self.station) self.spin_button_1.SetValue(int(self.station*10)) self.rot -= 3 elif self.rot <=-3: self.set_freq(self.station - .1) self.update_display(self.station) self.spin_button_1.SetValue(int(self.station*10)) self.rot += 3 elif (self.state == "VOL"): if self.rot >= 3: self.set_vol(self.vol * 1.05) if self.vol < 10: self.slider_4.SetValue(int(self.vol*200)) else: self.slider_4.SetValue(2000) self.rot -= 3 elif self.rot <=-3: self.set_vol(self.vol * .95) if self.vol < 10: self.slider_4.SetValue(int(self.vol*200)) else: self.slider_4.SetValue(2000) self.rot += 3 def on_button (self, event): if event.value == 0: # button up return self.rot = 0 if self.state == "VOL": self.state = "FREQ" self.radio_btn_1.SetValue(True) self.brightness = 128 self.knob.set_led_state(self.brightness, self.pulse_speed) elif self.state == "FREQ": self.state = "VOL" self.radio_btn_2.SetValue(True) self.brightness = 128 self.knob.set_led_state(self.brightness, self.pulse_speed) def set_adv (self, event): self.adv = self.slider_2.GetValue()*.1e-6 if self.adv < 0: self.adv = 0 if self.adv > 1/38e3: self.adv = 0 self.slider_2.SetValue(int(10e6*self.adv)) a_coefs = build_advance_interpolator(self.quad_rate,self.adv,self.degree,False,sinc) self.a_filter.set_taps(a_coefs) def set_freq(self, target_freq): self.station = target_freq target_freq = target_freq * 1e6 """ Set the center frequency we're interested in. @param target_freq: frequency in Hz @rypte: bool Tuning is a two step process. First we ask the front-end to tune as close to the desired frequency as it can. Then we use the result of that operation and our target_frequency to determine the value for the digital down converter. """ r = self.src.tune(0, self.subdev, target_freq) if r: self.freq = target_freq return True return False def volume (self, event): if self.slider_4.GetValue() > 200: self.set_vol(self.slider_4.GetValue()/200) def set_vol (self, vol): self.vol = vol self.volume_control_l.set_k(self.vol) self.volume_control_r.set_k(self.vol) def update_display(self, freq): n = int(freq * 10 + .000001) # needs a little help over the digit bound d = int(n/1e3) self.bitmap_1.SetBitmap(self.n_[d]) n -= int(d*1e3) d = int(n/1e2) self.bitmap_2.SetBitmap(self.n_[d]) n -= int(d*1e2) d = int(n/1e1) self.bitmap_3.SetBitmap(self.n_[d]) n -= int(d*1e1) d = int(n/1e0) self.bitmap_4.SetBitmap(self.n_[d]) def radio_button(self, event): id = event.GetId() if id == ID_RADIO_FREQ: self.state = "FREQ" if id == ID_RADIO_VOL: self.state = "VOL" def OnUpdate(self): for i in range (0, 32): self.gauge_[i].SetValue(min(300,self.L[i].level())) # pilot power self.gauge_34.SetValue(min(100,self.p_meter.level()*25)) def set_power(self,event): self.p_adjust.set_k(self.slider_3.GetValue()/50.) def MenuOpenFile(self,event): fname = wx.GetTextFromUser("Enter Filename",caption="Enter File to save to:",default_value="music.sw") if fname !='': self.save = gr.file_sink(gr.sizeof_short,str(fname)) self.FILEOPEN = True self.fg.stop() self.fg.connect (self.deemphl, self.sc1) self.fg.connect (self.deemphr, self.sc2) self.fg.connect (self.sc1, self.f2s1) self.fg.connect (self.sc2, self.f2s2) self.fg.connect (self.f2s1, (self.stereo, 0)) self.fg.connect (self.f2s2, (self.stereo, 1)) self.fg.connect (self.stereo, self.save) self.fg.start() def MenuCloseFile(self, event): if self.FILEOPEN == True: self.fg.stop() self.FILEOPEN = False self.fg.disconnect(self.deemphl,self.sc1) self.fg.disconnect(self.deemphr,self.sc2) self.fg.disconnect(self.sc1, self.f2s1) self.fg.disconnect(self.sc2, self.f2s2) self.fg.disconnect(self.f2s1, (self.stereo, 0)) self.fg.disconnect(self.f2s2, (self.stereo, 1)) self.fg.disconnect(self.stereo, self.save) self.fg.start() def station(self, event): id = event.GetId() if self.button_1.GetValue(): if id == ID_STATION_1: self.s1 = self.station self.text_ctrl_1.SetValue(str(self.station)) if id == ID_STATION_2: self.s2 = self.station self.text_ctrl_2.SetValue(str(self.station)) if id == ID_STATION_3: self.s3 = self.station self.text_ctrl_3.SetValue(str(self.station)) if id == ID_STATION_4: self.s4 = self.station self.text_ctrl_4.SetValue(str(self.station)) if id == ID_STATION_5: self.s5 = self.station self.text_ctrl_5.SetValue(str(self.station)) if id == ID_STATION_6: self.s6 = self.station self.text_ctrl_6.SetValue(str(self.station)) if id == ID_STATION_7: self.s7 = self.station self.text_ctrl_7.SetValue(str(self.station)) if id == ID_STATION_8: self.s8 = self.station self.text_ctrl_8.SetValue(str(self.station)) if id == ID_STATION_9: self.s9 = self.station self.text_ctrl_9.SetValue(str(self.station)) if id == ID_STATION_10: self.s10 = self.station self.text_ctrl_10.SetValue(str(self.station)) self.button_1.SetValue(False) else: if id == ID_STATION_1: self.station = self.s1 if id == ID_STATION_2: self.station = self.s2 if id == ID_STATION_3: self.station = self.s3 if id == ID_STATION_4: self.station = self.s4 if id == ID_STATION_5: self.station = self.s5 if id == ID_STATION_6: self.station = self.s6 if id == ID_STATION_7: self.station = self.s7 if id == ID_STATION_8: self.station = self.s8 if id == ID_STATION_9: self.station = self.s9 if id == ID_STATION_10: self.station = self.s10 self.set_freq(self.station) self.update_display(self.station) self.spin_button_1.SetValue(int(self.station*10)) # end of class MyFrame # utilities for FM stereo def find_arg(coefs,rate,f0): l = len(coefs) ii = range(l) s=0 for i in ii: p = -2*math.pi*ii[i]*f0/rate s = s + coefs[ii[i]] * (math.cos(p) + math.sin(p) * (0+1j)) s=s.conjugate() # because of the way GNURADIO implements filtering phi = argument(s) #print "argument = " , phi * 180 / math.pi #print "norm delay = ", - phi / 2 / math.pi / (f0/rate) delay = - phi / 2 / math.pi / f0 #print "absolute delay =", delay return delay def argument(c): if c.real > 0: phi = math.atan(c.imag/c.real) elif c.imag > 0: phi = math.atan(c.imag/c.real) + math.pi else: phi = math.atan(c.imag/c.real) - math.pi return phi def build_advance_interpolator(rate,advance,degree,symmetric,pulse): if advance<0: print "cannot implement negative advances, ie, delays" return -1 m=int(advance*rate) Delta = advance*rate - m # print m, Delta # interpolator using x_{k+m} and x_{k+m+d} if symmetric == False: c=[] i=0 while i <= m-1: c.append(0) i=i+1 i=0 while i <= degree: c.append(pulse(Delta-i)) i=i+1 c.reverse() return tuple(c) # interpolator using x_{k+m-d} .... x_{k+m+d} if degree > m: print "degree not consistent with advance" return -2 c=[] i=0 while i <= m-degree-1: c.append(0) i=i+1 i=-degree while i <= degree: c.append(pulse(Delta-i)) i=i+1 c.reverse() return tuple(c) def sinc(x): if x == 0: return 1 else: return math.sin(math.pi * x)/(math.pi * x) def pick_subdevice(u): """ The user didn't specify a subdevice on the command line. Try for one of these, in order: TV_RX, BASIC_RX, whatever is on side A. @return a subdev_spec """ return usrp.pick_subdev(u, (usrp_dbid.TV_RX, usrp_dbid.TV_RX_REV_2, usrp_dbid.BASIC_RX)) class UpdateTimer(wx.Timer): def __init__(self, target, dur=1000): wx.Timer.__init__(self) self.target = target self.Start(dur) def Notify(self): """Called every timer interval""" if self.target: self.target.OnUpdate() class MyApp(wx.App): def OnInit(self): frame = MyFrame(None, -1, "GNU FM Radio") frame.Show(True) self.SetTopWindow(frame) return True app = MyApp(0) app.MainLoop()