RP2040: The Little Engine that Could

Sitting at the heart of the Ploopy Headphones preamplifier is a chip called “RP2040”. It’s the microcontroller, or MCU, recently made and released by the Raspberry Pi Foundation. It’s cheap, it’s available, and it punches way above its weight. This post will explain why we chose it for the Headphones preamp, as well as the key features that make it work for us.

First of all: what is an MCU?

An MCU is the central nervous system of any electronics board. It holds the firmware, or code, that controls the actions of other chips on the board. It’s very similar to the microprocessor powering the computer or mobile device you’re using to read this post, but MCUs are typically less capable than those processors.

MCUs come in many different varieties. Some of them are extremely simple and cheap; others are incredibly complex and expensive. The RP2040 sits on the lower end of this spectrum in terms of cost, but in terms of capability, it’s got a lot of horsepower.

In order to perform the function of EQ and tuning, the Ploopy Headphones preamplifier has to do a lot of math, and it has to compute it in real-time. There will be another post about the math itself, but it’s enough to know for now that the RP2040 spends the vast majority of its time multiplying and adding numbers together.

How many calculations? Almost ten million multiplications and additions per second.

That is very little for a CPU, but for an MCU that costs a little more than a dollar, it’s an extremely large number of calculations. Anything that can be done to speed up these calculations is critical to the performance of the preamplifier. More calculations means more EQ capability and finer tuning.

The key features of the RP2040 that I’m going to be going over are:

  • 250MHz
  • Programmable I/O
  • Direct memory access
  • Dual-core

Let’s start with the first one.

250MHz? What does that have to do with anything?

A simple way of stating the processing speed of an MCU is via its clock speed. Out of the box, the RP2040 operates at 125MHz, which means the internal clock ticks up and down 125 million times per second.

To give a bit of contrast, the MCU powering a Ploopy Classic Trackball has a clock speed of 8MHz. So, the RP2040 is quite fast.

It also has the handy capability of being “overclocked”. What that means is that the RP2040 is specifically programmed to run its clock twice as fast as it was designed to do. This means that the code on the chip executes twice as fast.

There are downsides to overclocking, and the topic is rather advanced, so I won’t delve into it too much here. The point is this: the chip runs very quickly. Very quickly, indeed. That means, lots of calculations per second.

What is programmable I/O, and what does it do for the Ploopy Headphones preamp?

To understand programmable I/O, we first have to take a step back and talk about something called “Inter-IC Sound”, more commonly called I2S (pronounced “eye-squared-ess”).

I2S is a method of taking an analog sound signal and converting it into a stream of ones and zeros, which are a digital representation of the analog sound. It’s the method used by computers to communicate to chips called audio codecs, which translate ones and zeros back into an analog audio signal that go into your headphones.

The reason why this is relevant is because typically, MCUs have to be designed in such a way that a piece of their silicon is devoted to implementing communication drivers, and that is what powers protocols such as I2S. The RP2040 is conspicuously missing this silicon. To put it more tersely: the RP2040 has no I2S driver.

But…wait. The RP2040 is absolutely capable of doing I2S. How’s that possible? How can you enter a drag race if you don’t have a car?

This is where programmable I/O, or PIO, comes in.

PIO is a unique feature of the RP2040. It’s essentially a small MCU within the RP2040. It can be programmed to perform input-output operations (or I/O), and I2S is one such I/O operation.

To put it briefly: the RP2040 has no dedicated I2S driver, but PIO allows us to program our own I2S driver.

And now, we finally arrive at the very relevant part: PIO executes independently of the MCU. What does that mean? It means that the MCU doesn’t have to pay any attention whatsoever to I2S: it essentially runs on its own, completely indepedently of the MCU.

This is a very good thing: the MCU has lots of calculations that it needs to do, so it’s a great benefit that the MCU doesn’t have to pay attention to I2S.

What’s all this about direct memory access?

We’ve already talked about PIO. It streams I2S data to and from audio codecs. There’s a tiny little problem, though: data needs to be shared between the PIO and the MCU.

We talked a little bit about how the PIO executes separately from the MCU. It’s great because it means the MCU doesn’t have to bother giving instructions to the PIO, but it also means that the data from the PIO doesn’t magically show up in the MCU. It has to be transferred from the PIO to the MCU.

That’s kind of annoying, isn’t it? The PIO is off and running a marathon on its own, and now it’s asking that we give it a cup of water every half-mile? Ridiculous.

Well, thankfully, there’s a solution to this. It’s called direct memory access, or DMA.

Just like PIO, the DMA is kind of like a small MCU within the RP2040. It has one purpose: it directly accesses data from anywhere within the RP2040, and moves it to another location anywhere within the RP2040. That’s all it does.

The DMA is blazing fast. It can read and write (simultaneously!) up to 32 bits of data in one clock cycle. That means that, at 250MHz, it can read and write up to one gigabyte per second. That is stupid fast.

In the Ploopy Headphones preamp, the DMA has just one job: move data between the PIO and the MCU. And it does exactly that, extremely quickly.

As a bonus, it operates independently of the MCU, just like PIO. It doesn’t require instructions from the MCU in order to run, so it leaves the MCU free to perform other tasks, such as the endless real-time math it has to perform.

What does “dual-core” mean?

We’ve discussed how data moves from the audio domain into the digital domain via PIO, and how that data is moved from the PIO peripheral into the MCU via DMA. At this point, the MCU is looking at a long stream of digital data, and it has to perform math on this stream. Lots of math.

Every processor or microcontroller has a section that we refer to as the “core”. The core is what performs the actual mathematical operations on numbers, like additions and multiplications. It also moves data around into memory banks, and sends instructions out to other peripherals. In short, if the MCU is the central nervous system of the electronics board, then the core is the brain.

When I mentioned those ten million(ish) multiplications and additions per second, it’s the core that does the actual math. Or, in this case, cores.

The RP2040 sports two (!) fully-independent feature-complete cores. They share the same memory space.

For the Ploopy headphones preamplifier, this means that when the data arrives in memory from the PIO via DMA, both cores can perform math on it at the exact same time.

Two brains, doing two sets of math at the same time. Two brains. It implies exactly what you’d think: the calculations get done in half the time. Twice as many calculations per second.

Now, two cores operating on the same piece of data at the same time leaves the code vulnerable to “race conditions”. The topic is out of scope for this discussion, but all you have to know is that the code is written in such a way that race conditions are handled. It’s a fascinating topic, though.

Conclusion

We’ve gone over quite a bit in this post, haven’t we? Clock speeds, programmable input-output, direct memory access, and multi-core functionality…it’s enough to make you old.

The bottom line is this: the Ploopy Headphones preamp has to do a lot of math. The RP2040 chip is not only cheap and easy to get, but it has the necessary horsepower to actually do the math.