mirror of
https://github.com/alfishe/amiga-bootcamp.git
synced 2026-06-12 16:16:28 +00:00
10_devices: - serial.md: expanded with DB-25 pinout, custom chip UART registers, baud rate calculation table, open/configure/read/write patterns, serial debugging (KPrintF/Sushi) - input.md: expanded with handler chain architecture diagram, InputEvent struct, event classes table, qualifier bits, custom handler with key remapping, event consumption/blocking, synthetic event injection, Commodities Exchange Updated indexes: - 07_dos/README.md — enriched descriptions for all files - 10_devices/README.md — enriched descriptions for all files
130 lines
3.6 KiB
Markdown
130 lines
3.6 KiB
Markdown
[← Home](../README.md) · [Devices](README.md)
|
|
|
|
# serial.device — UART and RS-232 Communication
|
|
|
|
## Overview
|
|
|
|
`serial.device` provides access to the Amiga's built-in UART (Universal Asynchronous Receiver/Transmitter) for RS-232 serial communication. The hardware UART is implemented using **CIA-B** shift registers and custom chip DMA. Serial I/O is fundamental for debugging (serial console), modem communication, MIDI, and inter-machine networking.
|
|
|
|
---
|
|
|
|
## Hardware
|
|
|
|
### Serial Port Pins (DB-25)
|
|
|
|
| Pin | Signal | Direction | Description |
|
|
|---|---|---|---|
|
|
| 2 | TxD | Output | Transmit data |
|
|
| 3 | RxD | Input | Receive data |
|
|
| 4 | RTS | Output | Request to send (active low) |
|
|
| 5 | CTS | Input | Clear to send (active low) |
|
|
| 6 | DSR | Input | Data set ready |
|
|
| 7 | GND | — | Signal ground |
|
|
| 8 | CD | Input | Carrier detect |
|
|
| 20 | DTR | Output | Data terminal ready |
|
|
|
|
### Custom Chip Registers
|
|
|
|
| Register | Address | Description |
|
|
|---|---|---|
|
|
| `SERDAT` | `$DFF030` | Serial data write (transmit) — 9 bits: stop bit + 8 data |
|
|
| `SERDATR` | `$DFF018` | Serial data read (receive) — status + received byte |
|
|
| `SERPER` | `$DFF032` | Serial period (baud rate divider) |
|
|
| `ADKCON` | `$DFF09E` | UARTBRK bit for break signal |
|
|
|
|
### Baud Rate Calculation
|
|
|
|
```c
|
|
/* SERPER value = (system_clock / baud_rate) - 1 */
|
|
/* PAL system clock for serial = 3,546,895 Hz */
|
|
/* NTSC = 3,579,545 Hz */
|
|
|
|
#define SERIAL_CLOCK_PAL 3546895
|
|
#define SERIAL_CLOCK_NTSC 3579545
|
|
|
|
UWORD serper_from_baud(ULONG baud, BOOL isPAL) {
|
|
return (isPAL ? SERIAL_CLOCK_PAL : SERIAL_CLOCK_NTSC) / baud - 1;
|
|
}
|
|
```
|
|
|
|
| Baud Rate | SERPER (PAL) | SERPER (NTSC) |
|
|
|---|---|---|
|
|
| 1200 | 2955 | 2982 |
|
|
| 2400 | 1477 | 1491 |
|
|
| 9600 | 368 | 372 |
|
|
| 19200 | 184 | 185 |
|
|
| 31250 (MIDI) | 112 | 113 |
|
|
| 57600 | 60 | 61 |
|
|
| 115200 | 29 | 30 |
|
|
|
|
---
|
|
|
|
## Using serial.device
|
|
|
|
### Open and Configure
|
|
|
|
```c
|
|
struct MsgPort *serialPort = CreateMsgPort();
|
|
struct IOExtSer *serialReq = (struct IOExtSer *)
|
|
CreateIORequest(serialPort, sizeof(struct IOExtSer));
|
|
|
|
/* Open serial.device unit 0: */
|
|
BYTE err = OpenDevice("serial.device", 0,
|
|
(struct IORequest *)serialReq, 0);
|
|
|
|
/* Configure: */
|
|
serialReq->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
|
|
serialReq->io_Baud = 9600;
|
|
serialReq->io_ReadLen = 8; /* 8 data bits */
|
|
serialReq->io_WriteLen = 8;
|
|
serialReq->io_StopBits = 1;
|
|
serialReq->io_RBufLen = 4096; /* receive buffer size */
|
|
serialReq->IOSer.io_Command = SDCMD_SETPARAMS;
|
|
DoIO((struct IORequest *)serialReq);
|
|
```
|
|
|
|
### Write Data
|
|
|
|
```c
|
|
serialReq->IOSer.io_Command = CMD_WRITE;
|
|
serialReq->IOSer.io_Data = "Hello Serial\r\n";
|
|
serialReq->IOSer.io_Length = 14;
|
|
DoIO((struct IORequest *)serialReq);
|
|
```
|
|
|
|
### Read Data
|
|
|
|
```c
|
|
/* Check how many bytes are waiting: */
|
|
serialReq->IOSer.io_Command = SDCMD_QUERY;
|
|
DoIO((struct IORequest *)serialReq);
|
|
ULONG waiting = serialReq->IOSer.io_Actual;
|
|
|
|
if (waiting > 0) {
|
|
serialReq->IOSer.io_Command = CMD_READ;
|
|
serialReq->IOSer.io_Data = buffer;
|
|
serialReq->IOSer.io_Length = waiting;
|
|
DoIO((struct IORequest *)serialReq);
|
|
/* buffer now contains received data */
|
|
}
|
|
```
|
|
|
|
### Serial Debugging
|
|
|
|
Many developers use a null-modem cable to a terminal for kernel debugging:
|
|
|
|
```c
|
|
/* Kprintf — ROM debug output via serial (ROMTags/exec): */
|
|
/* This bypasses serial.device entirely — writes directly to SERDAT */
|
|
void KPrintF(const char *fmt, ...); /* available in debug ROMs */
|
|
|
|
/* Sushi/Sashimi — capture serial debug output on another Amiga */
|
|
```
|
|
|
|
---
|
|
|
|
## References
|
|
|
|
- NDK39: `devices/serial.h`
|
|
- HRM: *Amiga Hardware Reference Manual* — Serial Port chapter
|
|
- ADCD 2.1: serial.device autodocs
|