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.

WS2812Serial.cpp 4.9KB

7 jaren geleden
7 jaren geleden
7 jaren geleden
7 jaren geleden
7 jaren geleden
7 jaren geleden
7 jaren geleden
7 jaren geleden
7 jaren geleden
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #include "WS2812Serial.h"
  2. bool WS2812Serial::begin()
  3. {
  4. uint32_t divisor, portconfig, hwtrigger;
  5. KINETISK_UART_t *uart;
  6. switch (pin) {
  7. #if defined(KINETISK) // Teensy 3.x
  8. case 1: // Serial1
  9. case 5:
  10. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  11. case 26:
  12. #endif
  13. uart = &KINETISK_UART0;
  14. divisor = BAUD2DIV(4000000);
  15. portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
  16. hwtrigger = DMAMUX_SOURCE_UART0_TX;
  17. SIM_SCGC4 |= SIM_SCGC4_UART0;
  18. break;
  19. case 10: // Serial2
  20. #if defined(__MK20DX128__) || defined(__MK20DX256__)
  21. case 31:
  22. #elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
  23. case 58:
  24. #endif
  25. uart = &KINETISK_UART1;
  26. divisor = BAUD2DIV2(4000000);
  27. portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
  28. hwtrigger = DMAMUX_SOURCE_UART1_TX;
  29. SIM_SCGC4 |= SIM_SCGC4_UART1;
  30. break;
  31. case 8: // Serial3
  32. case 20:
  33. uart = &KINETISK_UART2;
  34. divisor = BAUD2DIV3(4000000);
  35. portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
  36. hwtrigger = DMAMUX_SOURCE_UART2_TX;
  37. SIM_SCGC4 |= SIM_SCGC4_UART2;
  38. break;
  39. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  40. case 32: // Serial4
  41. case 62:
  42. uart = &KINETISK_UART3;
  43. divisor = BAUD2DIV3(4000000);
  44. portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
  45. hwtrigger = DMAMUX_SOURCE_UART3_TX;
  46. SIM_SCGC4 |= SIM_SCGC4_UART3;
  47. break;
  48. case 33: // Serial5
  49. uart = &KINETISK_UART4;
  50. divisor = BAUD2DIV3(4000000);
  51. portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
  52. hwtrigger = DMAMUX_SOURCE_UART4_RXTX;
  53. SIM_SCGC1 |= SIM_SCGC1_UART4;
  54. break;
  55. #endif
  56. #if defined(__MK64FX512__)
  57. case 48: // Serial6
  58. uart = &KINETISK_UART5;
  59. divisor = BAUD2DIV3(4000000);
  60. portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
  61. hwtrigger = DMAMUX_SOURCE_UART5_RXTX;
  62. SIM_SCGC1 |= SIM_SCGC1_UART5;
  63. break;
  64. #endif
  65. #elif defined(KINETISL) // Teensy LC
  66. case 1: // Serial1
  67. case 5:
  68. uart = &KINETISK_UART0;
  69. divisor = 1;
  70. portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3);
  71. hwtrigger = DMAMUX_SOURCE_UART0_TX;
  72. SIM_SCGC4 |= SIM_SCGC4_UART0;
  73. break;
  74. case 4:
  75. uart = &KINETISK_UART0;
  76. divisor = 1;
  77. portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2);
  78. hwtrigger = DMAMUX_SOURCE_UART0_TX;
  79. SIM_SCGC4 |= SIM_SCGC4_UART0;
  80. break;
  81. case 24:
  82. uart = &KINETISK_UART0;
  83. divisor = 1;
  84. portconfig = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(4);
  85. hwtrigger = DMAMUX_SOURCE_UART0_TX;
  86. SIM_SCGC4 |= SIM_SCGC4_UART0;
  87. break;
  88. #endif
  89. default:
  90. return false; // pin not supported
  91. }
  92. if (!dma) {
  93. dma = new DMAChannel;
  94. if (!dma) return false; // unable to allocate DMA channel
  95. }
  96. #if defined(KINETISK)
  97. uart->BDH = (divisor >> 13) & 0x1F;
  98. uart->BDL = (divisor >> 5) & 0xFF;
  99. uart->C4 = divisor & 0x1F;
  100. #elif defined(KINETISL)
  101. uart->BDH = (divisor >> 8) & 0x1F;
  102. uart->BDL = divisor & 0xFF;
  103. uart->C4 = 11;
  104. #endif
  105. uart->C1 = 0;
  106. uart->C2 = UART_C2_TE | UART_C2_TIE;
  107. uart->C3 = UART_C3_TXINV;
  108. uart->C5 = UART_C5_TDMAS;
  109. #if defined(KINETISK)
  110. uart->PFIFO = 0; // TODO: is this ok for Serial3-6?
  111. #endif
  112. *(portConfigRegister(pin)) = portconfig;
  113. dma->destination(uart->D);
  114. dma->triggerAtHardwareEvent(hwtrigger);
  115. memset(drawBuffer, 0, numled * 3);
  116. return true;
  117. }
  118. void WS2812Serial::show()
  119. {
  120. // wait if prior DMA still in progress
  121. #if defined(KINETISK)
  122. while ((DMA_ERQ & (1 << dma->channel))) {
  123. yield();
  124. }
  125. #elif defined(KINETISL)
  126. while ((dma->CFG->DCR & DMA_DCR_ERQ)) {
  127. yield();
  128. }
  129. #endif
  130. // copy drawing buffer to frame buffer
  131. const uint8_t *p = drawBuffer;
  132. const uint8_t *end = p + (numled * 3);
  133. uint8_t *fb = frameBuffer;
  134. while (p < end) {
  135. uint8_t b = *p++;
  136. uint8_t g = *p++;
  137. uint8_t r = *p++;
  138. uint32_t n=0;
  139. switch (config) {
  140. case WS2812_RGB: n = (r << 16) | (g << 8) | b; break;
  141. case WS2812_RBG: n = (r << 16) | (b << 8) | g; break;
  142. case WS2812_GRB: n = (g << 16) | (r << 8) | b; break;
  143. case WS2812_GBR: n = (g << 16) | (b << 8) | r; break;
  144. case WS2812_BRG: n = (b << 16) | (r << 8) | g; break;
  145. case WS2812_BGR: n = (b << 16) | (g << 8) | r; break;
  146. }
  147. const uint8_t *stop = fb + 12;
  148. do {
  149. uint8_t x = 0x08;
  150. if (!(n & 0x00800000)) x |= 0x07;
  151. if (!(n & 0x00400000)) x |= 0xE0;
  152. n <<= 2;
  153. *fb++ = x;
  154. } while (fb < stop);
  155. }
  156. // wait 300us WS2812 reset time
  157. uint32_t min_elapsed = (numled * 30) + 300;
  158. if (min_elapsed < 2500) min_elapsed = 2500;
  159. uint32_t m;
  160. while (1) {
  161. m = micros();
  162. if ((m - prior_micros) > min_elapsed) break;
  163. yield();
  164. }
  165. prior_micros = m;
  166. // start DMA transfer to update LEDs :-)
  167. #if defined(KINETISK)
  168. dma->sourceBuffer(frameBuffer, numled * 12);
  169. dma->transferSize(1);
  170. dma->transferCount(numled * 12);
  171. dma->disableOnCompletion();
  172. dma->enable();
  173. #elif defined(KINETISL)
  174. dma->CFG->SAR = frameBuffer;
  175. dma->CFG->DSR_BCR = 0x01000000;
  176. dma->CFG->DSR_BCR = numled * 12;
  177. dma->CFG->DCR = DMA_DCR_ERQ | DMA_DCR_CS | DMA_DCR_SSIZE(1) |
  178. DMA_DCR_SINC | DMA_DCR_DSIZE(1) | DMA_DCR_D_REQ;
  179. #endif
  180. }