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

Function showRGBInternal

src/platforms/avr/clockless_avr.h:677–869  ·  view source on GitHub ↗

===== MAIN BIT-BANGING FUNCTION ===== This method is made static to force making register Y available to use for data on AVR - if the method is non-static, then gcc will use register Y for the this pointer. By making it static, Y register becomes available for general use. FUNCTION PURPOSE: Outputs RGB pixel data to WS2812/WS2811 LEDs using precisely timed bit-banging While outputting each byte (

Source from the content-addressed store, hash-verified

675 // 2. Output byte 1 (e.g., G) while preparing byte 2 (e.g., B)
676 // 3. Output byte 2 (e.g., B) while preparing byte 0 of next pixel (e.g., next R)
677 static void /*__attribute__((optimize("O0")))*/ /*__attribute__ ((always_inline))*/ showRGBInternal(PixelController<RGB_ORDER> & pixels) {
678 u8 *data = (u8*)pixels.mData; // Pointer to pixel array
679 data_ptr_t port = FastPin<DATA_PIN>::port(); // GPIO port register address
680 data_t mask = FastPin<DATA_PIN>::mask(); // Pin bit mask
681 u8 scale_base = 0; // Scratch variable for scaling operations
682
683 // FASTLED_REGISTER uint8_t *end = data + nLeds;
684
685 // Compute port values for HIGH and LOW states
686 data_t hi = *port | mask; // Set data pin bit to 1 (HIGH), preserve other pins
687 data_t lo = *port & ~mask; // Clear data pin bit to 0 (LOW), preserve other pins
688 *port = lo; // Initialize line to LOW state
689
690 // DOUBLE-BUFFER BYTES: b0=currently outputting, b1=next being prepared
691 u8 b0 = 0; // The byte currently being written out bit-by-bit
692 u8 b1 = 0; // The byte currently being loaded, dithered, and scaled for next output
693
694 // Setup the pixel controller
695 pixels.preStepFirstByteDithering();
696
697 // ===== EXTRACT VARIABLES FOR ASM ACCESS =====
698 // Pull all needed values into local variables so inline asm can reference them via ASM_VARS
699 // These are mapped to AVR registers through the ASM_VARS constraint list
700
701 // advanceBy: Stride to next pixel (typically 3 for RGB, 4 for RGBW, negative for reverse order)
702 // Cast to int16 for sign extension (handles negative strides correctly)
703 i16 advanceBy = pixels.advanceBy();
704 u16 count = pixels.mLen; // Number of pixels to output
705
706 // s0, s1, s2: Scale factors for each color channel (brightness/color correction)
707 // Range: 0-255 (0=off, 255=full brightness)
708 // RO() handles RGB_ORDER remapping (e.g., RGB vs GRB vs BGR)
709 u8 s0 = pixels.mColorAdjustment.premixed.raw[RO(0)];
710 u8 s1 = pixels.mColorAdjustment.premixed.raw[RO(1)];
711 u8 s2 = pixels.mColorAdjustment.premixed.raw[RO(2)];
712#if (FASTLED_SCALE8_FIXED==1)
713 // Scale8 fix: increment scale factors so 255 wraps to 0
714 // Assembly code detects s==0 as special case to return unscaled value
715 // This makes scale8(x, 255) return x instead of (x*255)/256
716 s0++; s1++; s2++;
717#endif
718
719 // d0, d1, d2: Current dither values for each channel
720 // Dithering reduces color banding by adding controlled temporal noise
721 u8 d0 = pixels.d[RO(0)];
722 u8 d1 = pixels.d[RO(1)];
723 u8 d2 = pixels.d[RO(2)];
724
725 // e0, e1, e2: Dither step values (d is updated by: d = e - d after each pixel)
726 u8 e0 = pixels.e[RO(0)];
727 u8 e1 = pixels.e[RO(1)];
728 u8 e2 = pixels.e[RO(2)];
729
730 u8 loopvar=0; // Scratch variable for delay loops
731
732 // ===== FIRST BYTE INITIALIZATION =====
733 // Load and scale the very first byte (byte 0 of first pixel) before entering main loop
734 // This has to be done in asm to keep gcc from messing up the asm code further down

Callers 15

clockless_avr.hFile · 0.70
showPixelsFunction · 0.50
showPixelsMethod · 0.50
showPixelsMethod · 0.50
showPixelsMethod · 0.50
showPixelsMethod · 0.50
showPixelsMethod · 0.50
showPixelsMethod · 0.50
showPixelsMethod · 0.50
showPixelsMethod · 0.50
showPixelsMethod · 0.50
showPixelsMethod · 0.50

Calls 4

advanceByMethod · 0.80
portFunction · 0.50
maskFunction · 0.50

Tested by

no test coverage detected