DEV Community

Cover image for Towards mesh networking with the Pinephone
joshbullock90
joshbullock90

Posted on

Towards mesh networking with the Pinephone

Where we began

I bought my first Pinephone in 2020. The thought of having a full GNU/Linux computer in my pocket was everything I never knew I wanted. I bought another Pinephone a few months later (the 3G variant with a fixed circuit). Then I got a Pinephone Pro last year. I actively hunted down applications that worked on them, at least decently, and for a while I almost ran the Mobian wiki with how much content I was adding to it. Despite the hiccups along the way it's been a fun ride.

But one accessory that really caught my eye was the LoRa backplate.

Pinephone LoRa Backplate

LoRa on the Pinephone

The concept of being able to communicate without Internet depply interested me, for a few reasons. One, when you're out backpacking in the middle of nowhere and have no cell service, the ability to still communicate with your friends if you get separated is pretty important. Two, the ability to attend events of interest such as protests, or public venues in the middle of a "lockdown", without being incriminated while not breaking any laws, is equally as important.

Experiments collecting dust

Without giving all the backstory, development in the Pine ecosystem hit a sharp decline. Notably, the backplate. By the time I got a couple of them, all that had been done with them by the community was that an alpha-state driver had been written by JF002, and the initial reverse engineering had been performed and documented by Lup Yuen Lee (to be clear these were no small feats!). But those projects sat untouched and unimproved. Nobody had ironed out the bugs, or added what would be considered full-featured functionality, or written a GTK4 communication app. It seemed like the dream of pocket-Linux mesh communication might be dead.

What I did

So I started reading through the code of the driver and test program written by JF002. I reached out and asked a few questions. And the first thing I found was that the backplate wasn't even seen by the Pinephone Pro! I knew nothing about SPI or anything embedded, really, but was determined that this idea shouldn't die. So I started researching the different busses and how it all worked together. And given that the code written by JF002 was all in C++, I decided to start learning that (and C). My main programming abilities up til now have been almost exclusively Bash and its tools. But I dove in and started learning, and as I learned new concepts, re-read the various .cpp files in the project, until I could figure out what was happening.

Then I started writing a bullet-point list of what needed to be done to make the app work as more than just a proof-of-concept test. Things like handling messages longer than 27 characters (a limitation of the SPI bus), encryption, reliable transport, among other things. A lot of serious functionality for a guy who barely just started learning C++! But I picked the first one in line, which was handling longer messages. If I tried to send a message longer than 27 characters, nothing would happen.

Eventually I stumbled my way through adding code (mostly loops) to iterate through the msgStr vector, split it into <27 byte chunks, and store it in its own vector. In order to know how many chunks would need to be received and concatenated however, I would need to add some sort of EOT for the receiving device to see. So I added 'EOT' as the last characters before '\0' (original, no?). Then as I was testing, I noticed the program would periodically dump other messages from devices around me transmitting on the same frequency, and as interesting as it is to see whose smart meter isn't happy, it wasn't what I wanted to deal with when talking to another Pinephone. So I prepended the message chunks with 'EPP' (Encrypted Pinephone Packet). So now I had my messages split into chunks with a "preamble" and an EOT. For the receiver, then, it would need to filter out any transmissions that didn't start with 'EPP', and then store them until it received one with an 'EOT' at the end. Can I just say that if you don't use arrays or vectors or indices all the time, it's really easy to be off by one?

So now the program can split messages into chunks small enough for the SPI to handle, and can concatenate received messages. I removed the hex debug statements so that all one would see is the message sent on the sender device, and the message received on the receiver device. It works! Four days of learning C++ and I was able to tackle Baby's First Project. Not too bad, but there is much work ahead of me.

Code For Receiving

What remains to be done

Currently there is the issue of some sent transmissions simply not being seen by the receiver device at all. I will have to troubleshoot this to see whether it's the sender garbling the data somehow (Baby's First Project, remember?), or the SX1262 being overloaded (timeouts?), or even frequency drift (does the radio, if set to 915000000, always transmit at 915 MHz? Or does it drift to 914.75 MHz?). Then there is the issue of encryption. That's going to be fun. But, in my experience you only truly learn by doing, so doing is what I'll do.

Check out the code at https://codeberg.org/joshbullock/pinedio-lora-driver

Top comments (0)