You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
4.5 KiB

  1. /* Copyright 2018 Jason Williams (Wilba)
  2. * Copyright 2021 Jamal Bouajjaj (Electro707)
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "is31fl3236.h"
  18. #include "i2c_master.h"
  19. // This is the full 8-bit address
  20. #define ISSI_DEFAULT_ADDRESS 0b0111100
  21. // These are the register addresses
  22. #define ISSI_REG_SHUTDOWN 0x00
  23. #define ISSI_REG_PWM 0x01
  24. #define ISSI_REG_CONTROL 0x26
  25. #define ISSI_REG_UPDATE 0x25
  26. #define ISSI_REG_RESET 0x4F
  27. #define ISSI_REG_G_CONTROL 0x4A
  28. #define ISSI_REG_FREQ 0x4B
  29. // Default timeout if no I2C response
  30. #define ISSI_TIMEOUT 100
  31. // Reusable buffer for transfers
  32. uint8_t g_twi_transfer_buffer[40];
  33. // IS31FL3236 has 36 PWM outputs.
  34. // If used as RGB LED driver, LEDs are assigned RGB,RGB,RGB,RGB,RGB,RGB
  35. // The RGB handling is done in user space
  36. uint8_t g_pwm_buffer[36];
  37. bool g_pwm_buffer_update_required = false;
  38. uint8_t g_led_control_registers[36];
  39. bool g_led_control_update_required = false;
  40. void IS31FL3236_write_register(uint8_t addr, uint8_t reg, uint8_t data) {
  41. g_twi_transfer_buffer[0] = reg;
  42. g_twi_transfer_buffer[1] = data;
  43. i2c_transmit(addr << 1, g_twi_transfer_buffer, 2, ISSI_TIMEOUT);
  44. }
  45. void IS31FL3236_write_pwm_buffer(uint8_t addr, uint8_t *pwm_buffer) {
  46. g_twi_transfer_buffer[0] = ISSI_REG_PWM;
  47. for (int i = 0; i < 36; i++) {
  48. g_twi_transfer_buffer[1 + i] = pwm_buffer[i];
  49. }
  50. i2c_transmit(addr << 1, g_twi_transfer_buffer, 37, ISSI_TIMEOUT);
  51. }
  52. void IS31FL3236_write_led_control_buffer(uint8_t addr, uint8_t *led_control_buffer) {
  53. g_twi_transfer_buffer[0] = ISSI_REG_CONTROL;
  54. for (int i = 0; i < 36; i++) {
  55. g_twi_transfer_buffer[1 + i] = led_control_buffer[i];
  56. }
  57. i2c_transmit(addr << 1, g_twi_transfer_buffer, 37, ISSI_TIMEOUT);
  58. }
  59. void IS31FL3236_init(uint8_t addr) {
  60. // In case we ever want to reinitialize (?)
  61. IS31FL3236_write_register(addr, ISSI_REG_RESET, 0x00);
  62. // Turn off software shutdown
  63. IS31FL3236_write_register(addr, ISSI_REG_SHUTDOWN, 0x01);
  64. // Set all PWM values to zero
  65. for (uint8_t i = 0; i < 36; i++) {
  66. IS31FL3236_write_register(addr, ISSI_REG_PWM + i, 0x00);
  67. }
  68. // Enable all channels
  69. for (uint8_t i = 0; i < 36; i++) {
  70. // Set each LED to half current and enable them
  71. // TODO: Set an option to change the current drive thru a calling function
  72. IS31FL3236_write_register(addr, ISSI_REG_CONTROL + i, 0b001);
  73. }
  74. // Load PWM registers and LED Control register data
  75. IS31FL3236_write_register(addr, ISSI_REG_UPDATE, 0x00);
  76. }
  77. void IS31FL3236_set_color(int index, uint8_t red, uint8_t green, uint8_t blue) {
  78. is31_led led;
  79. memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
  80. g_pwm_buffer[led.r] = red;
  81. g_pwm_buffer[led.g] = green;
  82. g_pwm_buffer[led.b] = blue;
  83. g_pwm_buffer_update_required = true;
  84. }
  85. void IS31FL3236_set_color_all(uint8_t red, uint8_t green, uint8_t blue) {
  86. for (int i = 0; i < 6; i++) {
  87. IS31FL3236_set_color(i, red, green, blue);
  88. }
  89. }
  90. void IS31FL3236_set_led_control_register(uint8_t index, bool red, bool green, bool blue) {
  91. is31_led led;
  92. memcpy_P(&led, (&g_is31_leds[index]), sizeof(led));
  93. g_led_control_registers[led.r] = red;
  94. g_led_control_registers[led.g] = green;
  95. g_led_control_registers[led.b] = blue;
  96. g_led_control_update_required = true;
  97. }
  98. void IS31FL3236_update_pwm_buffers(uint8_t addr) {
  99. if (g_pwm_buffer_update_required) {
  100. IS31FL3236_write_pwm_buffer(addr, g_pwm_buffer);
  101. // Load PWM registers and LED Control register data
  102. IS31FL3236_write_register(addr, ISSI_REG_UPDATE, 0x00);
  103. }
  104. g_pwm_buffer_update_required = false;
  105. }
  106. void IS31FL3236_update_led_control_registers(uint8_t addr) {
  107. if (g_led_control_update_required) {
  108. IS31FL3236_write_led_control_buffer(addr, g_led_control_registers);
  109. // Load PWM registers and LED Control register data
  110. IS31FL3236_write_register(addr, ISSI_REG_UPDATE, 0x00);
  111. }
  112. g_led_control_update_required = false;
  113. }