dbrgn / RPLCD

A Raspberry Pi LCD library for the widely used Hitachi HD44780 controller, written in Python. GPIO (parallel) and I²C modes supported.
https://rplcd.readthedocs.io/en/latest/
MIT License
261 stars 72 forks source link

Corrupt output when input string is longer than display size #125

Closed clach04 closed 3 years ago

clach04 commented 3 years ago

I have a 16x2 display and displaying strings works fine... unless more characters are given than the display can handle.

import sys

from RPLCD.i2c import CharLCD

#lcd = CharLCD('PCF8574', 0x27)  # determine address via "i2cdetect -y 1"
lcd = CharLCD('PCF8574', 0x27, cols=16, rows=2)  # determine address via "i2cdetect -y 1"
#lcd = CharLCD('PCF8574', 0x27, cols=16, rows=2, auto_linebreaks=True)  # determine address via "i2cdetect -y 1"

"""
lcd = CharLCD(i2c_expander='PCF8574', address=0x27, port=1,
              cols=20, rows=4, dotsize=8,
              charmap='A02',
              auto_linebreaks=True,
              backlight_enabled=True)
"""

lcd.clear()
#lcd.write_string('Hello world')
#lcd.write_string('world hello')
d_str = 'The quick brown fox jumps over the lazy dog'
d_str = 'The quick brown fox jumps over the lazy dog'
d_str = '1234567890abcdef\n\rabcdef1234567890'  # works
d_str = '1234567890abcdefabcdef1234567890'  # works
d_str = '1234 6789 abcde abcdef 23456 890'  # works
d_str = 'The quick brown fox jumps over t'  # works
d_str = 'The quick brown fox jumps over the lazy dog'  # bad
d_str = 'The quick brown fox jumps over the'  # bad
d_str = 'The quick brown fox jumps over th'  # bad
#d_str = sys.argv[1]
#lcd.write_string('The quick brown fox jumps over the lazy dog')
lcd.write_string(d_str)

I've not had chance to debug, logging what I know now. From cursory scan, suspect issue somewhere in BaseCharLCD

So I have no idea if this is specific to the i2c interface (probably not).

I did try the same test without specifying cols/rows and it wraps correctly without corruption for a 20x2 display (i.e. I loose characters on the first line but that makes sense if its a 20 line length).

Can anyone test my script above (possibly on a 20x4) and see if they see the same thing?

clach04 commented 3 years ago

The string 'The quick brown fox jumps over th' results in:

hhe quick brown 
fox jumps over t

so the last "h" appears to be printed at the first position (over writing the "T").

dbrgn commented 3 years ago

so the last "h" appears to be printed at the first position (over writing the "T").

Isn't this the expected outcome (with auto_linebreaks=True)? The first line is written, then the second line, then the output wraps around and starts filling the first line again.

clach04 commented 3 years ago

@dbrgn you are correct :) I was expecting a different behavior but this matches what https://github.com/dhylands/python_lcd does as well (I suspect this is the underlying behavior of the LCD controller?).

There was two things that confused me:

Thanks again for this library :-)

dbrgn commented 3 years ago

Well, the underlying LCD controller has a memory area that can be written to. The memory is usually larger than what you see on the display, so you can keep writing to it without seeing anything.

If you have a 2x16 LCD, then you'll see the first 16 bytes of the first memory area and the first 16 bytes of the second memory area. If you have a 4x20 LCD, then rows 1 and 3 are linked, and rows 2 and 4 are linked, meaning that the first 20 bytes of the first memory area will show on the first line, the next 20 bytes of the first memory area will show on the third line, and the rest will not be visible. Essentially it's a very long 2x40 LCD, where the second half of the LCD is cut off and put below the first half.

Because this overflowing behavior is not really intuitive, the auto linebreaks mode instead simulates "regular" overflow, so every line overflows into the next one, and the last one overflows into the first one. This means that you can keep writing data, and it will always be visible somewhere.

Hope that clears things up!