#!/usr/bin/python
from subprocess import *
import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

# toggle button pin
BUTTON = 18

# SPI port on the ADC MCP3008
SPICLK = 11     # CLK
SPIMISO = 9     # Dout
SPIMOSI = 10    # Din
SPICS = 25      # CS

# Define GPIO to LCD mapping
LCD_RS = 23
LCD_E  = 24
LCD_D4 = 4 
LCD_D5 = 17
LCD_D6 = 27
LCD_D7 = 22

# Define some LCD device constants
LCD_WIDTH = 16    # 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 for LCD
E_PULSE = 0.00005
E_DELAY = 0.00005
# delay for temperature readings / bounce time
DELAY = 2
BOUNCE = 300

# set up the SPI interface pins
GPIO.setup(SPIMOSI, GPIO.OUT)
GPIO.setup(SPIMISO, GPIO.IN)
GPIO.setup(SPICLK, GPIO.OUT)
GPIO.setup(SPICS, GPIO.OUT)
# set up the LCD interface pins
GPIO.setup(LCD_E, GPIO.OUT)
GPIO.setup(LCD_RS, GPIO.OUT)
GPIO.setup(LCD_D4, GPIO.OUT)
GPIO.setup(LCD_D5, GPIO.OUT)
GPIO.setup(LCD_D6, GPIO.OUT)
GPIO.setup(LCD_D7, GPIO.OUT)

# set up BUTTON as <in> and with internal pull-up resistor
GPIO.setup(BUTTON, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# temperature sensor connected channel 0 of mcp3008
adcnum = 0
# initial toggle-button state
button_state = 0
# initial temperature values
temp_cur = 0.0
temp_min = 0.0
temp_max = 0.0
temp_avg = 0.0

# initial strings
cmd_ip = "ip addr show wlan0 | grep inet | awk '{print $2}' | cut -d/ -f1"
cmd_date = "date +'%a, %d.%m.%Y '"
cmd_time = "date +'Es ist: %H:%M:%S'"
line1 = "Dies ist raspi2"
line2 = " ... bereit ..."

def run_cmd(cmd):
        p = Popen(cmd, shell=True, stdout=PIPE)
	output = p.communicate()[0]
	return output

# Initialise display
def lcd_init():
	global LCD_CMD
        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)

# send string to LCD  
def lcd_string(message):
        global LCD_WIDTH
        global LCD_CHR
        message = message.ljust(LCD_WIDTH," ")  
        for i in range(LCD_WIDTH):
                lcd_byte(ord(message[i]),LCD_CHR)

# Send byte to data pins
def lcd_byte(bits, mode):
        # bits = data
        # mode = True  for character
        #        False for command
	global LCD_RS
	global LCD_E
	global LCD_D4
	global LCD_D5
	global LCD_D6
	global LCD_D7
	global E_DELAY
	global E_PULSE
        GPIO.output(LCD_RS, mode) # RS
        # High bits
        GPIO.output(LCD_D4, False)
        GPIO.output(LCD_D5, False)
        GPIO.output(LCD_D6, False)
        GPIO.output(LCD_D7, False)
        if bits&0x10==0x10:
                GPIO.output(LCD_D4, True)
        if bits&0x20==0x20:
                GPIO.output(LCD_D5, True)
        if bits&0x40==0x40:
                GPIO.output(LCD_D6, True)
        if bits&0x80==0x80:
                GPIO.output(LCD_D7, True)
        # Toggle 'Enable' pin
        time.sleep(E_DELAY)    
        GPIO.output(LCD_E, True)  
        time.sleep(E_PULSE)
        GPIO.output(LCD_E, False)  
        time.sleep(E_DELAY)      
        # Low bits
        GPIO.output(LCD_D4, False)
        GPIO.output(LCD_D5, False)
        GPIO.output(LCD_D6, False)
        GPIO.output(LCD_D7, False)
        if bits&0x01==0x01:
                GPIO.output(LCD_D4, True)
        if bits&0x02==0x02:
                GPIO.output(LCD_D5, True)
        if bits&0x04==0x04:
                GPIO.output(LCD_D6, True)
        if bits&0x08==0x08:
                GPIO.output(LCD_D7, True)
        # Toggle 'Enable' pin
        time.sleep(E_DELAY)    
        GPIO.output(LCD_E, True)  
        time.sleep(E_PULSE)
        GPIO.output(LCD_E, False)  
        time.sleep(E_DELAY)    

# read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7)
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
        if ((adcnum > 7) or (adcnum < 0)):
                return -1
        GPIO.output(cspin, True)

        GPIO.output(clockpin, False)  # start clock low
        GPIO.output(cspin, False)     # bring CS low

        commandout = adcnum
        commandout |= 0x18  # start bit + single-ended bit
        commandout <<= 3    # we only need to send 5 bits here
        for i in range(5):
                if (commandout & 0x80):
                        GPIO.output(mosipin, True)
                else:   
                        GPIO.output(mosipin, False)
                commandout <<= 1
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)

        adcout = 0
        # read in one empty bit, one null bit and 10 ADC bits
        for i in range(12):
                GPIO.output(clockpin, True)
                GPIO.output(clockpin, False)
                adcout <<= 1
                if (GPIO.input(misopin)):
                        adcout |= 0x1

        GPIO.output(cspin, True)

        adcout /= 2       # first bit is 'null' so drop it
        return adcout

def output_ip():
        ip = run_cmd(cmd_ip)
        ip = "IP: " + ip
        return ip
def output_date():
        date = run_cmd(cmd_date)
        return date
        
def output_time():
        time = run_cmd(cmd_time)
        return time
        
def output_temp():
        # read the analog pin (temperature sensor LM35)
        read_adc0 = readadc(adcnum, SPICLK, SPIMOSI, SPIMISO, SPICS)
        # convert analog reading to millivolts = ADC * ( 3300 / 1024 )
        millivolts = read_adc0 * ( 3300.0 / 1024.0)
        # 10 mv per degree 
        temp_C = ((millivolts - 100.0) / 10.0) - 40.0
        # show only one decimal place for temprature and voltage readings
        temp_C = "%.1f" % temp_C
        
        return temp_C

def button_pressed(channel):  
        global button_state      
        button_state = button_state + 1
        if button_state==3:
                button_state = 0
      
####################################### Main ##############################################
lcd_init()
# add exception listener (for button pressed)
GPIO.add_event_detect(BUTTON, GPIO.FALLING, callback=button_pressed, bouncetime=BOUNCE)
# Initialise display
temp = output_temp()
temp_min = float(temp)
temp_max = float(temp)

try:
    #lcd_init() 
    while button_state < 3:
        temp = output_temp()
        if float(temp) > temp_max:
                temp_max = float(temp)
        if float(temp) < temp_min:
                temp_min = float(temp)

        if button_state==0:
                line1 = output_time()
                line2 = output_date() 
        
        if button_state==1:
                line1 = "aktuell: " + temp + " C"
                line2 = "mn/mx: " + str(temp_min) + "/" + str(temp_max)

        if button_state==2:
                line1 = "Dies ist raspi2"
                line2 = output_ip()                 
        
        lcd_byte(LCD_LINE_1, LCD_CMD)
        lcd_string(line1)
        lcd_byte(LCD_LINE_2, LCD_CMD)
        lcd_string(line2)
             
        time.sleep(DELAY)

    print "3x gedrueckt --> Ende !!."

except KeyboardInterrupt:
    GPIO.cleanup()       # clean up GPIO on CTRL+C exit
GPIO.cleanup()           # clean up GPIO on normal exit