[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gnuradio-discuss
Subject:    [Discuss-gnuradio] UHD Simultaneous tx/rx Loopback Problem
From:       Isaac Gerg <isaac.gerg () gergltd ! com>
Date:       2011-01-27 16:08:19
Message-ID: AANLkTin3CHv3bCLKm0v=qbfDOFhD6UqOyUpWNFv8nrUu () mail ! gmail ! com
[Download RAW message or body]

Using USRP 1.

I have 3 threads running.  A rx, a tx, and a sendMessage thread.  The rx
receives continuously.  I send a burst every 10 seconds with the sendMessage
thread.  sendMessage posts the message to a queue (mutex locked) which
triggers the tx thread to pull the message from the queue and send the
samples.  Currently, I have jimmy rigged the tx thread to send one cycle of
a complex exp() instead of sending the message (for debugging purposes).
However, I dont see the message on the rx side of the house.

I look for the message by monitoring the abs() of each sample and printing
out a message when the abs > 0.01.  I get about 10-20 samples that fit this
criteria every 10 seconds when I should be seeing a lot more.  No matter how
I vary my tx buffer length, I seem to always see the same number of samples
at the rx end.

Ive gone through my code again and I dont understand why this isnt working.
Here is a dump:

Some setup code:
    m_usrpSampsPerBlock = m_pDev->get_max_recv_samps_per_packet();

    //
http://ettus-apps.sourcerepo.com/redmine/ettus/projects/uhd/repository/revisions/master/entry/host/examples/benchmark_rx_rate.cpp
  // Flush rx buffer
    // idg - This seems to do nothing.
    uhd::rx_metadata_t md;
    std::vector<std::complex<float> > buff(m_usrpSampsPerBlock);
    while(m_pDev->recv(&buff.front(), buff.size(),
md,uhd::io_type_t::COMPLEX_FLOAT32,uhd::device::RECV_MODE_ONE_PACKET))
    {
        // NOP
    }
    //handle the error codes
    stringstream msg;
    switch(md.error_code)
    {
        case uhd::rx_metadata_t::ERROR_CODE_NONE:
            m_pLogger->log("USRP flush OK",__FILE__,__LINE__);
            break;
        case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
            //if (num_acc_samps == 0) continue;
            msg << "Got timeout before all samples received, possible packet
loss, exiting loop...";
            m_pLogger->log(msg.str(),__FILE__,__LINE__);
            break;
        case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
            //if (num_acc_samps == 0) continue;
            msg << "Overflow!";
            m_pLogger->log(msg.str(),__FILE__,__LINE__);
            break;
        default:
            msg << "Got error code 0x"<< md.error_code << ", exiting
loop...";
            m_pLogger->log(msg.str(),__FILE__,__LINE__);
            break;
    }

    //setup rx streaming

m_pSdev->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);


-- 
The tx thread
    Int32 burstSizeSamps = 100;
    vector<complex<Float32> > vec(burstSizeSamps);

    // Set up tx params.  We wish to send a burst.
    uhd::tx_metadata_t md;
    md.start_of_burst = true;
    md.end_of_burst   = true;

    Float32 v = 0;
    for (Int32 k=0;k<vec.size();++k)
    {
        v = 2*M_PI*(Float32(k)/Float32(vec.size()));
        vec[k] = complex<Float32>(cos(v), sin(v));
        //cout << vec[k] << " ";
    }
    cout << endl;

    // Send the entire contents of the buffer
    // This should be the only place where data is sent over the air!
    cout << "sending size [cpx samps]: " << vec.size() << endl;
    m_pDev->send(&(vec.front()), vec.size(),
md,uhd::io_type_t::COMPLEX_FLOAT32, uhd::device::SEND_MODE_FULL_BUFF);
}

