#!/usr/bin/python
#
# Google Voice Dialer for
# Raspberry Pi
#
# Author : Rick Seiden (Based on the work of Matt Hawkins)
# Site   : http://www.raspberrypi-spy.co.uk
# 
# Date   : 10/20/2012
#



#import
import RPi.GPIO as GPIO
import time
from datetime import datetime
from googlevoice import Voice
from shifter import Shifter


# Define variables for Dialer
rows=[26,24,23,21,10]
cols=[19,18,16,12,8]

digits=[["1","2","3"],
        ["4","5","6"],
        ["","","9"],
        ["7","8","0"],
        ["","","","*","#"]]
colsPusehd=[False,False,False,False,False,False]


string1=""
string2=""

#Define functions for dialer

def setupCols():
    for col in cols:
        #print col
        GPIO.setup(col,GPIO.IN,pull_up_down=GPIO.PUD_UP)

def setupRows():
    for row in rows:
        GPIO.setup(row,GPIO.OUT)
        
def rowsHigh():
    for row in rows:
        #print row
        GPIO.output(row,GPIO.LOW)

def rowsLow():
    for row in rows:
        #print row
        GPIO.output(row,GPIO.HIGH)

def findRow(col):
    rowsLow()
    retVal=doFind(col)
    rowsHigh()
    return retVal

def doFind(col):
    rowsLow()
    for row in range(0,len(rows)):
        GPIO.output(rows[row],GPIO.LOW)
        if GPIO.input(col)==False:
            return row
    return -1


# Define Shifter to LCD mapping
LCD_RS = 16 #Bin value
LCD_E  = 32 #Bin value
LCD_D4 = 1 
LCD_D5 = 2
LCD_D6 = 4
LCD_D7 = 8


# Define some device constants
LCD_WIDTH = 40    # Maximum characters per line
LCD_CHR = True
LCD_CMD = False

LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line 

# Timing constants
E_PULSE = 0.00005
E_DELAY = 0.00005

def showStrings(top,bottom):
  lcd_byte(LCD_LINE_1, LCD_CMD)
  lcd_string(top)
  lcd_string(bottom)
    
def main():
  # Main program block
  string1=""
  string2=""

  # Declare state "constants"
  waiting=0
  dialing=1
  calling=2
  placing=3
  telling=4

  # Google Voice Setup
  voice=Voice()
  showStrings("","Logging in")
  try:
    voice.login()
  except:
    showStrings("","Error Loggin In")
    time.sleep(1)
  
  
  #set pins for dialer

  setupCols()
  setupRows()
  rowsHigh()


  # Initialise display
  lcd_init()

  
  running=True
  state=waiting
  
  while running==True:
    try:
      if (state==calling):
        try:
          voice.call(string1,"7165551212")
        except:
          showStrings(string1,"Error Calling")
        else:
          showStrings(string1,"Call Placed")
        time.sleep(1)
        state=waiting
      if (state==waiting):
        showStrings("","Waiting")
      #Poll Dialer
      lenCols=len(cols)
      for col in range(0,lenCols):
        time.sleep(0.01)
        if GPIO.input(cols[col])==False:
          if colsPusehd[col]==False:
            #print str(cols[col])+" Pushed"
            activeRow=findRow(cols[col])                
            if activeRow>-1:
              #print(activeRow,col)
              #print digits[activeRow][col]
              keyPressed=digits[activeRow][col]
              if (state==waiting):
                  showStrings("","Waiting")
                  if (keyPressed=="*"):
                      state=dialing
                      string1=""
                      showStrings(string1,"Dialing")
              elif (state==dialing):
                if (keyPressed=="*"):
                  string1=""
                  showStrings(string1,"Dialing")
                elif (keyPressed=="#"):
                  state=calling
                  showStrings(string1,"Calling")
                else:
                  string1=string1+digits[activeRow][col]
                  showStrings(string1,"Dialing")
            time.sleep(0.1)                    
            colsPusehd[col]=True
        else:
          if colsPusehd[col]==True:
            #print str(cols[col])+" Released"
            time.sleep(0.1)
            colsPusehd[col]=False      

      
    except (KeyboardInterrupt):
      running=False

  lcd_byte(0x01,LCD_CMD)
def lcd_init():
  # Initialise display
  lcd_byte(0x33,LCD_CMD)
  lcd_byte(0x32,LCD_CMD)
  lcd_byte(0x28,LCD_CMD)
  lcd_byte(0x0C,LCD_CMD)  
  lcd_byte(0x06,LCD_CMD)
  lcd_byte(0x01,LCD_CMD)  

def lcd_string(message):
  # Send string to display

  message = message.center(LCD_WIDTH," ")  

  for i in range(LCD_WIDTH):
    lcd_byte(ord(message[i]),LCD_CHR)

def lcd_byte(bits, mode):
  # Send byte to data pins
  # bits = data
  # mode = True  for character
  #        False for command

  if (mode==True):
    value=LCD_RS
  else:
    value=0

  # High bits
  if bits&0x10==0x10:
    value=value+LCD_D4
  if bits&0x20==0x20:
    value=value+LCD_D5
  if bits&0x40==0x40:
    value=value+LCD_D6
  if bits&0x80==0x80:
    value=value+LCD_D7
  #print (value)
  # Toggle 'Enable' pin
  value=value+LCD_E
  time.sleep(E_DELAY)
  shifter.setValue(value)
  time.sleep(E_PULSE)
  shifter.clear()
  time.sleep(E_DELAY)      

  # Low bits
  if (mode==True):
    value=LCD_RS
  else:
    value=0
  if bits&0x01==0x01:
    value=value+LCD_D4
  if bits&0x02==0x02:
    value=value+LCD_D5
  if bits&0x04==0x04:
    value=value+LCD_D6
  if bits&0x08==0x08:
    value=value+LCD_D7

  # Toggle 'Enable' pin
  value=value+LCD_E
  time.sleep(E_DELAY)
  shifter.setValue(value)
  time.sleep(E_PULSE)
  shifter.clear()
  time.sleep(E_DELAY)
  
if __name__ == '__main__':
  GPIO.setmode(GPIO.BOARD)
  shifter=Shifter()
  main()

