Configuring Manual Streaming
1. Introduction
The purpose of this reference note is to provide additional information on how to configure the device to manually initialize streaming.
NOTE | |
---|---|
This reference is a work in progress. Contact us for more information. |
2. Transmit Streaming
Transmit streaming has a number of steps that are used to support flow control, some of which need to be set up first. The following attempts to document the process that is implemented in UHD when starting streaming.
2.1 Start clock sync in background (SFP port)
To stream at high rates you need to preemptively send packets so they arrive at Crimson when they will be needed instead of polling the buffer until there is space. Clock sync is done to figure out the latency from when you call libc’s send to when the packet is received by Crimson/Cyan.
2.2 Configure state tree
In the examples below, replace x with the channel(s) you want to use. These packets are sent over the management ethernet.
TODO: show get and set packets
TODO: add sample rate limit and nco_adj limit for ch C/D
State Tree | Note |
---|---|
time/source/ref | Normally set to “internal”, unless you are doing something synced to an external pps in which case use external |
time/source/ref | Normally set to “internal”, unless you are doing something synced to an external pps in which case use external |
tx/x/pwr | set to 1 to turn on channel |
tx/x/dsp | set to the sample rate you want in samples per second. You can check this value to see what the requested rate got rounded to. |
tx/x/rf/dac/nco | (optional) should virtually always be set to 0 |
tx/a/rf/freq/band | Crimson: 0 for low band, 1 for high band. Cyan: 0, 1, 2 for low, mid, high band respectively |
tx/a/rf/freq/val | The lo frequency (only used in mid/high band). The amount to shift the frequency down using analog lo in Hz. Must be a multiple of 5MHz for rtm10, 10MHz for rtm9 and 8, 25MHz for rtm 7 and earlier. You can querry this frequency to verify what the lo got set to. |
tx/a/dsp/nco_adj | the amount to shift the signal in the dsp in Hz. Positive shifts the frequency up, negative shifts it down |
tx/a/rf/gain/val | tx gain in dB |
tx/a/link/endian_swap | 0 to have the data be big endian, 1 to have the samples be little endian. Everything but the samples is big endian. Useful to use little endian samples since x86 is little endian so you can skip converting to big endian. |
tx/a/link/vita_en | enables responding to stream commands |
tx/a/dsp/rstreq | resets the dsp to clear any anomalies while configuring |
2.3 Poll Tx Buffer Level
Begin polling buffer level in the background (SFP ports). This is generally done after transitoning to steady state streaming to ensure rate matching with the radio.
TODO: include example packets
You should be polling the buffer level to figure out if the buffer level is above or below the target level and adjust when you send packets accordingly. Theoretically you can skip this step since clock sync should make sure packets are being sent at the correct time and Crimson/Cyan will wait until the timestamp on the packet in case of dropped packets. The packets containing the buffer level will also include underflow and overflow counts, but that feature is currently broken.
2.4 Set SDR time
Set time (management port)
State Tree | Note |
---|---|
time/clk/set_time | Normallyset the current time on the system in seconds. Usually I set it to 0 and then do everything relative to when it is set. |
2.5 Start Streaming
TODO: include example packet and diagram
The first packet should contain a flag indicating start of burst. Every packet should contain the time the packet should be consumed at. The time is in ticks. (On Crimson the tick rate is 162500000MHz, on Cyan it is 250MHz. i.e. to start at 10 seconds the time vita 49 fractional timestamp should be 1625000000MHz. Each packet can contain up to 2230 samples. When streaming we typically target having the buffer level at 70%. Crimson’s buffer can contain up to 65536 samples per channel. Buffers are channel independent. The number of samples Cyan can store is stored can be checked in the state tree by getting system/get_max_buffer_level from the server
2.6 Tx Stream Clean up
After ending transmission there are some clean up tasks that need to be completed.
Send end of burst command Same as data packets but has the end of burst flag set and contains 1 dummy sample on Crimson and 4 dummy samples on Cyan NOTE: if you want to stop streaming for a while then start again later you can send an end of burst, then when you want to send again reissue the start of burst
Clean up the state tree:
State Tree | Note |
---|---|
tx/a/pwr | Set to 0 to disable the channel. |
3.0 Example Transmission packet capture
A sample wireshark capture is included here in: tx_example_capture.pcapng.
This sample captures the SFP+ data packets from an example program of tx_waveforms:
./tx_waveforms --rate 10000000 --wave-freq 1000000 --freq 0 --first 5 --nsamps 1000000
NOTE: The samples in this capture are little endian, but everything else is big endian.
Within this capture, observe the following:
Packets 1 and 2 are a broadcast and reply looking for a Crimson (skip this step if you already know the IP)
Packets 3 and 4 are getting the serial number
Packet 675 is setting the tx rate, packet 676 is replying with the value is was actually set to.
Format of management packets: some_number,set/get,path(if set),value. They are sent to port 42799 Format of management reply packets: some_number(same as request being replied to),0,value. The reply for set packets isn’t useful other than checking when the server is done replying To see how they are formatted check fpga_xg_commands.ods in the fpga repo under docs. The relevant commands are time diff and tx fifo
Packets 682 and 682 are time diff requests and replies
Packets 1391 and 1392 are buffer level request and reply
Packet 1368 is the first data packet. Make is easier to interpret, open it in Wireshark and set it to decode as Vita 49
header: 0x021008b9
Bit 25: start of burst flag. Should be low in all but the first packet of a burst
Bit 24: end of burst flag (should be low in any packet containing non-dummy samples
Bit 21-20: fractional timestamp type. Bit 20 is always 1 and bit 21 always 0
Bit 16-19: 4 bit sequence number. Increment by 1 every packet, 0 for the first packet
Bit 0-15: Number of 32 bit words in the Vita 49 part of the packet. (1 for the vita header + 2 for the timestamp + 2330 for samples if using maximum samples per packet) fractional timestamp: 0x00000000306ee396 64 bit timestamp in ticks. In Crimson the tick rate is 162.5MHz, on Cyan it is 250MHz data: your samples in 16bit iq pairs. (Each half of the iq pair is 16 bit little endian)
Packet 22932 is the end of burst packet header: same as data packets, except bit 24 (end of burst flag) is high, and bits 21 and 20 are low since no timestamp is included timestamp: same as data packets data: dummy samples trailer: don’t know why a trailer is included here even though the has trailer flag is false. This might be required, might be a bug. There is no trailer in regular data packets