the rx thread:
    m_pLogger->log("CTransceiver::rxThread() started.",__FILE__,__LINE__);

    uhd::set_thread_priority_safe();

    uhd::rx_metadata_t md;
    std::vector<std::complex<Float32> >* pBuff = NULL;
    stringstream msg;

    UInt64 blocksProcessed = 0;
    CTimer myTimer;
    myTimer.start();

    while (!(m_shutdown))
    {
        // Rx data
        pBuff = new vector<complex<Float32> >(m_usrpSampsPerBlock);

        size_t num_rx_samps =
m_pDev->recv(&(pBuff->front()),pBuff->size(),md,uhd::io_type_t::COMPLEX_FLOAT32,uhd::device::RECV_MODE_ONE_PACKET);
  msg.str("");

        if (0 == num_rx_samps)
        {
            m_pLogger->log("No samps rx.",__FILE__,__LINE__);
        }

        //handle the error codes
        switch(md.error_code)
        {
            case uhd::rx_metadata_t::ERROR_CODE_NONE:
                break;
            case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
                //if (num_acc_samps == 0) continue;
                msg << "Got timeout before all samples received, possible
packet loss, exiting loop...";
                m_pLogger->log(msg.str(),__FILE__,__LINE__);
                goto done_loop;
            case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
                //if (num_acc_samps == 0) continue;
                msg << "Overflow!";
                m_pLogger->log(msg.str(),__FILE__,__LINE__);
                goto done_loop;
            default:
                msg << "Got error code 0x"<< md.error_code << ", exiting
loop...";
                m_pLogger->log(msg.str(),__FILE__,__LINE__);
                goto done_loop;
        }

        done_loop:

        {
             // Lock queue
            boost::mutex::scoped_lock l(*m_pMutexRxQueue);
             // Put data block on queue
             m_pRxQueue->push_back(pBuff);
        }
    }

  // another thread wakes up and if there are blocks on the queue, it sends
them to processBlock()


--
processBlock()
void CTransceiver::processBlock(vector<complex<Float32> >* pBlock)
{
    //cout << pBlock->size() << endl;
    for (Int32 k=0;k<pBlock->size();++k)
    {
        if (abs((*pBlock)[k]) > 0.01)
        {
            cout << " HERE  " << (*pBlock)[k] << " " << k << endl;
        }
    }
    delete pBlock;
}
--

My output (the logger wakes up every 1 second to write the message queue to
disk)

[2011-01-27|10:57:42 -0500] (../src/Transceiver.cpp:274) USRP flush OK
[2011-01-27|10:57:42 -0500] (../src/Transceiver.cpp:296)
CTransceiver::setupUsrp() setup complete.
[2011-01-27|10:57:42 -0500] (../src/Transceiver.cpp:301)
CTransceiver::rxWorkerThread started.
[2011-01-27|10:57:42 -0500] (../src/Transceiver.cpp:125)
CTransceiver::rxThread() started.
[2011-01-27|10:57:43 -0500] (../src/Transceiver.cpp:47)
CTransceiver::txThread() started.

sending size [cpx samps]: 100
 HERE  (-0.0129704,-0.0245979) 41
 HERE  (-0.0138554,-0.0418409) 42
 HERE  (-0.0126652,-0.0428785) 43
 HERE  (-0.00927763,-0.0444044) 44
 HERE  (-0.00708029,-0.044557) 45
 HERE  (-0.00366222,-0.0450758) 46
 HERE  (-0.00152593,-0.0452284) 47
 HERE  (0.00238044,-0.0451674) 48
 HERE  (0.00332652,-0.0452284) 49
 HERE  (0.00946074,-0.0398877) 50
 HERE  (-0.004944,-0.0150456) 51
[2011-01-27|10:57:52 -0500] (../src/Transceiver.cpp:389) Posted message to
Tx queue.
[2011-01-27|10:57:53 -0500] (../src/Transceiver.cpp:86)
CTransceiver::txThread() sent 1 messages.

sending size [cpx samps]: 100
 HERE  (0.00979644,0.00268563) 1374
 HERE  (-0.024659,-0.0125126) 1513
 HERE  (-0.0340892,-0.027131) 1514
 HERE  (-0.0344249,-0.0291757) 1515
 HERE  (-0.0332347,-0.0318918) 1516
 HERE  (-0.0297861,-0.0314646) 1517
 HERE  (-0.0299081,-0.0389416) 1518
 HERE  (-0.0249031,-0.0137944) 1519
[2011-01-27|10:58:02 -0500] (../src/Transceiver.cpp:389) Posted message to
Tx queue.
[2011-01-27|10:58:03 -0500] (../src/Transceiver.cpp:86)
CTransceiver::txThread() sent 1 messages.

