Skip to content

Apple //c serial printer integration + per-port device selection #87

Description

@relmer

Bridge the //c's built-in serial port to the printer pipeline, and add a Hardware-tab serial endpoint selector. Deferred to its own plan because it can only be built/validated after both spec 015 and spec 016 land — see Dependencies.

Why this is its own plan

  • Untestable until both land. Acceptance requires spec 015's printer pipeline on master AND a bootable Apple //c (spec 016). It is inherently last-mile.
  • It refactors 015's code (the ring-ownership hoist restructures PrinterCard/PrinterByteRing). Best done once 015 is settled on master, not while it is in flight — avoids two efforts editing the same files.
  • Keeps both specs' "done" crisp. 016 delivers a faithful //c (boots, phantom slots, disk, mouse, serial I/O via the 6551 ACIA + loopback/file endpoints — all real and testable standalone). 015 delivers the platform-neutral printer pipeline + the //e parallel front door. This plan is the bridge.

Scope

A. Serial printer front door (reuse 015's finished pipeline)

The //c has no parallel card — its printer rides serial port 1 into 015's card-agnostic pipeline (behind PrinterByteRing). Full brief: specs/016-apple2c-support/serial-printer-integration.md.

  • Hoist PrinterByteRing (+ its PrinterJob) out of PrinterCard into a machine-level PrinterSink owned at the EmulatorShell/machine level; the //e PrinterCard and the //c serial endpoint both target the shared ring; PrinterWorker drains the sink. Mechanical hoist -- no pipeline logic change. Regression: the //e parallel Print Shop path is unaffected.
  • Add AciaPrinterEndpoint (IAciaEndpoint): TX bytes -> PrinterSink ring; RX = "printer ready" stub (confirm against Print Shop's serial driver if it stalls).
  • Bind //c serial port 1 -> AciaPrinterEndpoint in Apple2c.json (port 2 stays comms/loopback); no parallel-printer slot row on the //c.
  • Unit test: drive AciaPrinterEndpoint with the reference capture (specs/016-apple2c-support/reference/printshop-color-testpage.bin, a real 2097-byte Print Shop Color stream) and assert the bytes land in the shared ring / produce the expected ImageWriterInterpreter events. Mocked, no real serial (Test Isolation).

B. Serial endpoint selector (Hardware settings tab)

Today the Hardware tab is only an enable/disable device tree (HardwareEntry in SettingsPanelState) -- the endpoint on a serial port is fixed in JSON. Add a per-port row pattern (a selector + a conditional detail area) and use it for the two serial ports:

  • Model: extend SettingsPanelState/HardwareEntry so a serial-port entry carries its selectable endpoint options + current selection (beyond the enable/disable checkbox).
  • UI: HardwarePage renders a per-port endpoint dropdown for the serial ports (reuse DxuiDropdown); unit-test via HardwarePageTests/SettingsPanelStateTests.
  • Persist the selection in UserConfigStore and apply at machine build -- bind the chosen IAciaEndpoint (printer / terminal loopback / raw file / none) to each port, overriding the Apple2c.json default.
  • Serial port 1: ImageWriter II printer / terminal loopback / raw-file / disconnected. Serial port 2: modem loopback / raw-file / disconnected.

Not in scope here (owned by spec 016, via their existing UI homes)

The //c has other connectable ports, but they are not serial endpoints and are handled in 016:

  • External disk (DB-19) -> a Connected / Not connected toggle that reveals the existing drive-mount widget. Owned by 016 IWM (Phase 7 / FR-014a). It reuses the same per-port row pattern this issue introduces.
  • Mouse/joystick (DB-9) -> the mouse and joystick share one physical port, so it is a single selection folded into the existing InputMappingMode (Off/Joystick/Paddle + new Mouse), shown as a skeuomorphic device selector. Owned by 016 mouse (Phase 6 / FR-013a). Not a Hardware-tab row.
  • Video expansion (DB-15) -> a display output mode (composite / RGB / mono), a Display-tab concern, not a device attachment.

Acceptance

  • A //c boots The (New) Print Shop; printing a page produces a non-empty raster via the serial port (not the raw file endpoint), and File -> Finish Printing (Eject Paper) yields a PNG equivalent to the //e parallel path for the same document (same interpreter/renderer).
  • The //e parallel path is unaffected by the ring-ownership hoist (regression: //e Print Shop still prints).
  • The user can switch serial port 1 between printer / terminal / file / disconnected in the Hardware settings tab; the choice persists per machine and drives the actual endpoint binding.
  • New/changed components are unit-tested with mocked I/O per the constitution.

Dependencies

  • Spec 015 (printer support) merged to master -- provides PrinterByteRing, ImageWriterInterpreter, raster/PNG stages, PrinterJob/PrinterWorker, and the reference capture. (CassoEmuCore/Devices/Printer/, Casso/Print/.)
  • Spec 016 (Apple //c support) -- provides the bootable //c profile (Apple2c.json), the dual Acia6551 + serial ports, and IAciaEndpoint. This work reuses 016's ACIA/serial; only the printer bridge + serial endpoint selector are deferred here.

References

  • Handoff brief: specs/016-apple2c-support/serial-printer-integration.md
  • Reference capture fixture: specs/016-apple2c-support/reference/printshop-color-testpage.bin
  • Spec 016: specs/016-apple2c-support/{spec.md (FR-011b/c deferred here; FR-013a mouse selector; FR-014a external-drive toggle), tasks.md, plan.md}
  • Spec 015 (printer pipeline): specs/015-printer-support/
  • Sibling deferred machine work: Add Apple //e Enhanced machine profile (65C02 + enhanced ROMs + MouseText) #86 (Apple //e Enhanced)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestpriority: highMarquee end-user impact (end-user-value triage)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions