Talking amongst yourselves

There's a need for processes to communicate. A wants to talk to B, because they want to share data. This has been done to death in computer science (and modern POSIX compliant implementations feature dozens of ways of performing inter-process communications).

And yet I invented my own. (To say “invented” is a bold overstatement — “adapted” is better).

I created a “scratchpad.” It's a small piece of shared memory where any process can read or write small bits of named data. It's very simple:

#define SP_NAME_SIZE        32
#define SP_VALUE_SIZE       32
#define NPAGES              1

typedef struct
{
    char    name  [SP_NAME_SIZE];
    char    value [SP_VALUE_SIZE];
} scratchpad_t;

// in shared memory:
scratchpad_t    *scratchpad [NPAGES * 4096 / (SP_NAME_SIZE + SP_VALUE_SIZE)];

The scratchpad is a 4k chunk of memory that holds 64 entries of 32 bytes worth of “name” and 32 bytes worth of “value.” It really couldn't be much simpler.

Why am I still writing? It's not so much the concept of the scratchpad that's interesting, but rather how it's used. Let's look at some of the applications.

Data Acquisition

In one embodiment, I have several data acquisition sensors (temperature, humidity, pressure) connected to a Raspberry Pi. I periodically sample these values, and then write them over the network to a database for storage and graphing. On the very same Pi, though, there's also an I2C 64x128 dot matrix display. I thought, “Wouldn't it be nice to show the temperature, humidity and pressure on the display?”

Then I thought about how the dot matrix display driver was going to get the data from the various sensors. Each sensor is an independent process — the process goes out, does some I2C bus magic to read its associated sensor, and writes the value to the central database.

My initial thought was to create an API so that the dot matrix display could query the drivers for their values. Too complicated.

Then I thought that the drivers could all open a file (say in /tmp so that it doesn't wear down the flash device), and write their data there. Not as complicated, but I still felt it to be a little too heavy handed — this would cause lots of open, write, close operations on the driver's side, and corresponding open, read, close operations on the dot matrix side.

Then I thought about putting it in shared memory. This is the scratchpad concept. It effectively creates named regions in the shared memory, where various processes can “meet up” and exchange data.

So, the I2C driver for the MEAS HTU-21D temperature and humidity module opens up the scratchpad and records two sets of values, a name of “temperature” with a string representation of the floating point value of the temperature in Celcius, (for example, “21.3”), and a name of “humidity” with the relative humidity. Easy-peasy as I like to say.

The key is that both the dot matrix driver and the HTU-21D driver agree on the name and format (which is helped by the scratchpad API being string oriented), and then just exchange information over shared memory.

MP3 Light Organ

The current in-progress MP3 light organ (see my article Real Time Fast Fourier Transforms (August 2015)) uses scratchpads as well, but in a bi-directional manner.

The light organ ultimately consists of modifying a stock MP3 player (say mpg123 for example) to perform the red, green, and blue value generation. Again, there's a binding problem. I don't want to entangle the MP3 player with the details of how to control the deck lighting (hint: in one case, it involves sending UDP packets to a 24-bit digital I/O card, in another case it involves some as-yet-undefined protocol with a Raspberry Pi, depending on which light controller you want to talk to).

So I decoupled it via the scratchpad. When the FFT algorithm inside of the MP3 player has decided what red, green, and blue values it wants to output, it just writes them to the scratchpad. Low overhead, light (pun intended) coupling. Whether or not the lights are even turned on, or are in “follow the music / light organ” mode, the MP3 player just plops three values into shared memory.

Bidirectionality

But then I thought some more about it. I really want to control the AGC (Automatic Gain Control) on some of the internal parameters to the FFT-based algorithm. I also want to control filter coefficients (so that the RGB light values aren't “jerky”). It sure would be a drag to have to modify the MP3 program to get the values from some command line, or a well known file, or... Why not just get the values from the scratchpad?

This way, a simple command line program (which is already part of the scratch command test suite) could be used to adjust parameters in shared memory, and the MP3 FFT light organ processor could just read them from there.

Again, I must say: “easy peasy.”

Caller ID

One new application just occurred to me — phone call indicator. I can write the phone number and its respective database lookup into a scratchpad area, and have other apps pick it up. For example, the deck LED app can look at the phone number indication and flash the lights to indicate mother, mother-in-law, or spam :-)