Creation of a signal generator program

This script takes command line arguments to play signals recorded
into a file. The format of the file should be a raw data file. This
program lets you broadcast multiple signals simultaneously over the
same antennae. Future commits will add a GUI to display the total
signal being broadcasted, addition of parameterized signals. Also
possibly will add the ability to run from a config file as opposed
to command line.

Change-Id: I34bab67e69e057862fa8e84d019cd0a389348b49
diff --git a/signal_generator/README b/signal_generator/README
new file mode 100644
index 0000000..691bbda
--- /dev/null
+++ b/signal_generator/README
@@ -0,0 +1,28 @@
+Signal Generator Script 1.0
+===============================================================================
+This script takes command line arguments to broadcast the sum of various signals
+with differing strengths. The script takes in arguments by specifying a type of
+signal to broadcast followed by the corresponding parameters for that signal.
+This script requires the user to specify at least 1 signal in order to operate.
+In order to broadcast from file, use the '-f' flag and specify the path to the
+file as well as a factor which corresponds to a db-gain on the specific signal.
+A general db-gain can also be specified by using the '-g' flag to amplify the
+combined signal.
+
+Options:
+  -h, --help            Show this help message and exit
+  -f FILENAME,FACTOR, --file=FILENAME,FACTOR
+                        Add signal from file (raw 64 bit complex) which can be
+                        generated using the 'bandpass_recorder.py' script. The
+                        raw file can be read using scipy.fromfile.
+  -u FREQUENCY, --frequency=FREQUENCY
+                        Specify the desired frequency in KHz, defaults
+                        to 2412KHz (Wifi Channel 1)
+  -g DB_GAIN, --gain=DB_GAIN
+                        Specify the db-gain amplification, defaults to 50db
+
+Note: If you are playing from a file and are getting Underruns (U), try moving
+the file to local storage.
+
+A set of useful recordings have been placed at "/google/data/rw/teams/gfiber/sdr/recordings"
+that can be used for testing or other purposes.
diff --git a/signal_generator/signal_generator.py b/signal_generator/signal_generator.py
new file mode 100755
index 0000000..a693e6a
--- /dev/null
+++ b/signal_generator/signal_generator.py
@@ -0,0 +1,101 @@
+#!/usr/bin/python
+from optparse import OptionParser
+import sys
+
+from gnuradio import blocks
+from gnuradio import gr
+from gnuradio import uhd
+
+
+class SignalGenerator(gr.top_block):
+
+  def __init__(self):
+    super(SignalGenerator, self).__init__('Signal Generator')
+
+    sample_rate = 30e6
+
+    # Initialize the SDR
+    stream_args = uhd.stream_args(cpu_format='fc32', otw_format='sc8',
+                                  channels=range(1))
+    self.usrp_sink = uhd.usrp_sink(',', stream_args)
+
+    # Create a list of the file source streams so we can add them as we read
+    # arguments.
+    self.sources = []
+
+    # Adjust parameters
+    self.usrp_sink.set_samp_rate(sample_rate)
+    self.usrp_sink.set_bandwidth(sample_rate)
+
+    # Initialize and connect the signal adder.
+    self.add_block = blocks.add_vcc(1)
+    self.connect((self.add_block, 0), (self.usrp_sink, 0))
+
+  # Adjust gain value on the USRP.
+  def set_gain(self, gain):
+    self.usrp_sink.set_gain(gain)
+
+  # Adjust center frequency value of the USRP.
+  def set_freq(self, freq):
+    self.usrp_sink.set_center_freq(freq, 0)
+
+  # Add a new signal to be broadcasted.
+  def add_file_source(self, filename, factor):
+    # Create and add our file sources paired with their multiplier block to the
+    # sources list.
+    src = blocks.file_source(gr.sizeof_gr_complex, filename, True)
+    multiply_block = blocks.multiply_const_vcc((factor,))
+    self.connect((src, 0), (multiply_block, 0))
+    self.sources.append(multiply_block)
+
+  def run(self):
+    # Connect all the sources to the adder.
+    for i in range(len(self.sources)):
+      self.connect((self.sources[i], 0), (self.add_block, i))
+    gr.top_block.run(self)
+
+if __name__ == '__main__':
+  # Get command line arguments.
+  parser = OptionParser()
+  parser.add_option('-f', '--file', dest='file', help='Add signal from file '
+                    '(raw 64 bit complex) which can be generated using the '
+                    '\'bandpass_recorder.py\' script. The raw file can be read '
+                    'using scipy.fromfile. If factor is not included, it defaults '
+                    'to 50.0', metavar='FILENAME,FACTOR', action='append')
+  parser.add_option('-u', '--frequency', dest='frequency',
+                    help='Specify the desired frequency in KHz, defaults to'
+                    '2412000KHz (Wifi Channel 1)', metavar='FREQUENCY',
+                    default='2412000')
+  parser.add_option('-g', '--gain', dest='gain',
+                    help='Specify the db-gain amplification, defaults to 50db',
+                    metavar='DB_GAIN', default='50')
+  options, args = parser.parse_args()
+
+  # Initialize the top_block
+  signal_gen_block = SignalGenerator()
+  signal_gen_block.set_freq(float(options.frequency) * 1000.0)
+  signal_gen_block.set_gain(float(options.gain))
+
+  # Add the signals to the top_block
+  if options.file is not None:
+    for signal in options.file:
+      args = signal.split(',')
+
+      # Check for number of arguments
+      if len(args) > 1:
+        # Verify that the second argument is a float.
+        try:
+          factor = float(args[1])
+        except:
+          print 'Invalid arguments: {0}'.format(signal)
+          sys.exit(1)
+      else:
+        factor = 50.0
+
+      # Add the signal to the top_block.
+      signal_gen_block.add_file_source(args[0], factor)
+  else:
+    print '\nAt least 1 signal is required to run\n'
+    sys.exit(1)
+
+  signal_gen_block.run()