Vintage Rotary Phone MIDI Controller – Part 2

This it the second in a series of posts looking at interfacing an Arduino to a vintage rotary telephone for musical purposes.

  • Part 1 – Understanding the telephone hardware and interfacing to an Arduino.
  • Part 2 – Decoding the rotary dial from the Arduino.
  • Part 3 – Rotary phone MIDI note controller.
  • Part 4 – Rotary phone MIDI program change.
  • Part 5 – Rotary phone MIDI random note sequencer.
  • Part 6 – Rotary phone to MIDI adaptor.
  • Part 7 – Rotary phone multi-mode applications.

IMG_5913

Warning! I strongly recommend using old or second hand equipment for your experiments.  I am not responsible for any damage to expensive instruments!

If you are new to Arduino, see the Getting Started pages.

Parts list

  • Arduino Uno
  • “GPO” or “BT” original 746 rotary telephone
  • Optional: Scrap ADSL filter
  • 120kΩ resistor
  • Breadboard and jumper wires

The Circuit

ArduinoRotaryPhoneLink2_bb

The basic idea is that given a working vintage rotary phone – i.e. one configured for actual use with the public switched telephone network (PSTN) today – it is possible to interface it with an Arduino simply from the connections exposed in the BT style telephone plug.

IMG_5906

We need access to the RED and WHITE wires:

  • Pin 2: Red
  • Pin 3: Blue
  • Pin 4: Green
  • Pin 5: White

How you do that is up to you, but I took apart an old ADSL line filter and messed about with it, as described in part 1.  Then the Arduino pin we’re using needs a 120kΩ pull-up resistor between the pin and 5V.

As described in the first part, the signals I’ll be working with are as follows:

  • On-hook: steady 3.5 – 4.5V.
  • Off-hook: drops to around 1.75V.
  • When dialing alternate between 0V and the 3.5 to 4.5V.

This means that on-hook will be interpreted by the Arduino as HIGH.  Off-hook will (probably) be interpreted as LOW.  And the dialing will be alternating LOW and HIGH pulses.

The Code

So, we know that both the “off-hook” and dialing signals will all be present on that one IO pin.  The Arduino will be set up with the pin in INPUT mode.  Note – I’m not using INPUT_PULLUP here, as we have an external pull-up resistor instead.

Full details of how the pulses work can be found here: The Strowger Switching System.

Although in my case the logic or sense of pulses is reversed (because of the “active LOW” switching and use of PULLUPs). This is a trace from the previous set of experiments showing the phone going “off hook” and then dialing the number “3”.

RotaryPhoneDial2

From that article, it suggests pulses of period T are “off” for 0.67T and “on” for 0.3T. This would work for me if off is HIGH and on is LOW (which it is).  Then there should be an “inter-digit gap” of at least 200mS.  The period for the pulses is typically around 10 pulses a second, so up to 100mS each.  This means that the HIGH pulse is probably around 60-80mS and then a short ~20-40mS gap before the next one.

When I first set out to decode the pulses, I thought it best to work with a “state machine” and consider the various states of the phone – WAITING, OFFHOOK, DIALING, etc.  However, as many of these state transitions are timing dependent, the code got quite complicated pretty quickly and there were errors in decoding the pulses and states that I got fed up with trying to debug, so I changed tack.

I also took a look at the Arduino RotaryDial library, but it doesn’t understand “on hook/off hook”, relies on pin-change interrupts (so you can only use it with specific IO pins), and assumes the use of internal pull-ups.  If you are using a dial on its own, this might be a good solution for you, but in my case it was too simplistic.

Instead, I opted to start with the transitions for the signal itself and then expand those out depending on the state of the decoding at that point.

This means I have the following basic algorithm:

Note the current time in milliseconds
Read the pulse signal from the IO pin

IF lastpulse == HIGH and pulse == LOW THEN
  IF last pulse was previously HIGH for more than a digit HIGH pulse time THEN
    Phone is now "off the hook"
    Clear PulseCount
    Clear ReadDigit
  ELSE IF last pulse was HIGH for more than the minimum digit pulse time THEN
    This was a pulse for a digit, so PulseCount++
  ELSE
    Probably a switch bouncing so ignore it
  Reset the timer to start timing again

IF lastpulse == LOW and pulse == LOW THEN
  IF it has been LOW for more than the digit gap time THEN
    This is the end of a digit so set the ReadDigit from the PulseCount
    Clear PulseCount

IF lastpulse == LOW and pulse == HIGH THEN
  This is a rising edge, so just reset the timer to start timing again

IF lastpulse == HIGH and pulse == HIGH THEN
  IF pulse has now been HIGH for something that looks longer than a digit THEN
    Phone is probably back on the hook so reset everything

Remember the state of pulse in lastpulse

The only quirk is that 0 is represented by 10 pulses, so in the code I use “-1” to mean “no digit read” and then set it to 0 if the PulseCount is 10, otherwise set it to the number of pulses read.

The timings I’m using for the various timers are as follows:

  • Minimum digit pulse time = 60 mS
  • Maximum digit pulse time = 140 mS
  • Minimum digit gap time = 200 mS
  • “Back on hook” time = 500 mS

I’ve included a “timing” debug mode where the following values can be plotted for display using the Arduino Serial plotter:

  • The state of the IO pin (blue in the plot below).
  • The “off hook” indication (red).
  • The PulseCount (green).
  • The last ReadDigit (orange).

Here is an example showing the phone going off-hook then ringing the number “4”.  It is possible to see the four pulses in blue, with the PulseCount increasing (green) before the ReadDigit is noted a while later (orange) as the number 4 and PulseCount is reset.

RotaryPhoneDialTrace

Having now spent a while dialing numbers and putting the receiver on and off the “hook”, this seems to be pretty reliable.

RotaryPhoneDialPrintout

In the next part, I’ll start to do something musical with it!

Find this test code on GitHub here.

Closing Thoughts

I think I have a reliable way of decoding the pulse dialing now, so I should be able to make a start on some proper musical applications.  I already have a few ideas, so watch this space!

And I’m really pleased I’ve been able to do this without changing the phone inside.  I can still plug it into the wall and it will still work (at least until 2025!).

Kevin

Leave a comment