sdrangel icon indicating copy to clipboard operation
sdrangel copied to clipboard

Disabling/re-enabling transmit for digital packet-based modulators

Open srcejon opened this issue 4 years ago • 15 comments

Hi Edouard,

The packet modulator and other future digital modulators that transmit packets rather than continuously, should typically disable the transmitter between packets (Assuming there isn't another modulator active, or perhaps not if the modulator's frequency offset is large enough that any carrier leakage is on a different channel).

What would you recommend the best way to do this would be? When enabling the transmitter, timing needs to be pretty reliable such that the modulator doesn't start trying to output the packet before the transmitter is ready.

Thanks, Jon

srcejon avatar Sep 24 '20 20:09 srcejon

The Tx chain is not designed for the channels to take action on the transmitting device. It just generates samples. A SDR transmitting device is essentially a DAC so if you send zero samples you do not output any RF.

Now if you want to design a more complex system like a digipeater combining Rx and Tx I think this should be implemented using the soon to come feature plugin framework and drive both Rx and Tx.

Driving a PA would be done in the same manner.

f4exb avatar Sep 24 '20 20:09 f4exb

A SDR transmitting device is essentially a DAC so if you send zero samples you do not output any RF.

This unfortunately isn't true for many RFICs. E.g. the AD9361 and Lime transceivers both have TX LO leakage specs of -50dBc. So if the transmitter is set to output at 0dBm, you can still see the carrier at -50dBm when the DACs are driven to 0.

Even if you reduce the gain to the minimum value, the leaked carrier (For the AD93xx) is still at -100dBm, so can block the channel.

Now if you want to design a more complex system like a digipeater combining Rx and Tx I think this should be implemented using the soon to come feature plugin framework and drive both Rx and Tx.

Sounds good! However, at the moment, it's not that complex, it's really just trying to disable the transmitter when there's nothing to transmit, so that the channel isn't blocked.

srcejon avatar Sep 24 '20 22:09 srcejon

Stopping the device using its API (of some sort) is not a guarantee that there will be no RF leak either. I have to check again this but I think that the HackRF has a residual carrier on the frequency it was last set even if you stop it. In fact cutting the RF power completely when enough consecutive null samples are received should be implemented at hardware level. Unfortunately it does not seem to be so. I don't know if some sophisticated hardware like Hermes do this. Maybe...

This could be implemented in software on the host side (thus in the device plugin) although it may not work in all cases and not be easy or practical to implement. This is the only possibility I see because nothing prevents you to have a mix of channels producing the final I/Q baseband that is sent to the device (although multiple channels in transmission have a performance hit due to the mixing so may not be practical in all cases). This makes a sort of I/Q "vox" at device level the only possibility and in fact this is practical only if the hardware device API has the provision to mute the RF without going through a close/open cycle. Maybe this could be investigated with each of the supported hardware.

In fact the leakage at the SDR level is not an issue as long as you do not use your SDR output to drive a higher power PA. Then it becomes an issue and potential annoyance to other users of the spectrum. But to drive a PA we fall in the second consideration that in this case some external process should take the control (via API or Feature plugin).

If you want to "play" in the shack without the annoyance of the remaining carrier you can always shift the center frequency of the channel. This is what I did to try the Packet plugin with the HackRF.

f4exb avatar Sep 25 '20 13:09 f4exb

If a switch off action is not available in the hardware API another possibility is to shift the LO away enough to fall outside the bandwidth of the filter that you may (should) put at the output port.

f4exb avatar Sep 25 '20 13:09 f4exb

Stopping the device using its API (of some sort) is not a guarantee that there will be no RF leak either. I have to check again this but I think that the HackRF has a residual carrier on the frequency it was last set even if you stop it.

I don't have a HackRF to try, but it looks like you call hackrf_stop_tx(), so if this is the case, it seems like a driver or h/w issue to me. Every transceiver should be able to turn the transmitter off.

This is the only possibility I see because nothing prevents you to have a mix of channels producing the final I/Q baseband that is sent to the device

Yep, I agree. To handle this, I was thinking that perhaps each channel would be able to indicate if it is inactive and then the device would only disable the transmitter if all channels are inactive, or something along those lines.

In fact the leakage at the SDR level is not an issue as long as you do not use your SDR output to drive a higher power PA.

I think that depends on the relative location of any transmitters and receivers. I was planning to have a look at adding support for some short range protocols next, where I think it would be a problem (given that the Lime and AD93xx parts are outputting at ~-50dBm, and the received signals can be well below this).

If a switch off action is not available in the hardware API another possibility is to shift the LO away enough to fall outside the bandwidth of the filter that you may (should) put at the output port.

While that could work in some circumstances, I don't think it would for something like the 802.* standards where the channels are spaced over ~80MHz at 2.4GHz, as you couldn't have a large enough offset.

But to drive a PA ... via API or Feature plugin

Yep, I'm not necessarily looking for a quick fix. But I think it would be very useful if you could consider this as you plan your future API. Thanks.

srcejon avatar Sep 25 '20 14:09 srcejon

Replying to myself...

The Tx chain is not designed for the channels to take action on the transmitting device

In fact this should be possible since channels have access to the DeviceAPI. All channels get the DeviceAPI pointer passed at construction time and they would normally store it in m_deviceAPI.

Then it takes just a chain of calls to access to the DeviceSampleSink interface: DeviceAPI::getDeviceSinkEngine()->getSink() returns a pointer to the DeviceSampleSink interface. The DeviceSampleSink interface is implemented by all "sink" devices (i.e. transmitters) and expose a start and stop method. So indeed this should be possible to stop and start a device from a channel. In general this is not desirable because it would cut the streaming for all channels present in the baseband. However for a single channel this could make sense. Then maybe it should be mentioned in the plugin description that it has control over the device and may misbehave in the presence of other plugins.

Having said that I haven't tried it and have no idea of the turnaround times or possible side effects.

f4exb avatar Apr 24 '21 03:04 f4exb

This is not working because if Tx is stopped then no samples are pulled anymore and there is no way to start the Tx again. Unless the hardware has the provision to shut down the RF while still running its incoming stream this feature cannot be implemented.

f4exb avatar Apr 24 '21 06:04 f4exb

A new interface could be provided and not implemented by default that enables/disables RF without stopping the Tx. For example libhackrf gives access to the MAX2837 RF device registers so maybe enabling/disabling RF is possible. I think one can enable or disable the Tx mixer which would I suppose cut the RF. I also expect that this way the switchover would be extremely fast.

f4exb avatar Apr 24 '21 06:04 f4exb

I think I opened this issue before you implemented MainCore.h and I implemented ChannelWebAPIUtils::run and stop via the web API - which I think should do roughly what I wanted - but I will double check, as it has been a while since I thought about it.

Without having looked at it, I guess a question would be, are all of the samples in the FIFOs flushed out before TX is stopped, or does it stop immediately? If the former, then I think it should be fine.

srcejon avatar Apr 24 '21 06:04 srcejon

Evenn If you go through API you still have the issue of stopping the thread. The point is that the Tx thead cannot be stopped. I ve made some experiments with the HackRF and what seems to work to stop the RF output is driving the mixer bias down to 0 with:

rc = (hackrf_error) hackrf_rffc5071_write(dev, 11, on ? 0x4800 : 0);

However this cannot be driven from the (Packet mod) plugin directly since there is a delay between the samples produced and the samples played due to the length of the FIFO.

f4exb avatar Apr 24 '21 14:04 f4exb

The point is that the Tx thead cannot be stopped.

Why's that a problem if the stop/start is done from the main thread? (I'm assuming there aren't any other channels active in this scenario). E.g. when all samples have been written, ModSource class sends a "finished" message back the main Mod class saying the packet has been transmitted, then that Mod class makes the call to stop generation? The tx thread isn't presumably needed until another event such as the user pressing the TX button in the GUI, or a WebAPI call says transmit - in which case the main Mod class makes the call the start generation and the tx thread is restarted? If a little bit of time is required for transmitter ramp up, the ModSource can output 0 for a user-defined period.

srcejon avatar Apr 24 '21 14:04 srcejon

I'm assuming there aren't any other channels active in this scenario

Indeed! Let's make it simple and assume it is a limitation known to the user. Mixing Tx channels can be considered an advanced usage and therefore at this point suppose people know what they are doing.

Why's that a problem if the stop/start is done from the main thread?

Yes this would work but (at least in the present state) the packet repetition in "loop" mode is handled in PacketModSource. If Tx on/off is handled at the upper level via message passing this could work. However this does not overcome the fact that samples generation and actual transmission are separated by a FIFO of certain length so the delay issue which is the most problematic remains. The only advantage of startng/stopping the thread vs direct RF output device control is that it is not guaranteed that it would work for any device and each device has its own way of doing it.

Also stopping/starting the thread plus message passing and processing has a certain turnaround time that may be OK for Packet but too long for faster modes.

f4exb avatar Apr 24 '21 17:04 f4exb

Yep.

Something else similar to think about is TX to RX turnaround time. At some point, I may get around to implementing an 802.15.4 demod to go with the mod. If we wanted to be able to receive ACKs for transmitted frames, we need to be able to switch from TX to RX within 12 symbols (<200us). Even if we just need to switch the state of the TX/RX switch to the antenna - I suspect that might be pretty hard with USB latency in the way.

srcejon avatar Apr 24 '21 19:04 srcejon

I've experimented with the HackRF at various sample rates to conclude that it is not possible to control the transmit window from software. The delay and its variation depending on the sample rate depends on parameters out of control. We could rely on heuristics but I think this would not be entirely reliable.

So in any case this should be done in hardware or not... It is only in the hardware that you could implement a sort of squelch that disables RF output stages when a certain number of consecutive incoming samples are null.

I have committed and pushed my changes on a feature-644 branch in case you want to play with it. It works at 2.4 MS/s, still at 3.2 MS/s but fails at 4.8 MS/s because the delay becomes too large. The law is not linear with regard to the sample rate.

f4exb avatar Apr 25 '21 06:04 f4exb

For 802.15.4 Rx/Tx I think the best option is to use a MIMO device so that Rx and Tx can run concurrently. Some devices like the BladeRF have the option to synchronize Tx and Rx samples so that even radar applications are possible. I am not sure this is implemented in the BladeRF2MIMO plugin but this may be possible. In any case I think the HackRF or split Rx/Tx between different devices is not suitable.

f4exb avatar Apr 25 '21 07:04 f4exb