From 0ee848488b48dec669f7381c60f30284ae21247a Mon Sep 17 00:00:00 2001 From: alblib Date: Mon, 8 Sep 2025 00:20:04 +0900 Subject: [PATCH] Update GigaDisplayRGB.h: Prevent Digital Mode, Implemented PDM mode, to make the backlight dimming working --- src/GigaDisplayRGB.h | 99 ++++++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/src/GigaDisplayRGB.h b/src/GigaDisplayRGB.h index c48a4d5..4a2a35f 100644 --- a/src/GigaDisplayRGB.h +++ b/src/GigaDisplayRGB.h @@ -17,37 +17,84 @@ class GigaDisplayRGB { using namespace std::chrono_literals; using namespace std::chrono; + class GigaDisplayBacklight { - public: - GigaDisplayBacklight() {} - void begin(int target_percent = 100) { - pin = new mbed::DigitalOut(PB_12); - ticker = new mbed::Ticker(); - ticker->attach(mbed::callback(this, &GigaDisplayBacklight::cb), 2ms); - set(target_percent); +private: + mbed::Ticker* ticker = nullptr; + mbed::DigitalOut* pin = nullptr; + + // Exponential Lightness Model: This constants are determined + // by Table II of the OSA report (exponent = 0.426, wikipedia: lightness) + // and empirical measurement of Giga Display KD040WVFID026-01-C025A by Albertus Liberius + static constexpr float min_pwm_percent = 3.36136f; + static constexpr float max_pwm_percent = 100.f; + static inline float pwm_percent_from_lightness_percent(float lightness_percent) { + return min_pwm_percent * pow(max_pwm_percent / min_pwm_percent, lightness_percent / 100); + } + + // Specification by LED Driver chip LV52204MT + inline static constexpr std::chrono::microseconds tick = 50us; // Ton(20us) < tick < Tw0(100us) + // to prevent digital mode and goto pwm mode + inline static constexpr uint16_t start_sequence_size = 50; // more than Tsel = 2.2ms + // (mode selection determination time period) + + // PDM counter + uint16_t intensity = 0xFFFF; //maxIntensity + uint16_t counter = 0; + uint16_t start_seq_cnt = 0; + + void callback() { + if (start_sequence_size > start_seq_cnt) { + *pin = start_seq_cnt++ & 1; + } else { + // PDM + static uint16_t newcounter = 0; + newcounter = (counter + intensity) & 0xFFFF; + *pin = (counter > newcounter) ? 1 : 0; + counter = newcounter; } - void cb() { - static int counter = 0; - if (counter >= intensity) { - *pin = 0; - } else { - *pin = 1; - } - counter += 10; - if (counter == 100) { - counter = 0; - } + } +public: + GigaDisplayBacklight() {} + + void begin(float target_percent=100.f) { + if (pin) delete pin; + if (ticker) { + ticker->detach(); + delete ticker; } - void set(int target_percent) { - intensity = target_percent; + pin = new mbed::DigitalOut(PB_12); + ticker = new mbed::Ticker(); + ticker->attach(mbed::callback(this, &GigaDisplayBacklight::callback), tick); + set(target_percent); + } + + void set(float target_percent) { + if (0 == intensity) start_seq_cnt = 0; // restart initialization sequence + intensity = static_cast( + constrain( + pwm_percent_from_lightness_percent(target_percent), + min_pwm_percent, + max_pwm_percent + ) / 100.f * 65535.f + ); + } + + void off() { + intensity = 0; // if it is longer than 8.9ms, it is shutdown mode. + } + + inline virtual ~GigaDisplayBacklight() { + if (ticker) { + ticker->detach(); + delete ticker; } - void off() { - set(0); + if (pin) { + delete pin; } - private: - mbed::Ticker* ticker; - mbed::DigitalOut* pin; - int intensity; + } + }; + #endif