please dont rip this site

SX RS232 Serial IO

UART with Parity

Peter Verkaik says:

Unable to find an existing uart for 8 databits + parity I wrote one myself. I saw a few posts on the basic stamp forum about this so I share this. It is an assembly source.

The program itself contains more than just the uart as it is written as a template to be extended for applications.

;*****************************************************************************************
; ELX1 board, co-procesor template
; ----------------------------------------------------------------------------------------
;
; version 0.9 beta
; december 9, 2004
; compile with SASM
;
; Author: Peter Verkaik
; Email: peterverkaik@boselectro.nl
;
; This program is a SX28 template providing a 2-wire host interface (halfduplex serial line +
; write enable line used for synchronization), and a 2-wire serial interface for terminal or
; other serial device. This terminal interface can be configured at runtime for:
;	TX/RX with or without xon/xoff handshake, TX only with CTS handshake, RX only with RTS handshake
;	four selectable baudrates (default 1200,2400,9600,19200)
;	7 or 8 databits
;	parity odd, even or none
;	powerup default is TX/RX without handshake, 1200 baud, 8 databits, no parity
; Port A is dedicated to the host and terminal.
; Ports B and C are not used and are available for the application.
; Code pages 2 and 3 are empty
; Ram banks 4, 5, 6 and 7 are empty
; 5 free global ram bank bytes
; four 8-byte buffers for terminal and host uarts
; Host command interface is expandable for up to 128 commands
;
;*****************************************************************************************
; Connection diagram. Both wires should have 4.7k-10k pullup resistor.
;
; MCU            co-processor (this device)
; -------+      +------------------------+
;        |      |                        |
;  pinWE o------o RA.1 = /WE             |
;  pinDQ o------o RA.0 = DQ              |
;        |      |              RC.0-RC.7 o-- application
; -------+      |              RB.0-RB.7 o-- application
;               |                        |
;               |                   RA.2 o-- terminal TX (or RTS in case of RX/RTS)
;               |                   RA.3 o-- terminal RX (or CTS in case of TX/CTS)
;               +------------------------+
;
;*****************************************************************************************
; Communication protocol between this device and the host MCU.
;
;      ------+                         +-+                             +------+-----
; pinWE  S0  |  S1 |       S2          | | S3  |       S4              |  S5  |  S0
;            +-----+-------------------+ +-----+-----------------------+
;            <--- pulled low by MCU ---> <- pulled low by this device ->
;
;      ------+                         +-+                             +------+-----
; pinDQ       <cmd> <param1>...<paramN>   <rsp>    <data1>...<dataN>
;      - hiZ +- - - - - input - - - - -+-+ - - - - output - - - - - - -+ - - hiZ - -
;
; State S0: idle
; State S1: receive command byte
; State S2: receive parameter bytes
; State S3: transmit response byte
; State S4: transmit data bytes
; State S5: finalize
;
; Each command sequence starts at the H->L transition on pinWE.
; This may be follwed by <cmd> and <param> bytes.
; A L->H transition on pinWE (from MCU) is ALWAYS follewed by
; a H->L transition and <rsp>.
; <data> bytes are optional and determined by command or status.
; The command sequence stops after this device releases pinWE.
;
;-----------------------------------------------------------------------------------------
; program modules
;-----------------------------------------------------------------------------------------
device				SX28,oschs1,turbo,stackx,optionx	;sx device options
irc_cal				IRC_SLOW
id				'ELX1TMPL'				;Elx1 board template
reset				reset_entry				;set reset vector
;select one of these freq
;freq				4_000_000
;freq				10_000_000
freq				20_000_000
;select according to freq
;RESONATOR		equ	4
;RESONATOR		equ	10
RESONATOR		equ	20


ERROR p2w 'Assembled assuming a ' RESONATOR ' MHz oscillator'
; The host interface (pins ra.0 and ra.1) is used to accept commands and data
; from a host mcu and delivers status and data to that mcu.


; The terminal interface (pins ra.2 and ra.3) is used to accept key input from a terminal(program)
; and delivers display/control characters to that terminal(program).


;-----------------------------------------------------------------------------------------
; uart constants
;-----------------------------------------------------------------------------------------


IF RESONATOR = 20
;128*1200=64*2400=32*4800=16*9600=8*19200
;uartfs=128*1200=153600
;int_period=20000000/153600=130
uartfs			equ	153600		; uart's basic frequency 128*1200 = 153600
int_period		equ	130		; 6.5uS used as seed for uart baud rate.
THREADS			equ	1
ENDIF


IF RESONATOR = 10
;64*1200=32*2400=16*4800=8*9600=4*19200
;uartfs=64*1200=76800
;int_period=10000000/76800=130
uartfs			equ	76800		; uart's basic frequency 64*1200 = 76800
int_period		equ	130		; 13uS used as seed for uart baud rate.
THREADS			equ	1
ENDIF


IF RESONATOR = 4
;32*1200=16*2400=8*4800=4*9600=2*19200
;uartfs=32*1200=38400
;int_period=4000000/38400=104
uartfs			equ	38400		; uart's basic frequency 32*1200 = 38400
int_period		equ	104		; 26uS used as seed for uart baud rate.
THREADS			equ	1
ENDIF


mscount			equ	((2000*RESONATOR/int_period)+1)/2	;number of int cycles for 1 msec
ERROR p2w '# of cycles per interrupt = ' mscount




XON			equ	17		;XON character (ctrl-Q)
XOFF			equ	19		;XOFF character (ctrl-S)


;The following baudrates are available


baud0			equ	1200
baud1			equ	2400
baud2			equ	4800
baud3			equ	9600
baud4			equ	19200
								; 20MHz  10MHz  4MHz
divide0			equ	uartfs / (baud0 * THREADS)	; 128    64     32
StDelay0 		equ	divide0 + (divide0 / 2)		; 192    96     48


divide1			equ	uartfs / (baud1 * THREADS)	;  64    32     16
StDelay1 		equ	divide1 + (divide1 / 2)		;  96    48     24


divide2			equ	uartfs / (baud2 * THREADS)	;  32    16      8
StDelay2 		equ	divide2 + (divide2 / 2)		;  48    24     12


divide3			equ	uartfs / (baud3 * THREADS)	;  16     8      4
StDelay3 		equ	divide3 + (divide3 / 2)		;  24    12      6


divide4			equ	uartfs / (baud4 * THREADS)	;   8     4      2
StDelay4 		equ	divide4 + (divide4 / 2)		;  12     6      3


hostDivide		equ	divide3		;baud used by host
hostStDelay		equ	StDelay3


;-----------------------------------------------------------------------------------------
; Pin definitions & Port assignments
;-----------------------------------------------------------------------------------------


;host and term pin definitions


hostDQ			equ	0
hostWE			equ	1
pinDQ			equ	ra.hostDQ	;host uart transmit/receive
pinWE			equ	ra.hostWE	;host write enable input


termTX			equ	2
termRX			equ	3
pinTX			equ	ra.termTX	;term uart transmit
pinRX			equ	ra.termRX	;term uart receive


; ra changes output level by changing direction register!! Never drive output high!!
RA_latch		equ	%00000000	;port A output latch init	1=high	0=low
RA_tris			equ	%11111111	;port A direction register	1=input	0=output
RA_plp			equ	%00000000	;port A pull up register	1=off	0=on
RA_lvl			equ	%11111111	;port A level register		1=ttl	0=cmos


; rb changes output level by changing direction register!! Never drive output high!!
RB_latch		equ	%00000000	;port B output latch			1=high	0=low
RB_tris			equ	%11111111	;port B direction register		1=input	0=output
RB_plp			equ	%00000000	;port B pull up register		1=off	0=on
RB_lvl			equ	%00000000	;port B level register			1=ttl	0=cmos
RB_st			equ	%11111111	;port B schmitt trigger register	1=off	0=on
RB_wken			equ	%11111111	;port B wake up enable register		1=off	0=on	** KEEP OFF
RB_wked			equ	%11111111	;port B wake up edge register		1=neg	0=pos


; rc changes output level by changing direction register!! Never drive output high!!
RC_latch		equ	%00000000	;port C output latch			1=high	0=low
RC_tris			equ	%11111111	;port C direction register		1=input	0=output
RC_plp			equ	%00000000	;port C pull up register		1=off	0=on
RC_lvl			equ	%11111111	;port C level register			1=ttl	0=cmos
RC_st			equ	%11111111	;port C schmitt trigger register	1=off	0=on


;-----------------------------------------------------------------------------------------
; Code Locations
;-----------------------------------------------------------------------------------------
CODEPAGE_0		equ	$0
CODEPAGE_1		equ	$200
CODEPAGE_2		equ	$400
CODEPAGE_3		equ	$600


;-----------------------------------------------------------------------------------------
; Data Memory address definitions
;-----------------------------------------------------------------------------------------
global_org		equ	$08
bank0_org		equ	$10
bank1_org		equ	$30
bank2_org		equ	$50
bank3_org		equ	$70
bank4_org		equ	$90
bank5_org		equ	$B0
bank6_org		equ	$D0
bank7_org		equ	$F0


;-----------------------------------------------------------------------------------------
; Global Register definitions
;-----------------------------------------------------------------------------------------
			org     global_org


temp			ds	1		;for temporary use (buffers, calculation)
ra_dir_buf		ds	1		;holds value for ra direction register


status_flags		ds	1
  cmd_invalid		equ	status_flags.0	;set if command invalid
  cmd_parameter_missing	equ	status_flags.1	;set if missing parameter
  buffer_overrun	equ	status_flags.2	;set if any buffer overrun
  term_parity_error	equ	status_flags.3	;set if parity error


free_global		ds	5


;-----------------------------------------------------------------------------------------
; RAM Bank Register definitions
;-----------------------------------------------------------------------------------------


	; Bank 0 - host uart bank, timer bank
	;---------------------------------------------------------------------------------
			org     bank0_org


hu_bank			=	$		;host uart bank
hu_rx_count		ds	1		;number of bits to receive
hu_rx_divide		ds	1		;receive timing counter
hu_rx_byte		ds	1		;received byte
hu_tx_count		ds	1		;number of bits to transmit
hu_tx_divide		ds	1		;transmit timing counter
hu_tx_low		ds	1		;low byte to transmit
hu_tx_high		ds	1		;high byte to transmit
hu_head			ds	1		;hinib=tx, lonib=rx: index of next free entry in buf
hu_tail			ds	1		;hinib=tx, lonib=rx: index of next byte to read from buf
hu_num			ds	1		;hinib=tx, lonib=rx: number of bytes in buf
  hu_rx_full		equ	hu_num.3	;  set if hu_rx full (num=8)
  hu_tx_full		equ	hu_num.7	;  set if hu_tx full (num=8)
hu_flags		ds	1
  hu_rx_data		equ	hu_flags.0	;set if hu_rx not empty
  hu_rx_overrun		equ	hu_flags.1	;set if hu_rx overruns
  hu_rx_enable		equ	hu_flags.2	;set to enable host uart receive
  hu_rx_flag		equ	hu_flags.3	;set if byte in hu_rx_byte
  hu_tx_data		equ	hu_flags.4	;set if hu_tx not empty
  hu_tx_overrun		equ	hu_flags.5	;set if hu_tx overruns
  hu_tx_enable		equ	hu_flags.6	;set to enable host uart transmit
  hu_tx_flag		equ	hu_flags.7	;not used
hu_state		ds	1		;host state
						;  b2-b0: state of host_command_task routine
  pinWE_present		equ	hu_state.6	;  current state of pinWE
  pinWE_past		equ	hu_state.7	;  past state of pinWE
hu_command		ds	1		;received host command
  cmd_done		equ	hu_command.7	;  set if command finished


timer_bank		=	$
timer_int		ds	1		;increments every isr
timer_1m		ds	1		;decrements every msec


free_bank0		ds	1


	; Bank 1 - term uart bank
	;---------------------------------------------------------------------------------
			org	bank1_org


tu_bank			=	$		;term uart bank
tu_rx_count		ds	1		;number of bits to receive
tu_rx_divide		ds	1		;receive timing counter
tu_rx_byte		ds	1		;received byte
tu_tx_count		ds	1		;number of bits to transmit
tu_tx_divide		ds	1		;transmit timing counter
tu_tx_low		ds	1		;low byte to transmit
tu_tx_high		ds	1		;high byte to transmit
tu_head			ds	1		;hinib=tx, lonib=rx: index of next free entry in buf
tu_tail			ds	1		;hinib=tx, lonib=rx: index of next byte to read from buf
tu_num			ds	1		;hinib=tx, lonib=rx: number of bytes in buf
  tu_rx_full		equ	tu_num.3	;  set if tu_rx full (num=8)
  tu_tx_full		equ	tu_num.7	;  set if tu_tx full (num=8)
tu_flags		ds	1
  tu_rx_data		equ	tu_flags.0	;set if tu_rx not empty
  tu_rx_overrun		equ	tu_flags.1	;set if tu_rx overruns
  tu_rx_enable		equ	tu_flags.2	;set if transmitted XON, cleared if transmitted XOFF
  tu_rx_flag		equ	tu_flags.3	;set if byte in tu_rx_byte
  tu_tx_data		equ	tu_flags.4	;set if tu_tx not empty
  tu_tx_overrun		equ	tu_flags.5	;set if tu_tx overruns
  tu_tx_enable		equ	hu_flags.6	;set if received XON, cleared if received XOFF
  tu_rx_parity		equ	tu_flags.7	;received parity bit
tu_state		ds	1		;term state (not implemented)
tu_command		ds	1		;received term command (not implemented)
tu_config		ds	1		;terminal configuration
						;  b1-b0 = baud (1200,2400,9600,19200)
  tu_rts		equ	tu_config.2	;  1 for rts handshake (TX used as RTS)
  tu_cts		equ	tu_config.3	;  1 for cts handshake (RX used as CTS)
  tu_xonxoff		equ	tu_config.4	;  1 for xon/xoff handshake (inter-character delay must be 1 msec at 9600 baud)
  tu_7bits		equ	tu_config.5	;  1 for 7 databits (0 = 8 databits)
  tu_parity_even	equ	tu_config.6	;  1 for even parity
  tu_parity_odd		equ	tu_config.7	;  1 for odd parity
tu_char			ds	1		;save received byte here
tu_bits			ds	1		;number of bits (startbit+databits+paritybit+stopbit)
						;  set by command TM_SET_CONFIG (bits is 9, 10 or 11)


	; Bank 2 - host uart buffers
	;---------------------------------------------------------------------------------
			org     bank2_org


hu_buf_bank		=	$
hu_rx_buf		ds	8
hu_tx_buf		ds	8


	; Bank 3 - term uart buffers
	;---------------------------------------------------------------------------------
			org	bank3_org


tu_buf_bank		=	$
tu_rx_buf		ds	8
tu_tx_buf		ds	8


	; Bank 4 - 
	;---------------------------------------------------------------------------------
			org	bank4_org


free_bank4		ds	16


	; Bank 5 - 
	;---------------------------------------------------------------------------------
			org	bank5_org


free_bank5		ds	16


	; Bank 6 - 
	;---------------------------------------------------------------------------------
			org     bank6_org


free_bank6		ds	16


	; Bank 7 - 
	;---------------------------------------------------------------------------------
			org     bank7_org


free_bank7		ds	16


;-------------- end of ram variables -----------------------------------------------------




;*****************************************************************************************
			org	CODEPAGE_0
;*****************************************************************************************




;-----------------------------------------------------------------------------------------
; Interrupt Service Routine
;-----------------------------------------------------------------------------------------


interrupt		jmp	_interrupt		;1


	; hooks for application
	;---------------------------------------------------------------------------------
app_isr			retp				;change to jmp @myapp_isr if any
app_main		retp				;change to jmp @myapp_main if any


	; jump table for template
	;---------------------------------------------------------------------------------
enqueue_hu_tx		jmp	_enqueue_hu_tx		;store byte for output to host
enqueue_hu_rx		jmp	_enqueue_hu_rx		;store byte received from host
dequeue_hu_tx		jmp	_dequeue_hu_tx		;retrieve byte for output to host
dequeue_hu_rx		jmp	_dequeue_hu_rx		;retrieve byte received from host
enqueue_tu_tx		jmp	_enqueue_tu_tx		;store byte for output to terminal
enqueue_tu_rx		jmp	_enqueue_tu_rx		;store byte received from terminal
dequeue_tu_tx		jmp	_dequeue_tu_tx		;retrieve byte for output to terminal
dequeue_tu_rx		jmp	_dequeue_tu_rx		;retrieve byte received from terminal
host_input_task		jmp	_host_input_task	;receives host bytes into hu_rx_buf
host_output_task	jmp	_host_output_task	;transmit host bytes from hu_tx_buf


	; get term baud parameters as determined by tu_config.0 and tu_config.1
	;---------------------------------------------------------------------------------
tu_divide
			mov	w,tu_config
			and	w,#$03
			add	pc,w
			retw	divide0			;1200
			retw	divide1			;2400
			retw	divide3			;9600
			retw	divide4			;19200


tu_StDelay
			mov	w,tu_config
			and	w,#$03
			add	pc,w
			retw	StDelay0		;1200
			retw	StDelay1		;2400
			retw	StDelay3		;9600
			retw	StDelay4		;19200


	; host command task
	; Wait for a command received from host MCU,
	; execute command and transmit results to host MCU.
	;---------------------------------------------------------------------------------


STATE_IDLE		equ	0
STATE_RECEIVE_COMMAND	equ	1
STATE_RECEIVE_PARAMETER	equ	2
STATE_TRANSMIT_RESPONSE	equ	3
STATE_TRANSMIT_DATA	equ	4
STATE_FINALIZE		equ	5


host_command_task
			call	@checkPinWE		;check for edges
			bank	hu_bank
			mov	w,hu_state
			and	w,#$07
			add	pc,w
			jmp	hostIdle		;0
			jmp	hostReceiveCommand	;1
			jmp	hostReceiveParameter	;2
			jmp	hostTransmitResponse	;3
			jmp	hostTransmitData	;4
			jmp	hostFinalize		;5
			jmp	hostIdle		;6 failsafe
			jmp	hostIdle		;7 failsafe


hostIdle
			clrb	hu_rx_enable
			clrb	hu_tx_enable
			setb	ra_dir_buf.hostDQ
			setb	ra_dir_buf.hostWE
			retp


hostReceiveCommand
			sb	hu_rx_data		;any received data?
			retp				;no
			call	dequeue_hu_rx
			mov	hu_command,w		;this is command
			mov	w,#$7F
			snb	cmd_done
			mov	hu_command,w		;make command $7F if b7 is set
			clrb	cmd_invalid
			clrb	term_parity_error
			setb	cmd_parameter_missing	;cleared by function
			call	@host_command_handler	;execute command
			bank	hu_bank
			inc	hu_state		;move to next state
			retp


hostReceiveParameter
			sb	hu_rx_data		;any received data?
			retp				;no
			jmp	@host_command_handler	;execute command


hostTransmitResponse
			clrb	ra_dir_buf.hostWE	;this device pulls pinWE low
			mov	w,hu_flags
			and	w,#$22			;extract overrun flags
			sz
			setb	buffer_overrun
			bank	tu_bank
			mov	w,tu_flags
			and	w,#$22			;extract overrun flags
			sz
			setb	buffer_overrun
			mov	w,status_flags		;transmit status flags
			call	enqueue_hu_tx
			clrb	hu_rx_overrun
			clrb	hu_tx_overrun
			inc	hu_state		;move to next state
			bank	tu_bank
			clrb	tu_rx_overrun
			clrb	tu_tx_overrun
			clrb	buffer_overrun
			retp


hostTransmitData
			snb	hu_tx_data		;output buffer empty?
			retp				;no
			call	@host_command_handler	;get next data
			bank	hu_bank
			snb	cmd_done		;all done?
			inc	hu_state		;yes, move to next state
			retp


hostFinalize
			snb	hu_tx_data		;output buffer empty
			retp				;no
			test	hu_tx_count		;transmitter ready?
			sz
			retp				;no
			clrb	hu_tx_enable		;disable transmitter
			setb	ra_dir_buf.hostWE	;release pinWE
			and	hu_state,#$C0		;wait for new command
			retp


;-------------- start of the Interrupt Service Routines ----------------------------------
_interrupt


	; Update timers
	;---------------------------------------------------------------------------------
inc_timer
			bank	timer_bank
			inc	timer_int		;increments every isr
			cjne	timer_int,#mscount,:it_done	; isr cycles for 1 msec
			clr	timer_int
			dec	timer_1m		;decrements every msec
:it_done
inc_timer_done


			call	app_isr			;call application isr routines


	; Update ra with buffered data
	;---------------------------------------------------------------------------------
			mov	w,ra_dir_buf
			mov	!ra,w


	; Run uarts
	;---------------------------------------------------------------------------------


hostVP
			bank	hu_bank


	;host uart receive				;receive only when enabled


			jnb	hu_rx_enable,:hu_rx_done
:receive
	        	sb	pinDQ			; get current rx bit
	        	clc 
	        	snb	pinDQ
	        	stc
			test	hu_rx_count		; currently receiving byte?
			sz 
			jmp	:hur1               	; if so, jump ahead
			mov	w,#9			; in case start, ready 9 bits
			sc				; skip ahead if not start bit
			mov	hu_rx_count,w		; it is, so renew bit count
			mov	w,#hostStDElay
			mov	hu_rx_divide,w 
:hur1
			decsz	hu_rx_divide		; middle of next bit?
          		jmp	:hu_rx_done
			dec	hu_rx_count		; last bit?
			sz				; if not
			rr      hu_rx_byte		;  then save bit
			jnz	:hur2			;  and exit
			setb	hu_rx_flag
:hur2
			mov	w,#hostDivide
			mov	hu_rx_divide,w
:hu_rx_done


	;host uart transmit				;transmit only when enabled


			jnb	hu_tx_enable,:hu_tx_done
:transmit
			decsz	hu_tx_divide		; only execute the transmit routine
			jmp	:hu_tx_done 
			mov	w,#hostDivide
			mov	hu_tx_divide,w
			test    hu_tx_count		; are we sending?
			snz
			jmp	:hu_tx_done
			clc				; yes, ready stop bit
			rr	hu_tx_high		;  and shift to next bit
			rr	hu_tx_low
			dec	hu_tx_count		; decrement bit counter
			snb	hu_tx_low.6		; output next bit
			clrb	ra_dir_buf.hostDQ	; update term_port_buf state
			sb	hu_tx_low.6		; (pin change state occurs next interrupt)
			setb	ra_dir_buf.hostDQ
:hu_tx_done


termVP
			bank	tu_bank


	;term uart receive


			jb	tu_cts,:term_rxdone	;only receive if rx is not cts
:receive
	        	sb	pinRX			; get current rx bit
	        	clc
	        	snb	pinRX
	        	stc
			test	tu_rx_count		; currently receiving byte?
			sz
			jmp	:term_rx1		; ;if so, jump ahead
			mov	w,--tu_bits		; in case start, ready bits
			sc				; skip ahead if not start bit
			mov     tu_rx_count,w		; it is, so renew bit count
			call	tu_StDelay
			mov     tu_rx_divide,w
:term_rx1
			decsz	tu_rx_divide		; middle of next bit?
          		jmp	:term_rxdone
			dec     tu_rx_count		; last bit?
			jz	:term_rx2		;   if not
			rr      tu_rx_byte		;   then save bit
			movb	tu_rx_parity,C		;   and save b0
			jmp	:term_rx3		;   and exit
:term_rx2
			movb	C,tu_rx_parity		;get last saved b0
			movb	tu_rx_parity,tu_rx_byte.7	;save possible parity bit
			sb	tu_bits.1
			rr	tu_rx_byte		;adjust for 7 databits + no parity (tu_bits=9)
			sb	tu_bits.1
			rr	tu_rx_byte
			snb	tu_bits.0
			rl	tu_rx_byte		;adjust for 8 databits + parity (tu_bits=11)
			snb	tu_7bits
			clrb	tu_rx_byte.7		;clear b7 for 7 databits
			mov	w,tu_rx_byte		;save byte to allow receive another byte
			mov	tu_char,w		;  while processing this one
			setb	tu_rx_flag		;mark byte received
:term_rx3
			call	tu_divide
			mov	tu_rx_divide,w
:term_rxdone


	;term uart transmit


			jb	tu_rts,:term_txdone	;only transmit if tx is not rts
:transmit
			decsz	tu_tx_divide		; only execute the transmit routine
			jmp	:term_txdone
			call	tu_divide
			mov	tu_tx_divide,w
			test    tu_tx_count		; are we sending?
			snz
			jmp	:term_txdone
			clc				; yes, ready stop bit
			rr	tu_tx_high		;  and shift to next bit
			rr	tu_tx_low
			dec	tu_tx_count		; decrement bit counter
			snb	tu_tx_low.5		; output next bit
			clrb	ra_dir_buf.termTX	; update term_port_buf state
			sb	tu_tx_low.5		; (pin change state occurs next interrupt)
			setb	ra_dir_buf.termTX
:term_txdone


	; Set Interrupt Rate
	;---------------------------------------------------------------------------------
isr_end
			mov	w,#(-int_period)&$FF	; refresh RTCC on return
			retiw				; return from the interrupt


;-------------- end of the Interrupt Service Routines ------------------------------------


	;RESET VECTOR	Program execution begins here on power-up or after a reset
	;---------------------------------------------------------------------------------
reset_entry


	; Initialise all port configuration
	;---------------------------------------------------------------------------------
M_WKED			equ	$0A
M_WKEN			equ	$0B
M_ST			equ	$0C
M_LVL			equ	$0D
M_PLP			equ	$0E
M_TRIS			equ	$0F


			mov	m,#M_WKED		; point mode to WKED
			mov	!rb,#RB_wked
			mov	m,#M_WKEN		; point mode to WKEN
			mov	!rb,#RB_wken
			mov	m,#M_ST			; point mode to ST
			mov	!rc,#RC_st
			mov	!rb,#RB_st
			mov	m,#M_LVL		; point mode to LVL
			mov	!rc,#RC_lvl
			mov	!rb,#RB_lvl
			mov	!ra,#RA_lvl
			mov	m,#M_PLP		; point mode to PLP
			mov	!rc,#RC_plp
			mov	!rb,#RB_plp
			mov	!ra,#RA_plp
			mov	rc,#RC_latch		; init latches
			mov	rb,#RB_latch
			mov	ra,#RA_latch
			mov	m,#M_TRIS		; point mode to TRIS
			mov	!rc,#RC_tris
			mov	!rb,#RB_tris
			mov	!ra,#RA_tris


	; Clear all Data RAM locations
	;---------------------------------------------------------------------------------
			mov	fsr,#global_org
:zero_global
			clr	indf
			inc	fsr
			cjne	fsr,#$10,:zero_global
:zero_ram
			clr	indf
			inc	fsr
			jz	:zero_end
			setb	fsr.4
			jmp	:zero_ram
:zero_end


	; Initialize registers
	;---------------------------------------------------------------------------------
			mov	ra_dir_buf,#$FF
			bank	hu_bank
			mov	hu_state,#$C0	;pin levels high
			bank	tu_bank
			setb	tu_tx_enable	;enable transmit
			setb	tu_rx_enable	;enable receive
			mov	tu_bits,#10	;set correct bits for startup (8N1,1200)


	; Setup option register. 
	;---------------------------------------------------------------------------------
RTCC_ON			equ	%10000000	;Enables RTCC at address $01 (RTW hi)
						;*WREG at address $01 (RTW lo) by default
RTCC_ID			equ	%01000000	;Disables RTCC edge interrupt (RTE_IE hi)
						;*RTCC edge interrupt (RTE_IE lo) enabled by default
RTCC_INC_EXT		equ	%00100000	;Sets RTCC increment on RTCC pin transition (RTS hi)
						;*RTCC increment on internal instruction (RTS lo) is defalut
RTCC_FE			equ	%00010000	;Sets RTCC to increment on falling edge (RTE_ES hi)
						;*RTCC to increment on rising edge (RTE_ES lo) is default
RTCC_PS_ON		equ	%00000000	;Assigns prescaler to RTCC (PSA lo)
RTCC_PS_OFF		equ	%00001000	;Assigns prescaler to WDT (PSA hi)
PS_000			equ	%00000000	;RTCC = 1:2, WDT = 1:1
PS_001			equ	%00000001	;RTCC = 1:4, WDT = 1:2
PS_010			equ	%00000010	;RTCC = 1:8, WDT = 1:4
PS_011			equ	%00000011	;RTCC = 1:16, WDT = 1:8
PS_100			equ	%00000100	;RTCC = 1:32, WDT = 1:16
PS_101			equ	%00000101	;RTCC = 1:64, WDT = 1:32
PS_110			equ	%00000110	;RTCC = 1:128, WDT = 1:64
PS_111			equ	%00000111	;RTCC = 1:256, WDT = 1:128


			mov	w,#RTCC_PS_OFF	;setup option register
			mov	!option,w


	; Mainloop
	;---------------------------------------------------------------------------------
mainloop
			call	host_input_task		;handle host data input
			call	host_output_task	;handle host data output
			call	host_command_task	;handle host command
			call	@term_input_task	;handle keypad input
			call	@term_output_task	;handle display output
			call	app_main		;call application mainloop
			jmp	mainloop


	;put w into hu_tx_buf
	;---------------------------------------------------------------------------------


_enqueue_hu_tx
			bank	hu_bank
			snb	hu_tx_full
			setb	hu_tx_overrun
			snb	hu_tx_full
			retp
			mov	temp,w
			mov	w,<>hu_head
			and	w,#$0F
			mov	fsr,w			;calculate buffer address
			mov	w,#hu_tx_buf
			add	fsr,w
			mov	w,temp			;store received byte
			mov	indf,w
			bank	hu_bank
			add	hu_num,#16		;adjust byte count
			add	hu_head,#16
			clrb	hu_head.7		;wrap around head
			setb	hu_tx_data		;mark holding data
			retp


	;put w into hu_rx_buf
	;---------------------------------------------------------------------------------


_enqueue_hu_rx
			bank	hu_bank
			snb	hu_rx_full
			setb	hu_rx_overrun
			snb	hu_rx_full
			retp
			mov	temp,w
			mov	w,hu_head
			and	w,#$0F
			mov	fsr,w			;calculate buffer address
			mov	w,#hu_rx_buf
			add	fsr,w
			mov	w,temp			;store received byte
			mov	indf,w
			bank	hu_bank
			add	hu_num,#1		;adjust byte count
			add	hu_head,#1
			clrb	hu_head.3		;wrap around head
			setb	hu_rx_data		;mark holding data
			retp


	;get w from hu_tx_buf
	;---------------------------------------------------------------------------------


_dequeue_hu_tx
			bank	hu_bank
			sb	hu_tx_data
			retp
			mov	w,<>hu_tail		;get next byte from buffer
			and	w,#$0F
			mov	fsr,w
			mov	w,#hu_tx_buf
			add	fsr,w
			mov	w,indf
			mov	temp,w
			bank	hu_bank
			sub	hu_num,#16		;adjust byte count
			mov	w,<>hu_num
			and	w,#$0F
			snz
			clrb	hu_tx_data
			add	hu_tail,#16
			clrb	hu_tail.7		;wrap around tail
			mov	w,temp
			retp


	;get w from hu_rx_buf
	;---------------------------------------------------------------------------------


_dequeue_hu_rx
			bank	hu_bank
			sb	hu_rx_data		;test if any byte in buffer
			retp				;if not then exit
			mov	w,hu_tail		;get next byte from buffer
			and	w,#$0F
			mov	fsr,w
			mov	w,#hu_rx_buf
			add	fsr,w
			mov	w,indf
			mov	temp,w
			bank	hu_bank
			sub	hu_num,#1		;adjust byte count
			mov	w,hu_num
			and	w,#$0F
			snz
			clrb	hu_rx_data		;mark buffer empty
			add	hu_tail,#1
			clrb	hu_tail.3		;wrap around tail
			mov	w,temp
			retp


	;put w into tu_tx_buf
	;---------------------------------------------------------------------------------


_enqueue_tu_tx
			bank	tu_bank
			snb	tu_tx_full
			setb	tu_tx_overrun
			snb	tu_tx_full
			retp
			mov	temp,w
			mov	w,<>tu_head
			and	w,#$0F
			mov	fsr,w			;calculate buffer address
			mov	w,#tu_tx_buf
			add	fsr,w
			mov	w,temp			;store received byte
			mov	indf,w
			bank	tu_bank
			add	tu_num,#16		;adjust byte count
			add	tu_head,#16
			clrb	tu_head.7		;wrap around head
			setb	tu_tx_data		;mark holding data
			retp


	;put w into tu_rx_buf
	;---------------------------------------------------------------------------------


_enqueue_tu_rx
			bank	tu_bank
			snb	tu_rx_full
			setb	tu_rx_overrun
			snb	tu_rx_full
			retp
			mov	temp,w
			mov	w,tu_head
			and	w,#$0F
			mov	fsr,w			;calculate buffer address
			mov	w,#tu_rx_buf
			add	fsr,w
			mov	w,temp			;store received byte
			mov	indf,w
			bank	tu_bank
			add	tu_num,#1		;adjust byte count
			add	tu_head,#1
			clrb	tu_head.3		;wrap around head
			setb	tu_rx_data		;mark holding data
			retp


	;get w from tu_tx_buf
	;---------------------------------------------------------------------------------


_dequeue_tu_tx
			bank	tu_bank
			sb	tu_tx_data
			retp
			mov	w,<>tu_tail		;get next byte from buffer
			and	w,#$0F
			mov	fsr,w
			mov	w,#tu_tx_buf
			add	fsr,w
			mov	w,indf
			mov	temp,w
			bank	tu_bank
			sub	tu_num,#16		;adjust byte count
			mov	w,<>tu_num
			and	w,#$0F
			snz
			clrb	tu_tx_data
			add	tu_tail,#16
			clrb	tu_tail.7		;wrap around tail
			mov	w,temp
			retp


	;get w from tu_rx_buf
	;---------------------------------------------------------------------------------


_dequeue_tu_rx
			bank	tu_bank
			sb	tu_rx_data		;test if any byte in buffer
			retp				;if not then exit
			mov	w,tu_tail		;get next byte from buffer
			and	w,#$0F
			mov	fsr,w
			mov	w,#tu_rx_buf
			add	fsr,w
			mov	w,indf
			mov	temp,w
			bank	tu_bank
			sub	tu_num,#1		;adjust byte count
			mov	w,tu_num
			and	w,#$0F
			snz
			clrb	tu_rx_data		;mark buffer empty
			add	tu_tail,#1
			clrb	tu_tail.3		;wrap around tail
			mov	w,temp
			retp


	; host input task
	;---------------------------------------------------------------------------------
_host_input_task
			bank	hu_bank
			sb	hu_rx_enable		;may we receive?
			retp				;no
			sb	hu_rx_flag		;byte received?
			retp				;no
			mov	w,hu_rx_byte
			clrb	hu_rx_flag
			jmp	enqueue_hu_rx		;store byte in buffer


	; host output task
	;---------------------------------------------------------------------------------
_host_output_task
			bank	hu_bank
			sb	hu_tx_enable		;may we transmit?
			retp				;no
			sb	hu_tx_data		;byte to transmit?
			retp				;no
			test	hu_tx_count		;transmitter ready?
			sz
			retp				;no
			call	dequeue_hu_tx		;get byte to transmit
			not     w			;ready bits (inverse logic)
			mov     hu_tx_high,w         	;store data byte
			setb    hu_tx_low.7          	;set up start bit
			mov     w,#10			;1 start + 8 data + 1 stop bit
			mov     hu_tx_count,w		;VP starts transmitting
			retp


;-------------- codepage 0 end -----------------------------------------------------------




;*****************************************************************************************
			org	CODEPAGE_1
;*****************************************************************************************
			jmp	$	;generates error if code above crosses page boundary


term_input_task		jmp	_term_input_task	;receives term bytes into tu_rx_buf
term_output_task	jmp	_term_output_task	;transmit term bytes from tu_tx_buf


	; set parity and stopbits for byte in tu_tx_high (just about to transmit)
	;---------------------------------------------------------------------------------
tu_set_parity
			snb	tu_7bits		;8 databits?
			clrb	tu_tx_high.7		;no, ready stop bit
			mov	w,tu_tx_high
			call	even_parity
:odd
			jnb	tu_parity_odd,:even
			movb	C,/temp.0
			jmp	:parity
:even
			jnb	tu_parity_even,:exit
			movb	C,temp.0
:parity
			sb	tu_7bits		;7 databits?
			retp				;no
			movb	tu_tx_high.7,C		;move parity into b7
:exit
			clc				;ready stop bit
			retp


	; calculate even parity for w
	; result in temp.0
	;---------------------------------------------------------------------------------
even_parity
			mov	temp,w


	;calculation code by John Payson, as found on sxlist.com
	;This routine will leave the parity of temp in temp.0
	;while blenderizing most of the rest of temp


			mov	w,<>temp	; temp = abcdefgh
			xor	temp,w
			mov	w,>>temp
			xor	temp,w


	; at this point, the parity for half the bits
	; (a, b, e, and f) is in bit 2 of temp, and the
	; parity for the other half (bits c, d, g, and h)
	; is in bit 0 of temp.


			snb	temp.2		; if the parity of (a,b,e,f) is 0,
                        			; then the parity of (a,b,c,d,e,f,g,h)
                        			; is equal to the parity of (c,d,g,h)...
                        			; which is already in bit 0, so skip ahead.


			inc	temp		; otherwise, the parity of (a,b,e,f) is 1,
						; so the parity of (a,b,c,d,e,f,g,h) is
						; NOT equal to the parity of (c,d,g,h).
						; invert bit 0.


	; at this point, bit 0 contains the parity of
	; (a,b,c,d,e,f,g,h).


			retp


	; term output handshake off (inform remote deivce to stop transmitting)
	; either RTS (on TX pin) or XON/XOFF
	;---------------------------------------------------------------------------------
tu_hs_off
			sb	tu_rx_enable
			retp				;hs already off
			mov	w,tu_config
			and	w,#$14			;test if tu_xonxoff or tu_rts set
			snz
			retp				;no handshake
			mov	w,tu_num
			and	w,#$0F			;extract bytes in tu_rx_buf
			jb	tu_xonxoff,:tu_xoff	;xonxoff handshake
			xor	w,#$05			;disable receive if 5 bytes in tu_rx_buf
			sz
			retp
			clrb	tu_rx_enable
			setb	ra_dir_buf.termTX	;turn off handshake
			retp
:tu_xoff
			xor	w,#$02			;disable receive if 2 byte in tu_rx_buf
			sz
			retp
:tu_xoff1
			test	tu_tx_count
			jnz	:tu_xoff1		;wait for not busy
			clrb	tu_rx_enable
			mov	w,#XOFF			;send XOFF
			jmp	tu_output_w


	; term output handshake on (inform remote deivce to start transmitting)
	; either RTS (on TX pin) or XON/XOFF
	;---------------------------------------------------------------------------------
tu_hs_on
			snb	tu_rx_enable
			retp				;hs already on
			mov	w,tu_config
			and	w,#$14			;test if tu_xonxoff or tu_rts set
			snz
			retp				;no handshake
			mov	w,tu_num
			and	w,#$0F			;extract bytes in tu_rx_buf
			jb	tu_xonxoff,:tu_xon	;xonxoff handshake
			xor	w,#$01			;enable receive if only 1 byte in tu_rx_buf
			sz
			retp
			setb	tu_rx_enable
			clrb	ra_dir_buf.termTX	;turn on handshake
			retp
:tu_xon
			xor	w,#$01			;enable receive if only 1 byte in tu_rx_buf
			sz
			retp
			setb	tu_rx_enable
:tu_xon1
			test	tu_tx_count
			jnz	:tu_xon1		;wait for not busy
			mov	w,#XON			;send XOFF
			jmp	tu_output_w


	; term input task
	;---------------------------------------------------------------------------------
_term_input_task
			bank	tu_bank
			snb	tu_cts			;test if rx is used as cts
			retp				;yes, so do not receive
			sb	tu_rx_flag		;byte received?
			retp				;no
			clrb	tu_rx_flag		;clear receive flag (byte in tu_char)
			jnb	tu_xonxoff,:tu_input	;jump ahead if no xon/xoff
			mov	w,tu_char
			mov	temp,w			;test for xon/xoff
			xor	w,#XON			;test if byte received is XON
			snz
			setb	tu_tx_enable		;yes, so enable tx
			snz
			retp				;and exit (XON is not stored)
			mov	w,tu_char
			xor	w,#XOFF			;test if byte received is XOFF
			snz
			clrb	tu_tx_enable		;yes, so disable tx
			snz
			retp				;and exit (XOFF is not stored)
:tu_input
			jb	tu_parity_odd,:parity
			jb	tu_parity_even,:parity
			jmp	:exit
:parity
			mov	w,tu_char
			call	even_parity
			snb	tu_parity_odd
			not	temp
			and	temp,#$01		;extract calculated parity bit
			addb	temp,tu_rx_parity	;add received parity bit
			snb	temp.0			;temp=0 or temp=2 if parity bits match
			setb	term_parity_error
:exit
			mov	w,tu_char
			call	@enqueue_tu_rx		;put byte in queue
			jmp	@tu_hs_off		;turn off handshake if required


	; term output task
	;---------------------------------------------------------------------------------
_term_output_task
			bank	tu_bank
			snb	tu_rts			;test if tx is used as rts
			retp				;tx is handshake so do not send
			sb	tu_tx_data		;data to send?
			retp				;no
			test	tu_tx_count		;transmitter busy?
			sz
			retp				;yes
			jb	tu_xonxoff,tu_hs_soft
			jnb	tu_cts,tu_output	;rx not used as handshake
tu_hs_cts						;test if handshake input on
			jnb	pinRX,tu_output		;if so then send
			retp
tu_hs_soft
			sb	tu_tx_enable		;send only if enabled
			retp
tu_output
			call	@dequeue_tu_tx
tu_output_w
			not	w			;ready bits (inverse logic)
			mov	tu_tx_high,w         	;store data byte
			setb	tu_tx_low.7          	;set up start bit
			call	tu_set_parity
			rr	tu_tx_high		;shiftin parity bit or stop bit
			rr	tu_tx_low
			mov	w,tu_bits		;start + data + parity + stop
			mov	tu_tx_count,w
			retp


	; detect transition on pinWE
	; actions when neg edge:
	;   - disable transmitter
	;   - clear buffers
	;   - initialize receive registers
	;   - enable receiver
	;   - move to state STATE_RECEIVE_COMMAND
	; actions when pos edge:
	;   - disable receiver
	;   - initialize transmit registers
	;   - enable transmitter
	;   - move to state STATE_TRANSMIT_RESPONSE
	;---------------------------------------------------------------------------------
checkPinWE
			bank	hu_bank
			snb	hu_tx_enable
			retp
			movb	pinWE_past,pinWE_present
			movb	pinWE_present,pinWE
			mov	w,hu_state
			and	w,#$C0			;extract pinWE states
			xor	w,#$40			;L->H transition?
			jz	:init_transmit		; yes
			xor	w,#$C0			;H->L transition
			sz
			retp				; no
:init_receive
			clrb	hu_tx_enable		;disable transmitter
			clr	hu_head			;clear buffers parameters (tx and rx)
			clr	hu_tail
			clr	hu_num
			clrb	hu_rx_data
			clrb	hu_rx_overrun
			clrb	hu_tx_data
			clrb	hu_tx_overrun
			clr	hu_rx_count		;initialize receive registers
			clrb	hu_rx_flag
			setb	hu_rx_enable		;enable receiver
			and	hu_state,#$C0		;keep pin states
			or	hu_state,#STATE_RECEIVE_COMMAND	;move to state RECEIVE_COMMAND
			retp
:init_transmit
			clrb	hu_rx_enable		;disable receiver
			clr	hu_tx_count		;initialize transmit registers
			setb	hu_tx_enable		;enable transmitter
			and	hu_state,#$C0		;keep pin states
			or	hu_state,#STATE_TRANSMIT_RESPONSE	;move to state TRANSMIT_RESPONSE
			retp


	; Delay approx. 1 second
	;--------------------------------------------------------------------
delay_1s00
			mov	w,#250
			call	delay_w
delay_0s75
			mov	w,#250
			call	delay_w


	; Delay approx. 0.5 second
	;--------------------------------------------------------------------
delay_0s50
			mov	w,#250
			call	delay_w
delay_0s25
			mov	w,#250


	; Delay w milliseconds
	;--------------------------------------------------------------------
delay_w
			bank	timer_bank
			mov	timer_1m,w
:wait
			test	timer_1m
			jnz	:wait
			retp


	; Host command handler.
	; This is the host command dispatcher entry.
	; It is always called when command or parameters are received.
	;---------------------------------------------------------------------------------


HOST_COMMANDS		equ	$08			;number of host commands


host_command_handler
			bank	hu_bank
			snb	cmd_done
			jmp	clear_input		;command already finished
			csb	hu_command,#HOST_COMMANDS
			jmp	invalid_host_command
			mov	w,hu_command
			add	pc,w
			jmp	_DV_GET_VERSION		;00 device get version
			jmp	_TM_SET_CONFIG		;01 terminal set configuration
			jmp	_TM_READ_DATA		;02 terminal read data
			jmp	_TM_WRITE_DATA		;03 terminal write data
			jmp	_IO_READ_PORTB		;04 i/o read port B
			jmp	_IO_WRITE_PORTB_DIR	;05 i/o write port B direction
			jmp	_IO_READ_PORTC		;06 i/o read port C
			jmp	_IO_WRITE_PORTC_DIR	;07 i/o write port C direction


			;new commands here


	; Invalid commands must remove input data to prevent hu_rx_buf overrun
	;---------------------------------------------------------------------------------
invalid_host_command
			setb	cmd_invalid
clear_input
			call	@dequeue_hu_rx		;get rid of any input


	; Mark command finished
	;---------------------------------------------------------------------------------
host_command_exit
			bank	hu_bank
			setb	cmd_done
			retp


	; Command $00	-	Get device version.
	; Parameters	-	none
	; Description	-	This command returns 8 bytes to the host
	;---------------------------------------------------------------------------------
_DV_GET_VERSION
			clrb	cmd_parameter_missing
			sb	hu_tx_enable		;may we transmit?
			retp				;no
			and	hu_head,#$0F		;reset hu_tx_buf parameters
			and	hu_tail,#$0F
			and	hu_num,#$0F
			or	hu_num,#$80
			bank	hu_buf_bank
			mov	hu_tx_buf+$0,#'T'	;co-processor identification
			mov	hu_tx_buf+$1,#'E'
			mov	hu_tx_buf+$2,#'M'
			mov	hu_tx_buf+$3,#'P'
			mov	hu_tx_buf+$4,#'L'
			mov	hu_tx_buf+$5,#'A'
			mov	hu_tx_buf+$6,#'T'
			mov	hu_tx_buf+$7,#'E'
			bank	hu_bank
			setb	hu_tx_data
			jmp	host_command_exit


	; Command $01	-	terminal set configuration
	; Parameters	-	config (default value = 0)
	;			b7  b6  b5  b4  b3  b2  b1  b0
	;			|   |   |   |   |   |   +---+-- baud (0 to 3 -> see baud table)
	;			|   |   |   |   |   +---------- 1 if TX used as RTS handshake
	;			|   |   |   |   +-------------- 1 if RX used as CTS handshake
	;			|   |   |   +------------------ 1 if xon/xoff handshake
	;			|   |   +---------------------- 1 for 7 databits (default = 8 databits)
	;			|   +-------------------------- 1 for even parity (default = no parity)
	;			+------------------------------ 1 for odd parity
	; Description	-	set terminal baud, parity, handshake
	;---------------------------------------------------------------------------------
_TM_SET_CONFIG
			jb	hu_tx_enable,:output	;prevent deadlock if not received byte
			sb	hu_rx_data
			retp
			clrb	cmd_parameter_missing
			call	@dequeue_hu_rx
			bank	tu_bank
			mov	tu_config,w
			mov	tu_bits,#10		;assume 8 databits and no parity
			snb	tu_parity_even
			setb	tu_bits.0		;if parity set bits to 11
			snb	tu_parity_odd
			setb	tu_bits.0
			snb	tu_7bits
			dec	tu_bits			;if 7 databits decrement bits
:output
			jmp	host_command_exit


	; Command $02	-	read terminal data (one byte)
	; Parameters	-	none
	; Description	-	Return current terminal character, if any, else 0
	;---------------------------------------------------------------------------------
_TM_READ_DATA
			clrb	cmd_parameter_missing
			sb	hu_tx_enable
			retp
			clr	w
			bank	tu_bank
			jnb	tu_rx_data,:tm_rd
			call	@dequeue_tu_rx
:tm_rd
			call	@enqueue_hu_tx
			bank	tu_bank
			call	@tu_hs_on		;turn on handshake if required
			jmp	host_command_exit


	; Command $03	-	write terminal data
	; Parameters	-	bytes to write
	; Description	-	write one or more characters to term
	;---------------------------------------------------------------------------------
_TM_WRITE_DATA
			clrb	cmd_parameter_missing
			jb	hu_tx_enable,:output
			sb	hu_rx_data
			retp
			call	@dequeue_hu_rx
			call	@enqueue_tu_tx
			retp
:output
			jmp	host_command_exit


	; Command $04	-	read port B
	; Parameters	-	none
	; Description	-	Return current port B input value to host
	;---------------------------------------------------------------------------------
_IO_READ_PORTB
			clrb	cmd_parameter_missing
			sb	hu_tx_enable		;may we transmit
			retp				;no
			mov	w,rb
			call	@enqueue_hu_tx
			jmp	host_command_exit


	; Command $05	-	write value to port B direction register
	; Parameters	-	dirmask
	; Description	-	Make port B pins low output (bit=0) or input (bit=1)
	;---------------------------------------------------------------------------------
_IO_WRITE_PORTB_DIR
			jb	hu_tx_enable,:output	;prevent deadlock if not received byte
			sb	hu_rx_data
			retp
			clrb	cmd_parameter_missing
			call	@dequeue_hu_rx
			mov	!rb,w
:output
			jmp	host_command_exit


	; Command $06	-	read port C
	; Parameters	-	none
	; Description	-	Return current port C input value to host
	;---------------------------------------------------------------------------------
_IO_READ_PORTC
			clrb	cmd_parameter_missing
			sb	hu_tx_enable		;may we transmit
			retp				;no
			mov	w,rc
			call	@enqueue_hu_tx
			jmp	host_command_exit


	; Command $07	-	write value to port C direction register
	; Parameters	-	dirmask
	; Description	-	Make port C pins low output (bit=0) or input (bit=1)
	;---------------------------------------------------------------------------------
_IO_WRITE_PORTC_DIR
			jb	hu_tx_enable,:output	;prevent deadlock if not received byte
			sb	hu_rx_data
			retp
			clrb	cmd_parameter_missing
			call	@dequeue_hu_rx
			mov	!rc,w
:output
			jmp	host_command_exit


;-------------- codepage 1 end -----------------------------------------------------------




;*****************************************************************************************
			org	CODEPAGE_2
;*****************************************************************************************
			jmp	$	;generates error if code above crosses page boundary


;-------------- codepage 2 end -----------------------------------------------------------




;*****************************************************************************************
			org	CODEPAGE_3
;*****************************************************************************************
			jmp	$	;generates error if code above crosses page boundary


;-------------- codepage 3 end ------------------------------------------------------

See also:


file: /Techref/scenix/lib/io/osi2/serial/elx1tmpl.htm, 45KB, , updated: 2013/7/22 18:23, local time: 2019/9/15 12:58,
TOP NEW HELP FIND: 
3.227.235.220:LOG IN

 ©2019 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE! / 

<A HREF="http://www.sxlist.com/techref/scenix/lib/io/osi2/serial/elx1tmpl.htm"> SX RS232 Serial IO </A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?

 
Quick, and RELIABLE! RCL-1 RS232 Level Converter in a DB9 backshell only $25.00
Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232!

Site supported by
sales, advertizing,
& kind contributors
just like you!

Please don't rip/copy
(here's why

Copies of the site on CD
are available at minimal cost.
 

Welcome to www.sxlist.com!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .