Support for panel-controlled backlights
Closed this issue · 8 comments
(Moved from #583 )
Some panels, i.e. SSD1963, come with built-in backlight control which require device-specific commands to manage.
Currently there isn't any ILight
implementation which supports this.
For SSD1963 specifically, these commands are needed for backlight control:
void Set_1963_PWM(uint8_t value)
{
startWrite();
writeCommand16(0xBE);
_bus_instance.flush();
writeData( 0x05 );
writeData( value );
writeData( 0x01 );
writeData( 0xFF );
writeData( 0x00 );
writeData( 0x00 );
endWrite();
}
Since this type of backlight control is specific to the particular Panel_LCD
, I wonder if any of these minor refactors would be appropriate:
// additional class to be mixed in when appropriate and manually called by the user if needed
class IPanel_LCD_InteractiveBacklight {
// (1) panel is capable of creating an ILight instance which references this panel for commands
virtual ILight* createLight() = 0;
// ... or ...
// (2) panel directly exposes a `setBrightness`, and a new `Light_InteractivePanel` class
// would simply defer to this
virtual void setBrightness(...) = 0;
};
// ... or ...
class Panel_SSD1963 {
public:
// (3) panel defines its own `ILight` impl to be explicitly created by the user and assigned to `LGFX_Device`
class Light : ILight { ... };
};
// ... or ...
class Panel_Device {
// ...
// (4) all panels may directly offer a `ILight`; panels like SSD1963 will always have backlight control
//
// if no `ILight` was specifically assigned to `LGFX_Device`, then it would defer to
// the panel
virtual ILight* getLight() { return nullptr; };
// ...
};
(2) seems most in line with current LGFX patterns
Hello, @tylercamp , @tobozo
Apologies for the late reply.
Here are my thoughts:
void Panel_SSD1963::setBrightness(uint8_t brightness) //override
{
if (_light) { Panel_LCD::setBrightness(brightness); }
else {
uint8_t cmds[] = { 0xBE, 6, 0x05, brightness, 0x01, 0xFF, 0x00, 0x00, 0xFF, 0xFF };
command_list(cmds);
}
}
I've updated the develop branch, so please try it out.
If Light is not configured, the SSD1963 built-in PWM control should work automatically.
@lovyan03 Nice! I didn't notice the panel had a setBrightness
on it directly
I'm away from home and don't have a device to test with, dekesone
may be able to test in the meantime (I'll comment on the original issue and tag him)
Merged
I'm not able to get this to work. I'm not instantiating an instance of the Light_PWM, but now get no response from the display. @tylercamp can you share your config?
On a side note, is anyone using PLatformIO ? If I change my platformio.ini file to reference the develop branch of LGFX
lib_deps = lovyan03/LovyanGFX #develop
it will not build. But if I download the develop branch from Github and extract it into the solution (and change my #include, it will build successfully.
@dekesone I'm also using PlatformIO and am referencing my own fork currently, but lovyan repo should work too since it's been merged:
lib_deps =
https://github.com/tylercamp/LovyanGFX#develop
(I also tried changing to lovyan repo with https://github.com/lovyan03/LovyanGFX#develop
just in case, and that also worked for me)
My LGFX config:
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_SSD1963 _panel_instance;
lgfx::Bus_Parallel8 _bus_instance;
lgfx::Touch_FT5x06 _touch_instance;
public:
LGFX(void)
{
{
auto cfg = _bus_instance.config();
cfg.pin_wr = DISPLAY_SSD1963_WR;
cfg.pin_rd = DISPLAY_SSD1963_RD;
cfg.pin_rs = DISPLAY_SSD1963_RS;
cfg.pin_d0 = DISPLAY_SSD1963_D0;
cfg.pin_d1 = DISPLAY_SSD1963_D1;
cfg.pin_d2 = DISPLAY_SSD1963_D2;
cfg.pin_d3 = DISPLAY_SSD1963_D3;
cfg.pin_d4 = DISPLAY_SSD1963_D4;
cfg.pin_d5 = DISPLAY_SSD1963_D5;
cfg.pin_d6 = DISPLAY_SSD1963_D6;
cfg.pin_d7 = DISPLAY_SSD1963_D7;
_bus_instance.config(cfg);
_panel_instance.setBus(&_bus_instance);
}
{
auto cfg = _panel_instance.config();
cfg.pin_cs = DISPLAY_SSD1963_CS;
cfg.pin_rst = DISPLAY_SSD1963_RST;
cfg.pin_busy = 35;
cfg.panel_width = cfg.memory_width = 800;
cfg.panel_height = cfg.memory_height = 480;
cfg.offset_x = 0;
cfg.offset_y = 0;
cfg.offset_rotation = 0;
cfg.rgb_order = true;
cfg.dlen_16bit = false;
_panel_instance.config(cfg);
}
{
auto cfg = _touch_instance.config();
cfg.x_min = 0;
cfg.x_max = 839;
cfg.y_min = 0;
cfg.y_max = 479;
cfg.pin_int = TOUCH_INT;
cfg.bus_shared = true;
cfg.offset_rotation = 0;
cfg.pin_rst = TOUCH_RST;
cfg.i2c_port = 1;
cfg.i2c_addr = 0x38;
cfg.pin_sda = TOUCH_SDA;
cfg.pin_scl = TOUCH_SCL;
cfg.freq = 400000;
_touch_instance.config(cfg);
_panel_instance.setTouch(&_touch_instance);
}
setPanel(&_panel_instance);
}
};
To change the brightness I just call display->setBrightness
. For my test I did it immediately after display init, since updating brightness in main loop needs to avoid calling LGFX functions in parallel (I'm using LVGL with multithreaded render and pushImageDMA
using a call on dedicated thread)
display = new LGFX();
display->init();
display->clear(0);
display->setBrightness(10);
(Set very low for testing just so it's easier to see diff. in brightness)
Everything's working fine now, and I can confirm the PWM control now works as expected. Thanks!
(for some reason, using the lib_deps reference to lovyan03/LovyanGFX#develop
still does not work, even though the code is downloaded on build. But explicitly using the full github url lib_deps = https://github.com/lovyan03/LovyanGFX#develop
works correctly.