diff --git a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py index 12e4cdf8..b5da2bc1 100644 --- a/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py +++ b/Adafruit_CharLCDPlate/Adafruit_CharLCDPlate.py @@ -1,303 +1,388 @@ -#!/usr/bin/pythonhttp://raspberrypi.local/editor - -# -# based on code from lrvick and LiquidCrystal -# lrvic - https://github.com/lrvick/raspi-hd44780/blob/master/hd44780.py -# LiquidCrystal - https://github.com/arduino/Arduino/blob/master/libraries/LiquidCrystal/LiquidCrystal.cpp -# - -from time import sleep -from Adafruit_I2C import Adafruit_I2C -from Adafruit_MCP230xx import Adafruit_MCP230XX -import smbus - - -class Adafruit_CharLCDPlate: - - OUTPUT = 0 - INPUT = 1 - - # LED colors - RED = 0x01 - GREEN = 0x02 - BLUE = 0x04 - YELLOW = 0x03 - TEAL = 0x06 - VIOLET = 0x05 - ON = 0x07 - OFF = 0x0 - - # buttons - SELECT = 0 - RIGHT = 1 - DOWN = 2 - UP = 3 - LEFT = 4 - - # commands - LCD_CLEARDISPLAY = 0x01 - LCD_RETURNHOME = 0x02 - LCD_ENTRYMODESET = 0x04 - LCD_DISPLAYCONTROL = 0x08 - LCD_CURSORSHIFT = 0x10 - LCD_FUNCTIONSET = 0x20 - LCD_SETCGRAMADDR = 0x40 - LCD_SETDDRAMADDR = 0x80 - - # flags for display entry mode - LCD_ENTRYRIGHT = 0x00 - LCD_ENTRYLEFT = 0x02 - LCD_ENTRYSHIFTINCREMENT = 0x01 - LCD_ENTRYSHIFTDECREMENT = 0x00 - - # flags for display on/off control - LCD_DISPLAYON = 0x04 - LCD_DISPLAYOFF = 0x00 - LCD_CURSORON = 0x02 - LCD_CURSOROFF = 0x00 - LCD_BLINKON = 0x01 - LCD_BLINKOFF = 0x00 - - # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 - - # flags for display/cursor shift - LCD_DISPLAYMOVE = 0x08 - LCD_CURSORMOVE = 0x00 - LCD_MOVERIGHT = 0x04 - LCD_MOVELEFT = 0x00 - - # flags for function set - LCD_8BITMODE = 0x10 - LCD_4BITMODE = 0x00 - LCD_2LINE = 0x08 - LCD_1LINE = 0x00 - LCD_5x10DOTS = 0x04 - LCD_5x8DOTS = 0x00 - - - - - def __init__(self, busnum=0, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): - self.pin_rs = pin_rs - self.pin_e = pin_e - self.pin_rw = pin_rw - self.pins_db = pins_db - - self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) - - self.mcp.config(self.pin_e, self.OUTPUT) - self.mcp.config(self.pin_rs, self.OUTPUT) - self.mcp.config(self.pin_rw, self.OUTPUT) - self.mcp.output(self.pin_rw, 0) - self.mcp.output(self.pin_e, 0) - - for pin in self.pins_db: - self.mcp.config(pin, self.OUTPUT) - - self.write4bits(0x33) # initialization - self.write4bits(0x32) # initialization - self.write4bits(0x28) # 2 line 5x7 matrix - self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor - self.write4bits(0x06) # shift cursor right - - self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF - - self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS - self.displayfunction |= self.LCD_2LINE - - """ Initialize to default text direction (for romance languages) """ - self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode - - # turn on backlights! - self.mcp.config(6, self.mcp.OUTPUT) - self.mcp.config(7, self.mcp.OUTPUT) - self.mcp.config(8, self.mcp.OUTPUT) - self.mcp.output(6, 0) # red - self.mcp.output(7, 0) # green - self.mcp.output(8, 0) # blue - - # turn on pullups - self.mcp.pullup(self.SELECT, True) - self.mcp.pullup(self.LEFT, True) - self.mcp.pullup(self.RIGHT, True) - self.mcp.pullup(self.UP, True) - self.mcp.pullup(self.DOWN, True) - self.mcp.config(self.SELECT, self.mcp.INPUT) - self.mcp.config(self.LEFT, self.mcp.INPUT) - self.mcp.config(self.RIGHT, self.mcp.INPUT) - self.mcp.config(self.DOWN, self.mcp.INPUT) - self.mcp.config(self.UP, self.mcp.INPUT) - - def begin(self, cols, lines): - if (lines > 1): - self.numlines = lines - self.displayfunction |= self.LCD_2LINE - self.currline = 0 - self.clear() - - def home(self): - self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero - self.delayMicroseconds(2000) # this command takes a long time! - - def clear(self): - self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display - self.delayMicroseconds(2000) # 2000 microsecond sleep, clearing the display takes a long time - - def setCursor(self, col, row): - self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] - if ( row > self.numlines ): - row = self.numlines - 1 # we count rows starting w/0 - self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row])) - - def noDisplay(self): - """ Turn the display off (quickly) """ - self.displaycontrol &= ~self.LCD_DISPLAYON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def display(self): - """ Turn the display on (quickly) """ - self.displaycontrol |= self.LCD_DISPLAYON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def noCursor(self): - """ Turns the underline cursor on/off """ - self.displaycontrol &= ~self.LCD_CURSORON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - - def cursor(self): - """ Cursor On """ - self.displaycontrol |= self.LCD_CURSORON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def noBlink(self): - """ Turn on and off the blinking cursor """ - self.displaycontrol &= ~self.LCD_BLINKON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def noBlink(self): - """ Turn on and off the blinking cursor """ - self.displaycontrol &= ~self.LCD_BLINKON - self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) - - def DisplayLeft(self): - """ These commands scroll the display without changing the RAM """ - self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) - - def scrollDisplayRight(self): - """ These commands scroll the display without changing the RAM """ - self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT); - - def leftToRight(self): - """ This is for text that flows Left to Right """ - self.displaymode |= self.LCD_ENTRYLEFT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode); - - def rightToLeft(self): - """ This is for text that flows Right to Left """ - self.displaymode &= ~self.LCD_ENTRYLEFT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) - - def autoscroll(self): - """ This will 'right justify' text from the cursor """ - self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) - - def noAutoscroll(self): - """ This will 'left justify' text from the cursor """ - self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT - self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) - - def write4bits(self, bits, char_mode=False): - """ Send command to LCD """ - #self.delayMicroseconds(1000) # 1000 microsecond sleep - bits=bin(bits)[2:].zfill(8) - self.mcp.output(self.pin_rs, char_mode) - - for i in range(4): - if bits[i] == "1": - self.mcp.output(self.pins_db[::-1][i], True) - else: - self.mcp.output(self.pins_db[::-1][i], False) - self.pulseEnable() - - for i in range(4,8): - if bits[i] == "1": - self.mcp.output(self.pins_db[::-1][i-4], True) - else: - self.mcp.output(self.pins_db[::-1][i-4], False) - self.pulseEnable() - - def delayMicroseconds(self, microseconds): - seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds - sleep(seconds) - - def pulseEnable(self): - self.mcp.output(self.pin_e, True) - self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns - self.mcp.output(self.pin_e, False) - #self.delayMicroseconds(1) # commands need > 37us to settle - - def message(self, text): - """ Send string to LCD. Newline wraps to second line""" - for char in text: - if char == '\n': - self.write4bits(0xC0) # next line - else: - self.write4bits(ord(char),True) - - def backlight(self, color): - self.mcp.output(6, not color & 0x01) - self.mcp.output(7, not color & 0x02) - self.mcp.output(8, not color & 0x04) - - def buttonPressed(self, buttonname): - if (buttonname > self.LEFT): - return false - - return not self.mcp.input(buttonname) - - -if __name__ == '__main__': - - lcd = Adafruit_CharLCDPlate(busnum = 0) - lcd.clear() - lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") - sleep(1) - while 1: - if (lcd.buttonPressed(lcd.LEFT)): - lcd.backlight(lcd.RED) - - if (lcd.buttonPressed(lcd.UP)): - lcd.backlight(lcd.BLUE) - - if (lcd.buttonPressed(lcd.DOWN)): - lcd.backlight(lcd.GREEN) - - if (lcd.buttonPressed(lcd.RIGHT)): - lcd.backlight(lcd.VIOLET) - - if (lcd.buttonPressed(lcd.SELECT)): - lcd.backlight(lcd.ON) - - - while 1: - lcd.backlight(lcd.RED) - sleep(1) - lcd.backlight(lcd.YELLOW) - sleep(1) - lcd.backlight(lcd.GREEN) - sleep(1) - lcd.backlight(lcd.TEAL) - sleep(1) - lcd.backlight(lcd.BLUE) - sleep(1) - lcd.backlight(lcd.VIOLET) - sleep(1) - lcd.backlight(lcd.ON) - sleep(1) - lcd.backlight(lcd.OFF) - sleep(1) +#!/usr/bin/pythonhttp://raspberrypi.local/editor + +# +# based on code from lrvick and LiquidCrystal +# lrvic - https://github.com/lrvick/raspi-hd44780/blob/master/hd44780.py +# LiquidCrystal - https://github.com/arduino/Arduino/blob/master/libraries/LiquidCrystal/LiquidCrystal.cpp + + +from time import sleep +from Adafruit_I2C import Adafruit_I2C +from Adafruit_MCP230xx import Adafruit_MCP230XX +import smbus + + +class Adafruit_CharLCDPlate: + + OUTPUT = 0 + INPUT = 1 + + # LED colors + RED = 0x01 + GREEN = 0x02 + BLUE = 0x04 + YELLOW = 0x03 + TEAL = 0x06 + VIOLET = 0x05 + ON = 0x07 + OFF = 0x0 + + # buttons + SELECT = 0 + RIGHT = 1 + DOWN = 2 + UP = 3 + LEFT = 4 + + # commands + LCD_CLEARDISPLAY = 0x01 + LCD_RETURNHOME = 0x02 + LCD_ENTRYMODESET = 0x04 + LCD_DISPLAYCONTROL = 0x08 + LCD_CURSORSHIFT = 0x10 + LCD_FUNCTIONSET = 0x20 + LCD_SETCGRAMADDR = 0x40 + LCD_SETDDRAMADDR = 0x80 + + # flags for display entry mode + LCD_ENTRYRIGHT = 0x00 + LCD_ENTRYLEFT = 0x02 + LCD_ENTRYSHIFTINCREMENT = 0x01 + LCD_ENTRYSHIFTDECREMENT = 0x00 + + # flags for display on/off control + LCD_DISPLAYON = 0x04 + LCD_DISPLAYOFF = 0x00 + LCD_CURSORON = 0x02 + LCD_CURSOROFF = 0x00 + LCD_BLINKON = 0x01 + LCD_BLINKOFF = 0x00 + + # flags for display/cursor shift + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 + + # flags for display/cursor shift + LCD_DISPLAYMOVE = 0x08 + LCD_CURSORMOVE = 0x00 + LCD_MOVERIGHT = 0x04 + LCD_MOVELEFT = 0x00 + + # flags for function set + LCD_8BITMODE = 0x10 + LCD_4BITMODE = 0x00 + LCD_2LINE = 0x08 + LCD_1LINE = 0x00 + LCD_5x10DOTS = 0x04 + LCD_5x8DOTS = 0x00 + + + + + def __init__(self, busnum=1, pin_rs=15, pin_e=13, pins_db=[12, 11, 10, 9], pin_rw=14): + self.pin_rs = pin_rs + self.pin_e = pin_e + self.pin_rw = pin_rw + self.pins_db = pins_db + + self.mcp = Adafruit_MCP230XX(busnum = busnum, address = 0x20, num_gpios = 16) + + self.mcp.config(self.pin_e, self.OUTPUT) + self.mcp.config(self.pin_rs, self.OUTPUT) + self.mcp.config(self.pin_rw, self.OUTPUT) + self.mcp.output(self.pin_rw, 0) + self.mcp.output(self.pin_e, 0) + + for pin in self.pins_db: + self.mcp.config(pin, self.OUTPUT) + + self.write4bits(0x33) # initialization + self.write4bits(0x32) # initialization + self.write4bits(0x28) # 2 line 5x8 matrix + self.write4bits(0x0C) # turn cursor off 0x0E to enable cursor + self.write4bits(0x06) # set cursor incrementing and no shift of display + + self.displaycontrol = self.LCD_DISPLAYON | self.LCD_CURSOROFF | self.LCD_BLINKOFF + + self.displayfunction = self.LCD_4BITMODE | self.LCD_1LINE | self.LCD_5x8DOTS + self.displayfunction |= self.LCD_2LINE + + """ Initialize to default text direction (for romance languages) """ + self.displaymode = self.LCD_ENTRYLEFT | self.LCD_ENTRYSHIFTDECREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) # set the entry mode + + # turn on backlights! + self.mcp.config(6, self.mcp.OUTPUT) + self.mcp.config(7, self.mcp.OUTPUT) + self.mcp.config(8, self.mcp.OUTPUT) + self.mcp.output(6, 0) # red + self.mcp.output(7, 0) # green + self.mcp.output(8, 0) # blue + + # turn on pullups + self.mcp.pullup(self.SELECT, True) + self.mcp.pullup(self.LEFT, True) + self.mcp.pullup(self.RIGHT, True) + self.mcp.pullup(self.UP, True) + self.mcp.pullup(self.DOWN, True) + self.mcp.config(self.SELECT, self.mcp.INPUT) + self.mcp.config(self.LEFT, self.mcp.INPUT) + self.mcp.config(self.RIGHT, self.mcp.INPUT) + self.mcp.config(self.DOWN, self.mcp.INPUT) + self.mcp.config(self.UP, self.mcp.INPUT) + + def begin(self, cols, lines): + if (lines > 1): + self.numlines = lines + self.displayfunction |= self.LCD_2LINE + self.currline = 0 + self.clear() + + def home(self): + self.write4bits(self.LCD_RETURNHOME) # set cursor position to zero + self.waitBFlow() #wait for Busy flag low + + + def clear(self): + self.write4bits(self.LCD_CLEARDISPLAY) # command to clear display + self.waitBFlow() #wait for Busy flag low + + def setCursor(self, col, row): + self.row_offsets = [ 0x00, 0x40, 0x14, 0x54 ] + if ( row > self.numlines ): + row = self.numlines - 1 # we count rows starting w/0 + self.write4bits(self.LCD_SETDDRAMADDR | (col + self.row_offsets[row])) + + def noDisplay(self): + """ Turn the display off (quickly) """ + self.displaycontrol &= ~self.LCD_DISPLAYON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def display(self): + """ Turn the display on (quickly) """ + self.displaycontrol |= self.LCD_DISPLAYON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def noCursor(self): + """ underline cursor off """ + self.displaycontrol &= ~self.LCD_CURSORON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + + def cursor(self): + """ underline Cursor On """ + self.displaycontrol |= self.LCD_CURSORON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def ToggleCursor(self): + """ Toggles the underline cursor On/Off bb""" + self.displaycontrol ^= self.LCD_CURSORON + self.delayMicroseconds(200000) + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def noBlink(self): + """ Turn off the blinking cursor """ + self.displaycontrol &= ~self.LCD_BLINKON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def blink(self): + """ Turn on the blinking cursor""" + self.displaycontrol |= self.LCD_BLINKON + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + def ToggleBlink(self): + """ Toggles the blinking cursor""" + self.displaycontrol ^= self.LCD_BLINKON + self.delayMicroseconds(200000) + self.write4bits(self.LCD_DISPLAYCONTROL | self.displaycontrol) + + + def DisplayLeft(self): + """ These commands scroll the display without changing the RAM """ + self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVELEFT) + + def scrollDisplayRight(self): + """ These commands scroll the display without changing the RAM """ + self.write4bits(self.LCD_CURSORSHIFT | self.LCD_DISPLAYMOVE | self.LCD_MOVERIGHT); + + def leftToRight(self): + """ This is for text that flows Left to Right """ + self.displaymode |= self.LCD_ENTRYLEFT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode); + + def rightToLeft(self): + """ This is for text that flows Right to Left """ + self.displaymode &= ~self.LCD_ENTRYLEFT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) + + def autoscroll(self): + """ This will 'right justify' text from the cursor """ + self.displaymode |= self.LCD_ENTRYSHIFTINCREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) + + def noAutoscroll(self): + """ This will 'left justify' text from the cursor """ + self.displaymode &= ~self.LCD_ENTRYSHIFTINCREMENT + self.write4bits(self.LCD_ENTRYMODESET | self.displaymode) + + def write4bits(self, bits, char_mode=False): + """ Send command to LCD """ + #self.delayMicroseconds(1000) # 1000 microsecond sleep + bits=bin(bits)[2:].zfill(8) + self.mcp.output(self.pin_rs, char_mode) + + for i in range(4): + if bits[i] == "1": + self.mcp.output(self.pins_db[::-1][i], True) + else: + self.mcp.output(self.pins_db[::-1][i], False) + self.pulseEnable() + + for i in range(4,8): + if bits[i] == "1": + self.mcp.output(self.pins_db[::-1][i-4], True) + else: + self.mcp.output(self.pins_db[::-1][i-4], False) + self.pulseEnable() + + #See pg. 24 and 58 HD44780.pdf and http://www.avrbeginners.net/ Standard LCD bit mode + def read4bits(self, char_mode=False): + """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ +# print "First:", bin(self.mcp.direction)[2:].zfill(16) + self.mcp.output(self.pin_rs, char_mode) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data + self.mcp.output(self.pin_rw, 1) #set rw to 1 + # Configure pins for input + makeinput=True + if makeinput: + for pin in self.pins_db: + self.mcp.config(pin, self.INPUT) + self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble + bits = range(8) + # get the pins values + for i in range(4): + bt = self.mcp.input(self.pins_db[::-1][i], makeinput) # if makeinput is False, pin direction checking is supressed in input + bits[i]=bt + #print i,bt,bits[i] + self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble + self.mcp.output(self.pin_e, True) # set Enable high and keep while read 2nd nibble + # get the pins values + for i in range(4,8): + bt = self.mcp.input(self.pins_db[::-1][i-4],makeinput) + bits[i]=bt + #print i,bt,bits[i] + self.mcp.output(self.pin_e, False) # set Enable low to finish 2nd nibble + # restore the pins to output and rw to 0 + for pin in self.pins_db: + self.mcp.config(pin, self.OUTPUT) + self.mcp.output(self.pin_rw, 0) # return rw to 0 +# print "Last :", bin(self.mcp.direction)[2:].zfill(16) + return bits; + + def readBF(self): + """ Get Data from LCD, when char_mode = 0 get Busy Flag and Address Counter, else get RAM data """ +# print "First:", bin(self.mcp.direction)[2:].zfill(16) + self.mcp.output(self.pin_rs, 0) # when char_mode = 0 get Busy Flag and Address Counter, else get RAM data + self.mcp.output(self.pin_rw, 1) #set rw to 1 + # Configure pins for input + makeinput=True + self.mcp.config(self.pins_db[::-1][1], self.INPUT) + self.mcp.output(self.pin_e, True) # set Enable high and keep while read first nibble + # get the pins values + bt = self.mcp.input(self.pins_db[::-1][1], makeinput) # if makeinput is False, pin direction checking is supressed in input + self.mcp.output(self.pin_e, False) # set Enable low to finish first nibble + self.pulseEnable() # one more pulse to get (but ingore the 2nd nibble) + # restore the pins to output and rw to 0 + self.mcp.config(self.pins_db[::-1][1], self.OUTPUT) + self.mcp.output(self.pin_rw, 0) # return rw to 0 + return bt==1 + + def waitBFlow(self): + for cnt in range(100000): + if not self.readBF(): + #print cnt + return + print "timed out of waitBFlow" + + def delayMicroseconds(self, microseconds): + seconds = microseconds / 1000000 # divide microseconds by 1 million for seconds + sleep(seconds) + + def pulseEnable(self): + self.mcp.output(self.pin_e, True) + self.delayMicroseconds(1) # 1 microsecond pause - enable pulse must be > 450ns + self.mcp.output(self.pin_e, False) + #self.delayMicroseconds(1) # commands need > 37us to settle + + def message(self, text): + """ Send string to LCD. Newline wraps to second line""" + for char in text: + if char == '\n': + self.write4bits(0xC0) # set DDRAM address 0x40 start of second line + else: + self.write4bits(ord(char),True) + + def backlight(self, color): + self.mcp.output(6, not color & 0x01) + self.mcp.output(7, not color & 0x02) + self.mcp.output(8, not color & 0x04) + + def buttonPressed(self, buttonname): + if (buttonname > self.LEFT): + return false + + return not self.mcp.input(buttonname) + + +if __name__ == '__main__': + + lcd = Adafruit_CharLCDPlate(busnum = 1) + lcd.clear() + lcd.message("Adafruit RGB LCD\nPlate w/Keypad!") + sleep(1) + + print " Cycle thru backlight colors 3 times " + + for i in range(3): + print "red" + lcd.backlight(lcd.RED) + sleep(1) + print "yellow" + lcd.backlight(lcd.YELLOW) + sleep(1) + print "green" + lcd.backlight(lcd.GREEN) + sleep(1) + print "teal" + lcd.backlight(lcd.TEAL) + sleep(1) + print "blue" + lcd.backlight(lcd.BLUE) + sleep(1) + print "violet" + lcd.backlight(lcd.VIOLET) + sleep(1) + print "off" + lcd.backlight(lcd.OFF) + sleep(1) + print "on" + lcd.backlight(lcd.ON) + sleep(1) + + print " Try buttons on plate" + + while 1: + if (lcd.buttonPressed(lcd.LEFT)): + lcd.backlight(lcd.RED) + + if (lcd.buttonPressed(lcd.UP)): + lcd.backlight(lcd.BLUE) + + if (lcd.buttonPressed(lcd.DOWN)): + lcd.backlight(lcd.GREEN) + + if (lcd.buttonPressed(lcd.RIGHT)): + lcd.backlight(lcd.VIOLET) + + if (lcd.buttonPressed(lcd.SELECT)): + lcd.backlight(lcd.ON) + diff --git a/Adafruit_CharLCDPlate/NewLCDTest.py b/Adafruit_CharLCDPlate/NewLCDTest.py new file mode 100644 index 00000000..7210de6b --- /dev/null +++ b/Adafruit_CharLCDPlate/NewLCDTest.py @@ -0,0 +1,566 @@ +#!/usr/bin/python +# mod by bb 29 Jan 2013 + +from time import sleep +from random import randint +from Adafruit_I2C import Adafruit_I2C +from Adafruit_MCP230xx import Adafruit_MCP230XX +from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate +#from Adafruit_MCP230xx import MCP23017_GPIOB, MCP23017_IODIRB +MCP23017_IODIRA = 0x00 +MCP23017_IODIRB = 0x01 +MCP23017_GPIOA = 0x12 +MCP23017_GPIOB = 0x13 +MCP23017_GPPUA = 0x0C +MCP23017_GPPUB = 0x0D +MCP23017_OLATA = 0x14 +MCP23017_OLATB = 0x15 +import smbus + + +def binfill(num,len=8): + return bin(num)[2:].zfill(len) + +ReverseNib = [0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15] + +def cur_right(num=1): # note num = 40 in 2 lines mode moves up/down to other line + for cnt in range(num): + lcd.mcp.write8(0x30, MCP23017_GPIOB) #RS=0, R/W=0, E=1, high nibble of lcd command reversed, 0. Going high sends this to LCD as hi bits of instruction code + lcd.mcp.write8(0x04, MCP23017_GPIOB) #RS=0, R/W=0, E=0, low nibble of lcd command reversed, 0 + lcd.mcp.write8(0x24, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(0x04, MCP23017_GPIOB) #same as line two to send E low to finish + +def cur_left(num=1): + for cnt in range(num): + lcd.mcp.write8(0x30, MCP23017_GPIOB) #RS=0, R/W=0, E=1, high nibble of lcd command reversed, 0. Going high sends this to LCD as hi bits of instruction code + lcd.mcp.write8(0x00, MCP23017_GPIOB) #RS=0, R/W=0, E=0, low nibble of lcd command reversed, 0 + lcd.mcp.write8(0x20, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(0x00, MCP23017_GPIOB) #same as line two to send E low to finish + +def display_right(num=1): # note num = 40 in 2 lines mode moves up/down to other line + for cnt in range(num): + lcd.mcp.write8(0x30, MCP23017_GPIOB) #RS=0, R/W=0, E=1, high nibble of lcd command reversed, 0. Going high sends this to LCD as hi bits of instruction code + lcd.mcp.write8(0x06, MCP23017_GPIOB) #RS=0, R/W=0, E=0, low nibble of lcd command reversed, 0 + lcd.mcp.write8(0x26, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(0x06, MCP23017_GPIOB) #same as line two to send E low to finish + +def cur_pos(num=0): +# i.e. Set DDRAM address - the cursor will move to this address +# Note +# in two line mode DDRAM 0 to 39 is first line +# DDRAM 64 to 39+64 is second line +# using num from 40 till 63 will set DDRAM to 64 +# using num from above 39+64 will set DDRAM to 0 +# in one line mode DDRAM goes from 0 to 79 and setting above will go to 0 + # make num become the instruction code for Set DDRAM address + num &= 0x7f # truncate num to 7 bits + num |= 0x80 # make highest bit 1 + # make first byte to send which contains the reverse high nibble of num + hinum = (num & 0xf0) >> 4 + byte1 = 0x20 | (ReverseNib[hinum] << 1) # RS=0, R/W = 0, E = 1, high nibble of lcd command reversed, 0. + lonum = (num & 0xf) + byte2 = (ReverseNib[lonum] << 1) # RS=0, R/W = 0, E = 0, low nibble of lcd command reversed, 0. + #print "num = ", bin8(num), "hinum = ", bin8(hinum), "lonum = ", bin8(lonum) + #print "byte1 = ", bin8(byte1), "byte2 = ", bin8(byte2) + lcd.mcp.write8(byte1, MCP23017_GPIOB) #Going high sends this to LCD as hi bits of instruction code + lcd.mcp.write8(byte2, MCP23017_GPIOB) # E goes low + lcd.mcp.write8(0x20 | byte2, MCP23017_GPIOB) # going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(byte2, MCP23017_GPIOB) # send E low to finish + +def setCGRAMadd(num=0): +# i.e. Set CGRAM address - Write/Read Data from RAM after this will use Character Graphic RAM + # make num become the instruction code for Set CGRAM address + num &= 0x3f # truncate num to 6 bits + num |= 0x40 # make 2nd to highest bit 1 + # make first byte to send which contains the reverse high nibble of num + hinum = (num & 0xf0) >> 4 + byte1 = 0x20 | (ReverseNib[hinum] << 1) # RS=0, R/W = 0, E = 1, high nibble of lcd command reversed, 0. + lonum = (num & 0xf) + byte2 = (ReverseNib[lonum] << 1) # RS=0, R/W = 0, E = 0, low nibble of lcd command reversed, 0. + print "num = ", binfill(num), "hinum = ", binfill(hinum), "lonum = ", binfill(lonum) + print "byte1 = ", binfill(byte1), "byte2 = ", binfill(byte2) + lcd.mcp.write8(byte1, MCP23017_GPIOB) #Going high sends this to LCD as hi bits of instruction code + lcd.mcp.write8(byte2, MCP23017_GPIOB) # E goes low + lcd.mcp.write8(0x20 | byte2, MCP23017_GPIOB) # going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(byte2, MCP23017_GPIOB) # send E low to finish + +def general_cmd(cmd,RS=0,RW=0,debug=0): +# execute a general command for the LCD TC1602A-01T +# cmd are the 8 bits of instuction code from table pg. 11 +# if cmd is a read command (RW = 1) the value read is returned + # make first byte to send which contains the reverse high nibble of cmd + RSbit=0x80 if RS else 0x00 + RWbit=0x40 if RW else 0x00 + Ebit = 0x20 + hicmd = (cmd & 0xf0) >> 4 + byte1 = RSbit | RWbit | Ebit | (ReverseNib[hicmd] << 1) # RS,RW, E = 1, high nibble of lcd command reversed, 0. + locmd = (cmd & 0xf) + byte2 = RSbit | RWbit | (ReverseNib[locmd] << 1) # RS,RW, E = 0, low nibble of lcd command reversed, 0. + if debug: + print "cmd = ", binfill(cmd), "hinum = ", binfill(hicmd), "locmd = ", binfill(locmd) + print "byte1 = ", binfill(byte1), "byte2 = ", binfill(byte2) + lcd.mcp.write8(byte1, MCP23017_GPIOB) #Going high sends this to LCD as hi bits of instruction code + if RW: + currentiodir = lcd.mcp.readU8(MCP23017_IODIRB) # save entering state of input/output for pins from 8-15 + lcd.mcp.write8(0b00011110 | currentiodir, MCP23017_IODIRB) # configure input for pins 9-12 which are 4-7 in GPB + num = lcd.mcp.readU8(MCP23017_GPIOB) # get input which will contain reversed high nibble from LCD + hinum = ReverseNib[(num & 0b00011110) >> 1] # extract the 4 bits and reverse + lcd.mcp.write8(byte2, MCP23017_GPIOB) # E goes low + lcd.mcp.write8(Ebit | byte2, MCP23017_GPIOB) # going high sends this nibble to LCD as low bits of instruction code + if RW: + num = lcd.mcp.readU8(MCP23017_GPIOB) # get input which will contain reversed low nibble from LCD + lonum = ReverseNib[(num & 0b00011110) >> 1] # extract the 4 bits and reverse + if RW: + lcd.mcp.write8(currentiodir, MCP23017_IODIRB) # restore pins input/output to state upon entering this routine + lcd.mcp.write8(0x00, MCP23017_GPIOB) # send all low to finish and be compatible with other CarLCDPlate routines + if RW: + return (hinum << 4) | lonum + +def readfast(ram=False): +# read BF and AC or RAM Data + if ram: + cmdhi = 0xe0 + cmdlo = 0xc0 + else: + cmdhi = 0x60 + cmdlo = 0x40 + lcd.mcp.write8(0b00011111, MCP23017_IODIRB) # configure so input on pins 9-12 which are 4-7 in GPB + lcd.mcp.write8(cmdhi, MCP23017_GPIOB) #Going high prepares to record first nibble info + num = lcd.mcp.readU8(MCP23017_GPIOB) # get input which will contain reversed high nibble from LCD + hinum = ReverseNib[(num & 0b00011110) >> 1] # extract the 4 bits and reverse# extract the 4 bits and reverse + lcd.mcp.write8(cmdlo, MCP23017_GPIOB) # E goes low + lcd.mcp.write8(cmdhi, MCP23017_GPIOB) # going high prepares to recond second nibble info + num = lcd.mcp.readU8(MCP23017_GPIOB) # get input which will contain reversed low nibble from LCD + lonum = ReverseNib[(num & 0b00011110) >> 1] # extract the 4 bits and reverse + lcd.mcp.write8(0x0, MCP23017_GPIOB) # send E low to finish and set RS, RW and all to zero + lcd.mcp.write8(0b00000001, MCP23017_IODIRB) # configure so all approrpriate pins are output again + return (hinum << 4) | lonum + +def DumpMCP23017Regs(regs_to_use=[0x0,18,20]): +# Dump MCP23017 registers see MCP2301721952b.pdf specifications but show first B then A +# Default is to dump only IODIR, GPIO and OLATA +# will show B bank followed by A bank i.e. IODIRB, IODIRA so +# the output corresponds to 'pins' 15,14,...,0 +# to dump all use regs_to_use = range(0x0,0x15,0x2) + RegName = ["IODIR","IPOL","GPINTEN","DEFVAL","INTCON","IOCON","GPPU","INTF","INTCAP","GPIO","OLATA"] + print "B bank then A bank so Pins 15, 14, ..., 0" + print binfill(lcd.mcp.direction,16), " lcd.mcp.direction" #ideally should be same as IODIR + for reg in regs_to_use: + str = binfill(lcd.mcp.readU16(reg),16) + # interchange bytes B reg then A reg so 'pins' are from left to right are 15,14,13,...,0 + print str[8:]+str[:8]," ", RegName[reg/2] + +def home_fast(): +# fast return home + lcd.mcp.write8(0x20, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as hi bits of instruction code + lcd.mcp.write8(0x08, MCP23017_GPIOB) #RS=0, R/W=0, E=0, low nibble of lcd command reversed, 0 + lcd.mcp.write8(0x28, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(0x08, MCP23017_GPIOB) #same as line three to send E low to finish + +def clear_fast(): +# fast clear + lcd.mcp.write8(0x20, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as hi bits of instruction code + lcd.mcp.write8(0x10, MCP23017_GPIOB) #RS=0, R/W=0, E=0, low nibble of clear display reversed, 0 + lcd.mcp.write8(0x30, MCP23017_GPIOB) #same with E=1 so going high sends this nibble to LCD as low bits of instruction code + lcd.mcp.write8(0x10, MCP23017_GPIOB) #same as line three to send E low to finish + +def dim_light(on=.5,time=1,nforsec=50): +# dimming routine doesnt work very well +# flashes display on and off over interval time +# on is fraction of time on during the interval + assert 0 <= on and on <= 1, "bad value for on" + ontime = float(on)/nforsec + offtime = (1.0-on)/nforsec + maxct = int(nforsec*time) + print ontime, offtime, maxct + for ct in range(maxct): + lcd.write4bits(0x8) # display off + sleep(offtime) + lcd.write4bits(0xc) # display on + sleep(ontime) + +def dispall(delay=.1): + for i in range(256): + general_cmd(i,1) + sleep(delay) + +def cycle(seq, n): +# cyclic premutation of seq shifting left n + n = n % len(seq) + return seq[n:] + seq[:n] + +def cyclerange(DDRAMrange=range(40), amount=1): +# cyclically shift characters in a range of DDRAM addresses by amount +# DDRAMrange default is line 1 in 2 line mode i.e. 0...39 + # get DDRAM address to be restored + add = general_cmd(0,0,1) + lenrange = len(DDRAMrange) + startadd = DDRAMrange[0] + # get data in DDRAMrange + # set DDRAM address to startadd + general_cmd(0b10000000 + startadd) + win = [0]*lenrange + for i in range(lenrange): #read DDRAM beginning at startadd + win[i] = general_cmd(0,1,1) + win = cycle(win,amount) + general_cmd(0b10000000 + startadd) + for i in range(lenrange): #write shifted values back in DDRAM starting at startadd + general_cmd(win[i],1,0) + # restore DDRAM address + general_cmd(add | 0x80) + +def scrollrange(DDRAMrange=range(40), num=1, delay=.01): + num = num*len(DDRAMrange) + for i in range(num): + cyclerange(DDRAMrange,1) + #sleep(delay) + +def shiftwithinrange(textstart,textlen,DDRAMrange=range(40)): +# cyclically shift characters in a range of DDRAM addresses by one position +# this code maybe faster than cyclerange code +# DDRAMrange default is line 1 in 2 line mode i.e. 0...39 + # if have string of text can shift it to the right one place within a range (say top line) + # assuming this string is surrounded by blanks in the rest of the range + # assuming LCD set in increment mode (rather than decrement mode) + # get DDRAM address to be restored + add = general_cmd(0,0,1) + startrange = DDRAMrange[0] + endrange = DDRAMrange[-1] + lenrange = len(DDRAMrange) + #print startrange, endrange, lenrange + for i in range(textstart+textlen-1,textstart-1,-1): # go thru in reverse + add = i + if i > endrange: + add = i - lenrange + startrange + #print "moving from ", add + # set DDRAM address to + general_cmd(0b10000000 + add) + byte = general_cmd(0,1,1) # this will get byte in DDRAM and increment address counter by 1 + if i+1 > endrange: + add = i + 1 - lenrange + startrange + general_cmd(0b10000000 + add ) + else: + add = add + 1 + general_cmd(byte,1,0) # this will put byte in DDRAM at the new address thus shifting it + #print "moving to ", add, "this char ", chr(byte) + general_cmd(0b10000000 + textstart) + general_cmd(0b00100000,1,0) # this will put blank + # restore DDRAM address + general_cmd(add | 0x80) + + +class Histogram: + def __init__(self): + # make bars in CGRAM of height 8 to 1 in for custom char 0 to 7 (and 8 to 15) + histdata = [31,31,31,31,31,31,31,31, 0,31,31,31,31,31,31,31, 0,0,31,31,31,31,31,31, 0,0,0,31,31,31,31,31, 0,0,0,0,31,31,31,31, 0,0,0,0,0,31,31,31, 0,0,0,0,0,0,31,31, 0,0,0,0,0,0,0,31 ] + general_cmd(0b01000000) # set CGRAM address 0 + for i in range(64): + general_cmd(histdata[i],1) # write data to ram + + def histogram(self,bar,DDRAMstart=64,UseTwoLines=True): + # draws bars of height bar[0],bar[1],... starting at + # DDRAMstart. Heights must >=0 and <= max 16 for TwoLines and 8 for OneLine). + # In the case UseTwoLines==True, the bars use two rows, so it is advised + # to make DDRAMstart on the 2nd line. + # note no checking done on values. If they are bigger than 16 other characters + # will be displayed instead of the custom bars. + # get DDRAM address to be restored + add = general_cmd(0,0,1) + # draw bottom row + # set DDRAM address to start + general_cmd(0b10000000 + DDRAMstart) + for y in bar: + char = max(16-y,8) + general_cmd(char,1,0) # put char which has appropriate height + if UseTwoLines: + # draw top row + # set DDRAM address to start + general_cmd(0b10000000 + DDRAMstart - 64) + for y in bar: + char = min(16-y,8) + 8 + general_cmd(char,1,0) # put char which has appropriate height + # restore DDRAM address + general_cmd(add | 0x80) + + +class DotGrid: + def __init__(self): + # make dot patterns in CGRAM + self.dotdata = [0,0,0,0,14,31,14,0, 14,31,14,0,0,0,0,0, 14,31,14,0,14,31,14,0, 0,0,0,0,0,14,31,14, 0,14,31,14,0,0,0,0, 0,14,31,14,0,14,31,14] + self.dedata = [[[64,2,1,0],[64,2,0,1],[0,5,4,3],[0,5,3,4]], [[64,1,2,32],[64,0,2,32],[0,4,5,32],[0,3,5,32]]] + self.isdotdata = [[64,0,2],[64,1,2],[0,3,5],[0,4,5]] + self.initialize_CGRAM() + + def initialize_CGRAM(self): + general_cmd(0b01000000) # set CGRAM address 0 + for i in range(len(self.dotdata)): + general_cmd(self.dotdata[i],1) # write data to ram + + def draw_erase_or_test(self,x,y,deort): # deort == 0 for draw, ==1 for erase, else test only + # draws, erases or tests a dot at (x,y) + # 0<=x<=39 but only x<=15 visable in default display but can shift to see + # 0<=y<=3 + # get DDRAM address to be restored + add = general_cmd(0,0,1) + addforx = x + self.dedata[0][y][0] + general_cmd(0b10000000 + addforx) # set DDRAM address + byte = general_cmd(0,1,1) # this will get byte in DDRAM + isdot = byte==self.isdotdata[y][1] or byte==self.isdotdata[y][2] + # if asked to draw a dot thats not there or erase a dot that is there do it! + if deort==0 and not isdot or deort==1 and isdot: + char = self.dedata[deort][y][1] if byte==self.dedata[deort][y][2] else self.dedata[deort][y][3] + general_cmd(0b10000000 + addforx) # set DDRAM address + general_cmd(char,1,0) # put char which is one or two dots + # restore DDRAM address + general_cmd(add | 0x80) + # return True if there was a dot at x,y when entered function + return isdot + + def draw(self,x,y): + return self.draw_erase_or_test(x,y,0) + + def erase(self,x,y): + return self.draw_erase_or_test(x,y,1) + + def isdot(self,x,y): + return self.draw_erase_or_test(x,y,2) + + +# OLD +# def draw(self,x,y): +# # draws a dot at (x,y) +# # 0<=x<=39 but only x<=15 in default display can shift to see +# # 0<=y<=3 +# # get DDRAM address to be restored +# add = general_cmd(0,0,1) +# if y==0: +# addforx = x + 64 +# general_cmd(0b10000000 + addforx) # set DDRAM address +# byte = general_cmd(0,1,1) # this will get byte in DDRAM +# char = 2 if byte==1 else 0 +# general_cmd(0b10000000 + addforx) # set DDRAM address +# general_cmd(char,1,0) # put char which is one or two dots +# elif y==1: +# addforx = 64 + x +# general_cmd(0b10000000 + addforx) # set DDRAM address +# byte = general_cmd(0,1,1) # this will get byte in DDRAM +# char = 2 if byte==0 else 1 +# general_cmd(0b10000000 + addforx) # set DDRAM address +# general_cmd(char,1,0) # put char which is one or two dots +# elif y==2: +# addforx = x +# general_cmd(0b10000000 + addforx) # set DDRAM address +# byte = general_cmd(0,1,1) # this will get byte in DDRAM +# char = 5 if byte==4 else 3 +# general_cmd(0b10000000 + addforx) # set DDRAM address +# general_cmd(char,1,0) # put char which is one or two dots +# elif y==3: +# addforx = x +# general_cmd(0b10000000 + addforx) # set DDRAM address +# byte = general_cmd(0,1,1) # this will get byte in DDRAM +# general_cmd(0b10000000 + addforx) # set DDRAM address +# general_cmd(char,1,0) # put char which is one or two dots +# else: +# print "y not 0,1,2 or 3" +# # restore DDRAM address +# general_cmd(add | 0x80) +# + + +back = 0 +def ToggleBacklight(back): + back ^= 1 + lcd.backlight(back) + sleep(.2) + return back + + + +# initialize the LCD plate +# use busnum = 0 for raspi version 1 (256MB) and busnum = 1 for version 2 +lcd = Adafruit_CharLCDPlate(busnum = 1) + +Hist = Histogram() +bar = [0]*16 + +DotG = DotGrid() + +general_cmd(0b1) # clear +lcd.waitBFlow() # must wait for clear to complete + +# Testing using keyboard +while 1: + cmd = raw_input() + if cmd == 'help': + print "10, 9, bf, cgram, config, cyclerange, dim, dispall, dot, dotinit, dump, edot, histogram, histograminit, longchar, mess, oneline, ramdata, sdr, scrollrange, shiftwithinrange, test, twoline, quit" + + if cmd == 'test': + print "Routine for testing" + + if cmd == '10': + str = raw_input("10 bits of instruction code:") + RS = str[0]=="1" # 1 is true + RW = str[1]=="1" # 1 is true + str = str[2:].zfill(8) + num = int('0b'+str,2) + numrpt = raw_input("repeat #:") + numrpt = 1 if numrpt=="" else int(numrpt) + for count in range(0,numrpt): + print(general_cmd(num,RS,RW)) + + if cmd == 'dim': + time = 2 + on = input("Fraction on? ") + nforsec = input("nforsec? ") + dim_light(on,time,nforsec) + + if cmd == 'bf': + #print "BF", lcd.readBF() + print "fast BF + AD = ", binfill(readfast()) # read Busy Flag and Adress + #print "BF + AD = ", lcd.read4bits() # read Busy Flag and Adress + + if cmd == 'sdr': + numrpt = raw_input("Shift Display Right by ") + numrpt = 1 if numrpt=="" else int(numrpt) + display_right(numrpt) + + if cmd == 'cyclerange': + line = input("Window Range? ") + line = range(40) if line=="" else line + amt = raw_input("How much? ") + amt = 1 if amt=="" else int(amt) + cyclerange(line,amt) + + if cmd == 'dotinit': + DotG.initialize_CGRAM() + + if cmd == 'dot': + x = input("x? ") + y = input("y? ") + #print(DotG.draw_erase_or_test(x,y,0)) + print(DotG.draw(x,y)) + + if cmd == 'edot': + x = input("x? ") + y = input("y? ") + #print(DotG.draw_erase_or_test(x,y,1)) + print(DotG.erase(x,y)) + + if cmd == 'histograminit': + Hist.__init__() + + if cmd == 'histogram': + #bar = input("Bar list? ") + barcurrent = [0]*16 + barnew = barcurrent[:] + barshow = barcurrent[:] + for cnt in range(30): + for ind in range(len(barcurrent)): + barnew[ind] = randint(0,16) + tmax = 4 + for time in range(tmax+1): + for ind in range(len(barcurrent)): + barshow[ind] = int(((tmax-time)*barcurrent[ind] + time*barnew[ind])/float(tmax)) + Hist.histogram(barshow) + barcurrent = barnew[:] + + if cmd == 'scrollrange': + line = input("Window Range? ") + line = range(40) if line=="" else line + scrollrange(line) + + if cmd == 'shiftwithinrange': + #textstart = input('Start? ') + #textlen = input('Length? ') + #shiftwithinrange(textstart,textlen, range(10)) + #general_cmd(0b00011000) # display shift left + for i in range(40): + shiftwithinrange(i,16) + general_cmd(0b00011000) # display shift left + sleep(.05) + + if cmd == 'cgram': + num = raw_input("CGRAM address? ") + setCGRAMadd(int(num)) + + if cmd == 'ramdata': + print "fast RAM Data = ", binfill(readfast(True)) # read data from RAM + #print "RAM Data = ", lcd.read4bits(True) # read data from RAM + + if cmd == 'mess': + str = raw_input("message:") + lcd.message(str); + + if cmd == '9': + str = raw_input("9 bits of instruction code:") + char_mode = str[0]=="1" # 1 is true + str = str[1:].zfill(8) + bits = int('0b'+str,2) + print char_mode, str, bits + numrpt = raw_input("repeat #:") + numrpt = 1 if numrpt=="" else int(numrpt) + for count in range(0,numrpt): + lcd.write4bits(bits, char_mode) + + if cmd == 'dump': + DumpMCP23017Regs() + + if cmd == 'config': + pin = int(raw_input("pin number ")) + state = int(raw_input("1 or 0 "))==1 + lcd.mcp.config(pin,state) + + if cmd == 'oneline': + general_cmd(0b100000) + + if cmd == 'twoline': + general_cmd(0b101000) + + if cmd == 'longchar': + general_cmd(0b100100) + + if cmd == 'dispall': + dispall() + + if cmd == 'quit': + exit() + +# Testing using buttons on LCDPlate +while 1: + if (lcd.buttonPressed(lcd.LEFT)): + #print "BF", lcd.readBF() + print "fast BF + AD = ", binfill(readfast()) # read Busy Flag and Adress + #print "BF + AD = ", lcd.read4bits() # read Busy Flag and Adress + #back = ToggleBacklight(back) + sleep(.2) + + if (lcd.buttonPressed(lcd.UP)): + num = raw_input("Shift Display Right by ") + display_right(int(num)) + #num = raw_input("CGRAM address? ") + #setCGRAMadd(int(num)) + sleep(.2) #prevent multiple execution while button is down + + if (lcd.buttonPressed(lcd.DOWN)): + print "fast RAM Data = ", binfill(readfast(True)) # read data from RAM + #print "RAM Data = ", lcd.read4bits(True) # read data from RAM + sleep(.2) + + if (lcd.buttonPressed(lcd.RIGHT)): + str = raw_input("message:") + lcd.message(str); + + if (lcd.buttonPressed(lcd.SELECT)): + str = raw_input("9 bits of instruction code:") + char_mode = str[0]=="1" # 1 is true + str = str[1:].zfill(8) + bits = int('0b'+str,2) + print char_mode, str, bits + numrpt = raw_input("repeat #:") + #print "input",numrpt + if (numrpt == ""): # return means 1 + numrpt = 1 + else: + numrpt = int(numrpt) + for count in range(0,numrpt): + lcd.write4bits(bits, char_mode) diff --git a/Adafruit_MCP230xx/Adafruit_MCP230xx.py b/Adafruit_MCP230xx/Adafruit_MCP230xx.py index 42565d8d..ab1f4f25 100755 --- a/Adafruit_MCP230xx/Adafruit_MCP230xx.py +++ b/Adafruit_MCP230xx/Adafruit_MCP230xx.py @@ -1,202 +1,204 @@ -#!/usr/bin/python - -# Copyright 2012 Daniel Berlin (with some changes by Adafruit Industries/Limor Fried) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy of -# this software and associated documentation files (the "Software"), to deal MCP230XX_GPIO(1, 0xin -# the Software without restriction, including without limitation the rights to -# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -# of the Software, and to permit persons to whom the Software is furnished to do -# so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from Adafruit_I2C import Adafruit_I2C -import smbus -import time - -MCP23017_IODIRA = 0x00 -MCP23017_IODIRB = 0x01 -MCP23017_GPIOA = 0x12 -MCP23017_GPIOB = 0x13 -MCP23017_GPPUA = 0x0C -MCP23017_GPPUB = 0x0D -MCP23017_OLATA = 0x14 -MCP23017_OLATB = 0x15 -MCP23008_GPIOA = 0x09 -MCP23008_GPPUA = 0x06 -MCP23008_OLATA = 0x0A - -class Adafruit_MCP230XX(object): - OUTPUT = 0 - INPUT = 1 - - def __init__(self, address, num_gpios, busnum = 0): - assert num_gpios >= 0 and num_gpios <= 16, "Number of GPIOs must be between 0 and 16" - self.i2c = Adafruit_I2C(address=address, bus=smbus.SMBus(busnum)) - self.address = address - self.num_gpios = num_gpios - - # set defaults - if num_gpios <= 8: - self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A - self.direction = self.i2c.readU8(MCP23017_IODIRA) - self.i2c.write8(MCP23008_GPPUA, 0x00) - elif num_gpios > 8 and num_gpios <= 16: - self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A - self.i2c.write8(MCP23017_IODIRB, 0xFF) # all inputs on port B - self.direction = self.i2c.readU8(MCP23017_IODIRA) - self.direction |= self.i2c.readU8(MCP23017_IODIRB) << 8 - self.i2c.write8(MCP23017_GPPUA, 0x00) - self.i2c.write8(MCP23017_GPPUB, 0x00) - - def _changebit(self, bitmap, bit, value): - assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value - if value == 0: - return bitmap & ~(1 << bit) - elif value == 1: - return bitmap | (1 << bit) - - def _readandchangepin(self, port, pin, value, currvalue = None): - assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) - #assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin - if not currvalue: - currvalue = self.i2c.readU8(port) - newvalue = self._changebit(currvalue, pin, value) - self.i2c.write8(port, newvalue) - return newvalue - - - def pullup(self, pin, value): - if self.num_gpios <= 8: - return self._readandchangepin(MCP23008_GPPUA, pin, value) - if self.num_gpios <= 16: - if (pin < 8): - return self._readandchangepin(MCP23017_GPPUA, pin, value) - else: - return self._readandchangepin(MCP23017_GPPUB, pin-8, value) - - # Set pin to either input or output mode - def config(self, pin, mode): - if self.num_gpios <= 8: - self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode) - if self.num_gpios <= 16: - if (pin < 8): - self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode) - else: - self.direction = self._readandchangepin(MCP23017_IODIRB, pin-8, mode) - - return self.direction - - def output(self, pin, value): - # assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin - if self.num_gpios <= 8: - self.outputvalue = self._readandchangepin(MCP23008_GPIOA, pin, value, self.i2c.readU8(MCP23008_OLATA)) - if self.num_gpios <= 16: - if (pin < 8): - self.outputvalue = self._readandchangepin(MCP23017_GPIOA, pin, value, self.i2c.readU8(MCP23017_OLATA)) - else: - self.outputvalue = self._readandchangepin(MCP23017_GPIOB, pin-8, value, self.i2c.readU8(MCP23017_OLATB)) - - return self.outputvalue - - - self.outputvalue = self._readandchangepin(MCP23017_IODIRA, pin, value, self.outputvalue) - return self.outputvalue - - def input(self, pin): - assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) - assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin - if self.num_gpios <= 8: - value = self.i2c.readU8(MCP23008_GPIOA) - elif self.num_gpios > 8 and self.num_gpios <= 16: - value = self.i2c.readU16(MCP23017_GPIOA) - temp = value >> 8 - value <<= 8 - value |= temp - return value & (1 << pin) - - def readU8(self): - result = self.i2c.readU8(MCP23008_OLATA) - return(result) - - def readS8(self): - result = self.i2c.readU8(MCP23008_OLATA) - if (result > 127): result -= 256 - return result - - def readU16(self): - assert self.num_gpios >= 16, "16bits required" - lo = self.i2c.readU8(MCP23017_OLATA) - hi = self.i2c.readU8(MCP23017_OLATB) - return((hi << 8) | lo) - - def readS16(self): - assert self.num_gpios >= 16, "16bits required" - lo = self.i2c.readU8(MCP23017_OLATA) - hi = self.i2c.readU8(MCP23017_OLATB) - if (hi > 127): hi -= 256 - return((hi << 8) | lo) - - def write8(self, value): - self.i2c.write8(MCP23008_OLATA, value) - - def write16(self, value): - assert self.num_gpios >= 16, "16bits required" - self.i2c.write8(MCP23017_OLATA, value & 0xFF) - self.i2c.write8(MCP23017_OLATB, (value >> 8) & 0xFF) - -# RPi.GPIO compatible interface for MCP23017 and MCP23008 - -class MCP230XX_GPIO(object): - OUT = 0 - IN = 1 - BCM = 0 - BOARD = 0 - def __init__(self, busnum, address, num_gpios): - self.chip = Adafruit_MCP230XX(busnum, address, num_gpios) - def setmode(self, mode): - # do nothing - pass - def setup(self, pin, mode): - self.chip.config(pin, mode) - def input(self, pin): - return self.chip.input(pin) - def output(self, pin, value): - self.chip.output(pin, value) - def pullup(self, pin, value): - self.chip.pullup(pin, value) - - -if __name__ == '__main__': - mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 8) - - # *************************************************** - # Set num_gpios to 8 for MCP23008 or 16 for MCP23017! - # If you have a new Pi you may also need to add: - # busnum = 1 - # *************************************************** - - # Set pins 0, 1 and 2 to output (you can set pins 0..15 this way) - mcp.config(0, mcp.OUTPUT) - mcp.config(1, mcp.OUTPUT) - mcp.config(2, mcp.OUTPUT) - - # Set pin 3 to input with the pullup resistor enabled - mcp.pullup(3, 1) - # Read pin 3 and display the results - print "%d: %x" % (3, mcp.input(3) >> 3) - - # Python speed test on output 0 toggling at max speed - while (True): - mcp.output(0, 1) # Pin 0 High - mcp.output(0, 0) # Pin 0 Low +#!/usr/bin/python + +# Copyright 2012 Daniel Berlin (with some changes by Adafruit Industries/Limor Fried) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal MCP230XX_GPIO(1, 0xin +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +from Adafruit_I2C import Adafruit_I2C +import smbus +import time + +MCP23017_IODIRA = 0x00 +MCP23017_IODIRB = 0x01 +MCP23017_GPIOA = 0x12 +MCP23017_GPIOB = 0x13 +MCP23017_GPPUA = 0x0C +MCP23017_GPPUB = 0x0D +MCP23017_OLATA = 0x14 +MCP23017_OLATB = 0x15 +MCP23008_GPIOA = 0x09 +MCP23008_GPPUA = 0x06 +MCP23008_OLATA = 0x0A + +class Adafruit_MCP230XX(object): + OUTPUT = 0 + INPUT = 1 + + def __init__(self, address, num_gpios, busnum = 0): + assert num_gpios >= 0 and num_gpios <= 16, "Number of GPIOs must be between 0 and 16" + self.i2c = Adafruit_I2C(address=address, bus=smbus.SMBus(busnum)) + self.address = address + self.num_gpios = num_gpios + + # set defaults + if num_gpios <= 8: + self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A + self.direction = self.i2c.readU8(MCP23017_IODIRA) + self.i2c.write8(MCP23008_GPPUA, 0x00) + elif num_gpios > 8 and num_gpios <= 16: + self.i2c.write8(MCP23017_IODIRA, 0xFF) # all inputs on port A + self.i2c.write8(MCP23017_IODIRB, 0xFF) # all inputs on port B + self.direction = self.i2c.readU8(MCP23017_IODIRA) + self.direction |= self.i2c.readU8(MCP23017_IODIRB) << 8 + self.i2c.write8(MCP23017_GPPUA, 0x00) + self.i2c.write8(MCP23017_GPPUB, 0x00) + + + def _changebit(self, bitmap, bit, value): + assert value == 1 or value == 0, "Value is %s must be 1 or 0" % value + if value == 0: + return bitmap & ~(1 << bit) + elif value == 1: + return bitmap | (1 << bit) + + def _readandchangepin(self, port, pin, value, currvalue = None): + assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) + #assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin + if not currvalue: + currvalue = self.i2c.readU8(port) + newvalue = self._changebit(currvalue, pin, value) + self.i2c.write8(port, newvalue) + return newvalue + + + def pullup(self, pin, value): + if self.num_gpios <= 8: + return self._readandchangepin(MCP23008_GPPUA, pin, value) + if self.num_gpios <= 16: + if (pin < 8): + return self._readandchangepin(MCP23017_GPPUA, pin, value) + else: + return self._readandchangepin(MCP23017_GPPUB, pin-8, value) + + # Set pin to either input or output mode + def config(self, pin, mode): + if self.num_gpios <= 8: + self.direction = self._readandchangepin(MCP23017_IODIRA, pin, mode) + if self.num_gpios <= 16: + if (pin < 8): + # replace low bits + self.direction = (self.direction & 0xff00) | self._readandchangepin(MCP23017_IODIRA, pin, mode) + else: + # replace hi bits + self.direction = (self.direction & 0xff) | self._readandchangepin(MCP23017_IODIRB, pin-8, mode) << 8 + #print "config ", pin, mode, self.direction, bin(self.direction)[2:].zfill(16) + return self.direction + + def output(self, pin, value): + # assert self.direction & (1 << pin) == 0, "Pin %s not set to output" % pin + if self.num_gpios <= 8: + self.outputvalue = self._readandchangepin(MCP23008_GPIOA, pin, value, self.i2c.readU8(MCP23008_OLATA)) + if self.num_gpios <= 16: + if (pin < 8): + self.outputvalue = self._readandchangepin(MCP23017_GPIOA, pin, value, self.i2c.readU8(MCP23017_OLATA)) + else: + self.outputvalue = self._readandchangepin(MCP23017_GPIOB, pin-8, value, self.i2c.readU8(MCP23017_OLATB)) + return self.outputvalue + +# inaccessible code removed from here + + def input(self, pin, check=True): + assert pin >= 0 and pin < self.num_gpios, "Pin number %s is invalid, only 0-%s are valid" % (pin, self.num_gpios) + if check: + assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin + if self.num_gpios <= 8: + value = self.i2c.readU8(MCP23008_GPIOA) + elif self.num_gpios > 8 and self.num_gpios <= 16: + value = self.i2c.readU16(MCP23017_GPIOA) + temp = value >> 8 + value <<= 8 + value |= temp + return (value & (1 << pin))>>pin # to make 0 or 1 + + + +# these were indented so within scope of input but have now made them all part of the class +# have modified so can read any address but default to those given in original code +# also use available routines in imported Adafruit_I2C class + def readU8(self, add=MCP23008_OLATA): + result = self.i2c.readU8(add) + return(result) + + def readS8(self, add=MCP23008_OLATA): + result = self.i2c.readS8(add) + return result + + def readU16(self, add=MCP23017_OLATA): + assert self.num_gpios >= 16, "16bits required" + result = self.i2c.readU16(add) + return result + + def readS16(self, add=MCP23017_OLATA): + assert self.num_gpios >= 16, "16bits required" + result = self.i2c.readS16(add) + return result + + def write8(self, value, add=MCP23008_OLATA): + self.i2c.write8(add, value) + + def write16(self, value, add=MCP23017_OLATA): + assert self.num_gpios >= 16, "16bits required" + self.i2c.write16(add, value) + + +# RPi.GPIO compatible interface for MCP23017 and MCP23008 + +class MCP230XX_GPIO(object): + OUT = 0 + IN = 1 + BCM = 0 + BOARD = 0 + def __init__(self, busnum, address, num_gpios): + self.chip = Adafruit_MCP230XX(busnum, address, num_gpios) + def setmode(self, mode): + # do nothing + pass + def setup(self, pin, mode): + self.chip.config(pin, mode) + def input(self, pin): + return self.chip.input(pin) + def output(self, pin, value): + self.chip.output(pin, value) + def pullup(self, pin, value): + self.chip.pullup(pin, value) + + +if __name__ == '__main__': + mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 8) + + # *************************************************** + # Set num_gpios to 8 for MCP23008 or 16 for MCP23017! + # If you have a new Pi you may also need to add: + # busnum = 1 + # *************************************************** + + # Set pins 0, 1 and 2 to output (you can set pins 0..15 this way) + mcp.config(0, mcp.OUTPUT) + mcp.config(1, mcp.OUTPUT) + mcp.config(2, mcp.OUTPUT) + + # Set pin 3 to input with the pullup resistor enabled + mcp.pullup(3, 1) + # Read pin 3 and display the results + print "%d: %x" % (3, mcp.input(3) >> 3) + + # Python speed test on output 0 toggling at max speed + while (True): + mcp.output(0, 1) # Pin 0 High + mcp.output(0, 0) # Pin 0 Low