; ASC_BIN numeric string
; This program converts a counted string of ASCII characters
; received by Serin into a 16-bit value in the variable n1.

	device	pic16c55,xt_osc,wdt_off,protect_off
	reset	start

buffer	=	31	; String buffer at end of memory
ASC_0	=	'0'	; ASCII chars for nos. are 30h thru 39h.

	org	8
dec_no	ds	1	; Decade (1,10,100...) to work on.
n1H	ds	1	; MSB of converted number.
n1L	ds	1	; LSB of converted number.
n2H	ds	1	; MSB of 16-bit temp variable.
n2L	ds	1	; LSB of 16-bit temp variable.
temp	ds	1	; Temporary storage

; Device data and reset vector
	org	0

decade	jmp	pc+w
	retw	39,16,3,232,0,100,0,10,0,1

start	mov	!rb,#0	; Set ports to output.
	mov	!rc,#0
	mov	buffer,#5	; String count.
	mov	buffer-1,#36h	; Numeric text: "65535."
	mov	buffer-2,#35h	; To view the results of the
	mov	buffer-3,#35h	; conversion, run this program
	mov	buffer-4,#33h	; on the PSIM simulator, or merge
	mov	buffer-5,#35h	; it with Serin.
	call	ASC_BIN
	mov	rb,n1L	; Show result on LEDs.
	mov	rc,n1H
	jmp	$	; Endless loop.

; ASC_BIN gets the value of each digit (0-9) of a numeric string. Depending
; on the number of digits in the string, it looks up the multiplier (10000, 1000,100,10, or 1) and adds that multiplier to n1 digit number of times.
ASC_BIN clr	n1H	; n1 = 0
	clr	n1L
	mov	fsr,#buffer-1	; If the string is empty,
	test	buffer	; return 0 in 16-bit answer
	jnz	:loop	; and error code (1) in
	retw	1	; w. Else, do the conversion.
:loop	mov	w,#ASC_0	; w = 30h (ASCII start point).
	subwf	indirect,0	; w = character_value-30h.
	jz	:next
	mov	temp,w	; temp = w
	mov	dec_no,#5
	sub	dec_no,buffer	; dec_no = 5-string_length
	clc
	rl	dec_no	; dec_no = dec_no*2
	mov	w,dec_no
	call	decade	; Look up MSB of multiplier.
	mov	n2H,w	; Store it in MSB of n2.
	mov	w,++dec_no	; Look up the LSB of multiplier.
	call	decade
	mov	n2L,w	; Store it in LSB of n2.
:add_it call	Add16	; n1 = n1 + n2.
	djnz	temp,:add_it	; Repeat 1 to 9 times for each digit.
:next	dec	fsr	; Get the next byte of the string.
	dec	buffer	; Adjust string counter.
	jnz	:loop	; Any bytes left? Yes: loop.
	ret	; No: return.
Add16	ADD	n1L,n2L ; Add the LSBs. If carry,
	snc	; increment MSB of sum.
	inc	n1H
	ADD	n1H,n2H ; Add the MSBs.
	ret

