My payphone runs Linux now.

In 2015, we threw a party called Cyberdelia, celebrating the 20th anniversary of the movie Hackers. It was epic: we built skate ramps and everything.

We did it again in 2016 and 2017, 2020! Check out the photos of the parties: 2015, 2016, 2017 and 2020!

One of the props that I picked up to decorate DNA Lounge at the first Cyberdelia in 2015 was an old payphone. It wasn't hooked up for that first party, but just in time for the second party, I modified it to run Linux.

(It's still here, by the way. Come play with it in person the next time you are at DNA Lounge!)

When I was trying to decide what I wanted the phone to do, "making phone calls" was obviously the least useful thing. Nobody needs that: that's why payphones are extinct in the wild. It's also why we no longer have Internet kiosks.

So instead, when you pick up this phone, it "rings" and connects you to a "voicemail" system. Press 1 to listen to our schedule of upcoming events (the same message you hear when you call us at 415-626-1409); press 2 to listen to your saved messages; press 3 to record a message.

Here is the sordid tale of how I made a payphone run Linux. I'm not so great at hardware hacks, and it shows. My bumbling exists for your amusement.

Phase One: The Keypad

My first goal was to turn the telephone's keypad into a USB keyboard. The plan: take a $5 USB numeric keypad; pull the USB chip out of it; and hook that up to the phone's buttons.

Behind the buttons on the telephone keypad is the same sort of design as exists inside most computer keyboards. The obvious way to do this would be for there to be a switch for each key, attached to a pin on the chip to tell it when the switch was pressed. But for a keyboard, that would mean your chip would need 100+ inputs. So instead, the way they work is, the keyboard is wired up in a grid: there is a set of horizontal wires, and a set of vertical wires, and pressing a key makes an electrical contact between one horizontal and one vertical wire: so pressing 5 connects wires X and B. The chip figures out which keys are pressed by polling thousands of times a second: it squirts some electrons down W, and if they come back on A, then 1 is pressed. Then it squirts some electrons down X, and if they come back on C, then 6 is pressed, and so on.

So for a simple keypad like this, it's a false economy, since this chip needs 7 inputs instead of 12. But for a full-sized keyboard, you reduce the number of inputs from about 100 to about 20. But, it is what it is.

The logical electrical layout of the phone's keypad is exactly what you'd expect: it's the drawing above. The logical layout of the generic USB numeric keypad is a bit weirder.

Physical layout:

Logical layout:


It's like the Platonic ideal of a keyboard: you think you're typing on the thing on the left, but that's just a shadow on the wall. The real keyboard is the thing on the right.

The positive numbers line up properly, but there's no choice of mappings here that will make the "*0#" row work. So, I used the "T/*" row for that and I re-map the keys in software. (The blank cells don't send any keys at all).

First I needed to get electrical connections out of the phone's keypad. The key contacts are printed on one side of a two-sided circuit board. I was able to use the "via" holes (where one side of the board connects to the other) to connect in. That looked like this:

That chip on the board is both the keyboard decoder and a DTMF (touch-tone) generator: the output of this board is audio. So that wasn't going to do me any good.

(Fun fact: the noises that telephone buttons make are chords of two notes played simultaneously, and those notes are also arranged in a grid just like the above, low frequencies vertically and high frequencies horizontally. Other notes and chords did other things on the old phone networks: one of the more famous frequencies was 2600 Hz, and that's why both the Atari 2600 and the magazine are called that. Fun fact two: Wozniak and Jobs funded Apple Computer by selling blue boxes that let you make phone calls for free.)

The next step was to connect those new wires to the inputs on the USB keyboard chip. Easier said than done, because that keyboard had a flat plastic membrane as its input: its socket accepted a paper-thin piece of flexible plastic with contacts printed on it that are 0.5mm wide and 1mm apart on center. I wasn't able to find a breakout board that had a socket that small on it: I found some blanks, but they required you to surface-mount the socket to it (and I couldn't find the socket either). So I did it the hard way: I manufactured a connector that would fit into that socket.

