# Special Notes on APA102 and the 'High Definition' Mode in FastLED

The APA102 LED driver includes a 5-bit per-LED brightness component. Previously, this feature was not fully utilized, except through a workaround that defined a global brightness affecting all LEDs uniformly rather than individually.

In FastLED the APA102 chipset will have extra resolution in comparison to the WS2812 RGB8 mode.

There are two modes:
  * APA102 "Regular Mode"
    * Has enhanced color resolution when using the "global brightness" factor
  * APA102HD Mode
    * Applies automatic gamma correction at the driver level using "pseudo 13-bit" color mixing.

**APA102HD Mode**

[example: examples/APA102HD](examples/Apa102HD/)

By introducing a 5-bit gamma bit-shift algorithm, we now effectively leverage this per-LED brightness control. Faced with the decision to either rewrite the entire `CRGB` library to expose the 5-bit brightness—including adaptations for formats like RGBW—or to retain the existing RGB8 format used by FastLED and implement the enhancement at the driver level, the latter option was chosen. This approach avoids widespread changes and maintains compatibility; if RGB8 suffices for game development, it is adequate for LED development as well.

The term "Pseudo-13-bit" arises because the additional resolution becomes significant only when all color components are at low values. For example, colors like `CRGB(255, 255, 254)` or `CRGB(255, 1, 1)` do not benefit from increased resolution due to the dominance of the brighter components. However, in low-light conditions with colors such as `CRGB(8, 8, 8)`, where the maximum component value is low, the pseudo-13-bit algorithm significantly enhances resolution—precisely where increased resolution is most desired.

Gamma correction is applied to preserve the RGB8 format and because future LEDs are expected to support gamma correction inherently. In game development, the 0-255 color values are based on the gamma scale rather than the linear power scale. LEDs like the WS2812 operate on a linear power scale, which results in washed-out, undersaturated colors when displaying captured video directly. Implementing software gamma correction for RGB8 severely reduces color resolution.

To address this, an internal gamma scale mapping is applied:

```
RGB8 → RGB16 + 5-bit gamma → RGB8 + 5-bit gamma
```

During the conversion back to RGB8, the brightness from the 5-bit gamma is optimally distributed using a closed-form mathematical algorithm. Rather than the iterative bit-shifting approach used in earlier versions, the current implementation uses a sophisticated quantization and scaling method that provides superior accuracy.

**Closed-Form Algorithm (Current Implementation)**

The algorithm works by:

1. **Finding the maximum component**: Determines which RGB component requires the highest brightness level
2. **Quantizing to 5-bit scale**: Computes the optimal 5-bit brightness value that accommodates the maximum component
3. **Applying pre-computed scaling**: Uses a lookup table of precise scaling factors to convert the 16-bit gamma-corrected values back to 8-bit RGB components

The key insight is the quantization formula:
```
scale = (max_component + (2047 - (max_component >> 5))) >> 11
```

This ensures the 5-bit brightness value is always sufficient to represent the maximum component while minimizing quantization error.

The scaling factors in the lookup table are computed as:
```
bright_scale[i] = (i/31) * (255/65536) * 256
```

These pre-computed values eliminate floating-point arithmetic while maintaining precision. The final RGB values are calculated with proper rounding:
```
rgb_out = (rgb16 * scale_factor + 0x808000) >> 24
```

**Algorithm Performance**

This closed-form approach delivers exceptional accuracy:
- **Worst-case error**: 0.2% over the full 16-bit input range
- **Average error**: 0.05% across the range
- **Perfect match**: to floating-point reference implementation

By eliminating iterative bit-shifting, this method also provides consistent performance regardless of input values and significantly reduces code size on embedded platforms.

**Version History**

In version 3.9.0, the algorithm was completely rewritten to function natively on 8-bit controllers like the `__AVR__` chipsets without significant performance loss. The current closed-form implementation replaced the previous iterative approach, providing both better accuracy and smaller code footprint.

**Further Enhancements in Version 3.9.0**

Additionally, version 3.9.0 separated the color temperature from the global brightness scale. Before this update, global brightness was pre-mixed with the component scales—a method suitable for the WS2812's RGB8 format but not for the APA102's RGB8 plus 5-bit brightness. The update saw the global brightness and color scales separated for non-AVR chipsets. While the WS2812 continues to use pre-mixed values for performance reasons on AVR chipsets, the APA102 now performs component mixing within the "pseudo-13-bit space."

Although APA102HD mode offers the highest dynamic range, the standard APA102 mode also benefits from increased resolution when adjusting global brightness. In this mode, instead of pre-mixing scales and multiplying them against each `CRGB` value, the global brightness is applied to the 5-bit brightness component, and only the color scales are multiplied against the `CRGB` values. This approach is superior because each component of the color scale typically exceeds 127, providing ample high-order bits to preserve color information.
