qmk_firmware

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

djinn.c (7696B)


      1 // Copyright 2018-2023 Nick Brassel (@tzarc)
      2 // SPDX-License-Identifier: GPL-2.0-or-later
      3 #include "djinn.h"
      4 #include <string.h>
      5 #include <hal_pal.h>
      6 #include "serial.h"
      7 #include "split_util.h"
      8 
      9 painter_device_t lcd;
     10 
     11 // clang-format off
     12 #ifdef SWAP_HANDS_ENABLE
     13 const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
     14    { { 6,  6 }, { 5,  6 }, { 4,  6 }, { 3,  6 }, { 2,  6 }, { 1,  6 }, { 0,  6 } },
     15    { { 6,  7 }, { 5,  7 }, { 4,  7 }, { 3,  7 }, { 2,  7 }, { 1,  7 }, { 0,  7 } },
     16    { { 6,  8 }, { 5,  8 }, { 4,  8 }, { 3,  8 }, { 2,  8 }, { 1,  8 }, { 0,  8 } },
     17    { { 6,  9 }, { 5,  9 }, { 4,  9 }, { 3,  9 }, { 2,  9 }, { 1,  9 }, { 0,  9 } },
     18    { { 0,  0 }, { 0,  0 }, { 0,  0 }, { 6, 10 }, { 5, 10 }, { 4, 10 }, { 3, 10 } },
     19    { { 0,  0 }, { 6, 11 }, { 5, 11 }, { 4, 11 }, { 3, 11 }, { 2, 11 }, { 1, 11 } },
     20 
     21    { { 6,  0 }, { 5,  0 }, { 4,  0 }, { 3,  0 }, { 2,  0 }, { 1,  0 }, { 0,  0 } },
     22    { { 6,  1 }, { 5,  1 }, { 4,  1 }, { 3,  1 }, { 2,  1 }, { 1,  1 }, { 0,  1 } },
     23    { { 6,  2 }, { 5,  2 }, { 4,  2 }, { 3,  2 }, { 2,  2 }, { 1,  2 }, { 0,  2 } },
     24    { { 6,  3 }, { 5,  3 }, { 4,  3 }, { 3,  3 }, { 2,  3 }, { 1,  3 }, { 0,  3 } },
     25    { { 0,  0 }, { 0,  0 }, { 0,  0 }, { 6,  4 }, { 5,  4 }, { 4,  4 }, { 3,  4 } },
     26    { { 0,  0 }, { 6,  5 }, { 5,  5 }, { 4,  5 }, { 3,  5 }, { 2,  5 }, { 1,  5 } },
     27 };
     28 #    ifdef ENCODER_MAP_ENABLE
     29 const uint8_t PROGMEM encoder_hand_swap_config[NUM_ENCODERS] = { 1, 0 };
     30 #    endif // ENCODER_MAP_ENABLE
     31 #endif // SWAP_HANDS_ENABLE
     32 // clang-format on
     33 
     34 void board_init(void) {
     35     usbpd_init();
     36 }
     37 
     38 //----------------------------------------------------------
     39 // Initialisation
     40 
     41 void keyboard_post_init_kb(void) {
     42     // Register keyboard state sync split transaction
     43     transaction_register_rpc(RPC_ID_SYNC_STATE_KB, kb_state_sync_slave);
     44 
     45     // Reset the initial shared data value between master and slave
     46     memset(&kb_state, 0, sizeof(kb_state));
     47 
     48     // Turn off increased current limits
     49     gpio_set_pin_output(RGB_CURR_1500mA_OK_PIN);
     50     gpio_write_pin_low(RGB_CURR_1500mA_OK_PIN);
     51     gpio_set_pin_output(RGB_CURR_3000mA_OK_PIN);
     52     gpio_write_pin_low(RGB_CURR_3000mA_OK_PIN);
     53 
     54     // Turn on the RGB
     55     gpio_set_pin_output(RGB_POWER_ENABLE_PIN);
     56     gpio_write_pin_high(RGB_POWER_ENABLE_PIN);
     57 
     58 #ifdef EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN
     59     gpio_set_pin_output(EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN);
     60     gpio_write_pin_high(EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN);
     61 #endif // EXTERNAL_FLASH_SPI_SLAVE_SELECT_PIN
     62 
     63     // Turn on the LCD
     64     gpio_set_pin_output(LCD_POWER_ENABLE_PIN);
     65     gpio_write_pin_high(LCD_POWER_ENABLE_PIN);
     66 
     67     // Let the LCD get some power...
     68     wait_ms(150);
     69 
     70     // Initialise the LCD
     71     lcd = qp_ili9341_make_spi_device(240, 320, LCD_CS_PIN, LCD_DC_PIN, LCD_RST_PIN, 4, 0);
     72     qp_init(lcd, QP_ROTATION_0);
     73 
     74     // Turn on the LCD and clear the display
     75     qp_power(lcd, true);
     76     qp_rect(lcd, 0, 0, 239, 319, HSV_BLACK, true);
     77 
     78     // Turn on the LCD backlight
     79     backlight_enable();
     80     backlight_level(BACKLIGHT_LEVELS);
     81 
     82     // Allow for user post-init
     83     keyboard_post_init_user();
     84 }
     85 
     86 //----------------------------------------------------------
     87 // RGB brightness scaling dependent on USBPD state
     88 
     89 #if defined(RGB_MATRIX_ENABLE)
     90 rgb_t rgb_matrix_hsv_to_rgb(hsv_t hsv) {
     91     float scale;
     92 
     93 #    ifdef DJINN_SUPPORTS_3A_FUSE
     94     // The updated BOM on the Djinn has properly-spec'ed fuses -- 1500mA/3000mA hold current
     95     switch (kb_state.current_setting) {
     96         default:
     97         case USBPD_500MA:
     98             scale = 0.35f;
     99             break;
    100         case USBPD_1500MA:
    101             scale = 0.75f;
    102             break;
    103         case USBPD_3000MA:
    104             scale = 1.0f;
    105             break;
    106     }
    107 #    else
    108     // The original BOM on the Djinn had wrongly-spec'ed fuses -- 750mA/1500mA hold current
    109     switch (kb_state.current_setting) {
    110         default:
    111         case USBPD_500MA:
    112         case USBPD_1500MA:
    113             scale = 0.35f;
    114             break;
    115         case USBPD_3000MA:
    116             scale = 0.75f;
    117             break;
    118     }
    119 #    endif
    120 
    121     hsv.v = (uint8_t)(hsv.v * scale);
    122     return hsv_to_rgb(hsv);
    123 }
    124 #endif
    125 
    126 //----------------------------------------------------------
    127 // UI Placeholder, implemented in themes
    128 
    129 __attribute__((weak)) void draw_ui_user(bool force_redraw) {}
    130 
    131 //----------------------------------------------------------
    132 // Housekeeping
    133 
    134 void housekeeping_task_kb(void) {
    135     // Update kb_state so we can send to slave
    136     kb_state_update();
    137 
    138     // Data sync from master to slave
    139     kb_state_sync();
    140 
    141     // Work out if we've changed our current limit, update the limiter circuit switches
    142     static uint8_t current_setting = USBPD_500MA;
    143     if (current_setting != kb_state.current_setting) {
    144         current_setting = kb_state.current_setting;
    145 
    146 #ifdef DJINN_SUPPORTS_3A_FUSE
    147         // The updated BOM on the Djinn has properly-spec'ed fuses -- 1500mA/3000mA hold current
    148         switch (current_setting) {
    149             default:
    150             case USBPD_500MA:
    151                 gpio_write_pin_low(RGB_CURR_1500mA_OK_PIN);
    152                 gpio_write_pin_low(RGB_CURR_3000mA_OK_PIN);
    153                 break;
    154             case USBPD_1500MA:
    155                 gpio_write_pin_high(RGB_CURR_1500mA_OK_PIN);
    156                 gpio_write_pin_low(RGB_CURR_3000mA_OK_PIN);
    157                 break;
    158             case USBPD_3000MA:
    159                 gpio_write_pin_high(RGB_CURR_1500mA_OK_PIN);
    160                 gpio_write_pin_high(RGB_CURR_3000mA_OK_PIN);
    161                 break;
    162         }
    163 #else
    164         // The original BOM on the Djinn had wrongly-spec'ed fuses -- 750mA/1500mA hold current
    165         switch (current_setting) {
    166             default:
    167             case USBPD_500MA:
    168             case USBPD_1500MA:
    169                 gpio_write_pin_low(RGB_CURR_1500mA_OK_PIN);
    170                 gpio_write_pin_low(RGB_CURR_3000mA_OK_PIN);
    171                 break;
    172             case USBPD_3000MA:
    173                 gpio_write_pin_high(RGB_CURR_1500mA_OK_PIN);
    174                 gpio_write_pin_low(RGB_CURR_3000mA_OK_PIN);
    175                 break;
    176         }
    177 #endif
    178 
    179         // If we've changed the current limit, toggle rgb off and on if it was on, to force a brightness update on all LEDs
    180         if (is_keyboard_master() && rgb_matrix_is_enabled()) {
    181             rgb_matrix_disable_noeeprom();
    182             rgb_matrix_enable_noeeprom();
    183         }
    184     }
    185 
    186     // Turn on/off the LCD
    187     bool peripherals_on = last_input_activity_elapsed() < LCD_ACTIVITY_TIMEOUT;
    188 
    189     // Enable/disable RGB
    190     if (peripherals_on) {
    191         // Turn on RGB
    192         gpio_write_pin_high(RGB_POWER_ENABLE_PIN);
    193         // Modify the RGB state if different to the LCD state
    194         if (rgb_matrix_is_enabled() != peripherals_on) {
    195             // Wait for a small amount of time to allow the RGB capacitors to charge, before enabling RGB output
    196             wait_ms(10);
    197             // Enable RGB
    198             rgb_matrix_enable_noeeprom();
    199         }
    200     } else {
    201         // Turn off RGB
    202         gpio_write_pin_low(RGB_POWER_ENABLE_PIN);
    203         // Disable the PWM output for the RGB
    204         if (rgb_matrix_is_enabled() != peripherals_on) {
    205             rgb_matrix_disable_noeeprom();
    206         }
    207     }
    208 
    209     // Match the backlight to the LCD state
    210     if (is_keyboard_master() && is_backlight_enabled() != peripherals_on) {
    211         if (peripherals_on)
    212             backlight_enable();
    213         else
    214             backlight_disable();
    215     }
    216 
    217     // Draw the UI
    218     if (peripherals_on) {
    219         draw_ui_user(false);
    220     }
    221 
    222     // Go into low-scan interrupt-based mode if we haven't had any matrix activity in the last 250 milliseconds
    223     if (last_input_activity_elapsed() > 250) {
    224         matrix_wait_for_interrupt();
    225     }
    226 }