logo

qmk_firmware

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

is31fl3236-mono.c (5415B)


  1. // Copyright 2024 QMK
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "is31fl3236-mono.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);
  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_value(int index, uint8_t value) {
  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.v] == value) {
  98. return;
  99. }
  100. driver_buffers[led.driver].pwm_buffer[led.v] = value;
  101. driver_buffers[led.driver].pwm_buffer_dirty = true;
  102. }
  103. }
  104. void is31fl3236_set_value_all(uint8_t value) {
  105. for (uint8_t i = 0; i < IS31FL3236_LED_COUNT; i++) {
  106. is31fl3236_set_value(i, value);
  107. }
  108. }
  109. void is31fl3236_set_led_control_register(uint8_t index, bool value) {
  110. is31fl3236_led_t led;
  111. memcpy_P(&led, (&g_is31fl3236_leds[index]), sizeof(led));
  112. driver_buffers[led.driver].led_control_buffer[led.v] = value ? 0x01 : 0x00;
  113. driver_buffers[led.driver].led_control_buffer_dirty = true;
  114. }
  115. void is31fl3236_update_pwm_buffers(uint8_t index) {
  116. if (driver_buffers[index].pwm_buffer_dirty) {
  117. is31fl3236_write_pwm_buffer(index);
  118. // Load PWM registers and LED Control register data
  119. is31fl3236_write_register(index, IS31FL3236_REG_UPDATE, 0x01);
  120. driver_buffers[index].pwm_buffer_dirty = false;
  121. }
  122. }
  123. void is31fl3236_update_led_control_registers(uint8_t index) {
  124. if (driver_buffers[index].led_control_buffer_dirty) {
  125. for (uint8_t i = 0; i < IS31FL3236_LED_CONTROL_REGISTER_COUNT; i++) {
  126. is31fl3236_write_register(index, IS31FL3236_REG_LED_CONTROL + i, driver_buffers[index].led_control_buffer[i]);
  127. }
  128. driver_buffers[index].led_control_buffer_dirty = false;
  129. }
  130. }
  131. void is31fl3236_flush(void) {
  132. for (uint8_t i = 0; i < IS31FL3236_DRIVER_COUNT; i++) {
  133. is31fl3236_update_pwm_buffers(i);
  134. }
  135. }