#!/usr/bin/python
#
# LCD     SMC1602SA - 3V3 from embedded adventures

# Adapted from
# HD44780 LCD Test Script for Raspberry Pi
# Site   : http://www.raspberrypi-spy.co.uk
# 
#
# The wiring for the LCD is as follows:
# 1 : VSS GND
# 2 : VDD <= 3V3
# 3 : V0  bias
# 4 : DI  Data In
# 5 : CLK
# 6 : Enable or Strobe
# 15: LCD Backlight 3V3 or resistor to 5V
# 16: LCD Backlight GND

#import
import RPi.GPIO as GPIO
import time

# Define GPIO to LCD mapping
LCD_DI = 22
LCD_CLK= 23
LCD_E  = 24

# Define some 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
CLK_PULSE = 0.000006
CLK_DELAY = 0.000006
T_DELAY   = 0.000001
E_DELAY   = 0.000002

def main():
    # Main program block
    GPIO.setmode(GPIO.BCM)       # Use BCM GPIO numbers
    GPIO.setup(LCD_DI, GPIO.OUT) # DI
    GPIO.setup(LCD_CLK,GPIO.OUT) # CLK
    GPIO.setup(LCD_E,  GPIO.OUT) # E

    # Initialise display
    lcd_init()

    # Send some test
    lcd_byte(LCD_LINE_1, LCD_CMD)
    lcd_string("Rasbperry Pi")
    lcd_byte(LCD_LINE_2, LCD_CMD)
    lcd_string("Model B")

    time.sleep(3) # 3 second delay

    # Send some text
    lcd_byte(LCD_LINE_1, LCD_CMD)
    lcd_string("    embedded")
    lcd_byte(LCD_LINE_2, LCD_CMD)
    lcd_string(" adventures.com")

    time.sleep(20)

def lcd_init():
    # Initialise display
    lcd_byte(0x38,LCD_CMD)
    time.sleep(0.003)
    lcd_byte(0x38,LCD_CMD)
    time.sleep(0.003)
    lcd_byte(0x38,LCD_CMD)
    time.sleep(0.003)
    lcd_byte(0x38,LCD_CMD)
    time.sleep(0.003)
    lcd_byte(0x08,LCD_CMD)			# Display off
    lcd_byte(0x01,LCD_CMD)			# Clear screen
    time.sleep(0.003)
    lcd_byte(0x06,LCD_CMD)			# Cursor setting
    lcd_byte(0x0C,LCD_CMD)			# Display on

def lcd_string(message):
    # Send string to display

    message = message.ljust(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

    GPIO.output(LCD_DI, mode)
    time.sleep(T_DELAY)				# Set up Time
    GPIO.output(LCD_CLK, 0)			# Take CLK low
    time.sleep(CLK_PULSE)			# Wait 6 uS
    GPIO.output(LCD_CLK, 1)			# Take CLK high again
    time.sleep(CLK_DELAY)

    for i in range(8):
        GPIO.output(LCD_DI, bits&0x01 != 0)
        time.sleep(T_DELAY)			# Set up Time
        GPIO.output(LCD_CLK, 0)			# Take CLK low
        time.sleep(CLK_PULSE)			# Wait 6 uS
        GPIO.output(LCD_CLK, 1)			# Take CLK high again
        time.sleep(CLK_DELAY)
        bits = bits >> 1
    
    # Toggle 'Enable' pin
    time.sleep(T_DELAY)    
    GPIO.output(LCD_E, True)  
    time.sleep(E_DELAY)
    GPIO.output(LCD_E, False)  
    time.sleep(E_DELAY)   

if __name__ == '__main__':
  main()
