Hey, sorry to post again, but I think this time I have a solution. In my grc-generated python file I added the lines:
cmd_time_1 = self.sender_A.get_time_now() + uhd.time_spec_t(5.0) self.uhd_rfnoc_streamer_fifo_0_0.set_start_time(cmd_time_1) self.uhd_rfnoc_streamer_fifo_0.set_start_time(cmd_time_1) Unfortunately this command did not do anything so i had to modify rfnoc_block_impl.cc in the gr-ettus folder. I added: #define BETTER #ifdef BETTER if (_start_time_set) { _tx.metadata.has_time_spec = true; _tx.metadata.time_spec = _start_time; std::cout << "Patch: Start Time Stream inserted"<< std::endl; } else { _tx.metadata.has_time_spec = false; } #endif around line 300 after the commands _tx.metadata.start_of_burst = false; _tx.metadata.end_of_burst = false; _tx.metadata.has_time_spec = false; so that now the _start_time_set variable actually is used. (I then of course used make and make install in the gr-ettus/build) Now I get the desired behauviour and in addition can set a start time for both my streams. Kudos to this guy https://discuss-gnuradio.gnu.narkive.com/joj8MDyW/gnu-radio-3-7-12-rfnoc-set-start-time who used this, to correct the set_start_time command and I hoped that this would also fix my random phase offset problem, which was the case. Best Regards Felix > Hello together, > > I wanted to give you a short update about phase-synchronizing my > USRPx310's ubx160 daugtherboards and clarify the problem I am facing for > better understandig. > > I am using both TX-Ports of my USRP to transmit the same complex cosine > generated with GNU-Radio. My image is a custom RFNoC image and contains > 2xDDC, 2xDUC, 2xRadio,1xDMA-FIFO,1xAddsub and 2xFIFO. My center frequency > is 2.45 GHz and the frequency of the cosine is 100 KHz. > > My flowgraph looks like this, > > SigSource--->RFNoC_FIFO_0--->DMA_FIFO--->RFNoC-DUC_0-->RFNoC_Radio_A > | | | > -->RFNoC_FIFO_1--- --->RFNoC_DUC_1-->RFNoC_Radio_B > > and both antenna outputs are connected to an Agilent infiniium > oscilloscope. > Thus I can measure the phase offset between both of my output ports, by > measuring the phase offset of both displayed cosines. My goal is to > receive the same/almost the same relative phase offset with each new > restart of the flowgraph. Sadly, using the RFNoC blocks, I get a different > phase offset every time. > > When I use UHD-USRP Sink instead, (with the same Image and without RFNoC > blocks) I do get a consistent phase offset between both ports with every > restart of the flowgraph or even power cycles. This is the behaviour I > want for my RFNoC Flowgraph as well; and because it is the same image, I > am pretty sure there just must be a way to clone this behaviour to the > RFNoC realm as well. > > My approach up till now was, to use timed commands in my GRC-generated > python code for both RFnoC-Radio Blocks A and B, which each represent one > daugtherboard, I think. I then put the .set_tx_freq commands in the code > betweeen set_command time and clear_command time: > > #A.get_time_now equals B.get_time_now > cmd_time = self.sender_A.get_time_now() + uhd.time_spec_t(0.1) > self.sender_A.set_command_time(cmd_time) > self.sender_B.set_command_time(cmd_time) > ---- > Tuning Commands > self.sender_A.set_tx_freq(c_freq, i) > self.sender_B.set_tx_freq(c_freq, i) > --- > > self.sender_A.clear_command_time(0) > self.sender_B.clear_command_time(0) > # End Timed Commands > > This approach however did not work for me. > > After my attempt with the timed commands failed, I tried to change all > paramters. When I set the frequency of my cosine to zero I actually got a > consistent phase offset. My conclusion is, that the mixers lock with a > consistent relative phase offset every time, because DC Signals do not > have relative phases. Because of that I think that maybe really both > Radio-Blocks start streaming with a random time offset or something > similar. > > Now to my questions > > 1) Is using the timed commands really the way to go? Remember I do NOT > want to synchronize multiple USRP-Devices but only that both > D-Boards/Radio-Blocks of one device, lock with the same relative phase. > > 2) Do I have to start the streaming manually somehow, with a timestamp or > something similar? And when the answer is yes, how do I do it in python > without the multi_usrp_api? > > 3) How can I control the start of streaming in my python code so that both > RFNoC Radios start at the same time? > > 4) How does the UHD_USRP_Sink Block work? I mean is there a verilog code > for it too and does it call the rfnoc_radio and rfnoc_duc modules etc.? > What are the parameters for the UHD_USRP_Sink Blocks DMA_FIFO and DUC? > I am asking this because I would like to clone that blocks behaviour > > 5) Any other question that I am not smart enough to ask but that deserves > an answer either way :D > > Again, any help is greatly appreciated because the synchronisation of both > TX-paths with RFnoC is crucial for my project and I can not work around > this issue. > > Best regard and thank you for reading > > Felix > > >> Hey Sam, >> >> thank you for your answer. Is your suggested [1] really useful for the >> RFNoC Radio Blocks I am using? I think I only can use the commands from >> path/include/ettus/rfnoc_radio.h, because the RFNoC_Radio Blocks are not >> derived from usrp_block. (As far as I know) >> >> I then tried the timed commands and modified them a little because I >> have >> to use two rfnoc_radio_blocks, one for each dboard which I sadly can not >> tune together. My thoughtprocess is, to tune the daugtherbaords in the >> initiantion process, before they lock in the wrong phase. Here is the >> code >> I modified (With sender_A and sender_B beeing my two RFNoC Radio Blocks >> which each represent one daugtherboard from the same USRP): >> >> # Radio B >> self.sender_B = ettus.rfnoc_radio( >> self.device3, >> uhd.stream_args( # Tx Stream Args >> cpu_format="fc32", >> otw_format="sc16", >> args='(cpu="fc32", otw="sc16")', >> ), >> uhd.stream_args( # Rx Stream Args >> cpu_format="fc32", >> otw_format="sc16", >> args="", # empty >> ), >> 1, -1 >> ) >> #Ende Radio B >> # Radio A >> self.sender_A = ettus.rfnoc_radio( >> self.device3, >> uhd.stream_args( # Tx Stream Args >> cpu_format="fc32", >> otw_format="sc16", >> args='(cpu="fc32", otw="sc16")', >> ), >> uhd.stream_args( # Rx Stream Args >> cpu_format="fc32", >> otw_format="sc16", >> args="", # empty >> ), >> 0, -1 >> ) >> # Ende Radio A >> >> # Timed Stuff >> #------------------------------------------------------------------ >> last_pps_time = self.sender_A.get_time_last_pps() >> while last_pps_time == self.sender_A.get_time_last_pps(): >> print("waiting...") >> self.sender_A.set_time_next_pps(uhd.time_spec_t(0.0)) >> self.sender_B.set_time_next_pps(uhd.time_spec_t(0.0)) >> #time.sleep(1) >> >> self.cmd_time = self.sender_A.get_time_now() + >> uhd.time_spec_t(0.1) >> self.sender_A.set_command_time(self.cmd_time,0) >> self.sender_B.set_command_time(self.cmd_time,0) >> #------------------------------------------------------------------ >> >> self.sender_A.set_rate(usrp_rate) >> for i in xrange(1): >> self.sender_A.set_tx_freq(c_freq, i) >> self.sender_B.set_tx_freq(c_freq, i) >> self.sender_A.set_tx_gain(0, i) >> self.sender_A.set_tx_dc_offset(True, i) >> >> self.sender_A.set_tx_antenna("TX/RX", 0) >> >> self.sender_A.set_clock_source("internal") >> >> >> self.sender_B.set_rate(usrp_rate) >> for i in xrange(1): >> #self.sender_B.set_tx_freq(c_freq, i) >> self.sender_B.set_tx_gain(0, i) >> self.sender_B.set_tx_dc_offset(True, i) >> >> self.sender_B.set_tx_antenna("TX/RX", 0) >> >> self.sender_B.set_clock_source("internal") >> #---------------------------------- >> self.sender_A.clear_command_time(0) >> self.sender_B.clear_command_time(0) >> #---------------------------------- >> # Ende Timed Stuff >> >> The edited Code does not throw errors but doesn't solve my problem >> either >> because with each new start of the flowgraph, there is still a different >> phase offset. Do I maybe missed instructions in the Initiation process, >> that have to be timed also to achieve phase sync? Or maybe its something >> about the DUC Blocks? >> >> I think the code is not all wrong, because when I use it in my >> set_c_freq >> method below for my qtrange_slider the phase seems to be constant with >> each retune. Just still not with each restart of the flowgraph sadly. >> >> def set_c_freq(self, c_freq): >> last_pps_time = self.sender_A.get_time_last_pps() >> while last_pps_time == self.sender_A.get_time_last_pps(): >> print("waiting...") >> self.sender_A.set_time_next_pps(uhd.time_spec_t(0.0)) >> self.sender_B.set_time_next_pps(uhd.time_spec_t(0.0)) >> self.cmd_time = self.sender_A.get_time_now() + >> uhd.time_spec_t(0.1) >> self.sender_A.set_command_time(self.cmd_time,0) >> self.sender_B.set_command_time(self.cmd_time,0) >> #tc start >> self.c_freq = c_freq >> for i in xrange(1): >> self.sender_B.set_tx_freq(self.c_freq, i) >> for i in xrange(1): >> self.sender_A.set_tx_freq(self.c_freq, i) >> #tc ende >> self.sender_A.clear_command_time(0) >> self.sender_B.clear_command_time(0) >> >> >> I also read your suggested reading [2] and am not sure if I have to >> follow >> the commands under Synchronizing Channel Phase. Reason for this, is >> because the rfnoc_radio.h controller does not support the >> issue_stream_command method (it is not listed in controller class >> rfnoc_radio.h). Changing to one single cosine did not solve my problem >> btw. >> >> Another thing that bothers me is, that the article talks about >> synchronising multiple device whereas in my case I only want to sync my >> two daugtherboards of the x310. Is it still the same process? (When I >> use >> the UHD_USRP_SINK Block with two inputs, the phase seems to be constant >> with each restart even without tuning them with timed commands. This >> behauviour is the goal; only that I want to use RFnoC instead) >> >> Thank you for your help and best regards, >> >> Felix >> >> >>> Hey Felix, >>> >>> Your hunch is correct -- you'll need to use timed commands to issue >>> your >>> tune requests and to initiate streaming. This will involve editing the >>> python script generated by GRC. Here's a relevant GRC manual section >>> [1], >>> and an example snippet of tuning with timed commands in the UHD Manual >>> [2]. >>> Doing this correctly should ensure that you are able to keep a >>> consistent >>> phase offset between your TX channels at a given frequency. >>> >>> I'm not sure if it'd actually be an issue, but one thing from your >>> flowgraph struck me. You might want to fork the output of your cosine >>> block >>> so that both TX streams are being fed data from a single source. I >>> don't >>> think this will solve your problem, but if the blocks are doing the >>> same >>> thing, may help take a variable out of the equation. >>> >>> Sam >>> >>> [1] >>> https://www.gnuradio.org/doc/doxygen/classgr_1_1uhd_1_1usrp__block.html >>> [2] https://files.ettus.com/manual/page_sync.html#sync_phase_lo >>> >>> >>> On Thu, Aug 29, 2019 at 8:49 AM Felix Greiwe via USRP-users < >>> usrp-users@lists.ettus.com> wrote: >>> >>>> Hello together, >>>> >>>> I am trying to transmit one complex cosine from both TX - Antenna of >>>> my >>>> USRP-x310 with two UBX-160 Daugtherboards. I am transmitting a cosine >>>> with >>>> the frequency of 100 kHz and the center frequency of my RFNoC Radio >>>> Blocks >>>> is 2.45 GHz. So basically I see a peak at 2.45 Ghz + 100 kHz at my >>>> spectrum analyzer (plus the lo leakage at 2.45 GHz). Additionally I >>>> receive the spectrum on another x310. >>>> >>>> In the following link you can see my flowgraph in GRC: >>>> https://ibb.co/7W6mTKf >>>> >>>> As you can see i have two multiply blocks to change the phase of the >>>> complex cosines, the value of the multiply blocks are >>>> >>>> > pow(math.e, 1j*phi*(math.pi/180)) and >>>> > pow(math.e, 1j*psi*(math.pi/180)). >>>> >>>> I can change phi and psi with a qt gui range slider. Default value ist >>>> multiplication by 1. >>>> >>>> My goal with this setup was to check the MIMO capabilities of the USRP >>>> x310. >>>> I calculated the Phase offset both transmitted waves should have at >>>> the >>>> antenna of my spectrum analyzer. With my multiplication blocks I >>>> created >>>> different phase offsets, thus causing destructive interference at the >>>> receiving end (peak at analyzer is the smallest at this phase). >>>> >>>> However most of the time when I start different runs of my flowgraph >>>> (or >>>> when I power cycle the device) I always have to set a different phase >>>> offset to see the destructive interference. To me it seems pretty >>>> random >>>> which phase offset both transmitting path get even though I don't >>>> understand why. >>>> >>>> In another thread I read that maybe timed tuning will work for me but >>>> I >>>> did not quite understand what that improves in particular nor who I >>>> use >>>> it >>>> in my GRC generated python file. (Using the RFnoC Radio Blocks does >>>> not >>>> make it easier by the way.) This is the link: >>>> >>>> >>>> http://ettus.80997.x6.nabble.com/USRP-users-use-a-usrp-x310-as-MIMO-transmitter-daughterboard-synchronization-tt11642.html >>>> >>>> Any ideas, suggestions and explanations on how to phase align the >>>> transmit >>>> path of my (single) USRP x310 would be greatly appreciated! >>>> >>>> Best regards >>>> >>>> Felix >>>> >>>> >>>> >>>> _______________________________________________ >>>> USRP-users mailing list >>>> USRP-users@lists.ettus.com >>>> http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com >>>> >>> >> >> >> >> _______________________________________________ >> USRP-users mailing list >> USRP-users@lists.ettus.com >> http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com >> > > > > _______________________________________________ > USRP-users mailing list > USRP-users@lists.ettus.com > http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com > _______________________________________________ USRP-users mailing list USRP-users@lists.ettus.com http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com