~ruther/qmk_firmware

acd3e79add2d47ab664b831936e5b6e71d3b8e15 — yiancar 6 years ago 8680c50
NK65 Addition (#5865)

* Nk65 initial commit

* Minor fix for compatibility

* Make everything pretty

* Update keyboards/nk65/config.h

Co-Authored-By: noroadsleft <18669334+noroadsleft@users.noreply.github.com>

* Update keyboards/nk65/readme.md

Co-Authored-By: noroadsleft <18669334+noroadsleft@users.noreply.github.com>

* Chmod Dummy

* Update getting_started_introduction.md

* Revert "Update getting_started_introduction.md"

This reverts commit daf446acf7ae4ae00488b389ce04f2cfca708d44.
M drivers/issi/is31fl3733.c => drivers/issi/is31fl3733.c +19 -19
@@ 75,10 75,10 @@ uint8_t g_twi_transfer_buffer[20];
// buffers and the transfers in IS31FL3733_write_pwm_buffer() but it's
// probably not worth the extra complexity.
uint8_t g_pwm_buffer[DRIVER_COUNT][192];
bool g_pwm_buffer_update_required = false;
bool g_pwm_buffer_update_required[DRIVER_COUNT] = { false };

uint8_t g_led_control_registers[DRIVER_COUNT][24] = { { 0 }, { 0 } };
bool g_led_control_registers_update_required = false;
bool g_led_control_registers_update_required[DRIVER_COUNT] = { false };

void IS31FL3733_write_register( uint8_t addr, uint8_t reg, uint8_t data )
{


@@ 123,12 123,13 @@ void IS31FL3733_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer )
    }
}

void IS31FL3733_init( uint8_t addr )
void IS31FL3733_init( uint8_t addr, uint8_t sync)
{
    // In order to avoid the LEDs being driven with garbage data
    // in the LED driver's PWM registers, shutdown is enabled last.
    // Set up the mode and other settings, clear the PWM registers,
    // then disable software shutdown.
    // Sync is passed so set it according to the datasheet.

    // Unlock the command register.
    IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );


@@ 161,7 162,7 @@ void IS31FL3733_init( uint8_t addr )
    // Set global current to maximum.
    IS31FL3733_write_register( addr, ISSI_REG_GLOBALCURRENT, 0xFF );
    // Disable software shutdown.
    IS31FL3733_write_register( addr, ISSI_REG_CONFIGURATION, 0x01 );
    IS31FL3733_write_register( addr, ISSI_REG_CONFIGURATION, (sync << 6) | 0x01 );

    // Wait 10ms to ensure the device has woken up.
    #ifdef __AVR__


@@ 179,7 180,7 @@ void IS31FL3733_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
        g_pwm_buffer[led.driver][led.r] = red;
        g_pwm_buffer[led.driver][led.g] = green;
        g_pwm_buffer[led.driver][led.b] = blue;
        g_pwm_buffer_update_required = true;
        g_pwm_buffer_update_required[led.driver] = true;
    }
}



@@ 218,35 219,34 @@ void IS31FL3733_set_led_control_register( uint8_t index, bool red, bool green, b
        g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b);
    }

    g_led_control_registers_update_required = true;
    g_led_control_registers_update_required[led.driver] = true;

}

void IS31FL3733_update_pwm_buffers( uint8_t addr1, uint8_t addr2 )
void IS31FL3733_update_pwm_buffers( uint8_t addr, uint8_t index )
{
    if ( g_pwm_buffer_update_required )
    if ( g_pwm_buffer_update_required[index] )
    {
        // Firstly we need to unlock the command register and select PG1
        IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
        IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM );
        IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
        IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_PWM );

        IS31FL3733_write_pwm_buffer( addr1, g_pwm_buffer[0] );
        //IS31FL3733_write_pwm_buffer( addr2, g_pwm_buffer[1] );
        IS31FL3733_write_pwm_buffer( addr, g_pwm_buffer[index] );
    }
    g_pwm_buffer_update_required = false;
    g_pwm_buffer_update_required[index] = false;
}

void IS31FL3733_update_led_control_registers( uint8_t addr1, uint8_t addr2 )
void IS31FL3733_update_led_control_registers( uint8_t addr, uint8_t index )
{
    if ( g_led_control_registers_update_required )
    if ( g_led_control_registers_update_required[index] )
    {
        // Firstly we need to unlock the command register and select PG0
        IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
        IS31FL3733_write_register( addr1, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL );
        IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER_WRITELOCK, 0xC5 );
        IS31FL3733_write_register( addr, ISSI_COMMANDREGISTER, ISSI_PAGE_LEDCONTROL );
        for ( int i=0; i<24; i++ )
        {
            IS31FL3733_write_register(addr1, i, g_led_control_registers[0][i] );
            //IS31FL3733_write_register(addr2, i, g_led_control_registers[1][i] );
            IS31FL3733_write_register(addr, i, g_led_control_registers[index][i] );
        }
    }
    g_led_control_registers_update_required[index] = false;
}

M drivers/issi/is31fl3733.h => drivers/issi/is31fl3733.h +3 -3
@@ 32,7 32,7 @@ typedef struct is31_led {

extern const is31_led g_is31_leds[DRIVER_LED_TOTAL];

void IS31FL3733_init( uint8_t addr );
void IS31FL3733_init( uint8_t addr, uint8_t sync );
void IS31FL3733_write_register( uint8_t addr, uint8_t reg, uint8_t data );
void IS31FL3733_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer );



@@ 45,8 45,8 @@ void IS31FL3733_set_led_control_register( uint8_t index, bool red, bool green, b
// (eg. from a timer interrupt).
// Call this while idle (in between matrix scans).
// If the buffer is dirty, it will update the driver with the buffer.
void IS31FL3733_update_pwm_buffers( uint8_t addr1, uint8_t addr2 );
void IS31FL3733_update_led_control_registers( uint8_t addr1, uint8_t addr2 );
void IS31FL3733_update_pwm_buffers( uint8_t addr, uint8_t index );
void IS31FL3733_update_led_control_registers( uint8_t addr, uint8_t index );

#define A_1  0x00
#define A_2  0x01

A keyboards/nk65/boards/GENERIC_STM32_F303XC/board.c => keyboards/nk65/boards/GENERIC_STM32_F303XC/board.c +126 -0
@@ 0,0 1,126 @@
/*
    ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#include "hal.h"

#if HAL_USE_PAL || defined(__DOXYGEN__)
/**
 * @brief   PAL setup.
 * @details Digital I/O ports static configuration as defined in @p board.h.
 *          This variable is used by the HAL when initializing the PAL driver.
 */
const PALConfig pal_default_config = {
#if STM32_HAS_GPIOA
  {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR,
   VAL_GPIOA_ODR,   VAL_GPIOA_AFRL,   VAL_GPIOA_AFRH},
#endif
#if STM32_HAS_GPIOB
  {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR,
   VAL_GPIOB_ODR,   VAL_GPIOB_AFRL,   VAL_GPIOB_AFRH},
#endif
#if STM32_HAS_GPIOC
  {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR,
   VAL_GPIOC_ODR,   VAL_GPIOC_AFRL,   VAL_GPIOC_AFRH},
#endif
#if STM32_HAS_GPIOD
  {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR,
   VAL_GPIOD_ODR,   VAL_GPIOD_AFRL,   VAL_GPIOD_AFRH},
#endif
#if STM32_HAS_GPIOE
  {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR,
   VAL_GPIOE_ODR,   VAL_GPIOE_AFRL,   VAL_GPIOE_AFRH},
#endif
#if STM32_HAS_GPIOF
  {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR,
   VAL_GPIOF_ODR,   VAL_GPIOF_AFRL,   VAL_GPIOF_AFRH},
#endif
#if STM32_HAS_GPIOG
  {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR,
   VAL_GPIOG_ODR,   VAL_GPIOG_AFRL,   VAL_GPIOG_AFRH},
#endif
#if STM32_HAS_GPIOH
  {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR,
   VAL_GPIOH_ODR,   VAL_GPIOH_AFRL,   VAL_GPIOH_AFRH},
#endif
#if STM32_HAS_GPIOI
  {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR,
   VAL_GPIOI_ODR,   VAL_GPIOI_AFRL,   VAL_GPIOI_AFRH}
#endif
};
#endif

void enter_bootloader_mode_if_requested(void);

/**
 * @brief   Early initialization code.
 * @details This initialization must be performed just after stack setup
 *          and before any other initialization.
 */
void __early_init(void) {
  enter_bootloader_mode_if_requested();
  stm32_clock_init();
}

#if HAL_USE_SDC || defined(__DOXYGEN__)
/**
 * @brief   SDC card detection.
 */
bool sdc_lld_is_card_inserted(SDCDriver *sdcp) {

  (void)sdcp;
  /* TODO: Fill the implementation.*/
  return true;
}

/**
 * @brief   SDC card write protection detection.
 */
bool sdc_lld_is_write_protected(SDCDriver *sdcp) {

  (void)sdcp;
  /* TODO: Fill the implementation.*/
  return false;
}
#endif /* HAL_USE_SDC */

#if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
/**
 * @brief   MMC_SPI card detection.
 */
bool mmc_lld_is_card_inserted(MMCDriver *mmcp) {

  (void)mmcp;
  /* TODO: Fill the implementation.*/
  return true;
}

/**
 * @brief   MMC_SPI card write protection detection.
 */
bool mmc_lld_is_write_protected(MMCDriver *mmcp) {

  (void)mmcp;
  /* TODO: Fill the implementation.*/
  return false;
}
#endif

/**
 * @brief   Board-specific initialization code.
 * @todo    Add your board-specific code, if any.
 */
void boardInit(void) {
}

A keyboards/nk65/boards/GENERIC_STM32_F303XC/board.h => keyboards/nk65/boards/GENERIC_STM32_F303XC/board.h +1187 -0
@@ 0,0 1,1187 @@
/*
    ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#ifndef _BOARD_H_
#define _BOARD_H_

/*
 * Setup for NK65 Keyboard
 */

/*
 * Board identifier.
 */
#define BOARD_GENERIC_STM32_F303XC
#define BOARD_NAME                  "NK65 PCB"

/*
 * Board oscillators-related settings.
 * NOTE: LSE not fitted.
 */
#if !defined(STM32_LSECLK)
#define STM32_LSECLK                0U
#endif

#define STM32_LSEDRV                (3U << 3U)

#if !defined(STM32_HSECLK)
#define STM32_HSECLK                8000000U
#endif

// #define STM32_HSE_BYPASS

/*
 * MCU type as defined in the ST header.
 */
#define STM32F303xC

/*
 * IO pins assignments.
 */
#define GPIOA_PIN0       0U
#define GPIOA_PIN1       1U
#define GPIOA_PIN2       2U
#define GPIOA_PIN3       3U
#define GPIOA_PIN4       4U
#define GPIOA_PIN5       5U
#define GPIOA_PIN6       6U
#define GPIOA_PIN7       7U
#define GPIOA_PIN8       8U
#define GPIOA_PIN9       9U
#define GPIOA_PIN10      10U
#define GPIOA_USB_DM     11U
#define GPIOA_USB_DP     12U
#define GPIOA_SWDIO      13U
#define GPIOA_SWCLK      14U
#define GPIOA_PIN15      15U

#define GPIOB_PIN0       0U
#define GPIOB_PIN1       1U
#define GPIOB_PIN2       2U
#define GPIOB_PIN3       3U
#define GPIOB_PIN4       4U
#define GPIOB_PIN5       5U
#define GPIOB_PIN6       6U
#define GPIOB_PIN7       7U
#define GPIOB_PIN8       8U
#define GPIOB_PIN9       9U
#define GPIOB_PIN10      10U
#define GPIOB_PIN11      11U
#define GPIOB_PIN12      12U
#define GPIOB_PIN13      13U
#define GPIOB_PIN14      14U
#define GPIOB_PIN15      15U

#define GPIOC_PIN0       0U
#define GPIOC_PIN1       1U
#define GPIOC_PIN2       2U
#define GPIOC_PIN3       3U
#define GPIOC_PIN4       4U
#define GPIOC_PIN5       5U
#define GPIOC_PIN6       6U
#define GPIOC_PIN7       7U
#define GPIOC_PIN8       8U
#define GPIOC_PIN9       9U
#define GPIOC_PIN10      10U
#define GPIOC_PIN11      11U
#define GPIOC_PIN12      12U
#define GPIOC_PIN13      13U
#define GPIOC_PIN14      14U
#define GPIOC_PIN15      15U

#define GPIOD_PIN0       0U
#define GPIOD_PIN1       1U
#define GPIOD_PIN2       2U
#define GPIOD_PIN3       3U
#define GPIOD_PIN4       4U
#define GPIOD_PIN5       5U
#define GPIOD_PIN6       6U
#define GPIOD_PIN7       7U
#define GPIOD_PIN8       8U
#define GPIOD_PIN9       9U
#define GPIOD_PIN10      10U
#define GPIOD_PIN11      11U
#define GPIOD_PIN12      12U
#define GPIOD_PIN13      13U
#define GPIOD_PIN14      14U
#define GPIOD_PIN15      15U

#define GPIOE_PIN0       0U
#define GPIOE_PIN1       1U
#define GPIOE_PIN2       2U
#define GPIOE_PIN3       3U
#define GPIOE_PIN4       4U
#define GPIOE_PIN5       5U
#define GPIOE_PIN6       6U
#define GPIOE_PIN7       7U
#define GPIOE_PIN8       8U
#define GPIOE_PIN9       9U
#define GPIOE_PIN10      10U
#define GPIOE_PIN11      11U
#define GPIOE_PIN12      12U
#define GPIOE_PIN13      13U
#define GPIOE_PIN14      14U
#define GPIOE_PIN15      15U

#define GPIOF_I2C2_SDA   0U
#define GPIOF_I2C2_SCL   1U
#define GPIOF_PIN2       2U
#define GPIOF_PIN3       3U
#define GPIOF_PIN4       4U
#define GPIOF_PIN5       5U
#define GPIOF_PIN6       6U
#define GPIOF_PIN7       7U
#define GPIOF_PIN8       8U
#define GPIOF_PIN9       9U
#define GPIOF_PIN10      10U
#define GPIOF_PIN11      11U
#define GPIOF_PIN12      12U
#define GPIOF_PIN13      13U
#define GPIOF_PIN14      14U
#define GPIOF_PIN15      15U

#define GPIOG_PIN0       0U
#define GPIOG_PIN1       1U
#define GPIOG_PIN2       2U
#define GPIOG_PIN3       3U
#define GPIOG_PIN4       4U
#define GPIOG_PIN5       5U
#define GPIOG_PIN6       6U
#define GPIOG_PIN7       7U
#define GPIOG_PIN8       8U
#define GPIOG_PIN9       9U
#define GPIOG_PIN10      10U
#define GPIOG_PIN11      11U
#define GPIOG_PIN12      12U
#define GPIOG_PIN13      13U
#define GPIOG_PIN14      14U
#define GPIOG_PIN15      15U

#define GPIOH_PIN0       0U
#define GPIOH_PIN1       1U
#define GPIOH_PIN2       2U
#define GPIOH_PIN3       3U
#define GPIOH_PIN4       4U
#define GPIOH_PIN5       5U
#define GPIOH_PIN6       6U
#define GPIOH_PIN7       7U
#define GPIOH_PIN8       8U
#define GPIOH_PIN9       9U
#define GPIOH_PIN10      10U
#define GPIOH_PIN11      11U
#define GPIOH_PIN12      12U
#define GPIOH_PIN13      13U
#define GPIOH_PIN14      14U
#define GPIOH_PIN15      15U

/*
 * IO lines assignments.
 */
#define LINE_L3GD20_SDI             PAL_LINE(GPIOA, 7U)
#define LINE_USB_DM                 PAL_LINE(GPIOA, 11U)
#define LINE_USB_DP                 PAL_LINE(GPIOA, 12U)
#define LINE_SWDIO                  PAL_LINE(GPIOA, 13U)
#define LINE_SWCLK                  PAL_LINE(GPIOA, 14U)

#define LINE_PIN6               PAL_LINE(GPIOF, 0U)
#define LINE_PIN7               PAL_LINE(GPIOF, 1U)

#define LINE_CAPS_LOCK               PAL_LINE(GPIOB, 7U)


/*
 * I/O ports initial setup, this configuration is established soon after reset
 * in the initialization code.
 * Please refer to the STM32 Reference Manual for details.
 */
#define PIN_MODE_INPUT(n)           (0U << ((n) * 2U))
#define PIN_MODE_OUTPUT(n)          (1U << ((n) * 2U))
#define PIN_MODE_ALTERNATE(n)       (2U << ((n) * 2U))
#define PIN_MODE_ANALOG(n)          (3U << ((n) * 2U))
#define PIN_ODR_LOW(n)              (0U << (n))
#define PIN_ODR_HIGH(n)             (1U << (n))
#define PIN_OTYPE_PUSHPULL(n)       (0U << (n))
#define PIN_OTYPE_OPENDRAIN(n)      (1U << (n))
#define PIN_OSPEED_VERYLOW(n)       (0U << ((n) * 2U))
#define PIN_OSPEED_LOW(n)           (1U << ((n) * 2U))
#define PIN_OSPEED_MEDIUM(n)        (2U << ((n) * 2U))
#define PIN_OSPEED_HIGH(n)          (3U << ((n) * 2U))
#define PIN_PUPDR_FLOATING(n)       (0U << ((n) * 2U))
#define PIN_PUPDR_PULLUP(n)         (1U << ((n) * 2U))
#define PIN_PUPDR_PULLDOWN(n)       (2U << ((n) * 2U))
#define PIN_AFIO_AF(n, v)           ((v) << (((n) % 8U) * 4U))

/*
 * GPIOA setup:
 *
 * PA0  - NC
 * PA1  - NC
 * PA2  - COL1
 * PA3  - COL2
 * PA4  - SPEAKER1
 * PA5  - SPEAKER2
 * PA6  - COL3
 * PA7  - COL8
 * PA8  - COL6
 * PA9  - COL7
 * PA10 - ROW5
 * PA11 - USB_DM                    (alternate 14).
 * PA12 - USB_DP                    (alternate 14).
 * PA13 - SWDIO                     (alternate 0).
 * PA14 - SWCLK                     (alternate 0).
 * PA15 - ROW4
 */
#define VAL_GPIOA_MODER             (PIN_MODE_INPUT(GPIOA_PIN0) |         \
                                     PIN_MODE_ALTERNATE(GPIOA_PIN1) |           \
                                     PIN_MODE_INPUT(GPIOA_PIN2) |           \
                                     PIN_MODE_INPUT(GPIOA_PIN3) |           \
                                     PIN_MODE_INPUT(GPIOA_PIN4) |           \
                                     PIN_MODE_INPUT(GPIOA_PIN5) |   \
                                     PIN_MODE_INPUT(GPIOA_PIN6) |  \
                                     PIN_MODE_INPUT(GPIOA_PIN7) |  \
                                     PIN_MODE_INPUT(GPIOA_PIN8) |           \
                                     PIN_MODE_INPUT(GPIOA_PIN9) |           \
                                     PIN_MODE_INPUT(GPIOA_PIN10) |          \
                                     PIN_MODE_ALTERNATE(GPIOA_USB_DM) |     \
                                     PIN_MODE_ALTERNATE(GPIOA_USB_DP) |     \
                                     PIN_MODE_ALTERNATE(GPIOA_SWDIO) |      \
                                     PIN_MODE_ALTERNATE(GPIOA_SWCLK) |      \
                                     PIN_MODE_INPUT(GPIOA_PIN15))
#define VAL_GPIOA_OTYPER            (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) |     \
                                     PIN_OTYPE_PUSHPULL(GPIOA_PIN1) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOA_PIN2) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOA_PIN3) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOA_PIN4) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOA_PIN5) |   \
                                     PIN_OTYPE_PUSHPULL(GPIOA_PIN6) |  \
                                     PIN_OTYPE_PUSHPULL(GPIOA_PIN7) |  \
                                     PIN_OTYPE_PUSHPULL(GPIOA_PIN8) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOA_PIN9) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOA_PIN10) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) |     \
                                     PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) |     \
                                     PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOA_PIN15))
#define VAL_GPIOA_OSPEEDR           (PIN_OSPEED_VERYLOW(GPIOA_PIN0) |     \
                                     PIN_OSPEED_HIGH(GPIOA_PIN1) |       \
                                     PIN_OSPEED_VERYLOW(GPIOA_PIN2) |       \
                                     PIN_OSPEED_VERYLOW(GPIOA_PIN3) |       \
                                     PIN_OSPEED_VERYLOW(GPIOA_PIN4) |       \
                                     PIN_OSPEED_VERYLOW(GPIOA_PIN5) |      \
                                     PIN_OSPEED_VERYLOW(GPIOA_PIN6) |     \
                                     PIN_OSPEED_VERYLOW(GPIOA_PIN7) |     \
                                     PIN_OSPEED_VERYLOW(GPIOA_PIN8) |       \
                                     PIN_OSPEED_VERYLOW(GPIOA_PIN9) |       \
                                     PIN_OSPEED_VERYLOW(GPIOA_PIN10) |      \
                                     PIN_OSPEED_HIGH(GPIOA_USB_DM) |        \
                                     PIN_OSPEED_VERYLOW(GPIOA_USB_DP) |     \
                                     PIN_OSPEED_HIGH(GPIOA_SWDIO) |         \
                                     PIN_OSPEED_HIGH(GPIOA_SWCLK) |         \
                                     PIN_OSPEED_VERYLOW(GPIOA_PIN15))
#define VAL_GPIOA_PUPDR             (PIN_PUPDR_FLOATING(GPIOA_PIN0) |     \
                                     PIN_PUPDR_FLOATING(GPIOA_PIN1) |         \
                                     PIN_PUPDR_PULLUP(GPIOA_PIN2) |         \
                                     PIN_PUPDR_PULLUP(GPIOA_PIN3) |         \
                                     PIN_PUPDR_PULLUP(GPIOA_PIN4) |         \
                                     PIN_PUPDR_PULLUP(GPIOA_PIN5) |   \
                                     PIN_PUPDR_PULLUP(GPIOA_PIN6) |    \
                                     PIN_PUPDR_FLOATING(GPIOA_PIN7) |  \
                                     PIN_PUPDR_PULLUP(GPIOA_PIN8) |         \
                                     PIN_PUPDR_PULLUP(GPIOA_PIN9) |         \
                                     PIN_PUPDR_PULLUP(GPIOA_PIN10) |        \
                                     PIN_PUPDR_FLOATING(GPIOA_USB_DM) |     \
                                     PIN_PUPDR_FLOATING(GPIOA_USB_DP) |     \
                                     PIN_PUPDR_PULLUP(GPIOA_SWDIO) |        \
                                     PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) |      \
                                     PIN_PUPDR_PULLUP(GPIOA_PIN15))
#define VAL_GPIOA_ODR               (PIN_ODR_HIGH(GPIOA_PIN0) |           \
                                     PIN_ODR_HIGH(GPIOA_PIN1) |             \
                                     PIN_ODR_HIGH(GPIOA_PIN2) |             \
                                     PIN_ODR_HIGH(GPIOA_PIN3) |             \
                                     PIN_ODR_HIGH(GPIOA_PIN4) |             \
                                     PIN_ODR_HIGH(GPIOA_PIN5) |         \
                                     PIN_ODR_HIGH(GPIOA_PIN6) |        \
                                     PIN_ODR_HIGH(GPIOA_PIN7) |        \
                                     PIN_ODR_HIGH(GPIOA_PIN8) |             \
                                     PIN_ODR_HIGH(GPIOA_PIN9) |             \
                                     PIN_ODR_HIGH(GPIOA_PIN10) |            \
                                     PIN_ODR_HIGH(GPIOA_USB_DM) |           \
                                     PIN_ODR_HIGH(GPIOA_USB_DP) |           \
                                     PIN_ODR_HIGH(GPIOA_SWDIO) |            \
                                     PIN_ODR_HIGH(GPIOA_SWCLK) |            \
                                     PIN_ODR_HIGH(GPIOA_PIN15))
#define VAL_GPIOA_AFRL              (PIN_AFIO_AF(GPIOA_PIN0, 0) |         \
                                     PIN_AFIO_AF(GPIOA_PIN1, 1) |           \
                                     PIN_AFIO_AF(GPIOA_PIN2, 0) |           \
                                     PIN_AFIO_AF(GPIOA_PIN3, 0) |           \
                                     PIN_AFIO_AF(GPIOA_PIN4, 0) |           \
                                     PIN_AFIO_AF(GPIOA_PIN5, 5) |       \
                                     PIN_AFIO_AF(GPIOA_PIN6, 5) |      \
                                     PIN_AFIO_AF(GPIOA_PIN7, 5))
#define VAL_GPIOA_AFRH              (PIN_AFIO_AF(GPIOA_PIN8, 0) |           \
                                     PIN_AFIO_AF(GPIOA_PIN9, 0) |           \
                                     PIN_AFIO_AF(GPIOA_PIN10, 0) |          \
                                     PIN_AFIO_AF(GPIOA_USB_DM, 14) |        \
                                     PIN_AFIO_AF(GPIOA_USB_DP, 14) |        \
                                     PIN_AFIO_AF(GPIOA_SWDIO, 0) |          \
                                     PIN_AFIO_AF(GPIOA_SWCLK, 0) |          \
                                     PIN_AFIO_AF(GPIOA_PIN15, 0))

/*
 * GPIOB setup:
 *
 * PB0  - PIN0                      (input pullup).
 * PB1  - PIN1                      (input pullup).
 * PB2  - PIN2                      (input pullup).
 * PB3  - PIN3                       (alternate 0).
 * PB4  - PIN4                      (input pullup).
 * PB5  - PIN5                      (input pullup).
 * PB6  - PIN6 LSM303DLHC_SCL   (alternate 4).
 * PB7  - PIN7 LSM303DLHC_SDA   (alternate 4).
 * PB8  - PIN8                      (input pullup).
 * PB9  - PIN9                      (input pullup).
 * PB10 - PIN10                     (input pullup).
 * PB11 - PIN11                     (input pullup).
 * PB12 - PIN12                     (input pullup).
 * PB13 - PIN13                     (input pullup).
 * PB14 - PIN14                     (input pullup).
 * PB15 - PIN15                     (input pullup).
 */
#define VAL_GPIOB_MODER             (PIN_MODE_INPUT(GPIOB_PIN0) |           \
                                     PIN_MODE_INPUT(GPIOB_PIN1) |           \
                                     PIN_MODE_INPUT(GPIOB_PIN2) |           \
                                     PIN_MODE_ALTERNATE(GPIOB_PIN3) |        \
                                     PIN_MODE_INPUT(GPIOB_PIN4) |           \
                                     PIN_MODE_INPUT(GPIOB_PIN5) |           \
                                     PIN_MODE_ALTERNATE(GPIOB_PIN6) |   \
                                     PIN_MODE_OUTPUT(GPIOB_PIN7) |   \
                                     PIN_MODE_INPUT(GPIOB_PIN8) |           \
                                     PIN_MODE_INPUT(GPIOB_PIN9) |           \
                                     PIN_MODE_INPUT(GPIOB_PIN10) |          \
                                     PIN_MODE_INPUT(GPIOB_PIN11) |          \
                                     PIN_MODE_INPUT(GPIOB_PIN12) |          \
                                     PIN_MODE_INPUT(GPIOB_PIN13) |          \
                                     PIN_MODE_INPUT(GPIOB_PIN14) |          \
                                     PIN_MODE_INPUT(GPIOB_PIN15))
#define VAL_GPIOB_OTYPER            (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN1) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN2) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN3) |        \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN4) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN5) |       \
                                     PIN_OTYPE_OPENDRAIN(GPIOB_PIN6) |  \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN7) |  \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN8) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN9) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN10) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN11) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN12) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN13) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN14) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOB_PIN15))
#define VAL_GPIOB_OSPEEDR           (PIN_OSPEED_VERYLOW(GPIOB_PIN0) |       \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN1) |       \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN2) |       \
                                     PIN_OSPEED_HIGH(GPIOB_PIN3) |           \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN4) |       \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN5) |       \
                                     PIN_OSPEED_HIGH(GPIOB_PIN6) |      \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN7) |      \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN8) |       \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN9) |       \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN10) |      \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN11) |      \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN12) |      \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN13) |      \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN14) |      \
                                     PIN_OSPEED_VERYLOW(GPIOB_PIN15))
#define VAL_GPIOB_PUPDR             (PIN_PUPDR_PULLUP(GPIOB_PIN0) |         \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN1) |         \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN2) |         \
                                     PIN_PUPDR_FLOATING(GPIOB_PIN3) |        \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN4) |         \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN5) |         \
                                     PIN_PUPDR_FLOATING(GPIOB_PIN6) |   \
                                     PIN_PUPDR_PULLDOWN(GPIOB_PIN7) |   \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN8) |         \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN9) |         \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN10) |        \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN11) |        \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN12) |        \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN13) |        \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN14) |        \
                                     PIN_PUPDR_PULLUP(GPIOB_PIN15))
#define VAL_GPIOB_ODR               (PIN_ODR_HIGH(GPIOB_PIN0) |             \
                                     PIN_ODR_HIGH(GPIOB_PIN1) |             \
                                     PIN_ODR_HIGH(GPIOB_PIN2) |             \
                                     PIN_ODR_HIGH(GPIOB_PIN3) |              \
                                     PIN_ODR_HIGH(GPIOB_PIN4) |             \
                                     PIN_ODR_HIGH(GPIOB_PIN5) |             \
                                     PIN_ODR_HIGH(GPIOB_PIN6) |         \
                                     PIN_ODR_LOW(GPIOB_PIN7) |         \
                                     PIN_ODR_HIGH(GPIOB_PIN8) |             \
                                     PIN_ODR_HIGH(GPIOB_PIN9) |             \
                                     PIN_ODR_HIGH(GPIOB_PIN10) |            \
                                     PIN_ODR_HIGH(GPIOB_PIN11) |            \
                                     PIN_ODR_HIGH(GPIOB_PIN12) |            \
                                     PIN_ODR_HIGH(GPIOB_PIN13) |            \
                                     PIN_ODR_HIGH(GPIOB_PIN14) |            \
                                     PIN_ODR_HIGH(GPIOB_PIN15))
#define VAL_GPIOB_AFRL              (PIN_AFIO_AF(GPIOB_PIN0, 0) |           \
                                     PIN_AFIO_AF(GPIOB_PIN1, 0) |           \
                                     PIN_AFIO_AF(GPIOB_PIN2, 0) |           \
                                     PIN_AFIO_AF(GPIOB_PIN3, 0) |            \
                                     PIN_AFIO_AF(GPIOB_PIN4, 0) |           \
                                     PIN_AFIO_AF(GPIOB_PIN5, 0) |           \
                                     PIN_AFIO_AF(GPIOB_PIN6, 4) |       \
                                     PIN_AFIO_AF(GPIOB_PIN7, 0))
#define VAL_GPIOB_AFRH              (PIN_AFIO_AF(GPIOB_PIN8, 0) |           \
                                     PIN_AFIO_AF(GPIOB_PIN9, 0) |           \
                                     PIN_AFIO_AF(GPIOB_PIN10, 0) |          \
                                     PIN_AFIO_AF(GPIOB_PIN11, 0) |          \
                                     PIN_AFIO_AF(GPIOB_PIN12, 0) |          \
                                     PIN_AFIO_AF(GPIOB_PIN13, 0) |          \
                                     PIN_AFIO_AF(GPIOB_PIN14, 0) |          \
                                     PIN_AFIO_AF(GPIOB_PIN15, 0))

/*
 * GPIOC setup:
 *
 * PC0  - PIN0                      (input pullup).
 * PC1  - PIN1                      (input pullup).
 * PC2  - PIN2                      (input pullup).
 * PC3  - PIN3                      (input pullup).
 * PC4  - PIN4                      (input pullup).
 * PC5  - PIN5                      (input pullup).
 * PC6  - PIN6                      (input pullup).
 * PC7  - PIN7                      (input pullup).
 * PC8  - PIN8                      (input pullup).
 * PC9  - PIN9                      (input pullup).
 * PC10 - PIN10                     (input pullup).
 * PC11 - PIN11                     (input pullup).
 * PC12 - PIN12                     (input pullup).
 * PC13 - PIN13                     (input pullup).
 * PC14 - PIN14                  (input floating).
 * PC15 - PIN15                 (input floating).
 */
#define VAL_GPIOC_MODER             (PIN_MODE_INPUT(GPIOC_PIN0) |           \
                                     PIN_MODE_INPUT(GPIOC_PIN1) |           \
                                     PIN_MODE_INPUT(GPIOC_PIN2) |           \
                                     PIN_MODE_INPUT(GPIOC_PIN3) |           \
                                     PIN_MODE_INPUT(GPIOC_PIN4) |           \
                                     PIN_MODE_INPUT(GPIOC_PIN5) |           \
                                     PIN_MODE_INPUT(GPIOC_PIN6) |           \
                                     PIN_MODE_INPUT(GPIOC_PIN7) |           \
                                     PIN_MODE_INPUT(GPIOC_PIN8) |           \
                                     PIN_MODE_INPUT(GPIOC_PIN9) |           \
                                     PIN_MODE_INPUT(GPIOC_PIN10) |          \
                                     PIN_MODE_INPUT(GPIOC_PIN11) |          \
                                     PIN_MODE_INPUT(GPIOC_PIN12) |          \
                                     PIN_MODE_INPUT(GPIOC_PIN13) |          \
                                     PIN_MODE_INPUT(GPIOC_PIN14) |       \
                                     PIN_MODE_INPUT(GPIOC_PIN15))
#define VAL_GPIOC_OTYPER            (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN1) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN2) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN3) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN4) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN5) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN6) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN7) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN8) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN9) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN10) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN11) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN12) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN13) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN14) |   \
                                     PIN_OTYPE_PUSHPULL(GPIOC_PIN15))
#define VAL_GPIOC_OSPEEDR           (PIN_OSPEED_VERYLOW(GPIOC_PIN0) |       \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN1) |       \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN2) |       \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN3) |       \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN4) |       \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN5) |       \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN6) |       \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN7) |       \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN8) |       \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN9) |       \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN10) |      \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN11) |      \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN12) |      \
                                     PIN_OSPEED_VERYLOW(GPIOC_PIN13) |      \
                                     PIN_OSPEED_HIGH(GPIOC_PIN14) |      \
                                     PIN_OSPEED_HIGH(GPIOC_PIN15))
#define VAL_GPIOC_PUPDR             (PIN_PUPDR_PULLUP(GPIOC_PIN0) |         \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN1) |         \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN2) |         \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN3) |         \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN4) |         \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN5) |         \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN6) |         \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN7) |         \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN8) |         \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN9) |         \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN10) |        \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN11) |        \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN12) |        \
                                     PIN_PUPDR_PULLUP(GPIOC_PIN13) |        \
                                     PIN_PUPDR_FLOATING(GPIOC_PIN14) |   \
                                     PIN_PUPDR_FLOATING(GPIOC_PIN15))
#define VAL_GPIOC_ODR               (PIN_ODR_HIGH(GPIOC_PIN0) |             \
                                     PIN_ODR_HIGH(GPIOC_PIN1) |             \
                                     PIN_ODR_HIGH(GPIOC_PIN2) |             \
                                     PIN_ODR_HIGH(GPIOC_PIN3) |             \
                                     PIN_ODR_HIGH(GPIOC_PIN4) |             \
                                     PIN_ODR_HIGH(GPIOC_PIN5) |             \
                                     PIN_ODR_HIGH(GPIOC_PIN6) |             \
                                     PIN_ODR_HIGH(GPIOC_PIN7) |             \
                                     PIN_ODR_HIGH(GPIOC_PIN8) |             \
                                     PIN_ODR_HIGH(GPIOC_PIN9) |             \
                                     PIN_ODR_HIGH(GPIOC_PIN10) |            \
                                     PIN_ODR_HIGH(GPIOC_PIN11) |            \
                                     PIN_ODR_HIGH(GPIOC_PIN12) |            \
                                     PIN_ODR_HIGH(GPIOC_PIN13) |            \
                                     PIN_ODR_HIGH(GPIOC_PIN14) |         \
                                     PIN_ODR_HIGH(GPIOC_PIN15))
#define VAL_GPIOC_AFRL              (PIN_AFIO_AF(GPIOC_PIN0, 0) |           \
                                     PIN_AFIO_AF(GPIOC_PIN1, 0) |           \
                                     PIN_AFIO_AF(GPIOC_PIN2, 0) |           \
                                     PIN_AFIO_AF(GPIOC_PIN3, 0) |           \
                                     PIN_AFIO_AF(GPIOC_PIN4, 0) |           \
                                     PIN_AFIO_AF(GPIOC_PIN5, 0) |           \
                                     PIN_AFIO_AF(GPIOC_PIN6, 0) |           \
                                     PIN_AFIO_AF(GPIOC_PIN7, 0))
#define VAL_GPIOC_AFRH              (PIN_AFIO_AF(GPIOC_PIN8, 0) |           \
                                     PIN_AFIO_AF(GPIOC_PIN9, 0) |           \
                                     PIN_AFIO_AF(GPIOC_PIN10, 0) |          \
                                     PIN_AFIO_AF(GPIOC_PIN11, 0) |          \
                                     PIN_AFIO_AF(GPIOC_PIN12, 0) |          \
                                     PIN_AFIO_AF(GPIOC_PIN13, 0) |          \
                                     PIN_AFIO_AF(GPIOC_PIN14, 0) |       \
                                     PIN_AFIO_AF(GPIOC_PIN15, 0))

/*
 * GPIOD setup:
 *
 * PD0  - PIN0                      (input pullup).
 * PD1  - PIN1                      (input pullup).
 * PD2  - PIN2                      (input pullup).
 * PD3  - PIN3                      (input pullup).
 * PD4  - PIN4                      (input pullup).
 * PD5  - PIN5                      (input pullup).
 * PD6  - PIN6                      (input pullup).
 * PD7  - PIN7                      (input pullup).
 * PD8  - PIN8                      (input pullup).
 * PD9  - PIN9                      (input pullup).
 * PD11 - PIN10                     (input pullup).
 * PD11 - PIN11                     (input pullup).
 * PD12 - PIN12                     (input pullup).
 * PD13 - PIN13                     (input pullup).
 * PD14 - PIN14                     (input pullup).
 * PD15 - PIN15                     (input pullup).
 */
#define VAL_GPIOD_MODER             (PIN_MODE_INPUT(GPIOD_PIN0) |           \
                                     PIN_MODE_INPUT(GPIOD_PIN1) |           \
                                     PIN_MODE_INPUT(GPIOD_PIN2) |           \
                                     PIN_MODE_INPUT(GPIOD_PIN3) |           \
                                     PIN_MODE_INPUT(GPIOD_PIN4) |           \
                                     PIN_MODE_INPUT(GPIOD_PIN5) |           \
                                     PIN_MODE_INPUT(GPIOD_PIN6) |           \
                                     PIN_MODE_INPUT(GPIOD_PIN7) |           \
                                     PIN_MODE_INPUT(GPIOD_PIN8) |           \
                                     PIN_MODE_INPUT(GPIOD_PIN9) |           \
                                     PIN_MODE_INPUT(GPIOD_PIN10) |          \
                                     PIN_MODE_INPUT(GPIOD_PIN11) |          \
                                     PIN_MODE_INPUT(GPIOD_PIN12) |          \
                                     PIN_MODE_INPUT(GPIOD_PIN13) |          \
                                     PIN_MODE_INPUT(GPIOD_PIN14) |          \
                                     PIN_MODE_INPUT(GPIOD_PIN15))
#define VAL_GPIOD_OTYPER            (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN1) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN2) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN3) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN4) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN5) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN6) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN7) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN8) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN9) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN10) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN11) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN12) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN13) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN14) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOD_PIN15))
#define VAL_GPIOD_OSPEEDR           (PIN_OSPEED_VERYLOW(GPIOD_PIN0) |       \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN1) |       \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN2) |       \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN3) |       \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN4) |       \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN5) |       \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN6) |       \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN7) |       \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN8) |       \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN9) |       \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN10) |      \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN11) |      \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN12) |      \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN13) |      \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN14) |      \
                                     PIN_OSPEED_VERYLOW(GPIOD_PIN15))
#define VAL_GPIOD_PUPDR             (PIN_PUPDR_PULLUP(GPIOD_PIN0) |         \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN1) |         \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN2) |         \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN3) |         \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN4) |         \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN5) |         \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN6) |         \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN7) |         \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN8) |         \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN9) |         \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN10) |        \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN11) |        \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN12) |        \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN13) |        \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN14) |        \
                                     PIN_PUPDR_PULLUP(GPIOD_PIN15))
#define VAL_GPIOD_ODR               (PIN_ODR_HIGH(GPIOD_PIN0) |             \
                                     PIN_ODR_HIGH(GPIOD_PIN1) |             \
                                     PIN_ODR_HIGH(GPIOD_PIN2) |             \
                                     PIN_ODR_HIGH(GPIOD_PIN3) |             \
                                     PIN_ODR_HIGH(GPIOD_PIN4) |             \
                                     PIN_ODR_HIGH(GPIOD_PIN5) |             \
                                     PIN_ODR_HIGH(GPIOD_PIN6) |             \
                                     PIN_ODR_HIGH(GPIOD_PIN7) |             \
                                     PIN_ODR_HIGH(GPIOD_PIN8) |             \
                                     PIN_ODR_HIGH(GPIOD_PIN9) |             \
                                     PIN_ODR_HIGH(GPIOD_PIN10) |            \
                                     PIN_ODR_HIGH(GPIOD_PIN11) |            \
                                     PIN_ODR_HIGH(GPIOD_PIN12) |            \
                                     PIN_ODR_HIGH(GPIOD_PIN13) |            \
                                     PIN_ODR_HIGH(GPIOD_PIN14) |            \
                                     PIN_ODR_HIGH(GPIOD_PIN15))
#define VAL_GPIOD_AFRL              (PIN_AFIO_AF(GPIOD_PIN0, 0) |           \
                                     PIN_AFIO_AF(GPIOD_PIN1, 0) |           \
                                     PIN_AFIO_AF(GPIOD_PIN2, 0) |           \
                                     PIN_AFIO_AF(GPIOD_PIN3, 0) |           \
                                     PIN_AFIO_AF(GPIOD_PIN4, 0) |           \
                                     PIN_AFIO_AF(GPIOD_PIN5, 0) |           \
                                     PIN_AFIO_AF(GPIOD_PIN6, 0) |           \
                                     PIN_AFIO_AF(GPIOD_PIN7, 0))
#define VAL_GPIOD_AFRH              (PIN_AFIO_AF(GPIOD_PIN8, 0) |           \
                                     PIN_AFIO_AF(GPIOD_PIN9, 0) |           \
                                     PIN_AFIO_AF(GPIOD_PIN10, 0) |          \
                                     PIN_AFIO_AF(GPIOD_PIN11, 0) |          \
                                     PIN_AFIO_AF(GPIOD_PIN12, 0) |          \
                                     PIN_AFIO_AF(GPIOD_PIN13, 0) |          \
                                     PIN_AFIO_AF(GPIOD_PIN14, 0) |          \
                                     PIN_AFIO_AF(GPIOD_PIN15, 0))

/*
 * GPIOE setup:
 *
 * PE0  - PIN0               (input pullup).
 * PE1  - PIN1               (input pullup).
 * PE2  - PIN2           (input pullup).
 * PE3  - PIN3 L3GD20_CS         (output pushpull maximum).
 * PE4  - PIN4           (input pullup).
 * PE5  - PIN5           (input pullup).
 * PE6  - PIN6                      (input pullup).
 * PE7  - PIN7                      (input pullup).
 * PE8  - PIN8                 (output pushpull maximum).
 * PE9  - PIN9                  (output pushpull maximum).
 * PE10 - PIN10               (output pushpull maximum).
 * PE11 - PIN11                (output pushpull maximum).
 * PE12 - PIN12                 (output pushpull maximum).
 * PE13 - PIN13                 (output pushpull maximum).
 * PE14 - PIN14               (output pushpull maximum).
 * PE15 - PIN15                (output pushpull maximum).
 */
#define VAL_GPIOE_MODER             (PIN_MODE_INPUT(GPIOE_PIN0) |    \
                                     PIN_MODE_INPUT(GPIOE_PIN1) |    \
                                     PIN_MODE_INPUT(GPIOE_PIN2) |\
                                     PIN_MODE_OUTPUT(GPIOE_PIN3) |       \
                                     PIN_MODE_INPUT(GPIOE_PIN4) |\
                                     PIN_MODE_INPUT(GPIOE_PIN5) |\
                                     PIN_MODE_INPUT(GPIOE_PIN6) |           \
                                     PIN_MODE_INPUT(GPIOE_PIN7) |           \
                                     PIN_MODE_OUTPUT(GPIOE_PIN8) |     \
                                     PIN_MODE_OUTPUT(GPIOE_PIN9) |      \
                                     PIN_MODE_OUTPUT(GPIOE_PIN10) |   \
                                     PIN_MODE_OUTPUT(GPIOE_PIN11) |    \
                                     PIN_MODE_OUTPUT(GPIOE_PIN12) |     \
                                     PIN_MODE_OUTPUT(GPIOE_PIN13) |     \
                                     PIN_MODE_OUTPUT(GPIOE_PIN14) |   \
                                     PIN_MODE_OUTPUT(GPIOE_PIN15))
#define VAL_GPIOE_OTYPER            (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) |\
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN1) |\
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN2) |\
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN3) |    \
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN4) |\
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN5) |\
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN6) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN7) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN8) |  \
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN9) |   \
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN10) |\
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN12) |  \
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN13) |  \
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN14) |\
                                     PIN_OTYPE_PUSHPULL(GPIOE_PIN15))
#define VAL_GPIOE_OSPEEDR           (PIN_OSPEED_VERYLOW(GPIOE_PIN0) |\
                                     PIN_OSPEED_VERYLOW(GPIOE_PIN1) |\
                                     PIN_OSPEED_VERYLOW(GPIOE_PIN2) |\
                                     PIN_OSPEED_HIGH(GPIOE_PIN3) |       \
                                     PIN_OSPEED_VERYLOW(GPIOE_PIN4) |\
                                     PIN_OSPEED_VERYLOW(GPIOE_PIN5) |\
                                     PIN_OSPEED_VERYLOW(GPIOE_PIN6) |       \
                                     PIN_OSPEED_VERYLOW(GPIOE_PIN7) |       \
                                     PIN_OSPEED_HIGH(GPIOE_PIN8) |     \
                                     PIN_OSPEED_HIGH(GPIOE_PIN9) |      \
                                     PIN_OSPEED_HIGH(GPIOE_PIN10) |   \
                                     PIN_OSPEED_HIGH(GPIOE_PIN11) |    \
                                     PIN_OSPEED_HIGH(GPIOE_PIN12) |     \
                                     PIN_OSPEED_HIGH(GPIOE_PIN13) |     \
                                     PIN_OSPEED_HIGH(GPIOE_PIN14) |   \
                                     PIN_OSPEED_HIGH(GPIOE_PIN15))
#define VAL_GPIOE_PUPDR             (PIN_PUPDR_PULLUP(GPIOE_PIN0) |  \
                                     PIN_PUPDR_PULLUP(GPIOE_PIN1) |  \
                                     PIN_PUPDR_PULLUP(GPIOE_PIN2) |\
                                     PIN_PUPDR_FLOATING(GPIOE_PIN3) |    \
                                     PIN_PUPDR_PULLUP(GPIOE_PIN4) |\
                                     PIN_PUPDR_PULLUP(GPIOE_PIN5) |\
                                     PIN_PUPDR_PULLUP(GPIOE_PIN6) |         \
                                     PIN_PUPDR_PULLUP(GPIOE_PIN7) |         \
                                     PIN_PUPDR_PULLUP(GPIOE_PIN8) |    \
                                     PIN_PUPDR_PULLUP(GPIOE_PIN9) |     \
                                     PIN_PUPDR_PULLUP(GPIOE_PIN10) |  \
                                     PIN_PUPDR_FLOATING(GPIOE_PIN11) | \
                                     PIN_PUPDR_PULLUP(GPIOE_PIN12) |    \
                                     PIN_PUPDR_FLOATING(GPIOE_PIN13) |  \
                                     PIN_PUPDR_FLOATING(GPIOE_PIN14) |\
                                     PIN_PUPDR_FLOATING(GPIOE_PIN15))
#define VAL_GPIOE_ODR               (PIN_ODR_HIGH(GPIOE_PIN0) |      \
                                     PIN_ODR_HIGH(GPIOE_PIN1) |      \
                                     PIN_ODR_HIGH(GPIOE_PIN2) |  \
                                     PIN_ODR_HIGH(GPIOE_PIN3) |          \
                                     PIN_ODR_HIGH(GPIOE_PIN4) |  \
                                     PIN_ODR_HIGH(GPIOE_PIN5) |  \
                                     PIN_ODR_HIGH(GPIOE_PIN6) |             \
                                     PIN_ODR_HIGH(GPIOE_PIN7) |             \
                                     PIN_ODR_LOW(GPIOE_PIN8) |         \
                                     PIN_ODR_LOW(GPIOE_PIN9) |          \
                                     PIN_ODR_LOW(GPIOE_PIN10) |       \
                                     PIN_ODR_LOW(GPIOE_PIN11) |        \
                                     PIN_ODR_LOW(GPIOE_PIN12) |         \
                                     PIN_ODR_LOW(GPIOE_PIN13) |         \
                                     PIN_ODR_LOW(GPIOE_PIN14) |       \
                                     PIN_ODR_LOW(GPIOE_PIN15))
#define VAL_GPIOE_AFRL              (PIN_AFIO_AF(GPIOE_PIN0, 0) |    \
                                     PIN_AFIO_AF(GPIOE_PIN1, 0) |    \
                                     PIN_AFIO_AF(GPIOE_PIN2, 0) |\
                                     PIN_AFIO_AF(GPIOE_PIN3, 0) |        \
                                     PIN_AFIO_AF(GPIOE_PIN4, 0) |\
                                     PIN_AFIO_AF(GPIOE_PIN5, 0) |\
                                     PIN_AFIO_AF(GPIOE_PIN6, 0) |           \
                                     PIN_AFIO_AF(GPIOE_PIN7, 0))
#define VAL_GPIOE_AFRH              (PIN_AFIO_AF(GPIOE_PIN8, 0) |      \
                                     PIN_AFIO_AF(GPIOE_PIN9, 0) |       \
                                     PIN_AFIO_AF(GPIOE_PIN10, 0) |    \
                                     PIN_AFIO_AF(GPIOE_PIN11, 0) |     \
                                     PIN_AFIO_AF(GPIOE_PIN12, 0) |      \
                                     PIN_AFIO_AF(GPIOE_PIN13, 0) |      \
                                     PIN_AFIO_AF(GPIOE_PIN14, 0) |    \
                                     PIN_AFIO_AF(GPIOE_PIN15, 0))

/*
 * GPIOF setup:
 *
 * PF0  - I2C2_SDA                    (input floating).
 * PF1  - I2C2_SCL                   (input floating).
 * PF2  - PIN2                      (input pullup).
 * PF3  - PIN3                      (input pullup).
 * PF4  - PIN4                      (input pullup).
 * PF5  - PIN5                      (input pullup).
 * PF6  - PIN6                      (input pullup).
 * PF7  - PIN7                      (input pullup).
 * PF8  - PIN8                      (input pullup).
 * PF9  - PIN9                      (input pullup).
 * PF10 - PIN10                     (input pullup).
 * PF11 - PIN11                     (input pullup).
 * PF12 - PIN12                     (input pullup).
 * PF13 - PIN13                     (input pullup).
 * PF14 - PIN14                     (input pullup).
 * PF15 - PIN15                     (input pullup).
 */
#define VAL_GPIOF_MODER             (PIN_MODE_INPUT(GPIOF_I2C2_SDA) |         \
                                     PIN_MODE_INPUT(GPIOF_I2C2_SCL) |        \
                                     PIN_MODE_INPUT(GPIOF_PIN2) |           \
                                     PIN_MODE_INPUT(GPIOF_PIN3) |           \
                                     PIN_MODE_INPUT(GPIOF_PIN4) |           \
                                     PIN_MODE_INPUT(GPIOF_PIN5) |           \
                                     PIN_MODE_INPUT(GPIOF_PIN6) |           \
                                     PIN_MODE_INPUT(GPIOF_PIN7) |           \
                                     PIN_MODE_INPUT(GPIOF_PIN8) |           \
                                     PIN_MODE_INPUT(GPIOF_PIN9) |           \
                                     PIN_MODE_INPUT(GPIOF_PIN10) |          \
                                     PIN_MODE_INPUT(GPIOF_PIN11) |          \
                                     PIN_MODE_INPUT(GPIOF_PIN12) |          \
                                     PIN_MODE_INPUT(GPIOF_PIN13) |          \
                                     PIN_MODE_INPUT(GPIOF_PIN14) |          \
                                     PIN_MODE_INPUT(GPIOF_PIN15))
#define VAL_GPIOF_OTYPER            (PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SDA) |     \
                                     PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SCL) |    \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN2) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN3) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN4) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN5) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN6) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN7) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN8) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN9) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN10) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN11) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN12) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN13) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN14) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOF_PIN15))
#define VAL_GPIOF_OSPEEDR           (PIN_OSPEED_HIGH(GPIOF_I2C2_SDA) |        \
                                     PIN_OSPEED_HIGH(GPIOF_I2C2_SCL) |       \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN2) |       \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN3) |       \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN4) |       \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN5) |       \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN6) |       \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN7) |       \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN8) |       \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN9) |       \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN10) |      \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN11) |      \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN12) |      \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN13) |      \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN14) |      \
                                     PIN_OSPEED_VERYLOW(GPIOF_PIN15))
#define VAL_GPIOF_PUPDR             (PIN_PUPDR_FLOATING(GPIOF_I2C2_SDA) |     \
                                     PIN_PUPDR_FLOATING(GPIOF_I2C2_SCL) |    \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN2) |         \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN3) |         \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN4) |         \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN5) |         \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN6) |         \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN7) |         \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN8) |         \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN9) |         \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN10) |        \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN11) |        \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN12) |        \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN13) |        \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN14) |        \
                                     PIN_PUPDR_PULLUP(GPIOF_PIN15))
#define VAL_GPIOF_ODR               (PIN_ODR_HIGH(GPIOF_I2C2_SDA) |           \
                                     PIN_ODR_HIGH(GPIOF_I2C2_SCL) |          \
                                     PIN_ODR_HIGH(GPIOF_PIN2) |             \
                                     PIN_ODR_HIGH(GPIOF_PIN3) |             \
                                     PIN_ODR_HIGH(GPIOF_PIN4) |             \
                                     PIN_ODR_HIGH(GPIOF_PIN5) |             \
                                     PIN_ODR_HIGH(GPIOF_PIN6) |             \
                                     PIN_ODR_HIGH(GPIOF_PIN7) |             \
                                     PIN_ODR_HIGH(GPIOF_PIN8) |             \
                                     PIN_ODR_HIGH(GPIOF_PIN9) |             \
                                     PIN_ODR_HIGH(GPIOF_PIN10) |            \
                                     PIN_ODR_HIGH(GPIOF_PIN11) |            \
                                     PIN_ODR_HIGH(GPIOF_PIN12) |            \
                                     PIN_ODR_HIGH(GPIOF_PIN13) |            \
                                     PIN_ODR_HIGH(GPIOF_PIN14) |            \
                                     PIN_ODR_HIGH(GPIOF_PIN15))
#define VAL_GPIOF_AFRL              (PIN_AFIO_AF(GPIOF_I2C2_SDA, 0) |         \
                                     PIN_AFIO_AF(GPIOF_I2C2_SCL, 0) |        \
                                     PIN_AFIO_AF(GPIOF_PIN2, 0) |           \
                                     PIN_AFIO_AF(GPIOF_PIN3, 0) |           \
                                     PIN_AFIO_AF(GPIOF_PIN4, 0) |           \
                                     PIN_AFIO_AF(GPIOF_PIN5, 0) |           \
                                     PIN_AFIO_AF(GPIOF_PIN6, 0) |           \
                                     PIN_AFIO_AF(GPIOF_PIN7, 0))
#define VAL_GPIOF_AFRH              (PIN_AFIO_AF(GPIOF_PIN8, 0) |           \
                                     PIN_AFIO_AF(GPIOF_PIN9, 0) |           \
                                     PIN_AFIO_AF(GPIOF_PIN10, 0) |          \
                                     PIN_AFIO_AF(GPIOF_PIN11, 0) |          \
                                     PIN_AFIO_AF(GPIOF_PIN12, 0) |          \
                                     PIN_AFIO_AF(GPIOF_PIN13, 0) |          \
                                     PIN_AFIO_AF(GPIOF_PIN14, 0) |          \
                                     PIN_AFIO_AF(GPIOF_PIN15, 0))

/*
 * GPIOG setup:
 *
 * PG0  - PIN0                      (input pullup).
 * PG1  - PIN1                      (input pullup).
 * PG2  - PIN2                      (input pullup).
 * PG3  - PIN3                      (input pullup).
 * PG4  - PIN4                      (input pullup).
 * PG5  - PIN5                      (input pullup).
 * PG6  - PIN6                      (input pullup).
 * PG7  - PIN7                      (input pullup).
 * PG8  - PIN8                      (input pullup).
 * PG9  - PIN9                      (input pullup).
 * PG10 - PIN10                     (input pullup).
 * PG11 - PIN11                     (input pullup).
 * PG12 - PIN12                     (input pullup).
 * PG13 - PIN13                     (input pullup).
 * PG14 - PIN14                     (input pullup).
 * PG15 - PIN15                     (input pullup).
 */
#define VAL_GPIOG_MODER             (PIN_MODE_INPUT(GPIOG_PIN0) |           \
                                     PIN_MODE_INPUT(GPIOG_PIN1) |           \
                                     PIN_MODE_INPUT(GPIOG_PIN2) |           \
                                     PIN_MODE_INPUT(GPIOG_PIN3) |           \
                                     PIN_MODE_INPUT(GPIOG_PIN4) |           \
                                     PIN_MODE_INPUT(GPIOG_PIN5) |           \
                                     PIN_MODE_INPUT(GPIOG_PIN6) |           \
                                     PIN_MODE_INPUT(GPIOG_PIN7) |           \
                                     PIN_MODE_INPUT(GPIOG_PIN8) |           \
                                     PIN_MODE_INPUT(GPIOG_PIN9) |           \
                                     PIN_MODE_INPUT(GPIOG_PIN10) |          \
                                     PIN_MODE_INPUT(GPIOG_PIN11) |          \
                                     PIN_MODE_INPUT(GPIOG_PIN12) |          \
                                     PIN_MODE_INPUT(GPIOG_PIN13) |          \
                                     PIN_MODE_INPUT(GPIOG_PIN14) |          \
                                     PIN_MODE_INPUT(GPIOG_PIN15))
#define VAL_GPIOG_OTYPER            (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN1) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN2) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN3) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN4) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN5) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN6) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN7) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN8) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN9) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN10) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN11) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN12) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN13) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN14) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOG_PIN15))
#define VAL_GPIOG_OSPEEDR           (PIN_OSPEED_VERYLOW(GPIOG_PIN0) |       \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN1) |       \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN2) |       \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN3) |       \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN4) |       \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN5) |       \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN6) |       \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN7) |       \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN8) |       \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN9) |       \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN10) |      \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN11) |      \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN12) |      \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN13) |      \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN14) |      \
                                     PIN_OSPEED_VERYLOW(GPIOG_PIN15))
#define VAL_GPIOG_PUPDR             (PIN_PUPDR_PULLUP(GPIOG_PIN0) |         \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN1) |         \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN2) |         \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN3) |         \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN4) |         \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN5) |         \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN6) |         \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN7) |         \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN8) |         \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN9) |         \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN10) |        \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN11) |        \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN12) |        \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN13) |        \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN14) |        \
                                     PIN_PUPDR_PULLUP(GPIOG_PIN15))
#define VAL_GPIOG_ODR               (PIN_ODR_HIGH(GPIOG_PIN0) |             \
                                     PIN_ODR_HIGH(GPIOG_PIN1) |             \
                                     PIN_ODR_HIGH(GPIOG_PIN2) |             \
                                     PIN_ODR_HIGH(GPIOG_PIN3) |             \
                                     PIN_ODR_HIGH(GPIOG_PIN4) |             \
                                     PIN_ODR_HIGH(GPIOG_PIN5) |             \
                                     PIN_ODR_HIGH(GPIOG_PIN6) |             \
                                     PIN_ODR_HIGH(GPIOG_PIN7) |             \
                                     PIN_ODR_HIGH(GPIOG_PIN8) |             \
                                     PIN_ODR_HIGH(GPIOG_PIN9) |             \
                                     PIN_ODR_HIGH(GPIOG_PIN10) |            \
                                     PIN_ODR_HIGH(GPIOG_PIN11) |            \
                                     PIN_ODR_HIGH(GPIOG_PIN12) |            \
                                     PIN_ODR_HIGH(GPIOG_PIN13) |            \
                                     PIN_ODR_HIGH(GPIOG_PIN14) |            \
                                     PIN_ODR_HIGH(GPIOG_PIN15))
#define VAL_GPIOG_AFRL              (PIN_AFIO_AF(GPIOG_PIN0, 0) |           \
                                     PIN_AFIO_AF(GPIOG_PIN1, 0) |           \
                                     PIN_AFIO_AF(GPIOG_PIN2, 0) |           \
                                     PIN_AFIO_AF(GPIOG_PIN3, 0) |           \
                                     PIN_AFIO_AF(GPIOG_PIN4, 0) |           \
                                     PIN_AFIO_AF(GPIOG_PIN5, 0) |           \
                                     PIN_AFIO_AF(GPIOG_PIN6, 0) |           \
                                     PIN_AFIO_AF(GPIOG_PIN7, 0))
#define VAL_GPIOG_AFRH              (PIN_AFIO_AF(GPIOG_PIN8, 0) |           \
                                     PIN_AFIO_AF(GPIOG_PIN9, 0) |           \
                                     PIN_AFIO_AF(GPIOG_PIN10, 0) |          \
                                     PIN_AFIO_AF(GPIOG_PIN11, 0) |          \
                                     PIN_AFIO_AF(GPIOG_PIN12, 0) |          \
                                     PIN_AFIO_AF(GPIOG_PIN13, 0) |          \
                                     PIN_AFIO_AF(GPIOG_PIN14, 0) |          \
                                     PIN_AFIO_AF(GPIOG_PIN15, 0))

/*
 * GPIOH setup:
 *
 * PH0  - PIN0                      (input pullup).
 * PH1  - PIN1                      (input pullup).
 * PH2  - PIN2                      (input pullup).
 * PH3  - PIN3                      (input pullup).
 * PH4  - PIN4                      (input pullup).
 * PH5  - PIN5                      (input pullup).
 * PH6  - PIN6                      (input pullup).
 * PH7  - PIN7                      (input pullup).
 * PH8  - PIN8                      (input pullup).
 * PH9  - PIN9                      (input pullup).
 * PH10 - PIN10                     (input pullup).
 * PH11 - PIN11                     (input pullup).
 * PH12 - PIN12                     (input pullup).
 * PH13 - PIN13                     (input pullup).
 * PH14 - PIN14                     (input pullup).
 * PH15 - PIN15                     (input pullup).
 */
#define VAL_GPIOH_MODER             (PIN_MODE_INPUT(GPIOH_PIN0) |           \
                                     PIN_MODE_INPUT(GPIOH_PIN1) |           \
                                     PIN_MODE_INPUT(GPIOH_PIN2) |           \
                                     PIN_MODE_INPUT(GPIOH_PIN3) |           \
                                     PIN_MODE_INPUT(GPIOH_PIN4) |           \
                                     PIN_MODE_INPUT(GPIOH_PIN5) |           \
                                     PIN_MODE_INPUT(GPIOH_PIN6) |           \
                                     PIN_MODE_INPUT(GPIOH_PIN7) |           \
                                     PIN_MODE_INPUT(GPIOH_PIN8) |           \
                                     PIN_MODE_INPUT(GPIOH_PIN9) |           \
                                     PIN_MODE_INPUT(GPIOH_PIN10) |          \
                                     PIN_MODE_INPUT(GPIOH_PIN11) |          \
                                     PIN_MODE_INPUT(GPIOH_PIN12) |          \
                                     PIN_MODE_INPUT(GPIOH_PIN13) |          \
                                     PIN_MODE_INPUT(GPIOH_PIN14) |          \
                                     PIN_MODE_INPUT(GPIOH_PIN15))
#define VAL_GPIOH_OTYPER            (PIN_OTYPE_PUSHPULL(GPIOH_PIN0) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN1) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN2) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN3) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN4) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN5) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN6) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN7) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN8) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN9) |       \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN10) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN11) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN12) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN13) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN14) |      \
                                     PIN_OTYPE_PUSHPULL(GPIOH_PIN15))
#define VAL_GPIOH_OSPEEDR           (PIN_OSPEED_VERYLOW(GPIOH_PIN0) |       \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN1) |       \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN2) |       \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN3) |       \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN4) |       \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN5) |       \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN6) |       \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN7) |       \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN8) |       \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN9) |       \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN10) |      \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN11) |      \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN12) |      \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN13) |      \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN14) |      \
                                     PIN_OSPEED_VERYLOW(GPIOH_PIN15))
#define VAL_GPIOH_PUPDR             (PIN_PUPDR_PULLUP(GPIOH_PIN0) |         \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN1) |         \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN2) |         \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN3) |         \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN4) |         \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN5) |         \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN6) |         \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN7) |         \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN8) |         \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN9) |         \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN10) |        \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN11) |        \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN12) |        \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN13) |        \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN14) |        \
                                     PIN_PUPDR_PULLUP(GPIOH_PIN15))
#define VAL_GPIOH_ODR               (PIN_ODR_HIGH(GPIOH_PIN0) |             \
                                     PIN_ODR_HIGH(GPIOH_PIN1) |             \
                                     PIN_ODR_HIGH(GPIOH_PIN2) |             \
                                     PIN_ODR_HIGH(GPIOH_PIN3) |             \
                                     PIN_ODR_HIGH(GPIOH_PIN4) |             \
                                     PIN_ODR_HIGH(GPIOH_PIN5) |             \
                                     PIN_ODR_HIGH(GPIOH_PIN6) |             \
                                     PIN_ODR_HIGH(GPIOH_PIN7) |             \
                                     PIN_ODR_HIGH(GPIOH_PIN8) |             \
                                     PIN_ODR_HIGH(GPIOH_PIN9) |             \
                                     PIN_ODR_HIGH(GPIOH_PIN10) |            \
                                     PIN_ODR_HIGH(GPIOH_PIN11) |            \
                                     PIN_ODR_HIGH(GPIOH_PIN12) |            \
                                     PIN_ODR_HIGH(GPIOH_PIN13) |            \
                                     PIN_ODR_HIGH(GPIOH_PIN14) |            \
                                     PIN_ODR_HIGH(GPIOH_PIN15))
#define VAL_GPIOH_AFRL              (PIN_AFIO_AF(GPIOH_PIN0, 0) |           \
                                     PIN_AFIO_AF(GPIOH_PIN1, 0) |           \
                                     PIN_AFIO_AF(GPIOH_PIN2, 0) |           \
                                     PIN_AFIO_AF(GPIOH_PIN3, 0) |           \
                                     PIN_AFIO_AF(GPIOH_PIN4, 0) |           \
                                     PIN_AFIO_AF(GPIOH_PIN5, 0) |           \
                                     PIN_AFIO_AF(GPIOH_PIN6, 0) |           \
                                     PIN_AFIO_AF(GPIOH_PIN7, 0))
#define VAL_GPIOH_AFRH              (PIN_AFIO_AF(GPIOH_PIN8, 0) |           \
                                     PIN_AFIO_AF(GPIOH_PIN9, 0) |           \
                                     PIN_AFIO_AF(GPIOH_PIN10, 0) |          \
                                     PIN_AFIO_AF(GPIOH_PIN11, 0) |          \
                                     PIN_AFIO_AF(GPIOH_PIN12, 0) |          \
                                     PIN_AFIO_AF(GPIOH_PIN13, 0) |          \
                                     PIN_AFIO_AF(GPIOH_PIN14, 0) |          \
                                     PIN_AFIO_AF(GPIOH_PIN15, 0))


/*
 * USB bus activation macro, required by the USB driver.
 */
// #define usb_lld_connect_bus(usbp)
#define usb_lld_connect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14)))
// #define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT)
/*
 * USB bus de-activation macro, required by the USB driver.
 */
// #define usb_lld_disconnect_bus(usbp)
#define usb_lld_disconnect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL)); palClearPad(GPIOA, GPIOA_USB_DP)
// #define usb_lld_disconnect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 12)

#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
  void boardInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */

#endif /* _BOARD_H_ */

A keyboards/nk65/boards/GENERIC_STM32_F303XC/board.mk => keyboards/nk65/boards/GENERIC_STM32_F303XC/board.mk +5 -0
@@ 0,0 1,5 @@
# List of all the board related files.
BOARDSRC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC/board.c

# Required include directories
BOARDINC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC

A keyboards/nk65/bootloader_defs.h => keyboards/nk65/bootloader_defs.h +7 -0
@@ 0,0 1,7 @@
/* Address for jumping to bootloader on STM32 chips. */
/* It is chip dependent, the correct number can be looked up here:
 * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
 * This also requires a patch to chibios:
 *  <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
 */
#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800

A keyboards/nk65/chconf.h => keyboards/nk65/chconf.h +520 -0
@@ 0,0 1,520 @@
/*
    ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

/**
 * @file    templates/chconf.h
 * @brief   Configuration file template.
 * @details A copy of this file must be placed in each project directory, it
 *          contains the application specific kernel settings.
 *
 * @addtogroup config
 * @details Kernel related settings and hooks.
 * @{
 */

#ifndef CHCONF_H
#define CHCONF_H

#define _CHIBIOS_RT_CONF_

/*===========================================================================*/
/**
 * @name System timers settings
 * @{
 */
/*===========================================================================*/

/**
 * @brief   System time counter resolution.
 * @note    Allowed values are 16 or 32 bits.
 */
#define CH_CFG_ST_RESOLUTION                32

/**
 * @brief   System tick frequency.
 * @details Frequency of the system timer that drives the system ticks. This
 *          setting also defines the system tick time unit.
 */
#define CH_CFG_ST_FREQUENCY                 100000

/**
 * @brief   Time delta constant for the tick-less mode.
 * @note    If this value is zero then the system uses the classic
 *          periodic tick. This value represents the minimum number
 *          of ticks that is safe to specify in a timeout directive.
 *          The value one is not valid, timeouts are rounded up to
 *          this value.
 */
#define CH_CFG_ST_TIMEDELTA                 2

/** @} */

/*===========================================================================*/
/**
 * @name Kernel parameters and options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Round robin interval.
 * @details This constant is the number of system ticks allowed for the
 *          threads before preemption occurs. Setting this value to zero
 *          disables the preemption for threads with equal priority and the
 *          round robin becomes cooperative. Note that higher priority
 *          threads can still preempt, the kernel is always preemptive.
 * @note    Disabling the round robin preemption makes the kernel more compact
 *          and generally faster.
 * @note    The round robin preemption is not supported in tickless mode and
 *          must be set to zero in that case.
 */
#define CH_CFG_TIME_QUANTUM                 0

/**
 * @brief   Managed RAM size.
 * @details Size of the RAM area to be managed by the OS. If set to zero
 *          then the whole available RAM is used. The core memory is made
 *          available to the heap allocator and/or can be used directly through
 *          the simplified core memory allocator.
 *
 * @note    In order to let the OS manage the whole RAM the linker script must
 *          provide the @p __heap_base__ and @p __heap_end__ symbols.
 * @note    Requires @p CH_CFG_USE_MEMCORE.
 */
#define CH_CFG_MEMCORE_SIZE                 0

/**
 * @brief   Idle thread automatic spawn suppression.
 * @details When this option is activated the function @p chSysInit()
 *          does not spawn the idle thread. The application @p main()
 *          function becomes the idle thread and must implement an
 *          infinite loop.
 */
#define CH_CFG_NO_IDLE_THREAD               FALSE

/** @} */

/*===========================================================================*/
/**
 * @name Performance options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   OS optimization.
 * @details If enabled then time efficient rather than space efficient code
 *          is used when two possible implementations exist.
 *
 * @note    This is not related to the compiler optimization options.
 * @note    The default is @p TRUE.
 */
#define CH_CFG_OPTIMIZE_SPEED               TRUE

/** @} */

/*===========================================================================*/
/**
 * @name Subsystem options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Time Measurement APIs.
 * @details If enabled then the time measurement APIs are included in
 *          the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_TM                       TRUE

/**
 * @brief   Threads registry APIs.
 * @details If enabled then the registry APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_REGISTRY                 TRUE

/**
 * @brief   Threads synchronization APIs.
 * @details If enabled then the @p chThdWait() function is included in
 *          the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_WAITEXIT                 TRUE

/**
 * @brief   Semaphores APIs.
 * @details If enabled then the Semaphores APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_SEMAPHORES               TRUE

/**
 * @brief   Semaphores queuing mode.
 * @details If enabled then the threads are enqueued on semaphores by
 *          priority rather than in FIFO order.
 *
 * @note    The default is @p FALSE. Enable this if you have special
 *          requirements.
 * @note    Requires @p CH_CFG_USE_SEMAPHORES.
 */
#define CH_CFG_USE_SEMAPHORES_PRIORITY      FALSE

/**
 * @brief   Mutexes APIs.
 * @details If enabled then the mutexes APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_MUTEXES                  TRUE

/**
 * @brief   Enables recursive behavior on mutexes.
 * @note    Recursive mutexes are heavier and have an increased
 *          memory footprint.
 *
 * @note    The default is @p FALSE.
 * @note    Requires @p CH_CFG_USE_MUTEXES.
 */
#define CH_CFG_USE_MUTEXES_RECURSIVE        FALSE

/**
 * @brief   Conditional Variables APIs.
 * @details If enabled then the conditional variables APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_MUTEXES.
 */
#define CH_CFG_USE_CONDVARS                 TRUE

/**
 * @brief   Conditional Variables APIs with timeout.
 * @details If enabled then the conditional variables APIs with timeout
 *          specification are included in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_CONDVARS.
 */
#define CH_CFG_USE_CONDVARS_TIMEOUT         TRUE

/**
 * @brief   Events Flags APIs.
 * @details If enabled then the event flags APIs are included in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_EVENTS                   TRUE

/**
 * @brief   Events Flags APIs with timeout.
 * @details If enabled then the events APIs with timeout specification
 *          are included in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_EVENTS.
 */
#define CH_CFG_USE_EVENTS_TIMEOUT           TRUE

/**
 * @brief   Synchronous Messages APIs.
 * @details If enabled then the synchronous messages APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_MESSAGES                 TRUE

/**
 * @brief   Synchronous Messages queuing mode.
 * @details If enabled then messages are served by priority rather than in
 *          FIFO order.
 *
 * @note    The default is @p FALSE. Enable this if you have special
 *          requirements.
 * @note    Requires @p CH_CFG_USE_MESSAGES.
 */
#define CH_CFG_USE_MESSAGES_PRIORITY        TRUE

/**
 * @brief   Mailboxes APIs.
 * @details If enabled then the asynchronous messages (mailboxes) APIs are
 *          included in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_SEMAPHORES.
 */
#define CH_CFG_USE_MAILBOXES                TRUE

/**
 * @brief   Core Memory Manager APIs.
 * @details If enabled then the core memory manager APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_MEMCORE                  TRUE

/**
 * @brief   Heap Allocator APIs.
 * @details If enabled then the memory heap allocator APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
 *          @p CH_CFG_USE_SEMAPHORES.
 * @note    Mutexes are recommended.
 */
#define CH_CFG_USE_HEAP                     TRUE

/**
 * @brief   Memory Pools Allocator APIs.
 * @details If enabled then the memory pools allocator APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 */
#define CH_CFG_USE_MEMPOOLS                 TRUE

/**
 * @brief   Dynamic Threads APIs.
 * @details If enabled then the dynamic threads creation APIs are included
 *          in the kernel.
 *
 * @note    The default is @p TRUE.
 * @note    Requires @p CH_CFG_USE_WAITEXIT.
 * @note    Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
 */
#define CH_CFG_USE_DYNAMIC                  TRUE

/** @} */

/*===========================================================================*/
/**
 * @name Debug options
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Debug option, kernel statistics.
 *
 * @note    The default is @p FALSE.
 */
#define CH_DBG_STATISTICS                   FALSE

/**
 * @brief   Debug option, system state check.
 * @details If enabled the correct call protocol for system APIs is checked
 *          at runtime.
 *
 * @note    The default is @p FALSE.
 */
#define CH_DBG_SYSTEM_STATE_CHECK           FALSE

/**
 * @brief   Debug option, parameters checks.
 * @details If enabled then the checks on the API functions input
 *          parameters are activated.
 *
 * @note    The default is @p FALSE.
 */
#define CH_DBG_ENABLE_CHECKS                FALSE

/**
 * @brief   Debug option, consistency checks.
 * @details If enabled then all the assertions in the kernel code are
 *          activated. This includes consistency checks inside the kernel,
 *          runtime anomalies and port-defined checks.
 *
 * @note    The default is @p FALSE.
 */
#define CH_DBG_ENABLE_ASSERTS               FALSE

/**
 * @brief   Debug option, trace buffer.
 * @details If enabled then the trace buffer is activated.
 *
 * @note    The default is @p CH_DBG_TRACE_MASK_DISABLED.
 */
#define CH_DBG_TRACE_MASK                   CH_DBG_TRACE_MASK_DISABLED

/**
 * @brief   Trace buffer entries.
 * @note    The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
 *          different from @p CH_DBG_TRACE_MASK_DISABLED.
 */
#define CH_DBG_TRACE_BUFFER_SIZE            128

/**
 * @brief   Debug option, stack checks.
 * @details If enabled then a runtime stack check is performed.
 *
 * @note    The default is @p FALSE.
 * @note    The stack check is performed in a architecture/port dependent way.
 *          It may not be implemented or some ports.
 * @note    The default failure mode is to halt the system with the global
 *          @p panic_msg variable set to @p NULL.
 */
#define CH_DBG_ENABLE_STACK_CHECK           TRUE

/**
 * @brief   Debug option, stacks initialization.
 * @details If enabled then the threads working area is filled with a byte
 *          value when a thread is created. This can be useful for the
 *          runtime measurement of the used stack.
 *
 * @note    The default is @p FALSE.
 */
#define CH_DBG_FILL_THREADS                 FALSE

/**
 * @brief   Debug option, threads profiling.
 * @details If enabled then a field is added to the @p thread_t structure that
 *          counts the system ticks occurred while executing the thread.
 *
 * @note    The default is @p FALSE.
 * @note    This debug option is not currently compatible with the
 *          tickless mode.
 */
#define CH_DBG_THREADS_PROFILING            FALSE

/** @} */

/*===========================================================================*/
/**
 * @name Kernel hooks
 * @{
 */
/*===========================================================================*/

/**
 * @brief   Threads descriptor structure extension.
 * @details User fields added to the end of the @p thread_t structure.
 */
#define CH_CFG_THREAD_EXTRA_FIELDS                                          \
  /* Add threads custom fields here.*/

/**
 * @brief   Threads initialization hook.
 * @details User initialization code added to the @p chThdInit() API.
 *
 * @note    It is invoked from within @p chThdInit() and implicitly from all
 *          the threads creation APIs.
 */
#define CH_CFG_THREAD_INIT_HOOK(tp) {                                       \
  /* Add threads initialization code here.*/                                \
}

/**
 * @brief   Threads finalization hook.
 * @details User finalization code added to the @p chThdExit() API.
 */
#define CH_CFG_THREAD_EXIT_HOOK(tp) {                                       \
  /* Add threads finalization code here.*/                                  \
}

/**
 * @brief   Context switch hook.
 * @details This hook is invoked just before switching between threads.
 */
#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) {                              \
  /* Context switch code here.*/                                            \
}

/**
 * @brief   ISR enter hook.
 */
#define CH_CFG_IRQ_PROLOGUE_HOOK() {                                        \
  /* IRQ prologue code here.*/                                              \
}

/**
 * @brief   ISR exit hook.
 */
#define CH_CFG_IRQ_EPILOGUE_HOOK() {                                        \
  /* IRQ epilogue code here.*/                                              \
}

/**
 * @brief   Idle thread enter hook.
 * @note    This hook is invoked within a critical zone, no OS functions
 *          should be invoked from here.
 * @note    This macro can be used to activate a power saving mode.
 */
#define CH_CFG_IDLE_ENTER_HOOK() {                                          \
  /* Idle-enter code here.*/                                                \
}

/**
 * @brief   Idle thread leave hook.
 * @note    This hook is invoked within a critical zone, no OS functions
 *          should be invoked from here.
 * @note    This macro can be used to deactivate a power saving mode.
 */
#define CH_CFG_IDLE_LEAVE_HOOK() {                                          \
  /* Idle-leave code here.*/                                                \
}

/**
 * @brief   Idle Loop hook.
 * @details This hook is continuously invoked by the idle thread loop.
 */
#define CH_CFG_IDLE_LOOP_HOOK() {                                           \
  /* Idle loop code here.*/                                                 \
}

/**
 * @brief   System tick event hook.
 * @details This hook is invoked in the system tick handler immediately
 *          after processing the virtual timers queue.
 */
#define CH_CFG_SYSTEM_TICK_HOOK() {                                         \
  /* System tick event code here.*/                                         \
}

/**
 * @brief   System halt hook.
 * @details This hook is invoked in case to a system halting error before
 *          the system is halted.
 */
#define CH_CFG_SYSTEM_HALT_HOOK(reason) {                                   \
  /* System halt code here.*/                                               \
}

/**
 * @brief   Trace hook.
 * @details This hook is invoked each time a new record is written in the
 *          trace buffer.
 */
#define CH_CFG_TRACE_HOOK(tep) {                                            \
  /* Trace code here.*/                                                     \
}

/** @} */

/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h).    */
/*===========================================================================*/

#endif  /* CHCONF_H */

/** @} */

A keyboards/nk65/config.h => keyboards/nk65/config.h +154 -0
@@ 0,0 1,154 @@
/*
Copyright 2019 Yiancar

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 <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "config_common.h"

/* USB Device descriptor parameter */
#define VENDOR_ID       0x8968
#define PRODUCT_ID      0x4E4B
#define DEVICE_VER      0x0001
#define MANUFACTURER    Yiancar-Designs
#define PRODUCT         NK65
#define DESCRIPTION     A 65-percent, tool-free RGB keyboard

/* key matrix size */
#define MATRIX_ROWS 5
#define MATRIX_COLS 15

#define MATRIX_ROW_PINS { B3, B4, B5, A8, A4 }
#define MATRIX_COL_PINS { A13, A10, A9, A14, A15, B8, B9, C13, C14, C15, A0, A1, A2, A3, A5 }
// To enable debugger set A13 A14 -> A5 A7

/* COL2ROW, ROW2COL*/
#define DIODE_DIRECTION COL2ROW

/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCING_DELAY 5

/* define if matrix has ghost (lacks anti-ghosting diodes) */
//#define MATRIX_HAS_GHOST

/* If defined, GRAVE_ESC will always act as ESC when CTRL is held.
 * This is userful for the Windows task manager shortcut (ctrl+shift+esc).
 */
// #define GRAVE_ESC_CTRL_OVERRIDE

/*
 * Force NKRO
 *
 * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
 * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
 * makefile for this to work.)
 *
 * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
 * until the next keyboard reset.
 *
 * NKRO may prevent your keystrokes from being detected in the BIOS, but it is
 * fully operational during normal computer usage.
 *
 * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
 * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
 * bootmagic, NKRO mode will always be enabled until it is toggled again during a
 * power-up.
 *
 */
//#define FORCE_NKRO

/*
 * Magic Key Options
 *
 * Magic keys are hotkey commands that allow control over firmware functions of
 * the keyboard. They are best used in combination with the HID Listen program,
 * found here: https://www.pjrc.com/teensy/hid_listen.html
 *
 * The options below allow the magic key functionality to be changed. This is
 * useful if your keyboard/keypad is missing keys and you want magic key support.
 *
 */

/* Backlight options */

#define RGB_BACKLIGHT_ENABLED 1

#define RGB_BACKLIGHT_NK65

// they aren't really used if RGB_BACKLIGHT_HS60 defined
#define RGB_BACKLIGHT_USE_SPLIT_BACKSPACE 0
#define RGB_BACKLIGHT_USE_SPLIT_LEFT_SHIFT 0
#define RGB_BACKLIGHT_USE_SPLIT_RIGHT_SHIFT 0
#define RGB_BACKLIGHT_USE_7U_SPACEBAR 0
#define RGB_BACKLIGHT_USE_ISO_ENTER 0
#define RGB_BACKLIGHT_DISABLE_HHKB_BLOCKER_LEDS 0

// disable backlight when USB suspended (PC sleep/hibernate/shutdown)
#define RGB_BACKLIGHT_DISABLE_WHEN_USB_SUSPENDED 0

// disable backlight after timeout in minutes, 0 = no timeout
#define RGB_BACKLIGHT_DISABLE_AFTER_TIMEOUT 0

// the default brightness
#define RGB_BACKLIGHT_BRIGHTNESS 255

// the default effect (RGB test)
#define RGB_BACKLIGHT_EFFECT 255

// the default effect speed (0-3)
#define RGB_BACKLIGHT_EFFECT_SPEED 0

// the default color1 and color2
#define RGB_BACKLIGHT_COLOR_1 { .h = 0, .s = 255 }
#define RGB_BACKLIGHT_COLOR_2 { .h = 127, .s = 255 }

#define DRIVER_COUNT 2
#define DRIVER_LED_TOTAL 128

// These define which keys in the matrix are alphas/mods
// Used for backlight effects so colors are different for
// alphas vs. mods
// Each value is for a row, bit 0 is column 0
// Alpha=0 Mod=1
#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_0 0b0110000000000001
#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_1 0b0100000000000001
#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_2 0b0110000000000001
#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_3 0b0111000000000001
#define RGB_BACKLIGHT_ALPHAS_MODS_ROW_4 0b0111111000000111

#define RGB_BACKLIGHT_CAPS_LOCK_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_1_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_2_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }
#define RGB_BACKLIGHT_LAYER_3_INDICATOR { .color = { .h = 0, .s = 0 }, .index = 255 }

// TODO: refactor with new user EEPROM code (coming soon)
#define EEPROM_MAGIC 0x451F
#define EEPROM_MAGIC_ADDR 32
// Bump this every time we change what we store
// This will automatically reset the EEPROM with defaults
// and avoid loading invalid data from the EEPROM
#define EEPROM_VERSION 0x08
#define EEPROM_VERSION_ADDR 34

// Backlight config starts after EEPROM version
#define RGB_BACKLIGHT_CONFIG_EEPROM_ADDR 35
// Dynamic keymap starts after backlight config (35+32)
#define DYNAMIC_KEYMAP_EEPROM_ADDR 67
#define DYNAMIC_KEYMAP_LAYER_COUNT 4
// Dynamic macro starts after dynamic keymaps (67+(4*5*15*2)) = (67+600)
#define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR 667
#define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE 398
#define DYNAMIC_KEYMAP_MACRO_COUNT 16

A keyboards/nk65/halconf.h => keyboards/nk65/halconf.h +388 -0
@@ 0,0 1,388 @@
/*
    ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

/**
 * @file    templates/halconf.h
 * @brief   HAL configuration header.
 * @details HAL configuration file, this file allows to enable or disable the
 *          various device drivers from your application. You may also use
 *          this file in order to override the device drivers default settings.
 *
 * @addtogroup HAL_CONF
 * @{
 */

#ifndef HALCONF_H
#define HALCONF_H

#include "mcuconf.h"

/**
 * @brief   Enables the PAL subsystem.
 */
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
#define HAL_USE_PAL                 TRUE
#endif

/**
 * @brief   Enables the ADC subsystem.
 */
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
#define HAL_USE_ADC                 FALSE
#endif

/**
 * @brief   Enables the CAN subsystem.
 */
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
#define HAL_USE_CAN                 FALSE
#endif

/**
 * @brief   Enables the DAC subsystem.
 */
#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
#define HAL_USE_DAC                 TRUE
#endif

/**
 * @brief   Enables the EXT subsystem.
 */
#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
#define HAL_USE_EXT                 FALSE
#endif

/**
 * @brief   Enables the GPT subsystem.
 */
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
#define HAL_USE_GPT                 TRUE
#endif

/**
 * @brief   Enables the I2C subsystem.
 */
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
#define HAL_USE_I2C                 TRUE
#endif

/**
 * @brief   Enables the I2S subsystem.
 */
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
#define HAL_USE_I2S                 FALSE
#endif

/**
 * @brief   Enables the ICU subsystem.
 */
#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
#define HAL_USE_ICU                 FALSE
#endif

/**
 * @brief   Enables the MAC subsystem.
 */
#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
#define HAL_USE_MAC                 FALSE
#endif

/**
 * @brief   Enables the MMC_SPI subsystem.
 */
#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
#define HAL_USE_MMC_SPI             FALSE
#endif

/**
 * @brief   Enables the PWM subsystem.
 */
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
#define HAL_USE_PWM                 FALSE
#endif

/**
 * @brief   Enables the QSPI subsystem.
 */
#if !defined(HAL_USE_QSPI) || defined(__DOXYGEN__)
#define HAL_USE_QSPI                FALSE
#endif

/**
 * @brief   Enables the RTC subsystem.
 */
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC                 FALSE
#endif

/**
 * @brief   Enables the SDC subsystem.
 */
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
#define HAL_USE_SDC                 FALSE
#endif

/**
 * @brief   Enables the SERIAL subsystem.
 */
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL              FALSE
#endif

/**
 * @brief   Enables the SERIAL over USB subsystem.
 */
#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL_USB          TRUE
#endif

/**
 * @brief   Enables the SPI subsystem.
 */
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
#define HAL_USE_SPI                 FALSE
#endif

/**
 * @brief   Enables the UART subsystem.
 */
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
#define HAL_USE_UART                FALSE
#endif

/**
 * @brief   Enables the USB subsystem.
 */
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
#define HAL_USE_USB                 TRUE
#endif

/**
 * @brief   Enables the WDG subsystem.
 */
#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
#define HAL_USE_WDG                 FALSE
#endif

/*===========================================================================*/
/* ADC driver related settings.                                              */
/*===========================================================================*/

/**
 * @brief   Enables synchronous APIs.
 * @note    Disabling this option saves both code and data space.
 */
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
#define ADC_USE_WAIT                TRUE
#endif

/**
 * @brief   Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
 * @note    Disabling this option saves both code and data space.
 */
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define ADC_USE_MUTUAL_EXCLUSION    TRUE
#endif

/*===========================================================================*/
/* CAN driver related settings.                                              */
/*===========================================================================*/

/**
 * @brief   Sleep mode related APIs inclusion switch.
 */
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
#define CAN_USE_SLEEP_MODE          TRUE
#endif

/*===========================================================================*/
/* I2C driver related settings.                                              */
/*===========================================================================*/

/**
 * @brief   Enables the mutual exclusion APIs on the I2C bus.
 */
#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define I2C_USE_MUTUAL_EXCLUSION    TRUE
#endif

/*===========================================================================*/
/* MAC driver related settings.                                              */
/*===========================================================================*/

/**
 * @brief   Enables an event sources for incoming packets.
 */
#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
#define MAC_USE_ZERO_COPY           FALSE
#endif

/**
 * @brief   Enables an event sources for incoming packets.
 */
#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
#define MAC_USE_EVENTS              TRUE
#endif

/*===========================================================================*/
/* MMC_SPI driver related settings.                                          */
/*===========================================================================*/

/**
 * @brief   Delays insertions.
 * @details If enabled this options inserts delays into the MMC waiting
 *          routines releasing some extra CPU time for the threads with
 *          lower priority, this may slow down the driver a bit however.
 *          This option is recommended also if the SPI driver does not
 *          use a DMA channel and heavily loads the CPU.
 */
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
#define MMC_NICE_WAITING            TRUE
#endif

/*===========================================================================*/
/* SDC driver related settings.                                              */
/*===========================================================================*/

/**
 * @brief   Number of initialization attempts before rejecting the card.
 * @note    Attempts are performed at 10mS intervals.
 */
#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
#define SDC_INIT_RETRY              100
#endif

/**
 * @brief   Include support for MMC cards.
 * @note    MMC support is not yet implemented so this option must be kept
 *          at @p FALSE.
 */
#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
#define SDC_MMC_SUPPORT             FALSE
#endif

/**
 * @brief   Delays insertions.
 * @details If enabled this options inserts delays into the MMC waiting
 *          routines releasing some extra CPU time for the threads with
 *          lower priority, this may slow down the driver a bit however.
 */
#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
#define SDC_NICE_WAITING            TRUE
#endif

/*===========================================================================*/
/* SERIAL driver related settings.                                           */
/*===========================================================================*/

/**
 * @brief   Default bit rate.
 * @details Configuration parameter, this is the baud rate selected for the
 *          default configuration.
 */
#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
#define SERIAL_DEFAULT_BITRATE      38400
#endif

/**
 * @brief   Serial buffers size.
 * @details Configuration parameter, you can change the depth of the queue
 *          buffers depending on the requirements of your application.
 * @note    The default is 16 bytes for both the transmission and receive
 *          buffers.
 */
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE         16
#endif

/*===========================================================================*/
/* SERIAL_USB driver related setting.                                        */
/*===========================================================================*/

/**
 * @brief   Serial over USB buffers size.
 * @details Configuration parameter, the buffer size must be a multiple of
 *          the USB data endpoint maximum packet size.
 * @note    The default is 256 bytes for both the transmission and receive
 *          buffers.
 */
#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_SIZE     1
#endif

/**
 * @brief   Serial over USB number of buffers.
 * @note    The default is 2 buffers.
 */
#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_NUMBER   2
#endif

/*===========================================================================*/
/* SPI driver related settings.                                              */
/*===========================================================================*/

/**
 * @brief   Enables synchronous APIs.
 * @note    Disabling this option saves both code and data space.
 */
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
#define SPI_USE_WAIT                TRUE
#endif

/**
 * @brief   Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
 * @note    Disabling this option saves both code and data space.
 */
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define SPI_USE_MUTUAL_EXCLUSION    TRUE
#endif

/*===========================================================================*/
/* UART driver related settings.                                             */
/*===========================================================================*/

/**
 * @brief   Enables synchronous APIs.
 * @note    Disabling this option saves both code and data space.
 */
#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
#define UART_USE_WAIT               FALSE
#endif

/**
 * @brief   Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
 * @note    Disabling this option saves both code and data space.
 */
#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define UART_USE_MUTUAL_EXCLUSION   FALSE
#endif

/*===========================================================================*/
/* USB driver related settings.                                              */
/*===========================================================================*/

/**
 * @brief   Enables synchronous APIs.
 * @note    Disabling this option saves both code and data space.
 */
#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
#define USB_USE_WAIT                TRUE
#endif

#endif /* HALCONF_H */

/** @} */

A keyboards/nk65/info.json => keyboards/nk65/info.json +12 -0
@@ 0,0 1,12 @@
{
    "keyboard_name": "NK65", 
    "url": "", 
    "maintainer": "yiancar", 
    "width": 16, 
    "height": 5, 
    "layouts": {
        "LAYOUT": {
            "layout": [{"label":"Esc", "x":0, "y":0}, {"label":"!", "x":1, "y":0}, {"label":"@", "x":2, "y":0}, {"label":"#", "x":3, "y":0}, {"label":"$", "x":4, "y":0}, {"label":"%", "x":5, "y":0}, {"label":"^", "x":6, "y":0}, {"label":"&", "x":7, "y":0}, {"label":"*", "x":8, "y":0}, {"label":"(", "x":9, "y":0}, {"label":")", "x":10, "y":0}, {"label":"_", "x":11, "y":0}, {"label":"+", "x":12, "y":0}, {"label":"Backspace", "x":13, "y":0, "w":2}, {"label":"Home", "x":15, "y":0}, {"label":"Tab", "x":0, "y":1, "w":1.5}, {"label":"Q", "x":1.5, "y":1}, {"label":"W", "x":2.5, "y":1}, {"label":"E", "x":3.5, "y":1}, {"label":"R", "x":4.5, "y":1}, {"label":"T", "x":5.5, "y":1}, {"label":"Y", "x":6.5, "y":1}, {"label":"U", "x":7.5, "y":1}, {"label":"I", "x":8.5, "y":1}, {"label":"O", "x":9.5, "y":1}, {"label":"P", "x":10.5, "y":1}, {"label":"{", "x":11.5, "y":1}, {"label":"}", "x":12.5, "y":1}, {"label":"|", "x":13.5, "y":1, "w":1.5}, {"label":"Page Up", "x":15, "y":1}, {"label":"Caps Lock", "x":0, "y":2, "w":1.75}, {"label":"A", "x":1.75, "y":2}, {"label":"S", "x":2.75, "y":2}, {"label":"D", "x":3.75, "y":2}, {"label":"F", "x":4.75, "y":2}, {"label":"G", "x":5.75, "y":2}, {"label":"H", "x":6.75, "y":2}, {"label":"J", "x":7.75, "y":2}, {"label":"K", "x":8.75, "y":2}, {"label":"L", "x":9.75, "y":2}, {"label":":", "x":10.75, "y":2}, {"label":"\"", "x":11.75, "y":2}, {"label":"Enter", "x":12.75, "y":2, "w":2.25}, {"label":"Page Down", "x":15, "y":2}, {"label":"Shift", "x":0, "y":3, "w":2.25}, {"label":"Z", "x":2.25, "y":3}, {"label":"X", "x":3.25, "y":3}, {"label":"C", "x":4.25, "y":3}, {"label":"V", "x":5.25, "y":3}, {"label":"B", "x":6.25, "y":3}, {"label":"N", "x":7.25, "y":3}, {"label":"M", "x":8.25, "y":3}, {"label":"<", "x":9.25, "y":3}, {"label":">", "x":10.25, "y":3}, {"label":"?", "x":11.25, "y":3}, {"label":"Shift", "x":12.25, "y":3, "w":1.75}, {"label":"\u2191", "x":14, "y":3}, {"label":"End", "x":15, "y":3}, {"label":"Ctrl", "x":0, "y":4, "w":1.25}, {"label":"Win", "x":1.25, "y":4, "w":1.25}, {"label":"Alt", "x":2.5, "y":4, "w":1.25}, {"x":3.75, "y":4, "w":6.25}, {"label":"Alt", "x":10, "y":4}, {"label":"Fn", "x":11, "y":4}, {"label":"Ctrl", "x":12, "y":4}, {"label":"\u2190", "x":13, "y":4}, {"label":"\u2193", "x":14, "y":4}, {"label":"\u2192", "x":15, "y":4}]
        }
    }
}
\ No newline at end of file

A keyboards/nk65/keymaps/default/keymap.c => keyboards/nk65/keymaps/default/keymap.c +58 -0
@@ 0,0 1,58 @@
/* Copyright 2019 Yiancar
 *
 * 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 <http://www.gnu.org/licenses/>.
 */
#include QMK_KEYBOARD_H

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_65_ansi( /* Base */
    KC_GESC, KC_1,    KC_2,   KC_3,   KC_4,   KC_5,   KC_6,   KC_7,   KC_8,    KC_9,    KC_0,    KC_MINS, KC_EQL,  KC_BSPC, KC_HOME,\
    KC_TAB,  KC_Q,    KC_W,   KC_E,   KC_R,   KC_T,   KC_Y,   KC_U,   KC_I,    KC_O,    KC_P,    KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,\
    KC_CAPS, KC_A,    KC_S,   KC_D,   KC_F,   KC_G,   KC_H,   KC_J,   KC_K,    KC_L,    KC_SCLN, KC_QUOT,          KC_ENT,  KC_PGDN,\
    KC_LSFT, KC_Z,    KC_X,   KC_C,   KC_V,   KC_B,   KC_N,   KC_M,   KC_COMM, KC_DOT,  KC_SLSH, KC_RSFT,          KC_UP,   KC_END, \
    KC_LCTL, KC_LGUI, KC_LALT,                KC_SPC,                          KC_RALT, MO(1),   KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),

