* @brief Check if symbol is a gap pulse (transmission gap like PARLIO DMA gap) * @param symbol RMT symbol to check * @param timing Timing thresholds * @param ns_per_tick Cached nanoseconds per tick * @return true if symbol is gap pulse (long low duration longer than reset but * within gap tolerance) * * Gap pulses are longer than normal bit LOW times but shorter than * gap_tolerance_ns. Th
| 138 | * errors. Common in PARLIO TX due to DMA transfer gaps (~20us). |
| 139 | */ |
| 140 | inline bool isGapPulse(RmtSymbol symbol, const ChipsetTiming4Phase &timing, |
| 141 | u32 ns_per_tick) { |
| 142 | // No gap tolerance configured - treat as error |
| 143 | if (timing.gap_tolerance_ns == 0) { |
| 144 | return false; |
| 145 | } |
| 146 | |
| 147 | // Cast RmtSymbol to rmt_symbol_word_t to access bitfields |
| 148 | const auto rmt_sym = fl::bit_cast<rmt_symbol_word_t>(symbol); |
| 149 | |
| 150 | // Convert durations to nanoseconds |
| 151 | u32 duration0_ns = ticksToNs(rmt_sym.duration0, ns_per_tick); |
| 152 | u32 duration1_ns = ticksToNs(rmt_sym.duration1, ns_per_tick); |
| 153 | |
| 154 | // Gap pulse characteristics: |
| 155 | // - Long LOW duration (longer than normal bit LOW timing) |
| 156 | // - Shorter than reset threshold (not a frame reset) |
| 157 | // - Within gap_tolerance_ns |
| 158 | // - Should have level=0 (low) for the long duration |
| 159 | // |
| 160 | // The longest normal LOW pulse is t0l_max_ns, so gap must be longer than |
| 161 | // that |
| 162 | |
| 163 | // Check duration1 (most common case - gap at end of bit sequence) |
| 164 | if (rmt_sym.level1 == 0 && duration1_ns > timing.t0l_max_ns && |
| 165 | duration1_ns <= timing.gap_tolerance_ns) { |
| 166 | FL_WARN("isGapPulse DETECTED: duration1=" << duration1_ns << "ns (level1=0), t0l_max=" |
| 167 | << timing.t0l_max_ns << "ns, gap_tolerance=" << timing.gap_tolerance_ns << "ns"); |
| 168 | return true; |
| 169 | } |
| 170 | |
| 171 | // Check duration0 (less common - gap at start) |
| 172 | if (rmt_sym.level0 == 0 && duration0_ns > timing.t0l_max_ns && |
| 173 | duration0_ns <= timing.gap_tolerance_ns) { |
| 174 | FL_WARN("isGapPulse DETECTED: duration0=" << duration0_ns << "ns (level0=0), t0l_max=" |
| 175 | << timing.t0l_max_ns << "ns, gap_tolerance=" << timing.gap_tolerance_ns << "ns"); |
| 176 | return true; |
| 177 | } |
| 178 | |
| 179 | return false; |
| 180 | } |
| 181 | |
| 182 | /** |
| 183 | * @brief Decode single symbol to bit value |
no test coverage detected