MCPcopy Create free account
hub / github.com/FastLED/FastLED / ClocklessController

Class ClocklessController

src/platforms/arm/lpc/clockless_arm_lpc_plu.h:296–400  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

294template <fl::u8 DATA_PIN, typename TIMING, EOrder RGB_ORDER = RGB,
295 int XTRA0 = 0, bool FLIP = false, int WAIT_TIME = 280>
296class ClocklessController : public CPixelLEDController<RGB_ORDER> {
297 typedef typename FastPin<DATA_PIN>::port_ptr_t data_ptr_t;
298 typedef typename FastPin<DATA_PIN>::port_t data_t;
299
300 data_t mPinMask;
301 data_ptr_t mPort;
302 CMinWait<WAIT_TIME> mWait;
303 bool mPluReady;
304
305public:
306 ClocklessController() FL_NOEXCEPT : mPinMask(0), mPort(0), mPluReady(false) {}
307
308 virtual void init() FL_NOEXCEPT {
309 // The CPU still owns the data pin - the PLU samples it via SWM, but
310 // the pin itself is a normal GPIO that the CPU writes to.
311 FastPin<DATA_PIN>::setOutput();
312 mPinMask = FastPin<DATA_PIN>::mask();
313 mPort = FastPin<DATA_PIN>::port();
314
315 // Program the PLU LUT graph once. Idempotent.
316 lpc_plu_detail::initPluGraph();
317 mPluReady = true;
318 }
319
320 virtual fl::u16 getMaxRefreshRate() const { return 400; }
321
322 virtual void showPixels(PixelController<RGB_ORDER>& pixels) FL_NOEXCEPT {
323 mWait.wait();
324
325 // The PLU drives the wire shape; the CPU's only job is to clock data
326 // bits out at the bit-rate cadence. We disable interrupts during the
327 // transfer because a long ISR could stretch a single bit past the
328 // WS2812 reset threshold (>50us) and end the frame prematurely.
329 cli();
330 feedPixels(pixels);
331 sei();
332
333 mWait.mark();
334 }
335
336private:
337 // Feed every bit of every pixel into the PLU's data-input GPIO.
338 //
339 // Per-bit cadence:
340 // 1. The PLU's timing counter is free-running on its own clock domain.
341 // 2. The CPU samples the next data bit, writes it to the data GPIO.
342 // 3. The PLU latches the resulting bit-window output on each counter
343 // rollover. We must guarantee the new DATA value is stable BEFORE
344 // the rollover edge that begins the bit.
345 //
346 // Synchronisation strategy:
347 // We do not poll the timing counter; we just push bits at slightly
348 // below the bit-rate. The PLU samples DATA at each rising edge of its
349 // internal bit-period clock; as long as we update DATA between
350 // rollovers, the LED stream is correct. At 15 MHz CPU and ~1.25us
351 // per WS2812 bit, that's ~18 cycles of slack per bit - plenty.
352 //
353 // TODO(2841): once the SCT-based timing source is integrated, expose a

Callers

nothing calls this directly

Calls 4

initPluGraphFunction · 0.85
setOutputFunction · 0.50
maskFunction · 0.50
portFunction · 0.50

Tested by

no test coverage detected