ui.c (5779B)
1 // Copyright 2018-2022 Nick Brassel (@tzarc) 2 // SPDX-License-Identifier: GPL-3.0-or-later 3 #include <stdio.h> 4 #include QMK_KEYBOARD_H 5 #include "analog.h" 6 #include "qp.h" 7 #include "qp_ssd1351.h" 8 9 #define NUM_ADC_READS 32 10 11 #include "graphics/ghoul-logo.qgf.c" 12 #include "graphics/ghoul-name.qgf.c" 13 #include "graphics/lock-caps.qgf.c" 14 #include "graphics/lock-num.qgf.c" 15 #include "graphics/lock-scrl.qgf.c" 16 #include "graphics/thintel15.qff.c" 17 18 static painter_device_t oled; 19 static painter_image_handle_t logo; 20 static painter_image_handle_t name; 21 static painter_font_handle_t font; 22 static painter_image_handle_t lock_caps; 23 static painter_image_handle_t lock_num; 24 static painter_image_handle_t lock_scrl; 25 26 void ui_init(void) { 27 oled = qp_ssd1351_make_spi_device(128, 128, OLED_CS_PIN, OLED_DC_PIN, OLED_RST_PIN, 8, 0); 28 logo = qp_load_image_mem(gfx_ghoul_logo); 29 name = qp_load_image_mem(gfx_ghoul_name); 30 font = qp_load_font_mem(font_thintel15); 31 lock_caps = qp_load_image_mem(gfx_lock_caps); 32 lock_num = qp_load_image_mem(gfx_lock_num); 33 lock_scrl = qp_load_image_mem(gfx_lock_scrl); 34 35 qp_init(oled, QP_ROTATION_90); 36 qp_rect(oled, 0, 0, 127, 127, 0, 0, 0, true); 37 qp_flush(oled); 38 } 39 40 void ui_task(void) { 41 bool hue_redraw = false; 42 static uint16_t last_hue = 0xFFFF; 43 uint8_t curr_hue = rgblight_get_hue(); 44 if (last_hue != curr_hue) { 45 last_hue = curr_hue; 46 hue_redraw = true; 47 } 48 49 if (hue_redraw) { 50 qp_drawimage_recolor(oled, 0, 64 - (name->height / 2), name, curr_hue, 255, 255, curr_hue, 255, 0); 51 qp_drawimage_recolor(oled, 127 - logo->width, 0, logo, curr_hue, 255, 255, curr_hue, 255, 0); 52 } 53 54 static led_t last_led_state = {0}; 55 if (hue_redraw || last_led_state.raw != host_keyboard_led_state().raw) { 56 last_led_state.raw = host_keyboard_led_state().raw; 57 qp_drawimage_recolor(oled, lock_caps->width * 0, 0, lock_caps, curr_hue, 255, last_led_state.caps_lock ? 255 : 32, curr_hue, 255, 0); 58 qp_drawimage_recolor(oled, lock_caps->width * 1, 0, lock_num, curr_hue, 255, last_led_state.num_lock ? 255 : 32, curr_hue, 255, 0); 59 qp_drawimage_recolor(oled, lock_caps->width * 2, 0, lock_scrl, curr_hue, 255, last_led_state.scroll_lock ? 255 : 32, curr_hue, 255, 0); 60 61 qp_rect(oled, lock_caps->width * 0 + 1, lock_caps->height + 2, lock_caps->width * 1 - 1, lock_caps->height + 3, curr_hue, 255, last_led_state.caps_lock ? 255 : 0, true); 62 qp_rect(oled, lock_caps->width * 1 + 1, lock_caps->height + 2, lock_caps->width * 2 - 1, lock_caps->height + 3, curr_hue, 255, last_led_state.num_lock ? 255 : 0, true); 63 qp_rect(oled, lock_caps->width * 2 + 1, lock_caps->height + 2, lock_caps->width * 3 - 1, lock_caps->height + 3, curr_hue, 255, last_led_state.scroll_lock ? 255 : 0, true); 64 } 65 66 #if HAL_USE_ADC 67 static int16_t current_reads[NUM_ADC_READS] = {0}; 68 static int16_t voltage_reads[NUM_ADC_READS] = {0}; 69 static int write_offset = 0; 70 71 static uint32_t last_read = 0; 72 if (timer_elapsed32(last_read) >= 1) { 73 // Perform the reads 74 int16_t current = analogReadPin(ADC_CURRENT_PIN); 75 int16_t voltage = analogReadPin(ADC_VOLTAGE_PIN); 76 int16_t current_ma = (int16_t)(((3300 * (int32_t)current) / ADC_SATURATION)); 77 int16_t voltage_mv = (int16_t)((2 * (3300 * (int32_t)voltage)) / ADC_SATURATION); 78 79 // Duplicate the first read so that averages work 80 if (last_read == 0) { 81 for (int i = 0; i < NUM_ADC_READS; ++i) { 82 current_reads[i] = current_ma; 83 voltage_reads[i] = voltage_mv; 84 } 85 } 86 87 // Dump in the current value 88 current_reads[write_offset] = current_ma; 89 voltage_reads[write_offset] = voltage_mv; 90 write_offset = (write_offset + 1) % NUM_ADC_READS; 91 92 static int counter = 0; 93 counter = (counter + 1) % 2500; 94 if (counter == 0) { 95 dprintf("Current: %dmA (%d) -- Voltage: %dmV (%d)\n", (int)current_ma, (int)current, (int)voltage_mv, (int)voltage); 96 } 97 98 last_read = timer_read32(); 99 } 100 101 static uint32_t last_draw = 0; 102 if (hue_redraw || timer_elapsed32(last_draw) >= 250) { 103 // Accumulate 104 int32_t total_current_ma = 0; 105 int32_t total_voltage_mv = 0; 106 for (int i = 0; i < NUM_ADC_READS; ++i) { 107 total_current_ma += current_reads[i]; 108 total_voltage_mv += voltage_reads[i]; 109 } 110 111 // Get the averages 112 int16_t avg_current_ma = (int16_t)(total_current_ma / NUM_ADC_READS); 113 int16_t avg_voltage_mv = (int16_t)(total_voltage_mv / NUM_ADC_READS); 114 115 char buf[32] = {0}; 116 sprintf(buf, "Current: %dmA", avg_current_ma); 117 static int16_t maxlen_curr = 0; 118 int16_t len = qp_drawtext_recolor(oled, 0, 127 - (font->line_height * 2), font, buf, 0, 0, 32, 0, 0, 0); 119 if (len < maxlen_curr) { 120 qp_rect(oled, len, 127 - (font->line_height * 2), maxlen_curr, 127 - (font->line_height * 1), 0, 0, 0, true); 121 } else if (len > maxlen_curr) { 122 maxlen_curr = len; 123 } 124 125 static int16_t maxlen_volt = 0; 126 sprintf(buf, "Voltage: %dmV", avg_voltage_mv); 127 len = qp_drawtext_recolor(oled, 0, 127 - (font->line_height * 1), font, buf, 0, 0, 32, 0, 0, 0); 128 if (len < maxlen_volt) { 129 qp_rect(oled, len, 127 - (font->line_height * 1), maxlen_volt, 127 - (font->line_height * 0), 0, 0, 0, true); 130 } else if (len > maxlen_volt) { 131 maxlen_volt = len; 132 } 133 134 qp_flush(oled); 135 136 last_draw = timer_read32(); 137 } 138 #endif // HAL_USE_ADC 139 }