Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Mark Lister
Published

Antique Phone Resurrection Using Raspberry-Pi

Converting an antique phone (made in 1895) into a mobile (cell) phone using a Raspberry-Pi

IntermediateFull instructions provided1,369
Antique Phone Resurrection Using Raspberry-Pi

Things used in this project

Hardware components

Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1
USB Speaker
×1
UPS (by Waveshare)
×1
GSM Hat (by Waveshare)
×1

Story

Read more

Code

phone.py

Python
I have swapped real phone numbers for "0123456789" in the code
import serial
import time
import RPi.GPIO as GPIO
import subprocess
import datetime
import smbus
import math
import vlc

#Set up GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_UP) #Handset
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP) #Rotary Dial

#Set up Radio
instance = vlc.Instance('--input-repeat=-1', '--fullscreen')
player=instance.media_player_new()

ser = serial.Serial('/dev/ttyUSB0', 115200) # When GSM board is USB, otherwise for HAT use this: ser = serial.Serial('/dev/ttyS0', 115200)
ser.flushInput()

# Set up variables
currMode = "WAITING"
pulseCount=0
pulseTime = 0
numberToDial = ""
blackButtonPressed = False
greenLightOn = False
SIMResponse=""
people = ["Mark,0123456789,21", "Melanie,0123456789,22"]
callLog=","

def readBattery(address):
    data = bus.read_i2c_block_data(0x43, address, 2)
    return ((data[0] * 256 ) + data[1])

def writeBattery(address,data):
    temp = [0,0]
    temp[1] = data & 0xFF
    temp[0] =(data & 0xFF00) >> 8
    bus.write_i2c_block_data(0x43,address,temp)
    
def getBatteryVoltage():
    writeBattery(0x05,4096)
    readBattery(0x02)
    return (readBattery(0x02) >> 3) * 0.004

#Initiate Battery Checker
bus = smbus.SMBus(1);
writeBattery(0x05,4096)
config = 0x01 << 13 | 0x03 << 11 | 0x0D << 7 | 0x0D << 3 | 0x07
writeBattery(0x00,config)

#Read battery percentage
def readBatteryPercentage():
    bus_voltage = getBatteryVoltage()
    p = (bus_voltage - 3)/1.2*100
    if(p > 100):p = 100
    if(p < 0):p = 0
    return (p)

def playRadioStation(url):
    global numberToDial
    if url != "":
        media=instance.media_new(url)
        player.set_media(media)
        player.play()
    else:
        player.stop()
    numberToDial = ""
def updateWebSite():
    websiteFile = open("/var/www/html/index.html", "w")
    websiteFile.write("<HTML><HEAD><meta name='format-detection' content='telephone=no'></HEAD><BODY style='background-color:#000000'>")
    websiteFile.write("<style>.status {color:black;font-family:arial;font-size:300%;background-color: #00ff00;}.calls {color:blue;font-family:arial;font-size:300%}</style>")
    websiteFile.write("<br><center><p class='status'>" + currMode + "</p></center>")
    calls = callLog.split(",")
    for call in calls:
        websiteFile.write("<p class='calls'>" + call + "</p>")
    websiteFile.write("</BODY></HTML>")
    websiteFile.close()
    
updateWebSite()
subprocess.call(['amixer', 'sset', 'Master', '80%'], shell=False)
                
def isSIMReady():
    data=""
    ser.write("AT+CPIN?\r\n".encode())
    startCheckTime = time.perf_counter() 
    while time.perf_counter() < startCheckTime + 5 and data == "":
        while ser.inWaiting() > 0:
            data = data + str(ser.read(ser.inWaiting()))
            time.sleep(0.05)
    if "READY" in data:
        return True
    else:
        return False

# PowerOn/Reset GSM board
def resetSIM():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(4, GPIO.OUT)
    GPIO.output(4, GPIO.LOW)
    time.sleep(4)
    GPIO.output(4, GPIO.HIGH)
    time.sleep(20)

# Connect the call
def connectCall(phoneNumber):
    global currMode
    global numberToDial
    global callLog
    if isSIMReady() == False:
        speak("pleaseWait")
        resetSIM()
    currMode="CALL"
    command="ATD" + phoneNumber + ";\n"
    ser.write(command.encode('iso-8859-1'))
    callLog = str(datetime.datetime.now())[0:19] + " " + numberToDial + " Out," + callLog
    updateWebSite()
    numberToDial = ""

def speak(speechFile):
    subprocess.call("mpg321 /home/pi/mark/phone/sounds/" + speechFile + ".mp3", shell=True)

def greenLight(onOff):
    global greenLightOn
    if greenLightOn == True and onOff == "OFF":
        greenLightOn = False
        #TO DO: switch it off
    if greenLightOn == False and onOff == "ON":
        greenLightOn = True
        #TO DO: switch it on

if isSIMReady() == False:
    resetSIM()

speak("readyToDial")

