| 483 | } |
| 484 | |
| 485 | fl::size LpcSctRxChannel::pollOnce() FL_NOEXCEPT { |
| 486 | #if defined(FASTLED_LPC_RX_SCT) && defined(FL_IS_ARM_LPC_845) |
| 487 | // Drain SCT EVFLAG into the edge buffer. For each event that has |
| 488 | // fired since the last poll: |
| 489 | // * EV0 (rising-edge capture) → read CAP[0]. If we already saw a |
| 490 | // prior edge, the line was LOW from `mPrevTick` to `tick` (since |
| 491 | // this is a rising edge, so it was LOW before). |
| 492 | // * EV1 (falling-edge capture) → read CAP[1]. Line was HIGH from |
| 493 | // `mPrevTick` to `tick`. |
| 494 | // |
| 495 | // The "phase level" labeled into EdgeTime.high is the level the line |
| 496 | // was at DURING the just-completed phase, not the edge direction. |
| 497 | // That matches the decoder's expectation: HIGH duration then LOW |
| 498 | // duration per WS2812 bit. |
| 499 | // |
| 500 | // We deliberately don't clear EVFLAG until AFTER reading CAP[n]; the |
| 501 | // SCT latches a fresh CAP[n] on the *next* matching edge regardless |
| 502 | // of the EVFLAG bit, so the read/W1C order matters only for the |
| 503 | // poll-once semantic (one capture per poll-cycle per event). |
| 504 | |
| 505 | fl::size pushed = 0; |
| 506 | const fl::u32 evflag = sct(kOffEVFLAG); |
| 507 | |
| 508 | if (evflag & 0x1u) { |
| 509 | const fl::u32 tick = sct_cap(0); |
| 510 | sct(kOffEVFLAG) = 0x1u; // W1C |
| 511 | if (mPrevSeen) { |
| 512 | const fl::u32 delta = tick - mPrevTick; // u32 wrap is fine — modulo arithmetic over 32-bit counter |
| 513 | if (mEdges.size() < mCapacity) { |
| 514 | mEdges.push_back(EdgeTime(mLastRising, ticksToNs(delta))); |
| 515 | ++pushed; |
| 516 | } |
| 517 | } |
| 518 | mPrevTick = tick; |
| 519 | mPrevSeen = true; |
| 520 | mLastRising = true; // a rising edge just fired → line was LOW before, HIGH now |
| 521 | } |
| 522 | |
| 523 | if (evflag & 0x2u) { |
| 524 | const fl::u32 tick = sct_cap(1); |
| 525 | sct(kOffEVFLAG) = 0x2u; |
| 526 | if (mPrevSeen) { |
| 527 | const fl::u32 delta = tick - mPrevTick; |
| 528 | if (mEdges.size() < mCapacity) { |
| 529 | mEdges.push_back(EdgeTime(mLastRising, ticksToNs(delta))); |
| 530 | ++pushed; |
| 531 | } |
| 532 | } |
| 533 | mPrevTick = tick; |
| 534 | mPrevSeen = true; |
| 535 | mLastRising = false; |
| 536 | } |
| 537 | |
| 538 | return pushed; |
| 539 | #else |
| 540 | return 0; |
| 541 | #endif |
| 542 | } |
no test coverage detected