head 4.4; access ; symbols ; locks oasisa:4.4; strict; comment @# @; 4.4 date 2001.06.19.12.15.25; author oasisa; state Exp; branches ; next ; desc @New Repository; 6/19/2001 (klh) @ 4.4 log @New Repository; 6/19/2001 (klh) @ text @;**************************************************************************** ;* Copyright 1994 MBARI * ;**************************************************************************** ;* Summary : Serial I/O routines for OASIS Microcontroller * ;* Filename : serial.s * ;* Author : Robert Herlien * ;* Project : OASIS Mooring Controller * ;* $Revision: 1.1 $ * ;* Created : 11/12/91 * ;* * ;* MBARI provides this documentation and code "as is", with no warranty, * ;* express or implied, of its quality or consistency. It is provided without* ;* support and without obligation on the part of the Monterey Bay Aquarium * ;* Research Institute to assist in its use, correction, modification, or * ;* enhancement. This information should not be published or distributed to * ;* third parties without specific written permission from MBARI. * ;* * ;**************************************************************************** ; $TITLE("OASIS Serial Functions") ; SERIAL MODULE ; $INCLUDE(..\C196\INCLUDE\8096.INC) $INCLUDE(OASIS.INC) $INCLUDE(IO.INC) ;***************************************************************************** ; EXTRN bad_int:ENTRY ;Spurious interrupt handler EXTRN ring_put:ENTRY ;Put character into ring buffer EXTRN ring_get:ENTRY ;Get character from ring buffer EXTRN enbl_xmit:ENTRY ;Routine to enable serial Tx RSEG ;Register segment EXTRN ioctrl:BYTE ;Local copy of oasis_ctrl EXTRN tick:WORD ;tick counter EXTRN tx_status:NULL ;Tx status for each UART EXTRN do_xon:NULL ;For each UART, TRUE if doing XON/XOFF EXTRN xoff_timer:NULL ;XOFF timer for each UART PUBLIC ser_stat, uarta_stat, uartb_stat ser_stat: dsb 1 ;Copy of sp_stat register uarta_stat: dsb 1 ;Copy of uarta_usr uartb_stat: dsb 1 ;Copy of uartb_usr ; Debug Variables ;curIntStates: dsw 1 ;maxIntStates: dsw 1 DSEG EXTRN rx_ring:NULL ;Receive rings for each UART EXTRN tx_ring:NULL ;Transmit rings for each UART ;**************************************************************** ; ; Interrupt Vectors ; ;**************************************************************** ; CSEG AT 2030H dcw xmit_int, rcv_int, bad_int, bad_int dcw bad_int, ext_int, bad_int, bad_int CSEG ;***************************************************************************** ; CHK_XON - See if we're doing XON/XOFF, and received char is an XON or XOFF ; Inputs: tmp2 = received char ; tmp4 = serial port number ; Output: plmreg = TRUE if XON/XOFF char ; 0000 if not ; Preserves tmp2 & tmp4 ; chk_xon: ld plmreg, R0 ;Prepare FALSE return add tmp6, tmp4, #do_xon cmpb R0, [tmp6] ;Check do_xon[port] be xon_ret ;If FALSE, return FALSE xon_chk1: add tmp6, tmp4, #tx_status ;Point to tx_status[port] cmp tmp2, #XON ;Check for XON/XOFF char be is_xon cmp tmp2, #XOFF bne xon_ret ;If neither, return FALSE is_xoff: ;XOFF routine ldb tmp0, [tmp6] orb tmp0, #XOFFSTS ;Turn on XOFFSTS stb tmp0, [tmp6] ; in tx_status[port] add tmp6, tmp4, #xoff_timer stb R0, [tmp6] ;Store zero in xoff_timer[port] ldbse plmreg, #0ffh ;Return TRUE ret is_xon: ;XON routine ldb tmp0, [tmp6] andb tmp0, #(NOT XOFFSTS) ;Turn off XOFFSTS in tx_status stb tmp0, [tmp6] ; in tx_status[port] push tmp2 push tmp4 lcall enbl_xmit ;Call enbl_xmit(port) pop tmp4 ;Restore port and rcvd char pop tmp2 ldbse plmreg, #0ffh ;Return TRUE xon_ret: ret ;***************************************************************************** ; RCV_INT - Receive character from CPU serial port Interrupt Handler ; ; Void rcv_int( Void ) ; rcv_int: pusha ;Save flags orb ser_stat, sp_stat ;Get serial status bbc ser_stat, SER_RI_BIT, rcvi_nochr push_cregs ;Macro defined in andb ser_stat, #(NOT SER_RI) ldbze tmp2, sbuf ;Get serial character ld tmp4, #CPU_SER ;Indicate CPU serial port scall chk_xon ;Check if XON/XOFF char cmp R0, plmreg ;If so, skip ring put bne rcvi_rtn push tmp2 ;Pass rcvd byte push #(rx_ring + (CPU_SER * RING_STRUC_SIZE)) lcall ring_put ;Put character in rcv ring add SP, #4 rcvi_rtn: pop_cregs ;Macro defined in rcvi_nochr: popa ;Restore flags ret ;***************************************************************************** ; XMIT_INT - Transmit ready on CPU serial port Interrupt Handler ; ; Void xmit_int( Void ) ; xmit_int: pusha ;Save flags push_cregs ;Macro defined in cmpb R0, tx_status + CPU_SER ;If xmitter off or XOFF on, return bne xmiti_rtn orb ser_stat, sp_stat ;Get serial status bbc ser_stat, SER_TI_BIT, xmiti_rtn ;If not ready, return push #(tx_ring + (CPU_SER * RING_STRUC_SIZE)) lcall ring_get ;Get char from ring buffer add SP, #2 cmp plmreg, #0ffffh ;Check for no more characters be xmiti_off ;If no more, turn off xmitter stb plmreg, sbuf andb ser_stat, #(NOT (SER_TI OR SER_TXE)) xmiti_rtn: pop_cregs ;Macro defined in popa ;Restore flags ret xmiti_off: orb tx_status + CPU_SER, #XMITOFF br xmiti_rtn ;***************************************************************************** ; EXT_INT - External Interrupt Handler - 82C52 UART Interrupt ; ; Void ext_int( Void ) ; ; Comment -- Because the CPU will only respond to an edge on the EXTINT pin, ; and because we're servicing 4 different sources of interrupts here ; (2 Tx, 2 Rx), we have to loop while the EXTINT pin is true. This is ; because a 2nd interrupt can come in while we're servicing the first. ; In this case, we would clear the first interrupt source, but the EXTINT ; pin would remain true and the CPU would never see a second positive edge. ; This has been the source of endless debugging headaches. ext_int: pusha ;Save flags push_cregs ;Save all C registers ;We may loop a long time, so let other ints in ldb int_mask, #SW_TIMER ldb imask1, #(XMIT OR RCV) ; st timer1, curIntStates ei ext_again: ;Loop while ext int asserted ldb tmp0b, piaa_pda ;Get interrupt bits bbs tmp0b, UARTA_DR_INT, rcva_int ;Check for rcv int on UART A bbs tmp0b, UARTB_DR_INT, rcvb_int ;Ditto UART B bbs tmp0b, UARTA_TBRE_INT, xmita_int ;Check for xmit int on A bbc tmp0b, UARTB_TBRE_INT, ext_donechk xmitb_int: ;UART B xmit int orb uartb_stat, uartb_usr ;Get UART B status cmpb R0, tx_status + UARTB ;check for XMIT on and no XOFF bne ext_txb_off ;if XMIT off or XOFF, turn off txb ints ; bbc uartb_stat, XMIT_RDY_BIT, ext_donechk ;Check deleted. If TBRE pin asserted, UART Tx is ready. push #(tx_ring + (UARTB * RING_STRUC_SIZE)) lcall ring_get ;Get char from ring buffer add SP, #2 cmp plmreg, #0ffffh ;Check for no more characters be turn_xmitb_off ;If no more, turn off xmitter stb plmreg, uartb_data andb uartb_stat, #(NOT (XMIT_RDY OR XMIT_DONE)) sjmp ext_donechk turn_xmitb_off: orb tx_status + UARTB, #XMITOFF ext_txb_off: andb ioctrl, #(NOT UARTB_INT) sjmp ext_donechk rcva_int: ;UART A rcv int orb uarta_stat, uarta_usr bbc uarta_stat, RCV_RDY_BIT, ext_donechk ldbze tmp2, uarta_data ;Get serial character andb uarta_stat, #(NOT RCV_RDY) ld tmp4, #UARTA ;Indicate UART A scall chk_xon ;Check if XON/XOFF char cmp R0, plmreg ;If so, skip ring put bne ext_donechk push tmp2 ;Pass rcvd byte push #(rx_ring + (UARTA * RING_STRUC_SIZE)) lcall ring_put ;Put character in rcv ring add SP, #4 sjmp ext_donechk rcvb_int: ;UART B rcv int orb uartb_stat, uartb_usr bbc uartb_stat, RCV_RDY_BIT, ext_donechk ldbze tmp2, uartb_data ;Get serial character andb uartb_stat, #(NOT RCV_RDY) ld tmp4, #UARTB ;Indicate UART B scall chk_xon ;Check if XON/XOFF char cmp R0, plmreg ;If so, skip ring put bne ext_donechk push tmp2 ;Pass rcvd byte push #(rx_ring + (UARTB * RING_STRUC_SIZE)) lcall ring_put ;Put character in rcv ring add SP, #4 ext_donechk: stb ioctrl, oasis_ctrl ;write out copy of oasis_ctrl bbs ioport2, EXTINT_BIT, ext_again ;Loop as long as ext int asserted extint_done: ;Test Code ; sub curIntStates, timer1, curIntStates ; cmp curIntStates, maxIntStates ; bnh extdone1 ; st curIntStates, maxIntStates ; nop ; nop ;extdone1: ;End Test Code pop_cregs ;Restore registers popa ;Restore flags ret xmita_int: ;UART A xmit int orb uarta_stat, uarta_usr ;Get UART A status cmpb R0, tx_status + UARTA ;check for XMIT on and no XOFF bne ext_txa_off ;if XMIT off or XOFF, turn off txa ints ; bbc uarta_stat, XMIT_RDY_BIT, ext_donechk ;Check deleted. If TBRE pin asserted, UART Tx is ready. push #(tx_ring + (UARTA * RING_STRUC_SIZE)) lcall ring_get ;Get char from ring buffer add SP, #2 cmp plmreg, #0ffffh ;Check for no more characters be turn_xmita_off ;If no more, turn off xmitter stb plmreg, uarta_data andb uarta_stat, #(NOT (XMIT_RDY OR XMIT_DONE)) sjmp ext_donechk turn_xmita_off: orb tx_status + UARTA, #XMITOFF ext_txa_off: andb ioctrl, #(NOT UARTA_INT) sjmp ext_donechk END @