mirror of
https://github.com/fairwaves/UHD-Fairwaves.git
synced 2025-10-31 20:13:43 +00:00
Compare commits
196 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3070ed467 | ||
|
|
064de45a45 | ||
|
|
8678899b70 | ||
|
|
32584f2d13 | ||
|
|
e03e43151b | ||
|
|
88e0f1c156 | ||
|
|
8d7b9d84ed | ||
|
|
7588631788 | ||
|
|
c5479d66b3 | ||
|
|
5bc5265fd7 | ||
|
|
dd16447884 | ||
|
|
76f0a92574 | ||
|
|
6731023b5c | ||
|
|
79938f6090 | ||
|
|
868f511f0d | ||
|
|
825a076c5c | ||
|
|
fc5067d9c1 | ||
|
|
5483f698f3 | ||
|
|
cb44fdb112 | ||
|
|
842e31803f | ||
|
|
8cef0f4c6c | ||
|
|
96ac532510 | ||
|
|
c0b8fc6687 | ||
|
|
f14e3022fc | ||
|
|
20b2a2f322 | ||
|
|
88df605601 | ||
|
|
a4afe97d54 | ||
|
|
f4f02a51c0 | ||
|
|
907c28f849 | ||
|
|
dfa6aa0a0c | ||
|
|
aa35f5cc40 | ||
|
|
dfc98a6900 | ||
|
|
7e351e3465 | ||
|
|
cc70a46fe4 | ||
|
|
0bf55bbca2 | ||
|
|
230d9c22c8 | ||
|
|
2be52f5741 | ||
|
|
a59b9c381a | ||
|
|
53526ef9b1 | ||
|
|
ce44a4ce47 | ||
|
|
4386d5938d | ||
|
|
204a7862d8 | ||
|
|
19c125a8ef | ||
|
|
d0a74632a8 | ||
|
|
3dac709c49 | ||
|
|
50a1b928ec | ||
|
|
41a94769fe | ||
|
|
b1e80e5c27 | ||
|
|
014e8123a3 | ||
|
|
16bc2bdd18 | ||
|
|
9cf7377866 | ||
|
|
a4568b4704 | ||
|
|
b24a4d0bb8 | ||
|
|
dc5718daea | ||
|
|
25394541fa | ||
|
|
b362710778 | ||
|
|
c9b7e8c884 | ||
|
|
e7eb8e87cc | ||
|
|
2a6b94bea9 | ||
|
|
143a9008d1 | ||
|
|
1e1a889448 | ||
|
|
f385a4355a | ||
|
|
3c240a2ab2 | ||
|
|
e4c59df63e | ||
|
|
ad8ff4a345 | ||
|
|
4f909bcfa2 | ||
|
|
9309e3c548 | ||
|
|
6b5ff4a460 | ||
|
|
53e7e5597f | ||
|
|
a89917faae | ||
|
|
09f323dc3c | ||
|
|
fee336bc5a | ||
|
|
fc4efd5cb0 | ||
|
|
0f7b0cbeab | ||
|
|
b600665303 | ||
|
|
2a89674c56 | ||
|
|
6e30c16773 | ||
|
|
401e64014c | ||
|
|
1dbd567102 | ||
|
|
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 | ||
|
|
0b105893a4 | ||
|
|
41b93944a0 | ||
|
|
a872102cd9 | ||
|
|
89277c6e56 | ||
|
|
1773223b81 | ||
|
|
24527ece28 | ||
|
|
7834aa4709 | ||
|
|
f61d102791 | ||
|
|
d8b282404b | ||
|
|
4cd94528aa | ||
|
|
fb59ec9bd2 | ||
|
|
9577f31bfb | ||
|
|
df513b81e5 | ||
|
|
471eedbb6a | ||
|
|
10e758be8c | ||
|
|
9c20b295d5 | ||
|
|
14e58af929 | ||
|
|
9a752069e7 | ||
|
|
283dae8214 | ||
|
|
df90e2b342 | ||
|
|
0b1c002f32 | ||
|
|
313488b2d3 | ||
|
|
189828f29c | ||
|
|
f913c39c0c | ||
|
|
84c5426fd8 | ||
|
|
ac22360125 | ||
|
|
6bf16b4e66 | ||
|
|
451cc221be | ||
|
|
73ab35d46c | ||
|
|
a189138078 | ||
|
|
2d83e6caed | ||
|
|
9becc6bdf8 | ||
|
|
a5cee8c757 | ||
|
|
5001cb8f95 | ||
|
|
1337b13d56 | ||
|
|
93aaef643d | ||
|
|
a33b3e92e4 | ||
|
|
08c05c5f1b | ||
|
|
000a874189 | ||
|
|
7b15bc857b | ||
|
|
e14c900821 | ||
|
|
271b8a045e | ||
|
|
30a4557825 | ||
|
|
32f82d646b | ||
|
|
c3754d5048 | ||
|
|
052a817f30 | ||
|
|
8e92e8ca43 | ||
|
|
e64d3d5940 | ||
|
|
158077c504 | ||
|
|
84ef0be96c | ||
|
|
84330517e5 | ||
|
|
72062b1466 | ||
|
|
453caf23e8 | ||
|
|
b671b8f8b1 | ||
|
|
b98d250be2 | ||
|
|
bf366bb7ae | ||
|
|
624f089dcb | ||
|
|
6af61a7cab | ||
|
|
99a409192e | ||
|
|
ce92a2f47a | ||
|
|
cbb5815fe0 | ||
|
|
108f250bf9 | ||
|
|
7e5cfac7af | ||
|
|
8b7cb405f1 | ||
|
|
6ded41c3fd | ||
|
|
fd2493f8fe | ||
|
|
34ac1cc22c | ||
|
|
3eb1fe8b46 | ||
|
|
ef99dbc9cb | ||
|
|
49921fe4ef | ||
|
|
04d08ea43b | ||
|
|
8a900aab52 | ||
|
|
ca98bfda97 | ||
|
|
96829b2e5a |
2
README
2
README
@@ -120,5 +120,5 @@ then RX VITA time alignment will not be possible due to ambiguity.
|
||||
Currently, the adc sample strobes are driven from a common sigal.
|
||||
|
||||
simple_gemac_wrapper.v was modified to have an axi_packet_gate in the eth transmit direction.
|
||||
This guarantees thats a packet is 100% buffered before being send out over ethernet.
|
||||
This guarantees thats a packet is 100% buffered before being sent out over ethernet.
|
||||
This avoid in-packet underflow when the mac is fed from a slower clock domain.
|
||||
|
||||
111
debian/changelog
vendored
Normal file
111
debian/changelog
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
umtrx (1.0.13) trusty; urgency=low
|
||||
|
||||
* [ZPU/host] Read TCXO DAC calibration from EEPROM once on UmTRX boot instead
|
||||
of reading and setting it every time we launch a UHD app.
|
||||
* [ZPU] Faster GPSDO converging when setting TCXO DAC value manually.
|
||||
* [ZPU] BUGFIX: Optimize ZPU image size to avoid stack overflow.
|
||||
* [ZPU] Print and check available ZPU stack space when compiling images.
|
||||
* [FPGA/ZPU] Increase FPGA minor version number, generate new stable images.
|
||||
|
||||
-- Alexander Chemeris <Alexander.Chemeris@fairwaves.co> Fri, 04 Aug 2017 15:55:56 +0300
|
||||
|
||||
umtrx (1.0.12) trusty; urgency=low
|
||||
|
||||
* [ZPU] BUGFIX: Fix GPSDO rounding issue to stabilize frequency down to +-1 Hz @ 52MHz.
|
||||
* [ZPU] Export measured frequency and last PPS time over the control socket.
|
||||
* [ZPU] Allow GPSDO debug enable/disable over the control socket.
|
||||
* [ZPU] Print firmware minor version and git hash on startup.
|
||||
* [ZPU] Make debug output on wrong packets less scary for users.
|
||||
* [host] Cleanup UmTRX detection on UHD startup.
|
||||
* [host] Export DC calibration registers through the property tree.
|
||||
* [host] Fix build with newer UHD versions.
|
||||
* [utils] BUGIX: Multiple fixes for the umtrx_ty_tree.py module.
|
||||
* [utils] Lowercase sensor names in umtrx2collectd.
|
||||
|
||||
-- Alexander Chemeris <Alexander.Chemeris@fairwaves.co> Thu, 27 Jul 2017 23:46:07 +0300
|
||||
|
||||
umtrx (1.0.11) trusty; urgency=low
|
||||
|
||||
* collectd: use 'fairwaves-monitoring' user to run plugin
|
||||
|
||||
-- Kirill Zakharenko <earwin@gmail.com> Sun, 27 Mar 2016 19:37:39 +0100
|
||||
|
||||
umtrx (1.0.10) trusty; urgency=low
|
||||
|
||||
* collectd: rewritten counter collection plugin
|
||||
|
||||
-- Kirill Zakharenko <earwin@gmail.com> Mon, 21 Mar 2016 19:21:00 +0100
|
||||
|
||||
umtrx (1.0.9) trusty; urgency=low
|
||||
|
||||
* collectd: osmo-nitb counter collection plugin
|
||||
|
||||
-- Kirill Zakharenko <earwin@gmail.com> Mon, 24 Feb 2016 19:35:56 +0300
|
||||
|
||||
umtrx (1.0.8) trusty; urgency=low
|
||||
|
||||
* host: integrate support class for umsel2
|
||||
* host: integrate support class for umsel2
|
||||
* host: implement selection for umsel2 + lms
|
||||
* host: umsel2 register work for adf355-2
|
||||
* host: umsel2 adf355-2 tuning algorithm
|
||||
* host: freq update sequence, copied registers from gui
|
||||
* host: print locked for debugging
|
||||
* umsel: device args for enabling umsel2 and verbose
|
||||
* add lmsvga1 device args parameter to override VGA1_DEF
|
||||
* autodetect DCDC translation version on startup
|
||||
* add lmsvga2 args parameter to override UMTRX_VGA2_DEF
|
||||
* turn off vin bypass to amplifiers by default
|
||||
* throw exception if incorrect DCDC version were provided
|
||||
|
||||
-- Kirill Zakharenko <earwin@gmail.com> Mon, 28 Dec 2015 15:07:56 +0300
|
||||
|
||||
umtrx (1.0.7) trusty; urgency=low
|
||||
|
||||
* host: Properly handle most corner cases in VSWR calculations
|
||||
* host: Add "STRING" to umtrx_monitor error output
|
||||
* host: Add string getters/setters to the Python property tree library
|
||||
* host: Checking in umtrx_query_versions.py
|
||||
* debian: packaged python utils in host/utils
|
||||
|
||||
-- Kirill Zakharenko <earwin@gmail.com> Mon, 25 Dec 2015 19:35:56 +0100
|
||||
|
||||
umtrx (1.0.6) trusty; urgency=low
|
||||
|
||||
* host: make boost property tree thread safe
|
||||
* host: support string type in JSON query
|
||||
* debian: build now produces an additional package with debug symbols
|
||||
* umtrx_firmware: fixed typo preventing it from working
|
||||
|
||||
-- Kirill Zakharenko <earwin@gmail.com> Mon, 21 Dec 2015 14:23:56 +0300
|
||||
|
||||
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
|
||||
40
debian/control
vendored
Normal file
40
debian/control
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
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.
|
||||
|
||||
Package: umtrx-dbg
|
||||
Section: debug
|
||||
Architecture: any
|
||||
Depends: umtrx, uhd-umtrx, ${misc:Depends}
|
||||
Description: Fairwaves UmTRX driver - debug symbols
|
||||
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
|
||||
21
debian/rules
vendored
Executable file
21
debian/rules
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/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)"
|
||||
|
||||
override_dh_strip:
|
||||
dh_strip --dbg-package=umtrx-dbg
|
||||
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/
|
||||
8
debian/umtrx.install
vendored
Normal file
8
debian/umtrx.install
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
usr/bin
|
||||
images/u2plus_umtrx_v2.bin images/umtrx_txrx_uhd.bin usr/share/umtrx/firmware
|
||||
host/utils/umtrx_property_tree.py host/utils/umtrx_vswr.py usr/share/umtrx
|
||||
host/utils/umtrx_query_sensors.py host/utils/umtrx_query_versions.py host/utils/umtrx_net_burner.py usr/share/umtrx
|
||||
|
||||
host/utils/collectd/umtrx.types.db usr/share/collectd
|
||||
host/utils/collectd/umtrx2collectd.py usr/share/umtrx
|
||||
host/utils/collectd/umtrx.conf etc/collectd/collectd.conf.d
|
||||
3
debian/umtrx.links
vendored
Normal file
3
debian/umtrx.links
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/usr/share/umtrx/umtrx_net_burner.py /usr/bin/umtrx_net_burner
|
||||
/usr/share/umtrx/umtrx_query_sensors.py /usr/bin/umtrx_query_sensors
|
||||
/usr/share/umtrx/umtrx_query_versions.py /usr/bin/umtrx_query_versions
|
||||
@@ -58,5 +58,6 @@ gpio_atr.v \
|
||||
user_settings.v \
|
||||
settings_fifo_ctrl.v \
|
||||
simple_spi_core.v \
|
||||
axis_spi_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
|
||||
@@ -97,7 +97,8 @@ MAP_PROPERTIES = \
|
||||
"Map Effort Level" High \
|
||||
"Extra Effort" Normal \
|
||||
"Combinatorial Logic Optimization" TRUE \
|
||||
"Register Duplication" TRUE
|
||||
"Register Duplication" TRUE \
|
||||
"Starting Placer Cost Table (1-100)" 24
|
||||
|
||||
PLACE_ROUTE_PROPERTIES = \
|
||||
"Place & Route Effort Level (Overall)" High \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
defparam bootram.RAM0.INIT_00=256'h00000000_00000000_00000000_dfb70400_3a0b0b80_80eea40c_82700b0b_0b0b0b0b;
|
||||
defparam bootram.RAM0.INIT_01=256'h00000000_00000000_00000000_800c0400_880c840c_80e0812d_88080b0b_80088408;
|
||||
defparam bootram.RAM0.INIT_00=256'h00000000_00000000_00000000_e2b30400_3a0b0b80_80f0a80c_82700b0b_0b0b0b0b;
|
||||
defparam bootram.RAM0.INIT_01=256'h00000000_00000000_00000000_800c0400_880c840c_80e2ff2d_88080b0b_80088408;
|
||||
defparam bootram.RAM0.INIT_02=256'h00000000_00000000_04000000_ffff0652_832b2a83_81058205_72830609_71fd0608;
|
||||
defparam bootram.RAM0.INIT_03=256'h83a70400_0b0b0b0b_7383ffff_2b2b0906_05820583_83060981_83ffff73_71fd0608;
|
||||
defparam bootram.RAM0.INIT_04=256'h00000000_00000000_53510400_070a8106_73097306_09060906_72057373_72098105;
|
||||
@@ -18,438 +18,438 @@ defparam bootram.RAM0.INIT_10=256'h00000000_00000000_00000000_00000000_00000000_
|
||||
defparam bootram.RAM0.INIT_11=256'h00000000_00000000_00000000_00000000_00000000_04000000_05055351_72720981;
|
||||
defparam bootram.RAM0.INIT_12=256'h00000000_00000000_00000000_00000000_00000000_07535104_73730906_72097206;
|
||||
defparam bootram.RAM0.INIT_13=256'h00000000_00000000_04000000_81ff0652_1010102a_81058305_72830609_71fc0608;
|
||||
defparam bootram.RAM0.INIT_14=256'h00000000_00000000_88aa0400_060b0b0b_10100508_90738306_0b0b80ee_71fc0608;
|
||||
defparam bootram.RAM0.INIT_15=256'h00000000_0c510400_0c840c80_80085688_d82d5050_0b0b80d6_88087575_80088408;
|
||||
defparam bootram.RAM0.INIT_16=256'h00000000_0c510400_0c840c80_80085688_8a2d5050_0b0b80d8_88087575_80088408;
|
||||
defparam bootram.RAM0.INIT_14=256'h00000000_00000000_88aa0400_060b0b0b_10100508_94738306_0b0b80f0_71fc0608;
|
||||
defparam bootram.RAM0.INIT_15=256'h00000000_0c510400_0c840c80_80085688_d42d5050_0b0b80d9_88087575_80088408;
|
||||
defparam bootram.RAM0.INIT_16=256'h00000000_0c510400_0c840c80_80085688_862d5050_0b0b80db_88087575_80088408;
|
||||
defparam bootram.RAM0.INIT_17=256'h04000000_07515151_05ff0506_73097274_70547106_8106ff05_0509060a_72097081;
|
||||
defparam bootram.RAM0.INIT_18=256'h51040000_06075151_7405ff05_06730972_05705471_098106ff_0509060a_72097081;
|
||||
defparam bootram.RAM0.INIT_19=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_05ff0504;
|
||||
defparam bootram.RAM0.INIT_1A=256'h00000000_00000000_00000000_00000000_00000000_51040000_80eea00c_810b0b0b;
|
||||
defparam bootram.RAM0.INIT_1A=256'h00000000_00000000_00000000_00000000_00000000_51040000_80f0a40c_810b0b0b;
|
||||
defparam bootram.RAM0.INIT_1B=256'h00000000_00000000_00000000_00000000_00000000_00000000_04000000_71810552;
|
||||
defparam bootram.RAM0.INIT_1C=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM0.INIT_1D=256'h00000000_00000000_00000000_00000000_00000000_04000000_10100552_02840572;
|
||||
defparam bootram.RAM0.INIT_1E=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM0.INIT_1F=256'h00000000_00000000_00000000_00000000_00000000_020d0400_05715351_717105ff;
|
||||
defparam bootram.RAM0.INIT_20=256'h10101010_10101010_10101010_10101010_10101010_10101010_d7fe3f04_82813f80;
|
||||
defparam bootram.RAM0.INIT_20=256'h10101010_10101010_10101010_10101010_10101010_10101010_dafc3f04_82813f80;
|
||||
defparam bootram.RAM0.INIT_21=256'hfc060c51_102b0772_83051010_06098105_ff067383_51047381_10101053_10101010;
|
||||
defparam bootram.RAM0.INIT_22=256'h51535104_72ed3851_0a100a53_71105272_09720605_8106ff05_72728072_51043c04;
|
||||
defparam bootram.RAM0.INIT_23=256'h800b80ef_800c82a0_0b0b80ef_8380800b_822ebd38_80eea408_802ea438_80eea008;
|
||||
defparam bootram.RAM0.INIT_24=256'h0b80ef84_80808280_ef800cf8_0b0b0b80_808080a4_880c04f8_800b80ef_840c8290;
|
||||
defparam bootram.RAM0.INIT_25=256'h940b80ef_80c0a880_80ef800c_8c0b0b0b_80c0a880_ef880c04_84800b80_0cf88080;
|
||||
defparam bootram.RAM0.INIT_26=256'h70085252_80eeac08_5170a738_80ef8c33_04ff3d0d_80ef880c_80e0b00b_840c0b0b;
|
||||
defparam bootram.RAM0.INIT_27=256'h8c34833d_810b80ef_5270ee38_08700852_2d80eeac_eeac0c70_38841280_70802e94;
|
||||
defparam bootram.RAM0.INIT_28=256'h38823d0d_09810685_800b802e_0b0b0b0b_802e8e38_80eefc08_3d0d0b0b_0d040480;
|
||||
defparam bootram.RAM0.INIT_29=256'h0b81e088_80ce3881_0d685a79_0404ee3d_3f823d0d_0b0bf5d4_eefc510b_040b0b80;
|
||||
defparam bootram.RAM0.INIT_23=256'h800b80f1_840c82a0_0b0b80f1_8380800b_822ebd38_80f0a808_802ea438_80f0a408;
|
||||
defparam bootram.RAM0.INIT_24=256'h0b80f188_80808280_f1840cf8_0b0b0b80_808080a4_8c0c04f8_800b80f1_880c8290;
|
||||
defparam bootram.RAM0.INIT_25=256'h940b80f1_80c0a880_80f1840c_8c0b0b0b_80c0a880_f18c0c04_84800b80_0cf88080;
|
||||
defparam bootram.RAM0.INIT_26=256'h70085252_80f0b008_5170a738_80f19033_04ff3d0d_80f18c0c_80e3b00b_880c0b0b;
|
||||
defparam bootram.RAM0.INIT_27=256'h9034833d_810b80f1_5270ee38_08700852_2d80f0b0_f0b00c70_38841280_70802e94;
|
||||
defparam bootram.RAM0.INIT_28=256'h38823d0d_09810685_800b802e_0b0b0b0b_802e8e38_80f18008_3d0d0b0b_0d040480;
|
||||
defparam bootram.RAM0.INIT_29=256'h0b81e088_80ce3881_0d685a79_0404ee3d_3f823d0d_0b0bf5d4_f180510b_040b0b80;
|
||||
defparam bootram.RAM0.INIT_2A=256'h7981e180_81e0f80c_0c890a0b_7981e598_81e5940c_e48c0c79_880c7981_0c7981e4;
|
||||
defparam bootram.RAM0.INIT_2B=256'h81e2e80c_0c890a0b_7981e2a0_81e2980c_0c890a0b_7981e1d0_81e1c80c_0c890a0b;
|
||||
defparam bootram.RAM0.INIT_2C=256'ha9a03f89_0553425a_54973d84_08933d70_8238881a_8b6a2781_0c818839_7981e2f0;
|
||||
defparam bootram.RAM0.INIT_2D=256'h7b34811c_5b5b7933_7b1d7f1d_3d415e5c_0b883d99_5b5f4080_0284057b_9e3f8008;
|
||||
defparam bootram.RAM0.INIT_2C=256'hae823f8c_0553425a_54973d84_08933d70_8238881a_8b6a2781_0c818839_7981e2f0;
|
||||
defparam bootram.RAM0.INIT_2D=256'h7b34811c_5b5b7933_7b1d7f1d_3d415e5c_0b883d99_5b5f4080_0284057b_af3f8008;
|
||||
defparam bootram.RAM0.INIT_2E=256'h7c26ed38_811c5c88_79337b34_7d055b5b_7b1d963d_901f5e5c_ef38800b_5c887c26;
|
||||
defparam bootram.RAM0.INIT_2F=256'h611d5b5b_805c7b1e_7c26ef38_811c5c86_79337b34_601d5b5b_5e5c7b1d_800b881f;
|
||||
defparam bootram.RAM0.INIT_30=256'h5a588379_84120859_3d0d686a_3d0d04ee_9a963f94_7c26ef38_811c5c86_79337b34;
|
||||
defparam bootram.RAM0.INIT_31=256'hf55778a3_958e3f80_80e0b451_75538c52_802e8c38_2e943875_0856758c_279c3877;
|
||||
defparam bootram.RAM0.INIT_32=256'h75922682_ff981756_8818085d_8c5ba05c_fb3fa057_e1845194_53a45280_268e3878;
|
||||
defparam bootram.RAM0.INIT_33=256'h5c8c1808_983980da_08085e82_88ad3f80_0480d55c_05567508_2980e2f4_ae387584;
|
||||
defparam bootram.RAM0.INIT_34=256'h39921822_065f81f5_0883ffff_abc23f80_38828239_75822e91_812e8938_5e7d5675;
|
||||
defparam bootram.RAM0.INIT_35=256'h1808538c_18335490_57765596_2e833884_577580f2_18335682_81eb3995_51ab903f;
|
||||
defparam bootram.RAM0.INIT_36=256'h81b3398d_5f80d35c_893f8008_57765196_2e833881_57577577_0b971933_18085280;
|
||||
defparam bootram.RAM0.INIT_37=256'h19538c19_3370548e_94398d18_3f80c95c_52568bc0_538c1933_953dea05_18337054;
|
||||
defparam bootram.RAM0.INIT_38=256'h80c23875_56758526_1833ff05_80ff3994_05b50534_5c750284_8e3f80c8_3352568d;
|
||||
defparam bootram.RAM0.INIT_39=256'h0ca23992_90180877_225fa939_5fae3976_08047608_08585675_c0058c19_842980e3;
|
||||
defparam bootram.RAM0.INIT_3A=256'h08710c56_90059019_842980ef_568e3976_05700840_2980ef90_9b397684_18227723;
|
||||
defparam bootram.RAM0.INIT_3B=256'h3d790557_58771996_0b833d5a_dc055480_0855943d_cc5c8c18_39785e80_80d25cad;
|
||||
defparam bootram.RAM0.INIT_3C=256'h5a587719_800b833d_3ddc0554_5ca45594_38a439a0_887826ed_34811858_57753377;
|
||||
defparam bootram.RAM0.INIT_3D=256'h04fd3d0d_3f943d0d_80519b85_ed388380_58887826_77348118_57577533_963d7905;
|
||||
defparam bootram.RAM0.INIT_3E=256'h52725186_80c05372_e82e8438_a0537387_802e9838_91fe3f73_e1d05254_75705380;
|
||||
defparam bootram.RAM0.INIT_3F=256'h0d82863f_0d04fa3d_a63f853d_52735186_ae3f80c0_52735186_3f9039a0_ba3f9b92;
|
||||
defparam bootram.RAM1.INIT_00=256'hefac0cab_3f800b80_ac5191b0_8c5280e2_5191b93f_5280e28c_879f3f89_80e1f051;
|
||||
defparam bootram.RAM1.INIT_01=256'h518fdc3f_863f8008_82d63f84_81e09c0c_9c0c800b_810b81e0_3f84e93f_d53f8480;
|
||||
defparam bootram.RAM1.INIT_02=256'h5194983f_73528008_5483e83f_ce3f8008_869e3f84_518ff63f_da3f8008_86aa3f84;
|
||||
defparam bootram.RAM1.INIT_03=256'h52838084_de3f8ab2_80805194_8c935283_3f94a23f_08518def_80845280_84bd3f83;
|
||||
defparam bootram.RAM1.INIT_04=256'haca03fae_3f8fbd51_fa3f8dda_809251a4_94c93f83_83808251_80c79452_5194d43f;
|
||||
defparam bootram.RAM1.INIT_05=256'h7382fdee_05225555_7680088e_2e80c938_56800880_ea3f8008_fc05518d_c53f883d;
|
||||
defparam bootram.RAM1.INIT_06=256'h518fe93f_3880e2d8_3f80089a_5180cc9c_80089005_80e2d052_ad388453_2e098106;
|
||||
defparam bootram.RAM1.INIT_07=256'ha4cf3f8b_3f8cf73f_75519a83_88397452_5183fd3f_85823f73_548eda3f_94167052;
|
||||
defparam bootram.RAM1.INIT_08=256'h9b3f9f52_52805184_86f23f9f_3f8ba13f_b13f85f6_84cb3f91_39fe3d0d_e93fff9e;
|
||||
defparam bootram.RAM1.INIT_09=256'h83dd3f82_88528851_518ad33f_ea3f82ac_52845183_8ae03f84_3f82ac51_805183f7;
|
||||
defparam bootram.RAM1.INIT_0A=256'he4518aaa_83c13f80_9f528051_b93f8253_82ac518a_5183d03f_3f905290_ac518ac6;
|
||||
defparam bootram.RAM1.INIT_0B=256'h3f9f5281_9e5183bc_df389f52_53728025_9d3fff13_80e4518a_5183b43f_3f9f529c;
|
||||
defparam bootram.RAM1.INIT_0C=256'h80760c80_5189ef3f_585680e4_e0807008_fa3d0d81_843d0d04_810b800c_5183983f;
|
||||
defparam bootram.RAM1.INIT_0D=256'h518e893f_5280e3d8_a93f8008_52815190_88805381_86559054_3f750856_e45189e6;
|
||||
defparam bootram.RAM1.INIT_0E=256'h0b800c88_a6d73f81_518df13f_5280e3f4_913f8008_52815190_88805382_86559054;
|
||||
defparam bootram.RAM1.INIT_0F=256'h802e8338_33525270_38721770_7276279e_56548053_57578170_3d0d787a_3d0d04fa;
|
||||
defparam bootram.RAM1.INIT_10=256'h5170800c_2e833881_07517080_df397474_55811353_2e833880_527181ff_80547133;
|
||||
defparam bootram.RAM1.INIT_11=256'h3d0d04f9_c78e3f84_eeb45180_e4945280_34865380_0b80efb4_fe3d0d81_883d0d04;
|
||||
defparam bootram.RAM1.INIT_12=256'hb5c63f80_5280d051_70545682_8654873d_80efb434_bd38810b_b4335574_3d0d80ef;
|
||||
defparam bootram.RAM1.INIT_13=256'h755280ee_8d388653_ff065574_3f800881_7551fef3_9d388652_5574802e_0881ff06;
|
||||
defparam bootram.RAM1.INIT_14=256'hb00c04fb_900880ee_b03480e4_810b80ef_893d0d04_b40b800c_c33f80ee_b45180c6;
|
||||
defparam bootram.RAM1.INIT_15=256'hb4e63f80_5280d051_fc05538c_8454873d_80efb034_b938810b_b0335574_3d0d80ef;
|
||||
defparam bootram.RAM1.INIT_16=256'h387580ee_06557486_800881ff_51fe903f_873dfc05_99388452_5574802e_0881ff06;
|
||||
defparam bootram.RAM1.INIT_17=256'h3f800881_d051b3ac_538c5280_56845475_fb3d0d77_873d0d04_b00b800c_b00c80ee;
|
||||
defparam bootram.RAM1.INIT_18=256'h3d0d7309_3d0d0480_74800c87_80efb034_b00c810b_750880ee_802e8d38_ff065574;
|
||||
defparam bootram.RAM1.INIT_19=256'h09737506_803d0d73_823d0d04_e08c0c51_efb80c81_06077080_80efb808_73750671;
|
||||
defparam bootram.RAM1.INIT_1A=256'h74705353_04fe3d0d_0481af3f_51823d0d_81e0980c_80efbc0c_08060770_7180efbc;
|
||||
defparam bootram.RAM1.INIT_1B=256'h0d777956_0d04fb3d_b63f833d_52805181_ff3d0d8a_843d0d04_3f72800c_805181c7;
|
||||
defparam bootram.RAM1.INIT_1C=256'h39800b80_81913fe5_53765255_7481ff06_90388115_5472802e_81ff0654_56743370;
|
||||
defparam bootram.RAM1.INIT_1D=256'hbd3f8a52_705253ff_0d747653_0d04fe3d_cd3f833d_73528051_04ff3d0d_0c873d0d;
|
||||
defparam bootram.RAM1.INIT_1E=256'h0d725102_0d04803d_dd3f833d_73528051_04ff3d0d_0c843d0d_3f800b80_725180e7;
|
||||
defparam bootram.RAM1.INIT_1F=256'h7022720c_80e49c05_80057510_a0298290_ff3d0d73_823d0d04_eebc1234_8f053380;
|
||||
defparam bootram.RAM1.INIT_20=256'h51ce3f81_13335272_3f80eec0_527251c6_eebc1333_0d805380_0d04fe3d_5351833d;
|
||||
defparam bootram.RAM1.INIT_21=256'hbc143353_953880ee_2e098106_5654748a_3d0d7678_3d0d04fc_25e53884_13538273;
|
||||
defparam bootram.RAM1.INIT_22=256'h2ef83874_08537280_05548414_29829080_de3f73a0_8d527351_81068738_72812e09;
|
||||
defparam bootram.RAM1.INIT_23=256'h38901208_70802e85_5252ff53_05881108_29829080_3d0d74a0_3d0d04fe_8c150c86;
|
||||
defparam bootram.RAM1.INIT_24=256'h0c70882a_0681a880_227081ff_0c80eec8_0b81a888_ff3d0d80_843d0d04_5372800c;
|
||||
defparam bootram.RAM1.INIT_25=256'h55568152_9f053357_7a028805_fb3d0d78_833d0d04_81a8880c_5181800b_81a8840c;
|
||||
defparam bootram.RAM1.INIT_26=256'hff135372_802e9338_51515271_2a708106_90087086_d05381a8_c7388386_73802e81;
|
||||
defparam bootram.RAM1.INIT_27=256'h0c8386d0_0b81a890_8c0c8190_810781a8_9f397410_3f725281_a851fde5_e93880e4;
|
||||
defparam bootram.RAM1.INIT_28=256'h51fdae3f_3880e4c4_135372e9_2e8e38ff_51527180_70810651_0870812a_5381a890;
|
||||
defparam bootram.RAM1.INIT_29=256'h3880e852_802e80c5_80cf3873_5271802e_32515151_81067081_70872a70_81a89008;
|
||||
defparam bootram.RAM1.INIT_2A=256'h5271802e_81065151_70812a70_81a89008_8386d053_81a8900c_38a05271_73812e83;
|
||||
defparam bootram.RAM1.INIT_2B=256'h1454ffb7_055834ff_71767081_a88c0852_fcdf3f81_80e4c451_5372e938_8e38ff13;
|
||||
defparam bootram.RAM1.INIT_2C=256'h05335755_0288059f_3d0d787a_3d0d04fb_71800c87_81a8900c_3980c00b_39815288;
|
||||
defparam bootram.RAM1.INIT_2D=256'h3880e4e4_135372e9_2e9338ff_51527180_70810651_0870862a_5381a890_568386d0;
|
||||
defparam bootram.RAM1.INIT_2E=256'ha8900c83_90527181_2e843881_d0527380_a88c0c81_39741081_725281bb_51fc8a3f;
|
||||
defparam bootram.RAM1.INIT_2F=256'he4c451fb_72e93880_38ff1353_71802e8e_06515152_812a7081_a8900870_86d05381;
|
||||
defparam bootram.RAM1.INIT_30=256'h80d83875_3873802e_802e80e2_51515271_70813251_2a708106_90087087_cc3f81a8;
|
||||
defparam bootram.RAM1.INIT_31=256'h70812a70_81a89008_8386d053_81a8900c_38905271_73812e83_0c80d052_3381a88c;
|
||||
defparam bootram.RAM1.INIT_32=256'h872a7081_a8900870_faf73f81_80e4c451_5372e938_8e38ff13_5271802e_81065151;
|
||||
defparam bootram.RAM1.INIT_33=256'h0b81a890_8a3980c0_a4398152_155556ff_388116ff_71802e8e_51515152_06708132;
|
||||
defparam bootram.RAM1.INIT_34=256'hb8ac0870_ac085281_9b3881b8_53727425_0d755480_0d04fd3d_800c873d_0c805271;
|
||||
defparam bootram.RAM1.INIT_35=256'h0c81e00b_0b828088_ff3d0dff_853d0d04_1353e239_27f13881_81cb8f71_73315151;
|
||||
defparam bootram.RAM1.INIT_36=256'h540cff11_72708405_87519eda_80f9fc52_82808c0c_840cff0b_ef0b8280_8280800c;
|
||||
defparam bootram.RAM1.INIT_37=256'h8053810b_06585152_808c0871_08700982_0d828088_0d04fb3d_f138833d_51708025;
|
||||
defparam bootram.RAM1.INIT_38=256'h81138415_8c0c8f39_2d748280_73085271_8f387251_5271802e_55747606_80f9fc55;
|
||||
defparam bootram.RAM1.INIT_39=256'hf9fc0575_71842980_87269f38_0d735271_0d04ff3d_dc38873d_53877325_76105755;
|
||||
defparam bootram.RAM1.INIT_3A=256'h3d0d0292_0d0404ff_5152833d_80880c53_70720682_82808808_722b7009_710c5181;
|
||||
defparam bootram.RAM1.INIT_3B=256'hb8a00870_e0c00c81_0d810b81_0d04803d_c80c833d_0c5281e0_0881e0c4_05227470;
|
||||
defparam bootram.RAM1.INIT_3C=256'h06545272_a0087081_3d0d81b8_3d0d04fe_e0c00c82_38820b81_70802ef3_84065151;
|
||||
defparam bootram.RAM1.INIT_3D=256'h51527180_2a708106_9a397181_81808052_710c5353_7571902a_81b8a008_802e9338;
|
||||
defparam bootram.RAM1.INIT_3E=256'h087080c0_0d81b8a0_0d04803d_800c843d_3f725271_dc3fffa6_e58051f7_2e8b3880;
|
||||
defparam bootram.RAM1.INIT_3F=256'h880781e0_2270902b_0d028e05_0d04ff3d_800c823d_8180800b_802ef238_06515170;
|
||||
defparam bootram.RAM2.INIT_00=256'h3d0d7554_3d0d04fd_e0c00c83_38840b81_70802ef3_90065151_b8a00870_c00c5281;
|
||||
defparam bootram.RAM2.INIT_01=256'h38853d0d_857327e6_3f811353_5252acc3_72147033_51f6ae3f_2e8638ba_80537280;
|
||||
defparam bootram.RAM2.INIT_02=256'h873d0d04_5180ed3f_5680e584_54703353_55811133_56821133_77831133_04fb3d0d;
|
||||
defparam bootram.RAM2.INIT_03=256'h8f387580_57768025_5f5d5b59_9f2a515b_33703070_9005bb05_7e616302_f63d0d7c;
|
||||
defparam bootram.RAM2.INIT_04=256'hf13f8008_527651b4_54805377_38795578_77772694_2d763057_52ad5178_2e8a3879;
|
||||
defparam bootram.RAM2.INIT_05=256'h028b0533_04803d0d_2d8c3d0d_05335178_0880e590_b5893f80_77527651_51ffbd3f;
|
||||
defparam bootram.RAM2.INIT_06=256'hff065757_78337081_b95c5a58_055208a1_3d707084_f73d0d8c_823d0d04_51f5963f;
|
||||
defparam bootram.RAM2.INIT_07=256'hf02e80fb_57597580_81197033_0680db38_a52e0981_ff065675_d1387681_75802e81;
|
||||
defparam bootram.RAM2.INIT_08=256'h7580e42e_38819539_802e819e_248a3875_387580e3_80e32eb9_24a03875_387580f0;
|
||||
defparam bootram.RAM2.INIT_09=256'h7580f82e_3880f539_f32e80db_8b387580_7580f524_f52eac38_8b397580_80c63881;
|
||||
defparam bootram.RAM2.INIT_0A=256'h52595680_84197108_80da3977_7551792d_59568052_83123352_39778419_ba3880ec;
|
||||
defparam bootram.RAM2.INIT_0B=256'h84197108_52923977_5481538a_8055a1b9_08525956_77841971_80539039_55a1b954;
|
||||
defparam bootram.RAM2.INIT_0C=256'h33567580_59595676_84197108_3f9e3977_7551fdd0_80539052_55a1b954_52595680;
|
||||
defparam bootram.RAM2.INIT_0D=256'h0d048a0b_800c8b3d_a339800b_811959fe_792dec39_05583351_52767081_2e8e3880;
|
||||
defparam bootram.RAM2.INIT_0E=256'h0d04fc3d_ef38823d_51515170_32708106_708c2a81_81b8b408_04803d0d_81e5e40c;
|
||||
defparam bootram.RAM2.INIT_0F=256'h810a0752_2e863871_54557080_06555556_7b077281_3372982b_88059b05_0d797b02;
|
||||
defparam bootram.RAM2.INIT_10=256'h3f7181e5_5151ffa9_3179712b_0752a075_3871820a_70802e86_81065151_72822a70;
|
||||
defparam bootram.RAM2.INIT_11=256'h04fc3d0d_0c863d0d_08517080_3f81b880_8938ff95_5173802e_e5ec0c73_e80c7081;
|
||||
defparam bootram.RAM2.INIT_12=256'h902a5170_51ee3971_81155553_70227305_38721015_7274278f_55558053_76787a54;
|
||||
defparam bootram.RAM2.INIT_13=256'h755280ef_3d0d8653_3d0d04fd_71800c86_0552ec39_0672902a_7183ffff_802e8d38;
|
||||
defparam bootram.RAM2.INIT_14=256'h0c8812ff_89518072_80efd452_04ff3d0d_54853d0d_80efcc0c_3f767008_c451b6c4;
|
||||
defparam bootram.RAM2.INIT_15=256'h22547274_d0525270_800b80ef_96052253_fd3d0d02_833d0d04_8025f338_12525270;
|
||||
defparam bootram.RAM2.INIT_16=256'h7183ffff_3d0d787a_3d0d04fa_70800c85_ee388051_52897225_12881252_2e8e3881;
|
||||
defparam bootram.RAM2.INIT_17=256'hd0555555_d40b80ef_800880ef_050cad39_76800884_802e8938_c73f8008_06535856;
|
||||
defparam bootram.RAM2.INIT_18=256'h7684140c_3f757323_eb38a381_55897525_15881454_2e8f3881_55527180_73088815;
|
||||
defparam bootram.RAM2.INIT_19=256'h52913ddc_923d8805_933f7353_055254b5_53923dd6_7054933d_f13d0d86_883d0d04;
|
||||
defparam bootram.RAM2.INIT_1A=256'h0b8c3d23_a6052380_80028405_0b8b3d23_23818a80_8405a205_3f908002_0551b584;
|
||||
defparam bootram.RAM2.INIT_1B=256'h538a5291_5d665e80_ae052368_80028405_0b8d3d23_2380c091_8405aa05_81808002;
|
||||
defparam bootram.RAM2.INIT_1C=256'h0523800b_028405ba_23963d22_3d22903d_ae052398_08028405_fdb73f80_3de40551;
|
||||
defparam bootram.RAM2.INIT_1D=256'h3f913d0d_0551a4f4_29829884_526980c0_913dd405_0523ac53_028405be_913d2380;
|
||||
defparam bootram.RAM2.INIT_1E=256'hc4529a3d_865380ef_51b3f13f_9a3df205_539b3d52_973d2386_805b800b_04e83d0d;
|
||||
defparam bootram.RAM2.INIT_1F=256'h0b9b3dc4_08585a80_3f800880_0523f7e2_840580e2_f2052202_e33f0280_f80551b3;
|
||||
defparam bootram.RAM2.INIT_20=256'h088305fc_085fa33d_6e5ea13d_845c905d_3d084659_3d0845a3_436e44a1_1143f005;
|
||||
defparam bootram.RAM2.INIT_21=256'h760c7508_27843873_5a557375_71315156_7c319080_08701a78_56845875_06408c3d;
|
||||
defparam bootram.RAM2.INIT_22=256'heeef3f75_80e5ac51_802e8838_83065473_38941608_0654738c_9a387383_5473802e;
|
||||
defparam bootram.RAM2.INIT_23=256'h78bf2684_25ffac38_59577780_0817ff19_70840557_a3c63f75_08527651_08539416;
|
||||
defparam bootram.RAM2.INIT_24=256'h237f1f94_800b943d_4040818a_3d0d6b6e_3d0d04ea_f6e83f9a_78822a51_3880c059;
|
||||
defparam bootram.RAM2.INIT_25=256'h80075a79_236980c0_0580ce05_80800284_953d2381_0523800b_840580ca_055a7902;
|
||||
defparam bootram.RAM2.INIT_26=256'he03f8008_70525cfa_8a52933d_68478053_efcc0846_d2052380_02840580_963d2380;
|
||||
defparam bootram.RAM2.INIT_27=256'h5a799238_0881ff06_8ac83f80_70535c5e_7053983d_0523913d_840580d2_095a7902;
|
||||
defparam bootram.RAM2.INIT_28=256'h557b5490_6b575d94_6d596058_39027f5a_ecde3fa9_51f6b63f_f7c23f7a_80e5d851;
|
||||
defparam bootram.RAM2.INIT_29=256'h04f73d0d_3f983d0d_ef38fd89_5c867c26_7b34811c_5b5b7933_7b1d7c1f_8053805c;
|
||||
defparam bootram.RAM2.INIT_2A=256'h05a60523_23800284_57768b3d_05238818_028405a2_238d3d22_05228a3d_7f5802ae;
|
||||
defparam bootram.RAM2.INIT_2B=256'h3d239080_0d810b8e_0d04ee3d_9e3f8b3d_527d51fe_f8055391_88548b3d_77567e55;
|
||||
defparam bootram.RAM2.INIT_2C=256'h86538008_23e9a43f_8405b605_05348102_028405b5_8f3d3484_0523860b_028405b2;
|
||||
defparam bootram.RAM2.INIT_2D=256'h52943df6_3f865380_0551b090_52943df2_84538008_3fe9f43f_0551b0a0_52943dec;
|
||||
defparam bootram.RAM2.INIT_2E=256'h54908653_943de405_80569c55_80588057_025c8059_80080843_3fe9d83f_0551b19d;
|
||||
defparam bootram.RAM2.INIT_2F=256'h3d0daa3d_3d0d04d9_fbcb3f94_7b26ef38_811b5b86_1b337a34_5a80e5a4_805b7a1c;
|
||||
defparam bootram.RAM2.INIT_30=256'h9b268d38_055b5b79_088429f2_901dac3d_06829d38_862e0981_5f5d7d90_088e1122;
|
||||
defparam bootram.RAM2.INIT_31=256'h7990802e_821b225a_0686e238_812e0981_7a225a79_3f86ee39_8851f5a0_795280e6;
|
||||
defparam bootram.RAM2.INIT_32=256'h810686b9_79812e09_861b225a_0686c638_842e0981_225a798c_d438841b_09810686;
|
||||
defparam bootram.RAM2.INIT_33=256'hffa80551_cc52a93d_845380ef_3f800843_525f87fd_3fa81d70_52408885_389e1d70;
|
||||
defparam bootram.RAM2.INIT_34=256'h3d23821b_3f7a22a1_7951aeb0_80efc452_3d5a8653_868f38a7_085c8008_add23f80;
|
||||
defparam bootram.RAM2.INIT_35=256'h81820523_82028405_81810534_33028405_3d34851b_841b33a2_80fe0523_22028405;
|
||||
defparam bootram.RAM2.INIT_36=256'h8e055b86_ef3f0281_05525aad_53aa3dea_8470547f_51adfd3f_a93de405_86537952;
|
||||
defparam bootram.RAM2.INIT_37=256'h7e51adc8_86537a52_3f9e3d5f_0551add4_52a93df4_3f79537f_7a51ade0_53981d52;
|
||||
defparam bootram.RAM2.INIT_38=256'h7b34811c_5b5b7933_7b1d7f1d_05547d53_55a93ddc_7c575d9c_7c597c58_3f027c5a;
|
||||
defparam bootram.RAM2.INIT_39=256'h2a435b5b_7022708c_e438901d_09810684_7d90802e_3f84ee39_ef38f999_5c867c26;
|
||||
defparam bootram.RAM2.INIT_3A=256'h2280ffff_c038861b_09810684_5a79852e_708f0651_3879882a_810684d1_60842e09;
|
||||
defparam bootram.RAM2.INIT_3B=256'h1c625580_815e7e90_80088338_51abe13f_a452821d_865380e5_b4387e5e_065f7e84;
|
||||
defparam bootram.RAM2.INIT_3C=256'h9c1d5184_38881d52_802e8481_7d87387b_8338815c_cb3f8008_535b5cab_efcc5470;
|
||||
defparam bootram.RAM2.INIT_3D=256'h8c1b087a_0683de38_912e0981_81bb387f_407f812e_ec11405d_33821c22_b83f891b;
|
||||
defparam bootram.RAM2.INIT_3E=256'h39ac1de4_ef3f83bd_e6a851f1_537d5280_2e8f3879_42407d7a_11225d5d_08a41f84;
|
||||
defparam bootram.RAM2.INIT_3F=256'h3d993d5f_237f499a_7a22993d_2e83a638_42800880_c33f8008_535d5df5_1d821d22;
|
||||
defparam bootram.RAM3.INIT_00=256'h60478853_22973d23_b33f821b_527f51ab_40885379_bf3f9c3d_527951ab_5a88537d;
|
||||
defparam bootram.RAM3.INIT_01=256'h5c7b1d7c_7e843d5e_7b567c55_51ab953f_5379527d_ab9e3f88_05527951_a93dffb4;
|
||||
defparam bootram.RAM3.INIT_02=256'h1b5b887b_051c3481_79330284_5b7f1b5a_26ef3880_1c5c887c_337b3481_1f5b5b79;
|
||||
defparam bootram.RAM3.INIT_03=256'h7d882e81_832e8a38_405b427d_a41e7033_398c1b08_792d82ad_8405085a_26ef3861;
|
||||
defparam bootram.RAM3.INIT_04=256'h5c79912e_12335c5e_80c01e89_a238ac1d_09810681_5a79832e_39811a33_bb388295;
|
||||
defparam bootram.RAM3.INIT_05=256'h9b3d2379_085a7c22_fe388c1c_08802e80_80084180_51f4813f_f4387c22_09810681;
|
||||
defparam bootram.RAM3.INIT_06=256'h901c085a_51a9ed3f_537d527f_963d4088_51a9f93f_537a527d_3d5c5e88_4b983d9b;
|
||||
defparam bootram.RAM3.INIT_07=256'h3f7e567e_7d51a9cc_88537a52_51a9d53f_cc05527a_8853a93d_3d23794d_821d229d;
|
||||
defparam bootram.RAM3.INIT_08=256'h5a793302_805b7f1b_7c26ef38_811c5c88_79337b34_7c1f5b5b_5e5c7b1d_557e843d;
|
||||
defparam bootram.RAM3.INIT_09=256'hac1de41d_3f80de39_e951e4a1_5a792d80_60840508_7b26ef38_811b5b88_84051c34;
|
||||
defparam bootram.RAM3.INIT_0A=256'h861a2202_22963d23_0523841a_840580ce_05347e02_840580cd_3d347e02_5d5d7e95;
|
||||
defparam bootram.RAM3.INIT_0B=256'hc03f8008_527c51f1_537b812a_cc3f8008_70525bf1_6052943d_05237e53_840580d2;
|
||||
defparam bootram.RAM3.INIT_0C=256'h04fc3d0d_3fa93d0d_6151f5f7_7a537f52_7c557d54_05237b56_840580ce_095a7902;
|
||||
defparam bootram.RAM3.INIT_0D=256'h70752e09_8c135351_56517108_80f0a854_38767008_727427a4_a0085553_800b80f0;
|
||||
defparam bootram.RAM3.INIT_0E=256'h77797153_04fb3d0d_0c863d0d_ff517080_7326e738_81135373_72518b39_81068538;
|
||||
defparam bootram.RAM3.INIT_0F=256'h3980f0a4_f0a00c8e_38811480_73872689_f0a00854_25ba3880_3f800880_5755ffb9;
|
||||
defparam bootram.RAM3.INIT_10=256'h5280f0ac_54865375_a8120c51_760880f0_1470822b_0c547310_0680f0a4_08811187;
|
||||
defparam bootram.RAM3.INIT_11=256'h0d04fd3d_8f3f873d_ac0551a7_842980f0_53755273_08055486_80081080_14519439;
|
||||
defparam bootram.RAM3.INIT_12=256'hac055276_842980f0_54865373_10800805_99388008_73800824_d83f8054_0d7551fe;
|
||||
defparam bootram.RAM3.INIT_13=256'h07821433_2b71902b_12337198_75703381_04fd3d0d_0c853d0d_81547380_51a6e53f;
|
||||
defparam bootram.RAM3.INIT_14=256'hf1882256_0d7d7f80_0d04f93d_5452853d_52535456_7107800c_07831633_70882b72;
|
||||
defparam bootram.RAM3.INIT_15=256'h14709029_38739029_832680d3_52565473_22707231_ff068b3d_387383ff_595776a8;
|
||||
defparam bootram.RAM3.INIT_16=256'h26ad3874_57547483_70723157_068d3d22_7383ffff_2380c039_51547674_80f18c05;
|
||||
defparam bootram.RAM3.INIT_17=256'h17703353_27913875_80567578_51a5d53f_80f18c05_52739029_88538a3d_90291554;
|
||||
defparam bootram.RAM3.INIT_18=256'h80f18c54_8823800b_052280f1_3d0d029a_3d0d04fc_56ec3989_a63f8116_547451e2;
|
||||
defparam bootram.RAM3.INIT_19=256'h3f811482_0551ef9b_f1882274_b5965280_828c140c_140c800b_800b8288_54807323;
|
||||
defparam bootram.RAM3.INIT_1A=256'h70810651_7c2c8132_8c5a5c82_800b80f1_04f43d0d_38863d0d_837427d9_90145454;
|
||||
defparam bootram.RAM3.INIT_1B=256'h3f8008ff_7b51e1eb_1a88055b_80d63878_7981ff26_1a085b5d_38758288_567581be;
|
||||
defparam bootram.RAM3.INIT_1C=256'h59515858_25075351_80257180_32703072_7030728d_06708a32_800881ff_2e80c538;
|
||||
defparam bootram.RAM3.INIT_1D=256'h1a0c811a_800b828c_82881a0c_19088105_5d348288_7b708105_38815d77_76802e83;
|
||||
defparam bootram.RAM3.INIT_1E=256'h1b0c568b_8111828c_828c1908_387c9138_802e80d2_82881908_27ffb138_5a81ff7a;
|
||||
defparam bootram.RAM3.INIT_1F=256'h781a5757_5b58771a_800b833d_55881954_82881908_802eab38_78225675_7627bf38;
|
||||
defparam bootram.RAM3.INIT_20=256'h800b828c_82881a0c_a83f800b_7c0551f2_80f18822_7826ef38_81185888_75337734;
|
||||
defparam bootram.RAM3.INIT_21=256'h80fa9c23_05225675_3d0d029e_3d0d04fb_fea9388e_5c837c27_82901a5a_1a0c811c;
|
||||
defparam bootram.RAM3.INIT_22=256'h3d0d81b0_800c04fa_80fa9c22_873d0d04_51eb8f3f_53845281_759fff06_85559054;
|
||||
defparam bootram.RAM3.INIT_23=256'he7a0a39f_81b0800c_0854810b_3881b084_802e81bd_51515372_2a708106_80087081;
|
||||
defparam bootram.RAM3.INIT_24=256'h7080eed0_0570832c_31741184_80eed008_d0088829_a43880ee_9abe2681_1453728c;
|
||||
defparam bootram.RAM3.INIT_25=256'h258538ff_72ffb1f0_90538c39_873880ce_ce907325_58515380_80713152_0c98e5ea;
|
||||
defparam bootram.RAM3.INIT_26=256'h2270902b_0c80f9ce_7080f9e0_f9e00816_2c752980_902b7090_f9cc2270_b1f05380;
|
||||
defparam bootram.RAM3.INIT_27=256'h18057087_f9dc0c73_2c297f80_7f317190_80f9dc08_2270902b_2980f9d0_70902c73;
|
||||
defparam bootram.RAM3.INIT_28=256'h38f08153_f0812584_538a3972_86388fff_8fff7325_56515654_5351555b_2c525755;
|
||||
defparam bootram.RAM3.INIT_29=256'h528151e3_fa3fb8db_908051fd_04fd3d0d_3f883d0d_5253fe87_83ffff06_90801370;
|
||||
defparam bootram.RAM3.INIT_2A=256'h800b9015_2398e5ea_800b8415_90732382_82055523_80c07370_cc705454_ed3f80f9;
|
||||
defparam bootram.RAM3.INIT_2B=256'h5199e83f_80c05268_3d705457_ea3d0d88_853d0d04_81b0800c_150c810b_0c800b94;
|
||||
defparam bootram.RAM3.INIT_2C=256'h38741670_09810694_7381aa2e_ff2e9d38_51547381_74177033_9d055755_80028405;
|
||||
defparam bootram.RAM3.INIT_2D=256'h0c983d0d_80547380_7527d138_811555be_81548b39_81068538_81992e09_33515473;
|
||||
defparam bootram.RAM3.INIT_2E=256'h3f800875_73519ef8_80e6cc52_80558453_5199983f_54845279_863d7054_04f93d0d;
|
||||
defparam bootram.RAM3.INIT_2F=256'h80e6d051_0d92d63f_0c04fc3d_0b81e094_3d0d0481_74800c89_83388155_2e098106;
|
||||
defparam bootram.RAM3.INIT_30=256'hb408708d_e33f81b8_3f80518d_5255e5b4_5380e6f0_81ff0670_ed3f8008_dbcb3f8e;
|
||||
defparam bootram.RAM3.INIT_31=256'h800a51fe_db933f98_80e7c051_3974b738_88518187_883880e7_51515473_2a708106;
|
||||
defparam bootram.RAM3.INIT_32=256'h98800a51_b13f7452_82ac51e0_518da93f_daff3f81_80e7ec51_802e9c38_af3f8008;
|
||||
defparam bootram.RAM3.INIT_33=256'hd03f8380_e8cc51da_2ebd3880_3f800880_0a51fed1_e43f8c80_e8a451da_83f93f80;
|
||||
defparam bootram.RAM3.INIT_34=256'h3f80e99c_f13ffed3_82ac51df_51daba3f_3f80e8f8_0a5197db_ff528c80_805380ff;
|
||||
defparam bootram.RAM3.INIT_35=256'h0d047180_943f863d_e9d851da_3f883980_805183ab_e13f8052_82ac51df_51daaa3f;
|
||||
defparam bootram.RAM3.INIT_36=256'h3f725272_a451e3ec_735280ea_3880c053_87e82e84_54a05373_fd3d0d75_f9e40c04;
|
||||
defparam bootram.RAM3.INIT_37=256'h51d89c3f_0da05280_0d04fe3d_722d853d_85387351_5372802e_80f9e408_51d8b83f;
|
||||
defparam bootram.RAM3.INIT_38=256'h0d9a518d_0d04fc3d_722d843d_85388051_5372802e_80f9e408_51d8943f_80c05280;
|
||||
defparam bootram.RAM3.INIT_39=256'h06535580_80088680_ec38820b_71802e80_53548155_70810651_8008862a_ac3fff0b;
|
||||
defparam bootram.RAM3.INIT_3A=256'h802e8338_e8547184_388a3987_71802e8e_8a388a54_71828024_802e9b38_e4547182;
|
||||
defparam bootram.RAM3.INIT_3B=256'h0780eb9c_70830672_80088a2c_882a8c06_8cdf3f71_08528551_8ce73f80_ff548451;
|
||||
defparam bootram.RAM3.INIT_3C=256'h5252d8ad_eed41108_2b8c0680_943f7182_515452d8_eadc5553_f9f00c80_11337080;
|
||||
defparam bootram.RAM3.INIT_3D=256'hb93f9e39_06a338fe_812e0981_2ea63874_e80c7482_387480f9_e8082e98_3f7480f9;
|
||||
defparam bootram.RAM3.INIT_3E=256'h3f99518b_7351fde8_0cfe9f3f_7380f9ec_082e8e38_7380f9ec_81069638_74822e09;
|
||||
defparam bootram.RAM3.INIT_3F=256'hec0c9951_ff0b80f9_80f9e80c_c13f800b_8008518b_0dd4d43f_0d04fd3d_ec3f863d;
|
||||
defparam bootram.RAM4.INIT_00=256'h518bae3f_de943f84_9a528451_8bec3fbe_80529c51_f53f81ae_5298518b_8bcb3f8d;
|
||||
defparam bootram.RAM4.INIT_01=256'h08537352_2e8d3880_3f738008_84518b99_518bcf3f_70535484_07f49f06_80089080;
|
||||
defparam bootram.RAM4.INIT_02=256'h3d0d7cd0_3d0d04f6_8ba83f85_07528051_80088480_518b823f_e1823f80_80eaf451;
|
||||
defparam bootram.RAM4.INIT_03=256'h51dc8b3f_710c578a_82c08072_83ffff52_0a075956_0a0681d0_0a077ed0_0a0681d0;
|
||||
defparam bootram.RAM4.INIT_04=256'hed3f80e1_0c7851db_82d4e677_f93f8a59_0c8a51db_81ab9977_51dc833f_71770c8a;
|
||||
defparam bootram.RAM4.INIT_05=256'h2a077183_82067187_0670852a_067081ff_7583ffff_51dbdf3f_86770c78_805a8199;
|
||||
defparam bootram.RAM4.INIT_06=256'h0676852b_077081ff_06717307_74832ba0_73109006_71730707_812a8806_2a840672;
|
||||
defparam bootram.RAM4.INIT_07=256'h71832a84_71872a07_852a8206_7a882a70_73730707_70818006_872b6306_80c00677;
|
||||
defparam bootram.RAM4.INIT_08=256'h852b80c0_81ff0676_73070770_2ba00671_90067483_07077310_88067173_0672812a;
|
||||
defparam bootram.RAM4.INIT_09=256'h586b4452_6d0c5151_83ffff06_2b7b0770_07077088_80067373_6d067081_0677872b;
|
||||
defparam bootram.RAM4.INIT_0A=256'hdaac3f75_770c7851_3f819981_5653dab6_5752575d_58525351_5a555b51_53515752;
|
||||
defparam bootram.RAM4.INIT_0B=256'h71832a84_71872a07_852a8206_81ff0670_70730770_7081ff06_0676902a_902a9680;
|
||||
defparam bootram.RAM4.INIT_0C=256'h852b80c0_81ff0676_73070770_2ba00671_90067483_07077310_88067173_0672812a;
|
||||
defparam bootram.RAM4.INIT_0D=256'h872b0770_06710772_852b80c0_10900671_7a882a70_7081ff06_78872b07_06707207;
|
||||
defparam bootram.RAM4.INIT_0E=256'h52d9ab3f_57515157_58525a5a_51555351_67405b51_680c5156_80067407_882b83fe;
|
||||
defparam bootram.RAM4.INIT_0F=256'h71872a07_852a8206_81ff0670_ffff0670_9d3f7783_0c7851d9_81998577_81a18056;
|
||||
defparam bootram.RAM4.INIT_10=256'h81ff0676_73070770_2ba00671_90067483_07077310_88067173_0672812a_71832a84;
|
||||
defparam bootram.RAM4.INIT_11=256'h2a077183_82067187_2a70852a_07077a88_80067373_7f067081_0677872b_852b80c0;
|
||||
defparam bootram.RAM4.INIT_12=256'h0676852b_077081ff_06717307_74832ba0_73109006_71730707_812a8806_2a840672;
|
||||
defparam bootram.RAM4.INIT_13=256'h5151586b_ff066d0c_077083ff_70882b7b_73730707_70818006_872b6906_80c00677;
|
||||
defparam bootram.RAM4.INIT_14=256'h9983770c_c1805581_d7f43f81_575c5653_53515752_5b515852_57525a55_44525351;
|
||||
defparam bootram.RAM4.INIT_15=256'h82067187_0670852a_077081ff_ff067073_902a7081_96800678_3f77902a_7851d7e6;
|
||||
defparam bootram.RAM4.INIT_16=256'h077081ff_06717307_74832ba0_73109006_71730707_812a8806_2a840672_2a077183;
|
||||
defparam bootram.RAM4.INIT_17=256'h852b80c0_10900671_7a882a70_73730707_70818006_872b6106_80c00677_0676852b;
|
||||
defparam bootram.RAM4.INIT_18=256'h5b515852_69425a54_6a0c5152_83ffff06_2b750770_07077088_66067173_0672872b;
|
||||
defparam bootram.RAM4.INIT_19=256'h7851d6ca_3f80770c_5252d6d2_70780c79_dd3f9985_515952d6_5a5b5751_53515852;
|
||||
defparam bootram.RAM4.INIT_1A=256'h3f71770c_5252d6ae_70780c79_b93f8880_0c7851d6_3f80f077_7851d6c2_3f71770c;
|
||||
defparam bootram.RAM4.INIT_1B=256'h8254873d_04fb3d0d_3f8c3d0d_7851d696_3f71770c_7851d69e_3f71770c_7851d6a6;
|
||||
defparam bootram.RAM4.INIT_1C=256'h80d73d08_80d53d08_ffb23d0d_873d0d04_3d22800c_839a3f86_5280d051_fc055380;
|
||||
defparam bootram.RAM4.INIT_1D=256'h9f165675_81ac39ff_51da913f_5280ebac_77538294_93269038_59577782_84120858;
|
||||
defparam bootram.RAM4.INIT_1E=256'h398cf33f_085e818c_ca3f8008_80c15ccd_56750804_80ebf805_38758429_962681a2;
|
||||
defparam bootram.RAM4.INIT_1F=256'h80ea3990_5e80d65c_83ffff06_883f8008_80fa39ff_5f80c65c_f73f8008_80085e8c;
|
||||
defparam bootram.RAM4.INIT_20=256'h0881ff06_8ae53f80_80faa051_5c80d539_a03f80c5_faa0518a_17085280_1708538c;
|
||||
defparam bootram.RAM4.INIT_21=256'h873f80d7_17085189_1708528c_94175390_c25cb939_5cbe3980_863880c4_5675802e;
|
||||
defparam bootram.RAM4.INIT_22=256'h5c805280_8f3980d3_3f80d25c_08518c93_08528c17_05539017_d03dfe80_5ca63980;
|
||||
defparam bootram.RAM4.INIT_23=256'h3d790557_771980d2_833d5a58_0554800b_d03dfdec_82945580_8339a05c_51f7f83f;
|
||||
defparam bootram.RAM4.INIT_24=256'h80ecd451_04803d0d_80d03d0d_51e1aa3f_38838082_887826ec_34811858_57753377;
|
||||
defparam bootram.RAM4.INIT_25=256'h38758117_807425b7_ff165654_57575874_7c7f7f5a_f83d0d7a_5183873f_ce833fff;
|
||||
defparam bootram.RAM4.INIT_26=256'h0651d1b3_527781ff_8a3dfc05_05348253_028405a1_81055833_3d347670_5754738a;
|
||||
defparam bootram.RAM4.INIT_27=256'hfa3d0d02_8a3d0d04_5473800c_38c13981_73802e85_51d39f3f_ff06548a_3f800881;
|
||||
defparam bootram.RAM4.INIT_28=256'h51ff893f_f75280d0_fc055381_8154883d_75883d34_8338dc56_80de5674_a3053355;
|
||||
defparam bootram.RAM4.INIT_29=256'h5256d0d3_a7053370_fc055202_8153893d_33893d34_5702ab05_f93d0d7c_883d0d04;
|
||||
defparam bootram.RAM4.INIT_2A=256'h800881ff_51ced53f_537b5275_25973876_9e388077_5473802e_ff067056_3f800881;
|
||||
defparam bootram.RAM4.INIT_2B=256'h81f75280_3dfc0553_0d815488_0d04fa3d_800c893d_38815574_73802e83_06705654;
|
||||
defparam bootram.RAM4.INIT_2C=256'h56567480_0b883d33_3f953980_e051ccb9_8a3880ec_ff065574_3f800881_d051ffa0;
|
||||
defparam bootram.RAM4.INIT_2D=256'hc0800ca6_80eb0b81_81c0940c_0d04990b_800c883d_56755574_06833881_de2e0981;
|
||||
defparam bootram.RAM4.INIT_2E=256'h0c51820b_0781c098_80067081_72882bbe_04803d0d_81c0b00c_0c89b00b_0b81c0ac;
|
||||
defparam bootram.RAM4.INIT_2F=256'h0d04803d_800c823d_81c0a808_5170f138_81065151_70812a70_81c0a408_81c0a00c;
|
||||
defparam bootram.RAM4.INIT_30=256'ha4087081_a00c81c0_840b81c0_81c09c0c_980c5173_810781c0_be800670_0d72882b;
|
||||
defparam bootram.RAM4.INIT_31=256'h57719138_06555557_7a7c7283_fa3d0d78_0d04ff39_f138823d_51515170_2a708106;
|
||||
defparam bootram.RAM4.INIT_32=256'h75279438_72555573_3f72822a_815189b2_802e8638_83065271_718a3872_75830652;
|
||||
defparam bootram.RAM4.INIT_33=256'h842a708f_3d0d7470_3d0d04fe_54e93988_54528114_08720c52_11771270_73822b77;
|
||||
defparam bootram.RAM4.INIT_34=256'h0d04fe3d_c03f843d_335253c9_80ed8011_3f728f06_5353c9cd_11335451_0680ed80;
|
||||
defparam bootram.RAM4.INIT_35=256'h3880ed90_135372e9_2e8e38ff_51527180_70810651_0870882a_5382e090_0d8386d0;
|
||||
defparam bootram.RAM4.INIT_36=256'h55558386_80c08007_8c800607_80ff067c_9b05337a_fc3d0d02_843d0d04_51ca8a3f;
|
||||
defparam bootram.RAM4.INIT_37=256'h9051c9cd_e93880ed_ff135372_802e8e38_51515271_2a708106_90087088_d05382e0;
|
||||
defparam bootram.RAM4.INIT_38=256'h5274802e_e0900c74_82800782_e0980c73_81ff0682_e0900c77_800c7382_3f7882e0;
|
||||
defparam bootram.RAM4.INIT_39=256'he93880ed_ff135372_802e8e38_51515271_2a708106_90087088_d05382e0_a9388386;
|
||||
defparam bootram.RAM4.INIT_3A=256'h55885480_940c8880_810b82e0_04fc3d0d_0c863d0d_08527180_3f82e080_9051c989;
|
||||
defparam bootram.RAM4.INIT_3B=256'hcb3f8008_528151fe_8a805381_80559054_fc3d0d88_863d0d04_51fee13f_53805280;
|
||||
defparam bootram.RAM4.INIT_3C=256'h0d04803d_af3f863d_528051fe_54865381_88805588_04fc3d0d_0c863d0d_81ff0680;
|
||||
defparam bootram.RAM4.INIT_3D=256'h2ef43882_06517080_800881ff_3d0deb3f_3d0d0480_06800c82_08813281_0dca3f80;
|
||||
defparam bootram.RAM4.INIT_3E=256'hfe9b0a06_55a05475_b43f8880_38dd3fff_8008269b_85923f75_3d0d7756_3d0d04fb;
|
||||
defparam bootram.RAM4.INIT_3F=256'h11565757_cb3d08ff_c93d0880_ba3d0d80_3d0d04ff_fdde3f87_81528051_9b0a0753;
|
||||
defparam bootram.RAM5.INIT_00=256'h883d7052_5381ff52_a7388280_80082681_84ce3f73_38751754_ff2681b4_80557381;
|
||||
defparam bootram.RAM5.INIT_01=256'h980c8880_3f7482e0_d43ffce6_fefd3ffe_518b993f_3d085273_755380cb_548cbe3f;
|
||||
defparam bootram.RAM5.INIT_02=256'he0900c8a_88a00b82_82e0980c_800c810b_0a0782e0_0a0680c0_0c76fec0_0b82e090;
|
||||
defparam bootram.RAM5.INIT_03=256'h700882e0_54fe8415_82e08c0c_80157008_558f56fe_3f80c83d_900cfcb6_a00b82e0;
|
||||
defparam bootram.RAM5.INIT_04=256'h900c8a80_800b82e0_800c5488_700882e0_54fe8c15_82e0840c_88157008_880c54fe;
|
||||
defparam bootram.RAM5.INIT_05=256'h74800c80_980c8155_800b82e0_25ffbc38_56567580_ff169016_0cfbf73f_0b82e090;
|
||||
defparam bootram.RAM5.INIT_06=256'h81577480_2680cb38_57738008_838a3f80_575a5656_7b7d7212_f93d0d79_c83d0d04;
|
||||
defparam bootram.RAM5.INIT_07=256'h77537352_83387654_57767527_74317555_a2388280_5473802e_7581ff06_2e80c338;
|
||||
defparam bootram.RAM5.INIT_08=256'h828054dc_7527e138_74548280_802e8e38_57595674_19767631_3f731674_7551fdeb;
|
||||
defparam bootram.RAM5.INIT_09=256'h1354829c_2e8d3873_54557380_76787a56_04fc3d0d_0c893d0d_81577680_39fd8c3f;
|
||||
defparam bootram.RAM5.INIT_0A=256'h707406ff_3f800830_a63981fa_0c80750c_800b8416_0b88160c_27903880_3f800874;
|
||||
defparam bootram.RAM5.INIT_0B=256'h3d0d04fd_fcc93f86_160c7151_160c7188_0c740684_08307276_81ec3f80_16565152;
|
||||
defparam bootram.RAM5.INIT_0C=256'h2e943881_08841508_81538814_802e9f38_70545271_0881ff06_fc983f80_3d0d7554;
|
||||
defparam bootram.RAM5.INIT_0D=256'h888055a0_04fc3d0d_0c853d0d_80537280_51fc943f_7088160c_08800805_b13f8814;
|
||||
defparam bootram.RAM5.INIT_0E=256'hf9f40855_fb3d0d80_863d0d04_0a06800c_8008fe80_51f9fd3f_53815281_5481f90a;
|
||||
defparam bootram.RAM5.INIT_0F=256'h5154cdc8_edac5458_56715580_81ff0670_ff068008_882a7081_d43f8008_7480c238;
|
||||
defparam bootram.RAM5.INIT_10=256'h883f9c39_edc451c3_2e8a3880_06547380_93387481_7380c02e_83388155_3f73a02e;
|
||||
defparam bootram.RAM5.INIT_11=256'hdc3f7480_cd8e3ff4_80ede451_8d387452_55827427_08ea1155_0c80f9f4_7580f9f4;
|
||||
defparam bootram.RAM5.INIT_12=256'hfefa3f81_2b800c04_810b8008_0c04f23f_ce053380_800880ee_04ff913f_0c873d0d;
|
||||
defparam bootram.RAM5.INIT_13=256'h8b0b82e0_82e0900c_0c88800b_0b82e098_f8b03f80_3d0d7d56_800c04f6_0b80082b;
|
||||
defparam bootram.RAM5.INIT_14=256'h0cf7ff3f_0b82e090_900c8aa8_a80b82e0_e0980c88_0c810b82_2b82e080_840c7c88;
|
||||
defparam bootram.RAM5.INIT_15=256'he08c0858_f7e43f82_82e0900c_0c8a800b_0b82e090_d3388880_73762780_7e558054;
|
||||
defparam bootram.RAM5.INIT_16=256'h38705380_70732783_52579053_3d767531_80085b88_085a82e0_5982e084_82e08808;
|
||||
defparam bootram.RAM5.INIT_17=256'h800b82e0_54ffa939_ec397214_34811252_70810557_51703375_91387117_52717327;
|
||||
defparam bootram.RAM5.INIT_18=256'h08528c08_8c088c05_3d0d8053_028c0cfd_a13f8c08_0d7251f6_0d04803d_980c8c3d;
|
||||
defparam bootram.RAM5.INIT_19=256'h538c088c_fd3d0d81_08028c0c_8c0c048c_54853d0d_0870800c_82de3f80_88050851;
|
||||
defparam bootram.RAM5.INIT_1A=256'h0cf93d0d_8c08028c_0d8c0c04_0c54853d_80087080_5182b93f_08880508_0508528c;
|
||||
defparam bootram.RAM5.INIT_1B=256'h0b8c08f4_88050c80_08308c08_8c088805_8025ab38_08880508_fc050c8c_800b8c08;
|
||||
defparam bootram.RAM5.INIT_1C=256'h8c050880_050c8c08_088c08fc_8c08f405_08f4050c_38810b8c_fc050888_050c8c08;
|
||||
defparam bootram.RAM5.INIT_1D=256'h810b8c08_05088838_0c8c08fc_8c08f005_050c800b_308c088c_088c0508_25ab388c;
|
||||
defparam bootram.RAM5.INIT_1E=256'ha73f8008_05085181_528c0888_088c0508_0c80538c_8c08fc05_08f00508_f0050c8c;
|
||||
defparam bootram.RAM5.INIT_1F=256'h08f80508_f8050c8c_08308c08_8c08f805_802e8c38_08fc0508_050c548c_708c08f8;
|
||||
defparam bootram.RAM5.INIT_20=256'h05088025_0c8c0888_8c08fc05_3d0d800b_028c0cfb_0c048c08_893d0d8c_70800c54;
|
||||
defparam bootram.RAM5.INIT_21=256'h388c088c_0880258c_8c088c05_08fc050c_0c810b8c_8c088805_88050830_93388c08;
|
||||
defparam bootram.RAM5.INIT_22=256'h08f8050c_8008708c_0851ad3f_8c088805_8c050852_81538c08_088c050c_0508308c;
|
||||
defparam bootram.RAM5.INIT_23=256'h0c54873d_05087080_0c8c08f8_8c08f805_f8050830_8c388c08_0508802e_548c08fc;
|
||||
defparam bootram.RAM5.INIT_24=256'h8c05088c_050c8c08_0b8c08f8_fc050c80_810b8c08_0cfd3d0d_8c08028c_0d8c0c04;
|
||||
defparam bootram.RAM5.INIT_25=256'h8c050810_99388c08_8c050824_800b8c08_802ea338_08fc0508_27ac388c_08880508;
|
||||
defparam bootram.RAM5.INIT_26=256'h8c088c05_2e80c938_fc050880_c9398c08_08fc050c_0508108c_0c8c08fc_8c088c05;
|
||||
defparam bootram.RAM5.INIT_27=256'h05088c08_0c8c08f8_8c088805_8c050831_05088c08_388c0888_050826a1_088c0888;
|
||||
defparam bootram.RAM5.INIT_28=256'h8c088c05_0508812a_0c8c088c_8c08fc05_0508812a_0c8c08fc_8c08f805_fc050807;
|
||||
defparam bootram.RAM5.INIT_29=256'h08f80508_518d398c_08f4050c_0508708c_388c0888_08802e8f_8c089005_0cffaf39;
|
||||
defparam bootram.RAM5.INIT_2A=256'h52837227_77795656_fc3d0d78_0d8c0c04_800c853d_08f40508_050c518c_708c08f4;
|
||||
defparam bootram.RAM5.INIT_2B=256'h712e0981_33525372_38743374_71ff2ea0_38ff1252_70802eb0_07830651_8c387474;
|
||||
defparam bootram.RAM5.INIT_2C=256'h74745451_863d0d04_800b800c_8106e238_71ff2e09_14545555_158115ff_06bd3881;
|
||||
defparam bootram.RAM5.INIT_2D=256'hffaf3972_70735555_8326e938_54545171_8414fc14_8f388411_2e098106_70087308;
|
||||
defparam bootram.RAM5.INIT_2E=256'h06517080_72750783_72278c38_5555558f_70797b55_fc3d0d76_863d0d04_7131800c;
|
||||
defparam bootram.RAM5.INIT_2F=256'h2e098106_125271ff_055634ff_33747081_70810554_2e983872_125271ff_2ea738ff;
|
||||
defparam bootram.RAM5.INIT_30=256'h08717084_70840554_05530c72_08717084_70840554_04745172_0c863d0d_ea387480;
|
||||
defparam bootram.RAM5.INIT_31=256'h1252718f_05530cf0_08717084_70840554_05530c72_08717084_70840554_05530c72;
|
||||
defparam bootram.RAM5.INIT_32=256'h7054ff83_8326ed38_fc125271_8405530c_54087170_72708405_72279538_26c93883;
|
||||
defparam bootram.RAM5.INIT_33=256'h2ea238ff_06517080_8a387483_55837227_33575553_8c059f05_76797102_39fc3d0d;
|
||||
defparam bootram.RAM5.INIT_34=256'h863d0d04_3874800c_098106ef_5271ff2e_5534ff12_73708105_2e933873_125271ff;
|
||||
defparam bootram.RAM5.INIT_35=256'h70840553_530c7271_71708405_27a53872_54518f72_902b0751_75077071_7474882b;
|
||||
defparam bootram.RAM5.INIT_36=256'h72717084_72279038_26dd3883_1252718f_05530cf0_72717084_8405530c_0c727170;
|
||||
defparam bootram.RAM5.INIT_37=256'h802e80d9_55555272_7a7c7054_fa3d0d78_53ff9039_26f23870_12527183_05530cfc;
|
||||
defparam bootram.RAM5.INIT_38=256'h712e0981_33565174_38713374_72ff2eb1_38ff1353_802e80d4_83065170_38717407;
|
||||
defparam bootram.RAM5.INIT_39=256'h5272ff2e_ff155555_81128115_2e80fc38_06517080_387081ff_802e8187_06a93872;
|
||||
defparam bootram.RAM5.INIT_3A=256'h883d0d04_5270800c_71315152_81ff0671_81ff0675_33565170_38713374_098106d1;
|
||||
defparam bootram.RAM5.INIT_3B=256'h2eb13874_13537280_ff9739fc_74765552_082e8838_38710874_83732788_71745755;
|
||||
defparam bootram.RAM5.INIT_3C=256'h837327d0_84175755_9a388415_51515170_82818006_0670f884_fbfdff12_087009f7;
|
||||
defparam bootram.RAM5.INIT_3D=256'h80eea408_3d0d800b_3d0d04fd_0b800c88_fedf3980_74765552_082ed038_38740876;
|
||||
defparam bootram.RAM5.INIT_3E=256'h9d3f8008_8151ffb0_80eee852_ffa8ad3f_ffa9913f_80f9f80c_2e9e3873_54547281;
|
||||
defparam bootram.RAM5.INIT_3F=256'h0851f686_b0803f80_528151ff_3f80eee8_3fffa890_0cffa8f4_7280f9f8_51f6a33f;
|
||||
defparam bootram.RAM6.INIT_00=256'h525270ff_fc127008_9138702d_5270ff2e_05700852_eef00bfc_ff3d0d80_3f00ff39;
|
||||
defparam bootram.RAM6.INIT_01=256'h6e20636f_6f722069_21457272_00000040_a99f3f04_0d0404ff_f138833d_2e098106;
|
||||
defparam bootram.RAM6.INIT_02=256'h65642063_70656374_3a204578_646c6572_2068616e_636b6574_6c207061_6e74726f;
|
||||
defparam bootram.RAM6.INIT_03=256'h676f7420_62757420_25642c20_62657220_206e756d_6c697479_74696269_6f6d7061;
|
||||
defparam bootram.RAM6.INIT_04=256'h2068616e_636b6574_6c207061_6e74726f_6e20636f_6f722069_21457272_25640a00;
|
||||
defparam bootram.RAM6.INIT_05=256'h68202564_656e6774_6164206c_61796c6f_65642070_70656374_3a204578_646c6572;
|
||||
defparam bootram.RAM6.INIT_06=256'h616e6765_6b206368_206c696e_0a657468_0a000000_74202564_7420676f_2c206275;
|
||||
defparam bootram.RAM6.INIT_07=256'h44502062_31302055_50204e32_0a555352_640a0000_203d2025_70656564_643a2073;
|
||||
defparam bootram.RAM6.INIT_08=256'h7479206e_62696c69_70617469_20636f6d_46504741_720a0000_6f616465_6f6f746c;
|
||||
defparam bootram.RAM6.INIT_09=256'h62696c69_70617469_20636f6d_77617265_4669726d_640a0000_723a2025_756d6265;
|
||||
defparam bootram.RAM6.INIT_0A=256'h69702072_476f7420_00000000_61646472_640a0000_723a2025_756d6265_7479206e;
|
||||
defparam bootram.RAM6.INIT_0B=256'h0000078f_000006df_000006f6_00000000_65743a20_7061636b_65727920_65636f76;
|
||||
defparam bootram.RAM6.INIT_0C=256'h00000713_0000078f_0000078f_0000078f_0000078f_0000078f_00000765_0000078f;
|
||||
defparam bootram.RAM6.INIT_0D=256'h0000067a_0000078f_0000078f_0000078f_0000078f_0000066d_0000078f_000006a7;
|
||||
defparam bootram.RAM6.INIT_0E=256'h20636869_4c4d5331_00000753_00000746_0000073f_00000738_00000733_0000072e;
|
||||
defparam bootram.RAM6.INIT_0F=256'h70207665_20636869_4c4d5332_0a000000_30782578_6e203d20_7273696f_70207665;
|
||||
defparam bootram.RAM6.INIT_10=256'h15290a94_3fff0000_0050c285_c0a80a02_0a000000_30782578_6e203d20_7273696f;
|
||||
defparam bootram.RAM6.INIT_11=256'h696c6564_47206661_4348444f_20574154_72656164_6932635f_01c300e2_054a0387;
|
||||
defparam bootram.RAM6.INIT_12=256'h61696c65_4f472066_54434844_72205741_5f786665_5f666f72_77616974_21000000;
|
||||
defparam bootram.RAM6.INIT_13=256'h64210000_61696c65_4f472066_54434844_65205741_77726974_6932635f_64210000;
|
||||
defparam bootram.RAM6.INIT_14=256'h43444546_38394142_34353637_30313233_2e256400_642e2564_25642e25_45000000;
|
||||
defparam bootram.RAM6.INIT_15=256'h69676e6d_6420616c_3a206261_5f706b74_73656e64_ffff0000_ffffffff_00000000;
|
||||
defparam bootram.RAM6.INIT_16=256'h636f6d6d_6e65745f_66000000_72206275_6e642f6f_656e2061_6f66206c_656e7420;
|
||||
defparam bootram.RAM6.INIT_17=256'h696e6720_6c6f6f6b_63686520_74206361_6f206869_65642074_6661696c_6f6e3a20;
|
||||
defparam bootram.RAM6.INIT_18=256'h697a6520_72642073_20776569_6172703a_646c655f_0a68616e_00000000_666f7220;
|
||||
defparam bootram.RAM6.INIT_19=256'h67746873_206c656e_74656e74_6e736973_696e636f_55445020_0a000000_3d202564;
|
||||
defparam bootram.RAM6.INIT_1A=256'h73206265_68206861_466c6173_53504920_0b0b0b0b_00000000_2025640a_3a202564;
|
||||
defparam bootram.RAM6.INIT_1B=256'h6d616765_6f6e2069_75637469_50726f64_65640000_616c697a_6e697469_656e2069;
|
||||
defparam bootram.RAM6.INIT_1C=256'h61666520_696e2073_50322b20_20555352_74696e67_53746172_640a0000_203d2025;
|
||||
defparam bootram.RAM6.INIT_1D=256'h00000000_6172652e_69726d77_66652066_67207361_6164696e_2e204c6f_6d6f6465;
|
||||
defparam bootram.RAM6.INIT_1E=256'h6e204650_6374696f_726f6475_69642070_2076616c_20666f72_6b696e67_43686563;
|
||||
defparam bootram.RAM6.INIT_1F=256'h20465047_74696f6e_6f647563_64207072_56616c69_2e2e2e00_6d616765_47412069;
|
||||
defparam bootram.RAM6.INIT_20=256'h20626f6f_6720746f_7074696e_7474656d_642e2041_666f756e_61676520_4120696d;
|
||||
defparam bootram.RAM6.INIT_21=256'h20696d61_46504741_696f6e20_64756374_2070726f_616c6964_4e6f2076_742e0000;
|
||||
defparam bootram.RAM6.INIT_22=256'h20666972_74696f6e_6f647563_64207072_56616c69_2e0a0000_6f756e64_67652066;
|
||||
defparam bootram.RAM6.INIT_23=256'h73686564_46696e69_2e2e2e00_64696e67_204c6f61_756e642e_6520666f_6d776172;
|
||||
defparam bootram.RAM6.INIT_24=256'h4552524f_2e000000_6d616765_6e672069_61727469_2e205374_64696e67_206c6f61;
|
||||
defparam bootram.RAM6.INIT_25=256'h20546869_72616d21_70726f67_61696e20_6f6d206d_6e206672_65747572_523a2052;
|
||||
defparam bootram.RAM6.INIT_26=256'h616c6964_4e6f2076_6e210000_61707065_65722068_206e6576_6f756c64_73207368;
|
||||
defparam bootram.RAM6.INIT_27=256'h46616c6c_6e642e20_20666f75_77617265_6669726d_696f6e20_64756374_2070726f;
|
||||
defparam bootram.RAM6.INIT_28=256'h77617265_6669726d_2d696e20_75696c74_746f2062_75676820_7468726f_696e6720;
|
||||
defparam bootram.RAM6.INIT_29=256'h00000000_4e4f4e45_00000000_2025640a_7420746f_64207365_53706565_2e000000;
|
||||
defparam bootram.RAM6.INIT_2A=256'h65746865_43000000_45545249_53594d4d_58000000_57455f52_58000000_57455f54;
|
||||
defparam bootram.RAM6.INIT_2B=256'h4e45475f_4155544f_5048595f_6c3a2000_6e74726f_7720636f_20666c6f_726e6574;
|
||||
defparam bootram.RAM6.INIT_2C=256'h00000000_780a0000_20307825_20676f74_7825782c_74652030_2077726f_4144563a;
|
||||
defparam bootram.RAM6.INIT_2D=256'h20706163_64617465_6e207570_6f722069_21457272_00030203_00000001_00030003;
|
||||
defparam bootram.RAM6.INIT_2E=256'h64206c65_796c6f61_64207061_65637465_20457870_6c65723a_68616e64_6b657420;
|
||||
defparam bootram.RAM6.INIT_2F=256'h00002466_000023d0_00000000_2025640a_20676f74_20627574_2025642c_6e677468;
|
||||
defparam bootram.RAM6.INIT_30=256'h00002466_00002466_00002466_00002466_000023dd_000023ff_00002414_00002466;
|
||||
defparam bootram.RAM6.INIT_31=256'h00002443_00002466_00002466_00002466_00002466_00002466_00002466_00002466;
|
||||
defparam bootram.RAM6.INIT_32=256'h00000000_6f72740a_0a0a6162_00002430_000023ef_00002466_00002466_0000245a;
|
||||
defparam bootram.RAM6.INIT_33=256'h67000000_20666c61_626f6f74_61666520_61642073_6f207265_65642074_4661696c;
|
||||
defparam bootram.RAM6.INIT_34=256'h54434844_74205741_5f776169_73706966_43444546_38394142_34353637_30313233;
|
||||
defparam bootram.RAM6.INIT_35=256'h697a653d_25642073_7970653d_73682074_0a666c61_64210000_61696c65_4f472066;
|
||||
defparam bootram.RAM6.INIT_36=256'h6e67210a_63687475_652e2041_20747970_6c617368_6e672066_0a57726f_25640a00;
|
||||
defparam bootram.RAM6.INIT_37=256'h6874756e_64204163_653a2025_2073697a_6c617368_6e672066_0a57726f_00000000;
|
||||
defparam bootram.RAM6.INIT_38=256'hffffff00_ffff00ff_ff00ffff_00ffffff_65000000_792e6578_64756d6d_67210a00;
|
||||
defparam bootram.RAM6.INIT_39=256'h01010100_3fff0000_0050c285_c0a80a02_00003778_00000000_00000000_00000000;
|
||||
defparam bootram.RAM6.INIT_3A=256'h00003548_00003540_00003538_03197500_000c0000_00190010_ffff0033_04000400;
|
||||
defparam bootram.RAM6.INIT_3B=256'h00000000_00000000_ffffffff_00000000_ffffffff_00003704_10101200_00003550;
|
||||
defparam bootram.RAM6.INIT_3C=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM6.INIT_3D=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM6.INIT_3E=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM6.INIT_3F=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM7.INIT_00=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM7.INIT_01=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM7.INIT_02=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM7.INIT_03=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM0.INIT_30=256'h5a588379_84120859_3d0d686a_3d0d04ee_9ef83f94_7c26ef38_811c5c86_79337b34;
|
||||
defparam bootram.RAM0.INIT_31=256'hf55778a3_99e63f80_80e3b451_8c537552_802e8c38_2e943875_0856758c_279c3877;
|
||||
defparam bootram.RAM0.INIT_32=256'h75922682_ff981756_8818085d_8c5ba05c_d33fa057_e4985199_53a45280_268e3878;
|
||||
defparam bootram.RAM0.INIT_33=256'h5c8c1808_cc3980da_08085e82_8bbe3f80_0480d55c_05567508_2980e698_e2387584;
|
||||
defparam bootram.RAM0.INIT_34=256'hff065f82_800883ff_04b48b3f_05567508_2980e6e4_bc387584_75862682_5eff1e56;
|
||||
defparam bootram.RAM0.INIT_35=256'h56b3c13f_2a545151_7107709f_30901a08_90180870_3f829a39_2251b3de_a4399218;
|
||||
defparam bootram.RAM0.INIT_36=256'h18335682_81eb3995_3f80085f_8439b3ea_39b3e83f_b3e63f89_e43f8e39_828339b3;
|
||||
defparam bootram.RAM0.INIT_37=256'h57577577_0b971933_18085280_1808538c_18335490_57765596_2e833884_577580f2;
|
||||
defparam bootram.RAM0.INIT_38=256'h538c1933_953dea05_18337054_81b3398d_5f80d35c_ad3f8008_5776519a_2e833881;
|
||||
defparam bootram.RAM0.INIT_39=256'h5c750284_d93f80c8_33525690_19538c19_3370548e_94398d18_3f80c95c_52568fa2;
|
||||
defparam bootram.RAM0.INIT_3A=256'h08585675_80058c19_842980e7_80c23875_56758526_1833ff05_80ff3994_05b50534;
|
||||
defparam bootram.RAM0.INIT_3B=256'h2980f194_9b397684_18227723_0ca23992_90180877_225fa939_5fae3976_08047608;
|
||||
defparam bootram.RAM0.INIT_3C=256'hcc5c8c18_39785e80_80d25cad_08710c56_94059019_842980f1_568e3976_05700840;
|
||||
defparam bootram.RAM0.INIT_3D=256'h887826ed_34811858_57753377_3d790557_58771996_0b833d5a_dc055480_0855943d;
|
||||
defparam bootram.RAM0.INIT_3E=256'h77348118_57577533_963d7905_5a587719_800b833d_3ddc0554_5ca45594_38a439a0;
|
||||
defparam bootram.RAM0.INIT_3F=256'h96a23f73_e4fc5254_75705380_04fd3d0d_3f943d0d_80519fb3_ed388380_58887826;
|
||||
defparam bootram.RAM1.INIT_00=256'h5273518a_3f9039a0_9c3f9fc0_5272518a_80c05372_e82e8438_a0537387_802e9838;
|
||||
defparam bootram.RAM1.INIT_01=256'h5280e5b0_8b813f89_80e59c51_0d829f3f_0d04f93d_883f853d_5273518a_903f80c0;
|
||||
defparam bootram.RAM1.INIT_02=256'hb3e2939b_f1b00cf8_3f830b80_d05195cc_8c5280e5_9b548353_f8b3e293_5195dd3f;
|
||||
defparam bootram.RAM1.INIT_03=256'h3f86d13f_9c0c82dd_800b81e0_81e09c0c_b43f810b_86cb3f87_0cbafe3f_0b80f1ac;
|
||||
defparam bootram.RAM1.INIT_04=256'hb33f7452_80085586_3f87993f_883f89ee_80085194_3f87a53f_ee3f89fa_80085193;
|
||||
defparam bootram.RAM1.INIT_05=256'h5198fa3f_52838080_be3f8c93_92813f98_52800851_3f838084_b43f8788_80085198;
|
||||
defparam bootram.RAM1.INIT_06=256'h91ec3f8f_51a9a53f_3f838092_825198e5_85528380_f03f80d7_80845198_8ab25283;
|
||||
defparam bootram.RAM1.INIT_07=256'h802e80c9_08578008_91f53f80_3dfc0551_89f53f89_80e5e451_3fbdee3f_f151bbc9;
|
||||
defparam bootram.RAM1.INIT_08=256'h055180ce_52800890_5380e5f4_06ad3884_ee2e0981_567482fd_8e052256_38778008;
|
||||
defparam bootram.RAM1.INIT_09=256'h3f883975_745186c1_3f88cb3f_525592e5_3f941770_fc5193f4_9a3880e5_cb3f8008;
|
||||
defparam bootram.RAM1.INIT_0A=256'hbf3f8fac_95bc3f89_0d88943f_9e39fe3d_8ff43fff_3fa9a13f_983f9182_5276519e;
|
||||
defparam bootram.RAM1.INIT_0B=256'h87b33f82_84528451_518dfd3f_c03f82ac_52805187_87e43f9f_9f528051_3f8abb3f;
|
||||
defparam bootram.RAM1.INIT_0C=256'h8dd63f82_3f82ac51_90518799_e33f9052_82ac518d_5187a63f_3f885288_ac518df0;
|
||||
defparam bootram.RAM1.INIT_0D=256'h13537280_8dba3fff_3f80e451_9c5186fd_c73f9f52_80e4518d_51878a3f_539f5280;
|
||||
defparam bootram.RAM1.INIT_0E=256'h81e08056_04fb3d0d_0c843d0d_3f810b80_815186e1_853f9f52_529e5187_25df389f;
|
||||
defparam bootram.RAM1.INIT_0F=256'h81528151_54888053_0c865590_833f8376_80e4518d_3f80760c_e4518d8c_83760c80;
|
||||
defparam bootram.RAM1.INIT_10=256'h085280e7_949c3f80_82528151_54888053_3f865590_98519294_085280e7_94b43f80;
|
||||
defparam bootram.RAM1.INIT_11=256'h85ea3ff8_823fff51_e7d05187_803d0d80_873d0d04_810b800c_3fac833f_b45191fc;
|
||||
defparam bootram.RAM1.INIT_12=256'h34767081_54738a3d_75811757_7425b738_16565480_575874ff_7f7f5a57_3d0d7a7c;
|
||||
defparam bootram.RAM1.INIT_13=256'h06548a51_800881ff_518a9b3f_7781ff06_3dfc0552_3482538a_8405a105_05583302;
|
||||
defparam bootram.RAM1.INIT_14=256'hde567483_05335580_3d0d02a3_3d0d04fa_73800c8a_c1398154_802e8538_8bf23f73;
|
||||
defparam bootram.RAM1.INIT_15=256'h3d0d7c57_3d0d04f9_ff893f88_5280d051_055381f7_54883dfc_883d3481_38dc5675;
|
||||
defparam bootram.RAM1.INIT_16=256'h06705654_800881ff_5689bb3f_05337052_055202a7_53893dfc_893d3481_02ab0533;
|
||||
defparam bootram.RAM1.INIT_17=256'h802e8338_70565473_0881ff06_87d43f80_7b527551_97387653_38807725_73802e9e;
|
||||
defparam bootram.RAM1.INIT_18=256'h800881ff_51ffa03f_f75280d0_fc055381_8154883d_04fa3d0d_0c893d0d_81557480;
|
||||
defparam bootram.RAM1.INIT_19=256'h83388156_2e098106_567480de_883d3356_9539800b_5185b83f_3880e7dc_0655748a;
|
||||
defparam bootram.RAM1.INIT_1A=256'h883d2270_51fee03f_fc5280d0_fc055381_8254893d_04f93d0d_0c883d0d_75557480;
|
||||
defparam bootram.RAM1.INIT_1B=256'h70565480_7a575781_fa3d0d78_893d0d04_800c5656_83ffff06_80290570_882a7182;
|
||||
defparam bootram.RAM1.INIT_1C=256'h80558113_ff2e8338_33527181_38805471_70802e83_70335252_9e387217_53727627;
|
||||
defparam bootram.RAM1.INIT_1D=256'hb8348653_810b80f1_04fe3d0d_0c883d0d_81517080_802e8338_74075170_53df3974;
|
||||
defparam bootram.RAM1.INIT_1E=256'h0b80f1b8_74bd3881_f1b83355_f93d0d80_843d0d04_80c6f93f_80f0b851_80e88052;
|
||||
defparam bootram.RAM1.INIT_1F=256'h527551fe_2e9d3886_06557480_800881ff_51fdcc3f_825280d0_3d705456_34865487;
|
||||
defparam bootram.RAM1.INIT_20=256'h0c893d0d_f0b80b80_c6ae3f80_f0b85180_53755280_748d3886_81ff0655_f33f8008;
|
||||
defparam bootram.RAM1.INIT_21=256'h0b80f1b4_74b93881_f1b43355_fb3d0d80_f0b40c04_e7fc0880_f1b43480_04810b80;
|
||||
defparam bootram.RAM1.INIT_22=256'h52873dfc_2e993884_06557480_800881ff_51fcec3f_8c5280d0_3dfc0553_34845487;
|
||||
defparam bootram.RAM1.INIT_23=256'h04fb3d0d_0c873d0d_f0b40b80_f0b40c80_86387580_ff065574_3f800881_0551fe90;
|
||||
defparam bootram.RAM1.INIT_24=256'hf0b40c81_38750880_74802e8d_81ff0655_b23f8008_80d051fb_75538c52_77568454;
|
||||
defparam bootram.RAM1.INIT_25=256'hc0ac0c89_0ca60b81_0b81c080_940c80eb_990b81c0_873d0d04_3474800c_0b80f1b4;
|
||||
defparam bootram.RAM1.INIT_26=256'ha00c81c0_820b81c0_c0980c51_70810781_2bbe8006_3d0d7288_b00c0480_b00b81c0;
|
||||
defparam bootram.RAM1.INIT_27=256'h882bbe80_803d0d72_823d0d04_a808800c_f13881c0_51515170_2a708106_a4087081;
|
||||
defparam bootram.RAM1.INIT_28=256'h81065151_70812a70_81c0a408_81c0a00c_9c0c840b_517381c0_81c0980c_06708107;
|
||||
defparam bootram.RAM1.INIT_29=256'hbc080607_067180f1_73097375_3f803d0d_0d7251f8_ff39803d_823d0d04_5170f138;
|
||||
defparam bootram.RAM1.INIT_2A=256'h077080f1_f1c00806_75067180_0d730973_0d04803d_0c51823d_0c81e08c_7080f1bc;
|
||||
defparam bootram.RAM1.INIT_2B=256'h800c843d_81c73f72_53538051_3d0d7470_af3f04fe_3d0d0481_980c5182_c00c81e0;
|
||||
defparam bootram.RAM1.INIT_2C=256'h06545472_337081ff_79565674_fb3d0d77_833d0d04_5181b63f_0d8a5280_0d04ff3d;
|
||||
defparam bootram.RAM1.INIT_2D=256'h3d0d7352_3d0d04ff_0b800c87_3fe53980_52558191_ff065376_81157481_802e9038;
|
||||
defparam bootram.RAM1.INIT_2E=256'h0b800c84_80e73f80_8a527251_53ffbd3f_76537052_fe3d0d74_833d0d04_8051cd3f;
|
||||
defparam bootram.RAM1.INIT_2F=256'h1234823d_3380f0c0_51028f05_803d0d72_833d0d04_8051dd3f_3d0d7352_3d0d04ff;
|
||||
defparam bootram.RAM1.INIT_30=256'hfe3d0d80_833d0d04_720c5351_88057022_751080e8_82908005_0d73a029_0d04ff3d;
|
||||
defparam bootram.RAM1.INIT_31=256'h38843d0d_827325e5_3f811353_527251ce_f0c41333_51c63f80_13335272_5380f0c0;
|
||||
defparam bootram.RAM1.INIT_32=256'h87388d52_2e098106_33537281_80f0c014_81069538_748a2e09_76785654_04fc3d0d;
|
||||
defparam bootram.RAM1.INIT_33=256'h04fe3d0d_0c863d0d_38748c15_72802ef8_84140853_90800554_73a02982_7351de3f;
|
||||
defparam bootram.RAM1.INIT_34=256'h0d04ff3d_800c843d_12085372_2e853890_ff537080_11085252_90800588_74a02982;
|
||||
defparam bootram.RAM1.INIT_35=256'h800b81a8_840c5181_882a81a8_a8800c70_81ff0681_f0cc2270_a8880c80_0d800b81;
|
||||
defparam bootram.RAM1.INIT_36=256'h8386d052_2e81b038_81517280_33565455_88059b05_0d777902_0d04fc3d_880c833d;
|
||||
defparam bootram.RAM1.INIT_37=256'h39731081_7151818f_5271e938_8c38ff12_5170802e_81065151_70862a70_81a89008;
|
||||
defparam bootram.RAM1.INIT_38=256'h5170802e_81065151_70812a70_81a89008_8386d052_81a8900c_0c81900b_0781a88c;
|
||||
defparam bootram.RAM1.INIT_39=256'h80c63872_5170802e_32515151_81067081_70872a70_81a89008_5271e938_8738ff12;
|
||||
defparam bootram.RAM1.INIT_3A=256'h812a7081_a8900870_86d05281_a8900c83_a0517081_812e8338_80e85172_802ebd38;
|
||||
defparam bootram.RAM1.INIT_3B=256'h1353c039_055734ff_70757081_a88c0851_71e93881_38ff1252_70802e87_06515151;
|
||||
defparam bootram.RAM1.INIT_3C=256'h33565455_88059b05_0d777902_0d04fc3d_800c863d_a8900c70_80c00b81_81518839;
|
||||
defparam bootram.RAM1.INIT_3D=256'h715181ad_5271e938_8c38ff12_5170802e_81065151_70862a70_81a89008_8386d052;
|
||||
defparam bootram.RAM1.INIT_3E=256'ha8900870_86d05281_a8900c83_90517081_2e843881_d0517280_a88c0c81_39731081;
|
||||
defparam bootram.RAM1.INIT_3F=256'h06708132_872a7081_a8900870_71e93881_38ff1252_70802e87_06515151_812a7081;
|
||||
defparam bootram.RAM2.INIT_00=256'h83389051_5172812e_8c0c80d0_743381a8_2e80d138_db387280_70802e80_51515151;
|
||||
defparam bootram.RAM2.INIT_01=256'h125271e9_2e8738ff_51517080_70810651_0870812a_5281a890_0c8386d0_7081a890;
|
||||
defparam bootram.RAM2.INIT_02=256'h55ffab39_15ff1454_2e8e3881_51517080_81325151_70810670_0870872a_3881a890;
|
||||
defparam bootram.RAM2.INIT_03=256'h74259b38_54805372_fd3d0d75_863d0d04_5170800c_a8900c80_80c00b81_81518a39;
|
||||
defparam bootram.RAM2.INIT_04=256'h0d04fa3d_e239853d_38811353_8f7127f1_515181cb_08707331_5281b8ac_81b8ac08;
|
||||
defparam bootram.RAM2.INIT_05=256'h86388151_5271802e_38728306_0652718a_91387583_55575771_72830655_0d787a7c;
|
||||
defparam bootram.RAM2.INIT_06=256'h811454e9_0c525452_12700872_2b771177_94387382_55737527_822a7255_f8e83f72;
|
||||
defparam bootram.RAM2.INIT_07=256'h8f0680e8_f8f53f72_54515353_e8941133_708f0680_7470842a_04fe3d0d_39883d0d;
|
||||
defparam bootram.RAM2.INIT_08=256'hef0b8280_8280800c_0c81e00b_0b828088_ff3d0dff_843d0d04_53f8e83f_94113352;
|
||||
defparam bootram.RAM2.INIT_09=256'hf138833d_51708025_540cff11_72708405_8751a3b2_80f3f452_82808c0c_840cff0b;
|
||||
defparam bootram.RAM2.INIT_0A=256'h55747606_80f3f455_8053810b_06585152_808c0871_08700982_0d828088_0d04fb3d;
|
||||
defparam bootram.RAM2.INIT_0B=256'h53877325_76105755_81138415_8c0c8f39_2d748280_73085271_8f387251_5271802e;
|
||||
defparam bootram.RAM2.INIT_0C=256'h722b7009_710c5181_f3f40575_71842980_87269f38_0d735271_0d04ff3d_dc38873d;
|
||||
defparam bootram.RAM2.INIT_0D=256'h0881e0c4_05227470_3d0d0292_0d0404ff_5152833d_80880c53_70720682_82808808;
|
||||
defparam bootram.RAM2.INIT_0E=256'h70802ef3_84065151_b8a00870_e0c00c81_0d810b81_0d04803d_c80c833d_0c5281e0;
|
||||
defparam bootram.RAM2.INIT_0F=256'h81b8a008_802e9338_06545272_a0087081_3d0d81b8_3d0d04fe_e0c00c82_38820b81;
|
||||
defparam bootram.RAM2.INIT_10=256'he8a451f7_2e8b3880_51527180_2a708106_9a397181_81808052_710c5353_7571902a;
|
||||
defparam bootram.RAM2.INIT_11=256'h802ef238_06515170_087080c0_0d81b8a0_0d04803d_800c843d_3f725271_9a3fffa6;
|
||||
defparam bootram.RAM2.INIT_12=256'hb8a00870_c00c5281_880781e0_2270902b_0d028e05_0d04ff3d_800c823d_8180800b;
|
||||
defparam bootram.RAM2.INIT_13=256'h2e8638ba_80537280_3d0d7554_3d0d04fd_e0c00c83_38840b81_70802ef3_90065151;
|
||||
defparam bootram.RAM2.INIT_14=256'h77831133_04fb3d0d_38853d0d_857327e6_3f811353_5252fcd9_72147033_51f5ec3f;
|
||||
defparam bootram.RAM2.INIT_15=256'h7e616302_f63d0d7c_873d0d04_5180ed3f_5680e8a8_54703353_55811133_56821133;
|
||||
defparam bootram.RAM2.INIT_16=256'h52ad5178_2e8a3879_8f387580_57768025_5f5d5b59_9f2a515b_33703070_9005bb05;
|
||||
defparam bootram.RAM2.INIT_17=256'h77527651_51ffbd3f_953f8008_527651b3_54805377_38795578_77772694_2d763057;
|
||||
defparam bootram.RAM2.INIT_18=256'h823d0d04_51f4d43f_028b0533_04803d0d_2d8c3d0d_05335178_0880e8b4_b3ad3f80;
|
||||
defparam bootram.RAM2.INIT_19=256'hd1387681_75802e81_ff065757_78337081_915c5a58_055208a6_3d707084_f73d0d8c;
|
||||
defparam bootram.RAM2.INIT_1A=256'h24a03875_387580f0_f02e80fb_57597580_81197033_0680db38_a52e0981_ff065675;
|
||||
defparam bootram.RAM2.INIT_1B=256'h8b397580_80c63881_7580e42e_38819539_802e819e_248a3875_387580e3_80e32eb9;
|
||||
defparam bootram.RAM2.INIT_1C=256'h39778419_ba3880ec_7580f82e_3880f539_f32e80db_8b387580_7580f524_f52eac38;
|
||||
defparam bootram.RAM2.INIT_1D=256'h80539039_55a69154_52595680_84197108_80da3977_7551792d_59568052_83123352;
|
||||
defparam bootram.RAM2.INIT_1E=256'h55a69154_52595680_84197108_52923977_5481538a_8055a691_08525956_77841971;
|
||||
defparam bootram.RAM2.INIT_1F=256'h52767081_2e8e3880_33567580_59595676_84197108_3f9e3977_7551fdd0_80539052;
|
||||
defparam bootram.RAM2.INIT_20=256'h04803d0d_81e5e40c_0d048a0b_800c8b3d_a339800b_811959fe_792dec39_05583351;
|
||||
defparam bootram.RAM2.INIT_21=256'h88059b05_0d797b02_0d04fc3d_ef38823d_51515170_32708106_708c2a81_81b8b408;
|
||||
defparam bootram.RAM2.INIT_22=256'h81065151_72822a70_810a0752_2e863871_54547080_06555557_7b077281_3372982b;
|
||||
defparam bootram.RAM2.INIT_23=256'he5ec0c74_e80c7081_3f7181e5_5151ffa9_3179712b_0752a074_3871820a_70802e86;
|
||||
defparam bootram.RAM2.INIT_24=256'h3d0d04fc_70800c86_06515252_80087072_ff0581b8_3f81742b_9338ff95_5174802e;
|
||||
defparam bootram.RAM2.INIT_25=256'h3971902a_555351ee_73058115_10157022_278f3872_80537274_7a545555_3d0d7678;
|
||||
defparam bootram.RAM2.INIT_26=256'h86537552_04fd3d0d_0c863d0d_ec397180_902a0552_ffff0672_8d387183_5170802e;
|
||||
defparam bootram.RAM2.INIT_27=256'h80720c88_d8528951_3d0d80f1_3d0d04ff_d00c5485_700880f1_b4de3f76_80f1c851;
|
||||
defparam bootram.RAM2.INIT_28=256'h52702254_80f1d452_2253800b_0d029605_0d04fd3d_f338833d_52708025_12ff1252;
|
||||
defparam bootram.RAM2.INIT_29=256'h787a7183_04fa3d0d_0c853d0d_80517080_7225ee38_12525289_38811288_72742e8e;
|
||||
defparam bootram.RAM2.INIT_2A=256'h80f1d455_80f1d80b_ad398008_0884050c_89387680_8008802e_5856c73f_ffff0653;
|
||||
defparam bootram.RAM2.INIT_2B=256'h73237684_e9b63f75_7525eb38_14545589_38811588_71802e8f_88155552_55557308;
|
||||
defparam bootram.RAM2.INIT_2C=256'h88055291_7353923d_54b3ad3f_3dd60552_933d5392_0d867054_0d04f13d_140c883d;
|
||||
defparam bootram.RAM2.INIT_2D=256'h23800b8c_8405a605_3d238002_8a800b8b_a2052381_80028405_b39e3f90_3ddc0551;
|
||||
defparam bootram.RAM2.INIT_2E=256'h5e80538a_23685d66_8405ae05_3d238002_c0910b8d_aa052380_80028405_3d238180;
|
||||
defparam bootram.RAM2.INIT_2F=256'h05ba0523_3d220284_903d2396_23983d22_8405ae05_3f800802_0551fdb7_52913de4;
|
||||
defparam bootram.RAM2.INIT_30=256'hf5803f91_98840551_80c02982_d4055269_ac53913d_05be0523_23800284_800b913d;
|
||||
defparam bootram.RAM2.INIT_31=256'h80f1c852_8b3f8653_f20551b2_3d529a3d_2386539b_800b973d_3d0d805b_3d0d04e8;
|
||||
defparam bootram.RAM2.INIT_32=256'h5a800b9b_08800858_f7d83f80_80e20523_22028405_0280f205_51b1fd3f_9a3df805;
|
||||
defparam bootram.RAM2.INIT_33=256'ha33d0883_a13d085f_905d6e5e_4659845c_45a33d08_44a13d08_f005436e_3dc41143;
|
||||
defparam bootram.RAM2.INIT_34=256'h3873760c_73752784_51565a55_90807131_1a787c31_58750870_8c3d5684_05fc0640;
|
||||
defparam bootram.RAM2.INIT_35=256'hd051eea3_883880e8_5473802e_16088306_738c3894_73830654_802e9a38_75085473;
|
||||
defparam bootram.RAM2.INIT_36=256'hac3878bf_778025ff_ff195957_05570817_3f757084_7651f3d2_94160852_3f750853;
|
||||
defparam bootram.RAM2.INIT_37=256'h943d237f_818a800b_6b6e4040_04ea3d0d_3f9a3d0d_2a51f6de_c0597882_26843880;
|
||||
defparam bootram.RAM2.INIT_38=256'h80c08007_ce052369_02840580_23818080_800b953d_80ca0523_79028405_1f94055a;
|
||||
defparam bootram.RAM2.INIT_39=256'h5cfae03f_933d7052_80538a52_08466847_2380f1d0_0580d205_23800284_5a79963d;
|
||||
defparam bootram.RAM2.INIT_3A=256'hff065a79_3f800881_5c5e8ac8_983d7053_913d7053_80d20523_79028405_8008095a;
|
||||
defparam bootram.RAM2.INIT_3B=256'h5d94557b_60586b57_7f5a6d59_3fa93902_ac3fec92_3f7a51f6_fc51f7b8_923880e8;
|
||||
defparam bootram.RAM2.INIT_3C=256'h3d0d04f7_fd893f98_7c26ef38_811c5c86_79337b34_7c1f5b5b_805c7b1d_54908053;
|
||||
defparam bootram.RAM2.INIT_3D=256'h028405a6_8b3d2380_88185776_05a20523_3d220284_8a3d238d_02ae0522_3d0d7f58;
|
||||
defparam bootram.RAM2.INIT_3E=256'h0b8e3d23_ee3d0d81_8b3d0d04_51fe9e3f_5391527d_8b3df805_7e558854_05237756;
|
||||
defparam bootram.RAM2.INIT_3F=256'hd33f8653_b60523e7_81028405_05b50534_34840284_860b8f3d_05b20523_90800284;
|
||||
defparam bootram.RAM3.INIT_00=256'h53805294_aeaa3f86_3df20551_80085294_a33f8453_aeba3fe8_3dec0551_80085294;
|
||||
defparam bootram.RAM3.INIT_01=256'he4055490_9c55943d_80578056_80598058_0843025c_873f8008_afb73fe8_3df60551;
|
||||
defparam bootram.RAM3.INIT_02=256'h04d93d0d_3f943d0d_ef38fbcb_5b867b26_7a34811b_e8c81b33_7a1c5a80_8653805b;
|
||||
defparam bootram.RAM3.INIT_03=256'h5b799b26_29f2055b_ac3d0884_9d38901d_09810682_7d90862e_11225f5d_aa3d088e;
|
||||
defparam bootram.RAM3.INIT_04=256'h225a7990_e238821b_09810686_5a79812e_ee397a22_f5963f86_80e9ac51_8d387952;
|
||||
defparam bootram.RAM3.INIT_05=256'h2e098106_225a7981_c638861b_09810686_798c842e_841b225a_0686d438_802e0981;
|
||||
defparam bootram.RAM3.INIT_06=256'ha93dffa8_80f1d052_08438453_87fd3f80_1d70525f_88853fa8_1d705240_86b9389e;
|
||||
defparam bootram.RAM3.INIT_07=256'h22a13d23_acca3f7a_c8527951_865380f1_38a73d5a_8008868f_3f80085c_0551abec;
|
||||
defparam bootram.RAM3.INIT_08=256'h84058182_05348202_84058181_851b3302_33a23d34_0523841b_840580fe_821b2202;
|
||||
defparam bootram.RAM3.INIT_09=256'h02818e05_5aac893f_3dea0552_547f53aa_973f8470_e40551ac_7952a93d_05238653;
|
||||
defparam bootram.RAM3.INIT_0A=256'h7a527e51_3d5f8653_abee3f9e_3df40551_537f52a9_abfa3f79_1d527a51_5b865398;
|
||||
defparam bootram.RAM3.INIT_0B=256'h79337b34_7f1d5b5b_7d537b1d_3ddc0554_5d9c55a9_7c587c57_7c5a7c59_abe23f02;
|
||||
defparam bootram.RAM3.INIT_0C=256'h708c2a43_901d7022_0684e438_802e0981_ee397d90_f9993f84_7c26ef38_811c5c86;
|
||||
defparam bootram.RAM3.INIT_0D=256'h861b2280_0684c038_852e0981_06515a79_882a708f_84d13879_2e098106_5b5b6084;
|
||||
defparam bootram.RAM3.INIT_0E=256'h7e901c62_8338815e_fb3f8008_821d51a9_80e8c852_7e5e8653_7e84b438_ffff065f;
|
||||
defparam bootram.RAM3.INIT_0F=256'h1d529c1d_84813888_387b802e_815c7d87_80088338_5ca9e53f_5470535b_5580f1d0;
|
||||
defparam bootram.RAM3.INIT_10=256'hde388c1b_09810683_387f912e_812e81bb_405d407f_1c22ec11_891b3382_5184b83f;
|
||||
defparam bootram.RAM3.INIT_11=256'h83bd39ac_51f1e53f_5280e9cc_3879537d_7d7a2e8f_5d5d4240_1f841122_087a08a4;
|
||||
defparam bootram.RAM3.INIT_12=256'h499a3d99_993d237f_a6387a22_08802e83_80084280_5df5c33f_1d22535d_1de41d82;
|
||||
defparam bootram.RAM3.INIT_13=256'h3d236047_821b2297_51a9cd3f_5379527f_9c3d4088_51a9d93f_537d5279_3d5f5a88;
|
||||
defparam bootram.RAM3.INIT_14=256'h3d5e5c7b_7c557e84_af3f7b56_527d51a9_3f885379_7951a9b8_ffb40552_8853a93d;
|
||||
defparam bootram.RAM3.INIT_15=256'h34811b5b_0284051c_1b5a7933_38805b7f_887c26ef_34811c5c_5b79337b_1d7c1f5b;
|
||||
defparam bootram.RAM3.INIT_16=256'h8a387d88_427d832e_7033405b_1b08a41e_82ad398c_085a792d_38618405_887b26ef;
|
||||
defparam bootram.RAM3.INIT_17=256'h5c5e5c79_1e891233_ac1d80c0_0681a238_832e0981_1a335a79_82953981_2e81bb38;
|
||||
defparam bootram.RAM3.INIT_18=256'h7c229b3d_8c1c085a_2e80fe38_41800880_813f8008_7c2251f4_0681f438_912e0981;
|
||||
defparam bootram.RAM3.INIT_19=256'h873f901c_527f51a8_4088537d_933f963d_527d51a8_5e88537a_3d9b3d5c_23794b98;
|
||||
defparam bootram.RAM3.INIT_1A=256'ha7e63f7e_7a527d51_ef3f8853_527a51a7_a93dcc05_794d8853_229d3d23_085a821d;
|
||||
defparam bootram.RAM3.INIT_1B=256'h7f1b5a79_ef38805b_5c887c26_7b34811c_5b5b7933_7b1d7c1f_843d5e5c_567e557e;
|
||||
defparam bootram.RAM3.INIT_1C=256'hde39ac1d_e3d53f80_2d80e951_05085a79_ef386084_5b887b26_1c34811b_33028405;
|
||||
defparam bootram.RAM3.INIT_1D=256'h3d23861a_841a2296_80ce0523_7e028405_80cd0534_7e028405_7e953d34_e41d5d5d;
|
||||
defparam bootram.RAM3.INIT_1E=256'h51f1c03f_812a527c_8008537b_5bf1cc3f_943d7052_7e536052_80d20523_22028405;
|
||||
defparam bootram.RAM3.INIT_1F=256'h3d0d04fc_f5f73fa9_7f526151_7d547a53_7b567c55_80ce0523_79028405_8008095a;
|
||||
defparam bootram.RAM3.INIT_20=256'h53517075_71088c13_ac545651_700880f2_27a43876_55537274_80f2a408_3d0d800b;
|
||||
defparam bootram.RAM3.INIT_21=256'h3d0d7779_3d0d04fb_70800c86_e738ff51_53737326_8b398113_85387251_2e098106;
|
||||
defparam bootram.RAM3.INIT_22=256'h0c8e3980_1480f2a4_26893881_08547387_3880f2a4_088025ba_ffb93f80_71535755;
|
||||
defparam bootram.RAM3.INIT_23=256'h53755280_0c515486_80f2ac12_822b7608_73101470_f2a80c54_11870680_f2a80881;
|
||||
defparam bootram.RAM3.INIT_24=256'h873d0d04_51a5a93f_80f2b005_52738429_54865375_10800805_94398008_f2b01451;
|
||||
defparam bootram.RAM3.INIT_25=256'h80f2b005_53738429_08055486_80081080_08249938_80547380_51fed83f_fd3d0d75;
|
||||
defparam bootram.RAM3.INIT_26=256'h902b0782_71982b71_33811233_3d0d7570_3d0d04fd_73800c85_ff3f8154_527651a4;
|
||||
defparam bootram.RAM3.INIT_27=256'h7f80f38c_f93d0d7d_853d0d04_54565452_800c5253_16337107_2b720783_14337088;
|
||||
defparam bootram.RAM3.INIT_28=256'hf3901433_80e23880_54738326_72315256_8b3d2270_83ffff06_76af3873_22565957;
|
||||
defparam bootram.RAM3.INIT_29=256'h22707231_ff068d3d_397383ff_942380c8_387680f3_547380d0_982c5151_70982b70;
|
||||
defparam bootram.RAM3.INIT_2A=256'h3d5280f3_3888538a_555573a4_70982c51_3370982b_80f39016_8326b538_58565475;
|
||||
defparam bootram.RAM3.INIT_2B=256'h893d0d04_1555ec39_e1cb3f81_53547551_74177033_78279138_3f735574_9451a3e0;
|
||||
defparam bootram.RAM3.INIT_2C=256'h810680f3_2c813270_c0398275_59565680_7080f394_f38c2380_a6052280_f93d0d02;
|
||||
defparam bootram.RAM3.INIT_2D=256'h729c180c_7298180c_34727723_a2397574_38ff7434_72802e86_5b565153_90178118;
|
||||
defparam bootram.RAM3.INIT_2E=256'h70837827_77078025_55753070_18585677_3f8116a0_0551eeed_f38c2275_b9f85280;
|
||||
defparam bootram.RAM3.INIT_2F=256'h51575775_2b70982c_1b337098_5b80f390_f53d0d80_893d0d04_72ffaf38_06515153;
|
||||
defparam bootram.RAM3.INIT_30=256'h3f8008ff_7a51e0e1_f39c195a_80d83880_5c788f26_9805085a_80f3940b_81d63875;
|
||||
defparam bootram.RAM3.INIT_31=256'h59515858_25075351_80257180_32703072_7030728d_06708a32_800881ff_2e80c738;
|
||||
defparam bootram.RAM3.INIT_32=256'h940b9c05_800b80f3_80f3ac0c_ac088105_5c3480f3_7a708105_38815c77_76802e83;
|
||||
defparam bootram.RAM3.INIT_33=256'h08811180_940b9c05_993880f3_80e6387b_ac08802e_af3880f3_8f7927ff_0c811959;
|
||||
defparam bootram.RAM3.INIT_34=256'h98050855_80f3940b_802eaf38_94225675_cb3880f3_fa762780_050c5681_f3940b9c;
|
||||
defparam bootram.RAM3.INIT_35=256'h80f38c22_7726ef38_81175788_17337634_5680f394_59577618_800b833d_80f39c54;
|
||||
defparam bootram.RAM3.INIT_36=256'h7b27fe91_811b5b83_0b9c050c_0b80f394_98050c80_80f3940b_da3f800b_7b0551f1;
|
||||
defparam bootram.RAM3.INIT_37=256'h528151ea_ff065384_9054759f_c4238555_567580f3_029e0522_04fb3d0d_388d3d0d;
|
||||
defparam bootram.RAM3.INIT_38=256'h800b8813_0c73710c_70840553_e5ea8071_70525298_0d80f3d0_0d04ff3d_b53f873d;
|
||||
defparam bootram.RAM3.INIT_39=256'hb084088a_81ec3881_5372802e_81065151_70812a70_81b08008_04f93d0d_0c833d0d;
|
||||
defparam bootram.RAM3.INIT_3A=256'h81be3872_f2e17324_801453f9_0ce79a96_0b81b080_82fb3f81_f8055254_3dfc1154;
|
||||
defparam bootram.RAM3.INIT_3B=256'h55807325_2b595154_982c7683_70982b70_80f0d833_80f3bc0c_81b63873_868d9f24;
|
||||
defparam bootram.RAM3.INIT_3C=256'h2980f0d4_f0d40888_81863980_80f3d00c_f0d40c73_d8347580_537280f0_9638ff15;
|
||||
defparam bootram.RAM3.INIT_3D=256'h90752587_515380ce_71315858_98e5ea80_0c70862a_2a80f0d4_84057083_08317611;
|
||||
defparam bootram.RAM3.INIT_3E=256'h80f3d008_80f3d80c_d8081570_f05580f3_8538ffb1_ffb1f025_558c3974_3880ce90;
|
||||
defparam bootram.RAM3.INIT_3F=256'h2586388f_538fff73_2c515255_05711187_29729029_0c7680c0_7780f3d0_7731882b;
|
||||
defparam bootram.RAM4.INIT_00=256'h7680f3b8_53fdca3f_ffff0652_08137083_5380f3d4_8438f081_72f08125_ff538a39;
|
||||
defparam bootram.RAM4.INIT_01=256'h53e5e13f_80e9f052_ff067053_800883ff_0dd69a3f_0d04fe3d_b40c893d_0c7780f3;
|
||||
defparam bootram.RAM4.INIT_02=256'h883fbea5_0c7251fd_0b80f3bc_f0d83480_53820b80_84389080_2e098106_7283ffff;
|
||||
defparam bootram.RAM4.INIT_03=256'h843d0d04_5180ca3f_5280f3b8_0c80f3b4_0b81b080_fd9c3f81_a13f7251_528151e2;
|
||||
defparam bootram.RAM4.INIT_04=256'hc83f833d_347151fc_0b80f0d8_fcf43f82_22705252_0d028e05_0c04ff3d_7180f3c0;
|
||||
defparam bootram.RAM4.INIT_05=256'h0c0480f3_f3b80880_800c0480_80f0d408_08800c04_0480f3bc_c422800c_0d0480f3;
|
||||
defparam bootram.RAM4.INIT_06=256'h70722e93_54545454_81b8a808_ac08720c_a80881b8_757781b8_04fd3d0d_b408800c;
|
||||
defparam bootram.RAM4.INIT_07=256'hd05382e0_3d0d8386_3d0d04fe_71740c85_740c8439_26863870_fffffffe_38720887;
|
||||
defparam bootram.RAM4.INIT_08=256'h3f843d0d_8051d9c7_e93880ea_ff135372_802e8e38_51515271_2a708106_90087088;
|
||||
defparam bootram.RAM4.INIT_09=256'he0900870_86d05382_07555583_0780c080_7c8c8006_7a80ff06_029b0533_04fc3d0d;
|
||||
defparam bootram.RAM4.INIT_0A=256'he0800c73_8a3f7882_ea8051d9_72e93880_38ff1353_71802e8e_06515152_882a7081;
|
||||
defparam bootram.RAM4.INIT_0B=256'h86d05382_2ea93883_74527480_82e0900c_73828007_82e0980c_7781ff06_82e0900c;
|
||||
defparam bootram.RAM4.INIT_0C=256'hc63f82e0_ea8051d8_72e93880_38ff1353_71802e8e_06515152_882a7081_e0900870;
|
||||
defparam bootram.RAM4.INIT_0D=256'h8051fee1_80538052_80558854_e0940c88_0d810b82_0d04fc3d_800c863d_80085271;
|
||||
defparam bootram.RAM4.INIT_0E=256'h800c863d_0881ff06_fecb3f80_81528151_548a8053_88805590_04fc3d0d_3f863d0d;
|
||||
defparam bootram.RAM4.INIT_0F=256'h80088132_3d0dca3f_3d0d0480_feaf3f86_81528051_88548653_0d888055_0d04fc3d;
|
||||
defparam bootram.RAM4.INIT_10=256'hfb3d0d77_823d0d04_802ef438_ff065170_3f800881_803d0deb_823d0d04_8106800c;
|
||||
defparam bootram.RAM4.INIT_11=256'h53815280_069b0a07_75fe9b0a_8055a054_ffb43f88_9b38dd3f_75800826_5685923f;
|
||||
defparam bootram.RAM4.INIT_12=256'h81ff2681_57805573_ff115657_80cb3d08_80c93d08_ffba3d0d_873d0d04_51fdde3f;
|
||||
defparam bootram.RAM4.INIT_13=256'h3f755380_52549ae1_52883d70_805381ff_81a73882_73800826_5484ce3f_b4387517;
|
||||
defparam bootram.RAM4.INIT_14=256'h900c76fe_800b82e0_e0980c88_e63f7482_fed43ffc_3ffefd3f_735199bc_cb3d0852;
|
||||
defparam bootram.RAM4.INIT_15=256'he0900cfc_8aa00b82_82e0900c_0c88a00b_0b82e098_e0800c81_c00a0782_c00a0680;
|
||||
defparam bootram.RAM4.INIT_16=256'hfe881570_e0880c54_15700882_0c54fe84_0882e08c_fe801570_3d558f56_b63f80c8;
|
||||
defparam bootram.RAM4.INIT_17=256'h900cfbf7_800b82e0_e0900c8a_88800b82_e0800c54_15700882_0c54fe8c_0882e084;
|
||||
defparam bootram.RAM4.INIT_18=256'h04f93d0d_80c83d0d_5574800c_e0980c81_38800b82_8025ffbc_16565675_3fff1690;
|
||||
defparam bootram.RAM4.INIT_19=256'h387581ff_802e80c3_38815774_082680cb_80577380_56838a3f_12575a56_797b7d72;
|
||||
defparam bootram.RAM4.INIT_1A=256'heb3f7316_527551fd_54775373_27833876_55577675_80743175_2ea23882_06547380;
|
||||
defparam bootram.RAM4.INIT_1B=256'h3f815776_dc39fd8c_38828054_807527e1_38745482_74802e8e_31575956_74197676;
|
||||
defparam bootram.RAM4.INIT_1C=256'h74279038_9c3f8008_73135482_802e8d38_56545573_0d76787a_0d04fc3d_800c893d;
|
||||
defparam bootram.RAM4.INIT_1D=256'h5281ec3f_ff165651_30707406_fa3f8008_0ca63981_160c8075_0c800b84_800b8816;
|
||||
defparam bootram.RAM4.INIT_1E=256'h54fc983f_fd3d0d75_863d0d04_51fcc93f_88160c71_84160c71_760c7406_80083072;
|
||||
defparam bootram.RAM4.INIT_1F=256'h14088008_81b13f88_082e9438_14088415_38815388_71802e9f_06705452_800881ff;
|
||||
defparam bootram.RAM4.INIT_20=256'h0a538152_a05481f9_0d888055_0d04fc3d_800c853d_3f805372_0c51fc94_05708816;
|
||||
defparam bootram.RAM4.INIT_21=256'h38d43f80_557480c2_80f3dc08_04fb3d0d_0c863d0d_800a0680_3f8008fe_8151f9fd;
|
||||
defparam bootram.RAM4.INIT_22=256'h2e833881_c73f73a0_585154dd_80ea9c54_70567155_0881ff06_81ff0680_08882a70;
|
||||
defparam bootram.RAM4.INIT_23=256'hdc0c80f3_397580f3_d2c53f9c_80eab451_802e8a38_81065473_2e933874_557380c0;
|
||||
defparam bootram.RAM4.INIT_24=256'h0d04ff91_800c873d_cb9a3f74_51dd8d3f_5280ead4_278d3874_55558274_dc08ea11;
|
||||
defparam bootram.RAM4.INIT_25=256'h2b800c04_810b8008_04fefa3f_082b800c_3f810b80_800c04f2_eade0533_3f800880;
|
||||
defparam bootram.RAM4.INIT_26=256'h882b82e0_e0840c7c_0c8b0b82_0b82e090_980c8880_800b82e0_56f8b03f_f63d0d7d;
|
||||
defparam bootram.RAM4.INIT_27=256'h54737627_3f7e5580_900cf7ff_a80b82e0_e0900c8a_88a80b82_82e0980c_800c810b;
|
||||
defparam bootram.RAM4.INIT_28=256'h085982e0_5882e088_82e08c08_0cf7e43f_0b82e090_900c8a80_800b82e0_80d33888;
|
||||
defparam bootram.RAM4.INIT_29=256'h27913871_80527173_83387053_53707327_31525790_883d7675_e080085b_84085a82;
|
||||
defparam bootram.RAM4.INIT_2A=256'h3d0d04ea_e0980c8c_39800b82_1454ffa9_52ec3972_57348112_75708105_17517033;
|
||||
defparam bootram.RAM4.INIT_2B=256'h547381ff_17703351_05575574_0284059d_fed23f80_c0526851_70545780_3d0d883d;
|
||||
defparam bootram.RAM4.INIT_2C=256'h548b3981_06853881_992e0981_51547381_74167033_81069438_81aa2e09_2e9d3873;
|
||||
defparam bootram.RAM4.INIT_2D=256'hfe823f80_82527751_3d705454_fb3d0d86_983d0d04_5473800c_27d13880_1555be75;
|
||||
defparam bootram.RAM4.INIT_2E=256'h0d04810b_800c873d_38815574_09810683_8008752e_5192853f_eaf85273_55825380;
|
||||
defparam bootram.RAM4.INIT_2F=256'h80eb9c52_ff067053_3f800881_f23fca95_eafc51cf_f7c03f80_04fc3d0d_81e0940c;
|
||||
defparam bootram.RAM4.INIT_30=256'h51818739_3880ebb4_51547388_70810651_08708d2a_3f81b8b4_8051c98b_55da9d3f;
|
||||
defparam bootram.RAM4.INIT_31=256'ha63f8151_ec8051cf_2e9c3880_3f800880_0a51feaf_ba3f9880_ebd451cf_74b73880;
|
||||
defparam bootram.RAM4.INIT_32=256'h51fed13f_398c800a_b05180ce_fa3f80ec_800a5183_3f745298_ac51d4ac_c8d13f82;
|
||||
defparam bootram.RAM4.INIT_33=256'h80ed8451_51fcc53f_528c800a_5380ffff_3f838080_d851cef7_bd3880ec_8008802e;
|
||||
defparam bootram.RAM4.INIT_34=256'h5183ac3f_3f805280_ac51d3dc_ced13f82_80ed9851_3ffed33f_ac51d3ec_cee13f82;
|
||||
defparam bootram.RAM4.INIT_35=256'he82e8438_a0537387_3d0d7554_e00c04fd_047180f3_3f863d0d_b451cebb_883980ed;
|
||||
defparam bootram.RAM4.INIT_36=256'h38735172_72802e85_f3e00853_ccdf3f80_72527251_51d8d53f_5280edd8_80c05373;
|
||||
defparam bootram.RAM4.INIT_37=256'h72802e85_f3e00853_ccbb3f80_c0528051_ccc33f80_a0528051_04fe3d0d_2d853d0d;
|
||||
defparam bootram.RAM4.INIT_38=256'h54815571_81065153_08862a70_3fff0b80_9a51cbb7_04fc3d0d_2d843d0d_38805172;
|
||||
defparam bootram.RAM4.INIT_39=256'h388a5471_8280248a_2e9b3871_54718280_535580e4_08868006_38820b80_802e80ec;
|
||||
defparam bootram.RAM4.INIT_3A=256'hea3f7188_528551ca_f23f8008_548451ca_2e8338ff_54718480_8a3987e8_802e8e38;
|
||||
defparam bootram.RAM4.INIT_3B=256'h5452ccbb_90555351_ec0c80ee_337080f3_80eed011_83067207_088a2c70_2a8c0680;
|
||||
defparam bootram.RAM4.INIT_3C=256'h0c74822e_7480f3e4_082e9838_7480f3e4_52ccd43f_dc110852_8c0680f0_3f71822b;
|
||||
defparam bootram.RAM4.INIT_3D=256'h2e8e3873_80f3e808_06963873_822e0981_3f9e3974_a338feb9_2e098106_a6387481;
|
||||
defparam bootram.RAM4.INIT_3E=256'h0851c9cc_c7f63f80_04fd3d0d_3f863d0d_9951c9f7_51fde83f_fe9f3f73_80f3e80c;
|
||||
defparam bootram.RAM4.INIT_3F=256'h529c51c9_3f81ae80_9851ca80_d63f8d52_0c9951c9_0b80f3e8_f3e40cff_3f800b80;
|
||||
defparam bootram.RAM5.INIT_00=256'h51c9d93f_70535484_07f49f06_80089080_51c9b83f_d2fc3f84_89528451_f73f80ce;
|
||||
defparam bootram.RAM5.INIT_01=256'h80088480_51c98c3f_d5ea3f80_80eea851_08537352_2e8d3880_3f738008_8451c9a3;
|
||||
defparam bootram.RAM5.INIT_02=256'h0a075956_0a0681d0_0a077ed0_0a0681d0_3d0d7cd0_3d0d04f6_c9b23f85_07528051;
|
||||
defparam bootram.RAM5.INIT_03=256'h0c8a51cf_81ab9977_51cffd3f_71770c8a_51d0853f_710c578a_82c08072_83ffff52;
|
||||
defparam bootram.RAM5.INIT_04=256'h7583ffff_51cfd93f_86770c78_805a8199_e73f80e1_0c7851cf_82d4e677_f33f8a59;
|
||||
defparam bootram.RAM5.INIT_05=256'h73109006_71730707_812a8806_2a840672_2a077183_82067187_0670852a_067081ff;
|
||||
defparam bootram.RAM5.INIT_06=256'h73730707_70818006_872b6306_80c00677_0676852b_077081ff_06717307_74832ba0;
|
||||
defparam bootram.RAM5.INIT_07=256'h90067483_07077310_88067173_0672812a_71832a84_71872a07_852a8206_7a882a70;
|
||||
defparam bootram.RAM5.INIT_08=256'h07077088_80067373_6d067081_0677872b_852b80c0_81ff0676_73070770_2ba00671;
|
||||
defparam bootram.RAM5.INIT_09=256'h5752575d_58525351_5a555b51_53515752_586b4452_6d0c5151_83ffff06_2b7b0770;
|
||||
defparam bootram.RAM5.INIT_0A=256'h70730770_7081ff06_0676902a_902a9680_cea63f75_770c7851_3f819981_5653ceb0;
|
||||
defparam bootram.RAM5.INIT_0B=256'h90067483_07077310_88067173_0672812a_71832a84_71872a07_852a8206_81ff0670;
|
||||
defparam bootram.RAM5.INIT_0C=256'h7a882a70_7081ff06_78872b07_06707207_852b80c0_81ff0676_73070770_2ba00671;
|
||||
defparam bootram.RAM5.INIT_0D=256'h67405b51_680c5156_80067407_882b83fe_872b0770_06710772_852b80c0_10900671;
|
||||
defparam bootram.RAM5.INIT_0E=256'h973f7783_0c7851cd_81998577_81a18056_52cda53f_57515157_58525a5a_51555351;
|
||||
defparam bootram.RAM5.INIT_0F=256'h07077310_88067173_0672812a_71832a84_71872a07_852a8206_81ff0670_ffff0670;
|
||||
defparam bootram.RAM5.INIT_10=256'h80067373_7f067081_0677872b_852b80c0_81ff0676_73070770_2ba00671_90067483;
|
||||
defparam bootram.RAM5.INIT_11=256'h73109006_71730707_812a8806_2a840672_2a077183_82067187_2a70852a_07077a88;
|
||||
defparam bootram.RAM5.INIT_12=256'h73730707_70818006_872b6906_80c00677_0676852b_077081ff_06717307_74832ba0;
|
||||
defparam bootram.RAM5.INIT_13=256'h53515752_5b515852_57525a55_44525351_5151586b_ff066d0c_077083ff_70882b7b;
|
||||
defparam bootram.RAM5.INIT_14=256'h902a7081_96800678_3f77902a_7851cbe0_9983770c_c1805581_cbee3f81_575c5653;
|
||||
defparam bootram.RAM5.INIT_15=256'h71730707_812a8806_2a840672_2a077183_82067187_0670852a_077081ff_ff067073;
|
||||
defparam bootram.RAM5.INIT_16=256'h70818006_872b6106_80c00677_0676852b_077081ff_06717307_74832ba0_73109006;
|
||||
defparam bootram.RAM5.INIT_17=256'h2b750770_07077088_66067173_0672872b_852b80c0_10900671_7a882a70_73730707;
|
||||
defparam bootram.RAM5.INIT_18=256'hd73f9985_515952ca_5a5b5751_53515852_5b515852_69425a54_6a0c5152_83ffff06;
|
||||
defparam bootram.RAM5.INIT_19=256'h0c7851ca_3f80f077_7851cabc_3f71770c_7851cac4_3f80770c_5252cacc_70780c79;
|
||||
defparam bootram.RAM5.INIT_1A=256'h3f71770c_7851ca98_3f71770c_7851caa0_3f71770c_5252caa8_70780c79_b33f8880;
|
||||
defparam bootram.RAM5.INIT_1B=256'h863d2280_ffbec03f_5280d051_fc055380_8254873d_04fb3d0d_3f8c3d0d_7851ca90;
|
||||
defparam bootram.RAM5.INIT_1C=256'h38775382_82932690_58595777_08841208_0880d73d_0d80d53d_04ffb23d_0c873d0d;
|
||||
defparam bootram.RAM5.INIT_1D=256'h05567508_2980efac_a2387584_75962681_ff9f1656_3f81ac39_e051cef8_945280ee;
|
||||
defparam bootram.RAM5.INIT_1E=256'h5c80fa39_085f80c6_f1df3f80_3f80085e_8c39f1db_08085e81_c0ea3f80_0480c15c;
|
||||
defparam bootram.RAM5.INIT_1F=256'hef883f80_80f49451_8c170852_90170853_5c80ea39_065e80d6_0883ffff_ff873f80;
|
||||
defparam bootram.RAM5.INIT_20=256'h80c25cb9_c45cbe39_2e863880_06567580_800881ff_51efcd3f_3980f494_c55c80d5;
|
||||
defparam bootram.RAM5.INIT_21=256'h1708528c_80055390_80d03dfe_d75ca639_edef3f80_8c170851_90170852_39941753;
|
||||
defparam bootram.RAM5.INIT_22=256'h80d03dfd_5c829455_3f8339a0_8051f7f7_d35c8052_5c8f3980_fb3f80d2_170851f0;
|
||||
defparam bootram.RAM5.INIT_23=256'hec388380_58887826_77348118_57577533_d23d7905_58771980_0b833d5a_ec055480;
|
||||
defparam bootram.RAM5.INIT_24=256'h88050851_08528c08_8c088c05_3d0d8053_028c0cfd_0d048c08_3f80d03d_8251d69b;
|
||||
defparam bootram.RAM5.INIT_25=256'h0508528c_538c088c_fd3d0d81_08028c0c_8c0c048c_54853d0d_0870800c_82de3f80;
|
||||
defparam bootram.RAM5.INIT_26=256'h800b8c08_0cf93d0d_8c08028c_0d8c0c04_0c54853d_80087080_5182b93f_08880508;
|
||||
defparam bootram.RAM5.INIT_27=256'h050c8c08_0b8c08f4_88050c80_08308c08_8c088805_8025ab38_08880508_fc050c8c;
|
||||
defparam bootram.RAM5.INIT_28=256'h25ab388c_8c050880_050c8c08_088c08fc_8c08f405_08f4050c_38810b8c_fc050888;
|
||||
defparam bootram.RAM5.INIT_29=256'hf0050c8c_810b8c08_05088838_0c8c08fc_8c08f005_050c800b_308c088c_088c0508;
|
||||
defparam bootram.RAM5.INIT_2A=256'h708c08f8_a73f8008_05085181_528c0888_088c0508_0c80538c_8c08fc05_08f00508;
|
||||
defparam bootram.RAM5.INIT_2B=256'h70800c54_08f80508_f8050c8c_08308c08_8c08f805_802e8c38_08fc0508_050c548c;
|
||||
defparam bootram.RAM5.INIT_2C=256'h93388c08_05088025_0c8c0888_8c08fc05_3d0d800b_028c0cfb_0c048c08_893d0d8c;
|
||||
defparam bootram.RAM5.INIT_2D=256'h0508308c_388c088c_0880258c_8c088c05_08fc050c_0c810b8c_8c088805_88050830;
|
||||
defparam bootram.RAM5.INIT_2E=256'h548c08fc_08f8050c_8008708c_0851ad3f_8c088805_8c050852_81538c08_088c050c;
|
||||
defparam bootram.RAM5.INIT_2F=256'h0d8c0c04_0c54873d_05087080_0c8c08f8_8c08f805_f8050830_8c388c08_0508802e;
|
||||
defparam bootram.RAM5.INIT_30=256'h08880508_8c05088c_050c8c08_0b8c08f8_fc050c80_810b8c08_0cfd3d0d_8c08028c;
|
||||
defparam bootram.RAM5.INIT_31=256'h8c088c05_8c050810_99388c08_8c050824_800b8c08_802ea338_08fc0508_27ac388c;
|
||||
defparam bootram.RAM5.INIT_32=256'h088c0888_8c088c05_2e80c938_fc050880_c9398c08_08fc050c_0508108c_0c8c08fc;
|
||||
defparam bootram.RAM5.INIT_33=256'hfc050807_05088c08_0c8c08f8_8c088805_8c050831_05088c08_388c0888_050826a1;
|
||||
defparam bootram.RAM5.INIT_34=256'h0cffaf39_8c088c05_0508812a_0c8c088c_8c08fc05_0508812a_0c8c08fc_8c08f805;
|
||||
defparam bootram.RAM5.INIT_35=256'h708c08f4_08f80508_518d398c_08f4050c_0508708c_388c0888_08802e8f_8c089005;
|
||||
defparam bootram.RAM5.INIT_36=256'h8c387474_52837227_77795656_fc3d0d78_0d8c0c04_800c853d_08f40508_050c518c;
|
||||
defparam bootram.RAM5.INIT_37=256'h06bd3881_712e0981_33525372_38743374_71ff2ea0_38ff1252_70802eb0_07830651;
|
||||
defparam bootram.RAM5.INIT_38=256'h70087308_74745451_863d0d04_800b800c_8106e238_71ff2e09_14545555_158115ff;
|
||||
defparam bootram.RAM5.INIT_39=256'h7131800c_ffaf3972_70735555_8326e938_54545171_8414fc14_8f388411_2e098106;
|
||||
defparam bootram.RAM5.INIT_3A=256'h2ea738ff_06517080_72750783_72278c38_5555558f_70797b55_fc3d0d76_863d0d04;
|
||||
defparam bootram.RAM5.INIT_3B=256'hea387480_2e098106_125271ff_055634ff_33747081_70810554_2e983872_125271ff;
|
||||
defparam bootram.RAM5.INIT_3C=256'h05530c72_08717084_70840554_05530c72_08717084_70840554_04745172_0c863d0d;
|
||||
defparam bootram.RAM5.INIT_3D=256'h26c93883_1252718f_05530cf0_08717084_70840554_05530c72_08717084_70840554;
|
||||
defparam bootram.RAM5.INIT_3E=256'h39fc3d0d_7054ff83_8326ed38_fc125271_8405530c_54087170_72708405_72279538;
|
||||
defparam bootram.RAM5.INIT_3F=256'h125271ff_2ea238ff_06517080_8a387483_55837227_33575553_8c059f05_76797102;
|
||||
defparam bootram.RAM6.INIT_00=256'h7474882b_863d0d04_3874800c_098106ef_5271ff2e_5534ff12_73708105_2e933873;
|
||||
defparam bootram.RAM6.INIT_01=256'h0c727170_70840553_530c7271_71708405_27a53872_54518f72_902b0751_75077071;
|
||||
defparam bootram.RAM6.INIT_02=256'h05530cfc_72717084_72279038_26dd3883_1252718f_05530cf0_72717084_8405530c;
|
||||
defparam bootram.RAM6.INIT_03=256'h38717407_802e80d9_55555272_7a7c7054_fa3d0d78_53ff9039_26f23870_12527183;
|
||||
defparam bootram.RAM6.INIT_04=256'h06a93872_712e0981_33565174_38713374_72ff2eb1_38ff1353_802e80d4_83065170;
|
||||
defparam bootram.RAM6.INIT_05=256'h098106d1_5272ff2e_ff155555_81128115_2e80fc38_06517080_387081ff_802e8187;
|
||||
defparam bootram.RAM6.INIT_06=256'h71745755_883d0d04_5270800c_71315152_81ff0671_81ff0675_33565170_38713374;
|
||||
defparam bootram.RAM6.INIT_07=256'h087009f7_2eb13874_13537280_ff9739fc_74765552_082e8838_38710874_83732788;
|
||||
defparam bootram.RAM6.INIT_08=256'h38740876_837327d0_84175755_9a388415_51515170_82818006_0670f884_fbfdff12;
|
||||
defparam bootram.RAM6.INIT_09=256'h54547281_80f0a808_3d0d800b_3d0d04fd_0b800c88_fedf3980_74765552_082ed038;
|
||||
defparam bootram.RAM6.INIT_0A=256'h51ffb7ca_d53f8008_8151ffad_80f0ec52_ffa5b13f_ffa6953f_80f3f00c_2e9f3873;
|
||||
defparam bootram.RAM6.INIT_0B=256'hb7ac3f00_800851ff_ffadb73f_ec528151_933f80f0_f73fffa5_f00cffa5_3f7280f3;
|
||||
defparam bootram.RAM6.INIT_0C=256'h70ff2e09_70085252_702dfc12_ff2e9138_08525270_0bfc0570_0d80f0f4_ff39ff3d;
|
||||
defparam bootram.RAM6.INIT_0D=256'h20612063_69766564_52656365_00000040_3f040000_04ffa6a1_833d0d04_8106f138;
|
||||
defparam bootram.RAM6.INIT_0E=256'h6c697479_74696269_6f6d7061_74682063_74207769_61636b65_6f6c2070_6f6e7472;
|
||||
defparam bootram.RAM6.INIT_0F=256'h7220636f_68206f75_20776974_79696e67_5265706c_25642e20_62657220_206e756d;
|
||||
defparam bootram.RAM6.INIT_10=256'h69766564_52656365_642e0a00_65722025_6e756d62_69747920_6962696c_6d706174;
|
||||
defparam bootram.RAM6.INIT_11=256'h796c6f61_64207061_65637465_20457870_6b65743a_20706163_686f7274_20612073;
|
||||
defparam bootram.RAM6.INIT_12=256'h64696e67_2053656e_2025642e_20676f74_20627574_2025642c_6e677468_64206c65;
|
||||
defparam bootram.RAM6.INIT_13=256'h0a657468_00000000_4841540a_55485f57_49445f48_54524c5f_50325f43_20555352;
|
||||
defparam bootram.RAM6.INIT_14=256'h0a556d54_640a0000_203d2025_70656564_643a2073_616e6765_6b206368_206c696e;
|
||||
defparam bootram.RAM6.INIT_15=256'h62696c69_70617469_20636f6d_46504741_720a0000_6f616465_6f6f746c_52582062;
|
||||
defparam bootram.RAM6.INIT_16=256'h2e25642d_3a202564_77617265_4669726d_640a0000_723a2025_756d6265_7479206e;
|
||||
defparam bootram.RAM6.INIT_17=256'h476f7420_00000000_61646472_00000000_646f6e65_20697320_496e6974_25780a00;
|
||||
defparam bootram.RAM6.INIT_18=256'h00000713_0000072a_00000000_65743a20_7061636b_65727920_65636f76_69702072;
|
||||
defparam bootram.RAM6.INIT_19=256'h000007c3_000007c3_000007c3_000007c3_000007c3_00000799_000007c3_000007c3;
|
||||
defparam bootram.RAM6.INIT_1A=256'h000007c3_000007c3_000007c3_000007c3_0000066d_000007c3_000006db_00000747;
|
||||
defparam bootram.RAM6.INIT_1B=256'h000006d2_000006cd_000006c8_000006c3_000006ac_000006a2_00000695_0000067a;
|
||||
defparam bootram.RAM6.INIT_1C=256'h20636869_4c4d5331_00000787_0000077a_00000773_0000076c_00000767_00000762;
|
||||
defparam bootram.RAM6.INIT_1D=256'h70207665_20636869_4c4d5332_0a000000_30782578_6e203d20_7273696f_70207665;
|
||||
defparam bootram.RAM6.INIT_1E=256'h4661696c_00000000_6f72740a_0a0a6162_0a000000_30782578_6e203d20_7273696f;
|
||||
defparam bootram.RAM6.INIT_1F=256'hc0a80a02_67000000_20666c61_626f6f74_61666520_61642073_6f207265_65642074;
|
||||
defparam bootram.RAM6.INIT_20=256'h38394142_34353637_30313233_01c300e2_054a0387_15290a94_3fff0000_0050c285;
|
||||
defparam bootram.RAM6.INIT_21=256'h38394142_34353637_30313233_2e256400_642e2564_25642e25_45000000_43444546;
|
||||
defparam bootram.RAM6.INIT_22=256'h6420616c_3a206261_5f706b74_73656e64_ffff0000_ffffffff_00000000_43444546;
|
||||
defparam bootram.RAM6.INIT_23=256'h6e65745f_66000000_72206275_6e642f6f_656e2061_6f66206c_656e7420_69676e6d;
|
||||
defparam bootram.RAM6.INIT_24=256'h6c6f6f6b_63686520_74206361_6f206869_65642074_6661696c_6f6e3a20_636f6d6d;
|
||||
defparam bootram.RAM6.INIT_25=256'h72642073_20776569_6172703a_646c655f_0a68616e_00000000_666f7220_696e6720;
|
||||
defparam bootram.RAM6.INIT_26=256'h206c656e_74656e74_6e736973_696e636f_55445020_0a000000_3d202564_697a6520;
|
||||
defparam bootram.RAM6.INIT_27=256'h20000000_3a202564_20444143_5443584f_00000000_2025640a_3a202564_67746873;
|
||||
defparam bootram.RAM6.INIT_28=256'h0a666c61_64210000_61696c65_4f472066_54434844_74205741_5f776169_73706966;
|
||||
defparam bootram.RAM6.INIT_29=256'h6c617368_6e672066_0a57726f_25640a00_697a653d_25642073_7970653d_73682074;
|
||||
defparam bootram.RAM6.INIT_2A=256'h6c617368_6e672066_0a57726f_00000000_6e67210a_63687475_652e2041_20747970;
|
||||
defparam bootram.RAM6.INIT_2B=256'h53504920_0b0b0000_10101200_67210a00_6874756e_64204163_653a2025_2073697a;
|
||||
defparam bootram.RAM6.INIT_2C=256'h50726f64_65640000_616c697a_6e697469_656e2069_73206265_68206861_466c6173;
|
||||
defparam bootram.RAM6.INIT_2D=256'h20556d54_74696e67_53746172_640a0000_203d2025_6d616765_6f6e2069_75637469;
|
||||
defparam bootram.RAM6.INIT_2E=256'h20666f72_6b696e67_43686563_00000000_6f64652e_6665206d_6e207361_52582069;
|
||||
defparam bootram.RAM6.INIT_2F=256'h2e2e2e00_6d616765_47412069_6e204650_6374696f_726f6475_69642070_2076616c;
|
||||
defparam bootram.RAM6.INIT_30=256'h666f756e_61676520_4120696d_20465047_74696f6e_6f647563_64207072_56616c69;
|
||||
defparam bootram.RAM6.INIT_31=256'h64756374_2070726f_616c6964_4e6f2076_00000000_6e672e2e_6f6f7469_642c2062;
|
||||
defparam bootram.RAM6.INIT_32=256'h64207072_56616c69_2e0a0000_6f756e64_67652066_20696d61_46504741_696f6e20;
|
||||
defparam bootram.RAM6.INIT_33=256'h64696e67_204c6f61_756e642e_6520666f_6d776172_20666972_74696f6e_6f647563;
|
||||
defparam bootram.RAM6.INIT_34=256'h523a2052_4552524f_2e000000_67652e2e_20696d61_74696e67_53746172_2e2e2e00;
|
||||
defparam bootram.RAM6.INIT_35=256'h2070726f_616c6964_4e6f2076_00000000_61696e21_6f6d206d_6e206672_65747572;
|
||||
defparam bootram.RAM6.INIT_36=256'h64207365_53706565_6e642100_20666f75_77617265_6669726d_696f6e20_64756374;
|
||||
defparam bootram.RAM6.INIT_37=256'h57455f52_58000000_57455f54_00000000_4e4f4e45_00000000_2025640a_7420746f;
|
||||
defparam bootram.RAM6.INIT_38=256'h7720636f_20666c6f_726e6574_65746865_43000000_45545249_53594d4d_58000000;
|
||||
defparam bootram.RAM6.INIT_39=256'h74652030_2077726f_4144563a_4e45475f_4155544f_5048595f_6c3a2000_6e74726f;
|
||||
defparam bootram.RAM6.INIT_3A=256'h00030203_00000001_00030003_00000000_780a0000_20307825_20676f74_7825782c;
|
||||
defparam bootram.RAM6.INIT_3B=256'h6c65723a_68616e64_6b657420_20706163_64617465_6e207570_6f722069_21457272;
|
||||
defparam bootram.RAM6.INIT_3C=256'h20627574_2025642c_6e677468_64206c65_796c6f61_64207061_65637465_20457870;
|
||||
defparam bootram.RAM6.INIT_3D=256'h00002bf0_00002c05_00002c57_00002c57_00002bc1_00000000_2025640a_20676f74;
|
||||
defparam bootram.RAM6.INIT_3E=256'h00002c57_00002c57_00002c57_00002c57_00002c57_00002c57_00002c57_00002bce;
|
||||
defparam bootram.RAM6.INIT_3F=256'h00002c57_00002c57_00002c4b_00002c34_00002c57_00002c57_00002c57_00002c57;
|
||||
defparam bootram.RAM7.INIT_00=256'hffff00ff_ff00ffff_00ffffff_65000000_792e6578_64756d6d_00002c21_00002be0;
|
||||
defparam bootram.RAM7.INIT_01=256'h3fff0000_0050c285_c0a80a02_0000387c_00000000_00000000_00000000_ffffff00;
|
||||
defparam bootram.RAM7.INIT_02=256'h000036ec_02000000_18cba800_000c0000_00190010_ffff0033_04000400_01010100;
|
||||
defparam bootram.RAM7.INIT_03=256'h00000000_ffffffff_00000000_ffffffff_00003808_00003704_000036fc_000036f4;
|
||||
defparam bootram.RAM7.INIT_04=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM7.INIT_05=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
defparam bootram.RAM7.INIT_06=256'h00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000;
|
||||
|
||||
28
fpga/top/UmTRX/mapextraeffortioreg.xds
Normal file
28
fpga/top/UmTRX/mapextraeffortioreg.xds
Normal file
@@ -0,0 +1,28 @@
|
||||
<DesignStrategy goal="Timing Performance" strategy="SmartXplorer - mapextraeffortioreg" version="14.7">
|
||||
<Description><![CDATA[ This is a Timing Performance optimized strategy.This strategy is also one of the strategies used by SmartXplorer. If you wish to run SmartXplorer to automatically try multiple Timing Performance strategies, including this one, close this dialog and then select Tools -> SmartXplorer -> Launch SmartXplorer . ]]></Description>
|
||||
<DeviceList devices="spartan6,spartan6l,aspartan6,qspartan6,qspartan6l" />
|
||||
<Properties>
|
||||
<property name = "Map:Placer Effort Level"
|
||||
value = "High" />
|
||||
<property name = "Map:Placer Extra Effort"
|
||||
value = "Normal" />
|
||||
<property name = "Map:Pack I/O Registers/Latches into IOBs"
|
||||
value = "For Inputs and Outputs" />
|
||||
<property name = "Map:Starting Placer Cost Table (1-100)"
|
||||
value = "24" />
|
||||
<property name = "Place & Route:Place & Route Effort Level (Overall)"
|
||||
value = "High" />
|
||||
<property name = "Place & Route:Extra Effort (Highest PAR level only)"
|
||||
value = "Normal" />
|
||||
<property name = "Generate Post-Place & Route Static Timing:Number of Paths in Error/Verbose Report"
|
||||
value = "10" />
|
||||
<property name = "Generate Post-Place & Route Static Timing:Report Type"
|
||||
value = "Error Report" />
|
||||
<property name = "Generate Post-Place & Route Static Timing:Change Device Speed To"
|
||||
value = "-2" />
|
||||
<property name = "Generate Post-Place & Route Static Timing:Report Paths by Endpoint"
|
||||
value = "3" />
|
||||
<property name = "Generate Post-Place & Route Static Timing:Report Fastest Path(s) in Each Constraint"
|
||||
value = "true" />
|
||||
</Properties>
|
||||
</DesignStrategy>
|
||||
@@ -174,6 +174,10 @@ module umtrx_core
|
||||
wire [7:0] set_addr, set_addr_dsp, set_addr_sys, set_addr_fe, set_addr_udp_wb, set_addr_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_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;
|
||||
wire dsp_rst, sys_rst, fe_rst;
|
||||
@@ -412,17 +416,80 @@ module umtrx_core
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// SPI -- Slave #2
|
||||
wire [31:0] spi_debug;
|
||||
wire [31:0] spi_readback;
|
||||
reg [31:0] spi_readback0;
|
||||
reg [31:0] spi_readback1;
|
||||
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),
|
||||
.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}),
|
||||
.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_master_top #(.ARST_LVL(1))
|
||||
@@ -448,7 +515,7 @@ module umtrx_core
|
||||
// Buffer Pool Status -- Slave #5
|
||||
|
||||
//compatibility number -> increment when the fpga has been sufficiently altered
|
||||
localparam compat_num = {16'd9, 16'd0}; //major, minor
|
||||
localparam compat_num = {16'd9, 16'd3}; //major, minor
|
||||
|
||||
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_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),
|
||||
.word08(status),.word09(32'b0),.word10(vita_time[63:32]),
|
||||
.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_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
|
||||
assign set_stb_dsp = set_stb_dsp0 | set_stb_dsp1;
|
||||
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),
|
||||
.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),
|
||||
.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),
|
||||
.word08(32'b0),.word09(32'b0),.word10(vita_time[63:32]),
|
||||
.word11(vita_time[31:0]),.word12(32'b0),.word13(irq_readback),
|
||||
@@ -672,20 +735,20 @@ module umtrx_core
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// RX Frontend
|
||||
wire [23:0] front0_i, front0_q;
|
||||
wire [23:0] rx_front0_i, rx_front0_q;
|
||||
rx_frontend #(.BASE(SR_RX_FRONT0)) rx_frontend0
|
||||
(
|
||||
.clk(fe_clk), .rst(fe_rst),
|
||||
.set_stb(set_stb_fe),.set_addr(set_addr_fe),.set_data(set_data_fe),
|
||||
.i_out(front0_i), .q_out(front0_q), .run(1'b1),
|
||||
.i_out(rx_front0_i), .q_out(rx_front0_q), .run(1'b1),
|
||||
.adc_a({adc0_a, 4'b0}), .adc_b({adc0_b, 4'b0})
|
||||
);
|
||||
wire [23:0] front1_i, front1_q;
|
||||
wire [23:0] rx_front1_i, rx_front1_q;
|
||||
rx_frontend #(.BASE(SR_RX_FRONT1)) rx_frontend1
|
||||
(
|
||||
.clk(fe_clk), .rst(fe_rst),
|
||||
.set_stb(set_stb_fe),.set_addr(set_addr_fe),.set_data(set_data_fe),
|
||||
.i_out(front1_i), .q_out(front1_q), .run(1'b1),
|
||||
.i_out(rx_front1_i), .q_out(rx_front1_q), .run(1'b1),
|
||||
.adc_a({adc1_a, 4'b0}), .adc_b({adc1_b, 4'b0})
|
||||
);
|
||||
|
||||
@@ -716,8 +779,8 @@ module umtrx_core
|
||||
.fe_clk(fe_clk), .fe_rst(fe_rst),
|
||||
.set_stb_dsp(set_stb_dsp), .set_addr_dsp(set_addr_dsp), .set_data_dsp(set_data_dsp),
|
||||
.set_stb_fe(set_stb_fe), .set_addr_fe(set_addr_fe), .set_data_fe(set_data_fe),
|
||||
.front_i(rx_fe_sw[0]?front1_i:front0_i),
|
||||
.front_q(rx_fe_sw[0]?front1_q:front0_q),
|
||||
.front_i(rx_fe_sw[0]?rx_front1_i:rx_front0_i),
|
||||
.front_q(rx_fe_sw[0]?rx_front1_q:rx_front0_q),
|
||||
.adc_stb(rx_fe_sw[0]?adc1_strobe:adc0_strobe),
|
||||
.run(run_rx_dsp[0]),
|
||||
.vita_data_sys(dsp_rx0_data), .vita_valid_sys(dsp_rx0_valid), .vita_ready_sys(dsp_rx0_ready),
|
||||
@@ -743,8 +806,8 @@ module umtrx_core
|
||||
.fe_clk(fe_clk), .fe_rst(fe_rst),
|
||||
.set_stb_dsp(set_stb_dsp), .set_addr_dsp(set_addr_dsp), .set_data_dsp(set_data_dsp),
|
||||
.set_stb_fe(set_stb_fe), .set_addr_fe(set_addr_fe), .set_data_fe(set_data_fe),
|
||||
.front_i(rx_fe_sw[1]?front1_i:front0_i),
|
||||
.front_q(rx_fe_sw[1]?front1_q:front0_q),
|
||||
.front_i(rx_fe_sw[1]?rx_front1_i:rx_front0_i),
|
||||
.front_q(rx_fe_sw[1]?rx_front1_q:rx_front0_q),
|
||||
.adc_stb(rx_fe_sw[1]?adc1_strobe:adc0_strobe),
|
||||
.run(run_rx_dsp[1]),
|
||||
.vita_data_sys(dsp_rx1_data), .vita_valid_sys(dsp_rx1_valid), .vita_ready_sys(dsp_rx1_ready),
|
||||
@@ -770,8 +833,8 @@ module umtrx_core
|
||||
.fe_clk(fe_clk), .fe_rst(fe_rst),
|
||||
.set_stb_dsp(set_stb_dsp), .set_addr_dsp(set_addr_dsp), .set_data_dsp(set_data_dsp),
|
||||
.set_stb_fe(set_stb_fe), .set_addr_fe(set_addr_fe), .set_data_fe(set_data_fe),
|
||||
.front_i(rx_fe_sw[2]?front1_i:front0_i),
|
||||
.front_q(rx_fe_sw[2]?front1_q:front0_q),
|
||||
.front_i(rx_fe_sw[2]?rx_front1_i:rx_front0_i),
|
||||
.front_q(rx_fe_sw[2]?rx_front1_q:rx_front0_q),
|
||||
.adc_stb(rx_fe_sw[2]?adc1_strobe:adc0_strobe),
|
||||
.run(run_rx_dsp[2]),
|
||||
.vita_data_sys(dsp_rx2_data), .vita_valid_sys(dsp_rx2_valid), .vita_ready_sys(dsp_rx2_ready),
|
||||
@@ -797,8 +860,8 @@ module umtrx_core
|
||||
.fe_clk(fe_clk), .fe_rst(fe_rst),
|
||||
.set_stb_dsp(set_stb_dsp), .set_addr_dsp(set_addr_dsp), .set_data_dsp(set_data_dsp),
|
||||
.set_stb_fe(set_stb_fe), .set_addr_fe(set_addr_fe), .set_data_fe(set_data_fe),
|
||||
.front_i(rx_fe_sw[3]?front1_i:front0_i),
|
||||
.front_q(rx_fe_sw[3]?front1_q:front0_q),
|
||||
.front_i(rx_fe_sw[3]?rx_front1_i:rx_front0_i),
|
||||
.front_q(rx_fe_sw[3]?rx_front1_q:rx_front0_q),
|
||||
.adc_stb(rx_fe_sw[3]?adc1_strobe:adc0_strobe),
|
||||
.run(run_rx_dsp[3]),
|
||||
.vita_data_sys(dsp_rx3_data), .vita_valid_sys(dsp_rx3_valid), .vita_ready_sys(dsp_rx3_ready),
|
||||
@@ -810,6 +873,28 @@ module umtrx_core
|
||||
end
|
||||
endgenerate
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// TX Frontend
|
||||
wire [23:0] tx_front0_i, tx_front0_q;
|
||||
wire [3:0] dac0_a_pad, dac0_b_pad;
|
||||
tx_frontend #(.BASE(SR_TX_FRONT0)) tx_frontend0
|
||||
(
|
||||
.clk(fe_clk), .rst(fe_rst),
|
||||
.set_stb(set_stb_fe),.set_addr(set_addr_fe),.set_data(set_data_fe),
|
||||
.tx_i(tx_front0_i), .tx_q(tx_front0_q), .run(1'b1),
|
||||
.dac_a({dac0_a, dac0_a_pad}), .dac_b({dac0_b, dac0_b_pad})
|
||||
);
|
||||
|
||||
wire [23:0] tx_front1_i, tx_front1_q;
|
||||
wire [3:0] dac1_a_pad, dac1_b_pad;
|
||||
tx_frontend #(.BASE(SR_TX_FRONT1)) tx_frontend1
|
||||
(
|
||||
.clk(fe_clk), .rst(fe_rst),
|
||||
.set_stb(set_stb_fe),.set_addr(set_addr_fe),.set_data(set_data_fe),
|
||||
.tx_i(tx_front1_i), .tx_q(tx_front1_q), .run(1'b1),
|
||||
.dac_a({dac1_a, dac1_a_pad}), .dac_b({dac1_b, dac1_b_pad})
|
||||
);
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// TX chains
|
||||
wire [35:0] sram0_data, sram1_data;
|
||||
@@ -823,10 +908,10 @@ module umtrx_core
|
||||
(.clk(dsp_clk),.rst(dsp_rst),.strobe(set_stb_dsp),.addr(set_addr_dsp),.in(set_data_dsp),.out(tx_fe_sw),.changed());
|
||||
|
||||
//assign dac switch
|
||||
wire [11:0] dac0_a_int, dac0_b_int;
|
||||
wire [11:0] dac1_a_int, dac1_b_int;
|
||||
assign {dac0_a, dac0_b} = (tx_fe_sw == 0)? {dac0_a_int, dac0_b_int} : {dac1_a_int, dac1_b_int};
|
||||
assign {dac1_a, dac1_b} = (tx_fe_sw == 1)? {dac0_a_int, dac0_b_int} : {dac1_a_int, dac1_b_int};
|
||||
wire [23:0] dac0_a_int, dac0_b_int;
|
||||
wire [23:0] dac1_a_int, dac1_b_int;
|
||||
assign {tx_front0_i, tx_front0_q} = (tx_fe_sw == 0)? {dac0_a_int, dac0_b_int} : {dac1_a_int, dac1_b_int};
|
||||
assign {tx_front1_i, tx_front1_q} = (tx_fe_sw == 1)? {dac0_a_int, dac0_b_int} : {dac1_a_int, dac1_b_int};
|
||||
|
||||
generate
|
||||
if (`NUMDUC > 0) begin
|
||||
@@ -834,7 +919,6 @@ module umtrx_core
|
||||
#(
|
||||
.PROT_DEST(0),
|
||||
.DSPNO(0),
|
||||
.FRONT_BASE(SR_TX_FRONT0),
|
||||
.DSP_BASE(SR_TX_DSP0),
|
||||
.CTRL_BASE(SR_TX_CTRL0),
|
||||
.FIFOSIZE(DSP_TX_FIFOSIZE)
|
||||
@@ -846,7 +930,7 @@ module umtrx_core
|
||||
.fe_clk(fe_clk), .fe_rst(fe_rst),
|
||||
.set_stb_dsp(set_stb_dsp), .set_addr_dsp(set_addr_dsp), .set_data_dsp(set_data_dsp),
|
||||
.set_stb_fe(set_stb_fe), .set_addr_fe(set_addr_fe), .set_data_fe(set_data_fe),
|
||||
.dac_a(dac0_a_int), .dac_b(dac0_b_int), .dac_stb(dac0_strobe), .run(run_tx_dsp0),
|
||||
.front_i(dac0_a_int), .front_q(dac0_b_int), .dac_stb(dac0_strobe), .run(run_tx_dsp0),
|
||||
.vita_data_sys(sram0_data), .vita_valid_sys(sram0_valid), .vita_ready_sys(sram0_ready),
|
||||
.err_data_sys(err_tx0_data), .err_valid_sys(err_tx0_valid), .err_ready_sys(err_tx0_ready),
|
||||
.vita_time(vita_time)
|
||||
@@ -861,7 +945,6 @@ module umtrx_core
|
||||
#(
|
||||
.PROT_DEST(1),
|
||||
.DSPNO(1),
|
||||
.FRONT_BASE(SR_TX_FRONT1),
|
||||
.DSP_BASE(SR_TX_DSP1),
|
||||
.CTRL_BASE(SR_TX_CTRL1),
|
||||
.FIFOSIZE(DSP_TX_FIFOSIZE)
|
||||
@@ -873,7 +956,7 @@ module umtrx_core
|
||||
.fe_clk(fe_clk), .fe_rst(fe_rst),
|
||||
.set_stb_dsp(set_stb_dsp), .set_addr_dsp(set_addr_dsp), .set_data_dsp(set_data_dsp),
|
||||
.set_stb_fe(set_stb_fe), .set_addr_fe(set_addr_fe), .set_data_fe(set_data_fe),
|
||||
.dac_a(dac1_a_int), .dac_b(dac1_b_int), .dac_stb(dac1_strobe), .run(run_tx_dsp1),
|
||||
.front_i(dac1_a_int), .front_q(dac1_b_int), .dac_stb(dac1_strobe), .run(run_tx_dsp1),
|
||||
.vita_data_sys(sram1_data), .vita_valid_sys(sram1_valid), .vita_ready_sys(sram1_ready),
|
||||
.err_data_sys(err_tx1_data), .err_valid_sys(err_tx1_valid), .err_ready_sys(err_tx1_ready),
|
||||
.vita_time(vita_time)
|
||||
|
||||
@@ -6,7 +6,6 @@ module umtrx_tx_chain
|
||||
#(
|
||||
parameter PROT_DEST = 0, //framer index
|
||||
parameter DSPNO = 0, //the dsp unit number: 0, 1, 2...
|
||||
parameter FRONT_BASE = 0,
|
||||
parameter DSP_BASE = 0,
|
||||
parameter CTRL_BASE = 0,
|
||||
parameter FIFOSIZE = 10,
|
||||
@@ -32,9 +31,9 @@ module umtrx_tx_chain
|
||||
input [7:0] set_addr_fe,
|
||||
input [31:0] set_data_fe,
|
||||
|
||||
//dsp clock domain
|
||||
output reg [11:0] dac_a,
|
||||
output reg [11:0] dac_b,
|
||||
//fe clock domain
|
||||
output [23:0] front_i,
|
||||
output [23:0] front_q,
|
||||
input dac_stb,
|
||||
output run,
|
||||
|
||||
@@ -52,28 +51,6 @@ module umtrx_tx_chain
|
||||
wire [63:0] vita_time
|
||||
);
|
||||
|
||||
/*******************************************************************
|
||||
* Cross DAC signals from fe to dsp clock domain
|
||||
* dac_a/b come from a register on the fe clock domain
|
||||
******************************************************************/
|
||||
wire [15:0] dac_a_16, dac_b_16;
|
||||
always @(posedge fe_clk) begin
|
||||
dac_a <= dac_a_16[15:4];
|
||||
dac_b <= dac_b_16[15:4];
|
||||
end
|
||||
|
||||
/*******************************************************************
|
||||
* TX frontend on fe clock domain
|
||||
******************************************************************/
|
||||
wire [23:0] front_i, front_q;
|
||||
tx_frontend #(.BASE(FRONT_BASE)) tx_frontend
|
||||
(
|
||||
.clk(fe_clk), .rst(fe_rst),
|
||||
.set_stb(set_stb_fe),.set_addr(set_addr_fe),.set_data(set_data_fe),
|
||||
.tx_i(front_i), .tx_q(front_q), .run(1'b1),
|
||||
.dac_a(dac_a_16), .dac_b(dac_b_16)
|
||||
);
|
||||
|
||||
/*******************************************************************
|
||||
* DUC chain on fe clock domain
|
||||
******************************************************************/
|
||||
@@ -180,8 +157,6 @@ module umtrx_tx_chain
|
||||
assign DATA[63:32] = vita_sample;
|
||||
assign DATA[95:64] = duc_sample;
|
||||
assign DATA[127:96] = {front_i[23:8], front_q[23:8]};
|
||||
assign DATA[159:128] = {dac_a_16, dac_b_16};
|
||||
assign DATA[191:160] = {dac_a, 4'b0, dac_b, 4'b0};
|
||||
end
|
||||
endgenerate
|
||||
|
||||
|
||||
@@ -21,13 +21,25 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project(UmTRX-UHD)
|
||||
|
||||
set(UMTRX_VERSION 1.0.0)
|
||||
########################################################################
|
||||
# extract version info from git
|
||||
########################################################################
|
||||
include(${PROJECT_SOURCE_DIR}/cmake/GetGitRevisionDescription.cmake)
|
||||
git_describe(UMTRX_VERSION --dirty)
|
||||
string(REPLACE "g" "" UMTRX_VERSION ${UMTRX_VERSION}) #remove hash prefix g
|
||||
message(STATUS "UMTRX_VERSION: ${UMTRX_VERSION}")
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/umtrx_version.in.hpp"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/umtrx_version.hpp"
|
||||
IMMEDIATE @ONLY)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
########################################################################
|
||||
## Create a list of module sources
|
||||
########################################################################
|
||||
list(APPEND UMTRX_SOURCES
|
||||
umtrx_impl.cpp
|
||||
umtrx_monitor.cpp
|
||||
umtrx_io_impl.cpp
|
||||
umtrx_find.cpp
|
||||
umtrx_iface.cpp
|
||||
@@ -36,6 +48,7 @@ list(APPEND UMTRX_SOURCES
|
||||
lms6002d_ctrl.cpp
|
||||
tmp102_ctrl.cpp
|
||||
ads1015_ctrl.cpp
|
||||
power_amp.cpp
|
||||
umtrx_fifo_ctrl.cpp
|
||||
missing/platform.cpp #not properly exported from uhd, so we had to copy it
|
||||
cores/rx_frontend_core_200.cpp
|
||||
@@ -45,6 +58,7 @@ list(APPEND UMTRX_SOURCES
|
||||
cores/time64_core_200.cpp
|
||||
cores/validate_subdev_spec.cpp
|
||||
cores/apply_corrections.cpp
|
||||
umsel2_ctrl.cpp
|
||||
)
|
||||
|
||||
########################################################################
|
||||
@@ -98,7 +112,7 @@ SET(Boost_ADDITIONAL_VERSIONS
|
||||
"1.60.0" "1.60" "1.61.0" "1.61" "1.62.0" "1.62" "1.63.0" "1.63" "1.64.0" "1.64"
|
||||
"1.65.0" "1.65" "1.66.0" "1.66" "1.67.0" "1.67" "1.68.0" "1.68" "1.69.0" "1.69"
|
||||
)
|
||||
FIND_PACKAGE(Boost 1.36 COMPONENTS ${BOOST_REQUIRED_COMPONENTS})
|
||||
FIND_PACKAGE(Boost 1.36 REQUIRED COMPONENTS ${BOOST_REQUIRED_COMPONENTS})
|
||||
|
||||
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
|
||||
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
|
||||
@@ -115,6 +129,10 @@ if (UNIX)
|
||||
list(APPEND UMTRX_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
#make boost property tree thread safe
|
||||
#http://stackoverflow.com/questions/8156948/is-boostproperty-treeptree-thread-safe
|
||||
add_definitions(-DBOOST_SPIRIT_THREADSAFE)
|
||||
|
||||
########################################################################
|
||||
# Helpful compiler flags
|
||||
########################################################################
|
||||
@@ -133,7 +151,7 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
endif()
|
||||
|
||||
########################################################################
|
||||
# Look for device filter
|
||||
# UHD compatibility checks
|
||||
########################################################################
|
||||
message(STATUS "Checking uhd::device::register_device() API...")
|
||||
message(STATUS " Reading ${UHD_INCLUDE_DIRS}/uhd/device.hpp...")
|
||||
@@ -146,6 +164,19 @@ else()
|
||||
message(STATUS " has filter API")
|
||||
endif()
|
||||
|
||||
message(STATUS "Checking uhd::property::set_publisher() API...")
|
||||
message(STATUS " Reading ${UHD_INCLUDE_DIRS}/uhd/property_tree.hpp...")
|
||||
file(READ ${UHD_INCLUDE_DIRS}/uhd/property_tree.hpp property_tree_hpp)
|
||||
string(FIND "${property_tree_hpp}" "set_publisher" has_set_publisher)
|
||||
if ("${has_set_publisher}" STREQUAL "-1")
|
||||
message(STATUS " missing set_publisher() API")
|
||||
else()
|
||||
add_definitions(-Dpublish=set_publisher)
|
||||
add_definitions(-Dsubscribe=add_desired_subscriber)
|
||||
add_definitions(-Dcoerce=add_coerced_subscriber)
|
||||
message(STATUS " has set_publisher() API")
|
||||
endif()
|
||||
|
||||
########################################################################
|
||||
# Build the UmTRX module
|
||||
########################################################################
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1700)
|
||||
#define nan(arg) std::strtod("NAN()", (char**)NULL)
|
||||
#endif
|
||||
|
||||
using namespace uhd;
|
||||
|
||||
ads1015_ctrl::ads1015_ctrl()
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
*
|
||||
* Control of TI's ADS1015 12bit ADC with 4 muliplexers
|
||||
*/
|
||||
class UHD_API ads1015_ctrl {
|
||||
class ads1015_ctrl {
|
||||
public:
|
||||
enum ads1015_addr {
|
||||
ADS1015_NONE = 0,
|
||||
|
||||
136
host/cmake/GetGitRevisionDescription.cmake
Normal file
136
host/cmake/GetGitRevisionDescription.cmake
Normal file
@@ -0,0 +1,136 @@
|
||||
# - Returns a version string from Git
|
||||
#
|
||||
# These functions force a re-configure on each git commit so that you can
|
||||
# trust the values of the variables in your build system.
|
||||
#
|
||||
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the source tree, and adjusting
|
||||
# the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe --exact-match on the source tree,
|
||||
# and adjusting the output so that it tests false if there was no exact
|
||||
# matching tag.
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(__get_git_revision_description)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_revision_description YES)
|
||||
|
||||
# We must run the following at "include" time, not at function call time,
|
||||
# to find the path to this module rather than the path to a calling list file
|
||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
|
||||
function(get_git_head_revision _refspecvar _hashvar)
|
||||
set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
||||
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
||||
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
||||
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
endwhile()
|
||||
# check if this is a submodule
|
||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||
file(READ ${GIT_DIR} submodule)
|
||||
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
|
||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
|
||||
endif()
|
||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||
if(NOT EXISTS "${GIT_DATA}")
|
||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||
"${GIT_DATA}/grabRef.cmake"
|
||||
@ONLY)
|
||||
include("${GIT_DATA}/grabRef.cmake")
|
||||
|
||||
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
|
||||
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# TODO sanitize
|
||||
#if((${ARGN}" MATCHES "&&") OR
|
||||
# (ARGN MATCHES "||") OR
|
||||
# (ARGN MATCHES "\\;"))
|
||||
# message("Please report the following error to the project!")
|
||||
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||
#endif()
|
||||
|
||||
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||
|
||||
#support dirty option (hash cant be specified)
|
||||
list(FIND ARGN "--dirty" _index)
|
||||
if (${_index} GREATER -1)
|
||||
unset(hash)
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}"
|
||||
describe
|
||||
${hash}
|
||||
${ARGN}
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_SOURCE_DIR}"
|
||||
RESULT_VARIABLE
|
||||
res
|
||||
OUTPUT_VARIABLE
|
||||
out
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_get_exact_tag _var)
|
||||
git_describe(out --exact-match ${ARGN})
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
38
host/cmake/GetGitRevisionDescription.cmake.in
Normal file
38
host/cmake/GetGitRevisionDescription.cmake.in
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
set(HEAD_HASH)
|
||||
|
||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||
|
||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||
if(HEAD_CONTENTS MATCHES "ref")
|
||||
# named branch
|
||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
set(HEAD_HASH "${HEAD_REF}")
|
||||
endif()
|
||||
else()
|
||||
# detached HEAD
|
||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
endif()
|
||||
@@ -105,7 +105,13 @@ static void apply_fe_corrections(
|
||||
|
||||
//make the calibration file path
|
||||
const fs::path cal_data_path = fs::path(uhd::get_app_path()) / ".uhd" / "cal" / (file_prefix + db_eeprom.serial + ".csv");
|
||||
if (not fs::exists(cal_data_path)) return;
|
||||
UHD_MSG(status) << "Looking for FE correction at: " << cal_data_path.c_str() << "... ";
|
||||
if (not fs::exists(cal_data_path)) {
|
||||
UHD_MSG(status) << "Not found" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
UHD_MSG(status) << "Found, loading... ";
|
||||
|
||||
//parse csv file or get from cache
|
||||
if (not fe_cal_cache.has_key(cal_data_path.string())){
|
||||
@@ -133,8 +139,9 @@ static void apply_fe_corrections(
|
||||
}
|
||||
std::sort(datas.begin(), datas.end(), fe_cal_comp);
|
||||
fe_cal_cache[cal_data_path.string()] = datas;
|
||||
UHD_MSG(status) << "Loaded " << cal_data_path.string() << std::endl;
|
||||
|
||||
UHD_MSG(status) << "Loaded" << std::endl;
|
||||
} else {
|
||||
UHD_MSG(status) << "Loaded from cache" << std::endl;
|
||||
}
|
||||
|
||||
sub_tree->access<std::complex<double> >(fe_path)
|
||||
|
||||
@@ -202,6 +202,141 @@ void lms6002d_dev::set_txrx_polarity_and_interleaving(int rx_fsync_polarity,
|
||||
lms_write_bits(0x5A, 0xD8, data);
|
||||
}
|
||||
|
||||
void lms6002d_dev::set_dc_calibration_value(uint8_t dc_addr, uint8_t calibration_reg_base, uint8_t value)
|
||||
{
|
||||
uint8_t reg_val;
|
||||
|
||||
if (verbosity > 0) printf("Manually setting DC Offset Calibration for base %x, ADDR %d: %d\n", calibration_reg_base, dc_addr, value);
|
||||
|
||||
// DC_CNTVAL[5:0] = value
|
||||
write_reg(calibration_reg_base+0x02, value&0x3f);
|
||||
// Save old register value
|
||||
reg_val = read_reg(calibration_reg_base+0x03);
|
||||
// DC_ADDR := ADDR
|
||||
reg_val = (reg_val & 0xf8) | dc_addr;
|
||||
write_reg(calibration_reg_base+0x03, reg_val);
|
||||
// DC_LOAD := 1
|
||||
reg_val = reg_val | (1 << 4);
|
||||
write_reg(calibration_reg_base+0x03, reg_val);
|
||||
// DC_LOAD := 0
|
||||
reg_val = reg_val ^ (1 << 4);
|
||||
write_reg(calibration_reg_base+0x03, reg_val);
|
||||
}
|
||||
|
||||
uint8_t lms6002d_dev::get_dc_calibration_value(uint8_t dc_addr, uint8_t calibration_reg_base)
|
||||
{
|
||||
// DC_ADDR := ADDR
|
||||
lms_write_bits(calibration_reg_base+0x03, 0xf8, dc_addr);
|
||||
|
||||
uint8_t res = read_reg(calibration_reg_base);
|
||||
if (verbosity > 0) printf("Reading DC Offset Calibration for base %x, ADDR %d: %d\n", calibration_reg_base, dc_addr, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void lms6002d_dev::set_rxfe_dc_i(int8_t value)
|
||||
{
|
||||
uint8_t coded_value = (value<0)?(64-value):value;
|
||||
if (verbosity > 0) printf("Setting DC Offset Calibration for RxFE Channel I to %d (0x%X)\n", value, coded_value);
|
||||
// DCOFF_I_RXFE := value
|
||||
lms_write_bits(0x71, 0x7f, coded_value);
|
||||
}
|
||||
|
||||
int8_t lms6002d_dev::get_rxfe_dc_i()
|
||||
{
|
||||
uint8_t res = lms_read_shift(0x71, 0x3f, 0);
|
||||
uint8_t sign = lms_read_shift(0x71, 0x40, 6);
|
||||
if (verbosity > 0) printf("Reading DC Offset Calibration for RxFE Channel I: sign=%d val=%d)\n", sign, res);
|
||||
return sign?-res:res;
|
||||
}
|
||||
|
||||
void lms6002d_dev::set_rxfe_dc_q(int8_t value)
|
||||
{
|
||||
uint8_t coded_value = (value<0)?(64-value):value;
|
||||
if (verbosity > 0) printf("Setting DC Offset Calibration for RxFE Channel Q to %d (0x%X)\n", value, coded_value);
|
||||
// DCOFF_I_RXFE := value
|
||||
lms_write_bits(0x72, 0x7f, coded_value);
|
||||
}
|
||||
|
||||
int8_t lms6002d_dev::get_rxfe_dc_q()
|
||||
{
|
||||
uint8_t res = lms_read_shift(0x72, 0x3f, 0);
|
||||
uint8_t sign = lms_read_shift(0x72, 0x40, 6);
|
||||
if (verbosity > 0) printf("Reading DC Offset Calibration for RxFE Channel Q: sign=%d val=%d)\n", sign, res);
|
||||
return sign?-res:res;
|
||||
}
|
||||
|
||||
void lms6002d_dev::set_rxlpf_dc_i(uint8_t value)
|
||||
{
|
||||
set_dc_calibration_value(0, 0x50, value);
|
||||
}
|
||||
|
||||
uint8_t lms6002d_dev::get_rxlpf_dc_i()
|
||||
{
|
||||
return get_dc_calibration_value(0, 0x50);
|
||||
}
|
||||
|
||||
void lms6002d_dev::set_rxlpf_dc_q(uint8_t value)
|
||||
{
|
||||
set_dc_calibration_value(1, 0x50, value);
|
||||
}
|
||||
|
||||
uint8_t lms6002d_dev::get_rxlpf_dc_q()
|
||||
{
|
||||
return get_dc_calibration_value(1, 0x50);
|
||||
}
|
||||
|
||||
void lms6002d_dev::set_rxvga2_dc_reference(uint8_t value)
|
||||
{
|
||||
set_dc_calibration_value(0, 0x60, value);
|
||||
}
|
||||
|
||||
uint8_t lms6002d_dev::get_rxvga2_dc_reference()
|
||||
{
|
||||
return get_dc_calibration_value(0, 0x60);
|
||||
}
|
||||
|
||||
void lms6002d_dev::set_rxvga2a_dc_i(uint8_t value)
|
||||
{
|
||||
set_dc_calibration_value(1, 0x60, value);
|
||||
}
|
||||
|
||||
uint8_t lms6002d_dev::get_rxvga2a_dc_i()
|
||||
{
|
||||
return get_dc_calibration_value(1, 0x60);
|
||||
}
|
||||
|
||||
void lms6002d_dev::set_rxvga2a_dc_q(uint8_t value)
|
||||
{
|
||||
set_dc_calibration_value(2, 0x60, value);
|
||||
}
|
||||
|
||||
uint8_t lms6002d_dev::get_rxvga2a_dc_q()
|
||||
{
|
||||
return get_dc_calibration_value(2, 0x60);
|
||||
}
|
||||
|
||||
void lms6002d_dev::set_rxvga2b_dc_i(uint8_t value)
|
||||
{
|
||||
set_dc_calibration_value(3, 0x60, value);
|
||||
}
|
||||
|
||||
uint8_t lms6002d_dev::get_rxvga2b_dc_i()
|
||||
{
|
||||
return get_dc_calibration_value(3, 0x60);
|
||||
}
|
||||
|
||||
void lms6002d_dev::set_rxvga2b_dc_q(uint8_t value)
|
||||
{
|
||||
set_dc_calibration_value(4, 0x60, value);
|
||||
}
|
||||
|
||||
uint8_t lms6002d_dev::get_rxvga2b_dc_q()
|
||||
{
|
||||
return get_dc_calibration_value(4, 0x60);
|
||||
}
|
||||
|
||||
|
||||
int lms6002d_dev::general_dc_calibration_loop(uint8_t dc_addr, uint8_t calibration_reg_base)
|
||||
{
|
||||
uint8_t reg_val;
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
#define INCLUDED_LMS6002D_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
|
||||
/*!
|
||||
* LMS6002D control class
|
||||
@@ -91,6 +92,14 @@ public:
|
||||
lms_clear_bits(0x09, (1 << 2));
|
||||
}
|
||||
|
||||
bool get_tx_pll_locked() {
|
||||
return get_txrx_pll_locked(0x10);
|
||||
}
|
||||
|
||||
bool get_rx_pll_locked() {
|
||||
return get_txrx_pll_locked(0x20);
|
||||
}
|
||||
|
||||
uint8_t get_tx_pa() {
|
||||
return lms_read_shift(0x44, (0x07 << 3), 3);
|
||||
}
|
||||
@@ -134,23 +143,49 @@ public:
|
||||
return lms_read_shift(0x41, 0x1f, 0) - 35;
|
||||
}
|
||||
|
||||
/** Set Rx VGA1 gain.
|
||||
gain is raw values [0 .. 127]
|
||||
/** Set Rx VGA1 gain raw value
|
||||
gain is raw values [0 .. 120]
|
||||
Returns the old gain value */
|
||||
int8_t set_rx_vga1gain(int8_t gain){
|
||||
if (gain < 0) // according to standard max value of int8_t is always 127
|
||||
int8_t set_rx_vga1gain_int(int8_t gain){
|
||||
if (gain < 0 || gain >120)
|
||||
gain = 0;
|
||||
int8_t old_bits = lms_write_bits(0x76, 0x7f, gain);
|
||||
return old_bits & 0x7f;
|
||||
}
|
||||
|
||||
/** Get Rx VGA1 gain in dB.
|
||||
gain is in [0 .. 127] range of abstract values
|
||||
/** Get Rx VGA1 gain raw value
|
||||
gain is in [0 .. 120] range of abstract values
|
||||
Returns the gain value */
|
||||
int8_t get_rx_vga1gain(){
|
||||
int8_t get_rx_vga1gain_int(){
|
||||
return lms_read_shift(0x76, 0x7f, 0);
|
||||
}
|
||||
|
||||
/** Converts Rx VGA1 raw values to absolute dBs
|
||||
code must be in [0 .. 120] range */
|
||||
double rxvga1_int_to_db(int8_t code){
|
||||
return 5.0 + 20*log10(127.0/(127.0-code));
|
||||
}
|
||||
|
||||
/** Converts Rx VGA1 gain into raw integer values
|
||||
db must be in [5 .. 30.17] dB range */
|
||||
int8_t rxvga1_db_to_int(double db){
|
||||
return (int8_t)(127.5 - 127 / pow(10, (db-5.0)/20));
|
||||
}
|
||||
|
||||
/** Set Rx VGA1 gain in dB
|
||||
gain is in [5 .. 30.17] dB range
|
||||
Returns the old gain value */
|
||||
double set_rx_vga1gain(double gain){
|
||||
int8_t code = rxvga1_db_to_int(gain);
|
||||
return rxvga1_int_to_db(set_rx_vga1gain_int(code));
|
||||
}
|
||||
|
||||
/** Get Rx VGA1 gain in dB
|
||||
Returns the gain value in [5 .. 30.17] dB range */
|
||||
double get_rx_vga1gain(){
|
||||
return rxvga1_int_to_db(get_rx_vga1gain_int());
|
||||
}
|
||||
|
||||
/** Set VGA2 gain.
|
||||
gain is in dB [0 .. 25]
|
||||
Returns the old gain value */
|
||||
@@ -426,6 +461,66 @@ public:
|
||||
lms_clear_bits(0x70, (1 << 1));
|
||||
}
|
||||
|
||||
/** Load value from 0x52/0x62 register to a selected DC calibration register */
|
||||
void set_dc_calibration_value(uint8_t dc_addr, uint8_t calibration_reg_base, uint8_t value);
|
||||
|
||||
/** Get selected DC calibration register value */
|
||||
uint8_t get_dc_calibration_value(uint8_t dc_addr, uint8_t calibration_reg_base);
|
||||
|
||||
/** Set value for the Rx FE DC calibration, I channel */
|
||||
void set_rxfe_dc_i(int8_t value);
|
||||
|
||||
/** Get value for the Rx FE DC calibration, I channel */
|
||||
int8_t get_rxfe_dc_i();
|
||||
|
||||
/** Set value for the Rx FE DC calibration, Q channel */
|
||||
void set_rxfe_dc_q(int8_t value);
|
||||
|
||||
/** Get value for the Rx FE DC calibration, Q channel */
|
||||
int8_t get_rxfe_dc_q();
|
||||
|
||||
/** Set value for the Rx LPF DC calibration, I channel */
|
||||
void set_rxlpf_dc_i(uint8_t value);
|
||||
|
||||
/** Get value for the Rx LPF DC calibration, I channel */
|
||||
uint8_t get_rxlpf_dc_i();
|
||||
|
||||
/** Set value for the Rx LPF DC calibration, Q channel */
|
||||
void set_rxlpf_dc_q(uint8_t value);
|
||||
|
||||
/** Get value for the Rx LPF DC calibration, Q channel */
|
||||
uint8_t get_rxlpf_dc_q();
|
||||
|
||||
/** Set value for the Rx VGA2 DC reference module */
|
||||
void set_rxvga2_dc_reference(uint8_t value);
|
||||
|
||||
/** Get value for the Rx VGA2 DC reference module */
|
||||
uint8_t get_rxvga2_dc_reference();
|
||||
|
||||
/** Set value for the Rx First gain stage (VGA2A), I channel */
|
||||
void set_rxvga2a_dc_i(uint8_t value);
|
||||
|
||||
/** Get value for the Rx First gain stage (VGA2A), I channel */
|
||||
uint8_t get_rxvga2a_dc_i();
|
||||
|
||||
/** Set value for the Rx First gain stage (VGA2A), Q channel */
|
||||
void set_rxvga2a_dc_q(uint8_t value);
|
||||
|
||||
/** Get value for the Rx First gain stage (VGA2A), Q channel */
|
||||
uint8_t get_rxvga2a_dc_q();
|
||||
|
||||
/** Set value for the Rx Second gain stage (VGA2B), I channel */
|
||||
void set_rxvga2b_dc_i(uint8_t value);
|
||||
|
||||
/** Get value for the Rx Second gain stage (VGA2A), I channel */
|
||||
uint8_t get_rxvga2b_dc_i();
|
||||
|
||||
/** Set value for the Rx Second gain stage (VGA2B), Q channel */
|
||||
void set_rxvga2b_dc_q(uint8_t value);
|
||||
|
||||
/** Get value for the Rx Second gain stage (VGA2B), Q channel */
|
||||
uint8_t get_rxvga2b_dc_q();
|
||||
|
||||
/** Programming and Calibration Guide: 4.1 General DC Calibration Procedure */
|
||||
int general_dc_calibration_loop(uint8_t dc_addr, uint8_t calibration_reg_base);
|
||||
|
||||
@@ -472,6 +567,14 @@ public:
|
||||
protected:
|
||||
double txrx_pll_tune(uint8_t reg, double ref_clock, double out_freq);
|
||||
|
||||
bool get_txrx_pll_locked(uint8_t reg) {
|
||||
int comp = read_reg(reg + 0x0a) >> 6;
|
||||
if (comp == 0x00)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void lms_set_bits(uint8_t address, uint8_t mask) {
|
||||
write_reg(address, read_reg(address) | (mask));
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <utility>
|
||||
#include <cmath>
|
||||
#include <cfloat>
|
||||
@@ -69,7 +70,34 @@ static const uhd::dict<std::string, gain_range_t> lms_tx_gain_ranges = map_list_
|
||||
;
|
||||
|
||||
static const uhd::dict<std::string, gain_range_t> lms_rx_gain_ranges = map_list_of
|
||||
("VGA1", gain_range_t(0, 126, double(1.0)))
|
||||
// VGA1 follows the approximation of [dB] = 5 + 20*log10(127/(127-Code)) where 0 <= Code <= 120
|
||||
("VGA1", gain_range_t( list_of
|
||||
(range_t(5.00))(range_t(5.07))(range_t(5.14))(range_t(5.21))(range_t(5.28))
|
||||
(range_t(5.35))(range_t(5.42))(range_t(5.49))(range_t(5.57))(range_t(5.64))
|
||||
(range_t(5.71))(range_t(5.79))(range_t(5.86))(range_t(5.94))(range_t(6.01))
|
||||
(range_t(6.09))(range_t(6.17))(range_t(6.25))(range_t(6.33))(range_t(6.41))
|
||||
(range_t(6.49))(range_t(6.57))(range_t(6.65))(range_t(6.74))(range_t(6.82))
|
||||
(range_t(6.90))(range_t(6.99))(range_t(7.08))(range_t(7.16))(range_t(7.25))
|
||||
(range_t(7.34))(range_t(7.43))(range_t(7.52))(range_t(7.61))(range_t(7.71))
|
||||
(range_t(7.80))(range_t(7.90))(range_t(7.99))(range_t(8.09))(range_t(8.19))
|
||||
(range_t(8.29))(range_t(8.39))(range_t(8.49))(range_t(8.59))(range_t(8.69))
|
||||
(range_t(8.80))(range_t(8.91))(range_t(9.01))(range_t(9.12))(range_t(9.23))
|
||||
(range_t(9.35))(range_t(9.46))(range_t(9.57))(range_t(9.69))(range_t(9.81))
|
||||
(range_t(9.93))(range_t(10.05))(range_t(10.17))(range_t(10.30))(range_t(10.43))
|
||||
(range_t(10.55))(range_t(10.69))(range_t(10.82))(range_t(10.95))(range_t(11.09))
|
||||
(range_t(11.23))(range_t(11.37))(range_t(11.51))(range_t(11.66))(range_t(11.81))
|
||||
(range_t(11.96))(range_t(12.11))(range_t(12.27))(range_t(12.43))(range_t(12.59))
|
||||
(range_t(12.76))(range_t(12.92))(range_t(13.10))(range_t(13.27))(range_t(13.45))
|
||||
(range_t(13.63))(range_t(13.82))(range_t(14.01))(range_t(14.21))(range_t(14.41))
|
||||
(range_t(14.61))(range_t(14.82))(range_t(15.03))(range_t(15.25))(range_t(15.48))
|
||||
(range_t(15.71))(range_t(15.95))(range_t(16.19))(range_t(16.45))(range_t(16.71))
|
||||
(range_t(16.97))(range_t(17.25))(range_t(17.53))(range_t(17.83))(range_t(18.13))
|
||||
(range_t(18.45))(range_t(18.78))(range_t(19.12))(range_t(19.47))(range_t(19.84))
|
||||
(range_t(20.23))(range_t(20.63))(range_t(21.06))(range_t(21.50))(range_t(21.97))
|
||||
(range_t(22.47))(range_t(22.99))(range_t(23.55))(range_t(24.15))(range_t(24.80))
|
||||
(range_t(25.49))(range_t(26.25))(range_t(27.08))(range_t(27.99))(range_t(29.01))
|
||||
(range_t(30.17))
|
||||
))
|
||||
// We limit Rx VGA2 to 30dB, as docs say higher values are dangerous
|
||||
("VGA2", gain_range_t(0, 30, double(3.0)))
|
||||
// ToDo: Add LNA control here
|
||||
@@ -87,14 +115,14 @@ public:
|
||||
umtrx_lms6002d_dev(uhd::spi_iface::sptr spiface, const int slaveno) : _spiface(spiface), _slaveno(slaveno) {};
|
||||
|
||||
virtual void write_reg(uint8_t addr, uint8_t data) {
|
||||
if (verbosity>2) printf("lms6002d_ctrl_impl::write_reg(addr=0x%x, data=0x%x)\n", addr, data);
|
||||
if (verbosity>2) printf("umtrx_lms6002d_dev::write_reg(addr=0x%x, data=0x%x)\n", addr, data);
|
||||
uint16_t command = (((uint16_t)0x80 | (uint16_t)addr) << 8) | (uint16_t)data;
|
||||
_spiface->write_spi(_slaveno, spi_config_t::EDGE_RISE, command, 16);
|
||||
}
|
||||
virtual uint8_t read_reg(uint8_t addr) {
|
||||
if(addr > 127) return 0; // incorrect address, 7 bit long expected
|
||||
uint8_t data = _spiface->read_spi(_slaveno, spi_config_t::EDGE_RISE, addr << 8, 16);
|
||||
if (verbosity>2) printf("lms6002d_ctrl_impl::read_reg(addr=0x%x) data=0x%x\n", addr, data);
|
||||
if (verbosity>2) printf("umtrx_lms6002d_dev::read_reg(addr=0x%x) data=0x%x\n", addr, data);
|
||||
return data;
|
||||
}
|
||||
};
|
||||
@@ -103,7 +131,7 @@ public:
|
||||
|
||||
class lms6002d_ctrl_impl : public lms6002d_ctrl {
|
||||
public:
|
||||
lms6002d_ctrl_impl(uhd::spi_iface::sptr spiface, const int lms_spi_number, const int adf4350_spi_number, const double clock_rate);
|
||||
lms6002d_ctrl_impl(uhd::spi_iface::sptr spiface, const int lms_spi_number, const double clock_rate);
|
||||
|
||||
double set_rx_freq(const double freq)
|
||||
{
|
||||
@@ -125,6 +153,18 @@ public:
|
||||
return this->set_enabled(dboard_iface::UNIT_TX, enb);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
uhd::freq_range_t get_rx_bw_range(void)
|
||||
{
|
||||
return lms_bandwidth_range;
|
||||
@@ -177,34 +217,27 @@ public:
|
||||
|
||||
uint8_t get_tx_vga1dc_i_int(void)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
return lms.get_tx_vga1dc_i_int();
|
||||
}
|
||||
|
||||
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:
|
||||
|
||||
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);
|
||||
unsigned ref_freq = _clock_rate;
|
||||
double actual_freq = 0;
|
||||
if (unit==dboard_iface::UNIT_TX) {
|
||||
actual_freq = lms.tx_pll_tune(ref_freq, f);
|
||||
} else if (unit==dboard_iface::UNIT_RX) {
|
||||
#if 1
|
||||
actual_freq = lms.rx_pll_tune(ref_freq, f);
|
||||
#else
|
||||
// New beta version of the code for UmSEL support.
|
||||
const double umsel_if = 359.5e6;
|
||||
double actual_lms_freq = lms.rx_pll_tune(ref_freq, umsel_if);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_freq() actual_lms_freq=%f\n", actual_lms_freq);
|
||||
double adf4350_freq = f - actual_lms_freq;
|
||||
actual_freq = tune_adf4350(adf4350_freq);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_freq() adf4350 freq=%f\n", actual_freq);
|
||||
actual_freq += actual_lms_freq;
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_freq() actual_freq=%f\n", actual_freq);
|
||||
#endif
|
||||
} else {
|
||||
assert(!"Wrong units_t value passed to lms6002d_ctrl_impl::set_freq()");
|
||||
}
|
||||
@@ -215,6 +248,7 @@ public:
|
||||
}
|
||||
|
||||
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 (unit==dboard_iface::UNIT_RX) {
|
||||
if (en)
|
||||
@@ -232,12 +266,13 @@ public:
|
||||
}
|
||||
|
||||
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());
|
||||
assert_has(lms_rx_gain_ranges.keys(), name, "LMS6002D rx gain name");
|
||||
if(name == "VGA1"){
|
||||
if(name == "VGA1"){
|
||||
lms.set_rx_vga1gain(gain);
|
||||
return lms.get_rx_vga1gain();
|
||||
} else if(name == "VGA2"){
|
||||
} else if(name == "VGA2"){
|
||||
lms.set_rx_vga2gain(gain);
|
||||
return lms.get_rx_vga2gain();
|
||||
} else UHD_THROW_INVALID_CODE_PATH();
|
||||
@@ -245,6 +280,7 @@ public:
|
||||
}
|
||||
|
||||
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());
|
||||
//validate input
|
||||
assert_has(lms_rx_antennas, ant, "LMS6002D rx antenna name");
|
||||
@@ -278,6 +314,7 @@ public:
|
||||
}
|
||||
|
||||
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);
|
||||
// Get the closest available bandwidth
|
||||
bandwidth = lms_bandwidth_range.clip(bandwidth);
|
||||
@@ -289,6 +326,7 @@ public:
|
||||
}
|
||||
|
||||
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());
|
||||
//validate input
|
||||
assert_has(lms_tx_gain_ranges.keys(), name, "LMS6002D tx gain name");
|
||||
@@ -310,6 +348,7 @@ public:
|
||||
}
|
||||
|
||||
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());
|
||||
//validate input
|
||||
assert_has(lms_tx_antennas, ant, "LMS6002D tx antenna ant");
|
||||
@@ -329,6 +368,7 @@ public:
|
||||
}
|
||||
|
||||
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);
|
||||
// Get the closest available bandwidth
|
||||
bandwidth = lms_bandwidth_range.clip(bandwidth);
|
||||
@@ -340,216 +380,153 @@ public:
|
||||
}
|
||||
|
||||
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);
|
||||
lms.set_tx_vga1dc_i_int(offset);
|
||||
return 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);
|
||||
lms.set_tx_vga1dc_q_int(offset);
|
||||
return offset;
|
||||
}
|
||||
|
||||
void set_rxfe_dc_i(uint8_t value) {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_rxfe_dc_i(%d)\n", value);
|
||||
lms.set_rxfe_dc_i(value);
|
||||
}
|
||||
|
||||
uint8_t get_rxfe_dc_i() {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::get_rxfe_dc_i()\n");
|
||||
return lms.get_rxfe_dc_i();
|
||||
}
|
||||
|
||||
void set_rxfe_dc_q(uint8_t value) {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_rxfe_dc_q(%d)\n", value);
|
||||
lms.set_rxfe_dc_q(value);
|
||||
}
|
||||
|
||||
uint8_t get_rxfe_dc_q() {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::get_rxfe_dc_q()\n");
|
||||
return lms.get_rxfe_dc_q();
|
||||
}
|
||||
|
||||
void set_rxlpf_dc_i(uint8_t value) {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_rxlpf_dc_i(%d)\n", value);
|
||||
lms.set_rxlpf_dc_i(value);
|
||||
}
|
||||
|
||||
uint8_t get_rxlpf_dc_i() {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::get_rxlpf_dc_i()\n");
|
||||
return lms.get_rxlpf_dc_i();
|
||||
}
|
||||
|
||||
void set_rxlpf_dc_q(uint8_t value) {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_rxlpf_dc_q(%d)\n", value);
|
||||
lms.set_rxlpf_dc_q(value);
|
||||
}
|
||||
|
||||
uint8_t get_rxlpf_dc_q() {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::get_rxlpf_dc_q()\n");
|
||||
return lms.get_rxlpf_dc_q();
|
||||
}
|
||||
|
||||
void set_rxvga2_dc_reference(uint8_t value) {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_rxvga2_dc_reference(%d)\n", value);
|
||||
lms.set_rxvga2_dc_reference(value);
|
||||
}
|
||||
|
||||
uint8_t get_rxvga2_dc_reference() {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::get_rxvga2_dc_reference()\n");
|
||||
return lms.get_rxvga2_dc_reference();
|
||||
}
|
||||
|
||||
void set_rxvga2a_dc_i(uint8_t value) {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_rxvga2a_dc_i(%d)\n", value);
|
||||
lms.set_rxvga2a_dc_i(value);
|
||||
}
|
||||
|
||||
uint8_t get_rxvga2a_dc_i() {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::get_rxvga2a_dc_i()\n");
|
||||
return lms.get_rxvga2a_dc_i();
|
||||
}
|
||||
|
||||
void set_rxvga2a_dc_q(uint8_t value) {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_rxvga2a_dc_q(%d)\n", value);
|
||||
lms.set_rxvga2a_dc_q(value);
|
||||
}
|
||||
|
||||
uint8_t get_rxvga2a_dc_q() {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::get_rxvga2a_dc_q()\n");
|
||||
return lms.get_rxvga2a_dc_q();
|
||||
}
|
||||
|
||||
void set_rxvga2b_dc_i(uint8_t value) {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_rxvga2b_dc_i(%d)\n", value);
|
||||
lms.set_rxvga2b_dc_i(value);
|
||||
}
|
||||
|
||||
uint8_t get_rxvga2b_dc_i() {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::get_rxvga2b_dc_i()\n");
|
||||
return lms.get_rxvga2b_dc_i();
|
||||
}
|
||||
|
||||
void set_rxvga2b_dc_q(uint8_t value) {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::set_rxvga2b_dc_q(%d)\n", value);
|
||||
lms.set_rxvga2b_dc_q(value);
|
||||
}
|
||||
|
||||
uint8_t get_rxvga2b_dc_q() {
|
||||
boost::recursive_mutex::scoped_lock l(_mutex);
|
||||
if (verbosity>0) printf("lms6002d_ctrl_impl::get_rxvga2b_dc_q()\n");
|
||||
return lms.get_rxvga2b_dc_q();
|
||||
}
|
||||
|
||||
private:
|
||||
umtrx_lms6002d_dev lms; // Interface to the LMS chip.
|
||||
int tx_vga1gain, tx_vga2gain; // Stored values of Tx VGA1 and VGA2 gains.
|
||||
bool rf_loopback_enabled; // Whether RF loopback is enabled.
|
||||
|
||||
// Tune ADF4350 on an UmSEL
|
||||
double tune_adf4350(double target_freq);
|
||||
|
||||
uhd::spi_iface::sptr _spiface;
|
||||
const int _lms_spi_number;
|
||||
const int _adf4350_spi_number;
|
||||
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 double clock_rate)
|
||||
{
|
||||
return sptr(new lms6002d_ctrl_impl(spiface, lms_spi_number, adf4350_spi_number, clock_rate));
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Tuning
|
||||
**********************************************************************/
|
||||
double lms6002d_ctrl_impl::tune_adf4350(double target_freq) {
|
||||
UHD_LOGV(often) << boost::format(
|
||||
"UmSEL tune: target frequency %f Mhz"
|
||||
) % (target_freq/1e6) << std::endl;
|
||||
|
||||
//clip the input
|
||||
// TODO::::::::::::::::::::::::::::::::
|
||||
// target_freq = sbx_freq_range.clip(target_freq);
|
||||
|
||||
//map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler)
|
||||
static const uhd::dict<int, int> prescaler_to_min_int_div = map_list_of
|
||||
(0,23) //adf4350_regs_t::PRESCALER_4_5
|
||||
(1,75) //adf4350_regs_t::PRESCALER_8_9
|
||||
;
|
||||
|
||||
//map rf divider select output dividers to enums
|
||||
static const uhd::dict<int, adf4350_regs_t::rf_divider_select_t> rfdivsel_to_enum = map_list_of
|
||||
(1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1)
|
||||
(2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2)
|
||||
(4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4)
|
||||
(8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8)
|
||||
(16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16)
|
||||
;
|
||||
|
||||
double actual_freq, pfd_freq;
|
||||
// TODO:: May be *2? Check
|
||||
double ref_freq = _clock_rate * 2;
|
||||
int R=0, BS=0, N=0, FRAC=0, MOD=0;
|
||||
int RFdiv = 1;
|
||||
adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED;
|
||||
adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED;
|
||||
|
||||
//Reference doubler for 50% duty cycle
|
||||
// if ref_freq < 12.5MHz enable regs.reference_divide_by_2
|
||||
if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED;
|
||||
|
||||
//increase RF divider until acceptable VCO frequency
|
||||
//start with target_freq*2 because mixer has divide by 2
|
||||
double vco_freq = target_freq;
|
||||
while (vco_freq < 2.2e9) {
|
||||
vco_freq *= 2;
|
||||
RFdiv *= 2;
|
||||
}
|
||||
|
||||
//use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler)
|
||||
adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5;
|
||||
|
||||
/*
|
||||
* The goal here is to loop though possible R dividers,
|
||||
* band select clock dividers, N (int) dividers, and FRAC
|
||||
* (frac) dividers.
|
||||
*
|
||||
* Calculate the N and F dividers for each set of values.
|
||||
* The loop exists when it meets all of the constraints.
|
||||
* The resulting loop values are loaded into the registers.
|
||||
*
|
||||
* from pg.21
|
||||
*
|
||||
* f_pfd = f_ref*(1+D)/(R*(1+T))
|
||||
* f_vco = (N + (FRAC/MOD))*f_pfd
|
||||
* N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD
|
||||
* f_rf = f_vco/RFdiv)
|
||||
* f_actual = f_rf/2
|
||||
*/
|
||||
for(R = 1; R <= 1023; R+=1){
|
||||
//PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T)
|
||||
pfd_freq = ref_freq*(1+D)/(R*(1+T));
|
||||
|
||||
//keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth)
|
||||
if (pfd_freq > 25e6) continue;
|
||||
|
||||
//ignore fractional part of tuning
|
||||
N = int(std::floor(vco_freq/pfd_freq));
|
||||
|
||||
//keep N > minimum int divider requirement
|
||||
if (N < prescaler_to_min_int_div[prescaler]) continue;
|
||||
|
||||
for(BS=1; BS <= 255; BS+=1){
|
||||
//keep the band select frequency at or below 100KHz
|
||||
//constraint on band select clock
|
||||
if (pfd_freq/BS > 100e3) continue;
|
||||
goto done_loop;
|
||||
}
|
||||
} done_loop:
|
||||
|
||||
//Fractional-N calculation
|
||||
MOD = 4095; //max fractional accuracy
|
||||
FRAC = int((vco_freq/pfd_freq - N)*MOD);
|
||||
|
||||
//Reference divide-by-2 for 50% duty cycle
|
||||
// if R even, move one divide by 2 to to regs.reference_divide_by_2
|
||||
if(R % 2 == 0){
|
||||
T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED;
|
||||
R /= 2;
|
||||
}
|
||||
|
||||
//actual frequency calculation
|
||||
actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv);
|
||||
|
||||
// TODO:: get_locked!
|
||||
// UHD_LOGV(often)
|
||||
std::cout
|
||||
<< boost::format("UmSEL Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl
|
||||
<< boost::format("UmSEL tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%s"
|
||||
) % R % BS % N % FRAC % MOD % T % D % RFdiv % true /* this->get_locked(unit).to_pp_string() */ << std::endl
|
||||
<< boost::format("UmSEL Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f"
|
||||
) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl;
|
||||
|
||||
//load the register values
|
||||
adf4350_regs_t regs;
|
||||
|
||||
// TODO:: What?
|
||||
// if ((unit == dboard_iface::UNIT_TX) and (actual_freq == sbx_tx_lo_2dbm.clip(actual_freq)))
|
||||
// regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM;
|
||||
// else
|
||||
regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM;
|
||||
|
||||
regs.frac_12_bit = FRAC;
|
||||
regs.int_16_bit = N;
|
||||
regs.mod_12_bit = MOD;
|
||||
regs.prescaler = prescaler;
|
||||
regs.r_counter_10_bit = R;
|
||||
regs.reference_divide_by_2 = T;
|
||||
regs.reference_doubler = D;
|
||||
regs.band_select_clock_div = BS;
|
||||
UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv));
|
||||
regs.rf_divider_select = rfdivsel_to_enum[RFdiv];
|
||||
|
||||
regs.mute_till_lock_detect = adf4350_regs_t::MUTE_TILL_LOCK_DETECT_MUTE_ENABLED;
|
||||
regs.charge_pump_current = adf4350_regs_t::CHARGE_PUMP_CURRENT_2_50MA;
|
||||
regs.double_buffer = adf4350_regs_t::DOUBLE_BUFFER_ENABLED;
|
||||
regs.muxout = adf4350_regs_t::MUXOUT_3STATE;
|
||||
regs.low_noise_and_spur = adf4350_regs_t::LOW_NOISE_AND_SPUR_LOW_NOISE;
|
||||
|
||||
|
||||
|
||||
//write the registers
|
||||
//correct power-up sequence to write registers (5, 4, 3, 2, 1, 0)
|
||||
|
||||
#if 0
|
||||
for(addr=5; addr>=0; addr--){
|
||||
// UHD_LOGV(often)
|
||||
std::cout << boost::format(
|
||||
"UmSEL SPI Reg (0x%02x): 0x%08x"
|
||||
) % addr % regs.get_reg(addr) << std::endl;
|
||||
this->get_iface()->write_spi(
|
||||
uhd::usrp::dboard_iface::UNIT_SYNT, spi_config_t::EDGE_RISE,
|
||||
regs.get_reg(addr), 32
|
||||
);
|
||||
}
|
||||
#else
|
||||
_spiface->write_spi(_adf4350_spi_number, spi_config_t::EDGE_RISE, 0x0580000|5, 32);
|
||||
_spiface->write_spi(_adf4350_spi_number, spi_config_t::EDGE_RISE, 0x0BFF4F8|4, 32);
|
||||
_spiface->write_spi(_adf4350_spi_number, spi_config_t::EDGE_RISE, 0x0040000|3, 32);
|
||||
_spiface->write_spi(_adf4350_spi_number, spi_config_t::EDGE_RISE, 0x1006E40|2, 32);
|
||||
_spiface->write_spi(_adf4350_spi_number, spi_config_t::EDGE_RISE, 0x8008208|1, 32);
|
||||
_spiface->write_spi(_adf4350_spi_number, spi_config_t::EDGE_RISE, (325<<15)|(1<<3)|0, 32);
|
||||
#endif
|
||||
|
||||
//return the actual frequency
|
||||
// UHD_LOGV(often) << boost::format(
|
||||
std::cout << boost::format(
|
||||
"UmSEL tune: actual frequency %f Mhz"
|
||||
) % (actual_freq/1e6) << std::endl;
|
||||
return actual_freq;
|
||||
return sptr(new lms6002d_ctrl_impl(spiface, lms_spi_number, clock_rate));
|
||||
}
|
||||
|
||||
// LMS RX dboard configuration
|
||||
|
||||
lms6002d_ctrl_impl::lms6002d_ctrl_impl(uhd::spi_iface::sptr spiface, const int lms_spi_number, const int adf4350_spi_number, const double clock_rate) :
|
||||
lms6002d_ctrl_impl::lms6002d_ctrl_impl(uhd::spi_iface::sptr spiface, const int lms_spi_number, const double clock_rate) :
|
||||
lms(umtrx_lms6002d_dev(spiface, lms_spi_number)),
|
||||
tx_vga1gain(lms.get_tx_vga1gain()),
|
||||
tx_vga2gain(lms.get_tx_vga2gain()),
|
||||
rf_loopback_enabled(false),
|
||||
_spiface(spiface),
|
||||
_lms_spi_number(lms_spi_number),
|
||||
_adf4350_spi_number(adf4350_spi_number),
|
||||
_clock_rate(clock_rate)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <uhd/types/ranges.hpp>
|
||||
#include <uhd/types/serial.hpp>
|
||||
#include <uhd/types/sensors.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
@@ -14,7 +15,7 @@ class lms6002d_ctrl
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<lms6002d_ctrl> sptr;
|
||||
static sptr make(uhd::spi_iface::sptr spiface, const int lms_spi_number, const int adf4350_spi_number, const double clock_rate);
|
||||
static sptr make(uhd::spi_iface::sptr spiface, const int lms_spi_number, const double clock_rate);
|
||||
|
||||
virtual double set_rx_freq(const double freq) = 0;
|
||||
virtual double set_tx_freq(const double freq) = 0;
|
||||
@@ -22,6 +23,9 @@ public:
|
||||
virtual bool set_rx_enabled(const bool enb) = 0;
|
||||
virtual bool set_tx_enabled(const bool enb) = 0;
|
||||
|
||||
virtual uhd::sensor_value_t get_rx_pll_locked() = 0;
|
||||
virtual uhd::sensor_value_t get_tx_pll_locked() = 0;
|
||||
|
||||
virtual double set_rx_gain(const double gain, const std::string &name) = 0;
|
||||
virtual double set_tx_gain(const double gain, const std::string &name) = 0;
|
||||
|
||||
@@ -51,6 +55,25 @@ public:
|
||||
|
||||
virtual uint8_t get_tx_vga1dc_i_int(void) = 0;
|
||||
virtual uint8_t get_tx_vga1dc_q_int(void) = 0;
|
||||
|
||||
virtual void set_rxfe_dc_i(uint8_t value) = 0;
|
||||
virtual uint8_t get_rxfe_dc_i() = 0;
|
||||
virtual void set_rxfe_dc_q(uint8_t value) = 0;
|
||||
virtual uint8_t get_rxfe_dc_q() = 0;
|
||||
virtual void set_rxlpf_dc_i(uint8_t value) = 0;
|
||||
virtual uint8_t get_rxlpf_dc_i() = 0;
|
||||
virtual void set_rxlpf_dc_q(uint8_t value) = 0;
|
||||
virtual uint8_t get_rxlpf_dc_q() = 0;
|
||||
virtual void set_rxvga2_dc_reference(uint8_t value) = 0;
|
||||
virtual uint8_t get_rxvga2_dc_reference() = 0;
|
||||
virtual void set_rxvga2a_dc_i(uint8_t value) = 0;
|
||||
virtual uint8_t get_rxvga2a_dc_i() = 0;
|
||||
virtual void set_rxvga2a_dc_q(uint8_t value) = 0;
|
||||
virtual uint8_t get_rxvga2a_dc_q() = 0;
|
||||
virtual void set_rxvga2b_dc_i(uint8_t value) = 0;
|
||||
virtual uint8_t get_rxvga2b_dc_i() = 0;
|
||||
virtual void set_rxvga2b_dc_q(uint8_t value) = 0;
|
||||
virtual uint8_t get_rxvga2b_dc_q() = 0;
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_LMS6002D_CTRL_HPP */
|
||||
|
||||
280
host/power_amp.cpp
Normal file
280
host/power_amp.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
#include "power_amp.hpp"
|
||||
#include <uhd/utils/msg.hpp>
|
||||
#include <uhd/exception.hpp>
|
||||
#include <boost/assign/list_of.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <cmath>
|
||||
|
||||
using namespace uhd;
|
||||
|
||||
/***********************************************************************
|
||||
* Declarations
|
||||
**********************************************************************/
|
||||
|
||||
class power_amp_impl : public power_amp {
|
||||
public:
|
||||
|
||||
// Voltage to Watts curves
|
||||
typedef std::map<double,double> pa_curve_t;
|
||||
|
||||
power_amp_impl(pa_type_t pa_type, const pa_curve_t &v2w, const pa_curve_t &w2v);
|
||||
virtual ~power_amp_impl();
|
||||
|
||||
// Get the PA type
|
||||
virtual pa_type_t get_pa_type() const {return _pa_type;}
|
||||
|
||||
// Get the PA type as a string
|
||||
virtual std::string get_pa_type_str() const {return pa_type_to_str(_pa_type);}
|
||||
|
||||
// Minimum and maximum supported output power in watts
|
||||
virtual double min_power_w() const;
|
||||
virtual double max_power_w() const;
|
||||
// Minimum and maximum supported output power in dBm
|
||||
virtual double min_power_dBm() const;
|
||||
virtual double max_power_dBm() const;
|
||||
|
||||
// Get output power in watts for a given voltage
|
||||
virtual double v2w(double v) const;
|
||||
// Get input voltage required to generate given output power (in watts)
|
||||
virtual double w2v(double w) const;
|
||||
// Get output power in dBm for a given voltage
|
||||
virtual double v2dBm(double v) const;
|
||||
// Get input voltage required to generate given output power (in dBm)
|
||||
virtual double dBm2v(double dBm) const;
|
||||
|
||||
protected:
|
||||
|
||||
// The PA type
|
||||
pa_type_t _pa_type;
|
||||
|
||||
// Curves
|
||||
const pa_curve_t &_v2w_curve;
|
||||
const pa_curve_t _w2v_curve;
|
||||
};
|
||||
|
||||
// Interpolate curve values
|
||||
static double pa_interpolate_curve(const power_amp_impl::pa_curve_t &curve, double v);
|
||||
// Convert an A->B map into a B->A map
|
||||
template<typename map_t> static map_t map_reverse(map_t curve);
|
||||
|
||||
/***********************************************************************
|
||||
* Constants
|
||||
**********************************************************************/
|
||||
|
||||
// NOTE: All names MUST be uppercase for pa_str_to_type() to work correctly
|
||||
const power_amp::pa_type_map_pair_t power_amp::_pa_type_map[] = {
|
||||
{power_amp::PA_NONE, "NONE"}, // Also serves as the default
|
||||
{power_amp::PA_EPA881F40A, "EPA881F40A"},
|
||||
{power_amp::PA_EPA942H40A, "EPA942H40A"},
|
||||
{power_amp::PA_EPA1800F37A, "EPA1800F37A"}
|
||||
};
|
||||
|
||||
const power_amp_impl::pa_curve_t EPA942H40A_v2w_curve = boost::assign::map_list_of
|
||||
(9.5, 1.15)
|
||||
(10, 1.31)
|
||||
(11, 1.6)
|
||||
(12, 1.9)
|
||||
(12.5, 2.1)
|
||||
(13, 2.25)
|
||||
(13.5, 2.44)
|
||||
(14, 2.6)
|
||||
(14.5, 2.8)
|
||||
(15, 3.0)
|
||||
(15.5, 3.2)
|
||||
(16, 3.45)
|
||||
(16.5, 3.7)
|
||||
(17, 3.9)
|
||||
(17.5, 4.1)
|
||||
(18, 4.35)
|
||||
(18.5, 4.6)
|
||||
(19, 4.8)
|
||||
(19.5, 5.1)
|
||||
(20, 5.4)
|
||||
(20.5, 5.65)
|
||||
(21.1, 6.0)
|
||||
(21.6, 6.2)
|
||||
(22.1, 6.5)
|
||||
(22.6, 6.8)
|
||||
(23.1, 7.1)
|
||||
(23.4, 7.25)
|
||||
(23.7, 7.4)
|
||||
(24, 7.55)
|
||||
(24.2, 7.7)
|
||||
(24.5, 7.9)
|
||||
(24.8, 8.0)
|
||||
(25.2, 8.25)
|
||||
(25.5, 8.45)
|
||||
(25.9, 8.65)
|
||||
(26.2, 8.9)
|
||||
(26.6, 9.1)
|
||||
(28, 10.0);
|
||||
|
||||
/***********************************************************************
|
||||
* Static functions
|
||||
**********************************************************************/
|
||||
|
||||
template<typename map_t>
|
||||
static map_t map_reverse(map_t curve)
|
||||
{
|
||||
map_t reversed;
|
||||
|
||||
for (typename map_t::iterator i = curve.begin(); i != curve.end(); ++i)
|
||||
reversed[i->second] = i->first;
|
||||
|
||||
return reversed;
|
||||
}
|
||||
|
||||
static double pa_interpolate_curve(const power_amp_impl::pa_curve_t &curve, double v)
|
||||
{
|
||||
power_amp_impl::pa_curve_t::const_iterator i = curve.upper_bound(v);
|
||||
if (i == curve.end())
|
||||
{
|
||||
return (--i)->second;
|
||||
}
|
||||
if (i == curve.begin())
|
||||
{
|
||||
return i->second;
|
||||
}
|
||||
power_amp_impl::pa_curve_t::const_iterator l=i;
|
||||
--l;
|
||||
|
||||
const double delta=(v - l->first) / (i->first - l->first);
|
||||
return delta*i->second + (1-delta)*l->second;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Make
|
||||
**********************************************************************/
|
||||
power_amp::sptr power_amp::make(pa_type_t pa_type) {
|
||||
switch (pa_type) {
|
||||
case PA_NONE:
|
||||
return power_amp::sptr();
|
||||
case PA_EPA881F40A:
|
||||
case PA_EPA942H40A:
|
||||
case PA_EPA1800F37A:
|
||||
default:
|
||||
return power_amp::sptr(new power_amp_impl(pa_type, EPA942H40A_v2w_curve,
|
||||
map_reverse(EPA942H40A_v2w_curve)));
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* power_amp methods
|
||||
**********************************************************************/
|
||||
|
||||
power_amp::~power_amp()
|
||||
{
|
||||
}
|
||||
|
||||
std::string power_amp::pa_type_to_str(pa_type_t pa)
|
||||
{
|
||||
BOOST_FOREACH(const power_amp::pa_type_map_pair_t &pa_map_pair, _pa_type_map)
|
||||
{
|
||||
if (pa_map_pair.type == pa)
|
||||
return pa_map_pair.name;
|
||||
}
|
||||
throw uhd::environment_error("Can't map PA type to a string.");
|
||||
return "NONE";
|
||||
}
|
||||
|
||||
power_amp::pa_type_t power_amp::pa_str_to_type(const std::string &pa_str)
|
||||
{
|
||||
std::string pa_str_upper = boost::to_upper_copy(pa_str);
|
||||
BOOST_FOREACH(const power_amp::pa_type_map_pair_t &pa_map_pair, _pa_type_map)
|
||||
{
|
||||
if (pa_map_pair.name == pa_str_upper)
|
||||
return pa_map_pair.type;
|
||||
}
|
||||
UHD_MSG(error) << "PA name " << pa_str << " is not recognized. "
|
||||
<< "Setting PA type to NONE." << std::endl;
|
||||
return power_amp::PA_NONE;
|
||||
}
|
||||
|
||||
std::list<power_amp::pa_type_t> power_amp::list_pa_type()
|
||||
{
|
||||
std::list<power_amp::pa_type_t> list;
|
||||
|
||||
BOOST_FOREACH(const power_amp::pa_type_map_pair_t &pa_map_pair, _pa_type_map) {
|
||||
list.push_back(pa_map_pair.type);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
std::list<std::string> power_amp::list_pa_str()
|
||||
{
|
||||
std::list<std::string> list;
|
||||
|
||||
BOOST_FOREACH(const power_amp::pa_type_map_pair_t &pa_map_pair, _pa_type_map) {
|
||||
list.push_back(pa_map_pair.name);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
double power_amp::w2dBm(double w)
|
||||
{
|
||||
return 10*log10(w) + 30;
|
||||
}
|
||||
|
||||
double power_amp::dBm2w(double dBm)
|
||||
{
|
||||
return pow(10, (dBm-30)/10);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* power_amp_impl methods
|
||||
**********************************************************************/
|
||||
|
||||
power_amp_impl::power_amp_impl(pa_type_t pa_type, const pa_curve_t &v2w, const pa_curve_t &w2v)
|
||||
: _pa_type(pa_type)
|
||||
, _v2w_curve(v2w)
|
||||
, _w2v_curve(w2v)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
power_amp_impl::~power_amp_impl()
|
||||
{
|
||||
}
|
||||
|
||||
double power_amp_impl::min_power_w() const
|
||||
{
|
||||
return _w2v_curve.begin()->first;
|
||||
}
|
||||
|
||||
double power_amp_impl::max_power_w() const
|
||||
{
|
||||
return _w2v_curve.rbegin()->first;
|
||||
}
|
||||
|
||||
double power_amp_impl::min_power_dBm() const
|
||||
{
|
||||
return w2dBm(min_power_w());
|
||||
}
|
||||
|
||||
double power_amp_impl::max_power_dBm() const
|
||||
{
|
||||
return w2dBm(max_power_w());
|
||||
}
|
||||
|
||||
double power_amp_impl::v2w(double v) const
|
||||
{
|
||||
return pa_interpolate_curve(_v2w_curve, v);
|
||||
}
|
||||
|
||||
double power_amp_impl::w2v(double w) const
|
||||
{
|
||||
return pa_interpolate_curve(_w2v_curve, w);
|
||||
}
|
||||
|
||||
double power_amp_impl::v2dBm(double v) const
|
||||
{
|
||||
return w2dBm(v2w(v));
|
||||
}
|
||||
|
||||
double power_amp_impl::dBm2v(double dBm) const
|
||||
{
|
||||
return w2v(dBm2w(dBm));
|
||||
}
|
||||
75
host/power_amp.hpp
Normal file
75
host/power_amp.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef POWER_AMP_HPP
|
||||
#define POWER_AMP_HPP
|
||||
|
||||
#include <uhd/config.hpp>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace uhd {
|
||||
|
||||
class power_amp {
|
||||
public:
|
||||
|
||||
// Supported Power Amplifiers
|
||||
enum pa_type_t {
|
||||
PA_NONE, // No PA connected
|
||||
PA_EPA881F40A, // EPA881F40A GSM850
|
||||
PA_EPA942H40A, // EPA942H40A EGSM900
|
||||
PA_EPA1800F37A // EPA1800F37A DCS1800
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<power_amp> sptr;
|
||||
static power_amp::sptr make(pa_type_t pa_type);
|
||||
virtual ~power_amp();
|
||||
|
||||
// Get the PA type
|
||||
virtual pa_type_t get_pa_type() const =0;
|
||||
// Get the PA type as a string
|
||||
virtual std::string get_pa_type_str() const =0;
|
||||
|
||||
// Convert PA type to a string
|
||||
static std::string pa_type_to_str(pa_type_t pa);
|
||||
// Convert a string to a PA type
|
||||
static pa_type_t pa_str_to_type(const std::string &pa_str);
|
||||
|
||||
// Return a list of PA types
|
||||
static std::list<pa_type_t> list_pa_type();
|
||||
// Return a list of PA type strings
|
||||
static std::list<std::string> list_pa_str();
|
||||
|
||||
// Convert watts -> dBm
|
||||
static double w2dBm(double w);
|
||||
// Convert dBm -> watts
|
||||
static double dBm2w(double dBm);
|
||||
|
||||
// Minimum and maximum supported output power in watts
|
||||
virtual double min_power_w() const =0;
|
||||
virtual double max_power_w() const =0;
|
||||
// Minimum and maximum supported output power in dBm
|
||||
virtual double min_power_dBm() const =0;
|
||||
virtual double max_power_dBm() const =0;
|
||||
|
||||
// Get output power in watts for a given voltage
|
||||
virtual double v2w(double v) const =0;
|
||||
// Get input voltage required to generate given output power (in watts)
|
||||
virtual double w2v(double w) const =0;
|
||||
// Get output power in dBm for a given voltage
|
||||
virtual double v2dBm(double v) const =0;
|
||||
// Get input voltage required to generate given output power (in dBm)
|
||||
virtual double dBm2v(double dBm) const =0;
|
||||
|
||||
protected:
|
||||
|
||||
// Map PA types to string names
|
||||
struct pa_type_map_pair_t {
|
||||
pa_type_t type;
|
||||
std::string name;
|
||||
};
|
||||
static const pa_type_map_pair_t _pa_type_map[];
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // POWER_AMP_HPP
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1700)
|
||||
#define nan(arg) std::strtod("NAN()", (char**)NULL)
|
||||
#endif
|
||||
|
||||
using namespace uhd;
|
||||
|
||||
tmp102_ctrl::tmp102_ctrl()
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
*
|
||||
* Control of TI's TMP102 temperature sensors
|
||||
*/
|
||||
class UHD_API tmp102_ctrl {
|
||||
class tmp102_ctrl {
|
||||
public:
|
||||
enum conversion_rate {
|
||||
TMP102_CR_025HZ = 0,
|
||||
|
||||
478
host/umsel2_ctrl.cpp
Normal file
478
host/umsel2_ctrl.cpp
Normal file
@@ -0,0 +1,478 @@
|
||||
// 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 "umsel2_ctrl.hpp"
|
||||
#include "umtrx_regs.hpp"
|
||||
#include <uhd/exception.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
|
||||
static const int REG0_NVALUE_SHIFT = 4;
|
||||
static const int REG0_NVALUE_MASK = 0xffff;
|
||||
static const int REG0_PRESCALER_SHIFT = 20;
|
||||
static const int REG0_AUTOCAL_SHIFT = 21;
|
||||
static const int REG1_MFRAC_SHIFT = 4;
|
||||
static const int REG1_MFRAC_MASK = 0xffffff;
|
||||
static const int REG2_AUX_FRAC_SHIFT = 18;
|
||||
static const int REG2_AUX_FRAC_MASK = ((1<<14)-1);
|
||||
static const int REG2_AUX_MOD_SHIFT = 4;
|
||||
static const int REG2_AUX_MOD_MASK = ((1<<14)-1);
|
||||
static const int REG3_SD_LOAD_SHIFT = 30;
|
||||
static const int REG3_PHASE_RSYNC_SHIFT = 29;
|
||||
static const int REG3_PHASE_ADJ_SHIFT = 28;
|
||||
static const int REG3_PHASE_SHIFT = 4;
|
||||
static const int REG3_PHASE_MASK = ((1<<24)-1);
|
||||
static const int REG4_MUXOUT_SHIFT = 27;
|
||||
static const int REG4_MUXOUT_MASK = ((1<<3)-1);
|
||||
static const int REG4_REF_DBL_SHIFT = 26;
|
||||
static const int REG4_REF_DIV_SHIFT = 25;
|
||||
static const int REG4_R_SHIFT = 15;
|
||||
static const int REG4_R_MASK = ((1<<10)-1);
|
||||
static const int REG4_DBL_BUFF_SHIFT = 14;
|
||||
static const int REG4_CURRENT_SHIFT = 10;
|
||||
static const int REG4_CURRENT_MASK = ((1<<4)-1);
|
||||
static const int REG4_REF_MODE_SHIFT = 9;
|
||||
static const int REG4_MUX_LOGIC_SHIFT = 8;
|
||||
static const int REG4_PD_POL_SHIFT = 7;
|
||||
static const int REG4_PWR_DOWN_SHIFT = 6;
|
||||
static const int REG4_CP_3STATE_SHIFT = 5;
|
||||
static const int REG4_CNTR_RESET = 4;
|
||||
static const int REG5_RESERVED = 0x00800025;
|
||||
static const int REG6_GATED_BLEED_SHIFT = 30;
|
||||
static const int REG6_NEG_BLEED_SHIFT = 29;
|
||||
static const int REG6_RESERVED_SHIFT = 25;
|
||||
static const int REG6_RESERVED_VALUE = 0xA;
|
||||
static const int REG6_FB_SEL_SHIFT = 24;
|
||||
static const int REG6_RF_DIV_SHIFT = 21;
|
||||
static const int REG6_RF_DIV_MASK = ((1<<3)-1);
|
||||
static const int REG6_CP_BLEED_CURR_SHIFT = 13;
|
||||
static const int REG6_CP_BLEED_CURR_MASK = ((1<<8)-1);
|
||||
static const int REG6_MLTD_SHIFT = 11;
|
||||
static const int REG6_AUX_PWR_EN_SHIFT = 9;
|
||||
static const int REG6_AUX_PWR_SHIFT = 7;
|
||||
static const int REG6_AUX_PWR_MASK = ((1<<2)-1);
|
||||
static const int REG6_PWR_EN_SHIFT = 6;
|
||||
static const int REG6_PWR_SHIFT = 4;
|
||||
static const int REG6_PWR_MASK = ((1<<2)-1);
|
||||
static const int REG7_RESERVED_SHIFT = 26;
|
||||
static const int REG7_RESERVED_VALUE = 0x4;
|
||||
static const int REG7_LE_SYNC_SHIFT = 25;
|
||||
static const int REG7_LD_CYCLE_CNT_SHIFT = 8;
|
||||
static const int REG7_LD_CYCLE_CNT_MASK = ((1<<2)-1);
|
||||
static const int REG7_LOL_MODE_SHIFT = 7;
|
||||
static const int REG7_FRAC_N_PREC_SHIFT = 5;
|
||||
static const int REG7_FRAC_N_PREC_MASK = ((1<<2)-1);
|
||||
static const int REG7_LD_MODE_SHIFT = 4;
|
||||
static const int REG8_RESERVED = 0x102D0428;
|
||||
static const int REG9_VCO_BAND_SHIFT = 24;
|
||||
static const int REG9_VCO_BAND_MASK = ((1<<8)-1);
|
||||
static const int REG9_TIMEOUT_SHIFT = 14;
|
||||
static const int REG9_TIMEOUT_MASK = ((1<<10)-1);
|
||||
static const int REG9_AUTO_LVL_TO_SHIFT = 9;
|
||||
static const int REG9_AUTO_LVL_TO_MASK = ((1<<5)-1);
|
||||
static const int REG9_SYNT_LOCK_TO_SHIFT = 4;
|
||||
static const int REG9_SYNT_LOCK_TO_MASK = ((1<<5)-1);
|
||||
static const int REG10_RESERVED_SHIFT = 14;
|
||||
static const int REG10_RESERVED_VALUE = 0x300;
|
||||
static const int REG10_ADC_CLK_DIV_SHIFT = 6;
|
||||
static const int REG10_ADC_CLK_DIV_MASK = ((1<<8)-1);
|
||||
static const int REG10_ADC_CONV_SHIFT = 5;
|
||||
static const int REG10_ADC_EN_SHIFT = 4;
|
||||
static const int REG11_RESERVED = 0x0061300B;
|
||||
static const int REG12_RESYNC_CLOCK_SHIFT = 16;
|
||||
static const int REG12_RESYNC_CLOCK_MASK = ((1<<16)-1);
|
||||
static const int REG12_RESERVED_SHIFT = 4;
|
||||
static const int REG12_RESERVED_VALUE = 0x41;
|
||||
|
||||
#define MODIFY_FIELD(reg, val, mask, shift) \
|
||||
reg = ((reg & ~(mask << shift)) | ((val & mask) << shift))
|
||||
|
||||
class umsel2_ctrl_impl : public umsel2_ctrl
|
||||
{
|
||||
public:
|
||||
|
||||
umsel2_ctrl_impl(uhd::wb_iface::sptr ctrl, uhd::spi_iface::sptr spiface, const double ref_clock, const bool verbose):
|
||||
_ctrl(ctrl), _spiface(spiface), _ref_clock(ref_clock), verbose(verbose)
|
||||
{
|
||||
this->init_synth(SPI_SS_AUX1);
|
||||
this->init_synth(SPI_SS_AUX2);
|
||||
|
||||
//--------- basic self tests, use the muxout to verify communication ----------//
|
||||
|
||||
//set mux out to ground in both cases
|
||||
MODIFY_FIELD(_regs[SPI_SS_AUX1][4], 2, REG4_MUXOUT_MASK, REG4_MUXOUT_SHIFT);
|
||||
MODIFY_FIELD(_regs[SPI_SS_AUX2][4], 2, REG4_MUXOUT_MASK, REG4_MUXOUT_SHIFT);
|
||||
this->write_reg(SPI_SS_AUX1, 4);
|
||||
this->write_reg(SPI_SS_AUX2, 4);
|
||||
UHD_ASSERT_THROW((_ctrl->peek32(U2_REG_IRQ_RB) & AUX_LD1_IRQ_BIT) == 0);
|
||||
UHD_ASSERT_THROW((_ctrl->peek32(U2_REG_IRQ_RB) & AUX_LD2_IRQ_BIT) == 0);
|
||||
|
||||
//set slave1 to muxout vdd
|
||||
MODIFY_FIELD(_regs[SPI_SS_AUX1][4], 1, REG4_MUXOUT_MASK, REG4_MUXOUT_SHIFT);
|
||||
MODIFY_FIELD(_regs[SPI_SS_AUX2][4], 2, REG4_MUXOUT_MASK, REG4_MUXOUT_SHIFT);
|
||||
this->write_reg(SPI_SS_AUX1, 4);
|
||||
this->write_reg(SPI_SS_AUX2, 4);
|
||||
UHD_ASSERT_THROW((_ctrl->peek32(U2_REG_IRQ_RB) & AUX_LD1_IRQ_BIT) != 0);
|
||||
UHD_ASSERT_THROW((_ctrl->peek32(U2_REG_IRQ_RB) & AUX_LD2_IRQ_BIT) == 0);
|
||||
|
||||
//set slave2 to muxout vdd
|
||||
MODIFY_FIELD(_regs[SPI_SS_AUX1][4], 2, REG4_MUXOUT_MASK, REG4_MUXOUT_SHIFT);
|
||||
MODIFY_FIELD(_regs[SPI_SS_AUX2][4], 1, REG4_MUXOUT_MASK, REG4_MUXOUT_SHIFT);
|
||||
this->write_reg(SPI_SS_AUX1, 4);
|
||||
this->write_reg(SPI_SS_AUX2, 4);
|
||||
UHD_ASSERT_THROW((_ctrl->peek32(U2_REG_IRQ_RB) & AUX_LD1_IRQ_BIT) == 0);
|
||||
UHD_ASSERT_THROW((_ctrl->peek32(U2_REG_IRQ_RB) & AUX_LD2_IRQ_BIT) != 0);
|
||||
|
||||
//restore lock detect out
|
||||
MODIFY_FIELD(_regs[SPI_SS_AUX1][4], 6, REG4_MUXOUT_MASK, REG4_MUXOUT_SHIFT);
|
||||
MODIFY_FIELD(_regs[SPI_SS_AUX2][4], 6, REG4_MUXOUT_MASK, REG4_MUXOUT_SHIFT);
|
||||
this->write_reg(SPI_SS_AUX1, 4);
|
||||
this->write_reg(SPI_SS_AUX2, 4);
|
||||
}
|
||||
|
||||
~umsel2_ctrl_impl(void)
|
||||
{
|
||||
try
|
||||
{
|
||||
this->pd_synth(SPI_SS_AUX1);
|
||||
this->pd_synth(SPI_SS_AUX2);
|
||||
}
|
||||
catch(...){}
|
||||
}
|
||||
|
||||
uhd::freq_range_t get_rx_freq_range(const int)
|
||||
{
|
||||
return uhd::freq_range_t(54e6, 4400e6);
|
||||
}
|
||||
|
||||
double set_rx_freq(const int which, const double freq)
|
||||
{
|
||||
const int slaveno = (which == 1)?SPI_SS_AUX1 : SPI_SS_AUX2;
|
||||
return this->tune_synth(slaveno, freq);
|
||||
}
|
||||
|
||||
uhd::sensor_value_t get_locked(const int which)
|
||||
{
|
||||
boost::uint32_t irq = _ctrl->peek32(U2_REG_IRQ_RB);
|
||||
bool locked = false;
|
||||
if (which == 1) locked = (irq & AUX_LD1_IRQ_BIT) != 0;
|
||||
if (which == 2) locked = (irq & AUX_LD2_IRQ_BIT) != 0;
|
||||
return uhd::sensor_value_t("LO", locked, "locked", "unlocked");
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void init_synth(const int slaveno)
|
||||
{
|
||||
//reset the registers
|
||||
_regs[slaveno][0] = 0;
|
||||
_regs[slaveno][1] = 0;
|
||||
_regs[slaveno][2] = 0;
|
||||
_regs[slaveno][3] = 0;
|
||||
_regs[slaveno][4] = 0;
|
||||
_regs[slaveno][5] = REG5_RESERVED;
|
||||
_regs[slaveno][6] = REG6_RESERVED_VALUE << REG6_RESERVED_SHIFT;
|
||||
_regs[slaveno][7] = REG7_RESERVED_VALUE << REG7_RESERVED_SHIFT;
|
||||
_regs[slaveno][8] = REG8_RESERVED;
|
||||
_regs[slaveno][9] = 0;
|
||||
_regs[slaveno][10] = REG10_RESERVED_VALUE << REG10_RESERVED_SHIFT;
|
||||
_regs[slaveno][11] = REG11_RESERVED;
|
||||
_regs[slaveno][12] = REG12_RESERVED_VALUE << REG12_RESERVED_SHIFT;
|
||||
|
||||
//------------------------------------------------------------//
|
||||
//----------------------- register 0 -------------------------//
|
||||
//------------------------------------------------------------//
|
||||
|
||||
//autocal enabled
|
||||
MODIFY_FIELD(_regs[slaveno][0], 1, 0x1, REG0_AUTOCAL_SHIFT);
|
||||
|
||||
//prescaler 4/5
|
||||
MODIFY_FIELD(_regs[slaveno][0], 0, 0x1, REG0_PRESCALER_SHIFT);
|
||||
|
||||
//------------------------------------------------------------//
|
||||
//----------------------- register 3 -------------------------//
|
||||
//------------------------------------------------------------//
|
||||
|
||||
//sd load reset, phase resync, phase adjust = disabled
|
||||
MODIFY_FIELD(_regs[slaveno][3], 0, 0x1, REG3_SD_LOAD_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][3], 0, 0x1, REG3_PHASE_RSYNC_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][3], 0, 0x1, REG3_PHASE_ADJ_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][3], 0, REG3_PHASE_MASK, REG3_PHASE_SHIFT);
|
||||
|
||||
//------------------------------------------------------------//
|
||||
//----------------------- register 4 -------------------------//
|
||||
//------------------------------------------------------------//
|
||||
|
||||
//muxout to lock detect
|
||||
MODIFY_FIELD(_regs[slaveno][4], 6, REG4_MUXOUT_MASK, REG4_MUXOUT_SHIFT);
|
||||
|
||||
//double buff disabled
|
||||
MODIFY_FIELD(_regs[slaveno][4], 0, 0x1, REG4_DBL_BUFF_SHIFT);
|
||||
|
||||
//charge pump current 0.31mA@5.1k
|
||||
MODIFY_FIELD(_regs[slaveno][4], 0, REG4_CURRENT_MASK, REG4_CURRENT_SHIFT);
|
||||
|
||||
//refin single ended
|
||||
MODIFY_FIELD(_regs[slaveno][4], 0, 0x1, REG4_REF_MODE_SHIFT);
|
||||
|
||||
//mux level 3V
|
||||
MODIFY_FIELD(_regs[slaveno][4], 1, 0x1, REG4_MUX_LOGIC_SHIFT);
|
||||
|
||||
//PD polarity positive
|
||||
MODIFY_FIELD(_regs[slaveno][4], 1, 0x1, REG4_PD_POL_SHIFT);
|
||||
|
||||
//power down disabled
|
||||
MODIFY_FIELD(_regs[slaveno][4], 0, 0x1, REG4_PWR_DOWN_SHIFT);
|
||||
|
||||
//charge-pump 3-state disabled
|
||||
MODIFY_FIELD(_regs[slaveno][4], 0, 0x1, REG4_CP_3STATE_SHIFT);
|
||||
|
||||
//counter reset disabled
|
||||
MODIFY_FIELD(_regs[slaveno][4], 0, 0x1, REG4_CNTR_RESET);
|
||||
|
||||
//------------------------------------------------------------//
|
||||
//----------------------- register 6 -------------------------//
|
||||
//------------------------------------------------------------//
|
||||
|
||||
//feedback fundamental
|
||||
MODIFY_FIELD(_regs[slaveno][6], 1, 0x1, REG6_FB_SEL_SHIFT);
|
||||
|
||||
//bleed current 7.5uA
|
||||
MODIFY_FIELD(_regs[slaveno][6], 2, REG6_CP_BLEED_CURR_MASK, REG6_CP_BLEED_CURR_SHIFT);
|
||||
|
||||
//mute until lock detect disabled
|
||||
MODIFY_FIELD(_regs[slaveno][6], 0, 0x1, REG6_MLTD_SHIFT);
|
||||
|
||||
//aux output disabled (-1dBm)
|
||||
MODIFY_FIELD(_regs[slaveno][6], 0, 0x1, REG6_AUX_PWR_EN_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][6], 1, REG6_AUX_PWR_MASK, REG6_AUX_PWR_SHIFT);
|
||||
|
||||
//RF output power (5dBm)
|
||||
MODIFY_FIELD(_regs[slaveno][6], 1, 0x1, REG6_PWR_EN_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][6], 3, REG6_PWR_MASK, REG6_PWR_SHIFT);
|
||||
|
||||
//negative bleed enabled
|
||||
MODIFY_FIELD(_regs[slaveno][6], 1, 0x1, REG6_NEG_BLEED_SHIFT);
|
||||
|
||||
//gated bleed disabled
|
||||
MODIFY_FIELD(_regs[slaveno][6], 0, 0x1, REG6_GATED_BLEED_SHIFT);
|
||||
|
||||
//------------------------------------------------------------//
|
||||
//----------------------- register 7 -------------------------//
|
||||
//------------------------------------------------------------//
|
||||
|
||||
//LE Sync REFin
|
||||
MODIFY_FIELD(_regs[slaveno][7], 1, 0x1, REG7_LE_SYNC_SHIFT);
|
||||
|
||||
//LD Cycles
|
||||
MODIFY_FIELD(_regs[slaveno][7], 1024, REG7_LD_CYCLE_CNT_MASK, REG7_LD_CYCLE_CNT_SHIFT);
|
||||
|
||||
//LOL Mode disabled
|
||||
MODIFY_FIELD(_regs[slaveno][7], 0, 0x1, REG7_LOL_MODE_SHIFT);
|
||||
|
||||
//Frac-N LD Prec 5.0ns
|
||||
MODIFY_FIELD(_regs[slaveno][7], 0, REG7_FRAC_N_PREC_MASK, REG7_FRAC_N_PREC_SHIFT);
|
||||
|
||||
//LD Mode Frac-N
|
||||
MODIFY_FIELD(_regs[slaveno][7], 0, 0x1, REG7_LD_MODE_SHIFT);
|
||||
|
||||
//------------------------------------------------------------//
|
||||
//----------------------- register 10 ------------------------//
|
||||
//------------------------------------------------------------//
|
||||
|
||||
//adc enable
|
||||
MODIFY_FIELD(_regs[slaveno][10], 1, 0x1, REG10_ADC_EN_SHIFT);
|
||||
|
||||
//adc conversion enable
|
||||
MODIFY_FIELD(_regs[slaveno][10], 1, 0x1, REG10_ADC_CONV_SHIFT);
|
||||
|
||||
//------------------------------------------------------------//
|
||||
//----------------------- register 12 ------------------------//
|
||||
//------------------------------------------------------------//
|
||||
|
||||
//phase resync 0
|
||||
MODIFY_FIELD(_regs[slaveno][12], 0, REG12_RESYNC_CLOCK_MASK, REG12_RESYNC_CLOCK_SHIFT);
|
||||
|
||||
//write all registers
|
||||
for (int addr = 12; addr >= 0; addr--)
|
||||
this->write_reg(slaveno, addr);
|
||||
}
|
||||
|
||||
void pd_synth(const int slaveno)
|
||||
{
|
||||
//muxout to lock 3state
|
||||
MODIFY_FIELD(_regs[slaveno][4], 0, REG4_MUXOUT_MASK, REG4_MUXOUT_SHIFT);
|
||||
|
||||
//charge pump 3state
|
||||
MODIFY_FIELD(_regs[slaveno][4], 1, 0x1, REG4_CP_3STATE_SHIFT);
|
||||
|
||||
//power down
|
||||
MODIFY_FIELD(_regs[slaveno][4], 1, 0x1, REG4_PWR_DOWN_SHIFT);
|
||||
|
||||
//outputs off
|
||||
MODIFY_FIELD(_regs[slaveno][6], 0, 0x1, REG6_AUX_PWR_EN_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][6], 0, 0x1, REG6_PWR_EN_SHIFT);
|
||||
|
||||
//write all registers
|
||||
for (int addr = 12; addr >= 0; addr--)
|
||||
this->write_reg(slaveno, addr);
|
||||
}
|
||||
|
||||
double tune_synth(const int slaveno, const double RFout)
|
||||
{
|
||||
if (verbose) std::cout << " tune_synth(slaveno=" << slaveno << ")" << std::endl;
|
||||
if (verbose) std::cout << " RFout " << (RFout/1e6) << " MHz" << std::endl;
|
||||
|
||||
//determine the reference out divider and VCOout
|
||||
double VCOout = 0;
|
||||
int RFOUTDIVSEL = 0;
|
||||
while (true)
|
||||
{
|
||||
int RFOUTDIV = 1 << RFOUTDIVSEL;
|
||||
VCOout = RFout*RFOUTDIV;
|
||||
if (VCOout < 3.4e9) RFOUTDIVSEL++;
|
||||
else break;
|
||||
}
|
||||
if (verbose) std::cout << " RFOUTDIV " << (1 << RFOUTDIVSEL) << "" << std::endl;
|
||||
if (verbose) std::cout << " VCOout " << (VCOout/1e6) << " MHz" << std::endl;
|
||||
|
||||
//use doubler to increase the pfd frequency (good for noise performance)
|
||||
int REFDBL = 0;
|
||||
int REFDIV = 0;
|
||||
|
||||
//prescaler settings
|
||||
int PRESCALER = 0; //4/5
|
||||
const int Nmin = (PRESCALER==0)?23:75;
|
||||
|
||||
//calculate the R divider, N divider, and PDF frequency
|
||||
double NDIV = 0;
|
||||
int RDIV = 1;
|
||||
double fPFD = 0;
|
||||
while (true)
|
||||
{
|
||||
fPFD = _ref_clock*(double(1+REFDBL)/double(RDIV*(1+REFDIV)));
|
||||
NDIV = VCOout/fPFD;
|
||||
if (NDIV < Nmin) RDIV++;
|
||||
else break;
|
||||
}
|
||||
if (verbose) std::cout << " RDIV " << RDIV << "" << std::endl;
|
||||
if (verbose) std::cout << " NDIV " << NDIV << "" << std::endl;
|
||||
if (verbose) std::cout << " fPFD " << (fPFD/1e6) << " MHz" << std::endl;
|
||||
|
||||
//calculate the integer parts of the N divider
|
||||
int NINT = int(NDIV);
|
||||
double NFRAC = std::ldexp(NDIV-NINT, 24);
|
||||
int FRAC1 = int(NFRAC);
|
||||
int MOD2 = fPFD/1e6; //TODO MOD2 = fPFD/GCD(fPFD, fCHSP)
|
||||
int FRAC2 = int((NFRAC-FRAC1)*MOD2);
|
||||
if (verbose) std::cout << " NINT " << NINT << "" << std::endl;
|
||||
if (verbose) std::cout << " FRAC1 " << FRAC1 << "" << std::endl;
|
||||
if (verbose) std::cout << " MOD2 " << MOD2 << "" << std::endl;
|
||||
if (verbose) std::cout << " FRAC2 " << FRAC2 << "" << std::endl;
|
||||
|
||||
//VCO Band Division
|
||||
//PFD/(band division × 16) < 150 kHz
|
||||
int VCObanddiv = 1;
|
||||
while (not(fPFD/(VCObanddiv*16) < 150e3)) VCObanddiv++;
|
||||
if (verbose) std::cout << " VCObanddiv " << VCObanddiv << "" << std::endl;
|
||||
|
||||
//Maximize ALC Wait (to reduce Timeout to minimize time) so
|
||||
//that ALC Wait = 30 and Synthesizer Lock Timeout = 12.
|
||||
int ALC = 30;
|
||||
int SLT = 12;
|
||||
int TIMEOUT = std::ceil((fPFD*50e-6)/ALC);
|
||||
if (verbose) std::cout << " TIMEOUT " << TIMEOUT << "" << std::endl;
|
||||
|
||||
//ADC Clock Divider (ADC_CLK_DIV)
|
||||
//PFD/((ADC_CLK_DIV × 4) × 2) < 100 kHz
|
||||
/*
|
||||
int ADC_CLK_DIV = 1;
|
||||
while (not(fPFD/((ADC_CLK_DIV*4)*2) < 100e3)) ADC_CLK_DIV++;
|
||||
if (verbose) std::cout << " ADC_CLK_DIV " << ADC_CLK_DIV << "" << std::endl;
|
||||
const long sleepUs = long(1e6*16*ADC_CLK_DIV/fPFD);
|
||||
*/
|
||||
|
||||
//Copied from the ADI GUI
|
||||
//after trying to juxtapose the documentation with the GUI
|
||||
int ADC_CLK_DIV = 65;
|
||||
const long sleepUs = 160;
|
||||
|
||||
//load registers
|
||||
MODIFY_FIELD(_regs[slaveno][0], NINT, REG0_NVALUE_MASK, REG0_NVALUE_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][0], PRESCALER, 0x1, REG0_PRESCALER_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][0], 1/*enb*/, 0x1, REG0_AUTOCAL_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][1], FRAC1, REG1_MFRAC_MASK, REG1_MFRAC_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][2], MOD2, REG2_AUX_MOD_MASK, REG2_AUX_MOD_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][2], FRAC2, REG2_AUX_FRAC_MASK, REG2_AUX_FRAC_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][4], RDIV, REG4_R_MASK, REG4_R_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][4], REFDIV, 0x1, REG4_REF_DIV_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][4], REFDBL, 0x1, REG4_REF_DBL_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][6], RFOUTDIVSEL, REG6_RF_DIV_MASK, REG6_RF_DIV_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][9], SLT, REG9_SYNT_LOCK_TO_MASK, REG9_SYNT_LOCK_TO_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][9], ALC, REG9_AUTO_LVL_TO_MASK, REG9_AUTO_LVL_TO_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][9], TIMEOUT, REG9_TIMEOUT_MASK, REG9_TIMEOUT_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][9], VCObanddiv, REG9_VCO_BAND_MASK, REG9_VCO_BAND_SHIFT);
|
||||
MODIFY_FIELD(_regs[slaveno][10], ADC_CLK_DIV, REG10_ADC_CLK_DIV_MASK, REG10_ADC_CLK_DIV_SHIFT);
|
||||
|
||||
//write other registers
|
||||
this->write_reg(slaveno, 6);
|
||||
this->write_reg(slaveno, 9);
|
||||
this->write_reg(slaveno, 10);
|
||||
|
||||
//FREQUENCY UPDATE SEQUENCE
|
||||
MODIFY_FIELD(_regs[slaveno][4], 1, 0x1, REG4_CNTR_RESET);
|
||||
this->write_reg(slaveno, 4);
|
||||
this->write_reg(slaveno, 2);
|
||||
this->write_reg(slaveno, 1);
|
||||
MODIFY_FIELD(_regs[slaveno][0], 0, 0x1, REG0_AUTOCAL_SHIFT);
|
||||
this->write_reg(slaveno, 0);
|
||||
MODIFY_FIELD(_regs[slaveno][4], 0, 0x1, REG4_CNTR_RESET);
|
||||
this->write_reg(slaveno, 4);
|
||||
boost::this_thread::sleep(boost::posix_time::microseconds(sleepUs));
|
||||
if (verbose) std::cout << " sleep time " << (sleepUs) << " us" << std::endl;
|
||||
MODIFY_FIELD(_regs[slaveno][0], 1, 0x1, REG0_AUTOCAL_SHIFT);
|
||||
this->write_reg(slaveno, 0);
|
||||
|
||||
//calculate actual tune value
|
||||
double Nactual = NINT + std::ldexp(double(FRAC1 + FRAC2/double(MOD2)), -24);
|
||||
double RFoutactual = (fPFD*Nactual)/(1 << RFOUTDIVSEL);
|
||||
if (verbose) std::cout << " Nactual " << Nactual << "" << std::endl;
|
||||
if (verbose) std::cout << " RFoutactual " << (RFoutactual/1e6) << " MHz" << std::endl;
|
||||
if (verbose) boost::this_thread::sleep(boost::posix_time::microseconds(10000));
|
||||
if (verbose) std::cout << " Locked " << this->get_locked((slaveno==SPI_SS_AUX1)?1:2).value << "" << std::endl;
|
||||
return RFoutactual;
|
||||
}
|
||||
|
||||
void write_reg(const int slaveno, const int addr)
|
||||
{
|
||||
int value = (_regs[slaveno][addr] & ~0xf) | addr;
|
||||
if (verbose) std::cout << "write_reg[" << addr << "] = 0x" << std::hex << value << std::dec << std::endl;
|
||||
_spiface->write_spi(slaveno, uhd::spi_config_t::EDGE_RISE, value, 32);
|
||||
}
|
||||
|
||||
uhd::wb_iface::sptr _ctrl;
|
||||
uhd::spi_iface::sptr _spiface;
|
||||
const double _ref_clock;
|
||||
std::map<int, std::map<int, int> > _regs;
|
||||
const bool verbose;
|
||||
};
|
||||
|
||||
umsel2_ctrl::sptr umsel2_ctrl::make(uhd::wb_iface::sptr ctrl, uhd::spi_iface::sptr spiface, const double ref_clock, const bool verbose)
|
||||
{
|
||||
return umsel2_ctrl::sptr(new umsel2_ctrl_impl(ctrl, spiface, ref_clock, verbose));
|
||||
}
|
||||
61
host/umsel2_ctrl.hpp
Normal file
61
host/umsel2_ctrl.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// 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/>.
|
||||
//
|
||||
|
||||
#ifndef INCLUDED_UMSEL2_CTRL_HPP
|
||||
#define INCLUDED_UMSEL2_CTRL_HPP
|
||||
|
||||
#include <uhd/types/serial.hpp>
|
||||
#include <uhd/types/wb_iface.hpp>
|
||||
#include <uhd/types/sensors.hpp>
|
||||
#include <uhd/types/ranges.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#define UMSEL2_CH1_LMS_IF 360e6
|
||||
#define UMSEL2_CH2_LMS_IF 400e6
|
||||
|
||||
/*!
|
||||
* Control UmSEL2 board.
|
||||
*/
|
||||
class umsel2_ctrl
|
||||
{
|
||||
public:
|
||||
typedef boost::shared_ptr<umsel2_ctrl> sptr;
|
||||
|
||||
static sptr make(uhd::wb_iface::sptr ctrl, uhd::spi_iface::sptr spiface, const double ref_clock, const bool verbose);
|
||||
|
||||
/*!
|
||||
* Query the tune range.
|
||||
* \param which values 1 or 2
|
||||
*/
|
||||
virtual uhd::freq_range_t get_rx_freq_range(const int which) = 0;
|
||||
|
||||
/*!
|
||||
* Tune the synthesizer
|
||||
* \param which values 1 or 2
|
||||
* \param freq the freq in Hz
|
||||
* \return the actual freq in Hz
|
||||
*/
|
||||
virtual double set_rx_freq(const int which, const double freq) = 0;
|
||||
|
||||
/*!
|
||||
* Query lock detect.
|
||||
* \param which values 1 or 2
|
||||
*/
|
||||
virtual uhd::sensor_value_t get_locked(const int which) = 0;
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_UMSEL2_CTRL_HPP */
|
||||
@@ -44,13 +44,15 @@ static const boost::uint32_t MAX_SEQS_OUT = 15;
|
||||
class umtrx_fifo_ctrl_impl : public umtrx_fifo_ctrl{
|
||||
public:
|
||||
|
||||
umtrx_fifo_ctrl_impl(zero_copy_if::sptr xport, const boost::uint32_t sid):
|
||||
umtrx_fifo_ctrl_impl(zero_copy_if::sptr xport, const boost::uint32_t sid, const boost::uint32_t window_size):
|
||||
_xport(xport),
|
||||
_sid(sid),
|
||||
_window_size(std::min(window_size, MAX_SEQS_OUT)),
|
||||
_seq_out(0),
|
||||
_seq_ack(0),
|
||||
_timeout(ACK_TIMEOUT)
|
||||
{
|
||||
UHD_MSG(status) << "fifo_ctrl.window_size = " << _window_size << std::endl;
|
||||
while (_xport->get_recv_buff(0.0)){} //flush
|
||||
this->set_time(uhd::time_spec_t(0.0));
|
||||
this->set_tick_rate(1.0); //something possible but bogus
|
||||
@@ -72,7 +74,7 @@ public:
|
||||
|
||||
this->send_pkt((addr - SETTING_REGS_BASE)/4, data, POKE32_CMD);
|
||||
|
||||
this->wait_for_ack(_seq_out-MAX_SEQS_OUT);
|
||||
this->wait_for_ack(_seq_out-_window_size);
|
||||
}
|
||||
|
||||
boost::uint32_t peek32(wb_addr_type addr){
|
||||
@@ -101,7 +103,7 @@ public:
|
||||
boost::mutex::scoped_lock lock(_mutex);
|
||||
|
||||
this->send_pkt(SPI_DIV, SPI_DIVIDER, POKE32_CMD);
|
||||
this->wait_for_ack(_seq_out-MAX_SEQS_OUT);
|
||||
this->wait_for_ack(_seq_out-_window_size);
|
||||
|
||||
_ctrl_word_cache = 0; // force update first time around
|
||||
}
|
||||
@@ -128,13 +130,13 @@ public:
|
||||
//conditionally send control word
|
||||
if (_ctrl_word_cache != ctrl_word){
|
||||
this->send_pkt(SPI_CTRL, ctrl_word, POKE32_CMD);
|
||||
this->wait_for_ack(_seq_out-MAX_SEQS_OUT);
|
||||
this->wait_for_ack(_seq_out-_window_size);
|
||||
_ctrl_word_cache = ctrl_word;
|
||||
}
|
||||
|
||||
//send data word
|
||||
this->send_pkt(SPI_DATA, data_out, POKE32_CMD);
|
||||
this->wait_for_ack(_seq_out-MAX_SEQS_OUT);
|
||||
this->wait_for_ack(_seq_out-_window_size);
|
||||
|
||||
//conditional readback
|
||||
if (readback){
|
||||
@@ -230,6 +232,7 @@ private:
|
||||
|
||||
zero_copy_if::sptr _xport;
|
||||
const boost::uint32_t _sid;
|
||||
const boost::uint32_t _window_size;
|
||||
boost::mutex _mutex;
|
||||
boost::uint16_t _seq_out;
|
||||
boost::uint16_t _seq_ack;
|
||||
@@ -241,6 +244,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
umtrx_fifo_ctrl::sptr umtrx_fifo_ctrl::make(zero_copy_if::sptr xport, const boost::uint32_t sid){
|
||||
return sptr(new umtrx_fifo_ctrl_impl(xport, sid));
|
||||
umtrx_fifo_ctrl::sptr umtrx_fifo_ctrl::make(zero_copy_if::sptr xport, const boost::uint32_t sid, const size_t window_size){
|
||||
return sptr(new umtrx_fifo_ctrl_impl(xport, sid, boost::uint32_t(window_size)));
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <uhd/transport/zero_copy.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <uhd/types/wb_iface.hpp>
|
||||
#include <string>
|
||||
|
||||
@@ -36,7 +37,7 @@ public:
|
||||
typedef boost::shared_ptr<umtrx_fifo_ctrl> sptr;
|
||||
|
||||
//! Make a new FIFO control object
|
||||
static sptr make(uhd::transport::zero_copy_if::sptr xport, const boost::uint32_t sid);
|
||||
static sptr make(uhd::transport::zero_copy_if::sptr xport, const boost::uint32_t sid, const size_t window_size);
|
||||
|
||||
//! Set the command time that will activate
|
||||
virtual void set_time(const uhd::time_spec_t &time) = 0;
|
||||
|
||||
@@ -70,21 +70,16 @@ public:
|
||||
umtrx_iface_impl(udp_simple::sptr ctrl_transport):
|
||||
_ctrl_transport(ctrl_transport),
|
||||
_ctrl_seq_num(0),
|
||||
_protocol_compat(0) //initialized below...
|
||||
_protocol_compat(USRP2_FW_COMPAT_NUM)
|
||||
{
|
||||
//Obtain the firmware's compat number.
|
||||
//Save the response compat number for communication.
|
||||
//TODO can choose to reject certain older compat numbers
|
||||
usrp2_ctrl_data_t ctrl_data;
|
||||
ctrl_data.id = htonl(USRP2_CTRL_ID_WAZZUP_BRO);
|
||||
ctrl_data = ctrl_send_and_recv(ctrl_data, 0, ~0);
|
||||
if (ntohl(ctrl_data.id) != USRP2_CTRL_ID_WAZZUP_DUDE) {
|
||||
ctrl_data.id = htonl(UMTRX_CTRL_ID_REQUEST);
|
||||
ctrl_data = ctrl_send_and_recv(ctrl_data, 0, ~0);
|
||||
if (ntohl(ctrl_data.id) != UMTRX_CTRL_ID_RESPONSE)
|
||||
throw uhd::runtime_error(str(boost::format("unexpected firmware response: -->%c<--") % (char)ntohl(ctrl_data.id)));
|
||||
}
|
||||
ctrl_data.id = htonl(UMTRX_CTRL_ID_REQUEST);
|
||||
ctrl_data = ctrl_send_and_recv(ctrl_data, _protocol_compat, ~0);
|
||||
if (ntohl(ctrl_data.id) != UMTRX_CTRL_ID_RESPONSE)
|
||||
throw uhd::runtime_error(str(boost::format("unexpected firmware response: -->%c<--") % (char)ntohl(ctrl_data.id)));
|
||||
|
||||
//Save the response compat number for future communication.
|
||||
_protocol_compat = ntohl(ctrl_data.proto_ver);
|
||||
|
||||
// Read EEPROM with UMTRX extensions
|
||||
@@ -321,7 +316,7 @@ public:
|
||||
if(len >= sizeof(boost::uint32_t) and (hi < compat or lo > compat)){
|
||||
throw uhd::runtime_error(str(boost::format(
|
||||
"\nPlease update the firmware and FPGA images for your device.\n"
|
||||
"See the application notes for USRP2/N-Series for instructions.\n"
|
||||
"See the application notes for UmTRX for instructions.\n"
|
||||
"Expected protocol compatibility number %s, but got %d:\n"
|
||||
"The firmware build is not compatible with the host code build."
|
||||
) % ((lo == hi)? (boost::format("%d") % hi) : (boost::format("[%d to %d]") % lo % hi)) % compat));
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "umtrx_impl.hpp"
|
||||
#include "umtrx_regs.hpp"
|
||||
#include "umtrx_version.hpp"
|
||||
#include "cores/apply_corrections.hpp"
|
||||
#include <uhd/utils/log.hpp>
|
||||
#include <uhd/utils/msg.hpp>
|
||||
@@ -32,6 +33,83 @@ using namespace uhd::usrp;
|
||||
using namespace uhd::transport;
|
||||
namespace asio = boost::asio;
|
||||
|
||||
// Values recommended by Andrey Sviyazov
|
||||
const int umtrx_impl::UMTRX_VGA1_DEF = -20;
|
||||
const int umtrx_impl::UMTRX_VGA2_DEF = 22;
|
||||
const int umtrx_impl::UMTRX_VGA2_MIN = 0;
|
||||
|
||||
const double umtrx_impl::_dcdc_val_to_volt[umtrx_impl::DCDC_VER_COUNT][256] =
|
||||
{
|
||||
{
|
||||
9.38, 9.38, 9.40, 9.42, 9.42, 9.44, 9.46, 9.46, 9.48, 9.50, // 10
|
||||
9.50, 9.52, 9.54, 9.54, 9.56, 9.58, 9.58, 9.60, 9.60, 9.62, // 20
|
||||
9.64, 9.66, 9.66, 9.68, 9.70, 9.70, 9.72, 9.74, 9.76, 9.76, // 30
|
||||
9.78, 9.80, 9.82, 9.82, 9.84, 9.86, 9.88, 9.90, 9.92, 9.92, // 40
|
||||
9.94, 9.96, 9.98, 9.98, 10.00, 10.02, 10.04, 10.06, 10.06, 10.08, // 50
|
||||
10.10, 10.12, 10.14, 10.16, 10.18, 10.20, 10.20, 10.24, 10.24, 10.28, // 60
|
||||
10.30, 10.32, 10.34, 10.34, 10.36, 10.38, 10.40, 10.42, 10.44, 10.46, // 70
|
||||
10.48, 10.50, 10.52, 10.54, 10.56, 10.60, 10.62, 10.64, 10.66, 10.68, // 80
|
||||
10.70, 10.72, 10.74, 10.76, 10.78, 10.80, 10.84, 10.86, 10.88, 10.90, // 90
|
||||
10.94, 10.96, 10.98, 11.00, 11.02, 11.06, 11.06, 11.10, 11.12, 11.16, // 100
|
||||
11.18, 11.20, 11.24, 11.26, 11.28, 11.32, 11.34, 11.38, 11.40, 11.44, // 110
|
||||
11.46, 11.50, 11.50, 11.54, 11.58, 11.60, 11.64, 11.66, 11.70, 11.74, // 120
|
||||
11.76, 11.80, 11.84, 11.86, 11.90, 11.94, 11.98, 12.00, 12.02, 12.06, // 130
|
||||
12.10, 12.14, 12.18, 12.22, 12.26, 12.28, 12.32, 12.36, 12.40, 12.44, // 140
|
||||
12.48, 12.54, 12.58, 12.62, 12.64, 12.68, 12.72, 12.76, 12.82, 12.86, // 150
|
||||
12.90, 12.96, 13.00, 13.04, 13.10, 13.14, 13.20, 13.24, 13.30, 13.34, // 160
|
||||
13.38, 13.44, 13.48, 13.54, 13.60, 13.66, 13.72, 13.76, 13.82, 13.88, // 170
|
||||
13.94, 14.02, 14.06, 14.14, 14.20, 14.26, 14.30, 14.36, 14.42, 14.50, // 180
|
||||
14.56, 14.64, 14.72, 14.78, 14.86, 14.92, 15.00, 15.08, 15.16, 15.24, // 190
|
||||
15.32, 15.40, 15.46, 15.54, 15.62, 15.72, 15.80, 15.90, 16.00, 16.08, // 200
|
||||
16.18, 16.28, 16.38, 16.48, 16.58, 16.68, 16.80, 16.90, 16.96, 17.08, // 210
|
||||
17.20, 17.32, 17.44, 17.56, 17.68, 17.82, 17.94, 18.06, 18.20, 18.36, // 220
|
||||
18.48, 18.64, 18.78, 18.94, 19.02, 19.18, 19.34, 19.50, 19.68, 19.84, // 230
|
||||
20.02, 20.20, 20.38, 20.58, 20.76, 20.96, 21.18, 21.38, 21.60, 21.82, // 240
|
||||
21.92, 22.16, 22.40, 22.66, 22.92, 23.18, 23.46, 23.74, 24.02, 24.30, // 250
|
||||
24.62, 24.94, 25.28, 25.62, 25.98, 26.34
|
||||
},{
|
||||
4.84, 4.84, 4.86, 4.88, 4.88, 4.90, 4.92, 4.94, 4.94, 4.96, // 10
|
||||
4.98, 5.00, 5.02, 5.02, 5.04, 5.06, 5.06, 5.08, 5.10, 5.12, // 20
|
||||
5.12, 5.14, 5.16, 5.18, 5.20, 5.22, 5.22, 5.24, 5.26, 5.28, // 30
|
||||
5.30, 5.32, 5.32, 5.34, 5.36, 5.38, 5.40, 5.42, 5.44, 5.46, // 40
|
||||
5.48, 5.50, 5.50, 5.52, 5.54, 5.56, 5.58, 5.60, 5.62, 5.64, // 50
|
||||
5.66, 5.68, 5.70, 5.72, 5.74, 5.76, 5.78, 5.80, 5.82, 5.86, // 60
|
||||
5.88, 5.90, 5.92, 5.94, 5.96, 5.98, 6.00, 6.02, 6.04, 6.08, // 70
|
||||
6.10, 6.12, 6.14, 6.16, 6.20, 6.22, 6.24, 6.28, 6.30, 6.32, // 80
|
||||
6.34, 6.36, 6.40, 6.42, 6.44, 6.48, 6.50, 6.54, 6.56, 6.58, // 90
|
||||
6.62, 6.64, 6.68, 6.70, 6.74, 6.76, 6.78, 6.82, 6.84, 6.88, // 100
|
||||
6.92, 6.94, 6.98, 7.00, 7.04, 7.08, 7.12, 7.14, 7.18, 7.22, // 110
|
||||
7.26, 7.28, 7.30, 7.34, 7.38, 7.42, 7.46, 7.50, 7.54, 7.58, // 120
|
||||
7.62, 7.66, 7.70, 7.74, 7.78, 7.82, 7.86, 7.90, 7.92, 7.98, // 130
|
||||
8.02, 8.06, 8.10, 8.16, 8.20, 8.26, 8.30, 8.34, 8.40, 8.44, // 140
|
||||
8.50, 8.54, 8.60, 8.66, 8.68, 8.74, 8.78, 8.84, 8.90, 8.96, // 150
|
||||
9.02, 9.08, 9.14, 9.20, 9.26, 9.32, 9.38, 9.44, 9.52, 9.58, // 160
|
||||
9.62, 9.68, 9.76, 9.82, 9.90, 9.96, 10.04, 10.12, 10.18, 10.26, // 170
|
||||
10.34, 10.42, 10.50, 10.58, 10.68, 10.76, 10.80, 10.88, 10.98, 11.08, // 180
|
||||
11.16, 11.26, 11.36, 11.44, 11.54, 11.64, 11.74, 11.86, 11.96, 12.08, // 190
|
||||
12.18, 12.30, 12.36, 12.48, 12.60, 12.72, 12.84, 12.96, 13.10, 13.24, // 200
|
||||
13.36, 13.50, 13.64, 13.78, 13.94, 14.08, 14.24, 14.40, 14.48, 14.66, // 210
|
||||
14.82, 15.00, 15.18, 15.36, 15.54, 15.74, 15.92, 16.12, 16.32, 16.54, // 220
|
||||
16.76, 16.98, 17.22, 17.44, 17.58, 17.82, 18.08, 18.34, 18.62, 18.90, // 230
|
||||
19.20, 19.48, 19.80, 20.10, 20.44, 20.78, 21.12, 21.50, 21.88, 22.26, // 240
|
||||
22.48, 22.90, 23.34, 23.80, 24.26, 24.74, 25.26, 25.76, 26.32, 26.86, // 250
|
||||
27.48, 28.12, 28.78, 29.50, 29.50, 29.50
|
||||
}
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* 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
|
||||
**********************************************************************/
|
||||
@@ -129,7 +207,9 @@ static mtu_result_t determine_mtu(const std::string &addr, const mtu_result_t &u
|
||||
**********************************************************************/
|
||||
umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
|
||||
{
|
||||
_umtrx_vga2_def = device_addr.cast<int>("lmsvga2", UMTRX_VGA2_DEF);
|
||||
_device_ip_addr = device_addr["addr"];
|
||||
UHD_MSG(status) << "UmTRX driver version: " << UMTRX_VERSION << std::endl;
|
||||
UHD_MSG(status) << "Opening a UmTRX device... " << _device_ip_addr << std::endl;
|
||||
|
||||
//mtu self check -- not really doing anything with it
|
||||
@@ -181,7 +261,8 @@ umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
|
||||
// high performance settings control
|
||||
////////////////////////////////////////////////////////////////
|
||||
_iface->poke32(U2_REG_MISC_CTRL_SFC_CLEAR, 1); //clear settings fifo control state machine
|
||||
_ctrl = umtrx_fifo_ctrl::make(this->make_xport(UMTRX_CTRL_FRAMER, device_addr_t()), UMTRX_CTRL_SID);
|
||||
const size_t fifo_ctrl_window(device_addr.cast<size_t>("fifo_ctrl_window", 1024)); //default gets clipped to hardware maximum
|
||||
_ctrl = umtrx_fifo_ctrl::make(this->make_xport(UMTRX_CTRL_FRAMER, device_addr_t()), UMTRX_CTRL_SID, fifo_ctrl_window);
|
||||
_ctrl->peek32(0); //test readback
|
||||
_tree->create<time_spec_t>(mb_path / "time/cmd")
|
||||
.subscribe(boost::bind(&umtrx_fifo_ctrl::set_time, _ctrl, _1));
|
||||
@@ -218,16 +299,106 @@ umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
|
||||
_tree->create<std::string>(mb_path / "hwrev").set(get_hw_rev());
|
||||
UHD_MSG(status) << "Detected UmTRX " << get_hw_rev() << std::endl;
|
||||
|
||||
_hw_dcdc_ver = device_addr.cast<int>("dcdc_ver", -1);
|
||||
if (_hw_dcdc_ver < 0)
|
||||
{
|
||||
detect_hw_dcdc_ver(mb_path);
|
||||
} else {
|
||||
UHD_ASSERT_THROW(_hw_dcdc_ver < DCDC_VER_COUNT);
|
||||
UHD_MSG(status) << "Using DCDC version " << _hw_dcdc_ver << std::endl;
|
||||
}
|
||||
_tree->create<int>(mb_path / "hwdcdc_ver").set(_hw_dcdc_ver);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// setup umsel2 control when present
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
const std::string detect_umsel = device_addr.get("umsel", "off");
|
||||
if (detect_umsel != "off")
|
||||
{
|
||||
//TODO delect umsel2 automatically with I2C communication
|
||||
const bool umsel_verbose = device_addr.has_key("umsel_verbose");
|
||||
_umsel2 = umsel2_ctrl::make(_ctrl/*peek*/, _ctrl/*spi*/, this->get_master_clock_rate(), umsel_verbose);
|
||||
}
|
||||
|
||||
//register lock detect for umsel2
|
||||
if (_umsel2)
|
||||
{
|
||||
_tree->create<sensor_value_t>(mb_path / "dboards" / "A" / "rx_frontends" / "0" / "sensors" / "aux_lo_locked")
|
||||
.publish(boost::bind(&umsel2_ctrl::get_locked, _umsel2, 1));
|
||||
_tree->create<sensor_value_t>(mb_path / "dboards" / "B" / "rx_frontends" / "0" / "sensors" / "aux_lo_locked")
|
||||
.publish(boost::bind(&umsel2_ctrl::get_locked, _umsel2, 2));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// configure diversity switches
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// note: the control is also aliased to RF frontend later
|
||||
_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")
|
||||
.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
|
||||
_pll_div = 1;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// get the atached PA type
|
||||
////////////////////////////////////////////////////////////////////
|
||||
std::list<std::string> pa_types = power_amp::list_pa_str();
|
||||
std::string pa_list_str;
|
||||
BOOST_FOREACH(const std::string &pa_str, pa_types)
|
||||
{
|
||||
pa_list_str += pa_str + " ";
|
||||
}
|
||||
UHD_MSG(status) << "Known PA types: " << pa_list_str << std::endl;
|
||||
|
||||
power_amp::pa_type_t pa_type = power_amp::pa_str_to_type(device_addr.cast<std::string>("pa", "NONE"));
|
||||
if (_hw_rev < UMTRX_VER_2_3_1 and pa_type != power_amp::PA_NONE)
|
||||
{
|
||||
UHD_MSG(error) << "PA type " << power_amp::pa_type_to_str(pa_type) << " is not supported for UmTRX "
|
||||
<< get_hw_rev() << ". Setting PA type to NONE." << std::endl;
|
||||
pa_type = power_amp::PA_NONE;
|
||||
}
|
||||
|
||||
for (char name = 'A'; name <= 'B'; name++)
|
||||
{
|
||||
std::string name_str = std::string(1, name);
|
||||
_pa[name_str] = power_amp::make(pa_type);
|
||||
UHD_MSG(status) << "Installed PA for side" << name_str << ": " << power_amp::pa_type_to_str(pa_type) << std::endl;
|
||||
}
|
||||
|
||||
if (_pa["A"])
|
||||
{
|
||||
_pa_power_max_dBm = _pa["A"]->max_power_dBm();
|
||||
|
||||
double limit_w = device_addr.cast<double>("pa_power_max_w", _pa["A"]->max_power_w());
|
||||
if (limit_w != _pa["A"]->max_power_w()) {
|
||||
_pa_power_max_dBm = power_amp::w2dBm(limit_w);
|
||||
}
|
||||
|
||||
double limit_dbm = device_addr.cast<double>("pa_power_max_dbm", _pa["A"]->max_power_dBm());
|
||||
if (limit_dbm != _pa["A"]->max_power_dBm()) {
|
||||
_pa_power_max_dBm = limit_dbm;
|
||||
}
|
||||
|
||||
if (_pa_power_max_dBm != _pa["A"]->max_power_dBm()) {
|
||||
UHD_MSG(status) << "Limiting PA output power to: " << _pa_power_max_dBm << "dBm (" << power_amp::dBm2w(_pa_power_max_dBm) << "W)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// create codec control objects
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@@ -276,9 +447,11 @@ umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
|
||||
_tree->create<std::complex<double> >(rx_fe_path / "iq_balance" / "value")
|
||||
.subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, rx_fe, _1))
|
||||
.set(std::polar<double>(0.0, 0.0));
|
||||
/*
|
||||
_tree->create<std::complex<double> >(tx_fe_path / "dc_offset" / "value")
|
||||
.coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, tx_fe, _1))
|
||||
.set(std::complex<double>(0.0, 0.0));
|
||||
*/
|
||||
_tree->create<std::complex<double> >(tx_fe_path / "iq_balance" / "value")
|
||||
.subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, tx_fe, _1))
|
||||
.set(std::polar<double>(0.0, 0.0));
|
||||
@@ -376,8 +549,8 @@ umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// create RF frontend interfacing
|
||||
////////////////////////////////////////////////////////////////////
|
||||
_lms_ctrl["A"] = lms6002d_ctrl::make(_ctrl/*spi*/, SPI_SS_LMS1, SPI_SS_AUX1, this->get_master_clock_rate() / _pll_div);
|
||||
_lms_ctrl["B"] = lms6002d_ctrl::make(_ctrl/*spi*/, SPI_SS_LMS2, SPI_SS_AUX2, this->get_master_clock_rate() / _pll_div);
|
||||
_lms_ctrl["A"] = lms6002d_ctrl::make(_ctrl/*spi*/, SPI_SS_LMS1, this->get_master_clock_rate() / _pll_div);
|
||||
_lms_ctrl["B"] = lms6002d_ctrl::make(_ctrl/*spi*/, SPI_SS_LMS2, this->get_master_clock_rate() / _pll_div);
|
||||
|
||||
// LMS dboard do not have physical eeprom so we just hardcode values from host/lib/usrp/dboard/db_lms.cpp
|
||||
dboard_eeprom_t rx_db_eeprom, tx_db_eeprom, gdb_db_eeprom;
|
||||
@@ -409,9 +582,9 @@ umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
|
||||
|
||||
//sensors -- always say locked
|
||||
_tree->create<sensor_value_t>(rx_rf_fe_path / "sensors" / "lo_locked")
|
||||
.set(sensor_value_t("LO", true, "locked", "unlocked"));
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_rx_pll_locked, ctrl));
|
||||
_tree->create<sensor_value_t>(tx_rf_fe_path / "sensors" / "lo_locked")
|
||||
.set(sensor_value_t("LO", true, "locked", "unlocked"));
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_tx_pll_locked, ctrl));
|
||||
|
||||
//rx gains
|
||||
BOOST_FOREACH(const std::string &name, ctrl->get_rx_gains())
|
||||
@@ -425,21 +598,41 @@ umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
|
||||
}
|
||||
|
||||
//tx gains
|
||||
BOOST_FOREACH(const std::string &name, ctrl->get_tx_gains())
|
||||
if (!_pa[fe_name])
|
||||
{
|
||||
_tree->create<meta_range_t>(tx_rf_fe_path / "gains" / name / "range")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_tx_gain_range, ctrl, name));
|
||||
// Use internal LMS gain control if we don't have a PA
|
||||
BOOST_FOREACH(const std::string &name, ctrl->get_tx_gains())
|
||||
{
|
||||
_tree->create<meta_range_t>(tx_rf_fe_path / "gains" / name / "range")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_tx_gain_range, ctrl, name));
|
||||
|
||||
_tree->create<double>(tx_rf_fe_path / "gains" / name / "value")
|
||||
.coerce(boost::bind(&lms6002d_ctrl::set_tx_gain, ctrl, _1, name))
|
||||
.set((ctrl->get_tx_gain_range(name).start() + ctrl->get_tx_gain_range(name).stop())/2.0);
|
||||
}
|
||||
} else {
|
||||
// Set LMS internal VGA1 gain to optimal value
|
||||
// VGA2 will be set in the set_tx_power()
|
||||
const int vga1 = device_addr.cast<int>("lmsvga1", UMTRX_VGA1_DEF);
|
||||
ctrl->set_tx_gain(vga1, "VGA1");
|
||||
_tx_power_range[fe_name] = generate_tx_power_range(fe_name);
|
||||
|
||||
// Use PA control to control output power
|
||||
_tree->create<meta_range_t>(tx_rf_fe_path / "gains" / "PA" / "range")
|
||||
.publish(boost::bind(&umtrx_impl::get_tx_power_range, this, fe_name));
|
||||
|
||||
_tree->create<double>(tx_rf_fe_path / "gains" / "PA" / "value")
|
||||
.coerce(boost::bind(&umtrx_impl::set_tx_power, this, _1, fe_name))
|
||||
// Set default output power to maximum
|
||||
.set(get_tx_power_range(fe_name).stop());
|
||||
|
||||
_tree->create<double>(tx_rf_fe_path / "gains" / name / "value")
|
||||
.coerce(boost::bind(&lms6002d_ctrl::set_tx_gain, ctrl, _1, name))
|
||||
.set((ctrl->get_tx_gain_range(name).start() + ctrl->get_tx_gain_range(name).stop())/2.0);
|
||||
}
|
||||
|
||||
//rx freq
|
||||
_tree->create<double>(rx_rf_fe_path / "freq" / "value")
|
||||
.coerce(boost::bind(&lms6002d_ctrl::set_rx_freq, ctrl, _1));
|
||||
.coerce(boost::bind(&umtrx_impl::set_rx_freq, this, fe_name, _1));
|
||||
_tree->create<meta_range_t>(rx_rf_fe_path / "freq" / "range")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_rx_freq_range, ctrl));
|
||||
.publish(boost::bind(&umtrx_impl::get_rx_freq_range, this, fe_name));
|
||||
_tree->create<bool>(rx_rf_fe_path / "use_lo_offset").set(false);
|
||||
|
||||
//tx freq
|
||||
@@ -503,19 +696,53 @@ umtrx_impl::umtrx_impl(const device_addr_t &device_addr)
|
||||
|
||||
//set Tx DC calibration values, which are read from mboard EEPROM
|
||||
std::string tx_name = (fe_name=="A")?"tx1":"tx2";
|
||||
const std::string dc_i = _iface->mb_eeprom.get(tx_name+"-vga1-dc-i", "");
|
||||
const std::string dc_q = _iface->mb_eeprom.get(tx_name+"-vga1-dc-q", "");
|
||||
if (not dc_i.empty()) _tree->access<uint8_t>(tx_rf_fe_path / "lms6002d" / "tx_dc_i" / "value")
|
||||
.set(boost::lexical_cast<int>(dc_i));
|
||||
if (not dc_q.empty()) _tree->access<uint8_t>(tx_rf_fe_path / "lms6002d" / "tx_dc_q" / "value")
|
||||
.set(boost::lexical_cast<int>(dc_q));
|
||||
const std::string dc_i_str = _iface->mb_eeprom.get(tx_name+"-vga1-dc-i", "");
|
||||
const std::string dc_q_str = _iface->mb_eeprom.get(tx_name+"-vga1-dc-q", "");
|
||||
double dc_i = dc_i_str.empty() ? 0.0 : dc_offset_int2double(boost::lexical_cast<int>(dc_i_str));
|
||||
double dc_q = dc_q_str.empty() ? 0.0 : dc_offset_int2double(boost::lexical_cast<int>(dc_q_str));
|
||||
|
||||
//plugin dc_offset from lms into the frontend corrections
|
||||
_tree->create<std::complex<double> >(mb_path / "tx_frontends" / fe_name / "dc_offset" / "value")
|
||||
.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))
|
||||
.set(std::complex<double>(dc_i, dc_q));
|
||||
|
||||
//rx cal props
|
||||
_tree->create<uint8_t>(rx_rf_fe_path / "lms6002d" / "rx_fe_dc_i" / "value")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_rxfe_dc_i, ctrl))
|
||||
.subscribe(boost::bind(&lms6002d_ctrl::set_rxfe_dc_i, ctrl, _1));
|
||||
_tree->create<uint8_t>(rx_rf_fe_path / "lms6002d" / "rx_fe_dc_q" / "value")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_rxfe_dc_q, ctrl))
|
||||
.subscribe(boost::bind(&lms6002d_ctrl::set_rxfe_dc_q, ctrl, _1));
|
||||
_tree->create<uint8_t>(rx_rf_fe_path / "lms6002d" / "rx_lpf_dc_i" / "value")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_rxlpf_dc_i, ctrl))
|
||||
.subscribe(boost::bind(&lms6002d_ctrl::set_rxlpf_dc_i, ctrl, _1));
|
||||
_tree->create<uint8_t>(rx_rf_fe_path / "lms6002d" / "rx_lpf_dc_q" / "value")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_rxlpf_dc_q, ctrl))
|
||||
.subscribe(boost::bind(&lms6002d_ctrl::set_rxlpf_dc_q, ctrl, _1));
|
||||
_tree->create<uint8_t>(rx_rf_fe_path / "lms6002d" / "rxvga2_dc_reference" / "value")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_rxvga2_dc_reference, ctrl))
|
||||
.subscribe(boost::bind(&lms6002d_ctrl::set_rxvga2_dc_reference, ctrl, _1));
|
||||
_tree->create<uint8_t>(rx_rf_fe_path / "lms6002d" / "rxvga2a_dc_i" / "value")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_rxvga2a_dc_i, ctrl))
|
||||
.subscribe(boost::bind(&lms6002d_ctrl::set_rxvga2a_dc_i, ctrl, _1));
|
||||
_tree->create<uint8_t>(rx_rf_fe_path / "lms6002d" / "rxvga2a_dc_q" / "value")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_rxvga2a_dc_q, ctrl))
|
||||
.subscribe(boost::bind(&lms6002d_ctrl::set_rxvga2a_dc_q, ctrl, _1));
|
||||
_tree->create<uint8_t>(rx_rf_fe_path / "lms6002d" / "rxvga2b_dc_i" / "value")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_rxvga2b_dc_i, ctrl))
|
||||
.subscribe(boost::bind(&lms6002d_ctrl::set_rxvga2b_dc_i, ctrl, _1));
|
||||
_tree->create<uint8_t>(rx_rf_fe_path / "lms6002d" / "rxvga2b_dc_q" / "value")
|
||||
.publish(boost::bind(&lms6002d_ctrl::get_rxvga2b_dc_q, ctrl))
|
||||
.subscribe(boost::bind(&lms6002d_ctrl::set_rxvga2b_dc_q, ctrl, _1));
|
||||
|
||||
// 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
|
||||
const std::string tcxo_dac = _iface->mb_eeprom.get("tcxo-dac", "");
|
||||
//TCXO DAC calibration control
|
||||
if (not tcxo_dac.empty()) _tree->create<uint16_t>(mb_path / "tcxo_dac" / "value")
|
||||
.subscribe(boost::bind(&umtrx_impl::set_tcxo_dac, this, _iface, _1))
|
||||
.set(boost::lexical_cast<uint16_t>(tcxo_dac));
|
||||
.subscribe(boost::bind(&umtrx_impl::set_tcxo_dac, this, _iface, _1));
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// post config tasks
|
||||
@@ -549,10 +776,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 / "time_source" / "value").set("none");
|
||||
|
||||
//create status monitor and client handler
|
||||
this->status_monitor_start(device_addr);
|
||||
}
|
||||
|
||||
umtrx_impl::~umtrx_impl(void)
|
||||
{
|
||||
this->status_monitor_stop();
|
||||
|
||||
BOOST_FOREACH(const std::string &fe_name, _lms_ctrl.keys())
|
||||
{
|
||||
lms6002d_ctrl::sptr ctrl = _lms_ctrl[fe_name];
|
||||
@@ -565,15 +797,106 @@ umtrx_impl::~umtrx_impl(void)
|
||||
}
|
||||
}
|
||||
|
||||
int umtrx_impl::volt_to_dcdc_r(double v)
|
||||
{
|
||||
if (v <= _dcdc_val_to_volt[_hw_dcdc_ver][0])
|
||||
return 0;
|
||||
else if (v >= _dcdc_val_to_volt[_hw_dcdc_ver][255])
|
||||
return 255;
|
||||
else
|
||||
return std::lower_bound(&_dcdc_val_to_volt[_hw_dcdc_ver][0], &_dcdc_val_to_volt[_hw_dcdc_ver][256], v) -
|
||||
&_dcdc_val_to_volt[_hw_dcdc_ver][0];
|
||||
}
|
||||
|
||||
void umtrx_impl::set_pa_dcdc_r(uint8_t val)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock l(_i2c_mutex);
|
||||
// AD5245 control
|
||||
if (_hw_rev >= UMTRX_VER_2_3_1)
|
||||
{
|
||||
_pa_dcdc_r = val;
|
||||
_iface->write_i2c(BOOST_BINARY(0101100), boost::assign::list_of(0)(val));
|
||||
}
|
||||
}
|
||||
|
||||
uhd::gain_range_t umtrx_impl::generate_tx_power_range(const std::string &which) const
|
||||
{
|
||||
// Native PA range plus LMS6 VGA2 control. We keep LMS6 VGA1 constant to
|
||||
// maintain high signal quality.
|
||||
uhd::gain_range_t pa_range = generate_pa_power_range(which);
|
||||
// UHD_MSG(status) << "Original PA output power range: " << pa_range.to_pp_string() << std::endl;
|
||||
uhd::gain_range_t vga_range(pa_range.start() - (_umtrx_vga2_def-UMTRX_VGA2_MIN), pa_range.start()-1, 1.0);
|
||||
uhd::gain_range_t res_range(vga_range);
|
||||
res_range.insert(res_range.end(), pa_range.begin(), pa_range.end());
|
||||
// UHD_MSG(status) << "Generated Tx output power range: " << res_range.to_pp_string() << std::endl;
|
||||
return res_range;
|
||||
}
|
||||
|
||||
uhd::gain_range_t umtrx_impl::generate_pa_power_range(const std::string &which) const
|
||||
{
|
||||
double min_power = _pa[which]->min_power_dBm();
|
||||
double max_power = _pa_power_max_dBm;
|
||||
return uhd::gain_range_t(min_power, max_power, 0.1);
|
||||
}
|
||||
|
||||
const uhd::gain_range_t &umtrx_impl::get_tx_power_range(const std::string &which) const
|
||||
{
|
||||
return _tx_power_range[which];
|
||||
}
|
||||
|
||||
double umtrx_impl::set_tx_power(double power, const std::string &which)
|
||||
{
|
||||
double min_pa_power = _pa[which]->min_power_dBm();
|
||||
double actual_power;
|
||||
|
||||
if (power >= min_pa_power)
|
||||
{
|
||||
UHD_MSG(status) << "Setting Tx power using PA (VGA2=" << _umtrx_vga2_def << ", PA=" << power << ")" << std::endl;
|
||||
// Set VGA2 to the recommended value and use PA to control Tx power
|
||||
_lms_ctrl[which]->set_tx_gain(_umtrx_vga2_def, "VGA2");
|
||||
actual_power = set_pa_power(power, which);
|
||||
} else {
|
||||
double vga2_gain = _umtrx_vga2_def - (min_pa_power-power);
|
||||
UHD_MSG(status) << "Setting Tx power using VGA2 (VGA2=" << vga2_gain << ", PA=" << min_pa_power << ")" << std::endl;
|
||||
// Set PA output power to minimum and use VGA2 to control Tx power
|
||||
actual_power = _lms_ctrl[which]->set_tx_gain(vga2_gain, "VGA2");
|
||||
actual_power = set_pa_power(min_pa_power, which) - (_umtrx_vga2_def-actual_power);
|
||||
}
|
||||
|
||||
return actual_power;
|
||||
}
|
||||
|
||||
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:: Limit output power for UmSITE-TM3
|
||||
|
||||
// Find voltage required for the requested output power
|
||||
double v = _pa[which]->dBm2v(power);
|
||||
uint8_t dcdc_val = volt_to_dcdc_r(v);
|
||||
// Set the value
|
||||
set_nlow(true);
|
||||
set_pa_dcdc_r(dcdc_val);
|
||||
|
||||
// Check what power do we actually have by reading the DCDC voltage
|
||||
// and converting it to the PA power
|
||||
double v_actual = read_dc_v("DCOUT").to_real();
|
||||
double power_actual = _pa[which]->v2dBm(v_actual);
|
||||
|
||||
// TODO:: Check that power is actually there by reading VSWR sensor.
|
||||
|
||||
UHD_MSG(status) << "Setting PA power: Requested: " << power << "dBm = " << power_amp::dBm2w(power) << "W "
|
||||
<< "(" << v << "V dcdc_r=" << int(dcdc_val) << "). "
|
||||
<< "Actual: " << power_actual << "dBm = " << power_amp::dBm2w(power_actual) <<"W "
|
||||
<< "(" << v_actual << "V)" << std::endl;
|
||||
|
||||
return power_actual;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -613,8 +936,75 @@ uint16_t umtrx_impl::get_tcxo_dac(const umtrx_iface::sptr &iface){
|
||||
return (uint16_t)val;
|
||||
}
|
||||
|
||||
std::complex<double> umtrx_impl::get_dc_offset_correction(const std::string &which) const
|
||||
{
|
||||
return std::complex<double>(
|
||||
dc_offset_int2double(_lms_ctrl[which]->get_tx_vga1dc_i_int()),
|
||||
dc_offset_int2double(_lms_ctrl[which]->get_tx_vga1dc_q_int()));
|
||||
}
|
||||
|
||||
void umtrx_impl::set_dc_offset_correction(const std::string &which, const std::complex<double> &corr)
|
||||
{
|
||||
_lms_ctrl[which]->_set_tx_vga1dc_i_int(dc_offset_double2int(corr.real()));
|
||||
_lms_ctrl[which]->_set_tx_vga1dc_q_int(dc_offset_double2int(corr.imag()));
|
||||
}
|
||||
|
||||
double umtrx_impl::dc_offset_int2double(uint8_t corr)
|
||||
{
|
||||
return (corr-128)/128.0;
|
||||
}
|
||||
|
||||
uint8_t umtrx_impl::dc_offset_double2int(double corr)
|
||||
{
|
||||
return (int)(corr*128 + 128.5);
|
||||
}
|
||||
|
||||
double umtrx_impl::set_rx_freq(const std::string &which, const double freq)
|
||||
{
|
||||
if (_umsel2)
|
||||
{
|
||||
const double target_lms_freq = (which=="A")?UMSEL2_CH1_LMS_IF:UMSEL2_CH2_LMS_IF;
|
||||
const double actual_lms_freq = _lms_ctrl[which]->set_rx_freq(target_lms_freq);
|
||||
|
||||
const double target_umsel_freq = freq - actual_lms_freq;
|
||||
const double actual_umsel_freq = _umsel2->set_rx_freq((which=="A")?1:2, target_umsel_freq);
|
||||
|
||||
/*
|
||||
std::cout << "target_total_freq " << freq/1e6 << " MHz" << std::endl;
|
||||
std::cout << "target_lms_freq " << target_lms_freq/1e6 << " MHz" << std::endl;
|
||||
std::cout << "actual_lms_freq " << actual_lms_freq/1e6 << " MHz" << std::endl;
|
||||
std::cout << "target_umsel_freq " << target_umsel_freq/1e6 << " MHz" << std::endl;
|
||||
std::cout << "actual_umsel_freq " << actual_umsel_freq/1e6 << " MHz" << std::endl;
|
||||
std::cout << "actual_total_freq " << (actual_umsel_freq + actual_lms_freq)/1e6 << " MHz" << std::endl;
|
||||
//*/
|
||||
|
||||
return actual_umsel_freq + actual_lms_freq;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _lms_ctrl[which]->set_rx_freq(freq);
|
||||
}
|
||||
}
|
||||
|
||||
uhd::freq_range_t umtrx_impl::get_rx_freq_range(const std::string &which) const
|
||||
{
|
||||
if (_umsel2)
|
||||
{
|
||||
const double target_lms_freq = (which=="A")?UMSEL2_CH1_LMS_IF:UMSEL2_CH2_LMS_IF;
|
||||
const uhd::freq_range_t range_umsel = _umsel2->get_rx_freq_range((which=="A")?1:2);
|
||||
return uhd::freq_range_t(
|
||||
range_umsel.start()+target_lms_freq,
|
||||
range_umsel.stop()+target_lms_freq);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _lms_ctrl[which]->get_rx_freq_range();
|
||||
}
|
||||
}
|
||||
|
||||
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() :
|
||||
_temp_side_b.get_temp();
|
||||
return uhd::sensor_value_t("Temp"+which, temp, "C");
|
||||
@@ -622,6 +1012,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)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock l(_i2c_mutex);
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (which == power_sensors[i])
|
||||
@@ -637,6 +1028,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)
|
||||
{
|
||||
boost::recursive_mutex::scoped_lock l(_i2c_mutex);
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (which == dc_sensors[i])
|
||||
@@ -740,7 +1132,7 @@ void umtrx_impl::detect_hw_rev(const fs_path& mb_path)
|
||||
pa_low = pa_low_env;
|
||||
}
|
||||
if (pa_low.empty())
|
||||
_pa_nlow = false;
|
||||
_pa_nlow = true; //Turn off Vin bypass by default
|
||||
else
|
||||
_pa_nlow = (boost::lexical_cast<int>(pa_low) == 0);
|
||||
|
||||
@@ -782,14 +1174,11 @@ void umtrx_impl::set_nlow(bool en)
|
||||
_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);
|
||||
}
|
||||
|
||||
void umtrx_impl::set_divsw2(bool en)
|
||||
{
|
||||
_iface->poke32(U2_REG_SR_ADDR(SR_DIVSW+1), (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);
|
||||
}
|
||||
|
||||
const char* umtrx_impl::get_hw_rev() const
|
||||
@@ -804,3 +1193,33 @@ const char* umtrx_impl::get_hw_rev() const
|
||||
}
|
||||
}
|
||||
|
||||
void umtrx_impl::detect_hw_dcdc_ver(const uhd::fs_path &)
|
||||
{
|
||||
_hw_dcdc_ver = DCDC_VER_2_3_1_OLD;
|
||||
if (_hw_rev < UMTRX_VER_2_3_1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t old = _pa_dcdc_r;
|
||||
bool old_pa_nlow = _pa_nlow;
|
||||
|
||||
set_nlow(true);
|
||||
set_pa_dcdc_r(0);
|
||||
boost::this_thread::sleep(boost::posix_time::seconds(1));
|
||||
double v_actual = read_dc_v("DCOUT").to_real();
|
||||
|
||||
double err_min = std::abs(v_actual - _dcdc_val_to_volt[0][0]);
|
||||
for (unsigned j = 1; j < DCDC_VER_COUNT; ++j) {
|
||||
double err = std::abs(v_actual - _dcdc_val_to_volt[j][0]);
|
||||
if (err < err_min) {
|
||||
err_min = err;
|
||||
_hw_dcdc_ver = j;
|
||||
}
|
||||
}
|
||||
set_pa_dcdc_r(old);
|
||||
set_nlow(old_pa_nlow);
|
||||
|
||||
UHD_MSG(status) << "Detected UmTRX DCDC ver. " << _hw_dcdc_ver
|
||||
<< " (err: " << err_min << ")" << std::endl;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "cores/time64_core_200.hpp"
|
||||
#include "ads1015_ctrl.hpp"
|
||||
#include "tmp102_ctrl.hpp"
|
||||
#include "power_amp.hpp"
|
||||
#include "umsel2_ctrl.hpp"
|
||||
#include <uhd/usrp/mboard_eeprom.hpp>
|
||||
#include <uhd/property_tree.hpp>
|
||||
#include <uhd/device.hpp>
|
||||
@@ -47,6 +49,8 @@
|
||||
#include <uhd/transport/udp_simple.hpp>
|
||||
#include <uhd/transport/udp_zero_copy.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/exception.hpp>
|
||||
#include <uhd/utils/static.hpp>
|
||||
@@ -57,6 +61,7 @@
|
||||
#include <boost/weak_ptr.hpp>
|
||||
#include <boost/asio.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.
|
||||
@@ -114,28 +119,55 @@ private:
|
||||
UMTRX_VER_2_3_1
|
||||
};
|
||||
|
||||
enum umtrx_dcdc_ver {
|
||||
DCDC_VER_2_3_1_OLD = 0,
|
||||
DCDC_VER_2_3_1_NEW = 1,
|
||||
|
||||
DCDC_VER_COUNT //Should be the last
|
||||
};
|
||||
|
||||
// hardware revision
|
||||
umtrx_hw_rev _hw_rev;
|
||||
int _hw_dcdc_ver;
|
||||
|
||||
unsigned _pll_div;
|
||||
const char* get_hw_rev() const;
|
||||
|
||||
//communication interfaces
|
||||
std::string _device_ip_addr;
|
||||
umtrx_iface::sptr _iface;
|
||||
umtrx_fifo_ctrl::sptr _ctrl;
|
||||
// Optimal VGA settings for GSM signal, according to our measurements.
|
||||
static const int UMTRX_VGA1_DEF;
|
||||
static const int UMTRX_VGA2_DEF;
|
||||
static const int UMTRX_VGA2_MIN;
|
||||
|
||||
static const double _dcdc_val_to_volt[umtrx_impl::DCDC_VER_COUNT][256];
|
||||
|
||||
ads1015_ctrl _sense_pwr;
|
||||
ads1015_ctrl _sense_dc;
|
||||
tmp102_ctrl _temp_side_a;
|
||||
tmp102_ctrl _temp_side_b;
|
||||
|
||||
// Optimal device specific value
|
||||
int _umtrx_vga2_def;
|
||||
|
||||
//PA control
|
||||
bool _pa_nlow;
|
||||
bool _pa_en1;
|
||||
bool _pa_en2;
|
||||
uint8_t _pa_dcdc_r;
|
||||
double _pa_power_max_dBm; // Artifical PA output power limit, dBm
|
||||
|
||||
void set_pa_dcdc_r(uint8_t val);
|
||||
uint8_t get_pa_dcdc_r() const {return _pa_dcdc_r;}
|
||||
|
||||
//communication interfaces
|
||||
std::string _device_ip_addr;
|
||||
umtrx_iface::sptr _iface;
|
||||
umtrx_fifo_ctrl::sptr _ctrl;
|
||||
umsel2_ctrl::sptr _umsel2;
|
||||
|
||||
//controls for perifs
|
||||
uhd::dict<std::string, lms6002d_ctrl::sptr> _lms_ctrl;
|
||||
uhd::dict<std::string, uhd::power_amp::sptr> _pa;
|
||||
uhd::dict<std::string, uhd::gain_range_t> _tx_power_range; // Tx output power range
|
||||
|
||||
//control for FPGA cores
|
||||
std::vector<rx_frontend_core_200::sptr> _rx_fes;
|
||||
@@ -145,7 +177,6 @@ private:
|
||||
time64_core_200::sptr _time64;
|
||||
|
||||
//helper routines
|
||||
void set_pa_dcdc_r(uint8_t val);
|
||||
void set_mb_eeprom(const uhd::i2c_iface::sptr &, const uhd::usrp::mboard_eeprom_t &);
|
||||
double get_master_clock_rate(void) const { return 26e6; }
|
||||
double get_master_dsp_rate(void) const { return get_master_clock_rate()/2; }
|
||||
@@ -161,19 +192,49 @@ private:
|
||||
void set_tx_fe_corrections(const std::string &mb, const std::string &board, const double);
|
||||
void set_tcxo_dac(const umtrx_iface::sptr &, const uint16_t val);
|
||||
void detect_hw_rev(const uhd::fs_path &mb_path);
|
||||
void detect_hw_dcdc_ver(const uhd::fs_path &mb_path);
|
||||
void commit_pa_state();
|
||||
void set_enpa1(bool en);
|
||||
void set_enpa2(bool en);
|
||||
void set_nlow(bool en);
|
||||
void set_divsw1(bool en);
|
||||
void set_divsw2(bool en);
|
||||
void set_diversity(bool en, int chan);
|
||||
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;
|
||||
const uhd::gain_range_t &get_tx_power_range(const std::string &which) const;
|
||||
double set_tx_power(double power, const std::string &which);
|
||||
double set_pa_power(double power, const std::string &which);
|
||||
uint16_t get_tcxo_dac(const umtrx_iface::sptr &);
|
||||
uhd::transport::zero_copy_if::sptr make_xport(const size_t which, const uhd::device_addr_t &args);
|
||||
std::complex<double> get_dc_offset_correction(const std::string &which) const;
|
||||
void set_dc_offset_correction(const std::string &which, const std::complex<double> &corr);
|
||||
double set_rx_freq(const std::string &which, const double freq);
|
||||
uhd::freq_range_t get_rx_freq_range(const std::string &which) const;
|
||||
|
||||
// Find a dcdc_r value to approximate requested Vout voltage
|
||||
int volt_to_dcdc_r(double v);
|
||||
|
||||
static double dc_offset_int2double(uint8_t corr);
|
||||
static uint8_t dc_offset_double2int(double corr);
|
||||
|
||||
//temp sensors read values in degC
|
||||
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_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
|
||||
std::vector<boost::weak_ptr<uhd::rx_streamer> > _rx_streamers;
|
||||
|
||||
271
host/umtrx_monitor.cpp
Normal file
271
host/umtrx_monitor.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
//
|
||||
// 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, COMPLEX, 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, COMPLEX
|
||||
* 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
|
||||
*
|
||||
* #in case of COMPLEX 'value' is an array of [real, imag] values
|
||||
* s.send(json.dumps(dict(action='SET', path='/mboards/0/rx_frontends/A/dc_offset/value', type='COMPLEX', value=[0.1, 0.0]))+'\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: STRING, BOOL, INT, DOUBLE, COMPLEX, SENSOR, RANGE");
|
||||
else if (type == "STRING") response.put("result", _tree->access<std::string>(path).get());
|
||||
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 == "COMPLEX")
|
||||
{
|
||||
boost::property_tree::ptree result;
|
||||
boost::property_tree::ptree ptree_i, ptree_q;
|
||||
const std::complex<double> c = _tree->access<std::complex<double> >(path).get();
|
||||
ptree_i.put("", c.real());
|
||||
ptree_q.put("", c.imag());
|
||||
result.push_back(std::make_pair("", ptree_i));
|
||||
result.push_back(std::make_pair("", ptree_q));
|
||||
response.add_child("result", result);
|
||||
}
|
||||
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: STRING, BOOL, INT, DOUBLE, COMPLEX");
|
||||
else if (type == "STRING") _tree->access<std::string>(path).set(request.get<std::string>("value"));
|
||||
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 if (type == "COMPLEX")
|
||||
{
|
||||
boost::property_tree::ptree value = request.get_child("value");
|
||||
double i = value.front().second.get<double>("");
|
||||
double q = value.back().second.get<double>("");
|
||||
_tree->access<std::complex<double> >(path).set(std::complex<double>(i, q));
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -104,6 +104,9 @@ localparam SR_SPI_CORE = 185; // 3
|
||||
#define U2_REG_TIME64_HI_RB_PPS READBACK_BASE + 4*14
|
||||
#define U2_REG_TIME64_LO_RB_PPS READBACK_BASE + 4*15
|
||||
|
||||
#define AUX_LD1_IRQ_BIT (1 << 14)
|
||||
#define AUX_LD2_IRQ_BIT (1 << 15)
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// LMS regs
|
||||
////////////////////////////////////////////////
|
||||
|
||||
1
host/umtrx_version.in.hpp
Normal file
1
host/umtrx_version.in.hpp
Normal file
@@ -0,0 +1 @@
|
||||
#define UMTRX_VERSION "@UMTRX_VERSION@"
|
||||
@@ -32,7 +32,7 @@ extern "C" {
|
||||
//fpga and firmware compatibility numbers
|
||||
#define USRP2_FPGA_COMPAT_NUM 9
|
||||
#define USRP2_FW_COMPAT_NUM 12
|
||||
#define USRP2_FW_VER_MINOR 1
|
||||
#define USRP2_FW_VER_MINOR 3
|
||||
|
||||
//used to differentiate control packets over data port
|
||||
#define USRP2_INVALID_VRT_HEADER 0
|
||||
@@ -127,8 +127,12 @@ typedef enum{
|
||||
|
||||
typedef enum{
|
||||
UMTRX_ZPU_REQUEST_GET_VCTCXO_DAC = 1,
|
||||
UMTRX_ZPU_REQUEST_SET_VCTCXO_DAC = 2
|
||||
/* GPSDO control to be here */
|
||||
UMTRX_ZPU_REQUEST_SET_VCTCXO_DAC = 2,
|
||||
UMTRX_ZPU_REQUEST_SET_GPSDO_DEBUG = 3,
|
||||
UMTRX_ZPU_REQUEST_GET_GPSDO_FREQ = 4,
|
||||
UMTRX_ZPU_REQUEST_GET_GPSDO_FREQ_LPF = 5,
|
||||
UMTRX_ZPU_REQUEST_GET_GPSDO_PPS_SECS = 6,
|
||||
UMTRX_ZPU_REQUEST_SET_GPSDO_PPS_TICKS = 7
|
||||
} umtrx_zpu_action_t;
|
||||
|
||||
typedef struct{
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
# Build and Install the UmTRX utils
|
||||
########################################################################
|
||||
INSTALL(PROGRAMS
|
||||
umtrx_net_burner
|
||||
umtrx_nmea
|
||||
umtrx_gps_coord
|
||||
umtrx_auto_calibration
|
||||
umtrx_firmware
|
||||
DESTINATION bin
|
||||
)
|
||||
|
||||
@@ -18,6 +21,10 @@ add_executable(umtrx_cal_tx_dc_offset umtrx_cal_tx_dc_offset.cpp)
|
||||
target_link_libraries(umtrx_cal_tx_dc_offset ${UMTRX_LIBRARIES})
|
||||
install(TARGETS umtrx_cal_tx_dc_offset DESTINATION bin)
|
||||
|
||||
add_executable(umtrx_cal_tx_iq_balance umtrx_cal_tx_iq_balance.cpp)
|
||||
target_link_libraries(umtrx_cal_tx_iq_balance ${UMTRX_LIBRARIES})
|
||||
install(TARGETS umtrx_cal_tx_iq_balance DESTINATION bin)
|
||||
|
||||
add_executable(umtrx_pa_ctrl umtrx_pa_ctrl.cpp)
|
||||
target_link_libraries(umtrx_pa_ctrl ${UMTRX_LIBRARIES})
|
||||
install(TARGETS umtrx_pa_ctrl DESTINATION bin)
|
||||
|
||||
6
host/utils/collectd/umtrx.conf
Normal file
6
host/utils/collectd/umtrx.conf
Normal file
@@ -0,0 +1,6 @@
|
||||
TypesDB "/usr/share/collectd/umtrx.types.db"
|
||||
|
||||
LoadPlugin exec
|
||||
<Plugin exec>
|
||||
Exec "fairwaves-monitoring" "/usr/share/umtrx/umtrx2collectd.py"
|
||||
</Plugin>
|
||||
1
host/utils/collectd/umtrx.types.db
Normal file
1
host/utils/collectd/umtrx.types.db
Normal file
@@ -0,0 +1 @@
|
||||
sensor value:GAUGE:U:U
|
||||
54
host/utils/collectd/umtrx2collectd.py
Executable file
54
host/utils/collectd/umtrx2collectd.py
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/python -u
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sched, time
|
||||
|
||||
from umtrx_property_tree import umtrx_property_tree
|
||||
from umtrx_vswr import umtrx_vswr
|
||||
|
||||
BOARD_ID = "0"
|
||||
SENSORS_PATH = "/mboards/{id}/sensors".format(id=BOARD_ID)
|
||||
VSWR_CALIBRATION = 0 # = TM10_VSWR_cal
|
||||
|
||||
HOSTNAME = os.environ['COLLECTD_HOSTNAME'] if 'COLLECTD_HOSTNAME' in os.environ else 'localhost'
|
||||
INTERVAL = os.environ['COLLECTD_INTERVAL'] if 'COLLECTD_INTERVAL' in os.environ else '60'
|
||||
|
||||
umtrx = umtrx_property_tree()
|
||||
umtrx.connect()
|
||||
|
||||
# typically this yields: ['tempA', 'tempB', 'voltagePR1', 'voltagePF1', 'voltagePR2', 'voltagePF2', 'voltagezero', 'voltageVin', 'voltageVinPA', 'voltageDCOUT']
|
||||
sensors_list = umtrx.list_path_raw(SENSORS_PATH).get("result", [])
|
||||
|
||||
|
||||
def publish():
|
||||
now = time.time()
|
||||
|
||||
current_sensors = {sensor: umtrx.query_sensor_value(SENSORS_PATH + "/" + sensor) for sensor in sensors_list}
|
||||
|
||||
for channel in ["1", "2"]:
|
||||
vpf_name = "voltagePF" + channel
|
||||
vpr_name = "voltagePR" + channel
|
||||
|
||||
if vpf_name in current_sensors and vpr_name in current_sensors:
|
||||
vswr = umtrx_vswr(float(current_sensors[vpf_name]), float(current_sensors[vpr_name]), VSWR_CALIBRATION)
|
||||
current_sensors["VSWR" + channel] = vswr.vswr()
|
||||
current_sensors["ReturnLoss" + channel] = vswr.return_loss()
|
||||
|
||||
for name, value in current_sensors.items():
|
||||
print "PUTVAL {host}/umtrx-{id}/sensor-{name} interval={interval} {now}:{value}".format(
|
||||
host=HOSTNAME, id=BOARD_ID, name=name.lower(), interval=INTERVAL, now=now, value=value)
|
||||
|
||||
|
||||
s = sched.scheduler(time.time, time.sleep)
|
||||
|
||||
|
||||
def timer_loop():
|
||||
s.enter(float(INTERVAL), 1, timer_loop, ())
|
||||
publish()
|
||||
|
||||
|
||||
timer_loop()
|
||||
s.run()
|
||||
|
||||
umtrx.close()
|
||||
@@ -20,8 +20,8 @@ def plot_csv(file_path):
|
||||
if not i: continue #skip titles
|
||||
tx_lo, icor, qcor, meadured, delta = row
|
||||
tx_lo = float(tx_lo)/1e9
|
||||
icor = int(icor)
|
||||
qcor = int(qcor)
|
||||
icor = float(icor)
|
||||
qcor = float(qcor)
|
||||
freq_vals.append(tx_lo)
|
||||
dc_i_vals.append(icor)
|
||||
dc_q_vals.append(qcor)
|
||||
@@ -34,7 +34,7 @@ def plot_csv(file_path):
|
||||
plt.figure(1)
|
||||
plt.subplot(311)
|
||||
plt.plot(freq_vals, dc_i_vals, freq_vals, dc_q_vals,)
|
||||
plt.ylim(0, 250)
|
||||
#plt.ylim(0, 250)
|
||||
plt.title("Freq (GHz) vs raw IQ corrections")
|
||||
#plt.xlabel('Freq (GHz)')
|
||||
plt.grid(True)
|
||||
@@ -45,7 +45,7 @@ def plot_csv(file_path):
|
||||
dc_i_std = [np.std(dc_i_vals_per_freq[f]) for f in freqs]
|
||||
dc_q_std = [np.std(dc_q_vals_per_freq[f]) for f in freqs]
|
||||
plt.plot(freqs, dc_i_std, freqs, dc_q_std)
|
||||
plt.ylim(0, 150)
|
||||
#plt.ylim(0, 150)
|
||||
plt.title("Freq (GHz) vs stddev IQ corrections")
|
||||
#plt.xlabel('Freq (GHz)')
|
||||
plt.grid(True)
|
||||
@@ -70,7 +70,7 @@ def plot_csv(file_path):
|
||||
dc_i_avg = [np.mean(dc_i_vals_per_freq[f]) for f in freqs]
|
||||
dc_q_avg = [np.mean(dc_q_vals_per_freq[f]) for f in freqs]
|
||||
plt.plot(freqs, dc_i_avg, freqs, dc_q_avg)
|
||||
plt.ylim(0, 250)
|
||||
#plt.ylim(0, 250)
|
||||
plt.title("Freq (GHz) vs averaged IQ corrections")
|
||||
#plt.xlabel('Freq (GHz)')
|
||||
plt.grid(True)
|
||||
|
||||
134
host/utils/umtrx_auto_calibration
Executable file
134
host/utils/umtrx_auto_calibration
Executable file
@@ -0,0 +1,134 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$#" -lt "1" ] ; then
|
||||
echo "Automatic calibration of an UmTRX for a set of given presets (bands)."
|
||||
echo
|
||||
echo "Usage:"
|
||||
echo " umtrx_cal <preset> [<preset>] [<preset>] ..."
|
||||
echo
|
||||
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
|
||||
fi
|
||||
|
||||
presets=$*
|
||||
|
||||
sides="A B"
|
||||
uhd_args="--args=fifo_ctrl_window=0"
|
||||
report=""
|
||||
|
||||
run_cal() {
|
||||
what=$1 ; shift
|
||||
freq_start=$1 ; shift
|
||||
freq_stop=$1 ; shift
|
||||
other_args=$*
|
||||
|
||||
freq_step=$(python -c "print $freq_stop - $freq_start if $freq_stop != $freq_start else 1e3")
|
||||
|
||||
if [ "$what" = "dc" ] ; then
|
||||
cmd="umtrx_cal_tx_dc_offset"
|
||||
elif [ "$what" = "iq" ] ; then
|
||||
cmd="umtrx_cal_tx_iq_balance"
|
||||
else
|
||||
echo "Unknown calibration type \"$what\""
|
||||
return 1
|
||||
fi
|
||||
|
||||
for side in $sides ; do
|
||||
|
||||
echo
|
||||
echo "------------------------------------------------------------------"
|
||||
echo " Calibrating $what from $freq_start to $freq_stop for side $side"
|
||||
echo "------------------------------------------------------------------"
|
||||
echo
|
||||
|
||||
res=255
|
||||
i=0
|
||||
while [ $i -lt 10 -a $res -ne 0 ] ; do
|
||||
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"
|
||||
echo $cmd_full
|
||||
$cmd_full
|
||||
res=$(echo $?)
|
||||
done
|
||||
|
||||
text_res="Calibration type $what side $side from $freq_start to $freq_stop:"
|
||||
if [ $res -ne 0 ] ; then
|
||||
text_res="$text_res FAIL"
|
||||
else
|
||||
text_res="$text_res SUCCESS"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "$text_res"
|
||||
echo
|
||||
|
||||
report="$report$text_res\n"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
run_preset() {
|
||||
preset=$1
|
||||
|
||||
echo
|
||||
echo "===================================================================="
|
||||
echo " Running preset $preset"
|
||||
echo "===================================================================="
|
||||
echo
|
||||
|
||||
case $preset in
|
||||
GSM850)
|
||||
run_cal dc 869e6 894e6
|
||||
# The band completely falls into the 810-930 VCO range
|
||||
run_cal iq 869e6 894e6
|
||||
;;
|
||||
|
||||
GSM900|EGSM900)
|
||||
run_cal dc 925e6 960e6
|
||||
# The band spans VCO ranges 810-930 and 930-11425
|
||||
run_cal iq 925e6 930e6
|
||||
run_cal iq 930.001e6 960e6 --append
|
||||
;;
|
||||
|
||||
GSM1800|DCS1800)
|
||||
run_cal dc 1805e6 1880e6
|
||||
# The band spans VCO ranges 1620-1860 and 1860-2285
|
||||
run_cal iq 1805e6 1860e6
|
||||
run_cal iq 1860.001e6 1880e6 --append
|
||||
;;
|
||||
|
||||
GSM1900|PCS1900)
|
||||
run_cal dc 1930e6 1990e6
|
||||
# The band completely falls into the 1860-2285 VCO range
|
||||
run_cal iq 1930e6 1990e6
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown preset"
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
for preset in $presets ; do
|
||||
run_preset $preset
|
||||
done
|
||||
|
||||
echo
|
||||
echo "===================================================================="
|
||||
echo " Result"
|
||||
echo "===================================================================="
|
||||
echo
|
||||
echo "$report"
|
||||
@@ -1,6 +1,6 @@
|
||||
//
|
||||
// Copyright 2010 Ettus Research LLC
|
||||
// Copyright 2012 Fairwaves LLC
|
||||
// Copyright 2012-1015 Fairwaves, Inc
|
||||
//
|
||||
// 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
|
||||
@@ -17,16 +17,10 @@
|
||||
//
|
||||
|
||||
#include "usrp_cal_utils.hpp"
|
||||
#include <uhd/utils/thread_priority.hpp>
|
||||
#include <uhd/utils/safe_main.hpp>
|
||||
#include <uhd/utils/paths.hpp>
|
||||
#include <uhd/utils/algorithm.hpp>
|
||||
#include <uhd/usrp/multi_usrp.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <boost/random.hpp>
|
||||
#include <iostream>
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
@@ -35,77 +29,271 @@
|
||||
namespace po = boost::program_options;
|
||||
|
||||
/***********************************************************************
|
||||
* Transmit thread
|
||||
* Calibration utility class
|
||||
**********************************************************************/
|
||||
static void tx_thread(uhd::usrp::multi_usrp::sptr usrp, const double tx_wave_freq, const double tx_wave_ampl){
|
||||
uhd::set_thread_priority_safe();
|
||||
class dc_cal_t {
|
||||
public:
|
||||
dc_cal_t(uhd::property<uint8_t> &dc_i_prop, uhd::property<uint8_t> &dc_q_prop,
|
||||
uhd::rx_streamer::sptr rx_stream,
|
||||
const size_t nsamps,
|
||||
double bb_dc_freq,
|
||||
double rx_rate,
|
||||
int verbose,
|
||||
bool debug_raw_data,
|
||||
int init_dc_i=128, int init_dc_q=128);
|
||||
|
||||
//create a transmit streamer
|
||||
uhd::stream_args_t stream_args("fc32"); //complex floats
|
||||
uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args);
|
||||
double init();
|
||||
void run_q(int dc_q);
|
||||
void run_i(int dc_i);
|
||||
void run_iq(int dc_i, int dc_q);
|
||||
|
||||
//setup variables and allocate buffer
|
||||
uhd::tx_metadata_t md;
|
||||
md.has_time_spec = false;
|
||||
std::vector<samp_type> buff(tx_stream->get_max_num_samps()*10);
|
||||
void set_dc_i(double i) {prop_set_check(_dc_i_prop, i);}
|
||||
void set_dc_q(double q) {prop_set_check(_dc_q_prop, q);}
|
||||
void set_dc_i_best() {set_dc_i(_best_dc_i);}
|
||||
void set_dc_q_best() {set_dc_q(_best_dc_q);}
|
||||
|
||||
//values for the wave table lookup
|
||||
size_t index = 0;
|
||||
const double tx_rate = usrp->get_tx_rate();
|
||||
const size_t step = boost::math::iround(wave_table_len * tx_wave_freq/tx_rate);
|
||||
wave_table table(tx_wave_ampl);
|
||||
double get_lowest_offset() const {return _lowest_offset;}
|
||||
int get_best_dc_i() const {return _best_dc_i;}
|
||||
int get_best_dc_q() const {return _best_dc_q;}
|
||||
|
||||
//fill buff and send until interrupted
|
||||
while (not boost::this_thread::interruption_requested()){
|
||||
for (size_t i = 0; i < buff.size(); i++){
|
||||
buff[i] = table(index += step);
|
||||
buff[i] = samp_type(0, 0); //using no-power transmit to cal with
|
||||
protected:
|
||||
double _lowest_offset;
|
||||
int _best_dc_i;
|
||||
int _best_dc_q;
|
||||
uhd::property<uint8_t> &_dc_i_prop;
|
||||
uhd::property<uint8_t> &_dc_q_prop;
|
||||
|
||||
uhd::rx_streamer::sptr _rx_stream;
|
||||
std::vector<samp_type> _buff;
|
||||
const size_t _nsamps;
|
||||
double _bb_dc_freq;
|
||||
double _rx_rate;
|
||||
int _verbose;
|
||||
bool _debug_raw_data;
|
||||
|
||||
void prop_set_check(uhd::property<uint8_t> &prop, uint8_t val);
|
||||
|
||||
double get_dbrms();
|
||||
bool run_x();
|
||||
};
|
||||
|
||||
dc_cal_t::dc_cal_t(uhd::property<uint8_t> &dc_i_prop, uhd::property<uint8_t> &dc_q_prop,
|
||||
uhd::rx_streamer::sptr rx_stream,
|
||||
const size_t nsamps,
|
||||
double bb_dc_freq,
|
||||
double rx_rate,
|
||||
int verbose,
|
||||
bool debug_raw_data,
|
||||
int init_dc_i,
|
||||
int init_dc_q)
|
||||
: _best_dc_i(init_dc_i), _best_dc_q(init_dc_q)
|
||||
, _dc_i_prop(dc_i_prop), _dc_q_prop(dc_q_prop)
|
||||
, _rx_stream(rx_stream)
|
||||
, _nsamps(nsamps)
|
||||
, _bb_dc_freq(bb_dc_freq)
|
||||
, _rx_rate(rx_rate)
|
||||
, _verbose(verbose)
|
||||
, _debug_raw_data(debug_raw_data)
|
||||
{
|
||||
}
|
||||
|
||||
double dc_cal_t::init()
|
||||
{
|
||||
set_dc_i_best();
|
||||
set_dc_q_best();
|
||||
|
||||
//get the DC offset tone size
|
||||
_lowest_offset = get_dbrms();
|
||||
|
||||
if (_verbose) printf("initial_dc_dbrms = %2.0f dB\n", _lowest_offset);
|
||||
if (_debug_raw_data) write_samples_to_file(_buff, "initial_samples.dat");
|
||||
|
||||
return _lowest_offset;
|
||||
}
|
||||
|
||||
void dc_cal_t::run_q(int dc_q)
|
||||
{
|
||||
if (_verbose) printf(" dc_q = %d", dc_q);
|
||||
set_dc_q(dc_q);
|
||||
if (run_x())
|
||||
_best_dc_q = dc_q;
|
||||
}
|
||||
|
||||
void dc_cal_t::run_i(int dc_i)
|
||||
{
|
||||
if (_verbose) printf(" dc_i = %d", dc_i);
|
||||
set_dc_i(dc_i);
|
||||
if (run_x())
|
||||
_best_dc_i = dc_i;
|
||||
}
|
||||
|
||||
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);
|
||||
set_dc_i(dc_i);
|
||||
set_dc_q(dc_q);
|
||||
if (run_x()) {
|
||||
_best_dc_i = dc_i;
|
||||
_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()
|
||||
{
|
||||
//receive some samples
|
||||
capture_samples(_rx_stream, _buff, _nsamps);
|
||||
//calculate dB rms
|
||||
return compute_tone_dbrms(_buff, _bb_dc_freq/_rx_rate);
|
||||
}
|
||||
|
||||
bool dc_cal_t::run_x()
|
||||
{
|
||||
bool better = false;
|
||||
|
||||
//get the DC offset tone size
|
||||
const double dc_dbrms = get_dbrms();
|
||||
if (_verbose) printf(" dc_dbrms = %2.0f dB", dc_dbrms);
|
||||
|
||||
if (dc_dbrms < _lowest_offset){
|
||||
_lowest_offset = dc_dbrms;
|
||||
better = true;
|
||||
if (_verbose) printf(" *");
|
||||
if (_debug_raw_data) write_samples_to_file(_buff, "best_samples.dat");
|
||||
}
|
||||
if (_verbose) printf("\n");
|
||||
|
||||
return better;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Calibration method: Downhill
|
||||
**********************************************************************/
|
||||
static result_t calibrate_downhill(dc_cal_t &dc_cal,
|
||||
double tx_lo,
|
||||
int verbose)
|
||||
{
|
||||
//bounds and results from searching
|
||||
int dc_i_start, dc_i_stop, dc_i_step;
|
||||
int dc_q_start, dc_q_stop, dc_q_step;
|
||||
|
||||
//capture initial uncorrected value
|
||||
const double initial_dc_dbrms = dc_cal.init();
|
||||
|
||||
for (size_t i = 0; i < 6; i++)
|
||||
{
|
||||
if (verbose) printf(" iteration %ld best_i = %d best_q = %d\n", i, dc_cal.get_best_dc_i(), dc_cal.get_best_dc_q());
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
dc_i_start = 0;
|
||||
dc_i_stop = 256;
|
||||
dc_q_start = 0;
|
||||
dc_q_stop = 256;
|
||||
dc_i_step = 10;
|
||||
dc_q_step = 10;
|
||||
break;
|
||||
case 1:
|
||||
dc_i_start = dc_cal.get_best_dc_i() - 15;
|
||||
dc_i_stop = dc_cal.get_best_dc_i() + 15;
|
||||
dc_q_start = dc_cal.get_best_dc_q() - 15;
|
||||
dc_q_stop = dc_cal.get_best_dc_q() + 15;
|
||||
dc_i_step = 1;
|
||||
dc_q_step = 1;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
dc_i_start = dc_cal.get_best_dc_i() - 3;
|
||||
dc_i_stop = dc_cal.get_best_dc_i() + 3;
|
||||
dc_q_start = dc_cal.get_best_dc_q() - 3;
|
||||
dc_q_stop = dc_cal.get_best_dc_q() + 3;
|
||||
dc_i_step = 1;
|
||||
dc_q_step = 1;
|
||||
break;
|
||||
default:
|
||||
dc_i_start = dc_cal.get_best_dc_i() - 1;
|
||||
dc_i_stop = dc_cal.get_best_dc_i() + 1;
|
||||
dc_q_start = dc_cal.get_best_dc_q() - 1;
|
||||
dc_q_stop = dc_cal.get_best_dc_q() + 1;
|
||||
dc_i_step = 1;
|
||||
dc_q_step = 1;
|
||||
break;
|
||||
};
|
||||
|
||||
if (i <= 2) {
|
||||
// Itereate through I and Q sequentially
|
||||
|
||||
if (verbose) printf(" I in [%d; %d] step %d Q = %d\n",
|
||||
dc_i_start, dc_i_stop, dc_i_step, dc_cal.get_best_dc_q());
|
||||
dc_cal.set_dc_q_best();
|
||||
for (int dc_i = dc_i_start; dc_i <= dc_i_stop; dc_i += dc_i_step){
|
||||
dc_cal.run_i(dc_i);
|
||||
}
|
||||
|
||||
if (verbose) printf(" I = %d Q in [%d; %d] step %d\n",
|
||||
dc_cal.get_best_dc_i(), dc_q_start, dc_q_stop, dc_q_step);
|
||||
dc_cal.set_dc_i_best();
|
||||
for (int dc_q = dc_q_start; dc_q <= dc_q_stop; dc_q += dc_q_step){
|
||||
dc_cal.run_q(dc_q);
|
||||
}
|
||||
} else {
|
||||
// Itereate through all combinations of I and Q
|
||||
|
||||
if (verbose) printf(" I in [%d; %d] step %d Q in [%d; %d] step %d\n",
|
||||
dc_i_start, dc_i_stop, dc_i_step,
|
||||
dc_q_start, dc_q_stop, dc_q_step);
|
||||
for (int dc_i = dc_i_start; dc_i <= dc_i_stop; dc_i += dc_i_step) {
|
||||
for (int dc_q = dc_q_start; dc_q <= dc_q_stop; dc_q += dc_q_step) {
|
||||
dc_cal.run_iq(dc_i, dc_q);
|
||||
}
|
||||
}
|
||||
}
|
||||
tx_stream->send(&buff.front(), buff.size(), md);
|
||||
|
||||
}
|
||||
|
||||
//send a mini EOB packet
|
||||
md.end_of_burst = true;
|
||||
tx_stream->send("", 0, md);
|
||||
}
|
||||
// Calibration result
|
||||
result_t result;
|
||||
result.freq = tx_lo;
|
||||
result.real_corr = dc_cal.get_best_dc_i();
|
||||
result.imag_corr = dc_cal.get_best_dc_q();
|
||||
result.best = dc_cal.get_lowest_offset();
|
||||
result.delta = initial_dc_dbrms - result.best;
|
||||
|
||||
/***********************************************************************
|
||||
* Tune RX and TX routine
|
||||
**********************************************************************/
|
||||
static double tune_rx_and_tx(uhd::usrp::multi_usrp::sptr usrp, const double tx_lo_freq, const double rx_offset){
|
||||
//tune the transmitter with no cordic
|
||||
uhd::tune_request_t tx_tune_req(tx_lo_freq);
|
||||
tx_tune_req.dsp_freq_policy = uhd::tune_request_t::POLICY_MANUAL;
|
||||
tx_tune_req.dsp_freq = 0;
|
||||
usrp->set_tx_freq(tx_tune_req);
|
||||
// Output to console
|
||||
std::cout
|
||||
<< result.freq/1e6 << " MHz "
|
||||
<< "I/Q = " << result.real_corr << "/" << result.imag_corr << " "
|
||||
<< "(" << dc_offset_int2double(result.real_corr) << "/"
|
||||
<< dc_offset_int2double(result.imag_corr) << ") "
|
||||
<< "leakage = " << result.best << " dB, "
|
||||
<< "improvement = " << result.delta << " dB\n"
|
||||
<< std::flush
|
||||
;
|
||||
|
||||
//tune the receiver
|
||||
usrp->set_rx_freq(uhd::tune_request_t(usrp->get_tx_freq(), rx_offset));
|
||||
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(10));
|
||||
return usrp->get_tx_freq();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* random uniform int
|
||||
**********************************************************************/
|
||||
static int uniform_rand(const int low, const int high)
|
||||
{
|
||||
static boost::random::mt19937 rng;
|
||||
boost::random::uniform_int_distribution<> dist(low, high);
|
||||
return dist(rng);
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Main
|
||||
**********************************************************************/
|
||||
int UHD_SAFE_MAIN(int argc, char *argv[]){
|
||||
std::string args;
|
||||
std::string args, which, serial;
|
||||
int verbose;
|
||||
int vga1_gain, vga2_gain, rx_gain;
|
||||
double tx_wave_freq, tx_wave_ampl, rx_offset;
|
||||
double freq_start, freq_stop, freq_step;
|
||||
size_t nsamps;
|
||||
size_t ntrials;
|
||||
std::string which;
|
||||
int single_test_i, single_test_q;
|
||||
|
||||
po::options_description desc("Allowed options");
|
||||
desc.add_options()
|
||||
@@ -113,15 +301,22 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
|
||||
("verbose", "enable some verbose")
|
||||
("debug_raw_data", "save raw captured signals to files")
|
||||
("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]")
|
||||
("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]")
|
||||
("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(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_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(.9344e6), "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")
|
||||
("freq_start", po::value<double>(&freq_start), "Frequency start in Hz (do not specify for default)")
|
||||
("freq_stop", po::value<double>(&freq_stop), "Frequency stop in Hz (do not specify for default)")
|
||||
("freq_step", po::value<double>(&freq_step)->default_value(default_freq_step), "Step size for LO sweep in Hz")
|
||||
("nsamps", po::value<size_t>(&nsamps)->default_value(default_num_samps), "Samples per data capture")
|
||||
("ntrials", po::value<size_t>(&ntrials)->default_value(1), "Num trials per TX LO")
|
||||
("which", po::value<std::string>(&which)->default_value("A"), "Which chain A or B?")
|
||||
("single_test", "Perform a single measurement and exit (freq = freq_start, I = single_test_i, Q = single_test_q]")
|
||||
("single_test_i", po::value<int>(&single_test_i)->default_value(128), "Only in the single test mode! I channel calibration value [0 to 255]")
|
||||
("single_test_q", po::value<int>(&single_test_q)->default_value(128), "Only in the single test mode! Q channel calibration value [0 to 255]")
|
||||
("append", "Append measurements to the calibratoin file instead of rewriting [default=overwrite]")
|
||||
;
|
||||
|
||||
po::variables_map vm;
|
||||
@@ -130,31 +325,17 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
|
||||
|
||||
//print the help message
|
||||
if (vm.count("help")){
|
||||
std::cout << boost::format("USRP Generate TX DC Offset Calibration Table %s") % desc << std::endl;
|
||||
std::cout << boost::format("UmTRX Generate TX DC Offset Calibration Table %s") % desc << std::endl;
|
||||
std::cout <<
|
||||
"This application measures leakage between RX and TX on an XCVR daughterboard to self-calibrate.\n"
|
||||
"This application measures leakage between RX and TX using LMS6002D internal RF loopback to self-calibrate.\n"
|
||||
<< std::endl;
|
||||
return ~0;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
//create a usrp device
|
||||
std::cout << std::endl;
|
||||
std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
|
||||
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
|
||||
verbose = vm.count("verbose");
|
||||
|
||||
//set subdev spec
|
||||
usrp->set_rx_subdev_spec(which+":0");
|
||||
usrp->set_tx_subdev_spec(which+":0");
|
||||
|
||||
//set the antennas to cal
|
||||
if (not uhd::has(usrp->get_rx_antennas(), "CAL") or not uhd::has(usrp->get_tx_antennas(), "CAL")){
|
||||
throw std::runtime_error("This board does not have the CAL antenna option, cannot self-calibrate.");
|
||||
}
|
||||
usrp->set_rx_antenna("CAL");
|
||||
usrp->set_tx_antenna("CAL");
|
||||
|
||||
//set optimum defaults
|
||||
set_optimum_defaults(usrp);
|
||||
// Create a USRP device
|
||||
uhd::usrp::multi_usrp::sptr usrp = setup_usrp_for_cal(args, which, serial, vga1_gain, vga2_gain, rx_gain, verbose);
|
||||
|
||||
//create a receive streamer
|
||||
uhd::stream_args_t stream_args("fc32"); //complex floats
|
||||
@@ -164,18 +345,18 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
|
||||
boost::thread_group threads;
|
||||
threads.create_thread(boost::bind(&tx_thread, usrp, tx_wave_freq, tx_wave_ampl));
|
||||
|
||||
//re-usable buffer for samples
|
||||
std::vector<samp_type> buff;
|
||||
|
||||
//store the results here
|
||||
std::vector<result_t> results;
|
||||
|
||||
uhd::property_tree::sptr tree = usrp->get_device()->get_tree();
|
||||
const uhd::fs_path tx_fe_path = "/mboards/0/dboards/"+which+"/tx_frontends/0";
|
||||
uhd::property<uint8_t> &dc_i_prop = usrp->get_device()->get_tree()->access<uint8_t>(tx_fe_path / "lms6002d/tx_dc_i/value");
|
||||
uhd::property<uint8_t> &dc_q_prop = usrp->get_device()->get_tree()->access<uint8_t>(tx_fe_path / "lms6002d/tx_dc_q/value");
|
||||
uhd::property<uint8_t> &dc_i_prop = tree->access<uint8_t>(tx_fe_path / "lms6002d/tx_dc_i/value");
|
||||
uhd::property<uint8_t> &dc_q_prop = tree->access<uint8_t>(tx_fe_path / "lms6002d/tx_dc_q/value");
|
||||
|
||||
if (not vm.count("freq_start")) freq_start = usrp->get_tx_freq_range().start() + 50e6;
|
||||
if (not vm.count("freq_stop")) freq_stop = usrp->get_tx_freq_range().stop() - 50e6;
|
||||
UHD_MSG(status) << boost::format("Calibration frequency type: DC offset") << std::endl;
|
||||
UHD_MSG(status) << boost::format("Calibration frequency range: %d MHz -> %d MHz") % (freq_start/1e6) % (freq_stop/1e6) << std::endl;
|
||||
|
||||
for (double tx_lo_i = freq_start; tx_lo_i <= freq_stop; tx_lo_i += freq_step){
|
||||
const double tx_lo = tune_rx_and_tx(usrp, tx_lo_i, rx_offset);
|
||||
@@ -185,77 +366,37 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
|
||||
const double actual_tx_freq = usrp->get_tx_freq();
|
||||
const double actual_rx_freq = usrp->get_rx_freq();
|
||||
const double bb_dc_freq = actual_tx_freq - actual_rx_freq;
|
||||
if (vm.count("verbose")) printf("actual_rx_rate = %0.2f MHz\n", actual_rx_rate/1e6);
|
||||
if (vm.count("verbose")) printf("actual_tx_freq = %0.2f MHz\n", actual_tx_freq/1e6);
|
||||
if (vm.count("verbose")) printf("actual_rx_freq = %0.2f MHz\n", actual_rx_freq/1e6);
|
||||
if (vm.count("verbose")) printf("bb_dc_freq = %0.2f MHz\n", bb_dc_freq/1e6);
|
||||
if (verbose) printf("actual_rx_rate = %0.2f MHz\n", actual_rx_rate/1e6);
|
||||
if (verbose) printf("actual_tx_freq = %0.2f MHz\n", actual_tx_freq/1e6);
|
||||
if (verbose) printf("actual_rx_freq = %0.2f MHz\n", actual_rx_freq/1e6);
|
||||
if (verbose) printf("bb_dc_freq = %0.2f MHz\n", bb_dc_freq/1e6);
|
||||
|
||||
for (size_t trial_no = 0; trial_no < ntrials; trial_no++)
|
||||
{
|
||||
//bounds and results from searching
|
||||
double lowest_offset;
|
||||
int best_dc_i = 128, best_dc_q = 128;
|
||||
|
||||
//capture initial uncorrected value
|
||||
dc_i_prop.set(best_dc_i);
|
||||
dc_q_prop.set(best_dc_q);
|
||||
capture_samples(rx_stream, buff, nsamps);
|
||||
const double initial_dc_dbrms = compute_tone_dbrms(buff, bb_dc_freq/actual_rx_rate);
|
||||
lowest_offset = initial_dc_dbrms;
|
||||
if (vm.count("verbose")) printf("initial_dc_dbrms = %2.0f dB\n", initial_dc_dbrms);
|
||||
|
||||
if (vm.count("debug_raw_data")) write_samples_to_file(buff, "initial_samples.dat");
|
||||
|
||||
for (int bound = 256; bound >= 8; bound /= 2) //how many bits of precision to care about for the search
|
||||
if (vm.count("single_test"))
|
||||
{
|
||||
if (vm.count("verbose")) printf(" iteration %du\n", bound);
|
||||
dc_cal_t dc_cal(dc_i_prop, dc_q_prop,
|
||||
rx_stream,
|
||||
nsamps,
|
||||
bb_dc_freq,
|
||||
actual_rx_rate,
|
||||
verbose,
|
||||
vm.count("debug_raw_data"),
|
||||
single_test_i, single_test_q);
|
||||
|
||||
bool has_improvement = false;
|
||||
for (int rand_search_no = 0; rand_search_no < bound/4; rand_search_no++) //how many random points to inspect
|
||||
{
|
||||
int dc_i = uniform_rand(std::max(0, best_dc_i-bound/2), std::min(256, best_dc_i+bound/2));
|
||||
int dc_q = uniform_rand(std::max(0, best_dc_q-bound/2), std::min(256, best_dc_q+bound/2));
|
||||
if (vm.count("verbose")) std::cout << "bound " << bound << " dc_i " << dc_i << " dc_q " << dc_q << std::endl;
|
||||
|
||||
dc_i_prop.set(dc_i);
|
||||
dc_q_prop.set(dc_q);
|
||||
|
||||
//receive some samples
|
||||
capture_samples(rx_stream, buff, nsamps);
|
||||
|
||||
const double dc_dbrms = compute_tone_dbrms(buff, bb_dc_freq/actual_rx_rate);
|
||||
if (vm.count("verbose")) printf(" dc_dbrms = %2.0f dB", dc_dbrms);
|
||||
|
||||
if (dc_dbrms < lowest_offset){
|
||||
lowest_offset = dc_dbrms;
|
||||
best_dc_i = dc_i;
|
||||
best_dc_q = dc_q;
|
||||
has_improvement = true;
|
||||
if (vm.count("verbose")) printf(" *");
|
||||
if (vm.count("debug_raw_data")) write_samples_to_file(buff, "best_samples.dat");
|
||||
}
|
||||
if (vm.count("verbose")) printf("\n");
|
||||
}
|
||||
|
||||
// Stop iterating if no imprevement, but do at least 3 iterations
|
||||
if (!has_improvement and bound < 64) break;
|
||||
}
|
||||
|
||||
if (vm.count("verbose")) printf(" best_dc_i = %d best_dc_q = %d", best_dc_i, best_dc_q);
|
||||
if (vm.count("verbose")) printf(" lowest_offset = %2.0f dB delta = %2.0f dB\n", lowest_offset, initial_dc_dbrms - lowest_offset);
|
||||
|
||||
if (lowest_offset < initial_dc_dbrms){ //most likely valid, keep result
|
||||
result_t result;
|
||||
result.freq = tx_lo;
|
||||
result.real_corr = best_dc_i;
|
||||
result.imag_corr = best_dc_q;
|
||||
result.best = lowest_offset;
|
||||
result.delta = initial_dc_dbrms - lowest_offset;
|
||||
results.push_back(result);
|
||||
if (vm.count("verbose")){
|
||||
std::cout << boost::format("TX DC: %f MHz: lowest offset %f dB, corrected %f dB") % (tx_lo/1e6) % result.best % result.delta << std::endl;
|
||||
}
|
||||
else std::cout << "." << std::flush;
|
||||
const double dc_dbrms = dc_cal.init();;
|
||||
printf("I = %d Q = %d ", single_test_i, single_test_q);
|
||||
printf("dc_dbrms = %2.1f dB\n", dc_dbrms);
|
||||
} else {
|
||||
dc_cal_t dc_cal(dc_i_prop, dc_q_prop,
|
||||
rx_stream,
|
||||
nsamps,
|
||||
bb_dc_freq,
|
||||
actual_rx_rate,
|
||||
verbose,
|
||||
vm.count("debug_raw_data"));
|
||||
// Perform normal calibration
|
||||
results.push_back(calibrate_downhill(dc_cal, tx_lo, verbose));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,7 +406,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
|
||||
threads.interrupt_all();
|
||||
threads.join_all();
|
||||
|
||||
store_results(usrp, results, "TX", "tx", "lms_dc", which);
|
||||
if (not vm.count("single_test"))
|
||||
store_results(usrp, results, "tx", "dc", vm.count("append"));
|
||||
|
||||
return 0;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
243
host/utils/umtrx_cal_tx_dc_offset.py
Normal file
243
host/utils/umtrx_cal_tx_dc_offset.py
Normal file
@@ -0,0 +1,243 @@
|
||||
import SoapySDR
|
||||
from SoapySDR import *
|
||||
import math
|
||||
import numpy
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy import signal
|
||||
import random
|
||||
import time
|
||||
import os
|
||||
from optparse import OptionParser
|
||||
|
||||
SAMP_RATE = 13e6/4
|
||||
FREQ_OFFSET = 0.3e6
|
||||
FREQ_START = 700e6
|
||||
FREQ_STOP = 1200e6
|
||||
FREQ_STEP = 7e6
|
||||
FREQ_VALIDATION_STEP = 2e6
|
||||
SIDE = "A"
|
||||
|
||||
import numpy as np
|
||||
def find_nearest(array,value):
|
||||
idx = (np.abs(array-value)).argmin()
|
||||
return array[idx]
|
||||
|
||||
def calcAvgPs(umtrx, rxStream, fftSize = 4096, numFFT = 10, numSkips=2):
|
||||
samps = numpy.array([0]*fftSize, numpy.complex64)
|
||||
avgFFT = numpy.array([0]*fftSize, numpy.complex64)
|
||||
|
||||
while umtrx.readStream(rxStream, [samps], fftSize, 0, 1000).ret != SOAPY_SDR_TIMEOUT: pass #read until timeout
|
||||
umtrx.activateStream(rxStream, SOAPY_SDR_END_BURST, 0, fftSize*(numFFT+numSkips))
|
||||
|
||||
numActualFFTs = 0
|
||||
for i in range(numFFT+numSkips):
|
||||
if umtrx.readStream(rxStream, [samps], fftSize).ret != fftSize:
|
||||
print 'D'
|
||||
return calcAvgPs(umtrx, rxStream, fftSize, numFFT, numSkips)
|
||||
if i < numSkips: continue #skip first for transients
|
||||
samps *= signal.flattop(fftSize)
|
||||
avgFFT += numpy.fft.fft(samps)
|
||||
numActualFFTs += 1
|
||||
avgFFT /= numActualFFTs
|
||||
assert(len(avgFFT) == fftSize)
|
||||
|
||||
ps = 10*numpy.log10(numpy.abs(avgFFT)) - 20*math.log10(fftSize)
|
||||
freqs = numpy.fft.fftfreq(fftSize, 1.0/SAMP_RATE)
|
||||
return ps, freqs
|
||||
|
||||
def measureToneFromPs(ps_freqs, toneFreq, BW=SAMP_RATE/25):
|
||||
ps, freqs = ps_freqs
|
||||
tonePower = None
|
||||
for idx in range(len(ps)):
|
||||
if freqs[idx] > toneFreq-BW/2 and freqs[idx] < toneFreq+BW/2:
|
||||
if tonePower is None: tonePower = ps[idx]
|
||||
tonePower = max(ps[idx], tonePower)
|
||||
return tonePower
|
||||
|
||||
def validateWithMeasurements(umtrx, rxStream, toneFreq, numAvgPts=5):
|
||||
powers = list()
|
||||
for i in range(numAvgPts):
|
||||
ps, freqs = calcAvgPs(umtrx, rxStream)
|
||||
powers.append(measureToneFromPs((ps, freqs), toneFreq))
|
||||
return 10*numpy.log(numpy.average(numpy.exp(numpy.array(powers)/10))), numpy.std(powers)
|
||||
|
||||
def main():
|
||||
umtrx = SoapySDR.Device(dict(driver='uhd', type='umtrx'))
|
||||
|
||||
#frontend map selects side on ch0
|
||||
umtrx.setFrontendMapping(SOAPY_SDR_RX, SIDE+":0")
|
||||
umtrx.setFrontendMapping(SOAPY_SDR_TX, SIDE+":0")
|
||||
|
||||
#print cal file we will use
|
||||
serial = umtrx.getHardwareInfo()['tx0_serial']
|
||||
cal_dest = os.path.join(os.path.expanduser("~"), '.uhd', 'cal', "tx_dc_cal_v0.2_%s.csv"%serial)
|
||||
print 'going to write calibration data to:', cal_dest
|
||||
|
||||
#cal antennas for loopback
|
||||
umtrx.setAntenna(SOAPY_SDR_RX, 0, "CAL")
|
||||
umtrx.setAntenna(SOAPY_SDR_TX, 0, "CAL")
|
||||
|
||||
#set a low sample rate
|
||||
umtrx.setSampleRate(SOAPY_SDR_RX, 0, SAMP_RATE)
|
||||
umtrx.setSampleRate(SOAPY_SDR_TX, 0, SAMP_RATE)
|
||||
|
||||
rxStream = umtrx.setupStream(SOAPY_SDR_RX, "CF32")
|
||||
|
||||
#calibrate out dc offset at select frequencies
|
||||
best_correction_per_freq = dict()
|
||||
best_dc_power_per_freq = dict()
|
||||
initial_dc_power_per_freq = dict()
|
||||
stddev_dc_power_per_freq = dict()
|
||||
average_dc_power_per_freq = dict()
|
||||
|
||||
for freq in numpy.arange(FREQ_START, FREQ_STOP, FREQ_STEP):
|
||||
|
||||
print 'Doing freq:', freq/1e6, 'MHz'
|
||||
|
||||
#tune rx with offset so we can see tx DC
|
||||
umtrx.setFrequency(SOAPY_SDR_TX, 0, freq)
|
||||
umtrx.setFrequency(SOAPY_SDR_RX, 0, freq + FREQ_OFFSET)
|
||||
umtrx.getHardwareTime() #readback so commands are processed
|
||||
|
||||
best_correction = 0.0
|
||||
best_dc_power = None
|
||||
|
||||
#grab values before correction
|
||||
umtrx.setDCOffset(SOAPY_SDR_TX, 0, best_correction)
|
||||
averagePowers, stddevPowers = validateWithMeasurements(umtrx, rxStream, -FREQ_OFFSET)
|
||||
initial_dc_power_per_freq[freq] = averagePowers
|
||||
|
||||
for bound in (0.1, 0.05, 0.01):
|
||||
this_correction = best_correction
|
||||
|
||||
for searchNo in range(50):
|
||||
|
||||
#print 'searchNo',searchNo
|
||||
|
||||
corr_i = random.uniform(this_correction.real-bound, this_correction.real+bound)
|
||||
corr_q = random.uniform(this_correction.imag-bound, this_correction.imag+bound)
|
||||
|
||||
correction = complex(min(max(corr_i, -1), 1), min(max(corr_q, -1), 1))
|
||||
|
||||
umtrx.setDCOffset(SOAPY_SDR_TX, 0, correction)
|
||||
|
||||
ps, freqs = calcAvgPs(umtrx, rxStream)
|
||||
dc_power = measureToneFromPs((ps, freqs), -FREQ_OFFSET)
|
||||
|
||||
if best_dc_power is None or best_dc_power > dc_power:
|
||||
best_dc_power = dc_power
|
||||
best_correction = correction
|
||||
|
||||
print 'best_dc_power', best_dc_power, ' best_correction', best_correction
|
||||
|
||||
#prove that its really the best...
|
||||
umtrx.setDCOffset(SOAPY_SDR_TX, 0, best_correction)
|
||||
averagePowers, stddevPowers = validateWithMeasurements(umtrx, rxStream, -FREQ_OFFSET)
|
||||
print 'averagePowers', averagePowers
|
||||
print 'stddevPowers', stddevPowers
|
||||
|
||||
best_correction_per_freq[freq] = best_correction
|
||||
best_dc_power_per_freq[freq] = best_dc_power
|
||||
stddev_dc_power_per_freq[freq] = stddevPowers
|
||||
average_dc_power_per_freq[freq] = averagePowers
|
||||
|
||||
########################################################################
|
||||
## produce tx cal serial format
|
||||
########################################################################
|
||||
cal_data = open(cal_dest, 'w')
|
||||
|
||||
cal_data.write("name, TX Frontend Calibration\n")
|
||||
cal_data.write("serial, %s\n"%serial)
|
||||
cal_data.write("timestamp, %d\n"%int(time.time()))
|
||||
cal_data.write("version, 0, 1\n")
|
||||
cal_data.write("DATA STARTS HERE\n")
|
||||
cal_data.write("lo_frequency, correction_real, correction_imag, measured, delta\n")
|
||||
for freq in sorted(best_correction_per_freq.keys()):
|
||||
cal_data.write(', '.join(map(str, [
|
||||
freq,
|
||||
best_correction_per_freq[freq].real,
|
||||
best_correction_per_freq[freq].imag,
|
||||
best_dc_power_per_freq[freq],
|
||||
initial_dc_power_per_freq[freq]-best_dc_power_per_freq[freq],
|
||||
])) + '\n')
|
||||
print ('wrote cal data to %s'%cal_dest)
|
||||
|
||||
"""
|
||||
#recollect dc offsets with corrections applied:
|
||||
validation_average_dc_offsets_per_freq = dict()
|
||||
validation_stddev_dc_offsets_per_freq = dict()
|
||||
original_dc_power_per_freq = dict()
|
||||
|
||||
for freq in numpy.arange(FREQ_START, FREQ_STOP, FREQ_VALIDATION_STEP):
|
||||
|
||||
#tune rx with offset so we can see tx DC
|
||||
umtrx.setFrequency(SOAPY_SDR_TX, 0, freq)
|
||||
umtrx.setFrequency(SOAPY_SDR_RX, 0, freq + FREQ_OFFSET)
|
||||
umtrx.getHardwareTime() #readback so commands are processed
|
||||
|
||||
umtrx.setDCOffset(SOAPY_SDR_TX, 0, 0.0)
|
||||
|
||||
#get the original value before corrections
|
||||
averagePowers, stddevPowers = validateWithMeasurements(umtrx, rxStream, -FREQ_OFFSET)
|
||||
original_dc_power_per_freq[freq] = averagePowers
|
||||
|
||||
#pick the correction to use (closest in freq)
|
||||
correction_freq = find_nearest(best_correction_per_freq.keys(), freq)
|
||||
correction = best_correction_per_freq[correction_freq]
|
||||
|
||||
#perform the measurements again
|
||||
umtrx.setDCOffset(SOAPY_SDR_TX, 0, correction)
|
||||
averagePowers, stddevPowers = validateWithMeasurements(umtrx, rxStream, -FREQ_OFFSET)
|
||||
|
||||
validation_average_dc_offsets_per_freq[freq] = averagePowers
|
||||
validation_stddev_dc_offsets_per_freq[freq] = stddevPowers
|
||||
|
||||
umtrx.closeStream(rxStream)
|
||||
|
||||
plt.figure(1)
|
||||
|
||||
plt.subplot(311)
|
||||
freqs = sorted(average_dc_power_per_freq.keys())
|
||||
vals = [average_dc_power_per_freq[f] for f in freqs]
|
||||
cor_data = plt.plot(numpy.array(freqs)/1e6, vals, label='Correction')
|
||||
freqs = sorted(validation_average_dc_offsets_per_freq.keys())
|
||||
vals = [validation_average_dc_offsets_per_freq[f] for f in freqs]
|
||||
val_data = plt.plot(numpy.array(freqs)/1e6, vals, label='Validation')
|
||||
legend = plt.legend(loc='upper right', shadow=True)
|
||||
plt.title("Freq (MHz) vs average power (dB)")
|
||||
plt.grid(True)
|
||||
|
||||
plt.subplot(312)
|
||||
freqs = sorted(stddev_dc_power_per_freq.keys())
|
||||
vals = [stddev_dc_power_per_freq[f] for f in freqs]
|
||||
cor_data = plt.plot(numpy.array(freqs)/1e6, vals, label='Correction')
|
||||
freqs = sorted(validation_stddev_dc_offsets_per_freq.keys())
|
||||
vals = [validation_stddev_dc_offsets_per_freq[f] for f in freqs]
|
||||
val_data = plt.plot(numpy.array(freqs)/1e6, vals, label='Validation')
|
||||
legend = plt.legend(loc='upper right', shadow=True)
|
||||
plt.title("Freq (MHz) vs stddev power (dB)")
|
||||
plt.grid(True)
|
||||
|
||||
plt.subplot(313)
|
||||
freqs = sorted(original_dc_power_per_freq.keys())
|
||||
vals = [abs(original_dc_power_per_freq[f]-validation_average_dc_offsets_per_freq[f]) for f in freqs]
|
||||
plt.plot(numpy.array(freqs)/1e6, vals, label='Correction')
|
||||
plt.title("Freq (MHz) vs correction (dB)")
|
||||
plt.grid(True)
|
||||
|
||||
plt.show()
|
||||
"""
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = OptionParser()
|
||||
parser.add_option("--side", dest="side", default=SIDE, help="A or B [default: %default]")
|
||||
parser.add_option("--freq-start", dest="freq_start", default=FREQ_START, type="float", help="frequency start point in Hz [default: %default]")
|
||||
parser.add_option("--freq-stop", dest="freq_stop", default=FREQ_STOP, type="float", help="frequency stop point in Hz [default: %default]")
|
||||
parser.add_option("--freq-step", dest="freq_step", default=FREQ_STEP, type="float", help="frequency step size in Hz [default: %default]")
|
||||
(options, args) = parser.parse_args()
|
||||
SIDE = options.side
|
||||
FREQ_START = options.freq_start
|
||||
FREQ_STOP = options.freq_stop
|
||||
FREQ_STEP = options.freq_step
|
||||
|
||||
main()
|
||||
187
host/utils/umtrx_cal_tx_iq_balance.cpp
Normal file
187
host/utils/umtrx_cal_tx_iq_balance.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
//
|
||||
// Copyright 2010,2012 Ettus Research LLC
|
||||
// Copyright 2015 Fairwaves, Inc
|
||||
//
|
||||
// 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 "usrp_cal_utils.hpp"
|
||||
#include <uhd/utils/safe_main.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <iostream>
|
||||
#include <complex>
|
||||
#include <ctime>
|
||||
#include <cstdlib>
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
static const size_t num_search_steps = 5;
|
||||
static const size_t num_search_iters = 7;
|
||||
|
||||
/***********************************************************************
|
||||
* Main
|
||||
**********************************************************************/
|
||||
int UHD_SAFE_MAIN(int argc, char *argv[]){
|
||||
std::string args, which, serial;
|
||||
int verbose;
|
||||
int vga1_gain, vga2_gain, rx_gain;
|
||||
double tx_wave_freq, tx_wave_ampl, rx_offset;
|
||||
double freq_start, freq_stop, freq_step;
|
||||
size_t nsamps;
|
||||
|
||||
po::options_description desc("Allowed options");
|
||||
desc.add_options()
|
||||
("help", "help message")
|
||||
("verbose", "enable some verbose")
|
||||
("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]")
|
||||
("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]")
|
||||
("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(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_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")
|
||||
("freq_start", po::value<double>(&freq_start), "Frequency start in Hz (do not specify for default)")
|
||||
("freq_stop", po::value<double>(&freq_stop), "Frequency stop in Hz (do not specify for default)")
|
||||
("freq_step", po::value<double>(&freq_step)->default_value(default_freq_step), "Step size for LO sweep in Hz")
|
||||
("nsamps", po::value<size_t>(&nsamps)->default_value(default_num_samps), "Samples per data capture")
|
||||
("append", "Append measurements to the calibratoin file instead of rewriting [default=overwrite]")
|
||||
;
|
||||
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
|
||||
//print the help message
|
||||
if (vm.count("help")){
|
||||
std::cout << boost::format("UmTRX Generate TX IQ Balance Calibration Table %s") % desc << std::endl;
|
||||
std::cout <<
|
||||
"This application measures leakage between RX and TX using LMS6002D internal RF loopback to self-calibrate.\n"
|
||||
<< std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
verbose = vm.count("verbose");
|
||||
|
||||
// Create a USRP device
|
||||
uhd::usrp::multi_usrp::sptr usrp = setup_usrp_for_cal(args, which, serial, vga1_gain, vga2_gain, rx_gain, verbose);
|
||||
|
||||
//create a receive streamer
|
||||
uhd::stream_args_t stream_args("fc32"); //complex floats
|
||||
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
|
||||
|
||||
//create a transmitter thread
|
||||
boost::thread_group threads;
|
||||
threads.create_thread(boost::bind(&tx_thread, usrp, tx_wave_freq, tx_wave_ampl));
|
||||
|
||||
//re-usable buffer for samples
|
||||
std::vector<samp_type> buff;
|
||||
|
||||
//store the results here
|
||||
std::vector<result_t> results;
|
||||
|
||||
uhd::property_tree::sptr tree = usrp->get_device()->get_tree();
|
||||
const uhd::fs_path tx_fe_path = "/mboards/0/tx_frontends/"+which;
|
||||
uhd::property<std::complex<double> > &iq_prop = tree->access<std::complex<double> >(tx_fe_path / "iq_balance" / "value");
|
||||
|
||||
if (not vm.count("freq_start")) freq_start = usrp->get_tx_freq_range().start() + 50e6;
|
||||
if (not vm.count("freq_stop")) freq_stop = usrp->get_tx_freq_range().stop() - 50e6;
|
||||
UHD_MSG(status) << boost::format("Calibration frequency type: IQ balance") << std::endl;
|
||||
UHD_MSG(status) << boost::format("Calibration frequency range: %d MHz -> %d MHz") % (freq_start/1e6) % (freq_stop/1e6) << std::endl;
|
||||
|
||||
for (double tx_lo_i = freq_start; tx_lo_i <= freq_stop; tx_lo_i += freq_step){
|
||||
const double tx_lo = tune_rx_and_tx(usrp, tx_lo_i, rx_offset);
|
||||
|
||||
//frequency constants for this tune event
|
||||
const double actual_rx_rate = usrp->get_rx_rate();
|
||||
const double actual_tx_freq = usrp->get_tx_freq();
|
||||
const double actual_rx_freq = usrp->get_rx_freq();
|
||||
const double bb_tone_freq = actual_tx_freq + tx_wave_freq - actual_rx_freq;
|
||||
const double bb_imag_freq = actual_tx_freq - tx_wave_freq - actual_rx_freq;
|
||||
|
||||
//capture initial uncorrected value
|
||||
iq_prop.set(0.0);
|
||||
capture_samples(rx_stream, buff, nsamps);
|
||||
const double initial_suppression = compute_tone_dbrms(buff, bb_tone_freq/actual_rx_rate) - compute_tone_dbrms(buff, bb_imag_freq/actual_rx_rate);
|
||||
|
||||
//bounds and results from searching
|
||||
std::complex<double> best_correction;
|
||||
double phase_corr_start = -.3, phase_corr_stop = .3, phase_corr_step;
|
||||
double ampl_corr_start = -.3, ampl_corr_stop = .3, ampl_corr_step;
|
||||
double best_suppression = 0, best_phase_corr = 0, best_ampl_corr = 0;
|
||||
|
||||
for (size_t i = 0; i < num_search_iters; i++){
|
||||
|
||||
phase_corr_step = (phase_corr_stop - phase_corr_start)/(num_search_steps-1);
|
||||
ampl_corr_step = (ampl_corr_stop - ampl_corr_start)/(num_search_steps-1);
|
||||
|
||||
for (double phase_corr = phase_corr_start; phase_corr <= phase_corr_stop + phase_corr_step/2; phase_corr += phase_corr_step){
|
||||
for (double ampl_corr = ampl_corr_start; ampl_corr <= ampl_corr_stop + ampl_corr_step/2; ampl_corr += ampl_corr_step){
|
||||
|
||||
const std::complex<double> correction(ampl_corr, phase_corr);
|
||||
iq_prop.set(correction);
|
||||
|
||||
//receive some samples
|
||||
capture_samples(rx_stream, buff, nsamps);
|
||||
|
||||
const double tone_dbrms = compute_tone_dbrms(buff, bb_tone_freq/actual_rx_rate);
|
||||
const double imag_dbrms = compute_tone_dbrms(buff, bb_imag_freq/actual_rx_rate);
|
||||
const double suppression = tone_dbrms - imag_dbrms;
|
||||
|
||||
if (suppression > best_suppression){
|
||||
best_correction = correction;
|
||||
best_suppression = suppression;
|
||||
best_phase_corr = phase_corr;
|
||||
best_ampl_corr = ampl_corr;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
if (verbose) std::cout << "best_phase_corr " << best_phase_corr << std::endl;
|
||||
if (verbose) std::cout << "best_ampl_corr " << best_ampl_corr << std::endl;
|
||||
if (verbose) std::cout << "best_suppression " << best_suppression << std::endl;
|
||||
|
||||
phase_corr_start = best_phase_corr - phase_corr_step;
|
||||
phase_corr_stop = best_phase_corr + phase_corr_step;
|
||||
ampl_corr_start = best_ampl_corr - ampl_corr_step;
|
||||
ampl_corr_stop = best_ampl_corr + ampl_corr_step;
|
||||
}
|
||||
|
||||
if (best_suppression > 30){ //most likely valid, keep result
|
||||
result_t result;
|
||||
result.freq = tx_lo;
|
||||
result.real_corr = best_correction.real();
|
||||
result.imag_corr = best_correction.imag();
|
||||
result.best = best_suppression;
|
||||
result.delta = best_suppression - initial_suppression;
|
||||
results.push_back(result);
|
||||
if (verbose){
|
||||
std::cout << boost::format("TX IQ: %f MHz: best suppression %f dB, corrected %f dB") % (tx_lo/1e6) % result.best % result.delta << std::endl;
|
||||
}
|
||||
else std::cout << "." << std::flush;
|
||||
}
|
||||
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
//stop the transmitter
|
||||
threads.interrupt_all();
|
||||
threads.join_all();
|
||||
|
||||
store_results(usrp, results, "tx", "iq", vm.count("append"));
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
16
host/utils/umtrx_firmware
Executable file
16
host/utils/umtrx_firmware
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
case $1 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
|
||||
22
host/utils/umtrx_gps_coord
Executable file
22
host/utils/umtrx_gps_coord
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "x$1" = "x-h" -o "x$1" = "x--help" ] ; then
|
||||
echo "Usage:"
|
||||
echo " umtrx_gps_coord [umtrx_ip]"
|
||||
echo
|
||||
echo " umtrx_ip - (optional) UmTRX IP address [default=192.168.10.2]"
|
||||
echo
|
||||
echo "Output:"
|
||||
echo " hh:mm:ss.SSS UTC <lat>N <lon>W <altitude> m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -eq 0 ] ; then
|
||||
UMTRX_ADDR="192.168.10.2"
|
||||
else
|
||||
UMTRX_ADDR=$1
|
||||
fi
|
||||
|
||||
echo . | nc -u $UMTRX_ADDR 49171 | \
|
||||
awk -F, '/\$GPGGA/ {print substr($2,0,3) ":" substr($2,3,2) ":" substr($2,5,2) "." substr($2,8,3) " UTC", (substr($3,0,2) + (substr($3,3) / 60.0)) $4, (substr($5,0,3) + (substr($5,4) / 60.0)) $6, $10 " m"; fflush();}'
|
||||
|
||||
17
host/utils/umtrx_nmea
Executable file
17
host/utils/umtrx_nmea
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "x$1" = "x-h" -o "x$1" = "x--help" ] ; then
|
||||
echo "Usage:"
|
||||
echo " umtrx_nmea [umtrx_ip]"
|
||||
echo
|
||||
echo " umtrx_ip - (optional) UmTRX IP address [default=192.168.10.2]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -eq 0 ] ; then
|
||||
UMTRX_ADDR="192.168.10.2"
|
||||
else
|
||||
UMTRX_ADDR=$1
|
||||
fi
|
||||
|
||||
echo . | nc -u $UMTRX_ADDR 49171
|
||||
@@ -103,10 +103,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
|
||||
for (i = 0; i < 256; i++) {
|
||||
tree->access<uint8_t>(mb_path / "pa_dcdc_r").set(i);
|
||||
if (i == 0) {
|
||||
sleep(1);
|
||||
boost::this_thread::sleep(boost::posix_time::seconds(1));
|
||||
}
|
||||
|
||||
usleep(100 * 1000); // Wait for value to settle
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(100)); // Wait for value to settle
|
||||
|
||||
std::cout << "[" << std::setw(3) << i << "]="
|
||||
<< tree->access<uhd::sensor_value_t>(mb_path / "sensors" / "voltageDCOUT").get().to_pp_string().c_str()
|
||||
@@ -114,10 +114,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
|
||||
}
|
||||
}
|
||||
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")) {
|
||||
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;
|
||||
|
||||
141
host/utils/umtrx_property_tree.py
Normal file
141
host/utils/umtrx_property_tree.py
Normal file
@@ -0,0 +1,141 @@
|
||||
#!/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(bytes(json.dumps(d)+'\n', 'UTF-8'))
|
||||
|
||||
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()
|
||||
|
||||
def query_string_raw(self, path):
|
||||
self._send_request('GET', path, value_type='STRING')
|
||||
return self._recv_response()
|
||||
|
||||
def query_complex_raw(self, path):
|
||||
self._send_request('GET', path, value_type='COMPLEX')
|
||||
return self._recv_response()
|
||||
|
||||
#
|
||||
# Getters (value)
|
||||
#
|
||||
|
||||
def query_bool_value(self, path):
|
||||
res = self.query_bool_raw(path)
|
||||
return res['result']
|
||||
|
||||
def query_int_value(self, path):
|
||||
res = self.query_int_raw(path)
|
||||
return int(res['result'])
|
||||
|
||||
def query_double_value(self, path):
|
||||
res = self.query_double_raw(path)
|
||||
return float(res['result'])
|
||||
|
||||
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']
|
||||
|
||||
def query_string_value(self, path):
|
||||
res = self.query_string_raw(path)
|
||||
return res['result']
|
||||
|
||||
def query_complex_value(self, path):
|
||||
res = self.query_complex_raw(path)
|
||||
i = float(res['result'][0])
|
||||
q = float(res['result'][1])
|
||||
return complex(i, q)
|
||||
|
||||
#
|
||||
# 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()
|
||||
|
||||
def set_string(self, path, val):
|
||||
self._send_request('SET', path, value_type='STRING', value=val)
|
||||
return self._recv_response()
|
||||
|
||||
def set_complex(self, path, val):
|
||||
if type(val) is complex:
|
||||
# Convert complex to an array
|
||||
val = [val.real, val.imag]
|
||||
self._send_request('SET', path, value_type='COMPLEX', 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()
|
||||
20
host/utils/umtrx_query_versions.py
Executable file
20
host/utils/umtrx_query_versions.py
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
##########################
|
||||
### Query sensors
|
||||
##########################
|
||||
|
||||
from umtrx_property_tree import umtrx_property_tree
|
||||
|
||||
s = umtrx_property_tree()
|
||||
s.connect()
|
||||
|
||||
mb_path="/mboards/0"
|
||||
fpga_version = s.query_string_value(mb_path+"/fpga_version")
|
||||
fw_version = s.query_string_value(mb_path+"/fw_version")
|
||||
|
||||
print "FPGA bitstream version: %s" % fpga_version
|
||||
print "ZPU firmware version: %s" % fw_version
|
||||
|
||||
s.close()
|
||||
76
host/utils/umtrx_vswr.py
Normal file
76
host/utils/umtrx_vswr.py
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/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")
|
||||
elif gamma > 1.0:
|
||||
return float("nan")
|
||||
else:
|
||||
return (1+gamma)/(1-gamma)
|
||||
|
||||
def mismatch_loss(self):
|
||||
''' Estimated mismatch loss, dB '''
|
||||
gamma = self._gamma
|
||||
if gamma == 1.0:
|
||||
return float("-inf")
|
||||
elif gamma > 1.0:
|
||||
return float("nan")
|
||||
else:
|
||||
return -10.0 * math.log(1.0-gamma*gamma, 10)
|
||||
|
||||
def pf_rate(self):
|
||||
''' Estimated reflected power rate, % '''
|
||||
gamma = self._gamma
|
||||
if gamma > 1.0:
|
||||
return float("nan")
|
||||
return 1.0 - gamma*gamma
|
||||
|
||||
def pr_rate(self):
|
||||
''' Estimated reflected power rate, % '''
|
||||
gamma = self._gamma
|
||||
if gamma > 1.0:
|
||||
return float("nan")
|
||||
return gamma*gamma
|
||||
@@ -16,10 +16,16 @@
|
||||
//
|
||||
|
||||
#include <uhd/utils/paths.hpp>
|
||||
#include <uhd/utils/thread_priority.hpp>
|
||||
#include <uhd/utils/algorithm.hpp>
|
||||
#include <uhd/utils/msg.hpp>
|
||||
#include <uhd/property_tree.hpp>
|
||||
#include <uhd/usrp/multi_usrp.hpp>
|
||||
#include <uhd/usrp/dboard_eeprom.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <complex>
|
||||
@@ -37,67 +43,9 @@ typedef std::complex<float> samp_type;
|
||||
**********************************************************************/
|
||||
static const double tau = 6.28318531;
|
||||
static const size_t wave_table_len = 8192;
|
||||
static const size_t num_search_steps = 5;
|
||||
static const size_t num_search_iters = 7;
|
||||
static const double default_freq_step = 1e6;
|
||||
static const size_t default_num_samps = 10000;
|
||||
|
||||
/***********************************************************************
|
||||
* Set standard defaults for devices
|
||||
**********************************************************************/
|
||||
static inline void set_optimum_defaults(uhd::usrp::multi_usrp::sptr usrp){
|
||||
uhd::property_tree::sptr tree = usrp->get_device()->get_tree();
|
||||
|
||||
const uhd::fs_path mb_path = "/mboards/0";
|
||||
const std::string mb_name = tree->access<std::string>(mb_path / "name").get();
|
||||
if (mb_name.find("USRP2") != std::string::npos or mb_name.find("N200") != std::string::npos or mb_name.find("N210") != std::string::npos){
|
||||
usrp->set_tx_rate(12.5e6);
|
||||
usrp->set_rx_rate(12.5e6);
|
||||
}
|
||||
else if (mb_name.find("UMTRX") != std::string::npos){
|
||||
usrp->set_tx_rate(13e6/2);
|
||||
usrp->set_tx_bandwidth(5e6);
|
||||
usrp->set_rx_rate(13e6/2);
|
||||
usrp->set_rx_bandwidth(5e6);
|
||||
}
|
||||
else if (mb_name.find("B100") != std::string::npos){
|
||||
usrp->set_tx_rate(4e6);
|
||||
usrp->set_rx_rate(4e6);
|
||||
}
|
||||
else if (mb_name.find("E100") != std::string::npos or mb_name.find("E110") != std::string::npos){
|
||||
usrp->set_tx_rate(4e6);
|
||||
usrp->set_rx_rate(8e6);
|
||||
}
|
||||
else{
|
||||
throw std::runtime_error("self-calibration is not supported for this hardware");
|
||||
}
|
||||
|
||||
const uhd::fs_path tx_fe_path = "/mboards/0/dboards/A/tx_frontends/0";
|
||||
const std::string tx_name = tree->access<std::string>(tx_fe_path / "name").get();
|
||||
if (tx_name.find("WBX") != std::string::npos or tx_name.find("SBX") != std::string::npos){
|
||||
usrp->set_tx_gain(0);
|
||||
}
|
||||
else if (tx_name.find("LMS6002D") != std::string::npos){
|
||||
usrp->set_tx_gain(10);
|
||||
}
|
||||
else{
|
||||
throw std::runtime_error("self-calibration is not supported for this hardware");
|
||||
}
|
||||
|
||||
const uhd::fs_path rx_fe_path = "/mboards/0/dboards/A/tx_frontends/0";
|
||||
const std::string rx_name = tree->access<std::string>(rx_fe_path / "name").get();
|
||||
if (rx_name.find("WBX") != std::string::npos or rx_name.find("SBX") != std::string::npos){
|
||||
usrp->set_rx_gain(25);
|
||||
}
|
||||
else if (rx_name.find("LMS6002D") != std::string::npos){
|
||||
usrp->set_rx_gain(10);
|
||||
}
|
||||
else{
|
||||
throw std::runtime_error("self-calibration is not supported for this hardware");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Sinusoid wave table
|
||||
**********************************************************************/
|
||||
@@ -146,50 +94,91 @@ static inline void write_samples_to_file(
|
||||
outfile.close();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Retrieve d'board serial
|
||||
**********************************************************************/
|
||||
static std::string get_serial(
|
||||
uhd::usrp::multi_usrp::sptr usrp,
|
||||
const std::string &tx_rx
|
||||
){
|
||||
uhd::property_tree::sptr tree = usrp->get_device()->get_tree();
|
||||
// Will work on 1st subdev, top-level must make sure it's the right one
|
||||
uhd::usrp::subdev_spec_t subdev_spec = usrp->get_rx_subdev_spec();
|
||||
const uhd::fs_path db_path = "/mboards/0/dboards/" + subdev_spec[0].db_name + "/" + tx_rx + "_eeprom";
|
||||
const uhd::usrp::dboard_eeprom_t db_eeprom = tree->access<uhd::usrp::dboard_eeprom_t>(db_path).get();
|
||||
return db_eeprom.serial;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Convert integer calibration values to floats
|
||||
**********************************************************************/
|
||||
static double dc_offset_int2double(uint8_t corr)
|
||||
{
|
||||
return (corr-128)/128.0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Store data to file
|
||||
**********************************************************************/
|
||||
static void store_results(
|
||||
uhd::usrp::multi_usrp::sptr usrp,
|
||||
const std::vector<result_t> &results,
|
||||
const std::string &XX,
|
||||
const std::string &xx,
|
||||
const std::string &what,
|
||||
const std::string &which
|
||||
const std::string &rx_tx, // "tx" or "rx"
|
||||
const std::string &what, // Type of test, e.g. "iq"
|
||||
bool append
|
||||
){
|
||||
//extract eeprom serial
|
||||
uhd::property_tree::sptr tree = usrp->get_device()->get_tree();
|
||||
const uhd::fs_path db_path = "/mboards/0/dboards/"+which+"/" + xx + "_eeprom";
|
||||
const uhd::usrp::dboard_eeprom_t db_eeprom = tree->access<uhd::usrp::dboard_eeprom_t>(db_path).get();
|
||||
if (db_eeprom.serial.empty()) throw std::runtime_error(XX + " dboard has empty serial!");
|
||||
std::ofstream cal_data;
|
||||
bool write_header=true;
|
||||
std::string rx_tx_upper = boost::to_upper_copy(rx_tx);
|
||||
std::string serial = get_serial(usrp, rx_tx);
|
||||
|
||||
//make the calibration file path
|
||||
fs::path cal_data_path = fs::path(uhd::get_app_path()) / ".uhd";
|
||||
fs::create_directory(cal_data_path);
|
||||
cal_data_path = cal_data_path / "cal";
|
||||
fs::create_directory(cal_data_path);
|
||||
cal_data_path = cal_data_path / str(boost::format("%s_%s_cal_v0.1_%s.csv") % xx % what % db_eeprom.serial);
|
||||
cal_data_path = cal_data_path / str(boost::format("%s_%s_cal_v0.2_%s.csv") % rx_tx % what % serial);
|
||||
if (fs::exists(cal_data_path)){
|
||||
fs::rename(cal_data_path, cal_data_path.string() + str(boost::format(".%d") % time(NULL)));
|
||||
if (append)
|
||||
write_header = false;
|
||||
else
|
||||
fs::rename(cal_data_path, cal_data_path.string() + str(boost::format(".%d") % time(NULL)));
|
||||
}
|
||||
|
||||
//fill the calibration file
|
||||
std::ofstream cal_data(cal_data_path.string().c_str());
|
||||
cal_data << boost::format("name, %s Frontend Calibration\n") % XX;
|
||||
cal_data << boost::format("serial, %s\n") % db_eeprom.serial;
|
||||
cal_data << boost::format("timestamp, %d\n") % time(NULL);
|
||||
cal_data << boost::format("version, 0, 1\n");
|
||||
cal_data << boost::format("DATA STARTS HERE\n");
|
||||
cal_data << "lo_frequency, correction_real, correction_imag, measured, delta\n";
|
||||
cal_data.open(cal_data_path.string().c_str(), std::ofstream::out | std::ofstream::app);
|
||||
|
||||
if (write_header)
|
||||
{
|
||||
//fill the calibration file
|
||||
cal_data << boost::format("name, %s Frontend Calibration\n") % rx_tx_upper;
|
||||
cal_data << boost::format("serial, %s\n") % serial;
|
||||
cal_data << boost::format("timestamp, %d\n") % time(NULL);
|
||||
cal_data << boost::format("version, 0, 1\n");
|
||||
cal_data << boost::format("DATA STARTS HERE\n");
|
||||
// For DC calibration we also store LMS6002D integer values
|
||||
if (what == "dc")
|
||||
cal_data << "lo_frequency, correction_real, correction_imag, measured, delta, int_i, int_q\n";
|
||||
else
|
||||
cal_data << "lo_frequency, correction_real, correction_imag, measured, delta\n";
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < results.size(); i++){
|
||||
cal_data
|
||||
<< results[i].freq << ", "
|
||||
<< results[i].real_corr << ", "
|
||||
<< results[i].imag_corr << ", "
|
||||
<< results[i].best << ", "
|
||||
<< results[i].delta << "\n"
|
||||
;
|
||||
// Write to file
|
||||
cal_data << results[i].freq;
|
||||
if (what == "dc") {
|
||||
cal_data << ", " << dc_offset_int2double(results[i].real_corr);
|
||||
cal_data << ", " << dc_offset_int2double(results[i].imag_corr);
|
||||
} else {
|
||||
cal_data << ", " << results[i].real_corr;
|
||||
cal_data << ", " << results[i].imag_corr;
|
||||
}
|
||||
cal_data << ", " << results[i].best;
|
||||
cal_data << ", " << results[i].delta;
|
||||
if (what == "dc") {
|
||||
cal_data << ", " << results[i].real_corr;
|
||||
cal_data << ", " << results[i].imag_corr;
|
||||
}
|
||||
cal_data << "\n";
|
||||
}
|
||||
|
||||
std::cout << "wrote cal data to " << cal_data_path << std::endl;
|
||||
@@ -234,3 +223,105 @@ static void capture_samples(
|
||||
throw std::runtime_error("did not get all the samples requested");
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Transmit thread
|
||||
**********************************************************************/
|
||||
static void tx_thread(uhd::usrp::multi_usrp::sptr usrp, const double tx_wave_freq, const double tx_wave_ampl){
|
||||
uhd::set_thread_priority_safe();
|
||||
|
||||
//create a transmit streamer
|
||||
uhd::stream_args_t stream_args("fc32"); //complex floats
|
||||
uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args);
|
||||
|
||||
//setup variables and allocate buffer
|
||||
uhd::tx_metadata_t md;
|
||||
md.has_time_spec = false;
|
||||
std::vector<samp_type> buff(tx_stream->get_max_num_samps()*10);
|
||||
|
||||
//values for the wave table lookup
|
||||
size_t index = 0;
|
||||
const double tx_rate = usrp->get_tx_rate();
|
||||
const size_t step = boost::math::iround(wave_table_len * tx_wave_freq/tx_rate);
|
||||
wave_table table(tx_wave_ampl);
|
||||
|
||||
//fill buff and send until interrupted
|
||||
while (not boost::this_thread::interruption_requested()){
|
||||
for (size_t i = 0; i < buff.size(); i++){
|
||||
buff[i] = table(index += step);
|
||||
}
|
||||
tx_stream->send(&buff.front(), buff.size(), md);
|
||||
}
|
||||
|
||||
//send a mini EOB packet
|
||||
md.end_of_burst = true;
|
||||
tx_stream->send("", 0, md);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Tune RX and TX routine
|
||||
**********************************************************************/
|
||||
static double tune_rx_and_tx(uhd::usrp::multi_usrp::sptr usrp, const double tx_lo_freq, const double rx_offset){
|
||||
//tune the transmitter with no cordic
|
||||
uhd::tune_request_t tx_tune_req(tx_lo_freq);
|
||||
tx_tune_req.dsp_freq_policy = uhd::tune_request_t::POLICY_MANUAL;
|
||||
tx_tune_req.dsp_freq = 0;
|
||||
usrp->set_tx_freq(tx_tune_req);
|
||||
|
||||
//tune the receiver
|
||||
usrp->set_rx_freq(uhd::tune_request_t(usrp->get_tx_freq(), rx_offset));
|
||||
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(10));
|
||||
return usrp->get_tx_freq();
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Setup function
|
||||
**********************************************************************/
|
||||
static uhd::usrp::multi_usrp::sptr setup_usrp_for_cal(const std::string &args, const std::string &which, std::string &serial,
|
||||
int vga1_gain, int vga2_gain, int rx_gain, int verbose)
|
||||
{
|
||||
std::cout << std::endl;
|
||||
std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
|
||||
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
|
||||
|
||||
// Do we have an UmTRX here?
|
||||
uhd::property_tree::sptr tree = usrp->get_device()->get_tree();
|
||||
const uhd::fs_path mb_path = "/mboards/0";
|
||||
const std::string mb_name = tree->access<std::string>(mb_path / "name").get();
|
||||
if (mb_name.find("UMTRX") == std::string::npos){
|
||||
throw std::runtime_error("This utility supports only UmTRX hardware.");
|
||||
}
|
||||
|
||||
//set subdev spec
|
||||
usrp->set_rx_subdev_spec(which+":0");
|
||||
usrp->set_tx_subdev_spec(which+":0");
|
||||
|
||||
UHD_MSG(status) << "Running calibration for " << usrp->get_tx_subdev_name(0) << std::endl;
|
||||
serial = get_serial(usrp, "tx");
|
||||
UHD_MSG(status) << "Daughterboard serial: " << serial << std::endl;
|
||||
|
||||
//set the antennas to cal
|
||||
if (not uhd::has(usrp->get_rx_antennas(), "CAL") or not uhd::has(usrp->get_tx_antennas(), "CAL")){
|
||||
throw std::runtime_error("This board does not have the CAL antenna option, cannot self-calibrate.");
|
||||
}
|
||||
usrp->set_rx_antenna("CAL");
|
||||
usrp->set_tx_antenna("CAL");
|
||||
|
||||
//set optimum defaults
|
||||
// GSM symbol rate * 4
|
||||
usrp->set_tx_rate(13e6/12);
|
||||
usrp->set_rx_rate(13e6/12);
|
||||
// 500kHz LPF
|
||||
usrp->set_tx_bandwidth(1e6);
|
||||
usrp->set_rx_bandwidth(1e6);
|
||||
// Our recommended VGA1/VGA2
|
||||
usrp->set_tx_gain(vga1_gain, "VGA1");
|
||||
usrp->set_tx_gain(vga2_gain, "VGA2");
|
||||
usrp->set_rx_gain(rx_gain);
|
||||
if (verbose) printf("actual Tx VGA1 gain = %.0f dB\n", usrp->get_tx_gain("VGA1"));
|
||||
if (verbose) printf("actual Tx VGA2 gain = %.0f dB\n", usrp->get_tx_gain("VGA2"));
|
||||
if (verbose) printf("actual Rx gain = %.0f dB\n", usrp->get_rx_gain());
|
||||
|
||||
return usrp;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
images/umtrx_txrx_uhd.bin
Executable file → Normal file
BIN
images/umtrx_txrx_uhd.bin
Executable file → Normal file
Binary file not shown.
@@ -87,6 +87,8 @@ INCLUDE_DIRECTORIES(
|
||||
FIND_PROGRAM(LINKER zpu-elf-ld)
|
||||
FIND_PROGRAM(OBJCOPY zpu-elf-objcopy)
|
||||
FIND_PROGRAM(OBJDUMP zpu-elf-objdump)
|
||||
FIND_PROGRAM(ELFSIZE zpu-elf-size)
|
||||
|
||||
FIND_PROGRAM(HEXDUMP hexdump)
|
||||
|
||||
########################################################################
|
||||
@@ -128,6 +130,19 @@ MACRO(GEN_OUTPUTS target)
|
||||
)
|
||||
ENDMACRO(GEN_OUTPUTS)
|
||||
|
||||
MACRO(TEST_STACK_SIZE target minsize)
|
||||
GET_FILENAME_COMPONENT(name ${target} NAME_WE)
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${name}.freestack DEPENDS ${target}
|
||||
COMMAND echo $$\(\(16383 - $$\(${ELFSIZE} ${target} | tail -n1 | { read text data bss dec hex\; echo $$dec\; }\)\)\) > ${name}.freestack
|
||||
COMMAND echo Free stack space for ${target} is `cat ${name}.freestack`
|
||||
COMMAND if [ `cat ${name}.freestack` -le ${minsize} ]\; then echo ERROR Image stack overflow `cat ${name}.freestack` is less than ${minsize}\; exit 1\; fi
|
||||
)
|
||||
#add a top level target for output files
|
||||
ADD_CUSTOM_TARGET(
|
||||
${name}_freestack ALL DEPENDS ${name}.freestack
|
||||
)
|
||||
ENDMACRO(TEST_STACK_SIZE)
|
||||
########################################################################
|
||||
# Add the subdirectories
|
||||
########################################################################
|
||||
|
||||
@@ -111,8 +111,8 @@ static void handle_udp_ctrl_packet(
|
||||
|
||||
//ensure that the protocol versions match
|
||||
if (payload_len >= sizeof(uint32_t) && ctrl_data_in->proto_ver != USRP2_FW_COMPAT_NUM){
|
||||
if (ctrl_data_in->proto_ver) printf("!Error in control packet handler: Expected compatibility number %d, but got %d\n",
|
||||
USRP2_FW_COMPAT_NUM, ctrl_data_in->proto_ver
|
||||
if (ctrl_data_in->proto_ver) printf("Received a control packet with compatibility number %d. Replying with our compatibility number %d.\n",
|
||||
ctrl_data_in->proto_ver, USRP2_FW_COMPAT_NUM
|
||||
);
|
||||
#ifdef UMTRX
|
||||
ctrl_data_in_id = UMTRX_CTRL_ID_REQUEST;
|
||||
@@ -123,7 +123,7 @@ static void handle_udp_ctrl_packet(
|
||||
|
||||
//ensure that this is not a short packet
|
||||
if (payload_len < sizeof(usrp2_ctrl_data_t)){
|
||||
printf("!Error in control packet handler: Expected payload length %d, but got %d\n",
|
||||
printf("Received a short packet: Expected payload length %d, but got %d. Sending USRP2_CTRL_ID_HUH_WHAT\n",
|
||||
(int)sizeof(usrp2_ctrl_data_t), payload_len
|
||||
);
|
||||
ctrl_data_in_id = USRP2_CTRL_ID_HUH_WHAT;
|
||||
@@ -162,10 +162,25 @@ static void handle_udp_ctrl_packet(
|
||||
ctrl_data_out.data.zpu_action.action = ctrl_data_in->data.zpu_action.action;
|
||||
switch (ctrl_data_in->data.zpu_action.action) {
|
||||
case UMTRX_ZPU_REQUEST_GET_VCTCXO_DAC:
|
||||
ctrl_data_out.data.zpu_action.data = (uint32_t)get_vctcxo_dac();
|
||||
ctrl_data_out.data.zpu_action.data = (uint32_t)gpsdo_get_dac();
|
||||
break;
|
||||
case UMTRX_ZPU_REQUEST_SET_VCTCXO_DAC:
|
||||
set_vctcxo_dac((uint16_t)ctrl_data_in->data.zpu_action.data);
|
||||
gpsdo_set_dac((uint16_t)ctrl_data_in->data.zpu_action.data);
|
||||
break;
|
||||
case UMTRX_ZPU_REQUEST_SET_GPSDO_DEBUG:
|
||||
gpsdo_set_debug((bool)ctrl_data_in->data.zpu_action.data);
|
||||
break;
|
||||
case UMTRX_ZPU_REQUEST_GET_GPSDO_FREQ:
|
||||
ctrl_data_out.data.zpu_action.data = gpsdo_get_last_freq();
|
||||
break;
|
||||
case UMTRX_ZPU_REQUEST_GET_GPSDO_FREQ_LPF:
|
||||
ctrl_data_out.data.zpu_action.data = gpsdo_get_lpf_freq();
|
||||
break;
|
||||
case UMTRX_ZPU_REQUEST_GET_GPSDO_PPS_SECS:
|
||||
ctrl_data_out.data.zpu_action.data = gpsdo_get_last_pps_secs();
|
||||
break;
|
||||
case UMTRX_ZPU_REQUEST_SET_GPSDO_PPS_TICKS:
|
||||
ctrl_data_out.data.zpu_action.data = gpsdo_get_last_pps_ticks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -314,12 +329,12 @@ main(void)
|
||||
{
|
||||
u2_init();
|
||||
#ifdef BOOTLOADER
|
||||
putstr("\nUSRP N210 UDP bootloader\n");
|
||||
putstr("\nUmTRX bootloader\n");
|
||||
#else
|
||||
putstr("\nTxRx-UHD-ZPU\n");
|
||||
putstr("\nUmTRX production\n");
|
||||
#endif
|
||||
printf("FPGA compatibility number: %d\n", USRP2_FPGA_COMPAT_NUM);
|
||||
printf("Firmware compatibility number: %d\n", USRP2_FW_COMPAT_NUM);
|
||||
printf("Firmware: %d.%d-%x\n", USRP2_FW_COMPAT_NUM, USRP2_FW_VER_MINOR, GITHASH);
|
||||
|
||||
//init readback for firmware minor version number
|
||||
fw_regs[U2_FW_REG_VER_MINOR] = USRP2_FW_VER_MINOR;
|
||||
@@ -367,6 +382,8 @@ main(void)
|
||||
ethernet_register_link_changed_callback(link_changed_callback);
|
||||
ethernet_init();
|
||||
|
||||
printf("Init is done\n");
|
||||
|
||||
while(true){
|
||||
|
||||
size_t num_lines;
|
||||
|
||||
@@ -47,4 +47,5 @@ SET(COMMON_SRCS
|
||||
${CMAKE_SOURCE_DIR}/lib/banal.c
|
||||
${CMAKE_SOURCE_DIR}/lib/udp_uart.c
|
||||
${CMAKE_SOURCE_DIR}/lib/gpsdo.c
|
||||
${CMAKE_SOURCE_DIR}/lib/time64.c
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2007 Free Software Foundation, Inc.
|
||||
* Copyright 2017 Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
|
||||
*
|
||||
* 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
|
||||
@@ -22,6 +23,8 @@
|
||||
|
||||
static const int EEPROM_PAGESIZE = 16;
|
||||
|
||||
#define EEPROM_TCXO_DAC_OFFSET (0xFF-3)
|
||||
|
||||
bool find_safe_booted_flag(void) {
|
||||
#ifdef NO_EEPROM
|
||||
return 0;
|
||||
@@ -91,3 +94,18 @@ eeprom_read (int i2c_addr, int eeprom_offset, void *buf, int len)
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t
|
||||
eeprom_read_tcxo_dac()
|
||||
{
|
||||
uint16_t val;
|
||||
eeprom_read(USRP2_I2C_ADDR_MBOARD, EEPROM_TCXO_DAC_OFFSET, &val, 2);
|
||||
return (val>>8)+(val<<8);
|
||||
}
|
||||
|
||||
bool
|
||||
eeprom_write_tcxo_dac(uint16_t tcxo_dac)
|
||||
{
|
||||
uint16_t val = (tcxo_dac>>8)+(tcxo_dac<<8);
|
||||
return eeprom_write(USRP2_I2C_ADDR_MBOARD, EEPROM_TCXO_DAC_OFFSET, &val, 2);
|
||||
}
|
||||
|
||||
39
zpu/lib/eeprom.h
Normal file
39
zpu/lib/eeprom.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2017 Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_EEPROM_H
|
||||
#define INCLUDED_EEPROM_H
|
||||
|
||||
/* Safe booted or not? (read from EEPROM) */
|
||||
bool find_safe_booted_flag(void);
|
||||
|
||||
/* Store safe booted flag to EEPROM */
|
||||
void set_safe_booted_flag(bool flag);
|
||||
|
||||
/* Write to EEPROM */
|
||||
bool eeprom_write(int i2c_addr, int eeprom_offset, const void *buf, int len);
|
||||
|
||||
/* Read from EEPROM */
|
||||
bool eeprom_read(int i2c_addr, int eeprom_offset, void *buf, int len);
|
||||
|
||||
/* Read TCXO DAC calibrtion value from EEPROM */
|
||||
uint16_t eeprom_read_tcxo_dac();
|
||||
|
||||
/* Write TCXO DAC calibrtion value to EEPROM */
|
||||
bool eeprom_write_tcxo_dac(uint16_t tcxo_dac);
|
||||
|
||||
#endif /* INCLUDED_EEPROM_H */
|
||||
193
zpu/lib/gpsdo.c
193
zpu/lib/gpsdo.c
@@ -19,6 +19,8 @@
|
||||
#include "u2_init.h"
|
||||
#include "pic.h"
|
||||
#include "spi.h"
|
||||
#include "time64.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
#include "memory_map.h"
|
||||
|
||||
@@ -31,7 +33,7 @@
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* #define GPSDO_DEBUG 1 */
|
||||
static int gpsdo_debug = 0;
|
||||
|
||||
|
||||
/* DAC */
|
||||
@@ -39,13 +41,13 @@
|
||||
|
||||
#define DAC_BITS 12
|
||||
|
||||
uint16_t dac_value; /* Current DAC value */
|
||||
static uint16_t dac_value; /* Current DAC value */
|
||||
|
||||
int
|
||||
set_vctcxo_dac(uint16_t v)
|
||||
static int
|
||||
_set_vctcxo_dac(uint16_t v)
|
||||
{
|
||||
#ifdef GPSDO_DEBUG
|
||||
printf("DAC: %d\n", v);
|
||||
#ifndef BOOTLOADER
|
||||
if (gpsdo_debug) printf("DAC: %d\n", v);
|
||||
#endif
|
||||
dac_value = v;
|
||||
return spi_transact(
|
||||
@@ -55,8 +57,8 @@ set_vctcxo_dac(uint16_t v)
|
||||
);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
get_vctcxo_dac(void)
|
||||
static uint16_t
|
||||
_get_vctcxo_dac(void)
|
||||
{
|
||||
return dac_value;
|
||||
}
|
||||
@@ -73,11 +75,16 @@ get_vctcxo_dac(void)
|
||||
|
||||
#define MAX_INT ((1<<31)-1)
|
||||
|
||||
#define G_PID_PK 64
|
||||
#define G_PID_IK 16
|
||||
#define G_PID_DK 256
|
||||
|
||||
|
||||
typedef struct {
|
||||
/* Loop constants */
|
||||
int16_t Pk;
|
||||
int16_t Ik;
|
||||
int16_t Dk;
|
||||
// int16_t Pk;
|
||||
// int16_t Ik;
|
||||
// int16_t Dk;
|
||||
|
||||
int32_t max_error;
|
||||
int32_t max_sum_error;
|
||||
@@ -86,6 +93,7 @@ typedef struct {
|
||||
int32_t val_prev;
|
||||
|
||||
/* State */
|
||||
int32_t init_val;
|
||||
int32_t err_sum;
|
||||
} pid_data_t;
|
||||
|
||||
@@ -93,18 +101,25 @@ typedef struct {
|
||||
static pid_data_t g_pid;
|
||||
|
||||
static void
|
||||
_gpsdo_pid_init(void)
|
||||
_gpsdo_pid_init(int32_t init_val)
|
||||
{
|
||||
/* Configure loop */
|
||||
g_pid.Pk = 64;
|
||||
g_pid.Ik = 16;
|
||||
g_pid.Dk = 256; /* Seems high but we LPF PID input so d is dampened */
|
||||
//g_pid.Pk = 64;
|
||||
//g_pid.Ik = 16;
|
||||
//g_pid.Dk = 256; /* Seems high but we LPF PID input so d is dampened */
|
||||
|
||||
/* Reset state */
|
||||
g_pid.val_prev = PID_TARGET;
|
||||
g_pid.init_val = init_val;
|
||||
g_pid.err_sum = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_gpsdo_pid_first_step(int32_t val)
|
||||
{
|
||||
g_pid.val_prev = val;
|
||||
}
|
||||
|
||||
static void
|
||||
_gpsdo_pid_step(int32_t val)
|
||||
{
|
||||
@@ -121,14 +136,14 @@ _gpsdo_pid_step(int32_t val)
|
||||
error = -PID_MAX_ERR;
|
||||
|
||||
/* Compute P term */
|
||||
p_term = error * g_pid.Pk;
|
||||
p_term = error * G_PID_PK;
|
||||
|
||||
/* Compute I term */
|
||||
g_pid.err_sum += error;
|
||||
i_term = g_pid.err_sum * g_pid.Ik;
|
||||
i_term = g_pid.err_sum * G_PID_IK;
|
||||
|
||||
/* Compute D term */
|
||||
d_term = (g_pid.val_prev - val) * g_pid.Dk;
|
||||
d_term = (g_pid.val_prev - val) * G_PID_DK;
|
||||
g_pid.val_prev = val;
|
||||
|
||||
/* Final value */
|
||||
@@ -139,8 +154,12 @@ _gpsdo_pid_step(int32_t val)
|
||||
else if (tot < -PID_MAX_DEV)
|
||||
tot = -PID_MAX_DEV;
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
if (gpsdo_debug) printf("GPSDO: DAC = %d %d (P=%d, I=%d, D=%d)>>%d limit +-%d\n",
|
||||
g_pid.init_val, tot, p_term, i_term, d_term, PID_SCALE_SHIFT, PID_MAX_DEV);
|
||||
#endif
|
||||
/* Update DAC */
|
||||
set_vctcxo_dac( PID_MID_VAL + tot );
|
||||
_set_vctcxo_dac( g_pid.init_val + tot );
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +167,23 @@ _gpsdo_pid_step(int32_t val)
|
||||
/* Driver */
|
||||
/* ------ */
|
||||
|
||||
static int32_t g_val_lpf = PID_TARGET;
|
||||
/* Extra bits of precision for g_val_lpf */
|
||||
#define VAL_LPF_PRECISION 3
|
||||
#define VAL_LPF_INIT_VALUE (PID_TARGET<<VAL_LPF_PRECISION)
|
||||
#define SKIP_ON_FIRST_RUN_VAL 2
|
||||
|
||||
/* Value > 0 indicates first run. Value itself is a ocunter how many IRQs
|
||||
* to skip before starting PID regulation. Value of 2 is selected, because
|
||||
* (1) the first tick will produce incorrect frequency counter because frequency
|
||||
* correction occue in the middle of counting and (2) we need one valid reading
|
||||
* to initialize g_pid.val_prev used for calculation of the D component. Previously
|
||||
* we always initialized g_pid.val_prev to a value of the ideal target value
|
||||
* which resulted in excessive oscillations. */
|
||||
static int8_t g_skip_on_first_run = SKIP_ON_FIRST_RUN_VAL;
|
||||
static uint32_t g_val_lpf = VAL_LPF_INIT_VALUE;
|
||||
static uint32_t g_prev_secs = 0;
|
||||
static uint32_t g_prev_ticks = 0;
|
||||
static uint32_t g_last_calc_freq = 0; /* Last calculated VCTCXO frequency */
|
||||
|
||||
static void
|
||||
_gpsdo_irq_handler(unsigned irq)
|
||||
@@ -156,43 +191,125 @@ _gpsdo_irq_handler(unsigned irq)
|
||||
if (gpsdo_regs->csr & GPSDO_CSR_RDY)
|
||||
{
|
||||
/* Counter value */
|
||||
int32_t val = gpsdo_regs->cnt;
|
||||
|
||||
#ifdef GPSDO_DEBUG
|
||||
printf("GPSDO Count: %d\n", val);
|
||||
#endif
|
||||
uint32_t val = gpsdo_regs->cnt;
|
||||
/* Read the current wall time */
|
||||
uint32_t cur_secs, cur_ticks;
|
||||
time64_read(&cur_secs, &cur_ticks);
|
||||
|
||||
/* Next request */
|
||||
gpsdo_regs->csr = GPSDO_CSR_REQ;
|
||||
|
||||
/* TODO:: Save the current wall time to be able check
|
||||
time passed since the last lock later. This is useful
|
||||
e.g. to check whether we still have a GPS lock.*/
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
if (gpsdo_debug) printf("GPSDO: Counter = %u @ %u sec %u ticks\n", val, cur_secs, cur_ticks);
|
||||
#endif
|
||||
/* Check validity of value */
|
||||
if (abs(val - PID_TARGET) < 100000)
|
||||
{
|
||||
/* LPF the value */
|
||||
g_val_lpf = (g_val_lpf * 7 + val + 4) >> 3;
|
||||
|
||||
/* Update PID */
|
||||
_gpsdo_pid_step(g_val_lpf);
|
||||
/* Save calculated frequency */
|
||||
g_last_calc_freq = val;
|
||||
|
||||
if (g_skip_on_first_run > 0) {
|
||||
g_skip_on_first_run--;
|
||||
g_val_lpf = val<<VAL_LPF_PRECISION;
|
||||
#ifndef BOOTLOADER
|
||||
printf("GPSDO init: Filtered counter = %u + %u/8\n",
|
||||
(g_val_lpf>>VAL_LPF_PRECISION), (g_val_lpf&((1<<VAL_LPF_PRECISION)-1)));
|
||||
#endif
|
||||
_gpsdo_pid_first_step(val);
|
||||
} else {
|
||||
/* LPF the value */
|
||||
/* Integer overlow warning! */
|
||||
/* This works for val ~= 52M, but don't try to use it with much larger values - it will overflow */
|
||||
g_val_lpf = (g_val_lpf * 7 + (val<<VAL_LPF_PRECISION) + 4) >> 3;
|
||||
#ifndef BOOTLOADER
|
||||
if (gpsdo_debug) printf("GPSDO: Filtered counter = %u + %u/8\n",
|
||||
(g_val_lpf>>VAL_LPF_PRECISION), (g_val_lpf&((1<<VAL_LPF_PRECISION)-1)));
|
||||
#endif
|
||||
/* Update PID */
|
||||
_gpsdo_pid_step(g_val_lpf>>VAL_LPF_PRECISION);
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the current wall time */
|
||||
g_prev_secs = cur_secs;
|
||||
g_prev_ticks = cur_ticks;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gpsdo_init(void)
|
||||
{
|
||||
/* Set the DAC to mid value */
|
||||
set_vctcxo_dac( PID_MID_VAL );
|
||||
uint16_t tcxo_dac = eeprom_read_tcxo_dac();
|
||||
printf("TCXO DAC: %d ", tcxo_dac);
|
||||
if (tcxo_dac == 0xFFFF) {
|
||||
tcxo_dac = PID_MID_VAL;
|
||||
#ifndef BOOTLOADER
|
||||
printf("(hardcoded init)\n");
|
||||
#endif
|
||||
} else {
|
||||
#ifndef BOOTLOADER
|
||||
printf("(init from EEPROM)\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Reset GPSDO */
|
||||
g_skip_on_first_run = SKIP_ON_FIRST_RUN_VAL;
|
||||
|
||||
/* Set last saved freq to an invalid value */
|
||||
g_last_calc_freq = 0;
|
||||
|
||||
/* Set the DAC to initial value */
|
||||
_set_vctcxo_dac( tcxo_dac );
|
||||
|
||||
/* Register IRQ handler */
|
||||
pic_register_handler(IRQ_GPSDO, _gpsdo_irq_handler);
|
||||
|
||||
/* Init PID */
|
||||
_gpsdo_pid_init();
|
||||
_gpsdo_pid_init(tcxo_dac);
|
||||
|
||||
/* Start request */
|
||||
gpsdo_regs->csr = GPSDO_CSR_REQ;
|
||||
|
||||
/* Save the current wall time.
|
||||
* We can use it to estimate time to lock */
|
||||
time64_read(&g_prev_secs, &g_prev_ticks);
|
||||
}
|
||||
|
||||
void gpsdo_set_debug(int level)
|
||||
{
|
||||
gpsdo_debug = level;
|
||||
}
|
||||
|
||||
void gpsdo_set_dac(uint16_t v)
|
||||
{
|
||||
/* Reset PID */
|
||||
_gpsdo_pid_init(v);
|
||||
/* Reset GPSDO */
|
||||
g_skip_on_first_run = SKIP_ON_FIRST_RUN_VAL;
|
||||
/* Set the DAC value */
|
||||
_set_vctcxo_dac(v);
|
||||
}
|
||||
|
||||
uint16_t gpsdo_get_dac(void)
|
||||
{
|
||||
return _get_vctcxo_dac();
|
||||
}
|
||||
|
||||
uint32_t gpsdo_get_last_freq(void)
|
||||
{
|
||||
return g_last_calc_freq;
|
||||
}
|
||||
|
||||
uint32_t gpsdo_get_lpf_freq(void)
|
||||
{
|
||||
return g_val_lpf;
|
||||
}
|
||||
|
||||
uint32_t gpsdo_get_last_pps_secs(void)
|
||||
{
|
||||
return g_prev_secs;
|
||||
}
|
||||
|
||||
uint32_t gpsdo_get_last_pps_ticks(void)
|
||||
{
|
||||
return g_prev_ticks;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2012 Sylvain Munaut <tnt@246tNt.com>
|
||||
* Copyright 2017 Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
|
||||
*
|
||||
* 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
|
||||
@@ -21,10 +22,25 @@
|
||||
|
||||
void gpsdo_init(void);
|
||||
|
||||
/* Enable/disable GPSDO debug printing */
|
||||
void gpsdo_set_debug(int level);
|
||||
|
||||
/* Set value of the VCTCXO DAC */
|
||||
int set_vctcxo_dac(uint16_t v);
|
||||
void gpsdo_set_dac(uint16_t v);
|
||||
|
||||
/* Get the current VCTCXO DAC value */
|
||||
uint16_t get_vctcxo_dac(void);
|
||||
uint16_t gpsdo_get_dac(void);
|
||||
|
||||
/* Get the last calculated VCTCXO frequency */
|
||||
uint32_t gpsdo_get_last_freq(void);
|
||||
|
||||
/* Get the last alpha/8 filtered VCTCXO frequency (29.3 fixed point) */
|
||||
uint32_t gpsdo_get_lpf_freq(void);
|
||||
|
||||
/* Get time (seconds part) of the last PPS pulse */
|
||||
uint32_t gpsdo_get_last_pps_secs(void);
|
||||
|
||||
/* Get time (ticks part) of the last PPS pulse */
|
||||
uint32_t gpsdo_get_last_pps_ticks(void);
|
||||
|
||||
#endif /* INCLUDED_GPSDO_H */
|
||||
|
||||
@@ -38,6 +38,13 @@ static uint16_t prescaler_values[MAX_WB_DIV+1] = {
|
||||
|
||||
#define WATCHDOG 50000
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
static void _print_wderr(const char* f)
|
||||
{
|
||||
printf("i2c_%s WATCHDOG failed!", f);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
i2c_init(void)
|
||||
{
|
||||
@@ -63,10 +70,11 @@ wait_for_xfer(void)
|
||||
unsigned i = WATCHDOG;
|
||||
while ((i != 0) && (i2c_regs->cmd_status & I2C_ST_TIP)) // wait for xfer to complete
|
||||
--i;
|
||||
|
||||
#ifndef BOOTLOADER
|
||||
if (i == 0) {
|
||||
puts("wait_for_xfer WATCHDOG failed!");
|
||||
_print_wderr("xfer");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@@ -90,7 +98,9 @@ i2c_read (unsigned char i2c_addr, unsigned char *buf, unsigned int len)
|
||||
while ((i != 0) && (i2c_regs->cmd_status & I2C_ST_BUSY))
|
||||
--i;
|
||||
if (i == 0) {
|
||||
puts("i2c_read WATCHDOG failed!");
|
||||
#ifndef BOOTLOADER
|
||||
_print_wderr("read");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -120,7 +130,9 @@ i2c_write(unsigned char i2c_addr, const unsigned char *buf, unsigned int len)
|
||||
while ((i != 0) && (i2c_regs->cmd_status & I2C_ST_BUSY))
|
||||
--i;
|
||||
if (i == 0) {
|
||||
puts("i2c_write WATCHDOG failed!");
|
||||
#ifndef BOOTLOADER
|
||||
_print_wderr("write");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
93
zpu/lib/time64.c
Normal file
93
zpu/lib/time64.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2017 Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
|
||||
*
|
||||
* 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 "memory_map.h"
|
||||
|
||||
/* printf headers */
|
||||
//#include "nonstdio.h"
|
||||
|
||||
/* standard headers */
|
||||
#include <stddef.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#define UINT32_MAX UINT_MAX
|
||||
|
||||
void
|
||||
time64_read(uint32_t *secs, uint32_t *ticks)
|
||||
{
|
||||
uint32_t cur_secs, cur_secs2;
|
||||
|
||||
cur_secs = readback_mux->time64_secs_rb;
|
||||
*ticks = readback_mux->time64_ticks_rb;
|
||||
cur_secs2 = readback_mux->time64_secs_rb;
|
||||
|
||||
/* Check for seconds wrap */
|
||||
if (cur_secs2 != cur_secs) {
|
||||
/* Decide which seconds reading is correct.
|
||||
* Here we assume that we're reading fast and time between
|
||||
* two readings is negligible compared to a 32-bit counter
|
||||
* wrap time.
|
||||
*/
|
||||
if (*ticks < UINT32_MAX/2) {
|
||||
/* First half of the time - wrap has just happened */
|
||||
*secs = cur_secs2;
|
||||
} else {
|
||||
/* Second half - wrap has not happened yet */
|
||||
*secs = cur_secs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
time64_compare(uint32_t secs1, uint32_t ticks1,
|
||||
uint32_t secs2, uint32_t ticks2)
|
||||
{
|
||||
if (secs1 == secs2) {
|
||||
if (ticks1 < ticks2) {
|
||||
return -1;
|
||||
} else if (ticks1 == ticks2) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else if (secs1 < secs2) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
time64_add_ticks(uint32_t *secs, uint32_t *ticks,
|
||||
uint32_t ticks2)
|
||||
{
|
||||
if (UINT32_MAX - *ticks > ticks2) {
|
||||
*secs += 1;
|
||||
}
|
||||
*ticks += ticks2;
|
||||
}
|
||||
|
||||
bool
|
||||
time64_is_elapsed(uint32_t secs1, uint32_t ticks1,
|
||||
uint32_t secs2, uint32_t ticks2,
|
||||
uint32_t ticks_elapsed)
|
||||
{
|
||||
time64_add_ticks(&secs1, &ticks1, ticks_elapsed);
|
||||
return time64_compare(secs1, ticks1, secs2, ticks2) >= 0;
|
||||
}
|
||||
42
zpu/lib/time64.h
Normal file
42
zpu/lib/time64.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2017 Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Operations with time64 counters handling wrapping safely */
|
||||
|
||||
/* Read counters */
|
||||
void
|
||||
time64_read(uint32_t *secs, uint32_t *ticks);
|
||||
|
||||
/* Compare two counters.
|
||||
* Return -1 if conter 1 is less than counter 2.
|
||||
* Return 0 if conter 1 is equal counter 2.
|
||||
* Return 1 if conter 1 is larger than counter 2.
|
||||
*/
|
||||
int
|
||||
time64_compare(uint32_t secs1, uint32_t ticks1,
|
||||
uint32_t secs2, uint32_t ticks2);
|
||||
|
||||
/* Add ticks to a counter */
|
||||
void
|
||||
time64_add_ticks(uint32_t *secs, uint32_t *ticks,
|
||||
uint32_t ticks2);
|
||||
|
||||
/* Is a given amount of ticks elapsed? */
|
||||
bool
|
||||
time64_is_elapsed(uint32_t secs1, uint32_t ticks1,
|
||||
uint32_t secs2, uint32_t ticks2,
|
||||
uint32_t ticks_elapsed);
|
||||
@@ -25,24 +25,35 @@
|
||||
* Constants
|
||||
**********************************************************************/
|
||||
#define MAX_NUM_UARTS 4
|
||||
#ifndef NUM_UARTS_STORAGE
|
||||
#error missing definition for NUM_UARTS_STORAGE
|
||||
#endif
|
||||
#ifndef UDP_UART_MASK
|
||||
#error missing definition for UDP_UART_MASK enable mask
|
||||
#endif
|
||||
static const size_t num_idle_cyc_b4_flush = 11; //small but lucky number
|
||||
static const size_t num_idle_cyc_b4_flush = 250; //small but lucky number
|
||||
|
||||
/***********************************************************************
|
||||
* Globals
|
||||
**********************************************************************/
|
||||
static uint16_t _base_port;
|
||||
static int8_t _storage_map[MAX_NUM_UARTS];
|
||||
|
||||
#ifdef BOOTLOADER
|
||||
#define UART_BUF_SZ 16
|
||||
#else
|
||||
#define UART_BUF_SZ 128
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct{
|
||||
struct socket_address dst;
|
||||
_AL4 uint8_t buf[256];
|
||||
_AL4 uint8_t buf[UART_BUF_SZ];
|
||||
size_t len; //length of buffer
|
||||
size_t cyc; //idle cycle count
|
||||
} udp_uart_state_t;
|
||||
|
||||
static udp_uart_state_t _states[MAX_NUM_UARTS];
|
||||
static udp_uart_state_t _states[NUM_UARTS_STORAGE];
|
||||
|
||||
/***********************************************************************
|
||||
* UDP handler for UARTs
|
||||
@@ -55,14 +66,20 @@ static void handle_uart_data_packet(
|
||||
if (payload == NULL){
|
||||
const size_t which = src.port-_base_port;
|
||||
if (which >= MAX_NUM_UARTS) return;
|
||||
_states[which].dst.port = 0;
|
||||
int8_t idx = _storage_map[which];
|
||||
if (idx >= NUM_UARTS_STORAGE || idx < 0) return;
|
||||
|
||||
_states[idx].dst.port = 0;
|
||||
}
|
||||
|
||||
//handle a regular blocking UART write
|
||||
else{
|
||||
const size_t which = dst.port-_base_port;
|
||||
if (which >= MAX_NUM_UARTS) return;
|
||||
_states[which].dst = src;
|
||||
int8_t idx = _storage_map[which];
|
||||
if (idx >= NUM_UARTS_STORAGE || idx < 0) return;
|
||||
|
||||
_states[idx].dst = src;
|
||||
for (size_t i = 0; i < payload_len; i++){
|
||||
hal_uart_putc((hal_uart_name_t)which, (int)payload[i]);
|
||||
}
|
||||
@@ -74,11 +91,20 @@ static void handle_uart_data_packet(
|
||||
**********************************************************************/
|
||||
void udp_uart_init(const uint16_t base_port){
|
||||
_base_port = base_port;
|
||||
for(size_t i = 0; i < MAX_NUM_UARTS; i++){
|
||||
_states[i].dst.port = 0; //reset to null port
|
||||
_states[i].len = 0;
|
||||
_states[i].cyc = 0;
|
||||
for(size_t i = 0, k = 0; (i < MAX_NUM_UARTS) && (k < NUM_UARTS_STORAGE); i++){
|
||||
if (((UDP_UART_MASK) & (1 << i)) == 0) {
|
||||
_storage_map[i] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
_storage_map[i] = k;
|
||||
|
||||
_states[k].dst.port = 0; //reset to null port
|
||||
_states[k].len = 0;
|
||||
_states[k].cyc = 0;
|
||||
register_udp_listener(_base_port+i, handle_uart_data_packet);
|
||||
|
||||
++k;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,10 +113,11 @@ void udp_uart_init(const uint16_t base_port){
|
||||
**********************************************************************/
|
||||
void udp_uart_poll(void){
|
||||
for (size_t i = 0; i < MAX_NUM_UARTS; i++){
|
||||
if (((UDP_UART_MASK) & (1 << i)) == 0) continue;
|
||||
int8_t idx = _storage_map[i];
|
||||
if (idx >= NUM_UARTS_STORAGE || idx < 0) continue;
|
||||
|
||||
bool newline = false;
|
||||
udp_uart_state_t *state = &_states[i];
|
||||
udp_uart_state_t *state = &_states[idx];
|
||||
|
||||
//read all characters we can without blocking
|
||||
for (size_t j = state->len; j < sizeof(_states[0].buf); j++){
|
||||
|
||||
@@ -19,28 +19,33 @@
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/lib/CMakeLists.txt)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
ADD_DEFINITIONS(-DUSRP2P)
|
||||
ADD_DEFINITIONS(-DUDP_UART_MASK=2) #GPS=UART1 streaming enabled
|
||||
SET(MIN_STACK 1300)
|
||||
|
||||
ADD_LIBRARY(libumtrxfw STATIC
|
||||
ADD_DEFINITIONS(-DUSRP2P)
|
||||
ADD_DEFINITIONS(-DUDP_UART_MASK=2 -DNUM_UARTS_STORAGE=1) #GPS=UART1 streaming enabled
|
||||
|
||||
SET(libumtrxfw_FILES
|
||||
${COMMON_SRCS}
|
||||
spif.c
|
||||
spi_flash.c
|
||||
spi_flash_read.c
|
||||
bootloader_utils.c
|
||||
ethernet.c
|
||||
xilinx_s3_icap.c
|
||||
xilinx_s6_icap.c
|
||||
udp_fw_update.c
|
||||
u2p_init.c
|
||||
${CMAKE_SOURCE_DIR}/umtrx/spif.c
|
||||
${CMAKE_SOURCE_DIR}/umtrx/spi_flash.c
|
||||
${CMAKE_SOURCE_DIR}/umtrx/spi_flash_read.c
|
||||
${CMAKE_SOURCE_DIR}/umtrx/bootloader_utils.c
|
||||
${CMAKE_SOURCE_DIR}/umtrx/ethernet.c
|
||||
${CMAKE_SOURCE_DIR}/umtrx/xilinx_s3_icap.c
|
||||
${CMAKE_SOURCE_DIR}/umtrx/xilinx_s6_icap.c
|
||||
${CMAKE_SOURCE_DIR}/umtrx/udp_fw_update.c
|
||||
${CMAKE_SOURCE_DIR}/umtrx/u2p_init.c
|
||||
)
|
||||
|
||||
# ADD_LIBRARY(libumtrxfw STATIC ${libumtrxfw_FILES})
|
||||
|
||||
ADD_SUBDIRECTORY(bootloader)
|
||||
|
||||
########################################################################
|
||||
SET(GEN_OUTPUTS_BIN_SIZE 0x3fff)
|
||||
|
||||
ADD_EXECUTABLE(umtrx_txrx_uhd.elf ${CMAKE_SOURCE_DIR}/apps/txrx_uhd.c)
|
||||
TARGET_LINK_LIBRARIES(umtrx_txrx_uhd.elf libumtrxfw)
|
||||
ADD_EXECUTABLE(umtrx_txrx_uhd.elf ${CMAKE_SOURCE_DIR}/apps/txrx_uhd.c ${libumtrxfw_FILES})
|
||||
# TARGET_LINK_LIBRARIES(umtrx_txrx_uhd.elf libumtrxfw)
|
||||
GEN_OUTPUTS(umtrx_txrx_uhd.elf)
|
||||
TEST_STACK_SIZE(umtrx_txrx_uhd.elf ${MIN_STACK})
|
||||
|
||||
|
||||
@@ -33,10 +33,13 @@ MACRO(GEN_RMI target)
|
||||
ENDMACRO(GEN_RMI)
|
||||
|
||||
########################################################################
|
||||
ADD_EXECUTABLE(bootloader.elf ${CMAKE_SOURCE_DIR}/apps/txrx_uhd.c)
|
||||
ADD_DEFINITIONS(-DUSRP2P)
|
||||
ADD_DEFINITIONS(-DBOOTLOADER)
|
||||
TARGET_LINK_LIBRARIES(bootloader.elf libumtrxfw)
|
||||
|
||||
ADD_EXECUTABLE(bootloader.elf ${CMAKE_SOURCE_DIR}/apps/txrx_uhd.c ${libumtrxfw_FILES})
|
||||
# TARGET_LINK_LIBRARIES(bootloader.elf libumtrxfw)
|
||||
SET(GEN_OUTPUTS_BIN_SIZE 0x3fff)
|
||||
GEN_OUTPUTS(bootloader.elf)
|
||||
GEN_RMI(bootloader.bin)
|
||||
TEST_STACK_SIZE(bootloader.elf ${MIN_STACK})
|
||||
|
||||
|
||||
@@ -40,14 +40,10 @@ int is_valid_fpga_image(uint32_t addr) {
|
||||
}
|
||||
|
||||
int is_valid_fw_image(uint32_t addr) {
|
||||
static const uint8_t fwheader[] = {0x0b, 0x0b, 0x0b, 0x0b}; //just lookin for a jump to anywhere located at the reset vector
|
||||
//printf("is_valid_fw_image(): starting with addr=%x...\n", addr);
|
||||
uint8_t buf[12];
|
||||
spi_flash_read(addr, 4, buf);
|
||||
//printf("is_valid_fw_image(): read ");
|
||||
//for(int i = 0; i < 5; i++) printf("%x ", buf[i]);
|
||||
//printf("\n");
|
||||
return memcmp(buf, fwheader, 4) == 0;
|
||||
static const uint8_t fwheader[2] = {0x0b, 0x0b}; //just lookin for a jump to anywhere located at the reset vector
|
||||
uint8_t buf[2];
|
||||
spi_flash_read(addr, 2, buf);
|
||||
return memcmp(buf, fwheader, 2) == 0;
|
||||
}
|
||||
|
||||
void start_program(void)
|
||||
@@ -59,7 +55,7 @@ void start_program(void)
|
||||
|
||||
void do_the_bootload_thing(void) {
|
||||
#ifdef NO_FLASH
|
||||
puts("Starting USRP2+ without flash.");
|
||||
puts("Starting UmTRX without flash.");
|
||||
return;
|
||||
#else
|
||||
spif_init(); //initialize SPI flash clock
|
||||
@@ -71,14 +67,14 @@ void do_the_bootload_thing(void) {
|
||||
set_safe_booted_flag(0); //haven't booted yet
|
||||
|
||||
if(BUTTON_PUSHED) { //see memory_map.h
|
||||
puts("Starting USRP2+ in safe mode. Loading safe firmware.");
|
||||
return;
|
||||
puts("Starting UmTRX in safe mode.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!production_image) {
|
||||
puts("Checking for valid production FPGA image...");
|
||||
if(is_valid_fpga_image(PROD_FPGA_IMAGE_LOCATION_ADDR)) {
|
||||
puts("Valid production FPGA image found. Attempting to boot.");
|
||||
puts("Valid production FPGA image found, booting..");
|
||||
set_safe_booted_flag(1);
|
||||
mdelay(300); //so serial output can finish
|
||||
#ifdef SPARTAN6
|
||||
@@ -88,15 +84,15 @@ void do_the_bootload_thing(void) {
|
||||
#endif
|
||||
}
|
||||
puts("No valid production FPGA image found.\n");
|
||||
// return;
|
||||
return;
|
||||
}
|
||||
if(is_valid_fw_image(PROD_FW_IMAGE_LOCATION_ADDR)) {
|
||||
puts("Valid production firmware found. Loading...");
|
||||
spi_flash_read(PROD_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES, (void *)RAM_BASE);
|
||||
puts("Finished loading. Starting image.");
|
||||
puts("Starting image...");
|
||||
mdelay(300);
|
||||
start_program();
|
||||
puts("ERROR: Return from main program! This should never happen!");
|
||||
puts("ERROR: Return from main!");
|
||||
//if this happens, though, the safest thing to do is reboot the whole FPGA and start over.
|
||||
mdelay(300);
|
||||
#ifdef SPARTAN6
|
||||
@@ -106,23 +102,6 @@ void do_the_bootload_thing(void) {
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
puts("No valid production firmware found. Falling through to built-in firmware.");
|
||||
/*
|
||||
if(is_valid_fw_image(SAFE_FW_IMAGE_LOCATION_ADDR)) {
|
||||
spi_flash_read(SAFE_FW_IMAGE_LOCATION_ADDR, FW_IMAGE_SIZE_BYTES, (void *)RAM_BASE);
|
||||
puts("Finished loading. Starting image.");
|
||||
mdelay(300);
|
||||
start_program();
|
||||
puts("ERROR: return from main program! This should never happen!");
|
||||
mdelay(300);
|
||||
#ifdef SPARTAN6
|
||||
icap_s6_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR, SAFE_FPGA_IMAGE_LOCATION_ADDR);
|
||||
#else
|
||||
icap_s3_reload_fpga(SAFE_FPGA_IMAGE_LOCATION_ADDR);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
puts("ERROR: no safe firmware image available. Falling through to built-in firmware.");
|
||||
*/
|
||||
puts("No valid production firmware found!");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ size_t spi_flash_log2_memory_size(void)
|
||||
}
|
||||
if (_spi_flash_log2_memory_size < 22 ||
|
||||
_spi_flash_log2_memory_size > 24 ){
|
||||
printf("\nWrong flash size: %d Achtung!\n", _spi_flash_log2_memory_size);
|
||||
printf("\nWrong flash size: %d Achtung!\n", (int)_spi_flash_log2_memory_size);
|
||||
abort();
|
||||
}
|
||||
return _spi_flash_log2_memory_size;
|
||||
@@ -51,7 +51,7 @@ size_t spi_flash_log2_memory_size(void)
|
||||
|
||||
size_t spi_flash_log2_sector_size(void)
|
||||
{
|
||||
static unsigned char log2_sector_size[3] = {
|
||||
static const unsigned char log2_sector_size[3] = {
|
||||
16, /* M25P32 */
|
||||
16, /* M25P64 */
|
||||
18, /* M25P128 */
|
||||
|
||||
Reference in New Issue
Block a user