greenLight("ON")
ser.write("AT+CPIN?\r\n".encode())  
while True:
    rotaryDial = GPIO.input(18)
    handsetDown = GPIO.input(16)

    if numberToDial != "":
        greenLight("OFF")

    # Check handset placed down
    if handsetDown == 1 and currMode == "CALL":
        print("1")
        ser.write("ATH;\n".encode('iso-8859-1'))      # Hang-Up
        currMode = "WAITING"
        greenLight("ON")
    if handsetDown == 0 and currMode == "RINGING":
        print("2")
        ser.write("ATA\n".encode('iso-8859-1'))       # Answer a call
        currMode = "CALL"
        greenLight("OFF")
    if handsetDown == 1 and numberToDial != "" and (numberToDial[0:1] == "0" or numberToDial[0:1] == "1"):       # Reset number
        print("3")
        numberToDial = ""
        currMode = "WAITING"
        greenLight("ON")

    # Check rotary dialling
    if rotaryDial == False:
        if currMode == "WAITING":
            currMode = "CLOCKWISE"
        if currMode == "ANTICLOCKWISE":
            pulseCount = pulseCount + 1
            pulseTime = time.perf_counter()
            currMode = "CLOCKWISE"
    else:
        if currMode == "CLOCKWISE":
            currMode = "ANTICLOCKWISE"
        if currMode == "ANTICLOCKWISE" and pulseTime > 0 and time.perf_counter() > pulseTime + 0.3:
            currMode = "WAITING"
            if pulseCount == 10:
                pulseCount = 0
            numberToDial = numberToDial + str(pulseCount)
            print(numberToDial)
            if numberToDial[0:1] == "0" and numberToDial[1:2] != "0" and len(numberToDial) == 11:  # UK landline
                connectCall(numberToDial)
            if numberToDial[0:2] == "00" and len(numberToDial) == 13:                              # International
                connectCall(numberToDial)
            if numberToDial[0:2] == "20":
                speak("speedDialMenu")
                numberToDial = ""
                for person in people:
                    speak("speedDial" + person.split(",")[2])
                    speak("name" + person.split(",")[0])
            if numberToDial[0:1] == "2" and len(numberToDial) > 1 and numberToDial[1:2] != "0":    # Speed Dial
                connectCall(people[int(numberToDial[1:2])-1].split(",")[1])
            if numberToDial[0:2] == "30":                                                          # Radio Off
                playRadioStation("")
            if numberToDial[0:2] == "31":                                                          # Radio Cheesy FM
                playRadioStation("http://listen-cheesyfm.sharp-stream.com/cheesyfm.mp3?ref=RF")
            if numberToDial[0:2] == "32":                                                          # Radio Absolute 80s
                playRadioStation("http://edge-bauerabsolute-05-gos2.sharp-stream.com/absolute80s.mp3")
            if numberToDial[0:2] == "33":                                                          # Radio Greatest Hits
                playRadioStation("http://tx.planetradio.co.uk/icecast.php?i=net2york.mp3")
            if numberToDial[0:1] == "4" and len(numberToDial) > 1:                                 # Volume
                if numberToDial[1:2] == "0":
                    volume = 100
                else:
                    volume = str(int(numberToDial[1:2]) * 10)
                subprocess.call(['amixer', 'sset', 'Master', volume + '%'], shell=False)
                numberToDial = ""
            if numberToDial[0:1] == "5":                                                           # Battery Percentage
                speak("battery" + str((round(math.floor(readBatteryPercentage() / 10)))*10))
                numberToDial = ""
            if numberToDial == "150":                                                              # Account Balance
                connectCall(numberToDial)
            pulseCount = 0
            pulseTime = 0
            
    # Check SIM messages
    if ser.inWaiting() > 0:
        SIMResponse = SIMResponse + str(ser.read(ser.inWaiting()))
    else:
        if SIMResponse != "":
            if "NO DIALTONE" in SIMResponse:
                ser.write("ATH;\n".encode('iso-8859-1'))  # Hang-Up
                currMode = "WAITING"
                updateWebSite()
                greenLight("ON")
                speak("noMobileSignal")
            if "RING" in SIMResponse:                     # Phone is ringing
                if currMode != "RINGING":
                    currMode = "RINGING"
                speak("ring")
                callingNumber = str(SIMResponse).split("\"")[1]
                callLog = str(datetime.datetime.now())[0:19] + " " + numberToDial + " In," + callLog
                updateWebSite()
                for person in people:
                    if person.split(",")[1] == callingNumber:
                        speak("name" + person.split(",")[0])
                        if "And" in person.split(",")[0]:
                            speak("areCalling")    
                        else:
                            speak("isCalling")
                    
            if currMode == "RINGING" and "RING" not in SIMResponse:
                currMode = "WAITING"
            print(SIMResponse)
            SIMResponse = ""

    time.sleep(0.005)

Credits

Mark Lister

Mark Lister

1 project • 2 followers
Started coding in 1980, only recently got into the Raspberry-Pi which allows my imagination to run wild :-)

Comments