From c10b198da228315311e83431485989071217c8b2 Mon Sep 17 00:00:00 2001 From: akasaka Date: Tue, 19 Nov 2024 19:04:13 +0900 Subject: [PATCH] [GU7000] Add display blanking to reduce strain on the heater filaments of VFD --- include/devices/mid_clock_noritake.h | 1 + include/devices/mid_clock_noritake_wide.h | 1 + include/display/gu7000.h | 1 + src/app/menu.cpp | 6 +-- src/display/gu7000.cpp | 64 ++++++++++++++++------- 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/include/devices/mid_clock_noritake.h b/include/devices/mid_clock_noritake.h index 1cf9dff..08673ab 100644 --- a/include/devices/mid_clock_noritake.h +++ b/include/devices/mid_clock_noritake.h @@ -5,6 +5,7 @@ // #define HAS_OTAFVU #define HAS_OUTPUT_GU7000 +#define HAS_DISPLAY_BLANKING #define HAS_MOTION_SENSOR #define HAS_TEMP_SENSOR #define HAS_KEYPAD diff --git a/include/devices/mid_clock_noritake_wide.h b/include/devices/mid_clock_noritake_wide.h index 8a200f7..aaf1196 100644 --- a/include/devices/mid_clock_noritake_wide.h +++ b/include/devices/mid_clock_noritake_wide.h @@ -5,6 +5,7 @@ #define HAS_OTAFVU #define HAS_OUTPUT_GU7000 +#define HAS_DISPLAY_BLANKING // #define HAS_TEMP_SENSOR #define HAS_MOTION_SENSOR #define HAS_KEYPAD diff --git a/include/display/gu7000.h b/include/display/gu7000.h index 0cc58ca..a85d57a 100644 --- a/include/display/gu7000.h +++ b/include/display/gu7000.h @@ -38,6 +38,7 @@ class ItronGU7000Driver: public DisplayDriver { gpio_num_t databus_gpios[8]; gpio_num_t wr_gpio; gpio_num_t busy_gpio; + bool show_state; inline void set_databus(uint8_t data); inline void pulse_clock(); diff --git a/src/app/menu.cpp b/src/app/menu.cpp index e5edf09..2fe89a9 100644 --- a/src/app/menu.cpp +++ b/src/app/menu.cpp @@ -229,9 +229,6 @@ AppShimMenu::AppShimMenu(Beeper *b, NewSequencer *s, Yukkuri *y, AmbientLightSen screen_times->add_view(new MenuNumberSelectorPreferenceView(localized_string("Wordnik"), PREFS_KEY_SCRN_TIME_WORD_OF_THE_DAY_SECONDS, 0, 3600, 1, normalActivationFunction)); #endif screen_times->add_view(new MenuNumberSelectorPreferenceView(localized_string("Foobar2000"), PREFS_KEY_SCRN_TIME_FOOBAR_SECONDS, 0, 3600, 1, normalActivationFunction)); -#if HAS(DISPLAY_BLANKING) - display_menu->add_view(new MenuNumberSelectorPreferenceView(localized_string("Blank display after (s)"), PREFS_KEY_MOTIONLESS_TIME_OFF_SECONDS, 0, 21600, 1, normalActivationFunction)); -#endif #if HAS(VARYING_BRIGHTNESS) display_menu->add_view(new MenuListSelectorPreferenceView( localized_string("Brightness"), @@ -245,6 +242,9 @@ AppShimMenu::AppShimMenu(Beeper *b, NewSequencer *s, Yukkuri *y, AmbientLightSen PREFS_KEY_BRIGHTNESS_MODE, normalActivationFunction )); +#endif +#if HAS(DISPLAY_BLANKING) + display_menu->add_view(new MenuNumberSelectorPreferenceView(localized_string("Blank display after (s)"), PREFS_KEY_MOTIONLESS_TIME_OFF_SECONDS, 0, 21600, 1, normalActivationFunction)); #endif display_menu->add_view(new MenuNumberSelectorPreferenceView(localized_string("Turn display off after (s)"), PREFS_KEY_MOTIONLESS_TIME_HV_OFF_SECONDS, 0, 72000, 1, normalActivationFunction)); display_menu->add_view(new MenuBooleanSettingView(localized_string("Keypress beep"), PREFS_KEY_BUTTON_BEEP, [b](bool newValue) { diff --git a/src/display/gu7000.cpp b/src/display/gu7000.cpp index 4f0a31b..b28efd2 100644 --- a/src/display/gu7000.cpp +++ b/src/display/gu7000.cpp @@ -54,6 +54,8 @@ void ItronGU7000Driver::initialize() { ESP_ERROR_CHECK(gpio_config(&io_conf)); + show_state = true; + wait_shit_through(); delay(2000); } @@ -94,7 +96,6 @@ void ItronGU7000Driver::write_string(const char * s) { } void ItronGU7000Driver::reset() { - // taskENTER_CRITICAL(&_spinlock); wait_shit_through(); // Bringup Step 1: Initialize display @@ -119,12 +120,37 @@ void ItronGU7000Driver::reset() { } void ItronGU7000Driver::set_show(bool show) { + taskENTER_CRITICAL(&_spinlock); + + ESP_LOGI(LOG_TAG, "Show = %i", show); + /** + * From datasheet: + * + * P=2~4の場合、スクリーンセーバーの起動を行ないます。スクリーンセーバーは + * 次のデータ入力により中断され、コマンド以前の表示状態に復帰します + * + * Thus we need to save the show state and stop data flow when entering screen blanking mode + */ + show_state = show; + write_string("\x1F\x28\x61\x40"); + // Turn off the display without turning off the heaters. This helps reduce strain on the heaters and prevent their failure from metal fatigue. + set_databus(show ? 0x1 : 0x2); + pulse_clock(); + taskEXIT_CRITICAL(&_spinlock); } void ItronGU7000Driver::set_power(bool power) { taskENTER_CRITICAL(&_spinlock); + /** + * From datasheet: + * P=0~1の場合、表示用電源のON/OFF制御を行ないます。 + * 次の表示用電源のON/OFF制御コマンドが入力されるまで保持されます + * + * Thus we don't need to save state unlike the `set_show` command + */ + ESP_LOGI(LOG_TAG, "Power = %i", power); write_string("\x1F\x28\x61\x40"); set_databus(power ? 0x1 : 0x0); pulse_clock(); @@ -152,25 +178,27 @@ inline uint8_t flipByte(uint8_t c){ void ItronGU7000Driver::write_fanta(const uint8_t * strides, size_t count) { taskENTER_CRITICAL(&_spinlock); - write_string("\x1F\x24"); // cursor move to 0 - set_databus(0); - pulse_clock(); pulse_clock(); pulse_clock(); pulse_clock(); - - write_string("\x1F\x28\x66\x11"); - set_databus(HWCONF_DISPLAY_WIDTH_PX & 0x00FF); - pulse_clock(); - set_databus(HWCONF_DISPLAY_WIDTH_PX & 0xFF00); - pulse_clock(); - set_databus((HWCONF_DISPLAY_HEIGHT_PX / 8) & 0x00FF); - pulse_clock(); - set_databus((HWCONF_DISPLAY_HEIGHT_PX / 8) & 0xFF00); - pulse_clock(); - set_databus(1); - pulse_clock(); + if(show_state) { // <- see technote in `set_show` method above + write_string("\x1F\x24"); // cursor move to 0 + set_databus(0); + pulse_clock(); pulse_clock(); pulse_clock(); pulse_clock(); - for(int i = 0; i < count; i++) { - set_databus(flipByte(strides[i])); + write_string("\x1F\x28\x66\x11"); + set_databus(HWCONF_DISPLAY_WIDTH_PX & 0x00FF); pulse_clock(); + set_databus(HWCONF_DISPLAY_WIDTH_PX & 0xFF00); + pulse_clock(); + set_databus((HWCONF_DISPLAY_HEIGHT_PX / 8) & 0x00FF); + pulse_clock(); + set_databus((HWCONF_DISPLAY_HEIGHT_PX / 8) & 0xFF00); + pulse_clock(); + set_databus(1); + pulse_clock(); + + for(int i = 0; i < count; i++) { + set_databus(flipByte(strides[i])); + pulse_clock(); + } } taskEXIT_CRITICAL(&_spinlock);