📄 serial.asm
字号:
;----------------------------------------------------------------
; Shift data byte right 1 bit. (Carry
; was cleared by previous "jnz" instruction.)
mov A, [X + rx_buffer] ; [6]
rrc A ; [4]
mov [X + rx_buffer], A ; [6]
; If parity is off, we're done.
mov A, [parity_on] ; [5]
cmp A, TRUE ; [5]
jnz Increment_Buffer_In ; [5/4]
; Kill 17 cycles (104 - 87 = 17).
8_CYCLE_DELAY ; [8]
7_CYCLE_DELAY ; [7]
BIT_DELAY ; [14 + (bit_rate * 104)]
jmp Rx_Parity_Bit ; [5]
;----------------------------------------------------------------
Rx_D7_Bit_Next:
; Shift data byte right one bit.
CLR_C ; [4]
mov A, [X + rx_buffer] ; [6]
rrc A ; [4]
mov [X + rx_buffer], A ; [6]
; Kill 31 cycles (104 - 73 = 31).
call 26_Cycle_Delay ; [26]
5_CYCLE_DELAY ; [5]
BIT_DELAY ; [14 + (bit_rate * 104)]
;****************************************************************
Rx_D7_Bit:
; Read RXD and update parity.
iord INPUT_PORT ; [5]
xor [parity], A ; [7]
; Add new bit to byte.
and A, RXD ; [4]
or [X + rx_buffer], A ; [8]
; If parity is off, we're done.
mov A, [parity_on] ; [5]
cmp A, TRUE ; [5]
jnz Increment_Buffer_In ; [5/4]
;----------------------------------------------------------------
; Kill 52 cycles (104 - 52 = 52).
call 46_Cycle_Delay ; [46]
6_CYCLE_DELAY ; [6]
BIT_DELAY ; [14 + (bit_rate * 104)]
;****************************************************************
Rx_Parity_Bit:
; Update parity and leave in A.
iord INPUT_PORT ; [5]
xor A, [parity] ; [6]
; Check parity
and A, RXD ; [4]
jz Increment_Buffer_In ; [5/4]
; There was a parity error. Save the buffer
; address in the error_location variable.
mov A, [rx_buffer_in] ; [5]
or A, ERROR_FLAG ; [4]
mov [error_location], A ; [5]
IFDEF HW_FLOW_CONTROL
mov A, RTS ; [4]
or [output_port_shadow], A ; [7]
ENDIF
;****************************************************************
Increment_Buffer_In:
; Increment the rx_buffer_in pointer.
inc [rx_buffer_in] ; [7]
mov A, (SIZEOF_RX_BUFFER - 1) ; [4]
and [rx_buffer_in], A ; [7]
IFDEF HW_FLOW_CONTROL
; If the amount of available buffer space is
; less than the RTS_LAG value, release RTS.
mov A, [rx_buffer_out] ; [5]
sub A, [rx_buffer_in] ; [6]
sub A, (RTS_LAG + 1) ; [4]
and A, (SIZEOF_RX_BUFFER - 1) ; [4]
jnz Update_Rts ; [5/4]
mov A, RTS ; [4]
or [output_port_shadow], A ; [7]
Update_Rts:
mov A, [output_port_shadow] ; [5]
iowr OUTPUT_PORT ; [5]
ENDIF
;----------------------------------------------------------------
Wait_For_Stop:
; Wait for the RXD high which either means that
; we're still in the parity bit and the parity
; bit is high or we're in the stop bit.
iord INPUT_PORT ; [5]
and A, RXD ; [4]
jz Wait_For_Stop ; [5/4]
; Re-enable RXD interrupt.
mov A, RXD ; [4]
iowr P0_IE ; [5]
Rx_Data_Done:
pop X ; [4]
pop A ; [4]
reti ; [8]
;************************************************************
; FUNCTION: Load_Ep1_Fifo
;************************************************************
; The Ep1 FIFO is currently empty. If there is data available
; in the rx_buffer, copy the minimum of either the amount of
; available data or the amount of data that will fill a
; report to ep1_fifo. In any case, create a new report
; header to send in to the host.
;************************************************************
Load_Ep1_Fifo:
push A ;
push X ;
mov A, 00h ;
mov [temp], A ;
mov [byte_counter], A ;
; Pre-clear the input report status and
; count bytes.
mov [input_status], A ;
mov [input_count], A ;
call Clear_Input_Report ;
;------------------------------------------------------------
.Load_Buffer:
; If the buffer is empty, stop loading
; the FIFO and go prepare the report
; header.
mov A, [rx_buffer_out] ; Is buffer empty?
cmp A, [rx_buffer_in] ;
jz .Exit_Load ; Yes
; If the current buffer location is an
; error location, stop loading the FIFO
; and set the error flag in the input
; report.
or A, ERROR_FLAG ;
cmp A, [error_location] ;
jz .Set_Error_Flag ;
; Copy byte from rx_buffer into input_data.
mov X, [rx_buffer_out] ;
mov A, [X + rx_buffer] ;
mov X, [byte_counter] ;
mov [X + (input_data)], A ;
; Increment rx_buffer_out.
mov A, [rx_buffer_out] ;
inc A ;
and A, (SIZEOF_RX_BUFFER-1) ;
mov [rx_buffer_out], A ;
; Increment byte_counter.
inc [byte_counter] ;
; If the FIFO is not full, loop to Load_Buffer
; and continue to load the FIFO.
mov A, [byte_counter] ; FIFO full?
cmp A, (SIZEOF_INPUT_REPORT - SIZEOF_INPUT_HEADER) ;
jnz .Load_Buffer ; no
; The FIFO is full. Jump to prepare the
; header for the report.
jmp .Exit_Load ; yes
;------------------------------------------------------------
.Set_Error_Flag:
; Load temp with INPUT_ERROR_FLAG.
mov A, INPUT_ERROR ;
mov [temp], A ;
; Increment rx_buffer_out.
mov A, [rx_buffer_out] ;
inc A ;
and A, (SIZEOF_RX_BUFFER-1) ;
mov [rx_buffer_out], A ;
; Clear error_location.
mov A, 00h ;
mov [error_location], A ;
;------------------------------------------------------------
.Exit_Load:
; Read the current state of the input bits
; (RI, CD, DSR, and CTS) located at P0.4 -
; P0.1 and shift them into the upper nibble.
; Invert the state of these bits. Clear the
; lower nibble and load the error flag into
; the lower nibble. Finally, put the resulting
; value into byte 0 of the ep1_fifo, which is
; the header location for the input report.
iord INPUT_PORT ; Read P0
asl ; Shift left 3 bits
asl ;
asl ;
xor A, FFh ; Invert value
and A, F0h ; Clear lower nibble
or A, [temp] ; Or in error flag
mov [input_status], A ; Load in byte 0
; Get the number of data bytes loaded into
; the ep1_fifo (not including the two header
; bytes) and load that value into byte 1 of
; the ep1_fifo.
mov A, [byte_counter] ;
or [input_count], A ;
; Now that the ep_fifo is loaded, clear
; the load_ep1 flag.
mov A, FALSE ;
mov [load_ep1], A ;
; Enable the new report to be transmitted
; from the endpoint at the next available
; opportunity.
mov A, ACK_IN ; EP1 MODE = ACK_IN
iowr EP1_MODE ;
; If buffer is empty, enable RXD interrupt.
mov A, [rx_buffer_in] ; Is buffer empty?
cmp A, [rx_buffer_out] ;
jnz .Do_Not_Reenable ; No
mov A, RXD ;
iowr P0_IE ;
IFDEF HW_FLOW_CONTROL
; Assert RTS low unless host has requested
; that RTS be deasserted high.
mov A, [output_port_shadow] ;
and A, ~RTS ;
or A, [rts_shadow] ;
mov [output_port_shadow], A ;
iowr OUTPUT_PORT ;
ENDIF
.Do_Not_Reenable:
pop X ;
pop A ;
Load_Ep1_Fifo_X:
ret ;
;************************************************************
; FUNCTION: nn_Cycle_Delay
;************************************************************
50_Cycle_Delay:
nop ; [4]
46_Cycle_Delay:
nop ; [4]
42_Cycle_Delay:
nop ; [4]
38_Cycle_Delay:
nop ; [4]
34_Cycle_Delay:
nop ; [4]
30_Cycle_Delay:
nop ; [4]
26_Cycle_Delay:
nop ; [4]
22_Cycle_Delay:
nop ; [4]
18_Cycle_Delay:
ret ; [8]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -