newman@dasys1.UUCP (Ken Newman) (05/02/88)
Sorry if this has whizzed by in this group before, but I would like to know if someone has a solution to the problem of buffering raw keyboard input on the ST, such as obtained by using the C routines Crawcin() or Bconin(). There doesn't seem to be any buffering at all with these routines, although I believe there is using the standard getchar (which is no good for my purposes). I would like perhaps a full 80-char line of typeahead and haven't been able to make sense of the keyboard queue routines in the Megamax docs. Thnx in advance. -- Ken Newman Big Electric Cat Public UNIX ..!cmcl2!phri!dasys1!newman
leo@philmds.UUCP (Leo de Wit) (05/04/88)
In article <4215@dasys1.UUCP> newman@dasys1.UUCP (Ken Newman) writes: > >Sorry if this has whizzed by in this group before, but I would like to >know if someone has a solution to the problem of buffering raw keyboard >input on the ST, such as obtained by using the C routines Crawcin() or >Bconin(). There doesn't seem to be any buffering at all with these >routines, although I believe there is using the standard getchar (which >is no good for my purposes). I would like perhaps a full 80-char line of >typeahead and haven't been able to make sense of the keyboard queue >routines in the Megamax docs. Thnx in advance. >-- >Ken Newman >Big Electric Cat Public UNIX >..!cmcl2!phri!dasys1!newman Here's how keyboard buffering is done (at least I thought so ...) : The keyboard ACIA chip reads the keyboard and makes the characters available at an I/O address (0xFF????). The processor, as part of the VBL routine, reads the byte at that address (if the status, another I/O address is O.K.) and places it in a buffer, let's call it the terminal I/O buffer. This buffer is used by the BIOS for reading a single character and testing availability of a character; also GEMDOS uses it to read a single character with/without echo and to read a complete line with editing capabilities (I think these are your Crawcin() and Bconin()). I don't quite see why you should need direct access to the terminal I/O buffer; you can use bios calls to check availability of a character (or use something like kb_hit()) and if there's a character, store it in your buffer. It could however be possible that you just want to look at characters in the buffer, and not mark them read, so here is some code (I used it to trap control C's: I can now use stdio without control C terminating the program - a shell): /* sh.prg */ . . . #define TRUE 1 #define FALSE 0 #define CONTROLC 0x2e0003 #define CONTROLQ 0x100011 #define CONTROLS 0x1f0013 typedef struct iorec { char *ibuf; short ibufsize, ibufhead, ibuftail, ibuflow, ibufhigh; } iorec; typedef unsigned char bool; . . . iorec *iop; . . . iop = (iorec *)xbios(14,1); /* get ptr. to terminal I/O buffer structure */ . . . bool test_ctrlc() /* test for control C; discard buffer if you see one */ { int i; for (i = iop->ibufhead; i != iop->ibuftail; ) { i += 4; if (i == iop->ibufsize) { i = 0; } if (*(int *)(iop->ibuf + i) == CONTROLC) { /* had one */ iop->ibufhead = iop->ibuftail; /* effectively clears the buffer */ return (bool)TRUE; } } return (bool)FALSE; } Some remarks: a) Lattice has int == 4 bytes, short == 2 (Megamax I thought int == 2). So you should replace the *(int *) by *(long *), and the short by int. b) The buffer struct contains: ibuf: start of the buffer ibuftail: index of write position ibufhead: index of read position ibuflow : index of low water mark ibufhigh: index of high water mark Each character is stored as a (4-byte) int, the scancode in the high word, the ASCII code in the low word. This is the same int as you get from gemdos(7) (character in without echo). Note that old BIOS versions used 2 bytes int to store a character (I know, I had TOS in RAM!), so there may be portability problems (i.e. between Ataris). c) An empty buffer is indicated by ibufhead == ibuftail. d) The xbios call returns a pointer to the structure. e) It would have been possible to define ibuf as (int *); the trouble is that then the indexes have to be converted (being byte-offsets). f) Of course, you can also use gets() or fgets(ptr,size,stdin) to read a line or use gemdos(10) (READLINE), but that is not very raw; several characters are interpreted and there must be a termination character (mostly Newline). I hope this helps and is raw enough? Have a nice byte ( %-) ! (please mail me if not). Leo. (What you C is what you get).
braner@batcomputer.tn.cornell.edu (braner) (05/05/88)
[] In article <478@philmds.UUCP> leo@philmds.UUCP (L.J.M. de Wit) writes: >Here's how keyboard buffering is done (at least I thought so ...) : >The keyboard ACIA chip reads the keyboard and makes the characters available >... The processor, as part of the VBL routine, reads the byte... - the keyboard (and mouse and joystick) events have their own interrupt. >#define CONTROLC 0x2e0003 > ... > for (i = iop->ibufhead; i != iop->ibuftail; ) { - note that what "they" call head and tail may be the reverse of what you (or I, anyway) would call them... > if (*(int *)(iop->ibuf + i) == CONTROLC) { - this may fail if "conterm" is set so that the kbdshift info is in the top byte of the top word. Better use: if (((*(int *)(iop->ibuf + i)) & 0xFF00FF) == CONTROLC) ^^^^^^^^^^ > a) Lattice has int == 4 bytes, short == 2 (Megamax I thought int == 2). > So you should replace the *(int *) by *(long *), and the short by int. - yup, in Megamax (and Laser) int==16 bits, long==32 bits. Avoid shorts. (I _think_ they're 8 bits in old Megamax, 16 in Laser.) Better to write code like this: #define WORD int /* this is for megamax */ ... ... WORD ... /* all through the code where it matters */ (Makes it a lot easier to port to another compiler.) >I hope this helps and is raw enough? Have a nice byte ( %-) ! - thanks, Leo! > Leo. (What you C is what you get). - Moshe Braner. (YAFIYGI) (You asked for it, you got it.) (TeX) (Still looking for a used 520ST system) STOP CONTRA AID: BOYCOTT COCAINE
leo@philmds.UUCP (Leo de Wit) (05/06/88)
In article <4694@batcomputer.tn.cornell.edu> braner@tcgould.tn.cornell.edu (braner) writes: >In article <478@philmds.UUCP> leo@philmds.UUCP (L.J.M. de Wit) writes: >>Here's how keyboard buffering is done (at least I thought so ...) : >> ...[stuff deleted]... >> for (i = iop->ibufhead; i != iop->ibuftail; ) { >- note that what "they" call head and tail may be the reverse of what you > (or I, anyway) would call them... Agree, but I got (a hint for) the names from Data Becker's Atari ST Intern. I think with a circular buffer, a reader and a writer it's anyway a question whose side you're on. >> for (i = iop->ibufhead; i != iop->ibuftail; ) { >> if (*(int *)(iop->ibuf + i) == CONTROLC) { >- this may fail if "conterm" is set so that the kbdshift info is in the top > byte of the top word. Better use: > if (((*(int *)(iop->ibuf + i)) & 0xFF00FF) == CONTROLC) > ^^^^^^^^^^ Still better maybe: for (i = iop->ibufhead; i != iop->ibuftail; ) { if (((*(int *)(iop->ibuf + i)) & 0xFF0000) == CONTROLC) the ascii bindings may be changed by an xbios call, it's safer to use just the scancode. But thanks for the correction, anyway! > Better to write code like this: > #define WORD int /* this is for megamax */ > ... WORD ... /* all through the code where it matters */ > (Makes it a lot easier to port to another compiler.) or to use: #include "portab.h" which just includes such definitions (at least for Lattice there's such a file). >- Moshe Braner. (YAFIYGI) (You asked for it, you got it.) (TeX) >(Still looking for a used 520ST system) I use one. A plus that is (520 ST++ :=) Leo (C-ing is believing).
apratt@atari.UUCP (Allan Pratt) (05/07/88)
Leo@philmds's description of keyboard input on the ST is imaginitive, but totally off the wall. The ST has INTERRUPT-DRIVEN keyboard input: when a character is pending at the keyboard port, the processor is INTERRUPTED (no Vblank). The character is read from the port, and placed in the keyboard input buffer (the one whose address you can get from the Iorec Xbios call). You don't need to use this buffer, however, if you understand the interactions between BIOS and GEMDOS I/O. The potentially confusing part is that if you do GEMDOS cooked input or output, the BIOS buffer is COMPLETELY EMPTIED into a GEMDOS buffer. So if you follow GEMDOS output with BIOS input you will get "no characters waiting." GEMDOS "cooked" I/O is Cconin, Cnecin, Cconout, Cconws, and Cconrs, and Fread and Fwrite on handles which refer to the console, such as handles 0 and 1 (stdin, stdout), handles DUP'ed from those, or -1, which always refers to the console, even if handles 0 and 1 are redirected. If you don't want ^C to terminate your program, you can either (A) use only BIOS calls, or (B) use only GEMDOS raw calls (Crawcin, Crawio, Cconis), or (C) use a terminate-vector handler which longjmp's to your recovery code. The best reason to use the buffer structure returned by the Iorec call is as a quick check for input keys pending. Checking to see if in == out (meaning the buffer is empty) is lots quicker than the equivalent BIOS call. This only works if you use NO GEMDOS console I/O calls. (I haven't forgotten about critical sections: I investigated, and they don't matter here.) ============================================ Opinions expressed above do not necessarily -- Allan Pratt, Atari Corp. reflect those of Atari Corp. or anyone else. ...ames!atari!apratt
apratt@atari.UUCP (Allan Pratt) (05/10/88)
From article <480@philmds.UUCP>, by leo@philmds.UUCP (Leo de Wit): >>> if (*(int *)(iop->ibuf + i) == CONTROLC) { > if (((*(int *)(iop->ibuf + i)) & 0xFF0000) == CONTROLC) > the ascii bindings may be changed by an xbios call, it's safer to use just > the scancode. But thanks for the correction, anyway! It is NOT safer to use the scan code, becuase the scan code for the ninth letter from the right of the next-to-bottom row of the keyboard is constant, while the position of the letter 'C' is not. INTERNATIONALIZE your programs. Don't make people hit ^B if that happens to be the key there. (I don't know if the letter C does, in fact, float...) Also note that European keyboards have a key (called the ISO key) between 'Z' and left-shift... The left-shift key is extra wide to cover this up on USA keyboards. That's why I didn't call the USA 'C' "the fourth key from the left." Use ASCII codes: check for ((value & 0x000000FFL) == 3). If your document says "^C," check this way. If your document says "^(ninth from right)" you should use the scan code. ============================================ Opinions expressed above do not necessarily -- Allan Pratt, Atari Corp. reflect those of Atari Corp. or anyone else. ...ames!atari!apratt