;* --------------------------------------------------------------------------------------
;*  Copyright (C) 2004 Dallas Semiconductor Corporation, All Rights Reserved.
;* 
;*  Permission is hereby granted, free of charge, to any person obtaining a
;*  copy of this software and associated documentation files (the "Software"),
;*  to deal in the Software without restriction, including without limitation
;*  the rights to use, copy, modify, merge, publish, distribute, sublicense,
;*  and/or sell copies of the Software, and to permit persons to whom the
;*  Software is furnished to do so, subject to the following conditions:
;* 
;*  The above copyright notice and this permission notice shall be included
;*  in all copies or substantial portions of the Software.
;* 
;*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
;*  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
;*  MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
;*  IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
;*  OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
;*  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
;*  OTHER DEALINGS IN THE SOFTWARE.
;* 
;*  Except as contained in this notice, the name of Dallas Semiconductor
;*  shall not be used except as stated in the Dallas Semiconductor
;*  Branding Policy.
;*
;*  Module:        serial_IO
;*  Description:   Convenience Serial IO routines 
;*  Filename:      serial_IO.asm
;*  Include FIle:  serial_IO.inc & maxQ2000.inc
;*  Date:          November 5, 2004
;*  Version:       1.00
;*
;*  Contains some convenience functions for setting synchronous and asycnchronous serial
;*  serial with various modes and sending and receiving data via the serial port using 
;*  the MAXQ2000.  Note that the following functions do not depend on the Evaluation Kit,
;*  and may be used in any MAXQ2000 system.
;*
;* --------------------------------------------------------------------------------------

#include "maxQ2000.inc"
#include "serial_IO.inc"
  .code
;********************************************************************************
;*  Function: 	serial_modeinput
;* 
;*  Descripton:	Allow User to select between serial modes 0-3 described below:
;*      		mode_0 synchronous   8-bit length  System Clock
;*      		mode_1 asynchronous 10-bit length  Uses Baud Clock Generator
;*      		mode_2 asynchronous 11-bit length  System Clock
;*      		mode_3 asynchronous 11-bit length  Uses Baud clock Generator
;* 
;*  Input:      A[0] - Sets either serial port 0 or 1 using: 
;*              PORT_0
;*				PORT_1
;*
;*              A[1] - Sets one of four mode for a serial port enter values:
;*				MODE_0
;*				MODE_1
;*				MODE_2
;*				MODE_3
;*                          
;*  Output:   	None
;* 
;*  Destroys: 	A[0],A[1]
;*            
;*******************************************************************************/
serial_modeinput::
	cmp   #PORT_1			;check for serial port 1
	jump  NE, mode_port0
	move  SMD1_FEDE, #0		;function as SM0
	move  ACC,A[1]
	cmp   #MODE_3			;check for serial mode 3
	jump  NE, port1_mode2
	move  SCON1_SM0FE, #1	;set to serial mode 3
	move  SCON1_SM1, #1		
	ret
port1_mode2:
	cmp   #MODE_2			;check for serial mode 2
	jump  NE, port1_mode1
	move  SCON1_SM0FE, #1   ;set to serial mode 2
	move  SCON1_SM1, #0	
	ret
port1_mode1:
	cmp   #MODE_1			;check for serial mode 1
	jump  NE, port1_mode0
	move  SCON1_SM0FE, #0	;set to serial mode 1
	move  SCON1_SM1, #1	
	ret
port1_mode0:
	cmp   #MODE_0			;check for serial mode 0
	jump  NE, mode_exit
	move  SCON1_SM0FE, #0	;set to serial mode 0
	move  SCON1_SM1, #0	
	ret
mode_port0:
	cmp   #PORT_0			;check for serial port 0
	jump  NE, mode_exit
	move  SMD0_FEDE, #0		;function as SM0
	move  ACC,A[1]
	cmp   #MODE_3			;check for serial mode 3
	jump  NE, port0_mode2
	move  SCON0_SM0FE, #1	;set to serial mode 3
	move  SCON0_SM1, #1	
	ret
port0_mode2:
	cmp   #MODE_2			;check for serial mode 2
	jump  NE, port0_mode1
	move  SCON0_SM0FE, #1	;set to serial mode 2
	move  SCON0_SM1, #0	
	ret
port0_mode1:
	cmp   #MODE_1			;check for serial mode 1
	jump  NE, port0_mode0
	move  SCON1_SM0FE, #0	;set to serial mode 1
	move  SCON0_SM1, #1	
	ret
port0_mode0:
	cmp   #MODE_0			;check for serial mode 0
	jump  NE, mode_exit
	move  SCON1_SM0FE, #0	;set to serial mode 1
	move  SCON0_SM1, #0	
mode_exit:
	ret  

;********************************************************************************
;*  Function: 	serial_receive
;*  
;*  Descripton:	Allow User to ENABLE or DISABLE the serial receiver
;*  
;*  Input:      A[0] - Sets either serial port 0 or 1 using: 
;*              PORT_0
;*				PORT_1
;*
;*            	A[1] - Sets either ENABLE or DISABLE serial receiver by entering:
;*				ENABLE
;*				DISABLE
;*  
;*  Output:   	None
;*  
;*  Destroys: 	A[0],A[1]
;*  
;********************************************************************************              
serial_receiver::
	cmp   #PORT_1					;check for serial port 1
	jump  NE, receive_port0
	move  ACC,A[1]
	cmp   #ENABLE					;check to enable receive
	jump  NE, port1_receive_disable
	move  SCON1_REN, #1				;port 1 receive enable
	ret
port1_receive_disable:
	cmp	  #DISABLE					;check to disable receive
	jump  NE, receive_exit
	move  SCON1_REN, #0				;port 1 receive disable
	ret	
receive_port0:
	cmp	  #PORT_0					;check for serial port 0
	jump  NE, receive_exit			
	move  ACC,A[1]
	cmp   #ENABLE					;check to enable receive
	jump  NE, port0_receive_disable
	move  SCON0_REN, #1				;port 0 receive enable
	ret
port0_receive_disable:
	cmp	  #DISABLE					;check to disable receive
	jump  NE, receive_exit
	move  SCON0_REN, #0				;port 1 receive disable
receive_exit:
	ret  

;********************************************************************************
;*  Function: 	serial_clearinterrupt
;*  
;*  Descripton:	Allow User to clear the TRANSMIT and RECEIVE interrupt flags
;*  
;*  Input:      A[0] - Sets either serial port 0 or 1 using: 
;*              PORT_0
;*				PORT_1
;*
;*            	A[1] - Clears TI Transmit interrupt flag or RI Receive Interrupt 
;*              	   flag by entering: 
;*				TRANSMIT
;*				RECEIVE
;*  
;*  Output:   	None
;*  
;*  Destroys: 	A[0],A[1]
;*  
;********************************************************************************              
serial_clearinterrupt::
	cmp   #PORT_1						;check for serial port 1
	jump  NE, clearinterrupt_port0
	move  ACC,A[1]
	cmp	  #TRANSMIT						;check to clear transmit flag
	jump  NE, port1_clear_receive
	move  SCON1_TI, #0					;clear transmit flag
	ret
port1_clear_receive:
	cmp	  #RECEIVE						;check to clear receive flag
	jump  NE, clearinterrupt_exit
	move  SCON1_RI, #0					;clear receive flag
	ret
clearinterrupt_port0:
	cmp   #PORT_0						;check for serial port 0
	jump  NE, clearinterrupt_exit
	move  ACC,A[1]
	cmp	  #TRANSMIT						;check to clear transmit flag
	jump  NE, port0_clear_receive
	move  SCON0_TI, #0					;clear transmit flag
	ret
port0_clear_receive:
	cmp	  #RECEIVE						;check to clear receive flag
	jump  NE, clearinterrupt_exit
	move  SCON0_RI, #0					;clear receive flag
clearinterrupt_exit:
	ret  
  
;********************************************************************************
;*  Function: 	serial_processormode
;*  
;*  Descripton:	Allow User to in mode 2 and 3 to ENABLE/DISABLE MULTI processor 
;*      		communication
;*  
;*  Input:      A[0] - Sets either serial port 0 or 1 using: 
;*              PORT_0
;*				PORT_1
;*
;*				A[1] - Sets the SM2 Serial Port Mode by entering:
;*				SINGLE
;*				MULTI
;*  
;*  Output:   	None
;*  
;*  Destroys: 	A[0],A[1]
;*  
;********************************************************************************
serial_processormode::
	cmp   #PORT_1					;check for serial port 1
	jump  NE, processormode_port0
	move  ACC,A[1]
	cmp	  #SINGLE					;check for single prossor mode
	jump  NE, port1_multi
	move  SCON1_SM2, #0				;set single processor in mode 2 and 3
	ret
port1_multi:
	cmp	  #MULTI					;check for mulit processor mode
	jump  NE, processormode_exit
	move  SCON1_SM2, #1				;set multi processor in mode 2 and 3
	ret
processormode_port0:
	cmp   #PORT_0					;check for serial port 0
	jump  NE, processormode_exit
	move  ACC,A[1]
	cmp	  #SINGLE					;check for single prossor mode
	jump  NE, port0_multi
	move  SCON0_SM2, #0				;set single processor in mode 2 and 3
	ret
port0_multi:
	cmp	  #MULTI					;check for mulit processor mode
	jump  NE, processormode_exit
	move  SCON0_SM2, #1				;set multi processor in mode 2 and 3
processormode_exit:
	ret    
;********************************************************************************
;*  Function: 	serial_divideclock
;*  
;*  Descripton:	Allow User to in mode 0 to divide system clock by 12 or 4.
;*   
;*  Input:      A[0] - Sets either serial port 0 or 1 using: 
;*              PORT_0
;*				PORT_1
;*
;*				A[1] - To divided system clock type
;*				DIV12
;*				DIV4
;*  
;*  Output:   	None
;*  
;*  Destroys: 	A[0],A[1]
;*  
;******************************************************************************** 
serial_divideclock::
	cmp   #PORT_1					;check for serial port 1
	jump  NE, divideclock_port0
	move  ACC,A[1]
	cmp	  #DIV12					;check for system clock divide 12
	jump  NE, port1_div4
	move  SCON1_SM2, #0				;set divide system clock by 12
	ret
port1_div4:
	cmp	  #DIV4						;check for system clock divide 4
	jump  NE, divideclock_exit
	move  SCON1_SM2, #1				;set divide system clock by 4
	ret
divideclock_port0:
	cmp   #PORT_0					;check for serial port 0
	jump  NE, divideclock_exit
	move  ACC,A[1]
	cmp	  #DIV12					;check for system clock divide 12
	jump  NE, port0_div4
	move  SCON0_SM2, #0				;set divide system clock by 12
	ret
port0_div4:
	cmp	  #DIV4						;check for system clock divide 4
	jump  NE, processormode_exit
	move  SCON0_SM2, #1				;set divide system clock by 4
divideclock_exit:
	ret     
    
;********************************************************************************
;*  Function: 	serial_senddata
;*  
;*  Descripton:	Allow User to send a character via the serial port, wait for the 
;*      		TRANSMIT interrupt and clears the TRANSMIT interrupt.
;*  
;*  Input:      A[0] - Sets either serial port 0 or 1 using: 
;*              PORT_0
;*				PORT_1
;*
;*            	A[1] - is used to clear transmit flag (no input requried) 
;*
;*            	A[2] - send data by entering character 
;*  
;*  Output:   	None
;*  
;*  Destroys: 	A[0],A[1],A[2]
;*  
;********************************************************************************  
serial_senddata::
	cmp   #PORT_1					;check for serial port 1
	jump  NE, senddata_port0
	move  SBUF1,A[2]				;load tranmit buffer
port1_TI_wait:
	move  ACC, SCON1				;Load SCON1 to get SCON1_TI Transmit flag
	move  C, ACC.1					;Move SCON_TI Transmit flag to carry flag
	jump  NC, port1_TI_wait		    ;check transmit flag and wait
	move  A[0], #PORT_1
	move  A[1], #TRANSMIT			;load transmit argument
	call  serial_clearinterrupt		;clear transmit flag
	ret	
senddata_port0:
	cmp   #PORT_0					;check for serial port 0
	jump  NE, senddata_exit
	move  SBUF0,A[2]				;load transmit buffer
port0_TI_wait:
	move  ACC, SCON0				;Load SCON1 to get SCON1_TI Transmit flag
	move  C, ACC.1					;Move SCON_TI Transmit flag to carry flag
	jump  NC, port0_TI_wait		    ;check transmit flag and wait
	move  A[0], #PORT_0
	move  A[1], #TRANSMIT			;load transmit argument
	call  serial_clearinterrupt		;clear transmit flag
senddata_exit:
	ret    
;********************************************************************************
;*  Function: 	serial_receivedata
;*  
;*  Descripton:	Allow User to RECEIVE a character via the serial port, wait for 
;*      		the RECEIVE interrupt and clears the interrupt.
;*   
;*  Input:      A[0] - Sets either serial port 0 or 1 using: 
;*              PORT_0
;*				PORT_1
;*
;*            	A[1] - is used to clear receive flag (no input requried) 
;*
;*            	A[2] - RECEIVE data by reading a character 
;*  
;*  
;*  Output:   	A[2]
;*  
;*  Destroys: 	A[0],A[1],A[2]
;*  
;********************************************************************************  
serial_receivedata::
	move  A[2], #0					;clear A[2]
	cmp   #PORT_1					;check for serial port 1
	jump  NE, receivedata_port0
