commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r10299 - in gnuradio/branches/developers/eb/u2-mimo-wi


From: eb
Subject: [Commit-gnuradio] r10299 - in gnuradio/branches/developers/eb/u2-mimo-wip/usrp2: firmware/apps host/apps
Date: Fri, 23 Jan 2009 20:08:37 -0700 (MST)

Author: eb
Date: 2009-01-23 20:08:36 -0700 (Fri, 23 Jan 2009)
New Revision: 10299

Added:
   
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_app_common_v2.c
   
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_app_common_v2.h
   gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_tx.c
   
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_tx_slave.c
   gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/host/apps/test_mimo_tx.cc
Modified:
   gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/
   gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/Makefile.am
   
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/app_common_v2.h
   
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/app_passthru_v2.h
   gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/host/apps/
   gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/host/apps/Makefile.am
Log:
Mimo Tx works at interp 32! 



Property changes on: 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/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
echo
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
eth_serdes
serdes_txrx
set_hw_rev
test_sd
factory_test
test_ram

   + *-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
echo
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
eth_serdes
serdes_txrx
set_hw_rev
test_sd
factory_test
test_ram
mimo_tx
mimo_tx_slave


Modified: 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/Makefile.am
===================================================================
--- gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/Makefile.am 
2009-01-24 02:57:51 UTC (rev 10298)
+++ gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/Makefile.am 
2009-01-24 03:08:36 UTC (rev 10299)
@@ -47,9 +47,12 @@
        factory_test \
        serdes_txrx \
        sd_gentest \
-       sd_bounce
+       sd_bounce \
+       mimo_tx \
+       mimo_tx_slave
 
 
+
 # tx_drop_SOURCES = tx_drop.c app_common.c
 # tx_drop_rate_limited_SOURCES = tx_drop_rate_limited.c app_common.c
 # tx_drop2_SOURCES = tx_drop2.c app_common.c
@@ -57,6 +60,8 @@
 factory_test_SOURCES = factory_test.c app_common_v2.c
 eth_serdes_SOURCES = eth_serdes.c app_passthru_v2.c
 serdes_txrx_SOURCES = serdes_txrx.c app_common_v2.c
+mimo_tx_SOURCES = mimo_tx.c mimo_app_common_v2.c
+mimo_tx_slave_SOURCES = mimo_tx_slave.c app_common_v2.c
 
 noinst_HEADERS = \
         app_common_v2.h \

Modified: 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/app_common_v2.h
===================================================================
--- 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/app_common_v2.h 
    2009-01-24 02:57:51 UTC (rev 10298)
+++ 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/app_common_v2.h 
    2009-01-24 03:08:36 UTC (rev 10299)
@@ -27,7 +27,7 @@
 #include <stddef.h>
 #include <db.h>
 
-#define CPU_TX_BUF     1       // cpu -> eth
+#define CPU_TX_BUF     7       // cpu -> eth
 
 #define        _AL4 __attribute__((aligned (4)))
 

Modified: 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/app_passthru_v2.h
===================================================================
--- 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/app_passthru_v2.h
   2009-01-24 02:57:51 UTC (rev 10298)
+++ 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/app_passthru_v2.h
   2009-01-24 03:08:36 UTC (rev 10299)
@@ -27,7 +27,7 @@
 #include <stddef.h>
 #include <db.h>
 
-#define CPU_TX_BUF     1       // cpu -> eth
+#define CPU_TX_BUF     7       // cpu -> eth
 
 #define        _AL4 __attribute__((aligned (4)))
 

Copied: 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_app_common_v2.c
 (from rev 10297, 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/app_common_v2.c)
===================================================================
--- 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_app_common_v2.c
                                (rev 0)
+++ 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_app_common_v2.c
        2009-01-24 03:08:36 UTC (rev 10299)
