qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

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 }