Wave Walker DSP

DSP Algorithms for RF Systems


Buy the Book!

DSP for Beginners: Simple Explanations for Complex Numbers! The second edition includes a new chapter on complex sinusoids.

Building a PSK and QAM Modulator in Python
June 8, 2022

Table of Contents


Taking an equation in a book and implementing it in hardware or software is hard. In this blog post I’ll show you how to interpret the equation for a PSK and QAM modulator and translate it into Python code.

Be sure to check out PySDR for another perspective on modulation!

More blog posts on DSP:


Single carrier modulators typically (but not always) involve the following operations:

  • Generating a data symbol or baud
  • Pulse shaping
  • Upconverting to pass-band

The next section describes common types of modulation schemes, or constellations, used for creating data symbols.


Binary Phase Shift Keying (BPSK) is one of the most fundamental modulation schemes for wireless communication. BPSK is characterized by two symbols, +1 and -1.

BPSK symbols in the complex plane, referred to as the BPSK constellation diagram.
BPSK symbols in the complex plane, referred to as the BPSK constellation diagram.

Where BPSK has two symbols, Quadrature Phase Shift Keying (QPSK) has four symbols. The symbols for QPSK are typically represented as

(1)   \begin{equation*}\frac{\sqrt{2}}{2}\left( 1 + j\right), \frac{\sqrt{2}}{2}\left( 1 - j\right), \frac{\sqrt{2}}{2}\left( -1 + j\right), \frac{\sqrt{2}}{2}\left( -1 - j\right).\end{equation*}

QPSK symbols in the complex plane, referred to as the QPSK constellation diagram.
QPSK symbols in the complex plane, referred to as the QPSK constellation diagram.

Phase Shift Keying (PSK) is a modulation whose symbols are only along the unit circle. An example is 8-PSK, represented by

(2)   \begin{equation*}e^{j2\pi m / 8}, ~ m = \{0, 1, 2, \dots, 7\}.\end{equation*}

The 8-PSK constellation diagram.
The 8-PSK constellation diagram.

BPSK can be considered 2-PSK and QPSK can be considered 4-PSK.

Quadrature Amplitude Modulation (QAM) is typically represents square or near-square modulations. An example is 16-QAM, whose real symbols are

(3)   \begin{equation*}-1, -1/3, 1/3, 1\end{equation*}


and whose imaginary symbols are

(4)   \begin{equation*}-j, -j/3, j/3, j.\end{equation*}

The 16-QAM constellation diagram.
The 16-QAM constellation diagram.

QPSK can be interpreted as 4-QAM. 

The modulations of BPSK, QPSK, PSK and QAM are all tightly related and only differ by the number of constellation points and their location in the complex plane.

Pulse Shaping

A pulse shape is applied to data symbols in order to be good spectral neighbor, meaning the power in the sidelobes of a transmission needs to be minimized such that other transmitters can exist in the adjacent spectrum.

You may have noticed that FM radio stations are not directly next to one another on the dial, this is because guard bands are needed to minimize the adjacent channel interference. 

An example of a pulse shape is the square-root raised cosine filter.


Upconversion, or frequency-mixing, is the process of translating a baseband signal up to a passband frequency. Upconversion is accomplished by multiplying the pulse shaped symbols by a complex exponential.

Textbook Equation

The following analysis uses QAM as the example signal. However, since BPSK, QPSK, PSK and QAM are all closely related the analysis will also apply to these modulations.

Proakis uses the following equation for QAM [proakis2001, p.174]:

(5)   \begin{equation*}s_{m}(t) = \text{RE}\left\{ (A_{mc} + j A_{ms}) g(t) e^{j2\pi f_{c}t} \right\}.\end{equation*}

Let’s break down (5):

  • s_{m}(t) is the result of modulating symbol m at time t
  • the real symbols are A_{mc}
  • the imaginary symbols are j A_{ms}
  • the pulse shape is g(t)
  • the upconversion is e^{j2\pi f_{c} t
  • the real component is taken through RE{ }

The next section will simplify the equation so it is easier to understand and translate into software.

Simplifying the Textbook Equation

Where (5) performs the upconversion to real pass-band, we will use a simplified representation by staying at complex baseband. This is accomplished by removing the upconversion step through setting f_c = 0 and removing the real operator RE{ },

(6)   \begin{equation*}  s_{bb,m}(t) = (A_{mc} + j A_{ms}) g(t) \end{equation*}

where s_{bb,m}(t) is the complex baseband signal for symbol m. Further simplify by substituting

(7)   \begin{equation*}A_{m} = A_{mc} + j A_{ms}\end{equation*}

where A_{m} is the complex symbol to be modulated. The baseband signal is now written as

(8)   \begin{equation*}s_{bb,m}(t) = A_m g(t).\end{equation*}

Since the signal is being generated digitally (8) needs to be sampled. The signal is sampled by substituting

(9)   \begin{equation*} t = n T_s, \end{equation*}

where T_s is the sampling period, resulting in

(10)   \begin{equation*}\begin{split}s_{bb,m}[n] & = s_{bb}(n T_s)\\& = A_{m} g(n T_s) \\& = A_{m} g[n].\end{split}\end{equation*}

Equation (10) shows the m^{th} complex symbol A_m being pulse shaped by g[n]. One modification (and a deviation from (5)) is the incorporation of a time delay such that the m+1 symbol occurs later in time than the m symbol,

(11)   \begin{equation*}s_{bb,m}[n] =A_{m} g[n-mN]\end{equation*}

where N is the symbol period in samples. Equation (10) is rewritten as a summation over all symbols,

(12)   \begin{equation*}  s_{bb}[n] = \sum_{m} A_{m} g[n-mN]. \end{equation*}

Analyzing the Modulation Equation

Let’s define g[n] to make analysis of (12) easier to understand.

A simple (but impractical) pulse shape filter is the rectangular pulse shape, sometimes referred to as the boxcar window. The rectangular pulse shape uses all 1’s for N samples. This example rectangular pulse shape is chose to be of length N = 4. The pulse shaping filter can then be written as

(13)   \begin{equation*}g[n] =\begin{cases}1, & 0 \le n \le 3 \\0, & \text{otherwise}.\end{cases}\end{equation*}

Example samples of the modulated signal (12) can then be written as

(14)   \begin{equation*}A_{0}, A_{0}, A_{0}, A_{0}, A_{1}, A_{1}, A_{1}, A_{1}, A_{2}, A_{2}, A_{2}, A_{2}, \dots ~.\end{equation*}

BPSK uses symbols of +1 and -1 and therefore an example of (14) could be written as

(15)   \begin{equation*}1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, \dots ~.\end{equation*}

PSK and QAM Modulator Python Code

The modulator code in Python has to generate the sequence (14). There are many ways to do this in Python, including some that are more efficient, but this an illustrative example.

Import NumPy:

import numpy as np

Create the QPSK symbol map:

QPSKMapper = (np.sqrt(2) / 2) * np.array([1+1j, 11j, –1+1j, –11j])

Randomly generate some QPSK symbols:

ns = 16
mapIndex = np.random.randint(0, len(QPSKMapper), ns) 
QPSKSymbols = QPSKMapper[mapIndex]

Define the samples per symbol, which is also the pulse shaping filter length:

SPS = 4

Upsample the symbols:

QPSKSymbolsUpsampled = np.zeros(ns*SPS,dtype=complex)
QPSKSymbolsUpsampled[::SPS] = QPSKSymbols

Define the pulse shaping filter:

pulseShape = np.ones(SPS)

Apply the pulse shaping filter:

QPSKSignal = np.convolve(QPSKSymbolsUpsampled,pulseShape)

The signal is now QPSK modulated!  Other modulations such as PSK and QAM can be used by changing the QPSKMapper variable to include the desired constellation points.

An example of QPSK modulation in Python
An example of QPSK modulation in Python


This blog post started with a continuous-time equation for QAM and then simplified it into a discrete-time complex baseband signal. The equation was analyzed and simplified, and then used to create Python code for modulating QPSK, PSK and QAM signals.

More blog posts on DSP:

2 Responses

  1. Hi Matt.
    I saw your excellent website. Congratulations! One question: what is your complete process of rendering the image from production to web display? I am asking this question because your png images look crisper than most other png images on the web (they fade in quality for high resolution display). Thanks.

    1. Thank you!

      I generate them using Matplotlib within Python and save them as .png files using the savefig() call. I upload the raw .png files which are then compressed automatically using the EWWW image optimizer plugin.

      Hope this helps!

Leave a Reply

God, the Lord, is my strength; He makes my feet like the deer's; He makes me tread on my high places. Habakkuk 3:19
For everything there is a season, and a time for every matter under heaven. A time to cast away stones, and a time to gather stones together. A time to embrace, and a time to refrain from embracing. Ecclesiastes 3:1,5
The earth was without form and void, and darkness was over the face of the deep. And the Spirit of God was hovering over the face of the waters. Genesis 1:2
Behold, I am toward God as you are; I too was pinched off from a piece of clay. Job 33:6
Enter His gates with thanksgiving, and His courts with praise! Give thanks to Him; bless His name! Psalm 100:4
Lift up your hands to the holy place and bless the Lord! Psalm 134:2
Blessed is the man who trusts in the Lord, whose trust is the Lord. He is like a tree planted by water, that sends out its roots by the stream, and does not fear when heat comes, for its leaves remain green, and is not anxious in the year of drought, for it does not cease to bear fruit. Jeremiah 17:7-8
He said to him, “You shall love the Lord your God with all your heart and with all your soul and with all your mind. This is the great and first commandment. And a second is like it: You shall love your neighbor as yourself. On these two commandments depend all the Law and the Prophets.” Matthew 22:37-39
Then He said to me, “Prophesy over these bones, and say to them, O dry bones, hear the word of the Lord. Thus says the Lord God to these bones: Behold, I will cause breath to enter you, and you shall live." Ezekiel 37:4-5
Riches do not profit in the day of wrath, but righteousness delivers from death. Proverbs 11:4
The angel of the Lord appeared to him in a flame of fire out of the midst of a bush. He looked, and behold, the bush was burning, yet it was not consumed. And Moses said, “I will turn aside to see this great sight, why the bush is not burned.” When the Lord saw that he turned aside to see, God called to him out of the bush, “Moses, Moses!” And he said, “Here I am.” Exodus 3:2-3
Daniel answered and said: “Blessed be the name of God forever and ever, to whom belong wisdom and might. He changes times and seasons; He removes kings and sets up kings; He gives wisdom to the wise and knowledge to those who have understanding." Daniel 2:20-21
Now the Lord is the Spirit, and where the Spirit of the Lord is, there is freedom. 2 Corinthians 3:17
Previous slide
Next slide

This website participates in the Amazon Associates program. As an Amazon Associate I earn from qualifying purchases.

© 2021-2024 Wave Walker DSP