aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--firmware/x300/lib/ethernet.c90
-rw-r--r--firmware/x300/x300/x300_init.c1
-rw-r--r--firmware/x300/x300/x300_main.c26
-rwxr-xr-xfpga/usrp3/top/x300/coregen/bootram.coe4754
-rw-r--r--host/CMakeLists.txt12
-rw-r--r--host/docs/usrp_x3x0_config.rst7
-rw-r--r--host/include/uhd/transport/udp_zero_copy.hpp2
-rw-r--r--host/lib/transport/nirio/rpc/rpc_client.cpp68
-rw-r--r--host/lib/transport/super_recv_packet_handler.hpp63
-rw-r--r--host/lib/transport/udp_wsa_zero_copy.cpp81
-rw-r--r--host/lib/usrp/b200/b200_impl.cpp9
-rw-r--r--host/lib/usrp/b200/b200_impl.hpp11
-rw-r--r--host/lib/usrp/b200/b200_io_impl.cpp69
-rw-r--r--host/lib/usrp/multi_usrp.cpp51
-rw-r--r--host/lib/usrp/x300/x300_clock_ctrl.cpp4
-rw-r--r--host/lib/usrp/x300/x300_clock_ctrl.hpp6
-rw-r--r--host/lib/usrp/x300/x300_fw_common.h2
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp289
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp57
-rw-r--r--host/lib/usrp/x300/x300_io_impl.cpp151
-rw-r--r--host/lib/usrp/x300/x300_regs.hpp14
-rw-r--r--host/utils/uhd_cal_rx_iq_balance.cpp18
-rw-r--r--host/utils/uhd_cal_tx_dc_offset.cpp16
-rw-r--r--host/utils/uhd_cal_tx_iq_balance.cpp19
-rw-r--r--host/utils/usrp_cal_utils.hpp31
25 files changed, 3074 insertions, 2777 deletions
diff --git a/firmware/x300/lib/ethernet.c b/firmware/x300/lib/ethernet.c
index fdde9e41b..7a86980c7 100644
--- a/firmware/x300/lib/ethernet.c
+++ b/firmware/x300/lib/ethernet.c
@@ -82,7 +82,7 @@ ethernet_ninterfaces(void)
// Clause 45 MDIO used for 10Gig Ethernet has two bus transactions to complete a transfer.
// An initial transaction sets up the address, and a subsequent one transfers the read or write data.
//
-static uint32_t
+static uint32_t
xge_read_mdio(const uint32_t base, const uint32_t address, const uint32_t device, const uint32_t port)
{
// Set register address each iteration
@@ -103,9 +103,9 @@ xge_read_mdio(const uint32_t base, const uint32_t address, const uint32_t device
return(xge_regs->mdio_data);
}
-static void
+static void
xge_write_mdio(const uint32_t base, const uint32_t address, const uint32_t device, const uint32_t port, const uint32_t data)
-{
+{
// Set register address each iteration
xge_regs->mdio_addr = address;
// Its a clause 45 device. We want to ADDRESS
@@ -114,13 +114,13 @@ xge_write_mdio(const uint32_t base, const uint32_t address, const uint32_t devic
xge_regs->mdio_control = 1;
// Wait until bus transaction complete
while (xge_regs->mdio_control == 1);
- // Write new value to mdio_write_data reg.
- xge_regs->mdio_data = data;
- // Its a clause 45 device. We want to WRITE
+ // Write new value to mdio_write_data reg.
+ xge_regs->mdio_data = data;
+ // Its a clause 45 device. We want to WRITE
xge_regs->mdio_op = XGE_MDIO_CLAUSE(CLAUSE45) | XGE_MDIO_OP(MDIO_WRITE) | XGE_MDIO_ADDR(port) | XGE_MDIO_MMD(device);
- // Start MDIO bus transaction
- xge_regs->mdio_control = 1;
- // Wait until bus transaction complete
+ // Start MDIO bus transaction
+ xge_regs->mdio_control = 1;
+ // Wait until bus transaction complete
while (xge_regs->mdio_control == 1);
}
@@ -128,7 +128,7 @@ xge_write_mdio(const uint32_t base, const uint32_t address, const uint32_t devic
//
// Clause 22 MDIO used for 1Gig Ethernet has one bus transaction to complete a transfer.
//
-static uint32_t
+static uint32_t
ge_read_mdio(const uint32_t base, const uint32_t address, const uint32_t port)
{
// Its a clause 22 device. We want to READ
@@ -141,16 +141,16 @@ ge_read_mdio(const uint32_t base, const uint32_t address, const uint32_t port)
return(xge_regs->mdio_data);
}
-static void
+static void
ge_write_mdio(const uint32_t base, const uint32_t address, const uint32_t port, const uint32_t data)
{
- // Write new value to mdio_write_data reg.
- xge_regs->mdio_data = data;
- // Its a clause 22 device. We want to WRITE
+ // Write new value to mdio_write_data reg.
+ xge_regs->mdio_data = data;
+ // Its a clause 22 device. We want to WRITE
xge_regs->mdio_op = XGE_MDIO_CLAUSE(CLAUSE22) | XGE_MDIO_OP(MDIO_C22_WRITE) | XGE_MDIO_ADDR(port) | address;
- // Start MDIO bus transaction
- xge_regs->mdio_control = 1;
- // Wait until bus transaction complete
+ // Start MDIO bus transaction
+ xge_regs->mdio_control = 1;
+ // Wait until bus transaction complete
while (xge_regs->mdio_control == 1);
}
@@ -205,7 +205,7 @@ xge_i2c_rd(const uint32_t base, const uint8_t i2c_dev_addr, const uint8_t i2c_wo
// Now read back a byte of data
if (wb_i2c_read(base, i2c_dev_addr, &buf, 1) == false)
return(-1);
-
+
return((int) buf);
}
@@ -334,15 +334,15 @@ xge_phy_init(const uint8_t eth, const uint32_t mdio_port)
printf("INFO: Begining XGE PHY init sequence.\n");
// Software reset
x = read_mdio(eth, 0x0, XGE_MDIO_DEVICE_PMA,mdio_port);
- x = x | (1 << 15);
- write_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port,x);
+ x = x | (1 << 15);
+ write_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port,x);
while(x&(1<<15))
x = read_mdio(eth, 0x0,XGE_MDIO_DEVICE_PMA,mdio_port);
}
void
xge_poll_sfpp_status(const uint32_t eth)
-{
+{
uint32_t x;
// Has MODDET/MODAbS changed since we last looked?
x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 ));
@@ -355,14 +355,20 @@ xge_poll_sfpp_status(const uint32_t eth)
printf("DEBUG: eth%1d MODABS changed state: %d\n", eth, (x & SFPP_STATUS_MODABS) >> 2);
if (x & (SFPP_STATUS_RXLOS_CHG|SFPP_STATUS_TXFAULT_CHG|SFPP_STATUS_MODABS_CHG))
- if (( x & (SFPP_STATUS_RXLOS|SFPP_STATUS_TXFAULT|SFPP_STATUS_MODABS)) == 0) {
- xge_ethernet_init(eth);
- dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT);
- mdelay(100);
- dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT);
- mdelay(100);
- dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT);
+ {
+ if (( x & (SFPP_STATUS_RXLOS|SFPP_STATUS_TXFAULT|SFPP_STATUS_MODABS)) == 0)
+ {
+ if (wb_peek32(SR_ADDR(RB0_BASE, eth == 0 ? RB_ETH_TYPE0 : RB_ETH_TYPE1)) == 1)
+ {
+ xge_ethernet_init(eth);
+ dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT);
+ mdelay(100);
+ dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT);
+ mdelay(100);
+ dump_mdio_regs((eth==0) ? XGE0_BASE : XGE1_BASE,MDIO_PORT);
}
+ }
+ }
if (x & SFPP_STATUS_MODABS_CHG) {
// MODDET has changed state since last checked
@@ -383,14 +389,14 @@ xge_poll_sfpp_status(const uint32_t eth)
//The link became up, send a GARP so everyone knows our mac/ip association
if (!old_link_up && links_up[eth]) u3_net_stack_send_arp_request(eth, u3_net_stack_get_ip_addr(eth));
}
-
+
void
xge_ethernet_init(const uint32_t eth)
-{
- xge_mac_init((eth==0) ? XGE0_BASE : XGE1_BASE);
- //xge_hard_phy_reset();
- xge_phy_init(eth ,MDIO_PORT);
+{
+ xge_mac_init((eth==0) ? XGE0_BASE : XGE1_BASE);
+ //xge_hard_phy_reset();
+ xge_phy_init(eth ,MDIO_PORT);
uint32_t x = wb_peek32(SR_ADDR(RB0_BASE, (eth==0) ? RB_SFPP_STATUS0 : RB_SFPP_STATUS1 ));
printf(" eth%1d SFP initial state: RXLOS: %d TXFAULT: %d MODABS: %d\n",
eth,
@@ -411,7 +417,7 @@ void decode_reg(uint32_t address, uint32_t device, uint32_t data)
printf("%x",device);
printf(" ");
switch(address) {
- case XGE_MDIO_CONTROL1:
+ case XGE_MDIO_CONTROL1:
printf("CONTROL1: ");
printf("%x",data); printf(" ");
for (x=15; x >= 0 ; x--)
@@ -423,7 +429,7 @@ void decode_reg(uint32_t address, uint32_t device, uint32_t data)
case 11: printf("Low Power Mode,"); break;
case 5:case 4:case 3:case 2: printf("RESERVED speed value,"); break;
case 0: printf("PMA loopback,"); break;
- } //else
+ } //else
// Bits clear.
//switch (x) {
//case 13: case 6: printf(" None 10Gb/s speed set!"); break;
@@ -440,7 +446,7 @@ void decode_reg(uint32_t address, uint32_t device, uint32_t data)
case 7: printf("Fault Detected,"); break;
case 2: printf("Link is Up,"); break;
case 1: printf("Supports Low Power,"); break;
- } else
+ } else
// Bits Clear
switch(x) {
case 2: printf("Link is Down,"); break;
@@ -457,7 +463,7 @@ void decode_reg(uint32_t address, uint32_t device, uint32_t data)
case 15:case 14:case 13:case 12:case 11:case 10:case 9:
case 8:case 7:case 6:case 5:case 4:case 3:case 2:case 1: printf("RESERVED bits set!,"); break;
case 0: printf("Capable of 10Gb/s,");
- } else
+ } else
// Bits clear.
switch(x) {
case 0: printf("Incapable of 10Gb/s,"); break;
@@ -572,7 +578,7 @@ void decode_reg(uint32_t address, uint32_t device, uint32_t data)
case 2: printf("Lane 2 not synced,"); break;
case 1: printf("Lane 1 not synced,"); break;
case 0: printf("Lane 0 not synced,"); break;
- }
+ }
printf(" \n");
break;
case XILINX_CORE_VERSION:
@@ -591,23 +597,23 @@ void decode_reg(uint32_t address, uint32_t device, uint32_t data)
}
}
-void
+void
dump_mdio_regs(const uint8_t eth, uint32_t mdio_port)
{
volatile unsigned int x;
int y;
unsigned int regs_a[9] = {0,1,4,5,6,7,8,32,33};
unsigned int regs_b[10] = {0,1,4,5,6,7,8,10,11,65535};
-
+
printf("\n");
- for (y = 0; y < 10; y++)
+ for (y = 0; y < 10; y++)
{
// Read MDIO data
x = read_mdio(eth,regs_b[y],XGE_MDIO_DEVICE_PMA,mdio_port);
decode_reg(regs_b[y],XGE_MDIO_DEVICE_PMA,x);
}
-
+
for (y = 0; y < 9; y++)
{
// Read MDIO data
diff --git a/firmware/x300/x300/x300_init.c b/firmware/x300/x300/x300_init.c
index 2ddfef86b..66fb120f3 100644
--- a/firmware/x300/x300/x300_init.c
+++ b/firmware/x300/x300/x300_init.c
@@ -75,6 +75,7 @@ static void init_network(void)
pkt_config = wb_pkt_iface64_init(PKT_RAM0_BASE, 0x1ffc);
printf("PKT RAM0 BASE 0x%x\n", (&pkt_config)->base);
u3_net_stack_init(&pkt_config);
+
link_state_route_proto_init();
//read everything from eeprom
diff --git a/firmware/x300/x300/x300_main.c b/firmware/x300/x300/x300_main.c
index 5f7c19624..809f181ba 100644
--- a/firmware/x300/x300/x300_main.c
+++ b/firmware/x300/x300/x300_main.c
@@ -372,15 +372,26 @@ static void handle_uarts(void)
**********************************************************************/
static void update_forwarding(const uint8_t e)
{
+ /* FIXME: This code is broken.
+ * It blindly enables forwarding without regard to whether or not
+ * packets can be forwarded. If one of the Ethernet interfaces is not
+ * connected, data backs up until the first interface becomes unresponsive.
+ *
+ * And for more fun, we had to re-enable forwarding of packets that were not
+ * addressed to this device's MAC address to work around an issue that was
+ * causing sequence errors.
+ */
//update forwarding rules
uint32_t forward = 0;
if (!link_state_route_proto_causes_cycle_cached(e, (e+1)%2))
{
- forward |= (1 << 0); //forward bcast
+ //FIXME: Uncomment when forwarding of broadcasts is properly handled
+ //forward |= (1 << 0); //forward bcast
forward |= (1 << 1); //forward not mac dest
}
const uint32_t eth_base = (e == 0)? SR_ETHINT0 : SR_ETHINT1;
wb_poke32(SR_ADDR(SET0_BASE, eth_base + 8 + 4), forward);
+
}
static void handle_link_state(void)
@@ -390,13 +401,9 @@ static void handle_link_state(void)
shmem[X300_FW_SHMEM_ROUTE_MAP_ADDR] = (uint32_t)link_state_route_get_node_mapping(&map_len);
shmem[X300_FW_SHMEM_ROUTE_MAP_LEN] = map_len;
- //update forwarding for all eths
- //low overhead: this does not run the algorithm
- for (uint8_t e = 0; e < ethernet_ninterfaces(); e++) update_forwarding(e);
-
static size_t count = 0;
- if (count++ < 2000) return; //2 seconds
- count = 0;
+ if (count--) return;
+ count = 2000; //repeat every ~2 seconds
link_state_route_proto_tick();
for (size_t e = 0; e < ethernet_ninterfaces(); e++)
@@ -406,7 +413,12 @@ static void handle_link_state(void)
link_state_route_proto_update(e);
link_state_route_proto_flood(e);
}
+
+ //update forwarding if something changed
+ bool before = link_state_route_proto_causes_cycle_cached(e, (e+1)%2);
link_state_route_proto_update_cycle_cache(e);
+ if (before != link_state_route_proto_causes_cycle_cached(e, (e+1)%2))
+ update_forwarding(e);
/*
printf("is there a cycle %s -> %s? %s\n",
ip_addr_to_str(u3_net_stack_get_ip_addr(e)),
diff --git a/fpga/usrp3/top/x300/coregen/bootram.coe b/fpga/usrp3/top/x300/coregen/bootram.coe
index 075e91f39..98796a4c6 100755
--- a/fpga/usrp3/top/x300/coregen/bootram.coe
+++ b/fpga/usrp3/top/x300/coregen/bootram.coe
@@ -2,15 +2,15 @@ memory_initialization_radix=16;
memory_initialization_vector=
0b0b0b0b,
82700b0b,
-8187b00c,
+8186f40c,
3a0b0b80,
-f28f0400,
+eef50400,
00000000,
00000000,
00000000,
80088408,
88080b0b,
-80f2da2d,
+80efc02d,
880c840c,
800c0400,
00000000,
@@ -161,8 +161,8 @@ c4040000,
00000000,
00000000,
71fc0608,
-0b0b8187,
-9c738306,
+0b0b8186,
+e0738306,
10100508,
060b0b0b,
88aa0400,
@@ -170,16 +170,16 @@ c4040000,
00000000,
80088408,
88087575,
-0b0b80e9,
-b42d5050,
+0b0b80e7,
+dd2d5050,
80085688,
0c840c80,
0c510400,
00000000,
80088408,
88087575,
-0b0b80ea,
-e62d5050,
+0b0b80e9,
+8f2d5050,
80085688,
0c840c80,
0c510400,
@@ -209,7 +209,7 @@ e62d5050,
00000000,
00000000,
810b0b0b,
-8187ac0c,
+8186f00c,
51040000,
00000000,
00000000,
@@ -257,7 +257,7 @@ e62d5050,
00000000,
00000000,
82813f80,
-ebfb3f04,
+e8e13f04,
10101010,
10101010,
10101010,
@@ -280,56 +280,56 @@ fc060c51,
0a100a53,
72ed3851,
51535104,
-8187ac08,
+8186f008,
802ea438,
-8187b008,
+8186f408,
822ebd38,
8380800b,
-0b0b818f,
-a40c82a0,
-800b818f,
-a80c8290,
-800b818f,
-ac0c04f8,
+0b0b818e,
+e80c82a0,
+800b818e,
+ec0c8290,
+800b818e,
+f00c04f8,
808080a4,
0b0b0b81,
-8fa40cf8,
+8ee80cf8,
80808280,
-0b818fa8,
+0b818eec,
0cf88080,
84800b81,
-8fac0c04,
+8ef00c04,
80c0a880,
8c0b0b0b,
-818fa40c,
+818ee80c,
80c0a880,
-940b818f,
-a80c0b0b,
-80f4b00b,
-818fac0c,
+940b818e,
+ec0c0b0b,
+80f1940b,
+818ef00c,
04ff3d0d,
-818fb033,
+818ef433,
5170a738,
-8187b808,
+8186fc08,
70085252,
70802e94,
38841281,
-87b80c70,
-2d8187b8,
+86fc0c70,
+2d8186fc,
08700852,
5270ee38,
-810b818f,
-b034833d,
+810b818e,
+f434833d,
0d040480,
3d0d0b0b,
-818fa008,
+818ee408,
802e8e38,
0b0b0b0b,
800b802e,
09810685,
38823d0d,
040b0b81,
-8fa0510b,
+8ee4510b,
0b0bf5d4,
3f823d0d,
0404f93d,
@@ -354,455 +354,461 @@ b1387218,
73833877,
5170800c,
893d0d04,
-04e23d0d,
+ff3d0d02,
+93053352,
+83f28051,
+97863f83,
+3d0d04e2,
+3d0d8bef,
+5283fa80,
+5196e93f,
8bef5283,
-fa805198,
-823f8bef,
-5283f280,
-5197f83f,
-8b885280,
-51a2a73f,
-81af5280,
-f4b851a2,
-a83f80d3,
+f2805196,
+df3f8b88,
+528051a1,
+8d3f81af,
+5280f19c,
+51a18e3f,
+80d3b993,
+c05283fc,
+80519785,
+3f80d3b9,
+93c05283,
+fe805196,
+f83f80d3,
b993c052,
-83fc8051,
-989e3f80,
-d3b993c0,
+83f88051,
+96eb3f81,
+0b82c084,
+0c82c090,
+08558a56,
+74812e83,
+38815675,
+5280f1c8,
+51a0ca3f,
+82c09408,
+558a5674,
+812e8338,
+81567552,
+80f1e051,
+a0b33fbf,
+fc538280,
+8052818e,
+f851a1ca,
+3f818ef8,
+085280f1,
+f851a099,
+3f818ef8,
+51a68e3f,
+8d3d5b80,
+cc538187,
+80527a51,
+80dffe3f,
+825480f1,
+985380d0,
5283fe80,
-5198913f,
-80d3b993,
-c05283f8,
-80519884,
-3f810b82,
-c0840c82,
+5197c03f,
+80cc547a,
+5380d052,
+83fe8051,
+96983f82,
c0900855,
-8a567481,
-2e833881,
-56755280,
-f4e451a1,
-e43f82c0,
-9408558a,
-5674812e,
-83388156,
-755280f4,
-fc51a1cd,
-3fbffc53,
-82808052,
-818fb451,
-a2e43f81,
-8fb40852,
-80f59451,
-a1b33f81,
-8fb451a7,
-a83f80da,
-843f8d3d,
-5b80cc53,
-8187bc52,
-7a5180e1,
-e33f8254,
-80f4b453,
-80d05283,
-fe805198,
-d53f80cc,
-547a5380,
-d05283fe,
-805197ad,
-3f82c090,
-08558257,
-74833874,
-5782c094,
-0855835c,
-74833881,
-5c865381,
-87c452a0,
-3dffbc05,
-51fdab3f,
-80085686,
-538187cc,
-52a03dc4,
-0551fd9a,
-3f800858,
-84537682,
-2b8187e8,
-1153701c,
-ac115358,
-55fd833f,
-80085a84,
-538187d8,
-15529c17,
-51fcf33f,
-80085984,
-537b822b,
-8187e811,
-53701cac,
-11535855,
-fcdc3f80,
-085b8453,
-8187d815,
-529c1751,
-fccc3f80,
-0879557a,
-54765357,
-8051a681,
-3f841633,
-85173371,
-882b0783,
-18337090,
-2b720782,
-1a337098,
-2b720782,
-c1c00c7a,
-33811c33,
+82577483,
+38745782,
+c0940855,
+835c7483,
+38815c86,
+53818788,
+52a03dff,
+bc0551fd,
+9d3f8008,
+56865381,
+879052a0,
+3dc40551,
+fd8c3f80,
+08588453,
+76822b81,
+87ac1153,
+701cac11,
+535855fc,
+f53f8008,
+5a845381,
+879c1552,
+9c1751fc,
+e53f8008,
+5984537b,
+822b8187,
+ac115370,
+1cac1153,
+5855fcce,
+3f80085b,
+84538187,
+9c15529c,
+1751fcbe,
+3f800879,
+557a5476,
+53578051,
+a4eb3f84,
+16338517,
+3371882b,
+07831833,
+70902b72,
+07821a33,
+70982b72,
+0782c1c0,
+0c7a3381,
+1c337188,
+2b0782c1,
+c40c7f08,
+82c1c80c,
+535d5252,
+565c800b,
+82c1d00c,
+9e800b82,
+c1d40c76,
+547a5377,
+528151a4,
+9c3f8418,
+33851933,
71882b07,
-82c1c40c,
-7f0882c1,
-c80c535d,
-5252565c,
-800b82c1,
-d00c9e80,
-0b82c1d4,
-0c76547a,
-53775281,
-51a5b23f,
-84183385,
-19337188,
-2b07831a,
-3370902b,
-7207821c,
-3370982b,
-720782c2,
-800c7c33,
-811e3371,
-882b0782,
-c2840c60,
-0882c288,
-0c555d52,
-59565c80,
-0b82c290,
-0c9e800b,
-82c2940c,
-800b82c0,
-840c80e4,
-51bccb3f,
-82c09008,
-5574812e,
-09810686,
-388051b6,
-903f82c0,
-94085574,
-812e0981,
-06863874,
-51b5fe3f,
-805580e9,
-397451a2,
-e03f8008,
-5180c9eb,
-3f800853,
-745280f5,
-a8519e85,
-3f7451a2,
-b33f8008,
-5180c9f9,
-3f800853,
-745280f5,
-bc519ded,
-3f7451a4,
-bf3f8008,
-5180c9e1,
-3f800853,
-745280f5,
-d0519dd5,
-3f7451a4,
-bc3f8008,
-5180c9c9,
-3f800853,
-745280f5,
-e4519dbd,
-3f811570,
-81ff0651,
-55b3a13f,
-80087524,
-ff8f38a0,
-3d0d04f5,
-3d0d7e60,
-028805b7,
-05337154,
-5b5b54a1,
-f43f8008,
-58a85578,
-802e8338,
-b8557390,
-2a7081ff,
-06705575,
-5480f5f8,
-5351579c,
-f43f7851,
-a1b73f74,
-822b82c0,
-80118008,
-33800881,
-05337188,
-2b07720c,
-82c08413,
-80088205,
-33800883,
-05337198,
-2b71902b,
-07800884,
-05337088,
-2b720780,
-08850533,
-7107760c,
-5282c088,
-18615a55,
-535a4152,
-525d5755,
-a0d23f80,
-0808760c,
-82c08c15,
-02840580,
-c6052271,
-0c5482c0,
-90157771,
-0c5482c0,
-94157a08,
-710c5682,
-c0981502,
-840580c2,
-05227933,
-71902b71,
-882b0781,
-1c337107,
-740c5282,
-c09c1882,
-1c33831d,
+831a3370,
+902b7207,
+821c3370,
+982b7207,
+82c2800c,
+7c33811e,
+3371882b,
+0782c284,
+0c600882,
+c2880c55,
+5d525956,
+5c800b82,
+c2900c9e,
+800b82c2,
+940c800b,
+82c0840c,
+80e45180,
+c7de3f82,
+c0900855,
+74812e09,
+81068638,
+8051b4f9,
+3f82c094,
+08557481,
+2e098106,
+86387451,
+b4e73f80,
+5580e939,
+7451a1c9,
+3f800851,
+80d4fe3f,
+80085374,
+5280f28c,
+519cee3f,
+7451a19c,
+3f800851,
+80d58c3f,
+80085374,
+5280f2a0,
+519cd63f,
+7451a3a8,
+3f800851,
+80d4f43f,
+80085374,
+5280f2b4,
+519cbe3f,
+7451a3a5,
+3f800851,
+80d4dc3f,
+80085374,
+5280f2c8,
+519ca63f,
+81157081,
+ff065155,
+b28a3f80,
+087524ff,
+8f38a03d,
+0d04f53d,
+0d7e6002,
+8805b705,
+3371545b,
+5b54a0dd,
+3f800858,
+a8557880,
+2e8338b8,
+5573902a,
+7081ff06,
+70557554,
+80f2dc53,
+51579bdd,
+3f7851a0,
+a03f7482,
+2b82c080,
+11800833,
+80088105,
+3371882b,
+07720c82,
+c0841380,
+08820533,
+80088305,
3371982b,
71902b07,
-841f3370,
-882b7207,
-60850533,
-7107760c,
-52555555,
-40585955,
-568d3d0d,
-04fb3d0d,
-7c567580,
-2e9d3884,
-16080284,
-05ae0522,
-56028405,
-aa052255,
-79545202,
-9f053351,
-fde53f87,
-3d0d04f2,
-3d0d655a,
-79802e81,
-b0388c3d,
-5b905379,
-527a5180,
-dbba3f66,
-8f268838,
-7b82075c,
-80f23979,
-08832a70,
-81065157,
-76802eab,
-38881a08,
-70942a70,
-81065158,
-5876802e,
-97388280,
-80548053,
-903dfc05,
-5277bfff,
-ff0651b9,
-c43f8439,
+80088405,
+3370882b,
+72078008,
+85053371,
+07760c52,
+82c08818,
+615a5553,
+5a415252,
+5d57559f,
+bb3f8008,
+08760c82,
+c08c1502,
+840580c6,
+0522710c,
+5482c090,
+1577710c,
+5482c094,
+157a0871,
+0c5682c0,
+98150284,
+0580c205,
+22793371,
+902b7188,
+2b07811c,
+33710774,
+0c5282c0,
+9c18821c,
+33831d33,
+71982b71,
+902b0784,
+1f337088,
+2b720760,
+85053371,
+07760c52,
+55555540,
+58595556,
+8d3d0d04,
+fb3d0d7c,
+5675802e,
+9d388416,
+08028405,
+ae052256,
+028405aa,
+05225579,
+5452029f,
+053351fd,
+e53f873d,
+0d04f23d,
+0d655a79,
+802e81b2,
+388c3d5b,
+90537952,
+7a5180d9,
+d43f668f,
+2688387b,
+82075c80,
+f4397908,
+832a7081,
+06515776,
+802eac38,
+881a0870,
+942a7081,
+06515858,
+76802e98,
+38828080,
+54805390,
+3dfc0552,
+77bfffff,
+065180c4,
+d63f8439,
77085f79,
08822a70,
81065157,
-76802eac,
+76802ead,
38881a08,
70942a70,
81068c1d,
085c5158,
5876802e,
-94388280,
+95388280,
80548053,
785277bf,
ffff0651,
-b8a63f84,
-3978780c,
-79088106,
-5776802e,
-9c389056,
-7a550280,
-ce052254,
-0280d205,
-22536152,
-0280c305,
-3351a7be,
-3f903d0d,
-048c0802,
-8c0cf03d,
-0d8c089c,
-05080284,
-058c08f8,
-050c8c08,
-ec050c80,
-0b8c08fc,
-050c8c08,
-ec050880,
-2e86cc38,
-8c08a005,
-088f268b,
-38820b8c,
-08fc050c,
-8681398c,
+80c3b73f,
+84397878,
+0c790881,
+06577680,
+2e9c3890,
+567a5502,
+80ce0522,
+540280d2,
+05225361,
+520280c3,
+053351a6,
+a53f903d,
+0d048c08,
+028c0cf0,
+3d0d8c08,
+9c050802,
+84058c08,
+f8050c8c,
+08ec050c,
+800b8c08,
+fc050c8c,
08ec0508,
-0870822a,
-70810651,
-8c08d405,
-0c8c08d8,
-050c8c08,
-d4050880,
-2e9038bb,
-fa3f8008,
-81068c08,
-dc050c85,
-bf398c08,
-d8050883,
+802e86d3,
+388c08a0,
+05088f26,
+8b38820b,
+8c08fc05,
+0c868839,
+8c08ec05,
+08087082,
2a708106,
518c08d4,
050c8c08,
-d4050880,
-2e8738be,
-883f85b3,
-398c08d8,
-0508862a,
-70810651,
+d8050c8c,
+08d40508,
+802e9138,
+80c78a3f,
+80088106,
+8c08dc05,
+0c85c539,
+8c08d805,
+08832a70,
+8106518c,
+08d4050c,
8c08d405,
-0c8c08d4,
-0508802e,
-883880c0,
-853f8593,
-398c08d8,
-0508872a,
-70810651,
+08802e88,
+3880c997,
+3f85b839,
+8c08d805,
+08862a70,
+8106518c,
+08d4050c,
8c08d405,
-0c8c08d4,
-0508802e,
-9b38bffb,
+08802e88,
+3880cb94,
+3f859839,
+8c08d805,
+08872a70,
+8106518c,
+08d4050c,
+8c08d405,
+08802e9c,
+3880cb89,
3f800881,
ff068c08,
d4050c8c,
08d40508,
-822e84e3,
-3884d439,
+822e84e7,
+3884d839,
8c08ec05,
08840508,
-51bdcf3f,
-80088106,
+5180c8dc,
+3f800881,
+068c08dc,
+050c8c08,
+dc050880,
+2e883881,
+0b8c08dc,
+050c8c08,
+ec050808,
+842a7081,
+06518c08,
+d4050c8c,
+08d40508,
+802e9838,
+8c08dc05,
+08802e8f,
+3880c8bc,
+3f800881,
+ff068c08,
+dc050c8c,
+08ec0508,
+8c050870,
+9f067030,
+72852a71,
+9f2a058c,
+08e8050c,
+518c08d4,
+050c8c08,
+d8050c80,
+708c08e0,
+050c8c08,
+e4050c8c,
+08e40508,
+8c08e805,
+082781aa,
+388c08dc,
+05088c08,
+e405082e,
+819c388c,
+08ec0508,
+8c05088c,
+08e00508,
+318c08d8,
+050ca00b,
+8c08d805,
+08278838,
+a00b8c08,
+d8050c8c,
+08d80508,
+538c08e0,
+0508108c,
+08ec0508,
+05900552,
+8c08ec05,
+08880508,
+8c08e005,
+08051051,
+80c2853f,
+80088c08,
+dc050806,
8c08dc05,
0c8c08dc,
0508802e,
8838810b,
8c08dc05,
-0c8c08ec,
-05080884,
-2a708106,
-518c08d4,
-050c8c08,
-d4050880,
-2e97388c,
-08dc0508,
-802e8e38,
-bdb03f80,
-0881ff06,
-8c08dc05,
-0c8c08ec,
-05088c05,
-08709f06,
-70307285,
-2a719f2a,
-058c08e8,
-050c518c,
-08d4050c,
-8c08d805,
-0c80708c,
-08e0050c,
+0c8c08e0,
+05088c08,
+d8050805,
8c08e405,
+0881058c,
+08e4050c,
+8c08e005,
0c8c08e4,
05088c08,
e8050827,
-81a9388c,
-08dc0508,
-8c08e405,
-082e819b,
-388c08ec,
-05088c05,
-088c08e0,
-0508318c,
+89388c08,
+dc0508fe,
+e6388c08,
+ec050808,
+852a7081,
+06518c08,
+d4050c8c,
+08d40508,
+802e81f8,
+38028c08,
+ec05088c,
+05087010,
+860570fc,
+06518c08,
+d4050c8c,
08d8050c,
-a00b8c08,
-d8050827,
-8838a00b,
-8c08d805,
-0c8c08d8,
-0508538c,
-08e00508,
-108c08ec,
-05080590,
-05528c08,
-ec050888,
-05088c08,
-e0050805,
-1051b6fa,
-3f80088c,
-08dc0508,
-068c08dc,
-050c8c08,
-dc050880,
-2e883881,
-0b8c08dc,
-050c8c08,
-e005088c,
+8c08f405,
+0c028c08,
+d4050831,
+0d873d8c,
08d80508,
-058c08e4,
-05088105,
-8c08e405,
-0c8c08e0,
-050c8c08,
-e405088c,
-08e80508,
-2789388c,
-08dc0508,
-fee7388c,
-08ec0508,
-08852a70,
-8106518c,
-08d4050c,
-8c08d405,
-08802e81,
-f738028c,
+5470538c,
08ec0508,
-8c050870,
-10860570,
-fc06518c,
-08d4050c,
-8c08d805,
-0c8c08f4,
-050c028c,
-08d40508,
-310d873d,
-8c08d805,
-08547053,
-8c08ec05,
-08880508,
-10528c08,
-f0050cb4,
-fe3f8008,
+88050810,
+528c08f0,
+050c80c0,
+883f8008,
8c08dc05,
08068c08,
dc050c8c,
@@ -865,7 +871,7 @@ fc050c8c,
8c088c05,
08528c08,
8b053351,
-a0c43f8c,
+9fa43f8c,
08f80508,
0d923d0d,
8c0c04f7,
@@ -873,8 +879,8 @@ a0c43f8c,
77802eb7,
38770881,
0657768c,
-3880f6a0,
-5192ae3f,
+3880f384,
+51918e3f,
78840759,
78820759,
615a8418,
@@ -884,417 +890,377 @@ ba052254,
02be0522,
537c5202,
af053351,
-9ff83f8b,
+9ed83f8b,
3d0d04f6,
3d0d7c7e,
59578070,
56567454,
76527753,
8c3df805,
-5180cb84,
+5180c995,
3f7a8106,
16811656,
56bf7527,
e5387580,
0c8c3d0d,
-04e63d0d,
-eeff3f92,
-d3528380,
-80519cbb,
-3f92a952,
+04e73d0d,
+eef93f92,
+e2528380,
+80519b9b,
+3f92b852,
83808151,
-9cb13f94,
-91528380,
-85519ca7,
-3f9b9352,
+9b913f94,
+a2528380,
+85519b87,
+3f9bab52,
83808651,
-9c9d3f80,
+9afd3f80,
5682c080,
08707731,
51538ad7,
-98732785,
-9e38805b,
-81888808,
-9d3dffbc,
-055253bf,
-b83f8008,
-ac140c81,
-8888087b,
-b0120c53,
-8054ba39,
-800b8115,
-70810654,
-75535656,
-80c99d3f,
-800881ff,
-06537276,
-2e098106,
-83388356,
-a8537380,
-2e8338b8,
-53728429,
-82c0b005,
-76710c53,
-7481ff06,
-54a6a53f,
-80087424,
-ffbe3881,
-8fc00881,
-11818fc0,
-0c538fcf,
-732780c3,
-38800b81,
-8fc00cbc,
-b63f8054,
-ad397351,
-ae803f80,
-0881ff06,
-5372802e,
-91387381,
-ff067052,
-53beea3f,
-725180c6,
-883f7381,
-ff065180,
-c1f33f81,
-1454a5d0,
-3f800874,
-26cc3881,
-88880898,
-11085454,
-72873872,
-94150ca0,
-39818fc4,
-08732e8e,
-38810b94,
-150c800b,
-818fc80c,
-8b39818f,
-c8088105,
-818fc80c,
-98140881,
-8fc40c8f,
-d00b818f,
-c8082786,
-38800b94,
-150c800b,
-818fcc0b,
-8e3d5a5b,
-597881ff,
-06558075,
-a02982c2,
-80055757,
-87547570,
-84055708,
-7705ff15,
-55577380,
-25f03874,
-842982c2,
-80055487,
-56730877,
-05ff17a0,
-16565757,
-758025f1,
-38748126,
-8a387451,
-96b13f80,
-08175777,
-08841908,
-709f2a72,
-10077110,
-717c0c70,
-841d0c71,
-715b5952,
-52555376,
-7a082e87,
-38738107,
-73565674,
-780c7584,
-190c767a,
-7084055c,
-0c811988,
-19595987,
-7927fef5,
-38818fec,
+98732783,
+e5388187,
+cc089811,
+08545472,
+87387294,
+150ca039,
+818f8408,
+732e8e38,
+810b9415,
+0c800b81,
+8f880c8b,
+39818f88,
08810581,
-8fec0c7b,
-7d555173,
-52fbe83f,
-80087e60,
-56527453,
-55fbdc3f,
-8075832b,
-818fec08,
-bf065656,
-58737527,
-83388158,
-800b8008,
-832b5457,
-73732783,
-38815780,
-51abab3f,
-800881ff,
-06558151,
-aba03f80,
+8f880c98,
+1408818f,
+840c8fd0,
+0b818f88,
+08278638,
+800b9415,
+0c800b81,
+8f8c0b8d,
+3d5a5b59,
+7881ff06,
+558075a0,
+2982c280,
+05575787,
+54757084,
+05570877,
+05ff1555,
+57738025,
+f0387484,
+2982c280,
+05548756,
+73087705,
+ff17a016,
+56575775,
+8025f138,
+7481268a,
+38745196,
+ca3f8008,
+17577708,
+84190870,
+9f2a7210,
+07711071,
+7c0c7084,
+1d0c7171,
+5b595252,
+5553767a,
+082e8738,
+73810773,
+56567478,
+0c758419,
+0c767a70,
+84055c0c,
+81198819,
+59598779,
+27fef538,
+818fac08,
+8105818f,
+ac0c7a7c,
+55517352,
+fda13f80,
+087d7f56,
+52745355,
+fd953f80,
+75832b81,
+8fac08bf,
+06565658,
+73752783,
+38815880,
+0b800883,
+2b545773,
+73278338,
+81578051,
+b7ee3f80,
0881ff06,
-81888808,
-94110856,
-54567380,
-2e833881,
-54845374,
-83387453,
-75802e85,
-38728807,
-5377802e,
-85387290,
-07538055,
-77752e09,
-81068638,
-76752e83,
-38815572,
-75075376,
+558151b7,
+e33f8008,
+81ff0681,
+87cc0894,
+11085654,
+5673802e,
+83388154,
+84537483,
+38745375,
802e8538,
-72a00753,
-73802e85,
-38728207,
-537282c0,
-800c818f,
-f0088111,
-818ff00c,
-5383d4df,
-7327b938,
-800b818f,
-f00c8054,
-a6397351,
-aaa43f80,
-0881ff06,
-5372802e,
-93387381,
-ff067052,
-5390cd3f,
-80085272,
-5195e83f,
-811454a1,
-fb3f8008,
-7426d338,
-8051a5d1,
-3f8151a5,
-cc3f82c0,
-8008569c,
-c03fb5ea,
-3f818888,
-08818ff4,
+72880753,
+77802e85,
+38729007,
+53805577,
+752e0981,
+06863876,
+752e8338,
+81557275,
+07537680,
+2e853872,
+a0075373,
+802e8538,
+72820753,
+7282c080,
+0c818fb0,
+08811181,
+8fb00c53,
+83d4df73,
+27b93880,
+0b818fb0,
+0c8054a6,
+397351b6,
+e73f8008,
+81ff0653,
+72802e93,
+387381ff,
+06705253,
+90e63f80,
+08527251,
+96813f81,
+1454a294,
+3f800874,
+26d33880,
+51b1fb3f,
+8151b1f6,
+3f82c080,
+08569cd9,
+3f80c2ac,
+3f8187cc,
+08818fb4,
0ba0120c,
-8191f40b,
+8191b40b,
a4120c53,
80c00ba8,
140c83fa,
-805181b5,
-3f8008ff,
-2e80c238,
-8193f408,
-81057081,
-ff067081,
-93f40c71,
-832b9806,
-52565372,
-86387281,
-93f80c80,
-08732b81,
-93f80807,
-708193f8,
-0c7581fc,
-06818ff4,
-0555740c,
-81888808,
-7588120c,
-538193fc,
-08818888,
-08545473,
-8c14082e,
-a9387383,
-2b980674,
-fc068191,
-f4057008,
-722a5455,
+805181ce,
+3f800854,
+8008ff2e,
+80c43881,
+93b40881,
+057081ff,
+06708193,
+b40c7183,
+2b980652,
+56537286,
+38728193,
+b80c7373,
+2b8193b8,
+08077081,
+93b80c75,
+81fc0681,
+8fb40555,
+740c8187,
+cc087588,
+120c53ff,
+ad398187,
+cc085381,
+93bc088c,
+14082ebf,
+388193bc,
+0870832b,
+980671fc,
+068191b4,
+05700872,
+2a555255,
5383fa80,
-51a93f81,
-93fc0881,
+51ba3f81,
+93bc0881,
057081ff,
-068193fc,
-0c538188,
-8808538c,
-8080730c,
-f99f3980,
-3d0d7274,
-710c5182,
-3d0d04fe,
-3d0d7484,
-11535371,
-08517080,
-2ef9388c,
-1376710c,
-51843d0d,
-04fe3d0d,
-74881170,
-08515253,
-ff527080,
-2e873890,
-13700853,
-5171800c,
-843d0d04,
-fc3d0d76,
-5380fa89,
-80527751,
-80c4ff3f,
-8008ff05,
-7083ffff,
-067081ff,
-06750c70,
-882a8416,
-0c515481,
-800b8814,
-0c863d0d,
-04fd3d0d,
-75787a55,
-55528151,
-72802e81,
-82389012,
-0870862a,
-70810651,
-515170f2,
-38029b05,
-33701081,
-078c140c,
-5181900b,
-90130c90,
-12087081,
-2a708106,
-51515170,
-f2389012,
-0870872a,
-70810670,
-81325151,
-51517080,
-2eb73872,
-802eae38,
-80e85172,
-812e8338,
-a0517090,
-130c9012,
-0870812a,
-70810651,
-515170f2,
-388c1208,
-51707470,
-81055634,
-ff1353cf,
-39815187,
-3980c00b,
-90130c70,
-800c853d,
+06708193,
+bc0c8187,
+cc085651,
+53728c15,
+082e0981,
+06c33881,
+87cc0853,
+8c808073,
+0cfabe39,
+803d0d72,
+74710c51,
+823d0d04,
+fe3d0d74,
+84115353,
+71085170,
+802ef938,
+8c137671,
+0c51843d,
+0d04fe3d,
+0d748811,
+70085152,
+53ff5270,
+802e8738,
+90137008,
+53517180,
+0c843d0d,
+04fc3d0d,
+765380fa,
+89805277,
+5180c4af,
+3f8008ff,
+057083ff,
+ff067081,
+ff06750c,
+70882a84,
+160c5154,
+81800b88,
+140c863d,
0d04fd3d,
0d75787a,
-55555290,
+55555281,
+5172802e,
+81823890,
12087086,
2a708106,
51515170,
f238029b,
05337010,
-8c140c51,
-81d05172,
-802e8438,
-81905170,
+81078c14,
+0c518190,
+0b90130c,
+90120870,
+812a7081,
+06515151,
+70f23890,
+12087087,
+2a708106,
+70813251,
+51515170,
+802eb738,
+72802eae,
+3880e851,
+72812e83,
+38a05170,
90130c90,
12087081,
2a708106,
51515170,
-f2389012,
-0870872a,
-70810670,
-81325151,
-51517080,
-2e80cb38,
-72802e80,
-c1387333,
-8c130c80,
-d0517281,
-2e833890,
-51709013,
-0c901208,
-70812a70,
-81065151,
-5170f238,
-90120870,
-872a7081,
-06708132,
-51515151,
-70802e8e,
-388114ff,
-145454ff,
-bb398151,
-893980c0,
+f2388c12,
+08517074,
+70810556,
+34ff1353,
+cf398151,
+873980c0,
0b90130c,
-80517080,
-0c853d0d,
+70800c85,
+3d0d04fd,
+3d0d7578,
+7a555552,
+90120870,
+862a7081,
+06515151,
+70f23802,
+9b053370,
+108c140c,
+5181d051,
+72802e84,
+38819051,
+7090130c,
+90120870,
+812a7081,
+06515151,
+70f23890,
+12087087,
+2a708106,
+70813251,
+51515170,
+802e80cb,
+3872802e,
+80c13873,
+338c130c,
+80d05172,
+812e8338,
+90517090,
+130c9012,
+0870812a,
+70810651,
+515170f2,
+38901208,
+70872a70,
+81067081,
+32515151,
+5170802e,
+8e388114,
+ff145454,
+ffbb3981,
+51893980,
+c00b9013,
+0c805170,
+800c853d,
+0d04f63d,
+0d7c7e60,
+625a5d5b,
+56805981,
+55853974,
+7a295574,
+52755180,
+c1a93f80,
+087a27ef,
+3874802e,
+80d83874,
+52755180,
+c1953f80,
+08755376,
+525480c1,
+af3f8008,
+7a537552,
+5680c0ff,
+3f800879,
+30707b07,
+9f2a7077,
+80240751,
+51545572,
+85388008,
+ca387681,
+18b01655,
+58588974,
+258b38b7,
+14537a85,
+3880d714,
+53727834,
+811959ff,
+a4398077,
+348c3d0d,
04f63d0d,
7c7e6062,
5a5d5b56,
80598155,
8539747a,
29557452,
-755180c1,
-f93f8008,
+755180c0,
+a23f8008,
7a27ef38,
74802e80,
-d8387452,
-755180c1,
-e53f8008,
+d7387452,
+755180c0,
+8e3f8008,
75537652,
-5480c1ff,
+5480c0a8,
3f80087a,
53755256,
-80c1cf3f,
-80087930,
-707b079f,
-2a707780,
-24075151,
-54557285,
-388008ca,
-38768118,
-b0165558,
-58897425,
-8b38b714,
-537a8538,
-80d71453,
-72783481,
-1959ffa4,
-39807734,
-8c3d0d04,
-f63d0d7c,
-7e60625a,
-5d5b5680,
-59815585,
-39747a29,
-55745275,
-5180c0f2,
-3f80087a,
-27ef3874,
-802e80d8,
-38745275,
-5180c0de,
-3f800875,
-53765254,
-80c0f83f,
-80087a53,
-75525680,
-c0c83f80,
+bff93f80,
08793070,
7b079f2a,
70778024,
07515154,
55728538,
-8008ca38,
+8008cb38,
768118b0,
16555858,
8974258b,
@@ -1302,7 +1268,7 @@ c0c83f80,
7a853880,
d7145372,
78348119,
-59ffa439,
+59ffa539,
8077348c,
3d0d04f7,
3d0d7b7d,
@@ -1435,7 +1401,7 @@ c139923d,
25555156,
90527984,
1b5b5675,
-0851f9e5,
+0851f9e6,
3f9f3977,
547b5676,
80d82e09,
@@ -1443,7 +1409,7 @@ c139923d,
81567553,
90527984,
1b5b5675,
-0851facc,
+0851facd,
3f953df4,
05557f54,
96397984,
@@ -1460,14 +1426,14 @@ c139923d,
810548fc,
9339953d,
0d047281,
-94800c71,
-8194840c,
+93c00c71,
+8193c40c,
04fb3d0d,
883d7070,
84055208,
57547553,
-81948008,
-52819484,
+8193c008,
+528193c4,
0851fbd6,
3f873d0d,
04ff3d0d,
@@ -1478,8 +1444,8 @@ c139923d,
0c833d0d,
04fc3d0d,
873d8811,
-557854ad,
-f95351fb,
+557854ac,
+f15351fb,
a93f8052,
873d51d1,
3f863d0d,
@@ -1511,8 +1477,8 @@ c53f833d,
54ffab3f,
7351ffb8,
3f8c5373,
-527451bf,
-833f7480,
+527451be,
+b43f7480,
0c893d0d,
04fd3d0d,
75705254,
@@ -1572,47 +1538,47 @@ ec397180,
7a7c0288,
05b30533,
5b595780,
-70819498,
+708193d8,
57575484,
53745276,
-51bc913f,
+51bbc23f,
80089838,
86537752,
-73168195,
-980551bc,
-f33f7881,
-96d81534,
+73168194,
+d80551bc,
+a43f7881,
+96981534,
80ce3981,
14841685,
18585654,
9f7427cf,
389f0b81,
-94940827,
+93d40827,
8738800b,
-8194940c,
-81949408,
+8193d40c,
+8193d408,
70822b78,
-08819498,
+088193d8,
120c7110,
05515486,
53775281,
-95981451,
-bcae3f81,
-94940854,
-788196d8,
+94d81451,
+bbdf3f81,
+93d40854,
+78819698,
15348114,
-8194940c,
+8193d40c,
8a3d0d04,
803d0d02,
8b053370,
84298196,
-f805800c,
+b805800c,
51823d0d,
04fe3d0d,
02930533,
70842971,
-10058197,
-8805800c,
+10058196,
+c805800c,
52843d0d,
04fa3d0d,
78578054,
@@ -1620,19 +1586,19 @@ f805800c,
705255c4,
3f845380,
08527651,
-bade3f80,
+ba8f3f80,
088a3874,
51c73f80,
0854b739,
81145483,
7427d938,
-80708194,
-98575754,
+80708193,
+d8575754,
84537452,
-7651bab8,
+7651b9e9,
3f80088a,
38731681,
-95980554,
+94d80554,
91398114,
84168518,
5856549f,
@@ -1640,25 +1606,25 @@ bade3f80,
80547380,
0c883d0d,
04ff3d0d,
-81949008,
+8193d008,
52718726,
a838028f,
05335170,
-8198b013,
+8197f013,
34029305,
33517081,
-98b81334,
+97f81334,
71842981,
-98c00576,
+98800576,
710c5181,
-12819490,
+128193d0,
0c833d0d,
04fe3d0d,
-74819488,
-0cbba753,
+748193c8,
+0cba9f53,
80528851,
-ffb73fbd,
-b3538352,
+ffb73fbc,
+ab538352,
8351ffad,
3f843d0d,
04fa3d0d,
@@ -1667,19 +1633,19 @@ b3538352,
54865379,
52731074,
84290581,
-97880551,
-ba923f7a,
+96c80551,
+b9c33f7a,
70088196,
-f8170c54,
+b8170c54,
7b700881,
-97a0170c,
+96e0170c,
54800b81,
-97c0160c,
+9780160c,
883d0d04,
803d0d02,
8b053370,
-84298197,
-a005800c,
+84298196,
+e005800c,
51823d0d,
04fd3d0d,
02970533,
@@ -1689,8 +1655,8 @@ bb3f8008,
d73f7182,
2b800808,
09750781,
-97b0120c,
-8197b005,
+96f0120c,
+8196f005,
800c853d,
0d04fb3d,
0d777957,
@@ -1698,7 +1664,7 @@ d73f7182,
81ff0651,
c43f8453,
74528008,
-51b8a53f,
+51b7d63f,
8008802e,
a3388114,
54837427,
@@ -1708,15 +1674,15 @@ fd9b3f80,
802e9938,
86538008,
527551b8,
-f33f8b39,
+a43f8b39,
865381ff,
-527551bb,
-c33f8154,
+527551b9,
+b13f8154,
73800c87,
3d0d04ff,
3d0d028f,
05337084,
-298197c0,
+29819780,
05700880,
0c525283,
3d0d0480,
@@ -1724,14 +1690,14 @@ c33f8154,
33515170,
83268f38,
70842981,
-97c00570,
+97800570,
08810571,
0c51823d,
0d04f73d,
0d7b7d60,
6373555b,
5b5b55d3,
-3f819488,
+3f8193c8,
0851f9be,
3f800b80,
08831c82,
@@ -1769,7 +1735,7 @@ ff145454,
84291753,
80730c78,
1a185281,
-94880851,
+93c80851,
f8cb3f8b,
3d0d04ec,
3d0d0280,
@@ -1777,12 +1743,12 @@ db053358,
778b3d34,
865381ff,
52963dd6,
-0551b9b8,
+0551b7a6,
3f7751fa,
d43f8670,
54800853,
973ddc05,
-5257b6c8,
+5257b5f9,
3f908602,
8405b605,
23810b90,
@@ -1796,15 +1762,15 @@ d43f8670,
7751fa99,
3f765380,
0852963d,
-ec0551b6,
-8f3f7751,
+ec0551b5,
+c03f7751,
f9f23f84,
53800852,
963df205,
-51b5fd3f,
+51b5ae3f,
76538052,
963df605,
-51b8cd3f,
+51b6bb3f,
67700846,
57805680,
55805480,
@@ -1812,18 +1778,18 @@ f9f23f84,
3dd00551,
fdb43f96,
3d0d04fe,
-3d0d8194,
-8c085372,
+3d0d8193,
+cc085372,
8f26a338,
72108197,
-d0050284,
+90050284,
05920522,
53517171,
23728429,
-8197f005,
+8197b005,
76710c51,
-81138194,
-8c0c843d,
+81138193,
+cc0c843d,
0d04e73d,
0da13d08,
a33d08a5,
@@ -1835,17 +1801,17 @@ a33d08a5,
fbd03f80,
0881ff06,
57768b38,
-80f6c851,
+80f3ac51,
f4a73f81,
ee39788e,
3d348653,
77529b3d,
ce0551b4,
-df3f7851,
+903f7851,
f8d73f86,
53800852,
9b3dd405,
-51b4cd3f,
+51b3fe3f,
90800284,
0580c205,
23818a80,
@@ -1915,18 +1881,18 @@ bd3f893d,
5b5bf98e,
3f800881,
ff065776,
-8b3880f7,
-8051f1e5,
+8b3880f3,
+e451f1e5,
3f81b839,
788d3d34,
86537752,
9a3dce05,
-51b29d3f,
+51b1ce3f,
7851f695,
3f865380,
08529a3d,
-d40551b2,
-8b3f9080,
+d40551b1,
+bc3f9080,
028405be,
0523818a,
800b923d,
@@ -1972,12 +1938,12 @@ f8d03f9a,
5f5f5877,
912e0981,
0680d238,
-800b8194,
-8c085b59,
+800b8193,
+cc085b59,
787a2780,
c4388197,
-f00b8197,
-d05d5b7b,
+b00b8197,
+905d5b7b,
7082055d,
227d2240,
58777f2e,
@@ -1996,7 +1962,7 @@ d05d5b7b,
04df3d0d,
8044a33d,
c4055281,
-94880851,
+93c80851,
f0f33f80,
085d8008,
802e8584,
@@ -2022,10 +1988,10 @@ f7993f94,
06a43893,
3d598453,
a21d5278,
-51af893f,
+51aeba3f,
a13d5886,
539c1d52,
-7751aefc,
+7751aead,
3f7a5377,
527851f1,
d03f861a,
@@ -2035,7 +2001,7 @@ d03f861a,
51f2c93f,
ac1d5f84,
53800852,
-7e51ade0,
+7e51ad91,
3f80085c,
800883e4,
387a51f2,
@@ -2044,12 +2010,12 @@ c43f8008,
349c1d59,
86537852,
a33dce05,
-51aeb13f,
+51ade23f,
7a51f2a9,
3f865380,
0852a33d,
-d40551ae,
-9f3f7d02,
+d40551ad,
+d03f7d02,
840580e2,
05237922,
9b3d2382,
@@ -2063,17 +2029,17 @@ d40551ae,
0580ea05,
23865377,
52a33de4,
-0551ade4,
+0551ad95,
3f847054,
7f53a43d,
ea055258,
-add63f86,
+ad873f86,
537852a3,
3dee0551,
-adca3f77,
+acfb3f77,
53a21d52,
a33df405,
-51adbd3f,
+51acee3f,
7b567b55,
7b547b53,
b052a33d,
@@ -2081,7 +2047,7 @@ c80551f5,
853f82c0,
397f51f1,
8b3f7884,
-298197f0,
+298197b0,
0561f805,
58881c57,
821c2256,
@@ -2092,7 +2058,7 @@ c80551f5,
81bd397c,
51f0e13f,
77842981,
-98c005f8,
+988005f8,
1d58881c,
57861c22,
56841c22,
@@ -2123,11 +2089,11 @@ ff065978,
098106bf,
387c3382,
1b22ec05,
-81948c08,
+8193cc08,
5e424080,
7c279e38,
821b2281,
-97d0405e,
+9790405e,
7e708205,
40225877,
7e2efeb1,
@@ -2135,7 +2101,7 @@ ff065978,
7b7926ec,
38821b22,
537a2252,
-80f7b451,
+80f49851,
eaf73f89,
1a335877,
812e0981,
@@ -2143,23 +2109,23 @@ eaf73f89,
7c338c1b,
821c22ec,
055e5f5d,
-800b8194,
-90085b58,
+800b8193,
+d0085b58,
777a27aa,
387a3359,
-8198b018,
+8197f018,
33407860,
2e098106,
9138811b,
-338198b8,
+338197f8,
1933415f,
7e602efd,
fe388118,
58797826,
db387a33,
-5280f7dc,
+5280f4c0,
51ea9e3f,
-81948808,
+8193c808,
51eb8d3f,
a33d0d04,
820b800c,
@@ -2208,14 +2174,14 @@ b705338b,
3d348154,
8b3dfc05,
53765277,
-51e0a33f,
+51e0a43f,
800881ff,
0655ff56,
74802e9e,
3881548b,
3df80553,
76527751,
-deef3f80,
+def03f80,
0881ff06,
5574802e,
8538893d,
@@ -2226,10 +2192,10 @@ deef3f80,
80567980,
2e853883,
a0805680,
-f7fc51e8,
+f4e051e8,
8c3f8176,
0c7981ff,
-0680f8a4,
+0680f588,
5259e7fd,
3f845481,
53805278,
@@ -2279,1451 +2245,1382 @@ c0a45675,
58708206,
70812a56,
58810653,
-795280f8,
-cc51e6b5,
+795280f5,
+b051e6b5,
3f8b3d0d,
-04f83d0d,
-7a5982c0,
-a0557880,
-2e853882,
-c0a45574,
-0870832a,
-70810651,
-56567480,
-2e8e3875,
-81065378,
-5280f98c,
-51e6823f,
-75842a70,
-81065155,
-74802e92,
-38758206,
-70812a54,
-55785280,
-f9b451e5,
-e43f7585,
+04fa3d0d,
+787a7c80,
+f5f05459,
+5754e6a1,
+3f755280,
+f5fc51e6,
+983f80f6,
+8051e691,
+3f73862e,
+83df3873,
+86269b38,
+73812e81,
+91388174,
+26ad3873,
+842e81ff,
+3873852e,
+82d1388a,
+9b397388,
+2e85f538,
+88742684,
+9f387398,
+2e888838,
+7383ffff,
+2e89b638,
+89fe3980,
+f68451e5,
+c83f7652,
+80f5fc51,
+e5bf3f80,
+f68051e5,
+b83f8f55,
+81752b77,
+06547380,
+2eb03874,
+8f26ab38,
+74842981,
+83d40554,
+73080480,
+f6905197,
+3980f698,
+51913980,
+f6a4518b,
+3980f6b4,
+51853980,
+f6cc51e4,
+fc3fff15,
+55748025,
+ffbe3888,
+cd3980f6,
+dc51e4e9,
+3f765280,
+f5fc51e4,
+e03f80f6,
+8051e4d9,
+3f8f5581,
+752b7706,
+5473802e,
+b6387482,
+2ea03874,
+82248838,
+74812e9c,
+38b93974,
+872e0981,
+06b13880,
+f6e851e4,
+ac3f8655,
+d23980f6,
+f8519839,
+80f78451,
+e49b3f80,
+55c13974,
+822e0981,
+068d3880,
+f79851e4,
+883f8155,
+ffad39ff,
+15557480,
+25ffa438,
+87d43980,
+f7a851e3,
+f03f7652,
+80f5fc51,
+e3e73f80,
+f68051e3,
+e03f8f55,
+81752b77,
+06547380,
+2ea03874,
+802e9438,
+807524a0,
+38748f24,
+9b3880f7,
+b851e3bd,
+3f923980,
+f7cc5183,
+bd397488,
+3880f7e0,
+5183b339,
+ff155574,
+8025c538,
+86fc3980,
+f7f851e3,
+983f7652,
+80f5fc51,
+e38f3f80,
+f68051e3,
+883f8f55,
+81752b77,
+06547380,
+2e80c238,
+748726bd,
+38748429,
+81849405,
+54730804,
+80f89051,
+a93980f8,
+a451a339,
+80f8a851,
+9d3980f8,
+b0519739,
+80f8b851,
+913980f8,
+c0518b39,
+80f8c851,
+853980f8,
+d451e2b9,
+3fff1555,
+748025ff,
+ab38868a,
+3980f8ec,
+51e2a63f,
+765280f5,
+fc51e29d,
+3f80f680,
+51e2963f,
+8f558175,
+2b770654,
+73802ebc,
+38748e2e,
+a038748e,
+24883874,
+8d2ea138,
+ab39748f,
+2e098106,
+a33880f9,
+8851e1e9,
+3f8e55d2,
+3980f99c,
+51e1de3f,
+8d55c739,
+80f9b051,
+e1d33f8c,
+55ffbb39,
+ff155574,
+8025ffb2,
+38859f39,
+80f9c851,
+e1bb3f76,
+5280f5fc,
+51e1b23f,
+80f68051,
+e1ab3f75,
+812e0981,
+0680f038,
+768f0654,
+738f2684,
+f5387384,
+298184b4,
+05547308,
+0480f9d4,
+51818f39,
+80f9e051,
+81883980,
+f9ec5181,
+813980f9,
+fc5180fa,
+3980fa88,
+5180f339,
+80fa9451,
+80ec3980,
+faa45180,
+e53980fa,
+b05180de,
+3980fac0,
+5180d739,
+80facc51,
+80d03980,
+fad85180,
+c93980fa,
+e45180c2,
+3980faf4,
+51bc3975,
+832e0981,
+06848738,
+76830654,
+73812ea0,
+38817426,
+a1387382,
+2e903873,
+832e0981,
+0683eb38,
+80fb8451,
+913980fb,
+94518b39,
+80fba451,
+853980fb,
+b451dff5,
+3f83cf39,
+80fbc451,
+dfeb3f76,
+5280f5fc,
+51dfe23f,
+80f68051,
+dfdb3f8f,
+5581752b,
+77065473,
+802e81ef,
+38748f26,
+81e93874,
+84298184,
+f4055473,
+0804768e,
+2a813270,
+81065154,
+73802e81,
+ce3880fb,
+d05181c4,
+3975812e,
+09810681,
+be3880fb,
+e45181b4,
+3975812e,
+09810681,
+ae3880fb,
+fc5181a4,
+3980fc98,
+51819d39,
+80fcac51,
+81963975,
+812e0981,
+06819038,
+80fcc051,
+81863975,
+812e0981,
+06818038,
+80fce051,
+80f63975,
+812e0981,
+0680f038,
+80fac051,
+80e63975,
+812e0981,
+0680e038,
+80facc51,
+80d63975,
+812e0981,
+0680d038,
+80fad851,
+80c63975,
+812e0981,
+0680c038,
+80fae451,
+b7397581,
+2e098106,
+b23880fc,
+f451a939,
+75812e09,
+8106a438,
+80fd8051,
+9b397581,
+2e098106,
+963880fd,
+8c518d39,
+75812e09,
+81068838,
+80f6d051,
+dddf3fff,
+15557480,
+25fdfe38,
+81b03980,
+fd9851dd,
+cc3f7652,
+80f5fc51,
+ddc33f80,
+f68051dd,
+bc3f8f55,
+81752b77,
+06547380,
+2eba3874,
+8c2680fd,
+38748429,
+8185b405,
+54730804,
+80fda851,
+9d3980fd,
+b8519739,
+80fdd851,
+913980fd,
+e8518b39,
+80fdf851,
+853980fe,
+8851dcf9,
+3f80ca39,
+74812eb2,
+38748124,
+88387480,
+2eb438b9,
+3974822e,
+95387483,
+2e098106,
+ac3880fe,
+9851dcd1,
+3f8255ff,
+933980fe,
+ac51dcc5,
+3f8155ff,
+873980fe,
+c051dcb9,
+3f7355fe,
+fb3980fe,
+d451fcb6,
+39ff1555,
+748025fe,
+eb3880fe,
+e85180c7,
+39765280,
+feec51dc,
+943f769e,
+80067088,
+2a545476,
+83e08006,
+708c2a53,
+5480ff88,
+51dbfa3f,
+768e0670,
+812a5354,
+80ff9851,
+dbeb3f76,
+81065473,
+802e8838,
+80ffa451,
+dbdb3f81,
+828c51db,
+d43fa139,
+80ffc051,
+dbcb3f73,
+5280f5fc,
+51dbc23f,
+80ffd851,
+dbbb3f76,
+5280f288,
+51dbb23f,
+883d0d04,
+e53d0d6e,
+02840580,
+f7053358,
+58a45381,
+85e8529d,
+3dd80551,
+9b8f3f89,
+3d55a853,
+81868c52,
+74519b81,
+3f81828c,
+51dafe3f,
+74568955,
+77548153,
+75085276,
+51f0e23f,
+80084c6b,
+53815275,
+70840557,
+0851f4ad,
+3fff1555,
+748025dc,
+38933d56,
+88557754,
+83537508,
+527651f0,
+b83f8008,
+4c6b5383,
+52757084,
+05570851,
+f4833fff,
+15557480,
+25dc3881,
+828c51da,
+a43f9d3d,
+0d04f93d,
+0d795882,
+c0a05577,
+802e8538,
+82c0a455,
+74087083,
2a708106,
-56577480,
-2e923875,
-84067082,
-2a545578,
-5280f9e0,
-51e5c63f,
-805882c0,
-94557881,
+51565674,
+802e8e38,
+75810653,
+775280ff,
+e851d9f1,
+3f75842a,
+70810651,
+5574802e,
+92387582,
+0670812a,
+54557752,
+81809051,
+d9d33f75,
+852a7081,
+06565774,
+802e9238,
+75840670,
+822a5455,
+77528180,
+bc51d9b5,
+3f75b806,
+5574802e,
+80c63875,
+87065574,
+bf3882c0,
+90557780,
2e853882,
-c0905574,
+c0945574,
08557481,
2e098106,
-83387458,
-75b80655,
-74802e92,
-38758706,
-55748b38,
-77802e86,
-387851fc,
-ec3f7681,
-06557480,
-2e82bd38,
-75822a70,
-81065155,
-74802e8d,
-38785280,
-fa8851e4,
-f03f82a4,
-39785280,
-fac451e4,
-e43f83fc,
-80567880,
-2e853883,
-f8805681,
-5182d73f,
-835380d0,
-527551fb,
-d23f800b,
-80082481,
-e4388008,
-81065574,
-81cb3880,
-08842a70,
-81065155,
-74802e88,
-3880fb84,
-5181d639,
-8008852a,
-70810651,
-5574802e,
-883880fb,
-9c5181c1,
-39800886,
+a7387751,
+f0e33f84,
+528051fd,
+d33f80e4,
+5183a93f,
+84528051,
+fdc63f80,
+e451839c,
+3f845280,
+51fdb93f,
+76810655,
+74802e82,
+bd387582,
2a708106,
51557480,
-2e883880,
-fbb45181,
-ac398653,
+2e8d3877,
+528180e4,
+51d8c63f,
+82a43977,
+528181a0,
+51d8ba3f,
+83fc8056,
+77802e85,
+3883f880,
+56815182,
+d73f8353,
80d05275,
-51faf83f,
+51efa83f,
800b8008,
-24818a38,
+2481e438,
80088106,
-5574802e,
-883880fb,
-cc518189,
-39800881,
+557481cb,
+38800884,
2a708106,
51557480,
-2e883880,
-fbec5180,
-f4398008,
-832a7081,
+2e883881,
+81e05181,
+d6398008,
+852a7081,
06515574,
802e8838,
-80fc8c51,
-80df3988,
-5380d052,
-7551faab,
-3f800b80,
-0824be38,
-8008822a,
-81327081,
-06515574,
-bc388a53,
-80d05275,
-51fa8c3f,
-800b8008,
-249f3880,
-08872a70,
+8181f851,
+81c13980,
+08862a70,
+81065155,
+74802e88,
+38818290,
+5181ac39,
+865380d0,
+527551ee,
+ce3f800b,
+80082481,
+8a388008,
+81065574,
+802e8838,
+8182a851,
+81893980,
+08812a70,
81065155,
-74802e9d,
-38925380,
+74802e88,
+388182c8,
+5180f439,
+8008832a,
+70810651,
+5574802e,
+88388182,
+e85180df,
+39885380,
d0527551,
-f9ed3f80,
-08802587,
-3880fcac,
-518b3980,
-fccc5185,
-3980fcdc,
-51e2ca3f,
-8198e019,
-33568454,
-81538152,
-7881ff06,
-705257f8,
-a83f8008,
-822a7081,
-06515574,
-8198e01a,
-34759338,
-74802e8e,
-387651e6,
-cb3f8008,
-527651eb,
-e63f8a3d,
-0d04803d,
-0d728198,
-e0113380,
-0c51823d,
-0d04fd3d,
-0d755480,
-53727425,
-9b3882c0,
-80085282,
-c0800870,
-73315151,
-8ad79771,
-27f13881,
-1353e239,
-853d0d04,
-fd3d0d78,
-0284059f,
-053377bf,
-ffff0655,
-52547080,
-2e863872,
-880a0753,
-72820a07,
-53800b83,
-f68c0870,
-842a7081,
-06515152,
-5270722e,
-9d388112,
-52737227,
-85388051,
-9d3983f6,
-8c087084,
-2a708106,
-51515170,
-e5387683,
-f6800c72,
-83f6840c,
-81517080,
-0c853d0d,
-04fc3d0d,
-777a0288,
-05a30533,
-79bfffff,
-06565356,
-5470802e,
-86387288,
-0a075372,
-840a0753,
-800b83f6,
-8c087084,
+ee813f80,
+0b800824,
+be388008,
+822a8132,
+70810651,
+5574bc38,
+8a5380d0,
+527551ed,
+e23f800b,
+8008249f,
+38800887,
2a708106,
-51515252,
-70722e99,
-38811252,
-717526b7,
-3883f68c,
+51557480,
+2e9d3892,
+5380d052,
+7551edc3,
+3f800880,
+25873881,
+8388518b,
+398183a8,
+51853981,
+83b851d6,
+a03f8198,
+a0183356,
+84548153,
+81527781,
+ff067052,
+57ebfe3f,
+8008822a,
+70810651,
+55748198,
+a0193475,
+93387480,
+2e8e3876,
+51daa13f,
+80085276,
+51dfbc3f,
+893d0d04,
+803d0d72,
+8198a011,
+33800c51,
+823d0d04,
+fd3d0d75,
+54805372,
+74259b38,
+82c08008,
+5282c080,
+08707331,
+51518ad7,
+977127f1,
+38811353,
+e239853d,
+0d04fd3d,
+0d780284,
+059f0533,
+77bfffff,
+06555254,
+70802e86,
+3872880a,
+07537282,
+0a075380,
+0b83f68c,
0870842a,
70810651,
-515170e9,
-3873802e,
-84388074,
+51525270,
+722e9d38,
+81125273,
+72278538,
+80519d39,
+83f68c08,
+70842a70,
+81065151,
+5170e538,
+7683f680,
0c7283f6,
-840c800b,
+840c8151,
+70800c85,
+3d0d04fc,
+3d0d777a,
+028805a3,
+053379bf,
+ffff0656,
+53565470,
+802e8638,
+72880a07,
+5372840a,
+0753800b,
83f68c08,
-70810651,
+70842a70,
+81065151,
52527072,
2e993881,
-12527472,
-27853880,
-519a3983,
+12527175,
+26b73883,
f68c0870,
-81065151,
+842a7081,
+06515151,
70e93873,
-802e8738,
-83f68808,
-740c8151,
-70800c86,
-3d0d04f6,
-3d0d7d7f,
-5a5a817d,
-9fffff06,
-98808007,
-59578056,
-757927af,
-38751655,
-82808054,
-81538c3d,
-fc055274,
-1851feb9,
-3f800881,
-ff067a16,
-565702aa,
-05227523,
-81165675,
-79278438,
-76d33876,
-800c8c3d,
-0d04f63d,
-0d7d7f71,
-30707307,
-80257073,
-a0260751,
-5157595a,
-80567476,
-2e098106,
-81ee3882,
-80805481,
-5381aa52,
-888851fd,
-833f8008,
-81ff0656,
-82808054,
-815380d5,
-52888051,
-fcee3f80,
-08760656,
-75802eb1,
+802e8438,
+80740c72,
+83f6840c,
+800b83f6,
+8c087081,
+06515252,
+70722e99,
+38811252,
+74722785,
+3880519a,
+3983f68c,
+08708106,
+515170e9,
+3873802e,
+873883f6,
+8808740c,
+81517080,
+0c863d0d,
+04f63d0d,
+7d7f5a5a,
+817d9fff,
+ff069880,
+80075957,
+80567579,
+27af3875,
+16558280,
+80548153,
+8c3dfc05,
+52741851,
+feb93f80,
+0881ff06,
+7a165657,
+02aa0522,
+75238116,
+56757927,
+843876d3,
+3876800c,
+8c3d0d04,
+f63d0d7d,
+7f713070,
+73078025,
+7073a026,
+07515157,
+595a8056,
+74762e09,
+810681ee,
38828080,
-548153a5,
-52988080,
-51fcd53f,
+54815381,
+aa528888,
+51fd833f,
800881ff,
+06568280,
+80548153,
+80d55288,
+8051fcee,
+3f800876,
06567580,
-2e973882,
+2eb13882,
80805481,
-53ff1852,
-98808051,
-fcba3f80,
-0881ff06,
-567c9fff,
-ff069880,
-80075980,
-57767827,
-a8387580,
-2e9e3876,
-177a1170,
-22515755,
-82808054,
-81537552,
-741951fc,
-873f8008,
+53a55298,
+808051fc,
+d53f8008,
81ff0656,
-811757d5,
-3975802e,
-96388280,
-80548153,
-a9529880,
-8051fbe8,
+75802e97,
+38828080,
+548153ff,
+18529880,
+8051fcba,
3f800881,
-ff065677,
-18558280,
+ff06567c,
+9fffff06,
+98808007,
+59805776,
+7827a838,
+75802e9e,
+3876177a,
+11702251,
+57558280,
80548153,
-8c3dfc05,
-527419fe,
-0551fcb1,
-3f800876,
-06567580,
-2e9e3881,
-7a160288,
-05aa0522,
-fe122270,
-7232872a,
-70750651,
-51525956,
-5674c438,
-75800c8c,
-3d0d04f7,
-3d0d8280,
-80548053,
-81a9ec52,
-81c051fb,
-f03f8280,
-80548053,
-81a9e852,
-81e051fb,
-e03f8158,
+75527419,
+51fc873f,
+800881ff,
+06568117,
+57d53975,
+802e9638,
82808054,
-80539881,
-915281c0,
-51fae93f,
-80087806,
-5776802e,
-83387757,
+8153a952,
+98808051,
+fbe83f80,
+0881ff06,
+56771855,
82808054,
-8053fdf5,
-b6fdef52,
-848051fa,
-cb3f8008,
-81ff0677,
-06577680,
-2e833877,
-57828080,
-54775381,
-acf85284,
-8451faac,
-3f800881,
-ff067706,
-5776802e,
-83387757,
-8a3d5982,
-80805477,
-53785280,
-51faf23f,
+81538c3d,
+fc055274,
+19fe0551,
+fcb13f80,
+08760656,
+75802e9e,
+38817a16,
+028805aa,
+0522fe12,
+22707232,
+872a7075,
+06515152,
+59565674,
+c4387580,
+0c8c3d0d,
+04f73d0d,
+82808054,
+80538199,
+d45281c0,
+51fbf03f,
+82808054,
+80538199,
+d05281e0,
+51fbe03f,
+81588280,
+80548053,
+98819152,
+81c051fa,
+e93f8008,
+78065776,
+802e8338,
+77578280,
+80548053,
+fdf5b6fd,
+ef528480,
+51facb3f,
800881ff,
06770657,
76802e83,
38775782,
80805477,
-53795284,
-8651f9f0,
-3f800881,
-ff067706,
-5776802e,
-83387757,
-82808054,
-80537852,
-848051fa,
-b83f8008,
+5381acf8,
+52848451,
+faac3f80,
+0881ff06,
+77065776,
+802e8338,
+77578a3d,
+59828080,
+54775378,
+528051fa,
+f23f8008,
81ff0677,
06577680,
2e833877,
-5779fdf5,
-b6fdef32,
-70307072,
-07700970,
-9f2c7c06,
-5c515157,
-55828080,
-54805378,
-52848451,
-fa833f80,
+57828080,
+54775379,
+52848651,
+f9f03f80,
0881ff06,
77065776,
802e8338,
-81577781,
-06587987,
-d6c1acf8,
-2e833880,
-58805576,
-802e8838,
-77802e83,
-38815574,
-81ff0680,
-0c8b3d0d,
-04fd3d0d,
-82808054,
-805381a9,
-ec085281,
-c051f8d4,
-3f828080,
-54805381,
-a9e80852,
-81e051f8,
-c33f853d,
-0d04fc3d,
-0d76912b,
-55828080,
-54805374,
-5281e051,
-f8aa3f80,
-0881ff06,
-800c863d,
-0d04fa3d,
-0d828080,
-54815381,
-aa528888,
-51f88d3f,
+77578280,
+80548053,
+78528480,
+51fab83f,
800881ff,
-06557480,
-2e81b038,
-82808054,
-815380d5,
-52888051,
-f7f23f80,
-0881ff06,
-5574802e,
-81953882,
+06770657,
+76802e83,
+38775779,
+fdf5b6fd,
+ef327030,
+70720770,
+09709f2c,
+7c065c51,
+51575582,
+80805480,
+53785284,
+8451fa83,
+3f800881,
+ff067706,
+5776802e,
+83388157,
+77810658,
+7987d6c1,
+acf82e83,
+38805880,
+5576802e,
+88387780,
+2e833881,
+557481ff,
+06800c8b,
+3d0d04fd,
+3d0d8280,
+80548053,
+8199d408,
+5281c051,
+f8d43f82,
+80805480,
+538199d0,
+085281e0,
+51f8c33f,
+853d0d04,
+fc3d0d76,
+912b5582,
+80805480,
+53745281,
+e051f8aa,
+3f800881,
+ff06800c,
+863d0d04,
+fa3d0d82,
80805481,
-53818052,
-888851f7,
-d73f8008,
+5381aa52,
+888851f8,
+8d3f8008,
81ff0655,
-74802e80,
-fa388280,
+74802e81,
+b0388280,
80548153,
-81aa5288,
-8851f7bc,
+80d55288,
+8051f7f2,
3f800881,
ff065574,
-802e80df,
+802e8195,
38828080,
-54815380,
-d5528880,
-51f7a13f,
+54815381,
+80528888,
+51f7d73f,
800881ff,
06557480,
-2e80c438,
+2e80fa38,
82808054,
-8153b052,
-98808051,
-f7863f80,
+815381aa,
+52888851,
+f7bc3f80,
0881ff06,
5574802e,
-aa388280,
+80df3882,
+80805481,
+5380d552,
+888051f7,
+a13f8008,
+81ff0655,
+74802e80,
+c4388280,
80548153,
-883dfc05,
-52988080,
-51f7ce3f,
-800881ff,
-06028405,
-9a052257,
-557583ff,
-ff2e0981,
-06d33874,
-800c883d,
-0d04fd3d,
-0d828080,
-54805381,
-5280d851,
-f6ba3f85,
-3d0d04fa,
-3d0d8280,
-80548053,
-883dfc05,
-5280d851,
-f7873f80,
-08810655,
-83567480,
-2e863802,
-9b053356,
-75800c88,
-3d0d04fe,
-3d0d800b,
-83f68c08,
-70842a70,
-81065151,
-52527072,
-2ea23881,
-a9f00853,
-81125272,
-72278538,
-80519f39,
-83f68c08,
-70842a70,
-81065151,
-5170e538,
-7483f680,
-0c810a0b,
-83f6840c,
-81517080,
-0c843d0d,
+b0529880,
+8051f786,
+3f800881,
+ff065574,
+802eaa38,
+82808054,
+8153883d,
+fc055298,
+808051f7,
+ce3f8008,
+81ff0602,
+84059a05,
+22575575,
+83ffff2e,
+098106d3,
+3874800c,
+883d0d04,
+fd3d0d82,
+80805480,
+53815280,
+d851f6ba,
+3f853d0d,
+04fa3d0d,
+82808054,
+8053883d,
+fc055280,
+d851f787,
+3f800881,
+06558356,
+74802e86,
+38029b05,
+33567580,
+0c883d0d,
04fe3d0d,
-7483f68c,
-0870812a,
-70810651,
-51525370,
-802e80e4,
-3880d5ff,
-0b81aa84,
-0c83f680,
-0881a9fc,
-0c83f684,
-0870bfff,
-ff0681a9,
-f80c709c,
+800b83f6,
+8c087084,
2a708106,
-51525270,
-81aa8034,
-719d2a70,
-81065151,
-70802e89,
-38810b81,
-a9f4349b,
-39719e2a,
-70810651,
-5170802e,
-8938820b,
-81a9f434,
-86397081,
-a9f43481,
-a9f4730c,
-81518439,
-70730c70,
-800c843d,
-0d04fb3d,
-0d873dfc,
-0551fef1,
-3f800881,
-ff065372,
-802e80c5,
-38758c11,
-33545572,
-bc387433,
-5372822e,
-0981068e,
-38841508,
-88160871,
-0c548153,
-a6397281,
-2e098106,
-9c388415,
-08700851,
-53828080,
-52725190,
-15085372,
-2d800881,
-ff065383,
-39805372,
-800c873d,
-0d04f93d,
-0d797b57,
-57807056,
-5474802e,
-8a387514,
-51ba7134,
-81145475,
-14751870,
-3370842a,
-545a5452,
-8186f011,
+51515252,
+70722ea2,
+388199d8,
+08538112,
+52727227,
+85388051,
+9f3983f6,
+8c087084,
+2a708106,
+51515170,
+e5387483,
+f6800c81,
+0a0b83f6,
+840c8151,
+70800c84,
+3d0d04fe,
+3d0d7483,
+f68c0870,
+812a7081,
+06515152,
+5370802e,
+80e43880,
+e1a10b81,
+99ec0c83,
+f6800881,
+99e40c83,
+f6840870,
+bfffff06,
+8199e00c,
+709c2a70,
+81065152,
+52708199,
+e834719d,
+2a708106,
+51517080,
+2e893881,
+0b8199dc,
+349b3971,
+9e2a7081,
+06515170,
+802e8938,
+820b8199,
+dc348639,
+708199dc,
+348199dc,
+730c8151,
+84397073,
+0c70800c,
+843d0d04,
+fb3d0d87,
+3dfc0551,
+fef13f80,
+0881ff06,
+5372802e,
+80c53875,
+8c113354,
+5572bc38,
+74335372,
+822e0981,
+068e3884,
+15088816,
+08710c54,
+8153a639,
+72812e09,
+81069c38,
+84150870,
+08515382,
+80805272,
+51901508,
+53722d80,
+0881ff06,
+53833980,
+5372800c,
+873d0d04,
+f93d0d79,
+7b575780,
+70565474,
+802e8a38,
+751451ba,
+71348114,
+54751475,
+18703370,
+842a545a,
+54528186,
+b4113372,
+34811476,
+1174338f,
+06535354,
+8186b411,
33723481,
-14761174,
-338f0653,
-53548186,
-f0113372,
-34811481,
-16565485,
-7527c238,
-75145180,
-71347580,
+14811656,
+54857527,
+c2387514,
+51807134,
+75800c89,
+3d0d04f9,
+3d0d797b,
+83123358,
+82123357,
+81123356,
+71335581,
+86c45470,
+535957c8,
+bc3f7780,
0c893d0d,
-04f93d0d,
-797b8312,
-33588212,
-33578112,
-33567133,
-55818780,
-54705359,
-57d4e63f,
-77800c89,
+04fe3d0d,
+8198a408,
+81058306,
+708198a4,
+0c701011,
+70882981,
+98a80554,
+51537451,
+fee23f84,
3d0d04fe,
-3d0d8198,
-e4088105,
+3d0d8199,
+88088105,
83067081,
-98e40c70,
-10117088,
-298198e8,
-05545153,
-7451fee2,
+99880c70,
+90298199,
+8c055353,
+7451ff97,
3f843d0d,
-04fe3d0d,
-8199c808,
-81058306,
-708199c8,
-0c709029,
-8199cc05,
-53537451,
-ff973f84,
-3d0d04ff,
-3d0d819a,
-8c228105,
-5170819a,
-8c23833d,
-0d04fe3d,
-0d745180,
-52881108,
-802e9b38,
-819a8c22,
-82122271,
-71317083,
-ffff0651,
-51525370,
-82268338,
-81527181,
-ff06800c,
-843d0d04,
-ff3d0d73,
-75982b70,
-982c5153,
-51029605,
-22712381,
-9a8c2282,
-12237184,
-12347670,
-0888130c,
-52833d0d,
-04f53d0d,
-7d7f6362,
-982b7098,
-2c029405,
-80c20522,
-5f515e5e,
-59598057,
-76782780,
-de387856,
-7551fefe,
-3f800881,
-ff065574,
-802eb638,
-8816087c,
-082e0981,
-06b53884,
-1633557a,
-752e0981,
-06a93875,
-22558057,
-79752e8e,
-38797531,
-902b5576,
-75248338,
-81577655,
-74802eb6,
-387b5479,
-537a5275,
-51a73981,
-178c1757,
-57777726,
-ffa63877,
-10187084,
-29f40554,
-5578528c,
-195193c5,
-3f7b5479,
-537a5278,
-51febd3f,
-81577680,
-0c8d3d0d,
-04803d0d,
-72518180,
-710c81a1,
-d40b800c,
-823d0d04,
-fe3d0d74,
-81a1d452,
-5380ff52,
-70087308,
-2e098106,
-89388071,
-0c800b84,
-120cff12,
-88125252,
-718025e4,
-38843d0d,
-04f63d0d,
-02b30533,
-70525bd7,
-ec3f8058,
-80578008,
-56819a90,
-2281115a,
-5a78819a,
-90237983,
-ffff0655,
-84805480,
-538f527a,
-51dc833f,
-8c3d0d04,
-f33d0d7f,
-61636573,
-1270335b,
-595e5f5d,
-5e7580dc,
-38817534,
-7581a1d8,
-0b81a1d4,
-5a5a5a7d,
-822b1c78,
-08881a5a,
-56567476,
-082e0981,
-06ad3880,
-56757b27,
-a6387b57,
-76708405,
-58085574,
-79082e09,
-81068c38,
-7a547c53,
-7b527551,
-ffa63f81,
-16567a76,
-26de3881,
-1a881a5a,
-5a80ff7a,
-27ffb438,
-8f3d0d04,
-fed43d0d,
-81af3d08,
-5d807081,
-a1d40bb1,
-3d5f5b5c,
-57780855,
-74802eb3,
-38841908,
-802eac38,
-80567577,
-279a3874,
-af3d5b58,
-79708405,
-5b085574,
-782e9438,
-81165676,
-7626ed38,
-78087c70,
-84055e0c,
-81175781,
-1b881a5a,
-5b80ff7b,
-27ffba38,
-80567577,
-2792388e,
-3d587518,
-55807534,
-81165676,
-7626f338,
-80567577,
-27ae38ae,
-3d587770,
-84055908,
-55747d08,
-2e098106,
-93387654,
-81ae3dfb,
-801154fc,
-80055275,
-51fded3f,
-81165676,
-7626d738,
-80567577,
-27b53881,
-b03d0870,
-08903db1,
-3d5c5c59,
-55787084,
-055a0855,
-74782e09,
-81069038,
-751a7033,
-51557480,
-2e853881,
-558b3981,
-16567676,
-26db3880,
-5574800c,
-81ae3d0d,
-04fb3d0d,
-029f0533,
-568055b0,
-3975752e,
-a8387582,
-2b81a9d4,
-05751176,
-81ff0653,
-5153d284,
-3f800876,
-5254d1fc,
-3f735280,
-0851fde0,
-3f800873,
-34811555,
-e3a63f80,
-087526c9,
-38873d0d,
-04ef3d0d,
-65028405,
-80cf0533,
-02880580,
-d2052288,
-13705971,
-5872982b,
-70982c58,
-5d404242,
-5e80c052,
-819bd451,
-fa8f3f80,
-0881ff06,
-5978802e,
-82bb3881,
-9bdc5cbf,
-0b819bd4,
-5b5b881a,
-08802e9e,
-38819a8c,
-22821b22,
-71713170,
-83ffff06,
-515b435f,
-82792786,
-387b51fb,
-8b3fff1b,
-8c1b8c1e,
-5e5b5b7a,
-8025cf38,
-7c51faf8,
-3f80705a,
-5f9a3978,
-81ff0651,
-d0d63f88,
-1e088008,
-082e0981,
-06833881,
-5f811959,
-e1fe3f80,
-087926df,
-38805c7d,
-087c2e80,
-d9388c1e,
-5b7e802e,
-8838841e,
-087c26bd,
-38800b81,
-a1d45a5a,
-78088c38,
-7c08790c,
-7a08841a,
-0ca73981,
-1a881a5a,
-5a80ff7a,
-27e63887,
-f85381a1,
-d45281a1,
-dc518da5,
-3f7c0881,
-a1d40c7a,
-0881a1d8,
-0c811c84,
-1c5c5c7d,
-087c26ff,
-ac38819a,
-9c0bfc11,
-5b5b805d,
-8f5c7c84,
-29819a94,
-05598819,
-08881f08,
-2ebc3878,
-51f7bb3f,
-800881ff,
-06597880,
-2eac3879,
-3351e8ea,
-3f800881,
-ff065978,
-802e9b38,
-7d088429,
-8c05587d,
-577a567f,
-55848154,
-80538f52,
-793351d5,
-f93fff1c,
-831e8c1c,
-8c1e5e5c,
-5e5c7b80,
-25ffa338,
-6051fcc5,
-3f933d0d,
-04f53d0d,
-62028405,
-b7053302,
-880580c2,
-0522028c,
-0580c605,
-225d5b5d,
-5b788480,
-2e893878,
-84812e98,
-389f3963,
-587a577e,
-56795578,
-54805390,
-527b51d5,
-a13f8a39,
-7a537952,
-7b51fcc1,
-3f8d3d0d,
-04fdf73d,
-0d0288af,
-05335a80,
-5981c239,
-8b3d5588,
-80538052,
-74518cf4,
-3f7881ff,
-0651cdf8,
-3f800808,
-5d80750c,
-805c8056,
-ad397876,
-2ea53874,
-08842915,
-8c117781,
-ff065376,
-08810577,
-0c5154cd,
-cf3f8008,
-08740c84,
-15088105,
-84160c81,
-1656def8,
-3f800876,
-26cc3880,
-0b819a94,
-57587408,
-822b9011,
-55577387,
-ff26b938,
-7551f59e,
-3f800881,
-ff065473,
-802e9d38,
-84163354,
-78742e09,
-81069138,
-74178c05,
-88170871,
-0c547408,
-8105750c,
-81188c17,
-57588f78,
-27ffbb38,
-7453819a,
-90228111,
-55557381,
-9a902374,
-83ffff06,
-527951fa,
-f03f8119,
-59de853f,
-80087926,
-feb63882,
-8b3d0d04,
-fa3d0d02,
-a3053302,
-8405ae05,
-22575775,
-84802e09,
-8106a938,
-795502b2,
-05225476,
-982b7098,
-2c545690,
-52819a94,
-51f4ea3f,
-800881ff,
-06567580,
-2e863876,
-51fde23f,
-883d0d04,
-ff3d0d02,
-8f053370,
-842981a9,
-d4050288,
-05930533,
-71057033,
-800c5152,
-52833d0d,
-04fa3d0d,
-80e3a553,
-80528f51,
-ccdb3f80,
-e5d05380,
-529051cc,
-d03f800b,
-81a9d457,
-57805574,
-16548174,
-34811555,
-837527f3,
-38811784,
-17575783,
-7727e638,
-883d0d04,
-8c08028c,
-0cf53d0d,
-8c089405,
-089d388c,
-088c0508,
-8c089005,
-088c0888,
-05085856,
-5473760c,
-7484170c,
-81bf3980,
-0b8c08f0,
-050c800b,
-8c08f405,
-0c8c088c,
+048c0802,
+8c0cf53d,
+0d8c0894,
+05089d38,
+8c088c05,
+088c0890,
05088c08,
-90050856,
-54738c08,
-f0050c74,
-8c08f405,
-0c8c08f8,
-058c08f0,
-05565688,
-70547553,
-76525486,
-cb3fa00b,
-8c089405,
-08318c08,
-ec050c8c,
-08ec0508,
-80249d38,
+88050858,
+56547376,
+0c748417,
+0c81bf39,
800b8c08,
-f0050c8c,
-08ec0508,
-308c08f8,
-0508712a,
-8c08f405,
-0c54b939,
-8c08f805,
-088c08ec,
-05082b8c,
-08e8050c,
-8c08f805,
-088c0894,
-05082a8c,
+f0050c80,
+0b8c08f4,
+050c8c08,
+8c05088c,
+08900508,
+5654738c,
08f0050c,
-8c08fc05,
-088c0894,
-05082a70,
+748c08f4,
+050c8c08,
+f8058c08,
+f0055656,
+88705475,
+53765254,
+86cb3fa0,
+0b8c0894,
+0508318c,
+08ec050c,
+8c08ec05,
+0880249d,
+38800b8c,
+08f0050c,
+8c08ec05,
+08308c08,
+f8050871,
+2a8c08f4,
+050c54b9,
+398c08f8,
+05088c08,
+ec05082b,
8c08e805,
-08078c08,
-f4050c54,
+0c8c08f8,
+05088c08,
+9405082a,
8c08f005,
-088c08f4,
+0c8c08fc,
05088c08,
-88050858,
-56547376,
-0c748417,
-0c8c0888,
-0508800c,
-8d3d0d8c,
-0c048c08,
-028c0cfd,
-3d0d8053,
-8c088c05,
-08528c08,
-88050851,
-82de3f80,
-0870800c,
-54853d0d,
+9405082a,
+708c08e8,
+0508078c,
+08f4050c,
+548c08f0,
+05088c08,
+f405088c,
+08880508,
+58565473,
+760c7484,
+170c8c08,
+88050880,
+0c8d3d0d,
8c0c048c,
08028c0c,
-fd3d0d81,
+fd3d0d80,
538c088c,
0508528c,
08880508,
-5182b93f,
+5182de3f,
80087080,
0c54853d,
0d8c0c04,
8c08028c,
-0cf93d0d,
+0cfd3d0d,
+81538c08,
+8c050852,
+8c088805,
+085182b9,
+3f800870,
+800c5485,
+3d0d8c0c,
+048c0802,
+8c0cf93d,
+0d800b8c,
+08fc050c,
+8c088805,
+088025ab,
+388c0888,
+0508308c,
+0888050c,
800b8c08,
+f4050c8c,
+08fc0508,
+8838810b,
+8c08f405,
+0c8c08f4,
+05088c08,
fc050c8c,
-08880508,
+088c0508,
8025ab38,
-8c088805,
+8c088c05,
08308c08,
-88050c80,
-0b8c08f4,
+8c050c80,
+0b8c08f0,
050c8c08,
fc050888,
38810b8c,
-08f4050c,
-8c08f405,
+08f0050c,
+8c08f005,
088c08fc,
+050c8053,
+8c088c05,
+08528c08,
+88050851,
+81a73f80,
+08708c08,
+f8050c54,
+8c08fc05,
+08802e8c,
+388c08f8,
+0508308c,
+08f8050c,
+8c08f805,
+0870800c,
+54893d0d,
+8c0c048c,
+08028c0c,
+fb3d0d80,
+0b8c08fc,
050c8c08,
-8c050880,
-25ab388c,
-088c0508,
-308c088c,
-050c800b,
-8c08f005,
-0c8c08fc,
-05088838,
-810b8c08,
-f0050c8c,
-08f00508,
+88050880,
+2593388c,
+08880508,
+308c0888,
+050c810b,
8c08fc05,
-0c80538c,
+0c8c088c,
+05088025,
+8c388c08,
+8c050830,
+8c088c05,
+0c81538c,
088c0508,
528c0888,
-05085181,
-a73f8008,
-708c08f8,
-050c548c,
-08fc0508,
-802e8c38,
+050851ad,
+3f800870,
8c08f805,
-08308c08,
-f8050c8c,
+0c548c08,
+fc050880,
+2e8c388c,
08f80508,
-70800c54,
-893d0d8c,
-0c048c08,
-028c0cfb,
-3d0d800b,
-8c08fc05,
-0c8c0888,
-05088025,
-93388c08,
-88050830,
-8c088805,
-0c810b8c,
+308c08f8,
+050c8c08,
+f8050870,
+800c5487,
+3d0d8c0c,
+048c0802,
+8c0cfd3d,
+0d810b8c,
08fc050c,
-8c088c05,
-0880258c,
-388c088c,
-0508308c,
-088c050c,
-81538c08,
-8c050852,
+800b8c08,
+f8050c8c,
+088c0508,
8c088805,
-0851ad3f,
-8008708c,
-08f8050c,
-548c08fc,
-0508802e,
-8c388c08,
-f8050830,
-8c08f805,
-0c8c08f8,
-05087080,
-0c54873d,
-0d8c0c04,
-8c08028c,
-0cfd3d0d,
-810b8c08,
-fc050c80,
-0b8c08f8,
+0827ac38,
+8c08fc05,
+08802ea3,
+38800b8c,
+088c0508,
+2499388c,
+088c0508,
+108c088c,
050c8c08,
-8c05088c,
-08880508,
-27ac388c,
+fc050810,
+8c08fc05,
+0cc9398c,
08fc0508,
-802ea338,
-800b8c08,
-8c050824,
-99388c08,
-8c050810,
-8c088c05,
-0c8c08fc,
-0508108c,
-08fc050c,
-c9398c08,
-fc050880,
-2e80c938,
-8c088c05,
-088c0888,
-050826a1,
-388c0888,
-05088c08,
-8c050831,
-8c088805,
-0c8c08f8,
+802e80c9,
+388c088c,
05088c08,
-fc050807,
+88050826,
+a1388c08,
+8805088c,
+088c0508,
+318c0888,
+050c8c08,
+f805088c,
+08fc0508,
+078c08f8,
+050c8c08,
+fc050881,
+2a8c08fc,
+050c8c08,
+8c050881,
+2a8c088c,
+050cffaf,
+398c0890,
+0508802e,
+8f388c08,
+88050870,
+8c08f405,
+0c518d39,
8c08f805,
-0c8c08fc,
-0508812a,
-8c08fc05,
-0c8c088c,
-0508812a,
-8c088c05,
-0cffaf39,
-8c089005,
-08802e8f,
-388c0888,
-0508708c,
-08f4050c,
-518d398c,
-08f80508,
-708c08f4,
-050c518c,
-08f40508,
-800c853d,
-0d8c0c04,
-fc3d0d78,
-77795656,
-52837227,
-8c387474,
-07830651,
-70802eb0,
-38ff1252,
-71ff2ea0,
-38743374,
-33525372,
-712e0981,
-06bd3881,
-158115ff,
-14545555,
-71ff2e09,
-8106e238,
-800b800c,
-863d0d04,
-74745451,
-70087308,
-2e098106,
-8f388411,
-8414fc14,
-54545171,
-8326e938,
-70735555,
-ffaf3972,
-7131800c,
-863d0d04,
-fc3d0d76,
-70797b55,
-5555558f,
-72278c38,
-72750783,
-06517080,
-2ea738ff,
-125271ff,
-2e983872,
-70810554,
-33747081,
-055634ff,
-125271ff,
-2e098106,
-ea387480,
+08708c08,
+f4050c51,
+8c08f405,
+08800c85,
+3d0d8c0c,
+04fc3d0d,
+78777956,
+56528372,
+278c3874,
+74078306,
+5170802e,
+b038ff12,
+5271ff2e,
+a0387433,
+74335253,
+72712e09,
+8106bd38,
+81158115,
+ff145455,
+5571ff2e,
+098106e2,
+38800b80,
0c863d0d,
-04745172,
-70840554,
-08717084,
-05530c72,
-70840554,
-08717084,
-05530c72,
-70840554,
-08717084,
-05530c72,
-70840554,
-08717084,
-05530cf0,
-1252718f,
-26c93883,
-72279538,
+04747454,
+51700873,
+082e0981,
+068f3884,
+118414fc,
+14545451,
+718326e9,
+38707355,
+55ffaf39,
+72713180,
+0c863d0d,
+04fc3d0d,
+7670797b,
+55555555,
+8f72278c,
+38727507,
+83065170,
+802ea738,
+ff125271,
+ff2e9838,
+72708105,
+54337470,
+81055634,
+ff125271,
+ff2e0981,
+06ea3874,
+800c863d,
+0d047451,
72708405,
54087170,
8405530c,
-fc125271,
-8326ed38,
-7054ff83,
-39fa3d0d,
-787a7c72,
-72725757,
-57595656,
-747627b2,
-38761551,
-757127aa,
-38707717,
-ff145455,
-5371ff2e,
-9638ff14,
-ff145454,
-72337434,
+72708405,
+54087170,
+8405530c,
+72708405,
+54087170,
+8405530c,
+72708405,
+54087170,
+8405530c,
+f0125271,
+8f26c938,
+83722795,
+38727084,
+05540871,
+70840553,
+0cfc1252,
+718326ed,
+387054ff,
+8339fc3d,
+0d767971,
+028c059f,
+05335755,
+53558372,
+278a3874,
+83065170,
+802ea238,
ff125271,
-ff2e0981,
-06ec3875,
-800c883d,
-0d04768f,
-269738ff,
+ff2e9338,
+73737081,
+055534ff,
125271ff,
-2eed3872,
-70810554,
-33747081,
-055634eb,
-39747607,
-83065170,
-e2387575,
-54517270,
-84055408,
-71708405,
-530c7270,
-84055408,
-71708405,
-530c7270,
-84055408,
-71708405,
-530c7270,
-84055408,
+2e098106,
+ef387480,
+0c863d0d,
+04747488,
+2b750770,
+71902b07,
+5154518f,
+7227a538,
+72717084,
+05530c72,
71708405,
-530cf012,
-52718f26,
-c9388372,
-27953872,
-70840554,
-08717084,
-05530cfc,
-12527183,
-26ed3870,
-54ff8839,
-fc3d0d76,
-7971028c,
-059f0533,
-57555355,
-8372278a,
-38748306,
-5170802e,
-a238ff12,
-5271ff2e,
-93387373,
-70810555,
-34ff1252,
-71ff2e09,
-8106ef38,
-74800c86,
-3d0d0474,
-74882b75,
-07707190,
-2b075154,
-518f7227,
-a5387271,
+530c7271,
70840553,
0c727170,
8405530c,
-72717084,
-05530c72,
-71708405,
-530cf012,
-52718f26,
-dd388372,
-27903872,
-71708405,
-530cfc12,
-52718326,
-f2387053,
-ff9039fd,
-3d0d800b,
-8187b008,
-54547281,
-2e9d3873,
-81a9e40c,
-ff96b93f,
-ff95d53f,
-81888c52,
-8151ffa9,
-d03f8008,
-51a33f72,
-81a9e40c,
-ff969d3f,
-ff95b93f,
-81888c52,
-8151ffa9,
-b43f8008,
-51873f00,
-ff3900ff,
-39f73d0d,
-7b818890,
-0882c811,
-085a545a,
-77802e80,
-da388188,
-18841908,
-ff058171,
-2b595559,
-80742480,
-ea388074,
-24b53873,
-822b7811,
-88055656,
-81801908,
-77065372,
-802eb638,
-78167008,
-53537951,
-74085372,
-2dff14fc,
-17fc1779,
-812c5a57,
-57547380,
-25d63877,
-085877ff,
-ad388188,
-900853bc,
-1308a538,
-7951ff83,
-3f740853,
-722dff14,
-fc17fc17,
-79812c5a,
-57575473,
-8025ffa8,
-38d13980,
-57ff9339,
-7251bc13,
+f0125271,
+8f26dd38,
+83722790,
+38727170,
+8405530c,
+fc125271,
+8326f238,
+7053ff90,
+39fd3d0d,
+800b8186,
+f4085454,
+72812e9d,
+38738199,
+cc0cff99,
+d33fff98,
+ef3f8187,
+d0528151,
+ffad823f,
+800851a3,
+3f728199,
+cc0cff99,
+b73fff98,
+d33f8187,
+d0528151,
+fface63f,
+80085187,
+3f00ff39,
+00ff39f7,
+3d0d7b81,
+87d40882,
+c811085a,
+545a7780,
+2e80da38,
+81881884,
+1908ff05,
+81712b59,
+55598074,
+2480ea38,
+807424b5,
+3873822b,
+78118805,
+56568180,
+19087706,
+5372802e,
+b6387816,
+70085353,
+79517408,
+53722dff,
+14fc17fc,
+1779812c,
+5a575754,
+738025d6,
+38770858,
+77ffad38,
+8187d408,
+53bc1308,
+a5387951,
+ff833f74,
0853722d,
-7951fed7,
-3fff3d0d,
-818f940b,
-fc057008,
-525270ff,
-2e913870,
-2dfc1270,
-08525270,
-ff2e0981,
-06f13883,
-3d0d0404,
-ff95a23f,
-04000000,
+ff14fc17,
+fc177981,
+2c5a5757,
+54738025,
+ffa838d1,
+398057ff,
+93397251,
+bc130853,
+722d7951,
+fed73fff,
+3d0d818e,
+d80bfc05,
+70085252,
+70ff2e91,
+38702dfc,
+12700852,
+5270ff2e,
+098106f1,
+38833d0d,
+0404ff98,
+bc3f0400,
00000040,
00000000,
58333030,
@@ -3875,129 +3772,6 @@ ff95a23f,
4f444142,
533a2025,
640a0000,
-44454255,
-473a2065,
-74682531,
-64205258,
-4c4f5320,
-6368616e,
-67656420,
-73746174,
-653a2025,
-640a0000,
-44454255,
-473a2065,
-74682531,
-64205458,
-4641554c,
-54206368,
-616e6765,
-64207374,
-6174653a,
-2025640a,
-00000000,
-44454255,
-473a2065,
-74682531,
-64204d4f,
-44414253,
-20636861,
-6e676564,
-20737461,
-74653a20,
-25640a00,
-494e464f,
-3a20416e,
-20534650,
-2b206d6f,
-64756c65,
-20686173,
-20626565,
-6e207265,
-6d6f7665,
-64206672,
-6f6d2065,
-74682070,
-6f727420,
-25642e0a,
-00000000,
-494e464f,
-3a204120,
-6e657720,
-5346502b,
-206d6f64,
-756c6520,
-68617320,
-6265656e,
-20696e73,
-65727465,
-6420696e,
-746f2065,
-74682070,
-6f727420,
-25642e0a,
-00000000,
-44454255,
-473a2053,
-4646505f,
-54595045,
-5f53522e,
-0a000000,
-44454255,
-473a2053,
-4646505f,
-54595045,
-5f4c522e,
-0a000000,
-44454255,
-473a2053,
-4646505f,
-54595045,
-5f4c524d,
-2e0a0000,
-44454255,
-473a2053,
-4646505f,
-54595045,
-5f313030,
-30424153,
-455f5358,
-2e0a0000,
-44454255,
-473a2053,
-4646505f,
-54595045,
-5f313030,
-30424153,
-455f4c58,
-2e0a0000,
-44454255,
-473a2053,
-4646505f,
-54595045,
-5f313030,
-30424153,
-455f542e,
-0a000000,
-44454255,
-473a2049,
-32432065,
-72726f72,
-20696e20,
-53465050,
-5f545950,
-452e0a00,
-44454255,
-473a2054,
-77696e41,
-782e0a00,
-44454255,
-473a2055,
-6e6b6e6f,
-776e2053,
-46502b20,
-74797065,
-2e0a0000,
44657669,
63653a20,
00000000,
@@ -4316,6 +4090,217 @@ ff95a23f,
2076616c,
75653a20,
00000000,
+44454255,
+473a2065,
+74682531,
+64205258,
+4c4f5320,
+6368616e,
+67656420,
+73746174,
+653a2025,
+640a0000,
+44454255,
+473a2065,
+74682531,
+64205458,
+4641554c,
+54206368,
+616e6765,
+64207374,
+6174653a,
+2025640a,
+00000000,
+44454255,
+473a2065,
+74682531,
+64204d4f,
+44414253,
+20636861,
+6e676564,
+20737461,
+74653a20,
+25640a00,
+494e464f,
+3a20416e,
+20534650,
+2b206d6f,
+64756c65,
+20686173,
+20626565,
+6e207265,
+6d6f7665,
+64206672,
+6f6d2065,
+74682070,
+6f727420,
+25642e0a,
+00000000,
+494e464f,
+3a204120,
+6e657720,
+5346502b,
+206d6f64,
+756c6520,
+68617320,
+6265656e,
+20696e73,
+65727465,
+6420696e,
+746f2065,
+74682070,
+6f727420,
+25642e0a,
+00000000,
+44454255,
+473a2053,
+4646505f,
+54595045,
+5f53522e,
+0a000000,
+44454255,
+473a2053,
+4646505f,
+54595045,
+5f4c522e,
+0a000000,
+44454255,
+473a2053,
+4646505f,
+54595045,
+5f4c524d,
+2e0a0000,
+44454255,
+473a2053,
+4646505f,
+54595045,
+5f313030,
+30424153,
+455f5358,
+2e0a0000,
+44454255,
+473a2053,
+4646505f,
+54595045,
+5f313030,
+30424153,
+455f4c58,
+2e0a0000,
+44454255,
+473a2053,
+4646505f,
+54595045,
+5f313030,
+30424153,
+455f542e,
+0a000000,
+44454255,
+473a2049,
+32432065,
+72726f72,
+20696e20,
+53465050,
+5f545950,
+452e0a00,
+44454255,
+473a2054,
+77696e41,
+782e0a00,
+44454255,
+473a2055,
+6e6b6e6f,
+776e2053,
+46502b20,
+74797065,
+2e0a0000,
+000023cf,
+000023d6,
+000023c9,
+000023c9,
+000023c9,
+000023c9,
+000023d6,
+000023d6,
+000023d6,
+000023d6,
+000023d6,
+000023c3,
+000023d6,
+000023d6,
+000023bd,
+000023b7,
+00002512,
+0000250c,
+00002506,
+00002500,
+000024fa,
+000024f4,
+000024ee,
+000024e8,
+00002619,
+0000282e,
+0000282e,
+0000282e,
+00002612,
+0000260b,
+00002604,
+000025fd,
+000025f6,
+000025ef,
+000025e8,
+000025e1,
+000025da,
+000025d3,
+000025cc,
+000025c5,
+00002764,
+00002756,
+00002748,
+0000273a,
+0000272b,
+0000271b,
+0000270b,
+000026fb,
+000026eb,
+000026db,
+000026d4,
+000026cd,
+000026bd,
+000026ad,
+00002773,
+00002696,
+000027d2,
+000027cc,
+000027c6,
+000027c0,
+00002825,
+00002825,
+00002825,
+00002825,
+00002825,
+00002825,
+00002825,
+000027ba,
+000027b4,
+00000000,
+00000001,
+00000004,
+00000005,
+00000006,
+00000007,
+00000008,
+00000020,
+00000021,
+00000000,
+00000001,
+00000004,
+00000005,
+00000006,
+00000007,
+00000008,
+0000000a,
+0000000b,
+0000ffff,
30313233,
34353637,
38394142,
@@ -4334,7 +4319,7 @@ ffffff00,
00000000,
00000000,
00000000,
-0000479c,
+00004760,
00000000,
00000000,
0050c285,
@@ -4355,12 +4340,12 @@ c0a82802,
00000000,
00000000,
00006000,
-0000438c,
-00004414,
+00004350,
+000043d8,
00000000,
-0000467c,
-000046d8,
-00004734,
+00004640,
+0000469c,
+000046f8,
00000000,
00000000,
00000000,
@@ -4370,7 +4355,7 @@ c0a82802,
00000000,
00000000,
00000000,
-00004398,
+0000435c,
00000000,
00000000,
00000000,
@@ -8191,4 +8176,19 @@ ffffffff,
00000000,
00000000,
00000000,
+00000000,
+00000000,
+00000000,
+00000000,
+00000000,
+00000000,
+00000000,
+00000000,
+00000000,
+00000000,
+00000000,
+00000000,
+00000000,
+00000000,
+00000000,
00000000; \ No newline at end of file
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
index 4ecdbd506..28ad6b968 100644
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -154,15 +154,11 @@ IF(MSVC)
ENDIF(MSVC)
SET(Boost_ADDITIONAL_VERSIONS
- "1.35.0" "1.35" "1.36.0" "1.36" "1.37.0" "1.37" "1.38.0" "1.38" "1.39.0" "1.39"
- "1.40.0" "1.40" "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44"
- "1.45.0" "1.45" "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.49.0" "1.49"
- "1.50.0" "1.50" "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54"
- "1.55.0" "1.55" "1.56.0" "1.56" "1.57.0" "1.57" "1.58.0" "1.58" "1.59.0" "1.59"
- "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"
+ "1.41.0" "1.41" "1.42.0" "1.42" "1.43.0" "1.43" "1.44.0" "1.44" "1.45.0" "1.45"
+ "1.46.0" "1.46" "1.47.0" "1.47" "1.48.0" "1.48" "1.48.0" "1.49" "1.50.0" "1.50"
+ "1.51.0" "1.51" "1.52.0" "1.52" "1.53.0" "1.53" "1.54.0" "1.54" "1.55.0" "1.55"
)
-FIND_PACKAGE(Boost 1.36 COMPONENTS ${BOOST_REQUIRED_COMPONENTS})
+FIND_PACKAGE(Boost 1.41 COMPONENTS ${BOOST_REQUIRED_COMPONENTS})
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
LINK_DIRECTORIES(${Boost_LIBRARY_DIRS})
diff --git a/host/docs/usrp_x3x0_config.rst b/host/docs/usrp_x3x0_config.rst
index 9cb000275..22ef8c595 100644
--- a/host/docs/usrp_x3x0_config.rst
+++ b/host/docs/usrp_x3x0_config.rst
@@ -69,19 +69,20 @@ Configuring the MTU
-------------------------------------
In order to achieve maximum performance, we recommend setting the MTU size to
9000 for 10 GigE and 1500 for 1 GigE. It is possible to use smaller MTUs, but this
-can affect performance. With some NICs, setting the MTU too high can also cause issues,
-though. To set the MTU to 9000, you can use the following command:
+can affect performance. With some NICs, setting the MTU too high can also cause issues.
+To set the MTU to 9000, you can use the following command:
::
sudo ifconfig <interface> mtu 9000 # For 10 GigE
+ sudo ifconfig <interface> mtu 1500 # For 1 GigE
Using these MTUs will set the frame sizes for UHD communication to 8000 and 1472,
respectively.
In some cases, specifying the frame size manually by adding the argument
"<send/recv>_frame_size=1472" can solve issues. Note that a frame size of 1472 will limit
-the available sampling rate, although this is likely not a problem issue on 1 GigE.
+the available sampling rate, although this is not a problem on 1 GigE.
Configuring the Firewall
diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp
index 8fb5115c2..de4721be0 100644
--- a/host/include/uhd/transport/udp_zero_copy.hpp
+++ b/host/include/uhd/transport/udp_zero_copy.hpp
@@ -56,6 +56,8 @@ public:
*
* \param addr a string representing the destination address
* \param port a string representing the destination port
+ * \param default_buff_args Default values for frame sizes and num frames
+ * \param[out] buff_params_out Returns the actual buffer sizes
* \param hints optional parameters to pass to the underlying transport
*/
static sptr make(
diff --git a/host/lib/transport/nirio/rpc/rpc_client.cpp b/host/lib/transport/nirio/rpc/rpc_client.cpp
index a5f8cf412..f8dc26b50 100644
--- a/host/lib/transport/nirio/rpc/rpc_client.cpp
+++ b/host/lib/transport/nirio/rpc/rpc_client.cpp
@@ -17,7 +17,9 @@
#include <uhd/transport/nirio/rpc/rpc_client.hpp>
#include <boost/bind.hpp>
+#include <boost/version.hpp>
#include <boost/format.hpp>
+#include <boost/asio/error.hpp>
#define CHAIN_BLOCKING_XFER(func, exp, status) \
if (status) { \
@@ -48,7 +50,23 @@ rpc_client::rpc_client (
tcp::resolver resolver(_io_service);
tcp::resolver::query query(tcp::v4(), server, port);
tcp::resolver::iterator iterator = resolver.resolve(query);
- boost::asio::connect(_socket, iterator);
+
+ #if BOOST_VERSION < 104700
+ // default constructor creates end iterator
+ tcp::resolver::iterator end;
+
+ boost::system::error_code error = boost::asio::error::host_not_found;
+ while (error && iterator != end)
+ {
+ _socket.close();
+ _socket.connect(*iterator++, error);
+ }
+ if (error)
+ throw boost::system::system_error(error);
+ #else
+ boost::asio::connect(_socket, iterator);
+ #endif
+
UHD_LOG << "rpc_client connected to server." << std::endl;
try {
@@ -74,18 +92,18 @@ rpc_client::rpc_client (
_io_service_thread.reset(new boost::thread(boost::bind(&boost::asio::io_service::run, &_io_service)));
} else {
UHD_LOG << "rpc_client handshake failed." << std::endl;
- _exec_err.assign(boost::asio::error::connection_refused, boost::system::system_category());
+ _exec_err.assign(boost::asio::error::connection_refused, boost::asio::error::get_system_category());
}
UHD_LOG << boost::format("rpc_client archive = %d, rpc_server archive = %d\n.") %
_hshake_args_client.boost_archive_version %
_hshake_args_server.boost_archive_version;
} catch (boost::exception&) {
UHD_LOG << "rpc_client handshake aborted." << std::endl;
- _exec_err.assign(boost::asio::error::connection_refused, boost::system::system_category());
+ _exec_err.assign(boost::asio::error::connection_refused, boost::asio::error::get_system_category());
}
} catch (boost::exception&) {
UHD_LOG << "rpc_client connection request cancelled/aborted." << std::endl;
- _exec_err.assign(boost::asio::error::connection_aborted, boost::system::system_category());
+ _exec_err.assign(boost::asio::error::connection_aborted, boost::asio::error::get_system_category());
}
}
@@ -115,9 +133,12 @@ const boost::system::error_code& rpc_client::call(
CHAIN_BLOCKING_XFER(
boost::asio::write(_socket, boost::asio::buffer(&_request.header, sizeof(_request.header))),
sizeof(_request.header), status);
- CHAIN_BLOCKING_XFER(
- boost::asio::write(_socket, boost::asio::buffer(&(*_request.data.begin()), _request.data.size())),
- _request.data.size(), status);
+ if (not _request.data.empty())
+ {
+ CHAIN_BLOCKING_XFER(
+ boost::asio::write(_socket, boost::asio::buffer(&(*_request.data.begin()), _request.data.size())),
+ _request.data.size(), status);
+ }
} catch (boost::exception&) {
status = false;
}
@@ -126,18 +147,18 @@ const boost::system::error_code& rpc_client::call(
if (status) {
if (!_exec_gate.timed_wait(lock, timeout)) {
UHD_LOG << "rpc_client function timed out." << std::endl;
- _exec_err.assign(boost::asio::error::timed_out, boost::system::system_category());
+ _exec_err.assign(boost::asio::error::timed_out, boost::asio::error::get_system_category());
}
} else {
UHD_LOG << "rpc_client connection dropped." << std::endl;
- _exec_err.assign(boost::asio::error::connection_aborted, boost::system::system_category());
+ _exec_err.assign(boost::asio::error::connection_aborted, boost::asio::error::get_system_category());
_stop_io_service();
}
//Verify that we are talking to the correct endpoint
if ((_request.header.client_id != _response.header.client_id) && !_exec_err) {
UHD_LOG << "rpc_client confused about who its talking to." << std::endl;
- _exec_err.assign(boost::asio::error::operation_aborted, boost::system::system_category());
+ _exec_err.assign(boost::asio::error::operation_aborted, boost::asio::error::get_system_category());
}
if (!_exec_err) out_args.load(_response.data);
@@ -153,19 +174,24 @@ void rpc_client::_handle_response_hdr(const boost::system::error_code& err, size
if (!_exec_err && (transferred == expected)) {
//Response header received. Verify that it is expected
if (func_args_header_t::match_function(_request.header, _response.header)) {
- _response.data.resize(_response.header.func_args_size);
-
- //Wait for response data
- boost::asio::async_read(_socket,
- boost::asio::buffer(&(*_response.data.begin()), _response.data.size()),
- boost::bind(&rpc_client::_handle_response_data, this,
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred,
- _response.data.size()));
+ if (_response.header.func_args_size)
+ {
+ _response.data.resize(_response.header.func_args_size);
+
+ //Wait for response data
+ boost::asio::async_read(_socket,
+ boost::asio::buffer(&(*_response.data.begin()), _response.data.size()),
+ boost::bind(&rpc_client::_handle_response_data, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred,
+ _response.data.size()));
+ } else {
+ _handle_response_data(err, 0, 0);
+ }
} else {
//Unexpected response. Ignore it.
UHD_LOG << "rpc_client received garbage responses." << std::endl;
- _exec_err.assign(boost::asio::error::operation_aborted, boost::system::system_category());
+ _exec_err.assign(boost::asio::error::operation_aborted, boost::asio::error::get_system_category());
_wait_for_next_response_header();
}
@@ -179,7 +205,7 @@ void rpc_client::_handle_response_data(const boost::system::error_code& err, siz
boost::mutex::scoped_lock lock(_mutex);
_exec_err = err;
if (transferred != expected) {
- _exec_err.assign(boost::asio::error::operation_aborted, boost::system::system_category());
+ _exec_err.assign(boost::asio::error::operation_aborted, boost::asio::error::get_system_category());
}
_exec_gate.notify_all();
diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp
index 5fdf2594d..5c84327a4 100644
--- a/host/lib/transport/super_recv_packet_handler.hpp
+++ b/host/lib/transport/super_recv_packet_handler.hpp
@@ -154,28 +154,12 @@ public:
/*!
* Flush all transports in the streamer:
- * This calls into get_and_process_single_packet(),
- * so the sequence and flow control are handled.
- * However, the packet payload is discarded.
+ * The packet payload is discarded.
*/
void flush_all(const double timeout = 0.0)
{
- increment_buffer_info(); //increment to next buffer
-
- for (size_t i = 0; i < _props.size(); i++)
- {
- while (true) //while (_props.at(i).get_buff(timeout));
- {
- //receive a single packet from the transport
- try
- {
- if (get_and_process_single_packet(i,
- get_prev_buffer_info(),
- get_curr_buffer_info(),
- timeout) == PACKET_TIMEOUT_ERROR) break;
- }catch(...){}
- }
- }
+ _flush_all(timeout);
+ return;
}
/*!
@@ -379,12 +363,12 @@ private:
******************************************************************/
UHD_INLINE packet_type get_and_process_single_packet(
const size_t index,
- buffers_info_type &prev_buffer_info,
- buffers_info_type &curr_buffer_info,
+ per_buffer_info_type &prev_buffer_info,
+ per_buffer_info_type &curr_buffer_info,
double timeout
){
//get a single packet from the transport layer
- managed_recv_buffer::sptr &buff = curr_buffer_info[index].buff;
+ managed_recv_buffer::sptr &buff = curr_buffer_info.buff;
buff = _props[index].get_buff(timeout);
if (buff.get() == NULL) return PACKET_TIMEOUT_ERROR;
@@ -405,7 +389,7 @@ private:
}
//extract packet info
- per_buffer_info_type &info = curr_buffer_info[index];
+ per_buffer_info_type &info = curr_buffer_info;
info.ifpi.num_packet_words32 = num_packet_words32 - _header_offset_words32;
info.vrt_hdr = buff->cast<const boost::uint32_t *>() + _header_offset_words32;
_vrt_unpacker(info.vrt_hdr, info.ifpi);
@@ -442,7 +426,7 @@ private:
#endif
//3) check for out of order timestamps
- if (info.ifpi.has_tsf and prev_buffer_info[index].time > info.time){
+ if (info.ifpi.has_tsf and prev_buffer_info.time > info.time){
return PACKET_TIMESTAMP_ERROR;
}
@@ -450,6 +434,33 @@ private:
return PACKET_IF_DATA;
}
+ void _flush_all(double timeout)
+ {
+ for (size_t i = 0; i < _props.size(); i++)
+ {
+ per_buffer_info_type prev_buffer_info, curr_buffer_info;
+ while (true)
+ {
+ //receive a single packet from the transport
+ try
+ {
+ // call into get_and_process_single_packet()
+ // to make sure flow control is handled
+ if (get_and_process_single_packet(
+ i,
+ prev_buffer_info,
+ curr_buffer_info,
+ timeout) == PACKET_TIMEOUT_ERROR) break;
+ } catch(...){}
+ prev_buffer_info = curr_buffer_info;
+ curr_buffer_info.reset();
+ }
+ }
+ get_prev_buffer_info().reset();
+ get_curr_buffer_info().reset();
+ get_next_buffer_info().reset();
+ }
+
/*******************************************************************
* Alignment check:
* Check the received packet for alignment and mark accordingly.
@@ -509,7 +520,7 @@ private:
//receive a single packet from the transport
try{
packet = get_and_process_single_packet(
- index, prev_info, curr_info, timeout
+ index, prev_info[index], curr_info[index], timeout
);
}
@@ -545,7 +556,9 @@ private:
curr_info.metadata.time_spec = next_info[index].time;
curr_info.metadata.error_code = rx_metadata_t::error_code_t(get_context_code(next_info[index].vrt_hdr, next_info[index].ifpi));
if (curr_info.metadata.error_code == rx_metadata_t::ERROR_CODE_OVERFLOW){
+ rx_metadata_t metadata = curr_info.metadata;
_props[index].handle_overflow();
+ curr_info.metadata = metadata;
UHD_MSG(fastpath) << "O";
}
return;
diff --git a/host/lib/transport/udp_wsa_zero_copy.cpp b/host/lib/transport/udp_wsa_zero_copy.cpp
index 031d26374..52382f84d 100644
--- a/host/lib/transport/udp_wsa_zero_copy.cpp
+++ b/host/lib/transport/udp_wsa_zero_copy.cpp
@@ -276,6 +276,36 @@ public:
size_t get_num_send_frames(void) const {return _num_send_frames;}
size_t get_send_frame_size(void) const {return _send_frame_size;}
+ //! Read back the socket's buffer space reserved for receives
+ size_t get_recv_buff_size(void) {
+ int recv_buff_size = 0;
+ int opt_len = sizeof(recv_buff_size);
+ getsockopt(
+ _sock_fd,
+ SOL_SOCKET,
+ SO_RCVBUF,
+ (char *)&recv_buff_size,
+ (int *)&opt_len
+ );
+
+ return (size_t) recv_buff_size;
+ }
+
+ //! Read back the socket's buffer space reserved for sends
+ size_t get_send_buff_size(void) {
+ int send_buff_size = 0;
+ int opt_len = sizeof(send_buff_size);
+ getsockopt(
+ _sock_fd,
+ SOL_SOCKET,
+ SO_SNDBUF,
+ (char *)&send_buff_size,
+ (int *)&opt_len
+ );
+
+ return (size_t) send_buff_size;
+ }
+
private:
//memory management -> buffers and fifos
const size_t _recv_frame_size, _num_recv_frames;
@@ -292,6 +322,25 @@ private:
/***********************************************************************
* UDP zero copy make function
**********************************************************************/
+void check_usr_buff_size(
+ size_t actual_buff_size,
+ size_t user_buff_size, // Set this to zero for no user-defined preference
+ const std::string tx_rx
+){
+ UHD_LOG << boost::format(
+ "Target %s sock buff size: %d bytes\n"
+ "Actual %s sock buff size: %d bytes"
+ ) % tx_rx % user_buff_size % tx_rx % actual_buff_size << std::endl;
+ if ((user_buff_size != 0.0) and (actual_buff_size < user_buff_size)) UHD_MSG(warning) << boost::format(
+ "The %s buffer could not be resized sufficiently.\n"
+ "Target sock buff size: %d bytes.\n"
+ "Actual sock buff size: %d bytes.\n"
+ "See the transport application notes on buffer resizing.\n"
+ ) % tx_rx % user_buff_size % actual_buff_size;
+}
+
+
+
udp_zero_copy::sptr udp_zero_copy::make(
const std::string &addr,
const std::string &port,
@@ -306,6 +355,34 @@ udp_zero_copy::sptr udp_zero_copy::make(
xport_params.num_recv_frames = size_t(hints.cast<double>("num_recv_frames", default_buff_args.num_recv_frames));
xport_params.send_frame_size = size_t(hints.cast<double>("send_frame_size", default_buff_args.send_frame_size));
xport_params.num_send_frames = size_t(hints.cast<double>("num_send_frames", default_buff_args.num_send_frames));
-
- return sptr(new udp_zero_copy_wsa_impl(addr, port, xport_params, hints));
+
+ //extract buffer size hints from the device addr and check if they match up
+ size_t usr_recv_buff_size = size_t(hints.cast<double>("recv_buff_size", 0.0));
+ size_t usr_send_buff_size = size_t(hints.cast<double>("send_buff_size", 0.0));
+ if (hints.has_key("recv_buff_size")) {
+ if (usr_recv_buff_size < xport_params.recv_frame_size * xport_params.num_recv_frames) {
+ throw uhd::value_error((boost::format(
+ "recv_buff_size must be equal to or greater than (num_recv_frames * recv_frame_size) where num_recv_frames=%d, recv_frame_size=%d")
+ % xport_params.num_recv_frames % xport_params.recv_frame_size).str());
+ }
+ }
+ if (hints.has_key("send_buff_size")) {
+ if (usr_send_buff_size < xport_params.send_frame_size * xport_params.num_send_frames) {
+ throw uhd::value_error((boost::format(
+ "send_buff_size must be equal to or greater than (num_send_frames * send_frame_size) where num_send_frames=%d, send_frame_size=%d")
+ % xport_params.num_send_frames % xport_params.send_frame_size).str());
+ }
+ }
+
+ udp_zero_copy_wsa_impl::sptr udp_trans(
+ new udp_zero_copy_wsa_impl(addr, port, xport_params, hints)
+ );
+
+ // Read back the actual socket buffer sizes
+ buff_params_out.recv_buff_size = udp_trans->get_recv_buff_size();
+ buff_params_out.send_buff_size = udp_trans->get_send_buff_size();
+ check_usr_buff_size(buff_params_out.recv_buff_size, usr_recv_buff_size, "recv");
+ check_usr_buff_size(buff_params_out.send_buff_size, usr_send_buff_size, "send");
+
+ return udp_trans;
}
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp
index 74e61143b..66df1f3bc 100644
--- a/host/lib/usrp/b200/b200_impl.cpp
+++ b/host/lib/usrp/b200/b200_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2012-2013 Ettus Research LLC
+// Copyright 2012-2014 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
@@ -373,12 +373,15 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
////////////////////////////////////////////////////////////////////
// create frontend mapping
////////////////////////////////////////////////////////////////////
+ std::vector<size_t> default_map(2, 0); default_map[1] = 1; // Set this to A->0 B->1 even if there's only A
+ _tree->create<std::vector<size_t> >(mb_path / "rx_chan_dsp_mapping").set(default_map);
+ _tree->create<std::vector<size_t> >(mb_path / "tx_chan_dsp_mapping").set(default_map);
_tree->create<subdev_spec_t>(mb_path / "rx_subdev_spec")
.set(subdev_spec_t())
- .subscribe(boost::bind(&b200_impl::update_rx_subdev_spec, this, _1));
+ .subscribe(boost::bind(&b200_impl::update_subdev_spec, this, "rx", _1));
_tree->create<subdev_spec_t>(mb_path / "tx_subdev_spec")
.set(subdev_spec_t())
- .subscribe(boost::bind(&b200_impl::update_tx_subdev_spec, this, _1));
+ .subscribe(boost::bind(&b200_impl::update_subdev_spec, this, "tx", _1));
////////////////////////////////////////////////////////////////////
// setup radio control
diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp
index c88d14ad5..a370e54f9 100644
--- a/host/lib/usrp/b200/b200_impl.hpp
+++ b/host/lib/usrp/b200/b200_impl.hpp
@@ -127,8 +127,7 @@ private:
void set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &);
void check_fw_compat(void);
void check_fpga_compat(void);
- void update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &);
- void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &);
+ void update_subdev_spec(const std::string &tx_rx, const uhd::usrp::subdev_spec_t &);
void update_time_source(const std::string &);
void update_clock_source(const std::string &);
void update_bandsel(const std::string& which, double freq);
@@ -150,8 +149,12 @@ private:
bool ant_rx2;
};
std::vector<radio_perifs_t> _radio_perifs;
- void setup_radio(const size_t which_radio);
- void handle_overflow(const size_t index);
+
+ /*! \brief Setup the DSP chain for one radio front-end.
+ *
+ */
+ void setup_radio(const size_t radio_index);
+ void handle_overflow(const size_t radio_index);
struct gpio_state {
boost::uint32_t tx_bandsel_a, tx_bandsel_b, rx_bandsel_a, rx_bandsel_b, rx_bandsel_c, codec_arst, mimo, ref_sel;
diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp
index 4768aa37b..4f072c4d4 100644
--- a/host/lib/usrp/b200/b200_io_impl.cpp
+++ b/host/lib/usrp/b200/b200_io_impl.cpp
@@ -72,44 +72,31 @@ void b200_impl::update_tx_samp_rate(const size_t dspno, const double rate)
/***********************************************************************
* frontend selection
**********************************************************************/
-void b200_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec)
+void b200_impl::update_subdev_spec(const std::string &tx_rx, const uhd::usrp::subdev_spec_t &spec)
{
//sanity checking
- if (spec.size()) validate_subdev_spec(_tree, spec, "rx");
+ if (spec.size()) validate_subdev_spec(_tree, spec, tx_rx);
UHD_ASSERT_THROW(spec.size() <= _radio_perifs.size());
- if (spec.size() > 0)
+ if (spec.size() >= 1)
{
UHD_ASSERT_THROW(spec[0].db_name == "A");
- UHD_ASSERT_THROW(spec[0].sd_name == "A");
+ UHD_ASSERT_THROW(spec[0].sd_name == "A" or spec[0].sd_name == "B");
}
- if (spec.size() > 1)
+ if (spec.size() == 2)
{
- //TODO we can support swapping at a later date, only this combo is supported
UHD_ASSERT_THROW(spec[1].db_name == "A");
- UHD_ASSERT_THROW(spec[1].sd_name == "B");
+ UHD_ASSERT_THROW(
+ (spec[0].sd_name == "A" and spec[1].sd_name == "B") or
+ (spec[0].sd_name == "B" and spec[1].sd_name == "A")
+ );
}
- this->update_enables();
-}
-
-void b200_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec)
-{
- //sanity checking
- if (spec.size()) validate_subdev_spec(_tree, spec, "tx");
- UHD_ASSERT_THROW(spec.size() <= _radio_perifs.size());
-
- if (spec.size() > 0)
- {
- UHD_ASSERT_THROW(spec[0].db_name == "A");
- UHD_ASSERT_THROW(spec[0].sd_name == "A");
- }
- if (spec.size() > 1)
- {
- //TODO we can support swapping at a later date, only this combo is supported
- UHD_ASSERT_THROW(spec[1].db_name == "A");
- UHD_ASSERT_THROW(spec[1].sd_name == "B");
+ std::vector<size_t> chan_to_dsp_map(spec.size(), 0);
+ for (size_t i = 0; i < spec.size(); i++) {
+ chan_to_dsp_map[i] = (spec[i].sd_name == "A") ? 0 : 1;
}
+ _tree->access<std::vector<size_t> >("/mboards/0" / (tx_rx + "_chan_dsp_mapping")).set(chan_to_dsp_map);
this->update_enables();
}
@@ -238,13 +225,14 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_)
boost::shared_ptr<sph::recv_packet_streamer> my_streamer;
for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++)
{
- const size_t chan = args.channels[stream_i];
- radio_perifs_t &perif = _radio_perifs[chan];
+ const size_t radio_index = _tree->access<std::vector<size_t> >("/mboards/0/rx_chan_dsp_mapping")
+ .get().at(args.channels[stream_i]);
+ radio_perifs_t &perif = _radio_perifs[radio_index];
if (args.otw_format == "sc16") perif.ctrl->poke32(TOREG(SR_RX_FMT), 0);
if (args.otw_format == "sc12") perif.ctrl->poke32(TOREG(SR_RX_FMT), 1);
if (args.otw_format == "fc32") perif.ctrl->poke32(TOREG(SR_RX_FMT), 2);
if (args.otw_format == "sc8") perif.ctrl->poke32(TOREG(SR_RX_FMT), 3);
- const boost::uint32_t sid = chan?B200_RX_DATA1_SID:B200_RX_DATA0_SID;
+ const boost::uint32_t sid = radio_index ? B200_RX_DATA1_SID : B200_RX_DATA0_SID;
//calculate packet size
static const size_t hdr_size = 0
@@ -283,7 +271,7 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_)
&recv_packet_demuxer_3000::get_recv_buff, _demux, sid, _1
), true /*flush*/);
my_streamer->set_overflow_handler(stream_i, boost::bind(
- &b200_impl::handle_overflow, this, chan
+ &b200_impl::handle_overflow, this, radio_index
));
my_streamer->set_issue_stream_cmd(stream_i, boost::bind(
&rx_vita_core_3000::issue_stream_command, perif.framer, _1
@@ -292,21 +280,21 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_)
//sets all tick and samp rates on this streamer
this->update_tick_rate(this->get_tick_rate());
- _tree->access<double>(str(boost::format("/mboards/0/rx_dsps/%u/rate/value") % chan)).update();
+ _tree->access<double>(str(boost::format("/mboards/0/rx_dsps/%u/rate/value") % radio_index)).update();
}
this->update_enables();
return my_streamer;
}
-void b200_impl::handle_overflow(const size_t i)
+void b200_impl::handle_overflow(const size_t radio_index)
{
boost::shared_ptr<sph::recv_packet_streamer> my_streamer =
- boost::dynamic_pointer_cast<sph::recv_packet_streamer>(_radio_perifs[i].rx_streamer.lock());
+ boost::dynamic_pointer_cast<sph::recv_packet_streamer>(_radio_perifs[radio_index].rx_streamer.lock());
if (my_streamer->get_num_channels() == 2) //MIMO time
{
//find out if we were in continuous mode before stopping
- const bool in_continuous_streaming_mode = _radio_perifs[i].framer->in_continuous_streaming_mode();
+ const bool in_continuous_streaming_mode = _radio_perifs[radio_index].framer->in_continuous_streaming_mode();
//stop streaming
my_streamer->issue_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
//flush demux
@@ -319,11 +307,11 @@ void b200_impl::handle_overflow(const size_t i)
{
stream_cmd_t stream_cmd(stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
stream_cmd.stream_now = false;
- stream_cmd.time_spec = _radio_perifs[i].time64->get_time_now() + time_spec_t(0.01);
+ stream_cmd.time_spec = _radio_perifs[radio_index].time64->get_time_now() + time_spec_t(0.01);
my_streamer->issue_stream_cmd(stream_cmd);
}
}
- else _radio_perifs[i].framer->handle_overflow();
+ else _radio_perifs[radio_index].framer->handle_overflow();
}
/***********************************************************************
@@ -340,8 +328,9 @@ tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t &args_)
boost::shared_ptr<sph::send_packet_streamer> my_streamer;
for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++)
{
- const size_t chan = args.channels[stream_i];
- radio_perifs_t &perif = _radio_perifs[chan];
+ const size_t radio_index = _tree->access<std::vector<size_t> >("/mboards/0/tx_chan_dsp_mapping")
+ .get().at(args.channels[stream_i]);
+ radio_perifs_t &perif = _radio_perifs[radio_index];
if (args.otw_format == "sc16") perif.ctrl->poke32(TOREG(SR_TX_FMT), 0);
if (args.otw_format == "sc12") perif.ctrl->poke32(TOREG(SR_TX_FMT), 1);
if (args.otw_format == "fc32") perif.ctrl->poke32(TOREG(SR_TX_FMT), 2);
@@ -382,13 +371,13 @@ tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t &args_)
my_streamer->set_async_receiver(boost::bind(
&async_md_type::pop_with_timed_wait, _async_task_data->async_md, _1, _2
));
- my_streamer->set_xport_chan_sid(stream_i, true, chan?B200_TX_DATA1_SID:B200_TX_DATA0_SID);
+ my_streamer->set_xport_chan_sid(stream_i, true, radio_index ? B200_TX_DATA1_SID : B200_TX_DATA0_SID);
my_streamer->set_enable_trailer(false); //TODO not implemented trailer support yet
perif.tx_streamer = my_streamer; //store weak pointer
//sets all tick and samp rates on this streamer
this->update_tick_rate(this->get_tick_rate());
- _tree->access<double>(str(boost::format("/mboards/0/tx_dsps/%u/rate/value") % chan)).update();
+ _tree->access<double>(str(boost::format("/mboards/0/tx_dsps/%u/rate/value") % radio_index)).update();
}
this->update_enables();
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index 182e774fc..f08709669 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -35,14 +35,20 @@ using namespace uhd::usrp;
const std::string multi_usrp::ALL_GAINS = "";
-UHD_INLINE std::string string_vector_to_string(std::vector<std::string> values, std::string delimeter = std::string(" "))
+UHD_INLINE std::string string_vector_to_string(std::vector<std::string> values, std::string delimiter = std::string(" "))
{
std::string out = "";
for (std::vector<std::string>::iterator iter = values.begin(); iter != values.end(); iter++)
- out += delimeter + *iter;
+ {
+ out += (iter != values.begin() ? delimiter : "") + *iter;
+ }
return out;
}
+#define THROW_GAIN_NAME_ERROR(name,chan,dir) throw uhd::exception::runtime_error( \
+ (boost::format("%s: gain \"%s\" not found for channel %d.\nAvailable gains: %s\n") % \
+ __FUNCTION__ % name % chan % string_vector_to_string(get_##dir##_gain_names(chan))).str());
+
/***********************************************************************
* Helper methods
**********************************************************************/
@@ -671,10 +677,7 @@ public:
try {
return rx_gain_group(chan)->set_value(gain, name);
} catch (uhd::key_error &e) {
- std::stringstream err;
- err << __FUNCTION__ << "(\"" << name << "\"): gain not found.\n" <<
- "Available gains: " << string_vector_to_string(get_rx_gain_names(chan)) << std::endl;
- throw uhd::exception::runtime_error(err.str());
+ THROW_GAIN_NAME_ERROR(name,chan,rx);
}
}
@@ -682,10 +685,7 @@ public:
try {
return rx_gain_group(chan)->get_value(name);
} catch (uhd::key_error &e) {
- std::stringstream err;
- err << __FUNCTION__ << "(\"" << name << "\"): gain not found.\n" <<
- "Available gains: " << string_vector_to_string(get_rx_gain_names(chan)) << std::endl;
- throw uhd::exception::runtime_error(err.str());
+ THROW_GAIN_NAME_ERROR(name,chan,rx);
}
}
@@ -693,10 +693,7 @@ public:
try {
return rx_gain_group(chan)->get_range(name);
} catch (uhd::key_error &e) {
- std::stringstream err;
- err << __FUNCTION__ << "(\"" << name << "\"): gain not found.\n" <<
- "Available gains: " << string_vector_to_string(get_rx_gain_names(chan)) << std::endl;
- throw uhd::exception::runtime_error(err.str());
+ THROW_GAIN_NAME_ERROR(name,chan,rx);
}
}
@@ -861,10 +858,7 @@ public:
try {
return tx_gain_group(chan)->set_value(gain, name);
} catch (uhd::key_error &e) {
- std::stringstream err;
- err << __FUNCTION__ << "(\"" << name << "\"): gain not found.\n" <<
- "Available gains: " << string_vector_to_string(get_rx_gain_names(chan)) << std::endl;
- throw uhd::exception::runtime_error(err.str());
+ THROW_GAIN_NAME_ERROR(name,chan,tx);
}
}
@@ -872,10 +866,7 @@ public:
try {
return tx_gain_group(chan)->get_value(name);
} catch (uhd::key_error &e) {
- std::stringstream err;
- err << __FUNCTION__ << "(\"" << name << "\"): gain not found.\n" <<
- "Available gains: " << string_vector_to_string(get_rx_gain_names(chan)) << std::endl;
- throw uhd::exception::runtime_error(err.str());
+ THROW_GAIN_NAME_ERROR(name,chan,tx);
}
}
@@ -883,10 +874,7 @@ public:
try {
return tx_gain_group(chan)->get_range(name);
} catch (uhd::key_error &e) {
- std::stringstream err;
- err << __FUNCTION__ << "(\"" << name << "\"): gain not found.\n" <<
- "Available gains: " << string_vector_to_string(get_rx_gain_names(chan)) << std::endl;
- throw uhd::exception::runtime_error(err.str());
+ THROW_GAIN_NAME_ERROR(name,chan,tx);
}
}
@@ -1073,6 +1061,12 @@ private:
fs_path rx_dsp_root(const size_t chan)
{
mboard_chan_pair mcp = rx_chan_to_mcp(chan);
+ if (_tree->exists(mb_root(mcp.mboard) / "rx_chan_dsp_mapping")) {
+ std::vector<size_t> map = _tree->access<std::vector<size_t> >(mb_root(mcp.mboard) / "rx_chan_dsp_mapping").get();
+ UHD_ASSERT_THROW(map.size() > mcp.chan);
+ mcp.chan = map[mcp.chan];
+ }
+
try
{
const std::string name = _tree->list(mb_root(mcp.mboard) / "rx_dsps").at(mcp.chan);
@@ -1087,6 +1081,11 @@ private:
fs_path tx_dsp_root(const size_t chan)
{
mboard_chan_pair mcp = tx_chan_to_mcp(chan);
+ if (_tree->exists(mb_root(mcp.mboard) / "tx_chan_dsp_mapping")) {
+ std::vector<size_t> map = _tree->access<std::vector<size_t> >(mb_root(mcp.mboard) / "tx_chan_dsp_mapping").get();
+ UHD_ASSERT_THROW(map.size() > mcp.chan);
+ mcp.chan = map[mcp.chan];
+ }
try
{
const std::string name = _tree->list(mb_root(mcp.mboard) / "tx_dsps").at(mcp.chan);
diff --git a/host/lib/usrp/x300/x300_clock_ctrl.cpp b/host/lib/usrp/x300/x300_clock_ctrl.cpp
index a986928a7..a8b30a0ab 100644
--- a/host/lib/usrp/x300/x300_clock_ctrl.cpp
+++ b/host/lib/usrp/x300/x300_clock_ctrl.cpp
@@ -48,6 +48,10 @@ x300_clock_ctrl_impl(uhd::spi_iface::sptr spiface,
set_master_clock_rate(master_clock_rate);
}
+void reset_clocks() {
+ set_master_clock_rate(_master_clock_rate);
+}
+
void sync_clocks(void) {
//soft sync:
//put the sync IO into output mode - FPGA must be input
diff --git a/host/lib/usrp/x300/x300_clock_ctrl.hpp b/host/lib/usrp/x300/x300_clock_ctrl.hpp
index 0e3caf900..e9904d25c 100644
--- a/host/lib/usrp/x300/x300_clock_ctrl.hpp
+++ b/host/lib/usrp/x300/x300_clock_ctrl.hpp
@@ -78,6 +78,12 @@ public:
* \param true = on, false = off
*/
virtual void set_ref_out(const bool) = 0;
+
+ /*! Reset the clocks.
+ * Should be called if the reference clock changes
+ * to reduce the time required to achieve a lock.
+ */
+ virtual void reset_clocks(void) = 0;
};
#endif /* INCLUDED_X300_CLOCK_CTRL_HPP */
diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h
index c470e9bff..632391644 100644
--- a/host/lib/usrp/x300/x300_fw_common.h
+++ b/host/lib/usrp/x300/x300_fw_common.h
@@ -31,7 +31,7 @@ extern "C" {
#define X300_FW_COMPAT_MAJOR 3
#define X300_FW_COMPAT_MINOR 0
-#define X300_FPGA_COMPAT_MAJOR 3
+#define X300_FPGA_COMPAT_MAJOR 4
//shared memory sections - in between the stack and the program space
#define X300_FW_SHMEM_BASE 0x6000
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index b20897fc6..e492b2238 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -430,16 +430,16 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
// Detect the frame size on the path to the USRP
try {
- max_frame_sizes = determine_max_frame_size(mb.addr, req_max_frame_size);
+ _max_frame_sizes = determine_max_frame_size(mb.addr, req_max_frame_size);
} catch(std::exception &e) {
UHD_MSG(error) << e.what() << std::endl;
}
if ((mb.recv_args.has_key("recv_frame_size"))
- && (req_max_frame_size.recv_frame_size < max_frame_sizes.recv_frame_size)) {
+ && (req_max_frame_size.recv_frame_size < _max_frame_sizes.recv_frame_size)) {
UHD_MSG(warning)
<< boost::format("You requested a receive frame size of (%lu) but your NIC's max frame size is (%lu).")
- % req_max_frame_size.recv_frame_size << max_frame_sizes.recv_frame_size << std::endl
+ % req_max_frame_size.recv_frame_size << _max_frame_sizes.recv_frame_size << std::endl
<< boost::format("Please verify your NIC's MTU setting using '%s' or set the recv_frame_size argument appropriately.")
% mtu_tool << std::endl
<< "UHD will use the auto-detected max frame size for this connection."
@@ -447,10 +447,10 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
}
if ((mb.recv_args.has_key("send_frame_size"))
- && (req_max_frame_size.send_frame_size < max_frame_sizes.send_frame_size)) {
+ && (req_max_frame_size.send_frame_size < _max_frame_sizes.send_frame_size)) {
UHD_MSG(warning)
<< boost::format("You requested a send frame size of (%lu) but your NIC's max frame size is (%lu).")
- % req_max_frame_size.send_frame_size << max_frame_sizes.send_frame_size << std::endl
+ % req_max_frame_size.send_frame_size << _max_frame_sizes.send_frame_size << std::endl
<< boost::format("Please verify your NIC's MTU setting using '%s' or set the send_frame_size argument appropriately.")
% mtu_tool << std::endl
<< "UHD will use the auto-detected max frame size for this connection."
@@ -458,8 +458,6 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
}
}
- const std::vector<std::string> DB_NAMES = boost::assign::list_of("A")("B");
-
//create basic communication
UHD_MSG(status) << "Setup basic communication..." << std::endl;
if (mb.xport_path == "nirio") {
@@ -579,20 +577,10 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
////////////////////////////////////////////////////////////////////
UHD_MSG(status) << "Setup RF frontend clocking..." << std::endl;
- // Init shadow and clock source; the device comes up with it's internal
- // clock source before locking to something else (if requested).
- mb.clock_control_regs__clock_source = 0;
- mb.clock_control_regs__pps_select = 0;
- mb.clock_control_regs__pps_out_enb = 0;
- mb.clock_control_regs__tcxo_enb = 1;
- mb.clock_control_regs__gpsdo_pwr = 1;
- this->update_clock_source(mb, "internal");
- this->update_clock_control(mb);
-
- size_t hw_rev = 0;
+ mb.hw_rev = 0;
if(mb_eeprom.has_key("revision") and not mb_eeprom["revision"].empty()) {
try {
- hw_rev = boost::lexical_cast<size_t>(mb_eeprom["revision"]);
+ mb.hw_rev = boost::lexical_cast<size_t>(mb_eeprom["revision"]);
} catch(...) {
UHD_MSG(warning) << "Revision in EEPROM is invalid! Please reprogram your EEPROM." << std::endl;
}
@@ -600,17 +588,38 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
UHD_MSG(warning) << "No revision detected MB EEPROM must be reprogrammed!" << std::endl;
}
- if(hw_rev == 0) {
+ if(mb.hw_rev == 0) {
UHD_MSG(warning) << "Defaulting to X300 RevD Clock Settings. This will result in non-optimal lock times." << std::endl;
- hw_rev = X300_REV("D");
+ mb.hw_rev = X300_REV("D");
}
+ //Initialize clock control with internal references and GPSDO power on.
+ mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL;
+ mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL;
+ mb.clock_control_regs_pps_out_enb = 0;
+ mb.clock_control_regs_tcxo_enb = 1;
+ mb.clock_control_regs_gpsdo_pwr = 1;
+ this->update_clock_control(mb);
+
+ //Create clock control
mb.clock = x300_clock_ctrl::make(mb.zpu_spi,
1 /*slaveno*/,
- hw_rev,
+ mb.hw_rev,
dev_addr.cast<double>("master_clock_rate", X300_DEFAULT_TICK_RATE),
dev_addr.cast<double>("system_ref_rate", X300_DEFAULT_SYSREF_RATE));
+ //wait for reference clock to lock
+ if(mb.hw_rev > 4)
+ {
+ try {
+ //FIXME: Need to verify timeout value to make sure lock can be achieved in < 1.0 seconds
+ wait_for_ref_locked(mb.zpu_ctrl, 1.0);
+ } catch (uhd::runtime_error &e) {
+ //Silently fail for now, but fix after we have the correct timeout value
+ //UHD_MSG(warning) << "Clock failed to lock to internal source during initialization." << std::endl;
+ }
+ }
+
////////////////////////////////////////////////////////////////////
// create clock properties
////////////////////////////////////////////////////////////////////
@@ -664,8 +673,8 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
// setup radios
////////////////////////////////////////////////////////////////////
UHD_MSG(status) << "Initialize Radio control..." << std::endl;
- this->setup_radio(mb_i, 0, DB_NAMES[0]);
- this->setup_radio(mb_i, 1, DB_NAMES[1]);
+ this->setup_radio(mb_i, "A");
+ this->setup_radio(mb_i, "B");
////////////////////////////////////////////////////////////////////
// front panel gpio
@@ -732,10 +741,13 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
////////////////////////////////////////////////////////////////////
// create frontend mapping
////////////////////////////////////////////////////////////////////
+ std::vector<size_t> default_map(2, 0); default_map[1] = 1;
+ _tree->create<std::vector<size_t> >(mb_path / "rx_chan_dsp_mapping").set(default_map);
+ _tree->create<std::vector<size_t> >(mb_path / "tx_chan_dsp_mapping").set(default_map);
_tree->create<subdev_spec_t>(mb_path / "rx_subdev_spec")
- .subscribe(boost::bind(&x300_impl::update_rx_subdev_spec, this, mb_i, _1));
+ .subscribe(boost::bind(&x300_impl::update_subdev_spec, this, "rx", mb_i, _1));
_tree->create<subdev_spec_t>(mb_path / "tx_subdev_spec")
- .subscribe(boost::bind(&x300_impl::update_tx_subdev_spec, this, mb_i, _1));
+ .subscribe(boost::bind(&x300_impl::update_subdev_spec, this, "tx", mb_i, _1));
////////////////////////////////////////////////////////////////////
// and do the misc mboard sensors
@@ -767,30 +779,42 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
_tree->access<subdev_spec_t>(mb_path / "rx_subdev_spec").set(rx_fe_spec);
_tree->access<subdev_spec_t>(mb_path / "tx_subdev_spec").set(tx_fe_spec);
- //GPS installed: use external ref, time, and init time spec
- if (mb.gps and mb.gps->gps_detected())
- {
- UHD_MSG(status) << "Setting references to the internal GPSDO" << std::endl;
- _tree->access<std::string>(mb_path / "time_source" / "value").set("gpsdo");
- _tree->access<std::string>(mb_path / "clock_source" / "value").set("gpsdo");
- UHD_MSG(status) << "Initializing time to the internal GPSDO" << std::endl;
- const time_t tp = time_t(mb.gps->get_sensor("gps_time").to_int()+1);
- _tree->access<time_spec_t>(mb_path / "time" / "pps").set(time_spec_t(tp));
- }
- else
- {
- _tree->access<std::string>(mb_path / "time_source" / "value").set("external");
+ UHD_MSG(status) << "Initializing clock and PPS references..." << std::endl;
+ try {
+ //First, try external source
_tree->access<std::string>(mb_path / "clock_source" / "value").set("external");
- boost::this_thread::sleep(boost::posix_time::milliseconds(100));
- if (this->get_ref_locked(mb.zpu_ctrl).to_bool())
- {
- UHD_MSG(status) << "Setting references to external sources" << std::endl;
- }
- else
+ wait_for_ref_locked(mb.zpu_ctrl, 1.0);
+ _tree->access<std::string>(mb_path / "time_source" / "value").set("external");
+ UHD_MSG(status) << "References initialized to external sources" << std::endl;
+ } catch (uhd::exception::runtime_error &e) {
+ //No external source detected - set to the GPSDO if installed
+ if (mb.gps and mb.gps->gps_detected())
{
- UHD_MSG(status) << "Setting references to internal sources" << std::endl;
- _tree->access<std::string>(mb_path / "time_source" / "value").set("internal");
+ _tree->access<std::string>(mb_path / "clock_source" / "value").set("gpsdo");
+ try {
+ wait_for_ref_locked(mb.zpu_ctrl, 1.0);
+ } catch (uhd::exception::runtime_error &e) {
+ UHD_MSG(warning) << "Clock reference failed to lock to GPSDO during device initialization. " <<
+ "Check for the lock before operation or ignore this warning if using another clock source." << std::endl;
+ }
+ _tree->access<std::string>(mb_path / "time_source" / "value").set("gpsdo");
+ UHD_MSG(status) << "References initialized to GPSDO sources" << std::endl;
+ UHD_MSG(status) << "Initializing time to the GPSDO time" << std::endl;
+ const time_t tp = time_t(mb.gps->get_sensor("gps_time").to_int()+1);
+ _tree->access<time_spec_t>(mb_path / "time" / "pps").set(time_spec_t(tp));
+ //wait for time to be set (timeout after 1 second)
+ for (int i = 0; i < 10 && tp != (_tree->access<time_spec_t>(mb_path / "time" / "pps").get()).get_full_secs(); i++)
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ } else {
_tree->access<std::string>(mb_path / "clock_source" / "value").set("internal");
+ try {
+ wait_for_ref_locked(mb.zpu_ctrl, 1.0);
+ } catch (uhd::exception::runtime_error &e) {
+ UHD_MSG(warning) << "Clock reference failed to lock to internal source during device initialization. " <<
+ "Check for the lock before operation or ignore this warning if using another clock source." << std::endl;
+ }
+ _tree->access<std::string>(mb_path / "time_source" / "value").set("internal");
+ UHD_MSG(status) << "References initialized to internal sources" << std::endl;
}
}
}
@@ -824,20 +848,21 @@ static void check_adc(wb_iface::sptr iface, const boost::uint32_t val)
UHD_ASSERT_THROW(adc_rb == val);
}
-void x300_impl::setup_radio(const size_t mb_i, const size_t i, const std::string &db_name)
+void x300_impl::setup_radio(const size_t mb_i, const std::string &slot_name)
{
const fs_path mb_path = "/mboards/"+boost::lexical_cast<std::string>(mb_i);
+ UHD_ASSERT_THROW(mb_i < _mb.size());
mboard_members_t &mb = _mb[mb_i];
- radio_perifs_t &perif = mb.radio_perifs[i];
- const size_t dspno = i;
+ const size_t radio_index = mb.get_radio_index(slot_name);
+ radio_perifs_t &perif = mb.radio_perifs[radio_index];
////////////////////////////////////////////////////////////////////
// radio control
////////////////////////////////////////////////////////////////////
- uint8_t dest = (i == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
+ uint8_t dest = (radio_index == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
boost::uint32_t ctrl_sid;
both_xports_t xport = this->make_transport(mb_i, dest, X300_RADIO_DEST_PREFIX_CTRL, device_addr_t(), ctrl_sid);
- perif.ctrl = radio_ctrl_core_3000::make(mb.if_pkt_is_big_endian, xport.recv, xport.send, ctrl_sid, db_name);
+ perif.ctrl = radio_ctrl_core_3000::make(mb.if_pkt_is_big_endian, xport.recv, xport.send, ctrl_sid, slot_name);
perif.ctrl->poke32(TOREG(SR_MISC_OUTS), (1 << 2)); //reset adc + dac
perif.ctrl->poke32(TOREG(SR_MISC_OUTS), (1 << 1) | (1 << 0)); //out of reset + dac enable
@@ -883,20 +908,20 @@ void x300_impl::setup_radio(const size_t mb_i, const size_t i, const std::string
////////////////////////////////////////////////////////////////
// create codec control objects
////////////////////////////////////////////////////////////////
- _tree->create<int>(mb_path / "rx_codecs" / db_name / "gains"); //phony property so this dir exists
- _tree->create<int>(mb_path / "tx_codecs" / db_name / "gains"); //phony property so this dir exists
- _tree->create<std::string>(mb_path / "rx_codecs" / db_name / "name").set("ads62p48");
- _tree->create<std::string>(mb_path / "tx_codecs" / db_name / "name").set("ad9146");
+ _tree->create<int>(mb_path / "rx_codecs" / slot_name / "gains"); //phony property so this dir exists
+ _tree->create<int>(mb_path / "tx_codecs" / slot_name / "gains"); //phony property so this dir exists
+ _tree->create<std::string>(mb_path / "rx_codecs" / slot_name / "name").set("ads62p48");
+ _tree->create<std::string>(mb_path / "tx_codecs" / slot_name / "name").set("ad9146");
- _tree->create<meta_range_t>(mb_path / "rx_codecs" / db_name / "gains" / "digital" / "range").set(meta_range_t(0, 6.0, 0.5));
- _tree->create<double>(mb_path / "rx_codecs" / db_name / "gains" / "digital" / "value")
+ _tree->create<meta_range_t>(mb_path / "rx_codecs" / slot_name / "gains" / "digital" / "range").set(meta_range_t(0, 6.0, 0.5));
+ _tree->create<double>(mb_path / "rx_codecs" / slot_name / "gains" / "digital" / "value")
.subscribe(boost::bind(&x300_adc_ctrl::set_gain, perif.adc, _1)).set(0);
////////////////////////////////////////////////////////////////////
// front end corrections
////////////////////////////////////////////////////////////////////
perif.rx_fe = rx_frontend_core_200::make(perif.ctrl, TOREG(SR_RX_FRONT));
- const fs_path rx_fe_path = mb_path / "rx_frontends" / db_name;
+ const fs_path rx_fe_path = mb_path / "rx_frontends" / slot_name;
_tree->create<std::complex<double> >(rx_fe_path / "dc_offset" / "value")
.coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, perif.rx_fe, _1))
.set(std::complex<double>(0.0, 0.0));
@@ -908,7 +933,7 @@ void x300_impl::setup_radio(const size_t mb_i, const size_t i, const std::string
.set(std::complex<double>(0.0, 0.0));
perif.tx_fe = tx_frontend_core_200::make(perif.ctrl, TOREG(SR_TX_FRONT));
- const fs_path tx_fe_path = mb_path / "tx_frontends" / db_name;
+ const fs_path tx_fe_path = mb_path / "tx_frontends" / slot_name;
_tree->create<std::complex<double> >(tx_fe_path / "dc_offset" / "value")
.coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, perif.tx_fe, _1))
.set(std::complex<double>(0.0, 0.0));
@@ -927,12 +952,12 @@ void x300_impl::setup_radio(const size_t mb_i, const size_t i, const std::string
_tree->access<double>(mb_path / "tick_rate")
.subscribe(boost::bind(&rx_vita_core_3000::set_tick_rate, perif.framer, _1))
.subscribe(boost::bind(&rx_dsp_core_3000::set_tick_rate, perif.ddc, _1));
- const fs_path rx_dsp_path = mb_path / "rx_dsps" / str(boost::format("%u") % dspno);
+ const fs_path rx_dsp_path = mb_path / "rx_dsps" / str(boost::format("%u") % radio_index);
_tree->create<meta_range_t>(rx_dsp_path / "rate" / "range")
.publish(boost::bind(&rx_dsp_core_3000::get_host_rates, perif.ddc));
_tree->create<double>(rx_dsp_path / "rate" / "value")
.coerce(boost::bind(&rx_dsp_core_3000::set_host_rate, perif.ddc, _1))
- .subscribe(boost::bind(&x300_impl::update_rx_samp_rate, this, boost::ref(mb), dspno, _1))
+ .subscribe(boost::bind(&x300_impl::update_rx_samp_rate, this, boost::ref(mb), radio_index, _1))
.set(1e6);
_tree->create<double>(rx_dsp_path / "freq" / "value")
.coerce(boost::bind(&rx_dsp_core_3000::set_freq, perif.ddc, _1))
@@ -951,12 +976,12 @@ void x300_impl::setup_radio(const size_t mb_i, const size_t i, const std::string
_tree->access<double>(mb_path / "tick_rate")
.subscribe(boost::bind(&tx_vita_core_3000::set_tick_rate, perif.deframer, _1))
.subscribe(boost::bind(&tx_dsp_core_3000::set_tick_rate, perif.duc, _1));
- const fs_path tx_dsp_path = mb_path / "tx_dsps" / str(boost::format("%u") % dspno);
+ const fs_path tx_dsp_path = mb_path / "tx_dsps" / str(boost::format("%u") % radio_index);
_tree->create<meta_range_t>(tx_dsp_path / "rate" / "range")
.publish(boost::bind(&tx_dsp_core_3000::get_host_rates, perif.duc));
_tree->create<double>(tx_dsp_path / "rate" / "value")
.coerce(boost::bind(&tx_dsp_core_3000::set_host_rate, perif.duc, _1))
- .subscribe(boost::bind(&x300_impl::update_tx_samp_rate, this, boost::ref(mb), dspno, _1))
+ .subscribe(boost::bind(&x300_impl::update_tx_samp_rate, this, boost::ref(mb), radio_index, _1))
.set(1e6);
_tree->create<double>(tx_dsp_path / "freq" / "value")
.coerce(boost::bind(&tx_dsp_core_3000::set_freq, perif.duc, _1))
@@ -975,14 +1000,15 @@ void x300_impl::setup_radio(const size_t mb_i, const size_t i, const std::string
////////////////////////////////////////////////////////////////////
// create RF frontend interfacing
////////////////////////////////////////////////////////////////////
- const size_t j = (db_name == "B")? 0x2 : 0x0;
- _tree->create<dboard_eeprom_t>(mb_path / "dboards" / db_name / "rx_eeprom")
+ const fs_path db_path = (mb_path / "dboards" / slot_name);
+ const size_t j = (slot_name == "B")? 0x2 : 0x0;
+ _tree->create<dboard_eeprom_t>(db_path / "rx_eeprom")
.set(mb.db_eeproms[X300_DB0_RX_EEPROM | j])
.subscribe(boost::bind(&x300_impl::set_db_eeprom, this, mb.zpu_i2c, (0x50 | X300_DB0_RX_EEPROM | j), _1));
- _tree->create<dboard_eeprom_t>(mb_path / "dboards" / db_name / "tx_eeprom")
+ _tree->create<dboard_eeprom_t>(db_path / "tx_eeprom")
.set(mb.db_eeproms[X300_DB0_TX_EEPROM | j])
.subscribe(boost::bind(&x300_impl::set_db_eeprom, this, mb.zpu_i2c, (0x50 | X300_DB0_TX_EEPROM | j), _1));
- _tree->create<dboard_eeprom_t>(mb_path / "dboards" / db_name / "gdb_eeprom")
+ _tree->create<dboard_eeprom_t>(db_path / "gdb_eeprom")
.set(mb.db_eeproms[X300_DB0_GDB_EEPROM | j])
.subscribe(boost::bind(&x300_impl::set_db_eeprom, this, mb.zpu_i2c, (0x50 | X300_DB0_GDB_EEPROM | j), _1));
@@ -994,33 +1020,33 @@ void x300_impl::setup_radio(const size_t mb_i, const size_t i, const std::string
db_config.tx_spi_slaveno = DB_TX_SEN;
db_config.i2c = mb.zpu_i2c;
db_config.clock = mb.clock;
- db_config.which_rx_clk = (db_name == "A")? X300_CLOCK_WHICH_DB0_RX : X300_CLOCK_WHICH_DB1_RX;
- db_config.which_tx_clk = (db_name == "A")? X300_CLOCK_WHICH_DB0_TX : X300_CLOCK_WHICH_DB1_TX;
- db_config.dboard_slot = (db_name == "A")? 0 : 1;
- _dboard_ifaces[db_name] = x300_make_dboard_iface(db_config);
+ db_config.which_rx_clk = (slot_name == "A")? X300_CLOCK_WHICH_DB0_RX : X300_CLOCK_WHICH_DB1_RX;
+ db_config.which_tx_clk = (slot_name == "A")? X300_CLOCK_WHICH_DB0_TX : X300_CLOCK_WHICH_DB1_TX;
+ db_config.dboard_slot = (slot_name == "A")? 0 : 1;
+ _dboard_ifaces[db_path] = x300_make_dboard_iface(db_config);
//create a new dboard manager
- _tree->create<dboard_iface::sptr>(mb_path / "dboards" / db_name / "iface").set(_dboard_ifaces[db_name]);
- _dboard_managers[db_name] = dboard_manager::make(
+ _tree->create<dboard_iface::sptr>(db_path / "iface").set(_dboard_ifaces[db_path]);
+ _dboard_managers[db_path] = dboard_manager::make(
mb.db_eeproms[X300_DB0_RX_EEPROM | j].id,
mb.db_eeproms[X300_DB0_TX_EEPROM | j].id,
mb.db_eeproms[X300_DB0_GDB_EEPROM | j].id,
- _dboard_ifaces[db_name],
- _tree->subtree(mb_path / "dboards" / db_name)
+ _dboard_ifaces[db_path],
+ _tree->subtree(db_path)
);
//now that dboard is created -- register into rx antenna event
- const std::string fe_name = _tree->list(mb_path / "dboards" / db_name / "rx_frontends").front();
- _tree->access<std::string>(mb_path / "dboards" / db_name / "rx_frontends" / fe_name / "antenna" / "value")
- .subscribe(boost::bind(&x300_impl::update_atr_leds, this, mb.radio_perifs[i].leds, _1));
- this->update_atr_leds(mb.radio_perifs[i].leds, ""); //init anyway, even if never called
+ const std::string fe_name = _tree->list(db_path / "rx_frontends").front();
+ _tree->access<std::string>(db_path / "rx_frontends" / fe_name / "antenna" / "value")
+ .subscribe(boost::bind(&x300_impl::update_atr_leds, this, mb.radio_perifs[radio_index].leds, _1));
+ this->update_atr_leds(mb.radio_perifs[radio_index].leds, ""); //init anyway, even if never called
//bind frontend corrections to the dboard freq props
- const fs_path db_rx_fe_path = mb_path / "dboards" / db_name / "rx_frontends";
+ const fs_path db_rx_fe_path = db_path / "rx_frontends";
BOOST_FOREACH(const std::string &name, _tree->list(db_rx_fe_path))
{
_tree->access<double>(db_rx_fe_path / name / "freq" / "value")
- .subscribe(boost::bind(&x300_impl::set_rx_fe_corrections, this, mb_path, db_name, _1));
+ .subscribe(boost::bind(&x300_impl::set_rx_fe_corrections, this, mb_path, slot_name, _1));
}
}
@@ -1120,29 +1146,28 @@ x300_impl::both_xports_t x300_impl::make_transport(
/* Print a warning if the system's max available frame size is less than the most optimal
* frame size for this type of connection. */
- if (max_frame_sizes.send_frame_size < eth_data_rec_frame_size) {
+ if (_max_frame_sizes.send_frame_size < eth_data_rec_frame_size) {
UHD_MSG(warning)
<< boost::format("For this connection, UHD recommends a send frame size of at least %lu for best\nperformance, but your system's MTU will only allow %lu.")
% eth_data_rec_frame_size
- % max_frame_sizes.send_frame_size
+ % _max_frame_sizes.send_frame_size
<< std::endl
<< "This will negatively impact your maximum achievable sample rate."
<< std::endl;
}
- if (max_frame_sizes.recv_frame_size < eth_data_rec_frame_size) {
+ if (_max_frame_sizes.recv_frame_size < eth_data_rec_frame_size) {
UHD_MSG(warning)
<< boost::format("For this connection, UHD recommends a receive frame size of at least %lu for best\nperformance, but your system's MTU will only allow %lu.")
% eth_data_rec_frame_size
- % max_frame_sizes.recv_frame_size
+ % _max_frame_sizes.recv_frame_size
<< std::endl
<< "This will negatively impact your maximum achievable sample rate."
<< std::endl;
}
- // Account for headers
- size_t system_max_send_frame_size = (size_t) max_frame_sizes.send_frame_size - 64;
- size_t system_max_recv_frame_size = (size_t) max_frame_sizes.recv_frame_size - 64;
+ size_t system_max_send_frame_size = (size_t) _max_frame_sizes.send_frame_size;
+ size_t system_max_recv_frame_size = (size_t) _max_frame_sizes.recv_frame_size;
// Make sure frame sizes do not exceed the max available value supported by UHD
default_buff_args.send_frame_size =
@@ -1165,7 +1190,7 @@ x300_impl::both_xports_t x300_impl::make_transport(
? X300_ETH_DATA_NUM_FRAMES
: X300_ETH_MSG_NUM_FRAMES;
- //make a new transport - fpga has no idea how to talk to use on this yet
+ //make a new transport - fpga has no idea how to talk to us on this yet
udp_zero_copy::buff_params buff_params;
xports.recv = udp_zero_copy::make(mb.addr,
BOOST_STRINGIZE(X300_VITA_UDP_PORT),
@@ -1289,60 +1314,112 @@ void x300_impl::register_loopback_self_test(wb_iface::sptr iface)
void x300_impl::set_time_source_out(mboard_members_t &mb, const bool enb)
{
- mb.clock_control_regs__pps_out_enb = enb? 1 : 0;
+ mb.clock_control_regs_pps_out_enb = enb? 1 : 0;
this->update_clock_control(mb);
}
void x300_impl::update_clock_control(mboard_members_t &mb)
{
- const size_t reg = mb.clock_control_regs__clock_source
- | (mb.clock_control_regs__pps_select << 2)
- | (mb.clock_control_regs__pps_out_enb << 3)
- | (mb.clock_control_regs__tcxo_enb << 4)
- | (mb.clock_control_regs__gpsdo_pwr << 5)
+ const size_t reg = mb.clock_control_regs_clock_source
+ | (mb.clock_control_regs_pps_select << 2)
+ | (mb.clock_control_regs_pps_out_enb << 4)
+ | (mb.clock_control_regs_tcxo_enb << 5)
+ | (mb.clock_control_regs_gpsdo_pwr << 6)
;
mb.zpu_ctrl->poke32(SR_ADDR(SET0_BASE, ZPU_SR_CLOCK_CTRL), reg);
}
void x300_impl::update_clock_source(mboard_members_t &mb, const std::string &source)
{
- mb.clock_control_regs__clock_source = 0;
+ mb.clock_control_regs_clock_source = 0;
+ mb.clock_control_regs_tcxo_enb = 0;
if (source == "internal") {
- mb.clock_control_regs__clock_source = 0x2;
-
- mb.clock_control_regs__tcxo_enb = (source == "internal")? 1 : 0;
+ mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL;
+ mb.clock_control_regs_tcxo_enb = 1;
} else if (source == "external") {
- mb.clock_control_regs__clock_source = 0x0;
+ mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL;
} else if (source == "gpsdo") {
- mb.clock_control_regs__clock_source = 0x3;
+ mb.clock_control_regs_clock_source = ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO;
} else {
throw uhd::key_error("update_clock_source: unknown source: " + source);
}
this->update_clock_control(mb);
+
+ //reset the clock control
+ //without this, the lock time is long and can be as much as 30 seconds
+ mb.clock->reset_clocks();
+
+ /* FIXME: implement when we know the correct timeouts
+ * //wait for lock
+ * double timeout = 1.0;
+ * try {
+ * if (mb.hw_rev > 4)
+ * wait_for_ref_locked(mb.zpu_ctrl, timeout);
+ * } catch (uhd::runtime_error &e) {
+ * //failed to lock on reference
+ * throw uhd::runtime_error((boost::format("Clock failed to lock to %s source.") % source).str());
+ * }
+ */
}
void x300_impl::update_time_source(mboard_members_t &mb, const std::string &source)
{
if (source == "internal") {
- // no action needed
+ mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL;
} else if (source == "external") {
- mb.clock_control_regs__pps_select = (source == "external")? 1 : 0;
+ mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL;
} else if (source == "gpsdo") {
- // no action needed
+ mb.clock_control_regs_pps_select = ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO;
} else {
throw uhd::key_error("update_time_source: unknown source: " + source);
}
this->update_clock_control(mb);
+
+ //check for valid pps
+ if (!is_pps_present(mb.zpu_ctrl))
+ {
+ throw uhd::runtime_error((boost::format("The %d PPS was not detected. Please check the PPS source and try again.") % source).str());
+ }
+}
+
+void x300_impl::wait_for_ref_locked(wb_iface::sptr ctrl, double timeout)
+{
+ boost::system_time timeout_time = boost::get_system_time() + boost::posix_time::milliseconds(timeout * 1000.0);
+ do
+ {
+ if (get_ref_locked(ctrl).to_bool())
+ return;
+ boost::this_thread::sleep(boost::posix_time::milliseconds(1));
+ } while (boost::get_system_time() < timeout_time);
+
+ //failed to lock on reference
+ throw uhd::runtime_error("The reference clock failed to lock.");
}
sensor_value_t x300_impl::get_ref_locked(wb_iface::sptr ctrl)
{
- const bool lock = (ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)) & (1 << 2)) != 0;
+ uint32_t clk_status = ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS));
+ const bool lock = ((clk_status & ZPU_RB_CLK_STATUS_LMK_LOCK) != 0);
return sensor_value_t("Ref", lock, "locked", "unlocked");
}
+bool x300_impl::is_pps_present(wb_iface::sptr ctrl)
+{
+ // The ZPU_RB_CLK_STATUS_PPS_DETECT bit toggles with each rising edge of the PPS.
+ // We monitor it for up to 1.5 seconds looking for it to toggle.
+ uint32_t pps_detect = ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS)) & ZPU_RB_CLK_STATUS_PPS_DETECT;
+ for (int i = 0; i < 15; i++)
+ {
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ uint32_t clk_status = ctrl->peek32(SR_ADDR(SET0_BASE, ZPU_RB_CLK_STATUS));
+ if (pps_detect != (clk_status & ZPU_RB_CLK_STATUS_PPS_DETECT))
+ return true;
+ }
+ return false;
+}
+
void x300_impl::set_db_eeprom(i2c_iface::sptr i2c, const size_t addr, const uhd::usrp::dboard_eeprom_t &db_eeprom)
{
db_eeprom.store(*i2c, addr);
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index 1fb3676a0..259ea253d 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -82,8 +82,8 @@ static const double X300_DEFAULT_SYSREF_RATE = 10e6;
#define X300_XB_DST_E0 0
#define X300_XB_DST_E1 1
-#define X300_XB_DST_R0 2
-#define X300_XB_DST_R1 3
+#define X300_XB_DST_R0 2 // Radio 0 -> Slot A
+#define X300_XB_DST_R1 3 // Radio 1 -> Slot B
#define X300_XB_DST_CE0 4
#define X300_XB_DST_CE1 5
#define X300_XB_DST_CE2 5
@@ -191,12 +191,13 @@ private:
i2c_core_100_wb32::sptr zpu_i2c;
//perifs in each radio
- radio_perifs_t radio_perifs[2];
+ radio_perifs_t radio_perifs[2]; //!< This is hardcoded s.t. radio_perifs[0] points to slot A and [1] to B
uhd::usrp::dboard_eeprom_t db_eeproms[8];
-
- //per mboard frontend mapping
- uhd::usrp::subdev_spec_t rx_fe_map;
- uhd::usrp::subdev_spec_t tx_fe_map;
+ //! Return the index of a radio component, given a slot name. This means DSPs, radio_perifs
+ size_t get_radio_index(const std::string &slot_name) {
+ UHD_ASSERT_THROW(slot_name == "A" or slot_name == "B");
+ return slot_name == "A" ? 0 : 1;
+ }
//other perifs on mboard
x300_clock_ctrl::sptr clock;
@@ -204,14 +205,16 @@ private:
gpio_core_200::sptr fp_gpio;
//clock control register bits
- int clock_control_regs__clock_source;
- int clock_control_regs__pps_select;
- int clock_control_regs__pps_out_enb;
- int clock_control_regs__tcxo_enb;
- int clock_control_regs__gpsdo_pwr;
+ int clock_control_regs_clock_source;
+ int clock_control_regs_pps_select;
+ int clock_control_regs_pps_out_enb;
+ int clock_control_regs_tcxo_enb;
+ int clock_control_regs_gpsdo_pwr;
//which FPGA image is loaded
std::string loaded_fpga_image;
+
+ size_t hw_rev;
};
std::vector<mboard_members_t> _mb;
@@ -222,7 +225,20 @@ private:
void register_loopback_self_test(uhd::wb_iface::sptr iface);
- void setup_radio(const size_t, const size_t which_radio, const std::string &db_name);
+ /*! \brief Initialize the radio component on a given slot.
+ *
+ * Call this function once per slot (A and B) and motherboard to initialize all the radio components.
+ * This will:
+ * - Reset and init DACs and ADCs
+ * - Setup controls for DAC, ADC, SPI and LEDs
+ * - Self test ADC
+ * - Sync DACs (for MIMO)
+ * - Initialize the property tree for control objects etc. (gain, rate...)
+ *
+ * \param mb_i Motherboard index
+ * \param slot_name Slot name (A or B).
+ */
+ void setup_radio(const size_t, const std::string &slot_name);
size_t _sid_framer;
struct sid_config_t
@@ -253,7 +269,7 @@ private:
size_t recv_frame_size;
size_t send_frame_size;
};
- frame_size_t max_frame_sizes;
+ frame_size_t _max_frame_sizes;
/*!
* Automatically determine the maximum frame size available by sending a UDP packet
@@ -288,8 +304,15 @@ private:
void set_rx_fe_corrections(const uhd::fs_path &mb_path, const std::string &fe_name, const double lo_freq);
- void update_rx_subdev_spec(const size_t, const uhd::usrp::subdev_spec_t &spec);
- void update_tx_subdev_spec(const size_t, const uhd::usrp::subdev_spec_t &spec);
+ /*! Update the IQ MUX settings for the radio peripheral according to given subdev spec.
+ *
+ * Also checks if the given subdev is valid for this device and updates the channel to DSP mapping.
+ *
+ * \param tx_rx "tx" or "rx", depending where you're setting the subdev spec
+ * \param mb_i Mainboard index number.
+ * \param spec Subdev spec
+ */
+ void update_subdev_spec(const std::string &tx_rx, const size_t mb_i, const uhd::usrp::subdev_spec_t &spec);
void set_tick_rate(mboard_members_t &, const double);
void update_tick_rate(mboard_members_t &, const double);
@@ -302,6 +325,8 @@ private:
void update_time_source(mboard_members_t&, const std::string &);
uhd::sensor_value_t get_ref_locked(uhd::wb_iface::sptr);
+ void wait_for_ref_locked(uhd::wb_iface::sptr, double timeout = 0.0);
+ bool is_pps_present(uhd::wb_iface::sptr);
void set_db_eeprom(uhd::i2c_iface::sptr i2c, const size_t, const uhd::usrp::dboard_eeprom_t &);
void set_mb_eeprom(uhd::i2c_iface::sptr i2c, const uhd::usrp::mboard_eeprom_t &);
diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp
index 00a31b8d6..85de34a54 100644
--- a/host/lib/usrp/x300/x300_io_impl.cpp
+++ b/host/lib/usrp/x300/x300_io_impl.cpp
@@ -77,76 +77,52 @@ void x300_impl::update_tx_samp_rate(mboard_members_t &mb, const size_t dspno, co
/***********************************************************************
* Setup dboard muxing for IQ
**********************************************************************/
-void x300_impl::update_rx_subdev_spec(const size_t mb_i, const subdev_spec_t &spec)
+void x300_impl::update_subdev_spec(const std::string &tx_rx, const size_t mb_i, const subdev_spec_t &spec)
{
+ UHD_ASSERT_THROW(tx_rx == "tx" or tx_rx == "rx");
+ UHD_ASSERT_THROW(mb_i < _mb.size());
const std::string mb_name = boost::lexical_cast<std::string>(mb_i);
- fs_path root = "/mboards/"+mb_name+"/dboards";
+ fs_path mb_root = "/mboards/" + mb_name;
//sanity checking
- validate_subdev_spec(_tree, spec, "rx", mb_name);
+ validate_subdev_spec(_tree, spec, tx_rx, mb_name);
UHD_ASSERT_THROW(spec.size() <= 2);
- if (spec.size() > 0) UHD_ASSERT_THROW(spec[0].db_name == "A");
- if (spec.size() > 1) UHD_ASSERT_THROW(spec[1].db_name == "B");
-
- //setup mux for this spec
- for (size_t i = 0; i < 2; i++)
- {
- //extract db name
- const std::string db_name = (i == 0)? "A" : "B";
- if (i < spec.size()) UHD_ASSERT_THROW(spec[i].db_name == db_name);
-
- //extract fe name
- std::string fe_name;
- if (i < spec.size()) fe_name = spec[i].sd_name;
- else fe_name = _tree->list(root / db_name / "rx_frontends").front();
-
- //extract connection
- const std::string conn = _tree->access<std::string>(root / db_name / "rx_frontends" / fe_name / "connection").get();
-
- //swap condition
- const bool fe_swapped = (conn == "QI" or conn == "Q");
- _mb[mb_i].radio_perifs[i].ddc->set_mux(conn, fe_swapped);
- //see usrp/io_impl.cpp if multiple DSPs share the frontend:
- _mb[mb_i].radio_perifs[i].rx_fe->set_mux(fe_swapped);
+ if (spec.size() == 1) {
+ UHD_ASSERT_THROW(spec[0].db_name == "A" || spec[0].db_name == "B");
+ }
+ else if (spec.size() == 2) {
+ UHD_ASSERT_THROW(
+ (spec[0].db_name == "A" && spec[1].db_name == "B") ||
+ (spec[0].db_name == "B" && spec[1].db_name == "A")
+ );
}
- _mb[mb_i].rx_fe_map = spec;
-}
-
-void x300_impl::update_tx_subdev_spec(const size_t mb_i, const subdev_spec_t &spec)
-{
- const std::string mb_name = boost::lexical_cast<std::string>(mb_i);
- fs_path root = "/mboards/"+mb_name+"/dboards";
-
- //sanity checking
- validate_subdev_spec(_tree, spec, "tx", mb_name);
- UHD_ASSERT_THROW(spec.size() <= 2);
- if (spec.size() > 0) UHD_ASSERT_THROW(spec[0].db_name == "A");
- if (spec.size() > 1) UHD_ASSERT_THROW(spec[1].db_name == "B");
-
- //set the mux for this spec
- for (size_t i = 0; i < 2; i++)
+ std::vector<size_t> chan_to_dsp_map(spec.size(), 0);
+ // setup mux for this spec
+ for (size_t i = 0; i < spec.size(); i++)
{
- //extract db name
- const std::string db_name = (i == 0)? "A" : "B";
- if (i < spec.size()) UHD_ASSERT_THROW(spec[i].db_name == db_name);
-
- //extract fe name
- std::string fe_name;
- if (i < spec.size()) fe_name = spec[i].sd_name;
- else fe_name = _tree->list(root / db_name / "tx_frontends").front();
+ const int radio_idx = _mb[mb_i].get_radio_index(spec[i].db_name);
+ chan_to_dsp_map[i] = radio_idx;
//extract connection
- const std::string conn = _tree->access<std::string>(root / db_name / "tx_frontends" / fe_name / "connection").get();
-
- //swap condition
- _mb[mb_i].radio_perifs[i].tx_fe->set_mux(conn);
+ const std::string conn = _tree->access<std::string>(mb_root / "dboards" / spec[i].db_name / (tx_rx + "_frontends") / spec[i].sd_name / "connection").get();
+ if (tx_rx == "tx") {
+ //swap condition
+ _mb[mb_i].radio_perifs[radio_idx].tx_fe->set_mux(conn);
+ } else {
+ //swap condition
+ const bool fe_swapped = (conn == "QI" or conn == "Q");
+ _mb[mb_i].radio_perifs[radio_idx].ddc->set_mux(conn, fe_swapped);
+ //see usrp/io_impl.cpp if multiple DSPs share the frontend:
+ _mb[mb_i].radio_perifs[radio_idx].rx_fe->set_mux(fe_swapped);
+ }
}
- _mb[mb_i].tx_fe_map = spec;
+ _tree->access<std::vector<size_t> >(mb_root / (tx_rx + "_chan_dsp_mapping")).set(chan_to_dsp_map);
}
+
/***********************************************************************
* VITA stuff
**********************************************************************/
@@ -375,16 +351,28 @@ rx_streamer::sptr x300_impl::get_rx_stream(const uhd::stream_args_t &args_)
boost::shared_ptr<sph::recv_packet_streamer> my_streamer;
for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++)
{
+ // Find the mainboard and subdev that corresponds to channel args.channels[stream_i]
const size_t chan = args.channels[stream_i];
- size_t mb_chan = chan, mb_index = 0;
- BOOST_FOREACH(mboard_members_t &mb, _mb)
- {
- if (mb_chan < mb.rx_fe_map.size()) break;
- else mb_chan -= mb.rx_fe_map.size();
- mb_index++;
+ size_t mb_chan = chan, mb_index;
+ for (mb_index = 0; mb_index < _mb.size(); mb_index++) {
+ const subdev_spec_t &curr_subdev_spec =
+ _tree->access<subdev_spec_t>("/mboards/" + boost::lexical_cast<std::string>(mb_index) / "rx_subdev_spec").get();
+ if (mb_chan < curr_subdev_spec.size()) {
+ break;
+ } else {
+ mb_chan -= curr_subdev_spec.size();
+ }
}
+
+ // Find the DSP that corresponds to this mainboard and subdev
+ UHD_ASSERT_THROW(mb_index < _mb.size());
mboard_members_t &mb = _mb[mb_index];
- radio_perifs_t &perif = mb.radio_perifs[mb_chan];
+ const std::vector<size_t> dsp_map = _tree->access<std::vector<size_t> >("/mboards/" + boost::lexical_cast<std::string>(mb_index) / "rx_chan_dsp_mapping")
+ .get(); //.at(mb_chan);
+ UHD_ASSERT_THROW(mb_chan < dsp_map.size());
+ const size_t radio_index = dsp_map[mb_chan];
+ UHD_ASSERT_THROW(radio_index < 2);
+ radio_perifs_t &perif = mb.radio_perifs[radio_index];
//setup the dsp transport hints (default to a large recv buff)
device_addr_t device_addr = mb.recv_args;
@@ -405,7 +393,7 @@ rx_streamer::sptr x300_impl::get_rx_stream(const uhd::stream_args_t &args_)
}
//allocate sid and create transport
- uint8_t dest = (mb_chan == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
+ uint8_t dest = (radio_index == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
boost::uint32_t data_sid;
UHD_LOG << "creating rx stream " << device_addr.to_string() << std::endl;
both_xports_t xport = this->make_transport(mb_index, dest, X300_RADIO_DEST_PREFIX_RX, device_addr, data_sid);
@@ -419,9 +407,9 @@ rx_streamer::sptr x300_impl::get_rx_stream(const uhd::stream_args_t &args_)
- sizeof(vrt::if_packet_info_t().cid) //no class id ever used
- sizeof(vrt::if_packet_info_t().tsi) //no int time ever used
;
- const size_t bpp = xport.recv->get_recv_frame_size() - hdr_size;
- const size_t bpi = convert::get_bytes_per_item(args.otw_format);
- const size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi));
+ const size_t bpp = xport.recv->get_recv_frame_size() - hdr_size; // bytes per packet
+ const size_t bpi = convert::get_bytes_per_item(args.otw_format); // bytes per item
+ const size_t spp = unsigned(args.args.cast<double>("spp", bpp/bpi)); // samples per packet
//make the new streamer given the samples per packet
if (not my_streamer) my_streamer = boost::make_shared<sph::recv_packet_streamer>(spp);
@@ -488,12 +476,12 @@ rx_streamer::sptr x300_impl::get_rx_stream(const uhd::stream_args_t &args_)
);
//Store a weak pointer to prevent a streamer->x300_impl->streamer circular dependency
- mb.rx_streamers[mb_chan] = boost::weak_ptr<sph::recv_packet_streamer>(my_streamer);
+ mb.rx_streamers[radio_index] = boost::weak_ptr<sph::recv_packet_streamer>(my_streamer);
//sets all tick and samp rates on this streamer
const fs_path mb_path = "/mboards/"+boost::lexical_cast<std::string>(mb_index);
_tree->access<double>(mb_path / "tick_rate").update();
- _tree->access<double>(mb_path / "rx_dsps" / boost::lexical_cast<std::string>(mb_chan) / "rate" / "value").update();
+ _tree->access<double>(mb_path / "rx_dsps" / boost::lexical_cast<std::string>(radio_index) / "rate" / "value").update();
}
return my_streamer;
@@ -552,22 +540,29 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_)
boost::shared_ptr<sph::send_packet_streamer> my_streamer;
for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++)
{
+ // Find the mainboard and subdev that corresponds to channel args.channels[stream_i]
const size_t chan = args.channels[stream_i];
- size_t mb_chan = chan, mb_index = 0;
- BOOST_FOREACH(mboard_members_t &mb, _mb)
- {
- if (mb_chan < mb.tx_fe_map.size()) break;
- else mb_chan -= mb.tx_fe_map.size();
- mb_index++;
+ size_t mb_chan = chan, mb_index;
+ for (mb_index = 0; mb_index < _mb.size(); mb_index++) {
+ const subdev_spec_t &curr_subdev_spec =
+ _tree->access<subdev_spec_t>("/mboards/" + boost::lexical_cast<std::string>(mb_index) / "tx_subdev_spec").get();
+ if (mb_chan < curr_subdev_spec.size()) {
+ break;
+ } else {
+ mb_chan -= curr_subdev_spec.size();
+ }
}
+ // Find the DSP that corresponds to this mainboard and subdev
mboard_members_t &mb = _mb[mb_index];
- radio_perifs_t &perif = mb.radio_perifs[mb_chan];
+ const size_t radio_index = _tree->access<std::vector<size_t> >("/mboards/" + boost::lexical_cast<std::string>(mb_index) / "tx_chan_dsp_mapping")
+ .get().at(mb_chan);
+ radio_perifs_t &perif = mb.radio_perifs[radio_index];
//setup the dsp transport hints (TODO)
device_addr_t device_addr = mb.send_args;
//allocate sid and create transport
- uint8_t dest = (mb_chan == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
+ uint8_t dest = (radio_index == 0)? X300_XB_DST_R0 : X300_XB_DST_R1;
boost::uint32_t data_sid;
UHD_LOG << "creating tx stream " << device_addr.to_string() << std::endl;
both_xports_t xport = this->make_transport(mb_index, dest, X300_RADIO_DEST_PREFIX_TX, device_addr, data_sid);
@@ -640,12 +635,12 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_)
my_streamer->set_enable_trailer(false); //TODO not implemented trailer support yet
//Store a weak pointer to prevent a streamer->x300_impl->streamer circular dependency
- mb.tx_streamers[mb_chan] = boost::weak_ptr<sph::send_packet_streamer>(my_streamer);
+ mb.tx_streamers[radio_index] = boost::weak_ptr<sph::send_packet_streamer>(my_streamer);
//sets all tick and samp rates on this streamer
const fs_path mb_path = "/mboards/"+boost::lexical_cast<std::string>(mb_index);
_tree->access<double>(mb_path / "tick_rate").update();
- _tree->access<double>(mb_path / "tx_dsps" / boost::lexical_cast<std::string>(mb_chan) / "rate" / "value").update();
+ _tree->access<double>(mb_path / "tx_dsps" / boost::lexical_cast<std::string>(radio_index) / "rate" / "value").update();
}
return my_streamer;
diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp
index e4ae76a38..fb1786deb 100644
--- a/host/lib/usrp/x300/x300_regs.hpp
+++ b/host/lib/usrp/x300/x300_regs.hpp
@@ -68,12 +68,26 @@ localparam ZPU_SR_SPI = 32;
localparam ZPU_SR_ETHINT0 = 40;
localparam ZPU_SR_ETHINT1 = 56;
+//clock controls
+#define ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL 0x00
+#define ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL 0x02
+#define ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO 0x03
+#define ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL 0x00
+#define ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL 0x02
+#define ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO 0x03
+
localparam ZPU_RB_SPI = 2;
localparam ZPU_RB_CLK_STATUS = 3;
localparam ZPU_RB_COMPAT_NUM = 6;
localparam ZPU_RB_ETH_TYPE0 = 4;
localparam ZPU_RB_ETH_TYPE1 = 5;
+//clock status
+#define ZPU_RB_CLK_STATUS_LMK_STATUS (0x3 << 0)
+#define ZPU_RB_CLK_STATUS_LMK_LOCK (0x1 << 2)
+#define ZPU_RB_CLK_STATUS_LMK_HOLDOVER (0x1 << 3)
+#define ZPU_RB_CLK_STATUS_PPS_DETECT (0x1 << 4)
+
//spi slaves on radio
#define DB_DAC_SEN (1 << 7)
#define DB_ADC_SEN (1 << 6)
diff --git a/host/utils/uhd_cal_rx_iq_balance.cpp b/host/utils/uhd_cal_rx_iq_balance.cpp
index 5fb494114..551da7544 100644
--- a/host/utils/uhd_cal_rx_iq_balance.cpp
+++ b/host/utils/uhd_cal_rx_iq_balance.cpp
@@ -20,6 +20,7 @@
#include <uhd/utils/safe_main.hpp>
#include <uhd/utils/paths.hpp>
#include <uhd/utils/algorithm.hpp>
+#include <uhd/utils/msg.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
@@ -93,7 +94,7 @@ static double tune_rx_and_tx(uhd::usrp::multi_usrp::sptr usrp, const double rx_l
* Main
**********************************************************************/
int UHD_SAFE_MAIN(int argc, char *argv[]){
- std::string args;
+ std::string args, subdev, serial;
double tx_wave_ampl, tx_offset;
double freq_start, freq_stop, freq_step;
size_t nsamps;
@@ -102,7 +103,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
desc.add_options()
("help", "help message")
("verbose", "enable some verbose")
- ("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]")
+ ("args", po::value<std::string>(&args)->default_value(""), "Device address args [default = \"\"]")
+ ("subdev", po::value<std::string>(&subdev), "Subdevice specification (default: first subdevice, often 'A')")
("tx_wave_ampl", po::value<double>(&tx_wave_ampl)->default_value(0.7), "Transmit wave amplitude in counts")
("tx_offset", po::value<double>(&tx_offset)->default_value(.9344e6), "TX LO offset from the RX LO in Hz")
("freq_start", po::value<double>(&freq_start), "Frequency start in Hz (do not specify for default)")
@@ -129,6 +131,15 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
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);
+ // Configure subdev
+ if (vm.count("subdev")) {
+ usrp->set_tx_subdev_spec(subdev);
+ usrp->set_rx_subdev_spec(subdev);
+ }
+ 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.");
@@ -158,6 +169,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (not vm.count("freq_start")) freq_start = usrp->get_rx_freq_range().start() + 50e6;
if (not vm.count("freq_stop")) freq_stop = usrp->get_rx_freq_range().stop() - 50e6;
+ UHD_MSG(status) << boost::format("Calibration frequency range: %d MHz -> %d MHz") % (freq_start/1e6) % (freq_stop/1e6) << std::endl;
for (double rx_lo_i = freq_start; rx_lo_i <= freq_stop; rx_lo_i += freq_step){
const double rx_lo = tune_rx_and_tx(usrp, rx_lo_i, tx_offset);
@@ -238,7 +250,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
threads.interrupt_all();
threads.join_all();
- store_results(usrp, results, "RX", "rx", "iq");
+ store_results(results, "RX", "rx", "iq", serial);
return EXIT_SUCCESS;
}
diff --git a/host/utils/uhd_cal_tx_dc_offset.cpp b/host/utils/uhd_cal_tx_dc_offset.cpp
index c9cf757f4..eb82db826 100644
--- a/host/utils/uhd_cal_tx_dc_offset.cpp
+++ b/host/utils/uhd_cal_tx_dc_offset.cpp
@@ -20,6 +20,7 @@
#include <uhd/utils/safe_main.hpp>
#include <uhd/utils/paths.hpp>
#include <uhd/utils/algorithm.hpp>
+#include <uhd/utils/msg.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
@@ -94,7 +95,7 @@ static double tune_rx_and_tx(uhd::usrp::multi_usrp::sptr usrp, const double tx_l
* Main
**********************************************************************/
int UHD_SAFE_MAIN(int argc, char *argv[]){
- std::string args;
+ std::string args, subdev, serial;
double tx_wave_freq, tx_wave_ampl, rx_offset;
double freq_start, freq_stop, freq_step;
size_t nsamps;
@@ -104,6 +105,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("help", "help message")
("verbose", "enable some verbose")
("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]")
+ ("subdev", po::value<std::string>(&subdev), "Subdevice specification (default: first subdevice, often 'A')")
("tx_wave_freq", po::value<double>(&tx_wave_freq)->default_value(507.123e3), "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")
@@ -131,6 +133,15 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
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);
+ // Configure subdev
+ if (vm.count("subdev")) {
+ usrp->set_tx_subdev_spec(subdev);
+ usrp->set_rx_subdev_spec(subdev);
+ }
+ 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.");
@@ -160,6 +171,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
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 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);
@@ -235,7 +247,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
threads.interrupt_all();
threads.join_all();
- store_results(usrp, results, "TX", "tx", "dc");
+ store_results(results, "TX", "tx", "dc", serial);
return EXIT_SUCCESS;
}
diff --git a/host/utils/uhd_cal_tx_iq_balance.cpp b/host/utils/uhd_cal_tx_iq_balance.cpp
index 20d018edf..786aac061 100644
--- a/host/utils/uhd_cal_tx_iq_balance.cpp
+++ b/host/utils/uhd_cal_tx_iq_balance.cpp
@@ -20,6 +20,7 @@
#include <uhd/utils/safe_main.hpp>
#include <uhd/utils/paths.hpp>
#include <uhd/utils/algorithm.hpp>
+#include <uhd/utils/msg.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
@@ -95,7 +96,7 @@ static double tune_rx_and_tx(uhd::usrp::multi_usrp::sptr usrp, const double tx_l
* Main
**********************************************************************/
int UHD_SAFE_MAIN(int argc, char *argv[]){
- std::string args;
+ std::string args, subdev, serial;
double tx_wave_freq, tx_wave_ampl, rx_offset;
double freq_start, freq_stop, freq_step;
size_t nsamps;
@@ -105,6 +106,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("help", "help message")
("verbose", "enable some verbose")
("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]")
+ ("subdev", po::value<std::string>(&subdev), "Subdevice specification (default: first subdevice, often 'A')")
("tx_wave_freq", po::value<double>(&tx_wave_freq)->default_value(507.123e3), "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")
@@ -122,7 +124,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (vm.count("help")){
std::cout << boost::format("USRP Generate TX IQ Balance 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 on a daughterboard to self-calibrate.\n"
<< std::endl;
return EXIT_FAILURE;
}
@@ -132,6 +134,15 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
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);
+ // Configure subdev
+ if (vm.count("subdev")) {
+ usrp->set_tx_subdev_spec(subdev);
+ usrp->set_rx_subdev_spec(subdev);
+ }
+ 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.");
@@ -161,6 +172,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
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 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);
@@ -241,7 +253,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
threads.interrupt_all();
threads.join_all();
- store_results(usrp, results, "TX", "tx", "iq");
+ store_results(results, "TX", "tx", "iq", serial);
return EXIT_SUCCESS;
}
+
diff --git a/host/utils/usrp_cal_utils.hpp b/host/utils/usrp_cal_utils.hpp
index 40626dfaa..5aff5e22f 100644
--- a/host/utils/usrp_cal_utils.hpp
+++ b/host/utils/usrp_cal_utils.hpp
@@ -179,27 +179,37 @@ static inline void write_samples_to_file(
outfile.close();
}
+
/***********************************************************************
- * Store data to file
+ * Retrieve d'board serial
**********************************************************************/
-static void store_results(
+static std::string get_serial(
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 &tx_rx
){
- //extract eeprom serial
uhd::property_tree::sptr tree = usrp->get_device()->get_tree();
- const uhd::fs_path db_path = "/mboards/0/dboards/A/" + xx + "_eeprom";
+ 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;
+}
+/***********************************************************************
+ * Store data to file
+ **********************************************************************/
+static void store_results(
+ const std::vector<result_t> &results,
+ const std::string &XX, // "TX" or "RX"
+ const std::string &xx, // "tx" or "rx"
+ const std::string &what, // Type of test, e.g. "iq",
+ const std::string &serial
+){
//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.2_%s.csv") % xx % what % db_eeprom.serial);
+ cal_data_path = cal_data_path / str(boost::format("%s_%s_cal_v0.2_%s.csv") % xx % what % serial);
if (fs::exists(cal_data_path)){
fs::rename(cal_data_path, cal_data_path.string() + str(boost::format(".%d") % time(NULL)));
}
@@ -207,7 +217,7 @@ static void store_results(
//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("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");
@@ -259,3 +269,4 @@ static void capture_samples(
throw std::runtime_error("did not get all the samples requested");
}
}
+