From 76c70bdf2c33437aa3d62205fb37d0a5fd66b7f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Wed, 7 Jun 2023 02:46:01 +0900 Subject: [PATCH] [FL-3316] Settings: add contrast adjustment (#2737) Co-authored-by: hedger --- .../services/notification/notification.h | 2 + .../services/notification/notification_app.c | 55 ++++++++++++------- .../services/notification/notification_app.h | 3 +- .../notification/notification_messages.c | 9 +++ .../notification/notification_messages.h | 6 ++ .../notification_settings_app.c | 44 +++++++++++++++ firmware/targets/f18/api_symbols.csv | 5 +- firmware/targets/f7/api_symbols.csv | 5 +- lib/toolbox/value_index.c | 13 +++++ lib/toolbox/value_index.h | 13 +++++ lib/u8g2/u8g2_glue.c | 20 ++++++- lib/u8g2/u8g2_glue.h | 2 + 12 files changed, 152 insertions(+), 25 deletions(-) diff --git a/applications/services/notification/notification.h b/applications/services/notification/notification.h index b38620f0f..0e1c07e5d 100644 --- a/applications/services/notification/notification.h +++ b/applications/services/notification/notification.h @@ -75,6 +75,8 @@ typedef enum { NotificationMessageTypeForceDisplayBrightnessSetting, NotificationMessageTypeLedBrightnessSettingApply, + + NotificationMessageTypeLcdContrastUpdate, } NotificationMessageType; typedef struct { diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c index f91a73f32..2f947fe8a 100644 --- a/applications/services/notification/notification_app.c +++ b/applications/services/notification/notification_app.c @@ -3,6 +3,9 @@ #include #include #include +#include +#include + #include "notification.h" #include "notification_messages.h" #include "notification_app.h" @@ -20,14 +23,14 @@ static const uint8_t reset_sound_mask = 1 << 4; static const uint8_t reset_display_mask = 1 << 5; static const uint8_t reset_blink_mask = 1 << 6; -void notification_vibro_on(bool force); -void notification_vibro_off(); -void notification_sound_on(float freq, float volume, bool force); -void notification_sound_off(); +static void notification_vibro_on(bool force); +static void notification_vibro_off(); +static void notification_sound_on(float freq, float volume, bool force); +static void notification_sound_off(); -uint8_t notification_settings_get_display_brightness(NotificationApp* app, uint8_t value); -uint8_t notification_settings_get_rgb_led_brightness(NotificationApp* app, uint8_t value); -uint32_t notification_settings_display_off_delay_ticks(NotificationApp* app); +static uint8_t notification_settings_get_display_brightness(NotificationApp* app, uint8_t value); +static uint8_t notification_settings_get_rgb_led_brightness(NotificationApp* app, uint8_t value); +static uint32_t notification_settings_display_off_delay_ticks(NotificationApp* app); void notification_message_save_settings(NotificationApp* app) { NotificationAppMessage m = { @@ -39,7 +42,8 @@ void notification_message_save_settings(NotificationApp* app) { }; // internal layer -void notification_apply_internal_led_layer(NotificationLedLayer* layer, uint8_t layer_value) { +static void + notification_apply_internal_led_layer(NotificationLedLayer* layer, uint8_t layer_value) { furi_assert(layer); furi_assert(layer->index < LayerMAX); @@ -52,7 +56,13 @@ void notification_apply_internal_led_layer(NotificationLedLayer* layer, uint8_t } } -bool notification_is_any_led_layer_internal_and_not_empty(NotificationApp* app) { +static void notification_apply_lcd_contrast(NotificationApp* app) { + Gui* gui = furi_record_open(RECORD_GUI); + u8x8_d_st756x_set_contrast(&gui->canvas->fb.u8x8, app->settings.contrast); + furi_record_close(RECORD_GUI); +} + +static bool notification_is_any_led_layer_internal_and_not_empty(NotificationApp* app) { bool result = false; if((app->led[0].index == LayerInternal) || (app->led[1].index == LayerInternal) || (app->led[2].index == LayerInternal)) { @@ -67,7 +77,7 @@ bool notification_is_any_led_layer_internal_and_not_empty(NotificationApp* app) } // notification layer -void notification_apply_notification_led_layer( +static void notification_apply_notification_led_layer( NotificationLedLayer* layer, const uint8_t layer_value) { furi_assert(layer); @@ -81,7 +91,7 @@ void notification_apply_notification_led_layer( furi_hal_light_set(layer->light, layer->value[LayerNotification]); } -void notification_reset_notification_led_layer(NotificationLedLayer* layer) { +static void notification_reset_notification_led_layer(NotificationLedLayer* layer) { furi_assert(layer); furi_assert(layer->index < LayerMAX); @@ -94,7 +104,7 @@ void notification_reset_notification_led_layer(NotificationLedLayer* layer) { furi_hal_light_set(layer->light, layer->value[LayerInternal]); } -void notification_reset_notification_layer(NotificationApp* app, uint8_t reset_mask) { +static void notification_reset_notification_layer(NotificationApp* app, uint8_t reset_mask) { if(reset_mask & reset_blink_mask) { furi_hal_light_blink_stop(); } @@ -130,28 +140,28 @@ uint8_t notification_settings_get_display_brightness(NotificationApp* app, uint8 return (value * app->settings.display_brightness); } -uint8_t notification_settings_get_rgb_led_brightness(NotificationApp* app, uint8_t value) { +static uint8_t notification_settings_get_rgb_led_brightness(NotificationApp* app, uint8_t value) { return (value * app->settings.led_brightness); } -uint32_t notification_settings_display_off_delay_ticks(NotificationApp* app) { +static uint32_t notification_settings_display_off_delay_ticks(NotificationApp* app) { return ( (float)(app->settings.display_off_delay_ms) / (1000.0f / furi_kernel_get_tick_frequency())); } // generics -void notification_vibro_on(bool force) { +static void notification_vibro_on(bool force) { if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode) || force) { furi_hal_vibro_on(true); } } -void notification_vibro_off() { +static void notification_vibro_off() { furi_hal_vibro_on(false); } -void notification_sound_on(float freq, float volume, bool force) { +static void notification_sound_on(float freq, float volume, bool force) { if(!furi_hal_rtc_is_flag_set(FuriHalRtcFlagStealthMode) || force) { if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(30)) { furi_hal_speaker_start(freq, volume); @@ -159,7 +169,7 @@ void notification_sound_on(float freq, float volume, bool force) { } } -void notification_sound_off() { +static void notification_sound_off() { if(furi_hal_speaker_is_mine()) { furi_hal_speaker_stop(); furi_hal_speaker_release(); @@ -174,7 +184,7 @@ static void notification_display_timer(void* ctx) { } // message processing -void notification_process_notification_message( +static void notification_process_notification_message( NotificationApp* app, NotificationAppMessage* message) { uint32_t notification_message_index = 0; @@ -333,6 +343,9 @@ void notification_process_notification_message( reset_mask |= reset_green_mask; reset_mask |= reset_blue_mask; break; + case NotificationMessageTypeLcdContrastUpdate: + notification_apply_lcd_contrast(app); + break; } notification_message_index++; notification_message = (*message->sequence)[notification_message_index]; @@ -361,7 +374,8 @@ void notification_process_notification_message( } } -void notification_process_internal_message(NotificationApp* app, NotificationAppMessage* message) { +static void + notification_process_internal_message(NotificationApp* app, NotificationAppMessage* message) { uint32_t notification_message_index = 0; const NotificationMessage* notification_message; notification_message = (*message->sequence)[notification_message_index]; @@ -548,6 +562,7 @@ int32_t notification_srv(void* p) { notification_apply_internal_led_layer(&app->led[0], 0x00); notification_apply_internal_led_layer(&app->led[1], 0x00); notification_apply_internal_led_layer(&app->led[2], 0x00); + notification_apply_lcd_contrast(app); furi_record_create(RECORD_NOTIFICATION, app); diff --git a/applications/services/notification/notification_app.h b/applications/services/notification/notification_app.h index 88194bfbd..cacc17ffb 100644 --- a/applications/services/notification/notification_app.h +++ b/applications/services/notification/notification_app.h @@ -32,7 +32,7 @@ typedef struct { Light light; } NotificationLedLayer; -#define NOTIFICATION_SETTINGS_VERSION 0x01 +#define NOTIFICATION_SETTINGS_VERSION 0x02 #define NOTIFICATION_SETTINGS_PATH INT_PATH(NOTIFICATION_SETTINGS_FILE_NAME) typedef struct { @@ -41,6 +41,7 @@ typedef struct { float led_brightness; float speaker_volume; uint32_t display_off_delay_ms; + int8_t contrast; bool vibro_on; } NotificationSettings; diff --git a/applications/services/notification/notification_messages.c b/applications/services/notification/notification_messages.c index 51f3533c3..28ec327c6 100644 --- a/applications/services/notification/notification_messages.c +++ b/applications/services/notification/notification_messages.c @@ -197,6 +197,10 @@ const NotificationMessage message_force_display_brightness_setting_1f = { .data.forced_settings.display_brightness = 1.0f, }; +const NotificationMessage message_lcd_contrast_update = { + .type = NotificationMessageTypeLcdContrastUpdate, +}; + /****************************** Message sequences ******************************/ // Reset @@ -566,3 +570,8 @@ const NotificationSequence sequence_audiovisual_alert = { &message_vibro_off, NULL, }; + +const NotificationSequence sequence_lcd_contrast_update = { + &message_lcd_contrast_update, + NULL, +}; diff --git a/applications/services/notification/notification_messages.h b/applications/services/notification/notification_messages.h index 100796917..d87cf74f4 100644 --- a/applications/services/notification/notification_messages.h +++ b/applications/services/notification/notification_messages.h @@ -63,6 +63,9 @@ extern const NotificationMessage message_force_vibro_setting_on; extern const NotificationMessage message_force_vibro_setting_off; extern const NotificationMessage message_force_display_brightness_setting_1f; +// LCD Messages +extern const NotificationMessage message_lcd_contrast_update; + /****************************** Message sequences ******************************/ // Reset @@ -138,6 +141,9 @@ extern const NotificationSequence sequence_success; extern const NotificationSequence sequence_error; extern const NotificationSequence sequence_audiovisual_alert; +// LCD +extern const NotificationSequence sequence_lcd_contrast_update; + #ifdef __cplusplus } #endif diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c index 8efbc5e08..450aaee14 100644 --- a/applications/settings/notification_settings/notification_settings_app.c +++ b/applications/settings/notification_settings/notification_settings_app.c @@ -20,6 +20,34 @@ static const NotificationSequence sequence_note_c = { NULL, }; +#define CONTRAST_COUNT 11 +const char* const contrast_text[CONTRAST_COUNT] = { + "-5", + "-4", + "-3", + "-2", + "-1", + "0", + "+1", + "+2", + "+3", + "+4", + "+5", +}; +const int32_t contrast_value[CONTRAST_COUNT] = { + -5, + -4, + -3, + -2, + -1, + 0, + 1, + 2, + 3, + 4, + 5, +}; + #define BACKLIGHT_COUNT 5 const char* const backlight_text[BACKLIGHT_COUNT] = { "0%", @@ -64,6 +92,15 @@ const char* const vibro_text[VIBRO_COUNT] = { }; const bool vibro_value[VIBRO_COUNT] = {false, true}; +static void contrast_changed(VariableItem* item) { + NotificationAppSettings* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, contrast_text[index]); + app->notification->settings.contrast = contrast_value[index]; + notification_message(app->notification, &sequence_lcd_contrast_update); +} + static void backlight_changed(VariableItem* item) { NotificationAppSettings* app = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); @@ -136,6 +173,13 @@ static NotificationAppSettings* alloc_settings() { VariableItem* item; uint8_t value_index; + item = variable_item_list_add( + app->variable_item_list, "LCD Contrast", CONTRAST_COUNT, contrast_changed, app); + value_index = + value_index_int32(app->notification->settings.contrast, contrast_value, CONTRAST_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, contrast_text[value_index]); + item = variable_item_list_add( app->variable_item_list, "LCD Backlight", BACKLIGHT_COUNT, backlight_changed, app); value_index = value_index_float( diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 3c075e0d1..f3c4e31d7 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,28.2,, +Version,+,28.3,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1999,6 +1999,7 @@ Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*" Function,+,validator_is_file_free,void,ValidatorIsFile* Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t" Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t" +Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t" Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t" Function,+,variable_item_get_context,void*,VariableItem* Function,+,variable_item_get_current_value_index,uint8_t,VariableItem* @@ -2259,6 +2260,7 @@ Variable,+,message_force_vibro_setting_off,const NotificationMessage, Variable,+,message_force_vibro_setting_on,const NotificationMessage, Variable,+,message_green_0,const NotificationMessage, Variable,+,message_green_255,const NotificationMessage, +Variable,+,message_lcd_contrast_update,const NotificationMessage, Variable,+,message_note_a0,const NotificationMessage, Variable,+,message_note_a1,const NotificationMessage, Variable,+,message_note_a2,const NotificationMessage, @@ -2402,6 +2404,7 @@ Variable,+,sequence_display_backlight_off_delay_1000,const NotificationSequence, Variable,+,sequence_display_backlight_on,const NotificationSequence, Variable,+,sequence_double_vibro,const NotificationSequence, Variable,+,sequence_error,const NotificationSequence, +Variable,+,sequence_lcd_contrast_update,const NotificationSequence, Variable,+,sequence_not_charging,const NotificationSequence, Variable,+,sequence_reset_blue,const NotificationSequence, Variable,+,sequence_reset_display,const NotificationSequence, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index a9ce0c26a..a8708ce8c 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,28.2,, +Version,+,28.3,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -2923,6 +2923,7 @@ Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*" Function,+,validator_is_file_free,void,ValidatorIsFile* Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t" Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t" +Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t" Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t" Function,+,variable_item_get_context,void*,VariableItem* Function,+,variable_item_get_current_value_index,uint8_t,VariableItem* @@ -3192,6 +3193,7 @@ Variable,+,message_force_vibro_setting_off,const NotificationMessage, Variable,+,message_force_vibro_setting_on,const NotificationMessage, Variable,+,message_green_0,const NotificationMessage, Variable,+,message_green_255,const NotificationMessage, +Variable,+,message_lcd_contrast_update,const NotificationMessage, Variable,+,message_note_a0,const NotificationMessage, Variable,+,message_note_a1,const NotificationMessage, Variable,+,message_note_a2,const NotificationMessage, @@ -3335,6 +3337,7 @@ Variable,+,sequence_display_backlight_off_delay_1000,const NotificationSequence, Variable,+,sequence_display_backlight_on,const NotificationSequence, Variable,+,sequence_double_vibro,const NotificationSequence, Variable,+,sequence_error,const NotificationSequence, +Variable,+,sequence_lcd_contrast_update,const NotificationSequence, Variable,+,sequence_not_charging,const NotificationSequence, Variable,+,sequence_reset_blue,const NotificationSequence, Variable,+,sequence_reset_display,const NotificationSequence, diff --git a/lib/toolbox/value_index.c b/lib/toolbox/value_index.c index e0745e434..5ec0fb962 100644 --- a/lib/toolbox/value_index.c +++ b/lib/toolbox/value_index.c @@ -1,5 +1,18 @@ #include "value_index.h" +uint8_t value_index_int32(const int32_t value, const int32_t values[], uint8_t values_count) { + int64_t last_value = INT64_MIN; + uint8_t index = 0; + for(uint8_t i = 0; i < values_count; i++) { + if((value >= last_value) && (value <= values[i])) { + index = i; + break; + } + last_value = values[i]; + } + return index; +} + uint8_t value_index_uint32(const uint32_t value, const uint32_t values[], uint8_t values_count) { int64_t last_value = INT64_MIN; uint8_t index = 0; diff --git a/lib/toolbox/value_index.h b/lib/toolbox/value_index.h index 9459292a7..5aa768e3d 100644 --- a/lib/toolbox/value_index.h +++ b/lib/toolbox/value_index.h @@ -7,6 +7,19 @@ extern "C" { #endif +/** Get the index of a int32_t array element which is closest to the given value. + * + * Returned index corresponds to the first element found. + * If no suitable elements were found, the function returns 0. + * + * @param value value to be searched. + * @param values pointer to the array to perform the search in. + * @param values_count array size. + * + * @return value's index. + */ +uint8_t value_index_int32(const int32_t value, const int32_t values[], uint8_t values_count); + /** Get the index of a uint32_t array element which is closest to the given value. * * Returned index corresponds to the first element found. diff --git a/lib/u8g2/u8g2_glue.c b/lib/u8g2/u8g2_glue.c index 17a702b50..0d4879bce 100644 --- a/lib/u8g2/u8g2_glue.c +++ b/lib/u8g2/u8g2_glue.c @@ -2,6 +2,9 @@ #include +#define CONTRAST_ERC 32 +#define CONTRAST_MGG 31 + uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { UNUSED(u8x8); UNUSED(arg_ptr); @@ -207,6 +210,19 @@ void u8x8_d_st756x_init(u8x8_t* u8x8, uint8_t contrast, uint8_t regulation_ratio u8x8_cad_EndTransfer(u8x8); } +void u8x8_d_st756x_set_contrast(u8x8_t* u8x8, int8_t contrast_offset) { + uint8_t contrast = (furi_hal_version_get_hw_display() == FuriHalVersionDisplayMgg) ? + CONTRAST_MGG : + CONTRAST_ERC; + contrast += contrast_offset; + contrast = contrast & 0b00111111; + + u8x8_cad_StartTransfer(u8x8); + u8x8_cad_SendCmd(u8x8, ST756X_CMD_SET_EV); + u8x8_cad_SendArg(u8x8, contrast); + u8x8_cad_EndTransfer(u8x8); +} + uint8_t u8x8_d_st756x_flipper(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) { /* call common procedure first and handle messages there */ if(u8x8_d_st756x_common(u8x8, msg, arg_int, arg_ptr) == 0) { @@ -225,7 +241,7 @@ uint8_t u8x8_d_st756x_flipper(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* * RR = 10 / ((1 - (63 - 32) / 162) * 2.1) ~= 5.88 is 6 (0b110) * Bias = 1/9 (false) */ - u8x8_d_st756x_init(u8x8, 31, 0b110, false); + u8x8_d_st756x_init(u8x8, CONTRAST_MGG, 0b110, false); } else { /* ERC v1(ST7565) and v2(ST7567) * EV = 33 @@ -233,7 +249,7 @@ uint8_t u8x8_d_st756x_flipper(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* * RR = 9.3 / ((1 - (63 - 32) / 162) * 2.1) ~= 5.47 is 5.5 (0b101) * Bias = 1/9 (false) */ - u8x8_d_st756x_init(u8x8, 32, 0b101, false); + u8x8_d_st756x_init(u8x8, CONTRAST_ERC, 0b101, false); } break; case U8X8_MSG_DISPLAY_SET_FLIP_MODE: diff --git a/lib/u8g2/u8g2_glue.h b/lib/u8g2/u8g2_glue.h index 91ba2980a..af236279e 100644 --- a/lib/u8g2/u8g2_glue.h +++ b/lib/u8g2/u8g2_glue.h @@ -14,3 +14,5 @@ void u8g2_Setup_st756x_flipper( u8x8_msg_cb gpio_and_delay_cb); void u8x8_d_st756x_init(u8x8_t* u8x8, uint8_t contrast, uint8_t regulation_ratio, bool bias); + +void u8x8_d_st756x_set_contrast(u8x8_t* u8x8, int8_t contrast_offset);