[1] = LAYOUT_65_ansi( /* FN */
    KC_GRV,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  KC_DEL,  KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET,   KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, S1_DEC,  S1_INC,  S2_DEC,  S2_INC,  KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_TRNS, EF_DEC,  EF_INC,  H1_DEC,  H1_INC,  H2_DEC,  H2_INC,  BR_DEC,  BR_INC,  ES_DEC,  ES_INC,  KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_VOLU, KC_VOLD, KC_MUTE,                KC_TRNS,                               KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),

[2] = LAYOUT_65_ansi( /* Empty for dynamic keymaps */
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS,                KC_TRNS,                               KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),

[3] = LAYOUT_65_ansi( /* Empty for dynamic keymaps */
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS,                KC_TRNS,                               KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
};

void matrix_init_user(void) {
  //user initialization
}

void matrix_scan_user(void) {
  //user matrix
}

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  return true;
}
\ No newline at end of file

A keyboards/nk65/keymaps/default/readme.md => keyboards/nk65/keymaps/default/readme.md +6 -0
@@ 0,0 1,6 @@
The default keymap for NK65. VIA support disabled.
=========================================================

![Layout image](https://i.imgur.com/DL0CjJO.png)

Default layer is normal ANSI 65%
\ No newline at end of file

A keyboards/nk65/keymaps/default_via/keymap.c => keyboards/nk65/keymaps/default_via/keymap.c +58 -0
@@ 0,0 1,58 @@
/* Copyright 2019 Yiancar
 *
 * 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 <http://www.gnu.org/licenses/>.
 */
#include QMK_KEYBOARD_H

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT_65_ansi( /* Base */
    KC_GESC, KC_1,    KC_2,   KC_3,   KC_4,   KC_5,   KC_6,   KC_7,   KC_8,    KC_9,    KC_0,    KC_MINS, KC_EQL,  KC_BSPC, KC_HOME,\
    KC_TAB,  KC_Q,    KC_W,   KC_E,   KC_R,   KC_T,   KC_Y,   KC_U,   KC_I,    KC_O,    KC_P,    KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,\
    KC_CAPS, KC_A,    KC_S,   KC_D,   KC_F,   KC_G,   KC_H,   KC_J,   KC_K,    KC_L,    KC_SCLN, KC_QUOT,          KC_ENT,  KC_PGDN,\
    KC_LSFT, KC_Z,    KC_X,   KC_C,   KC_V,   KC_B,   KC_N,   KC_M,   KC_COMM, KC_DOT,  KC_SLSH, KC_RSFT,          KC_UP,   KC_END, \
    KC_LCTL, KC_LGUI, KC_LALT,                KC_SPC,                          KC_RALT, MO(1),   KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),

[1] = LAYOUT_65_ansi( /* FN */
    KC_GRV,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  KC_DEL,  KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RESET,   KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, S1_DEC,  S1_INC,  S2_DEC,  S2_INC,  KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_TRNS, EF_DEC,  EF_INC,  H1_DEC,  H1_INC,  H2_DEC,  H2_INC,  BR_DEC,  BR_INC,  ES_DEC,  ES_INC,  KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_VOLU, KC_VOLD, KC_MUTE,                KC_TRNS,                               KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),

[2] = LAYOUT_65_ansi( /* Empty for dynamic keymaps */
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS,                KC_TRNS,                               KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),

[3] = LAYOUT_65_ansi( /* Empty for dynamic keymaps */
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,          KC_TRNS, KC_TRNS,\
    KC_TRNS, KC_TRNS, KC_TRNS,                KC_TRNS,                               KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
};

void matrix_init_user(void) {
  //user initialization
}

void matrix_scan_user(void) {
  //user matrix
}

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  return true;
}
\ No newline at end of file

A keyboards/nk65/keymaps/default_via/readme.md => keyboards/nk65/keymaps/default_via/readme.md +6 -0
@@ 0,0 1,6 @@
The default keymap for NK65. VIA support enabled.
=========================================================

![Layout image](https://i.imgur.com/DL0CjJO.png)

Default layer is normal ANSI 65%
\ No newline at end of file

A keyboards/nk65/keymaps/default_via/rules.mk => keyboards/nk65/keymaps/default_via/rules.mk +67 -0
@@ 0,0 1,67 @@
# project specific files
SRC =	keyboards/zeal60/zeal60.c \
		keyboards/zeal60/rgb_backlight.c \
		drivers/issi/is31fl3733.c \
		quantum/color.c \
		drivers/arm/i2c_master.c

## chip/board settings
#   the next two should match the directories in
#   <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
MCU_FAMILY = STM32
MCU_SERIES = STM32F3xx

# Linker script to use
#   it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
#   or <this_dir>/ld/
MCU_LDSCRIPT = STM32F303xC

# Startup code to use
#  - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
MCU_STARTUP = stm32f3xx

# Board: it should exist either in <chibios>/os/hal/boards/
#  or <this_dir>/boards
BOARD = GENERIC_STM32_F303XC

# Cortex version
MCU  = cortex-m4

# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
ARMV = 7

USE_FPU = yes

# Vector table for application
# 0x00000000-0x00001000 area is occupied by bootlaoder.*/
# The CORTEX_VTOR... is needed only for MCHCK/Infinity KB
# OPT_DEFS = -DCORTEX_VTOR_INIT=0x08005000
OPT_DEFS =

# Do not put the microcontroller into power saving mode
# when we get USB suspend event. We want it to keep updating
# backlight effects.
OPT_DEFS += -DNO_SUSPEND_POWER_DOWN

# Options to pass to dfu-util when flashing
DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave
DFU_SUFFIX_ARGS = -p DF11 -v 0483

# Build Options
#   comment out to disable the options.
#
BACKLIGHT_ENABLE = no              # Enable keyboard backlight functionality
BOOTMAGIC_ENABLE = no              # Virtual DIP switch configuration
MOUSEKEY_ENABLE = yes              # Mouse keys
EXTRAKEY_ENABLE = yes              # Audio control and System control
CONSOLE_ENABLE = no                # Console for debug
COMMAND_ENABLE = no                # Commands for debug and configuration
SLEEP_LED_ENABLE = no              # Breathing sleep LED during USB suspend
NKRO_ENABLE = yes                  # USB Nkey Rollover
AUDIO_ENABLE = no                  # Audio output on port C6
NO_USB_STARTUP_CHECK = no          # Disable initialization only when usb is plugged in
#SERIAL_LINK_ENABLE = yes

RAW_ENABLE = yes
DYNAMIC_KEYMAP_ENABLE = yes
CIE1931_CURVE = yes

A keyboards/nk65/mcuconf.h => keyboards/nk65/mcuconf.h +257 -0
@@ 0,0 1,257 @@
/*
    ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#ifndef MCUCONF_H
#define MCUCONF_H

/*
 * STM32F3xx drivers configuration.
 * The following settings override the default settings present in
 * the various device driver implementation headers.
 * Note that the settings for each driver only have effect if the whole
 * driver is enabled in halconf.h.
 *
 * IRQ priorities:
 * 15...0       Lowest...Highest.
 *
 * DMA priorities:
 * 0...3        Lowest...Highest.
 */

#define STM32F3xx_MCUCONF

/*
 * HAL driver system settings.
 */
#define STM32_NO_INIT                       FALSE
#define STM32_PVD_ENABLE                    FALSE
#define STM32_PLS                           STM32_PLS_LEV0
#define STM32_HSI_ENABLED                   TRUE
#define STM32_LSI_ENABLED                   TRUE
#define STM32_HSE_ENABLED                   TRUE
#define STM32_LSE_ENABLED                   FALSE
#define STM32_SW                            STM32_SW_PLL
#define STM32_PLLSRC                        STM32_PLLSRC_HSE
#define STM32_PREDIV_VALUE                  1
#define STM32_PLLMUL_VALUE                  9
#define STM32_HPRE                          STM32_HPRE_DIV1
#define STM32_PPRE1                         STM32_PPRE1_DIV2
#define STM32_PPRE2                         STM32_PPRE2_DIV2
#define STM32_MCOSEL                        STM32_MCOSEL_NOCLOCK
#define STM32_ADC12PRES                     STM32_ADC12PRES_DIV1
#define STM32_ADC34PRES                     STM32_ADC34PRES_DIV1
#define STM32_USART1SW                      STM32_USART1SW_PCLK
#define STM32_USART2SW                      STM32_USART2SW_PCLK
#define STM32_USART3SW                      STM32_USART3SW_PCLK
#define STM32_UART4SW                       STM32_UART4SW_PCLK
#define STM32_UART5SW                       STM32_UART5SW_PCLK
#define STM32_I2C1SW                        STM32_I2C1SW_SYSCLK
#define STM32_I2C2SW                        STM32_I2C2SW_SYSCLK
#define STM32_TIM1SW                        STM32_TIM1SW_PCLK2
#define STM32_TIM8SW                        STM32_TIM8SW_PCLK2
#define STM32_RTCSEL                        STM32_RTCSEL_LSI
#define STM32_USB_CLOCK_REQUIRED            TRUE
#define STM32_USBPRE                        STM32_USBPRE_DIV1P5

#undef STM32_HSE_BYPASS
// #error "oh no"
// #endif

/*
 * ADC driver system settings.
 */
#define STM32_ADC_DUAL_MODE                 FALSE
#define STM32_ADC_COMPACT_SAMPLES           FALSE
#define STM32_ADC_USE_ADC1                  FALSE
#define STM32_ADC_USE_ADC2                  FALSE
#define STM32_ADC_USE_ADC3                  FALSE
#define STM32_ADC_USE_ADC4                  FALSE
#define STM32_ADC_ADC1_DMA_STREAM           STM32_DMA_STREAM_ID(1, 1)
#define STM32_ADC_ADC2_DMA_STREAM           STM32_DMA_STREAM_ID(2, 1)
#define STM32_ADC_ADC3_DMA_STREAM           STM32_DMA_STREAM_ID(2, 5)
#define STM32_ADC_ADC4_DMA_STREAM           STM32_DMA_STREAM_ID(2, 2)
#define STM32_ADC_ADC1_DMA_PRIORITY         2
#define STM32_ADC_ADC2_DMA_PRIORITY         2
#define STM32_ADC_ADC3_DMA_PRIORITY         2
#define STM32_ADC_ADC4_DMA_PRIORITY         2
#define STM32_ADC_ADC12_IRQ_PRIORITY        5
#define STM32_ADC_ADC3_IRQ_PRIORITY         5
#define STM32_ADC_ADC4_IRQ_PRIORITY         5
#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY     5
#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY     5
#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY     5
#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY     5
#define STM32_ADC_ADC12_CLOCK_MODE          ADC_CCR_CKMODE_AHB_DIV1
#define STM32_ADC_ADC34_CLOCK_MODE          ADC_CCR_CKMODE_AHB_DIV1

/*
 * CAN driver system settings.
 */
#define STM32_CAN_USE_CAN1                  FALSE
#define STM32_CAN_CAN1_IRQ_PRIORITY         11

/*
 * DAC driver system settings.
 */
#define STM32_DAC_DUAL_MODE                 FALSE
#define STM32_DAC_USE_DAC1_CH1              TRUE
#define STM32_DAC_USE_DAC1_CH2              TRUE
#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY     10
#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY     10
#define STM32_DAC_DAC1_CH1_DMA_PRIORITY     2
#define STM32_DAC_DAC1_CH2_DMA_PRIORITY     2

/*
 * EXT driver system settings.
 */
#define STM32_EXT_EXTI0_IRQ_PRIORITY        6
#define STM32_EXT_EXTI1_IRQ_PRIORITY        6
#define STM32_EXT_EXTI2_IRQ_PRIORITY        6
#define STM32_EXT_EXTI3_IRQ_PRIORITY        6
#define STM32_EXT_EXTI4_IRQ_PRIORITY        6
#define STM32_EXT_EXTI5_9_IRQ_PRIORITY      6
#define STM32_EXT_EXTI10_15_IRQ_PRIORITY    6
#define STM32_EXT_EXTI16_IRQ_PRIORITY       6
#define STM32_EXT_EXTI17_IRQ_PRIORITY       6
#define STM32_EXT_EXTI18_IRQ_PRIORITY       6
#define STM32_EXT_EXTI19_IRQ_PRIORITY       6
#define STM32_EXT_EXTI20_IRQ_PRIORITY       6
#define STM32_EXT_EXTI21_22_29_IRQ_PRIORITY 6
#define STM32_EXT_EXTI30_32_IRQ_PRIORITY    6
#define STM32_EXT_EXTI33_IRQ_PRIORITY       6

/*
 * GPT driver system settings.
 */
#define STM32_GPT_USE_TIM1                  FALSE
#define STM32_GPT_USE_TIM2                  FALSE
#define STM32_GPT_USE_TIM3                  FALSE
#define STM32_GPT_USE_TIM4                  TRUE
#define STM32_GPT_USE_TIM6                  TRUE
#define STM32_GPT_USE_TIM7                  TRUE
#define STM32_GPT_USE_TIM8                  TRUE
#define STM32_GPT_TIM1_IRQ_PRIORITY         7
#define STM32_GPT_TIM2_IRQ_PRIORITY         7
#define STM32_GPT_TIM3_IRQ_PRIORITY         7
#define STM32_GPT_TIM4_IRQ_PRIORITY         7
#define STM32_GPT_TIM6_IRQ_PRIORITY         7
#define STM32_GPT_TIM7_IRQ_PRIORITY         7
#define STM32_GPT_TIM8_IRQ_PRIORITY         7

/*
 * I2C driver system settings.
 */
#define STM32_I2C_USE_I2C1                  TRUE
#define STM32_I2C_USE_I2C2                  FALSE
#define STM32_I2C_BUSY_TIMEOUT              50
#define STM32_I2C_I2C1_IRQ_PRIORITY         10
#define STM32_I2C_I2C2_IRQ_PRIORITY         10
#define STM32_I2C_USE_DMA                   TRUE
#define STM32_I2C_I2C1_DMA_PRIORITY         1
#define STM32_I2C_I2C2_DMA_PRIORITY         1
#define STM32_I2C_DMA_ERROR_HOOK(i2cp)      osalSysHalt("DMA failure")

/*
 * ICU driver system settings.
 */
#define STM32_ICU_USE_TIM1                  FALSE
#define STM32_ICU_USE_TIM2                  FALSE
#define STM32_ICU_USE_TIM3                  FALSE
#define STM32_ICU_USE_TIM4                  FALSE
#define STM32_ICU_USE_TIM8                  FALSE
#define STM32_ICU_TIM1_IRQ_PRIORITY         7
#define STM32_ICU_TIM2_IRQ_PRIORITY         7
#define STM32_ICU_TIM3_IRQ_PRIORITY         7
#define STM32_ICU_TIM4_IRQ_PRIORITY         7
#define STM32_ICU_TIM8_IRQ_PRIORITY         7

/*
 * PWM driver system settings.
 */
#define STM32_PWM_USE_ADVANCED              FALSE
#define STM32_PWM_USE_TIM1                  FALSE
#define STM32_PWM_USE_TIM2                  FALSE
#define STM32_PWM_USE_TIM3                  FALSE
#define STM32_PWM_USE_TIM4                  FALSE
#define STM32_PWM_USE_TIM8                  FALSE
#define STM32_PWM_TIM1_IRQ_PRIORITY         7
#define STM32_PWM_TIM2_IRQ_PRIORITY         7
#define STM32_PWM_TIM3_IRQ_PRIORITY         7
#define STM32_PWM_TIM4_IRQ_PRIORITY         7
#define STM32_PWM_TIM8_IRQ_PRIORITY         7

/*
 * SERIAL driver system settings.
 */
#define STM32_SERIAL_USE_USART1             FALSE
#define STM32_SERIAL_USE_USART2             FALSE
#define STM32_SERIAL_USE_USART3             FALSE
#define STM32_SERIAL_USE_UART4              FALSE
#define STM32_SERIAL_USE_UART5              FALSE
#define STM32_SERIAL_USART1_PRIORITY        12
#define STM32_SERIAL_USART2_PRIORITY        12
#define STM32_SERIAL_USART3_PRIORITY        12
#define STM32_SERIAL_UART4_PRIORITY         12
#define STM32_SERIAL_UART5_PRIORITY         12

/*
 * SPI driver system settings.
 */
#define STM32_SPI_USE_SPI1                  FALSE
#define STM32_SPI_USE_SPI2                  FALSE
#define STM32_SPI_USE_SPI3                  FALSE
#define STM32_SPI_SPI1_DMA_PRIORITY         1
#define STM32_SPI_SPI2_DMA_PRIORITY         1
#define STM32_SPI_SPI3_DMA_PRIORITY         1
#define STM32_SPI_SPI1_IRQ_PRIORITY         10
#define STM32_SPI_SPI2_IRQ_PRIORITY         10
#define STM32_SPI_SPI3_IRQ_PRIORITY         10
#define STM32_SPI_DMA_ERROR_HOOK(spip)      osalSysHalt("DMA failure")

/*
 * ST driver system settings.
 */
#define STM32_ST_IRQ_PRIORITY               8
#define STM32_ST_USE_TIMER                  2

/*
 * UART driver system settings.
 */
#define STM32_UART_USE_USART1               FALSE
#define STM32_UART_USE_USART2               FALSE
#define STM32_UART_USE_USART3               FALSE
#define STM32_UART_USART1_IRQ_PRIORITY      12
#define STM32_UART_USART2_IRQ_PRIORITY      12
#define STM32_UART_USART3_IRQ_PRIORITY      12
#define STM32_UART_USART1_DMA_PRIORITY      0
#define STM32_UART_USART2_DMA_PRIORITY      0
#define STM32_UART_USART3_DMA_PRIORITY      0
#define STM32_UART_DMA_ERROR_HOOK(uartp)    osalSysHalt("DMA failure")

/*
 * USB driver system settings.
 */
#define STM32_USB_USE_USB1                  TRUE
#define STM32_USB_LOW_POWER_ON_SUSPEND      FALSE
#define STM32_USB_USB1_HP_IRQ_PRIORITY      13
#define STM32_USB_USB1_LP_IRQ_PRIORITY      14

/*
 * WDG driver system settings.
 */
#define STM32_WDG_USE_IWDG                  FALSE

#endif /* MCUCONF_H */

A keyboards/nk65/nk65.c => keyboards/nk65/nk65.c +18 -0
@@ 0,0 1,18 @@
/* Copyright 2019 Yiancar
 *
 * 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 <http://www.gnu.org/licenses/>.
 */
 #ifndef RGB_BACKLIGHT_NK65
 #error RGB_BACKLIGHT_NK65 not defined, recheck config.h
 #endif

A keyboards/nk65/nk65.h => keyboards/nk65/nk65.h +38 -0
@@ 0,0 1,38 @@
/* Copyright 2019 Yiancar
 *
 * 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 <http://www.gnu.org/licenses/>.
 */
#pragma once

#define XXX KC_NO

#include "quantum.h"
#include "../zeal60/rgb_backlight_keycodes.h"
#include "../zeal60/zeal60_keycodes.h"

// This a shortcut to help you visually see your layout.

#define LAYOUT_65_ansi( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K2C, K1E, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B,      K2D, K2E, \
    K30,      K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, K3E, \
    K40, K41, K42,                K46,           K49, K4A, K4B, K4C, K4D, K4E  \
) { \
    { K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E }, \
    { K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, XXX, K1E }, \
    { K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, K2E }, \
    { K30, XXX, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, K3E }, \
    { K40, K41, K42, XXX, XXX, XXX, K46, XXX, XXX, K49, K4A, K4B, K4C, K4D, K4E }  \
}

A keyboards/nk65/readme.md => keyboards/nk65/readme.md +37 -0
@@ 0,0 1,37 @@
NK65
=========

[NK65]()

This is a standard fixed layout 65% PCB. It supports VIA and full per-key RGB.

Keyboard Maintainer: [Yiancar](http://yiancar-designs.com/) and on [github](https://github.com/yiancar)   
Hardware Supported: A 65% keyboard with STM32F303CC   
Hardware Availability: https://novelkeys.xyz/   

Due to the RGB implementation, the NK65 is currently not compatible with community layouts.

## Instructions

### Build

Make example for this keyboard (after setting up your build environment):

    make nk65:default_via

See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).

### Reset

- Unplug
- Hold Escape
- Plug In
- Unplug
- Release Escape

### Flash

- Unplug
- Hold Escape
- Plug In
- Flash using QMK Toolbox or dfu-util (`make nk65:<keymap>:dfu-util`)

A keyboards/nk65/rules.mk => keyboards/nk65/rules.mk +69 -0
@@ 0,0 1,69 @@
# project specific files
SRC =	keyboards/zeal60/zeal60.c \
		keyboards/zeal60/rgb_backlight.c \
		drivers/issi/is31fl3733.c \
		quantum/color.c \
		drivers/arm/i2c_master.c

## chip/board settings
#   the next two should match the directories in
#   <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
MCU_FAMILY = STM32
MCU_SERIES = STM32F3xx

# Linker script to use
#   it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
#   or <this_dir>/ld/
MCU_LDSCRIPT = STM32F303xC

# Startup code to use
#  - it should exist in <chibios>/os/common/startup/ARMCMx/compilers/GCC/mk/
MCU_STARTUP = stm32f3xx

# Board: it should exist either in <chibios>/os/hal/boards/
#  or <this_dir>/boards
BOARD = GENERIC_STM32_F303XC

# Cortex version
MCU  = cortex-m4

# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
ARMV = 7

USE_FPU = yes

# Vector table for application
# 0x00000000-0x00001000 area is occupied by bootlaoder.*/
# The CORTEX_VTOR... is needed only for MCHCK/Infinity KB
# OPT_DEFS = -DCORTEX_VTOR_INIT=0x08005000
OPT_DEFS =

# Do not put the microcontroller into power saving mode
# when we get USB suspend event. We want it to keep updating
# backlight effects.
OPT_DEFS += -DNO_SUSPEND_POWER_DOWN

# Options to pass to dfu-util when flashing
DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave
DFU_SUFFIX_ARGS = -p DF11 -v 0483

# Build Options
#   comment out to disable the options.
#
BACKLIGHT_ENABLE = no              # Enable keyboard backlight functionality
BOOTMAGIC_ENABLE = no              # Virtual DIP switch configuration
MOUSEKEY_ENABLE = yes              # Mouse keys
EXTRAKEY_ENABLE = yes              # Audio control and System control
CONSOLE_ENABLE = no                # Console for debug
COMMAND_ENABLE = no                # Commands for debug and configuration
SLEEP_LED_ENABLE = no              # Breathing sleep LED during USB suspend
NKRO_ENABLE = yes                  # USB Nkey Rollover
AUDIO_ENABLE = no                  # Audio output on port C6
NO_USB_STARTUP_CHECK = no          # Disable initialization only when usb is plugged in
#SERIAL_LINK_ENABLE = yes

RAW_ENABLE = no
DYNAMIC_KEYMAP_ENABLE = no
CIE1931_CURVE = yes

LAYOUTS = 65_ansi

M keyboards/zeal60/rgb_backlight.c => keyboards/zeal60/rgb_backlight.c +1600 -1368
@@ 15,9 15,9 @@
 */
#if RGB_BACKLIGHT_ENABLED

#if defined (RGB_BACKLIGHT_ZEAL60) || defined (RGB_BACKLIGHT_ZEAL65) || defined (RGB_BACKLIGHT_M60_A) || defined(RGB_BACKLIGHT_M6_B) || defined(RGB_BACKLIGHT_KOYU) || defined(RGB_BACKLIGHT_HS60)
#if defined(RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_ZEAL65) || defined(RGB_BACKLIGHT_M60_A) || defined(RGB_BACKLIGHT_M6_B) || defined(RGB_BACKLIGHT_KOYU) || defined(RGB_BACKLIGHT_HS60) || defined(RGB_BACKLIGHT_NK65)
#else
#error None of the following was defined: RGB_BACKLIGHT_ZEAL60, RGB_BACKLIGHT_ZEAL65, RGB_BACKLIGHT_M60_A, RGB_BACKLIGHT_M6_B, RGB_BACKLIGHT_KOYU
#error None of the following was defined: RGB_BACKLIGHT_ZEAL60, RGB_BACKLIGHT_ZEAL65, RGB_BACKLIGHT_M60_A, RGB_BACKLIGHT_M6_B, RGB_BACKLIGHT_KOYU, RGB_BACKLIGHT_HS60, RGB_BACKLIGHT_NK65
#endif

#ifndef MAX


@@ 33,7 33,7 @@
#include "rgb_backlight_api.h"
#include "rgb_backlight_keycodes.h"

#if !defined(RGB_BACKLIGHT_HS60)
#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65)
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>


@@ 47,12 47,15 @@
#include "progmem.h"
#include "quantum/color.h"

#if defined (RGB_BACKLIGHT_M6_B)
#if defined(RGB_BACKLIGHT_M6_B)
#include "drivers/issi/is31fl3218.h"
#define BACKLIGHT_LED_COUNT 6
#elif defined (RGB_BACKLIGHT_HS60)
#elif defined(RGB_BACKLIGHT_HS60)
#include "drivers/issi/is31fl3733.h"
#define BACKLIGHT_LED_COUNT 64
#elif defined(RGB_BACKLIGHT_NK65)
#include "drivers/issi/is31fl3733.h"
#define BACKLIGHT_LED_COUNT 69
#else
#include "drivers/issi/is31fl3731.h"
#define BACKLIGHT_LED_COUNT 72


@@ 61,31 64,31 @@
#define BACKLIGHT_EFFECT_MAX 10

backlight_config g_config = {
	.use_split_backspace = RGB_BACKLIGHT_USE_SPLIT_BACKSPACE,
	.use_split_left_shift = RGB_BACKLIGHT_USE_SPLIT_LEFT_SHIFT,
	.use_split_right_shift = RGB_BACKLIGHT_USE_SPLIT_RIGHT_SHIFT,
	.use_7u_spacebar = RGB_BACKLIGHT_USE_7U_SPACEBAR,
	.use_iso_enter = RGB_BACKLIGHT_USE_ISO_ENTER,
	.disable_hhkb_blocker_leds = RGB_BACKLIGHT_DISABLE_HHKB_BLOCKER_LEDS,
	.disable_when_usb_suspended = RGB_BACKLIGHT_DISABLE_WHEN_USB_SUSPENDED,
	.disable_after_timeout = RGB_BACKLIGHT_DISABLE_AFTER_TIMEOUT,
	.brightness = RGB_BACKLIGHT_BRIGHTNESS,
	.effect = RGB_BACKLIGHT_EFFECT,
	.effect_speed = RGB_BACKLIGHT_EFFECT_SPEED,
	.color_1 = RGB_BACKLIGHT_COLOR_1,
	.color_2 = RGB_BACKLIGHT_COLOR_2,
	.caps_lock_indicator = RGB_BACKLIGHT_CAPS_LOCK_INDICATOR,
	.layer_1_indicator = RGB_BACKLIGHT_LAYER_1_INDICATOR,
	.layer_2_indicator = RGB_BACKLIGHT_LAYER_2_INDICATOR,
	.layer_3_indicator = RGB_BACKLIGHT_LAYER_3_INDICATOR,
	.alphas_mods = {
		RGB_BACKLIGHT_ALPHAS_MODS_ROW_0,
		RGB_BACKLIGHT_ALPHAS_MODS_ROW_1,
		RGB_BACKLIGHT_ALPHAS_MODS_ROW_2,
		RGB_BACKLIGHT_ALPHAS_MODS_ROW_3,
		RGB_BACKLIGHT_ALPHAS_MODS_ROW_4 },
    .use_split_backspace = RGB_BACKLIGHT_USE_SPLIT_BACKSPACE,
    .use_split_left_shift = RGB_BACKLIGHT_USE_SPLIT_LEFT_SHIFT,
    .use_split_right_shift = RGB_BACKLIGHT_USE_SPLIT_RIGHT_SHIFT,
    .use_7u_spacebar = RGB_BACKLIGHT_USE_7U_SPACEBAR,
    .use_iso_enter = RGB_BACKLIGHT_USE_ISO_ENTER,
    .disable_hhkb_blocker_leds = RGB_BACKLIGHT_DISABLE_HHKB_BLOCKER_LEDS,
    .disable_when_usb_suspended = RGB_BACKLIGHT_DISABLE_WHEN_USB_SUSPENDED,
    .disable_after_timeout = RGB_BACKLIGHT_DISABLE_AFTER_TIMEOUT,
    .brightness = RGB_BACKLIGHT_BRIGHTNESS,
    .effect = RGB_BACKLIGHT_EFFECT,
    .effect_speed = RGB_BACKLIGHT_EFFECT_SPEED,
    .color_1 = RGB_BACKLIGHT_COLOR_1,
    .color_2 = RGB_BACKLIGHT_COLOR_2,
    .caps_lock_indicator = RGB_BACKLIGHT_CAPS_LOCK_INDICATOR,
    .layer_1_indicator = RGB_BACKLIGHT_LAYER_1_INDICATOR,
    .layer_2_indicator = RGB_BACKLIGHT_LAYER_2_INDICATOR,
    .layer_3_indicator = RGB_BACKLIGHT_LAYER_3_INDICATOR,
    .alphas_mods = {
        RGB_BACKLIGHT_ALPHAS_MODS_ROW_0,
        RGB_BACKLIGHT_ALPHAS_MODS_ROW_1,
        RGB_BACKLIGHT_ALPHAS_MODS_ROW_2,
        RGB_BACKLIGHT_ALPHAS_MODS_ROW_3,
        RGB_BACKLIGHT_ALPHAS_MODS_ROW_4 },
#if defined(RGB_BACKLIGHT_M6_B)
	.custom_color = { { 0, 255 }, { 43, 255 }, { 85, 255 }, { 128, 255 }, { 171, 255 }, { 213, 255 } }
    .custom_color = { { 0, 255 }, { 43, 255 }, { 85, 255 }, { 128, 255 }, { 171, 255 }, { 213, 255 } }
#endif
};



@@ 107,7 110,6 @@ uint32_t g_any_key_hit = 0;
// set to 0 for write, 1 for read (as per I2C protocol)
// ADDR_2 is not needed. it is here as a dummy
#define ISSI_ADDR_1 0x50
#define ISSI_ADDR_2 0x50

const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations


@@ 182,6 184,152 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
    {0, K_16,  J_16,  L_16}, //LA64
};

#elif defined(RGB_BACKLIGHT_NK65)

// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)
// ADDR_2 is not needed. it is here as a dummy
#define ISSI_ADDR_1 0x50
#define ISSI_ADDR_2 0x52

const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
/* Refer to IS31 manual for these locations
 *   driver
 *   |  R location
 *   |  |      G location
 *   |  |      |      B location
 *   |  |      |      | */
    {0, B_1,   A_1,   C_1}, //LA1
    {0, E_1,   D_1,   F_1}, //LA2
    {0, H_1,   G_1,   I_1}, //LA3
    {0, K_1,   J_1,   L_1}, //LA4
    {0, B_2,   A_2,   C_2}, //LA5
    {0, E_2,   D_2,   F_2}, //LA6
    {0, H_2,   G_2,   I_2}, //LA7
    {0, K_2,   J_2,   L_2}, //LA8
    {0, B_3,   A_3,   C_3}, //LA9
    {0, E_3,   D_3,   F_3}, //LA10
    {0, H_3,   G_3,   I_3}, //LA11
    {0, K_3,   J_3,   L_3}, //LA12
    {0, B_4,   A_4,   C_4}, //LA13
    {0, E_4,   D_4,   F_4}, //LA14
    {0, H_4,   G_4,   I_4}, //LA15
    {0, K_4,   J_4,   L_4}, //LA16
    {0, B_5,   A_5,   C_5}, //LA17
    {0, E_5,   D_5,   F_5}, //LA18
    {0, H_5,   G_5,   I_5}, //LA19
    {0, K_5,   J_5,   L_5}, //LA20
    {0, B_6,   A_6,   C_6}, //LA21
    {0, E_6,   D_6,   F_6}, //LA22
    {0, H_6,   G_6,   I_6}, //LA23
    {0, K_6,   J_6,   L_6}, //LA24
    {0, B_7,   A_7,   C_7}, //LA25
    {0, E_7,   D_7,   F_7}, //LA26
    {0, H_7,   G_7,   I_7}, //LA27
    {0, K_7,   J_7,   L_7}, //LA28
    {0, B_8,   A_8,   C_8}, //LA29
    {0, E_8,   D_8,   F_8}, //LA30
    {0, H_8,   G_8,   I_8}, //LA31
    {0, K_8,   J_8,   L_8}, //LA32
    {0, B_9,   A_9,   C_9}, //LA33
    {0, E_9,   D_9,   F_9}, //LA34
    {0, H_9,   G_9,   I_9}, //LA35
    {0, K_9,   J_9,   L_9}, //LA36
    {0, B_10,  A_10,  C_10}, //LA37
    {0, E_10,  D_10,  F_10}, //LA38
    {0, H_10,  G_10,  I_10}, //LA39
    {0, K_10,  J_10,  L_10}, //LA40
    {0, B_11,  A_11,  C_11}, //LA41
    {0, E_11,  D_11,  F_11}, //LA42
    {0, H_11,  G_11,  I_11}, //LA43
    {0, K_11,  J_11,  L_11}, //LA44
    {0, B_12,  A_12,  C_12}, //LA45
    {0, E_12,  D_12,  F_12}, //LA46
    {0, H_12,  G_12,  I_12}, //LA47
    {0, K_12,  J_12,  L_12}, //LA48
    {0, B_13,  A_13,  C_13}, //LA49
    {0, E_13,  D_13,  F_13}, //LA50
    {0, H_13,  G_13,  I_13}, //LA51
    {0, K_13,  J_13,  L_13}, //LA52
    {0, B_14,  A_14,  C_14}, //LA53
    {0, E_14,  D_14,  F_14}, //LA54
    {0, H_14,  G_14,  I_14}, //LA55
    {0, K_14,  J_14,  L_14}, //LA56
    {0, B_15,  A_15,  C_15}, //LA57
    {0, E_15,  D_15,  F_15}, //LA58
    {0, H_15,  G_15,  I_15}, //LA59
    {0, K_15,  J_15,  L_15}, //LA60
    {0, B_16,  A_16,  C_16}, //LA61
    {0, E_16,  D_16,  F_16}, //LA62
    {0, H_16,  G_16,  I_16}, //LA63
    {0, K_16,  J_16,  L_16}, //LA64

    {1, B_1,   A_1,   C_1}, //LB1
    {1, E_1,   D_1,   F_1}, //LB2
    {1, H_1,   G_1,   I_1}, //LB3
    {1, K_1,   J_1,   L_1}, //LB4
    {1, B_2,   A_2,   C_2}, //LB5
    {1, E_2,   D_2,   F_2}, //LB6
    {1, H_2,   G_2,   I_2}, //LB7
    {1, K_2,   J_2,   L_2}, //LB8
    {1, B_3,   A_3,   C_3}, //LB9
    {1, E_3,   D_3,   F_3}, //LB10
    {1, H_3,   G_3,   I_3}, //LB11
    {1, K_3,   J_3,   L_3}, //LB12
    {1, B_4,   A_4,   C_4}, //LB13
    {1, E_4,   D_4,   F_4}, //LB14
    {1, H_4,   G_4,   I_4}, //LB15
    {1, K_4,   J_4,   L_4}, //LB16
    {1, B_5,   A_5,   C_5}, //LB17
    {1, E_5,   D_5,   F_5}, //LB18
    {1, H_5,   G_5,   I_5}, //LB19
    {1, K_5,   J_5,   L_5}, //LB20
    {1, B_6,   A_6,   C_6}, //LB21
    {1, E_6,   D_6,   F_6}, //LB22
    {1, H_6,   G_6,   I_6}, //LB23
    {1, K_6,   J_6,   L_6}, //LB24
    {1, B_7,   A_7,   C_7}, //LB25
    {1, E_7,   D_7,   F_7}, //LB26
    {1, H_7,   G_7,   I_7}, //LB27
    {1, K_7,   J_7,   L_7}, //LB28
    {1, B_8,   A_8,   C_8}, //LB29
    {1, E_8,   D_8,   F_8}, //LB30
    {1, H_8,   G_8,   I_8}, //LB31
    {1, K_8,   J_8,   L_8}, //LB32
    {1, B_9,   A_9,   C_9}, //LB33
    {1, E_9,   D_9,   F_9}, //LB34
    {1, H_9,   G_9,   I_9}, //LB35
    {1, K_9,   J_9,   L_9}, //LB36
    {1, B_10,  A_10,  C_10}, //LB37
    {1, E_10,  D_10,  F_10}, //LB38
    {1, H_10,  G_10,  I_10}, //LB39
    {1, K_10,  J_10,  L_10}, //LB40
    {1, B_11,  A_11,  C_11}, //LB41
    {1, E_11,  D_11,  F_11}, //LB42
    {1, H_11,  G_11,  I_11}, //LB43
    {1, K_11,  J_11,  L_11}, //LB44
    {1, B_12,  A_12,  C_12}, //LB45
    {1, E_12,  D_12,  F_12}, //LB46
    {1, H_12,  G_12,  I_12}, //LB47
    {1, K_12,  J_12,  L_12}, //LB48
    {1, B_13,  A_13,  C_13}, //LB49
    {1, E_13,  D_13,  F_13}, //LB50
    {1, H_13,  G_13,  I_13}, //LB51
    {1, K_13,  J_13,  L_13}, //LB52
    {1, B_14,  A_14,  C_14}, //LB53
    {1, E_14,  D_14,  F_14}, //LB54
    {1, H_14,  G_14,  I_14}, //LB55
    {1, K_14,  J_14,  L_14}, //LB56
    {1, B_15,  A_15,  C_15}, //LB57
    {1, E_15,  D_15,  F_15}, //LB58
    {1, H_15,  G_15,  I_15}, //LB59
    {1, K_15,  J_15,  L_15}, //LB60
    {1, B_16,  A_16,  C_16}, //LB61
    {1, E_16,  D_16,  F_16}, //LB62
    {1, H_16,  G_16,  I_16}, //LB63
    {1, K_16,  J_16,  L_16}, //LB64
};

#elif !defined(RGB_BACKLIGHT_M6_B)
// This is a 7-bit address, that gets left-shifted and bit 0
// set to 0 for write, 1 for read (as per I2C protocol)


@@ 195,269 343,292 @@ const is31_led g_is31_leds[DRIVER_LED_TOTAL] = {
 *   |  |      G location
 *   |  |      |      B location
 *   |  |      |      | */
	{0, C2_1,  C3_1,  C4_1},  // LA0
	{0, C1_1,  C3_2, C4_2},   // LA1
	{0, C1_2,  C2_2, C4_3},   // LA2
	{0, C1_3,  C2_3, C3_3},   // LA3
	{0, C1_4,  C2_4, C3_4},   // LA4
	{0, C1_5,  C2_5, C3_5},   // LA5
	{0, C1_6,  C2_6, C3_6},   // LA6
	{0, C1_7,  C2_7, C3_7},   // LA7
	{0, C1_8,  C2_8, C3_8},   // LA8
	{0, C9_1,  C8_1,  C7_1},  // LA9
	{0, C9_2,  C8_2, C7_2},   // LA10
	{0, C9_3,  C8_3, C7_3},   // LA11
	{0, C9_4,  C8_4, C7_4},   // LA12
	{0, C9_5,  C8_5, C7_5},   // LA13
	{0, C9_6,  C8_6, C7_6},   // LA14
	{0, C9_7,  C8_7, C6_6},   // LA15
	{0, C9_8,  C7_7, C6_7},   // LA16
	{0, C8_8,  C7_8, C6_8},   // LA17

	{0, C2_9,  C3_9,  C4_9},  // LB0
	{0, C1_9,  C3_10, C4_10}, // LB1
	{0, C1_10, C2_10, C4_11}, // LB2
	{0, C1_11, C2_11, C3_11}, // LB3
	{0, C1_12, C2_12, C3_12}, // LB4
	{0, C1_13, C2_13, C3_13}, // LB5
	{0, C1_14, C2_14, C3_14}, // LB6
	{0, C1_15, C2_15, C3_15}, // LB7
	{0, C1_16, C2_16, C3_16}, // LB8
	{0, C9_9,  C8_9,  C7_9},  // LB9
	{0, C9_10, C8_10, C7_10}, // LB10
	{0, C9_11, C8_11, C7_11}, // LB11
	{0, C9_12, C8_12, C7_12}, // LB12
	{0, C9_13, C8_13, C7_13}, // LB13
	{0, C9_14, C8_14, C7_14}, // LB14
	{0, C9_15, C8_15, C6_14}, // LB15
	{0, C9_16, C7_15, C6_15}, // LB16
	{0, C8_16, C7_16, C6_16}, // LB17

	{1, C2_1,  C3_1,  C4_1},  // LC0
	{1, C1_1,  C3_2, C4_2},   // LC1
	{1, C1_2,  C2_2, C4_3},   // LC2
	{1, C1_3,  C2_3, C3_3},   // LC3
	{1, C1_4,  C2_4, C3_4},   // LC4
	{1, C1_5,  C2_5, C3_5},   // LC5
	{1, C1_6,  C2_6, C3_6},   // LC6
	{1, C1_7,  C2_7, C3_7},   // LC7
	{1, C1_8,  C2_8, C3_8},   // LC8
	{1, C9_1,  C8_1,  C7_1},  // LC9
	{1, C9_2,  C8_2, C7_2},   // LC10
	{1, C9_3,  C8_3, C7_3},   // LC11
	{1, C9_4,  C8_4, C7_4},   // LC12
	{1, C9_5,  C8_5, C7_5},   // LC13
	{1, C9_6,  C8_6, C7_6},   // LC14
	{1, C9_7,  C8_7, C6_6},   // LC15
	{1, C9_8,  C7_7, C6_7},   // LC16
	{1, C8_8,  C7_8, C6_8},   // LC17

	{1, C2_9,  C3_9,  C4_9},  // LD0
	{1, C1_9,  C3_10, C4_10}, // LD1
	{1, C1_10, C2_10, C4_11}, // LD2
	{1, C1_11, C2_11, C3_11}, // LD3
	{1, C1_12, C2_12, C3_12}, // LD4
	{1, C1_13, C2_13, C3_13}, // LD5
	{1, C1_14, C2_14, C3_14}, // LD6
	{1, C1_15, C2_15, C3_15}, // LD7
	{1, C1_16, C2_16, C3_16}, // LD8
	{1, C9_9,  C8_9,  C7_9},  // LD9
	{1, C9_10, C8_10, C7_10}, // LD10
	{1, C9_11, C8_11, C7_11}, // LD11
	{1, C9_12, C8_12, C7_12}, // LD12
	{1, C9_13, C8_13, C7_13}, // LD13
	{1, C9_14, C8_14, C7_14}, // LD14
	{1, C9_15, C8_15, C6_14}, // LD15
	{1, C9_16, C7_15, C6_15}, // LD16
	{1, C8_16, C7_16, C6_16}, // LD17
    {0, C2_1,  C3_1,  C4_1},  // LA0
    {0, C1_1,  C3_2, C4_2},   // LA1
    {0, C1_2,  C2_2, C4_3},   // LA2
    {0, C1_3,  C2_3, C3_3},   // LA3
    {0, C1_4,  C2_4, C3_4},   // LA4
    {0, C1_5,  C2_5, C3_5},   // LA5
    {0, C1_6,  C2_6, C3_6},   // LA6
    {0, C1_7,  C2_7, C3_7},   // LA7
    {0, C1_8,  C2_8, C3_8},   // LA8
    {0, C9_1,  C8_1, C7_1},   // LA9
    {0, C9_2,  C8_2, C7_2},   // LA10
    {0, C9_3,  C8_3, C7_3},   // LA11
    {0, C9_4,  C8_4, C7_4},   // LA12
    {0, C9_5,  C8_5, C7_5},   // LA13
    {0, C9_6,  C8_6, C7_6},   // LA14
    {0, C9_7,  C8_7, C6_6},   // LA15
    {0, C9_8,  C7_7, C6_7},   // LA16
    {0, C8_8,  C7_8, C6_8},   // LA17

    {0, C2_9,  C3_9,  C4_9},  // LB0
    {0, C1_9,  C3_10, C4_10}, // LB1
    {0, C1_10, C2_10, C4_11}, // LB2
    {0, C1_11, C2_11, C3_11}, // LB3
    {0, C1_12, C2_12, C3_12}, // LB4
    {0, C1_13, C2_13, C3_13}, // LB5
    {0, C1_14, C2_14, C3_14}, // LB6
    {0, C1_15, C2_15, C3_15}, // LB7
    {0, C1_16, C2_16, C3_16}, // LB8
    {0, C9_9,  C8_9,  C7_9},  // LB9
    {0, C9_10, C8_10, C7_10}, // LB10
    {0, C9_11, C8_11, C7_11}, // LB11
    {0, C9_12, C8_12, C7_12}, // LB12
    {0, C9_13, C8_13, C7_13}, // LB13
    {0, C9_14, C8_14, C7_14}, // LB14
    {0, C9_15, C8_15, C6_14}, // LB15
    {0, C9_16, C7_15, C6_15}, // LB16
    {0, C8_16, C7_16, C6_16}, // LB17

    {1, C2_1,  C3_1,  C4_1},  // LC0
    {1, C1_1,  C3_2, C4_2},   // LC1
    {1, C1_2,  C2_2, C4_3},   // LC2
    {1, C1_3,  C2_3, C3_3},   // LC3
    {1, C1_4,  C2_4, C3_4},   // LC4
    {1, C1_5,  C2_5, C3_5},   // LC5
    {1, C1_6,  C2_6, C3_6},   // LC6
    {1, C1_7,  C2_7, C3_7},   // LC7
    {1, C1_8,  C2_8, C3_8},   // LC8
    {1, C9_1,  C8_1,  C7_1},  // LC9
    {1, C9_2,  C8_2, C7_2},   // LC10
    {1, C9_3,  C8_3, C7_3},   // LC11
    {1, C9_4,  C8_4, C7_4},   // LC12
    {1, C9_5,  C8_5, C7_5},   // LC13
    {1, C9_6,  C8_6, C7_6},   // LC14
    {1, C9_7,  C8_7, C6_6},   // LC15
    {1, C9_8,  C7_7, C6_7},   // LC16
    {1, C8_8,  C7_8, C6_8},   // LC17

    {1, C2_9,  C3_9,  C4_9},  // LD0
    {1, C1_9,  C3_10, C4_10}, // LD1
    {1, C1_10, C2_10, C4_11}, // LD2
    {1, C1_11, C2_11, C3_11}, // LD3
    {1, C1_12, C2_12, C3_12}, // LD4
    {1, C1_13, C2_13, C3_13}, // LD5
    {1, C1_14, C2_14, C3_14}, // LD6
    {1, C1_15, C2_15, C3_15}, // LD7
    {1, C1_16, C2_16, C3_16}, // LD8
    {1, C9_9,  C8_9,  C7_9},  // LD9
    {1, C9_10, C8_10, C7_10}, // LD10
    {1, C9_11, C8_11, C7_11}, // LD11
    {1, C9_12, C8_12, C7_12}, // LD12
    {1, C9_13, C8_13, C7_13}, // LD13
    {1, C9_14, C8_14, C7_14}, // LD14
    {1, C9_15, C8_15, C6_14}, // LD15
    {1, C9_16, C7_15, C6_15}, // LD16
    {1, C8_16, C7_16, C6_16}, // LD17
};
#endif // !defined(RGB_BACKLIGHT_M6_B)


typedef struct Point {
	uint8_t x;
	uint8_t y;
    uint8_t x;
    uint8_t y;
} Point;


// index in range 0..71 (LA0..LA17, LB0..LB17, LC0..LC17, LD0..LD17)
// point values in range x=0..224 y=0..64
// origin is center of top-left key (i.e Esc)
#if defined (RGB_BACKLIGHT_ZEAL65)
#if defined(RGB_BACKLIGHT_ZEAL65)
const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA0..LA17
	{120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
	{128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
	// LB0..LB17
	{144,0}, {160,0}, {176,0}, {192,0}, {216,0}, {224,0}, {240,0}, {240,16}, {240,32},
	{136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {240,48}, {240,64}, {224,64},
	// LC0..LC17
	{96,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {255,255}, {48,60}, {28,64},
	{108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {20,44}, {10,48}, {4,64},
	// LD0..LD17
	{124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {202,48}, {224,48},
	{116,48}, {132,48}, {148,48}, {164,48}, {255,255}, {144,60}, {164,64}, {188,64}, {208,64}
    // LA0..LA17
    {120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
    {128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
    // LB0..LB17
    {144,0}, {160,0}, {176,0}, {192,0}, {216,0}, {224,0}, {240,0}, {240,16}, {240,32},
    {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {240,48}, {240,64}, {224,64},
    // LC0..LC17
    {96,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {255,255}, {48,60}, {28,64},
    {108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {20,44}, {10,48}, {4,64},
    // LD0..LD17
    {124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {202,48}, {224,48},
    {116,48}, {132,48}, {148,48}, {164,48}, {255,255}, {144,60}, {164,64}, {188,64}, {208,64}
};
const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA0..LA17
	{64,128}, {75,132}, {84,145}, {91,164}, {97,187}, {102,213}, {105,242}, {109,255}, {128,243},
	{61,255}, {67,255}, {72,255}, {77,255}, {82,255}, {86,255}, {90,255}, {93,255}, {96,255},
	// LB0..LB17
	{56,255}, {51,255}, {46,255}, {42,255}, {37,255}, {35,255}, {32,255}, {19,255}, {0,255},
	{53,132}, {44,145}, {37,164}, {31,187}, {26,213}, {22,249}, {237,255}, {224,255}, {221,255},
	// LC0..LC17
	{184,255}, {179,135}, {170,149}, {163,169}, {157,193}, {153,220}, {255,255}, {167,255}, {165,255},
	{128,26}, {128,60}, {128,94}, {128,128}, {128,162}, {128,196}, {145,233}, {148,255}, {161,255},
	// LD0..LD17
	{0,9}, {0,43}, {0,77}, {0,111}, {0,145}, {0,201}, {224,181}, {230,217}, {235,255},
	{189,128}, {200,131}, {210,141}, {218,159}, {255,255}, {201,228}, {206,255}, {213,255}, {218,255}
    // LA0..LA17
    {64,128}, {75,132}, {84,145}, {91,164}, {97,187}, {102,213}, {105,242}, {109,255}, {128,243},
    {61,255}, {67,255}, {72,255}, {77,255}, {82,255}, {86,255}, {90,255}, {93,255}, {96,255},
    // LB0..LB17
    {56,255}, {51,255}, {46,255}, {42,255}, {37,255}, {35,255}, {32,255}, {19,255}, {0,255},
    {53,132}, {44,145}, {37,164}, {31,187}, {26,213}, {22,249}, {237,255}, {224,255}, {221,255},
    // LC0..LC17
    {184,255}, {179,135}, {170,149}, {163,169}, {157,193}, {153,220}, {255,255}, {167,255}, {165,255},
    {128,26}, {128,60}, {128,94}, {128,128}, {128,162}, {128,196}, {145,233}, {148,255}, {161,255},
    // LD0..LD17
    {0,9}, {0,43}, {0,77}, {0,111}, {0,145}, {0,201}, {224,181}, {230,217}, {235,255},
    {189,128}, {200,131}, {210,141}, {218,159}, {255,255}, {201,228}, {206,255}, {213,255}, {218,255}
};
#elif defined (RGB_BACKLIGHT_KOYU)
#elif defined(RGB_BACKLIGHT_KOYU)
const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA0..LA17
	{120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
	{128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
	// LB0..LB17
	{144,0}, {160,0}, {176,0}, {192,0}, {208,0}, {224,0}, {240,0}, {240,16}, {240,32},
	{136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {240,48}, {240,64}, {224,64},
	// LC0..LC17
	{112,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {64,60}, {44,60}, {24,64},
	{108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {255,255}, {10,48}, {4,64},
	// LD0..LD17
	{124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {202,48}, {224,48},
	{116,48}, {132,48}, {148,48}, {164,48}, {255,255}, {160,60}, {180,64}, {208,64}, {255,255}
    // LA0..LA17
    {120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
    {128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
    // LB0..LB17
    {144,0}, {160,0}, {176,0}, {192,0}, {208,0}, {224,0}, {240,0}, {240,16}, {240,32},
    {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {240,48}, {240,64}, {224,64},
    // LC0..LC17
    {112,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {64,60}, {44,60}, {24,64},
    {108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {255,255}, {10,48}, {4,64},
    // LD0..LD17
    {124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {202,48}, {224,48},
    {116,48}, {132,48}, {148,48}, {164,48}, {255,255}, {160,60}, {180,64}, {208,64}, {255,255}
};
const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA0..LA17
	{64,128}, {75,132}, {84,145}, {91,164}, {97,187}, {102,213}, {105,242}, {109,255}, {128,243},
	{61,255}, {67,255}, {72,255}, {77,255}, {82,255}, {86,255}, {90,255}, {93,255}, {96,255},
	// LB0..LB17
	{56,255}, {51,255}, {46,255}, {42,255}, {38,255}, {35,255}, {32,255}, {19,255}, {0,255},
	{53,132}, {44,145}, {37,164}, {31,187}, {26,213}, {22,249}, {237,255}, {224,255}, {221,255},
	// LC0..LC17
	{189,255}, {179,135}, {170,149}, {163,169}, {157,193}, {153,220}, {172,252}, {169,255}, {165,255},
	{128,26}, {128,60}, {128,94}, {128,128}, {128,162}, {128,196}, {255,255}, {148,255}, {161,255},
	// LD0..LD17
	{0,9}, {0,43}, {0,77}, {0,111}, {0,145}, {0,201}, {224,181}, {230,217}, {235,255},
	{189,128}, {200,131}, {210,141}, {218,159}, {255,255}, {207,238}, {211,255}, {218,255}, {255,255}
    // LA0..LA17
    {64,128}, {75,132}, {84,145}, {91,164}, {97,187}, {102,213}, {105,242}, {109,255}, {128,243},
    {61,255}, {67,255}, {72,255}, {77,255}, {82,255}, {86,255}, {90,255}, {93,255}, {96,255},
    // LB0..LB17
    {56,255}, {51,255}, {46,255}, {42,255}, {38,255}, {35,255}, {32,255}, {19,255}, {0,255},
    {53,132}, {44,145}, {37,164}, {31,187}, {26,213}, {22,249}, {237,255}, {224,255}, {221,255},
    // LC0..LC17
    {189,255}, {179,135}, {170,149}, {163,169}, {157,193}, {153,220}, {172,252}, {169,255}, {165,255},
    {128,26}, {128,60}, {128,94}, {128,128}, {128,162}, {128,196}, {255,255}, {148,255}, {161,255},
    // LD0..LD17
    {0,9}, {0,43}, {0,77}, {0,111}, {0,145}, {0,201}, {224,181}, {230,217}, {235,255},
    {189,128}, {200,131}, {210,141}, {218,159}, {255,255}, {207,238}, {211,255}, {218,255}, {255,255}
};
#elif defined (RGB_BACKLIGHT_ZEAL60) || defined (RGB_BACKLIGHT_M60_A)
#elif defined(RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_M60_A)
const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA0..LA17
	{120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
	{128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
	// LB0..LB17
	{144,0}, {160,0}, {176,0}, {192,0}, {216,0}, {224,0}, {255,255}, {255,255}, {255,255},
	{136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {255,255}, {255,255}, {255,255},
	// LC0..LC17
	{102,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {60,64}, {43,64}, {23,64},
	{108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {20,48}, {2,48}, {3,64},
	// LD0..LD17
	{124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {210,48}, {224,48},
	{116,48}, {132,48}, {148,48}, {164,48}, {144,64}, {161,64}, {181,64}, {201,64}, {221,64}
    // LA0..LA17
    {120,16}, {104,16}, {88,16}, {72,16}, {56,16}, {40,16}, {24,16}, {4,16}, {4,32},
    {128,0}, {112,0}, {96,0}, {80,0}, {64,0}, {48,0}, {32,0}, {16,0}, {0,0},
    // LB0..LB17
    {144,0}, {160,0}, {176,0}, {192,0}, {216,0}, {224,0}, {255,255}, {255,255}, {255,255},
    {136,16}, {152,16}, {168,16}, {184,16}, {200,16}, {220,16}, {255,255}, {255,255}, {255,255},
    // LC0..LC17
    {102,64}, {100,48}, {84,48}, {68,48}, {52,48}, {36,48}, {60,64}, {43,64}, {23,64},
    {108,32}, {92,32}, {76,32}, {60,32}, {44,32}, {28,32}, {20,48}, {2,48}, {3,64},
    // LD0..LD17
    {124,32}, {140,32}, {156,32}, {172,32}, {188,32}, {214,32}, {180,48}, {210,48}, {224,48},
    {116,48}, {132,48}, {148,48}, {164,48}, {144,64}, {161,64}, {181,64}, {201,64}, {221,64}
};
const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA0..LA17
	{58,129}, {70,129}, {80,139}, {89,157}, {96,181}, {101,208}, {105,238}, {109,255}, {128,247}, {58,255},
	{64,255}, {70,255}, {75,255}, {80,255}, {85,255}, {89,255}, {93,255}, {96,255},
	// LB0..LB17
	{53,255}, {48,255}, {43,255}, {39,255}, {34,255}, {32,255}, {255,255}, {255,255}, {255,255},
	{48,139}, {39,157}, {32,181}, {27,208}, {23,238}, {19,255}, {255,255}, {255,255}, {255,255},
	// LC0..LC17
	{188,255}, {183,131}, {173,143}, {165,163}, {159,188}, {154,216}, {172,252}, {170,255}, {165,255},
	{128,9}, {128,46}, {128,82}, {128,119}, {128,155}, {128,192}, {150,244}, {147,255}, {161,255},
	// LD0..LD17
	{0,27}, {0,64}, {0,101}, {0,137}, {0,174}, {255,233}, {228,201}, {235,255}, {237,255},
	{195,128}, {206,136}, {215,152}, {222,175}, {205,234}, {209,255}, {214,255}, {219,255}, {223,255}
    // LA0..LA17
    {58,129}, {70,129}, {80,139}, {89,157}, {96,181}, {101,208}, {105,238}, {109,255}, {128,247}, {58,255},
    {64,255}, {70,255}, {75,255}, {80,255}, {85,255}, {89,255}, {93,255}, {96,255},
    // LB0..LB17
    {53,255}, {48,255}, {43,255}, {39,255}, {34,255}, {32,255}, {255,255}, {255,255}, {255,255},
    {48,139}, {39,157}, {32,181}, {27,208}, {23,238}, {19,255}, {255,255}, {255,255}, {255,255},
    // LC0..LC17
    {188,255}, {183,131}, {173,143}, {165,163}, {159,188}, {154,216}, {172,252}, {170,255}, {165,255},
    {128,9}, {128,46}, {128,82}, {128,119}, {128,155}, {128,192}, {150,244}, {147,255}, {161,255},
    // LD0..LD17
    {0,27}, {0,64}, {0,101}, {0,137}, {0,174}, {255,233}, {228,201}, {235,255}, {237,255},
    {195,128}, {206,136}, {215,152}, {222,175}, {205,234}, {209,255}, {214,255}, {219,255}, {223,255}
};
#elif defined (RGB_BACKLIGHT_HS60) && defined (HS60_ANSI)
#elif defined(RGB_BACKLIGHT_HS60) && defined(HS60_ANSI)
const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA1..LA47
	{0,0}, {4,16}, {6,32}, {10,48}, {16,0}, {24,16}, {28,32}, {36,48}, {32,0}, {40,16}, {44,32}, {52,48},
	{48,0}, {56,16}, {60,32}, {68,48}, {64,0}, {72,16}, {76,32}, {84,48}, {80,0}, {88,16}, {92,32}, {100,48},
	{96,0}, {104,16}, {108,32}, {116,48}, {112,0}, {120,16}, {124,32}, {132,48}, {128,0}, {136,16}, {140,32},
	{148,48}, {144,0}, {152,16}, {156,32}, {164,48}, {160,0}, {168,16}, {172,32}, {180,48}, {176,0}, {184, 16}, {188,32},
	{255,255},// LA48 does not exist, dummy
	// LA49..LA50
	{192,0}, {200,16},
	{255,255},// LA51 does not exit, dummy
	// LA52..LA60
	{210,48}, {216,0}, {220,16}, {214,32}, {222,64}, {2,64}, {22,64}, {42,64}, {102,64},
	{255,255},// LA61 does not exit, dummy
	{162,64}, {182,64}, {202,64}
    // LA1..LA47
    {0,0}, {4,16}, {6,32}, {10,48}, {16,0}, {24,16}, {28,32}, {36,48}, {32,0}, {40,16}, {44,32}, {52,48},
    {48,0}, {56,16}, {60,32}, {68,48}, {64,0}, {72,16}, {76,32}, {84,48}, {80,0}, {88,16}, {92,32}, {100,48},
    {96,0}, {104,16}, {108,32}, {116,48}, {112,0}, {120,16}, {124,32}, {132,48}, {128,0}, {136,16}, {140,32},
    {148,48}, {144,0}, {152,16}, {156,32}, {164,48}, {160,0}, {168,16}, {172,32}, {180,48}, {176,0}, {184, 16}, {188,32},
    {255,255},// LA48 does not exist, dummy
    // LA49..LA50
    {192,0}, {200,16},
    {255,255},// LA51 does not exit, dummy
    // LA52..LA60
    {210,48}, {216,0}, {220,16}, {214,32}, {222,64}, {2,64}, {22,64}, {42,64}, {102,64},
    {255,255},// LA61 does not exit, dummy
    {162,64}, {182,64}, {202,64}
};
const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA1..LA47
	{96,255}, {109,255}, {128,242}, {148,255}, {93,255}, {105,238}, {128,192}, {154,216}, {89,255}, {101,208}, {128,155}, {159,188},
	{85,255}, {96,181}, {128,119}, {165,163}, {81,255}, {89,157}, {128,82}, {173,143}, {75,255}, {81,139}, {128,46}, {183,131},
	{70,255}, {70,129}, {129,9}, {195,128}, {64,255}, {58,129}, {255,27}, {206,136}, {58,255}, {47,139}, {255,64}, {215,152},
	{53,255}, {39,157}, {255,101}, {222,175}, {47,255}, {32,181}, {255,137}, {228,201}, {43,255}, {27,208}, {255, 174},
	{255,255},// LA48 does not exist, dummy
	// LA49..LA50
	{39,255}, {23,238},
	{255,255},// LA51 does not exit, dummy
	// LA52..LA60
	{235,255}, {33,255}, {19,255}, {255,233}, {224,255}, {160,255}, {164,255}, {169,255}, {188,255},
	{255,255},// LA61 does not exit, dummy
	{209,255}, {215,255}, {220,255}
    // LA1..LA47
    {96,255}, {109,255}, {128,242}, {148,255}, {93,255}, {105,238}, {128,192}, {154,216}, {89,255}, {101,208}, {128,155}, {159,188},
    {85,255}, {96,181}, {128,119}, {165,163}, {81,255}, {89,157}, {128,82}, {173,143}, {75,255}, {81,139}, {128,46}, {183,131},
    {70,255}, {70,129}, {129,9}, {195,128}, {64,255}, {58,129}, {255,27}, {206,136}, {58,255}, {47,139}, {255,64}, {215,152},
    {53,255}, {39,157}, {255,101}, {222,175}, {47,255}, {32,181}, {255,137}, {228,201}, {43,255}, {27,208}, {255, 174},
    {255,255},// LA48 does not exist, dummy
    // LA49..LA50
    {39,255}, {23,238},
    {255,255},// LA51 does not exit, dummy
    // LA52..LA60
    {235,255}, {33,255}, {19,255}, {255,233}, {224,255}, {160,255}, {164,255}, {169,255}, {188,255},
    {255,255},// LA61 does not exit, dummy
    {209,255}, {215,255}, {220,255}
};
#elif defined (RGB_BACKLIGHT_HS60) && defined (HS60_HHKB)
#elif defined(RGB_BACKLIGHT_HS60) && defined(HS60_HHKB)
const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA1..LA60
	{0,0}, {4,16}, {6,32}, {10,48}, {16,0}, {24,16}, {28,32}, {36,48}, {32,0}, {40,16}, {44,32}, {52,48},
	{48,0}, {56,16}, {60,32}, {68,48}, {64,0}, {72,16}, {76,32}, {84,48}, {80,0}, {88,16}, {92,32}, {100,48},
	{96,0}, {104,16}, {108,32}, {116,48}, {112,0}, {120,16}, {124,32}, {132,48}, {128,0}, {136,16}, {140,32},
	{148,48}, {144,0}, {152,16}, {156,32}, {164,48}, {160,0}, {168,16}, {172,32}, {180,48}, {176,0}, {184, 16}, {188,32},
	{224,0}, {192,0}, {200,16}, {202,48}, {224,48}, {208,0}, {220,16}, {214,32}, {220,64}, {4,64}, {24,64}, {44,64}, {112,64},
	{255,255}, {255,255}, // LA61..LA62 does not exit, dummy
	// LA63..LA64
	{180,64}, {200,64}
    // LA1..LA60
    {0,0}, {4,16}, {6,32}, {10,48}, {16,0}, {24,16}, {28,32}, {36,48}, {32,0}, {40,16}, {44,32}, {52,48},
    {48,0}, {56,16}, {60,32}, {68,48}, {64,0}, {72,16}, {76,32}, {84,48}, {80,0}, {88,16}, {92,32}, {100,48},
    {96,0}, {104,16}, {108,32}, {116,48}, {112,0}, {120,16}, {124,32}, {132,48}, {128,0}, {136,16}, {140,32},
    {148,48}, {144,0}, {152,16}, {156,32}, {164,48}, {160,0}, {168,16}, {172,32}, {180,48}, {176,0}, {184, 16}, {188,32},
    {224,0}, {192,0}, {200,16}, {202,48}, {224,48}, {208,0}, {220,16}, {214,32}, {220,64}, {4,64}, {24,64}, {44,64}, {112,64},
    {255,255}, {255,255}, // LA61..LA62 does not exit, dummy
    // LA63..LA64
    {180,64}, {200,64}
};
const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA1..LA60
	{96,255}, {109,255}, {128,242}, {148,255}, {93,255}, {105,238}, {128,192}, {154,216}, {89,255}, {101,208}, {128,155}, {159,188},
	{85,255}, {96,181}, {128,119}, {165,163}, {81,255}, {89,157}, {128,82}, {173,143}, {75,255}, {81,139}, {128,46}, {183,131},
	{70,255}, {70,129}, {129,9}, {195,128}, {64,255}, {58,129}, {255,27}, {206,136}, {58,255}, {47,139}, {255,64}, {215,152},
	{53,255}, {39,157}, {255,101}, {222,175}, {47,255}, {32,181}, {255,137}, {228,201}, {43,255}, {27,208}, {255, 174}, {32,255},
	{39,255}, {23,238}, {233,242}, {237,255}, {35,255}, {19,255}, {255,233}, {223,255}, {161,255}, {165,255}, {170,255}, {192,255},
	{255,255}, {255,255}, // LA61..LA62 does not exit, dummy
	// LA63..LA64
	{214,255}, {219,255}
    // LA1..LA60
    {96,255}, {109,255}, {128,242}, {148,255}, {93,255}, {105,238}, {128,192}, {154,216}, {89,255}, {101,208}, {128,155}, {159,188},
    {85,255}, {96,181}, {128,119}, {165,163}, {81,255}, {89,157}, {128,82}, {173,143}, {75,255}, {81,139}, {128,46}, {183,131},
    {70,255}, {70,129}, {129,9}, {195,128}, {64,255}, {58,129}, {255,27}, {206,136}, {58,255}, {47,139}, {255,64}, {215,152},
    {53,255}, {39,157}, {255,101}, {222,175}, {47,255}, {32,181}, {255,137}, {228,201}, {43,255}, {27,208}, {255, 174}, {32,255},
    {39,255}, {23,238}, {233,242}, {237,255}, {35,255}, {19,255}, {255,233}, {223,255}, {161,255}, {165,255}, {170,255}, {192,255},
    {255,255}, {255,255}, // LA61..LA62 does not exit, dummy
    // LA63..LA64
    {214,255}, {219,255}
};
#elif defined (RGB_BACKLIGHT_HS60) //HS60_ISO
#elif defined(RGB_BACKLIGHT_HS60) //HS60_ISO
const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA1..LA50
	{0,0}, {4,16}, {6,32}, {2,48}, {16,0}, {24,16}, {28,32}, {36,48}, {32,0}, {40,16}, {44,32}, {52,48}, {48,0},
	{56,16}, {60,32}, {68,48}, {64,0}, {72,16}, {76,32}, {84,48}, {80,0}, {88,16}, {92,32}, {100,48}, {96,0}, {104,16}, 
	{108,32}, {116,48}, {112,0}, {120,16}, {124,32}, {132,48}, {128,0}, {136,16}, {140,32}, {148,48}, {144,0}, {152,16},
	{156,32}, {164,48}, {160,0}, {168,16}, {172,32}, {180,48}, {176,0}, {184, 16}, {188,32}, {20,48}, {192,0}, {200,16},
	{255,255},// LA51 does not exit, dummy
	// LA52..LA60
	{210,48}, {216,0}, {220,16}, {222,24}, {222,64}, {2,64}, {22,64}, {42,64}, {102,64},
	{255,255},// LA61 does not exit, dummy
	{162,64}, {182,64}, {202,64}
    // LA1..LA50
    {0,0}, {4,16}, {6,32}, {2,48}, {16,0}, {24,16}, {28,32}, {36,48}, {32,0}, {40,16}, {44,32}, {52,48}, {48,0},
    {56,16}, {60,32}, {68,48}, {64,0}, {72,16}, {76,32}, {84,48}, {80,0}, {88,16}, {92,32}, {100,48}, {96,0}, {104,16}, 
    {108,32}, {116,48}, {112,0}, {120,16}, {124,32}, {132,48}, {128,0}, {136,16}, {140,32}, {148,48}, {144,0}, {152,16},
    {156,32}, {164,48}, {160,0}, {168,16}, {172,32}, {180,48}, {176,0}, {184, 16}, {188,32}, {20,48}, {192,0}, {200,16},
    {255,255},// LA51 does not exit, dummy
    // LA52..LA60
    {210,48}, {216,0}, {220,16}, {222,24}, {222,64}, {2,64}, {22,64}, {42,64}, {102,64},
    {255,255},// LA61 does not exit, dummy
    {162,64}, {182,64}, {202,64}
};
const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
	// LA1..LA50
	{96,255}, {109,255}, {128,242}, {147,255}, {93,255}, {105,238}, {128,192}, {154,216}, {89,255}, {101,208}, {128,155}, {159,188}, {85,255},
	{96,181}, {128,119}, {165,163}, {81,255}, {89,157}, {128,82}, {173,143}, {75,255}, {81,139}, {128,46}, {183,131}, {70,255}, {70,129},
	{129,9}, {195,128}, {64,255}, {58,129}, {255,27}, {206,136}, {58,255}, {47,139}, {255,64}, {215,152}, {53,255}, {39,157}, {255,101}, 
	{222,175}, {47,255}, {32,181}, {255,137}, {228,201}, {43,255}, {27,208}, {255, 174}, {150,246}, {39,255}, {23,238},
	{255,255},// LA51 does not exit, dummy
	// LA52..LA60
	{235,255}, {33,255}, {19,255}, {10,255}, {224,255}, {160,255}, {164,255}, {169,255}, {188,255},
	{255,255},// LA61 does not exit, dummy
	{209,255}, {215,255}, {220,255}
    // LA1..LA50
    {96,255}, {109,255}, {128,242}, {147,255}, {93,255}, {105,238}, {128,192}, {154,216}, {89,255}, {101,208}, {128,155}, {159,188}, {85,255},
    {96,181}, {128,119}, {165,163}, {81,255}, {89,157}, {128,82}, {173,143}, {75,255}, {81,139}, {128,46}, {183,131}, {70,255}, {70,129},
    {129,9}, {195,128}, {64,255}, {58,129}, {255,27}, {206,136}, {58,255}, {47,139}, {255,64}, {215,152}, {53,255}, {39,157}, {255,101}, 
    {222,175}, {47,255}, {32,181}, {255,137}, {228,201}, {43,255}, {27,208}, {255, 174}, {150,246}, {39,255}, {23,238},
    {255,255},// LA51 does not exit, dummy
    // LA52..LA60
    {235,255}, {33,255}, {19,255}, {10,255}, {224,255}, {160,255}, {164,255}, {169,255}, {188,255},
    {255,255},// LA61 does not exit, dummy
    {209,255}, {215,255}, {220,255}
};
#elif defined (RGB_BACKLIGHT_M6_B)
#elif defined(RGB_BACKLIGHT_NK65)
const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
    // LA1..LA60
    {0,0}, {4,16}, {6,32}, {10,48}, {16,0}, {24,16}, {28,32}, {36,48}, {32,0}, {40,16}, {44,32}, {52,48},
    {48,0}, {56,16}, {60,32}, {68,48}, {64,0}, {72,16}, {76,32}, {84,48}, {80,0}, {88,16}, {92,32}, {100,48},
    {96,0}, {104,16}, {108,32}, {116,48}, {112,0}, {120,16}, {124,32}, {132,48}, {128,0}, {136,16}, {140,32},
    {148,48}, {144,0}, {152,16}, {156,32}, {164,48}, {160,0}, {168,16}, {172,32}, {180,48}, {176,0}, {184, 16}, {188,32},
    {160,64}, {192,0}, {200,16}, {210,48}, {224,48}, {216,0}, {220,16}, {214,32}, {224,64}, {2,64}, {22,64}, {42,64}, {102,64},
    {255,255},// LA61 does not exit, dummy
    //LA62..LB5
    {176,64}, {192,64}, {208,64}, {240,0}, {240,16}, {240,48}, {240,64}, {240,32}
};
const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
    // LA1..LA60
    {96,255}, {109,255}, {128,242}, {148,255}, {93,255}, {105,238}, {128,192}, {154,216}, {89,255}, {101,208}, {128,155}, {159,188},
    {85,255}, {96,181}, {128,119}, {165,163}, {81,255}, {89,157}, {128,82}, {173,143}, {75,255}, {81,139}, {128,46}, {183,131},
    {70,255}, {70,129}, {129,9}, {195,128}, {64,255}, {58,129}, {255,27}, {206,136}, {58,255}, {47,139}, {255,64}, {215,152},
    {53,255}, {39,157}, {255,101}, {222,175}, {47,255}, {32,181}, {255,137}, {228,201}, {43,255}, {27,208}, {255, 174},
    {208,255}, {39,255}, {23,238}, {235,255}, {235,255}, {33,255}, {19,255}, {255,233}, {224,255}, {160,255}, {164,255}, {169,255}, {188,255},
    {255,255},// LA61 does not exit, dummy
    //LA62..LB5
    {221,255}, {225,255}, {229,255}, {22,255}, {12,255}, {244,255}, {234,255}, {255,255},
};
#elif defined(RGB_BACKLIGHT_M6_B)
// M6-B is really simple:
// 0 3 5
// 1 2 4
const Point g_map_led_to_point[BACKLIGHT_LED_COUNT] PROGMEM = {
	{0,0}, {0,16}, {16,16}, {16,0}, {32,16}, {32,0}
    {0,0}, {0,16}, {16,16}, {16,0}, {32,16}, {32,0}
};
const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
	{160,255}, {96,255}, {77,255}, {179,255}, {51,255}, {205,255}
    {160,255}, {96,255}, {77,255}, {179,255}, {51,255}, {205,255}
};
#endif



@@ 467,58 638,58 @@ const Point g_map_led_to_point_polar[BACKLIGHT_LED_COUNT] PROGMEM = {
// or having a large "bitmap" and sampling them.
void map_led_to_point( uint8_t index, Point *point )
{
	// Slightly messy way to get Point structs out of progmem.
	uint8_t *addr = (uint8_t*)&g_map_led_to_point[index];
	point->x = pgm_read_byte(addr);
	point->y = pgm_read_byte(addr+1);
    // Slightly messy way to get Point structs out of progmem.
    uint8_t *addr = (uint8_t*)&g_map_led_to_point[index];
    point->x = pgm_read_byte(addr);
    point->y = pgm_read_byte(addr+1);

#if defined (RGB_BACKLIGHT_M6_B)
	return;
#if defined(RGB_BACKLIGHT_M6_B) || defined(RGB_BACKLIGHT_HS60) || defined(RGB_BACKLIGHT_NK65)
    return;
#endif

	switch (index)
	{
		case 18+4: // LB4A
			if ( g_config.use_split_backspace )
				point->x -= 8;
			break;
#if defined (RGB_BACKLIGHT_ZEAL60)
		case 18+14: // LB14A
			if ( g_config.use_iso_enter )
				point->y += 8; // extremely pedantic
			break;
		case 54+5: // LD5A
			if ( !g_config.use_iso_enter )
				point->x -= 10;
			break;
		case 36+16: // LC16A
			if ( !g_config.use_split_left_shift )
				point->x += 8;
			break;
    switch (index)
    {
        case 18+4: // LB4A
            if ( g_config.use_split_backspace )
                point->x -= 8;
            break;
#if defined(RGB_BACKLIGHT_ZEAL60)
        case 18+14: // LB14A
            if ( g_config.use_iso_enter )
                point->y += 8; // extremely pedantic
            break;
        case 54+5: // LD5A
            if ( !g_config.use_iso_enter )
                point->x -= 10;
            break;
        case 36+16: // LC16A
            if ( !g_config.use_split_left_shift )
                point->x += 8;
            break;
#endif
#if defined (RGB_BACKLIGHT_ZEAL60) || defined (RGB_BACKLIGHT_M60_A)
		case 36+0: // LC0A
			if ( g_config.use_7u_spacebar )
				point->x += 10;
			break;
		case 36+6: // LC6A
			if ( g_config.use_7u_spacebar )
				point->x += 4;
			break;
		case 54+7: // LD7A
			if ( !g_config.use_split_right_shift )
				point->x -= 8;
			break;
#if defined(RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_M60_A)
        case 36+0: // LC0A
            if ( g_config.use_7u_spacebar )
                point->x += 10;
            break;
        case 36+6: // LC6A
            if ( g_config.use_7u_spacebar )
                point->x += 4;
            break;
        case 54+7: // LD7A
            if ( !g_config.use_split_right_shift )
                point->x -= 8;
            break;
#endif
	}
    }
}

void map_led_to_point_polar( uint8_t index, Point *point )
{
	// Slightly messy way to get Point structs out of progmem.
	uint8_t *addr = (uint8_t*)&g_map_led_to_point_polar[index];
	point->x = pgm_read_byte(addr);
	point->y = pgm_read_byte(addr+1);
    // Slightly messy way to get Point structs out of progmem.
    uint8_t *addr = (uint8_t*)&g_map_led_to_point_polar[index];
    point->x = pgm_read_byte(addr);
    point->y = pgm_read_byte(addr+1);
}

//


@@ 526,7 697,7 @@ void map_led_to_point_polar( uint8_t index, Point *point )
//


#if defined (RGB_BACKLIGHT_ZEAL65)
#if defined(RGB_BACKLIGHT_ZEAL65)
// Note: Left spacebar stab is at 4,2 (LC7)
// Right spacebar stab is at 4,9 (D14)
//


@@ 536,11 707,11 @@ void map_led_to_point_polar( uint8_t index, Point *point )
// C16, C15,  C5,  C4,  C3,  C2,  C1,  D9, D10, D11, D12,  D6,  D7,  D8, B15
// C17,  C8,  C7, ---, ---, ---, ---,  C0, ---, D14, D15, D16, D17, B17, B16
const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
	{  0+17,  0+16,  0+15,  0+14,  0+13,  0+12,  0+11,  0+10,   0+9,  18+0,  18+1,  18+2,  18+3,  18+4,  18+6 },
	{   0+7,   0+6,   0+5,   0+4,   0+3,   0+2,   0+1,   0+0,  18+9, 18+10, 18+11, 18+12, 18+13, 18+14,  18+7 },
	{   0+8, 36+14, 36+13, 36+12, 36+11, 36+10,  36+9,  54+0,  54+1,  54+2,  54+3,  54+4,  54+5,  18+5,  18+8 },
	{ 36+16, 36+15,  36+5,  36+4,  36+3,  36+2,  36+1,  54+9, 54+10, 54+11, 54+12,  54+6,  54+7,  54+8, 18+15 },
	{ 36+17,  36+8,  36+7,   255,   255,   255,   255,  36+0,  255,  54+14, 54+15, 54+16, 54+17, 18+17, 18+16 }
    {  0+17,  0+16,  0+15,  0+14,  0+13,  0+12,  0+11,  0+10,   0+9,  18+0,  18+1,  18+2,  18+3,  18+4,  18+6 },
    {   0+7,   0+6,   0+5,   0+4,   0+3,   0+2,   0+1,   0+0,  18+9, 18+10, 18+11, 18+12, 18+13, 18+14,  18+7 },
    {   0+8, 36+14, 36+13, 36+12, 36+11, 36+10,  36+9,  54+0,  54+1,  54+2,  54+3,  54+4,  54+5,  18+5,  18+8 },
    { 36+16, 36+15,  36+5,  36+4,  36+3,  36+2,  36+1,  54+9, 54+10, 54+11, 54+12,  54+6,  54+7,  54+8, 18+15 },
    { 36+17,  36+8,  36+7,   255,   255,   255,   255,  36+0,  255,  54+14, 54+15, 54+16, 54+17, 18+17, 18+16 }
};
#elif defined(RGB_BACKLIGHT_KOYU)
// Note: Left spacebar stab is at 4,4 (LC6)


@@ 552,13 723,13 @@ const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
// C16, C15,  C5,  C4,  C3,  C2,  C1,  D9, D10, D11, D12,  D6,  D7,  D8, B15
// C17,  C8,  C7,  C6, ---, ---, ---,  C0, ---, ---, D14, D15, D16, B17, B16
const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
	{  0+17,  0+16,  0+15,  0+14,  0+13,  0+12,  0+11,  0+10,   0+9,  18+0,  18+1,  18+2,  18+3,  18+4,  18+6 },
	{   0+7,   0+6,   0+5,   0+4,   0+3,   0+2,   0+1,   0+0,  18+9, 18+10, 18+11, 18+12, 18+13, 18+14,  18+7 },
	{   0+8, 36+14, 36+13, 36+12, 36+11, 36+10,  36+9,  54+0,  54+1,  54+2,  54+3,  54+4,  54+5,  18+5,  18+8 },
	{ 36+16, 36+15,  36+5,  36+4,  36+3,  36+2,  36+1,  54+9, 54+10, 54+11, 54+12,  54+6,  54+7,  54+8, 18+15 },
	{ 36+17,  36+8,  36+7,  36+6,   255,   255,   255,  36+0,  255,    255, 54+14, 54+15, 54+16, 18+17, 18+16 }
    {  0+17,  0+16,  0+15,  0+14,  0+13,  0+12,  0+11,  0+10,   0+9,  18+0,  18+1,  18+2,  18+3,  18+4,  18+6 },
    {   0+7,   0+6,   0+5,   0+4,   0+3,   0+2,   0+1,   0+0,  18+9, 18+10, 18+11, 18+12, 18+13, 18+14,  18+7 },
    {   0+8, 36+14, 36+13, 36+12, 36+11, 36+10,  36+9,  54+0,  54+1,  54+2,  54+3,  54+4,  54+5,  18+5,  18+8 },
    { 36+16, 36+15,  36+5,  36+4,  36+3,  36+2,  36+1,  54+9, 54+10, 54+11, 54+12,  54+6,  54+7,  54+8, 18+15 },
    { 36+17,  36+8,  36+7,  36+6,   255,   255,   255,  36+0,  255,    255, 54+14, 54+15, 54+16, 18+17, 18+16 }
};
#elif defined (RGB_BACKLIGHT_ZEAL60) || defined (RGB_BACKLIGHT_M60_A)
#elif defined(RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_M60_A)
// Note: Left spacebar stab is at 4,3 (LC6)
// Right spacebar stab is at 4,9 (LD13) or 4,10 (LD14)
//


@@ 568,13 739,13 @@ const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
// C16, C15,  C5,  C4,  C3,  C2,  C1,  D9, D10, D11, D12,  D6,  D7,  D8,
// C17,  C8,  C7,  C6, ---, ---, ---,  C0, ---, D13, D14, D15, D16, D17,
const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
	{  0+17,  0+16,  0+15,  0+14,  0+13,  0+12,  0+11,  0+10,   0+9,  18+0,  18+1,  18+2,  18+3,  18+4 },
	{   0+7,   0+6,   0+5,   0+4,   0+3,   0+2,   0+1,   0+0,  18+9, 18+10, 18+11, 18+12, 18+13, 18+14 },
	{   0+8, 36+14, 36+13, 36+12, 36+11, 36+10,  36+9,  54+0,  54+1,  54+2,  54+3,  54+4,  54+5,  18+5 },
	{ 36+16, 36+15,  36+5,  36+4,  36+3,  36+2,  36+1,  54+9, 54+10, 54+11, 54+12,  54+6,  54+7,  54+8 },
	{ 36+17,  36+8,  36+7,  36+6,   255,   255,   255,  36+0,  255,  54+13, 54+14, 54+15, 54+16, 54+17 }
    {  0+17,  0+16,  0+15,  0+14,  0+13,  0+12,  0+11,  0+10,   0+9,  18+0,  18+1,  18+2,  18+3,  18+4 },
    {   0+7,   0+6,   0+5,   0+4,   0+3,   0+2,   0+1,   0+0,  18+9, 18+10, 18+11, 18+12, 18+13, 18+14 },
    {   0+8, 36+14, 36+13, 36+12, 36+11, 36+10,  36+9,  54+0,  54+1,  54+2,  54+3,  54+4,  54+5,  18+5 },
    { 36+16, 36+15,  36+5,  36+4,  36+3,  36+2,  36+1,  54+9, 54+10, 54+11, 54+12,  54+6,  54+7,  54+8 },
    { 36+17,  36+8,  36+7,  36+6,   255,   255,   255,  36+0,  255,  54+13, 54+14, 54+15, 54+16, 54+17 }
};
#elif defined (RGB_BACKLIGHT_HS60) && defined (HS60_ANSI)
#elif defined(RGB_BACKLIGHT_HS60) && defined(HS60_ANSI)
//
// LA1,  LA5,  LA9,  LA13, LA17, LA21, LA25, LA29, LA33, LA37, LA41, LA45, LA49, LA53,
// LA2,  LA6,  LA10, LA14, LA18, LA22, LA26, LA30, LA34, LA38, LA42, LA46, LA50,  ---,


@@ 582,13 753,13 @@ const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
// LA4,  ---,   LA8, LA12, LA16, LA20, LA24, LA28, LA32, LA36, LA40, LA44,  ---, LA52,
// LA57, LA58, LA59,  ---,  ---,  ---, LA60,  ---,  ---,  ---, LA62, LA63, LA64, LA56
const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
	{  1-1,  5-1,  9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1 },
	{  2-1,  6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1,  255 },
	{  3-1,  7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1 },
	{  4-1,  255,  8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1,  255, 52-1 },
	{ 57-1, 58-1, 59-1,  255,  255,  255, 60-1,  255,  255,  255, 62-1, 63-1, 64-1, 56-1 }
    {  1-1,  5-1,  9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1 },
    {  2-1,  6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1,  255 },
    {  3-1,  7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1 },
    {  4-1,  255,  8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1,  255, 52-1 },
    { 57-1, 58-1, 59-1,  255,  255,  255, 60-1,  255,  255,  255, 62-1, 63-1, 64-1, 56-1 }
};
#elif defined (RGB_BACKLIGHT_HS60) && defined (HS60_HHKB)
#elif defined(RGB_BACKLIGHT_HS60) && defined(HS60_HHKB)
//
// LA1,  LA5,   LA9, LA13, LA17, LA21, LA25, LA29, LA33, LA37, LA41, LA45, LA49, LA53,
// LA2,  LA6,  LA10, LA14, LA18, LA22, LA26, LA30, LA34, LA38, LA42, LA46, LA50, LA48,


@@ 596,13 767,13 @@ const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
// LA4,  ---,   LA8, LA12, LA16, LA20, LA24, LA28, LA32, LA36, LA40, LA44, LA51, LA52,
// LA57, LA58, LA59,  ---,  ---,  ---, LA60,  ---,  ---,  ---,  ---, LA63, LA64, LA56
const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
	{  1-1,  5-1,  9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1 },
	{  2-1,  6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1, 48-1 },
	{  3-1,  7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1 },
	{  4-1,  255,  8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1, 51-1, 52-1 },
	{ 57-1, 58-1, 59-1,  255,  255,  255, 60-1,  255,  255,  255,  255, 63-1, 64-1, 56-1 }
    {  1-1,  5-1,  9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1 },
    {  2-1,  6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1, 48-1 },
    {  3-1,  7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1 },
    {  4-1,  255,  8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1, 51-1, 52-1 },
    { 57-1, 58-1, 59-1,  255,  255,  255, 60-1,  255,  255,  255,  255, 63-1, 64-1, 56-1 }
};
#elif defined (RGB_BACKLIGHT_HS60) //HS60_ISO
#elif defined(RGB_BACKLIGHT_HS60) //HS60_ISO
//
// LA1,  LA5,   LA9, LA13, LA17, LA21, LA25, LA29, LA33, LA37, LA41, LA45, LA49, LA53,
// LA2,  LA6,  LA10, LA14, LA18, LA22, LA26, LA30, LA34, LA38, LA42, LA46, LA50,  ---,


@@ 610,75 781,94 @@ const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
// LA4,  LA48,  LA8, LA12, LA16, LA20, LA24, LA28, LA32, LA36, LA40, LA44,  ---, LA52,
// LA57, LA58, LA59,  ---,  ---,  ---, LA60,  ---,  ---,  ---, LA62, LA63, LA64, LA56
const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
	{  1-1,  5-1,  9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1 },
	{  2-1,  6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1,  255 },
	{  3-1,  7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1 },
	{  4-1, 48-1,  8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1,  255, 52-1 },
	{ 57-1, 58-1, 59-1,  255,  255,  255, 60-1,  255,  255,  255, 62-1, 63-1, 64-1, 56-1 }
    {  1-1,  5-1,  9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1 },
    {  2-1,  6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1,  255 },
    {  3-1,  7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1 },
    {  4-1, 48-1,  8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1,  255, 52-1 },
    { 57-1, 58-1, 59-1,  255,  255,  255, 60-1,  255,  255,  255, 62-1, 63-1, 64-1, 56-1 }
};
#elif defined(RGB_BACKLIGHT_NK65)
//
// LA1,  LA5,  LA9,  LA13, LA17, LA21, LA25, LA29, LA33, LA37, LA41, LA45, LA49, LA53, LB1,
// LA2,  LA6,  LA10, LA14, LA18, LA22, LA26, LA30, LA34, LA38, LA42, LA46, LA50,  ---, LB2,
// LA3,  LA7,  LA11, LA15, LA19, LA23, LA27, LA31, LA35, LA39, LA43, LA47, LA54, LA55, LB5,
// LA4,  ---,   LA8, LA12, LA16, LA20, LA24, LA28, LA32, LA36, LA40, LA44, LA51, LA52, LB3,
// LA57, LA58, LA59,  ---,  ---,  ---, LA60,  ---,  ---, LA48, LA62, LA63, LA64, LA56, LB4
const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
    {  1-1,  5-1,  9-1, 13-1, 17-1, 21-1, 25-1, 29-1, 33-1, 37-1, 41-1, 45-1, 49-1, 53-1, 1+64-1 },
    {  2-1,  6-1, 10-1, 14-1, 18-1, 22-1, 26-1, 30-1, 34-1, 38-1, 42-1, 46-1, 50-1,  255, 2+64-1 },
    {  3-1,  7-1, 11-1, 15-1, 19-1, 23-1, 27-1, 31-1, 35-1, 39-1, 43-1, 47-1, 54-1, 55-1, 5+64-1 },
    {  4-1,  255,  8-1, 12-1, 16-1, 20-1, 24-1, 28-1, 32-1, 36-1, 40-1, 44-1, 51-1, 52-1, 3+64-1 },
    { 57-1, 58-1, 59-1,  255,  255,  255, 60-1,  255,  255, 48-1, 62-1, 63-1, 64-1, 56-1, 4+64-1 }
};
#elif defined (RGB_BACKLIGHT_M6_B)
#elif defined(RGB_BACKLIGHT_M6_B)
// M6-B is really simple:
// 0 3 5
// 1 2 4
const uint8_t g_map_row_column_to_led[MATRIX_ROWS][MATRIX_COLS] PROGMEM = {
	{     0,     3,     5,     1,     2,     4 }
    {     0,     3,     5,     1,     2,     4 }
};
#endif

void map_row_column_to_led( uint8_t row, uint8_t column, uint8_t *led )
{
	*led = 255;
	if ( row < MATRIX_ROWS && column < MATRIX_COLS )
	{
		*led = pgm_read_byte(&g_map_row_column_to_led[row][column]);
	}
    *led = 255;
    if ( row < MATRIX_ROWS && column < MATRIX_COLS )
    {
        *led = pgm_read_byte(&g_map_row_column_to_led[row][column]);
    }
}

void backlight_update_pwm_buffers(void)
{
#if defined (RGB_BACKLIGHT_M6_B)
	IS31FL3218_update_pwm_buffers();
#elif defined (RGB_BACKLIGHT_HS60)
	IS31FL3733_update_pwm_buffers( ISSI_ADDR_1, ISSI_ADDR_2 );
	IS31FL3733_update_led_control_registers( ISSI_ADDR_1, ISSI_ADDR_2 );
#if defined(RGB_BACKLIGHT_M6_B)
    IS31FL3218_update_pwm_buffers();
#elif defined(RGB_BACKLIGHT_HS60)
    IS31FL3733_update_pwm_buffers( ISSI_ADDR_1, 0 );
    IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
#elif defined(RGB_BACKLIGHT_NK65)
    IS31FL3733_update_pwm_buffers( ISSI_ADDR_1, 0 );
    IS31FL3733_update_pwm_buffers( ISSI_ADDR_2, 1 );
    IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
    IS31FL3733_update_led_control_registers( ISSI_ADDR_2, 1 );
#else
	IS31FL3731_update_pwm_buffers( ISSI_ADDR_1, ISSI_ADDR_2 );
	IS31FL3731_update_led_control_registers( ISSI_ADDR_1, ISSI_ADDR_2 );
    IS31FL3731_update_pwm_buffers( ISSI_ADDR_1, ISSI_ADDR_2 );
    IS31FL3731_update_led_control_registers( ISSI_ADDR_1, ISSI_ADDR_2 );
#endif
}

void backlight_set_color( int index, uint8_t red, uint8_t green, uint8_t blue )
{
#if defined (RGB_BACKLIGHT_M6_B)
	IS31FL3218_set_color( index, red, green, blue );
#elif defined (RGB_BACKLIGHT_HS60)
	IS31FL3733_set_color( index, red, green, blue );
#if defined(RGB_BACKLIGHT_M6_B)
    IS31FL3218_set_color( index, red, green, blue );
#elif defined(RGB_BACKLIGHT_HS60) || defined(RGB_BACKLIGHT_NK65)
    IS31FL3733_set_color( index, red, green, blue );
#else
	IS31FL3731_set_color( index, red, green, blue );
    IS31FL3731_set_color( index, red, green, blue );
#endif
}

void backlight_set_color_all( uint8_t red, uint8_t green, uint8_t blue )
{
#if defined (RGB_BACKLIGHT_M6_B)
	IS31FL3218_set_color_all( red, green, blue );
#elif defined (RGB_BACKLIGHT_HS60)
	IS31FL3733_set_color_all( red, green, blue );
#if defined(RGB_BACKLIGHT_M6_B)
    IS31FL3218_set_color_all( red, green, blue );
#elif defined(RGB_BACKLIGHT_HS60) || defined(RGB_BACKLIGHT_NK65)
    IS31FL3733_set_color_all( red, green, blue );
#else
	IS31FL3731_set_color_all( red, green, blue );
    IS31FL3731_set_color_all( red, green, blue );
#endif
}

void backlight_set_key_hit(uint8_t row, uint8_t column)
{
	uint8_t led;
	map_row_column_to_led(row,column,&led);
	g_key_hit[led] = 0;
    uint8_t led;
    map_row_column_to_led(row,column,&led);
    g_key_hit[led] = 0;

	g_any_key_hit = 0;
    g_any_key_hit = 0;
}

#if !defined(RGB_BACKLIGHT_HS60)
#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65)
// This is (F_CPU/1024) / 20 Hz
// = 15625 Hz / 20 Hz
// = 781


@@ 686,95 876,95 @@ void backlight_set_key_hit(uint8_t row, uint8_t column)

void backlight_timer_init(void)
{
	static uint8_t backlight_timer_is_init = 0;
	if ( backlight_timer_is_init )
	{
		return;
	}
	backlight_timer_is_init = 1;

	// Timer 3 setup
	TCCR3B = _BV(WGM32) | 			// CTC mode OCR3A as TOP
			 _BV(CS32) | _BV(CS30); // prescale by /1024
	// Set TOP value
	uint8_t sreg = SREG;
	cli();

	OCR3AH = (TIMER3_TOP >> 8) & 0xff;
	OCR3AL = TIMER3_TOP & 0xff;
	SREG = sreg;
    static uint8_t backlight_timer_is_init = 0;
    if ( backlight_timer_is_init )
    {
        return;
    }
    backlight_timer_is_init = 1;

    // Timer 3 setup
    TCCR3B = _BV(WGM32) |           // CTC mode OCR3A as TOP
             _BV(CS32) | _BV(CS30); // prescale by /1024
    // Set TOP value
    uint8_t sreg = SREG;
    cli();

    OCR3AH = (TIMER3_TOP >> 8) & 0xff;
    OCR3AL = TIMER3_TOP & 0xff;
    SREG = sreg;
}

void backlight_timer_enable(void)
{
	TIMSK3 |= _BV(OCIE3A);
    TIMSK3 |= _BV(OCIE3A);
}

void backlight_timer_disable(void)
{
	TIMSK3 &= ~_BV(OCIE3A);
    TIMSK3 &= ~_BV(OCIE3A);
}
#else //STM32, use GPT with TIM4. Enable in halconf.h
static void gpt_backlight_timer_task(GPTDriver *gptp);
// Timer setup at 200Khz, callback at 10k ticks = 20Hz
static GPTConfig gpt4cfg1 = {
	.frequency = 200000U,
	.callback  = gpt_backlight_timer_task
    .frequency = 200000U,
    .callback  = gpt_backlight_timer_task
};

void backlight_timer_init(void)
{
	gptStart(&GPTD4, &gpt4cfg1);
    gptStart(&GPTD4, &gpt4cfg1);
}

void backlight_timer_enable(void)
{
	gptStartContinuous(&GPTD4, 10000);
    gptStartContinuous(&GPTD4, 10000);
}

void backlight_timer_disable(void)
{
	gptStopTimer(&GPTD4);
    gptStopTimer(&GPTD4);
}
#endif //!defined(RGB_BACKLIGHT_HS60)
#endif //!defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65)

void backlight_set_suspend_state(bool state)
{
	g_suspend_state = state;
    g_suspend_state = state;
}

void backlight_set_indicator_state(uint8_t state)
{
	g_indicator_state = state;
    g_indicator_state = state;
}

void backlight_effect_rgb_test(void)
{
	// Mask out bits 4 and 5
	// This 2-bit value will stay the same for 16 ticks.
	switch ( (g_tick & 0x30) >> 4 )
	{
		case 0:
		{
			backlight_set_color_all( 255, 0, 0 );
			break;
		}
		case 1:
		{
			backlight_set_color_all( 0, 255, 0 );
			break;
		}
		case 2:
		{
			backlight_set_color_all( 0, 0, 255 );
			break;
		}
		case 3:
		{
			backlight_set_color_all( 255, 255, 255 );
			break;
		}
	}
    // Mask out bits 4 and 5
    // This 2-bit value will stay the same for 16 ticks.
    switch ( (g_tick & 0x30) >> 4 )
    {
        case 0:
        {
            backlight_set_color_all( 255, 0, 0 );
            break;
        }
        case 1:
        {
            backlight_set_color_all( 0, 255, 0 );
            break;
        }
        case 2:
        {
            backlight_set_color_all( 0, 0, 255 );
            break;
        }
        case 3:
        {
            backlight_set_color_all( 255, 255, 255 );
            break;
        }
    }
}

#if defined(RGB_DEBUGGING_ONLY)


@@ 785,1179 975,1221 @@ void backlight_effect_rgb_test(void)
// ONLY USE THIS FOR TESTING LEDS!
void backlight_effect_single_LED_test(void)
{
	static uint8_t color = 0; // 0,1,2 for R,G,B
	static uint8_t row = 0;
	static uint8_t column = 0;

	static uint8_t tick = 0;
	tick++;

	if ( tick > 2 )
	{
		tick = 0;
		column++;
	}
	if ( column > 14 )
	{
		column = 0;
		row++;
	}
	if ( row > 4 )
	{
		row = 0;
		color++;
	}
	if ( color > 2 )
	{
		color = 0;
	}

	uint8_t led;
	map_row_column_to_led( row, column, &led );
	backlight_set_color_all( 255, 255, 255 );
	backlight_test_led( led, color==0, color==1, color==2 );
    static uint8_t color = 0; // 0,1,2 for R,G,B
    static uint8_t row = 0;
    static uint8_t column = 0;

    static uint8_t tick = 0;
    tick++;

    if ( tick > 2 )
    {
        tick = 0;
        column++;
    }
    if ( column > 14 )
    {
        column = 0;
        row++;
    }
    if ( row > 4 )
    {
        row = 0;
        color++;
    }
    if ( color > 2 )
    {
        color = 0;
    }

    uint8_t led;
    map_row_column_to_led( row, column, &led );
    backlight_set_color_all( 255, 255, 255 );
    backlight_test_led( led, color==0, color==1, color==2 );
}
#endif // defined(RGB_DEBUGGING_ONLY)

// All LEDs off
void backlight_effect_all_off(void)
{
	backlight_set_color_all( 0, 0, 0 );
    backlight_set_color_all( 0, 0, 0 );
}

// Solid color
void backlight_effect_solid_color(void)
{
	HSV hsv = { .h = g_config.color_1.h, .s = g_config.color_1.s, .v = g_config.brightness };
	RGB rgb = hsv_to_rgb( hsv );
	backlight_set_color_all( rgb.r, rgb.g, rgb.b );
    HSV hsv = { .h = g_config.color_1.h, .s = g_config.color_1.s, .v = g_config.brightness };
    RGB rgb = hsv_to_rgb( hsv );
    backlight_set_color_all( rgb.r, rgb.g, rgb.b );
}

// alphas = color1, mods = color2
void backlight_effect_alphas_mods(void)
{
	RGB rgb1 = hsv_to_rgb( (HSV){ .h = g_config.color_1.h, .s = g_config.color_1.s, .v = g_config.brightness } );
	RGB rgb2 = hsv_to_rgb( (HSV){ .h = g_config.color_2.h, .s = g_config.color_2.s, .v = g_config.brightness } );

	for ( int row = 0; row < MATRIX_ROWS; row++ )
	{
		for ( int column = 0; column < MATRIX_COLS; column++ )
		{
			uint8_t index;
			map_row_column_to_led( row, column, &index );
			if ( index < BACKLIGHT_LED_COUNT )
			{
				if ( ( g_config.alphas_mods[row] & (1<<column) ) == 0 )
				{
					backlight_set_color( index, rgb1.r, rgb1.g, rgb1.b );
				}
				else
				{
					backlight_set_color( index, rgb2.r, rgb2.g, rgb2.b );
				}
			}
		}
	}
    RGB rgb1 = hsv_to_rgb( (HSV){ .h = g_config.color_1.h, .s = g_config.color_1.s, .v = g_config.brightness } );
    RGB rgb2 = hsv_to_rgb( (HSV){ .h = g_config.color_2.h, .s = g_config.color_2.s, .v = g_config.brightness } );

    for ( int row = 0; row < MATRIX_ROWS; row++ )
    {
        for ( int column = 0; column < MATRIX_COLS; column++ )
        {
            uint8_t index;
            map_row_column_to_led( row, column, &index );
            if ( index < BACKLIGHT_LED_COUNT )
            {
                if ( ( g_config.alphas_mods[row] & (1<<column) ) == 0 )
                {
                    backlight_set_color( index, rgb1.r, rgb1.g, rgb1.b );
                }
                else
                {
                    backlight_set_color( index, rgb2.r, rgb2.g, rgb2.b );
                }
            }
        }
    }
}

void backlight_effect_gradient_up_down(void)
{
	int16_t h1 = g_config.color_1.h;
	int16_t h2 = g_config.color_2.h;
	int16_t deltaH = h2 - h1;

	// Take the shortest path between hues
	if ( deltaH > 127 )
	{
		deltaH -= 256;
	}
	else if ( deltaH < -127 )
	{
		deltaH += 256;
	}
	// Divide delta by 4, this gives the delta per row
	deltaH /= 4;

	int16_t s1 = g_config.color_1.s;
	int16_t s2 = g_config.color_2.s;
	int16_t deltaS = ( s2 - s1 ) / 4;

	HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
	RGB rgb;
	Point point;
	for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
	{
		map_led_to_point( i, &point );
		// The y range will be 0..64, map this to 0..4
		uint8_t y = (point.y>>4);
		// Relies on hue being 8-bit and wrapping
		hsv.h = g_config.color_1.h + ( deltaH * y );
		hsv.s = g_config.color_1.s + ( deltaS * y );
		rgb = hsv_to_rgb( hsv );
		backlight_set_color( i, rgb.r, rgb.g, rgb.b );
	}
    int16_t h1 = g_config.color_1.h;
    int16_t h2 = g_config.color_2.h;
    int16_t deltaH = h2 - h1;

    // Take the shortest path between hues
    if ( deltaH > 127 )
    {
        deltaH -= 256;
    }
    else if ( deltaH < -127 )
    {
        deltaH += 256;
    }
    // Divide delta by 4, this gives the delta per row
    deltaH /= 4;

    int16_t s1 = g_config.color_1.s;
    int16_t s2 = g_config.color_2.s;
    int16_t deltaS = ( s2 - s1 ) / 4;

    HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
    RGB rgb;
    Point point;
    for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
    {
        map_led_to_point( i, &point );
        // The y range will be 0..64, map this to 0..4
        uint8_t y = (point.y>>4);
        // Relies on hue being 8-bit and wrapping
        hsv.h = g_config.color_1.h + ( deltaH * y );
        hsv.s = g_config.color_1.s + ( deltaS * y );
        rgb = hsv_to_rgb( hsv );
        backlight_set_color( i, rgb.r, rgb.g, rgb.b );
    }
}

void backlight_effect_raindrops(bool initialize)
{
	int16_t h1 = g_config.color_1.h;
	int16_t h2 = g_config.color_2.h;
	int16_t deltaH = h2 - h1;
	deltaH /= 4;

	// Take the shortest path between hues
	if ( deltaH > 127 )
	{
		deltaH -= 256;
	}
	else if ( deltaH < -127 )
	{
		deltaH += 256;
	}

	int16_t s1 = g_config.color_1.s;
	int16_t s2 = g_config.color_2.s;
	int16_t deltaS = ( s2 - s1 ) / 4;

	HSV hsv;
	RGB rgb;

	// Change one LED every tick
	uint8_t led_to_change = ( g_tick & 0x000 ) == 0 ? rand() % BACKLIGHT_LED_COUNT : 255;

	for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
	{
		// If initialize, all get set to random colors
		// If not, all but one will stay the same as before.
		if ( initialize || i == led_to_change )
		{
			hsv.h = h1 + ( deltaH * ( rand() & 0x03 ) );
			hsv.s = s1 + ( deltaS * ( rand() & 0x03 ) );
			// Override brightness with global brightness control
			hsv.v = g_config.brightness;;

			rgb = hsv_to_rgb( hsv );
			backlight_set_color( i, rgb.r, rgb.g, rgb.b );
		}
	}
    int16_t h1 = g_config.color_1.h;
    int16_t h2 = g_config.color_2.h;
    int16_t deltaH = h2 - h1;
    deltaH /= 4;

    // Take the shortest path between hues
    if ( deltaH > 127 )
    {
        deltaH -= 256;
    }
    else if ( deltaH < -127 )
    {
        deltaH += 256;
    }

    int16_t s1 = g_config.color_1.s;
    int16_t s2 = g_config.color_2.s;
    int16_t deltaS = ( s2 - s1 ) / 4;

    HSV hsv;
    RGB rgb;

    // Change one LED every tick
    uint8_t led_to_change = ( g_tick & 0x000 ) == 0 ? rand() % BACKLIGHT_LED_COUNT : 255;

    for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
    {
        // If initialize, all get set to random colors
        // If not, all but one will stay the same as before.
        if ( initialize || i == led_to_change )
        {
            hsv.h = h1 + ( deltaH * ( rand() & 0x03 ) );
            hsv.s = s1 + ( deltaS * ( rand() & 0x03 ) );
            // Override brightness with global brightness control
            hsv.v = g_config.brightness;;

            rgb = hsv_to_rgb( hsv );
            backlight_set_color( i, rgb.r, rgb.g, rgb.b );
        }
    }
}

void backlight_effect_cycle_all(void)
{
	uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;

	// Relies on hue being 8-bit and wrapping
	for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
	{
		uint16_t offset2 = g_key_hit[i]<<2;
		// stabilizer LEDs use spacebar hits
		if ( i == 36+6 || i == 54+13 || // LC6, LD13
				( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
		{
			offset2 = g_key_hit[36+0]<<2;
		}
		offset2 = (offset2<=63) ? (63-offset2) : 0;

		HSV hsv = { .h = offset+offset2, .s = 255, .v = g_config.brightness };
		RGB rgb = hsv_to_rgb( hsv );
		backlight_set_color( i, rgb.r, rgb.g, rgb.b );
	}
    uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;

    // Relies on hue being 8-bit and wrapping
    for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
    {
        uint16_t offset2 = g_key_hit[i]<<2;
#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65)
        // stabilizer LEDs use spacebar hits
        if ( i == 36+6 || i == 54+13 || // LC6, LD13
                ( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
        {
            offset2 = g_key_hit[36+0]<<2;
        }
#endif
        offset2 = (offset2<=63) ? (63-offset2) : 0;

        HSV hsv = { .h = offset+offset2, .s = 255, .v = g_config.brightness };
        RGB rgb = hsv_to_rgb( hsv );
        backlight_set_color( i, rgb.r, rgb.g, rgb.b );
    }
}

void backlight_effect_cycle_left_right(void)
{
	uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
	HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
	RGB rgb;
	Point point;
	for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
	{
		uint16_t offset2 = g_key_hit[i]<<2;
		// stabilizer LEDs use spacebar hits
		if ( i == 36+6 || i == 54+13 || // LC6, LD13
				( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
		{
			offset2 = g_key_hit[36+0]<<2;
		}
		offset2 = (offset2<=63) ? (63-offset2) : 0;

		map_led_to_point( i, &point );
		// Relies on hue being 8-bit and wrapping
		hsv.h = point.x + offset + offset2;
		rgb = hsv_to_rgb( hsv );
		backlight_set_color( i, rgb.r, rgb.g, rgb.b );
	}
    uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
    HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
    RGB rgb;
    Point point;
    for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
    {
        uint16_t offset2 = g_key_hit[i]<<2;
#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65)
        // stabilizer LEDs use spacebar hits
        if ( i == 36+6 || i == 54+13 || // LC6, LD13
                ( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
        {
            offset2 = g_key_hit[36+0]<<2;
        }
#endif
        offset2 = (offset2<=63) ? (63-offset2) : 0;

        map_led_to_point( i, &point );
        // Relies on hue being 8-bit and wrapping
        hsv.h = point.x + offset + offset2;
        rgb = hsv_to_rgb( hsv );
        backlight_set_color( i, rgb.r, rgb.g, rgb.b );
    }
}

void backlight_effect_cycle_up_down(void)
{
	uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
	HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
	RGB rgb;
	Point point;
	for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
	{
		uint16_t offset2 = g_key_hit[i]<<2;
		// stabilizer LEDs use spacebar hits
		if ( i == 36+6 || i == 54+13 || // LC6, LD13
				( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
		{
			offset2 = g_key_hit[36+0]<<2;
		}
		offset2 = (offset2<=63) ? (63-offset2) : 0;

		map_led_to_point( i, &point );
		// Relies on hue being 8-bit and wrapping
		hsv.h = point.y + offset + offset2;
		rgb = hsv_to_rgb( hsv );
		backlight_set_color( i, rgb.r, rgb.g, rgb.b );
	}
    uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
    HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
    RGB rgb;
    Point point;
    for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
    {
        uint16_t offset2 = g_key_hit[i]<<2;
#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65)
        // stabilizer LEDs use spacebar hits
        if ( i == 36+6 || i == 54+13 || // LC6, LD13
                ( g_config.use_7u_spacebar && i == 54+14 ) ) // LD14
        {
            offset2 = g_key_hit[36+0]<<2;
        }
#endif
        offset2 = (offset2<=63) ? (63-offset2) : 0;

        map_led_to_point( i, &point );
        // Relies on hue being 8-bit and wrapping
        hsv.h = point.y + offset + offset2;
        rgb = hsv_to_rgb( hsv );
        backlight_set_color( i, rgb.r, rgb.g, rgb.b );
    }
}

void backlight_effect_jellybean_raindrops( bool initialize )
{
	HSV hsv;
	RGB rgb;

	// Change one LED every tick
	uint8_t led_to_change = ( g_tick & 0x000 ) == 0 ? rand() % BACKLIGHT_LED_COUNT : 255;

	for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
	{
		// If initialize, all get set to random colors
		// If not, all but one will stay the same as before.
		if ( initialize || i == led_to_change )
		{
			hsv.h = rand() & 0xFF;
			hsv.s = rand() & 0xFF;
			// Override brightness with global brightness control
			hsv.v = g_config.brightness;;

			rgb = hsv_to_rgb( hsv );
			backlight_set_color( i, rgb.r, rgb.g, rgb.b );
		}
	}
    HSV hsv;
    RGB rgb;

    // Change one LED every tick
    uint8_t led_to_change = ( g_tick & 0x000 ) == 0 ? rand() % BACKLIGHT_LED_COUNT : 255;

    for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
    {
        // If initialize, all get set to random colors
        // If not, all but one will stay the same as before.
        if ( initialize || i == led_to_change )
        {
            hsv.h = rand() & 0xFF;
            hsv.s = rand() & 0xFF;
            // Override brightness with global brightness control
            hsv.v = g_config.brightness;;

            rgb = hsv_to_rgb( hsv );
            backlight_set_color( i, rgb.r, rgb.g, rgb.b );
        }
    }
}

void backlight_effect_cycle_radial1(void)
{
	uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
	HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
	RGB rgb;
	Point point;
	for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
	{
		map_led_to_point_polar( i, &point );
		// Relies on hue being 8-bit and wrapping
		hsv.h = point.x + offset;
		hsv.s = point.y;
		rgb = hsv_to_rgb( hsv );
		backlight_set_color( i, rgb.r, rgb.g, rgb.b );
	}
    uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;
    HSV hsv = { .h = 0, .s = 255, .v = g_config.brightness };
    RGB rgb;
    Point point;
    for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
    {
        map_led_to_point_polar( i, &point );
        // Relies on hue being 8-bit and wrapping
        hsv.h = point.x + offset;
        hsv.s = point.y;
        rgb = hsv_to_rgb( hsv );
        backlight_set_color( i, rgb.r, rgb.g, rgb.b );
    }
}

void backlight_effect_cycle_radial2(void)
{
	uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;

	HSV hsv = { .h = 0, .s = g_config.color_1.s, .v = g_config.brightness };
	RGB rgb;
	Point point;
	for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
	{
		map_led_to_point_polar( i, &point );
		uint8_t offset2 = offset + point.x;
		if ( offset2 & 0x80 )
		{
			offset2 = ~offset2;
		}
		offset2 = offset2 >> 2;
		hsv.h = g_config.color_1.h + offset2;
		hsv.s = 127 + ( point.y >> 1 );
		rgb = hsv_to_rgb( hsv );
		backlight_set_color( i, rgb.r, rgb.g, rgb.b );
	}
    uint8_t offset = ( g_tick << g_config.effect_speed ) & 0xFF;

    HSV hsv = { .h = 0, .s = g_config.color_1.s, .v = g_config.brightness };
    RGB rgb;
    Point point;
    for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
    {
        map_led_to_point_polar( i, &point );
        uint8_t offset2 = offset + point.x;
        if ( offset2 & 0x80 )
        {
            offset2 = ~offset2;
        }
        offset2 = offset2 >> 2;
        hsv.h = g_config.color_1.h + offset2;
        hsv.s = 127 + ( point.y >> 1 );
        rgb = hsv_to_rgb( hsv );
        backlight_set_color( i, rgb.r, rgb.g, rgb.b );
    }
}

#if defined(RGB_BACKLIGHT_M6_B)
void backlight_effect_custom_colors(void)
{
	RGB rgb;
	for ( uint8_t i = 0; i < 6; i++ )
	{
		HSV hsv = { .h = g_config.custom_color[i].h, .s = g_config.custom_color[i].s, .v = g_config.brightness };
		rgb = hsv_to_rgb( hsv );
		uint8_t led;
		map_row_column_to_led( 0, i, &led );
		backlight_set_color( led, rgb.r, rgb.g, rgb.b );
	}
    RGB rgb;
    for ( uint8_t i = 0; i < 6; i++ )
    {
        HSV hsv = { .h = g_config.custom_color[i].h, .s = g_config.custom_color[i].s, .v = g_config.brightness };
        rgb = hsv_to_rgb( hsv );
        uint8_t led;
        map_row_column_to_led( 0, i, &led );
        backlight_set_color( led, rgb.r, rgb.g, rgb.b );
    }
}
#endif

void backlight_effect_indicators_set_colors( uint8_t index, HS color )
{
	HSV hsv = { .h = color.h, .s = color.s, .v = g_config.brightness };
	RGB rgb = hsv_to_rgb( hsv );
	if ( index == 254 )
	{
		backlight_set_color_all( rgb.r, rgb.g, rgb.b );
	}
	else
	{
		backlight_set_color( index, rgb.r, rgb.g, rgb.b );

		// If the spacebar LED is the indicator,
		// do the same for the spacebar stabilizers
		if ( index == 36+0 ) // LC0
		{
#if defined (RGB_BACKLIGHT_ZEAL65)
			backlight_set_color( 36+7, rgb.r, rgb.g, rgb.b ); // LC7
			backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
#elif defined (RGB_BACKLIGHT_KOYU)
			backlight_set_color( 36+6, rgb.r, rgb.g, rgb.b ); // LC6
			backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
#elif defined (RGB_BACKLIGHT_ZEAL60) || defined (RGB_BACKLIGHT_M60_A)
			backlight_set_color( 36+6, rgb.r, rgb.g, rgb.b ); // LC6
			backlight_set_color( 54+13, rgb.r, rgb.g, rgb.b ); // LD13
			if ( g_config.use_7u_spacebar )
			{
				backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
			}
    HSV hsv = { .h = color.h, .s = color.s, .v = g_config.brightness };
    RGB rgb = hsv_to_rgb( hsv );
    if ( index == 254 )
    {
        backlight_set_color_all( rgb.r, rgb.g, rgb.b );
    }
    else
    {
        backlight_set_color( index, rgb.r, rgb.g, rgb.b );

        // If the spacebar LED is the indicator,
        // do the same for the spacebar stabilizers
        if ( index == 36+0 ) // LC0
        {
#if defined(RGB_BACKLIGHT_ZEAL65)
            backlight_set_color( 36+7, rgb.r, rgb.g, rgb.b ); // LC7
            backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
#elif defined(RGB_BACKLIGHT_KOYU)
            backlight_set_color( 36+6, rgb.r, rgb.g, rgb.b ); // LC6
            backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
#elif defined(RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_M60_A)
            backlight_set_color( 36+6, rgb.r, rgb.g, rgb.b ); // LC6
            backlight_set_color( 54+13, rgb.r, rgb.g, rgb.b ); // LD13
            if ( g_config.use_7u_spacebar )
            {
                backlight_set_color( 54+14, rgb.r, rgb.g, rgb.b ); // LD14
            }
#endif
		}
	}
        }
    }
}

// This runs after another backlight effect and replaces
// colors already set
void backlight_effect_indicators(void)
{
	if ( g_config.caps_lock_indicator.index != 255 &&
			( g_indicator_state & (1<<USB_LED_CAPS_LOCK) ) )
	{
		backlight_effect_indicators_set_colors( g_config.caps_lock_indicator.index, g_config.caps_lock_indicator.color );
	}

	// This if/else if structure allows higher layers to
	// override lower ones. If we set layer 3's indicator
	// to none, then it will NOT show layer 2 or layer 1
	// indicators, even if those layers are on via the
	// MO13/MO23 Fn combo magic.
	//
	// Basically we want to handle the case where layer 3 is
	// still the backlight configuration layer and we don't
	// want "all LEDs" indicators hiding the backlight effect,
	// but still allow end users to do whatever they want.
	if ( IS_LAYER_ON(3) )
	{
		if ( g_config.layer_3_indicator.index != 255 )
		{
			backlight_effect_indicators_set_colors( g_config.layer_3_indicator.index, g_config.layer_3_indicator.color );
		}
	}
	else if ( IS_LAYER_ON(2) )
	{
		if ( g_config.layer_2_indicator.index != 255 )
		{
			backlight_effect_indicators_set_colors( g_config.layer_2_indicator.index, g_config.layer_2_indicator.color );
		}
	}
	else if ( IS_LAYER_ON(1) )
	{
		if ( g_config.layer_1_indicator.index != 255 )
		{
			backlight_effect_indicators_set_colors( g_config.layer_1_indicator.index, g_config.layer_1_indicator.color );
		}
	}
    if ( g_config.caps_lock_indicator.index != 255 &&
            ( g_indicator_state & (1<<USB_LED_CAPS_LOCK) ) )
    {
        backlight_effect_indicators_set_colors( g_config.caps_lock_indicator.index, g_config.caps_lock_indicator.color );
    }

#if defined(RGB_BACKLIGHT_NK65)
    if ( g_indicator_state & (1<<USB_LED_CAPS_LOCK) )
    {
        IS31FL3733_set_color( 7+64-1, 0, 255, 0 );
    } else {
        IS31FL3733_set_color( 7+64-1, 0, 0, 0 );
    }
    if ( g_indicator_state & (1<<USB_LED_SCROLL_LOCK) )
    {
        IS31FL3733_set_color( 6+64-1, 255, 0, 255 );
    } else {
        IS31FL3733_set_color( 6+64-1, 0, 0, 0 );
    }
    if ( g_indicator_state & (1<<USB_LED_NUM_LOCK) )
    {
        IS31FL3733_set_color( 6+64-1, 0, 255, 0 );
    } else {
        IS31FL3733_set_color( 6+64-1, 0, 0, 0 );
    }
#endif

    // This if/else if structure allows higher layers to
    // override lower ones. If we set layer 3's indicator
    // to none, then it will NOT show layer 2 or layer 1
    // indicators, even if those layers are on via the
    // MO13/MO23 Fn combo magic.
    //
    // Basically we want to handle the case where layer 3 is
    // still the backlight configuration layer and we don't
    // want "all LEDs" indicators hiding the backlight effect,
    // but still allow end users to do whatever they want.
    if ( IS_LAYER_ON(3) )
    {
        if ( g_config.layer_3_indicator.index != 255 )
        {
            backlight_effect_indicators_set_colors( g_config.layer_3_indicator.index, g_config.layer_3_indicator.color );
        }
    }
    else if ( IS_LAYER_ON(2) )
    {
        if ( g_config.layer_2_indicator.index != 255 )
        {
            backlight_effect_indicators_set_colors( g_config.layer_2_indicator.index, g_config.layer_2_indicator.color );
        }
    }
    else if ( IS_LAYER_ON(1) )
    {
        if ( g_config.layer_1_indicator.index != 255 )
        {
            backlight_effect_indicators_set_colors( g_config.layer_1_indicator.index, g_config.layer_1_indicator.color );
        }
    }
}

#if !defined(RGB_BACKLIGHT_HS60)
#if !defined(RGB_BACKLIGHT_HS60) && !defined(RGB_BACKLIGHT_NK65)
ISR(TIMER3_COMPA_vect)
#else //STM32 interrupt
static void gpt_backlight_timer_task(GPTDriver *gptp)
#endif
{
	// delay 1 second before driving LEDs or doing anything else
	static uint8_t startup_tick = 0;
	if ( startup_tick < 20 )
	{
		startup_tick++;
		return;
	}

	g_tick++;

	if ( g_any_key_hit < 0xFFFFFFFF )
	{
		g_any_key_hit++;
	}

	for ( int led = 0; led < BACKLIGHT_LED_COUNT; led++ )
	{
		if ( g_key_hit[led] < 255 )
		{
			g_key_hit[led]++;
		}
	}

	// Factory default magic value
	if ( g_config.effect == 255 )
	{
		backlight_effect_rgb_test();
		return;
	}

	// Ideally we would also stop sending zeros to the LED driver PWM buffers
	// while suspended and just do a software shutdown. This is a cheap hack for now.
	bool suspend_backlight = ((g_suspend_state && g_config.disable_when_usb_suspended) ||
			(g_config.disable_after_timeout > 0 && g_any_key_hit > g_config.disable_after_timeout * 60 * 20));
	uint8_t effect = suspend_backlight ? 0 : g_config.effect;

	// Keep track of the effect used last time,
	// detect change in effect, so each effect can
	// have an optional initialization.
	static uint8_t effect_last = 255;
	bool initialize = effect != effect_last;
	effect_last = effect;

	// this gets ticked at 20 Hz.
	// each effect can opt to do calculations
	// and/or request PWM buffer updates.
	switch ( effect )
	{
		case 0:
			backlight_effect_all_off();
			break;
		case 1:
			backlight_effect_solid_color();
			break;
		case 2:
    // delay 1 second before driving LEDs or doing anything else
    static uint8_t startup_tick = 0;
    if ( startup_tick < 20 )
    {
        startup_tick++;
        return;
    }

    g_tick++;

    if ( g_any_key_hit < 0xFFFFFFFF )
    {
        g_any_key_hit++;
    }

    for ( int led = 0; led < BACKLIGHT_LED_COUNT; led++ )
    {
        if ( g_key_hit[led] < 255 )
        {
            g_key_hit[led]++;
        }
    }

    // Factory default magic value
    if ( g_config.effect == 255 )
    {
        backlight_effect_rgb_test();
        return;
    }

    // Ideally we would also stop sending zeros to the LED driver PWM buffers
    // while suspended and just do a software shutdown. This is a cheap hack for now.
    bool suspend_backlight = ((g_suspend_state && g_config.disable_when_usb_suspended) ||
            (g_config.disable_after_timeout > 0 && g_any_key_hit > g_config.disable_after_timeout * 60 * 20));
    uint8_t effect = suspend_backlight ? 0 : g_config.effect;

    // Keep track of the effect used last time,
    // detect change in effect, so each effect can
    // have an optional initialization.
    static uint8_t effect_last = 255;
    bool initialize = effect != effect_last;
    effect_last = effect;

    // this gets ticked at 20 Hz.
    // each effect can opt to do calculations
    // and/or request PWM buffer updates.
    switch ( effect )
    {
        case 0:
            backlight_effect_all_off();
            break;
        case 1:
            backlight_effect_solid_color();
            break;
        case 2:
#if defined(RGB_BACKLIGHT_M6_B)
			backlight_effect_custom_colors();
            backlight_effect_custom_colors();
#else
			backlight_effect_alphas_mods();
            backlight_effect_alphas_mods();
#endif
			break;
		case 3:
			backlight_effect_gradient_up_down();
			break;
		case 4:
			backlight_effect_raindrops( initialize );
			break;
		case 5:
			backlight_effect_cycle_all();
			break;
		case 6:
			backlight_effect_cycle_left_right();
			break;
		case 7:
			backlight_effect_cycle_up_down();
			break;
		case 8:
			backlight_effect_jellybean_raindrops( initialize );
			break;
		case 9:
			backlight_effect_cycle_radial1();
			break;
		case 10:
			backlight_effect_cycle_radial2();
			break;
		default:
			backlight_effect_all_off();
			break;
	}

	if ( ! suspend_backlight )
	{
            break;
        case 3:
            backlight_effect_gradient_up_down();
            break;
        case 4:
            backlight_effect_raindrops( initialize );
            break;
        case 5:
            backlight_effect_cycle_all();
            break;
        case 6:
            backlight_effect_cycle_left_right();
            break;
        case 7:
            backlight_effect_cycle_up_down();
            break;
        case 8:
            backlight_effect_jellybean_raindrops( initialize );
            break;
        case 9:
            backlight_effect_cycle_radial1();
            break;
        case 10:
            backlight_effect_cycle_radial2();
            break;
        default:
            backlight_effect_all_off();
            break;
    }

    if ( ! suspend_backlight )
    {
#if !defined(RGB_BACKLIGHT_M6_B)
		backlight_effect_indicators();
        backlight_effect_indicators();
#endif
	}
    }
}

void backlight_set_indicator_index( uint8_t *index, uint8_t row, uint8_t column )
{
	if ( row >= MATRIX_ROWS )
	{
		// Special value, 255=none, 254=all
		*index = row;
	}
	else
	{
		map_row_column_to_led( row, column, index );
	}
    if ( row >= MATRIX_ROWS )
    {
        // Special value, 255=none, 254=all
        *index = row;
    }
    else
    {
        map_row_column_to_led( row, column, index );
    }
}

void backlight_get_indicator_row_col( uint8_t index, uint8_t *row, uint8_t *column )
{
	if ( index == 255 || index == 254 )
	{
		// Special value, 255=none, 254=all
		*row = index;
		*column = 0;
		return;
	}
	for ( uint8_t r = 0; r < MATRIX_ROWS; r++ )
	{
		for ( uint8_t c = 0; c < MATRIX_COLS; c++ )
		{
			uint8_t i = 255;
			map_row_column_to_led( r, c, &i );
			if ( i == index )
			{
				*row = r;
				*column = c;
				return;
			}
		}
	}
    if ( index == 255 || index == 254 )
    {
        // Special value, 255=none, 254=all
        *row = index;
        *column = 0;
        return;
    }
    for ( uint8_t r = 0; r < MATRIX_ROWS; r++ )
    {
        for ( uint8_t c = 0; c < MATRIX_COLS; c++ )
        {
            uint8_t i = 255;
            map_row_column_to_led( r, c, &i );
            if ( i == index )
            {
                *row = r;
                *column = c;
                return;
            }
        }
    }
}

// Some helpers for setting/getting HSV
void _set_color( HS *color, uint8_t *data )
{
	color->h = data[0];
	color->s = data[1];
    color->h = data[0];
    color->s = data[1];
}

void _get_color( HS *color, uint8_t *data )
{
	data[0] = color->h;
	data[1] = color->s;
    data[0] = color->h;
    data[1] = color->s;
}

void backlight_config_set_value( uint8_t *data )
{
	bool reinitialize = false;
	uint8_t *value_id = &(data[0]);
	uint8_t *value_data = &(data[1]);
	switch ( *value_id )
	{
    bool reinitialize = false;
    uint8_t *value_id = &(data[0]);
    uint8_t *value_data = &(data[1]);
    switch ( *value_id )
    {
#if defined (RGB_BACKLIGHT_ZEAL60) || defined(RGB_BACKLIGHT_ZEAL65)
		case id_use_split_backspace:
		{
			g_config.use_split_backspace = (bool)*value_data;
			reinitialize = true;
			break;
		}
        case id_use_split_backspace:
        {
            g_config.use_split_backspace = (bool)*value_data;
            reinitialize = true;
            break;
        }
#endif
#if defined (RGB_BACKLIGHT_ZEAL60)
		case id_use_split_left_shift:
		{
			g_config.use_split_left_shift = (bool)*value_data;
			reinitialize = true;
			break;
		}
		case id_use_split_right_shift:
		{
			g_config.use_split_right_shift = (bool)*value_data;
			reinitialize = true;
			break;
		}
		case id_use_7u_spacebar:
		{
			g_config.use_7u_spacebar = (bool)*value_data;
			reinitialize = true;
			break;
		}
		case id_use_iso_enter:
		{
			g_config.use_iso_enter = (bool)*value_data;
			reinitialize = true;
			break;
		}
		case id_disable_hhkb_blocker_leds:
		{
			g_config.disable_hhkb_blocker_leds = (bool)*value_data;
			reinitialize = true;
			break;
		}
        case id_use_split_left_shift:
        {
            g_config.use_split_left_shift = (bool)*value_data;
            reinitialize = true;
            break;
        }
        case id_use_split_right_shift:
        {
            g_config.use_split_right_shift = (bool)*value_data;
            reinitialize = true;
            break;
        }
        case id_use_7u_spacebar:
        {
            g_config.use_7u_spacebar = (bool)*value_data;
            reinitialize = true;
            break;
        }
        case id_use_iso_enter:
        {
            g_config.use_iso_enter = (bool)*value_data;
            reinitialize = true;
            break;
        }
        case id_disable_hhkb_blocker_leds:
        {
            g_config.disable_hhkb_blocker_leds = (bool)*value_data;
            reinitialize = true;
            break;
        }
#endif
		case id_disable_when_usb_suspended:
		{
			g_config.disable_when_usb_suspended = (bool)*value_data;
			break;
		}
		case id_disable_after_timeout:
		{
			g_config.disable_after_timeout = *value_data;
			break;
		}
		case id_brightness:
		{
			g_config.brightness = *value_data;
			break;
		}
		case id_effect:
		{
			g_config.effect = *value_data;
			break;
		}
		case id_effect_speed:
		{
			g_config.effect_speed = *value_data;
			break;
		}
		case id_color_1:
		{
			_set_color( &(g_config.color_1), value_data );
			break;
		}
		case id_color_2:
		{
			_set_color( &(g_config.color_2), value_data );
			break;
		}
		case id_caps_lock_indicator_color:
		{
			_set_color( &(g_config.caps_lock_indicator.color), value_data );
			break;
		}
		case id_caps_lock_indicator_row_col:
		{
			backlight_set_indicator_index( &(g_config.caps_lock_indicator.index), value_data[0], value_data[1] );
			break;
		}
		case id_layer_1_indicator_color:
		{
			_set_color( &(g_config.layer_1_indicator.color), value_data );
			break;
		}
		case id_layer_1_indicator_row_col:
		{
			backlight_set_indicator_index( &(g_config.layer_1_indicator.index), value_data[0], value_data[1] );
			break;
		}
		case id_layer_2_indicator_color:
		{
			_set_color( &(g_config.layer_2_indicator.color), value_data );
			break;
		}
		case id_layer_2_indicator_row_col:
		{
			backlight_set_indicator_index( &(g_config.layer_2_indicator.index), value_data[0], value_data[1] );
			break;
		}
		case id_layer_3_indicator_color:
		{
			_set_color( &(g_config.layer_3_indicator.color), value_data );
			break;
		}
		case id_layer_3_indicator_row_col:
		{
			backlight_set_indicator_index( &(g_config.layer_3_indicator.index), value_data[0], value_data[1] );
			break;
		}
		case id_alphas_mods:
		{
			for ( int i=0; i<5; i++ )
			{
				g_config.alphas_mods[i] = ( *(value_data+i*2) << 8 ) | ( *(value_data+i*2+1) );
			}
		}
        case id_disable_when_usb_suspended:
        {
            g_config.disable_when_usb_suspended = (bool)*value_data;
            break;
        }
        case id_disable_after_timeout:
        {
            g_config.disable_after_timeout = *value_data;
            break;
        }
        case id_brightness:
        {
            g_config.brightness = *value_data;
            break;
        }
        case id_effect:
        {
            g_config.effect = *value_data;
            break;
        }
        case id_effect_speed:
        {
            g_config.effect_speed = *value_data;
            break;
        }
        case id_color_1:
        {
            _set_color( &(g_config.color_1), value_data );
            break;
        }
        case id_color_2:
        {
            _set_color( &(g_config.color_2), value_data );
            break;
        }
        case id_caps_lock_indicator_color:
        {
            _set_color( &(g_config.caps_lock_indicator.color), value_data );
            break;
        }
        case id_caps_lock_indicator_row_col:
        {
            backlight_set_indicator_index( &(g_config.caps_lock_indicator.index), value_data[0], value_data[1] );
            break;
        }
        case id_layer_1_indicator_color:
        {
            _set_color( &(g_config.layer_1_indicator.color), value_data );
            break;
        }
        case id_layer_1_indicator_row_col:
        {
            backlight_set_indicator_index( &(g_config.layer_1_indicator.index), value_data[0], value_data[1] );
            break;
        }
        case id_layer_2_indicator_color:
        {
            _set_color( &(g_config.layer_2_indicator.color), value_data );
            break;
        }
        case id_layer_2_indicator_row_col:
        {
            backlight_set_indicator_index( &(g_config.layer_2_indicator.index), value_data[0], value_data[1] );
            break;
        }
        case id_layer_3_indicator_color:
        {
            _set_color( &(g_config.layer_3_indicator.color), value_data );
            break;
        }
        case id_layer_3_indicator_row_col:
        {
            backlight_set_indicator_index( &(g_config.layer_3_indicator.index), value_data[0], value_data[1] );
            break;
        }
        case id_alphas_mods:
        {
            for ( int i=0; i<5; i++ )
            {
                g_config.alphas_mods[i] = ( *(value_data+i*2) << 8 ) | ( *(value_data+i*2+1) );
            }
        }
#if defined(RGB_BACKLIGHT_M6_B)
		case id_custom_color:
		{
			uint8_t index = value_data[0];
			if ( index >= 0 && index <= 6 )
			{
				_set_color( &(g_config.custom_color[index]), &(value_data[1]) );
			}
		}
        case id_custom_color:
        {
            uint8_t index = value_data[0];
            if ( index >= 0 && index <= 6 )
            {
                _set_color( &(g_config.custom_color[index]), &(value_data[1]) );
            }
        }
#endif
	}
    }

	if ( reinitialize )
	{
		backlight_init_drivers();
	}
    if ( reinitialize )
    {
        backlight_init_drivers();
    }
}

void backlight_config_get_value( uint8_t *data )
{
	uint8_t *value_id = &(data[0]);
	uint8_t *value_data = &(data[1]);
	switch ( *value_id )
	{
		case id_use_split_backspace:
		{
			*value_data = ( g_config.use_split_backspace ? 1 : 0 );
			break;
		}
		case id_use_split_left_shift:
		{
			*value_data = ( g_config.use_split_left_shift ? 1 : 0 );
			break;
		}
		case id_use_split_right_shift:
		{
			*value_data = ( g_config.use_split_right_shift ? 1 : 0 );
			break;
		}
		case id_use_7u_spacebar:
		{
			*value_data = ( g_config.use_7u_spacebar ? 1 : 0 );
			break;
		}
		case id_use_iso_enter:
		{
			*value_data = ( g_config.use_iso_enter ? 1 : 0 );
			break;
		}
		case id_disable_when_usb_suspended:
		{
			*value_data = ( g_config.disable_when_usb_suspended ? 1 : 0 );
			break;
		}
		case id_disable_hhkb_blocker_leds:
		{
			*value_data = ( g_config.disable_hhkb_blocker_leds ? 1 : 0 );
			break;
		}
		case id_disable_after_timeout:
		{
			*value_data = g_config.disable_after_timeout;
			break;
		}
		case id_brightness:
		{
			*value_data = g_config.brightness;
			break;
		}
		case id_effect:
		{
			*value_data = g_config.effect;
			break;
		}
		case id_effect_speed:
		{
			*value_data = g_config.effect_speed;
			break;
		}
		case id_color_1:
		{
			_get_color( &(g_config.color_1), value_data );
			break;
		}
		case id_color_2:
		{
			_get_color( &(g_config.color_2), value_data );
			break;
		}
		case id_caps_lock_indicator_color:
		{
			_get_color( &(g_config.caps_lock_indicator.color), value_data );
			break;
		}
		case id_caps_lock_indicator_row_col:
		{
			backlight_get_indicator_row_col( g_config.caps_lock_indicator.index, &(value_data[0]), &(value_data[1]) );
			break;
		}
		case id_layer_1_indicator_color:
		{
			_get_color( &(g_config.layer_1_indicator.color), value_data );
			break;
		}
		case id_layer_1_indicator_row_col:
		{
			backlight_get_indicator_row_col( g_config.layer_1_indicator.index, &(value_data[0]), &(value_data[1]) );
			break;
		}
		case id_layer_2_indicator_color:
		{
			_get_color( &(g_config.layer_2_indicator.color), value_data );
			break;
		}
		case id_layer_2_indicator_row_col:
		{
			backlight_get_indicator_row_col( g_config.layer_2_indicator.index, &(value_data[0]), &(value_data[1]) );
			break;
		}
		case id_layer_3_indicator_color:
		{
			_get_color( &(g_config.layer_3_indicator.color), value_data );
			break;
		}
		case id_layer_3_indicator_row_col:
		{
			backlight_get_indicator_row_col( g_config.layer_3_indicator.index, &(value_data[0]), &(value_data[1]) );
			break;
		}
		case id_alphas_mods:
		{
			for ( int i=0; i<5; i++ )
			{
				*(value_data+i*2) = g_config.alphas_mods[i] >> 8;
				*(value_data+i*2+1)	= g_config.alphas_mods[i] & 0xFF;
			}
		}
    uint8_t *value_id = &(data[0]);
    uint8_t *value_data = &(data[1]);
    switch ( *value_id )
    {
        case id_use_split_backspace:
        {
            *value_data = ( g_config.use_split_backspace ? 1 : 0 );
            break;
        }
        case id_use_split_left_shift:
        {
            *value_data = ( g_config.use_split_left_shift ? 1 : 0 );
            break;
        }
        case id_use_split_right_shift:
        {
            *value_data = ( g_config.use_split_right_shift ? 1 : 0 );
            break;
        }
        case id_use_7u_spacebar:
        {
            *value_data = ( g_config.use_7u_spacebar ? 1 : 0 );
            break;
        }
        case id_use_iso_enter:
        {
            *value_data = ( g_config.use_iso_enter ? 1 : 0 );
            break;
        }
        case id_disable_when_usb_suspended:
        {
            *value_data = ( g_config.disable_when_usb_suspended ? 1 : 0 );
            break;
        }
        case id_disable_hhkb_blocker_leds:
        {
            *value_data = ( g_config.disable_hhkb_blocker_leds ? 1 : 0 );
            break;
        }
        case id_disable_after_timeout:
        {
            *value_data = g_config.disable_after_timeout;
            break;
        }
        case id_brightness:
        {
            *value_data = g_config.brightness;
            break;
        }
        case id_effect:
        {
            *value_data = g_config.effect;
            break;
        }
        case id_effect_speed:
        {
            *value_data = g_config.effect_speed;
            break;
        }
        case id_color_1:
        {
            _get_color( &(g_config.color_1), value_data );
            break;
        }
        case id_color_2:
        {
            _get_color( &(g_config.color_2), value_data );
            break;
        }
        case id_caps_lock_indicator_color:
        {
            _get_color( &(g_config.caps_lock_indicator.color), value_data );
            break;
        }
        case id_caps_lock_indicator_row_col:
        {
            backlight_get_indicator_row_col( g_config.caps_lock_indicator.index, &(value_data[0]), &(value_data[1]) );
            break;
        }
        case id_layer_1_indicator_color:
        {
            _get_color( &(g_config.layer_1_indicator.color), value_data );
            break;
        }
        case id_layer_1_indicator_row_col:
        {
            backlight_get_indicator_row_col( g_config.layer_1_indicator.index, &(value_data[0]), &(value_data[1]) );
            break;
        }
        case id_layer_2_indicator_color:
        {
            _get_color( &(g_config.layer_2_indicator.color), value_data );
            break;
        }
        case id_layer_2_indicator_row_col:
        {
            backlight_get_indicator_row_col( g_config.layer_2_indicator.index, &(value_data[0]), &(value_data[1]) );
            break;
        }
        case id_layer_3_indicator_color:
        {
            _get_color( &(g_config.layer_3_indicator.color), value_data );
            break;
        }
        case id_layer_3_indicator_row_col:
        {
            backlight_get_indicator_row_col( g_config.layer_3_indicator.index, &(value_data[0]), &(value_data[1]) );
            break;
        }
        case id_alphas_mods:
        {
            for ( int i=0; i<5; i++ )
            {
                *(value_data+i*2) = g_config.alphas_mods[i] >> 8;
                *(value_data+i*2+1) = g_config.alphas_mods[i] & 0xFF;
            }
        }
#if defined(RGB_BACKLIGHT_M6_B)
		case id_custom_color:
		{
			uint8_t index = value_data[0];
			if ( index >= 0 && index <= 6 )
			{
				_get_color( &(g_config.custom_color[index]), &(value_data[1]) );
			}
		}
        case id_custom_color:
        {
            uint8_t index = value_data[0];
            if ( index >= 0 && index <= 6 )
            {
                _get_color( &(g_config.custom_color[index]), &(value_data[1]) );
            }
        }
#endif
	}
    }
}

void backlight_config_set_alphas_mods( uint16_t *alphas_mods )
{
	for ( int i=0; i<5; i++ )
	{
		g_config.alphas_mods[i] = alphas_mods[i];
	}
    for ( int i=0; i<5; i++ )
    {
        g_config.alphas_mods[i] = alphas_mods[i];
    }

	backlight_config_save();
    backlight_config_save();
}

void backlight_config_load(void)
{
	eeprom_read_block( &g_config, ((void*)RGB_BACKLIGHT_CONFIG_EEPROM_ADDR), sizeof(backlight_config) );
    eeprom_read_block( &g_config, ((void*)RGB_BACKLIGHT_CONFIG_EEPROM_ADDR), sizeof(backlight_config) );
}

void backlight_config_save(void)
{
	eeprom_update_block( &g_config, ((void*)RGB_BACKLIGHT_CONFIG_EEPROM_ADDR), sizeof(backlight_config) );
    eeprom_update_block( &g_config, ((void*)RGB_BACKLIGHT_CONFIG_EEPROM_ADDR), sizeof(backlight_config) );
}

void backlight_init_drivers(void)
{
	// Initialize I2C
	i2c_init();
    // Initialize I2C
    i2c_init();

#if defined(RGB_BACKLIGHT_M6_B)
	IS31FL3218_init();
    IS31FL3218_init();
#elif defined(RGB_BACKLIGHT_HS60)
	IS31FL3733_init( ISSI_ADDR_1 );

	for ( int index = 0; index < BACKLIGHT_LED_COUNT; index++ )
	{
#if defined (HS60_ANSI)
		bool enabled = !( ( index == 48-1 ) || //LA48
						  ( index == 51-1 ) || //LA51
						  ( index == 61-1 ) ); //LA61
#elif defined (HS60_HHKB)
		bool enabled = !( ( index == 61-1 ) || //LA61
						  ( index == 62-1 ) ); //LA62
    IS31FL3733_init( ISSI_ADDR_1, 0 );

    for ( int index = 0; index < DRIVER_LED_TOTAL; index++ )
    {
#if defined(HS60_ANSI)
        bool enabled = !( ( index == 48-1 ) || //LA48
                          ( index == 51-1 ) || //LA51
                          ( index == 61-1 ) ); //LA61
#elif defined(HS60_HHKB)
        bool enabled = !( ( index == 61-1 ) || //LA61
                          ( index == 62-1 ) ); //LA62
#else //HS60_ISO
		bool enabled = !( ( index == 51-1 ) || //LA51
						  ( index == 61-1 ) ); //LA61
        bool enabled = !( ( index == 51-1 ) || //LA51
                          ( index == 61-1 ) ); //LA61
#endif
				// This only caches it for later
		IS31FL3733_set_led_control_register( index, enabled, enabled, enabled );
	}
	// This actually updates the LED drivers
	IS31FL3733_update_led_control_registers( ISSI_ADDR_1, ISSI_ADDR_2 );
                // This only caches it for later
        IS31FL3733_set_led_control_register( index, enabled, enabled, enabled );
    }
    // This actually updates the LED drivers
    IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
#elif defined(RGB_BACKLIGHT_NK65)
    IS31FL3733_init( ISSI_ADDR_1, 0 );
    IS31FL3733_init( ISSI_ADDR_2, 0 );

    for ( int index = 0; index < DRIVER_LED_TOTAL; index++ )
    {
        bool enabled = !( ( index == 61-1 )   || //LA61
                          ( index > 6+64-1 ) ); //LB7-LB64
        // This only caches it for later
        IS31FL3733_set_led_control_register( index, enabled, enabled, enabled );
    }
    IS31FL3733_set_led_control_register( 7+64-1, 0, 1, 0 ); //Enable LB7 green enable for indicators
    // This actually updates the LED drivers
    IS31FL3733_update_led_control_registers( ISSI_ADDR_1, 0 );
    IS31FL3733_update_led_control_registers( ISSI_ADDR_2, 1 );
#else
	IS31FL3731_init( ISSI_ADDR_1 );
	IS31FL3731_init( ISSI_ADDR_2 );

	for ( int index = 0; index < BACKLIGHT_LED_COUNT; index++ )
	{
		// OR the possible "disabled" cases together, then NOT the result to get the enabled state
		// LC6 LD13 not present on Zeal65
#if defined (RGB_BACKLIGHT_ZEAL65)
		bool enabled = !( ( index == 18+5 && !g_config.use_split_backspace ) || // LB5
						  ( index == 36+6 ) || // LC6
						  ( index == 54+13 ) ); // LD13
#elif defined (RGB_BACKLIGHT_KOYU)
		bool enabled = !( ( index == 36+15 ) || // LC15
						  ( index == 54+13 ) || // LD13
						  ( index == 54+17 ) ); // LD17
#elif defined (RGB_BACKLIGHT_M60_A)
		bool enabled = !(
		// LB6 LB7 LB8 LB15 LB16 LB17 not present on M60-A
						  ( index == 18+6 ) || // LB6
						  ( index == 18+7 ) || // LB7
						  ( index == 18+8 ) || // LB8
						  ( index == 18+15 ) || // LB15
						  ( index == 18+16 ) || // LB16
						  ( index == 18+17 ) || // LB17
		// HHKB blockers (LC17, LD17) and ISO extra keys (LC15,LD13) not present on M60-A
						  ( index == 36+17 ) || // LC17
						  ( index == 54+17 ) || // LD17
						  ( index == 36+15 ) || // LC15
						  ( index == 54+13 ) ); // LD13
#elif defined (RGB_BACKLIGHT_ZEAL60)
		// LB6 LB7 LB8 LB15 LB16 LB17 not present on Zeal60
		bool enabled = !( ( index == 18+5 && !g_config.use_split_backspace ) || // LB5
						  ( index == 36+15 && !g_config.use_split_left_shift ) || // LC15
						  ( index == 54+8 && !g_config.use_split_right_shift ) || // LD8
						  ( index == 54+13 && g_config.use_7u_spacebar ) || // LD13
						  ( index == 36+17 && g_config.disable_hhkb_blocker_leds ) || // LC17
						  ( index == 54+17 && g_config.disable_hhkb_blocker_leds ) ||  // LD17
						  ( index == 18+6 ) || // LB6
						  ( index == 18+7 ) || // LB7
						  ( index == 18+8 ) || // LB8
						  ( index == 18+15 ) || // LB15
						  ( index == 18+16 ) || // LB16
						  ( index == 18+17 ) ); // LB17
    IS31FL3731_init( ISSI_ADDR_1 );
    IS31FL3731_init( ISSI_ADDR_2 );

    for ( int index = 0; index < DRIVER_LED_TOTAL; index++ )
    {
        // OR the possible "disabled" cases together, then NOT the result to get the enabled state
        // LC6 LD13 not present on Zeal65
#if defined(RGB_BACKLIGHT_ZEAL65)
        bool enabled = !( ( index == 18+5 && !g_config.use_split_backspace ) || // LB5
                          ( index == 36+6 ) || // LC6
                          ( index == 54+13 ) ); // LD13
#elif defined(RGB_BACKLIGHT_KOYU)
        bool enabled = !( ( index == 36+15 ) || // LC15
                          ( index == 54+13 ) || // LD13
                          ( index == 54+17 ) ); // LD17
#elif defined(RGB_BACKLIGHT_M60_A)
        bool enabled = !(
        // LB6 LB7 LB8 LB15 LB16 LB17 not present on M60-A
                          ( index == 18+6 ) || // LB6
                          ( index == 18+7 ) || // LB7
                          ( index == 18+8 ) || // LB8
                          ( index == 18+15 ) || // LB15
                          ( index == 18+16 ) || // LB16
                          ( index == 18+17 ) || // LB17
        // HHKB blockers (LC17, LD17) and ISO extra keys (LC15,LD13) not present on M60-A
                          ( index == 36+17 ) || // LC17
                          ( index == 54+17 ) || // LD17
                          ( index == 36+15 ) || // LC15
                          ( index == 54+13 ) ); // LD13
#elif defined(RGB_BACKLIGHT_ZEAL60)
        // LB6 LB7 LB8 LB15 LB16 LB17 not present on Zeal60
        bool enabled = !( ( index == 18+5 && !g_config.use_split_backspace ) || // LB5
                          ( index == 36+15 && !g_config.use_split_left_shift ) || // LC15
                          ( index == 54+8 && !g_config.use_split_right_shift ) || // LD8
                          ( index == 54+13 && g_config.use_7u_spacebar ) || // LD13
                          ( index == 36+17 && g_config.disable_hhkb_blocker_leds ) || // LC17
                          ( index == 54+17 && g_config.disable_hhkb_blocker_leds ) ||  // LD17
                          ( index == 18+6 ) || // LB6
                          ( index == 18+7 ) || // LB7
                          ( index == 18+8 ) || // LB8
                          ( index == 18+15 ) || // LB15
                          ( index == 18+16 ) || // LB16
                          ( index == 18+17 ) ); // LB17
#endif
		// This only caches it for later
		IS31FL3731_set_led_control_register( index, enabled, enabled, enabled );
	}
	// This actually updates the LED drivers
	IS31FL3731_update_led_control_registers( ISSI_ADDR_1, ISSI_ADDR_2 );
        // This only caches it for later
        IS31FL3731_set_led_control_register( index, enabled, enabled, enabled );
    }
    // This actually updates the LED drivers
    IS31FL3731_update_led_control_registers( ISSI_ADDR_1, ISSI_ADDR_2 );
#endif // !defined(RGB_BACKLIGHT_M6_B)

	// TODO: put the 1 second startup delay here?
    // TODO: put the 1 second startup delay here?

	// clear the key hits
	for ( int led=0; led<BACKLIGHT_LED_COUNT; led++ )
	{
		g_key_hit[led] = 255;
	}
    // clear the key hits
    for ( int led=0; led<BACKLIGHT_LED_COUNT; led++ )
    {
        g_key_hit[led] = 255;
    }
}

bool process_record_backlight(uint16_t keycode, keyrecord_t *record)
{
	// Record keypresses for backlight effects
	if ( record->event.pressed )
	{
		backlight_set_key_hit( record->event.key.row, record->event.key.col );
	}

	switch(keycode)
	{
		case BR_INC:
			if (record->event.pressed)
			{
				backlight_brightness_increase();
			}
			return false;
			break;
		case BR_DEC:
			if (record->event.pressed)
			{
				backlight_brightness_decrease();
			}
			return false;
			break;
		case EF_INC:
			if (record->event.pressed)
			{
				backlight_effect_increase();
			}
			return false;
			break;
		case EF_DEC:
			if (record->event.pressed)
			{
				backlight_effect_decrease();
			}
			return false;
			break;
		case ES_INC:
			if (record->event.pressed)
			{
				backlight_effect_speed_increase();
			}
			return false;
			break;
		case ES_DEC:
			if (record->event.pressed)
			{
				backlight_effect_speed_decrease();
			}
			return false;
			break;
		case H1_INC:
			if (record->event.pressed)
			{
				backlight_color_1_hue_increase();
			}
			return false;
			break;
		case H1_DEC:
			if (record->event.pressed)
			{
				backlight_color_1_hue_decrease();
			}
			return false;
			break;
		case S1_INC:
			if (record->event.pressed)
			{
				backlight_color_1_sat_increase();
			}
			return false;
			break;
		case S1_DEC:
			if (record->event.pressed)
			{
				backlight_color_1_sat_decrease();
				break;
			}
			return false;
			break;
		case H2_INC:
			if (record->event.pressed)
			{
				backlight_color_2_hue_increase();
			}
			return false;
			break;
		case H2_DEC:
			if (record->event.pressed)
			{
				backlight_color_2_hue_decrease();
			}
			return false;
			break;
		case S2_INC:
			if (record->event.pressed)
			{
				backlight_color_2_sat_increase();
			}
			return false;
			break;
		case S2_DEC:
			if (record->event.pressed)
			{
				backlight_color_2_sat_decrease();
				break;
			}
			return false;
			break;
	}

	return true;
    // Record keypresses for backlight effects
    if ( record->event.pressed )
    {
        backlight_set_key_hit( record->event.key.row, record->event.key.col );
    }

    switch(keycode)
    {
        case BR_INC:
            if (record->event.pressed)
            {
                backlight_brightness_increase();
            }
            return false;
            break;
        case BR_DEC:
            if (record->event.pressed)
            {
                backlight_brightness_decrease();
            }
            return false;
            break;
        case EF_INC:
            if (record->event.pressed)
            {
                backlight_effect_increase();
            }
            return false;
            break;
        case EF_DEC:
            if (record->event.pressed)
            {
                backlight_effect_decrease();
            }
            return false;
            break;
        case ES_INC:
            if (record->event.pressed)
            {
                backlight_effect_speed_increase();
            }
            return false;
            break;
        case ES_DEC:
            if (record->event.pressed)
            {
                backlight_effect_speed_decrease();
            }
            return false;
            break;
        case H1_INC:
            if (record->event.pressed)
            {
                backlight_color_1_hue_increase();
            }
            return false;
            break;
        case H1_DEC:
            if (record->event.pressed)
            {
                backlight_color_1_hue_decrease();
            }
            return false;
            break;
        case S1_INC:
            if (record->event.pressed)
            {
                backlight_color_1_sat_increase();
            }
            return false;
            break;
        case S1_DEC:
            if (record->event.pressed)
            {
                backlight_color_1_sat_decrease();
                break;
            }
            return false;
            break;
        case H2_INC:
            if (record->event.pressed)
            {
                backlight_color_2_hue_increase();
            }
            return false;
            break;
        case H2_DEC:
            if (record->event.pressed)
            {
                backlight_color_2_hue_decrease();
            }
            return false;
            break;
        case S2_INC:
            if (record->event.pressed)
            {
                backlight_color_2_sat_increase();
            }
            return false;
            break;
        case S2_DEC:
            if (record->event.pressed)
            {
                backlight_color_2_sat_decrease();
                break;
            }
            return false;
            break;
    }

    return true;
}

// Deals with the messy details of incrementing an integer
uint8_t increment( uint8_t value, uint8_t step, uint8_t min, uint8_t max )
{
	int16_t new_value = value;
	new_value += step;
	return MIN( MAX( new_value, min ), max );
    int16_t new_value = value;
    new_value += step;
    return MIN( MAX( new_value, min ), max );
}

uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max )
{
	int16_t new_value = value;
	new_value -= step;
	return MIN( MAX( new_value, min ), max );
    int16_t new_value = value;
    new_value -= step;
    return MIN( MAX( new_value, min ), max );
}

void backlight_effect_increase(void)
{
	g_config.effect = increment( g_config.effect, 1, 0, BACKLIGHT_EFFECT_MAX );
	backlight_config_save();
    g_config.effect = increment( g_config.effect, 1, 0, BACKLIGHT_EFFECT_MAX );
    backlight_config_save();
}

void backlight_effect_decrease(void)
{
	g_config.effect = decrement( g_config.effect, 1, 0, BACKLIGHT_EFFECT_MAX );
	backlight_config_save();
    g_config.effect = decrement( g_config.effect, 1, 0, BACKLIGHT_EFFECT_MAX );
    backlight_config_save();
}

void backlight_effect_speed_increase(void)
{
	g_config.effect_speed = increment( g_config.effect_speed, 1, 0, 3 );
	backlight_config_save();
    g_config.effect_speed = increment( g_config.effect_speed, 1, 0, 3 );
    backlight_config_save();
}

void backlight_effect_speed_decrease(void)
{
	g_config.effect_speed = decrement( g_config.effect_speed, 1, 0, 3 );
	backlight_config_save();
    g_config.effect_speed = decrement( g_config.effect_speed, 1, 0, 3 );
    backlight_config_save();
}

void backlight_brightness_increase(void)
{
	g_config.brightness = increment( g_config.brightness, 8, 0, 255 );
	backlight_config_save();
    g_config.brightness = increment( g_config.brightness, 8, 0, 255 );
    backlight_config_save();
}

void backlight_brightness_decrease(void)
{
	g_config.brightness = decrement( g_config.brightness, 8, 0, 255 );
	backlight_config_save();
    g_config.brightness = decrement( g_config.brightness, 8, 0, 255 );
    backlight_config_save();
}

void backlight_color_1_hue_increase(void)
{
	g_config.color_1.h = increment( g_config.color_1.h, 8, 0, 255 );
	backlight_config_save();
    g_config.color_1.h = increment( g_config.color_1.h, 8, 0, 255 );
    backlight_config_save();
}

void backlight_color_1_hue_decrease(void)
{
	g_config.color_1.h = decrement( g_config.color_1.h, 8, 0, 255 );
	backlight_config_save();
    g_config.color_1.h = decrement( g_config.color_1.h, 8, 0, 255 );
    backlight_config_save();
}

void backlight_color_1_sat_increase(void)
{
	g_config.color_1.s = increment( g_config.color_1.s, 8, 0, 255 );
	backlight_config_save();
    g_config.color_1.s = increment( g_config.color_1.s, 8, 0, 255 );
    backlight_config_save();
}

void backlight_color_1_sat_decrease(void)
{
	g_config.color_1.s = decrement( g_config.color_1.s, 8, 0, 255 );
	backlight_config_save();
    g_config.color_1.s = decrement( g_config.color_1.s, 8, 0, 255 );
    backlight_config_save();
}

void backlight_color_2_hue_increase(void)
{
	g_config.color_2.h = increment( g_config.color_2.h, 8, 0, 255 );
	backlight_config_save();
    g_config.color_2.h = increment( g_config.color_2.h, 8, 0, 255 );
    backlight_config_save();
}

void backlight_color_2_hue_decrease(void)
{
	g_config.color_2.h = decrement( g_config.color_2.h, 8, 0, 255 );
	backlight_config_save();
    g_config.color_2.h = decrement( g_config.color_2.h, 8, 0, 255 );
    backlight_config_save();
}

void backlight_color_2_sat_increase(void)
{
	g_config.color_2.s = increment( g_config.color_2.s, 8, 0, 255 );
	backlight_config_save();
    g_config.color_2.s = increment( g_config.color_2.s, 8, 0, 255 );
    backlight_config_save();
}

void backlight_color_2_sat_decrease(void)
{
	g_config.color_2.s = decrement( g_config.color_2.s, 8, 0, 255 );
	backlight_config_save();
    g_config.color_2.s = decrement( g_config.color_2.s, 8, 0, 255 );
    backlight_config_save();
}

#if defined(RGB_DEBUGGING_ONLY)
void backlight_test_led( uint8_t index, bool red, bool green, bool blue )
{
	for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
	{
		if ( i == index )
		{
			IS31FL3731_set_led_control_register( i, red, green, blue );
		}
		else
		{
			IS31FL3731_set_led_control_register( i, false, false, false );
		}
	}
    for ( int i=0; i<BACKLIGHT_LED_COUNT; i++ )
    {
        if ( i == index )
        {
            IS31FL3731_set_led_control_register( i, red, green, blue );
        }
        else
        {
            IS31FL3731_set_led_control_register( i, false, false, false );
        }
    }
}

void backlight_debug_led( bool state )
{
	if (state)
	{
		// Output high.
		DDRE |= (1<<6);
		PORTE |= (1<<6);
	}
	else
	{
		// Output low.
		DDRE &= ~(1<<6);
		PORTE &= ~(1<<6);
	}
    if (state)
    {
        // Output high.
        DDRE |= (1<<6);
        PORTE |= (1<<6);
    }
    else
    {
        // Output low.
        DDRE &= ~(1<<6);
        PORTE &= ~(1<<6);
    }
}
#endif // defined(RGB_DEBUGGING_ONLY)


M quantum/led_matrix_drivers.c => quantum/led_matrix_drivers.c +4 -4
@@ 53,16 53,16 @@ static void init(void) {
        #endif
    #else
        #ifdef LED_DRIVER_ADDR_1
            IS31FL3733_init(LED_DRIVER_ADDR_1);
            IS31FL3733_init(LED_DRIVER_ADDR_1, 0 );
        #endif
        #ifdef LED_DRIVER_ADDR_2
            IS31FL3733_init(LED_DRIVER_ADDR_2);
            IS31FL3733_init(LED_DRIVER_ADDR_2, 0 );
        #endif
        #ifdef LED_DRIVER_ADDR_3
            IS31FL3733_init(LED_DRIVER_ADDR_3);
            IS31FL3733_init(LED_DRIVER_ADDR_3, 0 );
        #endif
        #ifdef LED_DRIVER_ADDR_4
            IS31FL3733_init(LED_DRIVER_ADDR_4);
            IS31FL3733_init(LED_DRIVER_ADDR_4, 0 );
        #endif
    #endif


M quantum/rgb_matrix_drivers.c => quantum/rgb_matrix_drivers.c +5 -3
@@ 34,7 34,7 @@ static void init( void )
    IS31FL3731_init( DRIVER_ADDR_1 );
    IS31FL3731_init( DRIVER_ADDR_2 );
#elif defined(IS31FL3733)
    IS31FL3733_init( DRIVER_ADDR_1 );
    IS31FL3733_init( DRIVER_ADDR_1, 0 );
#else
    IS31FL3737_init( DRIVER_ADDR_1 );
#endif


@@ 53,7 53,8 @@ static void init( void )
#ifdef IS31FL3731
    IS31FL3731_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
#elif defined(IS31FL3733)
    IS31FL3733_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
    IS31FL3733_update_led_control_registers( DRIVER_ADDR_1, 0 );
    IS31FL3733_update_led_control_registers( DRIVER_ADDR_2, 1 );
#else
    IS31FL3737_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
#endif


@@ 74,7 75,8 @@ const rgb_matrix_driver_t rgb_matrix_driver = {
#elif defined(IS31FL3733)
static void flush( void )
{
    IS31FL3733_update_pwm_buffers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
    IS31FL3733_update_pwm_buffers( DRIVER_ADDR_1, 0);
    IS31FL3733_update_pwm_buffers( DRIVER_ADDR_2, 1);
}

const rgb_matrix_driver_t rgb_matrix_driver = {