Menu

andipanda.dev

CaRadio: From Early Carlinkit Experiments to Working CarPlay

In previous articles, I described how I built my own CaRadio head unit using a Raspberry Pi, tried to reuse the electronics from a Volkswagen RCD510, and eventually installed a working system in my Golf.

But so far, I've barely talked about the software side of the project.

After all, a Raspberry Pi, a display, and an amplifier alone don't make a fully functional multimedia head unit. I wanted CarPlay — preferably wireless, with navigation, music, and touchscreen controls.

Today, all of that works in my car. But getting there took much longer than I originally expected.

It All Started with Choosing a Head Unit

A few years ago, I was looking for a new head unit for my car. Among the available options, Teyes devices seemed particularly interesting.

They came in different configurations, some with Apple CarPlay support and others without it.

While researching them, I came across guides explaining how to add CarPlay support to certain Teyes models by installing an additional chip.

That's when I had an idea: if a similar solution could be used in an Android head unit, perhaps it could also be adapted for a Raspberry Pi.

I already had experience building my own car head unit, so using a Raspberry Pi instead of a ready-made device seemed like a natural approach.

I started looking for information about chips, connection methods, and software implementations of CarPlay.

But it quickly became clear that things were a little more complicated than simply connecting a single chip.

Discovering pycarplay

During my research, I came across the pycarplay project on GitHub.

It was a Python implementation that could communicate with USB CarPlay adapters.

At first, I didn't fully understand how everything worked. From the description, I could see that the project made it possible to run CarPlay on a Raspberry Pi, but additional hardware was required.

After gradually working through the documentation and searching for more information online, I learned that I needed a special USB dongle, similar to Carlinkit.

Now I just had to find one.

I found an inexpensive ex-display adapter on Allegro — a Carlinkit clone. It cost very little by the standards of the time, so I decided to give it a try.

Incidentally, that same adapter is still working in my head unit today.

After buying it, I connected it to my Raspberry Pi, installed the necessary software, and saw CarPlay running on my own device for the first time.

That was an important moment.

Until then, I had only assumed that it would be possible to build a system like this myself. Now I knew the idea was actually feasible.

CarPlay in a Browser

As far as I remember, the first implementation I managed to get running was related to the idea of using CarPlay in Tesla vehicles.

The Raspberry Pi acted as a small web server, and the CarPlay display could be opened in a browser.

For experimentation, this turned out to be a fairly convenient solution.

The system started, the phone connected, the image appeared, and overall everything worked reasonably well.

But I had a different goal.

I wasn't planning to use a browser as the main interface of my head unit. I wanted a standalone application that I could integrate into my own system and use directly on a touchscreen.

So I continued looking for other implementations.

From mpv to VLC

My next discovery was the carplay-receiver project.

It was also written in Python, but it used a different approach to displaying video. Instead of a browser, it displayed the CarPlay image through the mpv media player.

This was much closer to what I needed.

I started exploring the code and trying to run the project on my Raspberry Pi.

However, I ran into problems with mpv. It's difficult to remember all the details now, but I couldn't quickly get the results I wanted.

On the other hand, I already had experience working with VLC.

So I decided to modify the video output to use a player I was familiar with.

After several experiments, I finally managed to get CarPlay running.

Unfortunately, it was far from perfect.

As long as I was only running the system on my workbench, I could live with its shortcomings. But when I started considering using it in a car, it became obvious that performance left a lot to be desired.

The video lagged noticeably, and I couldn't quickly figure out what was causing the problem.

Trying to Move to C++

By that time, I already had experience developing applications in C++ using Qt.

So I came up with the idea of moving away from Python and porting the necessary functionality into my own application.

I thought this approach would give me more control over the system and help eliminate at least some of the performance problems.

But running an existing project is one thing. Understanding its internals well enough to rewrite it in another language is something entirely different.

I needed to understand how communication with the USB adapter worked, how video and audio were transmitted, and how touch input and other control commands were handled.

At the time, I didn't have enough knowledge or spare time to tackle all of that.

The attempt was unsuccessful.

As a result, I put CarPlay development for Raspberry Pi on hold. As it turned out, for almost two years.

Returning to the Project

Almost two years later, I decided to take another look at the available solutions. A lot had changed in the meantime, and I hoped that new projects had appeared that could help me move forward.

During my search, I came across FastCarPlay.

FastCarPlay was written in C++, the language I had wanted to work with from the beginning.

That didn't mean I could simply download the project, compile it, and immediately have a finished head unit.

Problems appeared after the first launch, and I had to work through them one by one.

But this time, I had a much better starting point.

Unlike my earlier experiments with Python, I could work directly with C++ code and gradually adapt it to my own needs.

Not Just FastCarPlay

While studying existing solutions, I also came across the LIVI project.

It was interesting as another implementation that I could study to better understand communication with Carlinkit and compare different technical approaches.

However, I decided not to use LIVI as the foundation for CaRadio.

For my needs, the project seemed too large and complex, and I was barely familiar with the language it was written in.

Nevertheless, projects like this are extremely useful.

When you're trying to understand a poorly documented protocol, being able to see how different developers solved the same problem makes the work much easier.

LIVI also continues to be actively developed, and it's entirely possible that it already surpasses the current version of CaRadio in some areas.

From Experiment to Car Head Unit

Once I got FastCarPlay running, development of CaRadio finally started moving forward.

Step by step, I brought the software to a point where CarPlay could be used not just for experiments on a workbench, but in a car.

Eventually, the application gained its own interface written in C++ using SDL3.

I no longer needed to open a browser or launch a separate media player to display CarPlay.

Everything became part of a single application designed to work with a car head unit's touchscreen.

Of course, that doesn't mean I wrote the CarPlay implementation from scratch.

The foundation came from the work of other developers who had investigated communication with USB adapters and published their projects as open source.

Thanks to pycarplay, carplay-receiver, FastCarPlay, and other similar projects, I was able to make this journey.

My task was to understand the existing solutions, adapt them to my own hardware, and achieve stable operation in the car.

What's Next

CaRadio has now been running in my Volkswagen Golf for several months.

During that time, it has covered thousands of kilometers, and wireless CarPlay has become a normal part of my daily driving.

But behind its seemingly simple interface, there are quite a few interesting technical solutions.

How does the Raspberry Pi communicate with the Carlinkit USB dongle? Where does the video stream come from? How are audio and touch events transmitted? And what exactly did I have to change to make everything work in my own application?

I'd like to explore all of that in more detail in future articles.

For now, the main point is that CaRadio's software wasn't created in a single evening, and it wasn't written from scratch.

It is the result of several years of experiments, failed attempts, studying other developers' projects, and gradually searching for the right solution.

And perhaps that turned out to be the most interesting part of the story for me.