Browse Source

support arbitrary blended text colors

Thomas Buck 1 year ago
parent
commit
822302d3e8
7 changed files with 86 additions and 4 deletions
  1. 5
    0
      include/lcd.h
  2. 1
    0
      include/text.h
  3. 2
    0
      include/util.h
  4. 15
    2
      src/image.c
  5. 34
    0
      src/lcd.c
  6. 22
    2
      src/text.c
  7. 7
    0
      src/util.c

+ 5
- 0
include/lcd.h View File

26
     | (((g) >> 2) << 5)    \
26
     | (((g) >> 2) << 5)    \
27
     |  ((b) >> 3)          \
27
     |  ((b) >> 3)          \
28
 )
28
 )
29
+#define RGB_565_REV(c)            \
30
+    ((c & 0xF800) >> 8) / 255.0f, \
31
+    ((c & 0x07E0) >> 3) / 255.0f, \
32
+    ((c & 0x001F) << 3) / 255.0f
33
+uint32_t from_hsv(float h, float s, float v);
29
 
34
 
30
 void lcd_init(void);
35
 void lcd_init(void);
31
 
36
 

+ 1
- 0
include/text.h View File

39
     int width;
39
     int width;
40
     int height;
40
     int height;
41
     int margin;
41
     int margin;
42
+    int fg;
42
     int bg;
43
     int bg;
43
 
44
 
44
     struct text_font *font;
45
     struct text_font *font;

+ 2
- 0
include/util.h View File

31
 
31
 
32
 void hexdump(uint8_t *buff, size_t len);
32
 void hexdump(uint8_t *buff, size_t len);
33
 
33
 
34
+float map(float value, float leftMin, float leftMax, float rightMin, float rightMax);
35
+
34
 #endif // __UTIL_H__
36
 #endif // __UTIL_H__

+ 15
- 2
src/image.c View File

22
 #include "lcd.h"
22
 #include "lcd.h"
23
 #include "text.h"
23
 #include "text.h"
24
 #include "lipo.h"
24
 #include "lipo.h"
25
+#include "util.h"
25
 #include "image.h"
26
 #include "image.h"
26
 
27
 
27
 #pragma GCC diagnostic push
28
 #pragma GCC diagnostic push
65
         .width = 240,
66
         .width = 240,
66
         .height = 240,
67
         .height = 240,
67
         .margin = 2,
68
         .margin = 2,
69
+        .fg = RGB_565(0xFF, 0xFF, 0xFF),
68
         .bg = RGB_565(0x00, 0x00, 0x00),
70
         .bg = RGB_565(0x00, 0x00, 0x00),
69
         .font = &font_big,
71
         .font = &font_big,
70
     };
72
     };
79
         .width = 240,
81
         .width = 240,
80
         .height = 240,
82
         .height = 240,
81
         .margin = 2,
83
         .margin = 2,
84
+        .fg = RGB_565(0xFF, 0xFF, 0xFF),
82
         .bg = RGB_565(0x00, 0x00, 0x00),
85
         .bg = RGB_565(0x00, 0x00, 0x00),
83
         .font = &font_small,
86
         .font = &font_small,
84
     };
87
     };
86
 }
89
 }
87
 
90
 
88
 void draw_battery_indicator(void) {
91
 void draw_battery_indicator(void) {
89
-    float v = lipo_voltage();
92
+    static const float batt_warn_limit = 15.0f;
90
     static char s[30];
93
     static char s[30];
94
+    float v = lipo_voltage();
95
+    uint32_t c = RGB_565(0xFF, 0x00, 0x00);
91
     if (lipo_charging()) {
96
     if (lipo_charging()) {
92
         //                     "Batt:   99.9%   (4.20V)"
97
         //                     "Batt:   99.9%   (4.20V)"
93
         snprintf(s, sizeof(s), "Batt: Charging! (%.2fV)", v);
98
         snprintf(s, sizeof(s), "Batt: Charging! (%.2fV)", v);
99
+        c = RGB_565(0xFF, 0xFF, 0x00);
94
     } else {
100
     } else {
95
-        snprintf(s, sizeof(s), "Batt:   %02.1f%%   (%.2fV)", lipo_percentage(v), v);
101
+        float percentage = lipo_percentage(v);
102
+        snprintf(s, sizeof(s), "Batt:   %02.1f%%   (%.2fV)", percentage, v);
103
+
104
+        if (percentage > batt_warn_limit) {
105
+            float hue = map(percentage, batt_warn_limit, 100, 0.0, 0.333);
106
+            c = from_hsv(hue, 1.0, 1.0);
107
+        }
96
     }
108
     }
97
 
109
 
98
     static struct text_font font = {
110
     static struct text_font font = {
112
         .width = 240,
124
         .width = 240,
113
         .height = 240,
125
         .height = 240,
114
         .margin = 2,
126
         .margin = 2,
127
+        .fg = c,
115
         .bg = RGB_565(0x00, 0x00, 0x00),
128
         .bg = RGB_565(0x00, 0x00, 0x00),
116
         .font = &font,
129
         .font = &font,
117
     };
130
     };

+ 34
- 0
src/lcd.c View File

16
  * See <http://www.gnu.org/licenses/>.
16
  * See <http://www.gnu.org/licenses/>.
17
  */
17
  */
18
 
18
 
19
+#include <math.h>
20
+
19
 #include "pico/stdlib.h"
21
 #include "pico/stdlib.h"
20
 #include "hardware/spi.h"
22
 #include "hardware/spi.h"
21
 #include "hardware/pwm.h"
23
 #include "hardware/pwm.h"
273
 void lcd_write_rect(uint16_t left, uint16_t top, uint16_t right, uint16_t bottom, uint32_t color) {
275
 void lcd_write_rect(uint16_t left, uint16_t top, uint16_t right, uint16_t bottom, uint32_t color) {
274
     st7789_fill_rect(&gs_handle, left, top, right, bottom, color);
276
     st7789_fill_rect(&gs_handle, left, top, right, bottom, color);
275
 }
277
 }
278
+
279
+uint32_t from_hsv(float h, float s, float v) {
280
+    float i = floorf(h * 6.0f);
281
+    float f = h * 6.0f - i;
282
+    v *= 255.0f;
283
+    float p = v * (1.0f - s);
284
+    float q = v * (1.0f - f * s);
285
+    float t = v * (1.0f - (1.0f - f) * s);
286
+
287
+    switch (((uint32_t)i) % 6) {
288
+    case 0:
289
+        return RGB_565((uint32_t)v, (uint32_t)t, (uint32_t)p);
290
+
291
+    case 1:
292
+        return RGB_565((uint32_t)q, (uint32_t)v, (uint32_t)p);
293
+
294
+    case 2:
295
+        return RGB_565((uint32_t)p, (uint32_t)v, (uint32_t)t);
296
+
297
+    case 3:
298
+        return RGB_565((uint32_t)p, (uint32_t)q, (uint32_t)v);
299
+
300
+    case 4:
301
+        return RGB_565((uint32_t)t, (uint32_t)p, (uint32_t)v);
302
+
303
+    case 5:
304
+        return RGB_565((uint32_t)v, (uint32_t)p, (uint32_t)q);
305
+
306
+    default:
307
+        return RGB_565(0, 0, 0);
308
+    }
309
+}

+ 22
- 2
src/text.c View File

26
     uint16_t anchor;
26
     uint16_t anchor;
27
 } state_t;
27
 } state_t;
28
 
28
 
29
+static uint32_t blend(uint32_t fg_c, uint32_t bg_c, uint8_t alpha) {
30
+    float bg[4] = { RGB_565_REV(bg_c), 1.0f };
31
+    float fg[4] = { RGB_565_REV(fg_c), alpha / 255.0f };
32
+    float r[4];
33
+    r[3] = 1.0f - (1.0f - fg[3]) * (1.0f - bg[3]);
34
+    if (r[3] < 1.0e-6f) {
35
+        r[0] = 0.0f;
36
+        r[1] = 0.0f;
37
+        r[2] = 0.0f;
38
+    } else {
39
+        r[0] = fg[0] * fg[3] / r[3] + bg[0] * bg[3] * (1.0f - fg[3]) / r[3];
40
+        r[1] = fg[1] * fg[3] / r[3] + bg[1] * bg[3] * (1.0f - fg[3]) / r[3];
41
+        r[2] = fg[2] * fg[3] / r[3] + bg[2] * bg[3] * (1.0f - fg[3]) / r[3];
42
+    }
43
+
44
+    return RGB_565((uint32_t)(r[0] * 255.0f),
45
+                   (uint32_t)(r[1] * 255.0f),
46
+                   (uint32_t)(r[2] * 255.0f));
47
+}
48
+
29
 static void pixel_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha,
49
 static void pixel_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha,
30
                            void *state) {
50
                            void *state) {
31
     state_t *s = (state_t*)state;
51
     state_t *s = (state_t*)state;
34
     if (x < 0 || x + count >= s->options->width) return;
54
     if (x < 0 || x + count >= s->options->width) return;
35
 
55
 
36
     while (count--) {
56
     while (count--) {
37
-        uint32_t c = RGB_565(alpha, alpha, alpha);
38
-        lcd_write_point(240 - y - 1, x, c);
57
+        lcd_write_point(240 - y - 1, x,
58
+                        blend(s->options->fg, s->options->bg, alpha));
39
         x++;
59
         x++;
40
     }
60
     }
41
 }
61
 }

+ 7
- 0
src/util.c View File

100
         println();
100
         println();
101
     }
101
     }
102
 }
102
 }
103
+
104
+float map(float value, float leftMin, float leftMax, float rightMin, float rightMax) {
105
+    float leftSpan = leftMax - leftMin;
106
+    float rightSpan = rightMax - rightMin;
107
+    float valueScaled = (value - leftMin) / leftSpan;
108
+    return rightMin + (valueScaled * rightSpan);
109
+}

Loading…
Cancel
Save