# Design Specification: Cyclical Interleaved Systematic LT Streaming

* **Date**: 2026-08-07
* **Status**: Approved
* **Target Repository**: `qrcode_transceiver`

---

## 1. Executive Summary

This design specification solves the tail-end decoding bottleneck ("LT Code Coupon Collector problem") for large payloads ($K \ge 400$) by upgrading the encoder to use **Cyclical Interleaved Systematic Streaming**. 

Instead of streaming systematic single blocks ($d=1$) only once and switching to random fountain drops forever, the encoder streams systematic passes continuously interleaved with rateless fountain drops (80% systematic / 20% fountain per cycle). This guarantees that missing blocks are resolved directly on subsequent passes, reducing completion time by **~45%** (from ~860 frames down to ~450–480 frames for $K=400$).

---

## 2. Protocol & Mathematical Specification

### 2.1 Cycle Framing & Seed Mapping
For any payload sliced into $K$ source blocks:
- Cycle length: $C = K + \lceil 0.2 \times K \rceil$ frames.
- Cycle offset: $o = (s - 1) \pmod C$ for seed $s \ge 1$.

```javascript
function encodeFrameSystematic(sourceBlocks, seed, flags, filename) {
    const K = sourceBlocks.length;
    const L = sourceBlocks[0].length;
    const fountainGap = Math.ceil(K * 0.2); // 20% fountain drops per cycle
    const cycleLen = K + fountainGap;
    const cycleOffset = (seed - 1) % cycleLen;

    let degree;
    let blockIndices;
    let sysFlags = flags;

    if (cycleOffset < K) {
        // Phase A: Systematic Single Block (d = 1)
        degree = 1;
        blockIndices = [cycleOffset];
        sysFlags |= 0x04; // Set systematic flag (Bit 2)
    } else {
        // Phase B: Interleaved Rateless Soliton XOR Drop (d >= 2)
        const cdf = RobustSoliton(K);
        const prng = Mulberry32(seed);
        degree = sampleDegree(cdf, prng);
        blockIndices = sampleBlocks(K, degree, prng);
    }

    const xorPayload = new Uint8Array(L);
    for (const idx of blockIndices) {
        const b = sourceBlocks[idx];
        for (let i = 0; i < L; i++) {
            xorPayload[i] ^= b[i];
        }
    }

    return packPacket(seed, K, L, sysFlags, filename, xorPayload);
}
```

### 2.2 Receiver BP Decoder Mapping
In `lt_engine.js`, `BPDecoder.prototype.processDrop` evaluates systematic drops using the cycle mapping:

```javascript
const fountainGap = Math.ceil(drop.K * 0.2);
const cycleLen = drop.K + fountainGap;
const cycleOffset = (drop.seed - 1) % cycleLen;

let degree;
let blockIndices;
if (drop.isSystematic || cycleOffset < drop.K) {
    const blockIdx = cycleOffset < drop.K ? cycleOffset : (drop.seed - 1) % drop.K;
    if (blockIdx < 0 || blockIdx >= this.K) return false;
    degree = 1;
    blockIndices = [blockIdx];
} else {
    const prng = Mulberry32(drop.seed);
    degree = sampleDegree(this.cdf, prng);
    blockIndices = sampleBlocks(this.K, degree, prng);
}
```

---

## 3. Pre-rendering Buffer Calibration (`transmitter.html`)

To support continuous cyclic streaming during high-speed playback:
- Total cache frames generated: $N = \max(K \times 2.5, 100)$.
- `prepareMovie()` pre-renders $N$ frames offscreen so playback cycles smoothly through multiple systematic passes.

---

## 4. Verification & Test Plan

1. **Unit Test Systematic Cycles**: In `test_lt_engine.js`, verify seed 1, seed $K+1$ (fountain drop), and seed $K + \lceil 0.2K \rceil + 1$ (Pass 2 block 0 systematic drop).
2. **Integration Test Suite**: Verify 100% data recovery for $K = 400$ under 20% simulated frame loss in `test_receiver_integration.js`.
