Closed IhorNehrutsa closed 3 years ago
The height and width are height=280, width=240 but not as expected height=240, width=135.
ssd = SSD(spi, height=(135+5)*2, width=240, dc=pdc, cs=pcs, rst=prst) #, disp_mode=PORTRAIT | USD)
There is an invisible area outside the screen. Cyan and gray squares go off-screen. The top-left corner has coordinates (41, 53). ssd.fill_rect(0, 0, ssd.width//2, 41, CYAN) # Cyan square at top left ssd.fill_rect(0, 0, 53, ssd.height//2, GREY) # Grey square at top left
It's hard for me to support hardware I don't possess. From the URL's you posted it should be capable of working, and your code shows you are setting about investigating this in the same way that I would. Further, given your progress so far I'm confident we can fix this.
[EDITED]
That said, height
and width
values should match the display hardware otherwise it will break things in CWriter
and nano-gui
.
It seems that the principal problem is an offset such that (0, 0)
is off screen. This is common, and I was planning to support it, however the hardware I possess has zero offsets so I didn't progress this. I have posted an update with a final optional constructor arg offset=(0,0)
which allows you to enter an (x, y)
tuple. Here x
and y
(positive integers) represent the origin of a window in the device's internal RAM where the framebuf is to be rendered.
Determining these values is likely to be an iterative process unless you have someone else's code or docs to study. My simple test script helps with getting pixel-perfect values. I have had to do this with other displays.
To add a few general comments. Firstly, thank you for your excellent initial post which provided everything needed to offer support (see below). Secondly it's a great product to support and I'm keen to progress this and offer any help I can. Please keep me posted on progress.
Cheers, Pete
Beats "I installed this on a Chinese clone of the Scam Products Inc TotallyNackered V0.01 alpha and it doesn't work. Can u help?". I exaggerate only slightly...
Please see above edit.
Hello, Peter. Still unsuccessful with the offset parameter. You mentioned a datasheet here https://github.com/peterhinch/micropython-nano-gui/blob/d3759da1078810375c067c373ddeca2810b7a1b8/drivers/st7789/st7789_4bit.py#L134 I can't find it. Could you please give a link or datasheet.pdf Thanks for your work.
I'm damned if I can find where I got it. I'm pretty sure it was from the Adafruit site but I can't find it there. I've posted it here.
Thanks for the pdf. Why here grayscale mode is used instead of framebuf.RGB565? Is it faster? https://github.com/peterhinch/micropython-nano-gui/blob/b196fda84ef72fee5e7fc3359980d67f02a1d774/drivers/st7789/st7789_4bit.py#L67
The ST7789 driver can support displays up to 320x240. The driver was designed around the Adafruit 240x240 display. With RGB565 the buffer size would be 240x240x2 = 115200 bytes. This would be unusable on most platforms. By using a 4-bit greyscale buffer this reduces to 240x240/2 = 28800 bytes which is big but usable on Pyboards, Pico and ESP32 without SPIRAM.
The driver uses a lookup table (LUT) to map the 4-bit value onto a 12-bit color which is a mode that the hardware supports. The LUT is user configurable so the GUI can use a wide range of colors, but only from a palette of 16 user selectable colors. I chose 12-bit mode to minimise transfer time between the framebuf and the hardware.
This is a compromise: transfer time and color selection are offset against a big reduction in RAM usage (transfer time because of the real time mapping from the LUT),
When you use the offset values, what is the outcome? Does the image alter its position on screen? I'm trying to figure out if I made a mistake implementing it or whether the problem is something more subtle.
[EDIT] Answered my own question here.
I looked at the header file you posted. I suggest for a trial we set the window as the manufacturers do. This means commenting out lines 164 and 168 and entering
self._wcd(b'\x2a', b'\x00\x00\x00\xe5') # h says 239 (\xef) but it's actually 229
self._wcd(b'\x2b', b'\x00\x00\x01\x3f') # 319
[EDIT] You'll need to set height=320 and width=230 (or 240) to match these values.
This is a hack but it may point to where we're going wrong. If this doesn't work, try changing the e5
to ef
- it's possible that the header file comment is right and the code is wrong.
I'm puzzled, though. These values in the header seem to imply a zero offset which is where we started.
Tomorrow I'll study the header file in more detail to see if I can find any relevant issues.
I have now studied the TTGO header files in detail. In general they make sense. Many of the settings replicate the software reset defaults - I'm not sure why they explicitly set them to default values. They send one 0xb6 command which is not in the datasheet so I have no idea what that does. There are a couple of cases where their commands slightly alter voltages applied to the display. I've seen this kind of thing in other code - I'm not sure of the consequences but it is not going to cause your specific problem.
They do gamma setting. Adafruit don't, and nor do I. This is not necessary unless you are going to display images - which you're not with a 4-bit driver. Your colors look fine.
What continues to baffle me is their setting of the display window which assumes a 240x320 display. It seems inevitable that, with these settings, some content will be off-screen, which is what you're experiencing. Their Arduino code is complex and I really can't follow it. However I suspect that they later override the default window settings to match the physical display size.
I still therefore think that the problem should be fixable with the right display window settings. If the physical display is smaller than the chip's onboard RAM it must be mapped onto a subset of the RAM. The display window enables the driver to write just to that subset. Getting these settings right is tricky but should fix the problem.
I've ordered one of these from a local supplier so I will experiment. Until it arrives and I spend time with it I'm afraid I've run out of ideas.
1) I understand about the mode = framebuf.GS4_HMSB Thanks.
2) Offset works right. Thanks again.
3) You tell about the 12-bit mode, but here is set 16-bit mode. https://github.com/peterhinch/micropython-nano-gui/blob/b196fda84ef72fee5e7fc3359980d67f02a1d774/drivers/st7789/st7789_4bit.py#L117
as described at p224 9.1.32 COLMOD (3Ah): Interface Pixel Format and it correspondent to p105 8.8.42 Write data for 16-bit/pixel (RGB-5-6-5-bit input), 65K-Colors, 3Ah=”05h”
I'm sorry, I was thinking of another driver. It is 16-bit.
I received my board this morning and have produced color_setup_ttgo.py which is in the directory with the driver. This appears to be pixel-perfect and runs demos such as aclock and color15. It produces a landscape mode display. You'll need to update the driver as my handling of offset was wrong.
Hopefully you want a landscape mode display.
Currently only PORTRAIT mode works and produces a landscape display. I'll have to think that one through so there may be some changes.
Thank you, color_setup_ttgo.py is not pushed to Github.
Also, I found TTGO, which has offsets modes https://github.com/jikegong/TTGO-Esp32-ST7789-Display-MicroPython.git
It is now. I don't know what happened to that git push
- the driver update probably didn't happen either. Anyway, both look correct now.
That link will be very helpful. First thing I noticed is that in their "inverted landscape" mode they use the same offsets as me. I'll look at this further over the next day or two and hopefully produce an update that supports all possible rotations.
The next release of the docs will include a credit to you for your help with supporting this device - it is much appreciated!
I have pushed a new release which now supports all display modes.
There was a nasty bug in the driver which prevented portrait mode from working. I had not catered for the case where the physical width of a display was not divisible by 2. I have tested all modes on TTGO and Adafruit. Hopefully this has fixed all outstanding problems. The setup file has commented out code showing how to invoke each mode.
You'll observe that the setup file transposes PORTRAIT
and LANDSCAPE
constants. This is because the TTGO seems to be designed as a portrait mode display. My driver design assumed that asymmetrical displays would be landscape displays.
The relevant part of the driver doc has an acknowledgement of your work on this.
Please let me know if you find any issues or have any comments.
Hello, Peter. Please move micropython-nano-gui\drivers\st7789\color_setup_ttgo.py to micropython-nano-gui\color_setup\
Don't merge this pull request, but live it open, please.
I'm currently considering where the various color_setup files should go. It seems rather confusing to have them all in one directory, but I haven't thought of a satisfactory alternative. There are two variables, host microcontroller and display adaptor. In the case of TTGO there is currently a third variable - display type - but I hope to remove that.
I'm modifying the driver to handle the mapping of the various orientation options so that they work properly on any device. So if you choose PORTRAIT | USD you will get that on TTGO or Adafruit.
Little note. LANDSCAPE constant is redundant.
if (mode & PORTRAIT) == 0:
this is a LANDSCAPE
ssd = SSD(spi, height=135, width=240, dc=pdc, cs=pcs, rst=prst, offset=OFFSET) # disp_mode==0==LANDSCAPE,
# Portrait configs.
# Normal portrait display
ssd = SSD(spi, height=240, width=135, dc=pdc, cs=pcs, rst=prst, disp_mode=PORTRAIT, offset=OFFSET)
I appreciate that LANDSCAPE
is redundant, however I thought it might be clearer for some users to explicitly specify it. It's arguable either way.
I've moved the setup file as you requested but I'm still wondering how best to organise them.
The code now handles display_mode
options correctly on TTGO and Adafruit. So if you specify PORTRAIT | USD
that's what you'll get. You'll need to check your color_setup.py
as the swapping of modes is now done in the driver and the offset
constructor arg has an extra element.
Hopefully that is the end of the API changes.
The offset[2] will confuse users. They will think offset[0] - x offset[1] - y offset[2] - z ??? This is unclear.
Sorry for my tediousness, and thank you for your patience.
The problem is that the PORTRAIT constant may be the portrait or landscape for different manufacturers in real world (depending on the sequence of soldering the ST7789 and LEDs) https://github.com/peterhinch/micropython-nano-gui/blob/3c142e4f39c835f661230b36311b38c91e080feb/drivers/st7789/st7789_4bit.py#L24
More correct name is PORTRAIT = 0x20 # X-Y Exchange REFLECT = 0x40 # X-Mirror USD = 0x80 # Y-Mirror see Page 125 in pdf
PORTRAIT is a name in an absolute coordinate system, X-Y Exchange is a name in a relative coordinate system
I agree with you about offset and have replaced the offset
arg with display
. This accepts an object defined in the driver which is either GENERIC
(the default) or TDISPLAY
. The user does not need to know the data type of this object. This gives me the option to change its content or its data type in the future without affecting the API. This might be to accommodate some new device. This change also simplifies color_setup.py
and gets rid of the tuple of arbitrary numbers.
If a new device has a different connection (as you suggest above) I'll just need to create a new object for the display
arg, ensuring that PORTRAIT
, USD
and REFLECT
work correctly.
Regarding naming I think USD
is much more descriptive than X-Mirror
partly because it isn't visually a mirror image, and also because X is the long axis on a landscape display and the short one on a portrait. As you know the chip itself uses that terminology but my ageing brain finds it quite confusing :) Which is why I chose terminology which deliberately ignores X, Y, rows and columns:
Landscape: text runs parallel to the long axis. Portrait: text parallel to short axis. USD: Upside down, text is legible. Reflect: You'll need a mirror to read it. I find this easy to grasp. It would take a lot of persuasion to change my mind.
I've pushed an update - barring any bugs I think I'm happy with the API.
I do like the TTGO unit. It's nicely made and is surely the cheapest way to get a decent display on a MicroPython host.
"entities should not be multiplied without necessity" https://en.wikipedia.org/wiki/Occam%27s_razor GENERIC and TDISPLAY are new entities and increase the level of code abstraction. This is maybe good or maybe not. Your will, the developer. Thank you.
A little bit. Please rename micropython-nano-gui\color_setup\color_setup_ttgo.py to micropython-nano-gui\color_setup\ssd7789_ttgo.py
ssd7789_ttgo.py and ssd7789.py files will be located side by side in the browser.
There are two mentions in DRIVERS.md also. Thank you.
Hello, Peter. It seems that I was in a hurry to close the PR. Have you seen my last message about rename?
I think that the up-group level should be a display controller, and the next group level may be a display(or board) or manufacturer.
I have tested TTGO and I am glad.
GENERIC and TDISPLAY are new entities and increase the level of code abstraction.
The added abstraction is the reason for doing it :) It allows me to change the data type without changing the API. Further, there is no reason for the user to think about numeric offset values: these are an aspect of the driver and should be encapsulated in that file. In my opinion, of course.
[EDIT]
I renamed the files, but called them st7789*
rather than ssd7789*
in line with the chip.
Thank you again for your work on this. It has been an enjoyable and fruitful collaboration. I'd be interested to know what application you plan for the TTGO.
Hello, Peter. Could you help me?
I try to add support of TTGO T-Display 1.14" 135*240(Pixel) based on ST7789V
http://www.lilygo.cn/claprod_view.aspx?TypeId=62&Id=1274
https://github.com/Xinyuan-LilyGO/TTGO-T-Display
https://github.com/Xinyuan-LilyGO/TTGO-T-Display/blob/master/image/pinmap.jpg
https://github.com/Xinyuan-LilyGO/TTGO-T-Display/blob/master/schematic/ESP32-TFT(6-26).pdf
It should work as Adafruit 1.3" and 1.54" 240x240 Wide Angle TFT LCD Display with MicroSD - ST7789
but not works.
WIP.
FactoryTest https://github.com/Xinyuan-LilyGO/TTGO-T-Display/blob/master/TFT_eSPI/examples/FactoryTest/FactoryTest.ino ST7789 Initialization https://github.com/Xinyuan-LilyGO/TTGO-T-Display/blob/master/TFT_eSPI/TFT_Drivers/ST7789_Init.h
Thanks.