Firmware issue: Send a constant signal with the xcvr2450 dboard

Hi List,
I’m currently working on a standalone firmware app for USRP2. My goal is
to send a constant signal with the xcvr2450 dboard. I skipped the tuning
via firmware by doing this prior from a host using the simple_usrp c++
interface:

uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args);
uhd::device::sptr dev = sdev->get_device();
sdev->set_tx_rate(rate);
sdev->set_tx_freq(freq);
sdev->set_tx_gain(gain);

===============
So back to the firmware. Assuming the tuning of the dboard is properly
done from host, I basically understood the way sending is done as
follows:

  1. Wait for the buffer pool to become idle:

while((buffer_pool_status->status & BPS_IDLE(DSP_TX_BUF_0)) == 0)
;

  1. Copy the data which should be send to the DSP into the DSP tx-buffer:

uint32_t *p = buffer_ram(DSP_TX_BUF_0);
uint32_t sample = (32000 << 16) | 0; // for example
for (i = 0; i < BP_NLINE; i++) {
p[i] = sample;
}

  1. Send the data to the DSP:

bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1, 0, BP_LAST_LINE);

  1. Wait until transaction is done or an error occured

while((buffer_pool_status->status & (BPS_DONE(DSP_TX_BUF_0) |
BPS_ERROR(DSP_TX_BUF_0))) == 0)
;

  1. Clear the status flags and redo the whole procedure

bp_clear_buf(DSP_TX_BUF_0);
// goto 1.

===============

Unfortunately this doesn’t work for me like expected. I tried it in
several variations and listened with another usrp2 for a signal but
nothing happens. I think I understood something wrong and forgot
something but it’s hard for me to see the problem.

So maybe you guys can help me out with that.

Thanks in advance!

Cheers,
Matthias

On Wed, Sep 15, 2010 at 05:55:12PM +0200, Matthias Schäfer wrote:

sdev->set_tx_gain(gain);

bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1, 0, BP_LAST_LINE);
// goto 1.
Thanks in advance!

Cheers,
Matthias

A couple of things. 32000 is likely to be too big and will probably
result in clipping. Try 3200 to start with.

It’s unlikely that f/w can write samples to the buffer fast enough to
keep the data streaming. However in your case, you only need to
initialize the samples in the buffer once, then you can just keep
sending it over and over.

Do (2) once.

// Start in known good state (IDLE)
bp_clear_buf(DSP_TX_BUF_0);

// start first buffer xfer
bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1, 0, BP_LAST_LINE);

while (1){

// wait for xfer to complete
while ((buffer_pool_status->status &
(BPS_DONE(DSP_TX_BUF_0) | BPS_ERROR(DSP_TX_BUF_0))) == 0)
;

// Reset flags
bp_clear_buf(DSP_TX_BUF_0);

// start next xfer
bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1, 0, BP_LAST_LINE);
}

Eric

Am 16.09.2010 07:49, schrieb Eric B.:

sdev->set_tx_freq(freq);
;

bp_clear_buf(DSP_TX_BUF_0);

sending it over and over.

}

Eric
Hi Eric,
thank for your fast reply. I tried the things you told me but it doesn’t
work nevertheless. I’m using the txrx_uhd f/w with the additional void
SEND_DATA() (see below). After tuning the USRP2 with the mentioned
host-app (see above), I’m sending a UDP packet to the USRP2 with a
special port which becomes filtered by the eth_pkt_inspector which then
invokes SEND_DATA(). The serial port then tells me the following:

Waiting for the buffer pool.
Buffer pool idles. Filling buffer.
Filled buffer. Start sending.
Done.
Done.

and than the USRP2 stucks in the inner waiting-loop until I restart it.
If the debug-symbols (putstr) make any problems here, I tried it several
times without serial port but it didn’t have any effect. The H/W seems
to be okay, because sending and receiving with grc works fine.

Do I maybe have to set some dboard/buffer pool flags before sending?
Does my tuning procedure maybe leave the dboard in a “no-sending”-state?

static void SEND_DATA () {
putstr(“Waiting for the buffer pool.\n”);

while((buffer_pool_status->status & BPS_IDLE(DSP_TX_BUF_0)) == 0)
    ;

putstr("Buffer pool idles. Filling buffer.\n");

// fill buffer
uint32_t *p = buffer_ram(DSP_TX_BUF_0);
uint32_t i;
uint32_t sample = (3200 << 16) | 0;

for (i = 0; i < BP_NLINES; i++) {
    p[i] = sample;
}

putstr("Filled buffer. Start sending\n");

bp_clear_buf(DSP_TX_BUF_0);

// first xfer
bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1, 0, BP_LAST_LINE);

while (1) {

    // wait for xfer to complete
    while ((buffer_pool_status->status &
          (BPS_DONE(DSP_TX_BUF_0) | BPS_ERROR(DSP_TX_BUF_0))) == 0)
        ;

    putstr("Done.\n");

    bp_clear_buf(DSP_TX_BUF_0);

    // fire it off
    bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1, 0, BP_LAST_LINE);
}

}

Cheers,
Matthias

On Thu, Sep 16, 2010 at 03:26:17PM +0200, Matthias Schäfer wrote:

      (BPS_DONE(DSP_TX_BUF_0) | BPS_ERROR(DSP_TX_BUF_0))) == 0)

Eric
Filled buffer. Start sending.

uint32_t i;
// first xfer

    bp_clear_buf(DSP_TX_BUF_0);

    // fire it off
    bp_send_from_buf(DSP_TX_BUF_0, PORT_DSP, 1, 0, BP_LAST_LINE);
}

}

Cheers,
Matthias

Matthias,

I’m not familiar with the changes that were made for the UDH fpga
image. It may be that the timestamp checking is being done in the DSP
path. If so, raw samples won’t have the (possibly) required header.
I assume that there’s a “NOW” flag that can be set in the header, but
I don’t know the details. Looking at the UHD host code should show
you how the packet is built. Looking at the UDH firwmare will show
you which part of the header (UDP) is stripped off (probably by
adjusting the starting line number, passing on the VRT (or whatever)
header to the DSP pipe.

I believe the code above will work if you add the possibly required
header when you initialize the buffer.

Eric