forked from arendst/Tasmota
-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathledbar.tc
More file actions
135 lines (119 loc) · 4.13 KB
/
Copy pathledbar.tc
File metadata and controls
135 lines (119 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// LEDBAR — WS2812 position indicator with IR lamp control
// Translated from Scripter ws2812script.txt
//
// Left half: red stripes, right half: green stripes
// Blue marker shows 'ledbar' value (-5000..+5000) as position
// 'elamp' toggles IR lamp on/off via NEC protocol
// UDP shared variables (auto-updated from other device)
global float ledbar;
global float elamp;
// LED strip pixel buffer (heap-allocated, ESP8266 has only 64 global slots)
int leds[65]; // > 64 → auto heap; only [0..59] used
float last_elamp = -1.0; // remembers the last 'elamp' we acted on (-1 = none yet)
// Stripe colors (dim to save power)
int colr1 = 0x050000; // dark red
int colr2 = 0x050100; // dark red + tiny green
int colg1 = 0x000300; // dark green
int colg2 = 0x020300; // dark green + tiny red
int blue = 64; // 0x000040 — blue marker
// Configuration
int pixels = 60;
int steps = 10;
int divn;
int maxval = 5000;
int minval = -5000;
// Fill strip with alternating color stripes
void prep() {
int ind = 0;
int tog = 0;
for (int i = 0; i < pixels; i++) {
ind++;
if (ind > divn) {
ind = 1;
tog = tog ^ 1;
}
if (i < pixels / 2) {
if (tog) {
leds[i] = colr1;
} else {
leds[i] = colr2;
}
} else {
if (tog) {
leds[i] = colg1;
} else {
leds[i] = colg2;
}
}
}
}
int main() {
divn = pixels / steps;
prep();
setPixels(leds, pixels, 0);
return 0;
}
void WebCall() {
char buf[64];
sprintf(buf, "{s}ledbar{m}%f{e}", ledbar);
webSend(buf);
}
void UdpCall() {
// IMPORTANT: do NOT call IRsend (or any long/blocking command) here.
// UdpCall fires on EVERY received global from EVERY device on the
// multicast LAN. An IRsend NEC frame blocks ~67 ms with interrupts
// disabled; on a single-core ESP32-C3/C6 a flapping 'elamp' (or a busy
// LAN) turns that into an IR-send storm that starves WiFi + the web
// server and wedges the device.
//
// 'elamp' is auto-updated from the UDP packet before this callback runs;
// EverySecond() picks up the change and drives the IR lamp at most once
// per second. So UdpCall has nothing to do for the Matter "Ecklicht".
}
void EverySecond() {
// ledbar and elamp are auto-updated from UDP packets
// IR lamp control — only on change, and via tasmDefer (NOT tasmCmd).
// * Here (not UdpCall): so it can't fire per-UDP-packet.
// * tasmDefer: queues the command so ExecuteCommand() runs on the MAIN
// task (from TinyCEvery50ms, between callbacks) instead of inline in
// the VM-task context. IRsend blocks ~67 ms with interrupts disabled;
// running it inline in a callback wedges a single-core ESP32-C3/C6.
// This is how the Matter "Ecklicht" on/off (bridge sets g:elamp on
// MatterInvoke) reaches the IR lamp.
if (elamp != last_elamp) {
last_elamp = elamp;
if (elamp > 0.0) {
tasmDefer("IRsend {\"Protocol\":\"NEC\",\"Bits\":32,\"Data\":0x00F7E01F}");
} else {
tasmDefer("IRsend {\"Protocol\":\"NEC\",\"Bits\":32,\"Data\":0x00F740BF}");
}
}
// Clamp to range
if (ledbar < (float)minval) { ledbar = (float)minval; }
if (ledbar > (float)maxval) { ledbar = (float)maxval; }
// Map ledbar (-5000..+5000) to pixel position (0..59)
// Center = pixel 29/30, negative = left, positive = right
int half = pixels / 2;
int pos;
float fpos = (ledbar / (float)maxval) * (float)half;
if (ledbar > 0.0) {
pos = (int)fpos + half;
if (pos > pixels - 1) { pos = pixels - 1; }
} else {
pos = (int)fpos + half;
if (pos < 0) { pos = 0; }
}
// Fill base stripe pattern
prep();
// Overlay blue position marker
if (ledbar == 0.0) {
leds[pos] = blue;
if (pos > 0) { leds[pos - 1] = blue; }
} else {
leds[pos] = blue;
}
// Update strip only when power is off (manual LED control)
if (tasm_power == 0) {
setPixels(leds, pixels, 0);
}
}