| 58 | } |
| 59 | |
| 60 | bool validateEdgeTiming(fl::span<const fl::EdgeTime> edges, |
| 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); |