Dipl.-Ing. Detlef Rohde
Dept. BM (Broadband Mobile Radio Networks)
Group: OMW (Optical Microwave Generation)
Heinrich-Hertz-Institut Berlin GmbH
Einsteinufer 37
D-10587 Berlin
Germany
Phone: (49) 30 31002-444
Fax:   (49) 30 31002-213
e-mail: rohde@hhi.de
A.R.S.: DL7IY

says: 

I have just had success in porting a program which I found in Scott Edwards
booklet of Assembler routines for the PIC to the SX28. All what you have to
do is to adjust carefully the delay settings for your baud rate. I use the
50 MHz resonator and checked the usage for 9600 Baud.
Regards
--

; SERIN_2 bytes, filter (Fixed port, pin, baud rate, and polarity)

; Receives data serially. Stores the data as a counted string starting at
; buffer-1 (buffer is the number of bytes in the string). An optional filter
; causes the routine to ignore data outside a range of ASCII character
; values set by filt_lo and filt_hi.

; This routine differs from the Serin presented in the text in that you
; must set the baud rate and input pin through the equates below. They
; cannot be changed once the program is assembled. (The larger version
; can change pins, baud rate, and data polarity on the fly.) Removing
; the code necessary for runtime changes saves about 30 instruction
; words of space. If you only need to receive single bytes at a time,
; and don't require the buffering and filtering capabilities of this
; routine, check out SERIN_3 on this disk.

; To set the baud rate, just remove the comment symbol (;) in front of
; the desired baud rate in the list below. Make sure that all of the
; other "baud" definitions begin with (;) so that the assembler will
; ignore them.

; Note that the baud rates are all calculated at 4 MHz. At other clock
; rates, they will be proportional. For example, at 8 MHz, the fastest
; baud rate will be 4800. At 1 MHz, the fastest will be 600.

; To change the input pin, just change the line "sin_pin = " to the
; desired pin. Make sure that the pin is set up as an input before
; calling serin.

; To change the signalling polarity expected by serin, you must make
; three changes in the body of the program. There are comments next to
; the appropriate lines. Use comment symbols (;) to deactivate the
; version you don't want, and remove comment symbols from in front of
; the desired lines. The routine is currently set up for "inverted"
; polarity, meaning that it will receive input directly from a PC
; serial port with just a 22k resistor between the PC's data output
; and the PIC's sin_pin. Connect the PC signal ground to the PIC
; circuit ground.

baud	=	31	; Bit delay for 2400 baud (4-MHz PIC clock).
; baud	=	63	; Bit delay for 1200 baud (4-MHz PIC clock).
; baud	=	127	; Bit delay for 600 baud (4-MHz PIC clock).
; baud	=	255	; Bit delay for 300 baud (4-MHz PIC clock).
sin_pin =	ra.2	; Serial input pin.
buffer	=	31	; String storage.
filt_lo =	'0'     ; Set filter for ASCII
filt_hi =	'9'     ; chars representing 0-9.

	org	8
bytes	ds	1	; Number of bytes to receive.
temp1	ds	1	; Temporary counter for Serin.
temp2	ds	1	; Temporary counter for Serin.
temp3	ds	1	; Temporary counter for delay.
ser_fl	ds	1	; Flags for serin switches.

filter	  =	  ser_fl.1	  ; Range filter: 0=off, 1=on.
filt_1st  =	  ser_fl.2	  ; 1st filter byte passed?: 0=no, 1=yes.
aux	  =	  ser_fl.3	  ; Temporary flag for filter comparisons.

; Device data and reset vector
	device	pic16c55,xt_osc,wdt_off,protect_off
	reset	start
	org	0

; Subroutine used by Serin to get a bit and delay for a number of loops
; set by temp3. Jumping into get_bit:loop provides the delay, but ignores the
; input bit.

get_bit movb	c,/sin_pin	; > Uncomment this line for "inverted" polarity.
;get_bit movb	c,sin_pin	; > Uncomment this line for "true" polarity.
	rr	indirect	; Rotate carry into msb of data byte.
:loop	jmp	$+1		; Two-cycle nops.
	jmp	$+1
	jmp	$+1
	jmp	$+1
	jmp	$+1
	djnz	temp3,:loop
	ret

; Main program start. Receives a single byte of data, unfiltered,
; and displays the data bits on LEDs connected to port RB. Repeats
; endlessly.

start	clr	ser_fl		; Clear flag byte.
	mov	!ra, #15	; All inputs.
	mov	!rb,#0		; All outputs for LEDs.
	mov	bytes,#1	; Receive 1 byte
	clrb	filter		; not filtered.
	call	Serin		; Receive the data.
	mov	rb,buffer-1	; Move byte to LEDs on RB.
	jmp	start		; Do it again.

; Body of the Serin routine. Expects the number of bytes to receive in bytes
; and the flag settings in ser_fl.

Serin	clr	buffer		; Clear buffer counter.
	clrb	filt_1st	; Initialize filter flag.
	mov	fsr,#buffer-1	; Point to first data address.
:poll	jnb	sin_pin,:poll	; > Uncomment this line for "inverted" polarity.
;:poll	 jb	sin_pin,:poll	; > Uncomment this line for "true" polarity.
	clc
	mov	temp3,#baud/2	; Set up 1/2 bit time delay.
	call	get_bit:loop	; Jump into delay of get_bit.
	jnb	sin_pin,:poll	; > Uncomment this line for "inverted" polarity.
;	 jb	sin_pin,:poll	; > Uncomment this line for "true" polarity.        jnb     sin_pin,:poll   ; Change to "jb sin_pin,:poll" for "true" polarity.
	mov	temp3,#baud	; Set up full bit time delay.
	call	get_bit:loop	; Jump into delay of get_bit.
	mov	temp2,#8	; Eight data bits.
:rcv	mov	temp3,#baud	; Set up bit delay.
	call	get_bit 	; Get the next data bit.
	djnz	temp2,:rcv	; Eight bits received?
:done	mov	temp3,#baud	; Set up bit delay.
	call	get_bit:loop	; Wait for stop bit.
	jnb	filter,:skip	; IF filter=0 (off) THEN :skip
	clrb	aux		; LET aux = 0.
	csae	indirect,#filt_lo	; IF byte < filt_lo THEN aux=1
	setb	aux
	csbe	indirect,#filt_hi	; IF byte > filt_hi THEN aux=1
	setb	aux
	jnb	aux,:skip	; If aux = 0 (byte is within
	snb	filt_1st	; filter range) :skip. If byte is
	ret			; out of range, but valid bytes have
	jmp	:poll		; been received, return. Else poll.
:skip	setb	filt_1st
	dec	fsr		; Decrement buffer pointer.
	inc	buffer		; Increment buffer counter.
	djnz	bytes,:poll	; More bytes to receive: poll.
	ret