Wiki

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
university:tools:m2k:tutorials:buildingaradiowithm2k [31 Jan 2020 16:15]
Adrian Suciu [GRC Flowgraph]
university:tools:m2k:tutorials:buildingaradiowithm2k [25 Jan 2021 15:22] (current)
Adrian Suciu
Line 49: Line 49:
 =====Software===== =====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 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.+GNU Radio can be extended with own functionality and blocks using OutOfTreeModules. gr-m2k is a module containing blocks for interfacing with ADALM2000.
  
-Creating a flowgraph in GRC, using GNU Radio 3.7, is an easy and fast solution. There are two possible approaches:+Creating a flowgraph in GRC, using GNU Radio 3.8, is an easy and fast solution. There are two possible approaches:
   * Creating a new out-of-tree module. Please check the available OutOfTreeModules [[https://​wiki.gnuradio.org/​index.php/​OutOfTreeModules#​Tools_and_resources_at_my_disposal|documentation]]   * Creating a new out-of-tree module. Please check the available OutOfTreeModules [[https://​wiki.gnuradio.org/​index.php/​OutOfTreeModules#​Tools_and_resources_at_my_disposal|documentation]]
-  * Integrating the ADF4350 block with gr-iio +  * Integrating the ADF4350 block with gr-m2k 
-All steps for integrating ADF4350 with gr-iio will be further explained.+All steps for integrating ADF4350 with gr-m2k will be further explained.
  
 ====  ADF4350 block ==== ====  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. ​+Controlling the radio implies controlling the output voltage frequency of ADF4350. A GRC block, integrated with M2k 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-m2k that uses libm2k communication segment integrated with no-OS drivers. ​
  
-  - Install libm2k. Instructions can be found [[https://wiki.analog.com/​libm2k|here]]. +  - Install libm2k. Instructions can be found [[/university/tools/​m2k/​libm2k/​libm2k|here]]. 
-  - Compile the gr-iio blocks for your PC. Check the steps [[https://wiki.analog.com/resources/tools-software/linux-software/​gnuradio#​compiling_the_gr-iio_blocks_for_your_pc ​|here]].+  - Compile the gr-m2k blocks for your PC. Check the steps [[/university/tools/m2k/libm2k/gr-m2k|here]].
   - Download the ADF4350 driver from [[https://​github.com/​analogdevicesinc/​no-OS/​tree/​d00cc225a264d03807cafc4bf6a133af69affa36/​drivers/​frequency/​adf4350|no-OS page]].   - Download the ADF4350 driver from [[https://​github.com/​analogdevicesinc/​no-OS/​tree/​d00cc225a264d03807cafc4bf6a133af69affa36/​drivers/​frequency/​adf4350|no-OS page]].
  
Line 72: Line 72:
  
 Project structure: Project structure:
-  * gr-iio+  * gr-m2k
     * grc     * grc
-      * iio_adf4350_sink.xml +      * m2k_adf4350_sink.block.yml 
-    * include/gnuradio/​iio+    * include/m2k
       * adf4350_sink.h       * adf4350_sink.h
     * lib     * lib
Line 85: Line 85:
       * adf4350_sink_impl.cc       * adf4350_sink_impl.cc
     * swig     * swig
-      * iio_swig.i+      * m2k_swig.i
  
  
 **Create the inclusion header** **Create the inclusion header**
  
-Create //​adf4350_sink.h//​ in gr-iio/include/gnuradio/​iio.+Create //​adf4350_sink.h//​ in gr-m2k/include/m2k.
  
 Add this file in the corresponding CMake file. Add this file in the corresponding CMake file.
Line 96: Line 96:
     ...     ...
     adf4350_sink.h     adf4350_sink.h
-    DESTINATION ${GR_INCLUDE_DIR}/​gnuradio/​iio)+    DESTINATION ${GR_INCLUDE_DIR}/​m2k)
  
 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. 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.
Line 102: Line 102:
 **Create the implementation class** **Create the implementation class**
  
-In this part we are going to integrate libm2k with a no-OS driver. For more information please check this [[https://wiki.analog.com/​libm2k/​digital_communication#​libm2k_and_no-os_drivers|link]].+In this part we are going to integrate libm2k with a no-OS driver. For more information please check this [[/university/tools/m2k/​libm2k/​digital_communication#​libm2k_and_no-os_drivers|link]].
  
-Create //​adf4350_sink_impl.h//​ and //​adf4350_sink_impl.cc//​ in gr-iio/lib. +Create //​adf4350_sink_impl.h//​ and //​adf4350_sink_impl.cc//​ in gr-m2k/lib. 
-Create a drives directory in gr-iio/lib and add the ADF4350 driver. Add both source files in the corresponding CMake file. +Create a drives directory in gr-m2k/lib and add the ADF4350 driver. Add both source files in the corresponding CMake file. 
-    list(APPEND ​iio_sources+    list(APPEND ​m2k_sources
     ...     ...
     adf4350_sink_impl.cc     adf4350_sink_impl.cc
Line 115: Line 115:
     #include <​libm2k/​tools/​spi.hpp>​     #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.+ADF4350 block will receive a message from a QT GUI block. 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. 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 : 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());+    libm2k::​contexts::​M2k *context = analog_in_source_impl::get_context(uri);
     m2k_spi_init m2KSpiInit;     m2k_spi_init m2KSpiInit;
     m2KSpiInit.clock = 0;     m2KSpiInit.clock = 0;
Line 140: Line 140:
   * pass the value to the driver, in order to set the output frequency of ADF4350   * pass the value to the driver, in order to set the output frequency of ADF4350
  
-    ​long long freq; +    pmt::​pmt_t ​key;
-    ​pmt::​pmt_t ​keys;+
     ​     ​
-    if (!is_dict(pdu)) +    if (!is_pair(pdu)) ​{ 
-    throw std::​runtime_error("​Message not a dictionary!\n");+        throw std::​runtime_error("​Message not a pair!\n"); 
 +    }
     ​     ​
-    ​keys = pmt::dict_keys(pdu);+    ​key = pmt::car(pdu); 
 +    std::string skey = pmt::​symbol_to_string(key);
     ​     ​
-    ​freq = std::stoll(pmt::symbol_to_string(pmt::dict_ref(pdupmt::nth(0, keys), pmt::PMT_NIL))); +    ​if (skey == "​frequency"​) { 
-    adf4350_out_altvoltage0_frequency(adf4350_devicefreq);+        long long frequency;​ 
 +        ​pmt::pmt_t freq = pmt::cdr(pdu); 
 +        std::string sfreq = pmt::symbol_to_string(freq)
 +        frequency = std::stoll(sfreq); 
 +        adf4350_out_altvoltage0_frequency(d_adf4350_devicefrequency); 
 +        std::cout << "​ADF4350:​ PLL 0 frequency = " << frequency << "​Hz."​ << std::​endl;​ 
 +    }
  
 **Create python bindings** **Create python bindings**
  
-In swig directory is a file called //iio_swig.i//. Include the block'​s header in this file:+In swig directory is a file called //m2k_swig.i//. Include the block'​s header in this file:
    %{    %{
    ...    ...
-   #​include "gnuradio/​iio/​adf4350_sink.h"​+   #​include "m2k/​adf4350_sink.h"​
    %}    %}
        
    ...    ...
-   ​%include "gnuradio/​iio/​adf4350_sink.h"​+   ​%include "m2k/​adf4350_sink.h"​
        
    ...    ...
-   ​GR_SWIG_BLOCK_MAGIC2(iio, adf4350_sink);​+   ​GR_SWIG_BLOCK_MAGIC2(m2k, adf4350_sink);​
  
 **Create the GRC component** **Create the GRC component**
  
-GNU Radio 3.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.+GNU Radio 3.uses yml files for creating GRC blocks. Create a file //m2k_adf4350_sink.block.yml// in the //grc// directory. This file will describe how the GRC block should look like.
 Add all parameters using the following format: Add all parameters using the following format:
-    <param+    ​-   ​id: ​<key
-        <name>​name</​name> +        ​label: ​<​name>​ 
-        <key>​key</​key+        ​dtype: ​<type
-        <value>​val</​value> +        ​default: ​<​value>​ 
-        ​<​type>​type</​type>​ +        hidepart  ​optional
-        <hide>part</​hide> ​ <​!-- ​optional ​--> +
-    </​param>​+
  
 This block is a sink for messages, not streams. To specify this create the following tag: This block is a sink for messages, not streams. To specify this create the following tag:
-    ​<​sink>​ +    ​inputs: 
-        <​name>​attr</​name>​ +      ​- ​  ​domain: ​message 
-        <​type>​message</​type>​ +          id: msg 
-        <optional>​1</​optional>​ +          ​optional: false
-    </​sink>​+
  
 **Build the new created block** **Build the new created block**
-    cmake .+    ​cd build 
 +    ​cmake ..
     make     make
     sudo make install     sudo make install
-    cd ..+    cd ../..
     sudo ldconfig     sudo ldconfig
  
-The source code can be found on the gr-iio [[https://​github.com/​analogdevicesinc/​gr-iio/​tree/​grcon2019_m2k|github page]], ​grcon2019_m2k branch.+The source code can be found on the gr-m2k [[https://​github.com/​analogdevicesinc/​gr-m2k|github page]]. In order to build itmake sure to enable digital option (cmake -DDIGITAL=ON ..).
  
 ====  GNURadio-Companion Flowgraph ==== ====  GNURadio-Companion Flowgraph ====
  
-{{:​university:​tools:​m2k:​tutorials:​gnuradioflow.png|}}+{{:​university:​tools:​m2k:​tutorials:​m2k_fm.png|}}
  
-The file {{ :​university:​tools:​m2k:​tutorials:​m2k_fm_1.zip |}} contains the gnuradio flowgraph.+The file {{ :​university:​tools:​m2k:​tutorials:​m2k_fm.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 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. 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 [[https://​www.gnuradio.org/​grcon/​grcon19/​presentations/​building_a_radio_with_m2k_and_spare_parts/Adrian Suciu - Building a radio with m2k and spare parts.pdf|here]]+This project was presented in GRCon 2019. Slides are available [[https://​www.gnuradio.org/​grcon/​grcon19/​presentations/​Building_a_radio_with_M2K_and_spare_parts/|here]]
university/tools/m2k/tutorials/buildingaradiowithm2k.1580483741.txt.gz · Last modified: 31 Jan 2020 16:15 by Adrian Suciu