mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-30 23:03:05 +00:00 
			
		
		
		
	Inject file(s) via DMA if switch_position=0 in Ad9361_Fpga_Signal_Source
This commit is contained in:
		| @@ -37,13 +37,242 @@ | ||||
| #include "configuration_interface.h" | ||||
| #include <glog/logging.h> | ||||
| #include <iio.h> | ||||
| #include <cassert>  // for assert | ||||
| #include <exception> | ||||
| #include <fcntl.h>   // for open, O_WRONLY | ||||
| #include <fstream>   // for std::ifstream | ||||
| #include <iostream>  // for cout, endl | ||||
| #include <string> | ||||
| #include <unistd.h>  // for write | ||||
| #include <utility> | ||||
| #include <vector> | ||||
|  | ||||
|  | ||||
| Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configuration, | ||||
|     const std::string& role, unsigned int in_stream, unsigned int out_stream, | ||||
| void run_DMA_process(const std::string &FreqBand, const std::string &Filename1, const std::string &Filename2) | ||||
| { | ||||
|     const int MAX_INPUT_SAMPLES_TOTAL = 8192; | ||||
|     int max_value = 0; | ||||
|     int tx_fd;  // DMA descriptor | ||||
|     std::ifstream infile1; | ||||
|     infile1.exceptions(std::ifstream::failbit | std::ifstream::badbit); | ||||
|  | ||||
|     try | ||||
|         { | ||||
|             infile1.open(Filename1, std::ios::binary); | ||||
|         } | ||||
|     catch (const std::ifstream::failure &e) | ||||
|         { | ||||
|             std::cerr << "Exception opening file " << Filename1 << std::endl; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|     std::ifstream infile2; | ||||
|     infile2.exceptions(std::ifstream::failbit | std::ifstream::badbit); | ||||
|     try | ||||
|         { | ||||
|             infile2.open(Filename2, std::ios::binary); | ||||
|         } | ||||
|     catch (const std::ifstream::failure &e) | ||||
|         { | ||||
|             // could not exist | ||||
|         } | ||||
|  | ||||
|     // rx signal | ||||
|     std::vector<int8_t> input_samples(MAX_INPUT_SAMPLES_TOTAL * 2); | ||||
|     std::vector<int8_t> input_samples2(MAX_INPUT_SAMPLES_TOTAL * 2); | ||||
|     std::vector<int8_t> input_samples_dma(MAX_INPUT_SAMPLES_TOTAL * 2 * 2); | ||||
|  | ||||
|     int nread_elements; | ||||
|     int nread_elements2; | ||||
|     int file_completed = 0; | ||||
|     int num_transferred_bytes; | ||||
|  | ||||
|     //************************************************************************** | ||||
|     // Open DMA device | ||||
|     //************************************************************************** | ||||
|     tx_fd = open("/dev/loop_tx", O_WRONLY); | ||||
|     if (tx_fd < 0) | ||||
|         { | ||||
|             std::cout << "Cannot open loop device" << std::endl; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|     //************************************************************************** | ||||
|     // Open input file | ||||
|     //************************************************************************** | ||||
|     int nsamples = 0; | ||||
|  | ||||
|     while (file_completed == 0) | ||||
|         { | ||||
|             unsigned int dma_index = 0; | ||||
|  | ||||
|             if (FreqBand == "L1") | ||||
|                 { | ||||
|                     try | ||||
|                         { | ||||
|                             infile1.read(reinterpret_cast<char *>(input_samples.data()), MAX_INPUT_SAMPLES_TOTAL * 2); | ||||
|                         } | ||||
|                     catch (const std::ifstream::failure &e) | ||||
|                         { | ||||
|                             std::cerr << "Exception reading file " << Filename1 << std::endl; | ||||
|                         } | ||||
|                     if (infile1) | ||||
|                         { | ||||
|                             nread_elements = MAX_INPUT_SAMPLES_TOTAL * 2; | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             nread_elements = 0; | ||||
|                         } | ||||
|                     nsamples += (nread_elements / 2); | ||||
|  | ||||
|                     for (int index0 = 0; index0 < (nread_elements); index0 += 2) | ||||
|                         { | ||||
|                             // channel 1 (queue 1) | ||||
|                             input_samples_dma[dma_index] = 0; | ||||
|                             input_samples_dma[dma_index + 1] = 0; | ||||
|                             // channel 0 (queue 0) | ||||
|                             input_samples_dma[dma_index + 2] = input_samples[index0]; | ||||
|                             input_samples_dma[dma_index + 3] = input_samples[index0 + 1]; | ||||
|  | ||||
|                             dma_index += 4; | ||||
|                         } | ||||
|                 } | ||||
|             else if (FreqBand == "L2") | ||||
|                 { | ||||
|                     try | ||||
|                         { | ||||
|                             infile1.read(reinterpret_cast<char *>(input_samples.data()), MAX_INPUT_SAMPLES_TOTAL * 2); | ||||
|                         } | ||||
|                     catch (const std::ifstream::failure &e) | ||||
|                         { | ||||
|                             std::cerr << "Exception reading file " << Filename1 << std::endl; | ||||
|                         } | ||||
|                     if (infile1) | ||||
|                         { | ||||
|                             nread_elements = MAX_INPUT_SAMPLES_TOTAL * 2; | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             nread_elements = 0; | ||||
|                         } | ||||
|                     nsamples += (nread_elements / 2); | ||||
|  | ||||
|                     for (int index0 = 0; index0 < (nread_elements); index0 += 2) | ||||
|                         { | ||||
|                             // channel 1 (queue 1) | ||||
|                             input_samples_dma[dma_index] = input_samples[index0]; | ||||
|                             input_samples_dma[dma_index + 1] = input_samples[index0 + 1]; | ||||
|                             // channel 0 (queue 0) | ||||
|                             input_samples_dma[dma_index + 2] = 0; | ||||
|                             input_samples_dma[dma_index + 3] = 0; | ||||
|  | ||||
|                             dma_index += 4; | ||||
|                         } | ||||
|                 } | ||||
|             else if (FreqBand == "L1L2") | ||||
|                 { | ||||
|                     try | ||||
|                         { | ||||
|                             infile1.read(reinterpret_cast<char *>(input_samples.data()), MAX_INPUT_SAMPLES_TOTAL * 2); | ||||
|                         } | ||||
|                     catch (const std::ifstream::failure &e) | ||||
|                         { | ||||
|                             std::cerr << "Exception reading file " << Filename1 << std::endl; | ||||
|                         } | ||||
|                     if (infile1) | ||||
|                         { | ||||
|                             nread_elements = MAX_INPUT_SAMPLES_TOTAL * 2; | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             nread_elements = 0; | ||||
|                         } | ||||
|                     try | ||||
|                         { | ||||
|                             infile2.read(reinterpret_cast<char *>(input_samples2.data()), MAX_INPUT_SAMPLES_TOTAL * 2); | ||||
|                         } | ||||
|                     catch (const std::ifstream::failure &e) | ||||
|                         { | ||||
|                             std::cerr << "Exception reading file " << Filename1 << std::endl; | ||||
|                         } | ||||
|                     if (infile2) | ||||
|                         { | ||||
|                             nread_elements2 = MAX_INPUT_SAMPLES_TOTAL * 2; | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             nread_elements2 = 0; | ||||
|                         } | ||||
|  | ||||
|                     if (nread_elements > nread_elements2) | ||||
|                         { | ||||
|                             nread_elements = nread_elements2;  // take the smallest | ||||
|                         } | ||||
|  | ||||
|                     nsamples += (nread_elements / 2); | ||||
|  | ||||
|                     for (int index0 = 0; index0 < (nread_elements); index0 += 2) | ||||
|                         { | ||||
|                             input_samples[index0] = input_samples[index0]; | ||||
|                             input_samples[index0 + 1] = input_samples[index0 + 1]; | ||||
|  | ||||
|                             if (input_samples[index0] > max_value) | ||||
|                                 { | ||||
|                                     max_value = input_samples[index0]; | ||||
|                                 } | ||||
|                             else if (-input_samples[index0] > max_value) | ||||
|                                 { | ||||
|                                     max_value = -input_samples[index0]; | ||||
|                                 } | ||||
|  | ||||
|                             if (input_samples[index0 + 1] > max_value) | ||||
|                                 { | ||||
|                                     max_value = input_samples[index0 + 1]; | ||||
|                                 } | ||||
|                             else if (-input_samples[index0 + 1] > max_value) | ||||
|                                 { | ||||
|                                     max_value = -input_samples[index0 + 1]; | ||||
|                                 } | ||||
|  | ||||
|                             // channel 1 (queue 1) | ||||
|                             input_samples_dma[dma_index] = input_samples2[index0]; | ||||
|                             input_samples_dma[dma_index + 1] = input_samples2[index0 + 1]; | ||||
|                             // channel 0 (queue 0) | ||||
|                             input_samples_dma[dma_index + 2] = input_samples[index0]; | ||||
|                             input_samples_dma[dma_index + 3] = input_samples[index0 + 1]; | ||||
|  | ||||
|                             dma_index += 4; | ||||
|                         } | ||||
|                 } | ||||
|  | ||||
|             if (nread_elements > 0) | ||||
|                 { | ||||
|                     num_transferred_bytes = nread_elements * 2; | ||||
|                     assert(num_transferred_bytes == | ||||
|                            write(tx_fd, input_samples_dma.data(), nread_elements * 2)); | ||||
|                 } | ||||
|  | ||||
|             if (nread_elements != MAX_INPUT_SAMPLES_TOTAL * 2) | ||||
|                 { | ||||
|                     file_completed = 1; | ||||
|                 } | ||||
|         } | ||||
|  | ||||
|     try | ||||
|         { | ||||
|             infile1.close(); | ||||
|             infile2.close(); | ||||
|         } | ||||
|     catch (const std::ifstream::failure &e) | ||||
|         { | ||||
|             std::cerr << "Exception closing files " << Filename1 << " and " << Filename2 << std::endl; | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface *configuration, | ||||
|     const std::string &role, unsigned int in_stream, unsigned int out_stream, | ||||
|     std::shared_ptr<Concurrent_Queue<pmt::pmt_t>> queue) : role_(role), in_stream_(in_stream), out_stream_(out_stream), queue_(std::move(queue)) | ||||
| { | ||||
|     std::string default_dump_file = "./data/signal_source.dat"; | ||||
| @@ -74,38 +303,74 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configura | ||||
|     phase_dds_deg_ = configuration->property(role + ".phase_dds_deg", 0.0); | ||||
|     tx_attenuation_db_ = configuration->property(role + ".tx_attenuation_db", 0.0); | ||||
|  | ||||
|     item_size_ = sizeof(gr_complex); | ||||
|  | ||||
|     std::cout << "device address: " << uri_ << std::endl; | ||||
|     std::cout << "LO frequency : " << freq_ << " Hz" << std::endl; | ||||
|     std::cout << "sample rate: " << sample_rate_ << " Hz" << std::endl; | ||||
|  | ||||
|     config_ad9361_rx_local(bandwidth_, | ||||
|         sample_rate_, | ||||
|         freq_, | ||||
|         rf_port_select_, | ||||
|         gain_mode_rx1_, | ||||
|         gain_mode_rx2_, | ||||
|         rf_gain_rx1_, | ||||
|         rf_gain_rx2_); | ||||
|  | ||||
|     // LOCAL OSCILLATOR DDS GENERATOR FOR DUAL FREQUENCY OPERATION | ||||
|     if (enable_dds_lo_ == true) | ||||
|         { | ||||
|             config_ad9361_lo_local(bandwidth_, | ||||
|                 sample_rate_, | ||||
|                 freq_rf_tx_hz_, | ||||
|                 tx_attenuation_db_, | ||||
|                 freq_dds_tx_hz_, | ||||
|                 scale_dds_dbfs_); | ||||
|         } | ||||
|  | ||||
|     // turn switch to A/D position | ||||
|     std::string default_device_name = "/dev/uio1"; | ||||
|     std::string device_name = configuration->property(role + ".devicename", default_device_name); | ||||
|     int32_t switch_position = configuration->property(role + ".switch_position", 0); | ||||
|     switch_position = configuration->property(role + ".switch_position", 0); | ||||
|     switch_fpga = std::make_shared<Fpga_Switch>(device_name); | ||||
|     switch_fpga->set_switch_position(switch_position); | ||||
|  | ||||
|     item_size_ = sizeof(gr_complex); | ||||
|  | ||||
|     std::cout << "Sample rate: " << sample_rate_ << " Sps" << std::endl; | ||||
|  | ||||
|     if (switch_position == 0)  // Inject file(s) via DMA | ||||
|         { | ||||
|             std::string empty_string; | ||||
|             filename_rx1 = configuration->property(role + ".filename_rx1", empty_string); | ||||
|             filename_rx2 = configuration->property(role + ".filename_rx2", empty_string); | ||||
|             int l1_band = configuration->property("Channels_1C.count", 0) + | ||||
|                           configuration->property("Channels_1B.count", 0) + | ||||
|                           configuration->property("Channels_L5.count", 0) + | ||||
|                           configuration->property("Channels_2S.count", 0) + | ||||
|                           configuration->property("Channels_5X.count", 0); | ||||
|  | ||||
|             int l2_band = configuration->property("Channels_L5.count", 0) * configuration->property("Channels_1C.count", 0) + | ||||
|                           configuration->property("Channels_5X.count", 0) * configuration->property("Channels_1B.count", 0) + | ||||
|                           configuration->property("Channels_2S.count", 0) * configuration->property("Channels_1C.count", 0); | ||||
|  | ||||
|             if (l1_band != 0) | ||||
|                 { | ||||
|                     freq_band = "L1"; | ||||
|                 } | ||||
|             if (l2_band != 0 && l1_band == 0) | ||||
|                 { | ||||
|                     freq_band = "L2"; | ||||
|                 } | ||||
|             if (l1_band != 0 && l2_band != 0) | ||||
|                 { | ||||
|                     freq_band = "L1L2"; | ||||
|                 } | ||||
|  | ||||
|             thread_file_to_dma = std::thread([&] { run_DMA_process(freq_band, filename_rx1, filename_rx2); }); | ||||
|         } | ||||
|     if (switch_position == 2)  // Real-time via AD9361 | ||||
|         { | ||||
|             std::cout << "LO frequency : " << freq_ << " Hz" << std::endl; | ||||
|             config_ad9361_rx_local(bandwidth_, | ||||
|                 sample_rate_, | ||||
|                 freq_, | ||||
|                 rf_port_select_, | ||||
|                 gain_mode_rx1_, | ||||
|                 gain_mode_rx2_, | ||||
|                 rf_gain_rx1_, | ||||
|                 rf_gain_rx2_); | ||||
|  | ||||
|             // LOCAL OSCILLATOR DDS GENERATOR FOR DUAL FREQUENCY OPERATION | ||||
|             if (enable_dds_lo_ == true) | ||||
|                 { | ||||
|                     config_ad9361_lo_local(bandwidth_, | ||||
|                         sample_rate_, | ||||
|                         freq_rf_tx_hz_, | ||||
|                         tx_attenuation_db_, | ||||
|                         freq_dds_tx_hz_, | ||||
|                         scale_dds_dbfs_); | ||||
|                 } | ||||
|         } | ||||
|     if (switch_position != 0 && switch_position != 2) | ||||
|         { | ||||
|             std::cout << "SignalSource.switch_position configuration parameter must be either 0: read from file(s) via DMA, or 2: read from AD9361" << std::endl; | ||||
|         } | ||||
|     if (in_stream_ > 0) | ||||
|         { | ||||
|             LOG(ERROR) << "A signal source does not have an input stream"; | ||||
| @@ -130,12 +395,18 @@ Ad9361FpgaSignalSource::~Ad9361FpgaSignalSource() | ||||
|                 { | ||||
|                     ad9361_disable_lo_local(); | ||||
|                 } | ||||
|             catch (const std::exception& e) | ||||
|             catch (const std::exception &e) | ||||
|                 { | ||||
|                     LOG(WARNING) << "Problem closing the Ad9361FpgaSignalSource: " << e.what(); | ||||
|                 } | ||||
|         } | ||||
|  | ||||
|     if (switch_position == 0)  // read samples from a file via DMA | ||||
|         { | ||||
|             if (thread_file_to_dma.joinable()) | ||||
|                 { | ||||
|                     thread_file_to_dma.join(); | ||||
|                 } | ||||
|         } | ||||
|     // std::cout<<"* AD9361 Destroying context\n"; | ||||
|     // if (ctx) { iio_context_destroy(ctx); } | ||||
| } | ||||
| @@ -168,6 +439,5 @@ gr::basic_block_sptr Ad9361FpgaSignalSource::get_left_block() | ||||
|  | ||||
| gr::basic_block_sptr Ad9361FpgaSignalSource::get_right_block() | ||||
| { | ||||
|     LOG(WARNING) << "Trying to get AD9361 FPGA signal source right block."; | ||||
|     return gr::basic_block_sptr(); | ||||
| } | ||||
|   | ||||
| @@ -40,6 +40,7 @@ | ||||
| #include <cstdint> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <thread> | ||||
|  | ||||
| class ConfigurationInterface; | ||||
|  | ||||
| @@ -79,8 +80,7 @@ private: | ||||
|     std::string role_; | ||||
|  | ||||
|     // Front-end settings | ||||
|     std::string uri_;  // device direction | ||||
|     uint64_t freq_;    // frequency of local oscillator | ||||
|     uint64_t freq_;  // frequency of local oscillator | ||||
|     uint64_t sample_rate_; | ||||
|     uint64_t bandwidth_; | ||||
|     uint64_t buffer_size_;  // reception buffer | ||||
| @@ -116,6 +116,12 @@ private: | ||||
|     std::shared_ptr<Concurrent_Queue<pmt::pmt_t>> queue_; | ||||
|  | ||||
|     std::shared_ptr<Fpga_Switch> switch_fpga; | ||||
|     int32_t switch_position; | ||||
|  | ||||
|     std::thread thread_file_to_dma; | ||||
|     std::string filename_rx1; | ||||
|     std::string filename_rx2; | ||||
|     std::string freq_band; | ||||
| }; | ||||
|  | ||||
| #endif  // GNSS_SDR_AD9361_FPGA_SIGNAL_SOURCE_H_ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Carles Fernandez
					Carles Fernandez