<div dir="ltr"><div class="gmail_default" style="font-family:verdana,sans-serif"><div class="gmail_default" style="font-family:verdana,sans-serif">Hello Maurizio:<br><br></div>I have not reviewed your code in detail, but <span class="gmail-il">a</span> <span class="gmail-il">circular</span> <span class="gmail-il">buffer</span> using two separate threads, one for writing into the <span class="gmail-il">buffer</span>, and one for reading from the <span class="gmail-il">buffer</span> and writing <span class="gmail-il">to</span> the <span class="gmail-il">SD</span> <span class="gmail-il">card</span>, seems like <span class="gmail-il">a</span> reasonable approach. You will be limited by how fast <span class="gmail-il">samples</span> can be DMA'd from the FPGA <span class="gmail-il">to</span> the ARM CPU, which is probably around 12 Msps, as well as how fast you can write <span class="gmail-il">to</span> the <span class="gmail-il">SD</span> <span class="gmail-il">card</span>. You might want <span class="gmail-il">to</span> benchmark the write speed <span class="gmail-il">to</span> the <span class="gmail-il">SD</span> <span class="gmail-il">card</span> separately, using <span class="gmail-il">a</span> separate stand-alone program. What speed of <span class="gmail-il">SD</span> <span class="gmail-il">card</span> are you using? Have you been able <span class="gmail-il">to</span> make any further progress on this issue since initially making this post?<br><br>--​Neel Pandeya<br><br><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On 11 May 2017 at 09:22, Crozzoli Maurizio via USRP-users <span dir="ltr"><<a href="mailto:usrp-users@lists.ettus.com" target="_blank">usrp-users@lists.ettus.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi!<br>
We working on an E310.<br>
We are trying to implement a receiver operating at 1.92 Msps which is able to store data directly to the SD card of the E310 (a partitioned space with optimized ext4 performance).<br>
Our implementation is base do two threads:<br>
1. the main one receives samples from the E310 RX stages and stores them in a sort of circular buffer" in order to try and extend the total acquisition time frame (if we do not use the "circular buffer" approach we can save up to 84 million samples from two channels but we would like to get more if feasible);<br>
2. another one is in charge of getting data out of the "circular buffer" and save them to a file in the SD Card.<br>
<br>
A skeleton of our source code based on " rx_multi_samples.cpp" example provided by Ettus is given below.<br>
<br>
As a matter of fact the code runs and it can save about 17 million samples (8800*(1016*2)) from two channels with a buffer really small (samps_per_buff = 1016 elements; vect_size = samps_per_buff * 2) which would lead us to conclude that the activity related to writing data to SD is not as slow as we would have expected.<br>
<br>
If we can get such result with such a small buffer we would expect to be able to get more interesting with a much larger buffer (1016*N, N>>2) but, in practice, we found out that our idea is not true. We tried to use a buffer large enough to store 84 million (N=82000) samples (as we could do before implementing current "circular buffer" approach), but no way to save to SD more than the 17 million samples we could get with N=2.<br>
<br>
Is there anyone in the list who could help us to understand what is going on and, if possible, to find a solution?<br>
<br>
TIA!<br>
<br>
BR,<br>
Maurizio.<br>
<br>
<br>
/// GLOBAL VARIABLES //////////////////////////////<wbr>////////////<br>
const size_t samps_per_buff = 1016;<br>
size_t vect_size = samps_per_buff * 2; // Vector dimension<br>
size_t iRead  = 0;                     // Index of read item<br>
size_t iWrite = 0;                     // Index of written item<br>
<br>
vector<vector<complex<short> > > buffs(2, vector<complex<short> >(vect_size));<br>
//////////////////////////////<wbr>//////////////////////////////<wbr>///<br>
<br>
<br>
/// THREAD //////////////////////////////<wbr>//////////////////////<br>
void* writeData(void* param)<br>
{<br>
        [...]<br>
<br>
    do<br>
    {<br>
       if(iRead > iWrite)<br>
       {<br>
          buf_ptr[0] = &buffs[0].at(iWrite%vect_size)<wbr>;<br>
          buf_ptr[1] = &buffs[1].at(iWrite%vect_size)<wbr>;<br>
          if(iRead%vect_size == iWrite%vect_size) pthread_mutex_lock(&mtx);<br>
          fwrite(buf_ptr[0],4,samps_per_<wbr>buff,OutRXA);<br>
          fwrite(buf_ptr[1],4,samps_per_<wbr>buff,OutRXB);<br>
          if(iRead%vect_size == iWrite%vect_size) pthread_mutex_unlock(&mtx);<br>
          iWrite += samps_per_buff;<br>
       }<br>
    }<br>
    while (!done);<br>
<br>
    return NULL;<br>
}<br>
//////////////////////////////<wbr>//////////////////////////////<wbr>///<br>
<br>
<br>
<br>
/// START MAIN //////////////////////////////<wbr>//////////////////<br>
    //create a usrp device<br>
    //always select the subdevice first, the channel mapping affects the other settings<br>
    //set the rx sample rate (sets across all channels)<br>
    //detect which channels to use<br>
<br>
    //create a receive streamer<br>
    //linearly map channels (index0 = channel0, index1 = channel1, ...)<br>
    //meta-data will be filled in by recv()<br>
<br>
    //create a vector of pointers to point to each of the channel buffers<br>
    //setup streaming<br>
    //issue stream command<br>
<br>
        //////////////////////////////<wbr>//////////////////////////////<wbr>///////////<br>
    // Start Thread to enable "parallel" writing activity to SD (see above)<br>
    //////////////////////////////<wbr>//////////////////////////////<wbr>///////////<br>
<br>
<br>
    int iLoopMax = total_num_samps/samps_per_<wbr>buff;<br>
    for(int iLoop = 0; iLoop < iLoopMax; iLoop++)<br>
    {<br>
       if ( (iRead-iWrite) >= vect_size )<br>
         break;<br>
<br>
       // E310 reads bursts of size_t samps_per_buff = 1016 elements<br>
       size_t num_rx_samps = rx_stream->recv(buff_ptrs, samps_per_buff, md, timeout);<br>
<br>
       iRead += num_rx_samps;<br>
<br>
       //use a small timeout for subsequent packets (large enough to receive all samples)<br>
       timeout = ((double)samps_per_buff / rate) +0.1;<br>
<br>
       if(iRead < total_num_samps)<br>
       {<br>
          //advance pointers<br>
       }<br>
    }<br>
//////////////////////////////<wbr>//////////////////////////////<wbr>///<br>
<br>
Questo messaggio e i suoi allegati sono indirizzati esclusivamente alle persone indicate. La diffusione, copia o qualsiasi altra azione derivante dalla conoscenza di queste informazioni sono rigorosamente vietate. Qualora abbiate ricevuto questo documento per errore siete cortesemente pregati di darne immediata comunicazione al mittente e di provvedere alla sua distruzione, Grazie.<br>
<br>
This e-mail and any attachments is confidential and may contain privileged information intended for the addressee(s) only. Dissemination, copying, printing or use by anybody else is unauthorised. If you are not the intended recipient, please delete this message and any attachments and advise the sender by return e-mail, Thanks.<br>
<br>
Rispetta l'ambiente. Non stampare questa mail se non è necessario.<br>
<br>
______________________________<wbr>_________________<br>
USRP-users mailing list<br>
<a href="mailto:USRP-users@lists.ettus.com">USRP-users@lists.ettus.com</a><br>
<a href="http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com" rel="noreferrer" target="_blank">http://lists.ettus.com/<wbr>mailman/listinfo/usrp-users_<wbr>lists.ettus.com</a><br>
</blockquote></div><br></div>