Yeah, those are sewing needles.

First: let me draw your attention to the plastic shim holding those needles at 1mm spacing. Let me draw your attention to how hard it was to manufacture that thing. Though I have 0.5mm drill bits, I had to tape them to make them fit into the dremel at all without just vanishing. And even though I have a drill-press stand for my dremel, my first plan of drawing a pattern then lining up the drill and dropping it was totally not working at all. So in the end, I just eyeballed it: drop the drill; lift ever so slightly; give the plastic the slighest kick with my fingernail; drop the drill again. It only took me three tries to get it right!

Second: though those are the thinnest needles that I had in my house at the time, they weren't thin enough to fit into the socket. So I had to file them down. It was like I was making the world's tiniest shivs. I turned the dremel sideways, put a sanding wheel on it, and held the needles to it until they were flat and about 0.1mm thick. I was doing this while wearing a 20x magnification monocle, so all of this action was taking place with my face so close to the spinny bit that I had to exercise great care to avoid sanding off the tip of my nose.

When I described this to a friend he said, "So basically, you're looked like some guy I have to find to send me on a side-quest in Fallout." Pretty much.

Ok, remember that shim I was so proud of constructing? It didn't really work. It was still too hard to get every pin to make contact at the same time. So instead, I tore the top off of the jack and jammed the pins into the underside of the contacts in it, then used the tip of a needle to secure each with a drop of superglue.

Once everything was tested, I wrapped the whole mess of wires inside some Sugru (this amazing play doh-like stuff that dries into flexible rubber).

I did waste a few days trying to track down what I thought was series of bad connections that actually turned out to be: to make some keys work at all, you had to press really fucking hard. I solved this problem by shimming with a thin piece of cardboard between each key and the domes on the rubber membrane. I suspect this phone would also have had that problem when it was still a phone.

Phase Two: The Handset

Fortunately, telephone speaker and microphone design has not changed significantly since like, 1870 or something. Scoping out the four wires coming from the telephone's handset was pretty straightforward: one pair showed 150 Ω (that's the speaker); one pair showed 200 kΩ (that's the mic).

If you're like me, and do these sorts of projects at 4am without really planning ahead, you don't have, for example, a solderable TRRS plug when you need one. So you take what's lying around, and tear apart an old pre-made TRRS cable and solder a stacking header onto it. What, soldering onto wires that are just slightly thicker than a human hair? I'm getting used to it. Then a big old glob of epoxy to finish it off.

Best iPhone headset ever.

Update, 2020: What I described above is wiring the handset's speaker and microphone directly in to the pins on a TRRS jack and calling it a day. As it turns out, that doesn't really work: it was noisy and unreliable. The old-school telephone handset mics and modern mics (e.g., earbuds) are substantially different electrically, so this fell into the category of "lucky it worked at all, ever". The proper solution to this, which I did in my 2020 upgrade, was to open up the handset and replace the old speaker and mic with their modern equivalents. That also allowed me to include an audio amp to get the volume up to nightclub levels.

Phase Three: The Computer

I got a Raspberry Pi 2 B to drive it, which is probably a more powerful computer than your typical PC was at the time that this payphone was originally in service.

The Pi has an audio output, but it's shit, and it's not powerful enough to drive the speaker in this handset. But that doesn't matter since the Pi does not have an audio input, meaning I needed a different audio card anyway. I got a Cirrus Logic, which, conveniently enough, also has a TRRS headset input.

You know what this means, right? I voluntarily and of my own free will recompiled my kernel in order to get my audio card to work. I don't even know who I am any more. I don't even know what year this is. "And you did this on your home phone?"

Because of course Raspbian doesn't come with the modules pre-built. Of course it doesn't.

Anyway, after the usual jiggery-pokery, I had audio ouput via aplay and audio input via arecord and all was right with the world, except for the fact that I had hoped I would never hear the word "ALSA" again in my life. (It's "Advanced", you know. The "A" stands for "Advanced".)

So then I wrote some code: It sits there reading characters from the keyboard (the phone keypad) and responding to them by playing MP3 files, or recording and saving new ones. Most of the MP3 files are pre-recorded (generated by the Makefile using the free online text-to-speech service at -- which doesn't do a fantastic job, but it's adequate). The infoline is downloaded from the DNA Lounge web site every morning and re-converted to an MP3 in the same way.

I launch it as a getty from /etc/inittab on console 0 so that the machine boots up into the Perl script:

    1:2345:respawn:su phonebooth -l -c 'cd ~jwz/src/phonebooth && ./'

(I write junk like this in Perl because I still just can't get past Python's whitespace thing. I know, you kids today all think that it's not a big deal, but I can't. I just can't.)

Phase Four: The Switch Hook

Now I just need to detect when the handset has been taken off hook and hung up. This part should be easy, right? After all, the Pi 2 has about a zillion readable pins on it, and unlike the Arduino, they even come with built-in software-configurable pull-up and pull-down resistors, which saves a lot of soldering.

Well, no. Not so much. This next part took me days to figure out.

If you were me, you might assume that an audio card wouldn't consume all forty pins on the Pi's GPIO header. Well, it does... sorta...

The manual is pretty unclear about whether any of the GPIO pins are intended to be available for non-soundcard-related use, but in the tables it does describe some of them as "EXP", which I interpreted as "Expansion", which I further interpreted as "you can use these."

Also, the board has an "expansion header" (sometimes called a "feature header") on it. It has 20 pins. The manual describes a header that has 13 pins. Further, the 13 pins described in the manual bear no relation to the first 13 pins, or any pins, on that 20 pin header. What the hell, Cirrus.

Scoping out its continuity shows that the expansion header corresponds to these pins on the Pi's header. This table is looking at the board with the ethernet jack on the bottom left. The header is not numbered and I won't hazard a guess as to which corner the designers of this board thought of as "up".

? ? ? ? ? BCM 5 BCM 25 BCM 12 BCM 26
5v ? ? BCM 3 BCM 2 ? BCM 6 BCM 16

So, just pick a pin, like BCM 26 let's say, and go to town, right?

Well, no. Not so much.

It turns out that if you try to use any of these pins, they all behave as if they're "floating": you get random data, as if the software was unable to attach a pull-up or pull-down resistor to them. Or maybe it's not reading the pin at all but is reading something else entirely. Who knows! The pins I tried worked properly when the Cirrus card was not plugged in, but with it plugged in, they didn't function.

So we're dead in the water, right? Time to spin the wheel and buy a different audio card?

But I had an idea. Why is this card touching these pins at all? Does it really need to? So I got out the needle-nose pliers and very carefully bent one of the pins down, then plugged the audio card back in, denying it access to that pin.

Pin 40: Audio card doesn't function. Bend it back and try again.
Pin 38: Audio card doesn't function. Bend it back and try again.
Pin 36: Audio card doesn't function. Bend it back and try again.

Yup, I did that. I'm not proud. Or maybe I am. I can't tell.

I suppose it's possible that by doing this I have broken some feature of this audio card, but since both playback and recording work, it's not a feature that I use, so, so what!

Except the story didn't play out in quite so straightforward a way as all that, because there were multiple failures happening at the same time, as is my way, because I am cursed.

It turned out that, on this Pi, with this version of Raspbian, reading a pin state with Python worked great:

    import RPi.GPIO as GPIO
    import time
    import sys
    pin = 12

    GPIO.setmode (GPIO.BCM)
    GPIO.setup (pin, GPIO.IN, pull_up_down = GPIO.PUD_UP)

    while True:
      state = GPIO.input (pin)
      if state != last:
        if state == True:
          print ('CLOSED')
          print ('OPEN')
        last = state

But doing it from Perl didn't work at all. The pins always acted like they were floating:

    use Time::HiRes qw (sleep time);
    use Device::BCM2835;

    Device::BCM2835::init() || die;
    Device::BCM2835::gpio_fsel (&Device::BCM2835::RPI_GPIO_P1_12,
    Device::BCM2835::gpio_set_pud (&Device::BCM2835::RPI_GPIO_P1_12,
    my $last = -1;
    while (1) {
      my $state = Device::BCM2835::gpio_lev (RPI_GPIO_P1_12);
      if ($state != $last) {
        print ($state ? "CLOSED\n" : "OPEN\n");
        $state = $last;
      sleep (0.1);

This was weird, because both of these libraries appear to be a thin wrapper on top of the underlying bcm2835 library, which is written in C. Ok, fine, let's do it in C:

    #include <stdio.h>
    #include <bcm2835.h>

    #define PIN RPI_GPIO_P1_12

    int main (int argc, char **argv) {
      uint8_t last = ~0;
      if (!bcm2835_init()) return 1;
      bcm2835_gpio_fsel (PIN, BCM2835_GPIO_FSEL_INPT);
      bcm2835_gpio_set_pud (PIN, BCM2835_GPIO_PUD_UP);

      while (1) {
        uint8_t value = bcm2835_gpio_lev (PIN);
        if (value != last)
          printf (value ? "CLOSED\n" : "OPEN\n");
        last = value;
        delay (100);
      return 0;

Oh hey, the C version didn't work either! What the hell was Python doing under the covers that the Perl and C versions were not?

It turns out that they were using different pin numbering schemes! Python (and all the documentation of anything ever) use "BCP" numbers, but the C and Perl interfaces use Pi header pin numbers instead. So changing the "12" to a "32" in the C code made it work.


Here's the next monumentally moronic thing that I discovered: only root can read BPIO pins. And I don't mean "only users who have read permission on /dev/mem", I mean literally "only root". So either you have to run everything as root, or your Perl or Python program has to call out to a C helper program that is setuid, just to read the pins. (Said program being the one above, that simply loops, printing a line every time the pin state changes.)

(You might be thinking, "Well why not just run everything as root, then? So what?" If you are thinking that, then the Internet of Things, and by "Things" I mean "Moldovan Botnets", thanks you in advance for your complicity.)

Phase Five: Profit

I kind of wanted to make use of a few more pins, to do things like detect when a coin was inserted (at least to have it say "Thank you, and remember to tip your bartenders!") or to be able to ring the physical bell, but after my pin-bending hijinks on the audio card, I figured I had better quit while I was ahead. Maybe the next pin I bend blows up the board.

And here it is, the complete "payphone", before being re-inserted into its massive cast-iron chassis:

In conclusion, Hack the Planet.

Post Script: 2018

It has been two and a half years since I built and installed this payphone, and I've watched many people interact with it over the years. I am sad to report that it is... underappreciated. Nearly every night, I've watched the following drama play out:

    Someone says to their friend, "Oooh, neat! Take a picture of me!"

    They pick up the handset, place it to their ear, and mug for the camera.

    The phone rings once, and the person PANICS and slams down the handset and runs away.

They don't even stay on the line long enough to hear the menu of options! Honestly, I don't get it. How can you be so incurious as to not wonder what was going to happen next? With that kind of attitude, how are you ever going to get sent on that side-quest?

People only record messages on it about once every few months, and half of those sound to be from accidental button-mashing. Even of those people who listen to the menu, I don't think most of them even listen long enough to realize that pressing 4 will lead to a deadpan robotic voice telling them a random "walks into a bar" joke.

There are easter eggs, too. Forever undiscovered. Nobody even tries to make it to a barrel roll.

Anyway, the fact that the payphone is appreciated almost exclusively as a selfie-accessory and is barely acknowledged as an electronic toy has sapped my enthusiasm for the other ideas I had for it, like rigging up the physical bell, or the coin slot, or adding interactive lights or a display of some kind.

It has amassed quite a nice collection of stickers, though!

Planet, Hacking Thereof:

Regarding Cyberdelia, our Hackers party that was the inspiration for this project: we'd love to continue throwing that party once a year or so, but we had to skip it in 2018 because we were unable to find a sponsor for it. The party has a lot of expensive overhead, and in 2017 we were able to cover costs by making it be someone's official RSA / B-Sides after party. That went great!

But in 2018, sadly, that company dropped out. Their lawyers told they that they can't sponsor anything that involves alcohol, so their after-party had to be held somewhere that you can't get a drink at all. (Yeah, I don't get it either.)

If you love Hackers as much as we do and you'd like to see Cyberdelia happen again, see if you can get your corporate overlords to kick in some sponsorship money the next time you're in town for a trade show or product release or something.

Eclectic events like this are what we specialize in at DNA Lounge, but while such things make great art, they rarely make money. If you'd like to help us keep doing this sort of thing, please join the DNA Lounge Patreon!

Post Post Script: 2020:

We were able to bring back Cyberdelia one more time, in 2020 for the 25th anniversary of Hackers! And it was epic. I largely rebuilt the payphone's innards for that. The basic design remained the same, except that I re-built the handset, and used different audio hardware. A few details are on my 2020 blog post about it.

Also we have Cyberdelia posters for sale!

Join our Patreon, and hack the planet.

Post Post Post Script: March 261st, 2020:

The keypad had gotten a little flaky: stuck keys and such. I tried cleaning and adjusting it with little luck, so I just ordered a new one from, and while I was at it, I replaced the USB controller. Rather than jumping through the hoops necessary to Frankenstein the microcontroller from an existing USB keypad onto it, I built a new controller using a Teensy 2.0. It was trivial to drive it with a combination of the Arduino USB Keyboard library and the Adafruit keypad matrix decoder library.

Tags: , , , , , ,

65 Responses:

  1. Eddie says:

    Everything about this is spectacular.

  2. Joshka says:

    Sweet hack! You mentioned that the keypad sends audio. Did you consider using audio tones as a possible interface rather than the usb? Would be neat to be able to box the phone :)

    • jwz says:

      Thought about it, but getting realtime analysis of an audio stream sounded like exactly the sort of crap that ALSA would make impossible. (The "A" is for "Advanced", you know.) And if not "impossible" them certainly "exactly the kind of Linux crap I hate most."

      Also I never got as far as figuring out how to actually energize and read that board, which also sounded (at the time) like more work than what I did. Which may have turned out to be wrong, given how hard what I did turned out to be.

      • Aaron says:

        You probably made the right call; analyzing audio is complicated even when you don't have to find a way to get ALSA to turn it from analog signal into data. I'm still trying to find a way to do it reliably so I can write real functional tests around the SAME encoder I wrote for shits and grins.

        • Gabriel says:

          Dude! I was looking for a SAME encoder the other day! You wouldn't happen to be willing to share, would you?

          • Aaron says:

            Sure! It's on Github at aaron-em/same-encoder.

            Do note, it's written in Javascript; that said, it works both in Node (probably io.js as well, though haven't tried it) and in the browser, so you can use it in whichever of those ways suits you best. And, of course, as I already mentioned, there are no functional tests yet, because I haven't been able to find or write a decoder which I can build them around. As far as I can tell, it produces correct output, but I have as yet no way to prove that with certainty to myself or anyone else.

            With those caveats aside, of course you're more than welcome to it! If you find any bugs or see any opportunity for improvement, please oblige me by opening Github issues or pull requests. Thanks!

      • Jered says:

        I sincerely hope this is a reference to:

      • Tim says:

        Multimon-ng does DTMF decoding in real-time and can be piped to and from in shell.

        You can use sox to pipe the input audio to multimon. It also supports other encoding schemes so you could do some cool tricks to access/input some other features (Morse replay from smart phone? ;))

      • Jonathan says:

        "These days" Linux users are under the reign of terror of "Pulseaudio", and ALSA has been promoted in stature to fond, wistful memories of when things "just worked... slightly more."

        • gryazi says:

          It's Pulse on top of ALSA.

          • Jonathan says:

            I elided that because it wasn't relevant for my point: PA on top of ALSA still makes me pine for the "just ALSA" days; forgetting what exactly they were like.

            • ssl-3 says:

              I remember trying to use Pulse on purpose one time, trying to get networked audio to function between machines. With 4front's paid-for OSS drivers, and ALSA as a[nother] middle layer.

              Looking back, I may have had some masochistic tendencies in my youth.

              I pine for the days before universally-integrated AC'97 CODECs, when I could just pay 4front to make things work for me, and the sound card (if I chose carefully!) would do any required mixing in hardware.

              Also, more generally: I miss hardware that actually did stuff, including printers that inherently knew how to print words on paper.

              • jwz says:

                Come on, though, printers have always been awful.

                • ssl-3 says:

                  But they've gotten far, far worse.

                  (though admittedly, I've never written a VHS tape labeling system entirely in PostScript. So perhaps my hate is tempered differently.)

                  (I also keep 30-year-old TI thermal teletype around for posterity, though none of my machines currently have a serial port with which to operate it, and I tossed my expensive external Supra v.32bis modem over a decade ago. Not that it would have anyone to talk to, or a landline to plug into.)

                  (Ah, fuck. Is this what getting old is actually like? I thought it was supposed to be all titties and beer by now.)

                  • jwz says:

                    Dude you are talking to someone who is currently sitting on the floor of a filthy office wondering whether this cheap assed POE dingus scorched my Pi when titties and beer are happening literally on the other side of the door. So I dunno.

                    Thank you for making me realize the error of my ways, however.

                  • jwz says:

                    Exhibit A (titties, beer, not pictured; fully implied.)

                  • ChrisB says:

                    Technically ass not titties, although they're also fully implied.

  3. Mariachi says:

    Any reason not to, instead of converting it to USB, leave the original keypad hardware intact, use the original DTMF generator, have the Pi listen for tones on the audio card’s mic in, and recognize the waveforms? Or would that be more processing than it could handle?

    • Mariachi says:

      Doh! Ninja’d by Joshka. Damn, it took me half an hour to write that question?

  4. Photar says:

    One of your keypad layouts has two number 4 keys.

  5. Congrats on your finished project, I can feel your pain from reading your writeup! I know that giving advice after the fact sounds cocky, but in case anyone wants to recreate your payphone, please....

    For Audio: Don't buy any of these overpriced "audio shields", just cut off the headphone part from an old USB headset and reuse the usb soundcard molded either into the USB plug or that small blob between the USB plug and the headphone part. It will just work out of the box on your PC, Mac, Raspberry-Pi, Beagle-Bone...

    Switch-Hook: This python library is a very ugly hack and started out as the only thing working when no kernel-drivers existed for the gpio yet. But people never stopped using this idiotic thing, even now the "slow but proper" way works beautifully from every programming language or shell script: Also it doesn't require root (for poking directly into the hardware, which is a pretty insane idea anyway) once you've chmod'ed the files. And it will be fast enough for your hook detection in any case.

    Keypad: If you redo it, just invest the saved time from not having to deal with the crap mentioned above in doing the keyboard scanning yourself ;-) using the freed GPIOs you no longer have to waste on the audio shield.

    • Nate says:

      I concur with all the above.

    • James says:

      Can sysfs be added without recompiling the kernel?

      • crtxc says:

        Why would you want to add sysfs? Why would he need a pseudo file system.

        I wouldn't want to do that if I didn't have to, especially if I were surrounded by grinning conssies looking for ideas to steal; or to paraphrase JWZ "tail lights to chase"

        • James says:

          What are conssies?

          I was simply trying to identify how long it took between jwz mentioning Linux and someone else suggesting kernel recompilation.

  6. The bit about the audio card is insane. Note I understand why do many people hook an Arduino up to their RasbPi via serial if they want to do i/o.

  7. phuzz says:

    I was wondering, can you get a USB sound card that would work with the pi?

    • Adam says:

      That's how I have audio working on my Raspberry Pi. Without compiling any kernel modules.

  8. Cody says:

    Awesome, so awesome. Wish I could listen to the messages.

  9. Aaron says:

    You recompiled your kernel to make your audio card work! Now that's getting into the spirit of the thing. I mean, most people will probably just dress up for the party or something.

  10. nwf says:

    Next Time Around (TM), you may find it easier to use a SIP adapter and VoIP software, rather than banging the audio and keyboard yourself. The adapters are nice in that they are (shitty) sound cards with DTMF decoding built in.

    I do not know for sure, but I expect the phone keypad to want to sit between the mic and the phone line without much in the way of external components.

    • Tim says:

      Yeah, a cheap ata with an fxo port might have done it. You could just wire a rj11 on to the line cord and run asterisk on the rpi2.

  11. frymaster says:

    One alternative I've found to suid C wrappers around scripts is using sudo, allow passwordless root invocation of that specific script only

  12. Lee says:

    Suck it up and go with Python.

    • MattyJ says:

      After reading this blog for the better part of a decade, I've concluded that JWZ is not one who sucks it up, in any manner.

  13. Gushi says:

    Perhaps build a web version of this so other folks can hear the audio files?

  14. Cyranix0r says:

    This is awesome, you're my hero.

  15. I'm horrified at how you did it, but I'm super impressed that you did it at all. My pay phone is still standard. It's fun when it rings, but...

    Anyway, here's a couple things that you could have done and might consider for version 2:

    A ringdown box makes the phone call a specific number when it goes off-hook. These are how you make inmate phones and security phones. They, and everything like this, cost way too much. But if you're insane, you can hook one up to an Asterisk box and get a full interactive voice response system. You can still run Asterisk on RasPi. However, you trade configuring ALSA with configuring Asterisk, and I don't think that's an improvement...

    I would have used a USB audio card instead of the shield. This one in particular is really cheap and works really well. You're still having to mess with ALSA, though... and now you've got the problem of ALSA and multiple audio cards. Fun. But you've got all your GPIO back!

    But the easiest option might be Adafruit's Audio FX boards. They turn a button press into a playing wav/mp3 file. That's it. They're perfect for something like this! Except now you've got to load it with new audio files once a week...

    • ssl-3 says:

      I'm puzzled why you would want a fancy ring-generator "ringdown box," when you could just use an FXS port (which is already designed to talk to a telephone) instead of an FXO and do the rest in software.

  16. Jorgen says:

    Hey! This got posted to Hacker News, but following the link from there seems to intermittently trigger the hotlinking warning.

    • jwz says:

      Hacker News is a steaming cesspool and I don't have time or desire to deal with their bandwidth demands, so I just block them.

  17. pir says:

    What I tend to do with the RPi rather than using the built in IO ports (which are 3.3V, very limited in current, wired directly into the chip so easy to fry and as you note only accessible by root) I use an expansion board that breaks out i2c to IO ports that can be 5V, easy to replace if you fry them and i2c IO can be done as a non-root user (there are sample libraries for Python and C at least, don't know about perl). This also leaves the non-i2c pins available for whatever other cards you may be using.

    I use this one from a small UK manufacturer, I'm sure there are similar ones more easily available in the US:

    Or you can build one:

    (one of the advantage I always found with Python over perl was other people can't screw up indentation).

  18. Drew Roos says:

    Please tell me there's an easter egg if you play a 2600Hz tone into the mic.

    And for the love of god get a USB sound card and free up all those pins.

  19. Chris Davies says:

    It seems a shame not to hook up the coin detector. Couldn't you just multiplex it over the same pin you used for the hook switch? Build a little board to feed it 3 frequencies of square wave and no signal for your 4 states.

    • kwk says:

      I would want it to reject the coin and play "keep the change, ya filthy animal."

  20. Angus says:

    I think I can explain the GPIO thing. There are two[*] GPIO numbering schemes in use on the Pi. There's the actual pin numbers on the Pi's 40-pin "P1" connector header, and there are the GPIO numbers as used by the Broadcom system-on-chip.

    In the Python code, GPIO.setmode(GPIO.BCM) tells the library to use raw Broadcom numbering. So you get GPIO 12. However in the other code RPI_GPIO_P1_12 is "sugar" for pin number 12 on the "P1" connector, so you get a different GPIO (I think 18).


    According to the enum definition elsewhere on that second page, RPI_V2_GPIO_P1_32 = 12.

    (Yay embedded systems?)

    [*] I think one of the other Python libraries actually invented a third incompatible pin numbering scheme.

    • jwz says:

      Oh holy crap, you're right! Changing it to 32 in the C code makes it work!

      • Angus says:

        Good to hear!

        I realised that might explain the other "EXP" pins on the audio breakout not working as well. The GPIO/pin mapping changed between RPi 1 & RPi 2, so if the numbers on the audio breakout are Broadcom GPIO numbers for RPi 1, they'll probably need translating to the equivalent GPIOs for RPi 2.

        PS I noticed a typo in the update - s/BCP/BCM/. Normally I wouldn't be pedantic about typos but I know people will find this blog post in the future while having this exact problem, and will go off looking for the meaning of BCP.

        • jwz says:

          Unfortunately, no, it doesn't explain that. Pins that worked while the audio card was detached failed to work while it was attached, and I determined which pins were "the same" by continuity, not by number.

  21. > I voluntarily and of my own free will recompiled my kernel in order to get my audio card to work. I don't even know who I am any more. I don't even know what year this is.

    History doesn't repeat itself, but it sure does rhyme ;)

  22. vince says:

    I am happy/disappointed that you managed to use a version of Raspbian old enough to not involve systemd. I fear there might have been few survivors otherwise.

  23. jwz says:

    Of course, Limor did it better ages ago. Hers is red-boxable!

  24. jwz says:

    Maybe I should implement T9. Though without a display, that might be tricky.

    Now I'm regretting that I didn't get a payphone with a rotary dial instead.

    And implemented T9 on that.

    • Louis says:

      You could have audio responses to the button presses. After each quick button press the letter of the alphabet would be pronounced (Pressing 222 would make the phone say "abc", and if the user waits, there would be a beep to signal that the system is ready for the next character. You'd need a backspace, and "read input until now" button though.

  25. James says:

    The Link says the 29th, not the 22nd.

  26. Russ says:

    Rather than spending all the time making a connector, I would have just exopied some 0.1" header to the USB board, and then used wires to connect it up directly to the SOIC. That chip has quite a bit wider pitch than the header and would be pretty easy to solder up. Either that or desolder the connector and solder directly to the lands.

    • jwz says:

      I think you're saying, "the pin spacing on the chip might have been the same as the spacing of the pins on a header"? I don't have it in front of me, but from looking at the photo, I think the chip's spacing was tighter than that. Almost half, maybe.

      Trying to solder directly onto the round contacts on the board next to the socket was not possible, certainly not with the equipment I have. I would have gotten the solder on more than one contact and probably ended up delaminating the board trying to fix it.

  27. Ted says:

    All you had to do is use BOARD rather then BCM,
    now it matches with the Pin Number as a Pin Number!

  28. void says:

    In the python code you forgot to initialize the variable 'last'

    while True:
    state = GPIO.input (pin)
    if state != last:
    if state == True:
    print ('CLOSED')
    print ('OPEN')
    last = state

    In the perl code you swapped the two variables:,
    $state = $last; should be $last = $state;

    my $last = -1;
    while (1) {
    my $state = Device::BCM2835::gpio_lev (RPI_GPIO_P1_12);
    if ($state != $last) {
    print ($state ? "CLOSED\n" : "OPEN\n");
    $state = $last;

  29. Steve says:

    I tend to write my junk in Perl because I still just can't get past Python's whitespace thing. I know, you all think it's not a big deal, but I can't. I just can't.

    I'm totally with you.

    The only thing that's tempting me is that I have to worry about my whitespace in perl anyway, just purely for aesthetic reasons. I'm always indented, reindenting, etc. So, I figure I can cope with python deriving some meaning from beautification. I haven't taken the python plunge yet but this is the strategy I'm planning to make my brain use.