WonderWitch/FreyaBIOS/Communication

From WSdev Wiki
Revision as of 20:01, 16 December 2024 by Asie (talk | contribs) (→‎INT $14/AH=$0D - comm_xmodem)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

The Communication (comm) interrupt provides an abstraction layer and helpers for the WonderSwan's serial port.

Interrupts

INT $14/AH=$00 - comm_open

  • AH = $00

Opens the serial port. Note that the baud rate must be set before calling comm_open.

INT $14/AH=$01 - comm_close

  • AH = $01

Closes the serial port.

INT $14/AH=$02 - comm_send_char

  • AH = $02
  • BL = Character (byte) to send.

Return:

  • AX = Return code.

Return codes:

  • 0x0000 - Success
  • 0x8101 - Transfer timeout
  • 0x8102 - Transfer RX overrun
  • 0x8103 - Transfer cancelled

INT $14/AH=$03 - comm_receive_char

  • AH = $03

Return:

  • AX = Character (byte) read (0x0000 - 0xFFFF) or error return code.

INT $14/AH=$04 - comm_receive_with_timeout

  • AH = $03
  • CX = Timeout, in frames (as in comm_set_timeout).

Return:

  • AX = Character (byte) read (0x0000 - 0xFFFF) or error return code.

Unlike comm_receive_char, this function uses an user-provided timeout.

INT $14/AH=$05 - comm_send_string

  • AH = $05
  • DS:DX = Input string to send.

Return:

  • AX = Return code.

INT $14/AH=$06 - comm_send_block

  • AH = $06
  • CX = Buffer size, in bytes.
  • DS:DX = Input buffer to send.

Return:

  • AX = Return code.

INT $14/AH=$07 - comm_receive_block

  • AH = $07
  • CX = Buffer size, in bytes.
  • DS:DX = Buffer to receive bytes to.

Return:

  • AX = Return code.
  • DX = Number of bytes successfully received.

INT $14/AH=$08 - comm_set_timeout

  • AH = $08
  • BX = Receive timeout (in frames; 0xFFFF - wait forever)
  • CX = Send timeout (in frames; 0xFFFF - wait forever)

INT $14/AH=$09 - comm_set_baudrate

  • AH = $09
  • BX = Baud rate (0 = 9600 bps, 1 = 38400 bps).

Only affects newly opened serial port connections.

INT $14/AH=$0A - comm_get_baudrate

  • AH = $0A

Return:

  • AX = Baud rate (0 = 9600 bps, 1 = 38400 bps).

INT $14/AH=$0B - comm_set_cancel_key

  • AH = $0B
  • BX = Cancel key combination.

INT $14/AH=$0C - comm_get_cancel_key

  • AH = $0C

Return:

  • AX = Cancel key combination.

INT $14/AH=$0D - comm_xmodem

  • AH = $0D
  • DS:BX = pointer to XMODEM state structure

Returns:

  • AX = new state (equal to State in the structure)

Usage

To use comm_xmodem, allocate the state structure and set the following values:

  • State = $0001 ("Start")
  • Mode = your mode of choice
  • Maximum number of blocks = the transfer size, in XMODEM blocks
  • Bank, Offset = the transfer source/destination

Next, keep calling comm_xmodem until the "Done" state, or an error, is returned.

The Bank and Offset are auto-incremented by the block size (in bytes) on each successful transfer.

Typical flow - Send
  • Initial: State = Start, Mode = Send
  • State = Negotiate
  • State = Block, Count = 0
  • State = Block, Count = 1
  • ...
  • State = Block, Count = Max
  • State = Close
  • State = Done
Typical flow - Receive
  • Initial: State = Start, Mode = Receive
  • State = Negotiate
  • State = Block, Count = 1
  • State = Block, Count = 2
  • ...
  • State = Block, Count = N
  • State = Close
  • State = Done

Note that in the Receive flow, the Negotiate state returns after receiving the first block, as opposed to before sending the first block.

In both cases, the final block (Max) is not sent/received; if such a value is reached, the "transfer too large" error code is returned.

Data structures

XMODEM state structure
Offset Size Description
$00 2 State (or error code, if bit 15 set)
$02 1 Mode
$03 1 Number of total block transfer retries performed
$04 2 Number of blocks received/sent
$06 2 Maximum number of blocks to receive

Number of blocks to send

$08 2 Size of block, typically 128 bytes
$0A 2 Bank to write to/read from
$0C 2 Offset to write to/read from
$0E 2 ?
XMODEM state values
Value Description
$0001 Start

Set initial values:

  • Number of retries = 0
  • Current block = 0
  • Block size = 128 bytes

Goes to state "Negotiate".

$0002 Negotiate

Also receives the first block.
Goes to state "Block".

$0003 Block

Send: Sends a block and waits for ACK/NAK.
Receive: Sends ACK and receives a block.
Goes to state "Block" (if successful), "Retry Block" (if failed), or "Close" (if transfer complete).

$0004 Retry Block

Same as Block, except NAK is sent in "Receive" mode.

$0005 Close

Finishes the XMODEM transfer.
Goes to state "Done".

$0006 Abort

Treated as an "Invalid state value".

$0007 Done

Treated as an "Invalid state value".

$0008 Erase bank

Goes to state "Block".

$8100 Serial I/O: Busy
$8101 Serial I/O: Transfer timeout
$8102 Serial I/O: Transfer RX overrun
$8103 Serial I/O: Transfer cancelled
$8104 Invalid state value
$8105 XMODEM transfer cancelled
$8106 XMODEM block lost during transfer
$8107 XMODEM transfer too large

XMODEM mode:

7  bit  0
---- ----
.... .?od
       ||
       |+- Direction: 0 = Send, 1 = Receive
       +-- Enable obfuscation