Decoding ERMINAZ

ERMINAZ-1U and ERMINAZ-1V are upcoming 1P PocketQubes by AMSAT-DL that will be launched in Rocket Factory Augsburg first flight from SaxaVord (Shetland, UK) later this year, together with other PocketQubes from AMSAT-EA and Libre Space Foundation. The ERMINAZ-1 satellites are based on the Libre Space QUBIK design and use the same communications system. Recently I have added a decoder for the ERMINAZ-1 satellites to gr-satellites and tested it using some pre-flight recordings that the team has shared with me.

The QUBIK communications stack uses something know as OSDLP (Open Space Data Link Protocol), which was developed by Libre Space based on CCSDS. Unfortunately, there is not much documentation about OSDLP. The best I’ve found are these slides, which only speak about the Data Link and higher layers. A look at the QUBIK transceiver GNU Radio flowgraph that AMSAT-DL is using with these satellites, together with some gr-satnogs blocks used in the flowgraph has been quite useful to figure out how the Synchronization and Coding layer of QUBIK works. In the rest of this post I will document my findings.

Decoding the LTE-M SIB-BR

LTE-M is a family of several configurations supported by LTE for machine-to-machine and IoT communications. In this post I will talk specifically about BL/CE (bandwidth reduced low complexity / coverage enhancement), which is also known as LTE Cat M1. The main difference between a BL/CE UE and a regular LTE UE is that a BL/CE UE only supports a bandwidth of 1.4 MHz (in practice, 6 resource blocks, or 1.08 MHz) and can be half-duplex. These limitations reduce the cost, size and power of the UE, but require additional techniques to handle them.

If we think about the downlink, there are several signals that occupy the whole cell bandwidth, which is usually larger than 1.4 MHz. These are the PDCCH (physical downlink shared channel), the PCFICH (physical control format indicator channel) and the PHICH (physical hybrid-ARQ indicator channel). A BL/CE UE cannot receive any of these, so alternative signals must be used to provide similar functionality. Additionally, a BL/CE UE needs guard intervals in the time domain to support retuning of the 1.4 MHz slice in which the UE operates, and transmit/receive switching for half-duplex UEs. Another distinguishing feature of BL/CE is that messages are often repeated multiple times in order to support working with worse signal conditions than what is possible with a regular UE.

In LTE, the PSS and SSS (primary synchronization signal and secondary synchronization signal), as well as the PBCH (physical broadcast channel) occupy the central 6 resource blocks, so a BL/CE UE can synchronize to the cell and decode the MIB transmitted in the PBCH. The next step that a regular UE would perform is to monitor the PDCCH, first to find a SIB1 transmission (which is transmitted in the PDSCH), and then the rest of the SIBs (whose transmission schedule is listed in the SIB1). A BL/CE UE cannot do this, because it cannot receive the PDCCH and because the SIB PDSCH transmissions might be wider than 6 resource blocks. Therefore, in a cell that supports BL/CE UEs there are also SIB-BRs (BR stands for bandwidth reduced), which BL/CE UEs use instead of the regular SIBs. The SIB-BRs occupy 6 resource blocks and do not require receiving the PDCCH to be decoded. In this post I will use my recording of an LTE eNB to show how to decode the SIB-BRs, and other important aspects of BL/CE UEs.

Categorised as Software Tagged


I have implemented an FPGA DDC (digital downconverter) in Maia SDR. Intuitively speaking, a DDC is used to select a slice of the input spectrum. It works by using an NCO and mixer to move to the centre of the slice to baseband, and then applying low-pass filtering and decimation to reduce the sample rate as desired (according to the bandwidth of the slice that is selected).

At the moment, the output of the Maia SDR DDC can be used as input for the waterfall display (which uses a spectrometer that runs in the FPGA) and the IQ recorder. Using the DDC allows reaching sample rates below 2083.333 ksps, which is the minimum sample rate that can be used with the AD936x RFIC in the ADALM Pluto (at least according to the ad9361 Linux kernel module). Therefore, the DDC is useful to monitor or record narrowband signals. For instance, using a sample rate of 48 ksps, the 400 MiB RAM buffer used by the IQ recorder can be used to make a recording as long as 36 minutes in 16-bit integer mode, or 48 minutes in 12-bit integer mode. With such a sample rate, the 4096-point FFT used in the waterfall has a resolution of 11.7 Hz.

In the future, the DDC will be used by receivers implemented on the FPGA, both for analogue voice signals (SSB, AM, FM), and for digital signals. Additionally, I also have plans to allow streaming the DDC IQ output over the network, so that Maia SDR can be used with an SDR application running on a host computer. It is possible to fit several DDCs in the Pluto FPGA, so this would allow tuning independently several receivers within the same window of 61.44 MHz of spectrum. In the rest of this post I describe some technical details of the DDC.

Analysing the srsRAN LTE MAC layer with Wireshark

In my previous posts I have been decoding LTE PDSCH (physical downlink shared channel) transmissions from an IQ recording of an eNB and looking at the MAC PDUs with Wireshark. The analysis I have done of the upper layer protocols is somewhat limited because I have decoded only 500 ms of traffic and because I don’t have the encryption keys, and also because I’m just beginning to learn how the LTE upper layers work. When doing this analysis I thought that it would be good to have a more complete example that I could use as a reference. A Google search for examples of PCAP files containing LTE MAC PDUs yields very little, so I thought I would make my own example with srsRAN. In this post I show how to set up an srsRAN LTE eNB and UE communicating over ZMQ on a single machine and then analyze the traffic in Wireshark.

Decoding LTE MIMO with a single antenna

In my previous post I decoded LTE PDSCH (physical downlink shared channel) transmissions from an IQ recording that I had made of an eNB recording using an USRP B205mini and a single antenna. The eNB has two antenna ports, and it uses TM4 (closed-loop spatial multiplexing) to transmit the PDSCH to each individual UE. In the post, I repeated several times that two-codeword TM4 is intended for 2×2 MIMO and relies on the receiver having at least 2 antennas in order to separate the two transmitted codewords, so I couldn’t decode these transmissions with my recording.

In this post I will show that in some cases this is not true, and these two-codeword TM4 transmissions can be decoded with just one receive antenna. I will decode some of these two-codeword transmissions from my IQ recording by using the ideas I introduce below.

LTE downlink: PDSCH

This post is a continuation of my series about LTE, where I decode a recording of the downlink signal of an eNB using Jupyter notebooks written from scratch. Here I will decode the PDSCH (physical downlink shared channel), which contains the data transmitted by the eNB to the UEs, including PDUs from the MAC layer, and some broadcast information, such as the SIB (system information block) and paging. At first I planned this post to be about decoding the SIB1. This is the first block of system information, and it is the next thing that a UE must decode after decoding the MIB (located in the PBCH) to find the configuration of the cell. The SIB1 is always transmitted periodically, and its contents and format are relatively well known a priori (as opposed to a user data transmission, which could happen at any time and contain almost anything), so it is a good example to try to decode PDSCH transmissions.

After writing and testing all the code to decode the SIB1, it was too tempting to decode everything else. Even though at first I wrote my code thinking only about the SIB1, with a few modifications I could decode all the PSDCH transmissions (except those using two-codeword spatial multiplexing, since my recording was done with a single antenna). I will still use the SIB1 as an example to show how to decode the PDSCH step by step, but I will also show the rest of the data.

The post is rather long, but we will get from IQ samples to looking at packets in Wireshark using only Python, so I think it’s worth its length.

A modern implementation of the Parks-McClellan FIR design algorithm

The Parks-McClellan FIR filter design algorithm is used to design optimal FIR filters according to a minimax criterion: it tries to find the FIR filter with a given number of coefficients whose frequency response minimizes the maximum weighted error with respect to a desired response over a finite set of closed sub-intervals of the frequency domain. It is based on the Remez exchange algorithm, which is an algorithm to find uniform approximations by polynomials using the equioscillation theorem. In signal processing, the Parks-McClellan algorithm is often call Remez. This algorithm is a very popular FIR design algorithm. Compared to the windowing method, which is another commonly used algorithm, it is able to obtain better filters (for instance, meeting design constraints with less coefficients), in part because it allows the designer to control the passband ripple and stopband attenuation independently by means of the weight function.

I have been laying some groundwork for Maia SDR, and for this I will need to run the Parks-McClellan algorithm in maia-httpd, the piece of software that runs in the Pluto ARM CPU. To evaluate what implementation of this algorithm to use, I have first gone to the implementations that I normally use: the SciPy remez function, and GNU Radio’s pm_remez function. I read these implementations, but I didn’t like them much.

The SciPy implementation is a direct C translation of the original Fortran implementation by McClellan, Parks and Rabiner from 1973. This C translation was probably written decades ago and never updated. The code is very hard to read. The GNU Radio implementation looks somewhat better. It is a C implementation that was extracted from Octave and dates from the 90s. The code is much easier to follow, but there are some comments saying “There appear to be some problems with the routine search. See comments therein [search for PAK:]. I haven’t looked closely at the rest of the code—it may also have some problems.” that have seemingly been left unattended.

Because of this and since I want to keep all the Maia SDR software under permissive open source licenses (the GNU Radio / Octave implementation is GPL), I decided to write from scratch an implementation of the Parks-McClellan algorithm in Rust. The result of this has been the pm-remez crate, which I have released recently. It uses modern coding style and is inspired by recent papers about how to improve the numerical robustness of the Parks-McClellan algorithm. Since I figured that this implementation would also be useful outside of Maia SDR, I have written Python bindings and published a pm-remez Python package. This has a few neat features that SciPy’s remez function doesn’t have. The Python documentation gives a walkthrough of these by showing how to design several types of filters that are commonly used. This documentation is the best place to see what pm-remez is capable of.

The rest of this post has some comments about the implementation and the things I’ve learned while working on this.

LTE Transmission Mode 4 (closed-loop spatial multiplexing)

This is a long overdue post. In 2022, I wrote a series of posts about LTE as I studied its physical layer to understand it better. In the last post, I decoded the PDCCH (physical downlink control channel), which contains control information about each PDSCH (physical downlink shared channel) transmission. I found that, in the recording that I was using, some PDSCH transmissions used Transmission Mode 4 (TM4), which stands for closed-loop spatial multiplexing. For an eNB with two antenna ports (which is what I recorded), this transmission mode sends either one or two codewords simultaneously over the two ports by using a precoding matrix that is chosen from a list that contains a few options. The choice is done by means of channel-state information from the UE (hence the “closed-loop” in the name).

In the post I found a transmission where only one codeword was transmitted. It used the precoding matrix \([1, i]^T/\sqrt{2}\). This basically means that a 90º phase offset is applied to the two antenna ports as they simultaneously transmit the same data. I mentioned that this was the reason why I obtained bad results when I tried to equalize this PDSCH transmission using transmit diversity in another previous post, and that in a future post I would show how to equalize this transmission correctly. I have realized that I never wrote this post, so now it is as good a time as any.

5G NR downlink reference signals

Last summer I looked at the demodulation of the 5G NR downlink, using a short recording of an idle srsRAN gNB made by Benjamin Menkuec. In that post I looked at the phase compensation, which is new in NR compared to LTE, the SS/PBCH block, and performed OFDM demodulation of all the signals in the recording. One of these signals was the PDSCH transmitting the SIB1 (which is done periodically even on an idle cell), and its corresponding PDCCH transmission. However, there were some reference signals that I wasn’t able to identify at the time. In this post I will look at these reference signals in detail, and also to the DM-RS (demodulation reference signal) in the PDCCH and PDSCH.

Categorised as Software Tagged

Decoding MOVE-II

MOVE-II is a cubesat from Technical University of Munich that was launched in December 2018. It transmits telemetry in the 145 MHz amateur satellite band using a protocol that uses CCSDS LDPC codewords. Back in the day, there was a GNU Radio out-of-tree module developed by the satellite team to decode this satellite. Given the additional effort required to support LDPC decoding for just this satellite and since there was already a GNU Radio decoder available, I never added a decoder for MOVE-II to gr-satellites.

Fast forward 5 years, and MOVE-II is still active, but apparently its GNU Radio out-of-tree module has bit rotten. The Gitlab repository where this was hosted (I believe it was a self-hosted Gitlab) has disappeared, and while it was originally developed for GNU Radio 3.7, it was never ported to newer GNU Radio versions. Some days ago, some amateurs including Scott Chapman K4KDR and Bob Mattaliano N6RFM started doing some experiments to try to get a decoder for MOVE-II working.

Seeing this, I decided to revisit the situation and try to add a decoder for MOVE-II to gr-satellites. Since this satellite was launched, I have been dealing with CCSDS LDPC for the Artemis Orion, made my own LDPC decoder, and participated in fixing the GNU Radio in-tree LDPC decoder. Therefore, most of the heavy lifting seemed to be already done.

I have now added an example decoder flowgraph for MOVE-II to gr-satellites. Here I describe the details of this example, and why it is only an example instead of a fully supported decoder as the ones that exist for other satellites.