                .DO     Internal
                .LSTON
                .FIN
                .PAGE
;-------------------------------------------------------------------------------
;
;               AB start -- Applebus entry point
;
;-------------------------------------------------------------------------------

AB_start:       CALL    sccmain
                CALL    AB_init                 ;Initialize our vars
                CALL    Select_node             ;Get a node number
AB_dead:        JR      c,AB_dead               ;Lock up if no node number
                
                CALL    Save_reg                ;Save context and fall through

;-------------------------------------------------------------------------------
;
;               AB main -- Applebus main program
;
;-------------------------------------------------------------------------------

AB_main:        CALL    Restore_reg             ;Main entry point

AB_main_loop:   LD      io_buff_hi,#.HIBYTE.Cmnd_Ptr  ;Set up pointer to data
                LD      io_buff_lo,#.LOWBYTE.Cmnd_Ptr
                
                CLR     bus_stat1               ;Clear old state
                CLR     bus_stat3
                CLR     bus_stat4
                CLR     curr_node               ;Clear to receive from any node
                SRP     #wrk_sys                ;Use other bank
                LD      !r0,#1                  ;Enable scc
                CALL    edscc
                
                SRP     #wrk_absys
                CALL    Get_packet
                
                TM      bus_stat1,#d_busy       ;Check for cmd pending
                JR      nz,AB_interp
                
                TM      bus_stat2,#diag_bit     ;Check if last command was diag
                JR      nz,AB_main_loop         ;If true then no free process
                
                CALL    Save_reg                ;Save status
                
                SRP     #wrk_sys                ;Do free process
                CLR     !r0                     ;Disable scc
                CALL    edscc
                
                LD      !r2,#.HIBYTE.Strt_FreeProcess
                LD      !r3,#.LOWBYTE.Strt_FreeProcess
                CALL    Bank_Call
                
;-------------------------------------------------------------------------------
;
;       AB interp -- Interpret the widget call
;
;-------------------------------------------------------------------------------
AB_interp:      LD      curr_node,their_node    ;Save the senders node number
                SRP     #wrk_global             ;Use pointer already set
                LDE     !r3,@!!r6               ;Get the instruction in stat2
                SRP     #wrk_absys
                
Normal_int:     CALL    Save_reg                ;Save working sets
                SRP     #wrk_sys
                CLR     !r0                     ;Disable scc
                CALL    edscc
                LD      !r2,#.HIBYTE.Start_Command      ;Jump to Widget control
                LD      !r3,#.LOWBYTE.Start_Command
                CALL    Bank_Call
                
;--------------------------------------------------------------------------
;
;       Return handler -- Widget returns here after command completion
;
;----------------------------------------------------------------------
AB_multi_ret:   POP     !r0                     ;Remove return address
                POP     !r1                     ;If multiblock read
                LD      !r0,#1                  ;Enable scc
                CALL    edscc
                CALL    Restore_reg             ;Restore context
                JR      AB_ret2                 ;leap
                
AB_return:      LD      !r0,#1                  ;Enable scc
                CALL    edscc
                CALL    Restore_reg             ;Restore context
                AND     bus_stat2,#$FF-multi_bit   ;Clear multi flag
                
AB_ret2:        CP      bus_stat2,#write_cmd            ;Is this a write return
                JR      ne,AB_ret3                      ;Branch if not
                
                LD      io_cnt_hi,#.HIBYTE.write_len    ;Size of packet
                LD      io_cnt_lo,#.LOWBYTE.write_len
                JR      Abus_send
                
AB_ret3:        LD      io_cnt_hi,#.HIBYTE.read_len     ;Size of packet
                LD      io_cnt_lo,#.LOWBYTE.read_len
                
Abus_send:      LD      io_buff_hi,#.HIBYTE.StatusArray  ;Start of data buffer
                LD      io_buff_lo,#.LOWBYTE.StatusArray
                CALL    Send_packet             ;Return the data
                CP      bus_stat2,#multi        ;Check for multiblock
                JR      eq,AB_multi_cont
                
                JP      AB_main_loop    
                
