KPURCELL@LIVERPOOL.AC.UK (09/21/90)
Below is the text of a program that we wrote to find out why a piece of code written by a consultant wouldn't correctly control the serial port. We have since written some code to do the same stuff (that works :-) using the serial manager. Firstly, the open(Q1, 'modem:'); THINK Pascal considers the printer port as write-only and the modem port as read-write (this is mentioned in the Language Reference 9.5 on page 321-322). But when you open the modem: port for I/O, the I/O actually happens on the PRINTER port for I/O. Opening the printer: won't allow reading that port (hey, the printer is a write-only device, right) but the written output comes out of the physical MODEM port. The upshot of this is: 1. We can't use Appletalk, if we want to do serial I/O. 2. We are very confused why the ports in the program don't correspond to the right miniDINs on the mac. A secondary problem is that when you send a CR (CHAR(ORD(13))) out of the port the device actually sends a CR/LF pair. On reading a CR/LF the port returns a space for the CR character and a ORD(13) for the LF. Final problem. We tried a loopback (output of a port goes to input of a port) and write and read almost simultaneously then it seems to drop characters, whereas a routine using the Serial Drivers and FSRead/FSWrite has no problems. So the final question is: is this a known bug or, perhaps more likely, are we doing something really stupid? Take a look at the code below. I have RTFM but couldn't find anything relevant. Does it have anything to do with mixing Pascal TEXT I/O and the Serial Driver routines? (sinking feeling :-) This started as a quick "oh we'll do it this way to save some time" hack, but we've ended up doing it properly (with the drivers and the File Manager) in the end after wasting a couple of days chasing the problem. Thanks for any assistance, Kevin Kevin Purcell | kpurcell@liverpool.ac.uk Surface Science, | Liverpool University | Programming the Macintosh is easy if you understand Liverpool L69 3BX | how the Mac works and hard if you don't. -- Dan Allen ------------------------ program follows ------------------------------ {Lest it destroy my credibility I *didn't* write this! -kgp} program bull; var Event, h, i: integer; q1: text; p: char; l: longint; SerAshk: SerShk; SerASta: SerStaRec; evnt: eventrecord; Done: boolean; GrowLimit, DragLimit: rect; FirstClick: longint; window, txw, drw: WindowPtr; pnt: point; stn: str255; procedure HandleKey; var ch: char; j: integer; begin Evnt.Message := BitAnd(Evnt.Message, $FF); ch := Chr(Evnt.Message); setport(drw); GetPen(pnt); write(q1, ch); writedraw(ch); end; procedure HandleMouse; var part: integer; newSize: longint; begin part := FindWindow(Evnt.Where, window); if window = nil then exit(handleMouse); if window <> FrontWindow then SelectWindow(window); case part of InGrow: begin newSize := GrowWindow(Window, Evnt.Where, GrowLimit); if newSize <> 0 then SizeWindow(Window, LoWord(newsize), HiWord(newsize), TRUE); end; indrag: if TickCount > (FirstClick + GetDblTime) then begin FirstClick := TickCount; DragWindow(window, Evnt.where, DragLimit); end; ingoaway: done := true; otherwise end end; begin Done := false; SetRect(GrowLimit, 80, 80, 512, 322); SetRect(DragLimit, 50, 20, 512, 250); FirstClick := 0; showdrawing; getport(drw); showtext; getport(txw); moveto(0, 12); open(Q1, 'modem:'); for i := -20 to 0 do if SerGetBuf(i, l) = 0 then leave; if i >= 0 then Writeln('find failed'); if SerReset(i, $4c0a) <> 0 then writeln('speed failed'); with SerAshk do begin fxon := 0; finx := 0; errs := $70; fcts := 1; end; writeln(SerHshake(i, SerAshk)); writeln(SerStatus(i, SerASta)); writeln(SerASta.ctshold); writeln('ref:=', i : 4, ' ', l : 4, ' bytes in buffer'); WRITE(Q1, 'CD/0/', CHR(13), 'X'); WRITE(Q1, 'AB/', CHR(13), 'X'); repeat systemtask; if GetNextEvent(EveryEvent, Evnt) then case Evnt.What of KeyDown, AutoKey: HandleKey; MouseDown: HandleMouse; otherwise end; if SerGetBuf(i, l) = 0 then if l > 0 then begin read(q1, p); setport(txw); selectwindow(txw); GetPen(pnt); if ORD(P) = 10 then WRITELN else WRITE(P); end; until done; close(q1); end.