Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for panel-controlled backlights #586

Closed
tylercamp opened this issue Jul 4, 2024 · 8 comments
Closed

Support for panel-controlled backlights #586

tylercamp opened this issue Jul 4, 2024 · 8 comments
Labels
enhancement New feature or request pinned exempt from stale bot

Comments

@tylercamp
Copy link
Contributor

(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

@tylercamp tylercamp added the enhancement New feature or request label Jul 4, 2024
@tobozo tobozo added the pinned exempt from stale bot label Jul 4, 2024
@lovyan03
Copy link
Owner

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);
    }
  }

@lovyan03
Copy link
Owner

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.

@tylercamp
Copy link
Contributor Author

@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)

@tylercamp
Copy link
Contributor Author

@lovyan03 This almost works, it's just missing a call to start/endWrite, I've opened a PR here #599

@tylercamp
Copy link
Contributor Author

Merged

@dekesone
Copy link

dekesone commented Aug 4, 2024

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.

@tylercamp
Copy link
Contributor Author

@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)

@dekesone
Copy link

dekesone commented Aug 4, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request pinned exempt from stale bot
Projects
None yet
Development

No branches or pull requests

4 participants