FastLED 3.9.15
Loading...
Searching...
No Matches
test.cpp
Go to the documentation of this file.
1
2
3#include <Arduino.h>
4#include "FastLED.h"
5#include "test.h"
6
7bool verifyJumperWire(int pin_tx, int pin_rx) {
8 FL_WARN("Verifying jumper wire connection between GPIO " << pin_tx << " and GPIO " << pin_rx << "...");
9
10 pinMode(pin_tx, OUTPUT);
11 pinMode(pin_rx, INPUT);
12
13 // Test HIGH
14 digitalWrite(pin_tx, HIGH);
15 delay(1); // Allow signal to propagate
16 int rx_high = digitalRead(pin_rx);
17
18 // Test LOW
19 digitalWrite(pin_tx, LOW);
20 delay(1); // Allow signal to propagate
21 int rx_low = digitalRead(pin_rx);
22
23 if (rx_high != HIGH || rx_low != LOW) {
24 FL_ERROR("Jumper wire sanity check FAILED!");
25 FL_ERROR(" digitalWrite(TX=" << pin_tx << ", HIGH) → digitalRead(RX=" << pin_rx << ") = " << rx_high << " (expected HIGH=1)");
26 FL_ERROR(" digitalWrite(TX=" << pin_tx << ", LOW) → digitalRead(RX=" << pin_rx << ") = " << rx_low << " (expected LOW=0)");
27 FL_ERROR("");
28 FL_ERROR("REQUIRED: Physically connect GPIO " << pin_tx << " to GPIO " << pin_rx << " with a jumper wire!");
29 return false;
30 }
31
32 FL_WARN("✓ Jumper wire verified: GPIO " << pin_tx << " → GPIO " << pin_rx << " signal path working");
33 return true;
34}
35
38 int pin_tx,
39 uint32_t wait_ms) {
40 const fl::RxChannelConfig& config = rx.config();
41
42 // Set pin to initial state before begin()
43 pinMode(pin_tx, OUTPUT);
44 digitalWrite(pin_tx, config.start_low ? LOW : HIGH);
45 fl::delayMicroseconds(100); // Allow pin to settle
46
47 // Initialize RX channel
48 if (!rx.begin(config)) {
49 FL_ERROR("Failed to initialize RX channel");
50 return;
51 }
52
53 // Execute pin toggles
54 for (size_t i = 0; i < toggles.size(); i++) {
55 digitalWrite(pin_tx, toggles[i].is_high ? HIGH : LOW);
56 fl::delayMicroseconds(toggles[i].delay_us);
57 }
58}
59
61 size_t edge_count,
62 fl::span<const PinToggle> expected_pattern,
63 uint32_t tolerance_percent) {
64
65 FL_WARN("[TEST] Captured " << edge_count << " edges");
66
67 if (edge_count == 0) {
68 FL_ERROR("No edges captured!");
69 return false;
70 }
71
72 // Print edge timings
73 FL_WARN("[TEST] Edge timings:");
74 for (size_t i = 0; i < edge_count; i++) {
75 FL_WARN(" [" << i << "] " << (edges[i].high ? "HIGH" : "LOW ")
76 << " " << edges[i].ns << "ns (" << (edges[i].ns / 1000) << "us)");
77 }
78
79 // Validate edge alternation
80 bool alternation_valid = true;
81 for (size_t i = 1; i < edge_count; i++) {
82 if (edges[i].high == edges[i-1].high) {
83 FL_ERROR("Sequential " << (edges[i].high ? "HIGH" : "LOW")
84 << " values at indices " << (i-1) << " and " << i
85 << " - edges should alternate HIGH/LOW");
86 alternation_valid = false;
87 }
88 }
89
90 // Validate timing accuracy against expected pattern
91 bool timing_valid = true;
92 FL_WARN("[TEST] Validating timing accuracy (±" << tolerance_percent << "% tolerance):");
93
94 // Expected edge count is expected_pattern.size() - 1 because the last edge
95 // ends with timeout (no subsequent transition to measure duration)
96 size_t expected_edge_count = expected_pattern.size() - 1;
97 if (edge_count != expected_edge_count) {
98 FL_WARN("WARNING: Edge count mismatch - expected " << expected_edge_count
99 << ", got " << edge_count);
100 timing_valid = false;
101 }
102
103 size_t compare_count = edge_count < expected_edge_count ? edge_count : expected_edge_count;
104 for (size_t i = 0; i < compare_count; i++) {
105 uint32_t expected_us = expected_pattern[i].delay_us;
106 uint32_t actual_us = edges[i].ns / 1000;
107 bool expected_high = expected_pattern[i].is_high;
108 bool actual_high = edges[i].high;
109
110 // Calculate tolerance range
111 uint32_t tolerance_us = (expected_us * tolerance_percent) / 100;
112 uint32_t min_us = expected_us - tolerance_us;
113 uint32_t max_us = expected_us + tolerance_us;
114
115 // Validate timing and level
116 bool timing_ok = (actual_us >= min_us) && (actual_us <= max_us);
117 bool level_ok = (expected_high == actual_high);
118
119 if (timing_ok && level_ok) {
120 FL_WARN(" [" << i << "] ✓ " << (actual_high ? "HIGH" : "LOW ")
121 << " " << actual_us << "us (expected " << expected_us
122 << "us ±" << tolerance_us << "us)");
123 } else {
124 if (!level_ok) {
125 FL_WARN(" [" << i << "] ✗ Level mismatch: expected "
126 << (expected_high ? "HIGH" : "LOW") << ", got "
127 << (actual_high ? "HIGH" : "LOW"));
128 timing_valid = false;
129 }
130 if (!timing_ok) {
131 FL_WARN(" [" << i << "] ✗ Timing out of range: " << actual_us
132 << "us (expected " << expected_us << "us ±" << tolerance_us
133 << "us, range: " << min_us << "-" << max_us << "us)");
134 timing_valid = false;
135 }
136 }
137 }
138
139 // Validate results
140 if (!alternation_valid) {
141 FL_ERROR("Edge timings are not properly alternating");
142 FL_ERROR("Expected pattern: HIGH, LOW, HIGH, LOW, ...");
143 FL_ERROR("Actual pattern contains sequential identical states");
144 return false;
145 } else if (!timing_valid) {
146 FL_ERROR("Captured edge timings do not match expected pattern");
147 FL_ERROR("Check timing accuracy and tolerance settings");
148 return false;
149 } else if (edge_count >= 5) {
150 FL_WARN("[TEST] ✓ PASS: Captured " << edge_count << " edges with proper alternation");
151 FL_WARN("[TEST] ✓ PASS: All timing values match expected pattern within tolerance");
152 FL_WARN("[TEST] ✓ RX channel working correctly!");
153 return true;
154 } else {
155 FL_WARN("WARNING: Only captured " << edge_count << " edges (expected >=5)");
156 return false;
157 }
158}
159
161 FL_WARN("Testing RX channel with low-frequency pattern...");
162
163 if (!rx) {
164 FL_ERROR("Failed to test RX channel - null channel provided");
165 return false;
166 }
167
168 int pin_rx = rx->getPin();
169
170 // Configure RX channel for low-frequency test
171 fl::RxChannelConfig config(pin_rx);
172 config.signal_range_min_ns = 100; // 100ns glitch filter
173 config.signal_range_max_ns = 30000000; // 30ms idle timeout (ESP-IDF RMT limit: 32767000ns)
174 config.start_low = true; // Pin starts LOW
175
176 // Initialize TX pin and set to LOW
177 pinMode(pin_tx, OUTPUT);
178 pinMode(pin_rx, INPUT);
179 digitalWrite(pin_tx, LOW);
180 delay(10); // Allow pin to settle
181
182 if (!rx->begin(config)) {
183 FL_ERROR("Failed to initialize RX channel");
184 return false;
185 }
186
187 // Generate simple test pattern: 4 edges (LOW->HIGH->LOW->HIGH)
188 // Pattern: HIGH 10ms, LOW 10ms, HIGH 10ms
189 FL_WARN("Generating test pattern on GPIO " << pin_tx << "...");
190 digitalWrite(pin_tx, HIGH);
191 delay(10);
192 digitalWrite(pin_tx, LOW);
193 delay(10);
194 digitalWrite(pin_tx, HIGH);
195 delay(10);
196 digitalWrite(pin_tx, LOW);
197
198 // Wait for capture with timeout
199 FL_WARN("Waiting for RX capture...");
200 auto wait_result = rx->wait(100);
201
202 if (wait_result == fl::RxWaitResult::TIMEOUT) {
203 FL_ERROR("RX channel test FAILED - timeout waiting for data");
204 FL_ERROR(" No edges captured within 100ms");
205 FL_ERROR(" This suggests the RX channel cannot read from GPIO " << pin_rx);
206 return false;
207 }
208
209 // Get captured edges
210 fl::array<fl::EdgeTime, 10> edge_buffer;
211 size_t edge_count = rx->getRawEdgeTimes(edge_buffer);
212
213 if (edge_count < 3) {
214 FL_ERROR("RX channel test FAILED - insufficient edges captured");
215 FL_ERROR(" Expected at least 3 edges, got " << edge_count);
216 FL_ERROR(" Pin loopback may not be working correctly");
217 return false;
218 }
219
220 // Validate timing is reasonable (each edge should be ~10ms apart)
221 bool timing_ok = true;
222 for (size_t i = 0; i < edge_count && i < 3; i++) {
223 uint32_t duration_ms = edge_buffer[i].ns / 1000000;
224 if (duration_ms < 5 || duration_ms > 20) {
225 FL_WARN("WARNING: Edge " << i << " timing unusual: " << duration_ms << "ms (expected ~10ms)");
226 timing_ok = false;
227 }
228 }
229
230 if (timing_ok) {
231 FL_WARN("✓ RX channel test PASSED");
232 FL_WARN(" Captured " << edge_count << " edges");
233 FL_WARN(" Timing appears correct (~10ms per edge)");
234 return true;
235 } else {
236 FL_WARN("✓ RX channel test PASSED (with timing warnings)");
237 FL_WARN(" Captured " << edge_count << " edges");
238 FL_WARN(" Timing may be affected by system load");
239 return true; // Still pass - we got edges
240 }
241}
bool begin(const RxChannelConfig &config) FL_NOEXCEPT
const RxChannelConfig & config() const FL_NOEXCEPT
Definition channel.h:37
A fixed-size array implementation similar to std::array.
Definition array.h:27
constexpr fl::size size() const FL_NOEXCEPT
Definition span.h:458
#define FL_WARN(X)
Definition log.h:276
#define FL_ERROR(X)
Definition log.h:219
@ TIMEOUT
Operation timed out.
Definition rx.h:153
void delayMicroseconds(u32 us)
Delay for a given number of microseconds.
u32 signal_range_max_ns
Definition config.h:20
u32 signal_range_min_ns
Definition config.h:19
void executeToggles(fl::RxChannel &rx, fl::span< const PinToggle > toggles, int pin_tx, uint32_t wait_ms)
Execute pin toggles and initialize RX channel for capture.
Definition test.cpp:36
bool testRxChannelSanity(fl::shared_ptr< fl::RxChannel > rx, int pin_tx)
Test RX channel functionality with low-frequency pattern.
Definition test.cpp:160
bool validateEdgeTiming(fl::span< const fl::EdgeTime > edges, size_t edge_count, fl::span< const PinToggle > expected_pattern, uint32_t tolerance_percent)
Validate captured edge timings against expected pattern.
Definition test.cpp:60
bool verifyJumperWire(int pin_tx, int pin_rx)
Verify jumper wire connection between TX and RX pins.
Definition test.cpp:7