// Serial communications add-on -- portable RS-232 byte streams. // // OPTIONAL add-on: this header is NOT pulled in by . Include it // explicitly. An app that never references jlSerial* pays nothing -- the // linker drops the module (archive granularity / IIgs dead-strip). // // One byte-stream API spans every port; the per-port HAL hides the very // different hardware: // Apple IIgs -- direct Zilog 8530 SCC (modem/printer ports) or a 6551 // Super Serial Card in a slot; polled, drained on // jlSerialPoll(). // DOS -- 8250/16550 UART on a COM port; interrupt-driven RX ring. // Amiga -- serial.device (async exec IO); the OS buffers RX. // Atari ST -- BIOS Aux (Modem port) via XBIOS Rsconf; TOS buffers RX. // // Model: non-blocking + buffered. Received bytes accumulate in a background // ring (a hardware IRQ on DOS, the OS on Amiga/ST, or jlSerialPoll() on the // IIgs); jlSerialRead / jlSerialAvailable never block. Call jlSerialPoll() // once per game frame -- it is a no-op where the IRQ/OS already fills the // ring, and the hardware drain where it does not, so calling it every frame is // always correct. Transmit is a bounded poll. // // A failed jlSerialOpen is non-fatal: it returns false and every other call is // a safe no-op (Available 0, Read 0), exactly like a failed audio init. #ifndef JOEYLIB_SERIAL_H #define JOEYLIB_SERIAL_H #include "platform.h" #include "types.h" // Which physical interface to open. The IIgs is the oddball with three: // JL_SERIAL_MODEM -- IIgs modem port (SCC channel A). Elsewhere == DEFAULT. // JL_SERIAL_PRINTER -- IIgs printer port (SCC channel B). Only the IIgs has // a second built-in port; elsewhere == DEFAULT. // JL_SERIAL_SLOT -- a card/port selected by jlSerialConfigT.unit: IIgs // Super Serial Card slot (1..7); DOS COM number (1..4); // Amiga serial.device unit. // JL_SERIAL_DEFAULT -- the platform's natural RS-232 port (IIgs modem, DOS // COM1, ST Modem port, Amiga unit 0). typedef enum { JL_SERIAL_DEFAULT = 0, JL_SERIAL_MODEM, JL_SERIAL_PRINTER, JL_SERIAL_SLOT } jlSerialDeviceE; typedef enum { JL_SERIAL_PARITY_NONE = 0, JL_SERIAL_PARITY_ODD, JL_SERIAL_PARITY_EVEN } jlSerialParityE; typedef enum { JL_SERIAL_FLOW_NONE = 0, // no handshaking JL_SERIAL_FLOW_RTSCTS, // hardware RTS/CTS JL_SERIAL_FLOW_XONXOFF // software XON/XOFF } jlSerialFlowE; // Line configuration. `unit` disambiguates JL_SERIAL_SLOT (see jlSerialDeviceE) // and is ignored for the other devices. typedef struct { uint32_t baud; // 300 .. 115200 (each port clamps to what it supports) uint8_t dataBits; // 5 .. 8 uint8_t stopBits; // 1 or 2 jlSerialParityE parity; jlSerialFlowE flow; uint8_t unit; // JL_SERIAL_SLOT: IIgs slot 1..7 / DOS COM 1..4 / Amiga unit } jlSerialConfigT; // Open + configure the port. Only one port is open at a time; a second // jlSerialOpen without a jlSerialClose fails. Returns false (non-fatal) if the // port cannot be opened or the platform has no serial support -- every other // call then no-ops. bool jlSerialOpen(jlSerialDeviceE device, const jlSerialConfigT *config); // Close the open port and release its resources. Safe to call when not open. void jlSerialClose(void); // Pump the RX/TX buffers. Call once per game frame. No-op where a hardware IRQ // or the OS already services the port (DOS/Amiga/ST); drains the hardware FIFO // into the RX ring where it does not (IIgs). Calling it every frame is always // correct. void jlSerialPoll(void); // Bytes waiting in the RX buffer, readable now without blocking. uint16_t jlSerialAvailable(void); // Copy up to `max` received bytes into `buf`; returns the count copied // (0 .. max). Never blocks. uint16_t jlSerialRead(uint8_t *buf, uint16_t max); // Send `len` bytes; returns the count accepted (may be < len if a flow- // controlled peer or a full transmit path stalls). Transmit is a bounded poll. uint16_t jlSerialWrite(const uint8_t *buf, uint16_t len); // Single-byte convenience. jlSerialReadByte returns -1 when none is ready. bool jlSerialWriteByte(uint8_t b); int16_t jlSerialReadByte(void); // Discard any buffered received bytes. void jlSerialFlush(void); #endif