Main Content

VITA 49 File Reader

This example shows how to read signal time data packets and the associated metadata (context packet data) from a VITA 49.2 format file into the MATLAB® workspace.

Introduction

A Versa Module Eurocard (VME) bus International Trade Association (VITA) 49.2 file consists of signal data streams and associated metadata in structured packet format, as defined in Amercian National Standards Institue (ANSI)/VITA-49.2 (2017). This example demonstrates how to extract context and signal time data packets from a VITA 49.2 file. The VITA Radio Transport (VRT) standard, also known as the VITA 49 protocol, defines a standard format for sending and receiving digitized messages between radio frequency (RF) systems and related equipment.

The VRT is a packet based protocol to convey digitized signal data and metadata (or context data) pertaining to different reference points within a radio receiver. The metadata includes radio front-end parameters, such as RF center frequency, bandwidth, intermediate frequency (IF), center frequency, sampling rate, gain, and location of the satellite.

Packet Formats

A packet in a VITA 49 file starts with a packet prologue consisting of a mandatory packet header followed by a list of fields as determined by the packet type present in the packet header. The packet header includes packet type, packet size and additional information fields interpreted based on packet type. These additional information fields indicate how to interpret the rest of the packet prologue and the packet contents. VITA 49 specification defines eight different packet formats. This example supports only signal time data (packet type 0 to 3) and context data (packet type 4 and 5) packet formats. The packet header is as shown in the following figure.

VITA49Header.PNG

This table shows the eight different packet formats along with the data information they carry.

VITA49PacketTypes.PNG

Signal Data Packet

Signal data packets convey digitized IF and RF signals. Signal data packet is further divided into signal time data packet or signal spectral data packet. Signal time data packet represents the signal in time-domain as a sequence of samples sampled at a constant rate. Signal spectral data is a sequence of samples describing the signal frequency or spatial-domain. This example decodes only signal time data packets.

Signal Time Data Packet

Signal time data packets convey digitized IF and RF signals. Signal time data packets encapsulates variable-sized blocks of in-phase quadrature (IQ) data, along with a 32-bit trailer to convey additional information about the state of the receiver at the time the samples were obtained. For example, if the system was being overdriven this would be reported by an indicator in the trailer.

Signal time data may be either real or complex samples and can also be magnitude or power representations of a signal for spectral data. This example only supports complex, cartesian data formats; complex, polar data formats are not supported. The signal data packets in VITA 49.2 are organized as signal data packet streams. A signal data packet stream is identified by a stream identifier (SID) and is a sequence of signal data packets of same signal data packet class. Signal data packet class specifies the type of signal data and the packet content structure. Multiple streams can be formed from the same class, each stream has its own unique SID. The signal data packet structure is as shown in the following figure.

VITA49SignalDataPacket.PNG

The integer timestamp field (ITF) is a 32-bit number which specifies the reference point time where the data sample is collected with a resolution of 1 second. It may be used to convey coordinated universal time (UTC), global positioning system (GPS) time, or some user-specified timecode.

The fractional timestamp field (FTF) is a 64-bit integer that represents the reference point time with a better resolution than ITF. FTFs are classified into three types: sample-count, real-time, and free-running count timestamps.

  • The sample-count and real-time timestamps are used to add resolution to the ITF, allowing it to cover a time span of years with precision of sample period or one picosecond.

  • The free-running count timestamp provides an incrementing sample count from starting time and is not related to the ITF.

Context Packet

Context packets convey the spatial information and the information of the receiver settings. The information is of variable size, depending on the number of fields used, out of a total of 25 fields. The fields used in a given packet are communicated by the 32-bit context indicator field which precedes the context fields.

Context packets are sent whenever there is a change in receiver settings or spatial information. These packets are typically transmitted at some periodic interval to ensure that a VITA 49.2 receiver can recover from any miscommunication or loss of communication. Such periodic updates typically involve retransmitting all fields required by the application. The context packet structure is as shown in the following figure.

VITA49ContextPacket.PNG

The bits in the context indicator field (CIF) indicates which of the optional context fields are present in the context packet corresponding to each field. The CIF definitions shown in the following figure.

VITA49ContextFieldIndicators.PNG

Only fields that are marked 'Yes' in the CIF definitions figure will be decoded in this example.

Read VITA 49 Packets

Use the vita49Reader object to read files containing VITA 49 formatted data. The object contains information about the VITA 49 file and enables you to read the upcoming signal or context packets from the file.

Specify the VITA 49 file and set the OutputTimestampFormat property to seconds or datetime in the vita49Reader object.

Configure a VITA 49 file reader object to read the VITA49SampleData.bin data file. The sample data file contains a total of 40 packets. The first packet 10 packets are context packets and the remaining packets are signal data packets.

fileName = "VITA49SampleData.bin";
outputTimestampFormat = "seconds";
vita49ReaderObj = vita49Reader(fileName,OutputTimestampFormat=outputTimestampFormat);

Read the next upcoming VITA 49 packet in the file by using read function on the VITA 49 file reader object. This next packet can be either signal data packet or context packet, depending on the value of the PacketType field in the packet structure.

firstPacket = read(vita49ReaderObj) % read next packet
firstPacket = struct with fields:
                     PacketType: 4
                       StreamID: 0
                        ClassID: "7C386C0000"
           IntegerTimestampType: "GPS"
          IntegerTimestampValue: 1625215654
        FractionalTimestampType: "real time"
       FractionalTimestampValue: 0
                       RawBytes: [84x1 uint8]
    ContextFieldChangeIndicator: 1
       ReferencePointIdentifier: [1x0 double]
                      Bandwidth: 15500025
           IFReferenceFrequency: 0
                    RFFrequency: 1.2100e+09
              RFFrequencyOffset: [1x0 double]
                   IFBandOffset: [1x0 double]
                 ReferenceLevel: -30
                           Gain: 36
                 OverRangeCount: [1x0 double]
                     SampleRate: 17222250
            TimestampAdjustment: [1x1 struct]
       TimestampCalibrationTime: [1x0 double]
         StateAndEventIndicator: [1x1 struct]
        SignalDataPayloadFormat: [1x1 struct]

nextPacket  = read(vita49ReaderObj); % read next packet

You can use the read function to read a certain number of packets by specifying NumPackets.

  • When you specify only NumPackets and do not specify PacketType, the function returns signal data packets and context packets separately.

  • When you specify NumPackets and PacketType, the function returns only the information of the specified packet type (signal data or context). The packet type values from 0 to 3 indicate a signal data packet, a packet type value of 4 and 5 indicates a context packet.

n = 39; % Number of packets required
vita49ReaderObj = vita49Reader(fileName);
[signalDataPackets,contextPackets]  = read(vita49ReaderObj,NumPackets=n);
anotherPacket = read(vita49ReaderObj)
anotherPacket = struct with fields:
                  PacketType: 1
                    StreamID: 0
                     ClassID: "7C386C0000"
                 PadBitCount: 0
        IntegerTimestampType: "GPS"
       IntegerTimestampValue: 1625215654
     FractionalTimestampType: "real time"
    FractionalTimestampValue: 901216160000
                    RawBytes: [1472x1 uint8]
                   IQSamples: [722x1 double]
                     Trailer: [1x1 struct]

Read Signal Data Packets

To read only signal data packets, set PacketType to signal data.

vita49ReaderObj = vita49Reader(fileName);
packetType = "signal data";
% Skips the context packets until signal data packet arrives
signalDataPacket = read(vita49ReaderObj,PacketType=packetType)
signalDataPacket = struct with fields:
                  PacketType: 1
                    StreamID: 0
                     ClassID: "7C386C0000"
                 PadBitCount: 0
        IntegerTimestampType: "GPS"
       IntegerTimestampValue: 1625215654
     FractionalTimestampType: "real time"
    FractionalTimestampValue: 900000344000
                    RawBytes: [1472x1 uint8]
                   IQSamples: [722x1 double]
                     Trailer: [1x1 struct]

Read Context Packets

To read only context packets from the VITA 49 formatted file into the MATLAB workspace, set PacketType to context.

vita49ReaderObj = vita49Reader(fileName);
% Seeks to the next context Packet 
packetType = "context";
contextPacket = read(vita49ReaderObj,PacketType=packetType)
contextPacket = struct with fields:
                     PacketType: 4
                       StreamID: 0
                        ClassID: "7C386C0000"
           IntegerTimestampType: "GPS"
          IntegerTimestampValue: 1625215654
        FractionalTimestampType: "real time"
       FractionalTimestampValue: 0
                       RawBytes: [84x1 uint8]
    ContextFieldChangeIndicator: 1
       ReferencePointIdentifier: [1x0 double]
                      Bandwidth: 15500025
           IFReferenceFrequency: 0
                    RFFrequency: 1.2100e+09
              RFFrequencyOffset: [1x0 double]
                   IFBandOffset: [1x0 double]
                 ReferenceLevel: -30
                           Gain: 36
                 OverRangeCount: [1x0 double]
                     SampleRate: 17222250
            TimestampAdjustment: [1x1 struct]
       TimestampCalibrationTime: [1x0 double]
         StateAndEventIndicator: [1x1 struct]
        SignalDataPayloadFormat: [1x1 struct]

Reading Data from RF Capture

The VITA49SineWaveData.bin data file contains IQ samples of sine wave data captured from RF.

Configure a VITA 49 file reader object to read the VITA49SineWaveData.bin data file. The sample data file consists of a total of nine packets. The first packet is context packet and the remaining are signal data packets.

fileName = "VITA49SineWaveData.bin";           % VITA 49 file with sine wave data
vita49ReaderObj = vita49Reader(fileName);
numPackets = 9;                                % First packet is context packet in the file
[dataPackets,~] = read(vita49ReaderObj,NumPackets=numPackets);
iqSamples = dataPackets(1).IQSamples;          % Plot first packet data
plot(real(iqSamples)); 
hold on;
plot(imag(iqSamples));
xlabel("Samples")
ylabel("Amplitude")
title("RF Data Capture")
legend(["In-Phase","Quadrature"])

Reset to First Packet

Reset the position of the VITA 49 file reader to the first packet of the VITA 49 file.

reset(vita49ReaderObj);
readFirstPacket = read(vita49ReaderObj);
clear vita49ReaderObj

References

[1] VITA 49 website: https://www.vita.com