Skip to content

EmbLED (Embedded LED) is a lightweight, dependency-free, and RTOS-agnostic C library for LED control on embedded systems

License

Notifications You must be signed in to change notification settings

fbrlucas/embled

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EmbLED — 🧩 Lightweight LED control library

EmbLED (Embedded LED) is a lightweight, dependency-free, and RTOS-agnostic C library for LED control on embedded systems.

Designed for reliability, simplicity, and minimal resource usage.

It abstracts common patterns (ON/OFF, blinks), supports digital or PWM control, and lets you create dynamic profiles at runtime.

License: MIT Platform


Table of contents


Key Features

  • ⚡ Lightweight for embedded systems
  • 🧩 No dependencies or dynamic memory usage
  • 🕒 Fixed-time tick engine
  • 💡 Support for both GPIO and PWM control
  • 🔄 Dynamic profiles created at runtime
  • 🧠 RTOS and bare-metal compatible

Concepts & Execution Flow

  • Base cycle:
    Set a periodic timer or RTOS task to call embled_task() every EMBLED_CYCLE_TIME_MS (default 100 ms).

  • Modes:
    Each mode defines a sequence of ON/OFF states with durations expressed in ticks (multiples of the base cycle).

  • Dynamic profiles:
    Create new modes at runtime with embled_new_profile(), passing durations in milliseconds; the library converts them to ticks.

  • Driver abstraction:
    Each LED can use either a digital GPIO (ON/OFF) or a PWM driver (start/stop).

  • Logic levels:
    Supports both active-high and active-low outputs (EMBLED_ACTIVE_HIGH / EMBLED_ACTIVE_LOW).


Resource Footprint

Resource Typical Usage (per 4 LEDs, GCC -O0)
Flash ≈ 2.2 KB
RAM ≈ 540 B

⚡ Built for very low memory usage and zero dynamic allocation.


Data Structures

  • embled_modes_t — available modes
Mode Description
EMBLED_MODE_OFF LED remains off.
EMBLED_MODE_ON LED remains on continuously.
EMBLED_MODE_PULSE_FAST_ONCE Single short pulse — blinks once briefly, then turns off.
EMBLED_MODE_PULSE_SLOW_ONCE Single long pulse — blinks once longer, then turns off.
EMBLED_MODE_PULSE_FAST_DOUBLE_ONCE Two quick pulses, then turns off.
EMBLED_MODE_PULSE_SINGLE Single short pulse repeated continuously.
EMBLED_MODE_PULSE_DOUBLE Two short pulses repeated continuously.
EMBLED_MODE_PULSE_TRIPLE Three short pulses repeated continuously.
EMBLED_MODE_BLINK_SLOW Continuous slow blink (≈ 1 Hz).
EMBLED_MODE_BLINK_MEDIUM Continuous medium-speed blink (≈ 2 Hz).
EMBLED_MODE_BLINK_FAST Continuous fast blink (≈ 5 Hz).
EMBLED_MODE_DYNAMIC_X Reserved for dynamic, user-defined profiles created at runtime.

  • embled_levels_t — activation levels

    • EMBLED_ACTIVE_LOW: LED turns ON at low level (GND).
    • EMBLED_ACTIVE_HIGH: LED turns ON at high level (VCC).
  • embled_driver_mode_t — pin control mode

    • EMBLED_DRIVER_MODE_DIGITAL: Use GPIO peripheral driver control.
    • EMBLED_DRIVER_MODE_PWM: Use PWM peripheral driver control.
  • embled_callbacks_t — MCU integration

    • write_gpio(pin, level): Write the GPIO level.
    • read_gpio(pin): Read the current GPIO level.
    • start_pwm(pin): Start the PWM channel.
    • stop_pwm(pin): Stop the PWM channel.

Provide these callbacks once via embled_init(). Callbacks may be NULL if not used.


Public API

void embled_init(embled_callbacks_t* cbks)

Initializes the LED control service and registers the hardware driver callbacks.

Parameters:

  • cbks: Pointer to a structure containing function pointers for hardware-level control
    (e.g., write_gpio(), read_gpio(), start_pwm(), stop_pwm()).

Details:

  • Must be called once before using any other embled_* function.
  • If cbks is NULL, the function performs no hardware operation.

void embled_task(void* argument)

Main periodic service routine that executes the LED state machine.

Parameters:

  • argument: Optional user argument (not used internally; reserved for RTOS compatibility).

Details:

  • Must be called periodically every EMBLED_CYCLE_TIME_MS
    (default: 100 ms) by:
    • A hardware timer interrupt, or
    • A FreeRTOS task using vTaskDelay() or a software timer.
  • Responsible for:
    • Applying pending shadow updates (shadow.enabled).
    • Advancing LED state transitions according to their active profiles.
    • Automatically restoring previous modes if return_last_mode == true.

bool embled_set_mode(uint16_t pin, embled_driver_mode_t driver_mode, embled_modes_t new_mode, embled_levels_t level, bool return_last_mode)

Activates a new LED mode on the specified pin.

Parameters:

  • pin: Hardware pin identifier (application-defined).
  • driver_mode: Output driver type (EMBLED_DRIVER_MODE_DIGITAL or EMBLED_DRIVER_MODE_PWM).
  • new_mode: One of the predefined modes from embled_modes_t.
  • level: Active logic level (EMBLED_ACTIVE_HIGH or EMBLED_ACTIVE_LOW).
  • return_last_mode:
    • When true, the current active mode is stored in backup.
    • Once new_mode finishes, the previous mode is automatically restored.
      Useful for temporary actions like one-shot pulses or indications.

Returns:

  • true if the mode request was successfully queued.
  • false if:
    • No free LED slot is available.
    • A shadow update is already pending for that pin.
    • The driver mode differs from the one previously assigned to the same pin.

Thread Safety:

  • Safe to call from any task context.
  • Updates are atomic; no mutex or lock required.

int8_t embled_new_profile(uint8_t num_states, uint16_t num_repetitions, uint16_t* duration_ms)

Creates a dynamic LED profile at runtime, allowing custom blink or pulse patterns.

Parameters:

  • num_states: Number of ON/OFF states in the sequence (1–EMBLED_MAX_STATES).
  • num_repetitions:
    • Number of times the sequence repeats.
    • Use EMBLED_INFINITE for continuous patterns.
  • duration_ms: Array of num_states elements, each defining the duration (in milliseconds) of each state.

Returns:

  • Index (≥ 0) of the newly created mode (e.g., EMBLED_MODE_DYNAMIC_1).
  • -1 if:
    • num_states exceeds EMBLED_MAX_STATES.
    • No free dynamic profile slot is available.
    • Invalid parameter values.

Behavior:

  • Dynamic profiles occupy one of the reserved slots (EMBLED_MODE_DYNAMIC_1_5).
  • Finite profiles are automatically cleared once the sequence completes, freeing the slot.

Quick Start Code

  1. Initialize embled and set a digital LED
#include "embled.h"

// Minimal callbacks (replace with your platform HAL). PWM omitted if not used.

static void cb_write(uint16_t pin, bool level) { (void)pin; (void)level; }
static bool cb_read(uint16_t pin) { (void)pin; return false; }

void app_setup(void) {
        embled_callbacks_t cbks = {
                .write_gpio = cb_write,
                .read_gpio  = cb_read,
                .start_pwm  = NULL,
                .stop_pwm   = NULL,
        };

        embled_init(&cbks);

        // Configure a timer/RTOS to call embled_task() every 100 ms
        // ...

        // Turn ON LED on pin 5 (digital, active-high)
        embled_set_mode(5, EMBLED_DRIVER_MODE_DIGITAL, EMBLED_MODE_ON, EMBLED_ACTIVE_HIGH, false);
}
  1. Create a dynamic profile and activate it (200ms ON, 200ms OFF, 800ms ON, 400ms OFF)
// on/off/on/off in milliseconds
uint16_t pattern_ms[] = { 200, 200, 800, 400 };

int8_t mode_idx = embled_new_profile(4, EMBLED_INFINITE, pattern_ms);
if (mode_idx >= 0) {
    embled_set_mode(5, EMBLED_DRIVER_MODE_DIGITAL, (embled_modes_t) mode_idx, EMBLED_ACTIVE_HIGH, false);
}
  1. Temporary mode (blink once) and restore the previous state
// Start steady ON mode
embled_set_mode(5, EMBLED_DRIVER_MODE_DIGITAL, EMBLED_MODE_ON, EMBLED_ACTIVE_HIGH, false);

// Perform one fast blink, then return to ON automatically
embled_set_mode(5, EMBLED_DRIVER_MODE_DIGITAL, EMBLED_MODE_PULSE_FAST_ONCE, EMBLED_ACTIVE_HIGH, true);

Limits & Configuration

  • Static memory:
    embled uses only static allocation, ensuring predictable memory usage and zero heap fragmentation.

  • Number of supported LEDsdefault: 4
    EMBLED_NUM_LEDS defines how many LEDs can be controlled simultaneously.
    Adjust this value according to your hardware and memory constraints.

  • Maximum profile statesdefault: 10
    EMBLED_MAX_STATES defines the maximum number of states per LED profile (e.g., ON/OFF transitions).

  • Driver mode change:
    Changing the driver type (e.g., from digital to PWM) of an already active pin is not allowed.
    To reconfigure the driver, first set the LED to EMBLED_MODE_OFF.

  • Update Limitations:
    If embled_set_mode() is called multiple times within a period shorter than EMBLED_CYCLE_TIME_MS,
    only the first call will take effect; subsequent calls are ignored until the next update cycle.

  • LED brightness control:
    Brightness control via PWM duty cycle is supported in hardware but not yet implemented in the library API.

  • Time base:default: 100
    EMBLED_CYCLE_TIME_MS defines the base time to execute embled_task. All durations are stored in ticks, where 1 tick = 100 ms.

  • Timing precision:
    The timing accuracy of LED profiles depends on your system architecture — including timer interrupt priority or RTOS task scheduling.
    Some variations in blink timing may occur under heavy system load.

💡 Tip: Keep the 100 ms base unless you have strict timing requirements.
It offers a good balance between responsiveness and low CPU or RTOS overhead.


Examples

  • examples/embled_stm32 — Demonstrates integration with STM32 HAL using both GPIO and PWM drivers.
    Includes bare-metal and FreeRTOS variants.
    Build with STM32CubeIDE

    See: examples/embled_stm32/README.md


License

Licensed under the MIT License

See the LICENSE file at the repository root.


Contact

About

EmbLED (Embedded LED) is a lightweight, dependency-free, and RTOS-agnostic C library for LED control on embedded systems

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages