diff --git a/keyboards/ducky/one2sf/1967st/1967st.c b/keyboards/ducky/one2sf/1967st/1967st.c index 14eb70c49f4..371bd99d93f 100644 --- a/keyboards/ducky/one2sf/1967st/1967st.c +++ b/keyboards/ducky/one2sf/1967st/1967st.c @@ -15,27 +15,457 @@ * along with this program. If not, see . */ -#include "config.h" -#include "quantum.h" - -led_config_t g_led_config = { { - // Key Matrix to LED Index - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, NO_LED}, - { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, NO_LED}, - { 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, NO_LED, 42, 43, NO_LED}, - { 44, NO_LED, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, NO_LED, NO_LED}, - { 57, 58, 59, 60, NO_LED, 61, NO_LED, 62, NO_LED, 63, 64, 65, 66, 67, 68, NO_LED}, -}, { - { 0, 0 }, { 16, 0 }, { 32, 0 }, { 48, 0 }, { 64, 0 }, { 80, 0 }, { 96, 0 }, { 112, 0 }, { 128, 0 }, { 144, 0 }, { 160, 0 }, { 176, 0 }, { 192, 0 }, { 208, 0 }, { 224, 0 }, - { 0, 16 }, { 16, 16 }, { 32, 16 }, { 48, 16 }, { 64, 16 }, { 80, 16 }, { 96, 16 }, { 112, 16 }, { 128, 16 }, { 144, 16 }, { 160, 16 }, { 176, 16 }, { 192, 16 }, { 208, 16 }, { 224, 16 }, - { 0, 32 }, { 16, 32 }, { 32, 32 }, { 48, 32 }, { 64, 32 }, { 80, 32 }, { 96, 32 }, { 112, 32 }, { 128, 32 }, { 144, 32 }, { 160, 32 }, { 176, 32 }, { 208, 32 }, { 224, 32 }, - { 0, 48 }, { 32, 48 }, { 48, 48 }, { 64, 48 }, { 80, 48 }, { 96, 48 }, { 112, 48 }, { 128, 48 }, { 144, 48 }, { 160, 48 }, { 176, 48 }, { 192, 48 }, { 208, 48 }, - { 0, 64 }, { 16, 64 }, { 32, 64 }, { 48, 64 }, { 80, 64 }, { 112, 64 }, { 144, 64 }, { 160, 64 }, { 176, 64 }, { 192, 64 }, { 208, 64 }, { 224, 64 } -}, { - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, - 5, 5, 5, 4, 4, 4, 5, 5, 5, 4, 4, 4 -} }; +/* + * MBIA045 LED matrix driver. + * + * Datasheet available at + * https://pc-clinic.bg/wp-content/uploads/2021/05/mbia045-datasheet-va.00-en.pdf + */ + +#ifdef RGB_MATRIX_ENABLE + +# include + +# include "config.h" +# include "hal.h" +# include "progmem.h" +# include "rgb_matrix.h" + +# define MBIA045_CFGREG_DEFAULT 0b1000010000000000u + +# define MBIA045_DCLK PD4 +# define MBIA045_LE PD3 +# define MBIA045_EN PD5 + +# define MBIA045_ROW_COUNT 5 + +typedef struct mbi_led { + uint8_t row; + uint8_t col; +} __attribute__((packed)) mbi_led; + +typedef struct mbi_color { + uint8_t r; + uint8_t g; + uint8_t b; +} __attribute__((packed)) mbi_color; + +// Map physical layout to QMK led index +const mbi_led g_mbi_leds[RGB_MATRIX_LED_COUNT] = {{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}, {0, 9}, {0, 10}, {0, 11}, {0, 12}, {0, 13}, {0, 14}, {1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}, {1, 9}, {1, 10}, {1, 11}, {1, 12}, {1, 13}, {1, 14}, {2, 0}, {2, 1}, {2, 2}, {2, 3}, {2, 4}, {2, 5}, {2, 6}, {2, 7}, {2, 8}, {2, 9}, {2, 10}, {2, 11}, {2, 13}, {2, 14}, {3, 0}, {3, 2}, {3, 3}, {3, 4}, {3, 5}, {3, 6}, {3, 7}, {3, 8}, {3, 9}, {3, 10}, {3, 11}, {3, 12}, {3, 13}, {4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 5}, {4, 7}, {4, 9}, {4, 10}, {4, 11}, {4, 12}, {4, 13}, {4, 14}}; + +// Lightness curve using the CIE 1931 lightness formula +// Generated by the python script provided in http://jared.geek.nz/2013/feb/linear-led-pwm +const uint16_t CIE1931_16_CURVE[] PROGMEM = { + 0, 7, 14, 21, 28, 36, 43, 50, 57, 64, 71, 78, 85, 93, 100, 107, 114, 121, 128, 135, 142, 149, 157, 164, 172, 180, 189, 197, 206, 215, 225, 234, 244, 254, 265, 276, 287, 298, 310, 322, 334, 346, 359, 373, 386, 400, 414, 428, 443, 458, 474, 490, 506, 522, 539, 557, 574, 592, 610, 629, 648, 668, 688, 708, 729, 750, 771, 793, 815, 838, 861, 885, 909, 933, 958, 983, 1009, 1035, 1061, 1088, 1116, 1144, 1172, 1201, 1230, 1260, 1290, 1321, 1353, 1384, 1417, 1449, 1482, 1516, 1550, 1585, 1621, 1656, 1693, 1729, 1767, 1805, 1843, 1882, 1922, 1962, 2003, 2044, 2085, 2128, 2171, 2214, 2258, 2303, 2348, 2394, 2440, 2487, 2535, 2583, 2632, 2681, 2731, 2782, 2833, 2885, 2938, 2991, + 3045, 3099, 3154, 3210, 3266, 3323, 3381, 3439, 3498, 3558, 3618, 3679, 3741, 3803, 3867, 3930, 3995, 4060, 4126, 4193, 4260, 4328, 4397, 4466, 4536, 4607, 4679, 4752, 4825, 4899, 4973, 5049, 5125, 5202, 5280, 5358, 5437, 5517, 5598, 5680, 5762, 5845, 5929, 6014, 6100, 6186, 6273, 6361, 6450, 6540, 6630, 6722, 6814, 6907, 7001, 7095, 7191, 7287, 7385, 7483, 7582, 7682, 7782, 7884, 7986, 8090, 8194, 8299, 8405, 8512, 8620, 8729, 8838, 8949, 9060, 9173, 9286, 9400, 9516, 9632, 9749, 9867, 9986, 10106, 10227, 10348, 10471, 10595, 10720, 10845, 10972, 11100, 11228, 11358, 11489, 11620, 11753, 11887, 12021, 12157, 12294, 12432, 12570, 12710, 12851, 12993, 13136, 13279, 13424, 13570, 13718, 13866, 14015, 14165, 14317, 14469, 14622, 14777, 14933, 15089, 15247, 15406, 15566, 15727, 15890, 16053, 16217, 16383, +}; + +/** The PWM buffers the full rows of 16 PWM registers in each MBI5042 driver + * The buffers are arranged in serial format + * (MSB_R, MSB_G, MSB_B...LSB_R, LSB_G, LSB_B) + * as needed by the SDO pins on the MCU (R is B14; G is B13; B is B12) + * + * g_pwm_buffer has the DCLK-able output for an "R" row, a "G" row, and a "B" row of PWM + */ +uint16_t g_pwm_buffer[MBIA045_ROW_COUNT][16 * 16]; +mbi_color g_led_buffer[RGB_MATRIX_LED_COUNT]; + +bool g_pwm_buffer_update_required = false; +uint8_t g_pwm_buffer_row = 0; + +void MBIA045_init(void); +void MBIA045_set_current_gain(uint8_t gain); +void MBIA045_write_config_register(uint16_t regValue); +void MBIA045_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); +void MBIA045_set_color_all(uint8_t red, uint8_t green, uint8_t blue); +void MBIA045_update_pwm_buffers(void); +void MBIA045_flush(void); +void MBIA045_disable_rows(void); +void MBIA045_select_row(int row); + +void MBIA045_init(void) { + /* Initialise all PWM arrays to zero. + * Perform one group transfer to turn LEDs off + * + * If there's a DMA requirement, set up DMA subsystems + */ + for (int i = 0; i < MBIA045_ROW_COUNT; i++) { + for (int j = 0; j < 256; j++) { + g_pwm_buffer[i][j] = 0; + } + } + + /* Setup PWM0 control registers for 2MHz GCLK + * and also 50 percentage PWM duty (makes a nice clock) + * + * Set PWM1 to be used as a 2kHz timer (interrupt but no output pin) + * which is used for row refresh/enable. + */ + + // Use the HCLK + // Note we need to 0 the bits first as the clksel register has a reset value + // of 0xFFFF_FFFF + CLK->CLKSEL1 &= ~CLK_CLKSEL1_PWM01_S_Msk; + CLK->CLKSEL1 |= 2 << CLK_CLKSEL1_PWM01_S_Pos; + + CLK->CLKSEL2 &= ~CLK_CLKSEL2_PWM01_S_E_Msk; + CLK->CLKSEL2 |= 2 << CLK_CLKSEL2_PWM01_S_E_Pos; + + // Enable the PWM peripheral clock + CLK->APBCLK |= 1 << CLK_APBCLK_PWM01_EN_Pos; + + // Set prescaler for PWM0 and PWM1 to 1 + PWMA->PPR |= 1 << PWM_PPR_CP01_Pos; + + // Enable PWM interrupt vector + // Interrupt priority value taken from chibios defaults + nvicEnableVector(NUC123_PWMA_NUMBER, 3); + + // Set clock division to 1 + PWMA->CSR |= 1 << PWM_CSR_CSR2_Pos; + + // Set pin PA12 to PWM0 + SYS->GPA_MFP |= 1 << 12; + + // Enable PWM0 output + PWMA->POE |= 1 << PWM_POE_PWM0_Pos; + + // Enable PWM0 and PWM1 auto reload + PWMA->PCR |= (1 << PWM_PCR_CH0MOD_Pos | 1 << PWM_PCR_CH1MOD_Pos); + + // Enable PWM1 reset interrupt + PWMA->PIER |= 1 << PWM_PIER_PWMIE1_Pos; + + // Set PWM0 freq to 9MHz and 50% duty cycle (it's just a nice clock) + // + // freq = HCLK/[(prescale+1)*(clock divider)*(CNR+1)] + // 72MHz/(1 + 1)*(1)*(3+1) + // + // duty = (CMR+1)/(CNR+1) + // (1+1)/(3+1) + PWMA->CNR0 = 3; + PWMA->CMR0 = 1; + + // Set PWM1 freq to 1.8kHz (duty doesn't matter) + // + // freq = HCLK/[(prescale+1)*(clock divider)*(CNR+1)] + // 72MHz/(1 + 1)*(1)*(3+1) + PWMA->CNR1 = 19999; + PWMA->CMR1 = 1; + + // Start PWM channel 0 and 1 + PWMA->PCR |= (1 << PWM_PCR_CH0EN_Pos | 1 << PWM_PCR_CH1EN_Pos); + + MBIA045_disable_rows(); + + // Enable the LED controllers + MBIA045_EN = PAL_LOW; + + MBIA045_set_current_gain(0b000011u); +} + +/** + * @brief Set LED driver current gain + * @detail The MBI5042 has a 6-bit current gain value (000000b ~ 111111b) + * used to adjust the global brightness of the LEDs attached to the PWM outputs + * + * Default value is 101011b + * + * Use MBI5042_CURRENT_GAIN to pass from keyboard config + */ +void MBIA045_set_current_gain(uint8_t gain) { + /** MB data transfer requires: + * Tell chip config register change is coming (Enable Write Configutarion) + * Pass config register data (Write Configuration Register) + */ + uint16_t regConfig = 0b00111111u & gain; + + regConfig <<= 4; + regConfig |= MBIA045_CFGREG_DEFAULT; + + MBIA045_write_config_register(regConfig); +} + +/** + * @brief Write configuration register ONLY DURING INIT + * @detail Set the contents of the configuration register (see top for bitfields) + * Each register write needs 2 * 16 bit transfers (1 x setup and 1 x data) + * + * For the Ducky One 2 mini there are 3 drivers, so output all three configs at once + */ +void MBIA045_write_config_register(uint16_t regValue) { + uint32_t b_mask; + uint16_t tmp_r, tmp_g, tmp_b; + + /* Set Mask for GPIOB */ + b_mask = PB->DMASK; + PB->DMASK = ~(0x1u << 14 | 0x1u << 13 | 0x1u << 12); + + /* LE Low & DCLK Low */ + MBIA045_LE = PAL_LOW; + MBIA045_DCLK = PAL_LOW; + + /* Do one DCLK cycle */ + MBIA045_DCLK = PAL_HIGH; + MBIA045_DCLK = PAL_LOW; + + /* Set LE High */ + MBIA045_LE = PAL_HIGH; + + /* Loop 15 - Enable Write Configuration */ + for (int i = 0; i < 15; i++) { + /* Cycle DCLK */ + MBIA045_DCLK = PAL_HIGH; + MBIA045_DCLK = PAL_LOW; + } + + /* Reset LE Low */ + MBIA045_LE = PAL_LOW; + + /* Loop 16 - Transfer actual command data to all 3 LED drivers */ + for (int i = 0; i < 16; i++) { + tmp_r = tmp_g = tmp_b = regValue; + /* Set data bit */ + uint16_t bits = ((0x1u & (tmp_r >> 15)) << 14) | ((0x1u & (tmp_g >> 15)) << 13) | ((0x1u & (tmp_b >> 15)) << 12); + PB->DOUT = bits; + + /* Cycle DCLK */ + MBIA045_DCLK = PAL_HIGH; + MBIA045_DCLK = PAL_LOW; + + if (i == 5) { + MBIA045_LE = PAL_HIGH; + } + + /* Next bit to sample */ + regValue <<= 1; + } + + /* Put GPIOB DMASK back */ + PB->DMASK = b_mask; + + /* Reset LE Low */ + MBIA045_LE = PAL_LOW; +} + +void MBIA045_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { + /* + * @brief Pick a colour! Any colour! + */ + g_led_buffer[index] = (mbi_color){red, green, blue}; +} + +void MBIA045_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { + /* + * brief Set every led to the provided colour + */ + for (size_t i = 0; i < RGB_MATRIX_LED_COUNT; i++) { + g_led_buffer[i] = (mbi_color){red, green, blue}; + } +} + +void MBIA045_update_pwm_buffers(void) { + /** + * Pass current PWM row to MBIA045 shift registers + * + * LE low + * Outer Loop 16 (one per register transfer - high to low): + * Inner Loop 16 (one per PWM bit): + * R_SDIN, G_SDIN & B_SDIN write + * DCLK High + * DCLK Low + * For final loop, set LE High + * + * Send Global Latch (16 DCLKs with LE high for last 3) + * + * Disable current row + * + * Reset PWM count: + * Loop 3: + * DCLK High + * DCLK Low + * LE High + * Loop 13: + * DCLK High + * DCLK Low + * LE Low + * + * Select new row (row meant for above data) + */ + + if (!g_pwm_buffer_update_required) return; + + uint32_t b_mask; + + /* Set Mask for GPIOB */ + b_mask = PB->DMASK; + PB->DMASK = ~(0x1u << 14 | 0x1u << 13 | 0x1u << 12); + + // LE Low & DCLK Low + MBIA045_LE = PAL_LOW; + MBIA045_DCLK = PAL_LOW; + + for (int i = 0; i < 16; i++) { + /* Inner Loop 16 */ + for (int j = 0; j < 16; j++) { + /* R_SDIN/G_SDIN/B_SDIN write */ + PB->DOUT = g_pwm_buffer[g_pwm_buffer_row][16 * i + j]; + + // If j is 15 set LE High + if (j == 15) { + MBIA045_LE = PAL_HIGH; + } + + /* Cycle DCLK */ + MBIA045_DCLK = PAL_HIGH; + MBIA045_DCLK = PAL_LOW; + } // Inner Loop 16 + + // LE Low + MBIA045_LE = PAL_LOW; + } + + /* Send Global Latch */ + for (int i = 0; i < 16; i++) { + /* Cycle DCLK */ + MBIA045_DCLK = PAL_HIGH; + MBIA045_DCLK = PAL_LOW; + + // if i is 13 set LE high + if (i == 13) { + MBIA045_LE = PAL_HIGH; + } + } + + // Reset LE Low + MBIA045_LE = PAL_LOW; + + // Reset Masks + PB->DMASK = b_mask; + + // Reset PWM count + // 3 DCLK cycles + for (int i = 0; i < 3; i++) { + MBIA045_DCLK = PAL_HIGH; + MBIA045_DCLK = PAL_LOW; + } + + // Set LE High + MBIA045_LE = PAL_HIGH; + + // Loop 13 to generate PWM count reset + for (int i = 0; i < 13; i++) { + MBIA045_DCLK = PAL_HIGH; + MBIA045_DCLK = PAL_LOW; + } + + // Set LE Low + MBIA045_LE = PAL_LOW; + + // Set new row + MBIA045_select_row(g_pwm_buffer_row); + + // increment row count + check + g_pwm_buffer_row++; + if (g_pwm_buffer_row >= MBIA045_ROW_COUNT) { + g_pwm_buffer_row = 0; + } +} + +/** + * @brief Send the color buffer to the PWM buffer + */ +void MBIA045_flush(void) { + mbi_led led_pos; + mbi_color color; + + for (size_t i = 0; i < RGB_MATRIX_LED_COUNT; i++) { + led_pos = g_mbi_leds[i]; + color = g_led_buffer[i]; + + // Convert color values from 8 to 16 bit + uint16_t cur_r = pgm_read_word(&CIE1931_16_CURVE[color.r]); + uint16_t cur_g = pgm_read_word(&CIE1931_16_CURVE[color.g]); + uint16_t cur_b = pgm_read_word(&CIE1931_16_CURVE[color.b]); + + // Construct the pwm buffer + for (int i = 0; i < 16; i++) { + uint16_t tmp_r = cur_r; + uint16_t tmp_g = cur_g; + uint16_t tmp_b = cur_b; + + g_pwm_buffer[led_pos.row][i + (led_pos.col * 16)] = ((0x1u & (tmp_r >> 15)) << 14) | ((0x1u & (tmp_g >> 15)) << 13) | ((0x1u & (tmp_b >> 15)) << 12); + cur_r <<= 1; + cur_g <<= 1; + cur_b <<= 1; + } + } + + g_pwm_buffer_update_required = true; +} + +/** + * @brief Disable all LED Rows + */ +void MBIA045_disable_rows(void) { + // Row 0 + PC4 = PAL_LOW; + + // Row 1 + PC5 = PAL_LOW; + + // Row 2 + PB3 = PAL_LOW; + + // Row 3 + PB2 = PAL_LOW; + + // Row 4 + PD9 = PAL_LOW; +} + +/** + * @brief Enable the specific LED row, disabling all others + */ +void MBIA045_select_row(int row) { + MBIA045_disable_rows(); + switch (row) { + case 0: // Row 0 + PC4 = PAL_HIGH; + break; + case 1: // Row 1 + PC5 = PAL_HIGH; + break; + case 2: // Row 2 + PB3 = PAL_HIGH; + break; + case 3: // Row 3 + PB2 = PAL_HIGH; + break; + case 4: // Row 4 + PD9 = PAL_HIGH; + break; + } +} + +OSAL_IRQ_HANDLER(NUC123_PWMA_HANDLER) { + OSAL_IRQ_PROLOGUE(); + + /* Check for PWM1 underflow IRQ */ + if ((PWMA->PIIR >> PWM_PIIR_PWMIF1_Pos) & 1) { + /* Clear interrupt flag */ + PWMA->PIIR |= 1 << PWM_PIIR_PWMIF1_Pos; + MBIA045_update_pwm_buffers(); + } + + OSAL_IRQ_EPILOGUE(); +} + +const rgb_matrix_driver_t rgb_matrix_driver = { + .init = MBIA045_init, + .flush = MBIA045_flush, + .set_color = MBIA045_set_color, + .set_color_all = MBIA045_set_color_all, +}; +#endif diff --git a/keyboards/ducky/one2sf/1967st/config.h b/keyboards/ducky/one2sf/1967st/config.h index 66403f4a0a5..a2959c9d730 100644 --- a/keyboards/ducky/one2sf/1967st/config.h +++ b/keyboards/ducky/one2sf/1967st/config.h @@ -21,8 +21,6 @@ along with this program. If not, see . <<<<<<< HEAD ======= -#define RGB_MATRIX_LED_COUNT 69 - #define ENABLE_RGB_MATRIX_BREATHING #define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT #define ENABLE_RGB_MATRIX_TYPING_HEATMAP diff --git a/keyboards/ducky/one2sf/1967st/info.json b/keyboards/ducky/one2sf/1967st/info.json index 54564f248de..3624ba236c5 100644 --- a/keyboards/ducky/one2sf/1967st/info.json +++ b/keyboards/ducky/one2sf/1967st/info.json @@ -8,12 +8,83 @@ "device_version": "0.0.1", "force_nkro": true }, -<<<<<<< HEAD -======= + "features": { + "rgb_matrix": true + }, "rgb_matrix": { - "driver": "custom" + "driver": "custom", + "layout": [ + {"matrix": [0, 0], "x": 0, "y": 0, "flags": 4}, + {"matrix": [0, 1], "x": 16, "y": 0, "flags": 4}, + {"matrix": [0, 2], "x": 32, "y": 0, "flags": 4}, + {"matrix": [0, 3], "x": 48, "y": 0, "flags": 4}, + {"matrix": [0, 4], "x": 64, "y": 0, "flags": 4}, + {"matrix": [0, 5], "x": 80, "y": 0, "flags": 4}, + {"matrix": [0, 6], "x": 96, "y": 0, "flags": 4}, + {"matrix": [0, 7], "x": 112, "y": 0, "flags": 4}, + {"matrix": [0, 8], "x": 128, "y": 0, "flags": 4}, + {"matrix": [0, 9], "x": 144, "y": 0, "flags": 4}, + {"matrix": [0, 10], "x": 160, "y": 0, "flags": 4}, + {"matrix": [0, 11], "x": 176, "y": 0, "flags": 4}, + {"matrix": [0, 12], "x": 192, "y": 0, "flags": 4}, + {"matrix": [0, 13], "x": 208, "y": 0, "flags": 4}, + {"matrix": [0, 14], "x": 224, "y": 0, "flags": 4}, + {"matrix": [1, 0], "x": 0, "y": 16, "flags": 4}, + {"matrix": [1, 1], "x": 16, "y": 16, "flags": 4}, + {"matrix": [1, 2], "x": 32, "y": 16, "flags": 4}, + {"matrix": [1, 3], "x": 48, "y": 16, "flags": 4}, + {"matrix": [1, 4], "x": 64, "y": 16, "flags": 4}, + {"matrix": [1, 5], "x": 80, "y": 16, "flags": 4}, + {"matrix": [1, 6], "x": 96, "y": 16, "flags": 4}, + {"matrix": [1, 7], "x": 112, "y": 16, "flags": 4}, + {"matrix": [1, 8], "x": 128, "y": 16, "flags": 4}, + {"matrix": [1, 9], "x": 144, "y": 16, "flags": 4}, + {"matrix": [1, 10], "x": 160, "y": 16, "flags": 4}, + {"matrix": [1, 11], "x": 176, "y": 16, "flags": 4}, + {"matrix": [1, 12], "x": 192, "y": 16, "flags": 4}, + {"matrix": [1, 13], "x": 208, "y": 16, "flags": 4}, + {"matrix": [1, 14], "x": 224, "y": 16, "flags": 4}, + {"matrix": [2, 0], "x": 0, "y": 32, "flags": 5}, + {"matrix": [2, 1], "x": 16, "y": 32, "flags": 4}, + {"matrix": [2, 2], "x": 32, "y": 32, "flags": 4}, + {"matrix": [2, 3], "x": 48, "y": 32, "flags": 4}, + {"matrix": [2, 4], "x": 64, "y": 32, "flags": 4}, + {"matrix": [2, 5], "x": 80, "y": 32, "flags": 4}, + {"matrix": [2, 6], "x": 96, "y": 32, "flags": 4}, + {"matrix": [2, 7], "x": 112, "y": 32, "flags": 4}, + {"matrix": [2, 8], "x": 128, "y": 32, "flags": 4}, + {"matrix": [2, 9], "x": 144, "y": 32, "flags": 4}, + {"matrix": [2, 10], "x": 160, "y": 32, "flags": 4}, + {"matrix": [2, 11], "x": 176, "y": 32, "flags": 4}, + {"matrix": [2, 13], "x": 208, "y": 32, "flags": 4}, + {"matrix": [2, 14], "x": 224, "y": 32, "flags": 4}, + {"matrix": [3, 0], "x": 0, "y": 48, "flags": 5}, + {"matrix": [3, 2], "x": 32, "y": 48, "flags": 4}, + {"matrix": [3, 3], "x": 48, "y": 48, "flags": 4}, + {"matrix": [3, 4], "x": 64, "y": 48, "flags": 4}, + {"matrix": [3, 5], "x": 80, "y": 48, "flags": 4}, + {"matrix": [3, 6], "x": 96, "y": 48, "flags": 4}, + {"matrix": [3, 7], "x": 112, "y": 48, "flags": 4}, + {"matrix": [3, 8], "x": 128, "y": 48, "flags": 4}, + {"matrix": [3, 9], "x": 144, "y": 48, "flags": 4}, + {"matrix": [3, 10], "x": 160, "y": 48, "flags": 4}, + {"matrix": [3, 11], "x": 176, "y": 48, "flags": 4}, + {"matrix": [3, 12], "x": 192, "y": 48, "flags": 5}, + {"matrix": [3, 13], "x": 208, "y": 48, "flags": 4}, + {"matrix": [4, 0], "x": 0, "y": 64, "flags": 5}, + {"matrix": [4, 1], "x": 16, "y": 64, "flags": 5}, + {"matrix": [4, 2], "x": 32, "y": 64, "flags": 5}, + {"matrix": [4, 3], "x": 48, "y": 64, "flags": 4}, + {"matrix": [4, 5], "x": 80, "y": 64, "flags": 4}, + {"matrix": [4, 7], "x": 112, "y": 64, "flags": 4}, + {"matrix": [4, 9], "x": 144, "y": 64, "flags": 5}, + {"matrix": [4, 10], "x": 160, "y": 64, "flags": 5}, + {"matrix": [4, 11], "x": 176, "y": 64, "flags": 5}, + {"matrix": [4, 12], "x": 192, "y": 64, "flags": 4}, + {"matrix": [4, 13], "x": 208, "y": 64, "flags": 4}, + {"matrix": [4, 14], "x": 224, "y": 64, "flags": 4} + ] }, ->>>>>>> 41dc4aefcf (Move led driver into the keyboard) "matrix_pins": { "cols": ["B10", "B9", "C13", "C12", "C11", "C10", "C9", "C8", "A15", "A14", "A13", "D0", "D1", "D2", "B15", "B8"], "rows": ["D11", "B4", "B5", "B6", "B7"] diff --git a/keyboards/ducky/one2sf/1967st/rgb_matrix_drivers.c b/keyboards/ducky/one2sf/1967st/rgb_matrix_drivers.c deleted file mode 100644 index 980687b88b7..00000000000 --- a/keyboards/ducky/one2sf/1967st/rgb_matrix_drivers.c +++ /dev/null @@ -1,469 +0,0 @@ -/* Copyright 2019 /u/KeepItUnder - * Copyright 2023 Hayley Hughes - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * MBIA045 datasheet available at - * https://pc-clinic.bg/wp-content/uploads/2021/05/mbia045-datasheet-va.00-en.pdf - */ - -#ifdef RGB_MATRIX_ENABLE - -# include - -# include "config.h" -# include "hal.h" -# include "progmem.h" -# include "rgb_matrix.h" - -# define MBIA045_CFGREG_DEFAULT 0b1000010000000000u - -# define MBIA045_DCLK PD4 -# define MBIA045_LE PD3 -# define MBIA045_EN PD5 - -# define MBIA045_ROW_COUNT 5 - -typedef struct mbi_led { - uint8_t row; - uint8_t col; -} __attribute__((packed)) mbi_led; - -typedef struct mbi_color { - uint8_t r; - uint8_t g; - uint8_t b; -} __attribute__((packed)) mbi_color; - -// Map physical layout to QMK led index -const mbi_led g_mbi_leds[RGB_MATRIX_LED_COUNT] = {{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8}, {0, 9}, {0, 10}, {0, 11}, {0, 12}, {0, 13}, {0, 14}, {1, 0}, {1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}, {1, 9}, {1, 10}, {1, 11}, {1, 12}, {1, 13}, {1, 14}, {2, 0}, {2, 1}, {2, 2}, {2, 3}, {2, 4}, {2, 5}, {2, 6}, {2, 7}, {2, 8}, {2, 9}, {2, 10}, {2, 11}, {2, 13}, {2, 14}, {3, 0}, {3, 2}, {3, 3}, {3, 4}, {3, 5}, {3, 6}, {3, 7}, {3, 8}, {3, 9}, {3, 10}, {3, 11}, {3, 12}, {3, 13}, {4, 0}, {4, 1}, {4, 2}, {4, 3}, {4, 5}, {4, 7}, {4, 9}, {4, 10}, {4, 11}, {4, 12}, {4, 13}, {4, 14}}; - -// Lightness curve using the CIE 1931 lightness formula -// Generated by the python script provided in http://jared.geek.nz/2013/feb/linear-led-pwm -const uint16_t CIE1931_16_CURVE[] PROGMEM = { - 0, 7, 14, 21, 28, 36, 43, 50, 57, 64, 71, 78, 85, 93, 100, 107, 114, 121, 128, 135, 142, 149, 157, 164, 172, 180, 189, 197, 206, 215, 225, 234, 244, 254, 265, 276, 287, 298, 310, 322, 334, 346, 359, 373, 386, 400, 414, 428, 443, 458, 474, 490, 506, 522, 539, 557, 574, 592, 610, 629, 648, 668, 688, 708, 729, 750, 771, 793, 815, 838, 861, 885, 909, 933, 958, 983, 1009, 1035, 1061, 1088, 1116, 1144, 1172, 1201, 1230, 1260, 1290, 1321, 1353, 1384, 1417, 1449, 1482, 1516, 1550, 1585, 1621, 1656, 1693, 1729, 1767, 1805, 1843, 1882, 1922, 1962, 2003, 2044, 2085, 2128, 2171, 2214, 2258, 2303, 2348, 2394, 2440, 2487, 2535, 2583, 2632, 2681, 2731, 2782, 2833, 2885, 2938, 2991, - 3045, 3099, 3154, 3210, 3266, 3323, 3381, 3439, 3498, 3558, 3618, 3679, 3741, 3803, 3867, 3930, 3995, 4060, 4126, 4193, 4260, 4328, 4397, 4466, 4536, 4607, 4679, 4752, 4825, 4899, 4973, 5049, 5125, 5202, 5280, 5358, 5437, 5517, 5598, 5680, 5762, 5845, 5929, 6014, 6100, 6186, 6273, 6361, 6450, 6540, 6630, 6722, 6814, 6907, 7001, 7095, 7191, 7287, 7385, 7483, 7582, 7682, 7782, 7884, 7986, 8090, 8194, 8299, 8405, 8512, 8620, 8729, 8838, 8949, 9060, 9173, 9286, 9400, 9516, 9632, 9749, 9867, 9986, 10106, 10227, 10348, 10471, 10595, 10720, 10845, 10972, 11100, 11228, 11358, 11489, 11620, 11753, 11887, 12021, 12157, 12294, 12432, 12570, 12710, 12851, 12993, 13136, 13279, 13424, 13570, 13718, 13866, 14015, 14165, 14317, 14469, 14622, 14777, 14933, 15089, 15247, 15406, 15566, 15727, 15890, 16053, 16217, 16383, -}; - -/** The PWM buffers the full rows of 16 PWM registers in each MBI5042 driver - * The buffers are arranged in serial format - * (MSB_R, MSB_G, MSB_B...LSB_R, LSB_G, LSB_B) - * as needed by the SDO pins on the MCU (R is B14; G is B13; B is B12) - * - * g_pwm_buffer has the DCLK-able output for an "R" row, a "G" row, and a "B" row of PWM - */ -uint16_t g_pwm_buffer[MBIA045_ROW_COUNT][16 * 16]; -mbi_color g_led_buffer[RGB_MATRIX_LED_COUNT]; - -bool g_pwm_buffer_update_required = false; -uint8_t g_pwm_buffer_row = 0; - -void MBIA045_init(void); -void MBIA045_set_current_gain(uint8_t gain); -void MBIA045_write_config_register(uint16_t regValue); -void MBIA045_set_color(int index, uint8_t red, uint8_t green, uint8_t blue); -void MBIA045_set_color_all(uint8_t red, uint8_t green, uint8_t blue); -void MBIA045_update_pwm_buffers(void); -void MBIA045_flush(void); -void MBIA045_disable_rows(void); -void MBIA045_select_row(int row); - -void MBIA045_init(void) { - /* Initialise all PWM arrays to zero. - * Perform one group transfer to turn LEDs off - * - * If there's a DMA requirement, set up DMA subsystems - */ - for (int i = 0; i < MBIA045_ROW_COUNT; i++) { - for (int j = 0; j < 256; j++) { - g_pwm_buffer[i][j] = 0; - } - } - - /* Setup PWM0 control registers for 2MHz GCLK - * and also 50 percentage PWM duty (makes a nice clock) - * - * Set PWM1 to be used as a 2kHz timer (interrupt but no output pin) - * which is used for row refresh/enable. - */ - - // Use the HCLK - // Note we need to 0 the bits first as the clksel register has a reset value - // of 0xFFFF_FFFF - CLK->CLKSEL1 &= ~CLK_CLKSEL1_PWM01_S_Msk; - CLK->CLKSEL1 |= 2 << CLK_CLKSEL1_PWM01_S_Pos; - - CLK->CLKSEL2 &= ~CLK_CLKSEL2_PWM01_S_E_Msk; - CLK->CLKSEL2 |= 2 << CLK_CLKSEL2_PWM01_S_E_Pos; - - // Enable the PWM peripheral clock - CLK->APBCLK |= 1 << CLK_APBCLK_PWM01_EN_Pos; - - // Set prescaler for PWM0 and PWM1 to 1 - PWMA->PPR |= 1 << PWM_PPR_CP01_Pos; - - // Enable PWM interrupt vector - // Interrupt priority value taken from chibios defaults - nvicEnableVector(NUC123_PWMA_NUMBER, 3); - - // Set clock division to 1 - PWMA->CSR |= 1 << PWM_CSR_CSR2_Pos; - - // Set pin PA12 to PWM0 - SYS->GPA_MFP |= 1 << 12; - - // Enable PWM0 output - PWMA->POE |= 1 << PWM_POE_PWM0_Pos; - - // Enable PWM0 and PWM1 auto reload - PWMA->PCR |= (1 << PWM_PCR_CH0MOD_Pos | 1 << PWM_PCR_CH1MOD_Pos); - - // Enable PWM1 reset interrupt - PWMA->PIER |= 1 << PWM_PIER_PWMIE1_Pos; - - // Set PWM0 freq to 9MHz and 50% duty cycle (it's just a nice clock) - // - // freq = HCLK/[(prescale+1)*(clock divider)*(CNR+1)] - // 72MHz/(1 + 1)*(1)*(3+1) - // - // duty = (CMR+1)/(CNR+1) - // (1+1)/(3+1) - PWMA->CNR0 = 3; - PWMA->CMR0 = 1; - - // Set PWM1 freq to 1.8kHz (duty doesn't matter) - // - // freq = HCLK/[(prescale+1)*(clock divider)*(CNR+1)] - // 72MHz/(1 + 1)*(1)*(3+1) - PWMA->CNR1 = 19999; - PWMA->CMR1 = 1; - - // Start PWM channel 0 and 1 - PWMA->PCR |= (1 << PWM_PCR_CH0EN_Pos | 1 << PWM_PCR_CH1EN_Pos); - - MBIA045_disable_rows(); - - // Enable the LED controllers - MBIA045_EN = PAL_LOW; - - MBIA045_set_current_gain(0b000011u); -} - -/** - * @brief Set LED driver current gain - * @detail The MBI5042 has a 6-bit current gain value (000000b ~ 111111b) - * used to adjust the global brightness of the LEDs attached to the PWM outputs - * - * Default value is 101011b - * - * Use MBI5042_CURRENT_GAIN to pass from keyboard config - */ -void MBIA045_set_current_gain(uint8_t gain) { - /** MB data transfer requires: - * Tell chip config register change is coming (Enable Write Configutarion) - * Pass config register data (Write Configuration Register) - */ - uint16_t regConfig = 0b00111111u & gain; - - regConfig <<= 4; - regConfig |= MBIA045_CFGREG_DEFAULT; - - MBIA045_write_config_register(regConfig); -} - -/** - * @brief Write configuration register ONLY DURING INIT - * @detail Set the contents of the configuration register (see top for bitfields) - * Each register write needs 2 * 16 bit transfers (1 x setup and 1 x data) - * - * For the Ducky One 2 mini there are 3 drivers, so output all three configs at once - */ -void MBIA045_write_config_register(uint16_t regValue) { - uint32_t b_mask; - uint16_t tmp_r, tmp_g, tmp_b; - - /* Set Mask for GPIOB */ - b_mask = PB->DMASK; - PB->DMASK = ~(0x1u << 14 | 0x1u << 13 | 0x1u << 12); - - /* LE Low & DCLK Low */ - MBIA045_LE = PAL_LOW; - MBIA045_DCLK = PAL_LOW; - - /* Do one DCLK cycle */ - MBIA045_DCLK = PAL_HIGH; - MBIA045_DCLK = PAL_LOW; - - /* Set LE High */ - MBIA045_LE = PAL_HIGH; - - /* Loop 15 - Enable Write Configuration */ - for (int i = 0; i < 15; i++) { - /* Cycle DCLK */ - MBIA045_DCLK = PAL_HIGH; - MBIA045_DCLK = PAL_LOW; - } - - /* Reset LE Low */ - MBIA045_LE = PAL_LOW; - - /* Loop 16 - Transfer actual command data to all 3 LED drivers */ - for (int i = 0; i < 16; i++) { - tmp_r = tmp_g = tmp_b = regValue; - /* Set data bit */ - uint16_t bits = ((0x1u & (tmp_r >> 15)) << 14) | ((0x1u & (tmp_g >> 15)) << 13) | ((0x1u & (tmp_b >> 15)) << 12); - PB->DOUT = bits; - - /* Cycle DCLK */ - MBIA045_DCLK = PAL_HIGH; - MBIA045_DCLK = PAL_LOW; - - if (i == 5) { - MBIA045_LE = PAL_HIGH; - } - - /* Next bit to sample */ - regValue <<= 1; - } - - /* Put GPIOB DMASK back */ - PB->DMASK = b_mask; - - /* Reset LE Low */ - MBIA045_LE = PAL_LOW; -} - -void MBIA045_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) { - /* - * @brief Pick a colour! Any colour! - */ - g_led_buffer[index] = (mbi_color){red, green, blue}; -} - -void MBIA045_set_color_all(uint8_t red, uint8_t green, uint8_t blue) { - /* - * brief Set every led to the provided colour - */ - for (size_t i = 0; i < RGB_MATRIX_LED_COUNT; i++) { - g_led_buffer[i] = (mbi_color){red, green, blue}; - } -} - -void MBIA045_update_pwm_buffers(void) { - /** - * Pass current PWM row to MBIA045 shift registers - * - * LE low - * Outer Loop 16 (one per register transfer - high to low): - * Inner Loop 16 (one per PWM bit): - * R_SDIN, G_SDIN & B_SDIN write - * DCLK High - * DCLK Low - * For final loop, set LE High - * - * Send Global Latch (16 DCLKs with LE high for last 3) - * - * Disable current row - * - * Reset PWM count: - * Loop 3: - * DCLK High - * DCLK Low - * LE High - * Loop 13: - * DCLK High - * DCLK Low - * LE Low - * - * Select new row (row meant for above data) - */ - - if (!g_pwm_buffer_update_required) return; - - uint32_t b_mask; - - /* Set Mask for GPIOB */ - b_mask = PB->DMASK; - PB->DMASK = ~(0x1u << 14 | 0x1u << 13 | 0x1u << 12); - - // LE Low & DCLK Low - MBIA045_LE = PAL_LOW; - MBIA045_DCLK = PAL_LOW; - - for (int i = 0; i < 16; i++) { - /* Inner Loop 16 */ - for (int j = 0; j < 16; j++) { - /* R_SDIN/G_SDIN/B_SDIN write */ - PB->DOUT = g_pwm_buffer[g_pwm_buffer_row][16 * i + j]; - - // If j is 15 set LE High - if (j == 15) { - MBIA045_LE = PAL_HIGH; - } - - /* Cycle DCLK */ - MBIA045_DCLK = PAL_HIGH; - MBIA045_DCLK = PAL_LOW; - } // Inner Loop 16 - - // LE Low - MBIA045_LE = PAL_LOW; - } - - /* Send Global Latch */ - for (int i = 0; i < 16; i++) { - /* Cycle DCLK */ - MBIA045_DCLK = PAL_HIGH; - MBIA045_DCLK = PAL_LOW; - - // if i is 13 set LE high - if (i == 13) { - MBIA045_LE = PAL_HIGH; - } - } - - // Reset LE Low - MBIA045_LE = PAL_LOW; - - // Reset Masks - PB->DMASK = b_mask; - - // Reset PWM count - // 3 DCLK cycles - for (int i = 0; i < 3; i++) { - MBIA045_DCLK = PAL_HIGH; - MBIA045_DCLK = PAL_LOW; - } - - // Set LE High - MBIA045_LE = PAL_HIGH; - - // Loop 13 to generate PWM count reset - for (int i = 0; i < 13; i++) { - MBIA045_DCLK = PAL_HIGH; - MBIA045_DCLK = PAL_LOW; - } - - // Set LE Low - MBIA045_LE = PAL_LOW; - - // Set new row - MBIA045_select_row(g_pwm_buffer_row); - - // increment row count + check - g_pwm_buffer_row++; - if (g_pwm_buffer_row >= MBIA045_ROW_COUNT) { - g_pwm_buffer_row = 0; - } -} - -/** - * @brief Send the color buffer to the PWM buffer - */ -void MBIA045_flush(void) { - mbi_led led_pos; - mbi_color color; - - for (size_t i = 0; i < RGB_MATRIX_LED_COUNT; i++) { - led_pos = g_mbi_leds[i]; - color = g_led_buffer[i]; - - // Convert color values from 8 to 16 bit - uint16_t cur_r = pgm_read_word(&CIE1931_16_CURVE[color.r]); - uint16_t cur_g = pgm_read_word(&CIE1931_16_CURVE[color.g]); - uint16_t cur_b = pgm_read_word(&CIE1931_16_CURVE[color.b]); - - // Construct the pwm buffer - for (int i = 0; i < 16; i++) { - uint16_t tmp_r = cur_r; - uint16_t tmp_g = cur_g; - uint16_t tmp_b = cur_b; - - g_pwm_buffer[led_pos.row][i + (led_pos.col * 16)] = ((0x1u & (tmp_r >> 15)) << 14) | ((0x1u & (tmp_g >> 15)) << 13) | ((0x1u & (tmp_b >> 15)) << 12); - cur_r <<= 1; - cur_g <<= 1; - cur_b <<= 1; - } - } - - g_pwm_buffer_update_required = true; -} - -/** - * @brief Disable all LED Rows - */ -void MBIA045_disable_rows(void) { - // Row 0 - PC4 = PAL_LOW; - - // Row 1 - PC5 = PAL_LOW; - - // Row 2 - PB3 = PAL_LOW; - - // Row 3 - PB2 = PAL_LOW; - - // Row 4 - PD9 = PAL_LOW; -} - -/** - * @brief Enable the specific LED row, disabling all others - */ -void MBIA045_select_row(int row) { - MBIA045_disable_rows(); - switch (row) { - case 0: // Row 0 - PC4 = PAL_HIGH; - break; - case 1: // Row 1 - PC5 = PAL_HIGH; - break; - case 2: // Row 2 - PB3 = PAL_HIGH; - break; - case 3: // Row 3 - PB2 = PAL_HIGH; - break; - case 4: // Row 4 - PD9 = PAL_HIGH; - break; - } -} - -OSAL_IRQ_HANDLER(NUC123_PWMA_HANDLER) { - OSAL_IRQ_PROLOGUE(); - - /* Check for PWM1 underflow IRQ */ - if ((PWMA->PIIR >> PWM_PIIR_PWMIF1_Pos) & 1) { - /* Clear interrupt flag */ - PWMA->PIIR |= 1 << PWM_PIIR_PWMIF1_Pos; - MBIA045_update_pwm_buffers(); - } - - OSAL_IRQ_EPILOGUE(); -} - -const rgb_matrix_driver_t rgb_matrix_driver = { - .init = MBIA045_init, - .flush = MBIA045_flush, - .set_color = MBIA045_set_color, - .set_color_all = MBIA045_set_color_all, -}; - -#endif diff --git a/keyboards/ducky/one2sf/1967st/rules.mk b/keyboards/ducky/one2sf/1967st/rules.mk index 58b1fa8470f..c6a35c4ec1e 100644 --- a/keyboards/ducky/one2sf/1967st/rules.mk +++ b/keyboards/ducky/one2sf/1967st/rules.mk @@ -30,9 +30,6 @@ RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow AUDIO_ENABLE = no # Audio output DIP_SWITCH_ENABLE = yes -<<<<<<< HEAD -======= RGB_MATRIX_ENABLE = yes SRC += rgb_matrix_drivers.c ->>>>>>> 41dc4aefcf (Move led driver into the keyboard)