PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
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.

118 lines
3.4KB

  1. #pragma once
  2. FASTLED_NAMESPACE_BEGIN
  3. #ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES
  4. extern uint32_t _frame_cnt;
  5. extern uint32_t _retry_cnt;
  6. #endif
  7. // Info on reading cycle counter from https://github.com/kbeckmann/nodemcu-firmware/blob/ws2812-dual/app/modules/ws2812.c
  8. __attribute__ ((always_inline)) inline static uint32_t __clock_cycles() {
  9. uint32_t cyc;
  10. __asm__ __volatile__ ("rsr %0,ccount":"=a" (cyc));
  11. return cyc;
  12. }
  13. #define FASTLED_HAS_CLOCKLESS 1
  14. template <int DATA_PIN, int T1, int T2, int T3, EOrder RGB_ORDER = RGB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 50>
  15. class ClocklessController : public CPixelLEDController<RGB_ORDER> {
  16. typedef typename FastPin<DATA_PIN>::port_ptr_t data_ptr_t;
  17. typedef typename FastPin<DATA_PIN>::port_t data_t;
  18. data_t mPinMask;
  19. data_ptr_t mPort;
  20. CMinWait<WAIT_TIME> mWait;
  21. public:
  22. virtual void init() {
  23. FastPin<DATA_PIN>::setOutput();
  24. mPinMask = FastPin<DATA_PIN>::mask();
  25. mPort = FastPin<DATA_PIN>::port();
  26. }
  27. virtual uint16_t getMaxRefreshRate() const { return 400; }
  28. protected:
  29. virtual void showPixels(PixelController<RGB_ORDER> & pixels) {
  30. // mWait.wait();
  31. int cnt = FASTLED_INTERRUPT_RETRY_COUNT;
  32. while((showRGBInternal(pixels)==0) && cnt--) {
  33. #ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES
  34. _retry_cnt++;
  35. #endif
  36. os_intr_unlock();
  37. delayMicroseconds(WAIT_TIME);
  38. os_intr_lock();
  39. }
  40. // mWait.mark();
  41. }
  42. #define _ESP_ADJ (0)
  43. #define _ESP_ADJ2 (0)
  44. template<int BITS> __attribute__ ((always_inline)) inline static void writeBits(register uint32_t & last_mark, register uint32_t b) {
  45. b <<= 24; b = ~b;
  46. for(register uint32_t i = BITS; i > 0; i--) {
  47. while((__clock_cycles() - last_mark) < (T1+T2+T3));
  48. last_mark = __clock_cycles();
  49. FastPin<DATA_PIN>::hi();
  50. while((__clock_cycles() - last_mark) < T1);
  51. if(b & 0x80000000L) { FastPin<DATA_PIN>::lo(); }
  52. b <<= 1;
  53. while((__clock_cycles() - last_mark) < (T1+T2));
  54. FastPin<DATA_PIN>::lo();
  55. }
  56. }
  57. // This method is made static to force making register Y available to use for data on AVR - if the method is non-static, then
  58. // gcc will use register Y for the this pointer.
  59. static uint32_t ICACHE_RAM_ATTR showRGBInternal(PixelController<RGB_ORDER> pixels) {
  60. // Setup the pixel controller and load/scale the first byte
  61. pixels.preStepFirstByteDithering();
  62. register uint32_t b = pixels.loadAndScale0();
  63. pixels.preStepFirstByteDithering();
  64. os_intr_lock();
  65. uint32_t start = __clock_cycles();
  66. uint32_t last_mark = start;
  67. while(pixels.has(1)) {
  68. // Write first byte, read next byte
  69. writeBits<8+XTRA0>(last_mark, b);
  70. b = pixels.loadAndScale1();
  71. // Write second byte, read 3rd byte
  72. writeBits<8+XTRA0>(last_mark, b);
  73. b = pixels.loadAndScale2();
  74. // Write third byte, read 1st byte of next pixel
  75. writeBits<8+XTRA0>(last_mark, b);
  76. b = pixels.advanceAndLoadAndScale0();
  77. #if (FASTLED_ALLOW_INTERRUPTS == 1)
  78. os_intr_unlock();
  79. #endif
  80. pixels.stepDithering();
  81. #if (FASTLED_ALLOW_INTERRUPTS == 1)
  82. os_intr_lock();
  83. // if interrupts took longer than 45µs, punt on the current frame
  84. if((int32_t)(__clock_cycles()-last_mark) > 0) {
  85. if((int32_t)(__clock_cycles()-last_mark) > (T1+T2+T3+((WAIT_TIME-INTERRUPT_THRESHOLD)*CLKS_PER_US))) { sei(); return 0; }
  86. }
  87. #endif
  88. };
  89. os_intr_unlock();
  90. #ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES
  91. _frame_cnt++;
  92. #endif
  93. return __clock_cycles() - start;
  94. }
  95. };
  96. FASTLED_NAMESPACE_END