[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r8407 - in usrp2/trunk: doc firmware/apps firmware/inc
From: |
eb |
Subject: |
[Commit-gnuradio] r8407 - in usrp2/trunk: doc firmware/apps firmware/include firmware/lib host/apps host/lib |
Date: |
Sun, 11 May 2008 23:47:50 -0600 (MDT) |
Author: eb
Date: 2008-05-11 23:47:50 -0600 (Sun, 11 May 2008)
New Revision: 8407
Added:
usrp2/trunk/firmware/apps/app_common_v2.c
usrp2/trunk/firmware/apps/app_common_v2.h
usrp2/trunk/firmware/apps/rx_only_v2.c
usrp2/trunk/firmware/apps/tx_only_v2.c
usrp2/trunk/firmware/apps/txrx.c
usrp2/trunk/host/apps/rx_samples_at_t.cc
Modified:
usrp2/trunk/doc/inband-signaling-eth
usrp2/trunk/firmware/apps/
usrp2/trunk/firmware/apps/Makefile.am
usrp2/trunk/firmware/apps/app_common.c
usrp2/trunk/firmware/apps/app_passthru.c
usrp2/trunk/firmware/include/usrp2_eth_packet.h
usrp2/trunk/firmware/include/usrp2_types.h
usrp2/trunk/firmware/lib/db_basic.c
usrp2/trunk/firmware/lib/db_init.c
usrp2/trunk/firmware/lib/dbsm.c
usrp2/trunk/firmware/lib/dbsm.h
usrp2/trunk/host/apps/Makefile.am
usrp2/trunk/host/apps/rx_streaming_samples.cc
usrp2/trunk/host/apps/tx_samples.cc
usrp2/trunk/host/lib/usrp2_basic.cc
usrp2/trunk/host/lib/usrp2_basic.h
Log:
USRP2 simultaneous Tx and Rx is working. Uses new config packet
format. Merged eb/u2-newpktfmt -r8394:8406 into usrp2 trunk.
Modified: usrp2/trunk/doc/inband-signaling-eth
===================================================================
--- usrp2/trunk/doc/inband-signaling-eth 2008-05-12 05:32:16 UTC (rev
8406)
+++ usrp2/trunk/doc/inband-signaling-eth 2008-05-12 05:47:50 UTC (rev
8407)
@@ -161,10 +161,10 @@
Specific sub-packet formats:
----------------------------
- RID: 6-bit Request-ID. Copied from request sub-packet into corresponding
+ RID: 8-bit Request-ID. Copied from request sub-packet into corresponding
reply sub-packet. RID allows the host to match requests and replies.
- Reg Number: 10-bit Register Number.
+ Reg Number: 8-bit Register Number.
@@ -173,7 +173,7 @@
Opcode: OP_ID
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | 2 | RID | mbz |
+ | Opcode | 2 | RID | mbz |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -182,7 +182,7 @@
Opcode: OP_ID_REPLY
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | 50 | RID | mbz |
+ | Opcode | 50 | RID | mbz |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Mac Addr 0 | Mac Addr 1 | Mac Addr 2 | Mac Addr 3 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -210,30 +210,12 @@
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-Ping Fixed Length:
-
- Opcode: OP_PING_FIXED
-
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | 2 | RID | Ping Value |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-
-Ping Fixed Length Reply:
-
- Opcode: OP_PING_FIXED_REPLY
-
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | 2 | RID | Ping Value |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
-
Write Register:
Opcode: OP_WRITE_REG
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | 6 | mbz | Reg Number |
+ | Opcode | 6 | mbz | Reg Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Register Value |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -250,7 +232,7 @@
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | 10 | mbz | Reg Number |
+ | Opcode | 10 | mbz | Reg Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Register Value |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -263,7 +245,7 @@
Opcode: OP_READ_REG
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | 2 | RID | Reg Number |
+ | Opcode | 2 | RID | Reg Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -272,7 +254,7 @@
Opcode: OP_READ_REG_REPLY
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | 6 | RID | Reg Number |
+ | Opcode | 6 | RID | Reg Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Register Value |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -288,12 +270,25 @@
Length: Length of Data + 2
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | Length | mbz | I2C Addr |
+ | Opcode | Length | RID | I2C Addr |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data ... .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+I2C Write Reply:
+
+ Opcode: OP_I2C_WRITE_REPLY
+ Length: 2
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Opcode | 2 | RID | OK |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+OK is 1 if successful, else 0.
+
+
I2C Read:
Opcode: OP_I2C_READ
@@ -301,7 +296,7 @@
Nbytes: Number of bytes to read from I2C bus
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | 3 | RID | mbz | I2C Addr |
+ | Opcode | 3 | RID | I2C Addr |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Nbytes | unspecified padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -314,12 +309,14 @@
Data: Length - 2 bytes of data read from I2C bus.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | Length | RID | mbz | I2C Addr |
+ | Opcode | Length | RID | OK |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data ... .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+OK is 1 if successful, else 0
+
SPI Write:
Opcode: OP_SPI_WRITE
@@ -330,7 +327,7 @@
Length: Length of Data + 6
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | Length | mbz |
+ | Opcode | Length | RID | mbz |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Enables | Format | Opt Header Bytes |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -338,6 +335,19 @@
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+SPI Write Reply:
+
+ Opcode: OP_SPI_WRITE_REPLY
+ Length: 2
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Opcode | 2 | RID | OK |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+
+OK is 1 if successful, else 0.
+
+
SPI Read:
Opcode: OP_SPI_READ
@@ -347,7 +357,7 @@
Nbytes: Number of bytes to read from SPI bus.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Opcode | 7 | RID | mbz |
+ | Opcode | 7 | RID | mbz |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Enables | Format | Opt Header Bytes |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Property changes on: usrp2/trunk/firmware/apps
___________________________________________________________________
Name: svn:ignore
- *-stamp
*.a
*.bin
*.dump
*.log
*.rom
*.map
.deps
Makefile
Makefile.in
aclocal.m4
autom4te.cache
blink_leds
blink_leds2
build
compile
config.h
config.h.in
config.log
config.status
configure
depcomp
eth_test
gen_eth_packets
ibs_rx_test
ibs_tx_test
install-sh
libtool
ltmain.sh
missing
py-compile
rcv_eth_packets
run_tests.sh
stamp-h1
test1
test_phy_comm
timer_test
buf_ram_test
buf_ram_zero
hello
test_printf
test_spi
test_i2c
gen_pause_frames
test_serdes
rx_only
tx_only
tx_standalone
tx_drop
tx_drop2
tx_drop_rate_limited
test_lsdac
test_lsadc
read_dbids
test_db_spi
ramp_lsdac
eth_to_serdes
serdes_to_dsp
sd_gentest
sd_bounce
can_i_sub
+ *-stamp
*.a
*.bin
*.dump
*.log
*.rom
*.map
.deps
Makefile
Makefile.in
aclocal.m4
autom4te.cache
blink_leds
blink_leds2
build
compile
config.h
config.h.in
config.log
config.status
configure
depcomp
eth_test
gen_eth_packets
ibs_rx_test
ibs_tx_test
install-sh
libtool
ltmain.sh
missing
py-compile
rcv_eth_packets
run_tests.sh
stamp-h1
test1
test_phy_comm
timer_test
buf_ram_test
buf_ram_zero
hello
test_printf
test_spi
test_i2c
gen_pause_frames
test_serdes
rx_only
tx_only
tx_standalone
tx_drop
tx_drop2
tx_drop_rate_limited
test_lsdac
test_lsadc
read_dbids
test_db_spi
ramp_lsdac
eth_to_serdes
serdes_to_dsp
sd_gentest
sd_bounce
can_i_sub
tx_only_v2
rx_only_v2
txrx
Modified: usrp2/trunk/firmware/apps/Makefile.am
===================================================================
--- usrp2/trunk/firmware/apps/Makefile.am 2008-05-12 05:32:16 UTC (rev
8406)
+++ usrp2/trunk/firmware/apps/Makefile.am 2008-05-12 05:47:50 UTC (rev
8407)
@@ -30,6 +30,7 @@
ibs_tx_test \
rcv_eth_packets \
rx_only \
+ rx_only_v2 \
read_dbids \
test1 \
test_db_spi \
@@ -40,7 +41,9 @@
test_serdes \
timer_test \
tx_only \
+ tx_only_v2 \
tx_standalone \
+ txrx \
eth_to_serdes \
serdes_to_dsp \
sd_gentest \
@@ -52,6 +55,9 @@
# tx_drop2_SOURCES = tx_drop2.c app_common.c
tx_only_SOURCES = tx_only.c app_common.c
rx_only_SOURCES = rx_only.c app_common.c
+rx_only_v2_SOURCES = rx_only_v2.c app_common_v2.c
+tx_only_v2_SOURCES = tx_only_v2.c app_common_v2.c
+txrx_SOURCES = txrx.c app_common_v2.c
eth_to_serdes_SOURCES = eth_to_serdes.c app_passthru.c
serdes_to_dsp_SOURCES = serdes_to_dsp.c app_common.c
Modified: usrp2/trunk/firmware/apps/app_common.c
===================================================================
--- usrp2/trunk/firmware/apps/app_common.c 2008-05-12 05:32:16 UTC (rev
8406)
+++ usrp2/trunk/firmware/apps/app_common.c 2008-05-12 05:47:50 UTC (rev
8407)
@@ -91,7 +91,7 @@
reply_len = sizeof(u2_eth_packet_t) + sizeof(op_id_reply_t);
r->opcode = OP_ID_REPLY;
r->len = sizeof(op_id_reply_t);
- r->rid_mbz = ((op_id_t *) p)->rid_mbz;
+ r->rid = ((op_id_t *) p)->rid;
r->addr = *ethernet_mac_addr();
r->hw_rev = 0x0000; // FIXME
// r->fpga_md5sum = ; // FIXME
@@ -124,7 +124,7 @@
reply_len = sizeof(u2_eth_packet_t) + sizeof(op_read_time_reply_t);
r->opcode = OP_READ_TIME_REPLY;
r->len = sizeof(op_read_time_reply_t);
- r->rid_mbz = ((op_read_time_t *) p)->rid_mbz;
+ r->rid = ((op_read_time_t *) p)->rid;
r->time = timer_regs->time;
}
send_reply(reply, reply_len);
Copied: usrp2/trunk/firmware/apps/app_common_v2.c (from rev 8406,
usrp2/branches/developers/eb/u2-newpktfmt/firmware/apps/app_common_v2.c)
===================================================================
--- usrp2/trunk/firmware/apps/app_common_v2.c (rev 0)
+++ usrp2/trunk/firmware/apps/app_common_v2.c 2008-05-12 05:47:50 UTC (rev
8407)
@@ -0,0 +1,228 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "app_common_v2.h"
+#include "buffer_pool.h"
+#include "memcpy_wa.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "print_rmon_regs.h"
+#include <string.h>
+
+volatile bool link_is_up = false; // eth handler sets this
+
+
+// If this is non-zero, this dbsm could be writing to the ethernet
+dbsm_t *ac_could_be_sending_to_eth;
+
+static unsigned char exp_seqno = 0;
+
+
+static void
+burn_mac_addr(const op_burn_mac_addr_t *p)
+{
+ ethernet_set_mac_addr(&p->addr);
+}
+
+void
+set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt)
+{
+ reply_pkt->ehdr.dst = cmd_pkt->ehdr.src;
+ reply_pkt->ehdr.ethertype = U2_ETHERTYPE;
+ reply_pkt->thdr.flags = 0;
+ reply_pkt->thdr.fifo_status = 0; // written by protocol engine
+ reply_pkt->thdr.seqno = 0; // written by protocol engine
+ reply_pkt->thdr.ack = 0; // written by protocol engine
+ u2p_set_word0(&reply_pkt->fixed, 0, CONTROL_CHAN);
+ reply_pkt->fixed.timestamp = timer_regs->time;
+}
+
+static void
+send_reply(unsigned char *reply, size_t reply_len)
+{
+ if (reply_len < 64)
+ reply_len = 64;
+
+ // wait for buffer to become idle
+ while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0)
+ ;
+
+ // copy reply into CPU_TX_BUF
+ memcpy_wa(buffer_ram(CPU_TX_BUF), reply, reply_len);
+
+ // wait until nobody else is sending to the ethernet
+ if (ac_could_be_sending_to_eth)
+ dbsm_wait_for_opening(ac_could_be_sending_to_eth);
+
+ // fire it off
+ bp_send_from_buf(CPU_TX_BUF, PORT_ETH, 1, 0, reply_len/4);
+
+ // wait for it to complete (not long, it's a small pkt)
+ while((buffer_pool_status->status & (BPS_DONE(CPU_TX_BUF) |
BPS_ERROR(CPU_TX_BUF))) == 0)
+ ;
+
+ bp_clear_buf(CPU_TX_BUF);
+}
+
+
+void
+handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
+{
+ unsigned char reply[sizeof(u2_eth_packet_t) + sizeof(u2_subpkt_t)] _AL4;
+ unsigned char *s = &reply[sizeof(u2_eth_packet_t)];
+ size_t reply_len = 0;
+
+ // point to beginning of payload (subpackets)
+ unsigned char *p = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t);
+
+ // FIXME iterate over payload, handling more than a single subpacket
+
+ int opcode = p[0];
+
+ switch(opcode){
+ case OP_ID:
+ memset(reply, 0, sizeof(reply));
+ set_reply_hdr((u2_eth_packet_t *) reply, pkt);
+ {
+ op_id_reply_t *r = (op_id_reply_t *) s;
+ reply_len = sizeof(u2_eth_packet_t) + sizeof(op_id_reply_t);
+ r->opcode = OP_ID_REPLY;
+ r->len = sizeof(op_id_reply_t);
+ r->rid = ((op_id_t *) p)->rid;
+ r->addr = *ethernet_mac_addr();
+ r->hw_rev = 0x0000; // FIXME
+ // r->fpga_md5sum = ; // FIXME
+ // r->sw_md5sum = ; // FIXME
+
+ // FIXME Add d'board info, including dbid, min/max gain, min/max freq
+ }
+ send_reply(reply, reply_len);
+ break;
+
+ case OP_CONFIG_TX_V2:
+ config_tx_v2_cmd((op_config_tx_v2_t *) p);
+ break;
+
+ case OP_CONFIG_RX_V2:
+ config_rx_v2_cmd((op_config_rx_v2_t *) p);
+ break;
+
+ case OP_START_RX_STREAMING:
+ start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) p);
+ break;
+
+ case OP_STOP_RX:
+ stop_rx_cmd();
+ break;
+
+ case OP_BURN_MAC_ADDR:
+ burn_mac_addr((op_burn_mac_addr_t *) p);
+ break;
+
+ case OP_READ_TIME:
+ memset(reply, 0, sizeof(reply));
+ set_reply_hdr((u2_eth_packet_t *) reply, pkt);
+ {
+ op_read_time_reply_t *r = (op_read_time_reply_t *) s;
+ reply_len = sizeof(u2_eth_packet_t) + sizeof(op_read_time_reply_t);
+ r->opcode = OP_READ_TIME_REPLY;
+ r->len = sizeof(op_read_time_reply_t);
+ r->rid = ((op_read_time_t *) p)->rid;
+ r->time = timer_regs->time;
+ }
+ send_reply(reply, reply_len);
+ break;
+
+ default:
+ printf("app_common_v2: unhandled opcode = %d\n", opcode);
+ break;
+ }
+}
+
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here, otherwise
+ * it'll be passed on to the DSP Tx pipe
+ */
+bool
+eth_pkt_inspector(dbsm_t *sm, int bufno)
+{
+ u2_eth_packet_t *pkt = (u2_eth_packet_t *) buffer_ram(bufno);
+ size_t byte_len = (buffer_pool_status->last_line[bufno] - 3) * 4;
+
+ hal_toggle_leds(0x1);
+
+ // inspect rcvd frame and figure out what do do.
+
+ if (pkt->ehdr.ethertype != U2_ETHERTYPE)
+ return true; // ignore, probably bogus PAUSE frame from MAC
+
+ int chan = u2p_chan(&pkt->fixed);
+
+ switch (chan){
+ case CONTROL_CHAN:
+ handle_control_chan_frame(pkt, byte_len);
+ return true; // we handled the packet
+ break;
+
+ case 0:
+ default:
+#if 0
+ if((pkt->thdr.seqno) == exp_seqno){
+ exp_seqno++;
+ //putchar('.');
+ }
+ else {
+ // putchar('S');
+ //printf("S%d %d ",exp_seqno,pkt->thdr.seqno);
+ exp_seqno = pkt->thdr.seqno + 1;
+ }
+#endif
+ return false; // pass it on to Tx DSP
+ break;
+ }
+}
+
+/*
+ * Called when eth phy state changes (w/ interrupts disabled)
+ */
+void
+link_changed_callback(int speed)
+{
+ link_is_up = speed != 0;
+ hal_set_leds(link_is_up ? 0x10 : 0x0, 0x10);
+ printf("\neth link changed: speed = %d\n", speed);
+}
+
+
+void
+print_tune_result(char *msg, bool tune_ok,
+ u2_fxpt_freq_t target_freq, struct tune_result *r)
+{
+ printf("db_tune %s %s\n", msg, tune_ok ? "true" : "false");
+ putstr(" target_freq "); print_fxpt_freq(target_freq); newline();
+ putstr(" baseband_freq "); print_fxpt_freq(r->baseband_freq); newline();
+ putstr(" dxc_freq "); print_fxpt_freq(r->dxc_freq); newline();
+ putstr(" residual_freq "); print_fxpt_freq(r->residual_freq); newline();
+ printf(" inverted %s\n", r->inverted ? "true" : "false");
+}
Copied: usrp2/trunk/firmware/apps/app_common_v2.h (from rev 8406,
usrp2/branches/developers/eb/u2-newpktfmt/firmware/apps/app_common_v2.h)
===================================================================
--- usrp2/trunk/firmware/apps/app_common_v2.h (rev 0)
+++ usrp2/trunk/firmware/apps/app_common_v2.h 2008-05-12 05:47:50 UTC (rev
8407)
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDED_APP_COMMON_H
+#define INCLUDED_APP_COMMON_H
+
+#include "bool.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include <stddef.h>
+#include <db.h>
+
+#define CPU_TX_BUF 1 // cpu -> eth
+
+#define _AL4 __attribute__((aligned (4)))
+
+extern volatile bool link_is_up; // eth handler sets this
+
+
+// If there's a dbsm that sends to the ethernet, put it's address here
+extern dbsm_t *ac_could_be_sending_to_eth;
+
+
+void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt);
+
+/*
+ * Called when an ethernet packet is received.
+ * Return true if we handled it here, otherwise
+ * it'll be passed on to the DSP Tx pipe
+ */
+bool eth_pkt_inspector(dbsm_t *sm, int bufno);
+
+void link_changed_callback(int speed);
+
+void
+print_tune_result(char *msg, bool tune_ok,
+ u2_fxpt_freq_t target_freq, struct tune_result *r);
+
+
+// FIXME move these somewhere else?
+void config_tx_v2_cmd(op_config_tx_v2_t *p);
+void config_rx_v2_cmd(op_config_rx_v2_t *p);
+void start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t
*p);
+void stop_rx_cmd(void);
+
+void handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len);
+
+#endif /* INCLUDED_APP_COMMON_H */
Modified: usrp2/trunk/firmware/apps/app_passthru.c
===================================================================
--- usrp2/trunk/firmware/apps/app_passthru.c 2008-05-12 05:32:16 UTC (rev
8406)
+++ usrp2/trunk/firmware/apps/app_passthru.c 2008-05-12 05:47:50 UTC (rev
8407)
@@ -74,7 +74,7 @@
reply_len = 64;
r->opcode = OP_ID_REPLY;
r->len = sizeof(op_id_reply_t);
- r->rid_mbz = 0; // FIXME
+ r->rid = 0; // FIXME
r->addr = *ethernet_mac_addr();
r->hw_rev = 0x0000; // FIXME
// r->fpga_md5sum = ; // FIXME
Copied: usrp2/trunk/firmware/apps/rx_only_v2.c (from rev 8406,
usrp2/branches/developers/eb/u2-newpktfmt/firmware/apps/rx_only_v2.c)
===================================================================
--- usrp2/trunk/firmware/apps/rx_only_v2.c (rev 0)
+++ usrp2/trunk/firmware/apps/rx_only_v2.c 2008-05-12 05:47:50 UTC (rev
8407)
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2007 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "memcpy_wa.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <db.h>
+#include <db_base.h>
+
+
+#define FW_SETS_SEQNO 1 // define to 0 or 1
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno; // used when f/w is filling in sequence numbers
+#endif
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 0 is used for rcvd frames from ethernet
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ */
+#define CPU_RX_BUF 0 // eth -> cpu
+//#define CPU_TX_BUF 1 // cpu -> eth
+#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> eth
+
+
+// variables for streaming mode
+
+static bool streaming_p = false;
+static int streaming_frame_count = 0;
+#define FRAMES_PER_CMD 1000
+
+
+/*
+ * ================================================================
+ * configure DSP RX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) +
sizeof(u2_transport_hdr_t))/4 + 1)
+
+// receive from DSP
+buf_cmd_args_t dsp_rx_recv_args = {
+ PORT_DSP,
+ DSP_RX_FIRST_LINE,
+ BP_LAST_LINE
+};
+
+// send to ETH
+buf_cmd_args_t dsp_rx_send_args = {
+ PORT_ETH,
+ 0, // starts with ethernet header in line 0
+ 0, // filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm; // the state machine
+
+// ----------------------------------------------------------------
+
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+void link_changed_callback(int speed);
+static volatile bool link_is_up = false; // eth handler sets this
+
+
+void
+config_tx_v2_cmd(op_config_tx_v2_t *p)
+{
+ // FIXME nop
+}
+
+void
+config_rx_v2_cmd(op_config_rx_v2_t *p)
+{
+ struct tune_result tune_result;
+ memset(&tune_result, 0, sizeof(tune_result));
+
+ bool ok = true;
+
+ if (p->valid & CFGV_GAIN){
+ ok &= rx_dboard->set_gain(rx_dboard, p->gain);
+ }
+
+ if (p->valid & CFGV_FREQ){
+ u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+ bool tune_ok = db_tune(rx_dboard, f, &tune_result);
+ ok &= tune_ok;
+ print_tune_result("Rx", tune_ok, f, &tune_result);
+ }
+
+ if (p->valid & CFGV_INTERP_DECIM){
+ dsp_rx_regs->decim_rate = p->decim - 1; // register gets N-1
+ }
+
+ if (p->valid & CFGV_SCALE_IQ){
+ dsp_rx_regs->scale_iq = p->scale_iq;
+ }
+
+ // FIXME build and send reply
+}
+
+
+void
+start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+ host_mac_addr = *host; // remember who we're sending to
+
+ /*
+ * Construct ethernet header and word0 and preload into two buffers
+ */
+ u2_eth_packet_t pkt;
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.ehdr.dst = *host;
+ pkt.ehdr.ethertype = U2_ETHERTYPE;
+ u2p_set_word0(&pkt.fixed, 0, 0);
+ // DSP RX will fill in timestamp
+
+ memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+ memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+ if (FW_SETS_SEQNO)
+ fw_seqno = 0;
+
+ // setup RX DSP regs
+ dsp_rx_regs->clear_state = 1; // reset
+
+ if (1){ // we're streaming
+ streaming_p = true;
+ streaming_frame_count = FRAMES_PER_CMD;
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(FRAMES_PER_CMD * p->items_per_frame, p->items_per_frame,
+ 1, 1); // set "chain" bit
+
+ // kick off the state machine
+ dbsm_start(&dsp_rx_sm);
+ dsp_rx_regs->rx_time = 0; // enqueue first of two commands
+
+ // make sure this one and the rest have the "now" and "chain" bits set.
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(FRAMES_PER_CMD * p->items_per_frame, p->items_per_frame,
+ 1, 1);
+ dsp_rx_regs->rx_time = 0; // enqueue second command
+ }
+#if 0
+ else {
+ streaming_p = false;
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(p->total_samples, p->items_per_frame, p->rx_now, 0);
+
+ // kick off the state machine
+ dbsm_start(&dsp_rx_sm);
+ dsp_rx_regs->rx_time = p->rx_time;
+ }
+#endif
+}
+
+
+void
+stop_rx_cmd(void)
+{
+ streaming_p = false;
+ dsp_rx_regs->clear_state = 1; // flush cmd queue
+ bp_clear_buf(DSP_RX_BUF_0);
+ bp_clear_buf(DSP_RX_BUF_1);
+}
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ uint32_t status = buffer_pool_status->status;
+
+ if (status & BPS_DONE(CPU_RX_BUF)){ // we've rcvd a frame from ethernet
+ bp_clear_buf(CPU_RX_BUF);
+ eth_pkt_inspector(0, CPU_RX_BUF);
+ bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+ }
+ if (status & BPS_ERROR(CPU_RX_BUF)){ // error from ethernet
+ bp_clear_buf(CPU_RX_BUF);
+ bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+ }
+
+ dbsm_process_status(&dsp_rx_sm, status);
+
+ if (status & BPS_DONE(CPU_TX_BUF)){
+ bp_clear_buf(CPU_TX_BUF);
+ }
+}
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY. This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet. A bit of a kludge
+ * but it should work.
+ */
+bool
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
+{
+ uint32_t *p = buffer_ram(buf_this);
+ uint32_t seqno = fw_seqno++;
+
+ // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+ uint32_t t = p[4];
+ t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+ p[4] = t;
+
+ // queue up another rx command when required
+ if (streaming_p && --streaming_frame_count == 0){
+ streaming_frame_count = FRAMES_PER_CMD;
+ dsp_rx_regs->rx_time = 0;
+ }
+
+ return false; // we didn't handle the packet
+}
+#endif
+
+
+int
+main(void)
+{
+ u2_init();
+
+ putstr("\nrx_only_v2\n");
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+ // initialize double buffering state machine for DSP RX -> Ethernet
+
+ if (FW_SETS_SEQNO){
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ fw_sets_seqno_inspector);
+ }
+ else {
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ dbsm_nop_inspector);
+ }
+
+ // setup receive from ETH
+ bp_receive_to_buf(CPU_RX_BUF, PORT_ETH, 1, 0, BP_LAST_LINE);
+
+
+ while(1){
+ buffer_irq_handler(0);
+
+ int pending = pic_regs->pending; // poll for under or overrun
+
+ if (pending & PIC_OVERRUN_INT){
+ dbsm_handle_rx_overrun(&dsp_rx_sm);
+ pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt
+ putchar('O');
+ }
+ }
+}
Copied: usrp2/trunk/firmware/apps/tx_only_v2.c (from rev 8406,
usrp2/branches/developers/eb/u2-newpktfmt/firmware/apps/tx_only_v2.c)
===================================================================
--- usrp2/trunk/firmware/apps/tx_only_v2.c (rev 0)
+++ usrp2/trunk/firmware/apps/tx_only_v2.c 2008-05-12 05:47:50 UTC (rev
8407)
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <db.h>
+#include <db_base.h>
+
+
+/*
+ * This program can respond to queries from the host
+ * and stream rx samples.
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow
+ */
+//#define CPU_RX_BUF 0 // eth -> cpu
+//#define CPU_TX_BUF 1 // cpu -> eth
+
+#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> eth
+#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer)
+#define DSP_TX_BUF_1 5 // eth -> dsp tx
+
+/*
+ * ================================================================
+ * configure DSP TX double buffering state machine
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) +
sizeof(u2_transport_hdr_t))/4)
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+ PORT_ETH,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+ PORT_DSP,
+ DSP_TX_FIRST_LINE, // starts just past transport header
+ 0 // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm; // the state machine
+
+
+// ----------------------------------------------------------------
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+void
+config_tx_v2_cmd(op_config_tx_v2_t *p)
+{
+ struct tune_result tune_result;
+ memset(&tune_result, 0, sizeof(tune_result));
+
+ bool ok = true;
+
+ if (p->valid & CFGV_GAIN){
+ ok &= tx_dboard->set_gain(tx_dboard, p->gain);
+ }
+
+ if (p->valid & CFGV_FREQ){
+ u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+ bool tune_ok = db_tune(tx_dboard, f, &tune_result);
+ ok &= tune_ok;
+ print_tune_result("Tx", tune_ok, f, &tune_result);
+ }
+
+ if (p->valid & CFGV_INTERP_DECIM){
+ dsp_tx_regs->interp_rate = p->interp - 1; // register gets N-1
+ }
+
+ if (p->valid & CFGV_SCALE_IQ){
+ dsp_tx_regs->scale_iq = p->scale_iq;
+ }
+
+ // FIXME build and send reply
+}
+
+void
+config_rx_v2_cmd(op_config_rx_v2_t *p)
+{
+ // FIXME nop
+}
+
+
+void
+start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+ // FIXME nop
+}
+
+
+void
+stop_rx_cmd(void)
+{
+ // FIXME nop
+}
+
+
+static void
+setup_tx()
+{
+ dsp_tx_regs->clear_state = 1;
+ bp_clear_buf(DSP_TX_BUF_0);
+ bp_clear_buf(DSP_TX_BUF_1);
+
+ int tx_scale = 256;
+ int interp = 32;
+
+ // setup some defaults
+
+ dsp_tx_regs->freq = 0;
+ dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+ dsp_tx_regs->interp_rate = interp - 1; // register gets N-1
+}
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ //hal_toggle_leds(0x2);
+
+ uint32_t status = buffer_pool_status->status;
+
+ dbsm_process_status(&dsp_tx_sm, status);
+
+ if (status & BPS_DONE(CPU_TX_BUF)){
+ bp_clear_buf(CPU_TX_BUF);
+ }
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ putstr("\ntx_only_v2\n");
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+ // initialize double buffering state machine for ethernet -> DSP Tx
+
+ dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+ &dsp_tx_recv_args, &dsp_tx_send_args,
+ eth_pkt_inspector);
+
+ // program tx registers
+ setup_tx();
+
+ // kick off the state machine
+ dbsm_start(&dsp_tx_sm);
+
+ while(1){
+ buffer_irq_handler(0);
+
+ int pending = pic_regs->pending; // poll for under or overrun
+
+ if (pending & PIC_UNDERRUN_INT){
+ dbsm_handle_tx_underrun(&dsp_tx_sm);
+ pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt
+ putchar('U');
+ }
+ }
+}
Copied: usrp2/trunk/firmware/apps/txrx.c (from rev 8406,
usrp2/branches/developers/eb/u2-newpktfmt/firmware/apps/txrx.c)
===================================================================
--- usrp2/trunk/firmware/apps/txrx.c (rev 0)
+++ usrp2/trunk/firmware/apps/txrx.c 2008-05-12 05:47:50 UTC (rev 8407)
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "u2_init.h"
+#include "memory_map.h"
+#include "spi.h"
+#include "hal_io.h"
+#include "buffer_pool.h"
+#include "pic.h"
+#include "bool.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "usrp2_eth_packet.h"
+#include "dbsm.h"
+#include "app_common_v2.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <db.h>
+#include <db_base.h>
+
+
+#define FW_SETS_SEQNO 1 // define to 0 or 1 (FIXME must be 1 for now)
+
+#if (FW_SETS_SEQNO)
+static int fw_seqno; // used when f/w is filling in sequence numbers
+#endif
+
+
+/*
+ * Full duplex Tx and Rx between ethernet and DSP pipelines
+ *
+ * Buffer 1 is used by the cpu to send frames to the host.
+ * Buffers 2 and 3 are used to double-buffer the DSP Rx to eth flow
+ * Buffers 4 and 5 are used to double-buffer the eth to DSP Tx eth flow
+ */
+//#define CPU_RX_BUF 0 // eth -> cpu
+
+#define DSP_RX_BUF_0 2 // dsp rx -> eth (double buffer)
+#define DSP_RX_BUF_1 3 // dsp rx -> eth
+#define DSP_TX_BUF_0 4 // eth -> dsp tx (double buffer)
+#define DSP_TX_BUF_1 5 // eth -> dsp tx
+
+/*
+ * ================================================================
+ * configure DSP TX double buffering state machine (eth -> dsp)
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 2 lines (word0 + timestamp)
+// DSP Tx reads word0 (flags) + timestamp followed by samples
+
+#define DSP_TX_FIRST_LINE ((sizeof(u2_eth_hdr_t) +
sizeof(u2_transport_hdr_t))/4)
+
+// Receive from ethernet
+buf_cmd_args_t dsp_tx_recv_args = {
+ PORT_ETH,
+ 0,
+ BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t dsp_tx_send_args = {
+ PORT_DSP,
+ DSP_TX_FIRST_LINE, // starts just past transport header
+ 0 // filled in from last_line register
+};
+
+dbsm_t dsp_tx_sm; // the state machine
+
+/*
+ * ================================================================
+ * configure DSP RX double buffering state machine (dsp -> eth)
+ * ================================================================
+ */
+
+// 4 lines of ethernet hdr + 1 line transport hdr + 1 line (word0)
+// DSP Rx writes timestamp followed by nlines_per_frame of samples
+#define DSP_RX_FIRST_LINE ((sizeof(u2_eth_hdr_t) +
sizeof(u2_transport_hdr_t))/4 + 1)
+
+// receive from DSP
+buf_cmd_args_t dsp_rx_recv_args = {
+ PORT_DSP,
+ DSP_RX_FIRST_LINE,
+ BP_LAST_LINE
+};
+
+// send to ETH
+buf_cmd_args_t dsp_rx_send_args = {
+ PORT_ETH,
+ 0, // starts with ethernet header in line 0
+ 0, // filled in from list_line register
+};
+
+dbsm_t dsp_rx_sm; // the state machine
+
+
+// The mac address of the host we're sending to.
+u2_mac_addr_t host_mac_addr;
+
+
+// variables for streaming mode
+
+static bool streaming_p = false;
+static int streaming_frame_count = 0;
+#define FRAMES_PER_CMD 1000
+
+
+// ----------------------------------------------------------------
+
+
+
+void
+config_tx_v2_cmd(op_config_tx_v2_t *p)
+{
+ struct tune_result tune_result;
+ memset(&tune_result, 0, sizeof(tune_result));
+
+ bool ok = true;
+
+ if (p->valid & CFGV_GAIN){
+ ok &= tx_dboard->set_gain(tx_dboard, p->gain);
+ }
+
+ if (p->valid & CFGV_FREQ){
+ u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+ bool tune_ok = db_tune(tx_dboard, f, &tune_result);
+ ok &= tune_ok;
+ print_tune_result("Tx", tune_ok, f, &tune_result);
+ }
+
+ if (p->valid & CFGV_INTERP_DECIM){
+ dsp_tx_regs->interp_rate = p->interp - 1; // register gets N-1
+ }
+
+ if (p->valid & CFGV_SCALE_IQ){
+ dsp_tx_regs->scale_iq = p->scale_iq;
+ }
+
+ // FIXME build and send reply
+}
+
+void
+config_rx_v2_cmd(op_config_rx_v2_t *p)
+{
+ struct tune_result tune_result;
+ memset(&tune_result, 0, sizeof(tune_result));
+
+ bool ok = true;
+
+ if (p->valid & CFGV_GAIN){
+ ok &= rx_dboard->set_gain(rx_dboard, p->gain);
+ }
+
+ if (p->valid & CFGV_FREQ){
+ u2_fxpt_freq_t f = u2_fxpt_freq_from_hilo(p->freq_hi, p->freq_lo);
+ bool tune_ok = db_tune(rx_dboard, f, &tune_result);
+ ok &= tune_ok;
+ print_tune_result("Rx", tune_ok, f, &tune_result);
+ }
+
+ if (p->valid & CFGV_INTERP_DECIM){
+ dsp_rx_regs->decim_rate = p->decim - 1; // register gets N-1
+ }
+
+ if (p->valid & CFGV_SCALE_IQ){
+ dsp_rx_regs->scale_iq = p->scale_iq;
+ }
+
+ // FIXME build and send reply
+}
+
+
+void
+start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+ host_mac_addr = *host; // remember who we're sending to
+
+ /*
+ * Construct ethernet header and word0 and preload into two buffers
+ */
+ u2_eth_packet_t pkt;
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.ehdr.dst = *host;
+ pkt.ehdr.ethertype = U2_ETHERTYPE;
+ u2p_set_word0(&pkt.fixed, 0, 0);
+ // DSP RX will fill in timestamp
+
+ memcpy_wa(buffer_ram(DSP_RX_BUF_0), &pkt, sizeof(pkt));
+ memcpy_wa(buffer_ram(DSP_RX_BUF_1), &pkt, sizeof(pkt));
+
+
+ if (FW_SETS_SEQNO)
+ fw_seqno = 0;
+
+ // setup RX DSP regs
+ dsp_rx_regs->clear_state = 1; // reset
+
+ if (1){ // we're streaming
+ streaming_p = true;
+ streaming_frame_count = FRAMES_PER_CMD;
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(FRAMES_PER_CMD * p->items_per_frame, p->items_per_frame,
+ 1, 1); // set "chain" bit
+
+ // kick off the state machine
+ dbsm_start(&dsp_rx_sm);
+ dsp_rx_regs->rx_time = 0; // enqueue first of two commands
+
+ // make sure this one and the rest have the "now" and "chain" bits set.
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(FRAMES_PER_CMD * p->items_per_frame, p->items_per_frame,
+ 1, 1);
+ dsp_rx_regs->rx_time = 0; // enqueue second command
+ }
+#if 0
+ else {
+ streaming_p = false;
+ dsp_rx_regs->rx_command =
+ MK_RX_CMD(p->total_samples, p->items_per_frame, p->rx_now, 0);
+
+ // kick off the state machine
+ dbsm_start(&dsp_rx_sm);
+ dsp_rx_regs->rx_time = p->rx_time;
+ }
+#endif
+}
+
+
+void
+stop_rx_cmd(void)
+{
+ streaming_p = false;
+ dsp_rx_regs->clear_state = 1; // flush cmd queue
+ bp_clear_buf(DSP_RX_BUF_0);
+ bp_clear_buf(DSP_RX_BUF_1);
+}
+
+
+static void
+setup_tx()
+{
+ dsp_tx_regs->clear_state = 1;
+ bp_clear_buf(DSP_TX_BUF_0);
+ bp_clear_buf(DSP_TX_BUF_1);
+
+ int tx_scale = 256;
+ int interp = 32;
+
+ // setup some defaults
+
+ dsp_tx_regs->freq = 0;
+ dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+ dsp_tx_regs->interp_rate = interp - 1; // register gets N-1
+}
+
+
+#if (FW_SETS_SEQNO)
+/*
+ * Debugging ONLY. This will be handled by the tx_protocol_engine.
+ *
+ * This is called when the DSP Rx chain has filled in a packet.
+ * We set and increment the seqno, then return false, indicating
+ * that we didn't handle the packet. A bit of a kludge
+ * but it should work.
+ */
+bool
+fw_sets_seqno_inspector(dbsm_t *sm, int buf_this) // returns false
+{
+ uint32_t *p = buffer_ram(buf_this);
+ uint32_t seqno = fw_seqno++;
+
+ // KLUDGE all kinds of nasty magic numbers and embedded knowledge
+ uint32_t t = p[4];
+ t = (t & 0xffff00ff) | ((seqno & 0xff) << 8);
+ p[4] = t;
+
+ // queue up another rx command when required
+ if (streaming_p && --streaming_frame_count == 0){
+ streaming_frame_count = FRAMES_PER_CMD;
+ dsp_rx_regs->rx_time = 0;
+ }
+
+ return false; // we didn't handle the packet
+}
+#endif
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+ //hal_toggle_leds(0x2);
+
+ uint32_t status = buffer_pool_status->status;
+
+ dbsm_process_status(&dsp_tx_sm, status);
+ dbsm_process_status(&dsp_rx_sm, status);
+
+#if 0 // not needed, we busy wait in app_common_v2
+ if (status & BPS_DONE(CPU_TX_BUF)){
+ bp_clear_buf(CPU_TX_BUF);
+ }
+#endif
+
+}
+
+int
+main(void)
+{
+ u2_init();
+
+ putstr("\nTxRx\n");
+
+ ethernet_register_link_changed_callback(link_changed_callback);
+ ethernet_init();
+
+ // initialize double buffering state machine for ethernet -> DSP Tx
+
+ dbsm_init(&dsp_tx_sm, DSP_TX_BUF_0,
+ &dsp_tx_recv_args, &dsp_tx_send_args,
+ eth_pkt_inspector);
+
+
+ // initialize double buffering state machine for DSP RX -> Ethernet
+
+ if (FW_SETS_SEQNO){
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ fw_sets_seqno_inspector);
+ }
+ else {
+ dbsm_init(&dsp_rx_sm, DSP_RX_BUF_0,
+ &dsp_rx_recv_args, &dsp_rx_send_args,
+ dbsm_nop_inspector);
+ }
+
+ // tell app_common that this dbsm could be sending to the ethernet
+ ac_could_be_sending_to_eth = &dsp_rx_sm;
+
+
+ // program tx registers
+ setup_tx();
+
+ // kick off the state machine
+ dbsm_start(&dsp_tx_sm);
+
+ while(1){
+ buffer_irq_handler(0);
+
+ int pending = pic_regs->pending; // poll for under or overrun
+
+ if (pending & PIC_UNDERRUN_INT){
+ dbsm_handle_tx_underrun(&dsp_tx_sm);
+ pic_regs->pending = PIC_UNDERRUN_INT; // clear interrupt
+ putchar('U');
+ }
+
+ if (pending & PIC_OVERRUN_INT){
+ dbsm_handle_rx_overrun(&dsp_rx_sm);
+ pic_regs->pending = PIC_OVERRUN_INT; // clear pending interrupt
+ putchar('O');
+ }
+ }
+}
Modified: usrp2/trunk/firmware/include/usrp2_eth_packet.h
===================================================================
--- usrp2/trunk/firmware/include/usrp2_eth_packet.h 2008-05-12 05:32:16 UTC
(rev 8406)
+++ usrp2/trunk/firmware/include/usrp2_eth_packet.h 2008-05-12 05:47:50 UTC
(rev 8407)
@@ -77,6 +77,8 @@
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Timestamp |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * mbz == must be zero
*/
typedef struct {
@@ -138,11 +140,12 @@
/*
* full load of samples:
- * ethernet header + pad + fixed header + maximum number of samples.
- * sizeof(u2_eth_samples_t) == 2048
+ * ethernet header + transport header + fixed header + maximum number of
samples.
+ * sizeof(u2_eth_samples_t) == 1512
+ * (payload is 1498 bytes, two bytes shorter than 1500 byte MTU)
*/
-#define U2_MAX_SAMPLES 505
+#define U2_MAX_SAMPLES 371
typedef struct {
u2_eth_packet_t hdrs;
@@ -152,39 +155,55 @@
/*
* Opcodes for control channel
*/
-#define OP_EOF 0 // marks last subpacket in
packet
+#define OP_EOP 0 // marks last subpacket in
packet
#define OP_ID 1
#define OP_ID_REPLY 2
-#define OP_START_RX 3
-#define OP_STOP_RX 4
-#define OP_WRITE_REG 5
-#define OP_WRITE_REG_MASKED 6
-#define OP_READ_REG 7
-#define OP_READ_REG_REPLY 8
-#define OP_BURN_MAC_ADDR 9
-#define OP_CONFIG_TX 10
-#define OP_READ_TIME 11 // What time is it? (100 MHz
counter)
-#define OP_READ_TIME_REPLY 12 // This time.
-#define OP_CONFIG_RX_V2 13
-#define OP_CONFIG_TX_V2 14
+#define OP_BURN_MAC_ADDR 3
+#define OP_READ_TIME 4 // What time is it? (100 MHz
counter)
+#define OP_READ_TIME_REPLY 5 // This time.
+#define OP_CONFIG_RX_V2 6
+#define OP_CONFIG_RX_REPLY_V2 7
+#define OP_CONFIG_TX_V2 8
+#define OP_CONFIG_TX_REPLY_V2 9
+#define OP_START_RX_STREAMING 10
+#define OP_STOP_RX 11
+#define OP_START_RX 20 // deprecated
+#define OP_CONFIG_TX 21 // deprecated
+#define OP_WRITE_REG 25 // not implemented
+#define OP_WRITE_REG_MASKED 26
+#define OP_READ_REG 27
+#define OP_READ_REG_REPLY 28
+
+
+/*!
+ * \brief Marker for last subpacket in packet
+ */
typedef struct {
uint8_t opcode;
uint8_t len;
uint16_t mbz;
-} op_eof_t;
+} op_eop_t;
+/*!
+ * \brief Look for USRP2's
+ */
typedef struct {
uint8_t opcode;
uint8_t len;
- uint16_t rid_mbz;
+ uint8_t rid;
+ uint8_t mbz;
} op_id_t;
+/*!
+ * \brief Reply info from a USRP2
+ */
typedef struct {
uint8_t opcode;
uint8_t len;
- uint16_t rid_mbz;
+ uint8_t rid;
+ uint8_t mbz;
u2_mac_addr_t addr;
uint16_t hw_rev;
uint8_t fpga_md5sum[16];
@@ -194,15 +213,9 @@
typedef struct {
uint8_t opcode;
uint8_t len;
- uint8_t rx_now; // 1 -> receive now, 0 -> at rx_time
- uint8_t mbz;
- int32_t phase_inc; // 2**32 * desired_freq/100e6
- uint32_t scale_iq; // (scale_i << 16) | scale_q [16.0 format]
- uint32_t decim; // desired decimation factor (NOT -1)
- uint32_t samples_per_frame; // MTU=1500: [9,372]; MTU=2034: [9,506]
- uint32_t total_samples; // [9, 2^21-1] == [9, 2,097,151]
- uint32_t rx_time; // when to begin receiving
-} op_start_rx_t;
+ uint16_t mbz;
+ uint32_t items_per_frame; // # of 32-bit data items; MTU=1500: [9,371]
+} op_start_rx_streaming_t;
typedef struct {
uint8_t opcode;
@@ -213,45 +226,39 @@
typedef struct {
uint8_t opcode;
uint8_t len;
- uint16_t mbz;
- int32_t phase_inc; // 2**32 * desired_freq/100e6
- uint32_t scale_iq; // (scale_i << 16) | scale_q [16.0 format]
- uint32_t interp; // desired interpolation factor (NOT -1)
-} op_config_tx_t;
-
-typedef struct {
- uint8_t opcode;
- uint8_t len;
u2_mac_addr_t addr;
} op_burn_mac_addr_t;
typedef struct {
uint8_t opcode;
uint8_t len;
- uint16_t rid_mbz;
+ uint8_t rid;
+ uint8_t mbz;
} op_read_time_t;
typedef struct {
uint8_t opcode;
uint8_t len;
- uint16_t rid_mbz;
+ uint8_t rid;
+ uint8_t mbz;
uint32_t time;
} op_read_time_reply_t;
-/*
- * Configure the receiver.
+/*!
+ * \brief Configure receiver
*/
typedef struct {
uint8_t opcode;
uint8_t len;
- uint16_t rid_mbz;
+ uint8_t rid;
+ uint8_t mbz;
// bitmask indicating which of the following fields are valid
uint16_t valid;
uint16_t gain; // fxpt_db (Q9.7)
- uint32_t target_freq_hi; // high 32-bits of 64-bit fxpt_freq (Q44.20)
- uint32_t target_freq_lo; // low 32-bits of 64-bit fxpt_freq (Q44.20)
- uint32_t interp; // desired interpolation factor (NOT -1)
+ uint32_t freq_hi; // high 32-bits of 64-bit fxpt_freq (Q44.20)
+ uint32_t freq_lo; // low 32-bits of 64-bit fxpt_freq (Q44.20)
+ uint32_t decim; // desired decimation factor (NOT -1)
uint32_t scale_iq; // (scale_i << 16) | scale_q [16.0 format]
} op_config_rx_v2_t;
@@ -263,13 +270,14 @@
#define CFGV_INTERP_DECIM 0x0004 // interp or decim is valid
#define CFGV_SCALE_IQ 0x0008 // scale_iq is valid
-/*
- * Reply to receiver configuration
+/*!
+ * \brief Reply to receiver configuration
*/
typedef struct {
uint8_t opcode;
uint8_t len;
- uint16_t rid_mbz;
+ uint8_t rid;
+ uint8_t mbz;
uint16_t ok; // config was successful (bool)
uint16_t inverted; // spectrum is inverted (bool)
@@ -284,37 +292,101 @@
uint32_t residual_freq_hi;
uint32_t residual_freq_lo;
-} op_config_rx_v2_reply_t;
+} op_config_rx_reply_v2_t;
+/*!
+ * \brief Configure transmitter
+ */
typedef struct {
uint8_t opcode;
uint8_t len;
- uint16_t rid_mbz;
+ uint8_t rid;
+ uint8_t mbz;
+
// bitmask indicating which of the following fields are valid
uint16_t valid;
uint16_t gain; // fxpt_db (Q9.7)
uint32_t freq_hi; // high 32-bits of 64-bit fxpt_freq (Q44.20)
uint32_t freq_lo; // low 32-bits of 64-bit fxpt_freq (Q44.20)
- uint32_t decim; // desired decimation factor (NOT -1)
+ uint32_t interp; // desired interpolation factor (NOT -1)
uint32_t scale_iq; // (scale_i << 16) | scale_q [16.0 format]
} op_config_tx_v2_t;
+/*!
+ * \brief Reply to configure transmitter
+ */
+typedef struct {
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rid;
+ uint8_t mbz;
+ uint16_t ok; // config was successful (bool)
+ uint16_t inverted; // spectrum is inverted (bool)
-// union of all of them
+ // RF frequency that corresponds to DC in the IF (fxpt_freq)
+ uint32_t baseband_freq_hi;
+ uint32_t baseband_freq_lo;
+ // DUC frequency (fxpt_freq)
+ uint32_t ddc_freq_hi;
+ uint32_t ddc_freq_lo;
+ // residual frequency (fxpt_freq)
+ uint32_t residual_freq_hi;
+ uint32_t residual_freq_lo;
+} op_config_tx_reply_v2_t;
+
+
+/*
+ * ================================================================
+ * deprecated subpacket types
+ * ================================================================
+ */
+
+typedef struct { // Deprecated. Don't use.
+ uint8_t opcode;
+ uint8_t len;
+ uint8_t rx_now; // 1 -> receive now, 0 -> at rx_time
+ uint8_t mbz;
+ int32_t phase_inc; // 2**32 * desired_freq/100e6
+ uint32_t scale_iq; // (scale_i << 16) | scale_q [16.0 format]
+ uint32_t decim; // desired decimation factor (NOT -1)
+ uint32_t samples_per_frame; // MTU=1500: [9,372]; MTU=2034: [9,506]
+ uint32_t total_samples; // [9, 2^21-1] == [9, 2,097,151]
+ uint32_t rx_time; // when to begin receiving
+} op_start_rx_t;
+
+typedef struct { // Deprecated. Don't use
+ uint8_t opcode;
+ uint8_t len;
+ uint16_t mbz;
+ int32_t phase_inc; // 2**32 * desired_freq/100e6
+ uint32_t scale_iq; // (scale_i << 16) | scale_q [16.0 format]
+ uint32_t interp; // desired interpolation factor (NOT -1)
+} op_config_tx_t;
+
+/*
+ * ================================================================
+ * union of all of subpacket types
+ * ================================================================
+ */
typedef union {
- op_eof_t op_eof;
- op_id_t op_id;
- op_id_reply_t op_id_reply;
- op_start_rx_t op_start_rx;
- op_stop_rx_t op_stop_rx;
- op_config_tx_t op_config_tx;
- op_burn_mac_addr_t op_burn_mac_addr;
- op_read_time_t op_read_time;
- op_read_time_reply_t op_read_time_reply;
- op_config_rx_v2_t op_config_rx_v2;
- op_config_tx_v2_t op_config_tx_v2;
+ op_eop_t op_eop;
+ op_id_t op_id;
+ op_id_reply_t op_id_reply;
+ op_start_rx_streaming_t op_start_rx_streaming;
+ op_stop_rx_t op_stop_rx;
+ op_burn_mac_addr_t op_burn_mac_addr;
+ op_read_time_t op_read_time;
+ op_read_time_reply_t op_read_time_reply;
+ op_config_rx_v2_t op_config_rx_v2;
+ op_config_rx_reply_v2_t op_config_rx_reply_v2;
+ op_config_tx_v2_t op_config_tx_v2;
+ op_config_tx_reply_v2_t op_config_tx_reply_v2;
+
+ op_start_rx_t op_start_rx; // deprecated
+ op_config_tx_t op_config_tx; // deprecated
+
} u2_subpkt_t;
Modified: usrp2/trunk/firmware/include/usrp2_types.h
===================================================================
--- usrp2/trunk/firmware/include/usrp2_types.h 2008-05-12 05:32:16 UTC (rev
8406)
+++ usrp2/trunk/firmware/include/usrp2_types.h 2008-05-12 05:47:50 UTC (rev
8407)
@@ -33,8 +33,10 @@
*/
typedef int64_t u2_fxpt_freq_t;
+#define U2_FPF_RP 20 // location of radix point in u2_fxpt_freq_t
+
// macro so we can init structs at compile time
-#define U2_DOUBLE_TO_FXPT_FREQ(f) (int64_t)((f) * (1 << 20))
+#define U2_DOUBLE_TO_FXPT_FREQ(f) (int64_t)((f) * (1LL << U2_FPF_RP))
static inline u2_fxpt_freq_t
u2_double_to_fxpt_freq(double f)
@@ -45,16 +47,33 @@
static inline int
u2_fxpt_freq_round_to_int(u2_fxpt_freq_t fx)
{
- return (int)((fx+(1<<19))>>20);
+ return (int)((fx+(1<<(U2_FPF_RP-1)))>>U2_FPF_RP);
}
static inline double
u2_fxpt_freq_to_double(u2_fxpt_freq_t fx)
{
- return ((double) fx) * 1.0/(1 << 20);
+ return ((double) fx) * 1.0/(1 << U2_FPF_RP);
}
+static inline uint32_t
+u2_fxpt_freq_hi(u2_fxpt_freq_t f)
+{
+ return ((f >> 32) & 0xffffffff);
+}
+static inline uint32_t
+u2_fxpt_freq_lo(u2_fxpt_freq_t f)
+{
+ return (f & 0xffffffff);
+}
+
+static inline u2_fxpt_freq_t
+u2_fxpt_freq_from_hilo(uint32_t hi, uint32_t lo)
+{
+ return (((u2_fxpt_freq_t) hi) << 32) | lo;
+}
+
/*!
* \brief Fixed point representation of a gain in dB (VITA-49 compatible)
*
@@ -63,8 +82,10 @@
*/
typedef int16_t u2_fxpt_gain_t;
+#define U2_FPG_RP 7 // location of radix point in u2_fxpt_gain_t
+
// macro so we can init structs at compile time
-#define U2_DOUBLE_TO_FXPT_GAIN(g) (int16_t)((g) * (1 << 7))
+#define U2_DOUBLE_TO_FXPT_GAIN(g) (int16_t)((g) * (1 << U2_FPG_RP))
static inline u2_fxpt_gain_t
u2_double_to_fxpt_gain(double g)
@@ -75,7 +96,7 @@
static inline float
u2_fxpt_gain_to_double(u2_fxpt_gain_t fx)
{
- return ((double) fx) * 1.0/(1 << 7);
+ return ((double) fx) * 1.0/(1 << U2_FPG_RP);
}
Modified: usrp2/trunk/firmware/lib/db_basic.c
===================================================================
--- usrp2/trunk/firmware/lib/db_basic.c 2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/firmware/lib/db_basic.c 2008-05-12 05:47:50 UTC (rev 8407)
@@ -31,6 +31,7 @@
struct db_basic db_basic_tx = {
.base.dbid = 0x0000,
+ .base.is_tx = true,
.base.output_enables = 0x0000,
.base.used_pins = 0x0000,
.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(-90e9),
@@ -57,6 +58,7 @@
struct db_basic db_basic_rx = {
.base.dbid = 0x0001,
+ .base.is_tx = false,
.base.output_enables = 0x0000,
.base.used_pins = 0x0000,
.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(-90e9),
@@ -83,6 +85,7 @@
struct db_basic db_lf_tx = {
.base.dbid = 0x000e,
+ .base.is_tx = true,
.base.output_enables = 0x0000,
.base.used_pins = 0x0000,
.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(-32e6),
@@ -109,6 +112,7 @@
struct db_basic db_lf_rx = {
.base.dbid = 0x000f,
+ .base.is_tx = false,
.base.output_enables = 0x0000,
.base.used_pins = 0x0000,
.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(0),
Modified: usrp2/trunk/firmware/lib/db_init.c
===================================================================
--- usrp2/trunk/firmware/lib/db_init.c 2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/firmware/lib/db_init.c 2008-05-12 05:47:50 UTC (rev 8407)
@@ -211,13 +211,14 @@
printf(" baseband = "); print_fxpt_freq(baseband_freq); newline();
printf(" delta = "); print_fxpt_freq(delta); newline();
+#if 0
printf("--- printed as uint64_t ---\n");
printf(" fs = "); print_uint64(fs); newline();
printf(" target = "); print_uint64(target_freq); newline();
printf(" baseband = "); print_uint64(baseband_freq); newline();
printf(" delta = "); print_uint64(delta); newline();
+#endif
-
if (delta >= 0){
while (delta > fs)
delta -= fs;
Modified: usrp2/trunk/firmware/lib/dbsm.c
===================================================================
--- usrp2/trunk/firmware/lib/dbsm.c 2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/firmware/lib/dbsm.c 2008-05-12 05:47:50 UTC (rev 8407)
@@ -278,3 +278,20 @@
putchar('O');
}
+
+void
+dbsm_wait_for_opening(dbsm_t *sm)
+{
+ if (buffer_state[sm->buf0] == BS_EMPTYING){
+ // wait for xfer to complete
+ int mask = BPS_DONE(sm->buf0) | BPS_ERROR(sm->buf0);
+ while ((buffer_pool_status->status & mask) == 0)
+ ;
+ }
+ else if (buffer_state[sm->buf0 ^ 1] == BS_EMPTYING){
+ // wait for xfer to complete
+ int mask = BPS_DONE(sm->buf0 ^ 1) | BPS_ERROR(sm->buf0 ^ 1);
+ while ((buffer_pool_status->status & mask) == 0)
+ ;
+ }
+}
Modified: usrp2/trunk/firmware/lib/dbsm.h
===================================================================
--- usrp2/trunk/firmware/lib/dbsm.h 2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/firmware/lib/dbsm.h 2008-05-12 05:47:50 UTC (rev 8407)
@@ -74,4 +74,17 @@
void dbsm_handle_tx_underrun(dbsm_t *sm);
void dbsm_handle_rx_overrun(dbsm_t *sm);
+/*
+ * The cpu calls this when it want to ensure that it can send a buffer
+ * to the same destination being used by this state machine.
+ *
+ * If neither buffer is EMPTYING it returns immediately. If a buffer
+ * is EMPYTING, it waits for the h/w to transition to the DONE or
+ * ERROR state.
+ *
+ * When this function returns, the caller queues it's buffer and busy
+ * waits for it to complete.
+ */
+void dbsm_wait_for_opening(dbsm_t *sm);
+
#endif /* INCLUDED_DBSM_H */
Modified: usrp2/trunk/host/apps/Makefile.am
===================================================================
--- usrp2/trunk/host/apps/Makefile.am 2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/host/apps/Makefile.am 2008-05-12 05:47:50 UTC (rev 8407)
@@ -25,18 +25,16 @@
bin_PROGRAMS = \
find_usrps \
- rx_samples \
rx_streaming_samples \
tx_samples \
- tx_samples_at_t \
gen_const \
u2_burn_mac_addr
find_usrps_SOURCES = find_usrps.cc
-rx_samples_SOURCES = rx_samples.cc
+# rx_samples_SOURCES = rx_samples.cc
rx_streaming_samples_SOURCES = rx_streaming_samples.cc
tx_samples_SOURCES = tx_samples.cc
-tx_samples_at_t = tx_samples_at_t.cc
+# tx_samples_at_t = tx_samples_at_t.cc
gen_const_SOURCES = gen_const.cc
u2_burn_mac_addr = u2_burn_mac_addr.cc
Copied: usrp2/trunk/host/apps/rx_samples_at_t.cc (from rev 7964,
usrp2/trunk/host/apps/rx_samples.cc)
===================================================================
--- usrp2/trunk/host/apps/rx_samples_at_t.cc (rev 0)
+++ usrp2/trunk/host/apps/rx_samples_at_t.cc 2008-05-12 05:47:50 UTC (rev
8407)
@@ -0,0 +1,378 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "usrp2_basic.h"
+#include <iostream>
+#include <complex>
+#include <getopt.h>
+#include <string.h>
+#include "strtod_si.h"
+#include <signal.h>
+#include <stdexcept>
+#include "gri_if_stats.h"
+#include <gr_realtime.h>
+
+
+typedef std::complex<float> fcomplex;
+
+static volatile bool signaled = false;
+
+static void
+sig_handler(int sig)
+{
+ signaled = true;
+}
+
+static void
+install_sig_handler(int signum,
+ void (*new_handler)(int))
+{
+ struct sigaction new_action;
+ memset (&new_action, 0, sizeof (new_action));
+
+ new_action.sa_handler = new_handler;
+ sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+
+ if (sigaction (signum, &new_action, 0) < 0){
+ perror ("sigaction (install new)");
+ throw std::runtime_error ("sigaction");
+ }
+}
+
+
+/*
+ * Vectorize me!
+ */
+void
+convert_samples_to_complex(size_t nsamples,
+ uint32_t *i_samples,
+ fcomplex *c_samples)
+{
+ uint32_t *p = i_samples;
+ for (size_t i = 0; i < nsamples; i++){
+ int16_t si = ((int16_t) (p[i] >> 16));
+ int16_t sq = ((int16_t) (p[i] & 0xffff));
+ c_samples[i] = fcomplex((float) si, (float) sq);
+ }
+}
+
+
+static void
+usage(const char *progname)
+{
+ const char *p = strrchr(progname, '/'); // drop leading directory path
+ if (p)
+ p++;
+
+ if (strncmp(p, "lt-", 3) == 0) // drop lt- libtool prefix
+ p += 3;
+
+ fprintf(stderr, "Usage: %s [options]\n\n", p);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -h show this message and exit\n");
+ fprintf(stderr, " -e ETH_INTERFACE specify ethernet interface
[default=eth0]\n");
+ fprintf(stderr, " -m MAC_ADDR mac address of USRP2 HH:HH
[default=first one found]\n");
+ fprintf(stderr, " -o OUTPUT_FILE set output filename
[default=NONE]\n");
+ fprintf(stderr, " -f FREQ set frequency to FREQ
[default=0]\n");
+ fprintf(stderr, " -d DECIM set decimation rate to DECIM
[default=32]\n");
+ fprintf(stderr, " -N NSAMPLES total number of samples to receive
[default=2.5e6]\n");
+ fprintf(stderr, " -F SAMPLES_PER_FRAME number of samples in each frame
[default=371]\n");
+ fprintf(stderr, " -S SCALE fpga scaling factor for I & Q
[default=256]\n");
+ fprintf(stderr, " -O ON_TIME number of samples to capture
[default=750k]\n");
+ fprintf(stderr, " -F OFF_TIME number of samples to ignore
[default=250k]\n");
+}
+
+struct pkt_info {
+ int d_nsamples;
+ int d_timestamp;
+ unsigned int d_seqno;
+
+ pkt_info(int nsamples, int timestamp, int seqno)
+ : d_nsamples(nsamples),
+ d_timestamp(timestamp),
+ d_seqno(seqno) {}
+};
+
+int
+main(int argc, char **argv)
+{
+
+ // options and their defaults
+ const char *interface = "eth0";
+ const char *mac_addr_str = 0;
+ const char *output_filename = 0;
+ double freq = 0;
+ int32_t decim = 32;
+ int32_t nsamples = static_cast<int32_t>(2.5e6);
+ int32_t samples_per_frame = 371;
+ int32_t scale = 1024;
+ int32_t t_on_in_samples = static_cast<int32_t>(750e3);
+ int32_t t_off_in_samples = static_cast<int32_t>(250e3);
+
+ int ch;
+ double tmp;
+ u2_mac_addr_t mac_addr;
+
+ setvbuf(stdout, 0, _IOFBF, 64 * 1024); // make stdout fully buffered
+
+ while ((ch = getopt(argc, argv, "he:m:o:f:d:N:F:S:O:F:")) != EOF){
+ switch (ch){
+
+ case 'e':
+ interface = optarg;
+ break;
+
+ case 'm':
+ mac_addr_str = optarg;
+ if (!usrp2_basic::parse_mac_addr(optarg, &mac_addr)){
+ std::cerr << "invalid mac addr: " << optarg << std::endl;
+ usage(argv[0]);
+ exit(1);
+ }
+ break;
+
+ case 'o':
+ output_filename = optarg;
+ break;
+
+ case 'f':
+ if (!strtod_si(optarg, &freq)){
+ std::cerr << "invalid number: " << optarg << std::endl;
+ usage(argv[0]);
+ exit(1);
+ }
+ break;
+
+ case 'N':
+ if (!strtod_si(optarg, &tmp)){
+ std::cerr << "invalid number: " << optarg << std::endl;
+ usage(argv[0]);
+ exit(1);
+ }
+ nsamples = static_cast<int32_t>(tmp);
+ break;
+
+ case 'F':
+ samples_per_frame = strtol(optarg, 0, 0);
+ break;
+
+ case 'd':
+ decim = strtol(optarg, 0, 0);
+ break;
+
+ case 'S':
+ if (!strtod_si(optarg, &tmp)){
+ std::cerr << "invalid number: " << optarg << std::endl;
+ usage(argv[0]);
+ exit(1);
+ }
+ scale = static_cast<int32_t>(tmp);
+ break;
+
+ case 'O':
+ if (!strtod_si(optarg, &tmp)){
+ std::cerr << "invalid number: " << optarg << std::endl;
+ usage(argv[0]);
+ exit(1);
+ }
+ t_on_in_samples = static_cast<int32_t>(tmp);
+ break;
+
+ case 'F':
+ if (!strtod_si(optarg, &tmp)){
+ std::cerr << "invalid number: " << optarg << std::endl;
+ usage(argv[0]);
+ exit(1);
+ }
+ t_off_in_samples = static_cast<int32_t>(tmp);
+ break;
+
+ case 'h':
+ default:
+ usage(argv[0]);
+ exit(1);
+ }
+ }
+
+ if (argc - optind != 0){
+ usage(argv[0]);
+ exit(1);
+ }
+
+ FILE *of = 0;
+ if (output_filename)
+ of = fopen(output_filename, "wb");
+
+ usrp2_basic *u2 = new usrp2_basic();
+
+ if (!u2->open(interface)){
+ std::cerr << "couldn't open " << interface << std::endl;
+ return 0;
+ }
+
+
+ install_sig_handler(SIGINT, sig_handler);
+ if (1){
+ install_sig_handler(SIGALRM, sig_handler);
+ alarm(5);
+ }
+
+
+ std::vector<op_id_reply_t> r = u2->find_usrps();
+
+ for (size_t i = 0; i < r.size(); i++){
+ std::cout << r[i] << std::endl;
+ }
+
+ if (r.size() == 0){
+ std::cerr << "No USRP2 found.\n";
+ return 1;
+ }
+
+ u2_mac_addr_t which = r[0].addr; // pick the first one
+
+
+ gr_rt_status_t rt = gr_enable_realtime_scheduling();
+ if (rt != RT_OK)
+ std::cerr << "failed to enable realtime scheduling\n";
+
+
+ gri_if_stats start, stop;
+ gri_get_if_stats(interface, &start);
+
+ if (!u2->start_rx(which, freq, decim, nsamples, samples_per_frame, scale,
scale)){
+ std::cerr << "start_rx failed\n";
+ return 1;
+ }
+
+
+ std::vector<pkt_info> history;
+ history.reserve(64*1024); // preallocate 64K entries
+
+
+ long total_samples_recvd = 0;
+
+ while (!signaled && total_samples_recvd < nsamples){
+ u2_eth_samples_t pkt;
+ // fcomplex c_samples[U2_MAX_SAMPLES];
+
+ // read samples
+ int n = u2->read_samples(which, &pkt);
+ if (n <= 0)
+ break;
+
+ total_samples_recvd += n;
+
+ history.push_back(pkt_info(n, u2p_timestamp(&pkt.hdrs.fixed),
pkt.hdrs.thdr.seqno));
+
+ // convert_samples_to_complex(n, pkt.samples, c_samples);
+ // size_t r = fwrite(c_samples, sizeof(fcomplex), n, of);
+
+ if (of){
+ fwrite(pkt.samples, sizeof(uint32_t), n, of);
+ fflush(of);
+ }
+ }
+
+
+ gri_get_if_stats(interface, &stop);
+
+ if (!u2->stop_rx(which)){
+ std::cerr << "stop_rx failed\n";
+ return 1;
+ }
+
+
+ long expected_rx_packets =
+ (nsamples + samples_per_frame - 1)/samples_per_frame;
+
+ long expected_rx_bytes =
+ expected_rx_packets * sizeof(u2_eth_packet_t) + nsamples * 4;
+
+
+ long total_pkts_recvd = 0;
+ total_samples_recvd = 0;
+
+ int nbad_seqno = 0;
+
+ for (unsigned i = 0; i < history.size(); i++){
+ total_pkts_recvd++;
+ total_samples_recvd += history[i].d_nsamples;
+
+ bool bad_seqno = history[i].d_seqno != (i & 0xff);
+ if (bad_seqno)
+ nbad_seqno++;
+
+ printf("%3d %8d %8ld %8ld %3d %s\n",
+ history[i].d_nsamples,
+ history[i].d_timestamp,
+ total_pkts_recvd, total_samples_recvd,
+ history[i].d_seqno,
+ bad_seqno ? "BAD SEQNO" : ""
+ );
+ }
+
+ if (nbad_seqno == 0)
+ printf("\nAll sequence numbers are correct\n");
+ else
+ printf("\n%d sequence numbers were INCORRECT\n", nbad_seqno);
+
+
+ printf("\nUser space statistics:\n");
+ printf(" rx_samples: %8ld", total_samples_recvd);
+ printf(" expected %8d %s\n",
+ nsamples,
+ nsamples - total_samples_recvd == 0 ? "OK" : "NOT OK");
+
+ printf(" rx_packets: %8ld", total_pkts_recvd);
+ printf(" expected %8ld %s\n",
+ expected_rx_packets,
+ expected_rx_packets - total_pkts_recvd == 0 ? "OK" : "NOT OK");
+
+
+ fflush(stdout);
+
+ printf("\nKernel interface statistics:\n");
+
+ long long delta;
+ delta = stop.rx_bytes - start.rx_bytes;
+ printf(" rx_bytes: %8Ld", delta);
+ printf(" expected %8ld %s\n",
+ expected_rx_bytes,
+ expected_rx_bytes - delta == 0 ? "OK" : "NOT OK");
+
+ delta = stop.rx_packets - start.rx_packets;
+ printf(" rx_packets: %8Ld", delta);
+ printf(" expected %8ld %s\n",
+ expected_rx_packets,
+ expected_rx_packets - delta == 0 ? "OK" : "NOT OK");
+
+ printf(" rx_errs: %8Ld\n", stop.rx_errs - start.rx_errs);
+ printf(" rx_drop: %8Ld\n", stop.rx_drop - start.rx_drop);
+ printf(" tx_bytes: %8Ld\n", stop.tx_bytes - start.tx_bytes);
+ printf(" tx_packets: %8Ld\n", stop.tx_packets - start.tx_packets);
+ printf(" tx_errs: %8Ld\n", stop.tx_errs - start.tx_errs);
+ printf(" tx_drop: %8Ld\n", stop.tx_drop - start.tx_drop);
+
+
+ return 0;
+}
Modified: usrp2/trunk/host/apps/rx_streaming_samples.cc
===================================================================
--- usrp2/trunk/host/apps/rx_streaming_samples.cc 2008-05-12 05:32:16 UTC
(rev 8406)
+++ usrp2/trunk/host/apps/rx_streaming_samples.cc 2008-05-12 05:47:50 UTC
(rev 8407)
@@ -183,6 +183,7 @@
fprintf(stderr, " -o OUTPUT_FILE set output filename
[default=samples.dat]\n");
fprintf(stderr, " -f FREQ set frequency to FREQ
[default=0]\n");
fprintf(stderr, " -d DECIM set decimation rate to DECIM
[default=32]\n");
+ fprintf(stderr, " -g gain rx gain [default=0dB]\n");
fprintf(stderr, " -N NSAMPLES total number of samples to receive
[default=infinite]\n");
fprintf(stderr, " -F SAMPLES_PER_FRAME number of samples in each frame
[default=371]\n");
fprintf(stderr, " -S SCALE fpga scaling factor for I & Q
[default=256]\n");
@@ -199,6 +200,8 @@
d_seqno(seqno) {}
};
+#define GAIN_NOT_SET (-1000)
+
int
main(int argc, char **argv)
{
@@ -210,8 +213,9 @@
double freq = 0;
int32_t decim = 32;
uint64_t nsamples = ~0;
- int32_t samples_per_frame = 371;
+ int32_t samples_per_frame = 250;
int32_t scale = 1024;
+ double gain = GAIN_NOT_SET;
int ch;
double tmp;
@@ -219,7 +223,7 @@
// setvbuf(stdout, 0, _IOFBF, 64 * 1024); // make stdout fully buffered
- while ((ch = getopt(argc, argv, "he:m:o:f:d:N:F:S:")) != EOF){
+ while ((ch = getopt(argc, argv, "he:m:o:f:d:N:F:S:g:")) != EOF){
switch (ch){
case 'e':
@@ -273,6 +277,14 @@
scale = static_cast<int32_t>(tmp);
break;
+ case 'g':
+ if (!strtod_si(optarg, &gain)){
+ std::cerr << "invalid number: " << optarg << std::endl;
+ usage(argv[0]);
+ exit(1);
+ }
+ break;
+
case 'h':
default:
usage(argv[0]);
@@ -333,12 +345,37 @@
writer->start_undetached();
- if (!u2->start_rx(which, freq, decim, 0, samples_per_frame, scale, scale)){
- std::cerr << "start_rx failed\n";
+ usrp2_tune_result tune_result;
+
+ if (gain != GAIN_NOT_SET){
+ if (!u2->set_rx_gain(which, gain)){
+ std::cerr << "set_rx_gain failed\n";
+ return 1;
+ }
+ }
+
+ if (!u2->set_rx_freq(which, freq, &tune_result)){
+ std::cerr << "set_rx_freq failed\n";
return 1;
}
+ if (!u2->set_rx_decim(which, decim)){
+ std::cerr << "set_rx_decim failed\n";
+ return 1;
+ }
+ if (!u2->set_rx_scale_iq(which, scale, scale)){
+ std::cerr << "set_rx_scale_iq failed\n";
+ return 1;
+ }
+
+ if (!u2->start_rx_streaming(which, samples_per_frame)){
+ std::cerr << "start_rx_streaming failed\n";
+ return 1;
+ }
+
+
+
uint64_t total_samples_recvd = 0;
int expected_seqno = 0;
Modified: usrp2/trunk/host/apps/tx_samples.cc
===================================================================
--- usrp2/trunk/host/apps/tx_samples.cc 2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/host/apps/tx_samples.cc 2008-05-12 05:47:50 UTC (rev 8407)
@@ -55,10 +55,13 @@
fprintf(stderr, " -r repeat. When EOF of input file is
reached, seek to beginning\n");
fprintf(stderr, " -f FREQ set frequency to FREQ
[default=0]\n");
fprintf(stderr, " -i INTERP set interpolation rate to INTERP
[default=32]\n");
+ fprintf(stderr, " -g gain set tx gain\n");
fprintf(stderr, " -F SAMPLES_PER_FRAME number of samples in each frame
[default=371]\n");
fprintf(stderr, " -S SCALE fpga scaling factor for I & Q
[default=256]\n");
}
+#define GAIN_NOT_SET (-1000)
+
int
main(int argc, char **argv)
{
@@ -68,14 +71,15 @@
const char *mac_addr_str = 0;
double freq = 0;
int32_t interp = 32;
- int32_t samples_per_frame = 371;
+ int32_t samples_per_frame = U2_MAX_SAMPLES;
int32_t scale = 256;
+ double gain = GAIN_NOT_SET;
int ch;
double tmp;
u2_mac_addr_t mac_addr;
- while ((ch = getopt(argc, argv, "he:m:I:rf:i:F:S")) != EOF){
+ while ((ch = getopt(argc, argv, "he:m:I:rf:i:F:S:g:")) != EOF){
switch (ch){
case 'e':
@@ -148,9 +152,10 @@
}
}
- if (samples_per_frame < 9 || samples_per_frame > 506){
+ if (samples_per_frame < 9 || samples_per_frame > U2_MAX_SAMPLES){
std::cerr << prettify_progname(argv[0])
- << ": samples_per_frame is out of range. Must be in [9, 506].\n";
+ << ": samples_per_frame is out of range. "
+ << "Must be in [9, " << U2_MAX_SAMPLES << "].\n";
usage(argv[0]);
return 1;
}
@@ -176,13 +181,31 @@
u2_mac_addr_t which = r[0].addr; // pick the first one
- if (1){
- if (!u2->config_tx(which, freq, interp, scale, scale)){
- std::cerr << "tx_samples: config_tx failed\n";
+ usrp2_tune_result tune_result;
+
+ if (gain != GAIN_NOT_SET){
+ if (!u2->set_tx_gain(which, gain)){
+ std::cerr << "set_tx_gain failed\n";
return 1;
}
}
+ if (!u2->set_tx_freq(which, freq, &tune_result)){
+ std::cerr << "set_tx_freq failed\n";
+ return 1;
+ }
+
+ if (!u2->set_tx_interp(which, interp)){
+ std::cerr << "set_tx_interp failed\n";
+ return 1;
+ }
+
+ if (!u2->set_tx_scale_iq(which, scale, scale)){
+ std::cerr << "set_tx_scale_iq failed\n";
+ return 1;
+ }
+
+
u2_eth_samples_t pkt;
u2p_set_word0(&pkt.hdrs.fixed, U2P_TX_IMMEDIATE | U2P_TX_START_OF_BURST, 0);
u2p_set_timestamp(&pkt.hdrs.fixed, T_NOW);
Modified: usrp2/trunk/host/lib/usrp2_basic.cc
===================================================================
--- usrp2/trunk/host/lib/usrp2_basic.cc 2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/host/lib/usrp2_basic.cc 2008-05-12 05:47:50 UTC (rev 8407)
@@ -23,6 +23,7 @@
#include "gri_ethernet.h"
#include "gri_ethernet_pfring.h" // FIXME
#include "gri_pktfilter.h"
+#include <usrp2_types.h>
#include <iostream>
#include <math.h>
#include <time.h> // debug
@@ -47,12 +48,13 @@
* callbacks, etc.
*/
-#define MIN_PKTLEN 64 // per ethernet spec
-#define MAX_PKTLEN 2048 // biggest thing USRP2 can swallow
+#define MIN_PKTLEN 64 // per ethernet spec
+#define MAX_PKTLEN 1512 // biggest thing USRP2 can swallow
+ // (14-byte ethernet hdr + 1500 byte payload)
usrp2_basic::usrp2_basic()
- : d_ethernet(new GRI_ETHERNET()), d_pf(0), d_seqno(0)
+ : d_ethernet(new GRI_ETHERNET()), d_pf(0), d_seqno(0), d_next_rid(0)
{
assert(sizeof(u2_eth_samples_t) == (size_t) MAX_PKTLEN);
}
@@ -185,73 +187,187 @@
return false;
}
+/*
+ * ------------------------------------------------------------------------
+ * Rx configuration and control
+ * ------------------------------------------------------------------------
+ */
+bool
+usrp2_basic::set_rx_gain(const u2_mac_addr_t &which, double gain)
+{
+ uint8_t pktbuf[MAX_PKTLEN];
+ memset(pktbuf, 0, sizeof(pktbuf));
-// ------------------------------------------------------------------------
+ struct command {
+ u2_eth_packet_t h;
+ op_config_rx_v2_t op;
+ op_eop_t eop;
+ };
-static int32_t
-compute_freq_control_word_fpga(double master_freq, double target_freq,
- double *actual_freq)
-{
- int v = (int) rint (target_freq / master_freq * pow (2.0, 32.0));
- *actual_freq = v * master_freq / pow (2.0, 32.0);
- return v;
+ command *c = (command *) pktbuf;
+ init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+ c->op.opcode = OP_CONFIG_RX_V2;
+ c->op.len = sizeof(op_config_rx_v2_t);
+ c->op.rid = d_next_rid++;
+
+ c->op.valid = htons(CFGV_GAIN);
+ c->op.gain = htons(u2_double_to_fxpt_gain(gain));
+
+ c->eop.opcode = OP_EOP;
+ c->eop.len = sizeof(op_eop_t);
+
+ int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+ if (d_ethernet->write_packet(c, len) != len)
+ return false;
+
+ // FIXME wait for corresponding reply, etc.
+
+ return true;
}
bool
-usrp2_basic::start_rx(const u2_mac_addr_t &which,
- double freq,
- unsigned int decim,
- unsigned int total_samples, // 0 or [9, 2**21 - 1]
- unsigned int samples_per_frame, // [9, 371] or [9, 505]
if MTU==2034
- int scale_i, // 16.0 fixed point
format
- int scale_q, // 16.0 fixed point
format
- bool rx_now,
- uint32_t rx_time
- )
+usrp2_basic::set_rx_freq(const u2_mac_addr_t &which, double freq,
+ usrp2_tune_result *result)
{
uint8_t pktbuf[MAX_PKTLEN];
memset(pktbuf, 0, sizeof(pktbuf));
struct command {
u2_eth_packet_t h;
- op_start_rx_t op;
+ op_config_rx_v2_t op;
+ op_eop_t eop;
};
-
- if ((total_samples < 9 && total_samples != 0) || total_samples >= (1L <<
21)){
- std::cerr << "usrp2_basic::start_rx: total_samples is out of range\n";
+
+ command *c = (command *) pktbuf;
+ init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+ c->op.opcode = OP_CONFIG_RX_V2;
+ c->op.len = sizeof(op_config_rx_v2_t);
+ c->op.rid = d_next_rid++;
+
+ c->op.valid = htons(CFGV_FREQ);
+ u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(freq);
+ c->op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt));
+ c->op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
+
+ c->eop.opcode = OP_EOP;
+ c->eop.len = sizeof(op_eop_t);
+
+ int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+ if (d_ethernet->write_packet(c, len) != len)
return false;
- }
- if (samples_per_frame < 9 || samples_per_frame > U2_MAX_SAMPLES){
- std::cerr << "usrp2_basic::start_rx: samples_per_frame is out of range\n";
+ // FIXME wait for corresponding reply, etc.
+
+ if (result)
+ memset(result, 0, sizeof(*result));
+
+ return true;
+}
+
+bool
+usrp2_basic::set_rx_decim(const u2_mac_addr_t &which, int decimation_factor)
+{
+ uint8_t pktbuf[MAX_PKTLEN];
+ memset(pktbuf, 0, sizeof(pktbuf));
+
+ struct command {
+ u2_eth_packet_t h;
+ op_config_rx_v2_t op;
+ op_eop_t eop;
+ };
+
+ command *c = (command *) pktbuf;
+ init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+ c->op.opcode = OP_CONFIG_RX_V2;
+ c->op.len = sizeof(op_config_rx_v2_t);
+ c->op.rid = d_next_rid++;
+
+ c->op.valid = htons(CFGV_INTERP_DECIM);
+ c->op.decim = htonl(decimation_factor);
+
+ c->eop.opcode = OP_EOP;
+ c->eop.len = sizeof(op_eop_t);
+
+ int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+ if (d_ethernet->write_packet(c, len) != len)
return false;
- }
- command *c = (command *) pktbuf;
+ // FIXME wait for corresponding reply, etc.
+
+ return true;
+}
+
+bool
+usrp2_basic::set_rx_scale_iq(const u2_mac_addr_t &which, int scale_i, int
scale_q)
+{
+ uint8_t pktbuf[MAX_PKTLEN];
+ memset(pktbuf, 0, sizeof(pktbuf));
+
+ struct command {
+ u2_eth_packet_t h;
+ op_config_rx_v2_t op;
+ op_eop_t eop;
+ };
+
+ command *c = (command *) pktbuf;
init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
- c->op.opcode = OP_START_RX;
- c->op.len = sizeof(op_start_rx_t);
+ c->op.opcode = OP_CONFIG_RX_V2;
+ c->op.len = sizeof(op_config_rx_v2_t);
+ c->op.rid = d_next_rid++;
- double actual_freq;
- c->op.rx_now = rx_now ? 1 : 0;
- c->op.phase_inc = htonl(compute_freq_control_word_fpga(adc_rate(), freq,
&actual_freq));
+ c->op.valid = htons(CFGV_SCALE_IQ);
c->op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff));
- c->op.decim = htonl(decim);
- c->op.samples_per_frame = htonl(samples_per_frame);
- c->op.total_samples = htonl(total_samples);
- c->op.rx_time = htonl(rx_time);
+ c->eop.opcode = OP_EOP;
+ c->eop.len = sizeof(op_eop_t);
int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
if (d_ethernet->write_packet(c, len) != len)
return false;
+ // FIXME wait for corresponding reply, etc.
+
return true;
}
bool
+usrp2_basic::start_rx_streaming(const u2_mac_addr_t &which, unsigned int
items_per_frame)
+{
+ if (items_per_frame == 0) // provide our default
+ items_per_frame = 250;
+
+ uint8_t pktbuf[MAX_PKTLEN];
+ memset(pktbuf, 0, sizeof(pktbuf));
+
+ struct command {
+ u2_eth_packet_t h;
+ op_start_rx_streaming_t op;
+ op_eop_t eop;
+ };
+
+ command *c = (command *) pktbuf;
+ init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+ c->op.opcode = OP_START_RX_STREAMING;
+ c->op.len = sizeof(op_start_rx_streaming_t);
+ c->op.items_per_frame = htonl(items_per_frame);
+
+ c->eop.opcode = OP_EOP;
+ c->eop.len = sizeof(op_eop_t);
+
+ int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+ if (d_ethernet->write_packet(c, len) != len)
+ return false;
+
+ return true;
+}
+
+bool
usrp2_basic::stop_rx(const u2_mac_addr_t &which)
{
uint8_t pktbuf[MAX_PKTLEN];
@@ -274,41 +390,156 @@
return true;
}
+/*
+ * ------------------------------------------------------------------------
+ * Tx configuration
+ * ------------------------------------------------------------------------
+ */
+
bool
-usrp2_basic::config_tx(const u2_mac_addr_t &which,
- double freq,
- unsigned int interp,
- int scale_i, // 16.0 fixed point
format
- int scale_q // 16.0 fixed point
format
- )
+usrp2_basic::set_tx_gain(const u2_mac_addr_t &which, double gain)
{
uint8_t pktbuf[MAX_PKTLEN];
memset(pktbuf, 0, sizeof(pktbuf));
struct command {
u2_eth_packet_t h;
- op_config_tx_t op;
+ op_config_tx_v2_t op;
+ op_eop_t eop;
};
-
- command *c = (command *) pktbuf;
+
+ command *c = (command *) pktbuf;
init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
- c->op.opcode = OP_CONFIG_TX;
- c->op.len = sizeof(op_config_tx_t);
+ c->op.opcode = OP_CONFIG_TX_V2;
+ c->op.len = sizeof(op_config_tx_v2_t);
+ c->op.rid = d_next_rid++;
- double actual_freq;
- c->op.phase_inc = htonl(compute_freq_control_word_fpga(adc_rate(), freq,
&actual_freq));
+ c->op.valid = htons(CFGV_GAIN);
+ c->op.gain = htons(u2_double_to_fxpt_gain(gain));
+
+ c->eop.opcode = OP_EOP;
+ c->eop.len = sizeof(op_eop_t);
+
+ int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+ if (d_ethernet->write_packet(c, len) != len)
+ return false;
+
+ // FIXME wait for corresponding reply, etc.
+
+ return true;
+}
+
+bool
+usrp2_basic::set_tx_freq(const u2_mac_addr_t &which, double freq,
+ usrp2_tune_result *result)
+{
+ uint8_t pktbuf[MAX_PKTLEN];
+ memset(pktbuf, 0, sizeof(pktbuf));
+
+ struct command {
+ u2_eth_packet_t h;
+ op_config_tx_v2_t op;
+ op_eop_t eop;
+ };
+
+ command *c = (command *) pktbuf;
+ init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+ c->op.opcode = OP_CONFIG_TX_V2;
+ c->op.len = sizeof(op_config_tx_v2_t);
+ c->op.rid = d_next_rid++;
+
+ c->op.valid = htons(CFGV_FREQ);
+ u2_fxpt_freq_t fxpt = u2_double_to_fxpt_freq(freq);
+ c->op.freq_hi = htonl(u2_fxpt_freq_hi(fxpt));
+ c->op.freq_lo = htonl(u2_fxpt_freq_lo(fxpt));
+
+ c->eop.opcode = OP_EOP;
+ c->eop.len = sizeof(op_eop_t);
+
+ int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+ if (d_ethernet->write_packet(c, len) != len)
+ return false;
+
+ // FIXME wait for corresponding reply, etc.
+
+ if (result)
+ memset(result, 0, sizeof(*result));
+
+ return true;
+}
+
+bool
+usrp2_basic::set_tx_interp(const u2_mac_addr_t &which, int
interpolation_factor)
+{
+ uint8_t pktbuf[MAX_PKTLEN];
+ memset(pktbuf, 0, sizeof(pktbuf));
+
+ struct command {
+ u2_eth_packet_t h;
+ op_config_tx_v2_t op;
+ op_eop_t eop;
+ };
+
+ command *c = (command *) pktbuf;
+ init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+ c->op.opcode = OP_CONFIG_TX_V2;
+ c->op.len = sizeof(op_config_tx_v2_t);
+ c->op.rid = d_next_rid++;
+
+ c->op.valid = htons(CFGV_INTERP_DECIM);
+ c->op.interp = htonl(interpolation_factor);
+
+ c->eop.opcode = OP_EOP;
+ c->eop.len = sizeof(op_eop_t);
+
+ int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
+ if (d_ethernet->write_packet(c, len) != len)
+ return false;
+
+ // FIXME wait for corresponding reply, etc.
+
+ return true;
+}
+
+bool
+usrp2_basic::set_tx_scale_iq(const u2_mac_addr_t &which, int scale_i, int
scale_q)
+{
+ uint8_t pktbuf[MAX_PKTLEN];
+ memset(pktbuf, 0, sizeof(pktbuf));
+
+ struct command {
+ u2_eth_packet_t h;
+ op_config_tx_v2_t op;
+ op_eop_t eop;
+ };
+
+ command *c = (command *) pktbuf;
+ init_etf_hdrs(&c->h, which, 0, CONTROL_CHAN, -1);
+
+ c->op.opcode = OP_CONFIG_TX_V2;
+ c->op.len = sizeof(op_config_tx_v2_t);
+ c->op.rid = d_next_rid++;
+
+ c->op.valid = htons(CFGV_SCALE_IQ);
c->op.scale_iq = htonl(((scale_i & 0xffff) << 16) | (scale_q & 0xffff));
- c->op.interp = htonl(interp);
+ c->eop.opcode = OP_EOP;
+ c->eop.len = sizeof(op_eop_t);
+
int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
if (d_ethernet->write_packet(c, len) != len)
return false;
+ // FIXME wait for corresponding reply, etc.
+
return true;
}
+
// ------------------------------------------------------------------------
void
@@ -487,7 +718,7 @@
c->op.opcode = OP_READ_TIME;
c->op.len = sizeof(op_read_time_t);
- c->op.rid_mbz = 0;
+ c->op.rid = 0;
int len = std::max((size_t) MIN_PKTLEN, sizeof(command));
if (d_ethernet->write_packet(c, len) != len)
return false;
Modified: usrp2/trunk/host/lib/usrp2_basic.h
===================================================================
--- usrp2/trunk/host/lib/usrp2_basic.h 2008-05-12 05:32:16 UTC (rev 8406)
+++ usrp2/trunk/host/lib/usrp2_basic.h 2008-05-12 05:47:50 UTC (rev 8407)
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2007 Free Software Foundation, Inc.
+ * Copyright 2007,2008 Free Software Foundation, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,11 +30,33 @@
#define GRI_ETHERNET gri_ethernet
+//! Provides detailed result of tuning request
+
+struct usrp2_tune_result
+{
+ // RF frequency that corresponds to DC in the IF
+ double baseband_freq;
+
+ // frequency programmed into the DDC/DUC
+ double dxc_freq;
+
+ // residual frequency (typically < 0.01 Hz)
+ double residual_freq;
+
+ // is the spectrum inverted?
+ bool spectrum_inverted;
+
+ usrp2_tune_result()
+ : baseband_freq(0), dxc_freq(0), residual_freq(0),
spectrum_inverted(false) {}
+};
+
+
class usrp2_basic : public boost::noncopyable
{
GRI_ETHERNET *d_ethernet;
gri_pktfilter *d_pf;
int d_seqno;
+ int d_next_rid;
void init_et_hdrs(u2_eth_packet_t *p, const u2_mac_addr_t &dst);
@@ -83,6 +105,31 @@
static bool parse_mac_addr(const std::string &s, u2_mac_addr_t *p);
+ /*
+ * Rx configuration and control
+ */
+ bool set_rx_gain(const u2_mac_addr_t &which, double gain);
+ bool set_rx_freq(const u2_mac_addr_t &which, double frequency,
usrp2_tune_result *result);
+ bool set_rx_decim(const u2_mac_addr_t &which, int decimation_factor);
+ bool set_rx_scale_iq(const u2_mac_addr_t &which, int scale_i, int scale_q);
+
+ //! start streaming Rx samples
+ bool start_rx_streaming(const u2_mac_addr_t &which, unsigned int
items_per_frame=0);
+
+ //! stop streaming Rx samples
+ bool stop_rx(const u2_mac_addr_t &which);
+
+
+ /*
+ * Tx configuration and control
+ */
+ bool set_tx_gain(const u2_mac_addr_t &which, double gain);
+ bool set_tx_freq(const u2_mac_addr_t &which, double frequency,
usrp2_tune_result *result);
+ bool set_tx_interp(const u2_mac_addr_t &which, int interpolation_factor);
+ bool set_tx_scale_iq(const u2_mac_addr_t &which, int scale_i, int scale_q);
+
+
+#if 0
bool start_rx(const u2_mac_addr_t &which,
double freq,
unsigned int decim,
@@ -94,15 +141,14 @@
uint32_t rx_time = -1 // otherwise begin receiving at
rx_time
);
- bool stop_rx(const u2_mac_addr_t &which);
-
bool config_tx(const u2_mac_addr_t &which,
double freq,
unsigned int interp,
int scale_i, // 16.0 fixed point format
int scale_q // 16.0 fixed point format
);
+#endif
/*!
* \brief Read raw samples from USRP2.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r8407 - in usrp2/trunk: doc firmware/apps firmware/include firmware/lib host/apps host/lib,
eb <=