Phone slam 3: The slammening

In part two of project iRotary, we actually got the phone to make calls, but we couldn’t talk or hear the other person. In this part, I promised you some hardcore microphone-to-headset action, and that’s exactly what I won’t deliver!

Instead, what I did was to procure the gorgeous phone you saw in the previous posts. That’s right! All this series so far has been a ruse! I didn’t have that phone to start with, I didn’t have it at all!

However, I do have it now, and I managed to enclose the Arduino in the actual phone. Let’s see how that happened.

Part three

I am going to post some actual code in this part, since everything is tied together and mostly working. Let’s look at how events are implemented.

Events

Events are monitored with edge detection. Rather than check when a signal is high, we check for the edge transition from low to high, and vice versa. In this case, we’re checking for low because low means pressed, because of the INPUT_PULLUP input mode. Here’s the relevant code, straight from the iRotary repository

#define PIN_BUTTON_HALF 6 char buttonHalfEdge = 0 ; void checkButtonHalfPressed () { if ( digitalRead ( PIN_BUTTON_HALF ) == LOW ) { if ( buttonHalfEdge == 0 ) { buttonHalfPressed (); } buttonHalfEdge = 1 ; } else { if ( buttonHalfEdge == 1 ) { buttonHalfReleased (); } buttonHalfEdge = 0 ; } }

When a rising or falling edge is detected, the appropriate function is called. This allows us to decouple the code that does stuff from the code that checks when the stuff needs to be done, and not have to think about checking the buttons at all. All we need to worry about is filling in the buttonHalfPressed() and buttonHalfReleased() events, and the code above will make sure they get called at the appropriate times.

I duplicated this code for the other view events (hook, full button press), and those work the exact same way as the snippet above.

Pulse dialing

Reading the actual pulses is simple edge detection as well:

void readPulses () { char pinPulse = digitalRead ( PIN_PULSE ); if ( pinPulse == HIGH && edge == 0 ) { pulses ++ ; edge = 1 ; } else if ( pinPulse == LOW && edge == 1 ) { edge = 0 ; } }

First, we need to make sure we are actually in a dialing state, which is not shown in this snippet. This is because there are various states, such as “in call”, “idle” and “ready to dial”, which are different from “dialing”, which occurs when the user has rotated the dial all the way to the right and is now ready to release it so it can start rotating back to the beginning (that’s when we count the pulses).

If the edge goes from low to high, it’s a pulse, so count it. When dialing finishes, the results are tallied and the digit is formed.

Checking the phone state

Checking the phone state is very important. We don’t want to make a mistake and start dialing while there’s an incoming call, or begin dialing while there’s an outgoing call. However, this operation is expensive (and laggy), so we only want to do it once per second. Here’s the code:

void checkStatus () { byte status ; if ( millis () - 1000 > statusCheckTime ) { statusCheckTime = millis (); Serial . println ( "Checking status..." ); status = call . CallStatus (); if ( lastStatus != status && status == CALL_INCOM_VOICE ) { ringingStarted (); } if ( lastStatus != status && lastStatus == CALL_INCOM_VOICE ) { ringingStopped (); } lastStatus = status ; } }

We basically store the last check time in a variable and check to see whether a full second has passed. If it hasn’t, we return, otherwise we check to see what the status is and store that in a variable.

Part three result

This is the best-looking mobile phone to date:

workaround

You can definitely see the finished product starting to take shape. All that’s left to do now is connect the hook and handset, put some batteries in it, and my magnum opus will be complete.

The battery is going to be the hardest part of the build, since I want to somehow be able to both power the phone from it, and charge the battery itself if I plug a USB cable into the phone. I also want to install a switch somewhere, so I can turn it off when I don’t use it.

For all you loyal fans, here’s a small sneak peek of part four (the final part):

workaround

Please tell me how much this amazing project has changed your life in the comments below, or directly on Twitter. Until next time!