117 lines
4.5 KiB
C
117 lines
4.5 KiB
C
/******************************************************************************
|
|
* File: HAL_LED_prg.c
|
|
* Component: HAL_LED
|
|
* Description: LED abstraction implementation. Manages a pixel buffer with
|
|
* intensity scaling and pushes color data to the hardware via
|
|
* MCU_PIO. SetColor updates one LED and immediately pushes the
|
|
* entire strip — no separate Update call needed.
|
|
*
|
|
* Layer: HAL
|
|
*****************************************************************************/
|
|
|
|
#include "HAL_LED.h"
|
|
#include "HAL_LED_priv.h"
|
|
#include "HAL_LED_cfg.h"
|
|
|
|
#include "MCU_PIO.h"
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/* RUNTIME STATE */
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
static HAL_LED_tstrControl strControl;
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/* INTERNAL HELPERS */
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
/**
|
|
* @brief Push the entire pixel buffer for one instance to the PIO FIFO.
|
|
*
|
|
* Iterates through the pixel buffer, packs each pixel into a 32-bit
|
|
* GRB word (left-justified: G in [31:24], R in [23:16], B in [15:8],
|
|
* bits [7:0] unused), and sends it via MCU_PIO_vPutBlocking.
|
|
*
|
|
* @param u8Instance HAL_LED instance index.
|
|
*/
|
|
static void vPushStrip(u8 u8Instance)
|
|
{
|
|
u8 u8PioInstLoc = HAL_LED_astrConfig[u8Instance].u8PioInstance;
|
|
u8 u8NumLedsLoc = HAL_LED_astrConfig[u8Instance].u8NumLeds;
|
|
u8 u8LedLoc;
|
|
|
|
for (u8LedLoc = 0U; u8LedLoc < u8NumLedsLoc; u8LedLoc++)
|
|
{
|
|
HAL_LED_tstrPixel *pstrPixLoc = &strControl.astrPixels[u8Instance][u8LedLoc];
|
|
|
|
/* Pack RGB into bits [31:8] of the 32-bit word.
|
|
* The WS2812 variant on the RP2040-Zero uses RGB byte order
|
|
* (red first, green second, blue third) rather than the standard
|
|
* GRB. Bits [7:0] are padding (shifted out but ignored). */
|
|
u32 u32RgbLoc = ((u32)pstrPixLoc->u8Red << 24U)
|
|
| ((u32)pstrPixLoc->u8Green << 16U)
|
|
| ((u32)pstrPixLoc->u8Blue << 8U);
|
|
|
|
MCU_PIO_vPutBlocking(u8PioInstLoc, u32RgbLoc);
|
|
}
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
/* INIT */
|
|
/* ========================================================================= */
|
|
|
|
STD_tenuResult HAL_LED_enuInit(void)
|
|
{
|
|
STD_tenuResult enuResultLoc = STD_OK;
|
|
u8 u8InstLoc;
|
|
u8 u8LedLoc;
|
|
|
|
/* Clear all pixels to off (black) */
|
|
for (u8InstLoc = 0U; u8InstLoc < (u8)HAL_LED_NUM_INSTANCES; u8InstLoc++)
|
|
{
|
|
for (u8LedLoc = 0U; u8LedLoc < HAL_LED_astrConfig[u8InstLoc].u8NumLeds; u8LedLoc++)
|
|
{
|
|
strControl.astrPixels[u8InstLoc][u8LedLoc].u8Green = 0U;
|
|
strControl.astrPixels[u8InstLoc][u8LedLoc].u8Red = 0U;
|
|
strControl.astrPixels[u8InstLoc][u8LedLoc].u8Blue = 0U;
|
|
}
|
|
}
|
|
|
|
return enuResultLoc;
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
/* SET COLOR */
|
|
/* ========================================================================= */
|
|
|
|
STD_tenuResult HAL_LED_enuSetColor(u8 u8Instance, u8 u8LedIndex,
|
|
u8 u8Red, u8 u8Green, u8 u8Blue,
|
|
u8 u8Intensity)
|
|
{
|
|
STD_tenuResult enuResultLoc = STD_OK;
|
|
u8 u8NumLedsLoc = HAL_LED_astrConfig[u8Instance].u8NumLeds;
|
|
|
|
if (u8LedIndex >= u8NumLedsLoc)
|
|
{
|
|
enuResultLoc = STD_INDEX_OUT_OF_RANGE_ERROR;
|
|
}
|
|
else
|
|
{
|
|
/* Scale each channel by intensity: (channel * intensity) / 255.
|
|
* Use u16 intermediate to avoid overflow (255 * 255 = 65025,
|
|
* which fits in u16 but not u8). */
|
|
u8 u8ScaledRLoc = (u8)(((u16)u8Red * (u16)u8Intensity) / 255U);
|
|
u8 u8ScaledGLoc = (u8)(((u16)u8Green * (u16)u8Intensity) / 255U);
|
|
u8 u8ScaledBLoc = (u8)(((u16)u8Blue * (u16)u8Intensity) / 255U);
|
|
|
|
/* Store the scaled pixel in the buffer */
|
|
strControl.astrPixels[u8Instance][u8LedIndex].u8Red = u8ScaledRLoc;
|
|
strControl.astrPixels[u8Instance][u8LedIndex].u8Green = u8ScaledGLoc;
|
|
strControl.astrPixels[u8Instance][u8LedIndex].u8Blue = u8ScaledBLoc;
|
|
|
|
/* Immediately push the entire strip to the hardware */
|
|
vPushStrip(u8Instance);
|
|
}
|
|
|
|
return enuResultLoc;
|
|
} |