Just to continue this story, I now have a working executable. However I do still have a problem that I would like to resolve. The software is using a serial port. The serial port is provided by a Dynamode USB to serial adapter (which uses the Prolific chipset). The latest drivers from the Prolific web site are installed. My software works correctly providing that the adapter has just been plugged in. Attempting to use the software a second time fails; it looks to me as though some setting perhaps baud rate isn't correct on subsequent attempts (some times the first byte from the other end is missed or is incorrect). An extract of my code for opening and setting up the serial port is:
type Tterm_arg=packed record c_iflag:integer; c_oflag:integer; c_cflag:word; c_lflag:integer; c_cc :packed array [0..19] of char; c_ispeed:integer; c_ospeed:integer; end; var fildes_block,fildes_out:integer; block_status, write_status:integer; term_arg_block,SaveTermArg:Tterm_arg;
function open(protected Path: Cstring; Oflag: word; Mode: word): integer; External; function tcsetattr(fd:integer;actions:integer;pt:pointer):integer;External; function tcgetattr(fd:integer;pt:pointer):integer;External; procedure cfmakeraw(pt:pointer);External; function cfsetspeed(pt:pointer;speed:integer):integer;External; function cfgetispeed(pt:pointer):integer;External; function cfgetospeed(pt:pointer):integer;External; function sys_write(Fildes: integer; Buf: pointer; NByte: integer): integer; asmname 'write'; function sys_read(Fildes: integer; Buf: pointer; NByte: integer): integer; asmname 'read'; function sys_close(Fildes: integer): integer; asmname 'close';
function OpenCOMPort: boolean; CONST O_RDONLY = 8#0; O_WRONLY = 8#1; O_RDWR = 8#2; O_NONBLOCK= 8#4;
var Result : boolean; Mode:Word; begin Result:=True; SerialDevicename:='usbserial'; block_status:=integer(O_RDWR or O_NONBLOCK); mode:=0; fildes_block:=open(String2Cstring('/dev/tty.'+SerialDeviceName),word(blo ck_status),mode); if fildes_block<=0 then begin Result:=False; end; OpenCOMPort := Result; end;
function SetupCOMPort: boolean; const CS8 =16#0300; CLOCAL =16#8000; CREAD =16#0800; VMIN=16; VTIME=17;
var loop,InputSpeed,OutputSpeed:integer; dummy:word; Result : boolean;
begin (*SetupComPort*) retval:=tcgetattr(fildes_block,Addr(SaveTermArg)); If Retval<0 then Begin Writeln('Error retrieving existing serial port settings.'); Halt; End; Term_arg_block:=SaveTermArg; With term_arg_block Do Begin c_iflag:=0; c_oflag:=0; c_cflag:=(CREAD or CLOCAL or CS8); c_lflag:=0; for loop:=0 to 19 do c_cc[loop]:=chr(0); End; Result := True; cfmakeraw(Addr(term_arg_block)); Retval:=cfsetspeed(Addr(Term_arg_block),115200); If Retval=-1 then Begin Writeln('Error when setting speed.'); Halt; End; retval:=tcsetattr(fildes_block,TCSANOW,Addr(term_arg_block)); if retval=-1 then begin ErrorString:=CStringStrError(ErrorNumber); writeln(' When setting blocking, tcsetattr returned ',retval:1, ' errno ',ErrorNumber:1); writeln(' ',CString2String(ErrorString)); Result:=False; end; SetupCOMPort := Result; end;
Procedure WriteBuffer(Buffer : TBuffer; Size : longint); var Count: LongWord; begin retval:=sys_write(fildes_block,addr(Buffer),Size); if retval<0 then Begin ErrorString:=CStringStrError(ErrorNumber); writeln('Error from sys_write in writebuffer, retval = ', retval:1,' error = ',ErrorNumber); writeln(' ',CString2String(ErrorString)); End; end;
Procedure WriteByte(b : byte); var Count: LongWord; Begin retval:=sys_write(fildes_block,addr(b),1); if retval<0 then Begin ErrorString:=CStringStrError(ErrorNumber); writeln('Error from sys_write in writebyte, retval = ', retval:1,' error = ',ErrorNumber); writeln(' ',CString2String(ErrorString)); Halt; End; End;
Function ReadByte(var b : byte) : boolean; Var LoopCount,Retval:Integer; begin b:=0; LoopCount:=0; Retval:=0; Repeat retval:=sys_read(fildes_block,addr(b),1); If Retval<=0 then Begin Inc(LoopCount); SleepMicroSeconds(50); End; Until (Retval>0) or (Loopcount>20000); ReadByte:=(RetVal>0); End;
Procedure CloseCOMPort; Var Retval:Integer; Begin retval:=tcsetattr(fildes_block,TCSANOW,Addr(SaveTermArg)); Retval:=Sys_close(Fildes_block); End;
Any thoughts about why this only works once? Any other comments or suggestions on the code snippet?