converts a numeric text string received by Serin into a 16-bit number.
PBASIC's Serin can automatically convert incoming text to numbers. This means that a user can type a number like "5280" from the keyboard of a PC or terminal, and Serin will interpret the received string as the 16-bit number 5280 (14A0h).
Using the assembly version of Serin, you can do the same thing. Set up Serin to receive five bytes (for the five digits of a 16-bit number) and set the filter bit. Make sure that the filter range, determined by equates at the beginning of the Serin listing, is set up for ASCII '0' through '9'.
Serin will ignore data other than numbers. Once it begins receiving numeric text, it will store up to five digits in its string buffer. Once five digits are collected or the numeric string is ended by a non-numeric character, Serin will return.
An example will help clarify this. Suppose Serin is called with the filter on and a request for five bytes. The following stream of data arrives:
1st 2nd 3rd 4th 5th 6th 7th 8th 9th Q ( 5 2 0 ) ( &np; 9 1
Serin rejects the first and second bytes. It recognizes the third through fifth bytes as numbers and stores them in the string. It now has storage remaining for two more numeric bytes. However, the sixth byte is not a number, so Serin stops listening and returns with the three-byte string "520" in the buffer. If it didn't stop, it could skip the parentheses and combine "520" with "91" to produce "52091". That is clearly not the right answer.
Serin will also reject mathematical punctuation, like the minus sign, comma, and decimal point. People or programs sending data for use by Serin must not use these marks in their entries.
Once Serin has stored the data, a call to ASC_BIN converts it to a 16-bit number. If there is no data in the string (the first entry containing the number of bytes is 0), the routine returns with 1 in w to signal the error. Otherwise, it returns the binary equivalent of the text string in the 16-bit variable n1 and a 0 in w. ASC_BIN decrements the string counter to 0, so if the string is to be reused, your program should copy this value and rewrite it after ASC_BIN is done.
To see ASC_BIN in operation, you may run it on the PSIM simulator as suggested in the program listing. For a live demonstration, connect the circuit below to an erasable PIC or PIC emulator, such as the Parallax downloader. Program the PIC or downloader with the program assembled from the file SERIN_#.SRC on the accompanying disk. Make sure to use a 4-MHz clock on the PIC or downloader. Load a terminal program on the PC connected to the PIC and set it for 2400 baud, no parity , 8 data bits, 1 stop bit (N81). Now type in some numbers and text and watch the LEDs interpret the data as described on the previous page.
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. 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 device pic16c55,xt_osc,wdt_off,protect_off reset start 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