Saturday, July 11, 2009

Forks: Simple GUI

Hello again I bring you this time a simple frequency setting program with a GUI written in Python making heavy use of GNURadio. It's not pretty, but it works. The comments are terrible.

#! /usr/bin/env python

from gnuradio import gr, gru, audio, eng_notation
from gnuradio.eng_option import eng_option
from gnuradio.wxgui import stdgui2, form
from optparse import OptionParser
import wx

#This class exists to provide a clear reference to forms
class myform(form.form):
def __init__(self):
form.form.__init__(self)

class app_top_block(stdgui2.std_top_block):
def __init__(self, frame, panel, vbox, argv):
stdgui2.std_top_block.__init__(self, frame, panel, vbox, argv)

self.frame = frame
self.panel = panel

parser = OptionParser(option_class=eng_option)

parser.add_option("-s", "--sample-rate", type="eng_float", default=44100, help="Set sample rate to RATE [default:%default]")
parser.add_option("-v", "--volume", type="float", default=0.1, help="Set initial volume level [default:%default]")
parser.add_option("-l", "--left-frequency", type="int", dest="left", default=350, help="Set initial frequency for left side [default:%default]")
parser.add_option("-r", "--right-frequency", type="int", dest="right", default=440, help="Set intial frequency for right side [default:%default]")

(options, args) = parser.parse_args()
sample_rate = int(options.sample_rate)
self.ampl = options.volume
self.left = options.left
self.right = options.right

if len(args) != 0:
parser.print_help()
sys.exit(1)

#simply uses generated waves at this point but could be swapped out for
#something more exciting
self.src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, self.left, 1)
self.src1 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, self.right, 1)

#the multiply blocks serve as volume controls
self.amp0 = gr.multiply_const_ff(self.ampl)
self.amp1 = gr.multiply_const_ff(self.ampl)

dst = audio.sink (sample_rate, "")

self.connect (self.src0, self.amp0, (dst,0))
self.connect (self.src1, self.amp1, (dst,1))

self._build_gui(vbox)

def _build_gui(self, vbox_arg):

panel = self.panel
vbox = vbox_arg

freq_box = wx.BoxSizer(wx.HORIZONTAL)
left_box = wx.BoxSizer(wx.VERTICAL)
right_box = wx.BoxSizer(wx.VERTICAL)
volume_box = wx.BoxSizer(wx.VERTICAL)

self.left_form = myform()
self.right_form = myform()
self.volume_form = myform()

left_box.Add((5,0), 0)
self.left_form['title'] = form.static_text_field(parent=panel, sizer=left_box, value="Left Channel")
left_box.Add((2,0), 1)
self.left_form['curFreq'] = form.static_int_field(parent=panel, sizer=left_box, label="Curent Frequency", value=self.left)
left_box.Add((1,0), 1)
self.left_form['newFreq'] = form.int_field(parent=panel, sizer=left_box, label="Enter new Frequency", value=self.left)
left_box.Add((1,0), 1)
left_button = wx.Button(panel, -1, "Set Frequency")
left_box.Add(left_button, 0, wx.CENTER)
left_box.Add((5,0), 0)

right_box.Add((5,0), 0)
self.right_form['title'] = form.static_text_field(parent=panel, sizer=right_box, value="Right Channel")
right_box.Add((2,0), 1)
self.right_form['curFreq'] = form.static_int_field(parent=panel, sizer=right_box, label="Current Frequency", value=self.right)
right_box.Add((2,0), 1)
self.right_form['newFreq'] = form.int_field(parent=panel, sizer=right_box, label="Enter new Frequency", value=self.right)
right_box.Add((2,0), 1)
right_button = wx.Button(panel, -1, "Set Frequency")
right_box.Add(right_button, 0, wx.CENTER)
right_box.Add((5,0), 0)

freq_box.Add((5,0), 0)
freq_box.Add(left_box, 1)
freq_box.Add((5,0), 1)
freq_box.Add(right_box, 1)

volume_box.Add((1,0), 1)
self.volume_form['curVol'] = form.static_float_field(parent=panel, sizer=volume_box, label="Current Volume", value=self.ampl)
volume_box.Add((1,0), 1)
self.volume_form['newVol'] = form.float_field(parent=panel, sizer=volume_box, label="Enter New Volume", value=self.ampl)
volume_box.Add((1,0), 1)
volume_button = wx.Button(panel, -1, "Set Volume")
volume_box.Add(volume_button, 0, wx.CENTER)
volume_box.Add((5,0), 0)

vbox.Add(freq_box, 1, wx.EXPAND)
vbox.Add(volume_box, 1, wx.EXPAND)

left_button.Bind(wx.EVT_BUTTON, self.set_left_frequency, id=left_button.GetId())
right_button.Bind(wx.EVT_BUTTON, self.set_right_frequency, id=right_button.GetId())
volume_button.Bind(wx.EVT_BUTTON, self.set_volume, id=volume_button.GetId())

#the k parameter in each of the following functions exists to catch extra
#information being passed by Bind
def set_volume(self, k):
volume = self.volume_form['newVol'].get_value()
self.amp0.set_k(volume)
self.amp1.set_k(volume)
self.volume_form['curVol'].set_value(volume)

def set_right_frequency(self, k):
freq = self.right_form['newFreq'].get_value()
self.src1.set_frequency(freq)
self.right_form['curFreq'].set_value(freq)

def set_left_frequency(self, k):
freq = self.left_form['newFreq'].get_value()
self.src0.set_frequency(freq)
self.left_form['curFreq'].set_value(freq)


def main():
app = stdgui2.stdapp(app_top_block, "GUI Frequency Setter", nstatus=1)
app.MainLoop()

if __name__ == '__main__':
main()

Thursday, July 9, 2009

Forks: GNURadio-Simple Freq Setter

#! /usr/bin/env python

from gnuradio import gr
from gnuradio import audio
import time
class my_top_block(gr.top_block): #deriving a flow graph
def __init__(self):#Constructor
gr.top_block.__init__(self)#Base Class's Constructor

sample_rate = 44100
ampl = 0.1

#Making use of GNURadio's predefined sources to get sine waves
self.src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl)
self.src1 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 440, ampl)

#GNURadio predefined signal multipliers
self.amp0 = gr.multiply_const_ff(1)
self.amp1 = gr.multiply_const_ff(1)

#Audio sink that outputs to Sound Card
dst = audio.sink (sample_rate, "")

#Connecting the two seperate channels of the flow graph
self.connect (self.src0, self.amp0, (dst, 0))
self.connect (self.src1, self.amp1, (dst, 1))

#Quick little routine to set both the channel's volume together
def set_volume(self, volume):
self.amp0.set_k(volume)
self.amp1.set_k(volume)


if __name__ == '__main__':
try:
go = my_top_block()
go.start()
while True: #Infinite loop for User Interface
#interacting with user
#in fact this rest is mostly python tricks (kinda) and not much
#GNURadio...
mode = raw_input ('Change Freq, Change Volume or Quit? ')
mode = mode.lower()
for x in mode[:]:
if x == 'f':
mode = 'f'
break
elif x == 'v':
mode = 'v'
break
elif x == 'q':
mode = 'q'
break
if mode == 'f':
side = raw_input ('Which side? (l or r) ')
new_freq = input ('Enter freq: ')
if side == 'l':
#Accessing members directly! Big No-No in C++
#apparently not bad in python-I could be wrong...
go.src0.set_frequency(new_freq)
elif side == 'r':
go.src1.set_frequency(new_freq)
else:
print ('Invalid Side')
elif mode == 'v':
volume = input ('Enter Volume: ')
go.set_volume(volume)
elif mode == 'q':
print ('Goodbye')
break
else:
print 'Invalid Selection'
go.src0.set_frequency(140)
go.src1.set_frequency(140)
go.set_volume(0)
time.sleep(0.5)
go.set_volume(2)
time.sleep(0.5)
go.set_volume(0)
time.sleep(0.5)
go.set_volume(2)
time.sleep(0.5)
go.set_volume(0)
time.sleep(0.5)
go.set_volume(2)
time.sleep(0.5)
go.set_volume(0)
go.stop()
except KeyboardInterrupt:
pass





There it is, my simple and probably very bad little frequency setting program using GNURadio. I welcome comments (if anyone actually reads this) but you must remember I'm an Engineer not a Computer Science guy so you can't expect too much from me when it comes to pretty code.

Forks: GNURadio

Well, for my new job I'm learning GNU Radio, which means I'll be posting my heavily commented code as I get around to heavily commenting it. I am a terrible coder, but in my small team at work I'm the best coder right now, soo that means that I'm going to be using my sad excuses for programs to get my teammates from zero to where I am now. All that means heavy heavy comments....