Programming the interface

A project log for An old rotary phone as Bluetooth set

When did the charm of holding a bulky receiver to your ear end? What if we could bring the feel of the old times to our smartphones?

Xabi ZXabi Z 04/25/2019 at 20:461 Comment

The software tasks can be divided into the following parts:

Setting up the audio

The Raspberry Pi Zero with the latest Raspbian operating system should already automatically detect most of the USB sound-cards. To avoid any sort of confusion between devices we will disable the builtin audio by commenting the following line out from the /boot/config.txt file.


 Afterwards we can already test the speaker by typing the following command:

speaker-test --test=wav -w /usr/share/sounds/alsa/Front_Center.wav

We should be able to hear "Front Center" repeatedly spoken from our receiver's speaker.

We will come back to the audio setup when configuring the Bluetooth. The services we are willing to use for the Bluetooth hands-free profile require Pulseaudio to be modified, compiled, and installed from source.

Detection of signals

The dialing pulses and the hook can be read using the RPi.GPIO Python module. The following class snippet can be used to place the decoded number into a queue and be accessed from other threads (more about multi-threading and queuing can be read here).

class RotaryDial(Thread):
    def __init__(self, ns_pin, number_queue):
        Thread.__init__(self) = ns_pin
        self.number_q = number_queue
        GPIO.setup(, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        self.value = 0
        self.pulse_threshold = 0.2
        self.finish = False
        GPIO.add_event_detect(ns_pin, GPIO.FALLING, callback=self.__increment, bouncetime=90)

    def __increment(self, pin_num):
        self.value += 1

    def run(self):
        while not self.finish:
            last_value = self.value
            if last_value != self.value:
            elif self.value != 0:
                if self.value == 10:
                self.value = 0

 Similarly we can detect if the receiver is hooked or lifted:

# Receiver relevant functions
GPIO.setup(self.receiver_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    if GPIO.input(self.receiver_pin) is GPIO.HIGH:
        self.receiver_down = True
        self.receiver_down = False
GPIO.add_event_detect(self.receiver_pin, GPIO.BOTH, callback=self.receiver_changed, bouncetime=90)

def receiver_changed(self, pin_num):
    if self.receiver_down:
        self.receiver_down = False
        self.receiver_down = True

Notice that in my case because of wiring optimization I chose to join both switches to active low value (meaning they will be grounded when closed). Therefore the pull-up settings have to be set accordingly. 


f0m3 wrote 12/02/2020 at 18:06 point

I had to edit 

sudo nano /usr/share/alsa/alsa.conf

defaults.ctl.card 0
defaults.pcm.card 0


defaults.ctl.card 1
defaults.pcm.card 1

after i plugged in my usb audio device...

  Are you sure? yes | no