dhylands / python_lcd

Python based library for talking to character based LCDs.
MIT License
298 stars 116 forks source link

Custom characters #9

Closed mcauser closed 7 years ago

mcauser commented 7 years ago

Custom characters are 5x8 pixels and can be created using a 8 byte bytearray, where the first element is the top row and last element is the bottom row of pixels. Least significant bit is the right edge pixel and only 5 bits of significance are used.

Happy Face (where .=0, #=1)
..... == 0b00000000 == 0x00
.#.#. == 0b00001010 == 0x0A
..... == 0b00000000 == 0x00
..#.. == 0b00000100 == 0x04
..... == 0b00000000 == 0x00
#...# == 0b00010001 == 0x11
.###. == 0b00001110 == 0x0E
..... == 0b00000000 == 0x00

lcd.custom_char(0, bytearray([0x00,0x0A,0x00,0x04,0x00,0x11,0x0E,0x00]))
lcd.putchar(chr(0))
lcd.putchar(b'\x00')

Side note: the characters are displayed from cg-ram by reference. Once you have printed a custom character to the screen, you can overwrite the custom character and all visible instances will also update. Useful for drawing animations and graphs.

img_9158b

dhylands commented 7 years ago

It would be good to add mention of custom characters in the readme as well.

mcauser commented 7 years ago

I was thinking an /examples folder, with 20+ examples I'm porting across

mcauser commented 7 years ago

I'm also working on a SeeedStudio RGB LCD. Two I2C devices. One for the LCD and one for the backlight pwm driver. Separate PR coming shortly.

dhylands commented 7 years ago

That would be cool.

Perhaps put a README.md in the examples folder which has a summary of the example. I really liked the picture you posted with the battery gauge.

mcauser commented 7 years ago

img_9161b

lcd = I2cLcd(i2c, 0x27, 4, 20)

lcd.custom_char(0, bytearray([0x1F,0x10,0x17,0x14,0x14,0x14,0x14,0x14]))
lcd.custom_char(1, bytearray([0x1F,0x00,0x1F,0x00,0x00,0x00,0x00,0x00]))
lcd.custom_char(2, bytearray([0x1F,0x01,0x1D,0x05,0x05,0x05,0x05,0x05]))
lcd.custom_char(3, bytearray([0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05]))
lcd.custom_char(4, bytearray([0x05,0x05,0x05,0x05,0x05,0x1D,0x01,0x1F]))
lcd.custom_char(5, bytearray([0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x1F]))
lcd.custom_char(6, bytearray([0x14,0x14,0x14,0x14,0x14,0x17,0x10,0x1F]))
lcd.custom_char(7, bytearray([0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14]))

lcd.clear()
lcd.putstr(chr(0) + chr(1)*18 + chr(2))
lcd.putstr(chr(7))
lcd.move_to(19,1)
lcd.putstr(chr(3))
lcd.putstr(chr(7))
lcd.move_to(19,2)
lcd.putstr(chr(3))
lcd.putstr(chr(6) + chr(5)*18 + chr(4))

lcd.move_to(2,1)
lcd.putstr("Borders are more")
lcd.move_to(1,2)
lcd.putstr("fun than batteries")
dhylands commented 7 years ago

Sweet.

For the examples, it would probably be good to arrange them so that they take the lcd object as a parameter. That way they could be used with I2C/GPIO etc without having to edit them.

Perhaps something along the lines of say creating a borders.py example which contained:

def border_example(lcd):
    lcd.custom_char(0, bytearray([0x1F,0x10,0x17,0x14,0x14,0x14,0x14,0x14]))
    ...

and then to actually use the example:

>>> import border
>>> lcd = I2cLcd(i2c, 0x27, 4, 20)
>>> border.border_example(lcd)