mirror of
				https://github.com/fairwaves/UHD-Fairwaves.git
				synced 2025-11-04 05:53:17 +00:00 
			
		
		
		
	Compare commits
	
		
			45 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2a89674c56 | ||
| 
						 | 
					77e9066bf8 | ||
| 
						 | 
					1e43f04790 | ||
| 
						 | 
					cbff81745b | ||
| 
						 | 
					57d5ca4b51 | ||
| 
						 | 
					b78ceeb9b1 | ||
| 
						 | 
					fcd92d8f50 | ||
| 
						 | 
					2727f62ab8 | ||
| 
						 | 
					75c3380ccf | ||
| 
						 | 
					80e65f35cf | ||
| 
						 | 
					f16599cfa9 | ||
| 
						 | 
					e6b82c85e6 | ||
| 
						 | 
					8e5b9e8cba | ||
| 
						 | 
					fc9ecf7709 | ||
| 
						 | 
					913f19357b | ||
| 
						 | 
					d96cea8000 | ||
| 
						 | 
					c401071ea6 | ||
| 
						 | 
					b5b351e535 | ||
| 
						 | 
					1cf16e57f7 | ||
| 
						 | 
					b78a96661a | ||
| 
						 | 
					5452567fd9 | ||
| 
						 | 
					47b3e1aaea | ||
| 
						 | 
					1e042157be | ||
| 
						 | 
					4cb89755bb | ||
| 
						 | 
					efba897843 | ||
| 
						 | 
					35ccac9f54 | ||
| 
						 | 
					963f3e90dc | ||
| 
						 | 
					0e8abb2068 | ||
| 
						 | 
					e069b6d39c | ||
| 
						 | 
					28f423567b | ||
| 
						 | 
					67303bcbcc | ||
| 
						 | 
					0fc60d2275 | ||
| 
						 | 
					ce5f31f713 | ||
| 
						 | 
					802b24c565 | ||
| 
						 | 
					56c4174ad4 | ||
| 
						 | 
					0073096b27 | ||
| 
						 | 
					7727cd283c | ||
| 
						 | 
					ff13c7d73a | ||
| 
						 | 
					0bee662b81 | ||
| 
						 | 
					7b955574a5 | ||
| 
						 | 
					4b102f0c4c | ||
| 
						 | 
					0d7b517923 | ||
| 
						 | 
					aec754eb07 | ||
| 
						 | 
					756cb9a74c | ||
