title: Create GNURadio source block: how to tune the sample rate
body: <p>I'm trying to implement a custom source block for the Analog Discovery 2 oscilloscope in GNU radio. I already have a working python script to record samples from the Analog Discovery 2 device to a WAV file (code at the end of the question).</p>
  
  <p>I'd like to be able to connect this sample source directly in GNUradio companion. I've followed <a href="http://gnuradio.org/redmine/projects/gnuradio/wiki/Guided_Tutorial_GNU_Radio_in_Python#322-Setting-up-a-new-block" rel="nofollow">the official tutorial</a> to create custom block to generate template code for my block:</p>
  
  <pre><code>import numpy
  from gnuradio import gr
  
  class AnalogDiscovery2(gr.sync_block):
  
      def __init__(self, sample_rate):
          gr.sync_block.__init__(self,
              name="Analog Discovery 2",
              in_sig=None,
              out_sig=[numpy.float32])
          self.sample_rate = sample_rate
  
  
      def work(self, input_items, output_items):
          out = output_items[0]
          # &lt;+signal processing here+&gt;
          out[:] = whatever
          return len(output_items[0])
  </code></pre>
  
  <p>I understand I have to modify the <code>work</code> function to acquire the samples and copy them to the <code>out</code> variable, however I wonder how I can tune the sample rate? I don't know how the <code>work</code> function is called, and what is its timing. How can I set the sample rate??</p>
  
  <p>Python code to record samples into a WAV file:</p>
  
  <pre><code>from ctypes import *
  from dwfconstants import *
  import math
  import time
  import matplotlib.pyplot as plt
  import sys
  import wave
  import struct
  
  if sys.platform.startswith("win"):
      dwf = cdll.dwf
  elif sys.platform.startswith("darwin"):
      dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
  else:
      dwf = cdll.LoadLibrary("libdwf.so")
  
  #declare ctype variables
  hdwf = c_int()
  sts = c_byte()
  hzAcq = c_double(48000)
  nSamples = 96000
  rgdSamples = (c_double*nSamples)()
  cAvailable = c_int()
  cLost = c_int()
  cCorrupted = c_int()
  fLost = 0
  fCorrupted = 0
  
  #print DWF version
  version = create_string_buffer(16)
  dwf.FDwfGetVersion(version)
  print "DWF Version: "+version.value
  
  #open device
  print "Opening first device"
  dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
  
  if hdwf.value == hdwfNone.value:
      szerr = create_string_buffer(512)
      dwf.FDwfGetLastErrorMsg(szerr)
      print szerr.value
      print "failed to open device"
      quit()
  
  print "Preparing to read sample..."
  
  #print "Generating sine wave..."
  #dwf.FDwfAnalogOutNodeEnableSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_bool(True))
  #dwf.FDwfAnalogOutNodeFunctionSet(hdwf, c_int(0), AnalogOutNodeCarrier, funcSine)
  #dwf.FDwfAnalogOutNodeFrequencySet(hdwf, c_int(0), AnalogOutNodeCarrier, c_double(1))
  #dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, c_int(0), AnalogOutNodeCarrier, c_double(2))
  #dwf.FDwfAnalogOutConfigure(hdwf, c_int(0), c_bool(True))
  
  # enable positive supply
  dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(0), c_double(True)) 
  # set voltage to 3 V
  dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(1), c_double(3.0)) 
  # enable negative supply
  dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(1), c_int(0), c_double(True)) 
  # set voltage to -1 V
  dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(1), c_int(1), c_double(-1.0)) 
  # master enable
  dwf.FDwfAnalogIOEnableSet(hdwf, c_int(True))
  
  #set up acquisition
  dwf.FDwfAnalogInChannelEnableSet(hdwf, c_int(0), c_bool(True))
  dwf.FDwfAnalogInChannelRangeSet(hdwf, c_int(0), c_double(0.1))
  dwf.FDwfAnalogInAcquisitionModeSet(hdwf, acqmodeRecord)
  dwf.FDwfAnalogInFrequencySet(hdwf, hzAcq)
  dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(nSamples/hzAcq.value))
  
  #wait at least 2 seconds for the offset to stabilize
  time.sleep(2)
  
  #begin acquisition
  dwf.FDwfAnalogInConfigure(hdwf, c_int(0), c_int(1))
  print "   waiting to finish"
  
  cSamples = 0
  
  while cSamples &lt; nSamples:
      dwf.FDwfAnalogInStatus(hdwf, c_int(1), byref(sts))
      if cSamples == 0 and (sts == DwfStateConfig or sts == DwfStatePrefill or sts == DwfStateArmed) :
          # Acquisition not yet started.
          continue
  
      dwf.FDwfAnalogInStatusRecord(hdwf, byref(cAvailable), byref(cLost), byref(cCorrupted))
  
      cSamples += cLost.value
  
      if cLost.value :
          fLost = 1
      if cCorrupted.value :
          fCorrupted = 1
  
      if cAvailable.value==0 :
          continue
  
      if cSamples+cAvailable.value &gt; nSamples :
          cAvailable = c_int(nSamples-cSamples)
  
      # get samples
      dwf.FDwfAnalogInStatusData(hdwf, c_int(0), byref(rgdSamples, 8*cSamples), cAvailable)
      cSamples += cAvailable.value
  
  
  print "Recording finished"
  if fLost:
      print "Samples were lost! Reduce frequency"
  if cCorrupted:
      print "Samples could be corrupted! Reduce frequency"
  
  #f = open("record.bin", "w")
  #for v in rgdSamples:
  #    f.write("%s\n" % v)
  #f.close()
  
  # Write samples to file
  wav_output = wave.open('record.wav', 'w')
  wav_output.setparams((1, 2, 48000, nSamples, 'NONE', 'not compressed'))
  values = []
  for v in rgdSamples:
      packed_value = struct.pack('h', 32768*v)
      values.append(packed_value)
  
  value_str = ''.join(values)
  wav_output.writeframes(value_str)
  wav_output.close()
  </code></pre>