Fork of the espurna firmware for `mhsw` switches
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.

187 lines
4.3 KiB

  1. /*
  2. MY9291 LED Driver Arduino library 0.1.0
  3. Copyright (c) 2016 - 2026 MaiKe Labs
  4. Copyright (C) 2017 - Xose Pérez (for the library)
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  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. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include "my9291.h"
  17. extern "C" {
  18. void os_delay_us(unsigned int);
  19. }
  20. void my9291::_di_pulse(unsigned int times) {
  21. unsigned int i;
  22. for (i = 0; i < times; i++) {
  23. digitalWrite(_pin_di, HIGH);
  24. digitalWrite(_pin_di, LOW);
  25. }
  26. }
  27. void my9291::_dcki_pulse(unsigned int times) {
  28. unsigned int i;
  29. for (i = 0; i < times; i++) {
  30. digitalWrite(_pin_dcki, HIGH);
  31. digitalWrite(_pin_dcki, LOW);
  32. }
  33. }
  34. void my9291::_set_cmd(my9291_cmd_t command) {
  35. unsigned char i;
  36. unsigned char command_data = *(unsigned char *) (&command);
  37. _command = command;
  38. // ets_intr_lock();
  39. // TStop > 12us.
  40. os_delay_us(12);
  41. // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12
  42. // pulse's rising edge convert to command mode.
  43. _di_pulse(12);
  44. // Delay >12us, begin send CMD data
  45. os_delay_us(12);
  46. // Send CMD data
  47. for (i = 0; i < 4; i++) {
  48. // DCK = 0;
  49. digitalWrite(_pin_dcki, LOW);
  50. if (command_data & 0x80) {
  51. // DI = 1;
  52. digitalWrite(_pin_di, HIGH);
  53. } else {
  54. // DI = 0;
  55. digitalWrite(_pin_di, LOW);
  56. }
  57. // DCK = 1;
  58. digitalWrite(_pin_dcki, HIGH);
  59. command_data = command_data << 1;
  60. if (command_data & 0x80) {
  61. // DI = 1;
  62. digitalWrite(_pin_di, HIGH);
  63. } else {
  64. // DI = 0;
  65. digitalWrite(_pin_di, LOW);
  66. }
  67. // DCK = 0;
  68. digitalWrite(_pin_dcki, LOW);
  69. // DI = 0;
  70. digitalWrite(_pin_di, LOW);
  71. command_data = command_data << 1;
  72. }
  73. // TStart > 12us. Delay 12 us.
  74. os_delay_us(12);
  75. // Send 16 DI pulse,at 14 pulse's falling edge store CMD data, and
  76. // at 16 pulse's falling edge convert to duty mode.
  77. _di_pulse(16);
  78. // TStop > 12us.
  79. os_delay_us(12);
  80. // ets_intr_unlock();
  81. }
  82. void my9291::send(unsigned int duty_r, unsigned int duty_g, unsigned int duty_b, unsigned int duty_w) {
  83. unsigned char i = 0;
  84. unsigned char channel = 0;
  85. unsigned char bit_length = 8;
  86. unsigned int duty_current = 0;
  87. // Definition for RGBW channels
  88. unsigned int duty[4] = { duty_r, duty_g, duty_b, duty_w };
  89. switch (_command.bit_width) {
  90. case MY9291_CMD_BIT_WIDTH_16:
  91. bit_length = 16;
  92. break;
  93. case MY9291_CMD_BIT_WIDTH_14:
  94. bit_length = 14;
  95. break;
  96. case MY9291_CMD_BIT_WIDTH_12:
  97. bit_length = 12;
  98. break;
  99. case MY9291_CMD_BIT_WIDTH_8:
  100. bit_length = 8;
  101. break;
  102. default:
  103. bit_length = 8;
  104. break;
  105. }
  106. // ets_intr_lock();
  107. // TStop > 12us.
  108. os_delay_us(12);
  109. for (channel = 0; channel < 4; channel++) { //RGBW 4CH
  110. // RGBW Channel
  111. duty_current = duty[channel];
  112. // Send 8bit/12bit/14bit/16bit Data
  113. for (i = 0; i < bit_length / 2; i++) {
  114. // DCK = 0;
  115. digitalWrite(_pin_dcki, LOW);
  116. if (duty_current & (0x01 << (bit_length - 1))) {
  117. // DI = 1;
  118. digitalWrite(_pin_di, HIGH);
  119. } else {
  120. // DI = 0;
  121. digitalWrite(_pin_di, LOW);
  122. }
  123. // DCK = 1;
  124. digitalWrite(_pin_dcki, HIGH);
  125. duty_current = duty_current << 1;
  126. if (duty_current & (0x01 << (bit_length - 1))) {
  127. // DI = 1;
  128. digitalWrite(_pin_di, HIGH);
  129. } else {
  130. // DI = 0;
  131. digitalWrite(_pin_di, LOW);
  132. }
  133. //DCK = 0;
  134. digitalWrite(_pin_dcki, LOW);
  135. //DI = 0;
  136. digitalWrite(_pin_di, LOW);
  137. duty_current = duty_current << 1;
  138. }
  139. }
  140. // TStart > 12us. Ready for send DI pulse.
  141. os_delay_us(12);
  142. // Send 8 DI pulse. After 8 pulse falling edge, store old data.
  143. _di_pulse(8);
  144. // TStop > 12us.
  145. os_delay_us(12);
  146. // ets_intr_unlock();
  147. }
  148. my9291::my9291(unsigned char di, unsigned char dcki, my9291_cmd_t command) {
  149. _pin_di = di;
  150. _pin_dcki = dcki;
  151. pinMode(_pin_di, OUTPUT);
  152. pinMode(_pin_dcki, OUTPUT);
  153. digitalWrite(_pin_di, LOW);
  154. digitalWrite(_pin_dcki, LOW);
  155. // Clear all duty register
  156. _dcki_pulse(64 / 2);
  157. _set_cmd(command);
  158. }