Sub: Minutes of your RT Conference. >From Steno: "Sam" Date: 04/23/89 Time: 22:09EDT Attendees: [D.RUFFER] [[len] NMORGENSTERN] [[Kevin] APPERT] [[jax32] FIGCHAPTERS] Minutes: is here. <[len] NMORGENSTERN> Hi, I made it on time! hi len I thought you were not going to be here <[len] NMORGENSTERN> Hi I went to see my granddaughter in a play. I just made it despite traffic. If there had been any slowup... did you put together any kind of tutorial for tonight? <[len] NMORGENSTERN> I would not. No, but I can improvise. Any suggestions? do you normally? <[len] NMORGENSTERN> I discusDenpends on who is here. Usually the people who come are fairly experienced & we just chat. I presented vocabularies at the last North Bay Fig & can do it again. well, I've got a UART control system that I could talk about <[len] NMORGENSTERN> I would like that! <[len] NMORGENSTERN> brb %I had to set up my "chat mode" with split screen. ok I can extract some code from an application I did a couple years back. I've been looking at it again, and it could be interesting (maybe) <[len] NMORGENSTERN> Sounds good. I know v. little about real-time control v. little = nothing ok, then this one even gets into interrupts <[len] NMORGENSTERN> Great we'll wait till some more people show up, and see if they are intereseted also <[len] NMORGENSTERN> Just what I was going to suggest on another note... do you have data for the data base you are setting up? <[len] NMORGENSTERN> That is the problem. I have a few things: a list of bbs' a list of Fig chapters, probably not quite up to date a partial list of books on forth a list of vendors & a few other things. . is here. hi kevin <[len] NMORGENSTERN> Hi Kevin <[Kevin] APPERT> hi Len, Den did you see the stuff on the knowledge base I put into the Pivate Cat? <[len] NMORGENSTERN> No. Will look at it it might be interesting to do something online with the data <[len] NMORGENSTERN> What I would like to do is this: 1. Set up a small data base. 3. NOT accept any criticisms! If somebody thinks there is an error, he/she would have to submit a correct version, and then <[Kevin] APPERT> an error like skipping 2.? <[len] NMORGENSTERN> we would substitute it for the incorrect 1 2. Publish it, prossibly on Genie What I would like to do is this: I have a funny terminal program! it skips lines then transmits others! oh, interesting <[Kevin] APPERT> weird, the previous version of mirror works fine. <[len] NMORGENSTERN> I am always right because: If you show me that I am wrong, I will change my mind, and then I will be right. If I could find a volunteer to help (hint hint) to help set it up, we could put it online and maintain it quite easily <[len] NMORGENSTERN> Yep, Kevin, it died of "improvements" as the old medical joke goes. I would like to work on that, Dennis, with you. <[Kevin] APPERT> why don't you use the old version? Check out topic 3 in cat 16 before you agree to anything :-) <[len] NMORGENSTERN> John Peters, who used to be disk librarian Kevin, this is better in many ways. I just have to get used to it John said that Zimmer has done a hypertext in Forth! I want to look at that, & maybe we can run our data base in that. Thanks, Dennis will do <[Kevin] APPERT> be carefull what you call "hyper". It is becomming the "turbo" of this season <[len] NMORGENSTERN> Right, Kevin <[Kevin] APPERT> do you really mean hypertext, or hypercard? Tom need to make a windows version to do it right. <[len] NMORGENSTERN> Don't know the correct name; it should be able to go <[Kevin] APPERT> the concepts are similar, but not identical as I understand it <[len] NMORGENSTERN> from screen to screen by pressing keys; be intuitive & easy to learn. . Also easy to update, which Mac Hypercard really is not, point of view. <[Kevin] APPERT> does somebody know anything about controlling uarts? <[len] NMORGENSTERN> although it is powerful & not hard to learn from the programmers point of view. . I do kevin, but was waiting for some more people <[Kevin] APPERT> never struck me as being hard if you have the data sheet. impossible without it! they are not, but I was going to extract some code from an old application of mine that controls their features on a PC that is if there was any interest in seeing it :-) <[len] NMORGENSTERN> You have to use the "tools", set a button, etc. etc. The PC ypertext I use merely needs a file name enclosed in angle brackets, with optional screen # & line . What exactly is a UART? I don't have a precise idea, Dennis Universal Asyncronous Receiver/Transmitter <[Kevin] APPERT> universal asynchronous receiver/transmitter <[len] NMORGENSTERN> Thanx <[Kevin] APPERT> ^^^^^^types faster beat ya, na na really just a parrallel to serial converter <[Kevin] APPERT> changes parallel bus transactions... from the processor into serial async (like rs232) and back again... is here. hi jax <[len] NMORGENSTERN> Hi Jax <[jax32] FIGCHAPTERS> hi . why 32 tonight jack? <[Kevin] APPERT> although rs232 actually can be used syncronously. (with a seperate... clock rather than the self-clocking async. <[jax32] FIGCHAPTERS> because ... i wrote ans assembler over the weekend for the SC32. . <[len] NMORGENSTERN> ans assembler? <[jax32] FIGCHAPTERS> ( an ) . <[Kevin] APPERT> hi Jax <[jax32] FIGCHAPTERS> rehi kev why a seperate clock kevin? (thinking he might know more than I do) <[Kevin] APPERT> you do without the stop and start bits, and can run a lot faster in order to de-code async... I guess most of the chips I'm used to need a baud clock anyway, and can do sync as a byproduct <[jax32] FIGCHAPTERS> brb ... will stay on line but wandering off after runaway baby ... <[Kevin] APPERT> you use a clock which runs a clock... 16 * the bit rate... so you can count those clocks (16 + 8) from the start bit edge to the middle of the 1'st data bit... if you are using syncronous transmission, all you need is a 1x clock, and you shift the data right in, the only timing problem... is the question of wether the data has settled by the time you get the... active edge of the clock. . yes, I haven't played much with sync yet... but I understant that they usually use a special startup sequence... instead of the 1 start bit that async uses <[Kevin] APPERT> it isn't used much, as the whole reason for serial communications.... is to minimize the number of long, thin copper pieces. you need not have another one for the clock it is used a lot by IBM byt they use the bisync variety but please don't ask me to explain bisync :-( ok are we ready to start a little playing with code? <[len] NMORGENSTERN> ga ok, I will be pulling this stuff from the actual source, so please bear with the delays (Windows isn't exactly speedy) <[Kevin] APPERT> is Jennifer taking the night off? yes, "Sam" agreed to step in for here first we will start with some constants HEX 3F8 CONSTANT 1COM 2F8 CONSTANT 2COM 20 CONSTANT 8259A 21 CONSTANT 8259B DECIMAL CREATE SAVE-AUX 0 , 0 , VARIABLE AUX 1COM AUX ! 1COM and 2COM are the address for the uarts on a PC <[Kevin] APPERT> it's nice to know there are still some constants in this ever-changing world :-) the 8259A and B are the interrupt controllers that you have to deal with if you want "real fast" data input. SAVE-AUX is used to remember what the interrupt pointer was pointing to before you change it. MSDOS gets real upset if you don't restore it before you exit. and AUX contains the current port address, notice I start by using 1COM. is here. now some simple deffinitions <[Kevin] APPERT> hi gary <[Gary] GARY-S> 'lo : +AUX ( # -- a P: Add base address to port # ) AUX @ + ; : @AUX ( # -- b P: Fetch byte at com port ) +AUX PC@ ; : !AUX ( b # -- P: Store byte at com port ) +AUX PC! ; these words allow me to talk to either port from high level excuse the inefficient code, but these words are not used when time is a problem. now some more constants : UART ( name \ # -- P: Port Definitions ) CONSTANT ; 0 UART DLL 2 UART IIR 4 UART MCR 6 UART MSR 1 UART DLM 3 UART LCR 5 UART LSR 7 UART MSP 0 UART RBR 0 UART THR 1 UART IER and before you ask, here is what they stand for IIR Interrupt ID register IER Interrupt enable register RBR Recieve buffer register THR Transmitt holding register DLL LSB Divisor latch DLM MSB Divisor latch LCR Line control register LSR Line status register MCR Modem control register MSR Modem status register MSP Modem speed register these define all the registers on an 8250 UART that is in every IBM PC on the market some use more soffisticated chips, but these words should work on them all. most of the work is done in the Line control register. It is a read only port so I need the following word to talk to it. VARIABLE 'LCR ( -- a P: Contents of LCR ) HEX : !LCR ( b mask -- P: Mask and set bits in LCR register ) 'LCR C@ AND + DUP 'LCR C! LCR !AUX ; it saves the contents so I can set one "feature" at a time. <[Kevin] APPERT> who was that maske register? oops, masked }-) here is the control words: : Bits ( n -- P: Data bits) 5 MAX 8 MIN 5 - 0FC !LCR ; : Stps ( n -- P: Stop bits) 1 MAX 2 MIN 1 - 4 * 0FB !LCR ; : Penable ( ? -- P: Parity Enable) IF 8 ELSE 0 THEN 0F7 !LCR ; : Eparity ( ? -- P: Even Parity) IF 10 ELSE 0 THEN 0EF !LCR ; : Sparity ( ? -- P: Stick Parity) IF 20 ELSE 0 THEN 0DF !LCR ; : Break ( ? -- P: Send Break) IF 40 ELSE 0 THEN 0BF !LCR ; : Daccess ( ? -- P: Divisor Latch) IF 80 ELSE 0 THEN 07F !LCR ; DECIMAL I've used this stuff in a couple of Forths, so I could not garantee the value of true, thus the IFs instead of just ANDing the masks this is the normal stuff that needs to be set on a UART also we need baud control: : Baud ( n -- P: Set Baud Rate to n 1 1152 100 ROT */ 256 /MOD 1 Daccess DLM !AUX DLL !AUX 0 Daccess ; this allows you to say things like 1200 Baud <[len] NMORGENSTERN> v. nice next, we need to define all the other controls that a PC has: CREATE DTR MCR C, 1 C, ( -- a P: Data Term Rdy ) CREATE RTS MCR C, 2 C, ( -- a P: Request To Send ) CREATE Modem-reset MCR C, 4 C, ( -- a P: Reset bit ) CREATE Interrupts MCR C, 8 C, ( -- a P: Interrupt enable ) CREATE Loopback MCR C, 16 C, ( -- a P: Self test loop ) CREATE Receiver IER C, 1 C, ( -- a P: Uart receiver ) CREATE Transmitter IER C, 2 C, ( -- a P: Uart transmitter ) CREATE Line-status IER C, 4 C, ( -- a P: Line indicator ) CREATE Modem-status IER C, 8 C, ( -- a P: Modem indicator ) and since these are "do nothing" words, we need a way to turn them on and off: : ENABLE ( a -- P: Turn on control bit ) DUP 1+ C@ SWAP C@ DUP @AUX ROT OR SWAP !AUX ; : DISABLE ( a -- P: Turn off control bit ) DUP 1+ C@ 255 XOR SWAP C@ DUP @AUX ROT AND SWAP !AUX ; that is the extent of the modem control is there any questions before I move on to the "real meat"? <[len] NMORGENSTERN> Dennis, thanx <[Gary] GARY-S> Is tonite terminal emulator nite ? <[len] NMORGENSTERN> In ENABLE DISABLE what does "a" stand for? (in the stack diagrams) UART night gary "a" stands for an address on the stack <[len] NMORGENSTERN> Thanks I try to follow the conventions set up by Kim Harris <[Gary] GARY-S> earlier you said there were other... UART's besides the 8250... just a note, they have to accept the 8250 command set... to be compatible... they may do more, BUT they can NOT do less. ga true when I said these words should work, I meant on most IBM PCs and compatables there are a few that use some "improved" chips in the PC but since the must still be compatable, these words should still work. <[Gary] GARY-S> That was my point exactly any other questions, or are we ready for some code <[Gary] GARY-S> Since this is a gathering of the deacons - g'nite has left. is everyone else up for more of this? <[len] NMORGENSTERN> ga ok now for the root of the interrupt system: CREATE VECTORS ( -- a P: Interrupt vectors ) 8 ALLOT CREATE INTR ( -- a P: Initial Interrupt Entry ) ASSEMBLER DI PUSH DX PUSH CX PUSH AX PUSH DS PUSH CS AX MOV AX DS MOV 0 # AX MOV AUX #) DX MOV IIR # DX ADD DX AL IN 7 # AX AND 1 # AX CMP 0<> IF AX DI MOV VECTORS # DI ADD 0 [DI] JMP THEN HERE 8259A # DX MOV 32 # AL MOV DX AL OUT ( EOI ) DS POP AX POP CX POP DX POP DI POP IRET ok, does this need explaination? :-) the VECTORS will hold vectors for the interrupt code... the 8250 can generate 4 different interrupt that all use this code to get into them the first line of INTR just save all the registers I will use the next re-establishes the segment pointer, and loads the port address then we fetch the Interrupt Identification Register to see if the interrupt was me (in case of spurious interrupts) if it was one of mine, I jump to the proper vector <[Kevin] APPERT> or more than one device connected to a given interrupt otherwise, at the HERE I return from the interrupt. the EOI isn't needed (I found) since it is done by the IRET but that line acknowledges the interrupt to the 8259 that is a special chip to handle interrupt on the PC I also use the code after HERE to return from the vectored interrupts <[Kevin] APPERT> it's handy to have a disable-interrupt at the beginning and an enable at the end if you are going to test the code by invoking it yourself a disable is not needed at the beginning kevin since intel chips take care of that when vectoring to the interrupt test code??? but I KNOW this works! :-) <[Kevin] APPERT> :-) <[jax32] FIGCHAPTERS> are we swapping interrupt structure horror stories? then, I use a macro to patch in the interrupt vectors ASSEMBLER DEFINITIONS : VECTOR ( addr # -- P: Finish and vector UART interrupts ) 2* VECTORS + ! [ DUP ] LITERAL #) JMP ; DROP this code patches in the vector, and assembles a jump to the HERE that we saw in the previous code. <[jax32] FIGCHAPTERS> maybe one of the assembled assembly jeenyuses can help me ... this is a VESTA story ... called the "Interrupt that Wouldn't Die" a true horror story that continues to the present date! Some of our boards ... yes? <[jax32] FIGCHAPTERS> have always booted DOS ... if the detachable board with the disk controller is present ... and a disk is in the drive with MSDOS on it. ... Anyway ... on the 188 boards ... we changed the BIOS so that everything was synched ... with the NMI int service that originates in the DUART counter ... instead of timing the disk service by loops at powerup. Dig? much more scientific! :-) ... Anyway ... Nowadays .. If the board and BIOS find the disk controller ... and the disk is present ... the DUART INT goes active-lo and is NEVER SERVICED. BYE BYE Time. Board locked up. ....??????????????????????????????????????????????????? ???? . it sure will be if the DUART is not serviced... <[jax32] FIGCHAPTERS> right. <[Kevin] APPERT> is the int acknowledged? <[jax32] FIGCHAPTERS> but WHY is it not serviced? it is NMI have no idea what causes it, but I'd sugest a dummy routine to service it <[jax32] FIGCHAPTERS> It just goes /INT in the middle of the test to see if the controller is there and BOING! It is already active at powerup, has been serviced a few times already. <[len] NMORGENSTERN> What is NMI? <[Kevin] APPERT> non maskable interupt <[len] NMORGENSTERN> thanx is there an interrupt vector present to do it? <[jax32] FIGCHAPTERS> It gets to the place in the code and BYE. Oh, yes, the code is all there. If you knew how many times we have taken this apart . hum, sounds like logic analyzer time <[Kevin] APPERT> have you used your orion to capture a trace? <[jax32] FIGCHAPTERS> This is something we studied since last September. You bet, but Orion is a little flakey vis-a-vis NMIs on the 188. that is the problem with interrupts, you just have to assume that they happen properly. They are pretty tought to look at even with a good tracer. <[jax32] FIGCHAPTERS> right ... esp when analyzer wants same vect. . <[Kevin] APPERT> perhaps you have found a bug with the 188? <[jax32] FIGCHAPTERS> we thought ... that we MIGHT INDEED have found a 80188 bug. <[Kevin] APPERT> is this repeatable? does it happen every time? <[jax32] FIGCHAPTERS> HEVVINS NOSE that there are enough Intel buggies. yes, it happens EVERY Time. Since September. The goofy thing is .... if we launch the SAME ROUTINE after it is booted ... by "pencilling in" the BIOS variables that hold controller info ... and calling the int ... it boots DOS like a whiz. . does the orion have a time analyzer mode in it, where you can look at what is on the bus signals? <[Kevin] APPERT> something not getting initialized? <[jax32] FIGCHAPTERS> You'd think so kev, but it doesn't look like it. or bus cross talk <[jax32] FIGCHAPTERS> I say it's a hole in the DUART code ... what's that D.R. .. how so? . maybe, just maybe... the interrupt signals are getting crossed... or the address lines... I've seen it happen, and boy is it a bitch to track <[Kevin] APPERT> there are several logic analyzers (HP and Arium and Phillips) on the market ... <[jax32] FIGCHAPTERS> but! This is an int that occurs 18 times a second ... that works fine at all times EXCEPT during boot ... at one exact point in the code that we have been over ... time and time again ... at a point where ... a DMA xfer begins. . <[Kevin] APPERT> these days which record transitions and not states. perhaps you can rent a ... cad-o-lax and analyze it to death. ah, more clues.... have you toughrouly analyzed the code?.... <[jax32] FIGCHAPTERS> Well, is code ever analyzed thoroughly? That is a matter for Religion, not Science ... but as far as is within us, as they say, YES> maybe the is a bug, if it is reapeatable, that points to software, and it should be finable <[jax32] FIGCHAPTERS> . "should be" is the operative word in that sentence, in this case. . it is sometimes nice to have timeing diagrams right next to the source code, but it take a real good analyzer to do it. <[jax32] FIGCHAPTERS> well, Intel ... Keeps reassuring us ... that there is no conflict ... DMA<>NMI ... "but" ... . and you believe them <[Kevin] APPERT> see what you get for being clever. use a timing loop (and a stone knife while you are about it) <[jax32] FIGCHAPTERS> not my code! I have always gotten out the scopes to verify what they said. <[jax32] FIGCHAPTERS> my advice : "No more intel chips"! but do they listen? :-) . <[Kevin] APPERT> segments are for earthworms! hard to get away from them when making a MSDOS computer <[jax32] FIGCHAPTERS> If it was just segments, we could live with it. what it is all about, is outdated concepts embedded in silicon. which covers 90 % of the chips made. but NOT the SC32!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! . <[Kevin] APPERT> do you actually have a sc32, or are you just writing assemblers ? ok, have we proved we can't really help you jack? Do we want to continue the lesson? <[jax32] FIGCHAPTERS> answers: almost & yes. dennis ... ENOUGH BALONEY :-) Len ... are you member any computer book clubs? <[len] NMORGENSTERN> No, I am a member of no book club at all ga ok to continue? <[jax32] FIGCHAPTERS> . what did I interrupt Dennis ( pardon pun) ok, I don't hear any objections so here I go: we were just about to get into the interrupt code itself... before talking about the the receive and transmit, here are the ones that are not really used: ASSEMBLER HERE ( P: Modem status interrupt ) MSR # DX MOV AUX #) DX ADD DX AL IN 0 VECTOR ASSEMBLER HERE ( P: Line status interrupt ) LSR # DX MOV AUX #) DX ADD DX AL IN 3 VECTOR all these words do is reset the interrupting thingie you will get these with noise on the line, or when the modem is working... if you want to use this code for modem transfers, you will need to put some code into these... my application was on a clean line to a directly connected device a tape reader if you must know you can see the use of VECTOR here... it takes the address from the HERE at the beginning of the code and the interrupt vector number and patches in the return jump. <[Kevin] APPERT> tape reader? those were the days actually, it is still being used kevin cassette tapes no less <[len] NMORGENSTERN> I thought you meant paper tape. ok, to do the receive logic, first we need somewhere to put the characters <[jax32] FIGCHAPTERS> gnite all has left. VARIABLE IN-PTR ( -- a P: Buffer pointer ) VARIABLE IN-POINTER ( -- a P: Received pointer ) CREATE IN-BUFFER ( -- a P: Received character buffer ) HERE 2048 DUP ALLOT BLANK LABEL >CHR ( -- a P: Buffer character ) IN-BUFFER # DI MOV IN-PTR #) CX MOV CX DI ADD AL 0 [DI] MOV CX INC 2047 # CX AND IN-POINTER #) CX CMP 0<> IF CX IN-PTR #) MOV THEN RET CODE !CHR ( b -- P: Store character in buffer ) AX POP >CHR #) CALL NEXT END-CODE : ?CHRS ( -- # P: # of characters in buffer ) IN-PTR @ IN-POINTER @ - DUP 0< IF 2048 + THEN ; the IN-PTR is for putting characters in, and the IN-POINTER is for taking them back out. the >CHR is the subroutine I will call, and !CHR is a test word (yes even I do that from time to time) used to store characters into the buffer. ?CHRs will tell me how many characters are in the buffer. then we have the receive interrupt code: ASSEMBLER HERE ( P: Receive character interrupt ) RBR # DX MOV AUX #) DX ADD DX AL IN >CHR #) CALL 2 VECTOR this gets the character into the AL register, and passes it to the receive subroutine. the transmit interrupt is not used either, but is needed to clear the mask if it is ever received: ASSEMBLER HERE ( P: Transmit character interrupt ) IER # DX MOV AUX #) DX ADD DX AL IN 253 # AX AND DX AL OUT 1 VECTOR That is really all there is to it. except the reset routine, but first... are there any questions on this? <[len] NMORGENSTERN> ga ok the reset routine is a little custom... but I am pasting directly from the application: : URESET ( -- P: Reset the uart to operate ) 0 0 !LCR 0 MCR !AUX 0 IER !AUX IN-PTR OFF IN-POINTER OFF 8 Bits 1 Stps 2400 Baud SAVE-AUX 2@ OR 0= IF ?VECTOR @VECTOR SAVE-AUX 2! @SEG INTR ?VECTOR !VECTOR THEN 8259B PC@ 8 AUX @ 1COM = IF 2* THEN NOT AND 8259B PC! ( 8259 Interrupt mask ) Modem-reset ENABLE 50 MS Modem-reset DISABLE Receiver ENABLE DTR ENABLE RTS ENABLE RBR @AUX DROP Interrupts ENABLE 5 MS ; : UNRST ( -- P: Turn off UART ) 8259B PC@ 8 AUX @ 1COM = IF 2* THEN OR 8259B PC! SAVE-AUX 2@ ?VECTOR !VECTOR 0, SAVE-AUX 2! 0 IER !AUX ; this should be pretty self explainitory, but.... I see I missed something... : ?VECTOR ( -- a P: Determine which interrupt vector to use ) 11 AUX @ 1COM = IF 1+ THEN ; {ed: I think this is what the missing code does, but I did not test it} CREATE !VECTOR ( aseg a # -- P: Set interrupt vector ) HEX AX POP DX POP DS POP 25 # AH MOV 21 INT IS AX MOV AX DS MOV NEXT CREATE @VECTOR ( # -- aseg a P: Get interrupt vector ) AX POP 35 # AH MOV 21 INT ES PUSH BX PUSH IS AX MOV AX ES MOV NEXT this words determines which interrupt to patch... my words @VECTOR and !VECTOR are just the IBM function call way to look at and set the interrupt vectors... and I don't have the code on line to paste, sorry. the UNRST is needed before you can return to DOS. any questions? <[len] NMORGENSTERN> No. Thank you Dennis. I have a lot to think about here.. I will study it. <[Kevin] APPERT> For posterity, I recommend a look at John James article on this topic, which is more complete than Dennis has time to be tonight. You can find it by looking in the "Bibliograpy of Forth" it was in Forth Dimensions some time ago I will try to do some cleaning up of it before posting the transcript... I didn't have time to go into much depth. <[len] NMORGENSTERN> I'll look it up. <[Kevin] APPERT> 60 min. is on . good night all has left. I will have to look up Jon's stuff <[len] NMORGENSTERN> Dennis you put up a lot of material! a little too much I think were the delays too long? <[len] NMORGENSTERN> I have only recently caught on to the idea. . . that an interrupt is essentially a subroutine that can be called at a time determined either by the program or by an external device. That is why I said I know almost nothing about them! they are the only way to deal with real time situations <[len] NMORGENSTERN> I think your timing was good. good, I hope it gets a lot of downloads <[len] NMORGENSTERN> It probably will thanks to Microsoft Windows, which made this pasting possible <[len] NMORGENSTERN> I wondered how you did it! switching back and forth real fast :-) <[len] NMORGENSTERN> Thanks again for taking this! My granddaughter was in a play They may show a scene in a Pepsi ad! wouldn't that be something! (Still under negotiation) sounds real neet for her glad you could be there <[len] NMORGENSTERN> She's 9, and was a born actress! That is she was miming at about 18 months. sounds real talented, is she going to get into it? <[len] NMORGENSTERN> Well, I will be able to take next week, God willing I may discuss vocabularies, if there is interest. good, I will have to work on coming up with another topic <[len] NMORGENSTERN> There is not a lot of real-time stuff published, I believe,... so it would be useful to have it here. if nothing else, these are at least downloaded well, my fingers are tired... see ya later? <[len] NMORGENSTERN> right, thanks again, bye has left. === End of Steno notes. ===