AB_multi_cont:  CALL    Save_reg                ;Save working sets
                SRP     #wrk_sys
                CLR     !r0                     ;Disable scc
                CALL    edscc
                LD      !r2,#.HIBYTE.Sys_Ret    ;Set up bank to multiblock
                LD      !r3,#.LOWBYTE.Sys_Ret   ;  continuation routine
                CALL    Bank_Call               ;Continue multiblock read  
                
;--------------------------------------------------------------------------
;
;       Abort handler -- Widget returns here if an abort took place
;
;----------------------------------------------------------------------
Abus_abort:     TM      Excpt_Stat,#PwrRst      ;Check if  power up abort
                JR      z,Ab_ab2                ;Branch if not
                JP      AB_Start                ;Init system
                
Ab_ab2:         LD      !r0,#1                  ;Enable scc
                CALL    edscc
                CALL    Restore_reg
                LD      io_cnt_hi,#.HIBYTE.status_len   ;Size of packet
                LD      io_cnt_lo,#.LOWBYTE.status_len
                CLR     bus_stat2               ;Clear old command
                JR      Abus_send               ;Stay in loop
                
                
;-------------------------------------------------------------------------------
;
;               AB init -- Initializes the global variables.
;
;-------------------------------------------------------------------------------

AB_init:        CLR     bus_stat1               ;Init the variables
                CLR     bus_stat2
                CLR     bus_stat3
                CLR     bus_stat4
                
                CLR     io_buff_hi
                CLR     io_buff_lo
                
                CLR     io_cnt_hi
                CLR     io_cnt_lo
                
                CLR     our_sckt
                CLR     their_sckt
                CLR     curr_node
                CLR     our_node
                CLR     their_node
                CLR     lap_ctrl
                LD      boff_hist,#01
                LD      boff_mask,#03
                
                SRP     #wrk_absys
                LD      !pntr_hi,#.HIBYTE.sckt_tab  ;Clear the socket table
                LD      !pntr_lo,#.LOWBYTE.sckt_tab
                LD      !tab_size,#$20          ;32 elements
                CLR     !ddp_temp
                
AB_init_loop:   LDE     @!!pntr,!ddp_temp               ;Clear an entry
                INCW    !pntr
                DJNZ    !tab_size,AB_init_loop
                RET
                
                
                .PAGE
;-------------------------------------------------------------------------------
;
;               Misc utility routines.
;
;-------------------------------------------------------------------------------

;-------------------------------------------------------------------------------
;
;               Save/Restore Reg -- Save and restore working sets 30 & 40
;               to external memory.
;
;-------------------------------------------------------------------------------

Save_reg:       SRP     #wrk_sys
                LD      !r0,#.HIBYTE.reg_store  ;Get the pointer to ram
                LD      !r1,#.LOWBYTE.reg_store
                LD      !r2,#Wrk_sys2           ;Start at $30
                LD      !r3,#reg_cnt            ;And save two sets
                
S_R_loop:       LDEI    @!!r0,@!r2              ;Save a reg
                DJNZ    !r3,S_R_loop            ;Again
                RET
                
                
Restore_reg:    SRP     #wrk_sys
                LD      !r0,#.HIBYTE.reg_store  ;Get the pointer to ram
                LD      !r1,#.LOWBYTE.reg_store
                LD      !r2,#Wrk_sys2           ;Start at $30
                LD      !r3,#reg_cnt            ;And save two sets
                
R_R_loop:       LDEI    @!r2,@!!r0              ;Get a reg
                DJNZ    !r3,R_R_loop            ;Again
                SRP     #wrk_absys
                RET
                
;-------------------------------------------------------------------------------
;
;               Rangen -- Generates a new random number in seed (16 bit)
;
;-------------------------------------------------------------------------------

Rangen:         LD      !rand_cnt,#5            ;Loop 5 times
Rand:           CALL    Mult5                   ;Multiply by 5
                DJNZ    !rand_cnt,Rand
                ADD     seedlo,#$39             ;Add offset ($0039)
                ADC     seedhi,#$00
                RET
                
Mult5:          LD      !rand_temp,seedlo       ;Get seed
                LD      !rand2_temp,seedhi
                RCF
                RLC     !rand_temp              ;Shift left
                RLC     !rand2_temp
                ADD     seedlo,!rand_temp       ;Add for *5
                ADC     seedhi,!rand2_temp
                RET

;-------------------------------------------------------------------------------
;
;               Select node -- Find a node number for us to use
;                              Returns: carry=0  node found
;                                       carry=1  fatal error or node not found
;
;-------------------------------------------------------------------------------

Select_node:    LD      !sel_cnt,#find_cnt      ;Try many times
Select_loop:    CALL    Rangen                  ;Get a random node number
                LD      our_node,seed_hi
                OR      our_node,#$80           ;In range 128-254
                CP      our_node,#$FF
                JR      eq,Select_loop          ;May need to retry
                LD      my_node,our_node        ;This is how we do it
                
                LD      my_node,#$B7            ;Hardwired
                LD      our_node,#$B7
                
                LD      !pntr_hi,#.HIBYTE.scc_bank ;Set up scc for node number
                LD      !pntr_lo,#sw6adr
                LD      !rand_temp,our_node     ;Get the number we selected
                LDE     @!!pntr,!rand_temp
                
                CALL    Select_1                ;Try for response
                JR      c,Select_try            ;If one then try again
                
                RCF                             ;Flag success
                RET
                
Select_try:     TM      bus_stat3,#fatal
                JR      nz,Select_fail          ;Stop on fatal error
                
                DJNZ    !sel_cnt,Select_loop    ;Try again
                
Select_fail:    SCF                             ;Flag error (fatal or cant select)
                RET

;-------------------------------------------------------------------------------
;
;               Select 1 -- Sends an RTS to itself and waits for reply.
;                           Returns carry clear if no reply in 16 ties.
;                           Returns carry set if a reply in 16 tries or
;                           fatal condition exists.
;
;-------------------------------------------------------------------------------
                
Select_1:       LD      !retry_cnt,#xmt_retries ;Get the retry count

Select_2:       CALL    Rangen                  ;Get the backoff value
                LD      bofflo,seedhi           ;Start with a random number
                AND     bofflo,#$3F             ;Get lower 6 bits
                ADD     bofflo,#$4B             ;Put back off on range 30-60 ms.
                CLR     boffhi
                OR      bus_stat1,#lap_only     ;No data to send
                AND     bus_stat1,#$FF-msg_sent-msg_rcvd   ;Clear bit
                LD      their_node,my_node      ;Send to ourself
                LD      our_node,my_node
                LD      lap_ctrl,#ENQcode       ;Set up lap code
                LD      rt_pntr_hi,#.HIBYTE.dummy  ;Set up pointer to lap buffer
                LD      rt_pntr_lo,#.LOWBYTE.dummy
                
                CALL    tpack                   ;Send the packet
                TM      bus_stat1,#msg_sent     ;Check for sent message
                JR      nz,Select_3             ;Branch if no error
                
                TM      bus_stat3,#fatal        ;Check for fatal errors
                JR      z,Select_2              ;Branch if non fatal
                
                SCF                             ;Flag error
                RET
                
Select_3:       OR      bus_stat1,#l_busy       ;Set l_busy true
                LD      exp_ctrl,#ACKcode       ;Set up lap code
                CLR     boff_hi                 ;Set 200 us time out
                LD      boff_lo,#1
                
                CALL    rpack
                TM      bus_stat1,#msg_rcvd     ;Check for messege received
                JR      nz,Sel_out
                
Select_4:       DJNZ    !retry_cnt,Select_2     ;Try again
                RCF                             ;All is ok
                RET
                
Sel_out:        SCF                             ;Flag error
                RET

;-------------------------------------------------------------------------------
;
;               Get backoff -- Calculate a random backoff value
;
;-------------------------------------------------------------------------------

Get_boff:       LD      !boff_cnt,#8            ;Count the history
                CLR     !boff_temp              ;Clear accumulator
B_loop:         RL      boff_hist               ;Shift the history
                ADC     !boff_temp,#0           ;Add the incidence
                DJNZ    !boff_cnt,B_loop
                
                LD      boff_hist,#$01          ;Clear old value
                CP      !boff_temp,#2           ;Check for need to alter
                JR      lt,Dec_mask             ;If less than, shrink mask
                JR      gt,Inc_mask             ;If GT,enlarge mask
                RET                             ;Else do nothing
                
Dec_mask:       RR      boff_mask               ;Make small
                AND     boff_mask,#$0F          ;Limit size
                OR      boff_mask,#$03          ;Must be at least 3
                RET
                
Inc_mask:       SCF                             ;Set bit
                RLC     boff_mask               ;Make big
                AND     boff_mask,#$0F          ;Limit size to 0F
                RET
                
                 
                .PAGE
;-------------------------------------------------------------------------------
;
;       DDP Level -- Datagram Delivery Protocol level. This level does socket
;                    management; ie allocation, de-allocation, check for
;                    correct protocol type for next level up, insertion of
;                    socket numbers for lower levels.
;
;
;-------------------------------------------------------------------------------

;-------------------------------------------------------------------------------
;
;       Get DDP -- Attempts to receive a packet. If packet is received then
;                  it is checked to see if it is a socket management call
;                  or an ATP packet. An ATP packet must be directed to an 
;                  already opened socket. DDP level calls are handled here.
;
;-------------------------------------------------------------------------------

Get_DDP:        DECW    io_buff                 ;Move receive pointer to
                DECW    io_buff                 ; make room for DDP
                DECW    io_buff
                CALL    Get_packet              ;Receive a packet
                JR      nc,Got_DDP              ;Branch if received ok
                RET
                
Got_DDP:        LD      !pntr_hi,io_buff_hi     ;Get the pointer to the data
                LD      !pntr_lo,io_buff_lo
                LDE     !ddp_temp,@!!pntr
                LD      our_sckt,!ddp_temp      ;Get destination socket
                INCW    !pntr
                LDE     !ddp_temp,@!!pntr
                LD      their_sckt,!ddp_temp    ;Get source socket
                INCW    !pntr
                LDE     !ddp_temp,@!!pntr
                INCW    !pntr
                CP      !ddp_temp,#HDPcode      ;Check if correct protocol
                JR      eq,Got_DDP_cont
                
                RCF                             ;Clear error -ignore packet
                RET
                
Got_DDP_cont:   LD      !aux_pntr_hi,#.HIBYTE.sckt_tab ;Get pointer to socket table
                LD      !aux_pntr_lo,#.LOWBYTE.sckt_tab
                LDE     !sckt_cnt,@!!aux_pntr   ;Get sockets used count
                CP      our_sckt,#0             ;Socket allocate call?
                JR      ne,Sckt_de_alloc        ;Branch if not
                
                CP      !sckt_cnt,#open_max     ;Check for socket available
                JR      lt,Alloc_sckt           ;If so, allocate one
                
No_sckt_avail:  DECW    !pntr                   ;Store DDP header
                LD      !ddp_temp,#HDPcode      ;Protocol
                LDE     @!!pntr,!ddp_temp
                DECW    !pntr
                LD      !ddp_temp,our_sckt      ;Source
                LDE     @!!pntr,!ddp_temp
                DECW    !pntr
                LD      !ddp_temp,our_sckt      ;Dest. (It's all zeros)
                LDE     @!!pntr,!ddp_temp
                CLR     io_cnt_hi               ;3 byte DDP message
                LD      io_cnt_lo,#3
                CALL    Send_packet             ;Send the reply -none avail
                TM      bus_stat3,#fatal        ;Check for fatal error
                JP      nz,DDP_done
                
                RCF                             ;Ignore other errors
                RET
                
Alloc_sckt:     LD      !tab_size,#14           ;Only 14 tries needed
Search_sckt:    INCW    !aux_pntr               ;Next in table
                LDE     !ddp_temp,@!!aux_pntr   ;Get table value
                CP      !ddp_temp,#0            ;Check if used
                JR      eq,Empty_sckt           ;Branch if not
                
                DJNZ    !tab_size,Search_sckt    ;Loop til one found

Empty_sckt:     LD      our_sckt,!aux_pntr      ;Get our socket number
                SUB     our_sckt,#.LOWBYTE.sckt_tab   ; =pntr-base
                DECW    !pntr                   ;Store DDP header
                LD      !ddp_temp,#HDPcode      ;Protocol
                LDE     @!!pntr,!ddp_temp
                DECW    !pntr
                LD      !ddp_temp,our_sckt      ;Source
                LDE     @!!pntr,!ddp_temp
                DECW    !pntr
                LD      !ddp_temp,their_sckt    ;Dest
                LDE     @!!pntr,!ddp_temp
                CLR     io_cnt_hi               ;3 byte DDP message
                LD      io_cnt_lo,#3
                
                CALL    Send_packet             ;Send the reply -here is your
                JR      c,DDP_done              ; socket number
                
                LD      !ddp_temp,their_sckt
                LDE     @!!aux_pntr,!ddp_temp   ;Save the sckt num in table
                ADD     !aux_pntr_lo,#16        ;Add offset to node number
                LD      !ddp_temp,their_node    ;Get the node number of the request
                LDE     @!!aux_pntr,!ddp_temp   ;Save it
                INC     sckt_cnt                ;Increment count
                LD      !aux_pntr_lo,#.LOWBYTE.sckt_tab
                LDE     @!!aux_pntr,!sckt_cnt   ;Save count
                RET
                
Sckt_de_alloc:  CP      their_sckt,#0           ;Is it a de-alloc call
                JR      ne,Sckt_match           ;Branch if not
                
                DEC     !sckt_cnt               ;Remove allocated socket
                LDE     @!!aux_pntr,!sckt_cnt   ;Fix count
                ADD     our_sckt,!aux_pntr_lo   ;Index into the socket table
                CLR     !sckt_cnt
                LDE     @!!aux_pntr,!sckt_cnt   ;Clear the entry (their=0)
                RCF
                RET
                
Sckt_match:     ADD     !aux_pntr_lo,our_sckt   ;Index into the socket table
                LDE     !ddp_temp,@!!aux_pntr   ;Get our value
                CP      !ddp_temp,their_sckt    ;Compare the values
                JR      ne,Sckt_no_match        ;Branch if match
                
                ADD     !aux_pntr_lo,#16        ;Add offset to node number
                LDE     !ddp_temp,@!!aux_pntr   ;Get node number
                CP      !ddp_temp,their_node    ;Check if valid
                JR      ne,Sckt_no_match
                
                OR      bus_stat1,#d_busy       ;Transaction level busy
                DECW    io_cnt                  ;Reduce byte count
                DECW    io_cnt
                DECW    io_cnt
                RCF                             ;ATP packet received
                RET
                
Sckt_no_match:  LD      !ddp_temp,#HDPcode
                DECW    !pntr                   ;Store DDP header
                LDE     @!!pntr,!ddp_temp
                DECW    !pntr
                CLR     !ddp_temp               ;Send reply -no match
                LDE     @!!pntr,!ddp_temp       ;Store source sckt
                DECW    !pntr
                LDE     @!!pntr,!ddp_temp       ;Store dest sckt
                CLR     io_cnt_hi               ;3 byte DDP message
                LD      io_cnt_lo,#3
                
                CALL    Send_packet             ;Send the reply -none avail
                TM      bus_stat3,#fatal        ;Check for fatal error
                JR      nz,DDP_done
                
                RCF                             ;Ignore other errors
                RET

DDP_done:       SCF                             ;Flag error
                RET     
                
;-------------------------------------------------------------------------------
;
;       Send DDP -- Sends a DDP packet.
;
;-------------------------------------------------------------------------------

Send_DDP:       LD      !aux_pntr_hi,#.HIBYTE.sckt_tab ;Look up socket pair
                LD      !aux_pntr_lo,#.LOWBYTE.sckt_tab
                ADD     !aux_pntr_lo,our_sckt   ;Index into table
                LDE     !ddp_temp,@!!aux_pntr   ;Get their socket
                LD      their_sckt,!ddp_temp
                
                LD      !pntr_hi,io_buff_hi     ;Get pointer to data
                LD      !pntr_lo,io_buff_lo
                DECW    io_buff
                DECW    !pntr                   ;Store DDP header
                LD      !ddp_temp,#HDPcode      ;Store protocol
                LDE     @!!pntr,!ddp_temp
                DECW    io_buff
                DECW    !pntr
                LD      !ddp_temp,our_sckt
                LDE     @!!pntr,!ddp_temp
                DECW    io_buff
                DECW    !pntr
                LD      !ddp_temp,their_sckt    ;And the dest.
                LDE     @!!pntr,!ddp_temp
                INCW    io_cnt                  ;Adjust send count
                INCW    io_cnt
                INCW    io_cnt
                CALL    Send_packet
                RET
                
                
                
                .PAGE
;---------------------------------------------------------------------------
;
;       LAP - Link Access Protocol level
;       Handles RTS, CTS, DATA, ACK type calls.
;
;----------------------------------------------------------------------------

;----------------------------------------------------------------------------
;
;               Get_packet -- Receives packets on the bus. Will return if
;               good data received or 2 second time out. Byte count also
;               returned.
;               routine needs:  pointer to rcv buffer (rcv_buff)
;                               destination node (our_node)
;                               source node (their_node)
;               routine returns:byte count (count)
;                               pointer (rcv_buff)
;               The carry flag returns results: carry=0  no errror
;                                               carry=1  error
;               The status bytes determine error type.
;
;----------------------------------------------------------------------------

Get_packet:     AND     bus_stat1,#$FF-msg_rcvd-msg_sent-l_busy ;Clear bits
                LD      rt_source,curr_node     ;Get source
                LD      exp_ctrl,#RTScode       ;Allow rcv  of RTS packets
                LD      our_node,my_node        ;Set up node data
                LD      their_node,curr_node
                LD      boff_hi,#.HIBYTE.twosec ;2 second time out
                LD      boff_lo,#.LOWBYTE.twosec
                LD      rt_pntr_hi,#.HIBYTE.dummy ;Set up receive pointer
                LD      rt_pntr_lo,#.LOWBYTE.dummy
                LD      P01m,#scc_P01m          ;Set up extended timing
                
                CALL    Rpack                   ;Try to receive
                TM      bus_stat1,#msg_rcvd     ;Check if received
                JR      z,Get_pak_out
                
Send_CTS:       OR      bus_stat1,#l_busy+lap_only  ;Set bits
                AND     bus_stat1,#$FF-msg_rcvd ;Clear bit
                LD      lap_ctrl,#CTScode       ;Set up lap code
                
                CALL    tpack                   ;Send the packet
                TM      bus_stat1,#msg_sent     ;Check for sent message
                JR      nz,Get_DATA             ;Branch if no error
                
Get_pak_out:    LD      P01m,#wig_adrdata       ;Set up normal timing
                CALL    T1restore               ;Restore timer for widget
                SCF                             ;Flag error
                RET
                
Get_DATA:       LD      exp_ctrl,#DATAcode      ;Allow DATA packets only
                LD      rt_pntr_hi,io_buff_hi   ;Set up pointer to lap buffer
                LD      rt_pntr_lo,io_buff_lo
                CLR     boff_hi                 ;Set 200 us time out
                LD      boff_lo,#1
                
                CALL    rpack                   ;Receive it
                TM      bus_stat1,#msg_rcvd     ;Check for received message
                JR      z,Get_pak_out
                
Get_done:       AND     bus_stat1,#$FF-l_busy   ;Close link level
                OR      bus_stat1,#d_busy       ;Open ddp level
                LD      io_cnt_hi,rt_pntr_hi    ;Load the ending pointer
                LD      io_cnt_lo,rt_pntr_lo
                SUB     io_cnt_hi,io_buff_hi    ;Calculate the byte count
                SBC     io_cnt_lo,io_buff_lo
                DECW    io_cnt                  ;Remove CRC
                DECW    io_cnt
                LD      P01m,#wig_adrdata       ;Set up normal timing
                CALL    T1restore
                RCF                             ;Flag ok read
                RET                             ;rcv_buff is already ready

;----------------------------------------------------------------------------
;
;               Send_packet -- Sends the data packet passed to it. This
;               routine needs:  pointer to xmit buffer (xmt_buff)
;                               byte count of buffer (count)
;                               destination node (their_node)
;                               source node (our_node)
;               The carry flag returns results: carry=0  no errror
;                                               carry=1  error
;               The status bytes determine error type.
;
;----------------------------------------------------------------------------

Send_packet:    LD      !retry_cnt,#xmt_retries ;Get the retry count

Send_again:     CALL    Rangen                  ;Get the backoff value
                LD      bofflo,seedhi           ;A random value
                AND     bofflo,boff_mask        ;Mask size
                JR      nz,Send_boff            ;Check for boff overflow
                INC     bofflo

Send_boff:      CLR     boffhi                  ;Clear it
                OR      bus_stat1,#lap_only     ;No data to send
                AND     bus_stat1,#$FF-msg_sent-msg_rcvd-l_busy   ;Clear bit
                LD      our_node,my_node
                LD      their_node,curr_node    ;Save source number
                LD      lap_ctrl,#RTScode       ;Set up lap code
                LD      rt_pntr_hi,#.HIBYTE.dummy ;Set up pointer to lap buffer
                LD      rt_pntr_lo,#.LOWBYTE.dummy
                
                LD      P01m,#scc_P01m          ;Set up extended timing
                CALL    tpack                   ;Send the packet
                TM      bus_stat1,#msg_sent     ;Check for sent message
                JR      nz,Get_CTS              ;Branch if no error
                
                TM      bus_stat3,#fatal        ;Check for fatal errors
                JR      z,Send_loop             ;Branch if non fatal
                
                LD      P01m,#wig_adrdata       ;Set up normal timing
                CALL    T1restore
                SCF                             ;Flag error
                RET
                
Get_CTS:        OR      bus_stat1,#l_busy       ;Set l_busy true
                
Get_CTS2:       LD      rt_source,their_node    ;Set up exp node number
                LD      exp_ctrl,#CTScode       ;Set up lap code
                CLR     boff_hi                 ;Set 200 us time out
                LD      boff_lo,#1
                
                CALL    rpack
                TM      bus_stat1,#msg_rcvd     ;Check for messege received
                JR      nz,Send_DATA
                
                TM      bus_stat3,#fatal        ;Check for fatal errors
                JR      z,Send_loop             ;Branch if non fatal
                
Send_out:       LD      P01m,#wig_adrdata       ;Set up normal timing
                CALL    T1restore
                SCF                             ;Flag error
                RET
                
Send_DATA:      AND     bus_stat1,#$FF-msg_sent-lap_only  ;Clear bit
                LD      lap_ctrl,#DATAcode      ;Set up lap code
                LD      rt_pntr_hi,io_buff_hi   ;Set up pointer to lap buffer
                LD      rt_pntr_lo,io_buff_lo
                LD      bytecnthi,io_cnt_hi     ;Set up byte count
                LD      bytecntlo,io_cnt_lo
                
                CALL    tpack                   ;Send it
                
                RCF                             ;Flag ok send (The RTS that is)
                RLC     boff_hist               ;Save history
                JR      nc,Send2_DATA
                
                CALL    Get_boff                ;Time to adjust boff mask

Send2_DATA:     TM      bus_stat1,#msg_sent     ;Check for sent message
                JR      z,Send3                 ;Branch if error
                
                AND     bus_stat1,#$FF-l_busy   ;Close link level
                LD      P01m,#wig_adrdata       ;Set up normal timing
                CALL    T1restore
                RCF                             ;Flag ok send
                RET
                
Send3:          TM      bus_stat3,#fatal        ;Check for fatal condition
                JR      z,Send_out              ;Branch if true
                
Send_loop:      SCF                             ;Flag no send
                RLC     boff_hist               ;Save history
                JR      nc,Send2_loop
                CALL    Get_boff                ;Time to adjust boff mask

Send2_loop:     DJNZ    !retry_cnt,Send_patch   ;Try again
                JR      Send_out
                
Send_patch:     JP      Send_again
                
                
                .LSTOFF
                
