logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

is31fl3236.c (5897B)


  1. // Copyright 2024 QMK
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "is31fl3236.h"
  4. #include "i2c_master.h"
  5. #include "gpio.h"
  6. #define IS31FL3236_PWM_REGISTER_COUNT 36
  7. #define IS31FL3236_LED_CONTROL_REGISTER_COUNT 36
  8. #ifndef IS31FL3236_I2C_TIMEOUT
  9. # define IS31FL3236_I2C_TIMEOUT 100
  10. #endif
  11. #ifndef IS31FL3236_I2C_PERSISTENCE
  12. # define IS31FL3236_I2C_PERSISTENCE 0
  13. #endif
  14. #ifndef IS31FL3236_PWM_FREQUENCY
  15. # define IS31FL3236_PWM_FREQUENCY IS31FL3236_PWM_FREQUENCY_3K_HZ // OFS - IS31FL3236A only
  16. #endif
  17. const uint8_t i2c_addresses[IS31FL3236_DRIVER_COUNT] = {
  18. IS31FL3236_I2C_ADDRESS_1,
  19. #ifdef IS31FL3236_I2C_ADDRESS_2
  20. IS31FL3236_I2C_ADDRESS_2,
  21. # ifdef IS31FL3236_I2C_ADDRESS_3
  22. IS31FL3236_I2C_ADDRESS_3,
  23. # ifdef IS31FL3236_I2C_ADDRESS_4
  24. IS31FL3236_I2C_ADDRESS_4,
  25. # endif
  26. # endif
  27. #endif
  28. };
  29. typedef struct is31fl3236_driver_t {
  30. uint8_t pwm_buffer[IS31FL3236_PWM_REGISTER_COUNT];
  31. bool pwm_buffer_dirty;
  32. uint8_t led_control_buffer[IS31FL3236_LED_CONTROL_REGISTER_COUNT];
  33. bool led_control_buffer_dirty;
  34. } PACKED is31fl3236_driver_t;
  35. is31fl3236_driver_t driver_buffers[IS31FL3236_DRIVER_COUNT] = {{
  36. .pwm_buffer = {0},
  37. .pwm_buffer_dirty = false,
  38. .led_control_buffer = {0},
  39. .led_control_buffer_dirty = false,
  40. }};
  41. void is31fl3236_write_register(uint8_t index, uint8_t reg, uint8_t data) {
  42. #if IS31FL3236_I2C_PERSISTENCE > 0
  43. for (uint8_t i = 0; i < IS31FL3236_I2C_PERSISTENCE; i++) {
  44. if (i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, IS31FL3236_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break;
  45. }
  46. #else
  47. i2c_write_register(i2c_addresses[index] << 1, reg, &data, 1, IS31FL3236_I2C_TIMEOUT);
  48. #endif
  49. }
  50. void is31fl3236_write_pwm_buffer(uint8_t index) {
  51. #if IS31FL3236_I2C_PERSISTENCE > 0
  52. for (uint8_t i = 0; i < IS31FL3236_I2C_PERSISTENCE; i++) {
  53. if (i2c_write_register(i2c_addresses[index] << 1, IS31FL3236_REG_PWM, driver_buffers[index].pwm_buffer, 36, IS31FL3236_I2C_TIMEOUT) == I2C_STATUS_SUCCESS) break;
  54. }
  55. #else
  56. i2c_write_register(i2c_addresses[index] << 1, IS31FL3236_REG_PWM, driver_buffers[index].pwm_buffer, 36, IS31FL3236_I2C_TIMEOUT);
  57. #endif
  58. }
  59. void is31fl3236_init_drivers(void) {
  60. i2c_init();
  61. #if defined(IS31FL3236_SDB_PIN)
  62. gpio_set_pin_output(IS31FL3236_SDB_PIN);
  63. gpio_write_pin_high(IS31FL3236_SDB_PIN);
  64. #endif
  65. for (uint8_t i = 0; i < IS31FL3236_DRIVER_COUNT; i++) {
  66. is31fl3236_init(i);
  67. }
  68. for (uint8_t i = 0; i < IS31FL3236_LED_COUNT; i++) {
  69. is31fl3236_set_led_control_register(i, true, true, true);
  70. }
  71. for (uint8_t i = 0; i < IS31FL3236_DRIVER_COUNT; i++) {
  72. is31fl3236_update_led_control_registers(i);
  73. }
  74. }
  75. void is31fl3236_init(uint8_t index) {
  76. // In case we ever want to reinitialize (?)
  77. is31fl3236_write_register(index, IS31FL3236_REG_RESET, 0x00);
  78. // Turn off software shutdown
  79. is31fl3236_write_register(index, IS31FL3236_REG_SHUTDOWN, 0x01);
  80. // Set all PWM values to zero
  81. for (uint8_t i = 0; i < IS31FL3236_PWM_REGISTER_COUNT; i++) {
  82. is31fl3236_write_register(index, IS31FL3236_REG_PWM + i, 0x00);
  83. }
  84. // turn off all LEDs in the LED control register
  85. for (uint8_t i = 0; i < IS31FL3236_LED_CONTROL_REGISTER_COUNT; i++) {
  86. is31fl3236_write_register(index, IS31FL3236_REG_LED_CONTROL + i, 0x00);
  87. }
  88. // Set PWM frequency (IS31FL3236A)
  89. is31fl3236_write_register(index, IS31FL3236_REG_PWM_FREQUENCY, IS31FL3236_PWM_FREQUENCY);
  90. // Load PWM registers and LED Control register data
  91. is31fl3236_write_register(index, IS31FL3236_REG_UPDATE, 0x01);
  92. }
  93. void is31fl3236_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
  94. is31fl3236_led_t led;
  95. if (index < IS31FL3236_LED_COUNT) {
  96. memcpy_P(&led, (&g_is31fl3236_leds[index]), sizeof(led));
  97. if (driver_buffers[led.driver].pwm_buffer[led.r] == red && driver_buffers[led.driver].pwm_buffer[led.g] == green && driver_buffers[led.driver].pwm_buffer[led.b] == blue) {
  98. return;
  99. }
  100. driver_buffers[led.driver].pwm_buffer[led.r] = red;
  101. driver_buffers[led.driver].pwm_buffer[led.g] = green;
  102. driver_buffers[led.driver].pwm_buffer[led.b] = blue;
  103. driver_buffers[led.driver].pwm_buffer_dirty = true;
  104. }
  105. }
  106. void is31fl3236_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
  107. for (uint8_t i = 0; i < IS31FL3236_LED_COUNT; i++) {
  108. is31fl3236_set_color(i, red, green, blue);
  109. }
  110. }
  111. void is31fl3236_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
  112. is31fl3236_led_t led;
  113. memcpy_P(&led, (&g_is31fl3236_leds[index]), sizeof(led));
  114. driver_buffers[led.driver].led_control_buffer[led.r] = red ? 0x01 : 0x00;
  115. driver_buffers[led.driver].led_control_buffer[led.g] = green ? 0x01 : 0x00;
  116. driver_buffers[led.driver].led_control_buffer[led.b] = blue ? 0x01 : 0x00;
  117. driver_buffers[led.driver].led_control_buffer_dirty = true;
  118. }
  119. void is31fl3236_update_pwm_buffers(uint8_t index) {
  120. if (driver_buffers[index].pwm_buffer_dirty) {
  121. is31fl3236_write_pwm_buffer(index);
  122. // Load PWM registers and LED Control register data
  123. is31fl3236_write_register(index, IS31FL3236_REG_UPDATE, 0x01);
  124. driver_buffers[index].pwm_buffer_dirty = false;
  125. }
  126. }
  127. void is31fl3236_update_led_control_registers(uint8_t index) {
  128. if (driver_buffers[index].led_control_buffer_dirty) {
  129. for (uint8_t i = 0; i < IS31FL3236_LED_CONTROL_REGISTER_COUNT; i++) {
  130. is31fl3236_write_register(index, IS31FL3236_REG_LED_CONTROL + i, driver_buffers[index].led_control_buffer[i]);
  131. }
  132. driver_buffers[index].led_control_buffer_dirty = false;
  133. }
  134. }
  135. void is31fl3236_flush(void) {
  136. for (uint8_t i = 0; i < IS31FL3236_DRIVER_COUNT; i++) {
  137. is31fl3236_update_pwm_buffers(i);
  138. }
  139. }