2014 Retrochallenge Winter Warmup, Retrochallenge

2014 Retrochallenge Winter Warmup – Post 02

(This is part two of the chronicle of my 2014 Retrochallenge Winter Warmup submission.  The mediocrity starts here.)

Talking to the 6551

R6551
Si. We make all kind of chips: Tortillas, Papas y Plátanos, Silicio.

In order to send or receive data from the Apple II to the VMusic2 USB controller attached to the A2MP3 card, I need to understand how to communicate with, in this case, the Rockwell International R6551 ACIA (Asynchronous Communication Interface Adapter). This handy integrated circuit was designed to enable serial communications for 6502-based systems.

R6551-ds-cover
Link to R6551 Datasheet

The R6551’s four internal registers on the A2MP3 card are exposed to the Apple II’s 6502 at four addresses. The exact four are dependent on which slot the A2MP3 card is inserted.

Assuming the A2MP3 card is inserted in Slot #3, the addresses and registers are:

Address R6551 Register Description
$C0B0 DATA
  • Contains the current byte being sent to/received from the VMusic2 controller
$C0B1 STATUS
  • When sending a byte, indicates when the current one has been read from the DATA register by VMusic2 controller.
  • When receiving a byte, indicates when the next one is ready for grabbing from the DATA register
$C0B2 COMMAND Used in order to:

  • Set parity
$C0B3 CONTROL Used in order to:

  • Set BAUD rate
  • Set number of stop bits.

The registers provide several other functions, such as setting the clock source, detecting interrupts and errors but I’ve listed only those needed for this project. Regarding the addresses, if the card were in Slot #4, then the addresses would start at $C0C0, Slot #5: $C0D0, and so on.

Initializing the 6551

For the assembly language portion of my project, I started off with Vince Briel’s original code provided with the A2MP3 kit. Especially for the initialization since I’m making no hardware changes. Assuming the datasheet I found applies to the R6551P (and I’m interpreting it correctly), the predefined baud rates max out at 19.2k and Vince is using the external clock to get to 115k.

ACIA_DAT    equ $C0B0          ; 6551 DATA REGISTER
ACIA_SR     equ $C0B1          ; 6551 STATUS REGISTER
ACIA_CMD    equ $C0B2          ; 6551 COMMAND REGISTER
ACIA_CTRL   equ $C0B3          ; 6551 CONTROL REGISTER

;-------------------------------------------------------------------
; INITIALIZE THE 6551 CHIP
;-------------------------------------------------------------------
INIT        LDA     #$10       ; $10 = 1/16x EXTNL CLOCK; 1 STOP BIT
            STA     ACIA_CTRL  ; STORE IN 6551 CONTROL REGISTER
            LDA     #$0B       ; PARITY DISABLED, NO IRQS, DTR READY
            STA     ACIA_CMD   ; STORE IN 6551 COMMAND REGISTER
            RTS

Sending Bytes

To send a byte from the Apple II to the VMusic2 controller via the 6551, the process is:

  1. Poke the payload byte into the 6551’s DATA register
  2. Peek at bit 4 of the STATUS register, if it’s set then send is complete. Otherwise check again.
;-------------------------------------------------------------------
; SEND CHAR TO 6551
;-------------------------------------------------------------------
SENDCH      STA     ACIA_DAT   ; SEND BYTE TO 6551 DATA REG
NOT_EMPTY   LDA     ACIA_SR    ; TEST "TRANSMIT DATA REG EMPTY" FLG
            AND     #$10       ; IN STATUS REG 0=NOT_EMPTY 1=EMPTY
            BEQ     NOT_EMPTY  ; WAIT FOR "EMPTY"
            RTS

Reading Bytes

To read a byte delivered from the VMusic2 card to the Apple II via the 6551, the process is:

  1. Peek at bit 3 of the STATUS register. If it’s set then the reception is complete. Otherwise check again. Give up it’s its been a while.
  2. Peek the payload byte from the DATA register.
;-------------------------------------------------------------------
; READ CHAR FROM 6551
;-------------------------------------------------------------------
READCH      LDX     #$00
NEXTCHAR    CPX     #$E9       ; NO RESP IN A WHILE. ASSUME DONE
            BEQ     BAIL     
            INX
            LDA     ACIA_SR    ; TEST "RECV DATA REG FULL" FLG IN
            AND     #$08       ; STATUS REG (BIT3) 0=NEXTCHAR 1=FULL
            BEQ     NEXTCHAR   ; WAIT UNTIL "FULL"
            LDA     ACIA_DAT   ; GET CHAR FROM 6551
BAIL        RTS

From Here

In the final project code, there’s a little more going on. I currently have subroutines to:

  • Send an arbirary null-terminated string of characters to the VMusic2 controller (for sending Vinculum commands)
  • Send exactly 256 bytes of memory to the VMusic2 controller (for sending one DOS 3.3 sector)

Both of these call the SENDCH routine described above.

I’ll also need subroutines to:

  • Read an arbitrary double-$0D-terminated string from the VMusic2 controller (for retrieving command responses or error messages).
  • Read exactly 256 bytes from the VMusic2 controller (for reading one DOS 3.3 sector)

Next, a work-in-progress demonstration video of me transferring a floppy image to the A2MP3 and a brief explanation of calling Apple’s RWTS (Read Write Track Sector)