diff --git a/lib/libesp32/berry_animation/berry_animation_docs/ANIMATION_CLASS_HIERARCHY.md b/lib/libesp32/berry_animation/berry_animation_docs/ANIMATION_CLASS_HIERARCHY.md
deleted file mode 100644
index e5bf20db5..000000000
--- a/lib/libesp32/berry_animation/berry_animation_docs/ANIMATION_CLASS_HIERARCHY.md
+++ /dev/null
@@ -1,1197 +0,0 @@
-# Berry Animation Framework - Class Hierarchy and Parameters Reference
-
-This document provides a comprehensive reference for all classes in the Berry Animation Framework that extend `ParameterizedObject`, including their parameters and factory functions.
-
-## Table of Contents
-
-1. [Class Hierarchy](#class-hierarchy)
-2. [Base Classes](#base-classes)
-3. [Value Providers](#value-providers)
-4. [Color Providers](#color-providers)
-5. [Animation Classes](#animation-classes)
-6. [Parameter Constraints](#parameter-constraints)
-
-## Class Hierarchy
-
-```
-ParameterizedObject (base class with parameter management and playable interface)
-├── Animation (unified base class for all visual elements)
-│ ├── EngineProxy (combines rendering and orchestration)
-│ │ └── (user-defined template animations)
-│ ├── SolidAnimation (solid color fill)
-│ ├── BeaconAnimation (pulse at specific position)
-│ ├── CrenelPositionAnimation (crenel/square wave pattern)
-│ ├── BreatheAnimation (breathing effect)
-│ ├── PaletteGradientAnimation (gradient patterns with palette colors)
-│ │ ├── PaletteMeterAnimation (meter/bar patterns)
-│ │ └── GradientMeterAnimation (VU meter with gradient colors and peak hold)
-│ ├── CometAnimation (moving comet with tail)
-│ ├── FireAnimation (realistic fire effect)
-│ ├── TwinkleAnimation (twinkling stars effect)
-│ ├── GradientAnimation (color gradients)
-│ ├── NoiseAnimation (Perlin noise patterns)
-│ ├── WaveAnimation (wave motion effects)
-│ └── RichPaletteAnimation (smooth palette transitions)
-├── SequenceManager (orchestrates animation sequences)
-└── ValueProvider (dynamic value generation)
- ├── StaticValueProvider (wraps static values)
- ├── StripLengthProvider (provides LED strip length)
- ├── IterationNumberProvider (provides sequence iteration number)
- ├── OscillatorValueProvider (oscillating values with waveforms)
- ├── ClosureValueProvider (computed values, internal use only)
- └── ColorProvider (dynamic color generation)
- ├── StaticColorProvider (solid color)
- ├── ColorCycleColorProvider (cycles through palette)
- ├── RichPaletteColorProvider (smooth palette transitions)
- ├── BreatheColorProvider (breathing color effect)
- └── CompositeColorProvider (blends multiple colors)
-```
-
-## Base Classes
-
-### ParameterizedObject
-
-Base class for all parameterized objects in the framework. Provides parameter management with validation, storage, and retrieval, as well as the playable interface for lifecycle management (start/stop/update).
-
-This unified base class enables:
-- Consistent parameter handling across all framework objects
-- Unified engine management (animations and sequences treated uniformly)
-- Hybrid objects that combine rendering and orchestration
-- Consistent lifecycle management (start/stop/update)
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `is_running` | bool | false | - | Whether the object is active |
-
-**Key Methods**:
-- `start(time_ms)` - Start the object at a specific time
-- `stop()` - Stop the object
-- `update(time_ms)` - Update object state based on current time (no return value)
-
-**Factory**: N/A (base class)
-
-### Animation
-
-Unified base class for all visual elements. Inherits from `ParameterizedObject`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `id` | string | "animation" | - | Optional name for the animation |
-| `is_running` | bool | false | - | Whether the animation is active |
-| `priority` | int | 10 | 0-255 | Rendering priority (higher = on top) |
-| `duration` | int | 0 | min: 0 | Animation duration in ms (0 = infinite) |
-| `loop` | bool | false | - | Whether to loop when duration is reached |
-| `opacity` | any | 255 | - | Animation opacity (number, FrameBuffer, or Animation) |
-| `color` | int | 0xFFFFFFFF | - | Base color in ARGB format |
-
-**Special Behavior**: Setting `is_running = true/false` starts/stops the animation.
-
-**Timing Behavior**: The `start()` method only resets the time origin if the animation was already started previously (i.e., `self.start_time` is not nil). The first actual rendering tick occurs in `update()` or `render()` methods, which initialize `start_time` on first call.
-
-**Factory**: `animation.animation(engine)`
-
-### EngineProxy
-
-A specialized animation class that combines rendering and orchestration capabilities. Extends `Animation` and can contain child animations and sequences. Inherits from `Animation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| *(inherits all Animation parameters)* | | | | |
-
-**Key Features**:
-- Can render visual content like a regular animation
-- Can orchestrate sub-animations and sequences using `add()`
-- Enables complex composite effects
-- Used as base class for template animations
-
-**Child Management**:
-- `add(obj)` - Adds a child animation or sequence
-- `remove(obj)` - Removes a child
-- Children are automatically started/stopped with parent
-- Children are rendered in priority order (higher priority on top)
-
-**Use Cases**:
-- Composite effects combining multiple animations
-- Template animations with parameters
-- Complex patterns with timing control
-- Reusable animation components
-
-**Factory**: `animation.engine_proxy(engine)`
-
-### Template Animations
-
-Template animations are user-defined classes that extend `EngineProxy`, created using the DSL's `template animation` syntax. They provide reusable, parameterized animation patterns.
-
-**DSL Definition**:
-```berry
-template animation shutter_effect {
- param colors type palette nillable true
- param duration type time min 0 max 3600 default 5 nillable false
-
- # Animation definition with sequences, colors, etc.
- # Parameters accessed as self.colors, self.duration
-}
-```
-
-**Generated Class Structure**:
-```berry
-class shutter_effect_animation : animation.engine_proxy
- static var PARAMS = animation.enc_params({
- "colors": {"type": "palette", "nillable": true},
- "duration": {"type": "time", "min": 0, "max": 3600, "default": 5, "nillable": false}
- })
-
- def init(engine)
- super(self).init(engine)
- # Generated code with self.colors and self.duration references
- # Uses self.add() for sub-animations and sequences
- end
-end
-```
-
-**Parameter Constraints**:
-Template animation parameters support all standard constraints:
-- `type` - Parameter type (palette, time, int, color, etc.)
-- `min` - Minimum value (for numeric types)
-- `max` - Maximum value (for numeric types)
-- `default` - Default value
-- `nillable` - Whether parameter can be nil (true/false)
-
-**Implicit Parameters**:
-Template animations automatically inherit parameters from the `EngineProxy` class hierarchy without explicit declaration:
-- `id` (string, default: "animation") - Animation name
-- `priority` (int, default: 10) - Rendering priority
-- `duration` (int, default: 0) - Animation duration in milliseconds
-- `loop` (bool, default: false) - Whether animation loops
-- `opacity` (int, default: 255) - Animation opacity (0-255)
-- `color` (int, default: 0) - Base color value
-- `is_running` (bool, default: false) - Running state
-
-These parameters can be used directly in template animation bodies without declaration:
-```berry
-template animation fade_effect {
- param colors type palette
-
- # 'duration' is implicit - no need to declare
- set oscillator = sawtooth(min_value=0, max_value=255, duration=duration)
-
- color col = color_cycle(colors=colors, period=0)
- animation test = solid(color=col)
- test.opacity = oscillator # 'opacity' is also implicit
-
- run test
-}
-```
-
-**Usage**:
-```berry
-# Create instance with parameters
-palette rainbow = [red, orange, yellow, green, blue]
-animation my_shutter = shutter_effect(colors=rainbow, duration=2s)
-run my_shutter
-```
-
-**Key Differences from Regular Animations**:
-- Defined in DSL, not Berry code
-- Parameters accessed as `self.` instead of direct variables
-- Uses `self.add()` for composition
-- Can be instantiated multiple times with different parameters
-- Automatically registered as animation constructors
-
-**Factory**: User-defined (e.g., `shutter_effect(engine)`)
-
-## Value Providers
-
-Value providers generate dynamic values over time for use as animation parameters.
-
-### ValueProvider
-
-Base interface for all value providers. Inherits from `ParameterizedObject`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| *(none)* | - | - | - | Base interface has no parameters |
-
-**Timing Behavior**: For value providers, `start()` is typically not called because instances can be embedded in closures. Value providers consider the first call to `produce_value()` as the start of their internal time reference. The `start()` method only resets the time origin if the provider was already started previously (i.e., `self.start_time` is not nil).
-
-**Update Method**: The `update(time_ms)` method does not return any value. Subclasses should check `self.is_running` to determine if the object is still active.
-
-**Factory**: N/A (base interface)
-
-### StaticValueProvider
-
-Wraps static values to provide ValueProvider interface. Inherits from `ValueProvider`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `value` | any | nil | - | The static value to return |
-
-**Factory**: `animation.static_value(engine)`
-
-### StripLengthProvider
-
-Provides access to the LED strip length as a dynamic value. Inherits from `ValueProvider`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| *(none)* | - | - | - | No parameters - strip length obtained from engine |
-
-**Usage**: Returns the 1D length of the LED strip in pixels. Useful for animations that need to know the strip dimensions for positioning, scaling, or boundary calculations.
-
-**Factory**: `animation.strip_length(engine)`
-
-### OscillatorValueProvider
-
-Generates oscillating values using various waveforms. Inherits from `ValueProvider`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `min_value` | int | 0 | - | Minimum oscillation value |
-| `max_value` | int | 255 | - | Maximum oscillation value |
-| `duration` | int | 1000 | min: 1 | Oscillation period in milliseconds |
-| `form` | int | 1 | enum: [1,2,3,4,5,6,7,8,9] | Waveform type |
-| `phase` | int | 0 | 0-255 | Phase shift in 0-255 range (mapped to duration) |
-| `duty_cycle` | int | 127 | 0-255 | Duty cycle for square/triangle waves in 0-255 range |
-
-**Waveform Constants**:
-- `1` (SAWTOOTH) - Linear ramp from min to max
-- `2` (TRIANGLE) - Linear ramp from min to max and back
-- `3` (SQUARE) - Square wave alternating between min and max
-- `4` (COSINE) - Smooth cosine wave
-- `5` (SINE) - Pure sine wave
-- `6` (EASE_IN) - Quadratic acceleration
-- `7` (EASE_OUT) - Quadratic deceleration
-- `8` (ELASTIC) - Spring-like overshoot and oscillation
-- `9` (BOUNCE) - Ball-like bouncing with decreasing amplitude
-
-**Timing Behavior**: The `start_time` is initialized on the first call to `produce_value()`. The `start()` method only resets the time origin if the oscillator was already started previously (i.e., `self.start_time` is not nil).
-
-**Factories**: `animation.ramp(engine)`, `animation.sawtooth(engine)`, `animation.linear(engine)`, `animation.triangle(engine)`, `animation.smooth(engine)`, `animation.sine_osc(engine)`, `animation.cosine_osc(engine)`, `animation.square(engine)`, `animation.ease_in(engine)`, `animation.ease_out(engine)`, `animation.elastic(engine)`, `animation.bounce(engine)`, `animation.oscillator_value(engine)`
-
-**See Also**: [Oscillation Patterns](OSCILLATION_PATTERNS.md) - Visual examples and usage patterns for oscillation waveforms
-
-### ClosureValueProvider
-
-**⚠️ INTERNAL USE ONLY - NOT FOR DIRECT USE**
-
-Wraps a closure/function as a value provider for internal transpiler use. This class is used internally by the DSL transpiler to handle computed values and should not be used directly by users.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `closure` | function | nil | - | The closure function to call for value generation |
-
-**Internal Usage**: This provider is automatically created by the DSL transpiler when it encounters computed expressions or arithmetic operations involving value providers. The closure is called with `(self, param_name, time_ms)` parameters.
-
-#### Mathematical Helper Methods
-
-The ClosureValueProvider includes built-in mathematical helper methods that can be used within closures for computed values:
-
-| Method | Description | Parameters | Return Type | Example |
-|--------|-------------|------------|-------------|---------|
-| `min(a, b, ...)` | Minimum of two or more values | `a, b, *args: number` | `number` | `animation._math.min(5, 3, 8)` → `3` |
-| `max(a, b, ...)` | Maximum of two or more values | `a, b, *args: number` | `number` | `animation._math.max(5, 3, 8)` → `8` |
-| `abs(x)` | Absolute value | `x: number` | `number` | `animation._math.abs(-5)` → `5` |
-| `round(x)` | Round to nearest integer | `x: number` | `int` | `animation._math.round(3.7)` → `4` |
-| `sqrt(x)` | Square root with integer handling | `x: number` | `number` | `animation._math.sqrt(64)` → `128` (for 0-255 range) |
-| `scale(v, from_min, from_max, to_min, to_max)` | Scale value between ranges | `v, from_min, from_max, to_min, to_max: number` | `int` | `animation._math.scale(50, 0, 100, 0, 255)` → `127` |
-| `sin(angle)` | Sine function (0-255 input range) | `angle: number` | `int` | `animation._math.sin(64)` → `255` (90°) |
-| `cos(angle)` | Cosine function (0-255 input range) | `angle: number` | `int` | `animation._math.cos(0)` → `-255` (matches oscillator behavior) |
-
-**Mathematical Method Notes:**
-
-- **Integer Handling**: `sqrt()` treats integers in 0-255 range as normalized values (255 = 1.0)
-- **Angle Range**: `sin()` and `cos()` use 0-255 input range (0-360 degrees)
-- **Output Range**: Trigonometric functions return -255 to 255 (mapped from -1.0 to 1.0)
-- **Cosine Behavior**: Matches oscillator COSINE waveform (starts at minimum, not maximum)
-- **Scale Function**: Uses `tasmota.scale_int()` for efficient integer scaling
-
-#### Closure Signature
-
-Closures used with ClosureValueProvider must follow this signature:
-```berry
-def closure_func(engine, param_name, time_ms)
- # engine: AnimationEngine reference
- # param_name: Name of the parameter being computed
- # time_ms: Current time in milliseconds
- return computed_value
-end
-```
-
-#### Usage in Computed Values
-
-These methods are automatically available in DSL computed expressions:
-
-```berry
-# Example: Dynamic brightness based on strip position
-set strip_len = strip_length()
-animation pulse = pulsating_animation(
- color=red
- brightness=strip_len / 4 + 50 # Uses built-in arithmetic
-)
-
-# Complex mathematical expressions are automatically wrapped in closures
-# that have access to all mathematical helper methods
-```
-
-**Factory**: `animation.closure_value(engine)` (internal use only)
-
-**Note**: Users should not create ClosureValueProvider instances directly. Instead, use the DSL's computed value syntax which automatically creates these providers as needed.
-
-## Color Providers
-
-Color providers generate dynamic colors over time, extending ValueProvider for color-specific functionality.
-
-### ColorProvider
-
-Base interface for all color providers. Inherits from `ValueProvider`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `brightness` | int | 255 | 0-255 | Overall brightness scaling for all colors |
-
-**Static Methods**:
-- `apply_brightness(color, brightness)` - Applies brightness scaling to a color (ARGB format). Only performs scaling if brightness is not 255 (full brightness). This is a static utility method that can be called without an instance.
-
-**Factory**: N/A (base interface)
-
-### StaticColorProvider
-
-Returns a single, static color. Inherits from `ColorProvider`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color` | int | 0xFFFFFFFF | - | The solid color to return |
-| *(inherits brightness from ColorProvider)* | | | | |
-
-#### Usage Examples
-
-```berry
-# Using predefined colors
-color static_red = solid(color=red)
-color static_blue = solid(color=blue)
-
-# Using hex colors
-color static_orange = solid(color=0xFF8C00)
-
-# Using custom defined colors
-color accent = 0xFF6B35
-color static_accent = solid(color=accent)
-```
-
-**Note**: The `solid()` function is the recommended shorthand for `static_color()`.
-
-### ColorCycleColorProvider
-
-Cycles through a palette of colors with brutal switching. Inherits from `ColorProvider`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `colors` | bytes | default palette | - | Palette bytes in AARRGGBB format |
-| `period` | int | 5000 | min: 0 | Cycle time in ms (0 = manual only) |
-| `next` | int | 0 | - | Write 1 to move to next color manually, or any number to go forward or backwards by `n` colors |
-| `palette_size` | int | 3 | read-only | Number of colors in the palette (automatically updated when palette changes) |
-| *(inherits brightness from ColorProvider)* | | | | |
-
-**Note**: The `get_color_for_value()` method accepts values in the 0-255 range for value-based color mapping.
-
-**Modes**: Auto-cycle (`period > 0`) or Manual-only (`period = 0`)
-
-#### Usage Examples
-
-```berry
-# RGB cycle with brutal switching
-color rgb_cycle = color_cycle(
- colors=bytes("FF0000FF" "FF00FF00" "FFFF0000"),
- period=4s
-)
-
-# Custom warm colors
-color warm_cycle = color_cycle(
- colors=bytes("FF4500FF" "FF8C00FF" "FFFF00"),
- period=3s
-)
-
-# Mixed colors in AARRGGBB format
-color mixed_cycle = color_cycle(
- colors=bytes("FFFF0000" "FF00FF00" "FF0000FF"),
- period=2s
-)
-```
-
-### RichPaletteColorProvider
-
-Generates colors from predefined palettes with smooth transitions and professional color schemes. Inherits from `ColorProvider`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `colors` | bytes | rainbow palette | - | Palette bytes or predefined palette constant |
-| `period` | int | 5000 | min: 0 | Cycle time in ms (0 = value-based only) |
-| `transition_type` | int | animation.LINEAR | enum: [animation.LINEAR, animation.SINE] | LINEAR=constant speed, SINE=smooth ease-in/ease-out |
-| *(inherits brightness from ColorProvider)* | | | | |
-
-#### Available Predefined Palettes
-
-| Palette | Description | Colors |
-|---------|-------------|---------|
-| `PALETTE_RAINBOW` | Standard 7-color rainbow | Red → Orange → Yellow → Green → Blue → Indigo → Violet |
-| `PALETTE_RGB` | Simple RGB cycle | Red → Green → Blue |
-| `PALETTE_FIRE` | Warm fire colors | Black → Dark Red → Red → Orange → Yellow |
-
-#### Usage Examples
-
-```berry
-# Rainbow palette with smooth ease-in/ease-out transitions
-color rainbow_colors = rich_palette(
- colors=PALETTE_RAINBOW,
- period=5s,
- transition_type=SINE,
- brightness=255
-)
-
-# Fire effect with linear (constant speed) transitions
-color fire_colors = rich_palette(
- colors=PALETTE_FIRE,
- period=3s,
- transition_type=LINEAR,
- brightness=200
-)
-```
-
-### BreatheColorProvider
-
-Creates breathing/pulsing color effects by modulating the brightness of a base color over time. Inherits from `ColorProvider`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `base_color` | int | 0xFFFFFFFF | - | The base color to modulate (32-bit ARGB value) |
-| `min_brightness` | int | 0 | 0-255 | Minimum brightness level (breathing effect) |
-| `max_brightness` | int | 255 | 0-255 | Maximum brightness level (breathing effect) |
-| `duration` | int | 3000 | min: 1 | Time for one complete breathing cycle in ms |
-| `curve_factor` | int | 2 | 1-5 | Breathing curve shape (1=cosine wave, 2-5=curved breathing with pauses) |
-| *(inherits brightness from ColorProvider)* | | | | Overall brightness scaling applied after breathing effect |
-| *(inherits all OscillatorValueProvider parameters)* | | | | |
-
-**Curve Factor Effects:**
-- `1`: Pure cosine wave (smooth pulsing, equivalent to pulsating_color)
-- `2`: Natural breathing with slight pauses at peaks
-- `3`: More pronounced breathing with longer pauses
-- `4`: Deep breathing with extended pauses
-- `5`: Most pronounced pauses at peaks (dramatic breathing effect)
-
-#### Usage Examples
-
-```berry
-# Natural breathing effect
-color breathing_red = breathe_color(
- base_color=red,
- min_brightness=20,
- max_brightness=255,
- duration=4s,
- curve_factor=3
-)
-
-# Fast pulsing effect (equivalent to pulsating_color)
-color pulse_blue = breathe_color(
- base_color=blue,
- min_brightness=50,
- max_brightness=200,
- duration=1s,
- curve_factor=1
-)
-
-# Slow, deep breathing
-color deep_breath = breathe_color(
- base_color=purple,
- min_brightness=5,
- max_brightness=255,
- duration=6s,
- curve_factor=4
-)
-
-# Using dynamic base color
-color rainbow_cycle = color_cycle(colors=bytes("FF0000FF" "FF00FF00" "FFFF0000"), period=5s)
-color breathing_rainbow = breathe_color(
- base_color=rainbow_cycle,
- min_brightness=30,
- max_brightness=255,
- duration=3s,
- curve_factor=2
-)
-```
-
-**Factories**: `animation.breathe_color(engine)`, `animation.pulsating_color(engine)`
-
-**Note**: The `pulsating_color()` factory creates a BreatheColorProvider with `curve_factor=1` and `duration=1000ms` for fast pulsing effects.
-
-### CompositeColorProvider
-
-Combines multiple color providers with blending. Inherits from `ColorProvider`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `blend_mode` | int | 0 | enum: [0,1,2] | 0=overlay, 1=add, 2=multiply |
-| *(inherits brightness from ColorProvider)* | | | | Overall brightness scaling applied to final composite color |
-
-**Factory**: `animation.composite_color(engine)`
-
-## Animation Classes
-
-All animation classes extend the base `Animation` class and inherit its parameters.
-
-### BreatheAnimation
-
-Creates a smooth breathing effect with natural breathing curves. Inherits from `Animation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color` | int | 0xFFFFFFFF | - | The color to breathe |
-| `min_brightness` | int | 0 | 0-255 | Minimum brightness level |
-| `max_brightness` | int | 255 | 0-255 | Maximum brightness level |
-| `period` | int | 3000 | min: 100 | Breathing cycle time in ms |
-| `curve_factor` | int | 2 | 1-5 | Breathing curve shape (higher = sharper) |
-| *(inherits all Animation parameters)* | | | | |
-
-**Factory**: `animation.breathe_animation(engine)`
-
-### CometAnimation
-
-Creates a comet effect with a bright head and fading tail. Inherits from `Animation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color` | int | 0xFFFFFFFF | - | Color for the comet head |
-| `tail_length` | int | 5 | 1-50 | Length of the comet tail in pixels |
-| `speed` | int | 2560 | 1-25600 | Movement speed in 1/256th pixels per second |
-| `direction` | int | 1 | enum: [-1,1] | Direction of movement (1=forward, -1=backward) |
-| `wrap_around` | int | 1 | 0-1 | Whether comet wraps around the strip |
-| `fade_factor` | int | 179 | 0-255 | How quickly the tail fades |
-| *(inherits all Animation parameters)* | | | | |
-
-**Factory**: `animation.comet_animation(engine)`
-
-
-
-
-### FireAnimation
-
-Creates a realistic fire effect with flickering flames. Inherits from `Animation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color` | instance | nil | - | Color provider for fire palette (nil = default fire palette) |
-| `intensity` | int | 180 | 0-255 | Overall fire intensity |
-| `flicker_speed` | int | 8 | 1-20 | Flicker update frequency in Hz |
-| `flicker_amount` | int | 100 | 0-255 | Amount of random flicker |
-| `cooling_rate` | int | 55 | 0-255 | How quickly flames cool down |
-| `sparking_rate` | int | 120 | 0-255 | Rate of new spark generation |
-| *(inherits all Animation parameters)* | | | | |
-
-**Factory**: `animation.fire_animation(engine)`
-
-### GradientAnimation
-
-Creates smooth color gradients that can be linear or radial. Inherits from `Animation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color` | instance | nil | nillable | Color provider (nil = rainbow gradient) |
-| `gradient_type` | int | 0 | 0-1 | 0=linear, 1=radial |
-| `direction` | int | 0 | 0-255 | Gradient direction/orientation |
-| `center_pos` | int | 128 | 0-255 | Center position for radial gradients |
-| `spread` | int | 255 | 1-255 | Gradient spread/compression |
-| `movement_speed` | int | 0 | 0-255 | Speed of gradient movement |
-| *(inherits all Animation parameters)* | | | | |
-
-**Factories**: `animation.gradient_animation(engine)`, `animation.gradient_rainbow_linear(engine)`, `animation.gradient_rainbow_radial(engine)`, `animation.gradient_two_color_linear(engine)`
-
-### GradientMeterAnimation
-
-VU meter style animation that displays a gradient-colored bar from the start of the strip up to a configurable level. Includes optional peak hold indicator. Inherits from `PaletteGradientAnimation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `level` | int | 255 | 0-255 | Current meter level (0=empty, 255=full) |
-| `peak_hold` | int | 1000 | min: 0 | Peak hold time in ms (0=disabled) |
-| *(inherits all PaletteGradientAnimation parameters)* | | | | |
-
-#### Visual Representation
-
-```
-level=128 (50%), peak at 200
-[████████████████--------•-------]
-^ ^
-| peak indicator (single pixel)
-filled gradient area
-```
-
-#### Usage Examples
-
-```berry
-# Simple meter with rainbow gradient
-color rainbow = rich_palette()
-animation meter = gradient_meter_animation()
-meter.color_source = rainbow
-meter.level = 128
-
-# Meter with peak hold (1 second)
-color fire_colors = rich_palette(colors=PALETTE_FIRE)
-animation vu_meter = gradient_meter_animation(peak_hold=1000)
-vu_meter.color_source = fire_colors
-
-# Dynamic level from value provider
-set audio_level = triangle(min_value=0, max_value=255, period=2s)
-animation audio_meter = gradient_meter_animation(peak_hold=500)
-audio_meter.color_source = rainbow
-audio_meter.level = audio_level
-```
-
-**Factory**: `animation.gradient_meter_animation(engine)`
-
-### NoiseAnimation
-
-Creates pseudo-random noise patterns with configurable scale, speed, and fractal complexity. Perfect for organic, natural-looking effects like clouds, fire textures, or abstract patterns. Inherits from `Animation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color` | instance | nil | - | Color provider for noise mapping (nil = rainbow) |
-| `scale` | int | 50 | 1-255 | Noise scale/frequency (lower = larger patterns) |
-| `speed` | int | 30 | 0-255 | Animation speed (0 = static pattern) |
-| `octaves` | int | 1 | 1-4 | Number of noise octaves for fractal complexity |
-| `persistence` | int | 128 | 0-255 | How much each octave contributes to final pattern |
-| `seed` | int | 12345 | 0-65535 | Random seed for reproducible patterns |
-| *(inherits all Animation parameters)* | | | | |
-
-#### Noise Characteristics
-
-**Scale Effects:**
-- **Low scale (10-30)**: Large, flowing patterns
-- **Medium scale (40-80)**: Balanced detail and flow
-- **High scale (100-200)**: Fine, detailed textures
-
-**Octave Effects:**
-- **1 octave**: Smooth, simple patterns
-- **2 octaves**: Added medium-frequency detail
-- **3+ octaves**: Complex, natural-looking textures
-
-**Speed Effects:**
-- **Static (0)**: Fixed pattern for backgrounds
-- **Slow (10-40)**: Gentle, organic movement
-- **Fast (80-200)**: Dynamic, energetic patterns
-
-#### Usage Examples
-
-```berry
-# Rainbow noise with medium detail
-animation rainbow_noise = noise_animation(
- scale=60,
- speed=40,
- octaves=1
-)
-
-# Blue fire texture with fractal detail
-color blue_fire = 0xFF0066FF
-animation blue_texture = noise_animation(
- color=blue_fire,
- scale=120,
- speed=60,
- octaves=3,
- persistence=100
-)
-
-# Static cloud pattern
-animation cloud_pattern = noise_animation(
- color=white,
- scale=30,
- speed=0,
- octaves=2
-)
-```
-
-#### Common Use Cases
-
-- **Ambient Lighting**: Slow, low-scale noise for background ambiance
-- **Fire Effects**: Orange/red colors with medium scale and speed
-- **Water Effects**: Blue/cyan colors with flowing movement
-- **Cloud Simulation**: White/gray colors with large-scale patterns
-- **Abstract Art**: Rainbow colors with high detail and multiple octaves
-
-
-
-### PulseAnimation
-
-Creates a pulsing effect oscillating between min and max brightness. Inherits from `Animation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color` | int | 0xFFFFFFFF | - | Pulse color |
-| `min_brightness` | int | 0 | 0-255 | Minimum brightness level |
-| `max_brightness` | int | 255 | 0-255 | Maximum brightness level |
-| `period` | int | 1000 | min: 100 | Pulse period in milliseconds |
-| *(inherits all Animation parameters)* | | | | |
-
-**Factory**: `animation.pulsating_animation(engine)`
-
-### BeaconAnimation
-
-Creates a pulse effect at a specific position with optional fade regions. Inherits from `Animation`.
-
-#### Visual Pattern
-
-```
- pos (1)
- |
- v
- _______
- / \
- _______/ \____________
- | | | |
- |2| 3 |2|
-```
-
-Where:
-1. `pos` - Start of the pulse (in pixels)
-2. `slew_size` - Number of pixels to fade from back to fore color (can be 0)
-3. `beacon_size` - Number of pixels of the pulse
-
-The pulse consists of:
-- **Core pulse**: Full brightness region of `beacon_size` pixels
-- **Fade regions**: Optional `slew_size` pixels on each side with gradual fade
-- **Total width**: `beacon_size + (2 * slew_size)` pixels
-
-#### Parameters
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color` | int | 0xFFFFFFFF | - | Pulse color in ARGB format |
-| `back_color` | int | 0xFF000000 | - | Background color in ARGB format |
-| `pos` | int | 0 | - | Pulse start position in pixels |
-| `beacon_size` | int | 1 | min: 0 | Size of core pulse in pixels |
-| `slew_size` | int | 0 | min: 0 | Fade region size on each side in pixels |
-| *(inherits all Animation parameters)* | | | | |
-
-#### Pattern Behavior
-
-- **Sharp Pulse** (`slew_size = 0`): Rectangular pulse with hard edges
-- **Soft Pulse** (`slew_size > 0`): Pulse with smooth fade-in/fade-out regions
-- **Positioning**: `pos` defines the start of the core pulse region
-- **Fade Calculation**: Linear fade from full brightness to background color
-- **Boundary Handling**: Fade regions are clipped to frame boundaries
-
-#### Usage Examples
-
-```berry
-# Sharp pulse at center
-animation sharp_pulse = beacon_animation(
- color=red,
- pos=10,
- beacon_size=3,
- slew_size=0
-)
-
-# Soft pulse with fade regions
-animation soft_pulse = beacon_animation(
- color=green,
- pos=5,
- beacon_size=2,
- slew_size=3
-)
-# Total width: 2 + (2 * 3) = 8 pixels
-
-# Spotlight effect
-color dark_blue = 0xFF000040
-animation spotlight = beacon_animation(
- color=white,
- back_color=dark_blue,
- pos=15,
- beacon_size=1,
- slew_size=5
-)
-
-run spotlight
-```
-
-#### Common Use Cases
-
-**Spotlight Effects:**
-```berry
-# Moving spotlight with soft edges
-animation moving_spotlight = beacon_animation(
- color=white,
- back_color=0xFF000040,
- beacon_size=1,
- slew_size=5
-)
-moving_spotlight.pos = triangle(min_value=0, max_value=29, period=3s)
-```
-
-**Position Markers:**
-```berry
-# Sharp position marker
-animation position_marker = beacon_animation(
- color=red,
- pos=15,
- beacon_size=1,
- slew_size=0
-)
-```
-
-**Breathing Spots:**
-```berry
-# Breathing effect at specific position
-animation breathing_spot = beacon_animation(
- color=blue,
- pos=10,
- beacon_size=3,
- slew_size=2
-)
-breathing_spot.opacity = smooth(min_value=50, max_value=255, period=2s)
-```
-
-**Factory**: `animation.beacon_animation(engine)`
-
-### CrenelPositionAnimation
-
-Creates a crenel (square wave) pattern with repeating rectangular pulses. Inherits from `Animation`.
-
-#### Visual Pattern
-
-```
- pos (1)
- |
- v (*4)
- ______ ____
- | | |
- _________| |_________|
-
- | 2 | 3 |
-```
-
-Where:
-1. `pos` - Starting position of the first pulse (in pixels)
-2. `pulse_size` - Width of each pulse (in pixels)
-3. `low_size` - Gap between pulses (in pixels)
-4. `nb_pulse` - Number of pulses (-1 for infinite)
-
-The full period of the pattern is `pulse_size + low_size` pixels.
-
-#### Parameters
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color` | int | 0xFFFFFFFF | - | Pulse color in ARGB format |
-| `back_color` | int | 0xFF000000 | - | Background color in ARGB format |
-| `pos` | int | 0 | - | Starting position of first pulse in pixels |
-| `pulse_size` | int | 1 | min: 0 | Width of each pulse in pixels |
-| `low_size` | int | 3 | min: 0 | Gap between pulses in pixels |
-| `nb_pulse` | int | -1 | - | Number of pulses (-1 = infinite) |
-| *(inherits all Animation parameters)* | | | | |
-
-#### Pattern Behavior
-
-- **Infinite Mode** (`nb_pulse = -1`): Pattern repeats continuously across the strip
-- **Finite Mode** (`nb_pulse > 0`): Shows exactly the specified number of pulses
-- **Period**: Each pattern cycle spans `pulse_size + low_size` pixels
-- **Boundary Handling**: Pulses are clipped to frame boundaries
-- **Zero Sizes**: `pulse_size = 0` produces no output; `low_size = 0` creates continuous pulses
-
-#### Pattern Calculations
-
-- **Period and Positioning**: The pattern repeats every `pulse_size + low_size` pixels
-- **Optimization**: For infinite pulses, the algorithm calculates optimal starting position for efficient rendering
-- **Boundary Clipping**: Pulses are automatically clipped to frame boundaries
-- **Modulo Arithmetic**: Negative positions are handled correctly with modulo arithmetic
-
-#### Common Use Cases
-
-**Status Indicators:**
-```berry
-# Slow blinking pattern for status indication
-animation status_indicator = crenel_animation(
- color=green,
- pulse_size=1,
- low_size=9
-)
-```
-
-**Rhythmic Effects:**
-```berry
-# Fast rhythmic pattern
-animation rhythm_pattern = crenel_animation(
- color=red,
- pulse_size=2,
- low_size=2
-)
-```
-
-**Decorative Borders:**
-```berry
-# Decorative border pattern
-color gold = 0xFFFFD700
-animation border_pattern = crenel_animation(
- color=gold,
- pulse_size=3,
- low_size=1,
- nb_pulse=10
-)
-```
-
-**Progress Indicators:**
-```berry
-# Progress bar with limited pulses
-animation progress_bar = crenel_animation(
- color=0xFF0080FF,
- pulse_size=2,
- low_size=1,
- nb_pulse=5
-)
-```
-
-#### Integration Features
-
-- **Parameter System**: All parameters support dynamic updates with validation
-- **Method Chaining**: Fluent API for configuration (in Berry code)
-- **Animation Lifecycle**: Inherits standard animation lifecycle methods
-- **Framework Integration**: Seamless integration with animation engine
-- **Testing**: Comprehensive test suite covering edge cases and performance
-
-**Factory**: `animation.crenel_animation(engine)`
-
-### RichPaletteAnimation
-
-Creates smooth color transitions using rich palette data with direct parameter access. Inherits from `Animation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `colors` | bytes | rainbow palette | - | Palette bytes or predefined palette |
-| `period` | int | 5000 | min: 0 | Cycle time in ms (0 = value-based only) |
-| `transition_type` | int | animation.LINEAR | enum: [animation.LINEAR, animation.SINE] | LINEAR=constant speed, SINE=smooth ease-in/ease-out |
-| `brightness` | int | 255 | 0-255 | Overall brightness scaling |
-| *(inherits all Animation parameters)* | | | | |
-
-**Special Features**:
-- Direct parameter access (set `anim.colors` instead of `anim.color.colors`)
-- Parameters are automatically forwarded to internal `RichPaletteColorProvider`
-- Access to specialized methods via `anim.color_provider.method_name()`
-
-**Factory**: `animation.rich_palette_animation(engine)`
-
-### TwinkleAnimation
-
-Creates a twinkling stars effect with random lights appearing and fading. Inherits from `Animation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color` | int | 0xFFFFFFFF | - | Twinkle color |
-| `density` | int | 128 | 0-255 | Twinkle density/probability |
-| `twinkle_speed` | int | 6 | 1-5000 | Update frequency in Hz (or period in ms if ≥50) |
-| `fade_speed` | int | 180 | 0-255 | How quickly twinkles fade |
-| `min_brightness` | int | 32 | 0-255 | Minimum twinkle brightness |
-| `max_brightness` | int | 255 | 0-255 | Maximum twinkle brightness |
-| *(inherits all Animation parameters)* | | | | |
-
-**Factories**: `animation.twinkle_animation(engine)`, `animation.twinkle_classic(engine)`, `animation.twinkle_solid(engine)`, `animation.twinkle_rainbow(engine)`, `animation.twinkle_gentle(engine)`, `animation.twinkle_intense(engine)`
-
-### WaveAnimation
-
-Creates mathematical waveforms that can move along the LED strip. Perfect for rhythmic patterns, breathing effects, or mathematical visualizations. Inherits from `Animation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color` | int | 0xFFFF0000 | - | Wave color |
-| `back_color` | int | 0xFF000000 | - | Background color shown in wave valleys |
-| `wave_type` | int | 0 | 0-3 | 0=sine, 1=triangle, 2=square, 3=sawtooth |
-| `amplitude` | int | 128 | 0-255 | Wave height/intensity range |
-| `frequency` | int | 32 | 0-255 | How many wave cycles fit on the strip |
-| `phase` | int | 0 | 0-255 | Horizontal wave pattern shift |
-| `wave_speed` | int | 50 | 0-255 | Movement speed (0 = static wave) |
-| `center_level` | int | 128 | 0-255 | Baseline intensity around which wave oscillates |
-| *(inherits all Animation parameters)* | | | | |
-
-#### Wave Types
-
-**Sine Wave (0):**
-- **Characteristics**: Smooth, natural oscillation
-- **Best for**: Breathing effects, natural rhythms, ambient lighting
-
-**Triangle Wave (1):**
-- **Characteristics**: Linear ramps up and down with sharp peaks
-- **Best for**: Scanning effects, linear fades
-
-**Square Wave (2):**
-- **Characteristics**: Sharp on/off transitions
-- **Best for**: Strobing, digital effects, alerts
-
-**Sawtooth Wave (3):**
-- **Characteristics**: Gradual rise, instant drop
-- **Best for**: Scanning beams, ramp effects
-
-#### Wave Characteristics
-
-**Frequency Effects:**
-- **Low frequency (10-30)**: Long, flowing waves
-- **Medium frequency (40-80)**: Balanced wave patterns
-- **High frequency (100-200)**: Dense, detailed patterns
-
-**Amplitude Effects:**
-- **Low amplitude (50-100)**: Subtle intensity variation
-- **Medium amplitude (100-180)**: Noticeable wave pattern
-- **High amplitude (200-255)**: Dramatic intensity swings
-
-#### Usage Examples
-
-```berry
-# Rainbow sine wave
-animation rainbow_wave = wave_animation(
- wave_type=0,
- frequency=40,
- wave_speed=80,
- amplitude=150
-)
-
-# Green breathing effect
-animation breathing = wave_animation(
- color=green,
- wave_type=0,
- amplitude=150,
- frequency=20,
- wave_speed=30
-)
-
-# Fast square wave strobe
-animation strobe = wave_animation(
- color=white,
- wave_type=2,
- frequency=80,
- wave_speed=150
-)
-```
-
-#### Common Use Cases
-
-- **Breathing Effects**: Slow sine waves for calming ambiance
-- **Scanning Beams**: Sawtooth waves for radar-like effects
-- **Strobing**: Square waves for attention-getting flashes
-- **Color Cycling**: Rainbow waves for spectrum effects
-- **Pulse Patterns**: Triangle waves for rhythmic pulses
-
-
-
-### PaletteGradientAnimation
-
-Creates shifting gradient patterns with palette colors. Inherits from `Animation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `color_source` | instance | nil | - | Color provider for pattern mapping |
-| `shift_period` | int | 0 | min: 0 | Time for one complete shift cycle in ms (0 = static gradient) |
-| `spatial_period` | int | 0 | min: 0 | Spatial period in pixels (0 = full strip length) |
-| `phase_shift` | int | 0 | 0-255 | Phase shift in 0-255 range (mapped to spatial period) |
-| *(inherits all Animation parameters)* | | | | |
-
-**Implementation Details:**
-- Uses `bytes()` buffer for efficient storage of per-pixel values
-- Color source receives values in 0-255 range via `get_color_for_value(value, time_ms)`
-- Buffer automatically resizes when strip length changes
-- Optimized LUT (Lookup Table) support for color providers
-
-**Pattern Generation:**
-- Generates linear gradient values in 0-255 range across the specified spatial period
-- **shift_period**: Controls temporal movement - how long it takes for the gradient to shift one full spatial period
- - `0`: Static gradient (no movement)
- - `> 0`: Moving gradient with specified period in milliseconds
-- **spatial_period**: Controls spatial repetition - how many pixels before the gradient pattern repeats
- - `0`: Gradient spans the full strip length (single gradient across entire strip)
- - `> 0`: Gradient repeats every N pixels
-- **phase_shift**: Shifts the gradient pattern spatially by a percentage of the spatial period
-- Each pixel's value calculated using optimized fixed-point arithmetic
-
-**Factory**: `animation.palette_gradient_animation(engine)`
-
-### PaletteMeterAnimation
-
-Creates meter/bar patterns based on a value function. Inherits from `PaletteGradientAnimation`.
-
-| Parameter | Type | Default | Constraints | Description |
-|-----------|------|---------|-------------|-------------|
-| `value_func` | function | nil | - | Function that provides meter values (0-255 range) |
-| *(inherits all PaletteGradientAnimation parameters)* | | | | |
-
-**Pattern Generation:**
-- Value function signature: `value_func(engine, time_ms, self)` where:
- - `engine`: AnimationEngine reference
- - `time_ms`: Elapsed time since animation start
- - `self`: Reference to the animation instance
-- Value function returns value in 0-255 range representing meter level
-- Pixels within meter range get value 255, others get value 0
-- Meter position calculated as: `position = tasmota.scale_uint(value, 0, 255, 0, strip_length)`
-
-**Factory**: `animation.palette_meter_animation(engine)`
-
-## Motion Effects
-
-Motion effects are transformation animations that apply movement, scaling, and distortion to existing animations. They accept any animation as a source and can be chained together for complex effects.
-
-### Combining Motion Effects
-
-Motion effects can be chained to create sophisticated transformations:
-
-```berry
-# Base animation
-animation base_pulse = pulsating_animation(color=blue, period=3s)
-
-# Simple animation composition
-animation fire_effect = fire_animation(
- color=fire_colors,
- intensity=180,
- flicker_speed=8
-)
-
-animation gradient_wave = gradient_animation(
- color=rainbow_cycle,
- gradient_type=0,
- movement_speed=50
-)
-
-# Result: Multiple independent animations
-run base_pulse
-run fire_effect
-run gradient_wave
-```
-
-### Performance Considerations
-
-- Each animation uses approximately 4 bytes per pixel for color storage
-- Fire animation includes additional flicker calculations
-- Gradient animation requires color interpolation calculations
-- Noise animation includes pseudo-random pattern generation
-- Consider strip length impact on transformation calculations
-
-## Parameter Constraints
-
-### Constraint Types
-
-| Constraint | Type | Description | Example |
-|------------|------|-------------|---------|
-| `default` | any | Default value used during initialization | `"default": 50` |
-| `min` | int | Minimum allowed value for integers | `"min": 0` |
-| `max` | int | Maximum allowed value for integers | `"max": 100` |
-| `enum` | list | List of valid values | `"enum": [1, 2, 3]` |
-| `type` | string | Expected value type | `"type": "string"` |
-| `nillable` | bool | Whether nil values are allowed | `"nillable": true` |
-
-### Supported Types
-
-| Type | Description |
-|------|-------------|
-| `"int"` | Integer values (default if not specified) |
-| `"string"` | String values |
-| `"bool"` | Boolean values (true/false) |
-| `"instance"` | Object instances |
-| `"any"` | Any type (no type validation) |
-
-### Factory Function Rules
-
-1. **Engine-Only Parameters**: All factory functions take ONLY the `engine` parameter
-2. **No Redundant Factories**: If a factory only calls the constructor, export the class directly
-3. **Preset Factories**: Factory functions should provide useful presets or complex configurations
-4. **Parameter Assignment**: Set parameters via virtual member assignment after creation
\ No newline at end of file
diff --git a/lib/libesp32/berry_animation/berry_animation_docs/ANIMATION_DEVELOPMENT.md b/lib/libesp32/berry_animation/berry_animation_docs/ANIMATION_DEVELOPMENT.md
deleted file mode 100644
index 417c93306..000000000
--- a/lib/libesp32/berry_animation/berry_animation_docs/ANIMATION_DEVELOPMENT.md
+++ /dev/null
@@ -1,695 +0,0 @@
-# Animation Development Guide
-
-Guide for developers creating custom animation classes in the Berry Animation Framework.
-
-## Overview
-
-**Note**: This guide is for developers who want to extend the framework by creating new animation classes. For using existing animations, see the [DSL Reference](DSL_REFERENCE.md) which provides a declarative way to create animations without programming.
-
-The Berry Animation Framework uses a unified architecture where all visual elements inherit from the base `Animation` class. This guide explains how to create custom animation classes that integrate seamlessly with the framework's parameter system, value providers, and rendering pipeline.
-
-## Animation Class Structure
-
-### Basic Class Template
-
-```berry
-#@ solidify:MyAnimation,weak
-class MyAnimation : animation.animation
- # NO instance variables for parameters - they are handled by the virtual parameter system
-
- # Parameter definitions following the new specification
- static var PARAMS = {
- "my_param1": {"default": "default_value", "type": "string"},
- "my_param2": {"min": 0, "max": 255, "default": 100, "type": "int"}
- # Do NOT include inherited Animation parameters here
- }
-
- def init(engine)
- # Engine parameter is MANDATORY and cannot be nil
- super(self).init(engine)
-
- # Only initialize non-parameter instance variables (none in this example)
- # Parameters are handled by the virtual parameter system
- end
-
- # Handle parameter changes (optional)
- def on_param_changed(name, value)
- # Add custom logic for parameter changes if needed
- # Parameter validation is handled automatically by the framework
- end
-
- # Update animation state (no return value needed)
- def update(time_ms)
- super(self).update(time_ms)
- # Your update logic here
- end
-
- def render(frame, time_ms, strip_length)
- if !self.is_running || frame == nil
- return false
- end
-
- # Use virtual parameter access - automatically resolves ValueProviders
- var param1 = self.my_param1
- var param2 = self.my_param2
-
- # Use strip_length parameter instead of self.engine.strip_length for performance
- # Your rendering logic here
- # ...
-
- return true
- end
-
- # NO setter methods needed - use direct virtual parameter assignment:
- # obj.my_param1 = value
- # obj.my_param2 = value
-
- def tostring()
- return f"MyAnimation(param1={self.my_param1}, param2={self.my_param2}, running={self.is_running})"
- end
-end
-```
-
-## PARAMS System
-
-### Static Parameter Definition
-
-The `PARAMS` static variable defines all parameters specific to your animation class. This system provides:
-
-- **Parameter validation** with min/max constraints and type checking
-- **Default value handling** for initialization
-- **Virtual parameter access** through getmember/setmember
-- **Automatic ValueProvider resolution**
-
-#### Parameter Definition Format
-
-```berry
-static var PARAMS = {
- "parameter_name": {
- "default": default_value, # Default value (optional)
- "min": minimum_value, # Minimum value for integers (optional)
- "max": maximum_value, # Maximum value for integers (optional)
- "enum": [val1, val2, val3], # Valid enum values (optional)
- "type": "parameter_type", # Expected type (optional)
- "nillable": true # Whether nil values are allowed (optional)
- }
-}
-```
-
-#### Supported Types
-
-- **`"int"`** - Integer values (default if not specified)
-- **`"string"`** - String values
-- **`"bool"`** - Boolean values (true/false)
-- **`"bytes"`** - Bytes objects (validated using isinstance())
-- **`"instance"`** - Object instances
-- **`"any"`** - Any type (no type validation)
-
-#### Important Rules
-
-- **Do NOT include inherited parameters** - Animation base class parameters are handled automatically
-- **Only define class-specific parameters** in your PARAMS
-- **No constructor parameter mapping** - the new system uses engine-only constructors
-- **Parameters are accessed via virtual members**: `obj.param_name`
-
-## Constructor Implementation
-
-### Engine-Only Constructor Pattern
-
-```berry
-def init(engine)
- # 1. ALWAYS call super with engine (engine is the ONLY parameter)
- super(self).init(engine)
-
- # 2. Initialize non-parameter instance variables only
- self.internal_state = initial_value
- self.buffer = nil
- # Do NOT initialize parameters here - they are handled by the virtual system
-end
-```
-
-### Parameter Change Handling
-
-```berry
-def on_param_changed(name, value)
- # Optional method to handle parameter changes
- if name == "scale"
- # Recalculate internal state when scale changes
- self._update_internal_buffers()
- elif name == "color"
- # Handle color changes
- self._invalidate_color_cache()
- end
-end
-```
-
-### Key Changes from Old System
-
-- **Engine-only constructor**: Constructor takes ONLY the engine parameter
-- **No parameter initialization**: Parameters are set by caller using virtual member assignment
-- **No instance variables for parameters**: Parameters are handled by the virtual system
-- **Automatic validation**: Parameter validation happens automatically based on PARAMS constraints
-
-## Value Provider Integration
-
-### Automatic ValueProvider Resolution
-
-The virtual parameter system automatically resolves ValueProviders when you access parameters:
-
-```berry
-def render(frame, time_ms, strip_length)
- # Virtual parameter access automatically resolves ValueProviders
- var color = self.color # Returns current color value, not the provider
- var position = self.pos # Returns current position value
- var size = self.size # Returns current size value
-
- # Use strip_length parameter (computed once by engine_proxy) instead of self.engine.strip_length
- # Use resolved values in rendering logic
- for i: position..(position + size - 1)
- if i >= 0 && i < strip_length
- frame.set_pixel_color(i, color)
- end
- end
-
- return true
-end
-```
-
-### Setting Dynamic Parameters
-
-Users can set both static values and ValueProviders using the same syntax:
-
-```berry
-# Create animation
-var anim = animation.my_animation(engine)
-
-# Static values
-anim.color = 0xFFFF0000
-anim.pos = 5
-anim.size = 3
-
-# Dynamic values
-anim.color = animation.smooth(0xFF000000, 0xFFFFFFFF, 2000)
-anim.pos = animation.triangle(0, 29, 3000)
-```
-
-### Performance Optimization
-
-For performance-critical code, cache parameter values:
-
-```berry
-def render(frame, time_ms, strip_length)
- # Cache parameter values to avoid multiple virtual member access
- var current_color = self.color
- var current_pos = self.pos
- var current_size = self.size
-
- # Use cached values in loops
- for i: current_pos..(current_pos + current_size - 1)
- if i >= 0 && i < strip_length
- frame.set_pixel_color(i, current_color)
- end
- end
-
- return true
-end
-```
-
-### Color Provider LUT Optimization
-
-For color providers that perform expensive color calculations (like palette interpolation), the base `ColorProvider` class provides a Lookup Table (LUT) mechanism for caching pre-computed colors:
-
-```berry
-#@ solidify:MyColorProvider,weak
-class MyColorProvider : animation.color_provider
- # Instance variables (all should start with underscore)
- var _cached_data # Your custom cached data
-
- def init(engine)
- super(self).init(engine) # Initializes _color_lut and _lut_dirty
- self._cached_data = nil
- end
-
- # Mark LUT as dirty when parameters change
- def on_param_changed(name, value)
- super(self).on_param_changed(name, value)
- if name == "colors" || name == "transition_type"
- self._lut_dirty = true # Inherited from ColorProvider
- end
- end
-
- # Rebuild LUT when needed
- def _rebuild_color_lut()
- # Allocate LUT (e.g., 129 entries * 4 bytes = 516 bytes)
- if self._color_lut == nil
- self._color_lut = bytes()
- self._color_lut.resize(129 * 4)
- end
-
- # Pre-compute colors for values 0, 2, 4, ..., 254, 255
- var i = 0
- while i < 128
- var value = i * 2
- var color = self._compute_color_expensive(value)
- self._color_lut.set(i * 4, color, 4)
- i += 1
- end
-
- # Add final entry for value 255
- var color_255 = self._compute_color_expensive(255)
- self._color_lut.set(128 * 4, color_255, 4)
-
- self._lut_dirty = false
- end
-
- # Update method checks if LUT needs rebuilding
- def update(time_ms)
- if self._lut_dirty || self._color_lut == nil
- self._rebuild_color_lut()
- end
- return self.is_running
- end
-
- # Fast color lookup using LUT
- def get_color_for_value(value, time_ms)
- # Build LUT if needed (lazy initialization)
- if self._lut_dirty || self._color_lut == nil
- self._rebuild_color_lut()
- end
-
- # Map value to LUT index (divide by 2, special case for 255)
- var lut_index = value >> 1
- if value >= 255
- lut_index = 128
- end
-
- # Retrieve pre-computed color from LUT
- var color = self._color_lut.get(lut_index * 4, 4)
-
- # Apply brightness scaling using static method (only if not 255)
- var brightness = self.brightness
- if brightness != 255
- return animation.color_provider.apply_brightness(color, brightness)
- end
-
- return color
- end
-
- # Access LUT from outside (returns bytes() or nil)
- # Inherited from ColorProvider: get_lut()
-end
-```
-
-**LUT Benefits:**
-- **5-10x speedup** for expensive color calculations
-- **Reduced CPU usage** during rendering
-- **Smooth animations** even with complex color logic
-- **Memory efficient** (typically 516 bytes for 129 entries)
-
-**When to use LUT:**
-- Palette interpolation with binary search
-- Complex color transformations
-- Brightness calculations
-- Any expensive per-pixel color computation
-
-**LUT Guidelines:**
-- Store colors at maximum brightness, apply scaling after lookup
-- Use 2-step resolution (0, 2, 4, ..., 254, 255) to save memory
-- Invalidate LUT when parameters affecting color calculation change
-- Don't invalidate for brightness changes if brightness is applied post-lookup
-
-**Brightness Handling:**
-
-The `ColorProvider` base class includes a `brightness` parameter (0-255, default 255) and a static method for applying brightness scaling:
-
-```berry
-# Static method for brightness scaling (only scales if brightness != 255)
-animation.color_provider.apply_brightness(color, brightness)
-```
-
-**Best Practices:**
-- Store LUT colors at maximum brightness (255)
-- Apply brightness scaling after LUT lookup using the static method
-- Only call the static method if `brightness != 255` to avoid unnecessary overhead
-- For inline performance-critical code, you can inline the brightness calculation instead of calling the static method
-- Brightness changes do NOT invalidate the LUT since brightness is applied after lookup
-
-## Parameter Access
-
-### Direct Virtual Member Assignment
-
-The new system uses direct parameter assignment instead of setter methods:
-
-```berry
-# Create animation
-var anim = animation.my_animation(engine)
-
-# Direct parameter assignment (recommended)
-anim.color = 0xFF00FF00
-anim.pos = 10
-anim.size = 5
-
-# Method chaining is not needed - just set parameters directly
-```
-
-### Parameter Validation
-
-The parameter system handles validation automatically based on PARAMS constraints:
-
-```berry
-# This will raise an exception due to min: 0 constraint
-anim.size = -1 # Raises value_error
-
-# This will be accepted
-anim.size = 5 # Parameter updated successfully
-
-# Method-based setting returns true/false for validation
-var success = anim.set_param("size", -1) # Returns false, no exception
-```
-
-### Accessing Raw Parameters
-
-```berry
-# Get current parameter value (resolved if ValueProvider)
-var current_color = anim.color
-
-# Get raw parameter (returns ValueProvider if set)
-var raw_color = anim.get_param("color")
-
-# Check if parameter is a ValueProvider
-if animation.is_value_provider(raw_color)
- print("Color is dynamic")
-else
- print("Color is static")
-end
-```
-
-## Rendering Implementation
-
-### Frame Buffer Operations
-
-```berry
-def render(frame, time_ms, strip_length)
- if !self.is_running || frame == nil
- return false
- end
-
- # Resolve dynamic parameters
- var color = self.resolve_value(self.color, "color", time_ms)
- var opacity = self.resolve_value(self.opacity, "opacity", time_ms)
-
- # Render your effect using strip_length parameter
- for i: 0..(strip_length-1)
- var pixel_color = calculate_pixel_color(i, time_ms)
- frame.set_pixel_color(i, pixel_color)
- end
-
- # Apply opacity if not full (supports numbers, animations)
- if opacity < 255
- frame.apply_opacity(opacity)
- end
-
- return true # Frame was modified
-end
-```
-
-### Common Rendering Patterns
-
-#### Fill Pattern
-```berry
-# Fill entire frame with color
-frame.fill_pixels(color)
-```
-
-#### Position-Based Effects
-```berry
-# Render at specific positions
-var start_pos = self.resolve_value(self.pos, "pos", time_ms)
-var size = self.resolve_value(self.size, "size", time_ms)
-
-for i: 0..(size-1)
- var pixel_pos = start_pos + i
- if pixel_pos >= 0 && pixel_pos < frame.width
- frame.set_pixel_color(pixel_pos, color)
- end
-end
-```
-
-#### Gradient Effects
-```berry
-# Create gradient across frame
-for i: 0..(frame.width-1)
- var progress = i / (frame.width - 1.0) # 0.0 to 1.0
- var interpolated_color = interpolate_color(start_color, end_color, progress)
- frame.set_pixel_color(i, interpolated_color)
-end
-```
-
-## Complete Example: BeaconAnimation
-
-Here's a complete example showing all concepts:
-
-```berry
-#@ solidify:BeaconAnimation,weak
-class BeaconAnimation : animation.animation
- # NO instance variables for parameters - they are handled by the virtual parameter system
-
- # Parameter definitions following the new specification
- static var PARAMS = {
- "color": {"default": 0xFFFFFFFF},
- "back_color": {"default": 0xFF000000},
- "pos": {"default": 0},
- "beacon_size": {"min": 0, "default": 1},
- "slew_size": {"min": 0, "default": 0}
- }
-
- # Initialize a new Pulse Position animation
- # Engine parameter is MANDATORY and cannot be nil
- def init(engine)
- # Call parent constructor with engine (engine is the ONLY parameter)
- super(self).init(engine)
-
- # Only initialize non-parameter instance variables (none in this case)
- # Parameters are handled by the virtual parameter system
- end
-
- # Handle parameter changes (optional - can be removed if no special handling needed)
- def on_param_changed(name, value)
- # No special handling needed for this animation
- # Parameter validation is handled automatically by the framework
- end
-
- # Render the pulse to the provided frame buffer
- def render(frame, time_ms, strip_length)
- if frame == nil
- return false
- end
-
- var pixel_size = strip_length
- # Use virtual parameter access - automatically resolves ValueProviders
- var back_color = self.back_color
- var pos = self.pos
- var slew_size = self.slew_size
- var beacon_size = self.beacon_size
- var color = self.color
-
- # Fill background if not transparent
- if back_color != 0xFF000000
- frame.fill_pixels(back_color)
- end
-
- # Calculate pulse boundaries
- var pulse_min = pos
- var pulse_max = pos + beacon_size
-
- # Clamp to frame boundaries
- if pulse_min < 0
- pulse_min = 0
- end
- if pulse_max >= pixel_size
- pulse_max = pixel_size
- end
-
- # Draw the main pulse
- var i = pulse_min
- while i < pulse_max
- frame.set_pixel_color(i, color)
- i += 1
- end
-
- # Draw slew regions if slew_size > 0
- if slew_size > 0
- # Left slew (fade from background to pulse color)
- var left_slew_min = pos - slew_size
- var left_slew_max = pos
-
- if left_slew_min < 0
- left_slew_min = 0
- end
- if left_slew_max >= pixel_size
- left_slew_max = pixel_size
- end
-
- i = left_slew_min
- while i < left_slew_max
- # Calculate blend factor
- var blend_factor = tasmota.scale_uint(i, pos - slew_size, pos - 1, 255, 0)
- var alpha = 255 - blend_factor
- var blend_color = (alpha << 24) | (color & 0x00FFFFFF)
- var blended_color = frame.blend(back_color, blend_color)
- frame.set_pixel_color(i, blended_color)
- i += 1
- end
-
- # Right slew (fade from pulse color to background)
- var right_slew_min = pos + beacon_size
- var right_slew_max = pos + beacon_size + slew_size
-
- if right_slew_min < 0
- right_slew_min = 0
- end
- if right_slew_max >= pixel_size
- right_slew_max = pixel_size
- end
-
- i = right_slew_min
- while i < right_slew_max
- # Calculate blend factor
- var blend_factor = tasmota.scale_uint(i, pos + beacon_size, pos + beacon_size + slew_size - 1, 0, 255)
- var alpha = 255 - blend_factor
- var blend_color = (alpha << 24) | (color & 0x00FFFFFF)
- var blended_color = frame.blend(back_color, blend_color)
- frame.set_pixel_color(i, blended_color)
- i += 1
- end
- end
-
- return true
- end
-
- # NO setter methods - use direct virtual parameter assignment instead:
- # obj.color = value
- # obj.pos = value
- # obj.beacon_size = value
- # obj.slew_size = value
-
- # String representation of the animation
- def tostring()
- return f"BeaconAnimation(color=0x{self.color :08x}, pos={self.pos}, beacon_size={self.beacon_size}, slew_size={self.slew_size})"
- end
-end
-
-# Export class directly - no redundant factory function needed
-return {'beacon_animation': BeaconAnimation}
-```
-
-## Testing Your Animation
-
-### Unit Tests
-
-Create comprehensive tests for your animation:
-
-```berry
-import animation
-
-def test_my_animation()
- # Create LED strip and engine for testing
- var strip = global.Leds(10) # Use built-in LED strip for testing
- var engine = animation.create_engine(strip)
-
- # Test basic construction
- var anim = animation.my_animation(engine)
- assert(anim != nil, "Animation should be created")
-
- # Test parameter setting
- anim.color = 0xFFFF0000
- assert(anim.color == 0xFFFF0000, "Color should be set")
-
- # Test parameter updates
- anim.color = 0xFF00FF00
- assert(anim.color == 0xFF00FF00, "Color should be updated")
-
- # Test value providers
- var dynamic_color = animation.smooth(engine)
- dynamic_color.min_value = 0xFF000000
- dynamic_color.max_value = 0xFFFFFFFF
- dynamic_color.duration = 2000
-
- anim.color = dynamic_color
- var raw_color = anim.get_param("color")
- assert(animation.is_value_provider(raw_color), "Should accept value provider")
-
- # Test rendering
- var frame = animation.frame_buffer(10)
- anim.start()
- var result = anim.render(frame, 1000, engine.strip_length)
- assert(result == true, "Should render successfully")
-
- print("✓ All tests passed")
-end
-
-test_my_animation()
-```
-
-### Integration Testing
-
-Test with the animation engine:
-
-```berry
-var strip = global.Leds(30) # Use built-in LED strip
-var engine = animation.create_engine(strip)
-var anim = animation.my_animation(engine)
-
-# Set parameters
-anim.color = 0xFFFF0000
-anim.pos = 5
-anim.beacon_size = 3
-
-engine.add(anim) # Unified method for animations and sequence managers
-engine.run()
-
-# Let it run for a few seconds
-tasmota.delay(3000)
-
-engine.stop()
-print("Integration test completed")
-```
-
-## Best Practices
-
-### Performance
-- **Minimize calculations** in render() method
-- **Cache resolved values** when possible
-- **Use integer math** instead of floating point
-- **Avoid memory allocation** in render loops
-
-### Memory Management
-- **Reuse objects** when possible
-- **Clear references** to large objects when done
-- **Use static variables** for constants
-
-### Code Organization
-- **Group related parameters** together
-- **Use descriptive variable names**
-- **Comment complex algorithms**
-- **Follow Berry naming conventions**
-
-### Error Handling
-- **Validate parameters** in constructor
-- **Handle edge cases** gracefully
-- **Return false** from render() on errors
-- **Use meaningful error messages**
-
-## Publishing Your Animation Class
-
-Once you've created a new animation class:
-
-1. **Add it to the animation module** by importing it in `animation.be`
-2. **Create a factory function** following the engine-first pattern
-3. **Add DSL support** by ensuring the transpiler recognizes your factory function
-4. **Document parameters** in the class hierarchy documentation
-5. **Test with DSL** to ensure users can access your animation declaratively
-
-**Remember**: Users should primarily interact with animations through the DSL. The programmatic API is mainly for framework development and advanced integrations.
-
-This guide provides everything needed to create professional-quality animation classes that integrate seamlessly with the Berry Animation Framework's parameter system and rendering pipeline.
\ No newline at end of file
diff --git a/lib/libesp32/berry_animation/berry_animation_docs/DSL_REFERENCE.md b/lib/libesp32/berry_animation/berry_animation_docs/DSL_REFERENCE.md
deleted file mode 100644
index 2d6610d03..000000000
--- a/lib/libesp32/berry_animation/berry_animation_docs/DSL_REFERENCE.md
+++ /dev/null
@@ -1,1695 +0,0 @@
-# DSL Reference - Animation DSL Language Specification
-
-This document provides a comprehensive reference for the Animation DSL syntax, keywords, and grammar. It focuses purely on the language specification without implementation details.
-
-For detailed information about the DSL transpiler's internal architecture and processing flow, see [TRANSPILER_ARCHITECTURE.md](TRANSPILER_ARCHITECTURE.md).
-
-## Language Overview
-
-The Animation DSL is a declarative language for defining LED strip animations. It uses natural, readable syntax with named parameters and supports colors, animations, sequences, and property assignments.
-
-## Comments
-
-Comments use the `#` character and extend to the end of the line:
-
-```berry
-# This is a full-line comment
-# strip length 30 # This is an inline comment (TEMPORARILY DISABLED)
-color bordeaux = 0x6F2C4F # This is an inline comment
-```
-
-Comments are preserved in the generated code and can appear anywhere in the DSL.
-
-## Program Structure
-
-A DSL program consists of statements that can appear in any order:
-
-```berry
-# Strip configuration is handled automatically
-# strip length 60 # TEMPORARILY DISABLED
-
-# Color definitions
-color bordeaux = 0x6F2C4F
-color majorelle = 0x6050DC
-
-# Animation definitions
-animation pulse_bordeaux = pulsating_animation(color=bordeaux, period=2s)
-
-# Property assignments
-pulse_red.priority = 10
-
-# Sequences
-sequence demo {
- play pulse_bordeaux for 5s
- wait 1s
-}
-
-# Execution
-run demo
-```
-
-## Keywords
-
-### Reserved Keywords
-
-The following keywords are reserved and cannot be used as identifiers:
-
-**Configuration Keywords:**
-- `strip` - Strip configuration (temporarily disabled, reserved keyword)
-- `set` - Variable assignment
-- `import` - Import Berry modules
-- `berry` - Embed arbitrary Berry code
-- `extern` - Declare external Berry functions for DSL use
-
-**Definition Keywords:**
-- `color` - Color definition
-- `palette` - Palette definition
-- `animation` - Animation definition
-- `sequence` - Sequence definition
-- `template` - Template definition
-- `param` - Template parameter declaration
-- `type` - Parameter type annotation
-
-**Control Flow Keywords:**
-- `play` - Play animation in sequence
-- `wait` - Wait/pause in sequence
-- `repeat` - Repeat loop
-- `times` - Loop count specifier
-- `for` - Duration specifier
-- `run` - Execute animation or sequence
-- `restart` - Restart value provider or animation from beginning
-
-**Easing Keywords:**
-- `linear` - Linear/triangle wave easing
-- `triangle` - Triangle wave easing (alias for linear)
-- `smooth` - Smooth cosine easing
-- `sine` - Pure sine wave easing
-- `ease_in` - Ease in transition (quadratic acceleration)
-- `ease_out` - Ease out transition (quadratic deceleration)
-- `ramp` - Ramp/sawtooth easing
-- `sawtooth` - Sawtooth easing (alias for ramp)
-- `square` - Square wave easing
-- `elastic` - Elastic easing with spring-like overshoot
-- `bounce` - Bounce easing like a ball with decreasing amplitude
-
-**Value Keywords:**
-- `true` - Boolean true
-- `false` - Boolean false
-- `nil` - Null value
-- `transparent` - Transparent color
-
-### Predefined Colors
-
-The following color names are predefined and cannot be redefined:
-
-**Primary Colors:**
-- `red`, `green`, `blue`
-- `white`, `black`
-
-**Extended Colors:**
-- `yellow`, `orange`, `purple`, `pink`
-- `cyan`, `magenta`, `gray`, `grey`
-- `silver`, `gold`, `brown`
-- `lime`, `navy`, `olive`
-- `maroon`, `teal`, `aqua`
-- `fuchsia`, `indigo`, `violet`
-- `crimson`, `coral`, `salmon`
-- `khaki`, `plum`, `orchid`
-- `turquoise`, `tan`, `beige`
-- `ivory`, `snow`
-- `transparent`
-
-## Data Types
-
-### Numbers
-
-```berry
-42 # Integer
-3.14 # Floating point
--5 # Negative number
-```
-
-### Time Values
-
-Time values require a unit suffix and are automatically converted to milliseconds:
-
-```berry
-500ms # Milliseconds (stays 500)
-2s # Seconds (converted to 2000ms)
-1m # Minutes (converted to 60000ms)
-1h # Hours (converted to 3600000ms)
-```
-
-### Percentages
-
-Percentages use the `%` suffix and are automatically converted to 0-255 range with possible over-shooting:
-
-```berry
-0% # 0 percent (converted to 0)
-50% # 50 percent (converted to 128)
-100% # 100 percent (converted to 255)
-120% # 120 percent (converted to 306)
-```
-
-### Colors
-
-#### Hexadecimal Colors
-
-```berry
-0xFF0000 # Red (RGB format)
-0x80FF0000 # Semi-transparent red (ARGB format)
-```
-
-#### Named Colors
-
-```berry
-red # Predefined color name
-blue # Predefined color name
-transparent # Transparent color
-```
-
-### Strings
-
-```berry
-"hello" # Double-quoted string
-'world' # Single-quoted string
-```
-
-### Identifiers
-
-Identifiers must start with a letter or underscore, followed by letters, digits, or underscores:
-
-```berry
-my_color # Valid identifier
-_private_var # Valid identifier
-Color123 # Valid identifier
-```
-
-## Configuration Statements
-
-### Strip Configuration
-
-**Note: The `strip` directive is temporarily disabled.** Strip configuration is handled automatically by the host system.
-
-~~The `strip` statement configures the LED strip and must be the first statement if present:~~
-
-```berry
-# strip length 60 # TEMPORARILY DISABLED
-```
-
-~~If omitted,~~ The system uses the configured strip length from the host system.
-
-### Variable Assignment
-
-The `set` keyword assigns static values or value providers to global variables:
-
-```berry
-set brightness = 200 # Static integer value
-set cycle_time = 5s # Static time value (converted to 5000ms)
-set opacity_level = 80% # Static percentage (converted to 204)
-
-# Value providers for dynamic values
-set brightness_osc = smooth(min_value=50, max_value=255, period=3s)
-set position_sweep = triangle(min_value=0, max_value=29, period=5s)
-
-# Computed values using strip length
-set strip_len = strip_length() # Get current strip length
-```
-
-### Import Statements
-
-The `import` keyword imports Berry modules for use in animations:
-
-```berry
-import user_functions # Import user-defined functions
-import my_custom_module # Import custom animation libraries
-import math # Import standard Berry modules
-import string # Import utility modules
-```
-
-**Import Behavior:**
-- Module names should be valid identifiers (no quotes needed in DSL)
-- Import statements are typically placed at the beginning of DSL files
-- Transpiles to standard Berry `import "module_name"` statements
-- Imported modules become available for the entire animation
-
-**Common Use Cases:**
-```berry
-# Import user functions for computed parameters
-import user_functions
-
-animation dynamic = solid(color=blue)
-dynamic.opacity = my_custom_function()
-
-# Import custom animation libraries
-import fire_effects
-
-animation campfire = fire_effects.create_fire(intensity=200)
-```
-
-**Transpilation Example:**
-```berry
-# DSL Code
-import user_functions
-
-# Transpiles to Berry Code
-import "user_functions"
-```
-
-### Berry Code Blocks
-
-The `berry` keyword allows embedding arbitrary Berry code within DSL files using triple-quoted strings:
-
-```berry
-berry """
-import math
-var custom_value = math.pi * 2
-print("Custom calculation:", custom_value)
-"""
-
-berry '''
-# Alternative syntax with single quotes
-def helper_function(x)
- return x * 1.5
-end
-'''
-```
-
-**Berry Code Block Features:**
-- Code is copied verbatim to the generated Berry code
-- Supports both `"""` and `'''` triple-quote syntax
-- Can span multiple lines and include complex Berry syntax
-- Variables and functions defined in one block are available in subsequent blocks
-- Can interact with DSL-generated objects (e.g., `animation_name_.property = value`)
-
-**Example with DSL Integration:**
-```berry
-animation pulse = pulsating_animation(color=red, period=2s)
-
-berry """
-# Modify animation using Berry code
-pulse_.opacity = 200
-pulse_.priority = 10
-print("Animation configured")
-"""
-
-run pulse
-```
-
-### External Function Declarations
-
-The `extern` keyword declares Berry functions defined in `berry` code blocks so they can be used in DSL expressions and computed parameters:
-
-```berry
-# Define the function in a berry block
-berry """
-def rand_meter(time_ms, self)
- import math
- var r = math.rand() % 101
- return r
-end
-
-def breathing_effect(base_value, amplitude)
- import math
- var time_factor = (tasmota.millis() / 1000) % 4 # 4-second cycle
- var breath = math.sin(time_factor * math.pi / 2)
- return int(base_value + breath * amplitude)
-end
-"""
-
-# Declare functions as external so DSL knows about them
-extern function rand_meter
-extern function breathing_effect
-
-# Now they can be used in DSL expressions
-animation back_pattern = palette_meter_animation(value_func = rand_meter)
-animation breathing_light = solid(color=blue)
-breathing_light.opacity = breathing_effect
-
-run back_pattern
-```
-
-**External Function Features:**
-- Functions must be declared with `extern function function_name` after being defined in `berry` blocks
-- Can be used with or without parentheses: `rand_meter` or `rand_meter()`
-- Automatically receive `engine` as the first parameter when called from DSL
-- Can be used in computed parameters and property assignments
-- Support the same signature pattern as registered user functions
-
-**Function Signature Requirements:**
-External functions should follow the user function pattern where the first parameter is the engine:
-
-```berry
-berry """
-def my_external_func(engine, param1, param2)
- # engine is automatically provided by DSL
- # param1, param2 are user-provided parameters
- return computed_value
-end
-"""
-
-extern function my_external_func
-
-# Usage in DSL (engine parameter is automatic)
-animation test = solid(color=red)
-test.opacity = my_external_func # Called as my_external_func(engine)
-```
-
-**Comparison with User Functions:**
-- **External functions**: Defined in `berry` blocks within the same DSL file, declared with `extern function`
-- **User functions**: Defined in separate Berry modules, imported with `import`, registered with `animation.register_user_function()`
-- Both use the same calling convention and can be used interchangeably in DSL expressions
-
-## Color Definitions
-
-The `color` keyword defines static colors or color providers:
-
-```berry
-# Static colors
-color bordeaux = 0x6F2C4F # Static hex color
-color majorelle = 0x6050DC # Static hex color
-color semi_red = 0x80FF0000 # Static color with alpha channel
-color my_white = white # Reference to predefined color
-
-# Color providers for dynamic colors
-color rainbow_cycle = color_cycle(
- colors=bytes("FFFF0000" "FF00FF00" "FF0000FF")
- period=5s
-)
-color breathing_red = breathe_color(
- base_color=red
- min_brightness=5%
- max_brightness=100%
- duration=3s
- curve_factor=2
-)
-color pulsing_blue = pulsating_color(
- base_color=blue
- min_brightness=20%
- max_brightness=80%
- duration=1s
-)
-```
-
-## Palette Definitions
-
-Palettes define color gradients using position-color pairs and support two encoding formats with flexible syntax:
-
-### Value-Based Palettes (Recommended)
-
-Standard palettes use value positions from 0-255:
-
-```berry
-# Traditional syntax with commas
-palette fire_colors = [
- (0, 0x000000) # Position 0: Black
- (128, 0xFF0000) # Position 128: Red
- (255, 0xFFFF00) # Position 255: Yellow
-]
-
-# New syntax without commas (when entries are on separate lines)
-palette ocean_palette = [
- (0, navy) # Using named colors
- (128, cyan)
- (255, green)
-]
-
-# Mixed syntax also works
-palette matrix_greens = [
- (0, 0x000000), (64, 0x003300) # Multiple entries on one line
- (128, 0x006600) # Single entry on separate line
- (192, 0x00AA00)
- (255, 0x00FF00)
-]
-```
-
-### Tick-Based Palettes (Advanced)
-
-Palettes can also use tick counts for timing-based transitions:
-
-```berry
-palette timed_colors = [
- (10, 0xFF0000) # Red for 10 ticks
- (20, 0x00FF00) # Green for 20 ticks
- (15, 0x0000FF) # Blue for 15 ticks
-]
-```
-
-**Palette Rules:**
-- **Value-based**: Positions range from 0 to 255, represent intensity/brightness levels
-- **Tick-based**: Positions represent duration in arbitrary time units
-- **Colors**: Only hex values (0xRRGGBB) or predefined color names (red, blue, green, etc.)
-- **Custom colors**: Previously defined custom colors are NOT allowed in palettes
-- **Dynamic palettes**: For palettes with custom colors, use user functions instead
-- Entries are automatically sorted by position
-- Comments are preserved
-- Automatically converted to efficient VRGB bytes format
-
-### Palette Color Restrictions
-
-Palettes have strict color validation to ensure compile-time safety:
-
-**✅ Allowed:**
-```berry
-palette valid_colors = [
- (0, 0xFF0000) # Hex colors
- (128, red) # Predefined color names
- (255, blue) # More predefined colors
-]
-```
-
-**❌ Not Allowed:**
-```berry
-color custom_red = 0xFF0000
-palette invalid_colors = [
- (0, custom_red) # ERROR: Custom colors not allowed
- (128, my_color) # ERROR: Undefined color
-]
-```
-
-**Alternative for Dynamic Palettes:**
-For palettes that need custom or computed colors, use user functions:
-
-```berry
-# Define a user function that creates dynamic palettes
-def create_custom_palette(engine, base_color, intensity)
- # Create palette with custom logic
- var palette_data = create_dynamic_palette_bytes(base_color, intensity)
- return palette_data
-end
-
-# Register for DSL use
-animation.register_user_function("custom_palette", create_custom_palette)
-```
-
-```berry
-# Use in DSL
-animation dynamic_anim = rich_palette(
- colors=custom_palette(0xFF0000, 200)
- period=3s
-)
-```
-
-## Animation Definitions
-
-The `animation` keyword defines instances of animation classes (subclasses of Animation):
-
-```berry
-animation red_solid = solid(color=red)
-
-animation pulse_effect = pulsating_animation(
- color=blue
- period=2s
-)
-
-animation comet_trail = comet_animation(
- color=white
- tail_length=10
- speed=1500
- direction=1
-)
-```
-
-**Parameter Syntax:**
-- All parameters use `name=value` format
-- Parameters can reference colors, other animations, or literal values
-- Nested function calls are supported
-
-## Property Assignments
-
-Animation properties can be modified after creation:
-
-```berry
-animation pulse_red = pulsating_animation(color=red, period=2s)
-
-# Set properties
-pulse_red.priority = 10
-pulse_red.opacity = 200
-pulse_red.position = 15
-
-# Dynamic properties using value providers
-pulse_red.position = triangle(min_value=0, max_value=29, period=5s)
-pulse_red.opacity = smooth(min_value=100, max_value=255, period=2s)
-
-# Computed properties using arithmetic expressions
-set strip_len = strip_length()
-pulse_red.position = strip_len / 2 # Center position
-pulse_red.opacity = strip_len * 4 # Scale with strip size
-
-# Animation opacity (using another animation as opacity mask)
-animation opacity_mask = pulsating_animation(period=2s)
-pulse_red.opacity = opacity_mask # Dynamic opacity from animation
-```
-
-**Common Properties:**
-- `priority` - Animation priority (higher numbers have precedence)
-- `opacity` - Opacity level (number, value provider, or animation)
-- `position` - Position on strip
-- `speed` - Speed multiplier
-- `phase` - Phase offset
-
-## Computed Values
-
-The DSL supports computed values using arithmetic expressions with value providers and mathematical functions:
-
-### Safe Patterns
-
-```berry
-# ✅ RECOMMENDED: Single value provider assignment
-set strip_len = strip_length()
-
-# ✅ RECOMMENDED: Computation with existing values
-set strip_len2 = (strip_len + 1) / 2
-
-# Use computed values in animation parameters
-animation stream1 = comet_animation(
- color=red
- tail_length=strip_len / 4 # Computed: quarter of strip length
- speed=1.5
- priority=10
-)
-```
-
-### ⚠️ Dangerous Patterns (Prevented by Transpiler)
-
-The transpiler prevents dangerous patterns that would create new value provider instances at each evaluation:
-
-```berry
-# ❌ DANGEROUS: Function creation in computed expression
-# This would create a new strip_length() instance at each evaluation
-set strip_len3 = (strip_length() + 1) / 2
-
-# ❌ ERROR: Transpiler will reject this with:
-# "Function 'strip_length()' cannot be used in computed expressions.
-# This creates a new instance at each evaluation."
-```
-
-**Why This Is Dangerous:**
-- Creates a new function instance every time the expression is evaluated
-- Causes memory leaks and performance degradation
-- Each new instance has its own timing and state, leading to inconsistent behavior
-
-**Safe Alternative:**
-```berry
-# ✅ CORRECT: Separate the value provider creation from computation
-set strip_len = strip_length() # Single value provider
-set strip_len3 = (strip_len + 1) / 2 # Computation with existing value
-```
-
-**Functions That Are Restricted in Computed Expressions:**
-- Any function that creates instances (value providers, animations, etc.) when called
-- Examples: `strip_length()`, `triangle()`, `smooth()`, `solid()`, etc.
-
-**Note:** These functions are allowed in `set` statements as they create the instance once, but they cannot be used inside arithmetic expressions that get wrapped in closures, as this would create new instances at each evaluation.
-
-### Advanced Computed Values
-
-```berry
-# Complex expressions with multiple operations
-set base_speed = 2.0
-animation stream2 = comet_animation(
- color=blue
- tail_length=strip_len / 8 + 2 # Computed: eighth of strip + 2
- speed=base_speed * 1.5 # Computed: base speed × 1.5
-)
-
-# Computed values in property assignments
-stream1.position = strip_len / 2 # Center of strip
-stream2.opacity = strip_len * 4 # Scale opacity with strip size
-
-# Using mathematical functions in computed values
-animation pulse = pulsating_animation(
- color=red
- period=2s
-)
-pulse.opacity = abs(sine(strip_len) * 128 + 127) # Sine wave opacity
-pulse.position = max(0, min(strip_len - 1, round(strip_len / 2))) # Clamped center position
-```
-
-**Supported Operations:**
-- Addition: `+`
-- Subtraction: `-`
-- Multiplication: `*`
-- Division: `/`
-- Parentheses for grouping: `(expression)`
-
-**Mathematical Functions:**
-The following mathematical functions are available in computed parameters and are automatically detected by the transpiler:
-
-| Function | Description | Parameters | Return Value |
-|----------|-------------|------------|--------------|
-| `min(a, b, ...)` | Returns the minimum value | Two or more numbers | Minimum value |
-| `max(a, b, ...)` | Returns the maximum value | Two or more numbers | Maximum value |
-| `abs(x)` | Returns the absolute value | One number | Absolute value |
-| `round(x)` | Rounds to nearest integer | One number | Rounded integer |
-| `sqrt(x)` | Returns the square root | One number | Square root (scaled for integers) |
-| `scale(v, from_min, from_max, to_min, to_max)` | Scales value from one range to another | Value and range parameters | Scaled integer |
-| `sin(angle)` | Returns sine of angle | Angle in 0-255 range (0-360°) | Sine value in -255 to 255 range |
-| `cos(angle)` | Returns cosine of angle | Angle in 0-255 range (0-360°) | Cosine value in -255 to 255 range |
-
-**Mathematical Function Examples:**
-```berry
-# Basic math functions
-set strip_len = strip_length()
-animation test = pulsating_animation(color=red, period=2s)
-
-# Absolute value for ensuring positive results
-test.opacity = abs(strip_len - 200)
-
-# Min/max for clamping values
-test.position = max(0, min(strip_len - 1, 15)) # Clamp position to valid range
-
-# Rounding for integer positions
-test.position = round(strip_len / 2.5)
-
-# Square root for non-linear scaling
-test.brightness = sqrt(strip_len * 4) # Non-linear brightness based on strip size
-
-# Scaling values between ranges
-test.opacity = scale(strip_len, 10, 60, 50, 255) # Scale strip length to opacity range
-
-# Trigonometric functions for wave patterns
-set angle = 128 # 180 degrees in 0-255 range
-test.opacity = sin(angle) + 128 # Mathematical sine function (not oscillator)
-test.brightness = cos(angle) + 128 # Mathematical cosine function (not oscillator)
-
-# Complex expressions combining multiple functions
-test.position = max(0, round(abs(sin(strip_len * 2)) * (strip_len - 1) / 255))
-test.opacity = min(255, max(50, scale(sqrt(strip_len), 0, 16, 100, 255)))
-```
-
-**Special Notes:**
-- **Integer Optimization**: `sqrt()` function automatically handles integer scaling for 0-255 range values
-- **Trigonometric Range**: `sin()` and `cos()` use 0-255 input range (mapped to 0-360°) and return -255 to 255 output range
-- **Automatic Detection**: Mathematical functions are automatically detected at transpile time using dynamic introspection
-- **Closure Context**: In computed parameters, mathematical functions are called as `animation._math.()` in the generated closure context
-
-**How It Works:**
-When the DSL detects arithmetic expressions containing value providers, variable references, or mathematical functions, it automatically creates closure functions that capture the computation. These closures are called with `(self, param_name, time_ms)` parameters, allowing the computation to be re-evaluated dynamically as needed. Mathematical functions are automatically prefixed with `animation._math.` in the closure context to access the ClosureValueProvider's mathematical methods.
-
-**User Functions in Computed Parameters:**
-User-defined functions can also be used in computed parameter expressions, providing powerful custom effects:
-
-```berry
-# Simple user function in computed parameter
-animation base = solid(color=blue)
-base.opacity = rand_demo()
-
-# User functions mixed with math operations
-animation dynamic = solid(
- color=purple
- opacity=max(50, min(255, rand_demo() + 100))
-)
-```
-
-### User Functions
-
-User functions are custom Berry functions that can be called from computed parameters. They provide dynamic values that change over time.
-
-**Available User Functions:**
-- `rand_demo()` - Returns random values for demonstration purposes
-
-**Usage in Computed Parameters:**
-```berry
-# Simple user function
-animation.opacity = rand_demo()
-
-# User function with math operations
-animation.opacity = max(100, rand_demo())
-
-# User function in arithmetic expressions
-animation.opacity = abs(rand_demo() - 128) + 64
-```
-
-**Available User Functions:**
-The following user functions are available by default (see [User Functions Guide](USER_FUNCTIONS.md) for details):
-
-| Function | Parameters | Description |
-|----------|------------|-------------|
-| `rand_demo()` | none | Returns a random value (0-255) for demonstration |
-
-**User Function Behavior:**
-- User functions are automatically detected by the transpiler
-- They receive `self.engine` as the first parameter in closure context
-- They can be mixed with mathematical functions and arithmetic operations
-- The entire expression is wrapped in a single efficient closure
-
-## Sequences
-
-Sequences orchestrate multiple animations with timing control. The DSL supports two syntaxes for sequences with repeat functionality:
-
-### Basic Sequence Syntax
-
-```berry
-sequence demo {
- play red_animation for 3s
- wait 1s
- play blue_animation for 2s
-
- repeat 3 times {
- play flash_effect for 200ms
- wait 300ms
- }
-
- play final_animation
-}
-```
-
-### Repeat Sequence Syntax
-
-For sequences that are primarily repeating patterns, you can use the alternative syntax:
-
-```berry
-# Option 1: Traditional syntax with repeat sub-sequence
-sequence cylon_eye {
- repeat forever {
- play red_eye for 3s
- red_eye.pos = triangle_val
- play red_eye for 3s
- red_eye.pos = cosine_val
- eye_color.next = 1
- }
-}
-
-# Option 2: Alternative syntax - sequence with repeat modifier
-sequence cylon_eye repeat forever {
- play red_eye for 3s
- red_eye.pos = triangle_val
- play red_eye for 3s
- red_eye.pos = cosine_val
- eye_color.next = 1
-}
-
-# Option 3: Parametric repeat count
-sequence rainbow_cycle repeat palette.size times {
- play animation for 1s
- colors.next = 1
-}
-```
-
-**Note**: All syntaxes are functionally equivalent. The repeat count can be a literal number, variable, or dynamic expression that evaluates at runtime.
-
-### Sequence Statements
-
-#### Play Statement
-
-```berry
-play animation_name # Play indefinitely
-play animation_name for 5s # Play for specific duration
-play animation_name for duration_var # Play for variable duration
-```
-
-#### Wait Statement
-
-```berry
-wait 1s # Wait for 1 second
-wait 500ms # Wait for 500 milliseconds
-wait duration_var # Wait for variable duration
-```
-
-#### Duration Support
-
-Both `play` and `wait` statements support flexible duration specifications:
-
-**Literal Time Values:**
-```berry
-play animation for 5s # 5 seconds
-play animation for 2000ms # 2000 milliseconds
-play animation for 1m # 1 minute
-```
-
-**Variable References:**
-```berry
-set short_time = 2s
-set long_time = 10s
-
-sequence demo {
- play animation for short_time # Use variable duration
- wait long_time # Variables work in wait too
-}
-```
-
-**Value Providers (Dynamic Duration):**
-```berry
-set dynamic_duration = triangle(min_value=1000, max_value=5000, period=10s)
-
-sequence demo {
- play animation for dynamic_duration # Duration changes over time
-}
-```
-
-**Examples:**
-```berry
-# Cylon eye with variable duration
-set eye_duration = 5s
-
-sequence cylon_eye forever {
- play red_eye for eye_duration # Use variable for consistent timing
- red_eye.pos = triangle_val
- play red_eye for eye_duration # Same duration for both phases
- red_eye.pos = cosine_val
- eye_color.next = 1
-}
-```
-
-#### Repeat Statement
-
-Repeat statements create runtime sub-sequences that execute repeatedly:
-
-```berry
-repeat 3 times { # Repeat exactly 3 times
- play animation for 1s
- wait 500ms
-}
-
-repeat forever { # Repeat indefinitely until parent sequence stops
- play animation for 1s
- wait 500ms
-}
-
-repeat col1.palette_size times { # Parametric repeat count using property access
- play animation for 1s
- col1.next = 1
-}
-```
-
-**Repeat Count Types:**
-- **Literal numbers**: `repeat 5 times` - fixed repeat count
-- **Variables**: `repeat count_var times` - using previously defined variables
-- **Property access**: `repeat color_provider.palette_size times` - dynamic values from object properties
-- **Computed expressions**: `repeat strip_length() / 2 times` - calculated repeat counts
-
-**Repeat Behavior:**
-- **Runtime Execution**: Repeats are executed at runtime, not expanded at compile time
-- **Dynamic Evaluation**: Parametric repeat counts are evaluated when the sequence starts
-- **Sub-sequences**: Each repeat block creates a sub-sequence that manages its own iteration state
-- **Nested Repeats**: Supports nested repeats with multiplication (e.g., `repeat 3 times { repeat 2 times { ... } }` executes 6 times total)
-- **Forever Loops**: `repeat forever` continues until the parent sequence is stopped
-- **Efficient**: No memory overhead for large repeat counts
-
-#### Assignment Statement
-
-Property assignments can be performed within sequences to dynamically modify animation parameters during playback:
-
-```berry
-sequence demo {
- play red_eye for 3s
- red_eye.pos = triangle_val # Change position to triangle oscillator
- play red_eye for 3s
- red_eye.pos = cosine_val # Change position to cosine oscillator
- eye_color.next = 1 # Advance color cycle to next color
-}
-```
-
-**Assignment Semantics:**
-- Assignments in sequences have exactly the same semantics as assignments outside sequences
-- They can assign static values, value providers, or computed expressions
-- Assignments are executed instantly when the sequence step is reached
-- The assignment is wrapped in a closure: `def (engine) end`
-
-**Examples:**
-```berry
-sequence dynamic_show {
- play pulse_anim for 2s
- pulse_anim.opacity = 128 # Set static opacity
- play pulse_anim for 2s
- pulse_anim.opacity = brightness # Use value provider
- play pulse_anim for 2s
- pulse_anim.color = next_color # Change color provider
- play pulse_anim for 2s
-}
-
-# Assignments work in repeat blocks too
-sequence cylon_eye {
- repeat 3 times {
- play red_eye for 1s
- red_eye.pos = triangle_val # Change oscillator pattern
- play red_eye for 1s
- red_eye.pos = cosine_val # Change back
- eye_color.next = 1 # Advance color
- }
-}
-```
-
-#### If Statement
-
-Conditional execution statements that run their body 0 or 1 times based on a boolean condition:
-
-```berry
-if condition { # Execute if condition is true (non-zero)
- play animation for 1s
- wait 500ms
-}
-```
-
-**Condition Types:**
-- **Static values**: `if true { ... }`, `if false { ... }`, `if 5 { ... }`
-- **Variables**: `if flag { ... }` - using previously defined variables
-- **Template parameters**: `if self.enabled { ... }` - dynamic values from template parameters
-- **Computed expressions**: `if strip_length() > 30 { ... }` - calculated conditions
-
-**If Behavior:**
-- **Boolean Coercion**: All conditions are wrapped with `bool()` to ensure 0 or 1 iterations
-- **Static Optimization**: Static conditions (literals) are evaluated at compile time without closures
-- **Dynamic Evaluation**: Dynamic conditions (variables, parameters) are wrapped in closures
-- **Conditional Gate**: Useful for enabling/disabling parts of sequences based on flags
-
-**Examples:**
-```berry
-# Static condition
-sequence demo {
- if true {
- play animation for 1s
- }
-}
-
-# Template parameter condition
-template animation configurable {
- param enable_effect type bool default true
-
- color my_red = 0xFF0000
- animation solid_red = solid(color=my_red)
-
- sequence main repeat forever {
- if enable_effect {
- play solid_red for 1s
- }
- }
-
- run main
-}
-
-# Variable condition
-set flag = true
-sequence conditional {
- if flag {
- play animation for 2s
- }
-}
-
-# Bidirectional animation with flags
-template animation shutter_bidir {
- param ascending type bool default true
- param descending type bool default true
-
- sequence shutter_seq repeat forever {
- if ascending {
- play shutter_lr for 2s
- }
- if descending {
- play shutter_rl for 2s
- }
- }
-
- run shutter_seq
-}
-```
-
-**Comparison with Repeat:**
-- `if condition { ... }` - Runs 0 or 1 times (boolean gate)
-- `repeat count times { ... }` - Runs exactly `count` times (iteration)
-
-#### Restart Statements
-
-Restart statements allow you to restart value providers and animations from their initial state during sequence execution:
-
-```berry
-restart value_provider_name # Restart value provider from beginning
-restart animation_name # Restart animation from beginning
-```
-
-**Restart Statement:**
-- Restarts value providers (oscillators, color cycles, etc.) from their initial state
-- Restarts animations from their beginning state
-- Calls the `start()` method on the value provider or animation, which resets the time origin only if the object was already started previously
-- Useful for synchronizing oscillators, restarting color cycles, or restarting complex animations
-
-**Timing Behavior:**
-- The `start()` method only resets the time origin if `self.start_time` is not nil (i.e., the object was already started)
-- For fresh objects, the first call to `update()`, `render()`, or `produce_value()` initializes the time reference
-- This prevents premature time initialization and ensures proper timing behavior
-
-**Examples:**
-```berry
-# Restart oscillators for synchronized movement
-sequence sync_demo {
- play wave_anim for 3s
- restart position_osc # Restart oscillator time origin
- play wave_anim for 3s
-}
-
-# Restart animations for clean transitions
-sequence clean_transitions {
- play comet_anim for 5s
- restart comet_anim # Restart from beginning position
- play comet_anim for 5s
-}
-```
-
-## Template Animations
-
-Template animations provide a powerful way to create reusable, parameterized animation classes. They allow you to define animation blueprints that can be instantiated multiple times with different parameters, promoting code reuse and maintainability.
-
-**Template-Only Files**: DSL files containing only template animation definitions transpile to pure Berry classes without engine initialization or execution code. This allows template animations to be used as reusable animation libraries.
-
-### Template Animation Definition
-
-Template animations are defined using the `template animation` keywords followed by a parameter block and body:
-
-```berry
-template animation shutter_effect {
- param colors type palette nillable true
- param duration type time min 0 max 3600 default 5 nillable false
-
- set strip_len = strip_length()
- set shutter_size = sawtooth(min_value = 0, max_value = strip_len, duration = duration)
-
- color col = color_cycle(colors=colors, period=0)
-
- animation shutter = beacon_animation(
- color = col
- pos = strip_len / 2
- beacon_size = shutter_size
- priority = 5
- )
-
- sequence seq repeat forever {
- restart shutter_size
- play shutter for duration
- col.next = 1
- }
-
- run seq
-}
-
-# Use the template animation
-palette rainbow = [red, orange, yellow, green, blue, indigo, white]
-animation my_shutter = shutter_effect(colors=rainbow, duration=2s)
-run my_shutter
-```
-
-**Code Generation:**
-Template animations generate Berry classes extending `engine_proxy`:
-
-```berry
-class shutter_effect_animation : animation.engine_proxy
- static var PARAMS = animation.enc_params({
- "colors": {"type": "palette"},
- "duration": {"type": "time", "min": 0, "max": 3600, "default": 5}
- })
-
- def init(engine)
- super(self).init(engine)
- # Generated code with self.colors and self.duration references
- self.add(seq_)
- end
-end
-```
-
-**Parameter Constraints:**
-Template animation parameters support constraints:
-- `type` - Parameter type (palette, time, int, color, etc.)
-- `min` - Minimum value (for numeric types)
-- `max` - Maximum value (for numeric types)
-- `default` - Default value
-- `nillable` - Whether parameter can be nil (true/false)
-
-**Implicit Parameters:**
-Template animations automatically inherit parameters from the `engine_proxy` class hierarchy. These parameters are available without explicit declaration and can be used directly in your template animation body:
-
-```berry
-# These parameters are implicitly available in all template animations:
-param id type string default "animation"
-param priority type int default 10
-param duration type int default 0
-param loop type bool default false
-param opacity type int default 255
-param color type int default 0
-param is_running type bool default false
-```
-
-**Example using implicit parameters:**
-```berry
-template animation fade_effect {
- param colors type palette
-
- # 'duration' is an implicit parameter - no need to declare it
- set oscillator = sawtooth(min_value=0, max_value=255, duration=duration)
-
- color col = color_cycle(colors=colors, period=0)
- animation test = solid(color=col)
-
- # 'opacity' is also implicit
- test.opacity = oscillator
-
- run test
-}
-
-# When instantiating, you can set implicit parameters
-animation my_fade = fade_effect(colors=rainbow)
-my_fade.duration = 5000 # Set the implicit duration parameter
-my_fade.opacity = 200 # Set the implicit opacity parameter
-```
-
-**Notes on Implicit Parameters:**
-- Implicit parameters can be overridden by explicit declarations if needed
-- They follow the same constraint rules as explicit parameters
-- They are accessed as `self.` within the template body
-- All implicit parameters come from the `Animation` and `ParameterizedObject` base classes
-
-**Key Features:**
-- Generates reusable animation classes extending `engine_proxy`
-- Parameters accessed as `self.` within the template body
-- Uses `self.add()` to add child animations
-- Can be instantiated multiple times with different parameters
-- Supports parameter constraints (type, min, max, default, nillable)
-
-### Template Parameter Validation
-
-The DSL transpiler provides comprehensive validation for template parameters to ensure code quality and catch errors early:
-
-**Parameter Name Validation:**
-- **Duplicate Detection**: Prevents using the same parameter name twice
-- **Reserved Keywords**: Prevents conflicts with Berry keywords (`animation`, `color`, `def`, etc.)
-- **Built-in Colors**: Prevents conflicts with predefined color names (`red`, `blue`, etc.)
-
-```berry
-template bad_example {
- param color type color # ❌ Error: conflicts with built-in color
- param animation type number # ❌ Error: conflicts with reserved keyword
- param my_param type color
- param my_param type number # ❌ Error: duplicate parameter name
-}
-```
-
-**Type Annotation Validation:**
-
-Valid parameter types for `static var PARAMS` and template parameters:
-
-| Type | Description | Synonym For | Example |
-|------|-------------|-------------|---------|
-| `int` | Integer values | - | `{"type": "int", "default": 100}` |
-| `bool` | Boolean values | - | `{"type": "bool", "default": false}` |
-| `string` | String values | - | `{"type": "string", "default": "name"}` |
-| `bytes` | Byte buffers (palettes) | - | `{"type": "bytes", "default": bytes("FF0000")}` |
-| `function` | Functions/closures | - | `{"type": "function", "default": nil}` |
-| `animation` | Animation instances | - | Symbol table tracking |
-| `value_provider` | Value provider instances | - | Symbol table tracking |
-| `number` | Generic numeric type | - | Numeric constraints only |
-| `any` | Any type (no validation) | - | `{"type": "any", "default": nil}` |
-| `color` | Color values | `int` | `{"type": "color", "default": 0xFFFF0000}` |
-| `palette` | Palette definitions | `bytes` | `{"type": "palette", "default": bytes(...)}` |
-| `time` | Time values (ms) | `int` | `{"type": "time", "default": 5000}` |
-| `percentage` | Percentage (0-255) | `int` | `{"type": "percentage", "default": 128}` |
-
-**Note:** Types `color`, `palette`, `time`, and `percentage` are user-friendly synonyms that map to their base types during validation.
-
-```berry
-template type_example {
- param my_color type invalid_type # ❌ Error: invalid type annotation
- param valid_color type color # ✅ Valid type annotation
-}
-```
-
-**Parameter Usage Validation:**
-The transpiler generates **warnings** (not errors) for unused parameters:
-
-```berry
-template unused_example {
- param used_color type color
- param unused_param type number # ⚠️ Warning: parameter never used
-
- animation test = solid(color=used_color)
- run test
-}
-```
-
-**Validation Benefits:**
-- **Early Error Detection**: Catches parameter issues at compile time
-- **Clear Error Messages**: Provides helpful suggestions for fixing issues
-- **Code Quality**: Encourages proper parameter naming and usage
-- **Warnings vs Errors**: Unused parameters generate warnings that don't prevent compilation
-
-## Execution Statements
-
-Execute animations or sequences:
-
-```berry
-run animation_name # Run an animation
-run sequence_name # Run a sequence
-```
-
-### Debug and Logging
-
-Log debug messages during animation execution:
-
-```berry
-log("Debug message") # Log message at level 3
-log("Animation started") # Useful for debugging sequences
-log("Color changed to red") # Track animation state changes
-```
-
-**Log Function Behavior:**
-- Accepts string literals only (no variables or expressions)
-- Transpiles to Berry `log(f"message", 3)`
-- Messages are logged at level 3 for debugging purposes
-- Can be used anywhere in DSL code: standalone, in sequences, etc.
-
-## Operators and Expressions
-
-### Arithmetic Operators
-
-```berry
-+ # Addition
-- # Subtraction (also unary minus)
-* # Multiplication
-/ # Division
-% # Modulo
-```
-
-### Comparison Operators
-
-```berry
-== # Equal to
-!= # Not equal to
-< # Less than
-<= # Less than or equal
-> # Greater than
->= # Greater than or equal
-```
-
-### Logical Operators
-
-```berry
-&& # Logical AND
-|| # Logical OR
-! # Logical NOT
-```
-
-### Assignment Operators
-
-```berry
-= # Simple assignment
-```
-
-## Function Calls
-
-Functions use named parameter syntax with flexible formatting:
-
-```berry
-# Single line (commas required)
-function_name(param1=value1, param2=value2)
-
-# Multi-line (commas optional when parameters are on separate lines)
-function_name(
- param1=value1
- param2=value2
- param3=value3
-)
-
-# Mixed syntax (both commas and newlines work)
-function_name(
- param1=value1, param2=value2
- param3=value3
-)
-```
-
-**Examples:**
-```berry
-# Traditional single-line syntax
-solid(color=red)
-pulsating_animation(color=blue, period=2s)
-
-# New multi-line syntax (no commas needed)
-pulsating_animation(
- color=blue
- period=2s
- brightness=255
-)
-
-# Mixed syntax
-comet_animation(
- color=stream_pattern, tail_length=15
- speed=1.5s
- priority=10
-)
-```
-
-**Nested Function Calls:**
-```berry
-pulsating_animation(
- color=solid(color=red)
- period=smooth(
- min_value=1000
- max_value=3000
- period=10s
- )
-)
-```
-
-**Mathematical Functions in Computed Parameters:**
-Mathematical functions can be used in computed parameter expressions and are automatically detected by the transpiler:
-
-```berry
-animation wave = pulsating_animation(
- color=blue
- period=2s
-)
-
-# Mathematical functions in property assignments
-wave.opacity = abs(sine(strip_length()) - 128) # Sine wave opacity
-wave.position = max(0, min(strip_length() - 1, 15)) # Clamped position
-wave.brightness = round(sqrt(strip_length()) * 4) # Non-linear scaling
-```
-
-## Supported Classes
-
-### Value Providers
-
-Value providers create dynamic values that change over time:
-
-| Function | Description |
-|----------|-------------|
-| `static_value` | Returns a constant value |
-| `strip_length` | Returns the LED strip length in pixels |
-| `oscillator_value` | Oscillates between min/max values with various waveforms |
-
-**Oscillator Aliases:**
-| Function | Description |
-|----------|-------------|
-| `triangle` | Triangle wave oscillation (alias for oscillator with triangle waveform) |
-| `smooth` | Smooth cosine wave (alias for oscillator with smooth waveform) |
-| `cosine_osc` | Cosine wave oscillation (alias for smooth - cosine waveform) |
-| `sine_osc` | Pure sine wave oscillation (alias for oscillator with sine waveform) |
-| `linear` | Linear progression (alias for oscillator with linear waveform) |
-| `ramp` | Sawtooth wave (alias for oscillator with ramp waveform) |
-| `sawtooth` | Sawtooth wave (alias for ramp) |
-| `square` | Square wave oscillation |
-| `ease_in` | Quadratic ease-in (starts slow, accelerates) |
-| `ease_out` | Quadratic ease-out (starts fast, decelerates) |
-| `elastic` | Elastic easing with spring-like overshoot |
-| `bounce` | Bounce easing like a ball with decreasing amplitude |
-
-```berry
-# Direct oscillator usage
-triangle(min_value=0, max_value=255, period=2s) # Triangle wave
-smooth(min_value=50, max_value=200, period=3s) # Smooth cosine
-cosine_osc(min_value=3, max_value=1, period=5s) # Cosine wave (alias for smooth)
-sine_osc(min_value=0, max_value=255, period=2s) # Pure sine wave
-linear(min_value=0, max_value=100, period=1s) # Linear progression
-ramp(min_value=0, max_value=255, period=2s) # Sawtooth wave
-square(min_value=0, max_value=255, period=1s) # Square wave
-ease_in(min_value=0, max_value=255, period=2s) # Quadratic ease-in
-ease_out(min_value=0, max_value=255, period=2s) # Quadratic ease-out
-elastic(min_value=0, max_value=255, period=2s) # Elastic spring effect
-bounce(min_value=0, max_value=255, period=2s) # Bouncing ball effect
-
-# Value providers can be assigned to variables
-set brightness_oscillator = smooth(min_value=50, max_value=255, period=3s)
-set position_sweep = triangle(min_value=0, max_value=29, period=5s)
-set elastic_movement = elastic(min_value=0, max_value=30, period=4s)
-set sine_wave = sine_osc(min_value=0, max_value=255, period=2s)
-set cosine_wave = cosine_osc(min_value=50, max_value=200, period=3s)
-set strip_len = strip_length() # Get the current strip length
-```
-
-### Color Providers
-
-Color providers create dynamic colors that change over time:
-
-| Function | Description |
-|----------|-------------|
-| `static_color` | Solid color with optional dynamic opacity |
-| `color_cycle` | Cycles through a palette of colors |
-| `rich_palette` | Advanced palette-based color cycling with smooth transitions |
-| `composite_color` | Combines multiple color providers |
-| `breathe_color` | Breathing/pulsing color effect with brightness modulation |
-| `pulsating_color` | Fast pulsing color effect (alias for breathe_color with curve_factor=1) |
-
-### Animation Classes
-
-Animation classes create visual effects on LED strips:
-
-| Function | Description |
-|----------|-------------|
-| `solid` | Solid color fill |
-| `pulsating_animation` | Pulsing brightness effect |
-| `beacon_animation` | Positioned pulse effect |
-| `crenel_animation` | Square wave pulse at specific position |
-| `breathe_animation` | Breathing/fading effect |
-| `comet_animation` | Moving comet with trailing tail |
-| `fire_animation` | Realistic fire simulation |
-| `twinkle_animation` | Twinkling stars effect |
-| `gradient_animation` | Color gradient effects |
-| `noise_animation` | Perlin noise-based patterns |
-| `wave_animation` | Wave propagation effects |
-| `rich_palette_animation` | Palette-based color cycling |
-| `palette_wave_animation` | Wave patterns using palettes |
-| `palette_gradient_animation` | Gradient patterns using palettes |
-| `palette_meter_animation` | Meter/bar patterns using palettes |
-
-## Error Handling
-
-### Validation Rules
-
-The DSL performs comprehensive validation at compile time:
-
-1. **Reserved Names**: Cannot redefine keywords or predefined colors
-2. **Class Existence**: Animation and color provider factory functions must exist
-3. **Parameter Validation**: Function parameters must exist and be valid for the specific class
-4. **Type Checking**: Values must match expected types
-5. **Reference Resolution**: All referenced identifiers must be defined
-
-### Compile-Time Validation
-
-The DSL validates class and parameter existence during compilation, catching errors before execution:
-
-- **Factory Functions**: Verifies that animation and color provider factories exist in the animation module
-- **Parameter Names**: Checks that all named parameters are valid for the specific class
-- **Parameter Constraints**: Validates parameter values against defined constraints (min/max, enums, types)
-- **Nested Validation**: Validates parameters in nested function calls and value providers
-- **Property Assignment Validation**: Validates parameter names in property assignments (e.g., `animation.invalid_param = value`) against the actual class parameters
-- **Object Reference Validation**: Validates that referenced objects exist in `run` statements and sequence `play` statements
-
-### Common Errors
-
-```berry
-# Invalid: Redefining predefined color
-color red = 0x800000 # Error: Cannot redefine 'red'
-
-# Invalid: Unknown parameter in constructor
-animation bad = pulsating_animation(invalid_param=123) # Error: Unknown parameter
-
-# Invalid: Unknown parameter in property assignment
-animation pulse = pulsating_animation(color=red, period=2s)
-pulse.wrong_arg = 15 # Error: Parameter 'wrong_arg' not valid for PulseAnimation
-
-# Invalid: Undefined reference in color definition
-animation ref = solid(color=undefined_color) # Error: Undefined reference
-
-# Invalid: Undefined reference in run statement
-run undefined_animation # Error: Undefined reference 'undefined_animation' in run
-
-# Invalid: Undefined reference in sequence
-sequence demo {
- play undefined_animation for 5s # Error: Undefined reference 'undefined_animation' in sequence play
-}
-
-# Valid alternatives
-color my_red = 0x800000 # OK: Different name
-animation good = pulsating_animation(color=red, period=2s) # OK: Valid parameters
-good.priority = 10 # OK: Valid parameter assignment
-```
-
-## Formal Grammar (EBNF)
-
-```ebnf
-(* Animation DSL Grammar *)
-
-program = { statement } ;
-
-statement = import_stmt
- | config_stmt
- | definition
- | property_assignment
- | sequence
- | template_def
- | external_stmt
- | execution_stmt ;
-
-(* Import and Configuration *)
-import_stmt = "import" identifier ;
-config_stmt = variable_assignment ;
-external_stmt = "extern" "function" identifier ;
-(* strip_config = "strip" "length" number ; -- TEMPORARILY DISABLED *)
-variable_assignment = "set" identifier "=" expression ;
-
-(* Definitions *)
-definition = color_def | palette_def | animation_def | template_animation_def ;
-color_def = "color" identifier "=" color_expression ;
-palette_def = "palette" identifier "=" palette_array ;
-animation_def = "animation" identifier "=" animation_expression ;
-template_animation_def = "template" "animation" identifier "{" template_body "}" ;
-
-(* Property Assignments *)
-property_assignment = identifier "." identifier "=" expression ;
-
-(* Sequences *)
-sequence = "sequence" identifier [ "repeat" ( expression "times" | "forever" ) ] "{" sequence_body "}" ;
-sequence_body = { sequence_statement } ;
-sequence_statement = play_stmt | wait_stmt | repeat_stmt | if_stmt | sequence_assignment | restart_stmt ;
-
-play_stmt = "play" identifier [ "for" time_expression ] ;
-wait_stmt = "wait" time_expression ;
-repeat_stmt = "repeat" ( expression "times" | "forever" ) "{" sequence_body "}" ;
-if_stmt = "if" expression "{" sequence_body "}" ;
-sequence_assignment = identifier "." identifier "=" expression ;
-restart_stmt = "restart" identifier ;
-
-(* Template Animations *)
-template_animation_def = "template" "animation" identifier "{" template_body "}" ;
-template_body = { template_statement } ;
-template_statement = param_decl | color_def | palette_def | animation_def | property_assignment | sequence_def | execution_stmt ;
-param_decl = "param" identifier [ "type" identifier ] [ constraint_list ] ;
-constraint_list = ( "min" number | "max" number | "default" expression | "nillable" boolean ) { constraint_list } ;
-
-(* Execution *)
-execution_stmt = "run" identifier ;
-
-(* Expressions *)
-expression = logical_or_expr ;
-logical_or_expr = logical_and_expr { "||" logical_and_expr } ;
-logical_and_expr = equality_expr { "&&" equality_expr } ;
-equality_expr = relational_expr { ( "==" | "!=" ) relational_expr } ;
-relational_expr = additive_expr { ( "<" | "<=" | ">" | ">=" ) additive_expr } ;
-additive_expr = multiplicative_expr { ( "+" | "-" ) multiplicative_expr } ;
-multiplicative_expr = unary_expr { ( "*" | "/" | "%" ) unary_expr } ;
-unary_expr = ( "!" | "-" | "+" ) unary_expr | primary_expr ;
-primary_expr = literal | identifier | function_call | "(" expression ")" ;
-
-(* Color Expressions *)
-color_expression = hex_color | named_color | identifier ;
-hex_color = "0x" hex_digit{6} | "0x" hex_digit{8} ;
-named_color = color_name ;
-
-(* Animation Expressions *)
-animation_expression = function_call | identifier ;
-
-(* Palette Arrays *)
-palette_array = "[" palette_entry { "," palette_entry } "]" ;
-palette_entry = "(" number "," color_expression ")" ;
-
-(* Function Calls *)
-function_call = identifier "(" [ named_argument_list ] ")" ;
-named_argument_list = named_argument { "," named_argument } ;
-named_argument = identifier "=" expression ;
-
-(* Time Expressions *)
-time_expression = time_literal ;
-time_literal = number time_unit ;
-time_unit = "ms" | "s" | "m" | "h" ;
-
-(* Literals *)
-literal = number | string | color_expression | time_expression | percentage | boolean ;
-number = integer | real ;
-integer = [ "-" ] digit { digit } ;
-real = [ "-" ] digit { digit } "." digit { digit } ;
-string = '"' { string_char } '"' | "'" { string_char } "'" ;
-percentage = number "%" ;
-boolean = "true" | "false" ;
-
-(* Identifiers *)
-identifier = ( letter | "_" ) { letter | digit | "_" } ;
-color_name = "red" | "green" | "blue" | "white" | "black" | "yellow"
- | "orange" | "purple" | "pink" | "cyan" | "magenta" | "gray"
- | "silver" | "gold" | "brown" | "lime" | "navy" | "olive"
- | "maroon" | "teal" | "aqua" | "fuchsia" | "transparent" ;
-
-(* Character Classes *)
-letter = "a" .. "z" | "A" .. "Z" ;
-digit = "0" .. "9" ;
-hex_digit = digit | "A" .. "F" | "a" .. "f" ;
-string_char = (* any character except quote *) ;
-
-(* Comments and Whitespace *)
-comment = "#" { (* any character except newline *) } newline ;
-whitespace = " " | "\t" | "\r" | "\n" ;
-newline = "\n" | "\r\n" ;
-```
-
-## Flexible Parameter Syntax
-
-The DSL supports flexible parameter syntax that makes multi-line function calls more readable:
-
-### Traditional Syntax (Commas Required)
-```berry
-animation stream = comet_animation(color=red, tail_length=15, speed=1.5s, priority=10)
-```
-
-### New Multi-Line Syntax (Commas Optional)
-```berry
-animation stream = comet_animation(
- color=red
- tail_length=15
- speed=1.5s
- priority=10
-)
-```
-
-### Mixed Syntax (Both Supported)
-```berry
-animation stream = comet_animation(
- color=red, tail_length=15
- speed=1.5s
- priority=10
-)
-```
-
-### Rules
-- **Single line**: Commas are required between parameters
-- **Multi-line**: Commas are optional when parameters are on separate lines
-- **Mixed**: You can use both commas and newlines as separators
-- **Comments**: Inline comments work with both syntaxes
-
-This applies to:
-- Animation function calls
-- Color provider function calls
-- Value provider function calls
-- Palette entries
-
-## Language Features Summary
-
-### ✅ Currently Implemented
-- Comments with preservation
-- Strip configuration (optional)
-- Color definitions (hex and named)
-- Palette definitions with VRGB conversion
-- Animation definitions with named parameters
-- Property assignments
-- Basic sequences (play, wait, repeat, if)
-- **Conditional execution**: `if` statement for boolean-based conditional execution
-- Variable assignments with type conversion
-- Reserved name validation
-- Parameter validation at compile time
-- Execution statements
-- **Template animations**: Reusable animation classes with parameters extending `engine_proxy`
-- User-defined functions (with engine-first parameter pattern) - see **[User Functions Guide](USER_FUNCTIONS.md)**
-- **External function declarations**: `extern` keyword to declare Berry functions defined in `berry` blocks for DSL use
-- **User functions in computed parameters**: User functions can be used in arithmetic expressions alongside mathematical functions
-- **Flexible parameter syntax**: Commas optional when parameters are on separate lines
-- **Computed values**: Arithmetic expressions with value providers automatically create closures
-- **Mathematical functions**: `min`, `max`, `abs`, `round`, `sqrt`, `scale`, `sine`, `cosine` in computed parameters
-
-### 🚧 Partially Implemented
-- Expression evaluation (basic support)
-- Nested function calls (working but limited)
-- Error recovery (basic error reporting)
-
-### ❌ Planned Features
-- Advanced control flow (else, elif, choose random)
-- Event system and handlers
-- Variable references with $ syntax
-- Spatial operations and zones
-- 2D matrix support
-
-This reference provides the complete syntax specification for the Animation DSL language as currently implemented and planned for future development.
\ No newline at end of file
diff --git a/lib/libesp32/berry_animation/berry_animation_docs/DSL_TRANSPILATION.md b/lib/libesp32/berry_animation/berry_animation_docs/DSL_TRANSPILATION.md
deleted file mode 100644
index ed15d231b..000000000
--- a/lib/libesp32/berry_animation/berry_animation_docs/DSL_TRANSPILATION.md
+++ /dev/null
@@ -1,798 +0,0 @@
-# DSL Reference - Berry Animation Framework
-
-This document provides a comprehensive reference for the Animation DSL (Domain-Specific Language), which allows you to define animations using a declarative syntax with named parameters.
-
-## Module Import
-
-The DSL functionality is provided by a separate module:
-
-```berry
-import animation # Core framework (required)
-import animation_dsl # DSL compiler and runtime (required for DSL)
-```
-
-## Why Use the DSL?
-
-### Benefits
-- **Declarative syntax**: Describe what you want, not how to implement it
-- **Readable code**: Natural language-like syntax
-- **Rapid prototyping**: Quick iteration on animation ideas
-- **Event-driven**: Built-in support for interactive animations
-- **Composition**: Easy layering and sequencing of animations
-
-### When to Use DSL vs Programmatic
-
-**Use DSL when:**
-- Creating complex animation sequences
-- Building interactive, event-driven animations
-- Rapid prototyping and experimentation
-- Non-programmers need to create animations
-- You want declarative, readable animation definitions
-
-**Use programmatic API when:**
-- Building reusable animation components
-- Performance is critical (DSL has compilation overhead)
-- You need fine-grained control over animation logic
-- Integrating with existing Berry code
-- Firmware size is constrained (DSL module can be excluded)
-
-## Transpiler Architecture
-
-For detailed information about the DSL transpiler's internal architecture, including the core processing flow and expression processing chain, see [TRANSPILER_ARCHITECTURE.md](TRANSPILER_ARCHITECTURE.md).
-
-## DSL API Functions
-
-### Core Functions
-
-#### `animation_dsl.compile(source)`
-Compiles DSL source code to Berry code without executing it.
-
-```berry
-var dsl_source = "color red = 0xFF0000\n"
- "animation red_anim = solid(color=red)\n"
- "run red_anim"
-
-var berry_code = animation_dsl.compile(dsl_source)
-print(berry_code) # Shows generated Berry code
-```
-
-#### `animation_dsl.execute(source)`
-Compiles and executes DSL source code in one step.
-
-```berry
-animation_dsl.execute("color blue = 0x0000FF\n"
- "animation blue_anim = solid(color=blue)\n"
- "run blue_anim for 5s")
-```
-
-#### `animation_dsl.load_file(filename)`
-Loads DSL source from a file and executes it.
-
-```berry
-# Create a DSL file
-var f = open("my_animation.dsl", "w")
-f.write("color green = 0x00FF00\n"
- "animation pulse_green = pulsating_animation(color=green, period=2s)\n"
- "run pulse_green")
-f.close()
-
-# Load and execute
-animation_dsl.load_file("my_animation.dsl")
-```
-
-## DSL Language Overview
-
-The Animation DSL uses a declarative syntax with named parameters. All animations are created with an engine-first pattern and parameters are set individually for maximum flexibility.
-
-### Key Syntax Features
-
-- **Import statements**: `import module_name` for loading Berry modules
-- **Named parameters**: All function calls use `name=value` syntax
-- **Time units**: `2s`, `500ms`, `1m`, `1h`
-- **Hex colors**: `0xFF0000`, `0x80FF0000` (ARGB)
-- **Named colors**: `red`, `blue`, `white`, etc.
-- **Comments**: `# This is a comment`
-- **Property assignment**: `animation.property = value`
-- **User functions**: `function_name()` for custom functions
-
-### Basic Structure
-
-```berry
-# Import statements (optional, for user functions or custom modules)
-import user_functions
-
-# Optional strip configuration
-strip length 60
-
-# Color definitions
-color red = 0xFF0000
-color blue = 0x0000FF
-
-# Animation definitions with named parameters
-animation pulse_red = pulsating_animation(color=red, period=2s)
-animation comet_blue = comet_animation(color=blue, tail_length=10, speed=1500)
-
-# Property assignments with user functions
-pulse_red.priority = 10
-pulse_red.opacity = breathing_effect()
-comet_blue.direction = -1
-
-# Execution
-run pulse_red
-
-```
-
-The DSL transpiles to Berry code where each animation gets an engine parameter and named parameters are set individually.
-
-## Symbol Resolution
-
-The DSL transpiler uses intelligent symbol resolution at compile time to optimize generated code and eliminate runtime lookups:
-
-### Transpile-Time Symbol Resolution
-
-When the DSL encounters an identifier (like `SINE` or `red`), it checks at transpile time whether the symbol exists in the `animation` module using Berry's introspection capabilities:
-
-```berry
-# If SINE exists in animation module
-animation wave = wave_animation(waveform=SINE)
-# Transpiles to: animation.SINE (direct access)
-
-# If custom_color doesn't exist in animation module
-color custom_color = 0xFF0000
-animation solid_red = solid(color=custom_color)
-# Transpiles to: custom_color_ (user-defined variable)
-```
-
-### Benefits
-
-- **Performance**: Eliminates runtime symbol lookups for built-in constants
-- **Error Detection**: Catches undefined symbols at compile time
-- **Code Clarity**: Generated Berry code clearly shows built-in vs user-defined symbols
-- **Optimization**: Direct access to animation module symbols is faster
-
-### Symbol Categories
-
-**Built-in Symbols** (resolved to `animation.`):
-- Animation factory functions: `solid`, `pulsating_animation`, `comet_animation`
-- Value providers: `triangle`, `smooth`, `sine`, `static_value`
-- Color providers: `color_cycle`, `breathe_color`, `rich_palette`
-- Constants: `PALETTE_RAINBOW`, `SINE`, `TRIANGLE`, etc.
-
-**User-defined Symbols** (resolved to `_`):
-- Custom colors: `my_red`, `fire_color`
-- Custom animations: `pulse_effect`, `rainbow_wave`
-- Variables: `brightness_level`, `cycle_time`
-
-### Property Assignment Resolution
-
-Property assignments also use the same resolution logic:
-
-```berry
-# Built-in symbol (if 'engine' existed in animation module)
-engine.brightness = 200
-# Would transpile to: animation.engine.brightness = 200
-
-# User-defined symbol
-my_animation.priority = 10
-# Transpiles to: my_animation_.priority = 10
-```
-
-This intelligent resolution ensures optimal performance while maintaining clear separation between framework and user code.
-
-## Import Statement Transpilation
-
-The DSL supports importing Berry modules using the `import` keyword, which provides a clean way to load user functions and custom modules.
-
-### Import Syntax
-
-```berry
-# DSL Import Syntax
-import user_functions
-import my_custom_module
-import math
-```
-
-### Transpilation Behavior
-
-Import statements are transpiled directly to Berry import statements with quoted module names:
-
-```berry
-# DSL Code
-import user_functions
-
-# Transpiles to Berry Code
-import "user_functions"
-```
-
-### Import Processing
-
-1. **Early Processing**: Import statements are processed early in transpilation
-2. **Module Loading**: Imported modules are loaded using standard Berry import mechanism
-3. **Function Registration**: User function modules should register functions using `animation.register_user_function()`
-4. **No Validation**: The DSL doesn't validate module existence at compile time
-
-### Example Import Workflow
-
-**Step 1: Create User Functions Module (`user_functions.be`)**
-```berry
-import animation
-
-def rand_demo(engine)
- import math
- return math.rand() % 256
-end
-
-# Register for DSL use
-animation.register_user_function("rand_demo", rand_demo)
-```
-
-**Step 2: Use in DSL**
-```berry
-import user_functions
-
-animation test = solid(color=blue)
-test.opacity = rand_demo()
-run test
-```
-
-**Step 3: Generated Berry Code**
-```berry
-import animation
-var engine = animation.init_strip()
-
-import "user_functions"
-var test_ = animation.solid(engine)
-test_.color = 0xFF0000FF
-test_.opacity = animation.create_closure_value(engine,
- def (engine) return animation.get_user_function('rand_demo')(engine) end)
-engine.add(test_)
-engine.run()
-```
-
-## Berry Code Block Transpilation
-
-The DSL supports embedding arbitrary Berry code using the `berry` keyword with triple-quoted strings. This provides an escape hatch for complex logic while maintaining the declarative nature of the DSL.
-
-### Berry Code Block Syntax
-
-```berry
-# DSL Berry Code Block
-berry """
-import math
-var custom_value = math.pi * 2
-print("Custom calculation:", custom_value)
-"""
-```
-
-### Transpilation Behavior
-
-Berry code blocks are copied verbatim to the generated Berry code with comment markers:
-
-```berry
-# DSL Code
-berry """
-var test_var = 42
-print("Hello from berry block")
-"""
-
-# Transpiles to Berry Code
-# Berry code block
-var test_var = 42
-print("Hello from berry block")
-# End berry code block
-```
-
-### Integration with DSL Objects
-
-Berry code can interact with DSL-generated objects by using the underscore suffix naming convention:
-
-```berry
-# DSL Code
-animation pulse = pulsating_animation(color=red, period=2s)
-berry """
-pulse_.opacity = 200
-pulse_.priority = 10
-"""
-
-# Transpiles to Berry Code
-var pulse_ = animation.pulsating_animation(engine)
-pulse_.color = animation.red
-pulse_.period = 2000
-# Berry code block
-pulse_.opacity = 200
-pulse_.priority = 10
-# End berry code block
-```
-
-## Advanced DSL Features
-
-### Templates
-
-The DSL supports two types of templates: regular templates (functions) and template animations (classes).
-
-#### Template Animation Transpilation
-
-Template animations create reusable animation classes extending `engine_proxy`:
-
-```berry
-# DSL Template Animation
-template animation shutter_effect {
- param colors type palette nillable true
- param duration type time min 0 max 3600 default 5 nillable false
-
- set strip_len = strip_length()
- color col = color_cycle(colors=colors, period=0)
-
- animation shutter = beacon_animation(
- color = col
- beacon_size = strip_len / 2
- )
-
- sequence seq repeat forever {
- play shutter for duration
- col.next = 1
- }
-
- run seq
-}
-```
-
-**Transpiles to:**
-
-```berry
-class shutter_effect_animation : animation.engine_proxy
- static var PARAMS = animation.enc_params({
- "colors": {"type": "palette", "nillable": true},
- "duration": {"type": "time", "min": 0, "max": 3600, "default": 5, "nillable": false}
- })
-
- def init(engine)
- super(self).init(engine)
-
- var strip_len_ = animation.strip_length(engine)
- var col_ = animation.color_cycle(engine)
- col_.colors = animation.create_closure_value(engine, def (engine) return self.colors end)
- col_.period = 0
-
- var shutter_ = animation.beacon_animation(engine)
- shutter_.color = col_
- shutter_.beacon_size = animation.create_closure_value(engine, def (engine) return animation.resolve(strip_len_) / 2 end)
-
- var seq_ = animation.sequence_manager(engine, -1)
- .push_play_step(shutter_, animation.resolve(self.duration))
- .push_closure_step(def (engine) col_.next = 1 end)
-
- self.add(seq_)
- end
-end
-```
-
-**Key Features:**
-- Parameters accessed as `self.` and wrapped in closures
-- Constraints (min, max, default, nillable) encoded in PARAMS
-- Uses `self.add()` instead of `engine.add()`
-- Can be instantiated multiple times with different parameters
-
-#### Regular Template Transpilation
-
-Regular templates generate Berry functions:
-
-```berry
-# DSL Template
-template pulse_effect {
- param color type color
- param speed
-
- animation pulse = pulsating_animation(color=color, period=speed)
- run pulse
-}
-```
-
-**Transpiles to:**
-
-```berry
-def pulse_effect_template(engine, color_, speed_)
- var pulse_ = animation.pulsating_animation(engine)
- pulse_.color = color_
- pulse_.period = speed_
- engine.add(pulse_)
-end
-
-animation.register_user_function('pulse_effect', pulse_effect_template)
-```
-
-#### Template vs Template Animation
-
-**Template Animation** (`template animation`):
-- Generates classes extending `engine_proxy`
-- Parameters accessed as `self.`
-- Supports parameter constraints (min, max, default, nillable)
-- Uses `self.add()` for composition
-- Can be instantiated multiple times
-
-**Regular Template** (`template`):
-- Generates functions
-- Parameters accessed as `_`
-- Uses `engine.add()` for execution
-- Called like functions
-
-### User-Defined Functions
-
-Register custom Berry functions for use in DSL. User functions must take `engine` as the first parameter, followed by any user-provided arguments:
-
-```berry
-# Define custom function in Berry - engine must be first parameter
-def custom_twinkle(engine, color, count, period)
- var anim = animation.twinkle_animation(engine)
- anim.color = color
- anim.count = count
- atml:parameter>
-
- return anim
-end
-
-# Register the function for DSL use
-animation.register_user_function("twinkle", custom_twinkle)
-```
-
-```berry
-# Use in DSL - engine is automatically passed as first argument
-animation gold_twinkle = twinkle(0xFFD700, 8, 500ms)
-animation blue_twinkle = twinkle(blue, 12, 300ms)
-run gold_twinkle
-```
-
-**Important**: The DSL transpiler automatically passes `engine` as the first argument to all user functions. Your function signature must include `engine` as the first parameter, but DSL users don't need to provide it when calling the function.
-
-For comprehensive examples and best practices, see the **[User Functions Guide](USER_FUNCTIONS.md)**.
-
-### Event System
-
-Define event handlers that respond to triggers:
-
-```berry
-# Define animations for different states
-color normal = 0x000080
-color alert = 0xFF0000
-
-animation normal_state = solid(color=normal)
-animation alert_state = pulsating_animation(color=alert, period=500ms)
-
-# Event handlers
-on button_press {
- run alert_state for 3s
- run normal_state
-}
-
-on sensor_trigger {
- run alert_state for 5s
- wait 1s
- run normal_state
-}
-
-# Default state
-run normal_state
-```
-
-### Nested Function Calls
-
-DSL supports nested function calls for complex compositions:
-
-```berry
-# Nested calls in animation definitions (now supported)
-animation complex = pulsating_animation(
- color=red,
- period=2s
-)
-
-# Nested calls in run statements
-sequence demo {
- play pulsating_animation(color=blue, period=1s) for 10s
-}
-```
-
-## Error Handling
-
-The DSL compiler validates classes and parameters at transpilation time, catching errors before execution:
-
-```berry
-var invalid_dsl = "color red = #INVALID_COLOR\n"
- "animation bad = unknown_function(red)\n"
- "animation pulse = pulsating_animation(invalid_param=123)"
-
-try
- animation_dsl.execute(invalid_dsl)
-except .. as e
- print("DSL Error:", e)
-end
-```
-
-### Transpilation-Time Validation
-
-The DSL performs comprehensive validation during compilation:
-
-**Animation Factory Validation:**
-```berry
-# Error: Function doesn't exist
-animation bad = nonexistent_animation(color=red)
-# Transpiler error: "Animation factory function 'nonexistent_animation' does not exist"
-
-# Error: Function exists but doesn't create animation
-animation bad2 = math_function(value=10)
-# Transpiler error: "Function 'math_function' does not create an animation instance"
-```
-
-**Parameter Validation:**
-```berry
-# Error: Invalid parameter name in constructor
-animation pulse = pulsating_animation(invalid_param=123)
-# Transpiler error: "Parameter 'invalid_param' is not valid for pulsating_animation"
-
-# Error: Invalid parameter name in property assignment
-animation pulse = pulsating_animation(color=red, period=2s)
-pulse.wrong_arg = 15
-# Transpiler error: "Animation 'PulseAnimation' does not have parameter 'wrong_arg'"
-
-# Error: Parameter constraint violation
-animation comet = comet_animation(tail_length=-5)
-# Transpiler error: "Parameter 'tail_length' value -5 violates constraint: min=1"
-```
-
-**Color Provider Validation:**
-```berry
-# Error: Color provider doesn't exist
-color bad = nonexistent_color_provider(period=2s)
-# Transpiler error: "Color provider factory 'nonexistent_color_provider' does not exist"
-
-# Error: Function exists but doesn't create color provider
-color bad2 = pulsating_animation(color=red)
-# Transpiler error: "Function 'pulsating_animation' does not create a color provider instance"
-```
-
-**Reference Validation:**
-```berry
-# Error: Undefined color reference
-animation pulse = pulsating_animation(color=undefined_color)
-# Transpiler error: "Undefined reference: 'undefined_color'"
-
-# Error: Undefined animation reference in run statement
-run nonexistent_animation
-# Transpiler error: "Undefined reference 'nonexistent_animation' in run"
-
-# Error: Undefined animation reference in sequence
-sequence demo {
- play nonexistent_animation for 5s
-}
-# Transpiler error: "Undefined reference 'nonexistent_animation' in sequence play"
-```
-
-**Function Call Safety Validation:**
-```berry
-# Error: Dangerous function creation in computed expression
-set strip_len3 = (strip_length() + 1) / 2
-# Transpiler error: "Function 'strip_length()' cannot be used in computed expressions.
-# This creates a new instance at each evaluation. Use either:
-# set var_name = strip_length() # Single function call
-# set computed = (existing_var + 1) / 2 # Computation with existing values"
-```
-
-**Why This Validation Exists:**
-The transpiler prevents dangerous patterns where functions that create instances are called inside computed expressions that get wrapped in closures. This would create a new instance every time the closure is evaluated, leading to:
-- Memory leaks
-- Performance degradation
-- Inconsistent behavior due to multiple timing states
-
-**Safe Alternative:**
-```berry
-# ✅ CORRECT: Separate function call from computation
-set strip_len = strip_length() # Single function call
-set strip_len3 = (strip_len + 1) / 2 # Computation with existing value
-```
-
-**Template Parameter Validation:**
-```berry
-# Error: Duplicate parameter names
-template bad_template {
- param color type color
- param color type number # Error: duplicate parameter name
-}
-# Transpiler error: "Duplicate parameter name 'color' in template"
-
-# Error: Reserved keyword as parameter name
-template reserved_template {
- param animation type color # Error: conflicts with reserved keyword
-}
-# Transpiler error: "Parameter name 'animation' conflicts with reserved keyword"
-
-# Error: Built-in color name as parameter
-template color_template {
- param red type number # Error: conflicts with built-in color
-}
-# Transpiler error: "Parameter name 'red' conflicts with built-in color name"
-
-# Error: Invalid type annotation
-template type_template {
- param value type invalid_type # Error: invalid type
-}
-# Transpiler error: "Invalid parameter type 'invalid_type'. Valid types are: [...]"
-
-# Warning: Unused parameter (compilation succeeds)
-template unused_template {
- param used_color type color
- param unused_param type number # Warning: never used
-
- animation test = solid(color=used_color)
- run test
-}
-# Transpiler warning: "Template 'unused_template' parameter 'unused_param' is declared but never used"
-```
-
-### Error Categories
-
-- **Syntax errors**: Invalid DSL syntax (lexer/parser errors)
-- **Factory validation**: Non-existent or invalid animation/color provider factories
-- **Parameter validation**: Invalid parameter names in constructors or property assignments
-- **Template validation**: Invalid template parameter names, types, or usage patterns
-- **Constraint validation**: Parameter values that violate defined constraints (min/max, enums, types)
-- **Reference validation**: Using undefined colors, animations, or variables
-- **Type validation**: Incorrect parameter types or incompatible assignments
-- **Safety validation**: Dangerous patterns that could cause memory leaks or performance issues
-- **Runtime errors**: Errors during Berry code execution (rare with good validation)
-
-### Warning Categories
-
-The DSL transpiler also generates **warnings** that don't prevent compilation but indicate potential code quality issues:
-
-- **Unused parameters**: Template parameters that are declared but never used in the template body
-- **Code quality**: Suggestions for better coding practices
-
-**Warning Behavior:**
-- Warnings are included as comments in the generated Berry code
-- Compilation succeeds even with warnings present
-- Warnings help maintain code quality without being overly restrictive
-
-## Performance Considerations
-
-### DSL vs Programmatic Performance
-
-- **DSL compilation overhead**: ~10-50ms depending on complexity
-- **Generated code performance**: Identical to hand-written Berry code
-- **Memory usage**: DSL compiler uses temporary memory during compilation
-
-### Optimization Tips
-
-1. **Compile once, run many times**:
- ```berry
- var compiled = animation_dsl.compile(dsl_source)
- var fn = compile(compiled)
-
- # Run multiple times without recompilation
- fn() # First execution
- fn() # Subsequent executions are faster
- ```
-
-2. **Use programmatic API for performance-critical code**:
- ```berry
- # DSL for high-level structure
- animation_dsl.execute(
- "sequence main {\n"
- "play performance_critical_anim for 10s\n"
- "}\n"
- "run main"
- )
-
- # Programmatic for performance-critical animations
- var performance_critical_anim = animation.create_optimized_animation()
- ```
-
-## Integration Examples
-
-### With Tasmota Rules
-
-```berry
-# In autoexec.be
-import animation
-import animation_dsl
-
-def handle_rule_trigger(event)
- if event == "motion"
- animation_dsl.execute("color alert = 0xFF0000\n"
- "animation alert_anim = pulsating_animation(color=alert, period=500ms)\n"
- "run alert_anim for 5s")
- elif event == "door"
- animation_dsl.execute("color welcome = 0x00FF00\n"
- "animation welcome_anim = breathe_animation(color=welcome, period=2s)\n"
- "run welcome_anim for 8s")
- end
-end
-
-# Register with Tasmota's rule system
-tasmota.add_rule("motion", handle_rule_trigger)
-```
-
-### With Web Interface
-
-```berry
-# Create web endpoints for DSL execution
-import webserver
-
-def web_execute_dsl()
- var dsl_code = webserver.arg("dsl")
- if dsl_code
- try
- animation_dsl.execute(dsl_code)
- webserver.content_response("DSL executed successfully")
- except .. as e
- webserver.content_response(f"DSL Error: {e}")
- end
- else
- webserver.content_response("No DSL code provided")
- end
-end
-
-webserver.on("/execute_dsl", web_execute_dsl)
-```
-
-## Best Practices
-
-1. **Structure your DSL files**:
- ```berry
- # Strip configuration first
- strip length 60
-
- # Colors next
- color red = 0xFF0000
- color blue = 0x0000FF
-
- # Animations with named parameters
- animation red_solid = solid(color=red)
- animation pulse_red = pulsating_animation(color=red, period=2s)
-
- # Property assignments
- pulse_red.priority = 10
-
- # Sequences
- sequence demo {
- play pulse_red for 5s
- }
-
- # Execution last
- run demo
- ```
-
-2. **Use meaningful names**:
- ```berry
- # Good
- color warning_red = 0xFF0000
- animation door_alert = pulsating_animation(color=warning_red, period=500ms)
-
- # Avoid
- color c1 = 0xFF0000
- animation a1 = pulsating_animation(color=c1, period=500ms)
- ```
-
-3. **Comment your DSL**:
- ```berry
- # Security system colors
- color normal_blue = 0x000080 # Idle state
- color alert_red = 0xFF0000 # Alert state
- color success_green = 0x00FF00 # Success state
-
- # Main security animation sequence
- sequence security_demo {
- play solid(color=normal_blue) for 10s # Normal operation
- play pulsating_animation(color=alert_red, period=500ms) for 3s # Alert
- play breathe_animation(color=success_green, period=2s) for 5s # Success confirmation
- }
- ```
-
-4. **Organize complex projects**:
- ```berry
- # Load DSL modules
- animation_dsl.load_file("colors.dsl") # Color definitions
- animation_dsl.load_file("animations.dsl") # Animation library
- animation_dsl.load_file("sequences.dsl") # Sequence definitions
- animation_dsl.load_file("main.dsl") # Main execution
- ```
-
-This completes the DSL reference documentation. The DSL provides a powerful, declarative way to create complex animations while maintaining the option to use the lightweight programmatic API when needed.
\ No newline at end of file
diff --git a/lib/libesp32/berry_animation/berry_animation_docs/EXAMPLES.md b/lib/libesp32/berry_animation/berry_animation_docs/EXAMPLES.md
deleted file mode 100644
index 13a5bdafe..000000000
--- a/lib/libesp32/berry_animation/berry_animation_docs/EXAMPLES.md
+++ /dev/null
@@ -1,479 +0,0 @@
-# Examples
-
-Essential examples showcasing the Tasmota Berry Animation Framework using DSL syntax.
-
-## Basic Animations
-
-### 1. Solid Color
-```berry
-color red = 0xFF0000
-animation red_solid = solid(color=red)
-run red_solid
-```
-
-### 2. Pulsing Effect
-```berry
-color blue = 0x0000FF
-animation blue_pulse = pulsating_animation(color=blue, period=2s)
-run blue_pulse
-```
-
-### 3. Moving Comet
-```berry
-color cyan = 0x00FFFF
-animation comet_trail = comet_animation(color=cyan, tail_length=8, speed=100ms, direction=1)
-run comet_trail
-```
-
-## Using Value Providers
-
-### 4. Breathing Effect
-```berry
-set breathing = smooth(min_value=50, max_value=255, period=3s)
-color white = 0xFFFFFF
-animation breathing_white = solid(color=white)
-breathing_white.opacity = breathing
-run breathing_white
-```
-
-### 5. Color Cycling
-```berry
-color rainbow = rainbow_color_provider(period=5s)
-animation rainbow_cycle = solid(color=rainbow)
-run rainbow_cycle
-```
-
-## Palette Animations
-
-### 6. Fire Effect
-```berry
-palette fire_colors = [
- (0, 0x000000), # Black
- (128, 0xFF0000), # Red
- (192, 0xFF8000), # Orange
- (255, 0xFFFF00) # Yellow
-]
-
-animation fire_effect = palette_animation(colors=fire_colors, period=2s, intensity=255)
-run fire_effect
-```
-
-## Sequences
-
-### 7. RGB Show
-```berry
-color red = 0xFF0000
-color green = 0x00FF00
-color blue = 0x0000FF
-
-animation red_anim = solid(color=red)
-animation green_anim = solid(color=green)
-animation blue_anim = solid(color=blue)
-
-sequence rgb_show {
- play red_anim for 2s
- play green_anim for 2s
- play blue_anim for 2s
-}
-run rgb_show
-```
-
-### 8. Sunrise Sequence
-```berry
-color deep_blue = 0x000080
-color orange = 0xFFA500
-color yellow = 0xFFFF00
-
-animation night = solid(color=deep_blue)
-animation sunrise = pulsating_animation(color=orange, period=3s)
-animation day = solid(color=yellow)
-
-sequence sunrise_show {
- log("Starting sunrise sequence")
- play night for 3s
- log("Night phase complete, starting sunrise")
- play sunrise for 5s
- log("Sunrise complete, switching to day")
- play day for 3s
- log("Sunrise sequence finished")
-}
-run sunrise_show
-```
-
-### 8.1. Variable Duration Sequences
-```berry
-# Define timing variables for consistent durations
-set short_duration = 2s
-set long_duration = 5s
-set fade_time = 1s
-
-animation red_anim = solid(color=red)
-animation green_anim = solid(color=green)
-animation blue_anim = solid(color=blue)
-
-sequence timed_show forever {
- play red_anim for short_duration # Use variable duration
- wait fade_time # Variable wait time
- play green_anim for long_duration # Different variable duration
- wait fade_time
- play blue_anim for short_duration # Reuse timing variable
-}
-run timed_show
-```
-
-## Sequence Assignments
-
-### 9. Dynamic Property Changes
-```berry
-# Create oscillators for dynamic position
-set triangle_val = triangle(min_value=0, max_value=27, duration=5s)
-set cosine_val = cosine_osc(min_value=0, max_value=27, duration=5s)
-
-# Create color cycle
-palette eye_palette = [red, yellow, green, violet]
-color eye_color = color_cycle(colors=eye_palette, period=0)
-
-# Create beacon animation
-animation red_eye = beacon_animation(
- color=eye_color
- pos=cosine_val
- beacon_size=3
- slew_size=2
- priority=10
-)
-
-# Sequence with property assignments
-sequence cylon_eye {
- play red_eye for 3s
- red_eye.pos = triangle_val # Change to triangle oscillator
- play red_eye for 3s
- red_eye.pos = cosine_val # Change back to cosine
- eye_color.next = 1 # Advance to next color
-}
-run cylon_eye
-```
-
-### 10. Multiple Assignments in Sequence
-```berry
-set high_brightness = 255
-set low_brightness = 64
-color my_blue = 0x0000FF
-
-animation test = solid(color=red)
-test.opacity = high_brightness
-
-sequence demo {
- play test for 1s
- test.opacity = low_brightness # Dim the animation
- test.color = my_blue # Change color to blue
- play test for 1s
- test.opacity = high_brightness # Brighten again
- play test for 1s
-}
-run demo
-```
-
-### 11. Restart in Sequences
-```berry
-# Create oscillator and animation
-set wave_osc = triangle(min_value=0, max_value=29, period=4s)
-animation wave = beacon_animation(color=blue, pos=wave_osc, beacon_size=5)
-
-sequence sync_demo {
- play wave for 3s
- restart wave_osc # Restart oscillator time origin (if already started)
- play wave for 3s # Wave starts from beginning again
- restart wave # Restart animation time origin (if already started)
- play wave for 3s
-}
-run sync_demo
-```
-
-### 12. Assignments in Repeat Blocks
-```berry
-set brightness = smooth(min_value=50, max_value=255, period=2s)
-animation pulse = pulsating_animation(color=white, period=1s)
-
-sequence breathing_cycle {
- repeat 3 times {
- play pulse for 500ms
- pulse.opacity = brightness # Apply breathing effect
- wait 200ms
- pulse.opacity = 255 # Return to full brightness
- }
-}
-run breathing_cycle
-```
-
-## User Functions in Computed Parameters
-
-### 13. Simple User Function
-```berry
-# Simple user function in computed parameter
-animation random_base = solid(color=blue, priority=10)
-random_base.opacity = rand_demo()
-run random_base
-```
-
-### 14. User Function with Math Operations
-```berry
-# Mix user functions with mathematical functions
-animation random_bounded = solid(
- color=purple
- opacity=max(50, min(255, rand_demo() + 100))
- priority=15
-)
-run random_bounded
-```
-
-### 15. User Function in Arithmetic Expression
-```berry
-# Use user function in arithmetic expressions
-animation random_variation = solid(
- color=cyan
- opacity=abs(rand_demo() - 128) + 64
- priority=12
-)
-run random_variation
-```
-
-See `anim_examples/user_functions_demo.anim` for a complete working example.
-
-## New Repeat System Examples
-
-### 16. Runtime Repeat with Forever Loop
-```berry
-color red = 0xFF0000
-color blue = 0x0000FF
-animation red_anim = solid(color=red)
-animation blue_anim = solid(color=blue)
-
-# Traditional syntax with repeat sub-sequence
-sequence cylon_effect {
- repeat forever {
- play red_anim for 1s
- play blue_anim for 1s
- }
-}
-
-# Alternative syntax - sequence with repeat modifier
-sequence cylon_effect_alt repeat forever {
- play red_anim for 1s
- play blue_anim for 1s
-}
-
-run cylon_effect
-```
-
-### 17. Nested Repeats (Multiplication)
-```berry
-color green = 0x00FF00
-color yellow = 0xFFFF00
-animation green_anim = solid(color=green)
-animation yellow_anim = solid(color=yellow)
-
-# Nested repeats: 3 × 2 = 6 total iterations
-sequence nested_pattern {
- repeat 3 times {
- repeat 2 times {
- play green_anim for 200ms
- play yellow_anim for 200ms
- }
- wait 500ms # Pause between outer iterations
- }
-}
-run nested_pattern
-```
-
-### 18. Repeat with Property Assignments
-```berry
-set triangle_pos = triangle(min_value=0, max_value=29, period=3s)
-set cosine_pos = cosine_osc(min_value=0, max_value=29, period=3s)
-
-color eye_color = color_cycle(colors=[red, yellow, green, blue], period=0)
-animation moving_eye = beacon_animation(
- color=eye_color
- pos=triangle_pos
- beacon_size=2
- slew_size=1
-)
-
-sequence dynamic_cylon {
- repeat 5 times {
- play moving_eye for 2s
- moving_eye.pos = cosine_pos # Switch to cosine movement
- play moving_eye for 2s
- moving_eye.pos = triangle_pos # Switch back to triangle
- eye_color.next = 1 # Next color
- }
-}
-run dynamic_cylon
-```
-
-## Advanced Examples
-
-### 19. Dynamic Position
-```berry
-strip length 60
-
-set moving_position = smooth(min_value=5, max_value=55, period=4s)
-color purple = 0x8000FF
-
-animation moving_pulse = beacon_animation(
- color=purple,
- position=moving_position,
- beacon_size=3,
- fade_size=2
-)
-run moving_pulse
-```
-
-### 20. Multi-Layer Effect
-```berry
-# Base layer - slow breathing
-set breathing = smooth(min_value=100, max_value=255, period=4s)
-color base_blue = 0x000080
-animation base_layer = solid(color=base_blue)
-base_layer.opacity = breathing
-
-# Accent layer - twinkling stars
-color star_white = 0xFFFFFF
-animation stars = twinkle_animation(color=star_white, count=5, period=800ms)
-stars.opacity = 150
-
-sequence layered_effect {
- play base_layer for 10s
- play stars for 10s
-}
-run layered_effect
-```
-
-## Tips for Creating Animations
-
-### Start Simple
-```berry
-# Begin with basic colors and effects
-color my_color = 0xFF0000
-animation simple = solid(color=my_color)
-run simple
-```
-
-### Use Meaningful Names
-```berry
-# Good - descriptive names
-color sunset_orange = 0xFF8C00
-animation evening_glow = pulsating_animation(color=sunset_orange, period=4s)
-
-# Avoid - unclear names
-color c1 = 0xFF8C00
-animation a1 = pulsating_animation(color=c1, period=4s)
-```
-
-### Test Incrementally
-1. Start with solid colors
-2. Add simple effects like pulse
-3. Experiment with sequences
-4. Combine multiple animations
-
-### Performance Considerations
-- Use sequences instead of multiple simultaneous animations
-- Reuse value providers with the `set` keyword
-- Keep animation periods reasonable (>500ms)
-- Limit palette sizes for memory efficiency
-
-## Template Examples
-
-Templates provide reusable, parameterized animation patterns that promote code reuse and maintainability.
-
-### 21. Simple Template
-```berry
-# Define a reusable blinking template
-template blink_effect {
- param color type color
- param speed
- param intensity
-
- animation blink = pulsating_animation(
- color=color
- period=speed
- )
- blink.opacity = intensity
-
- run blink
-}
-
-# Use the template with different parameters
-blink_effect(red, 1s, 80%)
-blink_effect(blue, 500ms, 100%)
-```
-
-### 22. Multi-Animation Template
-```berry
-# Template that creates a comet chase effect
-template comet_chase {
- param trail_color type color
- param bg_color type color
- param chase_speed
- param tail_size
-
- # Background layer
- animation background = solid(color=bg_color)
- background.priority = 1
-
- # Comet effect layer
- animation comet = comet_animation(
- color=trail_color
- tail_length=tail_size
- speed=chase_speed
- )
- comet.priority = 10
-
- run background
- run comet
-}
-
-# Create different comet effects
-comet_chase(white, black, 1500ms, 8)
-```
-
-### 23. Template with Dynamic Colors
-```berry
-# Template using color cycling and breathing effects
-template breathing_rainbow {
- param cycle_time
- param breath_time
- param base_brightness
-
- # Create rainbow palette
- colors rainbow = [
- (0, red), (42, orange), (85, yellow)
- (128, green), (170, blue), (213, purple), (255, red)
- ]
-
- # Create cycling rainbow color
- color rainbow_cycle = color_cycle(
- colors=rainbow
- period=cycle_time
- )
-
- # Create breathing animation with rainbow colors
- animation breath = pulsating_animation(
- color=rainbow_cycle
- period=breath_time
- )
- breath.opacity = base_brightness
-
- run breath
-}
-
-# Use the rainbow breathing template
-breathing_rainbow(5s, 2s, 200)
-```
-
-## Next Steps
-
-- **[DSL Reference](DSL_REFERENCE.md)** - Complete language syntax
-- **[Troubleshooting](TROUBLESHOOTING.md)** - Common issues and solutions
-- **[Animation Development](ANIMATION_DEVELOPMENT.md)** - Creating custom animations
-
-Start with these examples and build your own amazing LED animations! 🎨✨
\ No newline at end of file
diff --git a/lib/libesp32/berry_animation/berry_animation_docs/OSCILLATION_PATTERNS.md b/lib/libesp32/berry_animation/berry_animation_docs/OSCILLATION_PATTERNS.md
deleted file mode 100644
index 3b4a64e08..000000000
--- a/lib/libesp32/berry_animation/berry_animation_docs/OSCILLATION_PATTERNS.md
+++ /dev/null
@@ -1,263 +0,0 @@
-# Oscillation Patterns
-
-Quick reference for oscillation patterns used with value providers in the Berry Animation Framework.
-
-## Available Oscillation Patterns
-
-These waveform constants can be used with `oscillator_value`:
-
-| Constant | Value | Alias Functions | Behavior | Use Case |
-|----------|-------|-----------------|----------|----------|
-| `SAWTOOTH` | 1 | `linear`, `ramp` | Linear ramp up | Uniform motion |
-| `TRIANGLE` | 2 | `triangle` | Linear up then down | Sharp direction changes |
-| `SQUARE` | 3 | `square` | Alternating min/max | On/off effects |
-| `COSINE` | 4 | `smooth` | Smooth cosine wave | Natural oscillation |
-| `SINE` | 5 | `sine` | Pure sine wave | Classic wave motion |
-| `EASE_IN` | 6 | `ease_in` | Slow start, fast end | Smooth acceleration |
-| `EASE_OUT` | 7 | `ease_out` | Fast start, slow end | Smooth deceleration |
-| `ELASTIC` | 8 | `elastic` | Spring overshoot | Bouncy effects |
-| `BOUNCE` | 9 | `bounce` | Ball bouncing | Physics simulation |
-
-## DSL Usage
-
-### With Oscillator Value Provider
-```berry
-# Basic oscillator with different waveform types
-set breathing = oscillator_value(min_value=50, max_value=255, duration=3000, form=COSINE)
-set pulsing = ease_in(min_value=0, max_value=255, duration=2000)
-set bouncing = oscillator_value(min_value=10, max_value=240, duration=4000, form=TRIANGLE)
-```
-
-### Using Alias Functions
-```berry
-# These are equivalent to oscillator_value with specific forms
-set smooth_fade = smooth(min_value=50, max_value=255, duration=3000) # form=COSINE
-set sine_wave = sine_osc(min_value=50, max_value=255, duration=3000) # form=SINE
-set cosine_wave = cosine_osc(min_value=50, max_value=255, duration=3000) # form=COSINE (alias for smooth)
-set linear_sweep = linear(min_value=0, max_value=255, duration=2000) # form=SAWTOOTH
-set triangle_wave = triangle(min_value=10, max_value=240, duration=4000) # form=TRIANGLE
-```
-
-### In Animations
-```berry
-color blue = 0x0000FF
-set breathing = smooth(min_value=100, max_value=255, duration=4000)
-
-animation breathing_blue = solid(color=blue)
-breathing_blue.opacity = breathing
-run breathing_blue
-```
-
-## Pattern Characteristics
-
-### SAWTOOTH (Linear)
-- **Constant speed** throughout the cycle
-- **Sharp reset** from max back to min
-- **Best for**: Uniform sweeps, mechanical movements
-
-```
-Value
- ^
- | /| /|
- | / | / |
- | / | / |
- | / | / |
- | / | / |
- |/ |/ |
- +------+------+----> Time
-```
-
-```berry
-set linear_brightness = linear(min_value=0, max_value=255, duration=2000)
-```
-
-### COSINE (Smooth)
-- **Gradual acceleration** and deceleration
-- **Natural feeling** transitions
-- **Best for**: Breathing effects, gentle fades
-
-```berry
-set breathing_effect = smooth(min_value=50, max_value=255, duration=3000)
-```
-
-### SINE (Pure Wave)
-- **Classic sine wave** starting from minimum
-- **Smooth acceleration** and deceleration like cosine but phase-shifted
-- **Best for**: Wave effects, classic oscillations, audio-visual sync
-
-```
-Value
- ^
- | ___
- | / \
- | / \
- | / \
- | / \
- | / \
- | / \
- | / \
- |/ \___
- +--------------------+----> Time
-```
-
-```berry
-set wave_motion = sine_osc(min_value=0, max_value=255, duration=2000)
-```
-
-### TRIANGLE
-- **Linear acceleration** to midpoint, then **linear deceleration**
-- **Sharp direction changes** at extremes
-- **Best for**: Bouncing effects, sharp transitions
-
-```
-Value
- ^
- | /\
- | / \
- | / \
- | / \
- | / \
- | / \
- |/ \
- +-------------+----> Time
-```
-
-```berry
-set bounce_position = triangle(min_value=5, max_value=55, duration=2000)
-```
-
-### SQUARE
-- **Alternating** between min and max values
-- **Instant transitions** with configurable duty cycle
-- **Best for**: On/off effects, strobing, digital patterns
-
-```
-Value
- ^
- | +---+ +---+
- | | | | |
- | | | | |
- | | +-----+ |
- | | |
- | | |
- +-+-------------+----> Time
-```
-
-```berry
-set strobe_effect = square(min_value=0, max_value=255, duration=500, duty_cycle=25)
-```
-
-### EASE_IN
-- **Slow start**, **fast finish**
-- **Smooth acceleration** curve
-- **Best for**: Starting animations, building intensity
-
-```berry
-set accelerating = ease_in(min_value=0, max_value=255, duration=3000)
-```
-
-### EASE_OUT
-- **Fast start**, **slow finish**
-- **Smooth deceleration** curve
-- **Best for**: Ending animations, gentle stops
-
-```berry
-set decelerating = ease_out(min_value=255, max_value=0, duration=3000)
-```
-
-## Value Progression Examples
-
-For a cycle from 0 to 100 over 2000ms:
-
-| Time | SAWTOOTH | COSINE | SINE | TRIANGLE | EASE_IN | EASE_OUT |
-|------|----------|--------|------|----------|---------|----------|
-| 0ms | 0 | 0 | 0 | 0 | 0 | 0 |
-| 500ms| 25 | 15 | 50 | 50 | 6 | 44 |
-| 1000ms| 50 | 50 | 100 | 100 | 25 | 75 |
-| 1500ms| 75 | 85 | 50 | 50 | 56 | 94 |
-| 2000ms| 100 | 100 | 0 | 0 | 100 | 100 |
-
-## Common Patterns
-
-### Breathing Effect
-```berry
-color soft_white = 0xC0C0C0
-set breathing = smooth(min_value=80, max_value=255, duration=4000)
-
-animation breathing_light = solid(color=soft_white)
-breathing_light.opacity = breathing
-run breathing_light
-```
-
-### Position Sweep
-```berry
-strip length 60
-color red = 0xFF0000
-set sweeping_position = linear(min_value=0, max_value=59, duration=3000)
-
-animation position_sweep = beacon_animation(
- color=red,
- position=sweeping_position,
- beacon_size=3,
- fade_size=1
-)
-run position_sweep
-```
-
-### Wave Motion
-```berry
-color purple = 0x8000FF
-set wave_brightness = sine(min_value=50, max_value=255, duration=2500)
-
-animation wave_effect = solid(color=purple)
-wave_effect.opacity = wave_brightness
-run wave_effect
-```
-
-### Bouncing Effect
-```berry
-color green = 0x00FF00
-set bounce_size = triangle(min_value=1, max_value=8, duration=1000)
-
-animation bouncing_pulse = beacon_animation(
- color=green,
- position=30,
- beacon_size=bounce_size,
- fade_size=1
-)
-run bouncing_pulse
-```
-
-### Accelerating Fade
-```berry
-color blue = 0x0000FF
-set fade_in = ease_in(min_value=0, max_value=255, duration=5000)
-
-animation accelerating_fade = solid(color=blue)
-accelerating_fade.opacity = fade_in
-run accelerating_fade
-```
-
-### Strobe Effect
-```berry
-color white = 0xFFFFFF
-set strobe_pattern = square(min_value=0, max_value=255, duration=200, duty_cycle=10)
-
-animation strobe_light = solid(color=white)
-strobe_light.opacity = strobe_pattern
-run strobe_light
-```
-
-## Tips
-
-- **COSINE (smooth)**: Most natural for breathing and gentle effects
-- **SINE**: Classic wave motion, perfect for audio-visual sync and pure oscillations
-- **SAWTOOTH (linear)**: Best for consistent sweeps and mechanical movements
-- **TRIANGLE**: Creates sharp, bouncing transitions
-- **EASE_IN**: Perfect for building up intensity
-- **EASE_OUT**: Ideal for gentle fade-outs
-- **ELASTIC**: Spring-like effects with overshoot
-- **BOUNCE**: Physics-based bouncing effects
-- **SQUARE**: Good for on/off blinking effects
-
-Choose the oscillation pattern that matches the feeling you want to create in your animation.
\ No newline at end of file
diff --git a/lib/libesp32/berry_animation/berry_animation_docs/QUICK_START.md b/lib/libesp32/berry_animation/berry_animation_docs/QUICK_START.md
deleted file mode 100644
index 5e3d37c1e..000000000
--- a/lib/libesp32/berry_animation/berry_animation_docs/QUICK_START.md
+++ /dev/null
@@ -1,257 +0,0 @@
-# Quick Start Guide
-
-Get up and running with the Berry Animation Framework in 5 minutes using the DSL!
-
-## Prerequisites
-
-- Tasmota device with Berry support
-- Addressable LED strip (WS2812, SK6812, etc.)
-
-## Step 1: Your First Animation
-
-Create a simple pulsing red light:
-
-```berry
-# Define colors
-color bordeaux = 0x6F2C4F
-
-# Create pulsing animation
-animation pulse_bordeaux = pulsating_animation(color=bordeaux, period=3s)
-
-# Run it
-run pulse_bordeaux
-```
-
-## Step 2: Color Cycling
-
-Create smooth color transitions:
-
-```berry
-# Use predefined rainbow palette
-animation rainbow_cycle = rich_palette(
- colors=PALETTE_RAINBOW
- period=5s
- transition_type=1
-)
-
-run rainbow_cycle
-```
-
-## Step 3: Custom Palettes
-
-Create your own color palettes:
-
-```berry
-# Define a sunset palette
-palette sunset = [
- (0, 0x191970) # Midnight blue
- (64, purple) # Purple
- (128, 0xFF69B4) # Hot pink
- (192, orange) # Orange
- (255, yellow) # Yellow
-]
-
-# Create palette animation
-animation sunset_glow = rich_palette(
- colors=sunset
- period=8s
- transition_type=1
-)
-
-run sunset_glow
-```
-
-## Step 4: Sequences
-
-Create complex shows with sequences:
-
-```berry
-animation red_pulse = pulsating_animation(color=red, period=2s)
-animation green_pulse = pulsating_animation(color=green, period=2s)
-animation blue_pulse = pulsating_animation(color=blue, period=2s)
-
-sequence rgb_show {
- play red_pulse for 3s
- wait 500ms
- play green_pulse for 3s
- wait 500ms
- play blue_pulse for 3s
-
- repeat 2 times {
- play red_pulse for 1s
- play green_pulse for 1s
- play blue_pulse for 1s
- }
-}
-
-run rgb_show
-```
-
-**Pro Tip: Variable Durations**
-Use variables for consistent timing:
-
-```berry
-# Define timing variables
-set short_time = 1s
-set long_time = 3s
-
-sequence timed_show {
- play red_pulse for long_time # Use variable duration
- wait 500ms
- play green_pulse for short_time # Different timing
- play blue_pulse for long_time # Reuse timing
-}
-```
-
-## Step 5: Dynamic Effects
-
-Add movement and variation to your animations:
-
-```berry
-# Breathing effect with smooth oscillation
-animation breathing = pulsating_animation(
- color=blue
- min_brightness=20%
- max_brightness=100%
- period=4s
-)
-
-# Moving comet effect
-animation comet = comet_animation(
- color=white
- tail_length=8
- speed=2000
-)
-
-# Twinkling effect
-animation sparkles = twinkle_animation(
- color=white
- count=8
- period=800ms
-)
-
-run breathing
-```
-
-## Common Patterns
-
-### Fire Effect
-```berry
-animation fire = rich_palette(
- colors=PALETTE_FIRE
- period=2s
- transition_type=1
-)
-
-run fire
-```
-
-## Loading DSL Files
-
-Save your DSL code in `.anim` files and load them:
-
-```berry
-import animation
-
-# Load DSL file
-var runtime = animation.load_dsl_file("my_animation.anim")
-```
-
-## Templates - Reusable Animation Patterns
-
-### Template Animations
-
-Template animations create reusable animation classes with parameters:
-
-```berry
-# Define a template animation with constraints
-template animation shutter_effect {
- param colors type palette nillable true
- param duration type time min 0 max 3600 default 5 nillable false
-
- set strip_len = strip_length()
- color col = color_cycle(colors=colors, period=0)
-
- animation shutter = beacon_animation(
- color = col
- beacon_size = strip_len / 2
- )
-
- sequence seq repeat forever {
- play shutter for duration
- col.next = 1
- }
-
- run seq
-}
-
-# Create multiple instances with different parameters
-palette rainbow = [red, orange, yellow, green, blue]
-animation shutter1 = shutter_effect(colors=rainbow, duration=2s)
-animation shutter2 = shutter_effect(colors=rainbow, duration=5s)
-
-run shutter1
-run shutter2
-```
-
-**Template Animation Features:**
-- **Reusable Classes** - Create multiple instances with different parameters
-- **Parameter Constraints** - min, max, default, nillable values
-- **Composition** - Combine multiple animations and sequences
-- **Type Safe** - Parameter type checking
-- **Implicit Parameters** - Automatically inherit parameters from base classes (name, priority, duration, loop, opacity, color, is_running)
-
-### Regular Templates
-
-Regular templates generate functions for simpler use cases:
-
-```berry
-template pulse_effect {
- param color type color
- param speed
-
- animation pulse = pulsating_animation(color=color, period=speed)
- run pulse
-}
-
-# Use the template
-pulse_effect(red, 2s)
-pulse_effect(blue, 1s)
-```
-
-## User-Defined Functions (Advanced)
-
-For complex logic, create custom functions in Berry:
-
-```berry
-# Define custom function - engine must be first parameter
-def my_twinkle(engine, color, count, period)
- var anim = animation.twinkle_animation(engine)
- anim.color = color
- anim.count = count
- anim.period = period
- return anim
-end
-
-# Register for DSL use
-animation.register_user_function("twinkle", my_twinkle)
-```
-
-```berry
-# Use in DSL - engine is automatically passed
-animation gold_twinkles = twinkle(0xFFD700, 8, 500ms)
-run gold_twinkles
-```
-
-**Note**: The DSL automatically passes `engine` as the first argument to user functions.
-
-## Next Steps
-
-- **[DSL Reference](DSL_REFERENCE.md)** - Complete DSL syntax and features
-- **[User Functions](USER_FUNCTIONS.md)** - Create custom animation functions
-- **[Examples](EXAMPLES.md)** - More complex animation examples
-- **[Animation Class Hierarchy](ANIMATION_CLASS_HIERARCHY.md)** - All available animations and parameters
-- **[Oscillation Patterns](OSCILLATION_PATTERNS.md)** - Dynamic value patterns
-- **[Troubleshooting](TROUBLESHOOTING.md)** - Common issues and solutions
-
-Happy animating! 🎨✨
\ No newline at end of file
diff --git a/lib/libesp32/berry_animation/berry_animation_docs/TRANSPILER_ARCHITECTURE.md b/lib/libesp32/berry_animation/berry_animation_docs/TRANSPILER_ARCHITECTURE.md
deleted file mode 100644
index 7ca28eed2..000000000
--- a/lib/libesp32/berry_animation/berry_animation_docs/TRANSPILER_ARCHITECTURE.md
+++ /dev/null
@@ -1,858 +0,0 @@
-# DSL Transpiler Architecture
-
-This document provides a detailed overview of the Berry Animation DSL transpiler architecture, including the core processing flow and expression processing chain.
-
-## Overview
-
-The DSL transpiler (`transpiler.be`) converts Animation DSL code into executable Berry code. It uses a **ultra-simplified single-pass architecture** with comprehensive validation and code generation capabilities. The refactored transpiler emphasizes simplicity, robustness, and maintainability while providing extensive compile-time validation.
-
-### Single-Pass Architecture Clarification
-
-The transpiler is truly **single-pass** - it processes the token stream once from start to finish. When the documentation mentions "sequential steps" (like in template processing), these refer to **sequential operations within the single pass**, not separate passes over the data. For example:
-
-- Template processing collects parameters, then collects body tokens **sequentially** in one pass
-- Expression transformation handles mathematical functions, then user variables **sequentially** in one operation
-- The transpiler never backtracks or re-processes the same tokens multiple times
-
-## Core Processing Flow
-
-The transpiler follows an **ultra-simplified single-pass architecture** with the following main flow:
-
-```
-transpile()
-├── add("import animation")
-├── while !at_end()
-│ └── process_statement()
-│ ├── Handle comments (preserve in output)
-│ ├── Skip whitespace/newlines
-│ ├── Auto-initialize strip if needed
-│ ├── process_color()
-│ │ ├── validate_user_name()
-│ │ ├── _validate_color_provider_factory_exists()
-│ │ └── _process_named_arguments_for_color_provider()
-│ ├── process_palette()
-│ │ ├── validate_user_name()
-│ │ ├── Detect tuple vs alternative syntax
-│ │ └── process_palette_color() (strict validation)
-│ ├── process_animation()
-│ │ ├── validate_user_name()
-│ │ ├── _validate_animation_factory_creates_animation()
-│ │ └── _process_named_arguments_for_animation()
-│ ├── process_set()
-│ │ ├── validate_user_name()
-│ │ └── process_value()
-│ ├── process_template()
-│ │ ├── validate_user_name()
-│ │ ├── Collect parameters with type annotations
-│ │ ├── Collect body tokens
-│ │ └── generate_template_function()
-│ ├── process_sequence()
-│ │ ├── validate_user_name()
-│ │ ├── Parse repeat syntax (multiple variants)
-│ │ └── process_sequence_statement() (fluent interface)
-│ │ ├── process_play_statement_fluent()
-│ │ ├── process_wait_statement_fluent()
-│ │ ├── process_log_statement_fluent()
-│ │ ├── process_restart_statement_fluent()
-│ │ └── process_sequence_assignment_fluent()
-│ ├── process_import() (direct Berry import generation)
-│ ├── process_event_handler() (basic event system support)
-│ ├── process_berry_code_block() (embed arbitrary Berry code)
-│ ├── process_run() (collect for single engine.run())
-│ └── process_property_assignment()
-└── generate_engine_start() (single call for all run statements)
-```
-
-### Statement Processing Details
-
-#### Color Processing
-```
-process_color()
-├── expect_identifier() → color name
-├── validate_user_name() → check against reserved names
-├── expect_assign() → '='
-├── Check if function call (color provider)
-│ ├── Check template_definitions first
-│ ├── _validate_color_provider_factory_exists()
-│ ├── add("var name_ = animation.func(engine)")
-│ ├── Track in symbol_table for validation
-│ └── _process_named_arguments_for_color_provider()
-└── OR process_value() → static color value with symbol tracking
-```
-
-#### Animation Processing
-```
-process_animation()
-├── expect_identifier() → animation name
-├── validate_user_name() → check against reserved names
-├── expect_assign() → '='
-├── Check if function call (animation factory)
-│ ├── Check template_definitions first
-│ ├── _validate_animation_factory_creates_animation()
-│ ├── add("var name_ = animation.func(engine)")
-│ ├── Track in symbol_table for validation
-│ └── _process_named_arguments_for_animation()
-└── OR process_value() → reference or literal with symbol tracking
-```
-
-#### Sequence Processing (Enhanced)
-```
-process_sequence()
-├── expect_identifier() → sequence name
-├── validate_user_name() → check against reserved names
-├── Track in sequence_names and symbol_table
-├── Parse multiple repeat syntaxes:
-│ ├── "sequence name repeat N times { ... }"
-│ ├── "sequence name forever { ... }"
-│ ├── "sequence name N times { ... }"
-│ └── "sequence name { repeat ... }"
-├── expect_left_brace() → '{'
-├── add("var name_ = animation.sequence_manager(engine, repeat_count)")
-├── while !check_right_brace()
-│ └── process_sequence_statement() (fluent interface)
-└── expect_right_brace() → '}'
-```
-
-#### Template Processing
-```
-process_template()
-├── expect_identifier() → template name
-├── validate_user_name() → check against reserved names
-├── expect_left_brace() → '{'
-├── Sequential step 1: collect parameters with type annotations
-├── Sequential step 2: collect body tokens
-├── expect_right_brace() → '}'
-├── Store in template_definitions
-├── generate_template_function()
-│ ├── Create new transpiler instance for body
-│ ├── Transpile body with fresh symbol table
-│ ├── Generate Berry function with engine parameter
-│ └── Register as user function
-└── Track in symbol_table as "template"
-
-process_template_animation()
-├── expect_identifier() → template animation name
-├── validate_user_name() → check against reserved names
-├── expect_left_brace() → '{'
-├── Sequential step 1: collect parameters with constraints (type, min, max, default)
-├── Sequential step 2: collect body tokens
-├── expect_right_brace() → '}'
-├── generate_template_animation_class()
-│ ├── Generate class extending engine_proxy
-│ ├── Generate PARAMS with encode_constraints
-│ ├── Create new transpiler instance for body
-│ ├── Set template_animation_params for special handling
-│ │ ├── Add user-defined parameters
-│ │ └── Add inherited parameters from engine_proxy hierarchy (dynamic discovery)
-│ ├── Transpile body with self.param references
-│ └── Use self.add() instead of engine.add()
-└── Track in symbol_table as "template"
-
-### Implicit Parameters in Template Animations
-
-Template animations automatically inherit parameters from the `engine_proxy` class hierarchy. The transpiler dynamically discovers these parameters at compile time:
-
-**Dynamic Parameter Discovery:**
-```
-_add_inherited_params_to_template(template_params_map)
-├── Create temporary engine_proxy instance
-├── Walk up class hierarchy using introspection
-├── For each class with PARAMS:
-│ └── Add all parameter names to template_params_map
-└── Fallback to static list if instance creation fails
-```
-
-**Inherited Parameters (from Animation and ParameterizedObject):**
-- `id` (string, default: "animation")
-- `priority` (int, default: 10)
-- `duration` (int, default: 0)
-- `loop` (bool, default: false)
-- `opacity` (int, default: 255)
-- `color` (int, default: 0)
-- `is_running` (bool, default: false)
-
-**Parameter Resolution Order:**
-1. Check if identifier is in `template_animation_params` (includes both user-defined and inherited)
-2. If found, resolve as `self.` (template animation parameter)
-3. Otherwise, check symbol table for user-defined variables
-4. If not found, raise "Unknown identifier" error
-
-This allows template animations to use inherited parameters like `duration` and `opacity` without explicit declaration, while still maintaining type safety and validation.
-```
-
-## Expression Processing Chain
-
-The transpiler uses a **unified recursive descent parser** for expressions with **raw mode support** for closure contexts:
-
-```
-process_value(context)
-└── process_additive_expression(context, is_top_level=true, raw_mode=false)
- ├── process_multiplicative_expression(context, is_top_level, raw_mode)
- │ ├── process_unary_expression(context, is_top_level, raw_mode)
- │ │ └── process_primary_expression(context, is_top_level, raw_mode)
- │ │ ├── Parenthesized expression → recursive call
- │ │ ├── Function call handling:
- │ │ │ ├── Raw mode: mathematical functions → animation._math.method()
- │ │ │ ├── Raw mode: template calls → template_func(self.engine, ...)
- │ │ │ ├── Regular mode: process_function_call() or process_nested_function_call()
- │ │ │ └── Simple function detection → _is_simple_function_call()
- │ │ ├── Color literal → convert_color() (enhanced ARGB support)
- │ │ ├── Time literal → process_time_value() (with variable support)
- │ │ ├── Percentage → process_percentage_value()
- │ │ ├── Number literal → return as-is
- │ │ ├── String literal → quote and return
- │ │ ├── Array literal → process_array_literal() (not in raw mode)
- │ │ ├── Identifier → enhanced symbol resolution
- │ │ │ ├── Object property → "obj.prop" with validation
- │ │ │ ├── User function → _process_user_function_call()
- │ │ │ ├── Palette constant → "animation.PALETTE_RAINBOW" etc.
- │ │ │ ├── Named color → get_named_color_value()
- │ │ │ └── Consolidated symbol resolution → resolve_symbol_reference()
- │ │ └── Boolean keywords → true/false
- │ └── Handle unary operators (-, +)
- └── Handle multiplicative operators (*, /)
-└── Handle additive operators (+, -)
-└── Closure wrapping logic:
- ├── Skip in raw_mode
- ├── Special handling for repeat_count context
- ├── is_computed_expression_string() detection
- └── create_computation_closure_from_string()
-```
-
-### Expression Context Handling
-
-The expression processor handles different contexts with **enhanced validation and processing**:
-
-- **`"color"`** - Color definitions and assignments
-- **`"animation"`** - Animation definitions and assignments
-- **`"argument"`** - Function call arguments
-- **`"property"`** - Property assignments with validation
-- **`"variable"`** - Variable assignments with type tracking
-- **`"repeat_count"`** - Sequence repeat counts (special closure handling)
-- **`"time"`** - Time value processing with variable support
-- **`"array_element"`** - Array literal elements
-- **`"event_param"`** - Event handler parameters
-- **`"expression"`** - Raw expression context (for closures)
-
-### Computed Expression Detection (Enhanced)
-
-The transpiler automatically detects computed expressions that need closures with **improved accuracy**:
-
-```
-is_computed_expression_string(expr_str)
-├── Check for arithmetic operators (+, -, *, /) with spaces
-├── Check for function calls (excluding simple functions)
-│ ├── Extract function name before parenthesis
-│ ├── Use _is_simple_function_call() to filter
-│ └── Only mark complex functions as needing closures
-├── Exclude simple parenthesized literals like (-1)
-└── Return true only for actual computations
-
-create_computation_closure_from_string(expr_str)
-├── transform_expression_for_closure()
-│ ├── Sequential step 1: Transform mathematical functions → animation._math.method()
-│ │ ├── Use dynamic introspection with is_math_method()
-│ │ ├── Check for existing "self." prefix /// TODO NOT SURE IT STILL EXISTS
-│ │ └── Only transform if not already prefixed
-│ ├── Sequential step 2: Transform user variables → animation.resolve(var_)
-│ │ ├── Find variables ending with _
-│ │ ├── Check for existing resolve() calls
-│ │ ├── Avoid double-wrapping
-│ │ └── Handle identifier character boundaries
-│ └── Clean up extra spaces
-└── Return "animation.create_closure_value(engine, closure)"
-
-is_anonymous_function(expr_str)
-├── Check if expression starts with "(def "
-├── Check if expression ends with ")(engine)"
-└── Skip closure wrapping for already-wrapped functions
-```
-
-## Enhanced Symbol Table System
-
-The transpiler uses a sophisticated **SymbolTable** system for holistic symbol management and caching. This system provides dynamic symbol detection, type validation, and conflict prevention.
-
-### SymbolTable Architecture
-
-The symbol table consists of two main classes in `symbol_table.be`:
-
-#### SymbolEntry Class
-```
-SymbolEntry
-├── name: string # Symbol name
-├── type: string # Symbol type classification
-├── instance: object # Actual instance for validation
-├── takes_args: boolean # Whether symbol accepts arguments
-├── arg_type: string # "positional", "named", or "none"
-└── is_builtin: boolean # Whether this is a built-in symbol from animation module
-```
-
-**Symbol Types Supported:**
-- `"palette"` - Palette objects like `PALETTE_RAINBOW` (bytes instances)
-- `"constant"` - Integer constants like `LINEAR`, `SINE`, `COSINE`
-- `"math_function"` - Mathematical functions like `max`, `min`
-- `"user_function"` - User-defined functions registered at runtime
-- `"value_provider"` - Value provider constructors
-- `"animation"` - Animation constructors
-- `"color"` - Color definitions and providers
-- `"variable"` - User-defined variables
-- `"sequence"` - Sequence definitions
-- `"template"` - Template definitions
-
-#### SymbolTable Class
-```
-SymbolTable
-├── entries: map # Map of name -> SymbolEntry
-├── mock_engine: MockEngine # For validation testing
-├── Dynamic Detection Methods:
-│ ├── _detect_and_cache_symbol() # On-demand symbol detection
-│ ├── contains() # Existence check with auto-detection
-│ └── get() # Retrieval with auto-detection
-├── Creation Methods:
-│ ├── create_palette()
-│ ├── create_color()
-│ ├── create_animation()
-│ ├── create_value_provider()
-│ ├── create_variable()
-│ ├── create_sequence()
-│ └── create_template()
-└── Validation Methods:
- ├── symbol_exists()
- ├── get_reference()
- └── takes_args() / takes_positional_args() / takes_named_args()
-```
-
-### Dynamic Symbol Detection
-
-The SymbolTable uses **lazy detection** to identify and cache symbols as they are encountered:
-
-```
-_detect_and_cache_symbol(name)
-├── Check if already cached → return cached entry
-├── Check animation module using introspection:
-│ ├── Detect bytes() instances → create_palette()
-│ ├── Detect integer constants (type == "int") → create_constant()
-│ ├── Detect math functions in animation._math → create_math_function()
-│ ├── Detect user functions via animation.is_user_function() → create_user_function()
-│ ├── Test constructors with MockEngine:
-│ │ ├── Create instance with mock_engine
-│ │ ├── Check isinstance(instance, animation.value_provider) → create_value_provider()
-│ │ └── Check isinstance(instance, animation.animation) → create_animation()
-│ └── Cache result for future lookups
-└── Return nil if not found (handled as user-defined)
-```
-
-### Symbol Type Detection Examples
-
-**Palette Detection:**
-```berry
-# DSL: animation rainbow = rich_palette_animation(colors=PALETTE_RAINBOW)
-# Detection: PALETTE_RAINBOW exists in animation module, isinstance(obj, bytes)
-# Result: SymbolEntry("PALETTE_RAINBOW", "palette", bytes_instance, true)
-# Reference: "animation.PALETTE_RAINBOW"
-```
-
-**Constant Detection:**
-```berry
-# DSL: animation wave = wave_animation(waveform=LINEAR)
-# Detection: LINEAR exists in animation module, type(LINEAR) == "int"
-# Result: SymbolEntry("LINEAR", "constant", 1, true)
-# Reference: "animation.LINEAR"
-```
-
-**Math Function Detection:**
-```berry
-# DSL: animation.opacity = max(100, min(255, brightness))
-# Detection: max exists in animation._math, is callable
-# Result: SymbolEntry("max", "math_function", nil, true)
-# Reference: "animation.max" (transformed to "animation._math.max" in closures)
-```
-
-**Value Provider Detection:**
-```berry
-# DSL: set oscillator = triangle(min_value=0, max_value=100, period=2s)
-# Detection: triangle(mock_engine) creates instance, isinstance(instance, animation.value_provider)
-# Result: SymbolEntry("triangle", "value_provider", instance, true)
-# Reference: "animation.triangle"
-```
-
-**User Function Detection:**
-```berry
-# DSL: animation demo = rand_demo(color=red)
-# Detection: animation.is_user_function("rand_demo") returns true
-# Result: SymbolEntry("rand_demo", "user_function", nil, true)
-# Reference: "rand_demo_" (handled specially in function calls)
-```
-
-### Symbol Conflict Prevention
-
-The SymbolTable prevents symbol redefinition conflicts:
-
-```
-add(name, entry)
-├── Check for built-in symbol conflicts:
-│ ├── _detect_and_cache_symbol(name)
-│ └── Raise "symbol_redefinition_error" if types differ
-├── Check existing user-defined symbols:
-│ ├── Compare entry.type with existing.type
-│ └── Raise "symbol_redefinition_error" if types differ
-├── Allow same-type updates (reassignment)
-└── Return entry for method chaining
-```
-
-**Example Conflict Detection:**
-```berry
-# This would raise an error:
-color max = 0xFF0000 # Conflicts with built-in math function "max"
-
-# This would also raise an error:
-color red = 0xFF0000
-animation red = solid(color=blue) # Redefining "red" as different type
-```
-
-### Integration with Transpiler
-
-The SymbolTable integrates seamlessly with the transpiler's processing flow:
-
-### Performance Optimizations
-
-**Caching Strategy:**
-- **Lazy Detection**: Symbols detected only when first encountered
-- **Instance Reuse**: MockEngine instances reused for validation
-- **Introspection Caching**: Built-in symbol detection cached permanently
-
-**Memory Efficiency:**
-- **Minimal Storage**: Only essential information stored per symbol
-- **Shared MockEngine**: Single MockEngine instance for all validation
-- **Reference Counting**: Automatic cleanup of unused entries
-
-### MockEngine Integration
-
-The SymbolTable uses a lightweight MockEngine for constructor validation:
-
-```
-MockEngine
-├── time_ms: 0 # Mock time for validation
-├── get_strip_length(): 30 # Default strip length
-└── Minimal interface for instance creation testing
-```
-
-**Usage in Detection:**
-```berry
-# Test if function creates value provider
-try
- var instance = factory_func(self.mock_engine)
- if isinstance(instance, animation.value_provider)
- return SymbolEntry.create_value_provider(name, instance, animation.value_provider)
- end
-except .. as e, msg
- # Constructor failed - not a valid provider
-end
-```
-
-## Validation System (Comprehensive)
-
-The transpiler includes **extensive compile-time validation** with robust error handling:
-
-### Factory Function Validation (Simplified using SymbolTable)
-```
-_validate_animation_factory_exists(func_name)
-├── Skip validation for mathematical functions
-├── Use symbol_table.get(func_name) for dynamic detection
-└── Return true if entry exists (any callable function is valid)
-
-_validate_animation_factory_creates_animation(func_name)
-├── Use symbol_table.get(func_name) for dynamic detection
-└── Return true if entry.type == "animation"
-
-_validate_color_provider_factory_onsts(func_name)
-├── Use symbol_table.get(func_name) for dynamic detection
-└── Return true if entry exists (any callable function is valid)
-
-_validate_value_provider_factory_exists(func_name)
-├── Use symbol_table.get(func_name) for dynamic detection
-└── Return true if entry.type == "value_provider"
-```
-
-### Parameter Validation (Real-time)
-```
-_validate_single_parameter(func_name, param_name, animation_instance)
-├── Use introspection to check if parameter exists
-├── Call instance.has_param(param_name) for validation
-├── Report detailed error messages with line numbers
-├── Validate immediately as parameters are parsed
-└── Graceful error handling to ensure transpiler robustness
-
-_create_instance_for_validation(func_name) - Simplified using SymbolTable
-├── Use symbol_table.get(func_name) for dynamic detection
-└── Return entry.instance if available, nil otherwise
-```
-
-### Reference Validation (Simplified using SymbolTable)
-```
-resolve_symbol_reference(name) - Simplified using SymbolTable
-└── Use symbol_table.get_reference(name) for all symbol resolution
-
-validate_symbol_reference(name, context) - With error reporting
-├── Use symbol_exists() to check symbol_table
-├── Report detailed error with context information
-└── Return validation status
-
-symbol_exists(name) - Simplified existence check
-└── Use symbol_table.symbol_exists(name) for unified checking
-
-_validate_value_provider_reference(object_name, context) - Simplified
-├── Check symbol_exists() using symbol_table
-├── Use symbol_table.get(name) for type information
-├── Check entry.type == "value_provider" || entry.type == "animation"
-└── Report detailed error messages for invalid types
-```
-
-### User Name Validation (Reserved Names)
-```
-validate_user_name(name, definition_type)
-├── Check against predefined color names
-├── Check against DSL statement keywords
-├── Report conflicts with suggestions for alternatives
-└── Prevent redefinition of reserved identifiers
-```
-
-### Value Provider Validation (New)
-```
-_validate_value_provider_reference(object_name, context)
-├── Check if symbol exists using validate_symbol_reference()
-├── Check symbol_table markers for type information
-├── Validate instance types using isinstance()
-├── Ensure only value providers/animations can be restarted
-└── Provide detailed error messages for invalid types
-```
-
-## Code Generation Patterns
-
-### Engine-First Pattern (Consistent)
-All factory functions use the engine-first pattern with **automatic strip initialization**:
-```berry
-# DSL: animation pulse = pulsating_animation(color=red, period=2s)
-# Generated:
-# Auto-generated strip initialization (using Tasmota configuration)
-var engine = animation.init_strip()
-
-var pulse_ = animation.pulsating_animation(engine)
-pulse_.color = animation.red
-pulse_.period = 2000
-```
-
-**Template-Only Exception**: Files containing only template definitions skip engine initialization and `engine.run()` generation, producing pure function libraries.
-
-### Symbol Resolution (Consolidated)
-The transpiler resolves symbols at compile time using **unified resolution logic** based on the `is_builtin` flag:
-```berry
-# Built-in symbols (is_builtin=true) from animation module → animation.symbol
-animation.linear, animation.PALETTE_RAINBOW, animation.SINE, animation.solid
-
-# User-defined symbols (is_builtin=false) → symbol_
-my_color_, my_animation_, my_sequence_
-
-# Named colors → direct ARGB values (resolved at compile time)
-red → 0xFFFF0000, blue → 0xFF0000FF
-
-# Template calls → template_function(engine, args)
-my_template(red, 2s) → my_template_template(engine, 0xFFFF0000, 2000)
-
-
-### Closure Generation (Enhanced)
-Dynamic expressions are wrapped in closures with **mathematical function support**:
-```berry
-# DSL: animation.opacity = strip_length() / 2 + 50
-# Generated:
-animation.opacity = animation.create_closure_value(engine,
- def (self) return animation.resolve(strip_length_(engine)) / 2 + 50 end)
-
-# DSL: animation.opacity = max(100, min(255, rand_demo() + 50))
-# Generated:
-animation.opacity = animation.create_closure_value(engine,
- def (self) return animation._math.max(100, animation._math.min(255, animation.get_user_function('rand_demo')(engine) + 50)) end)
-
-# Mathematical functions are automatically detected and prefixed with animation._math.
-# User functions are wrapped with animation.get_user_function() calls
-```
-
-### Template Generation (New)
-Templates are transpiled into Berry functions and registered as user functions:
-```berry
-# DSL Template:
-template pulse_effect {
- param color type color
- param speed
-
- animation pulse = pulsating_animation(color=color, period=speed)
- run pulse
-}
-
-# Generated:
-def pulse_effect_template(engine, color_, speed_)
- var pulse_ = animation.pulsating_animation(engine)
- pulse_.color = color_
- pulse_.period = speed_
- engine.add(pulse_)
-end
-
-animation.register_user_function('pulse_effect', pulse_effect_template)
-```
-
-### Sequence Generation (Fluent Interface)
-Sequences use fluent interface pattern for better readability:
-```berry
-# DSL: sequence demo { play anim for 2s; wait 1s }
-# Generated:
-var demo_ = animation.sequence_manager(engine)
- .push_play_step(anim_, 2000)
- .push_wait_step(1000)
-
-# Nested repeats use sub-sequences:
-var demo_ = animation.sequence_manager(engine)
- .push_repeat_subsequence(animation.sequence_manager(engine, 3)
- .push_play_step(anim_, 1000)
- )
-```
-
-## Template System (Enhanced)
-
-Templates are transpiled into Berry functions with **comprehensive parameter handling**:
-
-**Template-Only Optimization**: Files containing only template definitions skip engine initialization and execution code generation, producing pure Berry function libraries.
-
-```
-process_template()
-├── expect_identifier() → template name
-├── validate_user_name() → check against reserved names
-├── expect_left_brace() → '{'
-├── Sequential step 1: collect parameters with type annotations
-│ ├── Parse "param name type annotation" syntax
-│ ├── Store parameter names and optional types
-│ └── Support both typed and untyped parameters
-├── Sequential step 2: collect body tokens until closing brace
-│ ├── Handle nested braces correctly
-│ ├── Preserve all tokens for later transpilation
-│ └── Track brace depth for proper parsing
-├── expect_right_brace() → '}'
-├── Store in template_definitions for call resolution
-├── generate_template_function()
-│ ├── Create new SimpleDSLTranspiler instance for body
-│ ├── Set up fresh symbol table with parameters
-│ ├── Mark strip as initialized (templates assume engine exists)
-│ ├── Transpile body using transpile_template_body()
-│ ├── Generate Berry function with engine + parameters
-│ ├── Handle transpilation errors gracefully
-│ └── Register as user function automatically
-└── Track in symbol_table as "template"
-```
-
-### Template Call Resolution (Multiple Contexts)
-```berry
-# DSL template call in animation context:
-animation my_anim = my_template(red, 2s)
-# Generated: var my_anim_ = my_template_template(engine, 0xFFFF0000, 2000)
-
-# DSL template call in property context:
-animation.opacity = my_template(blue, 1s)
-# Generated: animation.opacity = my_template_template(self.engine, 0xFF0000FF, 1000)
-
-# DSL standalone template call:
-my_template(green, 3s)
-# Generated: my_template_template(engine, 0xFF008000, 3000)
-```
-
-### Template Body Transpilation
-Templates use a **separate transpiler instance** with isolated symbol table:
-- Fresh symbol table prevents name conflicts
-- Parameters are added as "parameter" markers
-- Run statements are processed immediately (not collected)
-- Template calls can be nested (templates calling other templates)
-- Error handling preserves context information
-
-## Error Handling (Robust)
-
-The transpiler provides **comprehensive error reporting** with graceful degradation:
-
-### Error Categories
-- **Syntax errors** - Invalid DSL syntax with line numbers
-- **Factory validation** - Non-existent animation/color factories with suggestions
-- **Parameter validation** - Invalid parameter names with class context
-- **Reference validation** - Undefined object references with context information
-- **Constraint validation** - Parameter values outside valid ranges
-- **Type validation** - Incorrect parameter types with expected types
-- **Safety validation** - Dangerous patterns that could cause memory leaks or performance issues
-- **Template errors** - Template definition and call validation
-- **Reserved name conflicts** - User names conflicting with built-ins
-
-### Error Reporting Features
-```berry
-error(msg)
-├── Capture current line number from token
-├── Format error with context: "Line X: message"
-├── Store in errors array for batch reporting
-└── Continue transpilation for additional error discovery
-
-get_error_report()
-├── Check if errors exist
-├── Format comprehensive error report
-├── Include all errors with line numbers
-└── Provide user-friendly error messages
-```
-
-### Graceful Error Handling
-- **Try-catch blocks** around validation to prevent crashes
-- **Robust validation** that continues on individual failures
-- **Skip statement** functionality to recover from parse errors
-- **Default values** when validation fails to maintain transpilation flow
-- **Context preservation** in error messages for better debugging
-
-## Performance Considerations
-
-### Ultra-Simplified Architecture
-- **Single-pass processing** - tokens processed once from start to finish
-- **Incremental symbol table** - builds validation context as it parses
-- **Immediate validation** - catches errors as soon as they're encountered
-- **Minimal state tracking** - only essential information is maintained
-
-### Compile-Time Optimization
-- **Symbol resolution at transpile time** - eliminates runtime lookups
-- **Parameter validation during parsing** - catches errors early
-- **Template pre-compilation** - templates become efficient Berry functions
-- **Closure detection** - only wraps expressions that actually need it
-- **Mathematical function detection** - uses dynamic introspection for accuracy
-
-### Memory Efficiency
-- **Streaming token processing** - no large intermediate AST structures
-- **Direct code generation** - output generated as parsing proceeds
-- **Minimal intermediate representations** - tokens and symbol table only
-- **Template isolation** - separate transpiler instances prevent memory leaks
-- **Graceful error handling** - prevents memory issues from validation failures
-
-### Validation Efficiency
-- **MockEngine pattern** - lightweight validation without full engine
-- **Introspection caching** - validation results can be cached
-- **Early termination** - stops processing invalid constructs quickly
-- **Batch error reporting** - collects multiple errors in single pass
-
-## Integration Points
-
-### Animation Module Integration
-- **Factory function discovery** via introspection with existence checking
-- **Parameter validation** using instance methods and has_param()
-- **Symbol resolution** using module contents with fallback handling
-- **Mathematical function detection** using dynamic introspection of ClosureValueProvider
-- **Automatic strip initialization** when no explicit strip configuration
-
-### User Function Integration
-- **Template registration** as user functions with automatic naming
-- **User function call detection** usable as normal functions with positional arguments
-- **Closure generation** for computed parameters with mathematical functions
-- **Template call resolution** in multiple contexts (animation, property, standalone)
-- **Import statement processing** for user function modules
-
-### DSL Language Integration
-- **Comment preservation** in generated Berry code
-- **Inline comment handling** with proper spacing
-- **Multiple syntax support** for sequences (repeat variants)
-- **Palette syntax flexibility** (tuple vs alternative syntax)
-- **Time unit conversion** with variable support
-- **Percentage conversion** to 0-255 range
-
-### Robustness Features
-- **Graceful error recovery** - continues parsing after errors
-- **Validation isolation** - validation failures don't crash transpiler
-- **Symbol table tracking** - maintains context for validation
-- **Template isolation** - separate transpiler instances prevent conflicts
-- **Reserved name protection** - prevents conflicts with built-in identifiers
-
-## Key Architectural Changes
-
-The refactored transpiler emphasizes:
-
-1. **Simplicity** - Ultra-simplified single-pass architecture
-2. **Robustness** - Comprehensive error handling and graceful degradation
-3. **Enhanced Symbol Management** - Dynamic SymbolTable system with intelligent caching and conflict detection
-4. **Validation** - Extensive compile-time validation with detailed error messages
-5. **Flexibility** - Support for templates, multiple syntax variants, and user functions
-6. **Performance** - Efficient processing with minimal memory overhead and lazy symbol detection
-7. **Maintainability** - Clear separation of concerns and unified processing methods
-
-## Recent Refactoring Improvements
-
-### Code Simplification Using SymbolTable
-
-The transpiler has been significantly refactored to leverage the `symbol_table.be` system more extensively:
-
-#### **Factory Validation Simplification**
-- **Before**: Complex validation with introspection and manual instance creation (~50 lines)
-- **After**: Simple validation using symbol_table's dynamic detection (~25 lines)
-- **Improvement**: 50% code reduction with better maintainability
-
-#### **Symbol Resolution Consolidation**
-- **Before**: Multiple separate checks for sequences, introspection, etc.
-- **After**: Unified resolution through `symbol_table.get_reference()`
-- **Improvement**: Single source of truth for all symbol resolution
-
-#### **Duplicate Code Elimination**
-- **Before**: Duplicate code patterns in `process_color()` and `process_animation()` methods
-- **After**: Consolidated into reusable `_process_simple_value_assignment()` helper
-- **Improvement**: 70% reduction in duplicate code blocks
-
-#### **Legacy Variable Removal**
-- **Before**: Separate tracking of sequences in `sequence_names` variable
-- **After**: All symbols tracked uniformly in `symbol_table`
-- **Improvement**: Eliminated redundancy and simplified state management
-
-### Major Enhancements
-
-**SymbolTable System:**
-- **Dynamic Detection**: Automatically detects and caches symbol types as encountered
-- **Conflict Prevention**: Prevents redefinition of symbols with different types
-- **Performance Optimization**: Lazy loading and efficient symbol resolution for optimal performance
-- **Type Safety**: Comprehensive type checking with MockEngine validation
-- **Modular Design**: Separated into `symbol_table.be` for reusability
-- **Constant Detection**: Added support for integer constants like `LINEAR`, `SINE`, `COSINE`
-
-**Enhanced Symbol Detection:**
-- **Palette Objects**: `PALETTE_RAINBOW` → `animation.PALETTE_RAINBOW`
-- **Integer Constants**: `LINEAR`, `SINE`, `COSINE` → `animation.LINEAR`, `animation.SINE`, `animation.COSINE`
-- **Math Functions**: `max`, `min` → `animation.max`, `animation.min` (transformed to `animation._math.*` in closures)
-- **Value Providers**: `triangle`, `smooth` → `animation.triangle`, `animation.smooth`
-- **Animation Constructors**: `solid`, `pulsating_animation` → `animation.solid`, `animation.pulsating_animation`
-- **User-defined Symbols**: `my_color`, `my_animation` → `my_color_`, `my_animation_`
-
-**Validation Improvements:**
-- **Real-time Validation**: Parameter validation as symbols are parsed
-- **Instance-based Checking**: Uses actual instances for accurate validation
-- **Graceful Error Handling**: Robust error recovery with detailed error messages
-- **Simplified Validation Methods**: Factory validation reduced from ~50 to ~25 lines using symbol_table
-- **Unified Symbol Checking**: All symbol existence checks go through symbol_table system
-- **Enhanced Type Detection**: Automatic detection of constants, palettes, functions, and constructors
-
-This architecture ensures robust, efficient transpilation from DSL to executable Berry code while providing comprehensive validation, detailed error reporting, intelligent symbol management, and extensive language features.
-
-### Symbol Reference Generation
-
-The enhanced SymbolEntry system uses the `is_builtin` flag to determine correct reference generation:
-
-```berry
-# SymbolEntry.get_reference() method
-def get_reference()
- if self.is_builtin
- return f"animation.{self.name}" # Built-in symbols: animation.LINEAR
- else
- return f"{self.name}_" # User-defined symbols: my_color_
- end
-end
-```
-
-**Examples:**
-- **Built-in Constants**: `LINEAR` → `animation.LINEAR`
-- **Built-in Functions**: `triangle` → `animation.triangle`
-- **Built-in Palettes**: `PALETTE_RAINBOW` → `animation.PALETTE_RAINBOW`
-- **User-defined Colors**: `my_red` → `my_red_`
-- **User-defined Animations**: `pulse_anim` → `pulse_anim_`
-
-This ensures consistent and correct symbol resolution throughout the transpilation process.
\ No newline at end of file
diff --git a/lib/libesp32/berry_animation/berry_animation_docs/TROUBLESHOOTING.md b/lib/libesp32/berry_animation/berry_animation_docs/TROUBLESHOOTING.md
deleted file mode 100644
index f0b93cda7..000000000
--- a/lib/libesp32/berry_animation/berry_animation_docs/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,1238 +0,0 @@
-# Troubleshooting Guide
-
-Common issues and solutions for the Tasmota Berry Animation Framework.
-
-**Note**: This guide focuses on DSL usage, which is the recommended way to create animations. For programmatic API issues, see the [Animation Development Guide](ANIMATION_DEVELOPMENT.md).
-
-## Installation Issues
-
-### Framework Not Found
-
-**Problem:** `import animation` or `import animation_dsl` fails with "module not found"
-
-**Solutions:**
-1. **Check Module Import:**
- ```berry
- import animation # Core framework
- import animation_dsl # DSL compiler
- ```
-
-2. **Set Module Path:**
- ```bash
- berry -m lib/libesp32/berry_animation
- ```
-
-3. **Verify File Structure:**
- ```
- lib/libesp32/berry_animation/
- ├── animation.be # Main module file
- ├── dsl/ # DSL components
- ├── core/ # Core classes
- ├── animations/ # Animation effects
- └── ...
- ```
-
-### Missing Dependencies
-
-**Problem:** Errors about missing `tasmota` or `Leds` classes
-
-**Solutions:**
-1. **For Tasmota Environment:**
- - Ensure you're running on actual Tasmota firmware
- - Check that Berry support is enabled
-
-2. **For Development Environment:**
- ```berry
- # Mock Tasmota for testing
- if !global.contains("tasmota")
- global.tasmota = {
- "millis": def() return 1000 end,
- "scale_uint": def(val, from_min, from_max, to_min, to_max)
- return int((val - from_min) * (to_max - to_min) / (from_max - from_min) + to_min)
- end
- }
- end
- ```
-
-## Animation Issues
-
-### Animations Not Starting
-
-**Problem:** DSL animations compile but LEDs don't change
-
-**Diagnostic Steps:**
-```berry
-import animation
-import animation_dsl
-
-# Test basic DSL execution
-var dsl_code = "color red = 0xFF0000\n" +
- "animation red_anim = solid(color=red)\n" +
- "run red_anim"
-
-try
- animation_dsl.execute(dsl_code)
- print("DSL executed successfully")
-except .. as e, msg
- print("DSL Error:", msg)
-end
-```
-
-**Timing Behavior Note:**
-The framework has updated timing behavior where:
-- The `start()` method only resets the time origin if the animation/value provider was already started previously
-- The first actual rendering tick occurs in `update()`, `render()`, or `produce_value()` methods
-- This ensures proper timing initialization and prevents premature time reference setting
-
-**Common Solutions:**
-
-1. **Missing Strip Declaration:**
- ```berry
- # Add explicit strip length if needed
- strip length 30
-
- color red = 0xFF0000
- animation red_anim = solid(color=red)
- run red_anim
- ```
-
-2. **Animation Not Executed:**
- ```berry
- # Make sure you have a 'run' statement
- color red = 0xFF0000
- animation red_anim = solid(color=red)
- run red_anim # Don't forget this!
- ```
-
-3. **Strip Auto-Detection Issues:**
- ```berry
- # Force strip length if auto-detection fails
- strip length 30 # Must be first statement
-
- color red = 0xFF0000
- animation red_anim = solid(color=red)
- run red_anim
- ```
-
-### Colors Look Wrong
-
-**Problem:** Colors appear different than expected
-
-**Common Issues:**
-
-1. **Missing Alpha Channel:**
- ```berry
- # Note: 0xFF0000 is valid RGB format (alpha defaults to 0xFF)
- color red = 0xFF0000 # RGB format (alpha=255 assumed)
-
- # Explicit alpha channel (ARGB format)
- color red = 0xFFFF0000 # ARGB format (alpha=255, red=255)
- color semi_red = 0x80FF0000 # ARGB format (alpha=128, red=255)
- ```
-
-2. **Color Format Confusion:**
- ```berry
- # ARGB format: 0xAARRGGBB
- color red = 0xFFFF0000 # Alpha=FF, Red=FF, Green=00, Blue=00
- color green = 0xFF00FF00 # Alpha=FF, Red=00, Green=FF, Blue=00
- color blue = 0xFF0000FF # Alpha=FF, Red=00, Green=00, Blue=FF
- ```
-
-3. **Brightness Issues:**
- ```berry
- # Use opacity parameter or property assignment
- animation red_anim = solid(color=red, opacity=255) # Full brightness
-
- # Or assign after creation
- animation pulse_red = pulsating_animation(color=red, period=2s)
- pulse_red.opacity = 200 # Adjust brightness
-
- # Use value providers for dynamic brightness
- set brightness = smooth(min_value=50, max_value=255, period=3s)
- animation breathing = solid(color=red)
- breathing.opacity = brightness
- ```
-
-### Animations Too Fast/Slow
-
-**Problem:** Animation timing doesn't match expectations
-
-**Solutions:**
-
-1. **Check Time Units:**
- ```berry
- # DSL uses time units (converted to milliseconds)
- animation pulse_anim = pulsating_animation(color=red, period=2s) # 2 seconds
- animation fast_pulse = pulsating_animation(color=blue, period=500ms) # 0.5 seconds
- ```
-
-2. **Adjust Periods:**
- ```berry
- # Too fast - increase period
- animation slow_pulse = pulsating_animation(color=red, period=5s) # 5 seconds
-
- # Too slow - decrease period
- animation fast_pulse = pulsating_animation(color=red, period=500ms) # 0.5 seconds
- ```
-
-3. **Performance Limitations:**
- ```berry
- # Use sequences instead of multiple simultaneous animations
- sequence optimized_show {
- play animation1 for 3s
- play animation2 for 3s
- play animation3 for 3s
- }
- run optimized_show
-
- # Instead of:
- # run animation1
- # run animation2
- # run animation3
- ```
-
-## DSL Issues
-
-### DSL Compilation Errors
-
-**Problem:** DSL code fails to compile
-
-**Diagnostic Approach:**
-```berry
-try
- var berry_code = animation_dsl.compile(dsl_source)
- print("Compilation successful")
-except "dsl_compilation_error" as e, msg
- print("DSL Error:", msg)
-end
-```
-
-**Common DSL Errors:**
-
-1. **Undefined Colors:**
- ```berry
- # Wrong - color not defined
- animation red_anim = solid(color=red)
-
- # Correct - define color first
- color red = 0xFF0000
- animation red_anim = solid(color=red)
- ```
-
-2. **Invalid Color Format:**
- ```berry
- # Wrong - # prefix not supported (conflicts with comments)
- color red = #FF0000
-
- # Correct - use 0x prefix
- color red = 0xFF0000
- ```
-
-3. **Missing Time Units:**
- ```berry
- # Wrong - no time unit
- animation pulse_anim = pulsating_animation(color=red, period=2000)
-
- # Correct - with time unit
- animation pulse_anim = pulsating_animation(color=red, period=2s)
- ```
-
-4. **Reserved Name Conflicts:**
- ```berry
- # Wrong - 'red' is a predefined color
- color red = 0x800000
-
- # Correct - use different name
- color dark_red = 0x800000
- ```
-
-5. **Invalid Parameter Names:**
- ```berry
- # Wrong - invalid parameter name
- animation pulse_anim = pulsating_animation(color=red, invalid_param=123)
- # Error: "Parameter 'invalid_param' is not valid for pulsating_animation"
-
- # Correct - use valid parameters (see DSL_REFERENCE.md for complete list)
- animation pulse_anim = pulsating_animation(color=red, period=2s)
- ```
-
-6. **Variable Duration Support:**
- ```berry
- # Now supported - variables in play/wait durations
- set eye_duration = 5s
-
- sequence cylon_eye {
- play red_eye for eye_duration # ✓ Variables now work
- wait eye_duration # ✓ Variables work in wait too
- }
-
- # Also supported - value providers for dynamic duration
- set dynamic_time = triangle(min_value=1000, max_value=3000, period=10s)
-
- sequence demo {
- play animation for dynamic_time # ✓ Dynamic duration
- }
- ```
-
-7. **Template Definition Errors:**
- ```berry
- # Wrong - missing braces
- template pulse_effect
- param color type color
- param speed
- # Error: Expected '{' after template name
-
- # Wrong - invalid parameter syntax
- template pulse_effect {
- param color as color # Error: Use 'type' instead of 'as'
- param speed
- }
-
- # Wrong - missing template body
- template pulse_effect {
- param color type color
- }
- # Error: Template body cannot be empty
-
- # Correct - proper template syntax
- template pulse_effect {
- param color type color
- param speed
-
- animation pulse = pulsating_animation(
- color=color
- period=speed
- )
-
- run pulse
- }
- ```
-
-8. **Template Call Errors:**
- ```berry
- # Wrong - template not defined
- pulse_effect(red, 2s)
- # Error: "Undefined reference: 'pulse_effect'"
-
- # Wrong - incorrect parameter count
- template pulse_effect {
- param color type color
- param speed
- # ... template body ...
- }
-
- pulse_effect(red) # Error: Expected 2 parameters, got 1
-
- # Correct - define template first, call with correct parameters
- template pulse_effect {
- param color type color
- param speed
-
- animation pulse = pulsating_animation(color=color, period=speed)
- run pulse
- }
-
- pulse_effect(red, 2s) # ✓ Correct usage
- ```
-
-6. **Parameter Constraint Violations:**
- ```berry
- # Wrong - negative period not allowed
- animation bad_pulse = pulsating_animation(color=red, period=-2s)
- # Error: "Parameter 'period' value -2000 violates constraint: min=1"
-
- # Wrong - invalid enum value
- animation bad_comet = comet_animation(color=red, direction=5)
- # Error: "Parameter 'direction' value 5 not in allowed values: [-1, 1]"
-
- # Correct - valid parameters within constraints
- animation good_pulse = pulsating_animation(color=red, period=2s)
- animation good_comet = comet_animation(color=red, direction=1)
- ```
-
-7. **Repeat Syntax Errors:**
- ```berry
- # Wrong - old colon syntax no longer supported
- sequence bad_demo {
- repeat 3 times: # Error: Expected '{' after 'times'
- play anim for 1s
- }
-
- # Wrong - missing braces
- sequence bad_demo2 {
- repeat 3 times
- play anim for 1s # Error: Expected '{' after 'times'
- }
-
- # Correct - use braces for repeat blocks
- sequence good_demo {
- repeat 3 times {
- play anim for 1s
- }
- }
-
- # Also correct - alternative syntax
- sequence good_demo_alt repeat 3 times {
- play anim for 1s
- }
-
- # Correct - forever syntax
- sequence infinite_demo {
- repeat forever {
- play anim for 1s
- wait 500ms
- }
- }
- ```
-
-### Template Issues
-
-### Template Definition Problems
-
-**Problem:** Template definitions fail to compile
-
-**Common Template Errors:**
-
-1. **Missing Template Body:**
- ```berry
- # Wrong - empty template
- template empty_template {
- param color type color
- }
- # Error: "Template body cannot be empty"
-
- # Correct - template must have content
- template pulse_effect {
- param color type color
- param speed
-
- animation pulse = pulsating_animation(color=color, period=speed)
- run pulse
- }
- ```
-
-2. **Invalid Parameter Syntax:**
- ```berry
- # Wrong - old 'as' syntax
- template pulse_effect {
- param color as color
- }
- # Error: Expected 'type' keyword, got 'as'
-
- # Correct - use 'type' keyword
- template pulse_effect {
- param color type color
- param speed # Type annotation is optional
- }
- ```
-
-3. **Template Name Conflicts:**
- ```berry
- # Wrong - template name conflicts with built-in function
- template solid { # 'solid' is a built-in animation function
- param color type color
- # ...
- }
- # Error: "Template name 'solid' conflicts with built-in function"
-
- # Correct - use unique template names
- template solid_effect {
- param color type color
- # ...
- }
- ```
-
-### Template Usage Problems
-
-**Problem:** Template calls fail or behave unexpectedly
-
-**Common Issues:**
-
-1. **Undefined Template:**
- ```berry
- # Wrong - calling undefined template
- my_effect(red, 2s)
- # Error: "Undefined reference: 'my_effect'"
-
- # Correct - define template first
- template my_effect {
- param color type color
- param speed
- # ... template body ...
- }
-
- my_effect(red, 2s) # Now works
- ```
-
-2. **Parameter Count Mismatch:**
- ```berry
- template pulse_effect {
- param color type color
- param speed
- param brightness
- }
-
- # Wrong - missing parameters
- pulse_effect(red, 2s) # Error: Expected 3 parameters, got 2
-
- # Correct - provide all parameters
- pulse_effect(red, 2s, 200)
- ```
-
-3. **Parameter Type Issues:**
- ```berry
- template pulse_effect {
- param color type color
- param speed
- }
-
- # Wrong - invalid color parameter
- pulse_effect("not_a_color", 2s)
- # Runtime error: Invalid color value
-
- # Correct - use valid color
- pulse_effect(red, 2s) # Named color
- pulse_effect(0xFF0000, 2s) # Hex color
- ```
-
-### Template vs User Function Confusion
-
-**Problem:** Mixing template and user function concepts
-
-**Key Differences:**
-
-```berry
-# Template (DSL-native) - Recommended for most cases
-template pulse_effect {
- param color type color
- param speed
-
- animation pulse = pulsating_animation(color=color, period=speed)
- run pulse
-}
-
-# User Function (Berry-native) - For complex logic
-def create_pulse_effect(engine, color, speed)
- var pulse = animation.pulsating_animation(engine)
- pulse.color = color
- pulse.period = speed
- return pulse
-end
-animation.register_user_function("pulse_effect", create_pulse_effect)
-```
-
-**When to Use Each:**
-- **Templates**: Simple to moderate effects, DSL syntax, type safety
-- **User Functions**: Complex logic, Berry features, return values
-
-## DSL Runtime Errors
-
-**Problem:** DSL compiles but fails at runtime
-
-**Common Issues:**
-
-1. **Strip Not Initialized:**
- ```berry
- # Add strip declaration if needed
- strip length 30
-
- color red = 0xFF0000
- animation red_anim = solid(color=red)
- run red_anim
- ```
-
-2. **Repeat Performance Issues:**
- ```berry
- # Efficient - runtime repeats don't expand at compile time
- sequence efficient {
- repeat 1000 times { # No memory overhead for large counts
- play anim for 100ms
- wait 50ms
- }
- }
-
- # Nested repeats work efficiently
- sequence nested {
- repeat 100 times {
- repeat 50 times { # Total: 5000 iterations, but efficient
- play quick_flash for 10ms
- }
- wait 100ms
- }
- }
- ```
-
-3. **Sequence Issues:**
- ```berry
- # Make sure animations are defined before sequences
- color red = 0xFF0000
- animation red_anim = solid(color=red) # Define first
-
- sequence demo {
- play red_anim for 3s # Use after definition
- wait 1s # Optional pause between animations
- }
- run demo
- ```
-
-4. **Undefined References:**
- ```berry
- # Wrong - using undefined animation in sequence
- sequence bad_demo {
- play undefined_animation for 3s
- }
- # Error: "Undefined reference: 'undefined_animation'"
-
- # Correct - define all references first
- color blue = 0x0000FF
- animation blue_anim = solid(color=blue)
-
- sequence good_demo {
- play blue_anim for 3s
- }
- run good_demo
- ```
-
-## Performance Issues
-
-### CPU Metrics and Profiling
-
-**Feature:** Built-in CPU metrics tracking to monitor animation performance
-
-The AnimationEngine automatically tracks CPU usage and provides detailed statistics every 5 seconds. This helps identify performance bottlenecks and optimize animations for ESP32 embedded systems.
-
-**Automatic Metrics:**
-
-When the engine is running, it automatically logs performance statistics:
-
-```
-AnimEngine: ticks=1000/1000 missed=0 total=0.50ms(0-2) anim=0.30ms(0-1) hw=0.20ms(0-1) cpu=10.0%
- Phase1(checks): mean=0.05ms(0-0)
- Phase2(events): mean=0.05ms(0-0)
- Phase3(anim): mean=0.20ms(0-1)
-```
-
-**Metrics Explained:**
-- **ticks**: Actual ticks executed vs expected (at 5ms intervals)
-- **missed**: Hint of missed ticks (negative means extra ticks, positive means missed)
-- **total**: Mean total tick time with (min-max) range in milliseconds
-- **anim**: Mean animation calculation time with (min-max) range - everything before hardware output
-- **hw**: Mean hardware output time with (min-max) range - just the LED strip update
-- **cpu**: Overall CPU usage percentage over the 5-second period
-
-**Phase Metrics (Optional):**
-When intermediate measurement points are available, the engine also reports phase-based timing:
-- **Phase1(checks)**: Initial checks (strip length, throttling, can_show)
-- **Phase2(events)**: Event processing time
-- **Phase3(anim)**: Animation update and render time (before hardware output)
-
-**Timestamp-Based Profiling:**
-
-The engine uses a timestamp-based profiling system that stores only timestamps (not durations) in instance variables:
-
-- `ts_start` - Tick start timestamp
-- `ts_1` - After initial checks (optional)
-- `ts_2` - After event processing (optional)
-- `ts_3` - After animation update/render (optional)
-- `ts_hw` - After hardware output
-- `ts_end` - Tick end timestamp
-
-Durations are computed from these timestamps in `_record_tick_metrics()` with nil checks to ensure values are valid.
-
-**Accessing Profiling Data:**
-
-```berry
-import animation
-
-var strip = Leds(30)
-var engine = animation.create_engine(strip)
-
-# Add an animation
-var anim = animation.solid(engine)
-anim.color = 0xFFFF0000
-engine.add(anim)
-engine.run()
-
-# Run for a while to collect metrics
-# After 5 seconds, metrics are automatically logged
-
-# Access current metrics programmatically
-print("Tick count:", engine.tick_count)
-print("Total time sum:", engine.tick_time_sum)
-print("Animation time sum:", engine.anim_time_sum)
-print("Hardware time sum:", engine.hw_time_sum)
-
-# Access phase metrics if available
-if engine.phase1_time_sum > 0
- print("Phase 1 time sum:", engine.phase1_time_sum)
-end
-```
-
-**Profiling Benefits:**
-
-1. **Memory Efficient:**
- - Only stores timestamps (6 instance variables)
- - No duration storage or arrays
- - Streaming statistics with no memory overhead
-
-2. **Automatic Tracking:**
- - No manual instrumentation needed
- - Runs continuously in background
- - Reports every 5 seconds
-
-3. **Detailed Breakdown:**
- - Separates animation calculation from hardware output
- - Optional phase-based timing for deeper analysis
- - Min/max/mean statistics for all metrics
-
-**Interpreting Performance Metrics:**
-
-1. **High Animation Time:**
- - Too many simultaneous animations
- - Complex value provider calculations
- - Inefficient custom effects
-
- **Solution:** Simplify animations or use sequences
-
-2. **High Hardware Time:**
- - Large LED strip (many pixels)
- - Slow SPI/I2C communication
- - Hardware limitations
-
- **Solution:** Reduce update frequency or strip length
-
-3. **Missed Ticks:**
- - CPU overload (total time > 5ms per tick)
- - Other Tasmota tasks interfering
-
- **Solution:** Optimize animations or reduce complexity
-
-4. **High CPU Percentage:**
- - Animations consuming too much CPU
- - May affect other Tasmota functions
-
- **Solution:** Increase animation periods or reduce effects
-
-**Example Performance Optimization:**
-
-```berry
-import animation
-
-var strip = Leds(60)
-var engine = animation.create_engine(strip)
-
-# Before optimization - complex animation
-var complex_anim = animation.rainbow_animation(engine)
-complex_anim.period = 100 # Very fast, high CPU
-
-engine.add(complex_anim)
-engine.run()
-
-# Check metrics after 5 seconds:
-# AnimEngine: ticks=950/1000 missed=50 total=5.2ms(4-8) cpu=104.0%
-# ^ Too slow! Missing ticks and over 100% CPU
-
-# After optimization - slower period
-complex_anim.period = 2000 # 2 seconds instead of 100ms
-
-# Check metrics after 5 seconds:
-# AnimEngine: ticks=1000/1000 missed=0 total=0.8ms(0-2) cpu=16.0%
-# ^ Much better! All ticks processed, reasonable CPU usage
-```
-
-### Choppy Animations
-
-**Problem:** Animations appear jerky or stuttering
-
-**Solutions:**
-
-1. **Use Sequences Instead of Multiple Animations:**
- ```berry
- # Good - sequential playback
- sequence smooth_show {
- play animation1 for 3s
- play animation2 for 3s
- play animation3 for 3s
- }
- run smooth_show
-
- # Avoid - too many simultaneous animations
- # run animation1
- # run animation2
- # run animation3
- ```
-
-2. **Increase Animation Periods:**
- ```berry
- # Smooth - longer periods
- animation smooth_pulse = pulsating_animation(color=red, period=3s)
-
- # Choppy - very short periods
- animation choppy_pulse = pulsating_animation(color=red, period=50ms)
- ```
-
-3. **Optimize Value Providers:**
- ```berry
- # Efficient - reuse providers
- set breathing = smooth(min_value=50, max_value=255, period=2s)
-
- color red = 0xFF0000
- color blue = 0x0000FF
-
- animation anim1 = pulsating_animation(color=red, period=2s)
- anim1.opacity = breathing
-
- animation anim2 = pulsating_animation(color=blue, period=2s)
- anim2.opacity = breathing # Reuse same provider
- ```
-
-4. **Monitor CPU Metrics:**
- ```berry
- # Check if CPU is overloaded
- # Look for missed ticks or high CPU percentage in metrics
- # AnimEngine: ticks=950/1000 missed=50 ... cpu=95.0%
- # ^ This indicates performance issues
-
- # Use profiling to find bottlenecks
- engine.profile_start("suspect_code")
- # ... code that might be slow ...
- engine.profile_end("suspect_code")
- ```
-
-### Memory Issues
-
-**Problem:** Out of memory errors or system crashes
-
-**Solutions:**
-
-1. **Clear Unused Animations:**
- ```berry
- # Clear before adding new animations
- engine.clear()
- engine.add(new_animation)
- ```
-
-2. **Limit Palette Size:**
- ```berry
- # Good - reasonable palette size
- palette simple_fire = [
- (0, 0x000000),
- (128, 0xFF0000),
- (255, 0xFFFF00)
- ]
-
- # Avoid - very large palettes
- # palette huge_palette = [
- # (0, color1), (1, color2), ... (255, color256)
- # ]
- ```
-
-3. **Use Sequences Instead of Simultaneous Animations:**
- ```berry
- # Memory efficient - sequential playback
- sequence show {
- play animation1 for 5s
- play animation2 for 5s
- play animation3 for 5s
- }
-
- # Memory intensive - all at once
- # run animation1
- # run animation2
- # run animation3
- ```
-
-## Event System Issues
-
-### Events Not Triggering
-
-**Problem:** Event handlers don't execute
-
-**Diagnostic Steps:**
-```berry
-# Check if handler is registered
-var handlers = animation.get_event_handlers("button_press")
-print("Handler count:", size(handlers))
-
-# Test event triggering
-animation.trigger_event("test_event", {"debug": true})
-```
-
-**Solutions:**
-
-1. **Verify Handler Registration:**
- ```berry
- def test_handler(event_data)
- print("Event triggered:", event_data)
- end
-
- var handler = animation.register_event_handler("test", test_handler, 0)
- print("Handler registered:", handler != nil)
- ```
-
-2. **Check Event Names:**
- ```berry
- # Event names are case-sensitive
- animation.register_event_handler("button_press", handler) # Correct
- animation.trigger_event("button_press", {}) # Must match exactly
- ```
-
-3. **Verify Conditions:**
- ```berry
- def condition_func(event_data)
- return event_data.contains("required_field")
- end
-
- animation.register_event_handler("event", handler, 0, condition_func)
-
- # Event data must satisfy condition
- animation.trigger_event("event", {"required_field": "value"})
- ```
-
-## Hardware Issues
-
-### LEDs Not Responding
-
-**Problem:** Framework runs but LEDs don't light up
-
-**Hardware Checks:**
-
-1. **Power Supply:**
- - Ensure adequate power for LED count
- - Check voltage (5V for WS2812)
- - Verify ground connections
-
-2. **Wiring:**
- - Data line connected to correct GPIO
- - Ground connected between controller and LEDs
- - Check for loose connections
-
-3. **LED Strip:**
- - Test with known working code
- - Check for damaged LEDs
- - Verify strip type (WS2812, SK6812, etc.)
-
-**Software Checks:**
-```berry
-# Test basic LED functionality
-var strip = Leds(30) # 30 LEDs
-strip.set_pixel_color(0, 0xFFFF0000) # Set first pixel red
-strip.show() # Update LEDs
-
-# Test with animation framework
-import animation
-var engine = animation.create_engine(strip)
-var red_anim = animation.solid(engine)
-red_anim.color = 0xFFFF0000
-engine.add(red_anim)
-engine.run()
-
-# If basic strip works but animation doesn't, check framework setup
-```
-
-### Wrong Colors on Hardware
-
-**Problem:** Colors look different on actual LEDs vs. expected
-
-**Solutions:**
-
-1. **Color Order:**
- ```berry
- # Some strips use different color orders
- # Try different strip types in Tasmota configuration
- # WS2812: RGB order
- # SK6812: GRBW order
- ```
-
-2. **Gamma Correction:**
- ```berry
- # Enable gamma correction in Tasmota
- # SetOption37 128 # Enable gamma correction
- ```
-
-3. **Power Supply Issues:**
- - Voltage drop causes color shifts
- - Use adequate power supply
- - Add power injection for long strips
-
-## Debugging Techniques
-
-### DSL vs Berry API Debugging
-
-**For DSL Issues (Recommended):**
-```berry
-# Enable DSL debug output
-import animation_dsl
-
-var dsl_code = "color red = 0xFF0000\nanimation test = solid(color=red)\nrun test"
-
-# Check compilation
-try
- var berry_code = animation_dsl.compile(dsl_code)
- print("DSL compilation successful")
- print("Generated Berry code:")
- print(berry_code)
-except .. as e, msg
- print("DSL compilation error:", msg)
-end
-
-# Execute with debug
-try
- animation_dsl.execute(dsl_code, true) # debug=true
-except .. as e, msg
- print("DSL execution error:", msg)
-end
-```
-
-**For Framework Issues (Advanced):**
-```berry
-# Direct Berry API debugging (for framework developers)
-import animation
-
-var strip = Leds(30)
-var engine = animation.create_engine(strip, true) # debug=true
-
-var anim = animation.solid(engine)
-anim.color = 0xFFFF0000
-engine.add(anim)
-engine.run()
-```
-
-### Step-by-Step Testing
-
-```berry
-# Test each component individually
-print("1. Creating strip...")
-var strip = Leds(30)
-print("Strip created:", strip != nil)
-
-print("2. Creating engine...")
-var engine = animation.create_engine(strip)
-print("Engine created:", engine != nil)
-
-print("3. Creating animation...")
-var anim = animation.solid(engine)
-anim.color = 0xFFFF0000
-print("Animation created:", anim != nil)
-
-print("4. Adding animation...")
-engine.add(anim)
-print("Animation count:", engine.size())
-
-print("5. Starting engine...")
-engine.run()
-print("Engine active:", engine.is_active())
-```
-
-### Monitor Performance
-
-```berry
-# Check timing
-var start_time = tasmota.millis()
-# ... run animation code ...
-var end_time = tasmota.millis()
-print("Execution time:", end_time - start_time, "ms")
-
-# Monitor memory (if available)
-import gc
-print("Memory before:", gc.allocated())
-# ... create animations ...
-print("Memory after:", gc.allocated())
-```
-
-## Getting Help
-
-### Information to Provide
-
-When asking for help, include:
-
-1. **Hardware Setup:**
- - LED strip type and count
- - GPIO pin used
- - Power supply specifications
-
-2. **Software Environment:**
- - Tasmota version
- - Berry version
- - Framework version
-
-3. **Code:**
- - Complete minimal example that reproduces the issue
- - Error messages (exact text)
- - Expected vs. actual behavior
-
-4. **Debugging Output:**
- - Debug mode output
- - Generated Berry code (for DSL issues)
- - Console output
-
-### Example Bug Report
-
-```
-**Problem:** DSL animation compiles but LEDs don't change
-
-**Hardware:**
-- 30x WS2812 LEDs on GPIO 1
-- ESP32 with 5V/2A power supply
-
-**Code:**
-```berry
-color red = 0xFF0000
-animation red_anim = solid(color=red)
-run red_anim
-```
-
-**Error Output:**
-```
-DSL compilation successful
-Engine created: true
-Animation count: 1
-Engine active: true
-```
-
-**Expected:** LEDs turn red
-**Actual:** LEDs remain off
-
-**Additional Info:**
-- Basic `strip.set_pixel_color(0, 0xFFFF0000); strip.show()` works
-- Tasmota 13.2.0, Berry enabled
-```
-
-This format helps identify issues quickly and provide targeted solutions.
-
-## Prevention Tips
-
-### Code Quality
-
-1. **Use Try-Catch Blocks:**
- ```berry
- try
- runtime.load_dsl(dsl_code)
- except .. as e, msg
- print("Error:", msg)
- end
- ```
-
-2. **Validate Inputs:**
- ```berry
- if type(color) == "int" && color >= 0
- var anim = animation.solid(color)
- else
- print("Invalid color:", color)
- end
- ```
-
-3. **Test Incrementally:**
- - Start with simple solid colors
- - Add one effect at a time
- - Test each change before proceeding
-
-### Performance Best Practices
-
-1. **Limit Complexity:**
- - 1-3 simultaneous animations
- - Reasonable animation periods (>1 second)
- - Moderate palette sizes
-
-2. **Resource Management:**
- - Clear unused animations
- - Reuse value providers
- - Use sequences for complex shows
-
-3. **Hardware Considerations:**
- - Adequate power supply
- - Proper wiring and connections
- - Appropriate LED strip for application
-
-## Quick Reference: Common DSL Patterns
-
-### Basic Animation
-```berry
-color red = 0xFF0000
-animation red_solid = solid(color=red)
-run red_solid
-```
-
-### Templates
-```berry
-# Define reusable template
-template pulse_effect {
- param base_color type color # Use descriptive names
- param speed type time # Add type annotations for clarity
-
- animation pulse = pulsating_animation(color=base_color, period=speed)
- run pulse
-}
-
-# Use template multiple times
-pulse_effect(red, 2s)
-pulse_effect(blue, 1s)
-```
-
-**Common Template Parameter Issues:**
-
-```berry
-# ❌ AVOID: Parameter name conflicts
-template bad_example {
- param color type color # Error: conflicts with built-in color name
- param animation type number # Error: conflicts with reserved keyword
-}
-
-# ✅ CORRECT: Use descriptive, non-conflicting names
-template good_example {
- param base_color type color # Clear, non-conflicting name
- param anim_speed type time # Descriptive parameter name
-}
-
-# ⚠️ WARNING: Unused parameters generate warnings
-template unused_param_example {
- param used_color type color
- param unused_value type number # Warning: never used in template body
-
- animation test = solid(color=used_color)
- run test
-}
-```
-
-### Animation with Parameters
-```berry
-color blue = 0x0000FF
-animation blue_pulse = pulsating_animation(color=blue, period=2s, opacity=200)
-run blue_pulse
-```
-
-### Using Value Providers
-```berry
-set breathing = smooth(min_value=50, max_value=255, period=3s)
-color green = 0x00FF00
-animation breathing_green = solid(color=green)
-breathing_green.opacity = breathing
-run breathing_green
-```
-
-### Sequences
-```berry
-color red = 0xFF0000
-color blue = 0x0000FF
-
-animation red_anim = solid(color=red)
-animation blue_anim = solid(color=blue)
-
-sequence demo {
- play red_anim for 2s
- wait 500ms
- play blue_anim for 2s
-}
-run demo
-```
-
-### Multiple Strip Lengths
-```berry
-strip length 60 # Must be first statement
-
-color rainbow = rainbow_color_provider(period=5s)
-animation rainbow_anim = solid(color=rainbow)
-run rainbow_anim
-```
-
-Following these guidelines will help you avoid most common issues and create reliable LED animations.
\ No newline at end of file
diff --git a/lib/libesp32/berry_animation/berry_animation_docs/USER_FUNCTIONS.md b/lib/libesp32/berry_animation/berry_animation_docs/USER_FUNCTIONS.md
deleted file mode 100644
index 63e60e641..000000000
--- a/lib/libesp32/berry_animation/berry_animation_docs/USER_FUNCTIONS.md
+++ /dev/null
@@ -1,677 +0,0 @@
-# User-Defined Functions
-
-Create custom animation functions in Berry and use them seamlessly in the Animation DSL.
-
-## Quick Start
-
-### 1. Create Your Function
-
-Write a Berry function that creates and returns an animation:
-
-```berry
-# Define a custom breathing effect
-def my_breathing(engine, color, speed)
- var anim = animation.pulsating_animation(engine)
- anim.color = color
- anim.min_brightness = 50
- anim.max_brightness = 255
- anim.period = speed
- return anim
-end
-```
-
-### 2. Register It
-
-Make your function available in DSL:
-
-```berry
-animation.register_user_function("breathing", my_breathing)
-```
-
-### 3. Use It in DSL
-
-First, import your user functions module, then call your function directly in computed parameters:
-
-```berry
-# Import your user functions module
-import user_functions
-
-# Use your custom function in computed parameters
-animation calm = solid(color=blue)
-calm.opacity = breathing_effect()
-
-animation energetic = solid(color=red)
-energetic.opacity = breathing_effect()
-
-sequence demo {
- play calm for 10s
- play energetic for 5s
-}
-
-run demo
-```
-
-## Importing User Functions
-
-### DSL Import Statement
-
-The DSL supports importing Berry modules using the `import` keyword. This is the recommended way to make user functions available in your animations:
-
-```berry
-# Import user functions at the beginning of your DSL file
-import user_functions
-
-# Now user functions are available directly
-animation test = solid(color=blue)
-test.opacity = my_function()
-```
-
-### Import Behavior
-
-- **Module Loading**: `import user_functions` transpiles to Berry `import "user_functions"`
-- **Function Registration**: The imported module should register functions using `animation.register_user_function()`
-- **Availability**: Once imported, functions are available throughout the DSL file
-- **No Compile-Time Checking**: The DSL doesn't validate user function existence at compile time
-
-### Example User Functions Module
-
-Create a file called `user_functions.be`:
-
-```berry
-import animation
-
-# Define your custom functions
-def rand_demo(engine)
- import math
- return math.rand() % 256 # Random value 0-255
-end
-
-def breathing_effect(engine, base_value, amplitude)
- import math
- var time_factor = (engine.time_ms / 1000) % 4 # 4-second cycle
- var breath = math.sin(time_factor * math.pi / 2)
- return int(base_value + breath * amplitude)
-end
-
-# Register functions for DSL use
-animation.register_user_function("rand_demo", rand_demo)
-animation.register_user_function("breathing", breathing_effect)
-
-print("User functions loaded!")
-```
-
-### Using Imported Functions in DSL
-
-```berry
-import user_functions
-
-# Simple user function call
-animation random_test = solid(color=red)
-random_test.opacity = rand_demo()
-
-# User function with parameters
-animation breathing_blue = solid(color=blue)
-breathing_blue.opacity = breathing(128, 64)
-
-# User functions in mathematical expressions
-animation complex = solid(color=green)
-complex.opacity = max(50, min(255, rand_demo() + 100))
-
-run random_test
-```
-
-### Multiple Module Imports
-
-You can import multiple modules in the same DSL file:
-
-```berry
-import user_functions # Basic user functions
-import fire_effects # Fire animation functions
-import color_utilities # Color manipulation functions
-
-animation base = solid(color=random_color())
-base.opacity = breathing(200, 50)
-
-animation flames = solid(color=red)
-flames.opacity = fire_intensity(180)
-```
-
-## Common Patterns
-
-### Simple Color Effects
-
-```berry
-def solid_bright(engine, color, brightness_percent)
- var anim = animation.solid_animation(engine)
- anim.color = color
- anim.brightness = int(brightness_percent * 255 / 100)
- return anim
-end
-
-animation.register_user_function("bright", solid_bright)
-```
-
-```berry
-animation bright_red = solid(color=red)
-bright_red.opacity = bright(80)
-
-animation dim_blue = solid(color=blue)
-dim_blue.opacity = bright(30)
-```
-
-### Fire Effects
-
-```berry
-def custom_fire(engine, intensity, speed)
- var color_provider = animation.rich_palette(engine)
- color_provider.colors = animation.PALETTE_FIRE
- color_provider.period = speed
-
- var fire_anim = animation.filled(engine)
- fire_anim.color_provider = color_provider
- fire_anim.brightness = intensity
- return fire_anim
-end
-
-animation.register_user_function("fire", custom_fire)
-```
-
-```berry
-animation campfire = solid(color=red)
-campfire.opacity = fire(200, 2000)
-
-animation torch = solid(color=orange)
-torch.opacity = fire(255, 500)
-```
-
-### Twinkling Effects
-
-```berry
-def twinkles(engine, color, count, period)
- var anim = animation.twinkle_animation(engine)
- anim.color = color
- anim.count = count
- anim.period = period
- return anim
-end
-
-animation.register_user_function("twinkles", twinkles)
-```
-
-```berry
-animation stars = solid(color=white)
-stars.opacity = twinkles(12, 800ms)
-
-animation fairy_dust = solid(color=0xFFD700)
-fairy_dust.opacity = twinkles(8, 600ms)
-```
-
-### Position-Based Effects
-
-```berry
-def pulse_at(engine, color, position, width, speed)
- var anim = animation.beacon_animation(engine)
- anim.color = color
- anim.position = position
- anim.width = width
- anim.period = speed
- return anim
-end
-
-animation.register_user_function("pulse_at", pulse_at)
-```
-
-```berry
-animation left_pulse = solid(color=green)
-left_pulse.position = pulse_at(5, 3, 2000)
-
-animation right_pulse = solid(color=blue)
-right_pulse.position = pulse_at(25, 3, 2000)
-```
-
-## Advanced Examples
-
-### Multi-Layer Effects
-
-```berry
-def rainbow_twinkle(engine, base_speed, twinkle_density)
- # Create base rainbow animation
- var rainbow_provider = animation.rich_palette(engine)
- rainbow_provider.colors = animation.PALETTE_RAINBOW
- rainbow_provider.period = base_speed
-
- var base_anim = animation.filled(engine)
- base_anim.color_provider = rainbow_provider
- base_anim.priority = 1
-
- # Note: This is a simplified example
- # Real multi-layer effects would require engine support
- return base_anim
-end
-
-animation.register_user_function("rainbow_sparkle", rainbow_sparkle)
-```
-
-### Dynamic Palettes
-
-Since DSL palettes only accept hex colors and predefined color names (not custom colors), use user functions for dynamic palettes with custom colors:
-
-```berry
-def create_custom_palette(engine, base_color, variation_count, intensity)
- # Create a palette with variations of the base color
- var palette_bytes = bytes()
-
- # Extract RGB components from base color
- var r = (base_color >> 16) & 0xFF
- var g = (base_color >> 8) & 0xFF
- var b = base_color & 0xFF
-
- # Create palette entries with color variations
- for i : 0..(variation_count-1)
- var position = int(i * 255 / (variation_count - 1))
- var factor = intensity * i / (variation_count - 1) / 255
-
- var new_r = int(r * factor)
- var new_g = int(g * factor)
- var new_b = int(b * factor)
-
- # Add VRGB entry (Value, Red, Green, Blue)
- palette_bytes.add(position, 1) # Position
- palette_bytes.add(new_r, 1) # Red
- palette_bytes.add(new_g, 1) # Green
- palette_bytes.add(new_b, 1) # Blue
- end
-
- return palette_bytes
-end
-
-animation.register_user_function("custom_palette", create_custom_palette)
-```
-
-```berry
-# Use dynamic colors in DSL
-animation gradient_effect = rich_palette(
- colors=custom_palette(0xFF6B35, 5, 255)
- period=4s
-)
-
-run gradient_effect
-```
-
-### Preset Configurations
-
-```berry
-def police_lights(engine, flash_speed)
- var anim = animation.pulsating_animation(engine)
- anim.color = 0xFFFF0000 # Red
- anim.min_brightness = 0
- anim.max_brightness = 255
- anim.period = flash_speed
- return anim
-end
-
-def warning_strobe(engine)
- return police_lights(engine, 200) # Fast strobe
-end
-
-def gentle_alert(engine)
- return police_lights(engine, 1000) # Slow pulse
-end
-
-animation.register_user_function("police", police_lights)
-animation.register_user_function("strobe", warning_strobe)
-animation.register_user_function("alert", gentle_alert)
-```
-
-```berry
-animation emergency = solid(color=red)
-emergency.opacity = strobe()
-
-animation notification = solid(color=yellow)
-notification.opacity = alert()
-
-animation custom_police = solid(color=blue)
-custom_police.opacity = police(500)
-```
-
-## Function Organization
-
-### Single File Approach
-
-```berry
-# user_animations.be
-import animation
-
-def breathing(engine, color, period)
- # ... implementation
-end
-
-def fire_effect(engine, intensity, speed)
- # ... implementation
-end
-
-def twinkle_effect(engine, color, count, period)
- # ... implementation
-end
-
-# Register all functions
-animation.register_user_function("breathing", breathing)
-animation.register_user_function("fire", fire_effect)
-animation.register_user_function("twinkle", twinkle_effect)
-
-print("Custom animations loaded!")
-```
-
-### Modular Approach
-
-```berry
-# animations/fire.be
-def fire_effect(engine, intensity, speed)
- # ... implementation
-end
-
-def torch_effect(engine)
- return fire_effect(engine, 255, 500)
-end
-
-return {
- 'fire': fire_effect,
- 'torch': torch_effect
-}
-```
-
-```berry
-# main.be
-import animation
-
-# Register functions
-animation.register_user_function("fire", fire_effects['fire'])
-animation.register_user_function("torch", fire_effects['torch'])
-```
-
-## Best Practices
-
-### Function Design
-
-1. **Use descriptive names**: `breathing_slow` not `bs`
-2. **Logical parameter order**: color first, then timing, then modifiers
-3. **Sensible defaults**: Make functions work with minimal parameters
-4. **Return animations**: Always return a configured animation object
-
-### Parameter Handling
-
-```berry
-def flexible_pulse(engine, color, period, min_brightness, max_brightness)
- # Provide defaults for optional parameters
- if min_brightness == nil min_brightness = 50 end
- if max_brightness == nil max_brightness = 255 end
-
- var anim = animation.pulsating_animation(engine)
- anim.color = color
- anim.period = period
- anim.min_brightness = min_brightness
- anim.max_brightness = max_brightness
- return anim
-end
-```
-
-### Error Handling
-
-```berry
-def safe_comet(engine, color, tail_length, speed)
- # Validate parameters
- if tail_length < 1 tail_length = 1 end
- if tail_length > 20 tail_length = 20 end
- if speed < 100 speed = 100 end
-
- var anim = animation.comet_animation(engine)
- anim.color = color
- anim.tail_length = tail_length
- anim.speed = speed
- return anim
-end
-```
-
-### Documentation
-
-```berry
-# Creates a pulsing animation with customizable brightness range
-# Parameters:
-# color: The color to pulse (hex or named color)
-# period: How long one pulse cycle takes (in milliseconds)
-# min_brightness: Minimum brightness (0-255, default: 50)
-# max_brightness: Maximum brightness (0-255, default: 255)
-# Returns: Configured pulse animation
-def breathing_effect(engine, color, period, min_brightness, max_brightness)
- # ... implementation
-end
-```
-
-## User Functions in Computed Parameters
-
-User functions can be used in computed parameter expressions alongside mathematical functions, creating powerful dynamic animations:
-
-### Simple User Function in Computed Parameter
-
-```berry
-# Simple user function call in property assignment
-animation base = solid(color=blue, priority=10)
-base.opacity = rand_demo() # User function as computed parameter
-```
-
-### User Functions with Mathematical Operations
-
-```berry
-# Get strip length for calculations
-set strip_len = strip_length()
-
-# Mix user functions with mathematical functions
-animation dynamic_solid = solid(
- color=purple
- opacity=max(50, min(255, rand_demo() + 100)) # Random opacity with bounds
- priority=15
-)
-```
-
-### User Functions in Complex Expressions
-
-```berry
-# Use user function in arithmetic expressions
-animation random_effect = solid(
- color=cyan
- opacity=abs(rand_demo() - 128) + 64 # Random variation around middle value
- priority=12
-)
-```
-
-### How It Works
-
-When you use user functions in computed parameters:
-
-1. **Automatic Detection**: The transpiler automatically detects user functions in expressions
-2. **Single Closure**: The entire expression is wrapped in a single efficient closure
-3. **Engine Access**: User functions receive `engine` in the closure context
-4. **Mixed Operations**: User functions work seamlessly with mathematical functions and arithmetic
-
-**Generated Code Example:**
-```berry
-# DSL code
-animation.opacity = max(100, breathing(red, 2000))
-```
-
-**Transpiles to:**
-```berry
-animation.opacity = animation.create_closure_value(engine,
- def (engine, param_name, time_ms)
- return (animation._math.max(100, animation.get_user_function('breathing')(engine, 0xFFFF0000, 2000)))
- end)
-```
-
-### Available User Functions
-
-The following user functions are available by default:
-
-| Function | Parameters | Description |
-|----------|------------|-------------|
-| `rand_demo()` | none | Returns a random value (0-255) for demonstration |
-
-### Best Practices for Computed Parameters
-
-1. **Keep expressions readable**: Break complex expressions across multiple lines
-2. **Use meaningful variable names**: `set strip_len = strip_length()` not `set s = strip_length()`
-3. **Combine wisely**: Mix user functions with math functions for rich effects
-4. **Test incrementally**: Start simple and build up complex expressions
-
-## Loading and Using Functions
-
-### In Tasmota autoexec.be
-
-```berry
-import animation
-
-# Load your custom functions
-load("user_animations.be")
-
-# Now they're available in DSL with import
-var dsl_code =
- "import user_functions\n"
- "\n"
- "animation my_fire = solid(color=red)\n"
- "my_fire.opacity = fire(200, 1500)\n"
- "animation my_twinkles = solid(color=white)\n"
- "my_twinkles.opacity = twinkle(8, 400ms)\n"
- "\n"
- "sequence show {\n"
- " play my_fire for 10s\n"
- " play my_twinkles for 5s\n"
- "}\n"
- "\n"
- "run show"
-
-animation_dsl.execute(dsl_code)
-```
-
-### From Files
-
-```berry
-# Save DSL with custom functions
-var my_show =
- "import user_functions\n"
- "\n"
- "animation campfire = solid(color=orange)\n"
- "campfire.opacity = fire(180, 2000)\n"
- "animation stars = solid(color=0xFFFFFF)\n"
- "stars.opacity = twinkle(6, 600ms)\n"
- "\n"
- "sequence night_scene {\n"
- " play campfire for 30s\n"
- " play stars for 10s\n"
- "}\n"
- "\n"
- "run night_scene"
-
-# Save to file
-var f = open("night_scene.anim", "w")
-f.write(my_show)
-f.close()
-
-# Load and run
-animation_dsl.load_file("night_scene.anim")
-```
-
-## Implementation Details
-
-### Function Signature Requirements
-
-User functions must follow this exact pattern:
-
-```berry
-def function_name(engine, param1, param2, ...)
- # engine is ALWAYS the first parameter
- # followed by user-provided parameters
- return animation_object
-end
-```
-
-### How the DSL Transpiler Works
-
-When you write DSL like this:
-```berry
-animation my_anim = my_function(arg1, arg2)
-```
-
-The transpiler generates Berry code like this:
-```berry
-var my_anim_ = animation.get_user_function('my_function')(engine, arg1, arg2)
-```
-
-The `engine` parameter is automatically inserted as the first argument.
-
-### Registration API
-
-```berry
-# Register a function
-animation.register_user_function(name, function)
-
-# Check if a function is registered
-if animation.is_user_function("my_function")
- print("Function is registered")
-end
-
-# Get a registered function
-var func = animation.get_user_function("my_function")
-
-# List all registered functions
-var functions = animation.list_user_functions()
-for name : functions
- print("Registered:", name)
-end
-```
-
-### Engine Parameter
-
-The `engine` parameter provides:
-- Access to the LED strip: `engine.get_strip_length()`
-- Current time: `engine.time_ms`
-- Animation management context
-
-Always use the provided engine when creating animations - don't create your own engine instances.
-
-### Return Value Requirements
-
-User functions must return an animation object that:
-- Extends `animation.animation` or `animation.pattern`
-- Is properly configured with the engine
-- Has all required parameters set
-
-### Error Handling
-
-The framework handles errors gracefully:
-- Invalid function names are caught at DSL compile time
-- Runtime errors in user functions are reported with context
-- Failed function calls don't crash the animation system
-
-## Troubleshooting
-
-### Function Not Found
-```
-Error: Unknown function 'my_function'
-```
-- Ensure the function is registered with `animation.register_user_function()`
-- Check that registration happens before DSL compilation
-- Verify the function name matches exactly (case-sensitive)
-
-### Wrong Number of Arguments
-```
-Error: Function call failed
-```
-- Check that your function signature matches the DSL call
-- Remember that `engine` is automatically added as the first parameter
-- Verify all required parameters are provided in the DSL
-
-### Animation Not Working
-- Ensure your function returns a valid animation object
-- Check that the animation is properly configured
-- Verify that the engine parameter is used correctly
-
-User-defined functions provide a powerful way to extend the Animation DSL with custom effects while maintaining the clean, declarative syntax that makes the DSL easy to use.
\ No newline at end of file