@@ -0,0 +1,581 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008,2009 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 "mimo_app_common_v2.h"
+#include "buffer_pool.h"
+#include "memcpy_wa.h"
+#include "ethernet.h"
+#include "nonstdio.h"
+#include "print_rmon_regs.h"
+#include "db.h"
+#include "db_base.h"
+#include "clocks.h"
+#include "u2_init.h"
+#include <string.h>
+
+volatile bool link_is_up = false;      // eth handler sets this
+int cpu_tx_buf_dest_port = PORT_ETH;
+
+// 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 __attribute__((unused)) = 0;
+
+void abort(void);
+
+static bool
+burn_mac_addr(const op_burn_mac_addr_t *p)
+{
+  return ethernet_set_mac_addr(&p->addr);
+}
+
+static bool
+sync_to_pps(const op_generic_t *p)
+{
+  timesync_regs->sync_on_next_pps = 1;
+  putstr("SYNC to PPS\n");
+  return true;
+}
+
+static bool
+config_mimo_cmd(const op_config_mimo_t *p)
+{
+  clocks_mimo_config(p->flags);
+  return true;
+}
+
+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
+  hal_set_leds(0x4, 0x4);
+  while((buffer_pool_status->status & BPS_IDLE(CPU_TX_BUF)) == 0)
+    ;
+  hal_set_leds(0x0, 0x4);
+
+  // 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){
+    hal_set_leds(0x8, 0x8);
+    dbsm_wait_for_opening(ac_could_be_sending_to_eth);
+    hal_set_leds(0x0, 0x8);
+  }
+
+  if (0){
+    printf("sending_reply to port %d, len = %d\n", cpu_tx_buf_dest_port, 
(int)reply_len);
+    print_buffer(buffer_ram(CPU_TX_BUF), reply_len/4);
+  }
+
+  // fire it off
+  bp_send_from_buf(CPU_TX_BUF, cpu_tx_buf_dest_port, 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);
+}
+
+
+static size_t
+op_id_cmd(const op_generic_t *p,
+         void *reply_payload, size_t reply_payload_space)
+{
+  op_id_reply_t *r = (op_id_reply_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))        // no room
+    return 0;
+
+  // Build reply subpacket
+
+  r->opcode = OP_ID_REPLY;
+  r->len = sizeof(op_id_reply_t);
+  r->rid = p->rid;
+  r->addr = *ethernet_mac_addr();
+  r->hw_rev = (u2_hw_rev_major << 8) | u2_hw_rev_minor;
+  // r->fpga_md5sum = ;        // FIXME
+  // r->sw_md5sum = ;  // FIXME
+
+  return r->len;
+}
+
+
+static size_t
+config_tx_v2_cmd(const op_config_tx_v2_t *p,
+                void *reply_payload, size_t reply_payload_space)
+{
+  op_config_tx_reply_v2_t *r = (op_config_tx_reply_v2_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))
+    return 0;                                  // no room
+
+  struct tune_result   tune_result;
+  memset(&tune_result, 0, sizeof(tune_result));
+
+  bool ok = true;
+  
+#if 0
+  if (p->valid & CFGV_GAIN){
+    ok &= db_set_gain(tx_dboard, p->gain);
+  }
+
+  if (p->valid & CFGV_FREQ){
+    bool was_streaming = is_streaming();
+    if (was_streaming)
+      stop_rx_cmd();
+    
+    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 (was_streaming)
+      restart_streaming();
+  }
+
+  if (p->valid & CFGV_INTERP_DECIM){
+    int interp = p->interp;
+    int hb1 = 0;
+    int hb2 = 0;
+
+    if (!(interp & 1)){
+      hb2 = 1;
+      interp = interp >> 1;
+    }
+
+    if (!(interp & 1)){
+      hb1 = 1;
+      interp = interp >> 1;
+    }
+    
+    if (interp < MIN_CIC_INTERP || interp > MAX_CIC_INTERP)
+      ok = false;
+    else {
+      dsp_tx_regs->interp_rate = (hb1<<9) | (hb2<<8) | interp;
+      // printf("Interp: %d, register %d\n", p->interp, (hb1<<9) | (hb2<<8) | 
interp);
+    }
+  }
+
+  if (p->valid & CFGV_SCALE_IQ){
+    dsp_tx_regs->scale_iq = p->scale_iq;
+  }
+#endif
+
+  // Build reply subpacket
+
+  r->opcode = OP_CONFIG_TX_REPLY_V2;
+  r->len = sizeof(*r);
+  r->rid = p->rid;
+  r->ok = ok;
+  r->inverted = tune_result.inverted;
+  r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq);
+  r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq);
+  r->duc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq);
+  r->duc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq);
+  r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq);
+  r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq);
+  return r->len;
+}
+
+static size_t
+config_rx_v2_cmd(const op_config_rx_v2_t *p, 
+                void *reply_payload, size_t reply_payload_space)
+{
+  op_config_rx_reply_v2_t *r = (op_config_rx_reply_v2_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))
+    return 0;                          // no room
+
+  struct tune_result   tune_result;
+  memset(&tune_result, 0, sizeof(tune_result));
+
+  bool ok = true;
+  
+  if (p->valid & CFGV_GAIN){
+    ok &= db_set_gain(rx_dboard, p->gain);
+  }
+
+  if (p->valid & CFGV_FREQ){
+    bool was_streaming = is_streaming();
+    if (was_streaming)
+      stop_rx_cmd();
+    
+    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 (was_streaming)
+      restart_streaming();
+  }
+
+  if (p->valid & CFGV_INTERP_DECIM){
+    int decim = p->decim;
+    int hb1 = 0;
+    int hb2 = 0;
+    
+    if(!(decim & 1)) {
+      hb2 = 1;
+      decim = decim >> 1;
+    }
+    
+    if(!(decim & 1)) {
+      hb1 = 1;
+      decim = decim >> 1;
+    }
+    
+    if (decim < MIN_CIC_DECIM || decim > MAX_CIC_DECIM)
+      ok = false;
+    else {
+      dsp_rx_regs->decim_rate = (hb1<<9) | (hb2<<8) | decim;
+      // printf("Decim: %d, register %d\n", p->decim, (hb1<<9) | (hb2<<8) | 
decim);
+    }
+  }
+
+  if (p->valid & CFGV_SCALE_IQ){
+    dsp_rx_regs->scale_iq = p->scale_iq;
+  }
+
+  // Build reply subpacket
+
+  r->opcode = OP_CONFIG_RX_REPLY_V2;
+  r->len = sizeof(*r);
+  r->rid = p->rid;
+  r->ok = ok;
+  r->inverted = tune_result.inverted;
+  r->baseband_freq_hi = u2_fxpt_freq_hi(tune_result.baseband_freq);
+  r->baseband_freq_lo = u2_fxpt_freq_lo(tune_result.baseband_freq);
+  r->ddc_freq_hi = u2_fxpt_freq_hi(tune_result.dxc_freq);
+  r->ddc_freq_lo = u2_fxpt_freq_lo(tune_result.dxc_freq);
+  r->residual_freq_hi = u2_fxpt_freq_hi(tune_result.residual_freq);
+  r->residual_freq_lo = u2_fxpt_freq_lo(tune_result.residual_freq);
+
+  return r->len;
+}
+
+static size_t
+read_time_cmd(const op_generic_t *p,
+             void *reply_payload, size_t reply_payload_space)
+{
+  op_read_time_reply_t *r = (op_read_time_reply_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))                
+    return 0;                                  // no room
+
+  r->opcode = OP_READ_TIME_REPLY;
+  r->len = sizeof(*r);
+  r->rid = p->rid;
+  r->time = timer_regs->time;
+
+  return r->len;
+}
+
+static void
+fill_db_info(u2_db_info_t *p, const struct db_base *db)
+{
+  p->dbid = db->dbid;
+  p->freq_min_hi = u2_fxpt_freq_hi(db->freq_min);
+  p->freq_min_lo = u2_fxpt_freq_lo(db->freq_min);
+  p->freq_max_hi = u2_fxpt_freq_hi(db->freq_max);
+  p->freq_max_lo = u2_fxpt_freq_lo(db->freq_max);
+  p->gain_min = db->gain_min;
+  p->gain_max = db->gain_max;
+  p->gain_step_size = db->gain_step_size;
+}
+
+static size_t
+dboard_info_cmd(const op_generic_t *p,
+               void *reply_payload, size_t reply_payload_space)
+{
+  op_dboard_info_reply_t *r = (op_dboard_info_reply_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))                
+    return 0;                                  // no room
+
+  r->opcode = OP_DBOARD_INFO_REPLY;
+  r->len = sizeof(*r);
+  r->rid = p->rid;
+  r->ok = true;
+
+  fill_db_info(&r->tx_db_info, tx_dboard);
+  fill_db_info(&r->rx_db_info, rx_dboard);
+
+  return r->len;
+}
+
+static size_t
+peek_cmd(const op_peek_t *p,
+        void *reply_payload, size_t reply_payload_space)
+{
+  op_generic_t *r = (op_generic_t *) reply_payload;
+
+  putstr("peek: addr="); puthex32(p->addr);
+  printf(" bytes=%u\n", p->bytes);
+
+  if ((reply_payload_space < (sizeof(*r) + p->bytes)) ||
+      p->bytes > MAX_SUBPKT_LEN - sizeof(op_generic_t)) {
+    putstr("peek: insufficient reply packet space\n");
+    return 0;                  // FIXME do partial read?
+  }
+
+  r->opcode = OP_PEEK_REPLY;
+  r->len = sizeof(*r)+p->bytes;
+  r->rid = p->rid;
+  r->ok = true;
+
+  memcpy_wa(reply_payload+sizeof(*r), (void *)p->addr, p->bytes);
+
+  return r->len;
+}
+
+static bool
+poke_cmd(const op_poke_t *p)
+{
+  int bytes = p->len - sizeof(*p);
+  putstr("poke: addr="); puthex32(p->addr);
+  printf(" bytes=%u\n", bytes);
+
+  uint8_t *src = (uint8_t *)p + sizeof(*p);
+  memcpy_wa((void *)p->addr, src, bytes);
+
+  return true;
+}
+
+static size_t
+generic_reply(const op_generic_t *p,
+             void *reply_payload, size_t reply_payload_space,
+             bool ok)
+{
+  op_generic_t *r = (op_generic_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))                
+    return 0;                                  // no room
+
+  r->opcode = p->opcode | OP_REPLY_BIT;
+  r->len = sizeof(*r);
+  r->rid = p->rid;
+  r->ok = ok;
+
+  return r->len;
+}
+
+static size_t
+add_eop(void *reply_payload, size_t reply_payload_space)
+{
+  op_generic_t *r = (op_generic_t *) reply_payload;
+  if (reply_payload_space < sizeof(*r))                
+    return 0;                                  // no room
+
+  r->opcode = OP_EOP;
+  r->len = sizeof(*r);
+  r->rid = 0;
+  r->ok =  0;
+
+  return r->len;
+}
+
+void
+handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len)
+{
+  unsigned char reply[sizeof(u2_eth_packet_t) + 4 * sizeof(u2_subpkt_t)] _AL4;
+  unsigned char *reply_payload = &reply[sizeof(u2_eth_packet_t)];
+  int reply_payload_space = sizeof(reply) - sizeof(u2_eth_packet_t);
+
+  // initialize reply
+  memset(reply, 0, sizeof(reply));
+  set_reply_hdr((u2_eth_packet_t *) reply, pkt);
+
+  // point to beginning of payload (subpackets)
+  unsigned char *payload = ((unsigned char *) pkt) + sizeof(u2_eth_packet_t);
+  int payload_len = len - sizeof(u2_eth_packet_t);
+
+  size_t subpktlen = 0;
+
+  while (payload_len >= sizeof(op_generic_t)){
+    const op_generic_t *gp = (const op_generic_t *) payload;
+    subpktlen = 0;
+
+    // printf("\nopcode = %d\n", gp->opcode);
+
+    switch(gp->opcode){
+    case OP_EOP:               // end of subpackets
+      goto end_of_subpackets;
+
+    case OP_ID:
+      subpktlen = op_id_cmd(gp, reply_payload, reply_payload_space);
+      break;
+    
+    case OP_CONFIG_TX_V2:
+      subpktlen = config_tx_v2_cmd((op_config_tx_v2_t *) payload,
+                                  reply_payload, reply_payload_space);
+      break;
+
+    case OP_CONFIG_RX_V2:
+      subpktlen = config_rx_v2_cmd((op_config_rx_v2_t *) payload,
+                                  reply_payload, reply_payload_space);
+      break;
+
+    case OP_START_RX_STREAMING:
+      start_rx_streaming_cmd(&pkt->ehdr.src, (op_start_rx_streaming_t *) 
payload);
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true);
+      break;
+    
+    case OP_STOP_RX:
+      stop_rx_cmd();
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space, true);
+      break;
+    
+    case OP_BURN_MAC_ADDR:
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
+                               burn_mac_addr((op_burn_mac_addr_t *) payload));
+      break;
+
+    case OP_CONFIG_MIMO:
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
+                               config_mimo_cmd((op_config_mimo_t *) payload));
+      break;
+
+    case OP_READ_TIME:
+      subpktlen = read_time_cmd(gp, reply_payload, reply_payload_space);
+      break;
+
+    case OP_DBOARD_INFO:
+      subpktlen = dboard_info_cmd(gp, reply_payload, reply_payload_space);
+      break;
+
+    case OP_SYNC_TO_PPS:
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
+                               sync_to_pps((op_generic_t *) payload));
+      break;
+
+    case OP_PEEK:
+      subpktlen = peek_cmd((op_peek_t *)payload, reply_payload, 
reply_payload_space);
+      break;
+
+    case OP_POKE:
+      subpktlen = generic_reply(gp, reply_payload, reply_payload_space,
+                               poke_cmd((op_poke_t *)payload));
+      break;
+
+    default:
+      printf("app_common_v2: unhandled opcode = %d\n", gp->opcode);
+      break;
+    }
+
+    int t = (gp->len + 3) & ~3;                // bump to a multiple of 4
+    payload += t;
+    payload_len -= t;
+
+    subpktlen = (subpktlen + 3) & ~3;  // bump to a multiple of 4
+    reply_payload += subpktlen;
+    reply_payload_space -= subpktlen;
+  }
+
+ end_of_subpackets:
+
+  // add the EOP marker
+  subpktlen = add_eop(reply_payload, reply_payload_space);
+  subpktlen = (subpktlen + 3) & ~3;    // bump to a multiple of 4
+  reply_payload += subpktlen;
+  reply_payload_space -= subpktlen;
+
+  send_reply(reply, reply_payload - reply);
+}
+
+
+/*
+ * 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
+ */
+int
+eth_pkt_inspector(bsm12_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;
+
+  //static size_t last_len = 0;
+
+  // 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 -1;
+    break;
+
+  case 0:
+    return 0;  // pass it off to DSP TX
+
+  case 1:
+    return 1;  // pass it off to SERDES TX
+
+  default:
+    abort();
+    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 ? LED_RJ45 : 0x0, LED_RJ45);
+  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)
+{
+#if 0
+  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");
+#endif
+}

Copied: 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_app_common_v2.h
 (from rev 10297, 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/app_common_v2.h)
===================================================================
--- 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_app_common_v2.h
                                (rev 0)
+++ 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_app_common_v2.h
        2009-01-24 03:08:36 UTC (rev 10299)
@@ -0,0 +1,63 @@
+/* -*- 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 "bsm12.h"
+#include "memory_map.h"
+#include "hal_io.h"
+#include <stddef.h>
+#include <db.h>
+
+#define CPU_TX_BUF     7       // 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;
+
+extern int cpu_tx_buf_dest_port;
+
+void set_reply_hdr(u2_eth_packet_t *reply_pkt, u2_eth_packet_t const *cmd_pkt);
+
+/*
+ * Called when an ethernet packet is received.
+ */
+int eth_pkt_inspector(bsm12_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);
+
+
+void start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t 
*p);
+void stop_rx_cmd(void);
+void restart_streaming(void);
+bool is_streaming(void);
+
+void handle_control_chan_frame(u2_eth_packet_t *pkt, size_t len);
+
+#endif /* INCLUDED_APP_COMMON_H */

Copied: 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_tx.c (from 
rev 10297, 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/txrx.c)
===================================================================
--- gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_tx.c   
                        (rev 0)
+++ gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_tx.c   
2009-01-24 03:08:36 UTC (rev 10299)
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2007,2008,2009 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 "bsm12.h"
+#include "mimo_app_common_v2.h"
+#include "memcpy_wa.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "clocks.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
+
+
+/*
+ * Experimental code to transmit packets to DSP Tx and SERDES
+ *
+ * Hard wire the Tx config so we don't have to deal with control stuff yet.
+ */
+
+#define        BUF_BSM12_0     4
+#define        BUF_BSM12_1     5
+#define        BUF_BSM12_2     6
+
+//#define CPU_TX_BUF   7       // cpu -> eth
+
+// 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 bsm12_recv_args = {
+  PORT_ETH,
+  0,
+  BP_LAST_LINE
+};
+
+// send to DSP Tx
+buf_cmd_args_t bsm12_send0_args = {
+  PORT_DSP,
+  DSP_TX_FIRST_LINE,   // starts just past transport header
+  0                    // filled in from last_line register
+};
+
+// send to SERDES
+buf_cmd_args_t bsm12_send1_args = {
+  PORT_SERDES,
+  0,                   // starts just past transport header
+  0                    // filled in from last_line register
+};
+
+bsm12_t bsm12_sm;      // the state machine
+
+#if 0
+/*
+ * ================================================================
+ *   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
+#endif
+
+
+// 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 unsigned int streaming_items_per_frame = 0;
+static int          streaming_frame_count = 0;
+#define FRAMES_PER_CMD 1000
+
+bool is_streaming(void){ return streaming_p; }
+
+
+// ----------------------------------------------------------------
+
+
+void
+restart_streaming(void)
+{
+#if 0
+  // setup RX DSP regs
+  dsp_rx_regs->clear_state = 1;                        // reset
+
+  streaming_p = true;
+  streaming_frame_count = FRAMES_PER_CMD;
+
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+             streaming_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 * streaming_items_per_frame,
+             streaming_items_per_frame,
+             1, 1);                            
+
+  dsp_rx_regs->rx_time = 0;            // enqueue second command
+#endif
+}
+
+void
+start_rx_streaming_cmd(const u2_mac_addr_t *host, op_start_rx_streaming_t *p)
+{
+#if 0
+  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;
+
+  streaming_items_per_frame = p->items_per_frame;
+  restart_streaming();
+#endif
+}
+
+
+void
+stop_rx_cmd(void)
+{
+#if 0
+  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);
+#endif
+}
+
+
+static void
+setup_tx()
+{
+  dsp_tx_regs->clear_state = 1;
+
+  int tx_scale = 2500;
+  int interp = 8;              // * 4
+
+  // setup some defaults
+
+  dsp_tx_regs->freq = 429496730;       // 10MHz
+  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+  dsp_tx_regs->interp_rate = (1 << 9) | (1 << 8) | interp;
+}
+
+
+#if 0
+#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.
+ */
+int
+fw_sets_seqno_inspector(bsm12_t *sm, int buf_this)
+{
+  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
+#endif
+
+
+inline static void
+buffer_irq_handler(unsigned irq)
+{
+  uint32_t  status = buffer_pool_status->status;
+
+  bsm12_process_status(&bsm12_sm, status);
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  putstr("\nMIMO Tx\n");
+  print_mac_addr(ethernet_mac_addr()->addr);
+  newline();
+
+  ethernet_register_link_changed_callback(link_changed_callback);
+  ethernet_init();
+
+  clocks_mimo_config(MC_WE_DONT_LOCK | MC_PROVIDE_CLK_TO_MIMO);
+
+#if 0
+  // make bit 15 of Tx gpio's be a s/w output
+  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
+#endif
+
+  output_regs->debug_mux_ctrl = 1;
+#if 0
+  hal_gpio_set_sels(GPIO_TX_BANK, "1111111111111111");
+  hal_gpio_set_sels(GPIO_RX_BANK, "1111111111111111");
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
+  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
+#endif
+
+
+  // initialize double buffering state machine for ethernet -> DSP Tx
+
+  bsm12_init(&bsm12_sm, BUF_BSM12_0,
+            &bsm12_recv_args, &bsm12_send0_args, &bsm12_send1_args,
+            eth_pkt_inspector);
+
+
+#if 0
+  // 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;
+#endif
+
+
+  // program tx registers
+  setup_tx();
+
+  // kick off the state machine
+  bsm12_start(&bsm12_sm);
+
+  //int which = 0;
+
+  while(1){
+    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
+    // which ^= 0x8000;
+
+    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
+
+      // FIXME Figure out how to handle this robustly.
+      // Any buffers that are emptying should be allowed to drain...
+
+      if (streaming_p){
+       // restart_streaming();
+       // FIXME report error
+      }
+      else {
+       // FIXME report error
+      }
+      putchar('O');
+    }
+  }
+}

