#!/usr/bin/env python # -*- coding: UTF-8 -*- # generated by wxGlade 0.3.5.1 on Tue Nov 8 14:53:23 2005 # # Copyright 2005 Free Software Foundation, Inc. # # This file is part of GNU Radio # # GNU Radio is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # GNU Radio is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Radio; see the file COPYING. If not, write to # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # import wx from gnuradio import gr, gru, usrp import usrp_siggen from gnuradio.eng_option import eng_option from optparse import OptionParser from gnuradio import eng_notation import math, time import Gnuplot ID_SPINCTRL_1 = wx.NewId() ID_TEXTCTRL_1 = wx.NewId() ID_BUTTON_1 = wx.NewId() ID_BUTTON_2 = wx.NewId() ID_BUTTON_3 = wx.NewId() ID_BUTTON_4 = wx.NewId() ID_BUTTON_5 = wx.NewId() ID_EXIT = 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) self.File = wx.Menu() self.Exit = wx.MenuItem(self.File, ID_EXIT, "Exit", "", wx.ITEM_NORMAL) self.File.AppendItem(self.Exit) self.frame_1_menubar.Append(self.File, "File") # Menu Bar end self.label_1 = wx.StaticText(self, -1, "Frequency: ") self.spin_ctrl_1 = wx.SpinCtrl(self, ID_SPINCTRL_1, "", min=2, max=250) self.label_2 = wx.StaticText(self, -1, " X 100Khz ") self.button_1 = wx.Button(self, ID_BUTTON_1, "Start") self.label_3 = wx.StaticText(self, -1, "Amplitude: ") self.text_ctrl_1 = wx.TextCtrl(self, ID_TEXTCTRL_1, "", style=wx.TE_PROCESS_ENTER) self.panel_1 = wx.Panel(self, -1) self.button_2 = wx.Button(self, ID_BUTTON_2, "Stop") self.label_4 = wx.StaticText(self, -1, "DUC/DDC: ") self.text_ctrl_2 = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY) self.label_5 = wx.StaticText(self, -1, "Frequency Out: ") self.text_ctrl_3 = wx.TextCtrl(self, -1, "", style=wx.TE_READONLY) self.panel_6 = wx.Panel(self, -1) self.panel_7 = wx.Panel(self, -1) self.panel_8 = wx.Panel(self, -1) self.panel_9 = wx.Panel(self, -1) self.static_line_1 = wx.StaticLine(self, -1) self.static_line_2 = wx.StaticLine(self, -1) self.static_line_3 = wx.StaticLine(self, -1) self.static_line_4 = wx.StaticLine(self, -1) self.panel_2 = wx.Panel(self, -1) self.panel_3 = wx.Panel(self, -1) self.panel_4 = wx.Panel(self, -1) self.panel_5 = wx.Panel(self, -1) self.label_6 = wx.StaticText(self, -1, "Amplitude In: ") self.text_ctrl_4 = wx.TextCtrl(self, -1, "") self.label_7 = wx.StaticText(self, -1, " Gamma Real: ") self.text_ctrl_7 = wx.TextCtrl(self, -1, "") self.label_8 = wx.StaticText(self, -1, " Phase In: ") self.text_ctrl_5 = wx.TextCtrl(self, -1, "") self.label_9 = wx.StaticText(self, -1, " Gamma Imag: ") self.text_ctrl_8 = wx.TextCtrl(self, -1, "") self.label_10 = wx.StaticText(self, -1, " R / Zo: ") self.text_ctrl_10 = wx.TextCtrl(self, -1, "") self.label_11 = wx.StaticText(self, -1, " R (Zo=50): ") self.text_ctrl_6 = wx.TextCtrl(self, -1, "") self.label_12 = wx.StaticText(self, -1, " X / Zo: ") self.text_ctrl_11 = wx.TextCtrl(self, -1, "") self.label_13 = wx.StaticText(self, -1, " L or C: ") self.text_ctrl_9 = wx.TextCtrl(self, -1, "") self.panel_10 = wx.Panel(self, -1) self.panel_11 = wx.Panel(self, -1) self.panel_12 = wx.Panel(self, -1) self.panel_13 = wx.Panel(self, -1) self.static_line_5 = wx.StaticLine(self, -1) self.static_line_6 = wx.StaticLine(self, -1) self.static_line_7 = wx.StaticLine(self, -1) self.static_line_8 = wx.StaticLine(self, -1) self.panel_14 = wx.Panel(self, -1) self.panel_15 = wx.Panel(self, -1) self.panel_16 = wx.Panel(self, -1) self.panel_17 = wx.Panel(self, -1) self.label_14 = wx.StaticText(self, -1, " Calibrate:") self.panel_20 = wx.Panel(self, -1) self.button_3 = wx.Button(self, ID_BUTTON_3, "Open") self.panel_21 = wx.Panel(self, -1) self.button_4 = wx.Button(self, ID_BUTTON_4, "Short") self.panel_22 = wx.Panel(self, -1) self.button_5 = wx.Button(self, ID_BUTTON_5, "Load") self.panel_23 = wx.Panel(self, -1) self.panel_18 = wx.Panel(self, -1) self.panel_19 = wx.Panel(self, -1) self.__set_properties() self.__do_layout() # end wxGlade wx.EVT_MENU(self, ID_EXIT, self.MenuExit) wx.EVT_TEXT_ENTER(self, ID_TEXTCTRL_1, self.SetAmplitude) wx.EVT_BUTTON(self, ID_BUTTON_1, self.Start) wx.EVT_BUTTON(self, ID_BUTTON_2, self.Stop) wx.EVT_BUTTON(self, ID_BUTTON_3, self.Calibrate) wx.EVT_BUTTON(self, ID_BUTTON_4, self.Calibrate) wx.EVT_BUTTON(self, ID_BUTTON_5, self.Calibrate) wx.EVT_SPINCTRL(self, ID_SPINCTRL_1, self.SetFrequency) parser = OptionParser (option_class=eng_option) parser.add_option ("-f", "--freq", type="eng_float", default=10e6, help="set frequency") parser.add_option ("-a", "--amplitude", type="eng_float", default=8e3, help="set waveform amplitude to AMPLITUDE", metavar="AMPL") (options, args) = parser.parse_args () self.run = False # ideal values self.CalibOpen = complex(1,0) self.CalibShort = complex(-1,0) self.CalibLoad = complex(0,0) self.Ed = self.CalibLoad self.Es = ( 2 * self.CalibLoad - ( self.CalibShort + self.CalibOpen ) ) / ( self.CalibShort - self.CalibOpen ) self.Et = ( 2 * ( self.CalibOpen + self.CalibLoad ) * ( self.CalibShort + self.CalibLoad ) ) / ( self.CalibShort - self.CalibOpen ) self.amplitude = options.amplitude self.text_ctrl_1.SetValue(eng_notation.num_to_str(self.amplitude)) self.freq = options.freq self.spin_ctrl_1.SetValue(int(self.freq/100e3)) self.f_ducddc = self.freq + 275e3 self.text_ctrl_2.SetValue(eng_notation.num_to_str(self.f_ducddc)) self.f_losc = -275e3 self.step_time = 250 self.timer = UpdateTimer(self,self.step_time) self.fg = gr.flow_graph() self.sample_freq = 1e6 # system impedance self.Zo = 50. # realtime display of phase and mag self.g = Gnuplot.Gnuplot() self.g('set size square') self.g('set time') self.g('set clip') self.g('set xtics axis nomirror') self.g('set ytics axis nomirror') self.g('unset grid') self.g('unset polar') self.g('set title "Primitive Smith Chart"') self.g('unset key') self.g('set xlabel "Impedance or Admittance Coordinates"') self.g('set para') self.g('set rrange [-0 : 10]') self.g('set trange [-pi : pi]') self.g('set xrange [-1:1]') self.g('set yrange [-1:1]') self.g('tv(t,r) = sin(t)/(1+r)') self.g('tu(t,r) = (cos(t) +r)/(1+r)') self.g('cu(t,x) = 1 + cos(t)/x') self.g('cv(t,x) = (1+ sin(t))/x') fp = open("plot_data","w") fp.write('0.5 0.5') fp.close() self.g('plot cu(t,.1),cv(t,.1),cu(t,.1),-cv(t,.1),cu(t,1),cv(t,1),cu(t,1),-cv(t,1),cu(t,10),cv(t,10),cu(t,10),-cv(t,10),tu(t,.1),tv(t,.1),tu(t,.5),tv(t,.5),tu(t,1),tv(t,1),tu(t,5),tv(t,5),tu(t,10),tv(t,10),cu(t,.5),cv(t,.5),cu(t,.5),-cv(t,.5),tu(t,0),tv(t,0),"plot_data"') # setup usrp decim = 64 self.dut_out = usrp.source_c(0, decim, 2, gru.hexint(0xf0f0f1f0), 0) self.dut_out.set_rx_freq(0,-self.f_ducddc) self.dut_out.set_rx_freq(1,-self.f_ducddc) rx_error = -self.f_ducddc - self.dut_out.rx_freq(0) self.dut_out.set_pga(0,8) self.dut_out.set_pga(1,0) # signal generator self.interp = 128 self.type = gr.GR_SIN_WAVE self.offset = 0 self.nchannels = 1 self.mux = 0x0098 self.sg = usrp_siggen.siggen () self.sg.set_waveform_ampl (self.amplitude) self.sg.set_waveform_freq (-275e3) self.sg.set_interpolator (self.interp) self.sg.set_waveform_type (self.type) self.sg.set_waveform_offset (self.offset) self.sg.set_duc_freq (self.f_ducddc) self.sg.usrp.set_nchannels (self.nchannels) self.sg.usrp.set_mux (self.mux) self.sg.fg.start () head = gr.stream_to_streams(gr.sizeof_gr_complex,2) mul1 = gr.multiply_ff() c2f1 = gr.complex_to_float () self.meter = gr.probe_signal_f() lp_taps = gr.firdes.low_pass ( .001, self.sample_freq, 5e3, 10e3, gr.firdes.WIN_HAMMING ) self.lp = gr.fir_filter_fff(1,lp_taps) # agc self.i_meter = gr.probe_avg_mag_sqrd_c(1,.0001) self.o_meter = gr.probe_avg_mag_sqrd_c(1,.0001) self.pga1 = gr.multiply_const_cc(complex(1,0)) self.pga2 = gr.multiply_const_cc(complex(1,0)) c2f2 = gr.complex_to_float () c2f4 = gr.complex_to_float () self.pshift = gr.multiply_const_cc(complex(1,0)) # # (gain control in python script) # (o_meter)------+ # 0,J19 | V # +------------------+-------(pga1)--(c2f4)--+ # usrp | | # (dut_out)--(head) (mul1)--(lp)--> # | | # +---(pshift)---------------(pga2)--(c2f1)--+ # 1,J18 | ^ # (i_meter)------| # (gain control in pythong script) # # >---(meter) # # # self.fg.connect ( self.dut_out, head ) self.fg.connect ( (head, 1), self.pshift, self.pga2, c2f1, (mul1, 0) ) self.fg.connect ( self.pshift, self.i_meter ) self.fg.connect ( (head, 0), self.pga1, c2f4, (mul1, 1) ) self.fg.connect ( (head, 0), self.o_meter ) self.fg.connect ( mul1, self.lp, self.meter ) self.fg.start() def __set_properties(self): # begin wxGlade: MyFrame.__set_properties self.SetTitle("Simple HF VNA") self.text_ctrl_9.SetSize((140, 25)) # end wxGlade def __do_layout(self): # begin wxGlade: MyFrame.__do_layout sizer_1 = wx.BoxSizer(wx.VERTICAL) grid_sizer_1 = wx.FlexGridSizer(3, 1, 0, 0) grid_sizer_4 = wx.FlexGridSizer(5, 2, 0, 0) grid_sizer_3 = wx.FlexGridSizer(7, 4, 0, 0) grid_sizer_2 = wx.FlexGridSizer(6, 4, 0, 0) grid_sizer_2.Add(self.label_1, 0, wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.spin_ctrl_1, 0, wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.label_2, 0, wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.button_1, 0, wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.label_3, 0, wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.text_ctrl_1, 0, wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.panel_1, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.button_2, 0, wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.label_4, 0, wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.text_ctrl_2, 0, wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.label_5, 0, wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.text_ctrl_3, 0, wx.FIXED_MINSIZE, 0) grid_sizer_2.Add(self.panel_6, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.panel_7, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.panel_8, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.panel_9, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.static_line_1, 0, wx.EXPAND, 0) grid_sizer_2.Add(self.static_line_2, 0, wx.EXPAND, 0) grid_sizer_2.Add(self.static_line_3, 0, wx.EXPAND, 0) grid_sizer_2.Add(self.static_line_4, 0, wx.EXPAND, 0) grid_sizer_2.Add(self.panel_2, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.panel_3, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.panel_4, 1, wx.EXPAND, 0) grid_sizer_2.Add(self.panel_5, 1, wx.EXPAND, 0) grid_sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0) grid_sizer_3.Add(self.label_6, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.text_ctrl_4, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.label_7, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.text_ctrl_7, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.label_8, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.text_ctrl_5, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.label_9, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.text_ctrl_8, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.label_10, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.text_ctrl_10, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.label_11, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.text_ctrl_6, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.label_12, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.text_ctrl_11, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.label_13, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.text_ctrl_9, 0, wx.FIXED_MINSIZE, 0) grid_sizer_3.Add(self.panel_10, 1, wx.EXPAND, 0) grid_sizer_3.Add(self.panel_11, 1, wx.EXPAND, 0) grid_sizer_3.Add(self.panel_12, 1, wx.EXPAND, 0) grid_sizer_3.Add(self.panel_13, 1, wx.EXPAND, 0) grid_sizer_3.Add(self.static_line_5, 0, wx.EXPAND, 0) grid_sizer_3.Add(self.static_line_6, 0, wx.EXPAND, 0) grid_sizer_3.Add(self.static_line_7, 0, wx.EXPAND, 0) grid_sizer_3.Add(self.static_line_8, 0, wx.EXPAND, 0) grid_sizer_3.Add(self.panel_14, 1, wx.EXPAND, 0) grid_sizer_3.Add(self.panel_15, 1, wx.EXPAND, 0) grid_sizer_3.Add(self.panel_16, 1, wx.EXPAND, 0) grid_sizer_3.Add(self.panel_17, 1, wx.EXPAND, 0) grid_sizer_1.Add(grid_sizer_3, 1, wx.EXPAND, 0) grid_sizer_4.Add(self.label_14, 0, wx.ALIGN_CENTER_VERTICAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.panel_20, 1, wx.EXPAND, 0) grid_sizer_4.Add(self.button_3, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.panel_21, 1, wx.EXPAND, 0) grid_sizer_4.Add(self.button_4, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.panel_22, 1, wx.EXPAND, 0) grid_sizer_4.Add(self.button_5, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.FIXED_MINSIZE, 0) grid_sizer_4.Add(self.panel_23, 1, wx.EXPAND, 0) grid_sizer_4.Add(self.panel_18, 1, wx.EXPAND, 0) grid_sizer_4.Add(self.panel_19, 1, wx.EXPAND, 0) grid_sizer_1.Add(grid_sizer_4, 1, wx.EXPAND, 0) sizer_1.Add(grid_sizer_1, 1, wx.EXPAND, 0) self.SetAutoLayout(True) self.SetSizer(sizer_1) sizer_1.Fit(self) sizer_1.SetSizeHints(self) self.Layout() # end wxGlade def MenuExit(self, event): self.fg.stop() self.sg.fg.stop() self.Close() def SetAmplitude(self,event): self.amplitude = eng_notation.str_to_num(self.text_ctrl_1.GetValue()) def Calibrate(self,event): in_level = self.i_meter.level() out_level = self.o_meter.level() if out_level > .000001 : gain = 141/math.sqrt(out_level) self.pga1.set_k(complex(gain,0)) if in_level > .000001 : gain = 141/math.sqrt(in_level) self.pga2.set_k(complex(gain,0)) io_ratio = math.sqrt((out_level / in_level)) io_ratio_str = str(io_ratio) self.text_ctrl_4.SetValue(io_ratio_str[0:4]) time.sleep(.01) phase = self.meter.level() phase_str = str(phase) self.text_ctrl_5.SetValue(phase_str[0:4]) self.pshift.set_k(complex(0,1)) time.sleep(.01) sphase = self.meter.level() self.pshift.set_k(complex(1,0)) x_pos = (io_ratio)*phase y_pos = (io_ratio)*sphase if event.GetId() == ID_BUTTON_3: self.CalibOpen = complex(x_pos,y_pos) elif event.GetId() == ID_BUTTON_4: self.CalibShort = complex(x_pos,y_pos) elif event.GetId() == ID_BUTTON_5: self.CalibLoad = complex(x_pos,y_pos) self.Ed = self.CalibLoad self.Es = ( 2 * self.CalibLoad - ( self.CalibShort + self.CalibOpen ) ) / ( self.CalibShort - self.CalibOpen ) self.Et = ( 2 * ( self.CalibOpen + self.CalibLoad ) * ( self.CalibShort + self.CalibLoad ) ) / ( self.CalibShort - self.CalibOpen ) def Start(self,event): self.f_ducddc = self.freq + 275e3 self.text_ctrl_2.SetValue(eng_notation.num_to_str(self.f_ducddc)) self.timer.Stop() self.fg.stop() self.sg.fg.stop() self.dut_out.stop() self.dut_out.set_rx_freq(0,-self.f_ducddc) self.dut_out.set_rx_freq(1,-self.f_ducddc) self.dut_out.start() del (self.sg) self.sg = usrp_siggen.siggen () self.sg.set_waveform_ampl (self.amplitude) self.sg.set_waveform_freq (-275e3) self.sg.set_interpolator (self.interp) self.sg.set_waveform_type (self.type) self.sg.set_waveform_offset (self.offset) self.sg.set_duc_freq (self.f_ducddc) self.sg.usrp.set_nchannels (self.nchannels) self.sg.usrp.set_mux (self.mux) self.sg.fg.start() self.fg.start() time.sleep(.5) self.timer.Start() self.f_losc = -275e3 self.run = True def Stop(self,event): self.run = False def SetFrequency(self,event): self.freq = self.spin_ctrl_1.GetValue() * 100e3 if (self.freq < (self.f_ducddc - 275e3)) | (self.freq >= (self.f_ducddc + 275e3)): self.Start(-1) else: self.f_losc = self.freq - self.f_ducddc self.sg.set_waveform_freq(self.f_losc) def OnUpdate(self): if self.run: in_level = self.i_meter.level() out_level = self.o_meter.level() if out_level > .000001 : gain = 141/math.sqrt(out_level) self.pga1.set_k(complex(gain,0)) if in_level > .000001 : gain = 141/math.sqrt(in_level) self.pga2.set_k(complex(gain,0)) io_ratio = math.sqrt((out_level / in_level)) io_ratio_str = str(io_ratio) self.text_ctrl_4.SetValue(io_ratio_str[0:4]) time.sleep(.01) phase = self.meter.level() phase_str = str(phase) self.text_ctrl_5.SetValue(phase_str[0:4]) self.pshift.set_k(complex(0,1)) time.sleep(.01) sphase = self.meter.level() self.pshift.set_k(complex(1,0)) freq = self.f_losc + self.f_ducddc self.text_ctrl_3.SetValue(eng_notation.num_to_str(self.freq)) # output for smith chart. Convert magnitude and angle into rect # coords -1 to 1, check for realistic phase measurements if (phase <= 10.) & (phase >= -10.) : x_pos = (io_ratio)*phase y_pos = (io_ratio)*sphase in_point = complex(x_pos,y_pos) point = ( in_point - self.Ed ) / ( self.Es * ( in_point - self.Ed ) + self.Et ) # this to cut down on meaningless insignificant digit bobble point_real_str = str(point.real) point_imag_str = str(point.imag) self.text_ctrl_7.SetValue(point_real_str[0:5]) self.text_ctrl_8.SetValue(point_imag_str[0:5]) # calculate and display normalized resistance and reactance # formula for reflection coeffecient/Gamma to r + jx Rn = (1.-point.real**2-point.imag**2)/(1.+point.real**2-2.*point.real+point.imag**2) Rn_str = str(Rn) self.text_ctrl_10.SetValue(Rn_str[0:5]) Xn = (2.*point.imag)/(1.+point.real**2-2.*point.real+point.imag**2) Xn_str = str(Xn) self.text_ctrl_11.SetValue(Xn_str[0:5]) # calculate and display actual resistance and L or C value R = self.Zo * Rn R_str = str(R) self.text_ctrl_6.SetValue(R_str[0:5]) X = self.Zo * Xn if X < 0 : # capacitive, leave - sign to indicate capacitive LC = 1. / ( 2. * math.pi * freq * X ) else: # inductive LC = X / ( 2. * math.pi * freq ) # don't truncate floating point exponential self.text_ctrl_9.SetValue(str(LC)) # some way of getting data to gnuplot fp = open("plot_data","w") fp.write('0. 0.\n') fp.write(str(point.real)+' '+str(point.imag)) fp.close() self.g('plot cu(t,.1),cv(t,.1),cu(t,.1),-cv(t,.1),cu(t,1),cv(t,1),cu(t,1),-cv(t,1),cu(t,10),cv(t,10),cu(t,10),-cv(t,10),tu(t,.1),tv(t,.1),tu(t,.5),tv(t,.5),tu(t,1),tv(t,1),tu(t,5),tv(t,5),tu(t,10),tv(t,10),cu(t,.5),cv(t,.5),cu(t,.5),-cv(t,.5),tu(t,0),tv(t,0),"plot_data" with lines') # end of class MyFrame 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, "Automatic Testing") frame.Show(True) self.SetTopWindow(frame) return True app = MyApp(0) app.MainLoop()