******************************************************************************
*
* THIS SOURCE CODE IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT
* AND/OR MODIFY IT WITHOUT RESTRICTION.
*
* THIS SOURCE CODE IS DISTRIBUTED IN THE HOPE THAT IT WILL BE
* USEFUL, BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* CREDITS:
*   THE INSPIRATION FOR THESE ROUTINES CAME FROM THE COMM6
*   PROGRAM BY BILL YAKOWENKO. THE COMM6 SOURCE CODE WAS
*   LAST KNOWN TO RESIDE HERE:
*
*      <http://www.cs.unc.edu/~yakowenk/coco/pgms/comm6.lst>
*
* REVISION HISTORY:
*    APR-30-2007    - REVISED TIMING DATA TO REFLECT THE ACTUAL
*                     0.89488625 MHz FREQUENCY USED IN THE COCO.
*                   - MINOR CHANGES TO THE CODE FLOW IN THE TRANSMITTER.
*                   - THE TRANSMITTER NO LONGER PRESERVES THE Y REGISTER.
*
*    APR-27-2007    - ADDED SETDP DIRECTIVES TO PREVENT ASSEMBLER BARFING.
*
*    APR-26-2007    - INITIAL PUBLIC RELEASE.
*
*-----------------------------------------------------------------------------
*
* THE SUBROUTINES IN THIS FILE PROVIDE GENERAL PURPOSE SERIAL I/O THROUGH
* THE TRS-80 COLOR COMPUTER'S BIT-BANGER PORT AT 57600 / 115.2K BAUD.
*
* ON A COCO 1 OR 2 THESE ROUTINES ONLY SUPPORT 57600 BAUD RUNNING AT
* THE STANDARD 0.89 MHZ SPEED.  WHEN RUN ON A COCO 3, THE ROUTINES
* OPERATE AT EITHER 57600 OR 115.2K BAUD BY SETTING THE CPU RATE TO
* 0.89 MHZ OR 1.78 MHZ RESPECTIVELY.
*
* DUE TO THE TIMING CRITICAL NATURE OF THIS CODE, IT IS ESSENTIAL THAT
* ANY ASSEMBLER USED TO BUILD IT WILL PRODUCE THE EXPECTED OBJECT CODE.
* IN PARTICULAR, THE '<' CHARACTER IS USED TO PREFIX OPERANDS THAT
* REQUIRE DIRECT ADDRESSING, AND INDEXED OPERANDS WITH NO OFFSET MUST
* USE A ZERO-OFFSET POST-BYTE.
*
* THE CODE SHOULD FUNCTION ON BOTH 6809 AND 6309 PROCESSORS, SO LONG AS
* THE 6309 IS NOT RUNNING IN NATIVE MODE (REDUCED CYCLES).
*
* THE CODE IS COMPLETELY POSITION-INDEPENDENT, AND DOES NOT USE ANY ROM
* ROUTINES OR SYSTEM VARIABLES.
*
******************************************************************************


          ORG       $0000     ; POSITION-INDEPENDENT - CAN BE LOADED ANYWHERE


******************************************************************************
* COCO 57600 / 115.2K BAUD BIT-BANGER RECEIVE
******************************************************************************
*
* THIS SUBROUTINE WILL WAIT FOR A SPECIFIED TIMEOUT PERIOD
* UNTIL A START-BIT APPEARS ON THE BIT-BANGER INPUT. IF A
* START-BIT IS DETECTED, THEN A LOOP IS EXECUTED TO READ
* THE SERIAL DATA. THE DATA FORMAT MUST BE:
*   1 START-BIT, 8 DATA BITS, NO PARITY, 1..2 STOP-BITS.
*
* THE RECEIVE LOOP TERMINATES WHEN:
*   - THE MAXIMUM NUMBER OF BYTES REQUESTED HAVE BEEN RECEIVED.
*   - A PERIOD OF APPROX 7.5 MS (3.25 MS) ELLAPSES WITHOUT A NEW START-BIT
*   - A FRAMING ERROR IS DETECTED.
*
* THE SUBROUTINE ALSO RETURNS A SIXTEEN-BIT CHECKSUM OF THE
* DATA RECEIVED. THIS CHECKSUM IS CALCUALTED BY STARTING WITH
* ZERO AND THEN ADDING IN THE UNSIGNED 8-BIT VALUE OF EACH
* DATA BYTE AS IT IS RECEIVED.
*
* IF YOU PASS 0 IN EITHER THE REQUEST COUNT OR TIMEOUT PARAMETERS
* THEN THE SUBROUTINE RETURNS WITHOUT DOING ANYTHING.
*
*  ON ENTRY:
*    X = ADDRESS OF THE RECEIVE BUFFER
*    Y = REQUEST COUNT (MAXIMUM NUMBER OF BYTES TO RECEIVE)
*    D = TIMEOUT VALUE (133 = APPROX ONE SECOND @ 0.89 MHz)
*
*  ON EXIT:
*    Y = DATA CHECKSUM
*    D = ACTUAL NUMBER OF BYTES RECEIVED
*    X AND U ARE PRESERVED
*    CC.CARRY IS SET IF A FRAMING ERROR WAS DETECTED
*

READBIT   EQU       $FF22               ; ADDRESS OF THE BIT-BANGER INPUT

* LOCAL STACK VARIABLES (OFFSETS FROM S)
TIMEOUT   EQU       0         ; TIMEOUT COUNTER (VALUE IS CRITICAL FOR TIMING)
BUFSTRT   EQU       2         ; BUFFER START ADDRESS
CHKSUM    EQU       4         ; CHECKSUM VALUE
LOCLSZ    EQU       6         ; TOTAL SIZE OF LOCAL STACK VARIABLES

RECV56K   ANDCC     #$FE                ; CLEAR CARRY FLAG (NO FRAMING ERROR)
          PSHS      CC,DP,X,U           ; PRESERVE REGISTERS
          ORCC      #$50                ; MASK INTERRUPTS
          LEAS      -LOCLSZ,S           ; ALLOCATE SPACE ON STACK FOR VARIABLES
          STD       TIMEOUT,S           ; SET TIMEOUT COUNTER VARIABLE
          STX       BUFSTRT,S           ; SAVE BUFFER START ADDRESS
          LEAU      -1,X                ; INITIALIZE READ PTR FOR PRE-INCREMENT
          LDA       #$FF                ; SETUP THE DP REGISTER TO..
          TFR       A,DP                ; ..ACCESS THE I/O PAGE ($FFxx)
          LDB       ,U                  ; GET NEGATIVE VALUE OF THE BYTE THAT..
          NEGB                          ; ..PRECEDES THE BUFFER AND STORE IT..
          STD       CHKSUM,S            ; ..AS THE INITIAL CHECKSUM VALUE.
          CMPY      #0                  ; CHECK THE REQUEST COUNT AND..
          LBEQ      RCVDONE             ; ..EXIT IF NOTHING REQUESTED
          LDB       #1                  ; SET B TO THE BIT-BANGER INPUT MASK
          LEAX      TIMEOUT+1,S         ; POINT X TO LSB OF THE TIMEOUT COUNTER

          SETDP     $FF                 ; INFORM ASSEMBLER OF NEW DP VALUE

* INTERLEAVE START-BIT DETECTION WITH A DECREMENT OF THE TIMEOUT COUNTER LSB
TOTICK    BITB      <READBIT  4 \
          BEQ       STARTBT   3  | 11
          LDA       ,X        4 /       ; LOAD TIMEOUT LSB
          BITB      <READBIT  4 \
          BEQ       STARTBT   3  | 9
          SUBA      #1        2 /       ; DECREMENT TIMEOUT LSB (CANT USE DECA)
          BITB      <READBIT  4 \
          BEQ       STARTBT   3  | 11
          STA       ,X        4 /       ; STORE NEW TIMEOUT LSB
          BITB      <READBIT  4 \
          BEQ       STARTBT   3  | 10
          BCC       WAITSBT   3 /       ; BRANCH IF TIMEOUT LSB >= 0


* INTERLEAVE START-BIT DETECTION WITH A DECREMENT OF THE TIMEOUT COUNTER MSB
*
*   NOTE:  THE "TIMEOUT" EQUATE IS NOT USED HERE BECAUSE SOME
*          ASSEMBLERS FAIL TO PRODUCE THE "ZERO-OFFSET" POST-BYTE
*          IF THERE IS *ANYTHING* PRECEDING THE COMMA.
*
          BITB      <READBIT  4 \
          BEQ       STARTBT   3  | 11
          LDA       ,S        4 /       ; LOAD TIMEOUT MSB
          BITB      <READBIT  4 \
          BEQ       STARTBT   3  | 9
          SUBA      #1        2 /       ; DECREMENT TIMEOUT MSB (CANT USE DECA)
          BITB      <READBIT  4 \
          BEQ       STARTBT   3  | 11
          STA       ,S        4 /       ; STORE NEW TIMEOUT MSB
          BITB      <READBIT  4 \
          BEQ       STARTBT   3  | 10
          BCS       RCVDONE   3 /       ; BRANCH IF TIMEOUT HAS EXPIRED


* THIS IS THE PRIMARY DELAY LOOP WHICH WAITS FOR A START BIT
WAITSBT   BITB      <READBIT  4 \
          BEQ       STARTBT   3  | 9
          LDA       #$FF      2 /       ; PREP FOR 256 ITERATIONS OF THE LOOP
WDELAY    BITB      <READBIT  4 \
          BEQ       STARTBT   3  | 9
          SUBA      #1        2 /       ; DECREMENT COUNTER (CANT USE DECA)
          BITB      <READBIT  4 \
          BEQ       STARTBT   3  | 10
          BCS       TOTICK    3 /       ; BRANCH IF 256 ITERATIONS COMPLETED
          BITB      <READBIT  4 \  7
          BNE       WDELAY    3 /

* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* AFTER THE START BIT IS DETECTED, 11 MORE CYCLES NEED TO BE CONSUMED
* TO PUT US IN POSITION FOR SAMPLING THE FIRST DATA BIT. THIS TIMING
* WAS DETERMINED AS FOLLOWS (VALUES ARE IN BUS CYCLES):
*
*
*                        |<------ 23.31 ------>|
*                        |                     |
*                        |<-- 15.54 -->|       |
*                        |             |       |
*
*   --------------------\   Start Bit   /-------------\      
*                        \-------------/   Data Bit 0  \--------
*
*  Detection window -->  xxxxxxxxxxx      xxxxxxxxxxx  <-- Sampling window
*                        |         |           |
*                        |<-- 11 ->|           |
*                        |                     |
*                        |    |                |
*                5.5 --->|    |<---- 17.81 --->|
*
*
* THERE ARE ROUGHLY 15.54 CYCLES PER-BIT (894886.25 / 57600). DETECTION OF THE
* START-BIT MAY HAVE OCCURED ANYWHERE WITHIN THE FIRST 11 CYCLES. IDEALLY, WE
* WOULD LIKE THE SAMPLING POINT TO BE CENTERED WITHIN EACH DATA BIT. THERE ARE
* ABOUT 17.81 CYCLES BETWEEN THE CENTER OF THE START-BIT DETECTION WINDOW AND
* THE CENTER OF THE FIRST DATA BIT.  THE CPU INSTRUCTIONS WHICH DETECTED THE
* START-BIT AND BROUGHT US HERE (BITB/BEQ) USED 7 CYCLES, LEAVING ANOTHER
* 10.81 CYCLES (11) TO CONSUME BEFORE SAMPLING THE FIRST DATA BIT.
*
* WE NEED TO CALCULATE THE OPTIMAL SAMPLING TIME FOR EACH SUBSEQUENT BIT AND
* ROUND TO THE NEAREST CYCLE.


STARTBT   LDD       #$0000    3  \      ; RESET THE TIMEOUT COUNTER..
          STD       ,S        5   | 11  ; ..FOR SUBSEQUENT BYTES
          ABX                 3  /      ; CONSUME 3 CYCLES
                                        ; WANTED 10.81 / USED 11 / 0.19 LATE

* SAMPLE DATA BIT 0
          LDB       <READBIT  4 \       ; SAMPLE
          LSRB                2  | 15   ; MOVE BIT VALUE INTO CARRY
          RORA                2  |      ; SHIFT DATA BIT INTO A
          CMPX      1,X       7 /       ; CONSUME 7 CYCLES
                                        ; WANTED 15.35 / USED 15 / 0.35 EARLY

* SAMPLE DATA BIT 1
          LDB       <READBIT  4 \       ; SAMPLE
          LSRB                2  |      ; MOVE BIT VALUE INTO CARRY
          RORA                2  | 16   ; SHIFT DATA BIT INTO A
          LDX       CHKSUM,S  6  |      ; LOAD CHECKSUM VARIABLE INTO X
          NOP                 2 /       ; CONSUME 2 CYCLES
                                        ; WANTED 15.89 / USED 16 / 0.11 LATE

* SAMPLE DATA BIT 2
          LDB       <READBIT  4 \       ; SAMPLE
          LSRB                2  |      ; MOVE BIT VALUE INTO CARRY
          RORA                2  | 15   ; SHIFT DATA BIT INTO A
          LDB       ,U        4  |      ; B = PREVIOUS BYTE RECEIVED
          ABX                 3 /       ; UPDATE CHECKSUM VALUE IN X
                                        ; WANTED 15.43 / USED 15 / 0.43 EARLY

* SAMPLE DATA BIT 3
          LDB       <READBIT  4 \       ; SAMPLE
          LSRB                2  |      ; MOVE BIT VALUE INTO CARRY
          RORA                2  | 16   ; SHIFT DATA BIT INTO A
          CMPB      ,U+       6  |      ; INCREMENT THE READ POINTER
          NOP                 2 /       ; CONSUME 2 CYCLES
                                        ; WANTED 15.97 / USED 16 / 0.03 LATE

* SAMPLE DATA BIT 4
          LDB       <READBIT  4 \       ; SAMPLE
          LSRB                2  |      ; MOVE BIT VALUE INTO CARRY
          RORA                2  | 16   ; SHIFT DATA BIT INTO A
          STX       CHKSUM,S  6  |      ; STORE CHECKSUM VARIABLE
          NOP                 2 /       ; CONSUME 2 CYCLES
                                        ; WANTED 15.51 / USED 16 / 0.49 LATE

* SAMPLE DATA BIT 5
          LDB       <READBIT  4 \       ; SAMPLE
          LSRB                2  |      ; MOVE BIT VALUE INTO CARRY
          RORA                2  | 15   ; SHIFT DATA BIT INTO A
          LEAX   TIMEOUT+1,S  5  |      ; POINT X TO LSB OF THE TIMEOUT COUNTER
          NOP                 2 /       ; CONSUME 2 CYCLES
                                        ; WANTED 15.05 / USED 15 / 0.05 EARLY

* SAMPLE DATA BIT 6
          LDB       <READBIT  4 \       ; SAMPLE
          LSRB                2  |      ; MOVE BIT VALUE INTO CARRY
          RORA                2  | 16   ; SHIFT DATA BIT INTO A
          LEAY      -1,Y      5  |      ; DECREMENT BYTES REMAINING COUNTER
          BEQ       FINBYT    3 /       ; BRANCH IF THIS IS THE FINAL BYTE
                                        ; WANTED 15.59 / USED 16 / 0.41 LATE

* SAMPLE DATA BIT 7 (WHEN THERE ARE MORE BYTES TO FOLLOW)
          LDB       <READBIT  4 \       ; SAMPLE
          LSRB                2  |      ; MOVE BIT VALUE INTO CARRY
          RORA                2  | 15   ; SHIFT DATA BIT INTO A
          STA       ,U        4  |      ; STORE RECEIVED BYTE IN BUFFER
          LDD       #1        3 /       ; SET B TO BIT-BANGER INPUT MASK
                                        ; WANTED 15.13 / USED 15 / 0.13 EARLY

* SAMPLE STOP BIT (FOR FRAMING ERROR)
          BITB      <READBIT  4 \  7    ; SAMPLE STOP BIT 
          BNE       WAITSBT   3 /       ; IF NO ERROR GO WAIT FOR START BIT

* FRAMING ERROR DETECTED
FRERROR   ORB       LOCLSZ,S            ; SET FRAMING ERROR FLAG (CARRY) IN..
          STB       LOCLSZ,S            ; ..THE CC PRESERVED ON THE STACK
          BRA       RCVDONE             ; ABORT DUE TO FRAMING ERROR

* SAMPLE DATA BIT 7 (ONLY FOR THE FINAL BYTE REQUESTED)
FINBYT    LDB       <READBIT  4 \       ; SAMPLE
          LSRB                2  |      ; MOVE BIT VALUE INTO CARRY
          RORA                2  | 15   ; SHIFT DATA BIT INTO A
          STA       ,U        4  |      ; STORE RECEIVED BYTE IN BUFFER
          LDD       #1        3 /       ; SET B TO BIT-BANGER INPUT MASK
                                        ; WANTED 15.13 / USED 15 / 0.13 EARLY

* SAMPLE STOP BIT (FOR FRAMING ERROR)
          BITB      <READBIT            ; SAMPLE STOP BIT 
          BEQ       FRERROR             ; BRANCH IF FRAMING ERROR

* FINISH UP AND RETURN
RCVDONE   LDX       CHKSUM,S            ; GET CURRENT CHECKSUM VALUE IN X
          LDB       ,U+                 ; GET FINAL DATA BYTE IN B
          ABX                           ; CALCULATE FINAL CHECKSUM
          LEAY      ,X                  ; RETURN CHECKSUM IN Y
          TFR       U,D                 ; CALCULATE NUMBER OF BYTES RECEIVED..
          SUBD      BUFSTRT,S           ; ..AS READ PTR MINUS START ADDRESS
          LEAS      LOCLSZ,S            ; RELEASE ALLOCATED STACK SPACE
          PULS      CC,DP,X,U,PC        ; RESTORE REGISTERS AND RETURN

          SETDP     $00                 ; INFORM ASSEMBLER OF NEW DP VALUE


******************************************************************************
* COCO 57600 / 115.2K BAUD BIT-BANGER TRANSMIT
******************************************************************************
*
* THIS SUBROUTINE TRNSMITS A SPECIFIED NUMBER OF DATA BYTES THROUGH
* THE BIT-BANGER PORT AT HIGH SPEED. ALL OF THE DATA IS SENT IN A
* SINGLE BURST, NO HANDSHAKING IS PROVIDED. THE TRANSMISSION FORMAT
* IS: 1 START BIT, 8 DATA BITS, NO PARITY, 1 STOP BIT.
*
*  ON ENTRY:
*    X = ADDRESS OF THE DATA TO TRANSMIT
*    Y = NUMBER OF BYTES TO TRANSMIT
*    THE BIT-BANGER OUTPUT MUST BE AT MARK (HIGH)
*
*  ON EXIT:
*    X = ADDRESS OF LAST BYTE TRANSMITTED + 1
*    Y = 0
*    OTHER REGISTERS (A,B,U) ARE PRESERVED
*    THE BIT-BANGER OUTPUT IS LEFT IN THE MARK STATE
*

BBNGOUT   EQU       $FF20               ; ADDRESS OF THE BIT-BANGER OUTPUT

XMT56K    PSHS      CC,A,B,DP           ; PRESERVE REGISTERS
          CMPY      #0                  ; CHECK THE TRANSMIT COUNT
          BEQ       XMTEXIT             ; EXIT IF TRANSMIT COUNT IS ZERO
          ORCC      #$50                ; MASK INTERRUPTS
          LDA       #$FF                ; SETUP THE DP REGISTER FOR..
          TFR       A,DP                ; ..ACCESSING THE I/O PAGE ($FFxx)
          LDA       ,X                  ; GET FIRST BYTE TO TRANSMIT

          SETDP     $FF                 ; INFORM ASSEMBLER OF NEW DP VALUE

* LOOP BACK HERE FOR EACH BYTE
BYTEOUT   NOP                 2 \  4    ; CONSUME 2 CYCLES
          CLRB                2 /       ; PREPARE START BIT VALUE (SPACE)

* START BIT
          STB       <BBNGOUT  4 \       ; SET BIT-BANGER STATE TO SPACE
          LSRA                2  |      ; SHIFT THE LS BIT FROM A TO..
          ROLB                2  | 16   ; ..THE BIT-BANGER OUTPUT..
          LSLB                2  |      ; ..POSITION IN B
          CMPX      ,X        6 /       ; CONSUME 6 CYCLES
                                        ; WANTED 15.54 / USED 16 / 0.46 LATE

* DATA BIT 0
          STB       <BBNGOUT  4 \       ; SET BIT-BANGER STATE FOR THE DATA BIT
          CLRB                2  |      ; CLEAR OUTPUT VALUE
          ABX                 3  |      ; CONSUME 3 CYCLES
          LSRA                2  | 15   ; SHIFT THE LS BIT FROM A TO..
          ROLB                2  |      ; ..THE BIT-BANGER OUTPUT..
          LSLB                2 /       ; ..POSITION IN B
                                        ; WANTED 15.08 / USED 15 / 0.08 EARLY

* DATA BIT 1
          STB       <BBNGOUT  4 \       ; SET BIT-BANGER STATE FOR THE DATA BIT
          CLRB                2  |      ; CLEAR OUTPUT VALUE
          LSRA                2  |      ; SHIFT THE LS BIT FROM A TO..
          ROLB                2  | 16   ; ..THE BIT-BANGER OUTPUT..
          LSLB                2  |      ; ..POSITION IN B
          NOP                 2  |      ; CONSUME..
          NOP                 2 /       ; ..4 CYCLES
                                        ; WANTED 15.62 / USED 16 / 0.38 LATE

* DATA BIT 2
          STB       <BBNGOUT  4 \       ; SET BIT-BANGER STATE FOR THE DATA BIT
          CLRB                2  |      ; CLEAR OUTPUT VALUE
          ABX                 3  |      ; CONSUME 3 CYCLES
          LSRA                2  | 15   ; SHIFT THE LS BIT FROM A TO..
          ROLB                2  |      ; ..THE BIT-BANGER OUTPUT..
          LSLB                2 /       ; ..POSITION IN B
                                        ; WANTED 15.16 / USED 15 / 0.16 EARLY

* DATA BIT 3
          STB       <BBNGOUT  4 \       ; SET BIT-BANGER STATE FOR THE DATA BIT
          CLRB                2  |      ; CLEAR OUTPUT VALUE
          LSRA                2  |      ; SHIFT THE LS BIT FROM A TO..
          ROLB                2  | 16   ; ..THE BIT-BANGER OUTPUT..
          LSLB                2  |      ; ..POSITION IN B
          NOP                 2  |      ; CONSUME..
          NOP                 2 /       ; ..4 CYCLES
                                        ; WANTED 15.70 / USED 16 / 0.30 LATE

* DATA BIT 4
          STB       <BBNGOUT  4 \       ; SET BIT-BANGER STATE FOR THE DATA BIT
          CLRB                2  |      ; CLEAR OUTPUT VALUE
          ABX                 3  |      ; CONSUME 3 CYCLES
          LSRA                2  | 15   ; SHIFT THE LS BIT FROM A TO..
          ROLB                2  |      ; ..THE BIT-BANGER OUTPUT..
          LSLB                2 /       ; ..POSITION IN B
                                        ; WANTED 15.24 / USED 15 / 0.24 EARLY

* DATA BIT 5
          STB       <BBNGOUT  4 \       ; SET BIT-BANGER STATE FOR THE DATA BIT
          CLRB                2  |      ; CLEAR OUTPUT VALUE
          LSRA                2  |      ; SHIFT THE LS BIT FROM A TO..
          ROLB                2  | 16   ; ..THE BIT-BANGER OUTPUT..
          LSLB                2  |      ; ..POSITION IN B
          NOP                 2  |      ; CONSUME..
          NOP                 2 /       ; ..4 CYCLES
                                        ; WANTED 15.78 / USED 16 / 0.22 LATE

* DATA BIT 6
          STB       <BBNGOUT  4 \       ; SET BIT-BANGER STATE FOR THE DATA BIT
          CLRB                2  |      ; CLEAR OUTPUT VALUE
          ABX                 3  |      ; CONSUME 3 CYCLES
          LSRA                2  | 15   ; SHIFT THE LS BIT FROM A TO..
          ROLB                2  |      ; ..THE BIT-BANGER OUTPUT..
          LSLB                2 /       ; ..POSITION IN B
                                        ; WANTED 15.32 / USED 15 / 0.32 EARLY

* DATA BIT 7
          STB       <BBNGOUT  4 \       ; SET BIT-BANGER STATE FOR THE DATA BIT
          LDA       1,X       5  | 16   ; GET NEXT DATA BYTE
          LEAX      1,X       5  |      ; INCREMENT BUFFER POINTER
          LDB       #2        2 /       ; PREPARE STOP BIT VALUE (MARK)
                                        ; WANTED 15.86 / USED 16 / 0.14 LATE

* STOP BIT
          STB       <BBNGOUT  4 \       ; SET BIT-BANGER STATE TO MARK
          LEAY      -1,Y      5  | 12   ; DECREMENT REMAINING BYTE COUNT
          BNE       BYTEOUT   3 / (+4)  ; LOOP IF MORE BYTES TO TRANSMIT
                                        ; WANTED 16.40 / USED 16 / 0.60 LATE

XMTEXIT   PULS      CC,A,B,DP,PC        ; RESTORE REGISTERS AND RETURN

          SETDP     $00                 ; INFORM ASSEMBLER OF NEW DP VALUE

******************************************************************************