Copied: 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_tx_slave.c 
(from rev 10297, 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/serdes_txrx.c)
===================================================================
--- 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_tx_slave.c 
                            (rev 0)
+++ 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/firmware/apps/mimo_tx_slave.c 
    2009-01-24 03:08:36 UTC (rev 10299)
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2007,2008,2009 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 "clocks.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.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 serdes 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 serdes flow
+ * Buffers 4 and 5 are used to double-buffer the serdes to DSP Tx flow
+ */
+//#define CPU_RX_BUF   0       // eth -> cpu
+
+#define        DSP_RX_BUF_0    2       // dsp rx -> serdes (double buffer)
+#define        DSP_RX_BUF_1    3       // dsp rx -> serdes
+#define        DSP_TX_BUF_0    4       // serdes -> dsp tx (double buffer)
+#define        DSP_TX_BUF_1    5       // serdes -> dsp tx
+
+/*
+ * ==================================================================
+ *   configure DSP TX double buffering state machine (serdes -> 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 serdes
+buf_cmd_args_t dsp_tx_recv_args = {
+  PORT_SERDES,
+  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 -> serdes)
+ * =================================================================
+ */
+
+// 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 serdes
+buf_cmd_args_t dsp_rx_send_args = {
+  PORT_SERDES,
+  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 unsigned int streaming_items_per_frame = 0;
+static int          streaming_frame_count = 0;
+#define FRAMES_PER_CMD 1000
+
+bool is_streaming(void){ return streaming_p; }
+
+// ----------------------------------------------------------------
+
+
+void
+restart_streaming(void)
+{
+  // setup RX DSP regs
+  dsp_rx_regs->clear_state = 1;                        // reset
+
+  streaming_p = true;
+  streaming_frame_count = FRAMES_PER_CMD;
+
+  dsp_rx_regs->rx_command =
+    MK_RX_CMD(FRAMES_PER_CMD * streaming_items_per_frame,
+             streaming_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 * streaming_items_per_frame,
+             streaming_items_per_frame,
+             1, 1);                            
+
+  dsp_rx_regs->rx_time = 0;            // enqueue second command
+}
+
+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;
+
+  streaming_items_per_frame = p->items_per_frame;
+  restart_streaming();
+}
+
+
+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 = 2500;
+  int interp = 8;              // * 4
+
+  // setup some defaults
+
+  dsp_tx_regs->freq = 429496730;       // 10MHz
+  dsp_tx_regs->scale_iq = (tx_scale << 16) | tx_scale;
+  dsp_tx_regs->interp_rate = (1 << 9) | (1 << 8) | interp;
+}
+
+
+#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(LED_A);
+
+  uint32_t  status = buffer_pool_status->status;
+
+  if (0 && (status & ~BPS_IDLE_ALL)){
+    putstr("status = ");
+    puthex32_nl(status);
+  }
+
+  dbsm_process_status(&dsp_tx_sm, status);
+  dbsm_process_status(&dsp_rx_sm, status);
+}
+
+int
+main(void)
+{
+  u2_init();
+
+  output_regs->led_src = 0x3;          // h/w controls bottom two bits
+  clocks_enable_test_clk(true, 1);
+
+  putstr("\nMIMO Tx Slave\n");
+
+  cpu_tx_buf_dest_port = PORT_SERDES;
+
+  // ethernet_register_link_changed_callback(link_changed_callback);
+  // ethernet_init();
+
+  clocks_mimo_config(MC_WE_LOCK_TO_MIMO);
+
+  // puts("post clocks_mimo_config");
+
+#if 0
+  // make bit 15 of Tx gpio's be a s/w output
+  hal_gpio_set_sel(GPIO_TX_BANK, 15, 's');
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0x8000, 0x8000);
+#endif
+
+#if 0
+  output_regs->debug_mux_ctrl = 1;
+  hal_gpio_set_sels(GPIO_TX_BANK, "0000000000000000");
+  hal_gpio_set_sels(GPIO_RX_BANK, "0000000000000000");
+  hal_gpio_set_ddr(GPIO_TX_BANK, 0xffff, 0xffff);
+  hal_gpio_set_ddr(GPIO_RX_BANK, 0xffff, 0xffff);
+#endif
+
+
+  // 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);
+
+
+  //output_regs->flush_icache = 1;
+ 
+  // 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);
+  }
+
+  // puts("post dbsm_init's");
+
+  // 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();
+
+  // puts("post setup_tx");
+
+  // kick off the state machine
+  dbsm_start(&dsp_tx_sm);
+
+  // puts("post dbsm_start");
+
+  //int which = 0;
+
+  while(1){
+    // hal_gpio_write(GPIO_TX_BANK, which, 0x8000);
+    // which ^= 0x8000;
+
+    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
+
+      // FIXME Figure out how to handle this robustly.
+      // Any buffers that are emptying should be allowed to drain...
+
+      if (streaming_p){
+       // restart_streaming();
+       // FIXME report error
+      }
+      else {
+       // FIXME report error
+      }
+      putchar('O');
+    }
+  }
+}


Property changes on: gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/host/apps
___________________________________________________________________
Name: svn:ignore
   - Makefile
Makefile.in
.libs
.deps
test_eth
test_usrp2
gen_const
find_usrps
cerr
*.sh
tx_samples
rx_streaming_samples
u2_burn_mac_addr
usrp2_burn_mac_addr

   + Makefile
Makefile.in
.libs
.deps
test_eth
test_usrp2
gen_const
find_usrps
cerr
*.sh
tx_samples
rx_streaming_samples
u2_burn_mac_addr
usrp2_burn_mac_addr
test_mimo_tx


Modified: 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/host/apps/Makefile.am
===================================================================
--- gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/host/apps/Makefile.am     
2009-01-24 02:57:51 UTC (rev 10298)
+++ gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/host/apps/Makefile.am     
2009-01-24 03:08:36 UTC (rev 10299)
@@ -35,10 +35,12 @@
 noinst_PROGRAMS = \
        gen_const \
        rx_streaming_samples \
-       tx_samples
+       tx_samples \
+       test_mimo_tx
 
 find_usrps_SOURCES = find_usrps.cc
 usrp2_burn_mac_addr_SOURCES = usrp2_burn_mac_addr.cc
 rx_streaming_samples_SOURCES = rx_streaming_samples.cc
 gen_const_SOURCES = gen_const.cc
 tx_samples_SOURCES = tx_samples.cc
+test_mimo_tx_SOURCES = test_mimo_tx.cc

Copied: 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/host/apps/test_mimo_tx.cc 
(from rev 10297, 
gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/host/apps/tx_samples.cc)
===================================================================
--- gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/host/apps/test_mimo_tx.cc 
                        (rev 0)
+++ gnuradio/branches/developers/eb/u2-mimo-wip/usrp2/host/apps/test_mimo_tx.cc 
2009-01-24 03:08:36 UTC (rev 10299)
@@ -0,0 +1,299 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2008,2009 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/usrp2.h>
+#include <usrp2/strtod_si.h>
+#include <iostream>
+#include <complex>
+#include <getopt.h>
+#include <gruel/realtime.h>
+#include <signal.h>
+#include <string.h>
+#include <stdexcept>
+#include <math.h>
+
+
+typedef std::complex<float> fcomplex;
+
+static volatile bool signaled = false;
+
+void 
+gen_and_send(usrp2::usrp2::sptr u2, int chan,
+            double *ph, double ph_incr, int nsamples);
+
+
+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");
+  }
+}
+
+
+static const char *
+prettify_progname(const char *progname)                // that's probably 
almost a word ;)
+{
+  const char *p = strrchr(progname, '/');      // drop leading directory path
+  if (p)
+    p++;
+
+  if (strncmp(p, "lt-", 3) == 0)               // drop lt- libtool prefix
+    p += 3;
+
+  return p;
+}
+
+static void
+usage(const char *progname)
+{
+  fprintf(stderr, "Usage: %s [options]\n\n", prettify_progname(progname));
+  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, "  -I INPUT_FILE        set input filename 
[default=stdin]\n");
+  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, "  -S SCALE             fpga scaling factor for I & Q 
[default=256]\n");
+}
+
+#define GAIN_NOT_SET (-1000)
+#define        MAX_SAMPLES (371)
+
+int
+main(int argc, char **argv)
+{
+  const char *interface = "eth0";
+  const char *input_filename = 0;
+  bool repeat = false;
+  const char *mac_addr_str = "";
+  double freq = 0;
+  int32_t interp = 32;
+  int32_t samples_per_frame = MAX_SAMPLES;
+  int32_t scale = -1;
+  double gain = GAIN_NOT_SET;
+  
+  int    ch;
+  double tmp;
+
+
+  while ((ch = getopt(argc, argv, "he:m:I:rf:i:S:F:g:")) != EOF){
+    switch (ch){
+
+    case 'e':
+      interface = optarg;
+      break;
+      
+    case 'm':
+      mac_addr_str = optarg;
+#if 0
+      if (!usrp2_basic::parse_mac_addr(optarg, &mac_addr)){
+       std::cerr << "invalid mac addr: " << optarg << std::endl;
+       usage(argv[0]);
+       return 1;
+      }
+#endif
+      break;
+
+    case 'I':
+      input_filename = optarg;
+      break;
+      
+    case 'r':
+      repeat = true;
+      break;
+      
+    case 'f':
+      if (!strtod_si(optarg, &freq)){
+       std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       return 1;
+      }
+      break;
+
+    case 'F':
+      samples_per_frame = strtol(optarg, 0, 0);
+      break;
+
+    case 'i':
+      interp = strtol(optarg, 0, 0);
+      break;
+
+    case 'S':
+      if (!strtod_si(optarg, &tmp)){
+       std::cerr << "invalid number: " << optarg << std::endl;
+       usage(argv[0]);
+       return 1;
+      }
+      scale = static_cast<int32_t>(tmp);
+      break;
+      
+    case 'h':
+    default:
+      usage(argv[0]);
+      return 1;
+    }
+  }
+
+  
+  if (argc - optind != 0){
+    usage(argv[0]);
+    return 1;
+  }
+  
+  if (samples_per_frame < 9 || samples_per_frame > MAX_SAMPLES){
+    std::cerr << prettify_progname(argv[0])
+             << ": samples_per_frame is out of range.  "
+             << "Must be in [9, " << MAX_SAMPLES << "].\n";
+    usage(argv[0]);
+    return 1;
+  }
+
+
+  FILE *fp = 0;
+  if (input_filename == 0)
+    fp = stdin;
+  else {
+    fp = fopen(input_filename, "rb");
+    if (fp == 0){
+      perror(input_filename);
+      return 1;
+    }
+  }
+
+  install_sig_handler(SIGINT, sig_handler);
+
+
+  gruel::rt_status_t rt = gruel::enable_realtime_scheduling();
+  if (rt != gruel::RT_OK)
+    std::cerr << "Failed to enable realtime scheduling" << std::endl;
+
+
+  usrp2::usrp2::sptr u2 = usrp2::usrp2::make(interface, mac_addr_str);
+  
+#if 0
+  if (gain != GAIN_NOT_SET){
+    if (!u2->set_tx_gain(gain)){
+      std::cerr << "set_tx_gain failed\n";
+      return 1;
+    }
+  }
+
+  usrp2::tune_result tr;
+  if (!u2->set_tx_center_freq(freq, &tr)){
+    fprintf(stderr, "set_tx_center_freq(%g) failed\n", freq);
+    return 1;
+  }
+
+  printf("Daughterboard configuration:\n");
+  printf("  baseband_freq=%f\n", tr.baseband_freq);
+  printf("       duc_freq=%f\n", tr.dxc_freq);
+  printf("  residual_freq=%f\n", tr.residual_freq);
+  printf("       inverted=%s\n\n", tr.spectrum_inverted ? "yes" : "no");
+
+  if (!u2->set_tx_interp(interp)){
+    fprintf(stderr, "set_tx_interp(%d) failed\n", interp);
+    return 1;
+  }
+
+  if (scale != -1){
+    if (!u2->set_tx_scale_iq(scale, scale)){
+      std::cerr << "set_tx_scale_iq failed\n";
+      return 1;
+    }
+  }
+#endif
+
+  double baseband_rate = 100e6 / 32;
+
+  double ph0 = 0;
+  double ph1 = 0;
+
+  double ph0_incr = 7.5e3/baseband_rate * 2 * M_PI;
+  double ph1_incr = 7.5e3/baseband_rate * 2 * M_PI;
+
+  while (!signaled){
+
+    gen_and_send(u2, 0, &ph0, ph0_incr, samples_per_frame);
+    gen_and_send(u2, 1, &ph1, ph1_incr, samples_per_frame);
+
+  }
+
+  return 0;
+}
+
+void
+gen_and_send(usrp2::usrp2::sptr u2, int chan,
+            double *ph_ptr, double ph_incr, int nsamples)
+{
+  double ph = *ph_ptr;
+  
+  std::complex<float>  buf[MAX_SAMPLES];
+
+  usrp2::tx_metadata   md;
+  md.timestamp = -1;
+  md.start_of_burst = 1;
+  md.send_now = 1;
+
+  float ampl;
+
+  if (chan == 0)
+    ampl = 0.5;
+  else
+    ampl = 0.75;
+
+
+  for (int i = 0; i < nsamples; i++){
+#if 0
+    float s, c;
+    sincosf((float) ph, &s, &c);
+    buf[i] = std::complex<float>(s * ampl, c * ampl);
+    ph += ph_incr;
+#else
+    buf[i] = std::complex<float>(ampl, 0);
+#endif
+  }
+
+  if (!u2->tx_32fc(chan, buf, nsamples, &md)){
+    fprintf(stderr, "tx_32fc failed\n");
+  }
+
+  ph = fmod(ph, 2*M_PI);
+  *ph_ptr = ph;
+}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]