port1_RI_wait:
	move  ACC, SCON1				;Load SCON1 to get SCON1_RI Receive flag
	move  C, ACC.0					;Move SCON1_RI Receive flag to Carry Flag
	jump  NC, port1_RI_wait			;check and wait for receive flag
	move  A[2], SBUF1				;store byte into A[2]
	move  A[1], #RECEIVE			;load RECEIVE argument
	move  A[0], #PORT_1
	call  serial_clearinterrupt		;clear RECEIVE flag
	ret
receivedata_port0:
	cmp   #PORT_0					;check for serial port 0
	jump  NE, receivedata_exit
port0_RI_wait:
	move  ACC, SCON0				;Load SCON0 to get SCON0_RI Receive flag
	move  C, ACC.0					;Move SCON0_RI Receive flag to Carry Flag
	jump  NC, port0_RI_wait			;check and wait for receive flag
	move  A[2], SBUF0				;store byte into A[2]
	move  A[1], #RECEIVE			;load RECEIVE argument
	move  A[0], #PORT_0				
	call  serial_clearinterrupt		;clear RECEIVE flag
receivedata_exit:
	ret  
;********************************************************************************
;*  Function: 	serial_enadisinterrupts
;*  
;*  Descripton:	Allow User to enable or disables serial port interrupt
;*   
;*  Input:      A[0] - Sets either serial port 0 or 1 using: 
;*              PORT_0
;*				PORT_1
;*
;*				A[1] - enables or disables interrupts using:
;*				ENABLE 
;*				DISABLE
;*  
;*  Output:   	None
;*  
;*  Destroys: 	A[0],A[1]
;*  
;********************************************************************************  
serial_enadisinterrupts::                              
	cmp   #PORT_1						;check for serial port 1
	jump  NE, enadisinterrupts_port0
	move  ACC,A[1]
	cmp	  #DISABLE						;check to disable interrupt
	jump  NE, port1_ena_interrupt
	move  SMD1_ESI, #0					;disable serial interrupt
	ret
port1_ena_interrupt:
	cmp	  #ENABLE						;check to enable interrupt
	jump  NE, enadisinterrupts_exit
	move  SMD1_ESI, #1					;enable serial interrupt
	ret
enadisinterrupts_port0:
	cmp   #PORT_0						;check for serial port 0
	jump  NE, enadisinterrupts_exit
	move  ACC,A[1]
	cmp	  #DISABLE						;check to disable interrupt
	jump  NE, port0_ena_interrupt
	move  SMD0_ESI, #0					;disable serial interrupt
	ret
port0_ena_interrupt:
	cmp	  #ENABLE						;check to enable interrupt
	jump  NE, enadisinterrupts_exit
	move  SMD0_ESI, #1					;enable serial interrupt
enadisinterrupts_exit:
	ret

;********************************************************************************
;*  Function: 	serial_dividebaud
;*  
;*  Descripton:	Allow User to in mode 1 to divide baudrate by 16 or 64.
;*   
;*  Input:      A[0] - Sets either serial port 0 or 1 using: 
;*              PORT_0
;*				PORT_1
;*
;*				A[1] - To divided baudrate type
;*				DIV16
;*				DIV64
;*  
;*  Output:   	None
;*  
;*  Destroys: 	A[0],A[1]
;*  
;******************************************************************************** 
serial_dividebaud::
	cmp   #PORT_1					;check for serial port 1
	jump  NE, dividebaud_port0
	move  ACC,A[1]
	cmp	  #DIV16					;check for baudrate divide 16
	jump  NE, port1_div64
	move  SMD1_SMOD, #1				;set divide baudrate by 16
	ret
port1_div64:
	cmp	  #DIV64					;check for baudrate divide 64
	jump  NE, dividebaud_exit
	move  SMD1_SMOD, #0				;set divide baudrate by 64
	ret
dividebaud_port0:
	cmp   #PORT_0					;check for serial port 0
	jump  NE, dividebaud_exit
	move  ACC,A[1]
	cmp	  #DIV16					;check for baudrate divide 16
	jump  NE, port0_div64
	move  SMD0_SMOD, #1				;set divide baudrate by 16
	ret
port0_div64:
	cmp	  #DIV64					;check for baudrate divide 64
	jump  NE, processormode_exit
	move  SMD0_SMOD, #0				;set divide baudrate by 64
dividebaud_exit:
	ret                              
end
