program COMIO, 1.0(5) ! Test COMIO.SBR ! ! Note: COMIO.SBR is provided under the A-Shell/W32 platform only, and is ! needed in order to read and write to COM1:-COM4: from within a Basic ! application. Attempts to use open a COM port and use INPUT # on it will ! cause A-Shell to lock-up. Under A-Shell/UNIX, however, you can open ! a serial port as a file and use INPUT (or XCALL GET) and PRINT to ! read and write to the port, and XCALL HOST,"stty..." to modify the ! parameters for the port. ! ! EDIT HISTORY ! [1] 05-Sep-98 Created /jdm ! [2] 08-Sep-98 Fix infinite loop if output string begins with "^" ! (thanks to Enzo at CCS srl for spotting this) /jdm ! [3] 18-Apr-08 Add binary output option /jdm ! [4] 04-Jan-09 Use msg param to display error info; support status -9 /jdm ! [5] 27-Oct-10 Add timer input, improve status output for sending... /jdm !------------------------------------------------------------------------- MAP1 CIO'PARAMS MAP2 OPCODE,F ! XCALL operation MAP2 CH,F ! "channel" MAP2 STATUS,F ! return status MAP2 BDCNT,F ! baud for open, else count to read/write MAP2 COMMSG$,S,100 ! [4] error messages MAP2 TIMEOUT,F ! [5] timeout (secs) MAP1 CIO'PORTINFO MAP2 CIO'BYTESIZE,B,1 ! 7=7 bits, 0 or 8 = 8 bits MAP2 CIO'PARITY,B,1 ! 0=none, 1=odd, 2=even, 3=mark, 4=space MAP2 CIO'STOPBITS,B,1 ! 0=1, 1=1.5, 2=2 MAP2 CIO'FLOWCTL,B,1 ! Add: 1=DTR/DSR, 2=RTS/CTS, 4=XON/XOFF MAP2 CIO'MISC,B,2 MAP2 CIO'PORT,S,20 MAP1 CIO'BUFFER,S,256,@CIO'PORTINFO MAP1 MISC MAP2 I,F MAP2 X,F MAP2 MODE,F MAP2 TSTRING,S,256 ! [2] MAP1 STSMSG$(10),S,50 DATA "Parameter Error" DATA "No more memory handles available" DATA "Memory allocation failure" DATA "Unable to create write event" DATA "Unable to create read event" DATA "Invalid channel passed in CH arg" DATA "Unable to open connection to port" DATA "^C abort while waiting for input" DATA "Unable to set port parameters" ! [4] for I = 1 to 9 read STSMSG$(I) next I ? TAB(-1,0);"COMIO - Test COMIO.SBR" LOOP: ? input "Enter -1=end, 1=open, 2=close, 4=check, 8=input, 16=output, 99=echo: ",OPCODE if OPCODE=-1 then END if OPCODE=1 then call GET'OPEN'PARAMS else ? "Enter channel # [";CH;"] "; :& input "",CH CIO'BUFFER = "" ! [5] add TIMEOUT TIMEOUT = 0 switch OPCODE ! [5] case 4 ! [5] check input "Timeout (seconds, 0=none): ",TIMEOUT exit case 8 ! input input "Enter # chars to input (0 for to-CRLF, -1 for to-CR, -N for to-chr(n) ) : ",BDCNT input "Timeout (seconds, 0=none): ",TIMEOUT exit case 16 ! output input "Enter string to output: (use ^m or \### notation): ",CIO'BUFFER input "Enter # chars to output (0 for up to null): ",BDCNT call INTERPRET'CTL'CHARS ! [3] add \### exit case 99 ! echo test call ECHO'TEST goto LOOP ! bad structure!!! endswitch endif ? call DO'COMIO call SHOW'STATUS goto LOOP !-------------------------------------------------------------------------- DO'COMIO: XCALL COMIO,OPCODE,CH,CIO'BUFFER,STATUS,BDCNT,COMMSG$, TIMEOUT ! [5] TIMEOUT = 0 ! [5] reset for next call return !-------------------------------------------------------------------------- SHOW'STATUS: ? "STATUS = ";STATUS; if STATUS < 0 and STATUS >= -9 then & ? " (";STSMSG$(-STATUS);")"; ? if COMMSG$#"" ? "ERROR MSG: ";COMMSG$ ! [4] ? "COUNT = ";BDCNT; if OPCODE=8 then ? " len(BUFFER) = ";len(CIO'BUFFER) if len(CIO'BUFFER) < BDCNT then ? "Note: terminating character(s) included in COUNT but stripped from BUFFER" endif call DISPLAY'BUFFER else ? endif if OPCODE=1 then ? "CH = ";CH ? return !-------------------------------------------------------------------------- INTERPRET'CTL'CHARS: ! Translate ^M to chr(13), etc., to allow CR, LF, and other ! control chars to be embedded in string to be sent ! [2] Note that a ^ in the first position has to be handled ! specially, since A$[1,0] returns the same as A$[1,1]. ! [3] support \### mode for decimal also X = instr(1, CIO'BUFFER, "^") if X < 1 or X >= len(CIO'BUFFER) goto ICC'DEC ! [3] then return if X > 1 then & TSTRING = CIO'BUFFER[1,X-1] & else & TSTRING = "" CIO'BUFFER = TSTRING + chr(asc(ucs(CIO'BUFFER[X+1;1]))-64) & + CIO'BUFFER[X+2,-1] : goto INTERPRET'CTL'CHARS return ICC'DEC: ! [3] interpret \### as a single byte chr(###) X = instr(1, CIO'BUFFER, "\") if X < 1 or X >= len(CIO'BUFFER) then goto ICC'DONE if X > 1 then & TSTRING = CIO'BUFFER[1,X-1] & else & TSTRING = "" CIO'BUFFER = TSTRING + chr(val(CIO'BUFFER[X+1;3])) & + CIO'BUFFER[X+4,-1] : goto INTERPRET'CTL'CHARS ICC'DONE: ? "Sending [ "; for X = 1 to (len(CIO'BUFFER) min 10) ! [5] ? "<";str(asc(CIO'BUFFER[X;1]));">"; ! [5] next X ! [5] if len(CIO'BUFFER) > 10 ? "..." ! [5] ? " ]" return !-------------------------------------------------------------------------- DISPLAY'BUFFER: ! display contents of buffer, translating any embedded control ! chars into <###> format ? "BUFFER : "; for I = 1 to len(CIO'BUFFER) if asc(CIO'BUFFER[I,I]) > 31 and asc(CIO'BUFFER[I,I]) < 128 then ? CIO'BUFFER[I,I]; else ? "<";asc(CIO'BUFFER[I,I]) using "##Z";">"; if asc(CIO'BUFFER[I,I]) = 10 then ? endif endif next I ? return !-------------------------------------------------------------------------- GET'OPEN'PARAMS: input "Enter COM port (e.g. 'COM1'): ",CIO'PORT input "Enter Bits Per Byte: ",CIO'BYTESIZE if CIO'BYTESIZE=0 then CIO'BYTESIZE = 8 input "Enter Stop Bits (0=1, 1=1.5, 2=2): ",CIO'STOPBITS input "Enter Parity (0=none, 1=odd, 2=even, 3=mark, 4=space): ",CIO'PARITY input "Enter Flow Control (0=none, 1=DTRDSR, 2=RTSCTS, 4=XONXOFF): ",CIO'FLOWCTL input "Enter Baud: ",BDCNT input "Hit RETURN to open & init the port: ",X return !-------------------------------------------------------------------------- ECHO'TEST: on error goto ECHO'TRAP: ? ? "ECHO Mode: This routine simply echoes everything that is entered" ? "on the open COM channel, both to this screen and to the COM" ? "device itself. To abort the test, hit ^C, or transmit 'END'" ? "from the device connected to the port. (This is most suitable" ? "when a terminal is connected to the port.)" ? ? "Open Channel #: [";CH;"] : "; input "",CH ? input "Enter 1) raw, 2) CR line mode, 3) CRLF line mode: ",MODE if MODE < 1 or MODE > 3 ? "Invalid test mode! " : goto ECHO'TEST ECHO'LOOP: ? "[Waiting]...";tab(-1,254); ! (force screen update) ECHO'LOOP2: OPCODE = 8 CIO'BUFFER = "" ! Setup BDCNT param according to the desired mode - ! raw (echo as we get them), wait for CR, or wait for CRLF IF MODE=1 then & BDCNT = 256 & else if MODE=2 then & BDCNT = -1 & else & BDCNT = 0 call DO'COMIO if STATUS#0 ? "< Error: Status =";STATUS;" > " ! If nothing there, sleep 1/4 sec and go back for more... if BDCNT=0 then & xcall SLEEP,0.25 :& goto ECHO'LOOP2 ! Otherwise, echo what we got here and on the port... ! ? CIO'BUFFER call DISPLAY'BUFFER OPCODE = 16 ! Since the line modes strip the line terminator, add them ! back on when outputting so the terminal device will get ! the expected aesthetics. if MODE=2 then & CIO'BUFFER = CIO'BUFFER + chr(13) :& else if MODE=3 then & CIO'BUFFER = CIO'BUFFER + chr(13) + chr(10) BDCNT = 0 ! output until null byte call DO'COMIO if CIO'BUFFER[1,3]#"END" then & goto ECHO'LOOP ECHO'EXIT: on error goto 0 ? ? "Exiting ECHO Test mode" ? return ECHO'TRAP: if err(0) # 1 ? "Error #";err(0) resume ECHO'EXIT