adafruit / Adafruit_CircuitPython_ST7735R

ST7735R TFT LCD display driver
MIT License
17 stars 11 forks source link

BGR mode custom init sequence #21

Closed mcauser closed 3 years ago

mcauser commented 3 years ago

I'm trying to get the Unexpected Maker RGB IPS shield working on a TinyS2.

It uses a ST7735R 160x80 "Green Tab" with colstart=26, rowstart=1, BGR mode and inverted. Works fine with TFT_eSPI.

I'm able to get the hello world example working, however it seems the BGR custom init sequence code is not actually setting the BGR bit.

if bgr:
    init_sequence += (
        b"\x36\x01\xC0"  # _MADCTL Default rotation plus BGR encoding
    )

I think that 0xC0 should be 0xC8.

0xC0 == MY | MX
0xC8 == MY | MX | BGR
#define TFT_MAD_MY  0x80
#define TFT_MAD_MX  0x40
#define TFT_MAD_MV  0x20
#define TFT_MAD_ML  0x10
#define TFT_MAD_BGR 0x08 <--
#define TFT_MAD_MH  0x04
#define TFT_MAD_RGB 0x00

When I send the MADCTL command, the colours show up correctly.

# shows as cyan
color_palette[0] = 0xFFFF00

# madctl = my | mx | bgr
display_bus.send(0x36, b'\xC8')

# now shows as yellow
color_palette[0] = 0xFFFF00
ladyada commented 3 years ago

try https://learn.adafruit.com/adafruit-mini-tft-0-dot-96-inch-180x60-breakout/circuitpython-displayio-quickstart

mcauser commented 3 years ago

Hey @ladyada, already read that one - was very helpful.

I think the issue is just the BGR bit is not being set (where 0x00 defaults to RGB order)

Here's it in the old Arduino version: https://github.com/adafruit/Adafruit-ST7735-Library/blob/master/Adafruit_ST7735.h#L18 https://github.com/adafruit/Adafruit-ST7735-Library/blob/master/Adafruit_ST7735.cpp#L283

ladyada commented 3 years ago

hmm! ok please submit a PR for the change and we'll take a look :)

ladyada commented 3 years ago

can you post a pic of what you're seeing with the tinys2 when you pass bgr kwarg or not in? im nt sure the PR is doing what we think it is and i dont own of of those

mcauser commented 3 years ago

Hey @ladyada

If you don't pass in the bgr argument on __init__, it uses the default init sequence b"\x36\x01\x18", which sets mode=BGR. The 8 in 0x18 is the BGR bit being set.

If you do pass in bgr=True, it's actually setting mode=RGB. Appends custom init sequence b"\x36\x01\xC0". The C in 0xC0 sets the rotation and the 0 is the BGR bit unset.

The 1 or C only affects the default orientation. display.rotation = 90 renders like display.rotation = 270 when init'd with 1 instead of C. Other than that, no difference.

Initting this display without the bgr argument actually makes it render the correct colors. display = ST7735R(display_bus, width=80, height=160, colstart=26, rowstart=1, rotation=0, invert=True)

What tripped me is that I know this is a BGR mode display (from using it with Arduino), but setting bgr=True was actually putting the display in RGB mode. It's as if the argument should be renamed to not_bgr or rgb.


Detailed example

import board
import busio
import displayio
import terminalio
from adafruit_display_text import label
from adafruit_st7735r import ST7735R

spi = busio.SPI(clock=board.SCK, MISO=board.MISO, MOSI=board.MOSI)
# using busio instead of board.SPI() as there was incorrect default pins in the board definition - circuitpython PR #4887

tft_cs = board.D16
tft_dc = board.D18
tft_bl = board.D19

displayio.release_displays()
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs, reset=None)

display = ST7735R(display_bus, width=80, height=160, colstart=26, rowstart=1, rotation=0, bgr=True, invert=True)
display.rotation = 90

splash = displayio.Group(max_size=10)
display.show(splash)

color_bitmap = displayio.Bitmap(160, 80, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0xFF0000 # red

bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
splash.append(bg_sprite)

Example 1 - Expecting to see solid red background, see solid blue as this display uses inverted BGR mode

color_palette[0] = 0xFF0000 # red

red


Example 2 - Correctly shows solid green as the green position doesn't change between BGR/RGB

color_palette[0] = 0x00FF00 # green

green


Example 3 - Expecting to see solid blue background, see solid red

color_palette[0] = 0x0000FF # blue

blue


Example 4 - Expecting to see "RED" text in red, but it shows in blue

# write some text in each font color, rgb, cmyk
color_palette[0] = 0x111111 # light grey

text_group_left = displayio.Group(max_size=10, scale=1, x=0, y=6)
text_area_red = label.Label(terminalio.FONT, text="RED", color=0xFF0000)
text_area_green = label.Label(terminalio.FONT, text="\nGREEN", color=0x00FF00)
text_area_blue = label.Label(terminalio.FONT, text="\n\nBLUE", color=0x0000FF)
text_area_white = label.Label(terminalio.FONT, text="\n\n\nWHITE", color=0xFFFFFF)
text_group_left.append(text_area_red)
text_group_left.append(text_area_green)
text_group_left.append(text_area_blue)
text_group_left.append(text_area_white)
splash.append(text_group_left)

text_group_right = displayio.Group(max_size=10, scale=1, x=80, y=6)
text_area_cyan = label.Label(terminalio.FONT, text="CYAN", color=0x00FFFF)
text_group_right.append(text_area_cyan)
text_area_magenta = label.Label(terminalio.FONT, text="\nMAGENTA", color=0xFF00FF)
text_group_right.append(text_area_magenta)
text_area_yellow = label.Label(terminalio.FONT, text="\n\nYELLOW", color=0xFFFF00)
text_group_right.append(text_area_yellow)
text_area_black = label.Label(terminalio.FONT, text="\n\n\nBLACK", color=0x000000)
text_group_right.append(text_area_black)
splash.append(text_group_right)

bgr2


Example 5 - After sending the revised MADCTL command, now correctly shows "RED" in red and "BLUE" in blue.

# set MADCTL == MY | MX | BGR
display_bus.send(0x36, b'\xC8')
# this is my proposed changes 0xC0 -> 0xC8
# however, in doing so, there's no way to unset BGR mode as the default init sequence and bgr=True both set the 8

rgb2


Example 6 - If you send the original MADCTL command, shows blues where reds should be, same as Example 4 above.

# set MADCTL == MY | MX
display_bus.send(0x36, b'\xC0')
# this is the existing behaviour, shows blues where reds should be
mcauser commented 3 years ago

TL;DR Default mode set in the init sequence = BGR Constructing with argument bgr=True actually sets mode = RGB (not BGR)

ladyada commented 3 years ago

!! @makermelissa fyi

tannewt commented 3 years ago

Fixed by #22. Thanks @mcauser

ladyada commented 3 years ago

@tannewt that PR i think was backwards - so re-opening, @makermelissa please take a look this week

makermelissa commented 3 years ago

Yeah, it was backwards. Now the Adafruit displays show up reversed. I think it was a terminology issue, like the setting should have been called rgb or something.

makermelissa commented 3 years ago

Also now setting bgr=False flips the image 180 degrees, but keeps the colors wrong.

makermelissa commented 3 years ago

The terminology in the Arduino code is wrong. According to the Datasheet (https://cdn-shop.adafruit.com/datasheets/ST7735R_V0.2.pdf), that bit is an RGB bit, not a BGR bit, so this was correct before the PR. However, I also have a Chinese RGB display (probably similar to what you have) and it's not looking right with BGR set to false.