| 29 | |
| 30 | template <int DATA_PIN, typename TIMING, EOrder RGB_ORDER = RGB, int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 85> |
| 31 | class ClocklessController : public CPixelLEDController<RGB_ORDER> { |
| 32 | typedef typename FastPin<DATA_PIN>::port_ptr_t data_ptr_t; |
| 33 | typedef typename FastPin<DATA_PIN>::port_t data_t; |
| 34 | |
| 35 | // Convert nanoseconds to CPU cycles (compile-time) |
| 36 | // Formula: cycles = (ns * (F_CPU / 1MHz) + 500) / 1000 |
| 37 | // +500 for rounding to nearest cycle |
| 38 | static constexpr u32 NS_TO_CYCLES(u32 ns) { |
| 39 | return (ns * (F_CPU / 1000000UL) + 500) / 1000; |
| 40 | } |
| 41 | |
| 42 | static constexpr u32 T1 = NS_TO_CYCLES(TIMING::T1); // Convert nanoseconds → CPU cycles |
| 43 | static constexpr u32 T2 = NS_TO_CYCLES(TIMING::T2); |
| 44 | static constexpr u32 T3 = NS_TO_CYCLES(TIMING::T3); |
| 45 | |
| 46 | data_t mPinMask; |
| 47 | data_ptr_t mPort; |
| 48 | CMinWait<WAIT_TIME> mWait; |
| 49 | public: |
| 50 | virtual void init() FL_NOEXCEPT { |
| 51 | FastPin<DATA_PIN>::setOutput(); |
| 52 | mPinMask = FastPin<DATA_PIN>::mask(); |
| 53 | mPort = FastPin<DATA_PIN>::port(); |
| 54 | } |
| 55 | |
| 56 | virtual u16 getMaxRefreshRate() const { return 400; } |
| 57 | |
| 58 | protected: |
| 59 | |
| 60 | virtual void showPixels(PixelController<RGB_ORDER> & pixels) FL_NOEXCEPT { |
| 61 | mWait.wait(); |
| 62 | int cnt = FASTLED_INTERRUPT_RETRY_COUNT; |
| 63 | while((showRGBInternal(pixels)==0) && cnt--) { |
| 64 | #ifdef FASTLED_DEBUG_COUNT_FRAME_RETRIES |
| 65 | ++_retry_cnt; |
| 66 | #endif |
| 67 | delayMicroseconds(WAIT_TIME); |
| 68 | } |
| 69 | mWait.mark(); |
| 70 | } |
| 71 | |
| 72 | #define _ESP_ADJ (0) |
| 73 | #define _ESP_ADJ2 (0) |
| 74 | |
| 75 | template<int BITS> __attribute__ ((always_inline)) inline static bool writeBits(FASTLED_REGISTER u32 & last_mark, FASTLED_REGISTER u32 b) FL_NOEXCEPT { |
| 76 | b <<= 24; b = ~b; |
| 77 | for(FASTLED_REGISTER u32 i = BITS; i > 0; --i) { |
| 78 | while((__clock_cycles() - last_mark) < (T1+T2+T3)) { |
| 79 | ; |
| 80 | } |
| 81 | last_mark = __clock_cycles(); |
| 82 | FastPin<DATA_PIN>::hi(); |
| 83 | |
| 84 | while((__clock_cycles() - last_mark) < T1) { |
| 85 | ; |
| 86 | } |
| 87 | if(b & 0x80000000L) { FastPin<DATA_PIN>::lo(); } |
| 88 | b <<= 1; |
nothing calls this directly
no test coverage detected