選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

190 行
4.8KB

  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(2400000);
  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(2400000);
  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(2400000);
  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(2400000);
  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(2400000);
  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(2400000);
  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 = 2;
  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 = 2;
  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 = 2;
  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 = 9;
  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. // wait 300us WS2812 reset time
  131. uint32_t min_elapsed = ((numled * 34134) >> 10) + 300;
  132. if (min_elapsed < 2500) min_elapsed = 2500;
  133. uint32_t m;
  134. while (1) {
  135. m = micros();
  136. if ((m - prior_micros) > min_elapsed) break;
  137. yield();
  138. }
  139. prior_micros = m;
  140. const uint8_t *p = drawBuffer;
  141. const uint8_t *end = p + (numled * 3);
  142. uint8_t *fb = frameBuffer;
  143. while (p < end) {
  144. uint8_t b = *p++;
  145. uint8_t g = *p++;
  146. uint8_t r = *p++;
  147. uint32_t n=0;
  148. switch (config) {
  149. case WS2812_RGB: n = (r << 16) | (g << 8) | b; break;
  150. case WS2812_RBG: n = (r << 16) | (b << 8) | g; break;
  151. case WS2812_GRB: n = (g << 16) | (r << 8) | b; break;
  152. case WS2812_GBR: n = (g << 16) | (b << 8) | r; break;
  153. case WS2812_BRG: n = (b << 16) | (r << 8) | g; break;
  154. case WS2812_BGR: n = (b << 16) | (g << 8) | r; break;
  155. }
  156. const uint8_t *stop = fb + 8;
  157. do {
  158. uint8_t x = 0x92;
  159. if (!(n & 0x00800000)) x |= 0x01;
  160. if (!(n & 0x00400000)) x |= 0x04;
  161. if (!(n & 0x00200000)) x |= 0x20;
  162. n <<= 3;
  163. *fb++ = x;
  164. } while (fb < stop);
  165. }
  166. #if defined(KINETISK)
  167. dma->sourceBuffer(frameBuffer, numled * 8);
  168. dma->transferSize(1);
  169. dma->transferCount(numled * 8);
  170. dma->disableOnCompletion();
  171. dma->enable();
  172. #elif defined(KINETISL)
  173. dma->CFG->SAR = frameBuffer;
  174. dma->CFG->DSR_BCR = 0x01000000;
  175. dma->CFG->DSR_BCR = numled * 8;
  176. dma->CFG->DCR = DMA_DCR_ERQ | DMA_DCR_CS | DMA_DCR_SSIZE(1) |
  177. DMA_DCR_SINC | DMA_DCR_DSIZE(1) | DMA_DCR_D_REQ;
  178. #endif
  179. }