Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can a RFNOC Replay block perform record and play simultaneously? #793

Closed
tomwts opened this issue Oct 5, 2024 · 7 comments
Closed

Can a RFNOC Replay block perform record and play simultaneously? #793

tomwts opened this issue Oct 5, 2024 · 7 comments

Comments

@tomwts
Copy link

tomwts commented Oct 5, 2024

Issue Description

I am working on a RFNOC application that buffers or delays the samples received from a Rx radio block for a fixed short interval and then retransmits the samples on a Tx radio block. It seems the prebuilt RFNOC Replay block may be able to do the job, but I am not sure whether the RFNOC replay block is capable of performing record and play at the same time.

Does anyone have had any success running a RFNOC Replay block to stream non-repeating data continuously?

@cjhonlyone
Copy link

cjhonlyone commented Oct 5, 2024

Replay_trx_simultaneously.zip
Code for recording and playing simultaneously using the Replay module.

(1) Store the transmitted data in DRAM:
TxStreamer#0:0 --> 0/Replay#0:0

(2) Recording and playing simultaneously
0/Replay#0:0 --> 0/DUC#0:0
0/DUC#0:0 ==> 0/Radio#0:0
0/Radio#0:0 ==> 0/DDC#0:0
0/DDC#0:0 --> 0/Replay#0:0 (connect as a back edge)

(3) Transfer to the computer:
0/Replay#0:0 --> RxStreamer#0:0

@cjhonlyone
Copy link

cjhonlyone commented Oct 6, 2024

I thought a more concise way.

    dram_replay_chan = 0;
    radio_replay_chan = 1;

    graph->connect(tx_stream, 0, replay_ctrl->get_block_id(), dram_replay_chan);

    graph->connect(replay_ctrl->get_block_id(), radio_replay_chan, duc_ctrl->get_block_id(), duc_chan);
    graph->connect(duc_ctrl->get_block_id(), duc_chan, tx_radio_ctrl->get_block_id(), tx_chan);

    graph->connect(rx_radio_ctrl->get_block_id(), rx_chan, ddc_ctrl->get_block_id(), ddc_chan);
    graph->connect(ddc_ctrl->get_block_id(), ddc_chan, replay_ctrl->get_block_id(), radio_replay_chan, true);

    graph->connect(replay_ctrl->get_block_id(), dram_replay_chan, rx_stream, 0);

+-------------------------------------------------------+
| # means channel                                       |
|                        +--------+                     |
| #1 DRAM to Radio  <----+        |<---- PC to DRAM #0  |
|                        | Replay |                     |
| #1 Radio to DRAM  ---->|        +----> DRAM to PC #0  |
|                        +--------+                     |
|                                                       |
+-------------------------------------------------------+

That is
Active connections:

  • TxStreamer#0:0-->0/Replay#0:0
  • 0/Replay#0:1-->0/DUC#0:0
  • 0/DUC#0:0==>0/Radio#0:0
  • 0/Radio#0:0==>0/DDC#0:0
  • 0/DDC#0:0-->0/Replay#0:1
  • 0/Replay#0:0-->RxStreamer#0:0
    Tested it successfully with my platform (x310).

@mbr0wn
Copy link
Contributor

mbr0wn commented Oct 7, 2024

@tomwts yeah, that's possible. Just pre-load all the relevant commands to the replay block.

@mbr0wn mbr0wn closed this as completed Oct 7, 2024
@tomwts
Copy link
Author

tomwts commented Oct 7, 2024

Hi cjhonlyone, thank you for your response. I definitely will try it on my X310.

Once the record() API is called, will it record the input samples until the buffer is full or it will continue to record by overwriting the record buffer?

The USRP manual doesn't mention the behavior of record() API when the entire buffer is full. I wonder if there is a way to configure the record() API to continuously writing or overwriting data to the record buffer.

Thanks,

@cjhonlyone
Copy link

cjhonlyone commented Oct 8, 2024

Hi cjhonlyone, thank you for your response. I definitely will try it on my X310.

Once the record() API is called, will it record the input samples until the buffer is full or it will continue to record by overwriting the record buffer?

The USRP manual doesn't mention the behavior of record() API when the entire buffer is full. I wonder if there is a way to configure the record() API to continuously writing or overwriting data to the record buffer.

Thanks,

When the record() API is called, there are no samples to record. You must issue time command to tell radio to generate stream to Replay module, and you can specify the number of samples.
Steam come from upstream module. So, if the number of samples from upstream is more than your entire buffer, the record() API will overwrite data to the record buffer.

There is still a problem with the above code. This is the main code for recording and playing simultaneously.


    replay_ctrl->record(record_buff_addr, record_buff_size, radio_replay_chan);
    replay_ctrl->record_restart(radio_replay_chan);
    cout << "Record fullness:      " << replay_ctrl->get_record_fullness(radio_replay_chan)
         << " bytes" << endl;

    replay_ctrl->config_play(play_buff_addr, play_buff_size, radio_replay_chan);

    uhd::stream_cmd_t stream_cmd_radio(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
    uhd::stream_cmd_t stream_cmd_replay(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);

    uint32_t rate_ratio = int(rx_radio_ctrl->get_rate() / rate);
    stream_cmd_radio.num_samps = record_buff_size / 4 * rate_ratio;
    stream_cmd_replay.num_samps = record_buff_size / 4;
    stream_cmd_radio.stream_now = false;
    stream_cmd_replay.stream_now = false;
    stream_cmd_radio.time_spec = graph->get_mb_controller()->get_timekeeper(0)->get_time_now() + uhd::time_spec_t(0.01);
    stream_cmd_replay.time_spec = stream_cmd_radio.time_spec;

    replay_ctrl->issue_stream_cmd(stream_cmd_replay, radio_replay_chan);
    rx_radio_ctrl->issue_stream_cmd(stream_cmd_radio, rx_chan);

@tomwts
Copy link
Author

tomwts commented Oct 9, 2024

Hi cjhonlyone,

I have some questions on your updated source. Both stream_cmd_radio and stream_cmd_replay were instantiated with STREAM_MODE_NUM_SAMPS_AND_DONE. For my case, I want the record and replay continuous. Such setting may not applicable to me.

Another question is about the start time. There is a slight delay (0.01) specified. Would stream_cmd_radio buffer the received samples between now and 0.01sec to the future and starts the record session when the target time arrived, or it would miss recording the samples between now and 0.01sec to the future?

I had read from other posting about the time_spec setting. Someone claimed the received samples would be buffered before the start time arrived. I wonder if it is truly the case or not. If it is true, then I don't really need a Replay block to perform the samples delay. I would just set the start time to = (now + delay time) and let the streamer to perform the buffering, but personally I am skeptical about such claim.

What I really want is to simulate a RF path delay using a Replay block, but if the DDC's start time is set to (now + delay time desired) and DDC would buffer the received samples until the start time arrives, that would be awesome!

Do you know if that is indeed the case?

Thanks,

@cjhonlyone
Copy link

As far as I know, the received samples will not be buffered until the start time has arrived.
It might be helpful to consider setting the radio to start immediately, while delaying the start time of the Replay block by a little.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants