please dont rip this site
;-----------------------------------------------------------------------------
; Full-duplex software UART
;
; This version is for the Scenix SX Microcontroller, and runs on the
; Parallax SX-Key Demo Board.  Assemble with Microchip's MPASM assembler.
;
; Copyright 1996, 1998 Eric Smith
;
; Permission is granted to use this code or portions thereof for
; non-commercial purposes provided that the copyright notice is preserved
; intact and that credit is given to the author.  For any other use, a
; license may be obtained from the author; send email to eric@brouhaha.com.
;
; $Id: fduart.asm,v 1.3 1998/11/05 06:35:07 eric Exp eric $
;-----------------------------------------------------------------------------

	radix	dec

	errorlevel	-302
	errorlevel	-305

	processor	16c57	; really a Scenix SX, but MPASM doesn't
				; know about those


;-----------------------------------------------------------------------------
; Scenix SX18AC/SX28AC register definitions
;-----------------------------------------------------------------------------

indf	equ	00h
rtcc	equ	01h
pcl	equ	02h
status	equ	03h
fsr	equ	04h
porta	equ	05h
portb	equ	06h
portc	equ	07h

; bits in status:
c	equ	0
z	equ	2


;-----------------------------------------------------------------------------
; ASCII characters
;-----------------------------------------------------------------------------

lf	equ	00ah
cr	equ	00dh


;-----------------------------------------------------------------------------
; Scenix instruction macros
;-----------------------------------------------------------------------------

ret	macro
	data	0ch	;RET	;return without destroying W register
	endm

reti	macro
	data	0eh
	endm

retiw	macro
	data	0fh
	endm

pagex	macro	n		;(MPASM already uses "PAGE")
	data	10h|n	;PAGE	;write N into bits PA2:PA0 (N = 0-7)
	endm

bankx	macro	n		;(MPASM already uses "BANK")
	data	18h|(n>>5)	;BANK	;write N into bits FSR7:FSR5 (N = 0-7)
	endm

mode	macro	n
	data	50h|n	;MODE	;write N into MODE register (N = 0-F)
	endm


;-----------------------------------------------------------------------------
; target-specific definitions
;-----------------------------------------------------------------------------

rx_ring_size	equ	010h
tx_ring_size	equ	010h


xtalfreq	equ	50000000

b115200		equ	-145	; xtalfreq/(3*115200)


rxport		equ	porta
rxbit		equ	2
rxinv		equ	0

txport		equ	porta
txbit		equ	3
txinv		equ	0


button_port	equ	portb
maxbutton	equ	4


porta_init	equ	0ffh
porta_tris	equ	(1<<rxbit)

portb_init	equ	0ffh
portb_tris	equ	(1<<maxbutton)-1	; button inputs

portc_init	equ	0ffh
portc_tris	equ	000h


;-----------------------------------------------------------------------------
; RAM usage
;-----------------------------------------------------------------------------

		org	008h
; globals

rxbyte:		res	1	; this must be global rather than in ser_vars
				; rxbyte may >only< be used in interrupt handler

ser_temp:	res	1	; ser_temp  must be global rather than in ser_vars
				; ser_temp may not be used in interrupt handler

msg_temp:	res	1	; this could be in main_vars

temp:		res	1
temp2:		res	1
temp3:		res	1

led_stat:	res	1	; this should be in button_vars, but I got lazy
				; and referenced it directly from main


		org	010h

main_vars	=	$

		org	030h

button_vars	=	$

but_press_cnt:	res	maxbutton
but_mask:	res	1
but_poll_cnt:	res	1
but_stat:	res	1	; button status, 1 bit per button
				; mainline code will clear bit to acknowledge

		org	050h

ser_vars	=	$

uartspeed:	res	1

uartstat:	res	1

; bits in uartstat:
rbf	equ	7
tbf	equ	6
rxovr	equ	5
rxfrm	equ	4
rxphase	equ	1
txphase	equ	0

rx_ring_ip:	res	1
rx_ring_op:	res	1
rx_ring_cnt:	res	1

tx_ring_ip:	res	1
tx_ring_op:	res	1
tx_ring_cnt:	res	1

rxbits:		res	1
rxbitcnt:	res	1
rxmask:		res	1

txbyte:		res	1
txbitcnt:	res	1

		org	070h

rx_ring:	res	rx_ring_size

		org	090h

tx_ring:	res	tx_ring_size


;-----------------------------------------------------------------------------
; UART macros
;-----------------------------------------------------------------------------

ringadv	macro	ptr,base,size
	local	pow2,aligned,bit,val
pow2	set	!(size&(size-1))
aligned	set	pow2&&((base&(size-1))==0)

	if	aligned
val	set	size
bit	set	0
	while	val>1
bit	set	bit+1
val	set	val>>1
	endw
	endif

	incf	ptr

	if	aligned&&!(base&(1<<bit))
	bcf	ptr,bit
	else
	movf	ptr,w
	xorlw	base+size
	movlw	base
	btfsc	status,z
	movwf	ptr
	endif
	endm


;-----------------------------------------------------------------------------
; interrupt entry point
; all subroutine entry points must be in first page of ROM
;-----------------------------------------------------------------------------

	org	0

int	call	ser_int
	call	but_int
	bankx	ser_vars
	movf	uartspeed,w
	retiw


;-----------------------------------------------------------------------------
; jump table
; all subroutine entry points must be in first page of ROM
;-----------------------------------------------------------------------------

uartinit:
	goto	uartinit_x
xmit:	goto	xmit_x
recv:	goto	recv_x
rxavail:
	goto	rxavail_x
msgout:	goto	msgout_x

buttoninit:
	goto	buttoninit_x
getbutstat:
	goto	getbutstat_x
clrbutstat:
	goto	clrbutstat_x


;-----------------------------------------------------------------------------
; tables
;-----------------------------------------------------------------------------

msg_table:	addwf	pcl
banner		equ	$-(msg_table+1)
		dt	cr,lf,"Hello, world!",cr,lf
		dt	"This is a test to see if very long messages",cr,lf
		dt	"lose characters.  If they do, there must be",cr,lf
		dt	"a problem with buffer management.",cr,lf,0
button_msg	equ	$-(msg_table+1)
		dt	"button ",0
pressed_msg	equ	$-(msg_table+1)
		dt	" pressed",cr,lf,0


;-----------------------------------------------------------------------------
; button interrupt handler code
;-----------------------------------------------------------------------------

but_int:
	bankx	button_vars
	incf	but_poll_cnt	; poll button every 256 ticks

	movf	but_poll_cnt,w	; if but_poll_cnt > 3, return
	andlw	0fch
	btfss	status,z
	ret

	movf	but_poll_cnt,w	; must be between 0 and 3
	addwf	pcl
	goto	but_set_input
	goto	but_read_input
	goto	led_set_output
	ret

led_set_output:
	movf	led_stat,w
	xorlw	0ffh
	movwf	button_port
	movlw	0
	tris	button_port
	ret

but_set_input:
	movlw	(1<<maxbutton)-1
	tris	button_port
	ret

but_read_input:
	movlw	button_vars
	movwf	fsr
	movlw	001h
	movwf	but_mask

butint1:
	movf	button_port,w
	andwf	but_mask,w
	btfss	status,z
	goto	butrel

	btfsc	indf,5		; already pressed?
	goto	butint9

	incf	indf
	btfss	indf,5
	goto	butint9

	movf	but_mask,w
	iorwf	but_stat
	goto	butint9

butrel:
	clrf	indf

butint9:
	incf	fsr
	bcf	status,c
	rlf	but_mask
	btfss	but_mask,maxbutton
	goto	butint1
	ret


;-----------------------------------------------------------------------------
; serial interrupt handler code
;-----------------------------------------------------------------------------

ser_int:
	bankx	ser_vars

	if	rxbit==0	; get current receive sample in one instruction
	rrf	rxport,w	;   if possible, otherwise three instructions
	else
	if	rxbit==7
	rlf	rxport,w
	else
	bcf	status,c
	btfsc	rxport,rxbit
	bsf	status,c
	endif
	endif

	rlf	rxbits

	btfsc	uartstat,rxphase
	goto	rxint
	btfsc	uartstat,txphase
	goto	txint

; housekeeping phase

	bsf	uartstat,txphase	; transmit phase next

	btfss	uartstat,rbf	; has the receiver collected a byte?
	goto	try_xmit_ring	; no, check transmitter

	movf	rx_ring_cnt,w	; is the receive buffer full?
	xorlw	rx_ring_size
	btfss	status,z
	goto	rx_ok		; no, go store the char
	bsf	uartstat,rxovr	; yes, set the overrun flag
	goto	try_xmit_ring	;   and skip storing the char

rx_ok:	movf	rx_ring_ip,w	; store character in receive buffer
	movwf	fsr
	movf	rxbyte,w	; rxbyte must be global!!!
	movwf	indf
	bankx	ser_vars

	ringadv	rx_ring_ip,rx_ring,rx_ring_size

	incf	rx_ring_cnt

	bcf	uartstat,rbf

try_xmit_ring:
	btfsc	uartstat,tbf	; is the transmitter busy?
	ret			; yes, don't do anything

	movf	tx_ring_cnt,w	; is there anything in the ring?
	btfsc	status,z
	ret			; no, don't do anything

	movf	tx_ring_op,w	; move one character from the ring to the
	movwf	fsr		;   transmitter
	movf	indf,w
	bankx	ser_vars
	movwf	txbyte

	decf	tx_ring_cnt	; decrement tx char count

	ringadv	tx_ring_op,tx_ring,tx_ring_size	; advance pointer

	bsf	uartstat,tbf	; now the transmitter will be busy
	ret


rxint:	bcf	uartstat,rxphase	; housekeeping phase next

	if	rxinv
	movlw	7
	xorwf	rxbits
	endif

	movf	rxmask,w
	btfss	status,z
	goto	rxgetbit

	movlw	9
	movwf	rxbitcnt

	movlw	2
	btfss	rxbits,2
	goto	rxstart9
	movlw	1
	btfss	rxbits,1
	goto	rxstart9
	movlw	4

	btfsc	rxbits,0
	ret

rxstart10:
	incf	rxbitcnt
rxstart9:
	movwf	rxmask
	ret

rxgetbit:
	andwf	rxbits,w	; extract the appropriate sample bit
	bcf	status,c	;   into the carry flag
	btfss	status,z
	bsf	status,c

	decfsz	rxbitcnt	; is it a stop bit?
	goto	rxdbit		; no, it's a data bit

	btfss	status,c	; is the stop bit a 1 like it's supposed to be?
	bsf	uartstat,rxfrm	; no, framing error!

	bsf	uartstat,rbf

	btfss	rxmask,2	; could there be a start bit in this group?
	goto	rxnost		;  no

	btfsc	rxbits,0	; is there in fact a start bit?
	goto	rxnost		;  no

	movlw	4		; yes, start up again
	movwf	rxmask
	movlw	10
	movwf	rxbitcnt
	ret

rxnost:	clrf	rxmask
	ret

rxdbit:	rrf	rxbyte
	ret


txint:	bcf	uartstat,txphase
	bsf	uartstat,rxphase	; receive phase next

	movf	txbitcnt	; are we transmitting?
	btfss	status,z
	goto	txputbit

	btfss	uartstat,tbf	; is there a char awaiting transmission?
	ret

	if	txinv
	bsf	txport,txbit	; send start bit
	else
	bcf	txport,txbit	; send start bit
	endif

	movlw	9		; 8 data bits plus a stop bit
	movwf	txbitcnt

	ret

txputbit:
	bsf	status,c
	rrf	txbyte

	if	txinv
	btfss	status,c
	bsf	txport,txbit
	btfsc	status,c
	bcf	txport,txbit
	else
	btfss	status,c
	bcf	txport,txbit
	btfsc	status,c
	bsf	txport,txbit
	endif

	decfsz	txbitcnt	; any more bits to send?
	ret			;   yes
	bcf	uartstat,tbf	;   no, the transmit buffer is now empty
	ret


;-----------------------------------------------------------------------------
; UART initialization
; caller must restore register bank
; returns with register bank 010h selected
;-----------------------------------------------------------------------------

uartinit_x:
	bankx	ser_vars
	clrf	uartstat
	clrf	rxmask
	clrf	txbitcnt

	clrf	rx_ring_cnt
	movlw	rx_ring
	movwf	rx_ring_ip
	movwf	rx_ring_op

	clrf	tx_ring_cnt
	movlw	tx_ring
	movwf	tx_ring_ip
	movwf	tx_ring_op

	movlw	b115200
	movwf	uartspeed

	clrf	rtcc

	bankx	010h
	ret


;-----------------------------------------------------------------------------
; serial transmit character
; blocks until space if available in buffer
; returns with register bank 010h selected
;-----------------------------------------------------------------------------

xmit_x:	bankx	ser_vars
	movwf	ser_temp

xmit0:	movf	tx_ring_cnt,w	; is there room for a character?
	xorlw	tx_ring_size
	btfsc	status,z
	goto	xmit0

	movf	tx_ring_ip,w	; store char in buffer
	movwf	fsr
	movf	ser_temp,w	; must be global!!!
	movwf	indf
	bankx	ser_vars

	ringadv	tx_ring_ip,tx_ring,tx_ring_size	; advance pointer

	incf	tx_ring_cnt	; increment tx char count
				; (this must not be done until after character
				; has been stored in buffer)

	bankx	010h
	ret


;-----------------------------------------------------------------------------
; rxavail
; returns count of received characters available
; returns with register bank 010h selected
;-----------------------------------------------------------------------------

rxavail_x:
	bankx	ser_vars
	movf	rx_ring_cnt,w
	bankx	010h
	ret


;-----------------------------------------------------------------------------
; serial receive character
; blocks until a character is available
; returns with register bank 010h selected
;-----------------------------------------------------------------------------

recv_x:	bankx	ser_vars
	movf	rx_ring_cnt
	btfsc	status,z
	goto	recv

	movf	rx_ring_op,w
	movwf	fsr
	movf	indf,w		; get character from buffer
	movwf	ser_temp	; must be global!!!
	bankx	ser_vars

	ringadv	rx_ring_op,rx_ring,rx_ring_size	; advance pointer

	decf	rx_ring_cnt	; decrement rx char count
				; (this must not be done until after character
				; has been pulled from buffer)

	movf	ser_temp,w

	bankx	010h
	ret


;-----------------------------------------------------------------------------
; message output
;-----------------------------------------------------------------------------

msgout_x:
	movwf	msg_temp
msglp:	movf	msg_temp,w
	call	msg_table
	xorlw	0
	btfsc	status,z
	ret
	call	xmit
	incf	msg_temp
	goto	msglp


;-----------------------------------------------------------------------------
; button routines
;-----------------------------------------------------------------------------

buttoninit_x:
	bankx	button_vars
	clrf	but_stat
	clrf	led_stat
	bankx	010h
	ret

; return button state in W
getbutstat_x:
	bankx	button_vars
	movf	but_stat,w
	bankx	010h
	ret

; clear buttons that are selected by bits set in W
clrbutstat_x:
	bankx	button_vars
	xorlw	0ffh
	andwf	but_stat
	bankx	010h
	ret


;-----------------------------------------------------------------------------
; reset
;-----------------------------------------------------------------------------

reset:	
	clrf	fsr

	movlw	porta_init
	movwf	porta
	movlw	porta_tris
	tris	porta

	movlw	portb_init
	movwf	portb
	movlw	portb_tris
	tris	portb

	movlw	portc_init
	movwf	portc
	movlw	portc_tris
	tris	portc

	movlw	0dfh
	option

	call	uartinit
	call	buttoninit

	movlw	09fh		; enable RTCC interrupt
	option


;-----------------------------------------------------------------------------
; main
;-----------------------------------------------------------------------------

main:	movlw	banner
	call	msgout

loop:
	call	rxavail
	btfsc	status,z
	goto	loop1
	call	recv
	call	xmit

loop1:	call	getbutstat
	btfsc	status,z
	goto	loop9

	movwf	temp
	call	clrbutstat
	movf	temp,w

	movlw	001h
	movwf	temp2

	movlw	'0'
	movwf	temp3

loop2:	movf	temp,w
	andwf	temp2,w
	btfsc	status,z
	goto	loop3

	movf	temp,w
	xorwf	led_stat

	movf	' '		; don't know why, but this fixes the bug that
	call	xmit		;   loses the leading 'b' in the button message
	movlw	button_msg
	call	msgout
	movf	temp3,w
	call	xmit
	movlw	pressed_msg
	call	msgout

loop3:	incf	temp3
	bcf	status,c
	rlf	temp2
	btfss	temp2,maxbutton
	goto	loop2

loop9:	goto	loop

		
;-----------------------------------------------------------------------------
; reset vector
;-----------------------------------------------------------------------------

	errorlevel	-306	; don't display "crossing page boundary" warning
	org	07ffh
	goto	reset
	errorlevel	+306


;-----------------------------------------------------------------------------
; fuses
;-----------------------------------------------------------------------------

_DEVICE	equ	0x44e4fa

	errorlevel	-220	;don't display "address exceeds range" warning
	org	1010h
	data	_DEVICE&0xfff	;configuration bits (TURBO, SYNC, OPTIONX, etc.)
	data	_DEVICE>>12	; (PINS, CARRYX, BOR40, BANKS, PAGES)
	errorlevel	+220	;restore warning message

	end


file: /Techref/scenix/lib/io/osi2/serial/fduart_asm.htm, 14KB, , updated: 2013/7/22 17:24, local time: 2024/12/26 18:04,
TOP NEW HELP FIND: 
18.226.17.3:LOG IN

 ©2024 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://sxlist.com/TECHREF/scenix/lib/io/osi2/serial/fduart_asm.htm"> scenix lib io osi2 serial fduart_asm</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 a nice message (short messages are blocked as spam) 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?

 

Welcome to sxlist.com!


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 sxlist.com!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .