Wiki

The most recent version of this page is a draft.DiffThis version is outdated by a newer approved version.DiffThis version (31 Jan 2020 16:15) was approved by Adrian Suciu.

This is an old revision of the document!


How to build a radio with the M2k

Background

In order to be able to process radio signals with ADALM2000 is necessary a receiver that can convert the incoming RF signal to a lower intermediate frequency. The FM signal, centered on a carrier frequency with high values, is reduced to an intermediate value, called IF, through a downconverter receiver. The receiver built for the m2k-radio has a basic radio architecture with four main components: Antenna, Low noise amplifier, Mixer and a Local oscillator. These 3 main parts need additional components (usually some filters) in order to work well together and receive signals in certain desired bandwidths.

Figure 1. Block Schematic of the M2k Receiver

  • Low noise amplifier: Because antennas are sources of weak signal, it is necessary to amplify the signal received through it but is also important to keep the noise level as low as possible. For this purpose, is used a low noise amplifier which amplifies a low power signal without introducing additional noise. As FM radio has a 200kHz bandwidth, from 88.1 to 108.1 MHz is important to use an LNA with a bandwidth that includes these frequencies.
  • Mixer: A well-suited IC component for RF to IF down-conversion applications is the AD831 Low Distortion Mixer. It consists of a mixer core, a limiting amplifier, a low noise output amplifier, and a bias circuit. The mixer produces a high-level output at IFP and IFN—consisting of the sum and difference frequencies of the RF and LO inputs.
  • Local Oscillator: The Local oscillator of this receiver can be implemented using ADF4351 component. This is a wideband synthesizer with integrated VCO which allows implementation of fractional-N or integer-N phase-locked loop (PLL) frequency synthesizers when used with an external loop filter and external reference frequency. The optimum LO frequency and power can be software programmed on the ADF4351.

Hardware setup:

EVAL boards interconnection

For building a first prototype, it is possible to find each block in the form of an EVAL-board which has all the necessary components already integrated and is ready to be easily used in the project. The blocks are interconnected with SMA connectors. The filters between the blocks can be used to reduce the unwanted frequencies so the acquired signal is at a better quality.

Figure 2. EVAL Boards

Power Supplies

The last thing necessary, from a hardware point of view, is the power supply. Using an external supply and some voltage regulators is possible to implement an easy solution. In this case, with a 12V supply and simple voltage regulators together with their bypass capacitors you can implement the 5V and 9V supplies needed for the boards.

Figure 3. Power Supplies schematic

Figure 4. Power Supplies breadboard connections

The outputs of the regulators should be connected on the corresponding VCC pins/pads of each board (5V for LNA and PLL, 9V for the mixer).

Connections to M2k

1+ - AD831 IFout
1- - AD831 GND (outer part of the SMA connector)
2+ -
2- -
W1 –  
DIO0 - ADF4351 CLK
DIO1 - ADF4351 DATA
DIO2 - ADF4351 LE
DIO3 - ADF4351 MUXOUT

Figure 5. M2k Pinout

Figure 6. M2k Radio Receiver

Software

GNU Radio is a free and open-source software development toolkit that provides signal processing blocks to implement software radios. GNU Radio Companion (GRC) is a graphical tool for creating signal flow graphs and generating flow-graph source code. GNU Radio can be extended with own functionality and blocks using OutOfTreeModules. gr-iio is a module containing IIO blocks for GNU Radio.

Creating a flowgraph in GRC, using GNU Radio 3.7, is an easy and fast solution. There are two possible approaches:

  • Creating a new out-of-tree module. Please check the available OutOfTreeModules documentation
  • Integrating the ADF4350 block with gr-iio

All steps for integrating ADF4350 with gr-iio will be further explained.

ADF4350 block

Controlling the radio implies controlling the output voltage frequency of ADF4350. A GRC block, integrated with IIO blocks, that controls the frequency can be created. no-OS provides a driver for ADF4350 that simplifies the work. This driver communicates using SPI. In the following steps we are going to create a GRC block for gr-iio that uses libm2k communication segment integrated with no-OS drivers.

  1. Install libm2k. Instructions can be found here.
  2. Compile the gr-iio blocks for your PC. Check the steps here.
  3. Download the ADF4350 driver from no-OS page.

The steps to implement a GRC block:

  1. Create the inclusion header
  2. Create the implementation class
    1. Add the driver
    2. Implement the class
  3. Create python bindings
  4. Create the GRC component

Project structure:

  • gr-iio
    • grc
      • iio_adf4350_sink.xml
    • include/gnuradio/iio
      • adf4350_sink.h
    • lib
      • drivers
        • adf4350.h
        • adf4350.c
        • spi.h
      • adf4350_sink_impl.h
      • adf4350_sink_impl.cc
    • swig
      • iio_swig.i

Create the inclusion header

Create adf4350_sink.h in gr-iio/include/gnuradio/iio.

Add this file in the corresponding CMake file.

  install(FILES
  ...
  adf4350_sink.h
  DESTINATION ${GR_INCLUDE_DIR}/gnuradio/iio)

In the make function add as parameters the URI and all attributes from the adf4350_init_param structure (23 attributes) found in the driver. This way they could be change from GRC without hard coding them.

Create the implementation class

In this part we are going to integrate libm2k with a no-OS driver. For more information please check this link.

Create adf4350_sink_impl.h and adf4350_sink_impl.cc in gr-iio/lib. Create a drives directory in gr-iio/lib and add the ADF4350 driver. Add both source files in the corresponding CMake file.

  list(APPEND iio_sources
  ...
  adf4350_sink_impl.cc
  drivers/adf4350.c)

Create a header called spi.h and include the SPI header of libm2k:

  //spi.h
  #include <libm2k/tools/spi.hpp>

ADF4350 block will receive a message from an IIO Attribute Updater block every 1 ms. The message contains the value of the frequency. The adf4350_sink_impl class has to implement the class constructor and a method (write_attribute) that will receive the message and will communicate with the chip in order to set its output frequency.

In the source file (adf4350_sink_impl.cc) include the SPI extra header of libm2k (<libm2k/tools/spi_extra.hpp>). In the constructor open the context and initialize m2k_spi_init structure :

  libm2k::contexts::M2k *context = libm2k::contexts::m2kOpen(uri.c_str());
  m2k_spi_init m2KSpiInit;
  m2KSpiInit.clock = 0;
  m2KSpiInit.mosi = 1;
  m2KSpiInit.miso = 7;
  m2KSpiInit.bit_numbering = MSB;
  m2KSpiInit.context = context;

Initialize the adf4350 structure with the given parameters. The first parameter, spi_init_param, should contain these values:

  {
      1000000,
      2,
      SPI_MODE_0,
      (void*)&m2KSpiInit
  }

write_attribute function is supposed to:

  • receive the message
  • convert it into a number
  • pass the value to the driver, in order to set the output frequency of ADF4350
  long long freq;
  pmt::pmt_t keys;
  
  if (!is_dict(pdu))
  throw std::runtime_error("Message not a dictionary!\n");
  
  keys = pmt::dict_keys(pdu);
  
  freq = std::stoll(pmt::symbol_to_string(pmt::dict_ref(pdu, pmt::nth(0, keys), pmt::PMT_NIL)));
  adf4350_out_altvoltage0_frequency(adf4350_device, freq);

Create python bindings

In swig directory is a file called iio_swig.i. Include the block's header in this file:

 %{
 ...
 #include "gnuradio/iio/adf4350_sink.h"
 %}
 
 ...
 %include "gnuradio/iio/adf4350_sink.h"
 
 ...
 GR_SWIG_BLOCK_MAGIC2(iio, adf4350_sink);

Create the GRC component

GNU Radio 3.7 uses xml files for creating GRC blocks. Create a file iio_adf4350_sink.xml in the grc directory. This file will describe how the GRC block should look like. Add all parameters using the following format:

  <param>
      <name>name</name>
      <key>key</key>
      <value>val</value>
      <type>type</type>
      <hide>part</hide>  <!-- optional -->
  </param>

This block is a sink for messages, not streams. To specify this create the following tag:

  <sink>
      <name>attr</name>
      <type>message</type>
      <optional>1</optional>
  </sink>

Build the new created block

  cmake .
  make
  sudo make install
  cd ..
  sudo ldconfig

The source code can be found on the gr-iio github page, grcon2019_m2k branch.

GNURadio-Companion Flowgraph

The file m2k_fm_1.zip contains the gnuradio flowgraph. The gnuradio flowgraph acquires the data from the M2K and sets the ADF4350 PLL frequency. When changing the PLL frequency slider, the gnuradio ADF4350 block that we just written, encodes SPI messages to the PLL in order to change the frequency that is fed into the mixer. The data acquired from the mixer is captured by the M2k using GNURadio. The flow then shifts the frequency by a smaller offset in the “offset” slider. The offset slider allows fine tuning of the signal before it gets demodulated by the WBFM receiver block. Eventually the data is sent to an audio sink which plays back the radio in the speakers.

This project was presented in GRCon 2019. Slides are available here

university/tools/m2k/tutorials/buildingaradiowithm2k.1580483741.txt.gz · Last modified: 31 Jan 2020 16:15 by Adrian Suciu