void BladeRfTxComponent::process()
{
    //Get a DataSet from the input DataBuffer
    DataSet< complex<float> >* readDataSet = NULL;
    inBuf_->getReadData(readDataSet);

    // Check if we have to append dummy frames, samps must be multiple of 1024
    size_t size = readDataSet->data.size();
    if (size % BLADERF_SAMPLE_BLOCK_SIZE != 0) {
        int num_samps_to_append = BLADERF_SAMPLE_BLOCK_SIZE - (size % BLADERF_SAMPLE_BLOCK_SIZE);
        std::vector<std::complex<float> > samples(num_samps_to_append, std::complex<float>(0.0, 0.0));
        readDataSet->data.insert(readDataSet->data.end(), samples.begin(), samples.end());
        size += num_samps_to_append;
    }

    // Adjust raw buffer if needed
    if (rawSampleBuffer_.data.capacity() < size) rawSampleBuffer_.data.resize(size);

    // convert samples to bladeRF format
    for (int i = 0; i < size; i++) {
        rawSampleBuffer_.data[i].real(0xa000 | (int16_t)((readDataSet->data[i].real()) * 2000));
        rawSampleBuffer_.data[i].imag(0x5000 | (int16_t)((readDataSet->data[i].imag()) * 2000));
    }

    // Write samples to device
    int ret = bladerf_sync_tx(device_, &(rawSampleBuffer_.data.front()), size, NULL, BLADERF_SYNC_TIMEOUT_MS);
    if (ret != 0) {
        throw IrisException("Failed to send samples to device!");
        LOG(LERROR) << bladerf_strerror(ret);
    }

    //Release the DataSet
    inBuf_->releaseReadData(readDataSet);
}
//! This gets called whenever a parameter is reconfigured
void BladeRfTxComponent::parameterHasChanged(std::string name)
{
  try
  {
    if(name == "frequency") {
        // Set center frequency
        uint32_t actualValue;
        int ret = bladerf_set_frequency(device_, BLADERF_MODULE_TX, frequency_x);
        if (ret != 0) {
            throw IrisException("Failed to set center frequency!");
        }
        bladerf_get_frequency(device_, BLADERF_MODULE_TX, &actualValue);
        LOG(LINFO) << "Actual Tx center frequency is: " << actualValue << " Hz";
    } else if(name == "rate") {
        uint32_t actualValue;
        int ret = bladerf_set_sample_rate(device_, BLADERF_MODULE_TX, (uint32_t)rate_x, &actualValue);
        if (ret != 0) {
            throw IrisException("Failed to set sample rate!");
        }
        LOG(LINFO) << "Actual Tx sample rate is: " << actualValue << " Hz";
    } else if(name == "vga1gain") {
        if (bladerf_set_txvga1(device_, vga1Gain_x) != 0) {
            throw IrisException("Failed to set VGA1 gain!");
        }
        int actualGain;
        bladerf_get_txvga1(device_, &actualGain);
        LOG(LINFO) << "Actual VGA1 gain is " << actualGain << " dB";
    } else if(name == "vga2gain") {
        if (bladerf_set_txvga2(device_, vga2Gain_x) != 0) {
            throw IrisException("Failed to set VGA2 gain!");
        }
        int actualGain;
        bladerf_get_txvga2(device_, &actualGain);
        LOG(LINFO) << "Actual VGA2 gain is " << actualGain << " dB";
    }
  }
  catch(std::exception &e)
  {
    throw IrisException(e.what());
  }
}
//! This gets called whenever a parameter is reconfigured
void Dvbt1UsrpTxComponent::parameterHasChanged(std::string name)
{
#if 1
  try
  {
    if(name == "frequency")
    {
      LOG(LINFO) << "Setting TX Frequency: " << (frequency_x/1e6) << "MHz...";
      double lo_offset = 2*rate_x;  //Set LO offset to twice signal rate by default
      if(fixLoOffset_x >= 0)
      {
        lo_offset = fixLoOffset_x;
      }
      usrp_->set_tx_freq(tune_request_t(frequency_x, lo_offset));
      LOG(LINFO) << "LOG TX Frequency: " << (usrp_->get_tx_freq()/1e6) << "MHz";
    }
    else if(name == "rate")
    {
      LOG(LINFO) << "Setting TX Rate: " << (rate_x/1e6) << "Msps...";
      usrp_->set_tx_rate(rate_x);
      LOG(LINFO) << "Actual TX Rate: " << (usrp_->get_tx_rate()/1e6) << "Msps...";
    }
    else if(name == "gain")
    {
      gain_range_t range = usrp_->get_tx_gain_range();
      LOG(LINFO) << "Gain range: " << range.to_pp_string();
      LOG(LINFO) << "Setting TX Gain: " << gain_x << " dB...";
      usrp_->set_tx_gain(gain_x);
      LOG(LINFO) << "Actual TX Gain: " <<  usrp_->get_tx_gain() << " dB...";
    }
  }
  catch(std::exception &e)
  {
    throw IrisException(e.what());
  }
#endif
}
//! Do any initialization required
void Dvbt1UsrpTxComponent::initialize()
{
  //uhd::set_thread_priority_safe();

  //Set up the input DataBuffer
  inBuf_ = castToType< complex<float> >(inputBuffers.at(0));

  // prepare buffers
  bufs_.resize(numBuffers_x);
  fulls_.resize(numBuffers_x);
  bufs_.resize(numBuffers_x);
  for(int i = 0; i < numBuffers_x; i++)
  {
    bufs_[i].resize(bufferSize_x);
    fulls_[i] = 0;
  }
  currentRead_ = numBuffers_x - 1;
  currentWrite_ = 0;

  // the thread
  if(usrpThread_)
  {
    runUsrp_ = false;
    usrpThread_->join();
    delete usrpThread_;
  }
  runUsrp_ = true;
  usrpThread_ = new boost::thread(boost::bind(&Dvbt1UsrpTxComponent::usrpThreadProcedure, this));

#if 1
  //Set up the usrp
  try
  {
    //Create the device
    LOG(LINFO) << "Creating the usrp device with args: " << args_x;
    usrp_ = uhd::usrp::multi_usrp::make(args_x);
    //Lock mboard clocks
    usrp_->set_clock_source(ref_x);
    //always select the subdevice first, the channel mapping affects the other settings
    if (subDev_x!="")
      usrp_->set_tx_subdev_spec(subDev_x);
    LOG(LINFO) << "Using Device: " << usrp_->get_pp_string();

    //Set rate
    LOG(LINFO) << "Setting TX Rate: " << (rate_x/1e6) << "Msps...";
    usrp_->set_tx_rate(rate_x);
    LOG(LINFO) << "Actual TX Rate: " << (usrp_->get_tx_rate()/1e6) << "Msps...";

    //Set frequency
    LOG(LINFO) << "Setting TX Frequency: " << (frequency_x/1e6) << "MHz...";
    double lo_offset = 0;  //Set LO offset to zero by default
    if(fixLoOffset_x >= 0)
      lo_offset = fixLoOffset_x;
    usrp_->set_tx_freq(tune_request_t(frequency_x, lo_offset));
    LOG(LINFO) << "Actual TX Frequency: " << (usrp_->get_tx_freq()/1e6) << "MHz";
    LOG(LINFO) << "RX LO offset: " << (lo_offset/1e6) << "MHz...";

    //We can only set the time on usrp2 devices
    if(usrp_->get_mboard_name().find("usrp1") == string::npos)
    {
      LOG(LINFO) << "Setting device timestamp to 0...";
      usrp_->set_time_now(uhd::time_spec_t((double)0));
    }

    //set the rf gain
    gain_range_t range = usrp_->get_tx_gain_range();
    LOG(LINFO) << "Gain range: " << range.to_pp_string();
    LOG(LINFO) << "Setting TX Gain: " << gain_x << " dB...";
    usrp_->set_tx_gain(gain_x);
    LOG(LINFO) << "Actual TX Gain: " <<  usrp_->get_tx_gain() << " dB...";

    //set the IF filter bandwidth
    if(bw_x!=0)
    {
      LOG(LINFO) << "Setting TX Bandwidth: " << bw_x << " MHz...";
      usrp_->set_tx_bandwidth(bw_x);
      LOG(LINFO) << "Actual TX Bandwidth: " << usrp_->get_tx_bandwidth() << " MHz...";
    }

    //Set the antenna
    if(antenna_x!="")
      usrp_->set_tx_antenna(boost::to_upper_copy(antenna_x));
    LOG(LINFO) << "Using TX Antenna: " << usrp_->get_tx_antenna();

    boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time

    //Check Ref and LO Lock detect
    std::vector<std::string> sensor_names;
    sensor_names = usrp_->get_tx_sensor_names(0);
    if (std::find(sensor_names.begin(),
                  sensor_names.end(),
                  "lo_locked") != sensor_names.end())
    {
      uhd::sensor_value_t lo_locked = usrp_->get_tx_sensor("lo_locked",0);
      LOG(LINFO) << "Checking TX: " << lo_locked.to_pp_string() << " ...";
      if(!lo_locked.to_bool())
        throw IrisException("Failed to lock LO");
    }
    sensor_names = usrp_->get_mboard_sensor_names(0);
    if ((ref_x == "mimo") and (std::find(sensor_names.begin(),
                                         sensor_names.end(),
                                         "mimo_locked") != sensor_names.end()))
    {
      uhd::sensor_value_t mimo_locked = usrp_->get_mboard_sensor("mimo_locked",0);
      LOG(LINFO) << "Checking TX: " << mimo_locked.to_pp_string() << " ...";
      if(!mimo_locked.to_bool())
        throw IrisException("Failed to lock LO");
    }
    if ((ref_x == "external") and (std::find(sensor_names.begin(),
                                             sensor_names.end(),
                                             "ref_locked") != sensor_names.end()))
    {
      uhd::sensor_value_t ref_locked = usrp_->get_mboard_sensor("ref_locked",0);
      LOG(LINFO) << "Checking TX: " << ref_locked.to_pp_string() << " ...";
      if(!ref_locked.to_bool())
        throw IrisException("Failed to lock LO");
    }

    //create a transmit streamer
    uhd::stream_args_t stream_args(fmt_x);
    txStream_ = usrp_->get_tx_stream(stream_args);
  }
  catch(std::exception& e)
  {
    throw IrisException(e.what());
  }
#endif
}
//! Do any initialization required
void BladeRfTxComponent::initialize()
{
    // Set up the input DataBuffer
    inBuf_ = castToType< complex<float> >(inputBuffers.at(0));

    // Initialize raw sample vector to some multiple of block size
    rawSampleBuffer_.data.resize(128 * BLADERF_SAMPLE_BLOCK_SIZE);

    // Set up the BladeRF
    try
    {
        // Create the device
        LOG(LINFO) << "Trying to open device " << deviceName_x;
        int ret = bladerf_open(&device_, deviceName_x.c_str());
        if (ret != 0) {
            throw IrisException("Failed to open bladeRF device!");
        }

        // Check whether FPGA is configured yet
        if (bladerf_is_fpga_configured(device_) != 1 ) {
            // try to load FPGA image
            if (not fpgaImage_x.empty()) {
                ret = bladerf_load_fpga(device_, fpgaImage_x.c_str());
                if (ret != 0) {
                    throw IrisException("Failed to load FPGA to bladeRF!");
                } else {
                    LOG(LINFO) << "FPGA image successfully loaded.";
                }
            } else {
                throw IrisException("BladeRF FPGA is not configured and no FPGA image given!");
            }
        }

        // Print some information about device
        struct bladerf_version version;
        if (bladerf_fw_version(device_, &version) == 0) {
            LOG(LINFO) << "Using FW " << version.describe;
        }
        if (bladerf_fpga_version(device_, &version) == 0) {
            LOG(LINFO) << "Using FPGA " << version.describe;
        }
        if (bladerf_is_fpga_configured(device_) != 1 ) {
            throw IrisException("BladeRF FPGA is not configured!");
        }

        // setting up sync config
        ret = bladerf_sync_config(device_,
                                  BLADERF_MODULE_TX,
                                  BLADERF_FORMAT_SC16_Q11,
                                  BLADERF_DEFAULT_STREAM_BUFFERS,
                                  BLADERF_DEFAULT_STREAM_SAMPLES,
                                  BLADERF_DEFAULT_STREAM_XFERS,
                                  BLADERF_SYNC_TIMEOUT_MS);
        if (ret != 0) {
            throw IrisException("Couldn't enable BladeRF Tx sync handle!");
            LOG(LERROR) << bladerf_strerror(ret);
        }

        // Turn on transmitter
        ret = bladerf_enable_module(device_, BLADERF_MODULE_TX, true);
        if ( ret != 0 ) {
            throw IrisException("Couldn't enable BladeRF Tx module!");
        }

        // Set sample rate
        uint32_t actualValue;
        ret = bladerf_set_sample_rate(device_, BLADERF_MODULE_TX, (uint32_t)rate_x, &actualValue);
        if (ret != 0) {
            throw IrisException("Failed to set sample rate!");
        }
        LOG(LINFO) << "Actual Tx sample rate is: " << actualValue << " Hz";

        // Set center frequency
        ret = bladerf_set_frequency(device_, BLADERF_MODULE_TX, frequency_x);
        if (ret != 0) {
            throw IrisException("Failed to set center frequency!");
        }
        bladerf_get_frequency(device_, BLADERF_MODULE_TX, &actualValue);
        LOG(LINFO) << "Actual Tx center frequency is: " << actualValue << " Hz";

        // Set bandwidth
        ret = bladerf_set_bandwidth(device_, BLADERF_MODULE_TX, bw_x, &actualValue);
        if (ret != 0) {
            throw IrisException("Failed to set receive bandwidth!");
        }
        LOG(LINFO) << "Actual Tx bandwidth is " << actualValue << " Hz";

        // Set VGA1 gain
        int actualGain;
        ret = bladerf_set_txvga1(device_, vga1Gain_x);
        if (ret != 0) {
            throw IrisException("Failed to set VGA1 gain!");
        }
        bladerf_get_txvga1(device_, &actualGain);
        LOG(LINFO) << "Actual VGA1 gain is " << actualGain << " dB";

        // Set VGA2 gain
        ret = bladerf_set_txvga2(device_, vga2Gain_x);
        if (ret != 0) {
            throw IrisException("Failed to set VGA2 gain!");
        }
        bladerf_get_txvga2(device_, &actualGain);
        LOG(LINFO) << "Actual VGA2 gain is " << actualGain << " dB";
    }
    catch(const boost::exception &e)
    {
        throw IrisException(boost::diagnostic_information(e));
    }
    catch(std::exception& e)
    {
        throw IrisException(e.what());
    }
}