Serin (convert # data)

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.

Demonstrating ASC_BIN.

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