sending size [cpx samps]: 100
 HERE  (0.0184027,-0.00933866) 2819
 HERE  (-0.00930815,-0.0262764) 2924
 HERE  (-0.00799585,-0.0425428) 2925
 HERE  (-0.00534074,-0.0445265) 2926
 HERE  (-0.00323496,-0.0449538) 2927
 HERE  (0.000549333,-0.0451979) 2928
 HERE  (0.00173956,-0.0447401) 2929
 HERE  (0.00778222,-0.04532) 2930
 HERE  (0.000671407,-0.0408643) 2931
[2011-01-27|10:58:12 -0500] (../src/Transceiver.cpp:389) Posted message to
Tx queue.
[2011-01-27|10:58:13 -0500] (../src/Transceiver.cpp:86)
CTransceiver::txThread() sent 1 messages.
--

Also, the code I got from the repo to flush the rx buffer doesnt seem to
work.  Upon startup, I get a bunch of samples that trip the threshold
(abs()>0.01) before a message is even sent out.  Why is this?

Any help would be greatly appreciated!

Thanks,
Isaac


[Attachment #3 (text/html)]

Using USRP 1.<br><br>I have 3 threads running.  A rx, a tx, and a sendMessage thread. \
The rx receives continuously.  I send a burst every 10 seconds with the sendMessage \
thread.  sendMessage posts the message to a queue (mutex locked) which triggers the \
tx thread to pull the message from the queue and send the samples.  Currently, I have \
jimmy rigged the tx thread to send one cycle of a complex exp() instead of sending \
the message (for debugging purposes).  However, I dont see the message on the rx side \
of the house.  <br> <br>I look for the message by monitoring the abs() of each sample \
and printing out a message when the abs &gt; 0.01.  I get about 10-20 samples that \
fit this criteria every 10 seconds when I should be seeing a lot more.  No matter how \
I vary my tx buffer length, I seem to always see the same number of samples at the rx \
end.<br> <br>Ive gone through my code again and I dont understand why this isnt \
working.  Here is a dump:<br><br>Some setup code:<br>    m_usrpSampsPerBlock = \
m_pDev-&gt;get_max_recv_samps_per_packet();<br><br>    // <a \
href="http://ettus-apps.sourcerepo.com/redmine/ettus/projects/uhd/repository/revisions \
/master/entry/host/examples/benchmark_rx_rate.cpp">http://ettus-apps.sourcerepo.com/re \
dmine/ettus/projects/uhd/repository/revisions/master/entry/host/examples/benchmark_rx_rate.cpp</a><br>
  // Flush rx buffer<br>    // idg - This seems to do nothing.<br>    \
uhd::rx_metadata_t md;<br>    std::vector&lt;std::complex&lt;float&gt; &gt; \
buff(m_usrpSampsPerBlock);<br>    while(m_pDev-&gt;recv(&amp;buff.front(), \
buff.size(), md,uhd::io_type_t::COMPLEX_FLOAT32,uhd::device::RECV_MODE_ONE_PACKET))<br>
  {<br>        // NOP<br>    }<br>    //handle the error codes<br>    stringstream \
msg;<br>    switch(md.error_code)<br>    {<br>        case \
uhd::rx_metadata_t::ERROR_CODE_NONE:<br>            m_pLogger-&gt;log(&quot;USRP \
flush OK&quot;,__FILE__,__LINE__);<br>  break;<br>        case \
uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:<br>            //if (num_acc_samps == 0) \
continue;<br>            msg &lt;&lt; &quot;Got timeout before all samples received, \
possible packet loss, exiting loop...&quot;;<br>  \
m_pLogger-&gt;log(msg.str(),__FILE__,__LINE__);<br>            break;<br>        case \
uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:<br>            //if (num_acc_samps == 0) \
continue;<br>            msg &lt;&lt; &quot;Overflow!&quot;;<br>  \
m_pLogger-&gt;log(msg.str(),__FILE__,__LINE__);<br>            break;<br>        \
default:<br>            msg &lt;&lt; &quot;Got error code 0x&quot;&lt;&lt; \
md.error_code &lt;&lt; &quot;, exiting loop...&quot;;<br>  \
m_pLogger-&gt;log(msg.str(),__FILE__,__LINE__);<br>            break;<br>    \
}<br><br>    //setup rx streaming<br>    \
m_pSdev-&gt;issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);<br><br><br>-- \
<br> The tx thread<br>    Int32 burstSizeSamps = 100;<br>    \
vector&lt;complex&lt;Float32&gt; &gt; vec(burstSizeSamps);<br><br>    // Set up tx \
params.  We wish to send a burst.<br>    uhd::tx_metadata_t md;<br>    \
md.start_of_burst = true;<br>  md.end_of_burst   = true;<br><br>    Float32 v = \
0;<br>    for (Int32 k=0;k&lt;vec.size();++k)<br>    {<br>        v = \
2*M_PI*(Float32(k)/Float32(vec.size()));<br>        vec[k] = \
complex&lt;Float32&gt;(cos(v), sin(v));<br>  //cout &lt;&lt; vec[k] &lt;&lt; &quot; \
&quot;;<br>    }<br>    cout &lt;&lt; endl;<br><br>    // Send the entire contents of \
the buffer<br>    // This should be the only place where data is sent over the \
air!<br>    cout &lt;&lt; &quot;sending size [cpx samps]: &quot; &lt;&lt; vec.size() \
&lt;&lt; endl;<br>  m_pDev-&gt;send(&amp;(vec.front()), vec.size(), \
md,uhd::io_type_t::COMPLEX_FLOAT32, \
uhd::device::SEND_MODE_FULL_BUFF);<br>}<br><br>the rx thread:<br>    \
m_pLogger-&gt;log(&quot;CTransceiver::rxThread() \
started.&quot;,__FILE__,__LINE__);<br> <br>    \
uhd::set_thread_priority_safe();<br><br>    uhd::rx_metadata_t md;<br>    \
std::vector&lt;std::complex&lt;Float32&gt; &gt;* pBuff = NULL;<br>    stringstream \
msg;<br><br>    UInt64 blocksProcessed = 0;<br>    CTimer myTimer;<br>  \
myTimer.start();<br><br>    while (!(m_shutdown))<br>    {<br>        // Rx data<br>  \
pBuff = new vector&lt;complex&lt;Float32&gt; &gt;(m_usrpSampsPerBlock);<br><br>       \
size_t num_rx_samps = \
m_pDev-&gt;recv(&amp;(pBuff-&gt;front()),pBuff-&gt;size(),md,uhd::io_type_t::COMPLEX_FLOAT32,uhd::device::RECV_MODE_ONE_PACKET);<br>
  msg.str(&quot;&quot;);<br><br>        if (0 == num_rx_samps)<br>        {<br>       \
m_pLogger-&gt;log(&quot;No samps rx.&quot;,__FILE__,__LINE__);<br>        }<br><br>   \
//handle the error codes<br>        switch(md.error_code)<br>  {<br>            case \
uhd::rx_metadata_t::ERROR_CODE_NONE:<br>                break;<br>            case \
uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:<br>                //if (num_acc_samps == 0) \
continue;<br>                msg &lt;&lt; &quot;Got timeout before all samples \
received, possible packet loss, exiting loop...&quot;;<br>  \
m_pLogger-&gt;log(msg.str(),__FILE__,__LINE__);<br>                goto \
done_loop;<br>            case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:<br>           \
//if (num_acc_samps == 0) continue;<br>                msg &lt;&lt; \
&quot;Overflow!&quot;;<br>  m_pLogger-&gt;log(msg.str(),__FILE__,__LINE__);<br>       \
goto done_loop;<br>            default:<br>                msg &lt;&lt; &quot;Got \
error code 0x&quot;&lt;&lt; md.error_code &lt;&lt; &quot;, exiting loop...&quot;;<br> \
m_pLogger-&gt;log(msg.str(),__FILE__,__LINE__);<br>                goto \
done_loop;<br>        }<br><br>        done_loop:<br><br>        {<br>             // \
Lock queue<br>            boost::mutex::scoped_lock l(*m_pMutexRxQueue);<br>  // Put \
data block on queue<br>             m_pRxQueue-&gt;push_back(pBuff);<br>        }<br> \
}<br><br>  // another thread wakes up and if there are blocks on the queue, it sends \
them to processBlock()<br><br> <br>--<br>processBlock()<br>void \
CTransceiver::processBlock(vector&lt;complex&lt;Float32&gt; &gt;* pBlock)<br>{<br>    \
//cout &lt;&lt; pBlock-&gt;size() &lt;&lt; endl;<br>    for (Int32 \
k=0;k&lt;pBlock-&gt;size();++k)<br>  {<br>        if (abs((*pBlock)[k]) &gt; \
0.01)<br>        {<br>            cout &lt;&lt; &quot; HERE  &quot; &lt;&lt; \
(*pBlock)[k] &lt;&lt; &quot; &quot; &lt;&lt; k &lt;&lt; endl;<br>        }<br>    \
}<br>    delete pBlock;<br> }<br>--<br><br>My output (the logger wakes up every 1 \
second to write the message queue to disk)<br><br>[2011-01-27|10:57:42 -0500] \
(../src/Transceiver.cpp:274) USRP flush OK<br>[2011-01-27|10:57:42 -0500] \
(../src/Transceiver.cpp:296) CTransceiver::setupUsrp() setup complete.<br> \
[2011-01-27|10:57:42 -0500] (../src/Transceiver.cpp:301) CTransceiver::rxWorkerThread \
started.<br>[2011-01-27|10:57:42 -0500] (../src/Transceiver.cpp:125) \
CTransceiver::rxThread() started.<br>[2011-01-27|10:57:43 -0500] \
(../src/Transceiver.cpp:47) CTransceiver::txThread() started.<br> <br>sending size \
[cpx samps]: 100<br> HERE  (-0.0129704,-0.0245979) 41<br> HERE  \
(-0.0138554,-0.0418409) 42<br> HERE  (-0.0126652,-0.0428785) 43<br> HERE  \
(-0.00927763,-0.0444044) 44<br> HERE  (-0.00708029,-0.044557) 45<br>  HERE  \
(-0.00366222,-0.0450758) 46<br> HERE  (-0.00152593,-0.0452284) 47<br> HERE  \
(0.00238044,-0.0451674) 48<br> HERE  (0.00332652,-0.0452284) 49<br> HERE  \
(0.00946074,-0.0398877) 50<br> HERE  (-0.004944,-0.0150456) 51<br> \
[2011-01-27|10:57:52 -0500] (../src/Transceiver.cpp:389) Posted message to Tx \
queue.<br>[2011-01-27|10:57:53 -0500] (../src/Transceiver.cpp:86) \
CTransceiver::txThread() sent 1 messages.<br><br>sending size [cpx samps]: 100<br>  \
HERE  (0.00979644,0.00268563) 1374<br> HERE  (-0.024659,-0.0125126) 1513<br> HERE  \
(-0.0340892,-0.027131) 1514<br> HERE  (-0.0344249,-0.0291757) 1515<br> HERE  \
(-0.0332347,-0.0318918) 1516<br> HERE  (-0.0297861,-0.0314646) 1517<br>  HERE  \
(-0.0299081,-0.0389416) 1518<br> HERE  (-0.0249031,-0.0137944) \
1519<br>[2011-01-27|10:58:02 -0500] (../src/Transceiver.cpp:389) Posted message to Tx \
queue.<br>[2011-01-27|10:58:03 -0500] (../src/Transceiver.cpp:86) \
CTransceiver::txThread() sent 1 messages.<br> <br>sending size [cpx samps]: 100<br> \
HERE  (0.0184027,-0.00933866) 2819<br> HERE  (-0.00930815,-0.0262764) 2924<br> HERE  \
(-0.00799585,-0.0425428) 2925<br> HERE  (-0.00534074,-0.0445265) 2926<br> HERE  \
(-0.00323496,-0.0449538) 2927<br>  HERE  (0.000549333,-0.0451979) 2928<br> HERE  \
(0.00173956,-0.0447401) 2929<br> HERE  (0.00778222,-0.04532) 2930<br> HERE  \
(0.000671407,-0.0408643) 2931<br>[2011-01-27|10:58:12 -0500] \
(../src/Transceiver.cpp:389) Posted message to Tx queue.<br> [2011-01-27|10:58:13 \
-0500] (../src/Transceiver.cpp:86) CTransceiver::txThread() sent 1 \
messages.<br>--<br><br>Also, the code I got from the repo to flush the rx buffer \
doesnt seem to work.  Upon startup, I get a bunch of samples that trip the threshold \
(abs()&gt;0.01) before a message is even sent out.  Why is this?<br> <br>Any help \
would be greatly appreciated!<br><br>Thanks,<br>Isaac<br>



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic