In a previous post I showed how to demodulate the LTE physical uplink shared channel (PUSCH) by using a recording of my phone and some Python code. This is a continuation of that post. Here we will look at the physical uplink control channel (PUCCH) transmissions in that recording, and use a similar approach to demodulate them. All the work is done in a Jupyter notebook, which is linked at the end of the post.
The PUCCH carries control information from the UE to the eNodeB, such as scheduling requests, ACK/NACK for HARQ, and the CQI (channel quality indicator). A PUCCH transmission lasts for one subframe (1 ms) and typically occupies a single 12-subcarrier resource block in each of the two 0.5 ms slots in the subframe (there are more recently introduced PUCCH formats which use more subcarriers).
PUCCH transmissions are allocated to the edges of the uplink bandwidth, so as to leave the centre clear as a contiguous segment to be used for PUSCH. On its first slot, the PUCCH transmission uses some particular resource block. On its second slot it uses the symmetric resource block with respect to the centre frequency. This gives some frequency diversity to the transmissions.
The figure below shows a portion of the waterfall of the LTE uplink recording that we will be using (the link to the recording is included in the previous post). It corresponds to a 10MHz-wide cell in the B20 band. The PUCCH transmissions are the narrow bursts. The wider stronger bursts are PUSCH.
This illustrates that the PUCCH subframes are allocated to the edges of the cell, and how each subframe jumps to the symmetric resource block on its second slot.