From 2073575f546ed7439b0427e690692d907f510934 Mon Sep 17 00:00:00 2001 From: Slavasil Date: Sat, 12 Sep 2026 21:02:29 +0300 Subject: [PATCH] ui changes speedometer: digit color now changes gradually with speed odometer: the last digit is now aligned to bottom --- main.c | 59 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/main.c b/main.c index ac5e4b5..b00a94d 100644 --- a/main.c +++ b/main.c @@ -381,6 +381,14 @@ bool speed_measure_timer_callback(repeating_timer_t *rt) { return true; } +uint16_t color565_lerp(uint16_t a, uint16_t b, uint alphaPercent) { + uint alphaComplement = 100 - alphaPercent; + uint16_t red = ((b >> 11) * alphaPercent + (a >> 11) * alphaComplement) / 100; + uint16_t green = (((b >> 5) & 0x3F) * alphaPercent + ((a >> 5) & 0x3F) * alphaComplement) / 100; + uint16_t blue = ((b & 0x1F) * alphaPercent + (a & 0x1F) * alphaComplement) / 100; + return blue | (green << 5) | (red << 11); +} + // speed is in "2.1" decimal fixed-point, in km/h void draw_speed(uint value) { #define DIGITS_START_X 20 @@ -391,24 +399,23 @@ void draw_speed(uint value) { if (value > 999) value = 999; - uint16_t color; - if (value >= 300) - color = 0xfd04; - else if (value >= 200) - color = 0xfe84; - else if (value >= 150) - color = 0xdfe4; - else if (value >= 100) - color = 0x6fe4; - else if (value >= 50) - color = 0x27fb; - else - color = 0x04ff; + const uint16_t speedToColorX[] = {0, 50, 100, 150, 200, 300}; + const uint16_t speedToColorY[] = {0x04ff, 0x27fb, 0x6fe4, 0xdfe4, 0xfe84, 0xfd04}; + const size_t speedToColorPointCount = 6; - lcd_draw_digit(value / 100, DIGITS_START_X, DIGITS_START_Y, color, 0x0000); - lcd_draw_digit((value / 10) % 10, DIGITS_START_X + DIGIT_WIDTH + DIGIT_SPACING, DIGITS_START_Y, color, 0x0000); + uint16_t color = speedToColorY[speedToColorPointCount - 1]; + for (int i = 1; i < speedToColorPointCount; ++i) { + if (value <= speedToColorX[i]) { + color = color565_lerp(speedToColorY[i - 1], speedToColorY[i], + (value - speedToColorX[i - 1]) * 100 / (speedToColorX[i] - speedToColorX[i - 1])); + break; + } + } + + lcd_draw_digit(value / 100, DIGITS_START_X, DIGITS_START_Y, color, 0x528a); + lcd_draw_digit((value / 10) % 10, DIGITS_START_X + DIGIT_WIDTH + DIGIT_SPACING, DIGITS_START_Y, color, 0x528a); lcd_draw_decimal_point(DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING, DIGITS_START_Y + 101, color); - lcd_draw_digit(value % 10, DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING * 2 + 5, DIGITS_START_Y, color, 0x0000); + lcd_draw_digit(value % 10, DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING * 2 + 5, DIGITS_START_Y, color, 0x528a); #undef DIGITS_START_X #undef DIGITS_START_Y @@ -417,11 +424,11 @@ void draw_speed(uint value) { } // distance is in "2.3" decimal fixed-point, in kilometers -void draw_distance(uint value) { +void draw_short_term_distance(uint value) { #define DIGITS_START_X 20 #define DIGITS_START_Y 37 #define SMALL_DIGITS_Y_OFFSET 28 -#define XSMALL_DIGITS_Y_OFFSET 28 +#define XSMALL_DIGITS_Y_OFFSET 60 #define DIGIT_WIDTH 64 #define SMALL_DIGIT_WIDTH 48 #define XSMALL_DIGIT_WIDTH 30 @@ -432,19 +439,19 @@ void draw_distance(uint value) { if (value > 99999) value = 99999; - lcd_draw_digit(value / 10000, DIGITS_START_X, DIGITS_START_Y, 0xffff, 0x0000); - lcd_draw_digit((value / 1000) % 10, DIGITS_START_X + DIGIT_WIDTH + DIGIT_SPACING, DIGITS_START_Y, 0xffff, 0x0000); + lcd_draw_digit(value / 10000, DIGITS_START_X, DIGITS_START_Y, 0xffff, 0x528a); + lcd_draw_digit((value / 1000) % 10, DIGITS_START_X + DIGIT_WIDTH + DIGIT_SPACING, DIGITS_START_Y, 0xffff, 0x528a); lcd_draw_decimal_point(DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING, DIGITS_START_Y + 101, 0xffff); lcd_draw_small_digit((value / 100) % 10, DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING * 2 + 10, - DIGITS_START_Y + SMALL_DIGITS_Y_OFFSET, 0xffff, 0x0000); + DIGITS_START_Y + SMALL_DIGITS_Y_OFFSET, 0xffff, 0x528a); lcd_draw_small_digit((value / 10) % 10, DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING * 2 + SMALL_DIGIT_WIDTH + SMALL_DIGIT_SPACING + 10, - DIGITS_START_Y + SMALL_DIGITS_Y_OFFSET, 0xffff, 0x0000); + DIGITS_START_Y + SMALL_DIGITS_Y_OFFSET, 0xffff, 0x528a); lcd_draw_xsmall_digit(value % 10, DIGITS_START_X + DIGIT_WIDTH * 2 + DIGIT_SPACING * 2 + SMALL_DIGIT_WIDTH * 2 + - SMALL_DIGIT_SPACING + XSMALL_DIGIT_SPACING + 10, - DIGITS_START_Y + XSMALL_DIGITS_Y_OFFSET, 0xffff, 0x0000); + SMALL_DIGIT_SPACING * 2 + 10, + DIGITS_START_Y + XSMALL_DIGITS_Y_OFFSET, 0xffff, 0x528a); #undef DIGITS_START_X #undef DIGITS_START_Y @@ -467,9 +474,9 @@ void update_lcd() { lcd_write_string("км/ч", 241, 126, 0xffff, 0x0000); } else if (guiState.screenState.mainScreen.displayMode == DISPLAY_MODE_DISTANCE) { uint convertedDistance = totalTicks * cmPerTick / 100; - draw_distance(convertedDistance); + draw_short_term_distance(convertedDistance); lcd_write_string("Расстояние", 20, 0, 0xffff, 0x0000); - lcd_write_string("км", 280, 126, 0xffff, 0x0000); + lcd_write_string("км", 280, 37, 0xffff, 0x0000); } char timeDisplay[6];