Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,26 @@ SUCCESS
SUCCESS
```

## demo_value_meter.anim

**Status:** ✅ Success

## Symbol Table

| Symbol | Type | Builtin | Dangerous | Takes Args |
|---------------------------|----------------------------|---------|-----------|------------|
| `back_pattern` | animation | | | |
| `closure_value` | value_provider_constructor | ✓ | ⚠️ | ✓ |
| `palette_meter_animation` | animation_constructor | ✓ | ⚠️ | ✓ |
| `rainbow_with_white` | palette | | | |
| `rand_meter` | user_function | | | ✓ |

### Compilation Output

```
SUCCESS
```

## disco_strobe.anim

**Status:** ✅ Success
Expand Down Expand Up @@ -702,34 +722,6 @@ SUCCESS
SUCCESS
```

## plasma_wave.anim

**Status:** ✅ Success

## Symbol Table

| Symbol | Type | Builtin | Dangerous | Takes Args |
|--------------------------|----------------------------|---------|-----------|------------|
| `SINE` | constant | ✓ | | |
| `beacon_animation` | animation_constructor | ✓ | ⚠️ | ✓ |
| `plasma_base` | animation | | | |
| `plasma_colors` | palette | | | |
| `plasma_wave1` | animation | | | |
| `plasma_wave2` | animation | | | |
| `plasma_wave3` | animation | | | |
| `rich_palette_animation` | animation_constructor | ✓ | ⚠️ | ✓ |
| `rich_palette` | color_constructor | ✓ | ⚠️ | ✓ |
| `smooth` | value_provider_constructor | ✓ | ⚠️ | ✓ |
| `wave1_pattern` | color | | | |
| `wave2_pattern` | color | | | |
| `wave3_pattern` | color | | | |

### Compilation Output

```
SUCCESS
```

## palette_demo.anim

**Status:** ✅ Success
Expand Down Expand Up @@ -789,6 +781,34 @@ SUCCESS
SUCCESS
```

## plasma_wave.anim

**Status:** ✅ Success

## Symbol Table

| Symbol | Type | Builtin | Dangerous | Takes Args |
|--------------------------|----------------------------|---------|-----------|------------|
| `SINE` | constant | ✓ | | |
| `beacon_animation` | animation_constructor | ✓ | ⚠️ | ✓ |
| `plasma_base` | animation | | | |
| `plasma_colors` | palette | | | |
| `plasma_wave1` | animation | | | |
| `plasma_wave2` | animation | | | |
| `plasma_wave3` | animation | | | |
| `rich_palette_animation` | animation_constructor | ✓ | ⚠️ | ✓ |
| `rich_palette` | color_constructor | ✓ | ⚠️ | ✓ |
| `smooth` | value_provider_constructor | ✓ | ⚠️ | ✓ |
| `wave1_pattern` | color | | | |
| `wave2_pattern` | color | | | |
| `wave3_pattern` | color | | | |

### Compilation Output

```
SUCCESS
```

## police_lights.anim

**Status:** ✅ Success
Expand Down Expand Up @@ -1236,8 +1256,8 @@ SUCCESS

## Summary

- **Total files processed:** 50
- **Successfully compiled:** 47
- **Total files processed:** 51
- **Successfully compiled:** 48
- **Failed to compile:** 3

### Successful Files
Expand All @@ -1257,6 +1277,7 @@ SUCCESS
- ✅ demo_shutter_rainbow_central.anim
- ✅ demo_shutter_rainbow_leftright.anim
- ✅ demo_shutter_rainbow2.anim
- ✅ demo_value_meter.anim
- ✅ disco_strobe.anim
- ✅ fire_flicker.anim
- ✅ heartbeat_pulse.anim
Expand All @@ -1267,9 +1288,9 @@ SUCCESS
- ✅ meteor_shower.anim
- ✅ neon_glow.anim
- ✅ ocean_waves.anim
- ✅ plasma_wave.anim
- ✅ palette_demo.anim
- ✅ palette_showcase.anim
- ✅ plasma_wave.anim
- ✅ police_lights.anim
- ✅ property_assignment_demo.anim
- ✅ rainbow_cycle.anim
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Generated Berry code from Animation DSL
# Source: demo_value_meter.anim
#
# This file was automatically generated by compile_all_examples.sh
# Do not edit manually - changes will be overwritten

import animation

# Pattern of colors in the background based on palette, rotating over 5 s
# Auto-generated strip initialization (using Tasmota configuration)
var engine = animation.init_strip()

# Berry code block

def rand_meter(time_ms, self)
import math
var r = math.rand() % 101
return r
end

# End berry code block
# External function declaration: rand_meter
animation.register_user_function("rand_meter", rand_meter)
# define a palette of rainbow colors including white with constant brightness
var rainbow_with_white_ = bytes(
"FFFC0000" # Red
"FFFF8000" # Orange
"FFFFFF00" # Yellow
"FF00FF00" # Green
"FF00FFFF" # Cyan
"FF0080FF" # Blue
"FF8000FF" # Violet
"FFCCCCCC" # White
"FFFC0000" # Red - need to add the first color at last position to ensure roll-over
)
# define a gradient across the whole strip
var back_pattern_ = animation.palette_meter_animation(engine)
back_pattern_.value_func = animation.create_closure_value(engine, def (engine) return animation.get_user_function('rand_meter')(engine) end)
engine.add(back_pattern_)
engine.run()


#- Original DSL source:
# Pattern of colors in the background based on palette, rotating over 5 s

berry """
def rand_meter(time_ms, self)
import math
var r = math.rand() % 101
return r
end
"""

extern function rand_meter

# define a palette of rainbow colors including white with constant brightness
palette rainbow_with_white = [
0xFC0000 # Red
0xFF8000 # Orange
0xFFFF00 # Yellow
0x00FF00 # Green
0x00FFFF # Cyan
0x0080FF # Blue
0x8000FF # Violet
0xCCCCCC # White
0xFC0000 # Red - need to add the first color at last position to ensure roll-over
]

# define a gradient across the whole strip
animation back_pattern = palette_meter_animation(value_func = rand_meter)

run back_pattern

-#
29 changes: 29 additions & 0 deletions lib/libesp32/berry_animation/anim_examples/demo_value_meter.anim
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Pattern of colors in the background based on palette, rotating over 5 s

berry """
def rand_meter(time_ms, self)
import math
var r = math.rand() % 101
return r
end
"""

extern function rand_meter

# define a palette of rainbow colors including white with constant brightness
palette rainbow_with_white = [
0xFC0000 # Red
0xFF8000 # Orange
0xFFFF00 # Yellow
0x00FF00 # Green
0x00FFFF # Cyan
0x0080FF # Blue
0x8000FF # Violet
0xCCCCCC # White
0xFC0000 # Red - need to add the first color at last position to ensure roll-over
]

# define a gradient across the whole strip
animation back_pattern = palette_meter_animation(value_func = rand_meter)

run back_pattern
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ palette rainbow_with_white = [
0xFC0000 # Red - need to add the first color at last position to ensure roll-over
]

# define a color attribute that cycles over time, cycle is 10 seconds
# define a color attribute cycles color in space
color rainbow_rich_color = rich_palette(palette=rainbow_with_white, cycle_period=0, transition_type=SINE)

# define a gradient across the whole strip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ def rand_meter(time_ms, self)
end
"""

extern function rand_meter

# define a palette of rainbow colors including white with constant brightness
palette rainbow_with_white = [
0xFC0000 # Red
Expand All @@ -21,7 +23,10 @@ palette rainbow_with_white = [
0xFC0000 # Red - need to add the first color at last position to ensure roll-over
]

# define a color attribute cycles color in space
color rainbow_rich_color = rich_palette(palette=rainbow_with_white, cycle_period=0, transition_type=SINE)

# define a gradient across the whole strip
animation back_pattern = palette_meter_animation(value_func = rand_meter)
animation back_pattern = palette_meter_animation(color_source = rainbow_rich_color, value_func = rand_meter)

run back_pattern
77 changes: 33 additions & 44 deletions lib/libesp32/berry_animation/docs/ANIMATION_CLASS_HIERARCHY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ ParameterizedObject (base class with parameter management and playable interface
│ ├── BeaconAnimation (pulse at specific position)
│ ├── CrenelPositionAnimation (crenel/square wave pattern)
│ ├── BreatheAnimation (breathing effect)
│ ├── PalettePatternAnimation (base for palette-based animations)
│ ├── PaletteGradientAnimation (gradient patterns with palette colors)
│ │ └── PaletteMeterAnimation (meter/bar patterns)
│ ├── CometAnimation (moving comet with tail)
│ ├── FireAnimation (realistic fire effect)
│ ├── TwinkleAnimation (twinkling stars effect)
Expand Down Expand Up @@ -243,11 +244,11 @@ Generates oscillating values using various waveforms. Inherits from `ValueProvid
| Parameter | Type | Default | Constraints | Description |
|-----------|------|---------|-------------|-------------|
| `min_value` | int | 0 | - | Minimum oscillation value |
| `max_value` | int | 100 | - | Maximum 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-100 | Phase shift percentage |
| `duty_cycle` | int | 50 | 0-100 | Duty cycle for square/triangle waves |
| `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
Expand Down Expand Up @@ -301,6 +302,18 @@ The ClosureValueProvider includes built-in mathematical helper methods that can
- **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:
Expand Down Expand Up @@ -1029,51 +1042,23 @@ animation strobe = wave_animation(



### PalettePatternAnimation
### PaletteGradientAnimation

Applies colors from a color provider to specific patterns using an efficient bytes() buffer. Inherits from `Animation`.
Creates shifting gradient patterns with palette colors. Inherits from `Animation`.

| Parameter | Type | Default | Constraints | Description |
|-----------|------|---------|-------------|-------------|
| `color_source` | instance | nil | - | Color provider for pattern mapping |
| `pattern_func` | function | nil | - | Function that generates pattern values (0-255) for each pixel |
| `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
- Pattern function should return values in 0-255 range
- Color source receives values in 0-255 range via `get_color_for_value(value, time_ms)`
- Buffer automatically resizes when strip length changes

**Factory**: `animation.palette_pattern_animation(engine)`

### PaletteWaveAnimation

Creates sine wave patterns with palette colors. Inherits from `PalettePatternAnimation`.

| Parameter | Type | Default | Constraints | Description |
|-----------|------|---------|-------------|-------------|
| `wave_period` | int | 5000 | min: 1 | Wave animation period in ms |
| `wave_length` | int | 10 | min: 1 | Wave length in pixels |
| *(inherits all PalettePatternAnimation parameters)* | | | | |

**Pattern Generation:**
- Generates sine wave values in 0-255 range using `tasmota.sine_int()`
- Wave position advances based on `wave_period` timing
- Each pixel's value calculated as: `sine_value = tasmota.scale_int(sine_int(angle), -4096, 4096, 0, 255)`

**Factory**: `animation.palette_wave_animation(engine)`

### PaletteGradientAnimation

Creates shifting gradient patterns with palette colors. Inherits from `PalettePatternAnimation`.

| Parameter | Type | Default | Constraints | Description |
|-----------|------|---------|-------------|-------------|
| `shift_period` | int | 10000 | 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-100 | Phase shift as percentage of spatial period |
| *(inherits all PalettePatternAnimation parameters)* | | | | |
- Optimized LUT (Lookup Table) support for color providers

**Pattern Generation:**
- Generates linear gradient values in 0-255 range across the specified spatial period
Expand All @@ -1084,23 +1069,27 @@ Creates shifting gradient patterns with palette colors. Inherits from `PalettePa
- `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 as: `value = tasmota.scale_uint(spatial_position, 0, spatial_period-1, 0, 255)`
- 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 `PalettePatternAnimation`.
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-100 range) |
| *(inherits all PalettePatternAnimation parameters)* | | | | |
| `value_func` | function | nil | - | Function that provides meter values (0-255 range) |
| *(inherits all PaletteGradientAnimation parameters)* | | | | |

**Pattern Generation:**
- Value function returns percentage (0-100) representing meter level
- 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, 100, 0, strip_length)`
- Meter position calculated as: `position = tasmota.scale_uint(value, 0, 255, 0, strip_length)`

**Factory**: `animation.palette_meter_animation(engine)`

Expand Down
Loading