Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (06/04/90)
Submitted-by: jcs@crash.uucp
Posting-number: Volume 90, Issue 176
Archive-name: util/st/part01
This code directly accesses the hardware and achieves very high
baud rates without errors. This code should be legal if the serial
device is first opened and exclusive access is granted. Speeds of
over 130k baud between a stock, nofastmem 500 and a 25mhz GVP 68030
have been achieved. The '030 Amiga can go much faster; it can read
at least 223,720 baud. The 500 poops out at 132,575 baud. Writing
fast is no problem, reading eats up some bandwidth, and is thus
the bottleneck. Polled I/O (yuk) can yield faster rates. These
baud rates were accomplished with a direct 2,3,7 wire, 50 foot
shielded cable. Max baud rates may vary depending on cable and
hardware configurations.
#!/bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 1 (of 1)."
# Contents: input.c input.h inputhandler.a makefile readme serial.a
# st.c
# Wrapped by tadguy@xanth on Sun Jun 3 20:05:27 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'input.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'input.c'\"
else
echo shar: Extracting \"'input.c'\" \(2035 characters\)
sed "s/^X//" >'input.c' <<'END_OF_FILE'
X/* input.c
X created by John Schultz, 10-Sep-89
X
X*/
X
X#include <exec/types.h>
X#include <exec/io.h>
X#include <exec/ports.h>
X#include <exec/interrupts.h>
X#include <proto/exec.h>
X#include <proto/graphics.h>
X#include <devices/input.h>
X#include <devices/inputevent.h>
X#include "input.h"
X
Xunsigned short volatile raw; /* raw key value */
X
Xstruct MsgPort indevport;
Xstruct MsgPort * indevportptr;
Xstruct IOStdReq * inreqblockptr;
Xstruct Interrupt inhandler;
Xstruct InputEvent * eventp;
X
Xextern void totalinput();
X
Xint createti(void) {
X
X indevportptr = CreatePort("indevport",0);
X if (!indevportptr) {
X return 0;
X }
X
X inreqblockptr = CreateStdIO((struct MsgPort *)indevportptr);
X if (!inreqblockptr) {
X DeletePort(indevportptr);
X return 0;
X }
X
X inhandler.is_Data = (APTR)&raw;
X inhandler.is_Code = totalinput;
X inhandler.is_Node.ln_Pri = 51; /* One ahead of Intuition */
X
X if (OpenDevice("input.device",0L,
X (struct IORequest *)inreqblockptr,0L)) {
X DeletePort(indevportptr);
X DeleteStdIO(inreqblockptr);
X return 0;
X }
X
X inreqblockptr->io_Command = IND_ADDHANDLER;
X inreqblockptr->io_Data = (APTR)&inhandler;
X
X if (DoIO((struct IORequest *)inreqblockptr)) {
X DeletePort(indevportptr);
X DeleteStdIO(inreqblockptr);
X CloseDevice((struct IORequest *)inreqblockptr);
X return 0;
X }
X
X GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
X if(!GfxBase) {
X DeletePort(indevportptr);
X DeleteStdIO(inreqblockptr);
X CloseDevice((struct IORequest *)inreqblockptr);
X return 0;
X }
X FreeSprite(0);
X
X CloseLibrary((struct Library *)GfxBase);
X
X return 1;
X
X} /* end createti */
X
Xvoid deleteti(void) {
X
X if ((indevportptr) && (inreqblockptr)) {
X inreqblockptr->io_Command = IND_REMHANDLER;
X inreqblockptr->io_Data = (APTR)&inhandler;
X DoIO((struct IORequest *)inreqblockptr);
X CloseDevice((struct IORequest *)inreqblockptr);
X DeleteStdIO(inreqblockptr);
X DeletePort(indevportptr);
X } /* end if */
X
X} /* END deleteti */
X
X
X/* END input.c */
END_OF_FILE
if test 2035 -ne `wc -c <'input.c'`; then
echo shar: \"'input.c'\" unpacked with wrong size!
fi
# end of 'input.c'
fi
if test -f 'input.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'input.h'\"
else
echo shar: Extracting \"'input.h'\" \(241 characters\)
sed "s/^X//" >'input.h' <<'END_OF_FILE'
X/* input.h - total input
X created by John Schultz, 10-Sep-89
X*/
X
X#ifndef INPUTTI
X#define INPUTTI
X
Xextern unsigned short volatile raw; /* raw key input */
X
Xextern int createti(void);
X
Xextern void deleteti(void);
X
X#endif
X
X/* end input.h */
END_OF_FILE
if test 241 -ne `wc -c <'input.h'`; then
echo shar: \"'input.h'\" unpacked with wrong size!
fi
# end of 'input.h'
fi
if test -f 'inputhandler.a' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'inputhandler.a'\"
else
echo shar: Extracting \"'inputhandler.a'\" \(418 characters\)
sed "s/^X//" >'inputhandler.a' <<'END_OF_FILE'
X; Input Handler
X; created by John Schultz, 17-Sep-89
X
X section "TotalInput",code
X
X xdef _totalinput
X
X; Input event structure offsets
X
XIECLASS equ 4
XIECODE equ 6
X
X; A0 = inputevent pointer
X; A1 = data pointer
X
X_totalinput:
X cmp.b #1,IECLASS(A0) ; event->ie_Class == IECLASS_RAWKEY ?
X bne.b notrawkey
X move.w IECODE(A0),(A1) ; raw = event->ie_Code
Xnotrawkey:
X moveq.l #0,D0 ; don't pass events to intuition
X rts
X
X END
X
END_OF_FILE
if test 418 -ne `wc -c <'inputhandler.a'`; then
echo shar: \"'inputhandler.a'\" unpacked with wrong size!
fi
# end of 'inputhandler.a'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(352 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
X# serial makefile, created by John Schultz, 17-Sep-89
X
Xst: st.o serial.o input.o inputhandler.o
X blink from lib:c.o+st.o+serial.o+input.o+inputhandler.o to st \
X lib lib:lc.lib sc sd nd
X
Xst.o: st.c
X lc -O st.c
X
Xserial.o: serial.a
X asm serial.a
X
Xinput.o: input.h input.c
X lc input.c
X
Xinputhandler.o: inputhandler.a
X asm inputhandler.a
X
END_OF_FILE
if test 352 -ne `wc -c <'makefile'`; then
echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
if test -f 'readme' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'readme'\"
else
echo shar: Extracting \"'readme'\" \(2076 characters\)
sed "s/^X//" >'readme' <<'END_OF_FILE'
X
X Interrupt-driven Serial I/O Testbed
X by John Schultz
X 4/16/90
X
X This code directly accesses the hardware and achieves very high
Xbaud rates without errors. This code should be legal if the serial
Xdevice is first opened and exclusive access is granted. Speeds of
Xover 130k baud between a stock, nofastmem 500 and a 25mhz GVP 68030
Xhave been achieved. The '030 Amiga can go much faster; it can read
Xat least 223,720 baud. The 500 poops out at 132,575 baud. Writing
Xfast is no problem, reading eats up some bandwidth, and is thus
Xthe bottleneck. Polled I/O (yuk) can yield faster rates. These
Xbaud rates were accomplished with a direct 2,3,7 wire, 50 foot
Xshielded cable. Max baud rates may vary depending on cable and
Xhardware configurations.
X The current test code, ST (Serial Test), writes characters typed
Xon the keyboard 10 times. Errors at high speed show up when less
Xthan 10 characters are received or funny characters are inserted.
X I can run DNet and leave it running while I run this code! DNet
Xmust be idling, and the baud rate must be the same as DNet's (usually
X19200) the last time you run ST. This is very useful as quiting and
Xrestarting DNet is not necessary.
X Part of the original assembly code came from the Amiga Transactor,
XSeptember 1989: Volume 2, Issue 6,pp 42-44, by Mike Schwartz. The
Xexample changed the AutoVectors directly, and had a few typos. I use
XSetIntVector(), and do things a little differently with the rbf and
Xtbe code. This was pretty much the first assembly language program I
Xwrote, so experts feel free to point out improvements.
X I wrote the code using Lattice 5.04. I currently use the Cape
Xor Devpac assemblers for speed, but for this example used Lattice's
Xasm (everyone with Lattice should have it).
X
X As always, please point out any optimizations, errors, or illegal
Xacts committed in this code. If you enhance the code, please email me
Xa copy.
X
X Use this code as you wish; no strings, ropes, cables, or
Xbungee cords attached.
X
X
X
X John
END_OF_FILE
if test 2076 -ne `wc -c <'readme'`; then
echo shar: \"'readme'\" unpacked with wrong size!
fi
# end of 'readme'
fi
if test -f 'serial.a' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'serial.a'\"
else
echo shar: Extracting \"'serial.a'\" \(5691 characters\)
sed "s/^X//" >'serial.a' <<'END_OF_FILE'
X; Serial.a
X; created by John Schultz, 17-Sep-89
X; last modified 17-April-90
X
X section Serial,CODE
X
X xref _raw
X
X xdef _baudper
X xdef _openserial
X xdef _closeserial
X xdef _sendser
X xdef _readser
X xdef _checkser
X xdef _rawtoascii
X xdef _sendsernobuff
X
X
X_LVOSetIntVector equ $FFFFFF5E
X
XESCAPE equ 69 ; input-handler rawkey code
X
XCLOCK equ 3579545
X_baudper dc.w (CLOCK/19200)-1 ; defaualt
X
XCUSTOM equ $dff000
XSERDATR equ $000018
XSERDAT equ $000030
XSERPER equ $000032
X
XINTENA equ $00009a
XINTENAR equ $00001c
XINTREQ equ $00009c
X
XTBEQSIZE equ 128 ; buffer size in bytes,
XRBFQSIZE equ 128 ; increase or decrease as needed
X
XLED equ $bfe001 ; toggle power led, audio filter
X
Xledroll dc.b %00010001 ; flash every 4 bytes
Xledpad dc.b 0
X
Xoldintena dc.w 0
X
Xtbequeue ds.b TBEQSIZE ; circular queue
Xtbeqend
Xtbehead dc.l tbequeue
Xtbetail dc.l tbequeue
X
Xoldtbeinterrupt dc.l 0
Xoldrbfinterrupt dc.l 0
X
Xtbeinterrupt
X dc.l 0 ; ln_succ
X dc.l 0 ; ln_prec
X dc.b 2 ; NT_INTERRUPT
X dc.b 127 ; ln_pri
X dc.l 0 ; ln_name
X dc.l tbehead ; is_data
X dc.l tbehandler ; is_code
X
Xrbfinterrupt
X dc.l 0 ; ln_succ
X dc.l 0 ; ln_prec
X dc.b 2 ; NT_INTERRUPT
X dc.b 127 ; ln_pri
X dc.l 0 ; ln_name
X dc.l rbftail ; is_data
X dc.l rbfhandler ; is_code
X
X
Xtbehandler
X move.w #1,INTREQ(a0) ; clear TBE interrupt
X move.l (a1),a1 ; a1 = tbehead, (a1) = pointer
X cmp.l tbetail,a1 ; now a1 = pointer
X beq.b 99$
X move.w SERDATR(a0),d0 ; check to make sure emtpy
X btst #13,d0
X beq.b 99$
X move.w #$100,d0
X move.b (a1)+,d0 ; get byte from queue
X move.w d0,SERDAT(a0) ; send byte
X cmpa.l #tbeqend,a1
X bne.b 10$
X lea tbequeue(pc),a1
X10$ move.l a1,tbehead
X99$
X rts
X
Xrbfqueue ds.b RBFQSIZE
Xrbfqend
Xrbfhead dc.l rbfqueue
Xrbftail dc.l rbfqueue
X
Xrbfhandler
X move.w SERDATR(a0),d0 ; a0 = custom
X move.w #$800,INTREQ(a0) ; clear RBF interrupt
X move.l (a1),a0 ; a1 = rbftail, get pointer
X move.b d0,(a0)+ ; write byte to buffer
X cmpa.l #rbfqend,a0
X bne.b 10$
X lea rbfqueue(pc),a0
X10$ move.l a0,(a1) ; a1 = rbftail
X
X;99$
X; move.b ledroll(pc),d0 ; remove from 99$-100$ for more
X; rol.b #1,d0 ; speed
X; move.b d0,ledroll
X; btst #1,d0
X; beq.b 100$
X; bchg.b #1,LED ; toggle power led / audio filter
X;100$
X rts
X
X_openserial
X move.l a6,-(sp)
X lea CUSTOM,a0
X move.w #$4000,INTENA(a0) ; disable
X move.l $4,a6 ; execbase
X lea rbfinterrupt(pc),a1
X moveq.l #11,d0
X jsr _LVOSetIntVector(a6)
X move.l d0,oldrbfinterrupt
X lea tbeinterrupt(pc),a1
X moveq.l #0,d0
X jsr _LVOSetIntVector(a6)
X move.l d0,oldtbeinterrupt
X
X lea CUSTOM,a0
X move.w _baudper,SERPER(a0) ; set period
X
X move.w #$3fff,$bfd0fe ; init handshake lines
X move.w INTENAR(a0),oldintena
X move.w #$8801,INTENA(a0) ; turn on RBF and TBE INTENA
X move.w #$0801,INTREQ(a0) ; clear RBF and TBE INTREQ
X move.w #$c000,INTENA(a0) ; enable
X move.l (sp)+,a6
X rts
X
X
X_closeserial
X move.l a6,-(sp)
X lea CUSTOM,a0
X move.w #$4000,INTENA(a0) ; disable
X move.l $4,a6 ; execbase
X move.l oldrbfinterrupt,a1
X moveq.l #11,d0
X jsr _LVOSetIntVector(a6)
X move.l oldtbeinterrupt,a1
X moveq.l #0,d0
X jsr _LVOSetIntVector(a6)
X
X lea CUSTOM,a0
X move.w #$0801,INTENA(a0) ; turn off RBF and TBE INTENA
X move.w oldintena,d0
X and.w #$0801,d0 ; mask for bit 11 and bit 1.
X bset #15,d0 ; set/clr = 1 (set)
X move.w d0,INTENA(a0) ; reset old RBF and TBE INTENA
X
X bclr.b #1,LED
X
X move.w #$0801,INTREQ(a0) ; clear RBF and TBE INTREQ
X move.w #$c000,INTENA(a0) ; enable
X move.l (sp)+,a6
X rts
X
X_sendser
X lea CUSTOM,a0
X move.w #$4000,INTENA(a0)
X
X move.l tbetail,a1
X cmpa.l tbehead,a1
X beq.b 5$
X move.w #$8001,INTREQ(a0) ; generate a tbe interrupt
X5$
X move.b d0,(a1)+ ; queue up byte
X cmpa.l #tbeqend,a1
X bne.b 10$
X lea tbequeue(pc),a1
X10$ move.l a1,tbetail
X
X move.w #$c000,INTENA(a0)
X rts
X
X
X; send byte in d0 to serial port, non-buffered.
X_sendsernobuff
X lea CUSTOM,a0
X move.w #$4000,INTENA(a0)
X1$ move.w SERDATR,d1
X btst #13,d1 ; check TBE
X beq.b 1$ ; buffer busy
X
X move.w #$100,d1
X move.b d0,d1
X move.w d1,SERDAT(a0)
X2$ move.w SERDATR(a0),d1
X btst #13,d1 ; check TBE
X beq.b 2$ ; buffer busy
X move.w #$001,INTREQ(a0) ; clear TBE interrupt
X
X move.w #$c000,INTENA(a0)
X rts
X
X
X; uses a0
X_readser
X cmp.w #ESCAPE,_raw ; quits on ESC from input handler
X beq.b 20$
X move.l rbfhead,a0
X cmpa.l rbftail,a0
X beq.b _readser
X move.b (a0)+,d0
X cmpa.l #rbfqend,a0
X bne.b 10$
X lea rbfqueue(pc),a0
X10$ move.l a0,rbfhead
X20$
X rts
X
X_checkser
X move.l rbfhead,a0
X cmpa.l rbftail,a0
X bne.b dataisin
X moveq.l #0,d0
X rts
Xdataisin
X moveq.l #1,d0
X rts
X
X
X; rawkey in d0
X; ascii returned in d0
X_rawtoascii
X cmp.b #79,d0
X bls.b getascii
X moveq.l #0,d0
X rts
Xgetascii
X lea asciitable,a0
X move.b 0(a0,d0),d0
X rts
X
X
X section asciitable,data
X
X; This is a quick trick, don't do this for anything other than
X; home use, boys and girls. Use rawkeyconvert, etc.
X
Xasciitable
X dc.b '`' ; backquote `
X dc.b '1'
X dc.b '2'
X dc.b '3'
X dc.b '4'
X dc.b '5'
X dc.b '6'
X dc.b '7'
X dc.b '8'
X dc.b '9'
X dc.b '0'
X dc.b '-'
X dc.b '='
X dc.b $0D ; \
X dc.b 0
X dc.b '0' ; keypad 0
X dc.b 'q'
X dc.b 'w'
X dc.b 'e'
X dc.b 'r'
X dc.b 't'
X dc.b 'y'
X dc.b 'u'
X dc.b 'i'
X dc.b 'o'
X dc.b 'p'
X dc.b '['
X dc.b ']'
X dc.b 0
X dc.b '1'
X dc.b '2'
X dc.b '3'
X dc.b 'a'
X dc.b 's'
X dc.b 'd'
X dc.b 'f'
X dc.b 'g'
X dc.b 'h'
X dc.b 'j'
X dc.b 'k'
X dc.b 'l'
X dc.b ';'
X dc.b $27 ; ' single quote
X dc.b 0
X dc.b 0
X dc.b '4'
X dc.b '5'
X dc.b '6'
X dc.b 0
X dc.b 'z'
X dc.b 'x'
X dc.b 'c'
X dc.b 'v'
X dc.b 'b'
X dc.b 'n'
X dc.b 'm'
X dc.b ','
X dc.b '.'
X dc.b '/'
X dc.b 0
X dc.b '.' ; keypad
X dc.b '7'
X dc.b '8'
X dc.b '9'
X dc.b ' '
X dc.b $8 ; backspace
X dc.b $9 ; tab
X dc.b $D ; enter cr
X dc.b $D ; return cr
X dc.b $1B ; ESC
X dc.b $7f ; delete
X dc.b ''
X dc.b 0
X dc.b 0
X dc.b '-' ; keypad
X dc.b 0
X dc.b 0
X dc.b $b ; up arrow
X dc.b $a ; down arrow
X dc.b $20 ; rt arrow
X dc.b $8 ; left arrow
X
X END
END_OF_FILE
if test 5691 -ne `wc -c <'serial.a'`; then
echo shar: \"'serial.a'\" unpacked with wrong size!
fi
# end of 'serial.a'
fi
if test -f 'st.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'st.c'\"
else
echo shar: Extracting \"'st.c'\" \(1882 characters\)
sed "s/^X//" >'st.c' <<'END_OF_FILE'
X/* ST.c : Serial Test */
X/* Created by John Schultz, 4/16/90 */
X/* Interrupt driven serial I/O testbed */
X
X#include <stdio.h>
X#include <dos.h>
X#include "input.h"
X
X#define CLOCK 3579545
X
X#define MINBAUD 300 /* Change these at will */
X#define MAXBAUD 230000
X
X#define BUFFSIZE 80
X
X#define ESCAPE 69
X
Xextern void openserial(void);
Xextern void __asm sendser(register __d0 char c);
Xextern void __asm sendsernobuff(register __d0 char c);
Xextern char __asm readser(void);
Xextern short __asm checkser(void);
Xextern char __asm rawtoascii(register __d0 char c);
X
Xextern short far baudper;
X
Xvoid main(int argc,char ** argv) {
Xshort i = 0;
Xlong console;
Xlong baud;
Xchar traw;
Xshort notquit = 1;
Xchar buffer[BUFFSIZE];
X
X
X if (argc != 2) {
X printf("USAGE: st <baud>\n");
X exit(0);
X }
X
X baud = atoi(argv[1]);
X if (baud < MINBAUD)
X baud = MINBAUD;
X else if (baud > MAXBAUD)
X baud = MAXBAUD;
X
X printf("Setting baud to %d. Press ESC to quit.\n",baud);
X
X baudper = (CLOCK / baud)-1;
X
X console = _dopen("*",MODE_OLDFILE);
X if (console == -1) {
X printf("Couldn't open console.\n");
X exit(0);
X }
X
X if (createti()) {
X openserial();
X traw = 0;
X raw = 0;
X
X while (notquit) {
X if (raw) {
X traw = raw;
X raw = 0;
X if (traw == ESCAPE) notquit = 0; /* ESC */
X traw = rawtoascii(traw);
X sendser(traw);
X sendser(traw);
X sendser(traw);
X sendser(traw);
X sendser(traw);
X sendser(traw);
X sendser(traw);
X sendser(traw);
X sendser(traw);
X sendser(traw);
X
X }
X
X if (checkser())
X for (i = 0;
X (i < BUFFSIZE) && (checkser());
X buffer[i++] = readser());
X
X if (i > 0) _dwrite(console,buffer,i);
X
X i = 0;
X
X } /* while notquit */
X
X closeserial();
X deleteti();
X } /* if createti */
X
X printf("\n");
X
X} /* END ST.c */
END_OF_FILE
if test 1882 -ne `wc -c <'st.c'`; then
echo shar: \"'st.c'\" unpacked with wrong size!
fi
# end of 'st.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have the archive.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.