Case C - One large image, multi-pass delivery
Two candidates presented for CONOPS-call alignment, neither picked yet. WIP
The actual problem isn't "doesn't fit" - it's control
Images are stored compressed on the satellite by default - that's not a step chosen specifically for this case, it's just the normal state of any image data. A single CFDP transaction can span as many passes as needed via ordinary Freeze/Thaw - the protocol itself imposes no ceiling: freeze/thaw fires unconditionally on every pass boundary with no counter anywhere in its definition, and the one mechanism that could turn "long gap" into a timeout fault - the inactivity timer - is explicitly suspended during a freeze. So a large image, left alone as one ongoing transaction, will eventually complete regardless of size - CFDP itself never breaks this.
The problem this case actually solves is control, not fit: ground/PPS wants to deliberately decide how much of a given pass's bandwidth this transaction consumes, typically because other content (other images, repairs, etc.) is competing for that same pass's capacity. Left alone, the transaction would just opportunistically grab whatever it can each pass, with no coordination against everything else that pass also needs to carry.
The options for getting that control
Two candidates are on the table, both written up here for the CONOPS call - lean toward whichever is cheaper unless there's a real need the other one specifically serves.
The arithmetic that makes both candidates actually plannable
Once an image is compressed, its size is known onboard. X-band's downlink bitrate is a known link parameter (real value still pending Q11). Combined: time needed = compressed size / bitrate - simple arithmetic, computable entirely in advance, no telemetry feedback required. This is what turns "control" from a vague goal into something ground can actually pre-plan:
- For Tiling: knowing a given tile/band's compressed size tells ground exactly how long that piece takes to downlink, which directly feeds the "which tile goes in which pass" scheduling decision.
- For Pause/Resume's byte-threshold extension: ground doesn't have to guess at a byte count - it computes the threshold as bitrate × (time allocated to this Tx in this pass), using the same known quantities. "15MB in Pass 1" and "6MB in Pass 2" aren't arbitrary numbers ground picks; they fall out of how much pass time ground decides to give this transaction, converted through a known rate.
This is the same real number (X-band bitrate) already needed for Q11 - Case C just gives it a second, more granular use beyond Q5's original capacity-budget context.
Candidate 1 - Tiling (split into multiple files)
Split the image into multiple smaller files before any downlink activity, minimizing file count, along boundaries meaningful enough that each chunk is independently useful even on its own - not an arbitrary byte-count slice. Each resulting file is its own ordinary CFDP transaction, closing independently. This isn't a new mechanism - it's exactly Case A's already-solved multi-transaction dispatch pattern, just spread deliberately across multiple passes.
What we don't actually know, and shouldn't assert as settled: whether splitting by band is the right choice for "each chunk independently meaningful." That rests on whether a single band alone has standalone analytical value for how this data actually gets used downstream - we haven't confirmed that, so band-wise is a plausible candidate, not a recommendation. Tile-wise (spatial) splitting remains equally plausible and needs the same confirmation before either gets picked.
Rendered from diagram/case_c_tiling.puml (PlantUML)
How do we actually get a piece out of compressed storage?
Since the image is already compressed as a whole by default, splitting it isn't free - genuinely open, a few candidate approaches, per CONOPS:
- Decompress the full image, extract the needed band/tile, then re-compress just that piece before sending it as its own file. Costs onboard decompress+recompress cycles per tile.
- Store the image in a pre-decided split layout from the start (e.g., each band compressed separately at capture/processing time, before it's ever combined into one blob) - so a piece is already separately accessible and compressed, no decompress/recompress needed later, at the cost of losing whatever compression efficiency comes from compressing bands together.
- Any other way that fits - not settled, this is a real design question Tiling introduces that Pause/Resume never has to answer.
Which approach is workable depends on onboard compute budget and the actual compression scheme in use - outside what this project can settle on its own.
Candidate 2 - Pause/Resume (single file, sequential)
Keep one single file/transaction for the compressed image, even if it doesn't fit one pass. The simplest version needs literally nothing beyond ordinary Freeze/Thaw. If ground additionally wants finer timing control - a deliberate stand-down mid-pass, not just waiting for the next natural pass boundary - that uses CFDP's own already-defined Suspend/Resume primitives.
Suspend.requestsaves the transaction's transmission progress - just the ordinary sequential send cursor, no byte-range bookkeeping needed.Resume.requestcontinues transmission of "Metadata PDU, file segments, and EOF PDU" from exactly where it left off - sequential, no offset selection, no gaps introduced.- Neither primitive has any byte-count or offset parameter - this specific ceiling is real, straight from the book: Resume has no way to say "resume, but only for N bytes then stop." Left to CFDP's own primitives alone, the amount sent per window is just whatever throughput happens between one Suspend and the next Resume - not a pre-plannable exact quantity.
Suspend.request locally once it's hit. This isn't a CFDP protocol feature; it's application logic layered on top, the exact same pattern already used for the cheap Suspend/Resume shortcut.
Result: ground can pre-plan an exact quantity per pass this way (e.g., "15MB of Tx X in Pass 1, 6MB of Tx X plus other content in Pass 2") - not arbitrary numbers, but the direct output of the size/bitrate arithmetic above (bitrate × time allocated to this Tx = byte threshold to command). Genuinely useful for exactly the kind of mixed-content, multi-pass bandwidth sharing this case is actually about. What this still cannot do: pick a specific non-sequential byte range out of order - the payload app is still just reading/sending the file forward from wherever it is; only Tiling gets you out-of-order or independently-meaningful-on-arrival chunks. Quantity per pass, yes; which specific bytes, still no.
Only Option B can do this - Option A cannot: CFDP's native Remote Suspend Request message has a fixed format - just source entity ID and transaction sequence number, no room for a byte-count field. Since it's a CCSDS-defined Reserved Message, we can't add one. Option B's command is ours, not CFDP's, so extending it with a threshold parameter costs nothing - one more reason favoring Option B below.
One more nuance this surfaces: once the payload app locally invokes Suspend.request to stop early mid-pass, the transaction becomes formally suspended - not just frozen. And "thawing transmission for a suspended transaction shall have no effect whatsoever." So the ordinary automatic pass-boundary thaw will not wake this back up on its own - something has to explicitly invoke Resume.request for each subsequent controlled pass, not just the initial Suspend.
Correction: this does not mean ground has to send a live command every single pass. If the whole multi-pass plan (every pass's threshold, including which passes to skip and when to resume) is loaded onto the satellite once, upfront, the payload app can invoke both Suspend.request and Resume.request locally, on its own, for every subsequent pass - driven by its own pass-boundary observations, its own byte-progress tracking, and (for something like "wait for another Tx to finish first") locally-observable conditions it can evaluate onboard without any ground involvement at all. Ground's job is the one upfront schedule-loading command; everything after that is the payload app executing its own plan. See the worked example below.
Rendered from diagram/case_c_5pass_mixed_schedule.puml (PlantUML)
Rendered from diagram/case_c_pause_resume.puml (PlantUML)
Open dependency: this only matters for the reactive case - when ground wants to suspend/resume something that wasn't already part of a pre-loaded plan (an emergency, a mid-stream repriority, correcting a plan that turned out wrong - Case B/D territory). For the nominal, fully-pre-planned execution above, this doesn't come up at all - the payload app handles it autonomously. Still needs Q7.12 answered for the reactive case though - see the detailed breakdown below.
Q7.12 - reactively triggering suspend/resume for something NOT in a pre-loaded plan
Scope check first: if the whole plan was pre-loaded upfront (the normal case above), neither option below is needed at all - the payload app just executes its own plan. This section is specifically about ground wanting to intervene live, mid-stream, on something the original plan didn't cover. Two real options for that, verified against the book, both diagrammed:
Option B - cheap ground-side shortcut
A plain, non-CFDP command - "Suspend Tx X" / "Resume Tx X" - riding the same ordinary-PUS-APID path already established in the TC vs X-band concept. The command processor delivers it to the onboard payload app, which locally invokes Suspend.request/Resume.request on the CFDP entity - the underlying CFDP effect is identical to Option A's; only how the instruction gets there differs. Cost: 2 simple commands, no new CFDP transactions, no role reversal - PLDP stays receive-only throughout, exactly as everywhere else in this project.
Rendered from diagram/case_c_suspend_shortcut.puml (PlantUML)
The trade-off: Option A gets a built-in, protocol-level confirmation (the Remote Suspend/Resume Response message actually tells you it worked). Option B gets no such confirmation for Suspend specifically - ground would have to infer it from telemetry (File Data PDUs stopping), a weak signal since a pass simply ending looks identical from ground's side. Resume is less of a problem either way - it mostly self-confirms, since ground directly sees File Data flowing again once it does.
Comparison, for the call
| Tiling | Pause/Resume | |
|---|---|---|
| New mechanism needed | None (reuses Case A) | None (reuses existing CFDP primitives) |
| Extra cost | Splitting-out-of-compressed-storage mechanics, splitting strategy, application-layer reassembly | Nothing extra - no compressed-storage-splitting problem to solve |
| Partial/early value | Yes - each piece usable on arrival | No - only once fully complete |
| Exact quantity per pass | Yes, at whole-piece granularity | Yes, with the byte-threshold extension (PAVI) |
| Non-sequential/out-of-order selection | Yes, at band granularity | No |
If there's no real need for partial/early value per band or for picking a specific non-sequential region, Pause/Resume (with the threshold extension) covers exact per-pass quantity control at much lower cost. Tiling only earns its extra cost if per-band partial value or true out-of-order selection genuinely matters.