| 
						 | 
					471eedbb6a | 
							
								
								
									
										30
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					umtrx (1.0.5) trusty; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * host: disable umtrx_fifo_ctrl cache of spi config
 | 
				
			||||||
 | 
					  * host: Fix getters in umtrx_property_tree.py.
 | 
				
			||||||
 | 
					  * debian: added firmware to package and umtrx_firmware script to handle it
 | 
				
			||||||
 | 
					  * fpga: created axi stream controled spi core
 | 
				
			||||||
 | 
					  * fpga: use axi stream spi core (still single dest)
 | 
				
			||||||
 | 
					  * fpga: connect both spi settings drivers
 | 
				
			||||||
 | 
					  * fpga: simplify spi setting regs with generate loop
 | 
				
			||||||
 | 
					  * fpga: updated 4x ddc image for spi work
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Kirill Zakharenko <earwin@gmail.com>  Mon, 23 Nov 2015 15:51:56 +0300
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					umtrx (1.0.4) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Do not add 'g' to a git id when creating a version string.
 | 
				
			||||||
 | 
					  * Proper debianization.
 | 
				
			||||||
 | 
					  * Add ability to set diversity switches position from UHD args.
 | 
				
			||||||
 | 
					  * By default route each Rx channel to it's own antenna.
 | 
				
			||||||
 | 
					  * JSON API to question/control property tree of a running UHD app. Useful for querying sensors and for debugging purposes.
 | 
				
			||||||
 | 
					  * Python utility to query VSWR from a running UHD app in real time using JSON API.
 | 
				
			||||||
 | 
					  * Fix DC and IQ calibration utilities.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Alexander Chemeris <Alexander.Chemeris@fairwaves.co>  Tue, 21 Jul 2015 18:51:56 -0400
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					umtrx (1.0.3) unstable; urgency=low
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  * Created debian control files for 1.0.3 release of umtrx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 -- Josh Blum <josh@pothosware.com>  Sat, 20 Jun 2015 16:31:24 -0700
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/compat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/compat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					9
 | 
				
			||||||
							
								
								
									
										33
									
								
								debian/control
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								debian/control
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					Source: umtrx
 | 
				
			||||||
 | 
					Section: libs
 | 
				
			||||||
 | 
					Priority: optional
 | 
				
			||||||
 | 
					Maintainer: Josh Blum <josh@pothosware.com>
 | 
				
			||||||
 | 
					Build-Depends:
 | 
				
			||||||
 | 
					    debhelper (>= 9.0.0),
 | 
				
			||||||
 | 
					    cmake (>= 2.8),
 | 
				
			||||||
 | 
					    libboost-all-dev,
 | 
				
			||||||
 | 
					    libuhd-dev (>= 3.7)
 | 
				
			||||||
 | 
					Standards-Version: 3.9.5
 | 
				
			||||||
 | 
					Homepage: http://umtrx.org/
 | 
				
			||||||
 | 
					Vcs-Git: https://github.com/fairwaves/UHD-Fairwaves.git
 | 
				
			||||||
 | 
					Vcs-Browser: https://github.com/fairwaves/UHD-Fairwaves
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: umtrx
 | 
				
			||||||
 | 
					Section: libs
 | 
				
			||||||
 | 
					Architecture: any
 | 
				
			||||||
 | 
					Pre-Depends: multiarch-support, ${misc:Pre-Depends}
 | 
				
			||||||
 | 
					Depends: ${shlibs:Depends}, ${misc:Depends}, uhd-umtrx
 | 
				
			||||||
 | 
					Conflicts: umtrx-uhd
 | 
				
			||||||
 | 
					Replaces: umtrx-uhd
 | 
				
			||||||
 | 
					Recommends: python
 | 
				
			||||||
 | 
					Description: Fairwaves UmTRX driver - runtime utilities
 | 
				
			||||||
 | 
					 The industrial grade dual-channel wide-band SDR transceiver.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Package: uhd-umtrx
 | 
				
			||||||
 | 
					Section: libs
 | 
				
			||||||
 | 
					Architecture: any
 | 
				
			||||||
 | 
					Depends: ${shlibs:Depends}, ${misc:Depends}
 | 
				
			||||||
 | 
					Conflicts: umtrx-uhd
 | 
				
			||||||
 | 
					Replaces: umtrx-uhd
 | 
				
			||||||
 | 
					Description: Fairwaves UmTRX driver - UHD plugin module
 | 
				
			||||||
 | 
					 The industrial grade dual-channel wide-band SDR transceiver.
 | 
				
			||||||
							
								
								
									
										12
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 | 
				
			||||||
 | 
					Upstream-Name: umtrx
 | 
				
			||||||
 | 
					Source: https://github.com/fairwaves/UHD-Fairwaves
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: *
 | 
				
			||||||
 | 
					Copyright:
 | 
				
			||||||
 | 
					    Copyright 2012-2015 Fairwaves LLC
 | 
				
			||||||
 | 
					    Copyright 2010-2012 Ettus Research LLC
 | 
				
			||||||
 | 
					License: GPL-3
 | 
				
			||||||
 | 
					 On Debian systems, the full text of the GNU General Public
 | 
				
			||||||
 | 
					 License version 3 can be found in the file
 | 
				
			||||||
 | 
					 `/usr/share/common-licenses/GPL-3'.
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/docs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/docs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					README
 | 
				
			||||||
							
								
								
									
										18
									
								
								debian/rules
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										18
									
								
								debian/rules
									
									
									
									
										vendored
									
									
										Executable file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/make -f
 | 
				
			||||||
 | 
					# -*- makefile -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
 | 
				
			||||||
 | 
					export DEB_HOST_MULTIARCH
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Uncomment this to turn on verbose mode.
 | 
				
			||||||
 | 
					#export DH_VERBOSE=1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This has to be exported to make some magic below work.
 | 
				
			||||||
 | 
					export DH_OPTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%:
 | 
				
			||||||
 | 
						dh $@ --buildsystem=cmake --parallel --sourcedirectory=host
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					override_dh_auto_configure:
 | 
				
			||||||
 | 
						dh_auto_configure -- -DLIB_SUFFIX="/$(DEB_HOST_MULTIARCH)"
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					3.0 (native)
 | 
				
			||||||
							
								
								
									
										1
									
								
								debian/uhd-umtrx.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/uhd-umtrx.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					usr/lib/*/uhd/modules/
 | 
				
			||||||
							
								
								
									
										2
									
								
								debian/umtrx.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								debian/umtrx.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					usr/bin
 | 
				
			||||||
 | 
					images/u2plus_umtrx_v2.bin images/umtrx_txrx_uhd.bin usr/share/umtrx/firmware
 | 
				
			||||||
@@ -58,5 +58,6 @@ gpio_atr.v \
 | 
				
			|||||||
user_settings.v \
 | 
					user_settings.v \
 | 
				
			||||||
settings_fifo_ctrl.v \
 | 
					settings_fifo_ctrl.v \
 | 
				
			||||||
simple_spi_core.v \
 | 
					simple_spi_core.v \
 | 
				
			||||||
 | 
					axis_spi_core.v \
 | 
				
			||||||
simple_i2c_core.v \
 | 
					simple_i2c_core.v \
 | 
				
			||||||
))
 | 
					))
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										243
									
								
								fpga/control_lib/axis_spi_core.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								fpga/control_lib/axis_spi_core.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,243 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright 2012 Ettus Research LLC
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// (at your option) any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Simple SPI core, the simplest, yet complete spi core I can think of
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Settings register controlled.
 | 
				
			||||||
 | 
					// 2 settings regs, control and data
 | 
				
			||||||
 | 
					// 1 32-bit readback and status signal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Settings reg map:
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// BASE+0 divider setting
 | 
				
			||||||
 | 
					// bits [15:0] spi clock divider
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// BASE+1 configuration input
 | 
				
			||||||
 | 
					// bits [23:0] slave select, bit0 = slave0 enabled
 | 
				
			||||||
 | 
					// bits [29:24] num bits (1 through 32)
 | 
				
			||||||
 | 
					// bit [30] data input edge = in data bit latched on rising edge of clock
 | 
				
			||||||
 | 
					// bit [31] data output edge = out data bit latched on rising edge of clock
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// BASE+2 input data
 | 
				
			||||||
 | 
					// Writing this register begins a spi transaction.
 | 
				
			||||||
 | 
					// Bits are latched out from bit 0.
 | 
				
			||||||
 | 
					// Therefore, load this register in reverse.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Readback
 | 
				
			||||||
 | 
					// Bits are latched into bit 0.
 | 
				
			||||||
 | 
					// Therefore, data will be in-order.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module axis_spi_core
 | 
				
			||||||
 | 
					    #(
 | 
				
			||||||
 | 
					        //set to 1 for ILA
 | 
				
			||||||
 | 
					        parameter DEBUG = 0,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //tdest width for number of core users
 | 
				
			||||||
 | 
					        parameter DESTW = 1,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //width of serial enables (up to 24 is possible)
 | 
				
			||||||
 | 
					        parameter WIDTH = 8,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //idle state of the spi clock
 | 
				
			||||||
 | 
					        parameter CLK_IDLE = 0,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //idle state of the serial enables
 | 
				
			||||||
 | 
					        parameter SEN_IDLE = 24'hffffff
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    (
 | 
				
			||||||
 | 
					        //clock and synchronous reset
 | 
				
			||||||
 | 
					        input clock, input reset,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //configuration settings bus
 | 
				
			||||||
 | 
					        input [DESTW-1:0] CONFIG_tdest,
 | 
				
			||||||
 | 
					        input [79:0] CONFIG_tdata,
 | 
				
			||||||
 | 
					        input CONFIG_tvalid,
 | 
				
			||||||
 | 
					        output CONFIG_tready,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //32-bit data readback
 | 
				
			||||||
 | 
					        output reg [DESTW-1:0] READBACK_tdest,
 | 
				
			||||||
 | 
					        output [31:0] READBACK_tdata,
 | 
				
			||||||
 | 
					        output READBACK_tvalid,
 | 
				
			||||||
 | 
					        input READBACK_tready,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //spi interface, slave selects, clock, data in, data out
 | 
				
			||||||
 | 
					        output [WIDTH-1:0] sen,
 | 
				
			||||||
 | 
					        output sclk,
 | 
				
			||||||
 | 
					        output mosi,
 | 
				
			||||||
 | 
					        input miso
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //state
 | 
				
			||||||
 | 
					    localparam WAIT_CONFIG = 0;
 | 
				
			||||||
 | 
					    localparam PRE_IDLE = 1;
 | 
				
			||||||
 | 
					    localparam CLK_REG = 2;
 | 
				
			||||||
 | 
					    localparam CLK_INV = 3;
 | 
				
			||||||
 | 
					    localparam POST_IDLE = 4;
 | 
				
			||||||
 | 
					    localparam IDLE_SEN = 5;
 | 
				
			||||||
 | 
					    localparam WAIT_READBACK = 6;
 | 
				
			||||||
 | 
					    reg [2:0] state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //configuration settings
 | 
				
			||||||
 | 
					    reg [15:0] sclk_divider;
 | 
				
			||||||
 | 
					    reg [23:0] slave_select;
 | 
				
			||||||
 | 
					    reg [5:0] num_bits;
 | 
				
			||||||
 | 
					    reg datain_edge, dataout_edge;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //output ready/valid signals
 | 
				
			||||||
 | 
					    assign CONFIG_tready = (state == WAIT_CONFIG);
 | 
				
			||||||
 | 
					    assign READBACK_tvalid = (state == WAIT_READBACK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //serial clock either idles or is in one of two clock states
 | 
				
			||||||
 | 
					    reg sclk_reg;
 | 
				
			||||||
 | 
					    assign sclk = sclk_reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //serial enables either idle or enabled based on state
 | 
				
			||||||
 | 
					    wire sen_is_idle = (state == WAIT_CONFIG) || (state == IDLE_SEN);
 | 
				
			||||||
 | 
					    wire [23:0] sen24 = (sen_is_idle)? SEN_IDLE : (SEN_IDLE ^ slave_select);
 | 
				
			||||||
 | 
					    reg [WIDTH-1:0] sen_reg;
 | 
				
			||||||
 | 
					    always @(posedge clock) sen_reg <= sen24[WIDTH-1:0];
 | 
				
			||||||
 | 
					    assign sen = sen_reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //data output shift register
 | 
				
			||||||
 | 
					    reg [31:0] dataout_reg;
 | 
				
			||||||
 | 
					    wire [31:0] dataout_next = {dataout_reg[30:0], 1'b0};
 | 
				
			||||||
 | 
					    assign mosi = dataout_reg[31];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //data input shift register
 | 
				
			||||||
 | 
					    reg [31:0] datain_reg;
 | 
				
			||||||
 | 
					    wire [31:0] datain_next = {datain_reg[30:0], miso};
 | 
				
			||||||
 | 
					    assign READBACK_tdata = datain_reg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //counter for spi clock
 | 
				
			||||||
 | 
					    reg [15:0] sclk_counter;
 | 
				
			||||||
 | 
					    wire sclk_counter_done = (sclk_counter == sclk_divider);
 | 
				
			||||||
 | 
					    wire [15:0] sclk_counter_next = (sclk_counter_done)? 0 : sclk_counter + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //counter for latching bits miso/mosi
 | 
				
			||||||
 | 
					    reg [6:0] bit_counter;
 | 
				
			||||||
 | 
					    wire [6:0] bit_counter_next = bit_counter + 1;
 | 
				
			||||||
 | 
					    wire bit_counter_done = (bit_counter_next == num_bits);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    always @(posedge clock) begin
 | 
				
			||||||
 | 
					        if (reset) begin
 | 
				
			||||||
 | 
					            state <= WAIT_CONFIG;
 | 
				
			||||||
 | 
					            sclk_reg <= CLK_IDLE;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        else begin
 | 
				
			||||||
 | 
					            case (state)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            WAIT_CONFIG: begin
 | 
				
			||||||
 | 
					                if (CONFIG_tvalid && CONFIG_tready) begin
 | 
				
			||||||
 | 
					                    state <= PRE_IDLE;
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					                {sclk_divider, dataout_edge, datain_edge, num_bits, slave_select, dataout_reg} <= CONFIG_tdata;
 | 
				
			||||||
 | 
					                READBACK_tdest <= CONFIG_tdest;
 | 
				
			||||||
 | 
					                sclk_counter <= 0;
 | 
				
			||||||
 | 
					                bit_counter <= 0;
 | 
				
			||||||
 | 
					                sclk_reg <= CLK_IDLE;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            PRE_IDLE: begin
 | 
				
			||||||
 | 
					                if (sclk_counter_done) state <= CLK_REG;
 | 
				
			||||||
 | 
					                sclk_counter <= sclk_counter_next;
 | 
				
			||||||
 | 
					                sclk_reg <= CLK_IDLE;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            CLK_REG: begin
 | 
				
			||||||
 | 
					                if (sclk_counter_done) begin
 | 
				
			||||||
 | 
					                    state <= CLK_INV;
 | 
				
			||||||
 | 
					                    if (datain_edge  != CLK_IDLE)                     datain_reg  <= datain_next;
 | 
				
			||||||
 | 
					                    if (dataout_edge != CLK_IDLE && bit_counter != 0) dataout_reg <= dataout_next;
 | 
				
			||||||
 | 
					                    sclk_reg <= ~CLK_IDLE; //transition to rising when CLK_IDLE == 0
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					                sclk_counter <= sclk_counter_next;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            CLK_INV: begin
 | 
				
			||||||
 | 
					                if (sclk_counter_done) begin
 | 
				
			||||||
 | 
					                    state <= (bit_counter_done)? POST_IDLE : CLK_REG;
 | 
				
			||||||
 | 
					                    bit_counter <= bit_counter_next;
 | 
				
			||||||
 | 
					                    if (datain_edge  == CLK_IDLE)                      datain_reg  <= datain_next;
 | 
				
			||||||
 | 
					                    if (dataout_edge == CLK_IDLE && ~bit_counter_done) dataout_reg <= dataout_next;
 | 
				
			||||||
 | 
					                    sclk_reg <= CLK_IDLE; //transition to falling when CLK_IDLE == 0
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					                sclk_counter <= sclk_counter_next;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            POST_IDLE: begin
 | 
				
			||||||
 | 
					                if (sclk_counter_done) state <= IDLE_SEN;
 | 
				
			||||||
 | 
					                sclk_counter <= sclk_counter_next;
 | 
				
			||||||
 | 
					                sclk_reg <= CLK_IDLE;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            IDLE_SEN: begin
 | 
				
			||||||
 | 
					                if (sclk_counter_done) state <= WAIT_READBACK;
 | 
				
			||||||
 | 
					                sclk_counter <= sclk_counter_next;
 | 
				
			||||||
 | 
					                sclk_reg <= CLK_IDLE;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            WAIT_READBACK: begin
 | 
				
			||||||
 | 
					                if (READBACK_tready && READBACK_tvalid) begin
 | 
				
			||||||
 | 
					                    state <= WAIT_CONFIG;
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            default: state <= WAIT_CONFIG;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            endcase //state
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*******************************************************************
 | 
				
			||||||
 | 
					     * Debug
 | 
				
			||||||
 | 
					     ******************************************************************/
 | 
				
			||||||
 | 
					    generate
 | 
				
			||||||
 | 
					    if (DEBUG == 1) begin
 | 
				
			||||||
 | 
					        wire [35:0] CONTROL0;
 | 
				
			||||||
 | 
					        chipscope_icon chipscope_icon
 | 
				
			||||||
 | 
					        (
 | 
				
			||||||
 | 
					            .CONTROL0(CONTROL0)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        wire [255:0] DATA;
 | 
				
			||||||
 | 
					        wire [7:0] TRIG0;
 | 
				
			||||||
 | 
					        chipscope_ila chipscope_ila
 | 
				
			||||||
 | 
					        (
 | 
				
			||||||
 | 
					            .CONTROL(CONTROL0),
 | 
				
			||||||
 | 
					            .CLK(clock),
 | 
				
			||||||
 | 
					            .DATA(DATA),
 | 
				
			||||||
 | 
					            .TRIG0(TRIG0)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        assign TRIG0 =
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            4'b0,
 | 
				
			||||||
 | 
					            CONFIG_tvalid, CONFIG_tready,
 | 
				
			||||||
 | 
					            READBACK_tvalid, READBACK_tready
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assign DATA[79:0] = CONFIG_tdata;
 | 
				
			||||||
 | 
					        assign DATA[111:80] = READBACK_tdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assign DATA[112] = CONFIG_tvalid;
 | 
				
			||||||
 | 
					        assign DATA[113] = CONFIG_tready;
 | 
				
			||||||
 | 
					        assign DATA[114] = READBACK_tvalid;
 | 
				
			||||||
 | 
					        assign DATA[115] = READBACK_tready;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assign DATA[127:120] = state;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    endgenerate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					endmodule //axis_spi_core
 | 
				
			||||||
@@ -175,6 +175,10 @@ module umtrx_core
 | 
				
			|||||||
   wire [31:0] 	set_data, set_data_dsp, set_data_sys, set_data_fe, set_data_udp_wb, set_data_udp_sys;
 | 
					   wire [31:0] 	set_data, set_data_dsp, set_data_sys, set_data_fe, set_data_udp_wb, set_data_udp_sys;
 | 
				
			||||||
   wire 	set_stb, set_stb_dsp, set_stb_sys, set_stb_fe, set_stb_udp_wb, set_stb_udp_sys;
 | 
					   wire 	set_stb, set_stb_dsp, set_stb_sys, set_stb_fe, set_stb_udp_wb, set_stb_udp_sys;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   wire set_stb_dsp0, set_stb_dsp1;
 | 
				
			||||||
 | 
					   wire [31:0] set_data_dsp0, set_data_dsp1;
 | 
				
			||||||
 | 
					   wire [7:0] set_addr_dsp0, set_addr_dsp1;
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
   reg 		wb_rst;
 | 
					   reg 		wb_rst;
 | 
				
			||||||
   wire 	dsp_rst, sys_rst, fe_rst;
 | 
					   wire 	dsp_rst, sys_rst, fe_rst;
 | 
				
			||||||
   wire     net_clr;
 | 
					   wire     net_clr;
 | 
				
			||||||
@@ -412,17 +416,80 @@ module umtrx_core
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
   // /////////////////////////////////////////////////////////////////////////
 | 
					   // /////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
   // SPI -- Slave #2
 | 
					   // SPI -- Slave #2
 | 
				
			||||||
    wire [31:0] spi_debug;
 | 
					    reg [31:0] spi_readback0;
 | 
				
			||||||
    wire [31:0] spi_readback;
 | 
					    reg [31:0] spi_readback1;
 | 
				
			||||||
    wire spi_ready;
 | 
					    wire spi_ready;
 | 
				
			||||||
    simple_spi_core #(.BASE(SR_SPI_CORE), .WIDTH(5)) shared_spi(
 | 
					
 | 
				
			||||||
 | 
					    wire [0:0] AXIS_SPI_CONFIG_tdest;
 | 
				
			||||||
 | 
					    wire [79:0] AXIS_SPI_CONFIG_tdata;
 | 
				
			||||||
 | 
					    wire AXIS_SPI_CONFIG_tvalid;
 | 
				
			||||||
 | 
					    wire AXIS_SPI_CONFIG_tready;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wire [0:0] AXIS_SPI_READBACK_tdest;
 | 
				
			||||||
 | 
					    wire [31:0] AXIS_SPI_READBACK_tdata;
 | 
				
			||||||
 | 
					    wire AXIS_SPI_READBACK_tvalid;
 | 
				
			||||||
 | 
					    wire AXIS_SPI_READBACK_tready;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    axis_spi_core #(.DESTW(1), .WIDTH(5), .DEBUG(0)) axis_shared_spi(
 | 
				
			||||||
        .clock(dsp_clk), .reset(dsp_rst),
 | 
					        .clock(dsp_clk), .reset(dsp_rst),
 | 
				
			||||||
        .set_stb(set_stb_dsp), .set_addr(set_addr_dsp), .set_data(set_data_dsp),
 | 
					
 | 
				
			||||||
        .readback(spi_readback), .ready(spi_ready),
 | 
					        .CONFIG_tdest(AXIS_SPI_CONFIG_tdest),
 | 
				
			||||||
 | 
					        .CONFIG_tdata(AXIS_SPI_CONFIG_tdata),
 | 
				
			||||||
 | 
					        .CONFIG_tvalid(AXIS_SPI_CONFIG_tvalid),
 | 
				
			||||||
 | 
					        .CONFIG_tready(AXIS_SPI_CONFIG_tready),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        .READBACK_tdest(AXIS_SPI_READBACK_tdest),
 | 
				
			||||||
 | 
					        .READBACK_tdata(AXIS_SPI_READBACK_tdata),
 | 
				
			||||||
 | 
					        .READBACK_tvalid(AXIS_SPI_READBACK_tvalid),
 | 
				
			||||||
 | 
					        .READBACK_tready(AXIS_SPI_READBACK_tready),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .sen({aux_sen2,aux_sen1,sen_dac,sen_lms2,sen_lms1}),
 | 
					        .sen({aux_sen2,aux_sen1,sen_dac,sen_lms2,sen_lms1}),
 | 
				
			||||||
        .sclk(sclk), .mosi(mosi), .miso(miso), .debug(spi_debug)
 | 
					        .sclk(sclk), .mosi(mosi), .miso(miso)
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //setting register block for spi dest 0 (wishbone) and spi dest 1 (ctrl fifo)
 | 
				
			||||||
 | 
					    //Note: the strobes are exclusive (settings fifo cross clock)
 | 
				
			||||||
 | 
					    wire [79:0] spi_config [0:1];
 | 
				
			||||||
 | 
					    wire [0:1] spi_trigger;
 | 
				
			||||||
 | 
					    wire [0:1] set_stb_dsp_n = {set_stb_dsp0, set_stb_dsp1};
 | 
				
			||||||
 | 
					    genvar i;
 | 
				
			||||||
 | 
					    generate for (i=0; i <= 1; i=i+1) begin
 | 
				
			||||||
 | 
					        setting_reg #(.my_addr(SR_SPI_CORE+2),.width(32)) axis_shared_spi_sr0(
 | 
				
			||||||
 | 
					            .clk(dsp_clk),.rst(dsp_rst),.strobe(set_stb_dsp_n[i]),.addr(set_addr_dsp),.in(set_data_dsp),
 | 
				
			||||||
 | 
					            .out(spi_config[i][31:0]),.changed(spi_trigger[i]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        setting_reg #(.my_addr(SR_SPI_CORE+1),.width(32)) axis_shared_spi_sr1(
 | 
				
			||||||
 | 
					            .clk(dsp_clk),.rst(dsp_rst),.strobe(set_stb_dsp_n[i]),.addr(set_addr_dsp),.in(set_data_dsp),
 | 
				
			||||||
 | 
					            .out(spi_config[i][63:32]),.changed());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        setting_reg #(.my_addr(SR_SPI_CORE+0),.width(16)) axis_shared_spi_sr2(
 | 
				
			||||||
 | 
					            .clk(dsp_clk),.rst(dsp_rst),.strobe(set_stb_dsp_n[i]),.addr(set_addr_dsp),.in(set_data_dsp),
 | 
				
			||||||
 | 
					            .out(spi_config[i][79:64]),.changed());
 | 
				
			||||||
 | 
					    end endgenerate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //assign config bus from setting register sources
 | 
				
			||||||
 | 
					    //Note: the triggers are exclusive (settings fifo cross clock)
 | 
				
			||||||
 | 
					    assign AXIS_SPI_CONFIG_tdest = (spi_trigger[0])?1'b0:1'b1;
 | 
				
			||||||
 | 
					    assign AXIS_SPI_CONFIG_tdata = (spi_trigger[0])?spi_config[0]:spi_config[1];
 | 
				
			||||||
 | 
					    assign AXIS_SPI_CONFIG_tvalid = (spi_trigger != 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //create spi ready to block the ctrl fifo ASAP
 | 
				
			||||||
 | 
					    wire spi_ready_now = AXIS_SPI_CONFIG_tready && !AXIS_SPI_CONFIG_tvalid;
 | 
				
			||||||
 | 
					    assign spi_ready = spi_ready_now && spi_ready_prev;
 | 
				
			||||||
 | 
					    reg spi_ready_prev;
 | 
				
			||||||
 | 
					    always @(posedge dsp_clk) begin
 | 
				
			||||||
 | 
					        spi_ready_prev <= spi_ready_now;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //readback output bus latches values into readback register
 | 
				
			||||||
 | 
					    assign AXIS_SPI_READBACK_tready = 1'b1;
 | 
				
			||||||
 | 
					    always @(posedge dsp_clk) begin
 | 
				
			||||||
 | 
					        if (AXIS_SPI_READBACK_tvalid && AXIS_SPI_READBACK_tready) begin
 | 
				
			||||||
 | 
					            if (AXIS_SPI_READBACK_tdest == 1'b0) spi_readback0 <= AXIS_SPI_READBACK_tdata;
 | 
				
			||||||
 | 
					            if (AXIS_SPI_READBACK_tdest == 1'b1) spi_readback1 <= AXIS_SPI_READBACK_tdata;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   // /////////////////////////////////////////////////////////////////////////
 | 
					   // /////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
   // I2C -- Slave #3
 | 
					   // I2C -- Slave #3
 | 
				
			||||||
   i2c_master_top #(.ARST_LVL(1)) 
 | 
					   i2c_master_top #(.ARST_LVL(1)) 
 | 
				
			||||||
@@ -448,7 +515,7 @@ module umtrx_core
 | 
				
			|||||||
   // Buffer Pool Status -- Slave #5   
 | 
					   // Buffer Pool Status -- Slave #5   
 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
   //compatibility number -> increment when the fpga has been sufficiently altered
 | 
					   //compatibility number -> increment when the fpga has been sufficiently altered
 | 
				
			||||||
   localparam compat_num = {16'd9, 16'd1}; //major, minor
 | 
					   localparam compat_num = {16'd9, 16'd2}; //major, minor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   wire [31:0] irq_readback = {16'b0, aux_ld2, aux_ld1, button, spi_ready, 12'b0};
 | 
					   wire [31:0] irq_readback = {16'b0, aux_ld2, aux_ld1, button, spi_ready, 12'b0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -456,7 +523,7 @@ module umtrx_core
 | 
				
			|||||||
     (.wb_clk_i(wb_clk), .wb_rst_i(wb_rst), .wb_stb_i(s5_stb),
 | 
					     (.wb_clk_i(wb_clk), .wb_rst_i(wb_rst), .wb_stb_i(s5_stb),
 | 
				
			||||||
      .wb_adr_i(s5_adr), .wb_dat_o(s5_dat_i), .wb_ack_o(s5_ack),
 | 
					      .wb_adr_i(s5_adr), .wb_dat_o(s5_dat_i), .wb_ack_o(s5_ack),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      .word00(spi_readback),.word01(`NUMDDC),.word02(`NUMDUC),.word03(32'b0),
 | 
					      .word00(spi_readback0),.word01(`NUMDDC),.word02(`NUMDUC),.word03(32'b0),
 | 
				
			||||||
      .word04(32'b0),.word05(32'b0),.word06(32'b0),.word07(32'b0),
 | 
					      .word04(32'b0),.word05(32'b0),.word06(32'b0),.word07(32'b0),
 | 
				
			||||||
      .word08(status),.word09(32'b0),.word10(vita_time[63:32]),
 | 
					      .word08(status),.word09(32'b0),.word10(vita_time[63:32]),
 | 
				
			||||||
      .word11(vita_time[31:0]),.word12(compat_num),.word13(irq_readback),
 | 
					      .word11(vita_time[31:0]),.word12(compat_num),.word13(irq_readback),
 | 
				
			||||||
@@ -498,10 +565,6 @@ module umtrx_core
 | 
				
			|||||||
     (.clk_i(dsp_clk), .rst_i(dsp_rst), .set_stb_i(set_stb_dsp), .set_addr_i(set_addr_dsp), .set_data_i(set_data_dsp),
 | 
					     (.clk_i(dsp_clk), .rst_i(dsp_rst), .set_stb_i(set_stb_dsp), .set_addr_i(set_addr_dsp), .set_data_i(set_data_dsp),
 | 
				
			||||||
      .clk_o(fe_clk), .rst_o(fe_rst), .set_stb_o(set_stb_fe), .set_addr_o(set_addr_fe), .set_data_o(set_data_fe));
 | 
					      .clk_o(fe_clk), .rst_o(fe_rst), .set_stb_o(set_stb_fe), .set_addr_o(set_addr_fe), .set_data_o(set_data_fe));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   wire set_stb_dsp0, set_stb_dsp1;
 | 
					 | 
				
			||||||
   wire [31:0] set_data_dsp0, set_data_dsp1;
 | 
					 | 
				
			||||||
   wire [7:0] set_addr_dsp0, set_addr_dsp1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   //mux settings_bus_crossclock and settings_readback_bus_fifo_ctrl with prio
 | 
					   //mux settings_bus_crossclock and settings_readback_bus_fifo_ctrl with prio
 | 
				
			||||||
   assign set_stb_dsp = set_stb_dsp0 | set_stb_dsp1;
 | 
					   assign set_stb_dsp = set_stb_dsp0 | set_stb_dsp1;
 | 
				
			||||||
   assign set_addr_dsp = set_stb_dsp1? set_addr_dsp1 : set_addr_dsp0;
 | 
					   assign set_addr_dsp = set_stb_dsp1? set_addr_dsp1 : set_addr_dsp0;
 | 
				
			||||||
@@ -542,7 +605,7 @@ module umtrx_core
 | 
				
			|||||||
        .in_data(ctrl_data_dsp), .in_valid(ctrl_valid_dsp), .in_ready(ctrl_ready_dsp),
 | 
					        .in_data(ctrl_data_dsp), .in_valid(ctrl_valid_dsp), .in_ready(ctrl_ready_dsp),
 | 
				
			||||||
        .out_data(resp_data_dsp), .out_valid(resp_valid_dsp), .out_ready(resp_ready_dsp),
 | 
					        .out_data(resp_data_dsp), .out_valid(resp_valid_dsp), .out_ready(resp_ready_dsp),
 | 
				
			||||||
        .strobe(set_stb_dsp1), .addr(set_addr_dsp1), .data(set_data_dsp1),
 | 
					        .strobe(set_stb_dsp1), .addr(set_addr_dsp1), .data(set_data_dsp1),
 | 
				
			||||||
        .word00(spi_readback),.word01(32'b0),.word02(32'b0),.word03(32'b0),
 | 
					        .word00(spi_readback1),.word01(32'b0),.word02(32'b0),.word03(32'b0),
 | 
				
			||||||
        .word04(32'b0),.word05(32'b0),.word06(32'b0),.word07(32'b0),
 | 
					        .word04(32'b0),.word05(32'b0),.word06(32'b0),.word07(32'b0),
 | 
				
			||||||
        .word08(32'b0),.word09(32'b0),.word10(vita_time[63:32]),
 | 
					        .word08(32'b0),.word09(32'b0),.word10(vita_time[63:32]),
 | 
				
			||||||
        .word11(vita_time[31:0]),.word12(32'b0),.word13(irq_readback),
 | 
					        .word11(vita_time[31:0]),.word12(32'b0),.word13(irq_readback),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,6 +26,7 @@ project(UmTRX-UHD)
 | 
				
			|||||||
########################################################################
 | 
					########################################################################
 | 
				
			||||||
include(${PROJECT_SOURCE_DIR}/cmake/GetGitRevisionDescription.cmake)
 | 
					include(${PROJECT_SOURCE_DIR}/cmake/GetGitRevisionDescription.cmake)
 | 
				
			||||||
git_describe(UMTRX_VERSION --dirty)
 | 
					git_describe(UMTRX_VERSION --dirty)
 | 
				
			||||||
 | 
					string(REPLACE "g" "" UMTRX_VERSION ${UMTRX_VERSION}) #remove hash prefix g
 | 
				
			||||||
message(STATUS "UMTRX_VERSION: ${UMTRX_VERSION}")
 | 
					message(STATUS "UMTRX_VERSION: ${UMTRX_VERSION}")
 | 
				
			||||||
configure_file(
 | 
					configure_file(
 | 
				
			||||||
    "${CMAKE_CURRENT_SOURCE_DIR}/umtrx_version.in.hpp"
 | 
					    "${CMAKE_CURRENT_SOURCE_DIR}/umtrx_version.in.hpp"
 | 
				
			||||||
@@ -38,6 +39,7 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
 | 
				
			|||||||
########################################################################
 | 
					########################################################################
 | 
				
			||||||
list(APPEND UMTRX_SOURCES
 | 
					list(APPEND UMTRX_SOURCES
 | 
				
			||||||
    umtrx_impl.cpp
 | 
					    umtrx_impl.cpp
 | 
				
			||||||
 | 
					    umtrx_monitor.cpp
 | 
				
			||||||
    umtrx_io_impl.cpp
 | 
					    umtrx_io_impl.cpp
 | 
				
			||||||
    umtrx_find.cpp
 | 
					    umtrx_find.cpp
 | 
				
			||||||
    umtrx_iface.cpp
 | 
					    umtrx_iface.cpp
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,7 @@
 | 
				
			|||||||
#include <boost/thread.hpp>
 | 
					#include <boost/thread.hpp>
 | 
				
			||||||
#include <boost/array.hpp>
 | 
					#include <boost/array.hpp>
 | 
				
			||||||
#include <boost/math/special_functions/round.hpp>
 | 
					#include <boost/math/special_functions/round.hpp>
 | 
				
			||||||
 | 
					#include <boost/thread/recursive_mutex.hpp>
 | 
				
			||||||
#include <utility>
 | 
					#include <utility>
 | 
				
			||||||
#include <cmath>
 | 
					#include <cmath>
 | 
				
			||||||
#include <cfloat>
 | 
					#include <cfloat>
 | 
				
			||||||
@@ -154,11 +155,13 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    uhd::sensor_value_t get_rx_pll_locked()
 | 
					    uhd::sensor_value_t get_rx_pll_locked()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        return uhd::sensor_value_t("LO", lms.get_rx_pll_locked(), "locked", "unlocked");
 | 
					        return uhd::sensor_value_t("LO", lms.get_rx_pll_locked(), "locked", "unlocked");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uhd::sensor_value_t get_tx_pll_locked()
 | 
					    uhd::sensor_value_t get_tx_pll_locked()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        return uhd::sensor_value_t("LO", lms.get_tx_pll_locked(), "locked", "unlocked");
 | 
					        return uhd::sensor_value_t("LO", lms.get_tx_pll_locked(), "locked", "unlocked");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -214,17 +217,20 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    uint8_t get_tx_vga1dc_i_int(void)
 | 
					    uint8_t get_tx_vga1dc_i_int(void)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        return lms.get_tx_vga1dc_i_int();
 | 
					        return lms.get_tx_vga1dc_i_int();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t get_tx_vga1dc_q_int(void)
 | 
					    uint8_t get_tx_vga1dc_q_int(void)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return lms.get_tx_vga1dc_i_int();
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
 | 
					        return lms.get_tx_vga1dc_q_int();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    double set_freq(dboard_iface::unit_t unit, double f) {
 | 
					    double set_freq(dboard_iface::unit_t unit, double f) {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        if (verbosity>0) printf("lms6002d_ctrl_impl::set_freq(%f)\n", f);
 | 
					        if (verbosity>0) printf("lms6002d_ctrl_impl::set_freq(%f)\n", f);
 | 
				
			||||||
        unsigned ref_freq = _clock_rate;
 | 
					        unsigned ref_freq = _clock_rate;
 | 
				
			||||||
        double actual_freq = 0;
 | 
					        double actual_freq = 0;
 | 
				
			||||||
@@ -254,6 +260,7 @@ protected:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool set_enabled(dboard_iface::unit_t unit, bool en) {
 | 
					    bool set_enabled(dboard_iface::unit_t unit, bool en) {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        if (verbosity>0) printf("lms6002d_ctrl_impl::set_enabled(%d)\n", en);
 | 
					        if (verbosity>0) printf("lms6002d_ctrl_impl::set_enabled(%d)\n", en);
 | 
				
			||||||
        if (unit==dboard_iface::UNIT_RX) {
 | 
					        if (unit==dboard_iface::UNIT_RX) {
 | 
				
			||||||
            if (en)
 | 
					            if (en)
 | 
				
			||||||
@@ -271,6 +278,7 @@ protected:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    double set_rx_gain(double gain, const std::string &name) {
 | 
					    double set_rx_gain(double gain, const std::string &name) {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        if (verbosity>0) printf("lms6002d_ctrl_impl::set_rx_gain(%f, %s)\n", gain, name.c_str());
 | 
					        if (verbosity>0) printf("lms6002d_ctrl_impl::set_rx_gain(%f, %s)\n", gain, name.c_str());
 | 
				
			||||||
        assert_has(lms_rx_gain_ranges.keys(), name, "LMS6002D rx gain name");
 | 
					        assert_has(lms_rx_gain_ranges.keys(), name, "LMS6002D rx gain name");
 | 
				
			||||||
        if(name == "VGA1"){
 | 
					        if(name == "VGA1"){
 | 
				
			||||||
@@ -284,6 +292,7 @@ protected:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void set_rx_ant(const std::string &ant) {
 | 
					    void set_rx_ant(const std::string &ant) {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        if (verbosity>0) printf("lms6002d_ctrl_impl::set_rx_ant(%s)\n", ant.c_str());
 | 
					        if (verbosity>0) printf("lms6002d_ctrl_impl::set_rx_ant(%s)\n", ant.c_str());
 | 
				
			||||||
        //validate input
 | 
					        //validate input
 | 
				
			||||||
        assert_has(lms_rx_antennas, ant, "LMS6002D rx antenna name");
 | 
					        assert_has(lms_rx_antennas, ant, "LMS6002D rx antenna name");
 | 
				
			||||||
@@ -317,6 +326,7 @@ protected:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    double set_rx_bandwidth(double bandwidth) {
 | 
					    double set_rx_bandwidth(double bandwidth) {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        if (verbosity>0) printf("lms6002d_ctrl_impl::set_rx_bandwidth(%f)\n", bandwidth);
 | 
					        if (verbosity>0) printf("lms6002d_ctrl_impl::set_rx_bandwidth(%f)\n", bandwidth);
 | 
				
			||||||
        // Get the closest available bandwidth
 | 
					        // Get the closest available bandwidth
 | 
				
			||||||
        bandwidth = lms_bandwidth_range.clip(bandwidth);
 | 
					        bandwidth = lms_bandwidth_range.clip(bandwidth);
 | 
				
			||||||
@@ -328,6 +338,7 @@ protected:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    double set_tx_gain(double gain, const std::string &name) {
 | 
					    double set_tx_gain(double gain, const std::string &name) {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        if (verbosity>0) printf("lms6002d_ctrl_impl::set_tx_gain(%f, %s)\n", gain, name.c_str());
 | 
					        if (verbosity>0) printf("lms6002d_ctrl_impl::set_tx_gain(%f, %s)\n", gain, name.c_str());
 | 
				
			||||||
        //validate input
 | 
					        //validate input
 | 
				
			||||||
        assert_has(lms_tx_gain_ranges.keys(), name, "LMS6002D tx gain name");
 | 
					        assert_has(lms_tx_gain_ranges.keys(), name, "LMS6002D tx gain name");
 | 
				
			||||||
@@ -349,6 +360,7 @@ protected:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void set_tx_ant(const std::string &ant) {
 | 
					    void set_tx_ant(const std::string &ant) {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        if (verbosity>0) printf("lms6002d_ctrl_impl::set_tx_ant(%s)\n", ant.c_str());
 | 
					        if (verbosity>0) printf("lms6002d_ctrl_impl::set_tx_ant(%s)\n", ant.c_str());
 | 
				
			||||||
        //validate input
 | 
					        //validate input
 | 
				
			||||||
        assert_has(lms_tx_antennas, ant, "LMS6002D tx antenna ant");
 | 
					        assert_has(lms_tx_antennas, ant, "LMS6002D tx antenna ant");
 | 
				
			||||||
@@ -368,6 +380,7 @@ protected:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    double set_tx_bandwidth(double bandwidth) {
 | 
					    double set_tx_bandwidth(double bandwidth) {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        if (verbosity>0) printf("lms6002d_ctrl_impl::set_tx_bandwidth(%f)\n", bandwidth);
 | 
					        if (verbosity>0) printf("lms6002d_ctrl_impl::set_tx_bandwidth(%f)\n", bandwidth);
 | 
				
			||||||
        // Get the closest available bandwidth
 | 
					        // Get the closest available bandwidth
 | 
				
			||||||
        bandwidth = lms_bandwidth_range.clip(bandwidth);
 | 
					        bandwidth = lms_bandwidth_range.clip(bandwidth);
 | 
				
			||||||
@@ -379,12 +392,14 @@ protected:
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t _set_tx_vga1dc_i_int(uint8_t offset) {
 | 
					    uint8_t _set_tx_vga1dc_i_int(uint8_t offset) {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        if (verbosity>0) printf("lms6002d_ctrl_impl::set_tx_vga1dc_i_int(%d)\n", offset);
 | 
					        if (verbosity>0) printf("lms6002d_ctrl_impl::set_tx_vga1dc_i_int(%d)\n", offset);
 | 
				
			||||||
        lms.set_tx_vga1dc_i_int(offset);
 | 
					        lms.set_tx_vga1dc_i_int(offset);
 | 
				
			||||||
        return offset;
 | 
					        return offset;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t _set_tx_vga1dc_q_int(uint8_t offset) {
 | 
					    uint8_t _set_tx_vga1dc_q_int(uint8_t offset) {
 | 
				
			||||||
 | 
					        boost::recursive_mutex::scoped_lock l(_mutex);
 | 
				
			||||||
        if (verbosity>0) printf("lms6002d_ctrl_impl::set_tx_vga1dc_q_int(%d)\n", offset);
 | 
					        if (verbosity>0) printf("lms6002d_ctrl_impl::set_tx_vga1dc_q_int(%d)\n", offset);
 | 
				
			||||||
        lms.set_tx_vga1dc_q_int(offset);
 | 
					        lms.set_tx_vga1dc_q_int(offset);
 | 
				
			||||||
        return offset;
 | 
					        return offset;
 | 
				
			||||||
@@ -402,6 +417,8 @@ private:
 | 
				
			|||||||
    const int _lms_spi_number;
 | 
					    const int _lms_spi_number;
 | 
				
			||||||
    const int _adf4350_spi_number;
 | 
					    const int _adf4350_spi_number;
 | 
				
			||||||
    const double _clock_rate;
 | 
					    const double _clock_rate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    boost::recursive_mutex _mutex;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lms6002d_ctrl::sptr lms6002d_ctrl::make(uhd::spi_iface::sptr spiface, const int lms_spi_number, const int adf4350_spi_number, const double clock_rate)
 | 
					lms6002d_ctrl::sptr lms6002d_ctrl::make(uhd::spi_iface::sptr spiface, const int lms_spi_number, const int adf4350_spi_number, const double clock_rate)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,6 +69,18 @@ static const double _dcdc_val_to_volt_init[256] =
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
const std::vector<double> umtrx_impl::_dcdc_val_to_volt(_dcdc_val_to_volt_init, &_dcdc_val_to_volt_init[256]);
 | 
					const std::vector<double> umtrx_impl::_dcdc_val_to_volt(_dcdc_val_to_volt_init, &_dcdc_val_to_volt_init[256]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/***********************************************************************
 | 
				
			||||||
 | 
					 * Property tree "alias" function
 | 
				
			||||||
 | 
					 **********************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					template <typename T> property<T> &property_alias(uhd::property_tree::sptr &_tree,
 | 
				
			||||||
 | 
					                                                  const uhd::fs_path &orig, const uhd::fs_path &alias)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // By default route each chanel to its own antenna
 | 
				
			||||||
 | 
					    return _tree->create<T>(alias)
 | 
				
			||||||
 | 
					        .subscribe(boost::bind(&uhd::property<T>::set, boost::ref(_tree->access<T>(orig)), _1))
 | 
				
			||||||
 | 
					        .publish(boost::bind(&uhd::property<T>::get, boost::ref(_tree->access<T>(orig))));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/***********************************************************************
 | 
					/***********************************************************************
 | 
				
			||||||
 * Make
 | 
					 * Make
 | 
				
			||||||
@@ -258,12 +270,27 @@ umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
 | 
				
			|||||||
    _tree->create<std::string>(mb_path / "hwrev").set(get_hw_rev());
 | 
					    _tree->create<std::string>(mb_path / "hwrev").set(get_hw_rev());
 | 
				
			||||||
    UHD_MSG(status) << "Detected UmTRX " << get_hw_rev() << std::endl;
 | 
					    UHD_MSG(status) << "Detected UmTRX " << get_hw_rev() << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					    // configure diversity switches
 | 
				
			||||||
 | 
					    ////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // note: the control is also aliased to RF frontend later
 | 
				
			||||||
    _tree->create<bool>(mb_path / "divsw1")
 | 
					    _tree->create<bool>(mb_path / "divsw1")
 | 
				
			||||||
            .subscribe(boost::bind(&umtrx_impl::set_divsw1, this, _1));
 | 
					            .subscribe(boost::bind(&umtrx_impl::set_diversity, this, _1, 0))
 | 
				
			||||||
 | 
					            .set(device_addr.cast<bool>("divsw1", false));
 | 
				
			||||||
 | 
					    UHD_MSG(status) << "Diversity switch for channel 1: "
 | 
				
			||||||
 | 
					                    << (_tree->access<bool>(mb_path / "divsw1").get()?"true":"false")
 | 
				
			||||||
 | 
					                    << std::endl;
 | 
				
			||||||
    _tree->create<bool>(mb_path / "divsw2")
 | 
					    _tree->create<bool>(mb_path / "divsw2")
 | 
				
			||||||
            .subscribe(boost::bind(&umtrx_impl::set_divsw2, this, _1));
 | 
					            .subscribe(boost::bind(&umtrx_impl::set_diversity, this, _1, 1))
 | 
				
			||||||
 | 
					            .set(device_addr.cast<bool>("divsw2", false));
 | 
				
			||||||
 | 
					    UHD_MSG(status) << "Diversity switch for channel 2: "
 | 
				
			||||||
 | 
					                    << (_tree->access<bool>(mb_path / "divsw2").get()?"true":"false")
 | 
				
			||||||
 | 
					                    << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					    // set PLL divider
 | 
				
			||||||
 | 
					    ////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO: Add EEPROM cell to manually override this
 | 
					    // TODO: Add EEPROM cell to manually override this
 | 
				
			||||||
    _pll_div = 1;
 | 
					    _pll_div = 1;
 | 
				
			||||||
@@ -619,6 +646,9 @@ umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
 | 
				
			|||||||
            .publish(boost::bind(&umtrx_impl::get_dc_offset_correction, this, fe_name))
 | 
					            .publish(boost::bind(&umtrx_impl::get_dc_offset_correction, this, fe_name))
 | 
				
			||||||
            .subscribe(boost::bind(&umtrx_impl::set_dc_offset_correction, this, fe_name, _1))
 | 
					            .subscribe(boost::bind(&umtrx_impl::set_dc_offset_correction, this, fe_name, _1))
 | 
				
			||||||
            .set(std::complex<double>(dc_i, dc_q));
 | 
					            .set(std::complex<double>(dc_i, dc_q));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Alias diversity switch control from mb_path
 | 
				
			||||||
 | 
					        property_alias<bool>(_tree, mb_path / "divsw"+(fe_name=="A"?"1":"2"), rx_rf_fe_path / "diversity");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //set TCXO DAC calibration value, which is read from mboard EEPROM
 | 
					    //set TCXO DAC calibration value, which is read from mboard EEPROM
 | 
				
			||||||
@@ -659,10 +689,15 @@ umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    _tree->access<std::string>(mb_path / "clock_source" / "value").set("internal");
 | 
					    _tree->access<std::string>(mb_path / "clock_source" / "value").set("internal");
 | 
				
			||||||
    _tree->access<std::string>(mb_path / "time_source" / "value").set("none");
 | 
					    _tree->access<std::string>(mb_path / "time_source" / "value").set("none");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //create status monitor and client handler
 | 
				
			||||||
 | 
					    this->status_monitor_start(device_addr);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
umtrx_impl::~umtrx_impl(void)
 | 
					umtrx_impl::~umtrx_impl(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    this->status_monitor_stop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    BOOST_FOREACH(const std::string &fe_name, _lms_ctrl.keys())
 | 
					    BOOST_FOREACH(const std::string &fe_name, _lms_ctrl.keys())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        lms6002d_ctrl::sptr ctrl = _lms_ctrl[fe_name];
 | 
					        lms6002d_ctrl::sptr ctrl = _lms_ctrl[fe_name];
 | 
				
			||||||
@@ -687,6 +722,7 @@ int umtrx_impl::volt_to_dcdc_r(double v)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void umtrx_impl::set_pa_dcdc_r(uint8_t val)
 | 
					void umtrx_impl::set_pa_dcdc_r(uint8_t val)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    boost::recursive_mutex::scoped_lock l(_i2c_mutex);
 | 
				
			||||||
    // AD5245 control
 | 
					    // AD5245 control
 | 
				
			||||||
    if (_hw_rev >= UMTRX_VER_2_3_1)
 | 
					    if (_hw_rev >= UMTRX_VER_2_3_1)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -744,6 +780,7 @@ double umtrx_impl::set_tx_power(double power, const std::string &which)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
double umtrx_impl::set_pa_power(double power, const std::string &which)
 | 
					double umtrx_impl::set_pa_power(double power, const std::string &which)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    boost::recursive_mutex::scoped_lock l(_i2c_mutex);
 | 
				
			||||||
    // TODO:: Use DCDC bypass for maximum output power
 | 
					    // TODO:: Use DCDC bypass for maximum output power
 | 
				
			||||||
    // TODO:: Limit output power for UmSITE-TM3
 | 
					    // TODO:: Limit output power for UmSITE-TM3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -771,6 +808,7 @@ double umtrx_impl::set_pa_power(double power, const std::string &which)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void umtrx_impl::set_mb_eeprom(const uhd::i2c_iface::sptr &iface, const uhd::usrp::mboard_eeprom_t &eeprom)
 | 
					void umtrx_impl::set_mb_eeprom(const uhd::i2c_iface::sptr &iface, const uhd::usrp::mboard_eeprom_t &eeprom)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    boost::recursive_mutex::scoped_lock l(_i2c_mutex);
 | 
				
			||||||
    store_umtrx_eeprom(eeprom, *iface);
 | 
					    store_umtrx_eeprom(eeprom, *iface);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -835,6 +873,7 @@ uint8_t umtrx_impl::dc_offset_double2int(double corr)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
uhd::sensor_value_t umtrx_impl::read_temp_c(const std::string &which)
 | 
					uhd::sensor_value_t umtrx_impl::read_temp_c(const std::string &which)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    boost::recursive_mutex::scoped_lock l(_i2c_mutex);
 | 
				
			||||||
    double temp = (which == "A") ? _temp_side_a.get_temp() :
 | 
					    double temp = (which == "A") ? _temp_side_a.get_temp() :
 | 
				
			||||||
                                   _temp_side_b.get_temp();
 | 
					                                   _temp_side_b.get_temp();
 | 
				
			||||||
    return uhd::sensor_value_t("Temp"+which, temp, "C");
 | 
					    return uhd::sensor_value_t("Temp"+which, temp, "C");
 | 
				
			||||||
@@ -842,6 +881,7 @@ uhd::sensor_value_t umtrx_impl::read_temp_c(const std::string &which)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
uhd::sensor_value_t umtrx_impl::read_pa_v(const std::string &which)
 | 
					uhd::sensor_value_t umtrx_impl::read_pa_v(const std::string &which)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    boost::recursive_mutex::scoped_lock l(_i2c_mutex);
 | 
				
			||||||
    unsigned i;
 | 
					    unsigned i;
 | 
				
			||||||
    for (i = 0; i < 4; i++) {
 | 
					    for (i = 0; i < 4; i++) {
 | 
				
			||||||
        if (which == power_sensors[i])
 | 
					        if (which == power_sensors[i])
 | 
				
			||||||
@@ -857,6 +897,7 @@ uhd::sensor_value_t umtrx_impl::read_pa_v(const std::string &which)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
uhd::sensor_value_t umtrx_impl::read_dc_v(const std::string &which)
 | 
					uhd::sensor_value_t umtrx_impl::read_dc_v(const std::string &which)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    boost::recursive_mutex::scoped_lock l(_i2c_mutex);
 | 
				
			||||||
    unsigned i;
 | 
					    unsigned i;
 | 
				
			||||||
    for (i = 0; i < 4; i++) {
 | 
					    for (i = 0; i < 4; i++) {
 | 
				
			||||||
        if (which == dc_sensors[i])
 | 
					        if (which == dc_sensors[i])
 | 
				
			||||||
@@ -1002,14 +1043,11 @@ void umtrx_impl::set_nlow(bool en)
 | 
				
			|||||||
    _pa_nlow = en; commit_pa_state();
 | 
					    _pa_nlow = en; commit_pa_state();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void umtrx_impl::set_divsw1(bool en)
 | 
					void umtrx_impl::set_diversity(bool en, int chan)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    _iface->poke32(U2_REG_SR_ADDR(SR_DIVSW+0), (en) ? 1 : 0);
 | 
					    // chan 0 has inversed switch polarity
 | 
				
			||||||
}
 | 
					    // chan 1 has straight switch polarity
 | 
				
			||||||
 | 
					    _iface->poke32(U2_REG_SR_ADDR(SR_DIVSW+chan), (en != (chan==1)) ? 0 : 1);
 | 
				
			||||||
void umtrx_impl::set_divsw2(bool en)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    _iface->poke32(U2_REG_SR_ADDR(SR_DIVSW+1), (en) ? 1 : 0);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char* umtrx_impl::get_hw_rev() const
 | 
					const char* umtrx_impl::get_hw_rev() const
 | 
				
			||||||
@@ -1023,4 +1061,3 @@ const char* umtrx_impl::get_hw_rev() const
 | 
				
			|||||||
    default:               return "[unknown]";
 | 
					    default:               return "[unknown]";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,6 +48,8 @@
 | 
				
			|||||||
#include <uhd/transport/udp_simple.hpp>
 | 
					#include <uhd/transport/udp_simple.hpp>
 | 
				
			||||||
#include <uhd/transport/udp_zero_copy.hpp>
 | 
					#include <uhd/transport/udp_zero_copy.hpp>
 | 
				
			||||||
#include <uhd/transport/bounded_buffer.hpp>
 | 
					#include <uhd/transport/bounded_buffer.hpp>
 | 
				
			||||||
 | 
					#include <boost/thread/recursive_mutex.hpp>
 | 
				
			||||||
 | 
					#include <boost/property_tree/json_parser.hpp>
 | 
				
			||||||
#include <uhd/types/ranges.hpp>
 | 
					#include <uhd/types/ranges.hpp>
 | 
				
			||||||
#include <uhd/exception.hpp>
 | 
					#include <uhd/exception.hpp>
 | 
				
			||||||
#include <uhd/utils/static.hpp>
 | 
					#include <uhd/utils/static.hpp>
 | 
				
			||||||
@@ -58,6 +60,7 @@
 | 
				
			|||||||
#include <boost/weak_ptr.hpp>
 | 
					#include <boost/weak_ptr.hpp>
 | 
				
			||||||
#include <boost/asio.hpp>
 | 
					#include <boost/asio.hpp>
 | 
				
			||||||
#include <boost/thread/mutex.hpp>
 | 
					#include <boost/thread/mutex.hpp>
 | 
				
			||||||
 | 
					#include <uhd/utils/tasks.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Halfthe size of USRP2 SRAM, because we split the same SRAM into buffers for two Tx channels instead of one.
 | 
					// Halfthe size of USRP2 SRAM, because we split the same SRAM into buffers for two Tx channels instead of one.
 | 
				
			||||||
@@ -182,8 +185,7 @@ private:
 | 
				
			|||||||
    void set_enpa1(bool en);
 | 
					    void set_enpa1(bool en);
 | 
				
			||||||
    void set_enpa2(bool en);
 | 
					    void set_enpa2(bool en);
 | 
				
			||||||
    void set_nlow(bool en);
 | 
					    void set_nlow(bool en);
 | 
				
			||||||
    void set_divsw1(bool en);
 | 
					    void set_diversity(bool en, int chan);
 | 
				
			||||||
    void set_divsw2(bool en);
 | 
					 | 
				
			||||||
    uhd::gain_range_t generate_tx_power_range(const std::string &which) const;
 | 
					    uhd::gain_range_t generate_tx_power_range(const std::string &which) const;
 | 
				
			||||||
    uhd::gain_range_t generate_pa_power_range(const std::string &which) const;
 | 
					    uhd::gain_range_t generate_pa_power_range(const std::string &which) const;
 | 
				
			||||||
    const uhd::gain_range_t &get_tx_power_range(const std::string &which) const;
 | 
					    const uhd::gain_range_t &get_tx_power_range(const std::string &which) const;
 | 
				
			||||||
@@ -201,6 +203,21 @@ private:
 | 
				
			|||||||
    uhd::sensor_value_t read_temp_c(const std::string &which);
 | 
					    uhd::sensor_value_t read_temp_c(const std::string &which);
 | 
				
			||||||
    uhd::sensor_value_t read_pa_v(const std::string &which);
 | 
					    uhd::sensor_value_t read_pa_v(const std::string &which);
 | 
				
			||||||
    uhd::sensor_value_t read_dc_v(const std::string &which);
 | 
					    uhd::sensor_value_t read_dc_v(const std::string &which);
 | 
				
			||||||
 | 
					    boost::recursive_mutex _i2c_mutex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //status monitoring
 | 
				
			||||||
 | 
					    void status_monitor_start(const uhd::device_addr_t &device_addr);
 | 
				
			||||||
 | 
					    void status_monitor_stop(void);
 | 
				
			||||||
 | 
					    uhd::task::sptr _status_monitor_task;
 | 
				
			||||||
 | 
					    void status_monitor_handler(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //tcp query server
 | 
				
			||||||
 | 
					    uhd::task::sptr _server_query_task;
 | 
				
			||||||
 | 
					    void server_query_handler(void);
 | 
				
			||||||
 | 
					    boost::asio::io_service _server_query_io_service;
 | 
				
			||||||
 | 
					    boost::shared_ptr<boost::asio::ip::tcp::acceptor> _server_query_tcp_acceptor;
 | 
				
			||||||
 | 
					    void client_query_handle(boost::shared_ptr<boost::asio::ip::tcp::socket>);
 | 
				
			||||||
 | 
					    void client_query_handle1(const boost::property_tree::ptree &request, boost::property_tree::ptree &response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //streaming
 | 
					    //streaming
 | 
				
			||||||
    std::vector<boost::weak_ptr<uhd::rx_streamer> > _rx_streamers;
 | 
					    std::vector<boost::weak_ptr<uhd::rx_streamer> > _rx_streamers;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										246
									
								
								host/umtrx_monitor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								host/umtrx_monitor.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,246 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Copyright 2015-2015 Fairwaves LLC
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// (at your option) any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "umtrx_impl.hpp"
 | 
				
			||||||
 | 
					#include <uhd/utils/msg.hpp>
 | 
				
			||||||
 | 
					#include <uhd/types/sensors.hpp>
 | 
				
			||||||
 | 
					#include <uhd/types/ranges.hpp>
 | 
				
			||||||
 | 
					#include <boost/asio.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace uhd;
 | 
				
			||||||
 | 
					using namespace uhd::usrp;
 | 
				
			||||||
 | 
					namespace asio = boost::asio;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * Querying sensors using the status monitor server.
 | 
				
			||||||
 | 
					 * Requests are encoded in JSON and end in a newline.
 | 
				
			||||||
 | 
					 * Responses are encoded in JSON and end in a newline.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Start UmTRX driver with status_port set in args
 | 
				
			||||||
 | 
					 * ./some_application --args="status_port=12345"
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * import json
 | 
				
			||||||
 | 
					 * import socket
 | 
				
			||||||
 | 
					 * s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
				
			||||||
 | 
					 * s.connect(("localhost", 12345))
 | 
				
			||||||
 | 
					 * f = s.makefile() #gives us readline()
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * #list branches in the property tree
 | 
				
			||||||
 | 
					 * s.send(json.dumps(dict(action='LIST', path='/mboards/0/sensors'))+'\n')
 | 
				
			||||||
 | 
					 * print json.loads(f.readline())
 | 
				
			||||||
 | 
					 * {u'result': [u'tempA']}
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * #check if the specified path exists
 | 
				
			||||||
 | 
					 * s.send(json.dumps(dict(action='HAS', path='/mboards/0/sensors/tempA'))+'\n')
 | 
				
			||||||
 | 
					 * print json.loads(f.readline())
 | 
				
			||||||
 | 
					 * {u'result': u'true'}
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * #get the value of a tree entry, types can be BOOL, INT, DOUBLE, SENSOR, RANGE
 | 
				
			||||||
 | 
					 * s.send(json.dumps(dict(action='GET', path='/mboards/0/sensors/tempA', type='SENSOR'))+'\n')
 | 
				
			||||||
 | 
					 * print json.loads(f.readline())
 | 
				
			||||||
 | 
					 * {u'result': {u'unit': u'C', u'name': u'TempA', u'value': u'61.625000'}}
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * #set the value of a tree entry, types can be BOOL, INT, DOUBLE
 | 
				
			||||||
 | 
					 * s.send(json.dumps(dict(action='SET', path='/mboards/0/dboards/A/rx_frontends/0/freq/value', type='DOUBLE', value=1e9))+'\n')
 | 
				
			||||||
 | 
					 * print json.loads(f.readline())
 | 
				
			||||||
 | 
					 * {} #empty response means no error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void umtrx_impl::status_monitor_start(const uhd::device_addr_t &device_addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (device_addr.has_key("status_port"))
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        UHD_MSG(status) << "Creating TCP monitor on port " << device_addr.get("status_port") << std::endl;
 | 
				
			||||||
 | 
					        _server_query_tcp_acceptor.reset(new asio::ip::tcp::acceptor(
 | 
				
			||||||
 | 
					            _server_query_io_service, asio::ip::tcp::endpoint(asio::ip::tcp::v4(), device_addr.cast<int>("status_port", 0))));
 | 
				
			||||||
 | 
					        _server_query_task = task::make(boost::bind(&umtrx_impl::server_query_handler, this));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    _status_monitor_task = task::make(boost::bind(&umtrx_impl::status_monitor_handler, this));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void umtrx_impl::status_monitor_stop(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _status_monitor_task.reset();
 | 
				
			||||||
 | 
					    _server_query_task.reset();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool wait_read_sockfd(const int sockfd, const size_t timeoutMs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //setup timeval for timeout
 | 
				
			||||||
 | 
					    timeval tv;
 | 
				
			||||||
 | 
					    tv.tv_sec = 0;
 | 
				
			||||||
 | 
					    tv.tv_usec = timeoutMs*1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //setup rset for timeout
 | 
				
			||||||
 | 
					    fd_set rset;
 | 
				
			||||||
 | 
					    FD_ZERO(&rset);
 | 
				
			||||||
 | 
					    FD_SET(sockfd, &rset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //call select with timeout on receive socket
 | 
				
			||||||
 | 
					    return ::select(sockfd+1, &rset, NULL, NULL, &tv) > 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void umtrx_impl::status_monitor_handler(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //TODO read the sensors and react...
 | 
				
			||||||
 | 
					    //read_dc_v, etc...
 | 
				
			||||||
 | 
					    //UHD_MSG(status) << this->read_temp_c("A").to_pp_string() << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //TODO shutdown frontend when temp > thresh
 | 
				
			||||||
 | 
					    //ctrl->set_rx_enabled(false);
 | 
				
			||||||
 | 
					    //ctrl->set_tx_enabled(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //this sleep defines the polling time between status checks
 | 
				
			||||||
 | 
					    //when the handler completes, it will be called again asap
 | 
				
			||||||
 | 
					    //if the task is canceled, this sleep in interrupted for exit
 | 
				
			||||||
 | 
					    boost::this_thread::sleep(boost::posix_time::milliseconds(1500));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void umtrx_impl::server_query_handler(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //accept the client socket (timeout is 100 ms, task is called again)
 | 
				
			||||||
 | 
					    if (not wait_read_sockfd(_server_query_tcp_acceptor->native(), 100)) return;
 | 
				
			||||||
 | 
					    boost::shared_ptr<asio::ip::tcp::socket> socket(new asio::ip::tcp::socket(_server_query_io_service));
 | 
				
			||||||
 | 
					    _server_query_tcp_acceptor->accept(*socket);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //create a new thread to handle the client
 | 
				
			||||||
 | 
					    boost::thread handler(boost::bind(&umtrx_impl::client_query_handle, this, socket));
 | 
				
			||||||
 | 
					    handler.detach();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void umtrx_impl::client_query_handle(boost::shared_ptr<boost::asio::ip::tcp::socket> socket)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    while (not boost::this_thread::interruption_requested())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        boost::property_tree::ptree request, response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //receive the request in JSON markup
 | 
				
			||||||
 | 
					        boost::asio::streambuf requestBuff;
 | 
				
			||||||
 | 
					        try
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boost::asio::read_until(*socket, requestBuff, "\n");
 | 
				
			||||||
 | 
					            std::istream is(&requestBuff);
 | 
				
			||||||
 | 
					            boost::property_tree::read_json(is, request);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch (const std::exception &ex)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (requestBuff.size() == 0) return; //client ended
 | 
				
			||||||
 | 
					            response.put("error", "request parser error: " + std::string(ex.what()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //handle the request
 | 
				
			||||||
 | 
					        try
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this->client_query_handle1(request, response);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch (const std::exception &ex)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            response.put("error", "failed to handle request: " + std::string(ex.what()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //send the response
 | 
				
			||||||
 | 
					        boost::asio::streambuf responseBuff;
 | 
				
			||||||
 | 
					        std::ostream os(&responseBuff);
 | 
				
			||||||
 | 
					        try
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boost::property_tree::write_json(os, response, false/*not pretty required*/);
 | 
				
			||||||
 | 
					            boost::asio::write(*socket, responseBuff);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        catch (const std::exception &ex)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            UHD_MSG(error) << "client_query_handle send response failed, exit client thread: " << ex.what() << std::endl;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void umtrx_impl::client_query_handle1(const boost::property_tree::ptree &request, boost::property_tree::ptree &response)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const std::string action = request.get("action", "");
 | 
				
			||||||
 | 
					    const std::string path = request.get("path", "");
 | 
				
			||||||
 | 
					    if (response.count("error") != 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        //already in error
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (path.empty())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        response.put("error", "path field not specified");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (action.empty())
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        response.put("error", "action field not specified: GET, SET, HAS, LIST");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (action == "GET")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string type = request.get("type", "");
 | 
				
			||||||
 | 
					        if (type.empty()) response.put("error", "type field not specified: BOOL, INT, DOUBLE, SENSOR, RANGE");
 | 
				
			||||||
 | 
					        else if (type == "BOOL") response.put("result", _tree->access<bool>(path).get());
 | 
				
			||||||
 | 
					        else if (type == "INT") response.put("result", _tree->access<int>(path).get());
 | 
				
			||||||
 | 
					        else if (type == "DOUBLE") response.put("result", _tree->access<double>(path).get());
 | 
				
			||||||
 | 
					        else if (type == "SENSOR")
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boost::property_tree::ptree result;
 | 
				
			||||||
 | 
					            const sensor_value_t sensor = _tree->access<sensor_value_t>(path).get();
 | 
				
			||||||
 | 
					            result.put("name", sensor.name);
 | 
				
			||||||
 | 
					            result.put("value", sensor.value);
 | 
				
			||||||
 | 
					            result.put("unit", sensor.unit);
 | 
				
			||||||
 | 
					            response.add_child("result", result);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (type == "RANGE")
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boost::property_tree::ptree result;
 | 
				
			||||||
 | 
					            BOOST_FOREACH(const range_t &range, _tree->access<meta_range_t>(path).get())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                boost::property_tree::ptree rangeData;
 | 
				
			||||||
 | 
					                rangeData.put("start", range.start());
 | 
				
			||||||
 | 
					                rangeData.put("stop", range.stop());
 | 
				
			||||||
 | 
					                rangeData.put("step", range.step());
 | 
				
			||||||
 | 
					                result.push_back(std::make_pair("", rangeData));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            response.add_child("result", result);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else response.put("error", "unknown type: " + type);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (action == "SET")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        const std::string type = request.get("type", "");
 | 
				
			||||||
 | 
					        if (type.empty()) response.put("error", "type field not specified: BOOL, INT, DOUBLE");
 | 
				
			||||||
 | 
					        else if (type == "BOOL") _tree->access<bool>(path).set(request.get<bool>("value"));
 | 
				
			||||||
 | 
					        else if (type == "INT") _tree->access<int>(path).set(request.get<int>("value"));
 | 
				
			||||||
 | 
					        else if (type == "DOUBLE") _tree->access<double>(path).set(request.get<double>("value"));
 | 
				
			||||||
 | 
					        else response.put("error", "unknown type: " + type);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (action == "HAS")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        response.put("result", _tree->exists(path));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (action == "LIST")
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        boost::property_tree::ptree result;
 | 
				
			||||||
 | 
					        BOOST_FOREACH(const std::string &branchName, _tree->list(path))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            boost::property_tree::ptree branchData;
 | 
				
			||||||
 | 
					            branchData.put("", branchName);
 | 
				
			||||||
 | 
					            result.push_back(std::make_pair("", branchData));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        response.add_child("result", result);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        response.put("error", "unknown action: " + action);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -6,6 +6,7 @@ INSTALL(PROGRAMS
 | 
				
			|||||||
    umtrx_nmea
 | 
					    umtrx_nmea
 | 
				
			||||||
    umtrx_gps_coord
 | 
					    umtrx_gps_coord
 | 
				
			||||||
    umtrx_auto_calibration
 | 
					    umtrx_auto_calibration
 | 
				
			||||||
 | 
					    umtrx_firmware
 | 
				
			||||||
    DESTINATION bin
 | 
					    DESTINATION bin
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,14 +2,23 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
if [ "$#" -lt "1" ] ; then
 | 
					if [ "$#" -lt "1" ] ; then
 | 
				
			||||||
  echo "Automatic calibration of an UmTRX for a set of given presets (bands)."
 | 
					  echo "Automatic calibration of an UmTRX for a set of given presets (bands)."
 | 
				
			||||||
  echo "Calibrations to be performed:"
 | 
					 | 
				
			||||||
  echo "  - Tx DC offset calibration"
 | 
					 | 
				
			||||||
  echo "  - Tx IQ balance calibration"
 | 
					 | 
				
			||||||
  echo
 | 
					  echo
 | 
				
			||||||
  echo "Usage:"
 | 
					  echo "Usage:"
 | 
				
			||||||
  echo "  umtrx_cal <preset> [<preset>] [<preset>] ..."
 | 
					  echo "  umtrx_cal <preset> [<preset>] [<preset>] ..."
 | 
				
			||||||
  echo
 | 
					  echo
 | 
				
			||||||
  echo "  preset - GSM850, EGSM900 (same as GSM900), GSM1800 (same as DCS1800), GSM1900 (same as PCS1900)."
 | 
					  echo "  preset - GSM850, EGSM900 (same as GSM900), GSM1800 (same as DCS1800), GSM1900 (same as PCS1900)."
 | 
				
			||||||
 | 
					  echo
 | 
				
			||||||
 | 
					  echo "Calibrations to be performed:"
 | 
				
			||||||
 | 
					  echo "  - Tx DC offset calibration"
 | 
				
			||||||
 | 
					  echo "  - Tx IQ balance calibration"
 | 
				
			||||||
 | 
					  echo
 | 
				
			||||||
 | 
					  echo "The result of the calibration is stored in the DIR/.uhd/cal/ directory. DIR is one of the \$APPDATA, \$HOME and /tmp,"
 | 
				
			||||||
 | 
					  echo "whichever is defined. Make sure you run calibration from the same user as the one who runs applications or define"
 | 
				
			||||||
 | 
					  echo "\$APPDATA or \$HOME appropriately. Calibration files will be loaded by the application automatically on startup."
 | 
				
			||||||
 | 
					  echo "Old calibration files are renamed when you run a calibration to avoid overwriting."
 | 
				
			||||||
 | 
					  echo
 | 
				
			||||||
 | 
					  echo "Calibration is permanent and only depends on temperature. If the temperature of the system is stable, you need to"
 | 
				
			||||||
 | 
					  echo "run the calibration only once."
 | 
				
			||||||
  exit 1
 | 
					  exit 1
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,12 +34,6 @@ run_cal() {
 | 
				
			|||||||
  freq_stop=$1 ; shift
 | 
					  freq_stop=$1 ; shift
 | 
				
			||||||
  other_args=$*
 | 
					  other_args=$*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  echo
 | 
					 | 
				
			||||||
  echo "------------------------------------------------------------------"
 | 
					 | 
				
			||||||
  echo "         Calibrating $what from $freq_start to $freq_stop"
 | 
					 | 
				
			||||||
  echo "------------------------------------------------------------------"
 | 
					 | 
				
			||||||
  echo
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  freq_step=$(python -c "print $freq_stop - $freq_start if $freq_stop != $freq_start else 1e3")
 | 
					  freq_step=$(python -c "print $freq_stop - $freq_start if $freq_stop != $freq_start else 1e3")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if [ "$what" = "dc" ] ; then
 | 
					  if [ "$what" = "dc" ] ; then
 | 
				
			||||||
@@ -43,12 +46,19 @@ run_cal() {
 | 
				
			|||||||
  fi
 | 
					  fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for side in $sides ; do
 | 
					  for side in $sides ; do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    echo
 | 
				
			||||||
 | 
					    echo "------------------------------------------------------------------"
 | 
				
			||||||
 | 
					    echo "       Calibrating $what from $freq_start to $freq_stop for side $side"
 | 
				
			||||||
 | 
					    echo "------------------------------------------------------------------"
 | 
				
			||||||
 | 
					    echo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    res=255
 | 
					    res=255
 | 
				
			||||||
    i=0
 | 
					    i=0
 | 
				
			||||||
    while [ $i -lt 10 -a $res -ne 0 ] ; do
 | 
					    while [ $i -lt 10 -a $res -ne 0 ] ; do
 | 
				
			||||||
      i=$(expr $i + 1)
 | 
					      i=$(expr $i + 1)
 | 
				
			||||||
      cmd_full="$cmd $uhd_args --freq_start $freq_start --freq_stop $freq_stop --freq_step $freq_step --which $side $other_args"
 | 
					      cmd_full="$cmd $uhd_args --freq_start $freq_start --freq_stop $freq_stop --freq_step $freq_step --which $side $other_args"
 | 
				
			||||||
      $echo $cmd_full
 | 
					      echo $cmd_full
 | 
				
			||||||
      $cmd_full
 | 
					      $cmd_full
 | 
				
			||||||
      res=$(echo $?)
 | 
					      res=$(echo $?)
 | 
				
			||||||
    done
 | 
					    done
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,10 +47,10 @@ public:
 | 
				
			|||||||
    void run_i(int dc_i);
 | 
					    void run_i(int dc_i);
 | 
				
			||||||
    void run_iq(int dc_i, int dc_q);
 | 
					    void run_iq(int dc_i, int dc_q);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void set_dc_i(double i) {_dc_i_prop.set(i);}
 | 
					    void set_dc_i(double i) {prop_set_check(_dc_i_prop, i);}
 | 
				
			||||||
    void set_dc_q(double q) {_dc_q_prop.set(q);}
 | 
					    void set_dc_q(double q) {prop_set_check(_dc_q_prop, q);}
 | 
				
			||||||
    void set_dc_i_best() {_dc_i_prop.set(_best_dc_i);}
 | 
					    void set_dc_i_best() {set_dc_i(_best_dc_i);}
 | 
				
			||||||
    void set_dc_q_best() {_dc_q_prop.set(_best_dc_q);}
 | 
					    void set_dc_q_best() {set_dc_q(_best_dc_q);}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    double get_lowest_offset() const {return _lowest_offset;}
 | 
					    double get_lowest_offset() const {return _lowest_offset;}
 | 
				
			||||||
    int get_best_dc_i() const {return _best_dc_i;}
 | 
					    int get_best_dc_i() const {return _best_dc_i;}
 | 
				
			||||||
@@ -71,6 +71,8 @@ protected:
 | 
				
			|||||||
    int _verbose;
 | 
					    int _verbose;
 | 
				
			||||||
    bool _debug_raw_data;
 | 
					    bool _debug_raw_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void prop_set_check(uhd::property<uint8_t> &prop, uint8_t val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    double get_dbrms();
 | 
					    double get_dbrms();
 | 
				
			||||||
    bool run_x();
 | 
					    bool run_x();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -97,8 +99,8 @@ dc_cal_t::dc_cal_t(uhd::property<uint8_t> &dc_i_prop, uhd::property<uint8_t> &dc
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
double dc_cal_t::init()
 | 
					double dc_cal_t::init()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    _dc_i_prop.set(_best_dc_i);
 | 
					    set_dc_i_best();
 | 
				
			||||||
    _dc_q_prop.set(_best_dc_q);
 | 
					    set_dc_q_best();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //get the DC offset tone size
 | 
					    //get the DC offset tone size
 | 
				
			||||||
    _lowest_offset = get_dbrms();
 | 
					    _lowest_offset = get_dbrms();
 | 
				
			||||||
@@ -112,7 +114,7 @@ double dc_cal_t::init()
 | 
				
			|||||||
void dc_cal_t::run_q(int dc_q)
 | 
					void dc_cal_t::run_q(int dc_q)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (_verbose) printf("      dc_q = %d", dc_q);
 | 
					    if (_verbose) printf("      dc_q = %d", dc_q);
 | 
				
			||||||
    _dc_q_prop.set(dc_q);
 | 
					    set_dc_q(dc_q);
 | 
				
			||||||
    if (run_x())
 | 
					    if (run_x())
 | 
				
			||||||
        _best_dc_q = dc_q;
 | 
					        _best_dc_q = dc_q;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -120,7 +122,7 @@ void dc_cal_t::run_q(int dc_q)
 | 
				
			|||||||
void dc_cal_t::run_i(int dc_i)
 | 
					void dc_cal_t::run_i(int dc_i)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (_verbose) printf("      dc_i = %d", dc_i);
 | 
					    if (_verbose) printf("      dc_i = %d", dc_i);
 | 
				
			||||||
    _dc_i_prop.set(dc_i);
 | 
					    set_dc_i(dc_i);
 | 
				
			||||||
    if (run_x())
 | 
					    if (run_x())
 | 
				
			||||||
        _best_dc_i = dc_i;
 | 
					        _best_dc_i = dc_i;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -128,14 +130,24 @@ void dc_cal_t::run_i(int dc_i)
 | 
				
			|||||||
void dc_cal_t::run_iq(int dc_i, int dc_q)
 | 
					void dc_cal_t::run_iq(int dc_i, int dc_q)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (_verbose) printf("      dc_i = %d dc_q = %d", dc_i, dc_q);
 | 
					    if (_verbose) printf("      dc_i = %d dc_q = %d", dc_i, dc_q);
 | 
				
			||||||
    _dc_i_prop.set(dc_i);
 | 
					    set_dc_i(dc_i);
 | 
				
			||||||
    _dc_q_prop.set(dc_q);
 | 
					    set_dc_q(dc_q);
 | 
				
			||||||
    if (run_x()) {
 | 
					    if (run_x()) {
 | 
				
			||||||
        _best_dc_i = dc_i;
 | 
					        _best_dc_i = dc_i;
 | 
				
			||||||
        _best_dc_q = dc_q;
 | 
					        _best_dc_q = dc_q;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void dc_cal_t::prop_set_check(uhd::property<uint8_t> &prop, uint8_t val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    prop.set(val);
 | 
				
			||||||
 | 
					    uint8_t val_read = prop.get();
 | 
				
			||||||
 | 
					    if (val_read != val)
 | 
				
			||||||
 | 
					        throw std::runtime_error(
 | 
				
			||||||
 | 
					            str(boost::format("Calibration property sets incorrectly. Requested %d, read back %d")
 | 
				
			||||||
 | 
					                          % int(val) % int(val_read)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
double dc_cal_t::get_dbrms()
 | 
					double dc_cal_t::get_dbrms()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    //receive some samples
 | 
					    //receive some samples
 | 
				
			||||||
@@ -292,7 +304,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
 | 
				
			|||||||
        ("which", po::value<std::string>(&which)->default_value("A"), "Which chain A or B?")
 | 
					        ("which", po::value<std::string>(&which)->default_value("A"), "Which chain A or B?")
 | 
				
			||||||
        ("vga1", po::value<int>(&vga1_gain)->default_value(-20), "LMS6002D Tx VGA1 gain [-35 to -4]")
 | 
					        ("vga1", po::value<int>(&vga1_gain)->default_value(-20), "LMS6002D Tx VGA1 gain [-35 to -4]")
 | 
				
			||||||
        ("vga2", po::value<int>(&vga2_gain)->default_value(22), "LMS6002D Tx VGA2 gain [0 to 25]")
 | 
					        ("vga2", po::value<int>(&vga2_gain)->default_value(22), "LMS6002D Tx VGA2 gain [0 to 25]")
 | 
				
			||||||
        ("rx_gain", po::value<int>(&rx_gain)->default_value(100), "LMS6002D Rx combined gain [0 to 156]")
 | 
					        ("rx_gain", po::value<int>(&rx_gain)->default_value(50), "LMS6002D Rx combined gain [0 to 156]")
 | 
				
			||||||
        ("tx_wave_freq", po::value<double>(&tx_wave_freq)->default_value(50e3), "Transmit wave frequency in Hz")
 | 
					        ("tx_wave_freq", po::value<double>(&tx_wave_freq)->default_value(50e3), "Transmit wave frequency in Hz")
 | 
				
			||||||
        ("tx_wave_ampl", po::value<double>(&tx_wave_ampl)->default_value(0.7), "Transmit wave amplitude in counts")
 | 
					        ("tx_wave_ampl", po::value<double>(&tx_wave_ampl)->default_value(0.7), "Transmit wave amplitude in counts")
 | 
				
			||||||
        ("rx_offset", po::value<double>(&rx_offset)->default_value(300e3), "RX LO offset from the TX LO in Hz")
 | 
					        ("rx_offset", po::value<double>(&rx_offset)->default_value(300e3), "RX LO offset from the TX LO in Hz")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
 | 
				
			|||||||
        ("which", po::value<std::string>(&which)->default_value("A"), "Which chain A or B?")
 | 
					        ("which", po::value<std::string>(&which)->default_value("A"), "Which chain A or B?")
 | 
				
			||||||
        ("vga1", po::value<int>(&vga1_gain)->default_value(-20), "LMS6002D Tx VGA1 gain [-35 to -4]")
 | 
					        ("vga1", po::value<int>(&vga1_gain)->default_value(-20), "LMS6002D Tx VGA1 gain [-35 to -4]")
 | 
				
			||||||
        ("vga2", po::value<int>(&vga2_gain)->default_value(22), "LMS6002D Tx VGA2 gain [0 to 25]")
 | 
					        ("vga2", po::value<int>(&vga2_gain)->default_value(22), "LMS6002D Tx VGA2 gain [0 to 25]")
 | 
				
			||||||
        ("rx_gain", po::value<int>(&rx_gain)->default_value(100), "LMS6002D Rx combined gain [0 to 156]")
 | 
					        ("rx_gain", po::value<int>(&rx_gain)->default_value(50), "LMS6002D Rx combined gain [0 to 156]")
 | 
				
			||||||
        ("tx_wave_freq", po::value<double>(&tx_wave_freq)->default_value(50e3), "Transmit wave frequency in Hz")
 | 
					        ("tx_wave_freq", po::value<double>(&tx_wave_freq)->default_value(50e3), "Transmit wave frequency in Hz")
 | 
				
			||||||
        ("tx_wave_ampl", po::value<double>(&tx_wave_ampl)->default_value(0.7), "Transmit wave amplitude in counts")
 | 
					        ("tx_wave_ampl", po::value<double>(&tx_wave_ampl)->default_value(0.7), "Transmit wave amplitude in counts")
 | 
				
			||||||
        ("rx_offset", po::value<double>(&rx_offset)->default_value(300e3), "RX LO offset from the TX LO in Hz")
 | 
					        ("rx_offset", po::value<double>(&rx_offset)->default_value(300e3), "RX LO offset from the TX LO in Hz")
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								host/utils/umtrx_firmware
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										16
									
								
								host/utils/umtrx_firmware
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case word in
 | 
				
			||||||
 | 
					    flash )
 | 
				
			||||||
 | 
					        umtrx_net_burner --addr=192.168.10.2 --fpga=/usr/share/umtrx/firmware/u2plus_umtrx_v2.bin --fw=/usr/share/umtrx/firmware/umtrx_txrx_uhd.bin --reset
 | 
				
			||||||
 | 
					        ;;
 | 
				
			||||||
 | 
					    check )
 | 
				
			||||||
 | 
					        ;;
 | 
				
			||||||
 | 
					    * )
 | 
				
			||||||
 | 
					        cat <<-EOF
 | 
				
			||||||
 | 
					        Usage:
 | 
				
			||||||
 | 
					        $0 flash  - burn packaged firmware to umtrx
 | 
				
			||||||
 | 
					        $0 check  - compare versions of packaged firmware and one installed on umtrx
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
					        ;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
@@ -114,10 +114,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (vm.count("divsw1")) {
 | 
					    if (vm.count("divsw1")) {
 | 
				
			||||||
        tree->access<bool>(mb_path / "divsw1").set(divsw1 ? 1 : 0);
 | 
					        tree->access<bool>(mb_path / "dboards" / "A" / "rx_frontends" / "0" / "diversiy").set(divsw1 ? 1 : 0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (vm.count("divsw2")) {
 | 
					    if (vm.count("divsw2")) {
 | 
				
			||||||
        tree->access<bool>(mb_path / "divsw2").set(divsw2 ? 1 : 0);
 | 
					        tree->access<bool>(mb_path / "dboards" / "B" / "rx_frontends" / "0" / "diversiy").set(divsw1 ? 1 : 0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										112
									
								
								host/utils/umtrx_property_tree.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								host/utils/umtrx_property_tree.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##########################
 | 
				
			||||||
 | 
					###  Property tree API
 | 
				
			||||||
 | 
					##########################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import socket
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class umtrx_property_tree:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def connect(self, host="localhost", port=12345):
 | 
				
			||||||
 | 
					    self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 | 
				
			||||||
 | 
					    self.s.connect((host, port))
 | 
				
			||||||
 | 
					    self.f = self.s.makefile()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def close(self):
 | 
				
			||||||
 | 
					    self.s.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					  # Helper methods
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def _send_request(self, action, path, value_type=None, value=None):
 | 
				
			||||||
 | 
					    d = dict(action=action, path=path)
 | 
				
			||||||
 | 
					    if value_type is not None: d['type'] = value_type
 | 
				
			||||||
 | 
					    if value is not None: d['value'] = value
 | 
				
			||||||
 | 
					    return self.s.send(json.dumps(d)+'\n')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def _recv_response(self):
 | 
				
			||||||
 | 
					    resp = self.f.readline().strip()
 | 
				
			||||||
 | 
					    if len(resp)>0:
 | 
				
			||||||
 | 
					      return json.loads(resp)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					      return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					  # Getters (raw)
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def query_bool_raw(self, path):
 | 
				
			||||||
 | 
					    self._send_request('GET', path, value_type='BOOL')
 | 
				
			||||||
 | 
					    return self._recv_response()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def query_int_raw(self, path):
 | 
				
			||||||
 | 
					    self._send_request('GET', path, value_type='INT')
 | 
				
			||||||
 | 
					    return self._recv_response()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def query_double_raw(self, path):
 | 
				
			||||||
 | 
					    self._send_request('GET', path, value_type='DOUBLE')
 | 
				
			||||||
 | 
					    return self._recv_response()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def query_sensor_raw(self, path):
 | 
				
			||||||
 | 
					    self._send_request('GET', path, value_type='SENSOR')
 | 
				
			||||||
 | 
					    return self._recv_response()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def query_range_raw(self, path):
 | 
				
			||||||
 | 
					    self._send_request('GET', path, value_type='RANGE')
 | 
				
			||||||
 | 
					    return self._recv_response()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					  # Getters (value)
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def query_bool_value(self, path):
 | 
				
			||||||
 | 
					    res = self.query_bool_raw(path)
 | 
				
			||||||
 | 
					    return res['result']['value']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def query_int_value(self, path):
 | 
				
			||||||
 | 
					    res = self.query_int_raw(path)
 | 
				
			||||||
 | 
					    return res['result']['value']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def query_double_value(self, path):
 | 
				
			||||||
 | 
					    res = self.query_double_raw(path)
 | 
				
			||||||
 | 
					    return res['result']['value']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def query_sensor_value(self, path):
 | 
				
			||||||
 | 
					    res = self.query_sensor_raw(path)
 | 
				
			||||||
 | 
					    return res['result']['value']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def query_range_value(self, path):
 | 
				
			||||||
 | 
					    res = self.query_range_raw(path)
 | 
				
			||||||
 | 
					    return res['result']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					  # Setters
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_bool(self, path, val):
 | 
				
			||||||
 | 
					    self._send_request('SET', path, value_type='BOOL', value=val)
 | 
				
			||||||
 | 
					    return self._recv_response()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_int(self, path, val):
 | 
				
			||||||
 | 
					    self._send_request('SET', path, value_type='INT', value=val)
 | 
				
			||||||
 | 
					    return self._recv_response()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def set_double(self, path, val):
 | 
				
			||||||
 | 
					    self._send_request('SET', path, value_type='DOUBLE', value=val)
 | 
				
			||||||
 | 
					    return self._recv_response()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					  # Check path presence and list paths
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def has_path_raw(self, path):
 | 
				
			||||||
 | 
					    self._send_request('HAS', path)
 | 
				
			||||||
 | 
					    return self._recv_response()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def list_path_raw(self, path):
 | 
				
			||||||
 | 
					    self._send_request('LIST', path)
 | 
				
			||||||
 | 
					    return self._recv_response()
 | 
				
			||||||
							
								
								
									
										49
									
								
								host/utils/umtrx_query_sensors.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										49
									
								
								host/utils/umtrx_query_sensors.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##########################
 | 
				
			||||||
 | 
					###  Query sensors
 | 
				
			||||||
 | 
					##########################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from umtrx_property_tree import umtrx_property_tree
 | 
				
			||||||
 | 
					from umtrx_vswr import umtrx_vswr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					s = umtrx_property_tree()
 | 
				
			||||||
 | 
					s.connect()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sensors_path="/mboards/0/sensors"
 | 
				
			||||||
 | 
					res = s.list_path_raw(sensors_path)
 | 
				
			||||||
 | 
					sensors_list = res.get('result', [])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print "Sensors:"
 | 
				
			||||||
 | 
					for sensor in sensors_list:
 | 
				
			||||||
 | 
					  reply = s.query_sensor_raw(sensors_path+"/"+sensor)
 | 
				
			||||||
 | 
					  if reply.has_key('result'):
 | 
				
			||||||
 | 
					    res = reply['result']
 | 
				
			||||||
 | 
					    print "  %15s = %9s %s" % (res['name'], res['value'], res['unit'])
 | 
				
			||||||
 | 
					  else:
 | 
				
			||||||
 | 
					    print "Can't read sensor %s" % sensor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#vswr_calibration = TM10_VSWR_cal
 | 
				
			||||||
 | 
					#vswr_calibration = TM3_VSWR_cal
 | 
				
			||||||
 | 
					vswr_calibration = 0
 | 
				
			||||||
 | 
					for num in [1, 2]:
 | 
				
			||||||
 | 
					  vpr_name = 'voltagePR'+str(num)
 | 
				
			||||||
 | 
					  vpf_name = 'voltagePF'+str(num)
 | 
				
			||||||
 | 
					  if vpr_name in sensors_list and vpf_name in sensors_list:
 | 
				
			||||||
 | 
					    vpr = float(s.query_sensor_value(sensors_path+'/'+vpr_name))
 | 
				
			||||||
 | 
					    vpf = float(s.query_sensor_value(sensors_path+'/'+vpf_name))
 | 
				
			||||||
 | 
					    vswr = umtrx_vswr(vpf, vpr, vswr_calibration)
 | 
				
			||||||
 | 
					    print "TRX %d power detector:" % num
 | 
				
			||||||
 | 
					    print "              VPF =  %5.2f  V"   % vpf
 | 
				
			||||||
 | 
					    print "               PF = %5.1f   dBm" % vswr.pf()
 | 
				
			||||||
 | 
					    print "              VPR =  %5.2f  V"   % vpr
 | 
				
			||||||
 | 
					    print "               PR = %5.1f   dBm" % vswr.pr()
 | 
				
			||||||
 | 
					    print "             VSWR = %6.2f"       % vswr.vswr()
 | 
				
			||||||
 | 
					    print "            Gamma =   %5.3f"     % vswr.gamma()
 | 
				
			||||||
 | 
					    print "      Return Loss = %5.1f   dB"  % vswr.return_loss()
 | 
				
			||||||
 | 
					    print "    Mismatch Loss =   %5.3f dB"  % vswr.mismatch_loss()
 | 
				
			||||||
 | 
					    print "    Through power =  %5.2f  %%"  % (100.0*vswr.pf_rate())
 | 
				
			||||||
 | 
					    print "  Reflected power =  %5.2f  %%"  % (100.0*vswr.pr_rate())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					s.close()
 | 
				
			||||||
							
								
								
									
										68
									
								
								host/utils/umtrx_vswr.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								host/utils/umtrx_vswr.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					##########################
 | 
				
			||||||
 | 
					###  VSWR calculations
 | 
				
			||||||
 | 
					##########################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Implemented as described at:
 | 
				
			||||||
 | 
					# http://www.markimicrowave.com/assets/data/return%20loss%20to%20vswr.pdf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import math
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TODO: requires better calibration
 | 
				
			||||||
 | 
					TM10_VSWR_cal=0.3/2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class umtrx_vswr:
 | 
				
			||||||
 | 
					  def __init__(self, VPF, VPR, calibration=0, coef=0.05):
 | 
				
			||||||
 | 
					    self.vpf = VPF
 | 
				
			||||||
 | 
					    self.vpr = VPR
 | 
				
			||||||
 | 
					    self.calibration = calibration
 | 
				
			||||||
 | 
					    self.coef = coef
 | 
				
			||||||
 | 
					    self._gamma = self._calc_gamma()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def _calc_gamma(self):
 | 
				
			||||||
 | 
					    ''' Internal function: calculate Gamma '''
 | 
				
			||||||
 | 
					    return math.pow(10, -self.return_loss()/20.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def pf(self):
 | 
				
			||||||
 | 
					    ''' Estimated through power, dBm '''
 | 
				
			||||||
 | 
					    return (self.vpf-self.calibration)/self.coef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def pr(self):
 | 
				
			||||||
 | 
					    ''' Estimated reflected power, dBm '''
 | 
				
			||||||
 | 
					    return (self.vpr-self.calibration)/self.coef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def return_loss(self):
 | 
				
			||||||
 | 
					    ''' Estimated return loss, dB '''
 | 
				
			||||||
 | 
					    return self.pf()-self.pr()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def gamma(self):
 | 
				
			||||||
 | 
					    ''' Estimated Gamma '''
 | 
				
			||||||
 | 
					    return self._gamma
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def vswr(self):
 | 
				
			||||||
 | 
					    ''' Estimated VSWR '''
 | 
				
			||||||
 | 
					    gamma = self._gamma
 | 
				
			||||||
 | 
					    if gamma == 1.0:
 | 
				
			||||||
 | 
					      return float("inf")
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					      return (1+gamma)/(1-gamma)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def mismatch_loss(self):
 | 
				
			||||||
 | 
					    ''' Estimated mismatch loss, dB '''
 | 
				
			||||||
 | 
					    gamma = self._gamma
 | 
				
			||||||
 | 
					    if gamma == 1.0:
 | 
				
			||||||
 | 
					      return float("-inf")
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					      return -10.0 * math.log(1.0-gamma*gamma, 10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def pf_rate(self):
 | 
				
			||||||
 | 
					    ''' Estimated reflected power rate, % '''
 | 
				
			||||||
 | 
					    gamma = self._gamma
 | 
				
			||||||
 | 
					    return 1.0 - gamma*gamma
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  def pr_rate(self):
 | 
				
			||||||
 | 
					    ''' Estimated reflected power rate, % '''
 | 
				
			||||||
 | 
					    gamma = self._gamma
 | 
				
			||||||
 | 
					    return gamma*gamma
 | 
				
			||||||
@@ -25,6 +25,7 @@
 | 
				
			|||||||
#include <boost/filesystem.hpp>
 | 
					#include <boost/filesystem.hpp>
 | 
				
			||||||
#include <boost/algorithm/string.hpp>
 | 
					#include <boost/algorithm/string.hpp>
 | 
				
			||||||
#include <boost/thread/thread.hpp>
 | 
					#include <boost/thread/thread.hpp>
 | 
				
			||||||
 | 
					#include <boost/math/special_functions/round.hpp>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <complex>
 | 
					#include <complex>
 | 
				
			||||||
 
 | 
				
			|||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user