Jumat, 02 November 2012

Serial Com Access

Sejak kemarin coba mencari cara untuk mengakses port serial com dari PHP. Berhasil sih, tetapi untuk membaca data dari port masih tidak sinkron, karena timingnya tidak sesuai dengan sinyal RtS dari hardware. hardware yang sedang coba di akses adalah Magnetic Card Reader/Writer. Lalu kecurigaan muncul, dan beberapa cara pemecahan dijalani, salah satunya dicoba dengan native apps.

Lalu dibuatlah program percobaan sederhana menggunakan FPC 2.6.0 dan beberapa function dari Windows API. Awalnya sama saja dengan ketika melakukan percobaan di PHP, yaitu timing untuk membaca tak bisa sinkron dengan RtS dari device. Diselidiki... dicari... dan terus mencari hingga seharian. Ternyata masalahnya harus menggunakan teknik overlapped reading/writing. Tetapi masih saja belum saja berhasil, selidiki lagi..., selidiki lagi..., selidiki terus...., dan ketemu juga. Overlapped harus menggunakan timeout, kalau tidak maka percuma saja karena ketika reading dari port tidak akan menunggu input masuk.

Hehehe... setelah setting overlapped dan timeout, JRENG.... berhasil deh. Data masuk dan bisa diolah. Di bawah ini adalah sourcenya, atau bisa download di: http://sites.google.com/site/karuniaprojects/documents/magread.pas

Berikutnya coba porting ke PHP, pastinya menggunakan library Windows dan command linux stty. Hmm... tantangan.


uses crt,windows;

const
 bfsize=4096;

var
 comhnd:handle;
 evtwr:toverlapped;
 evtrd:toverlapped;
 tmo:_commtimeouts;
 dcb:_dcb;

procedure comwrite(st:string);
var
 ln:dword;
 written:dword;
begin
 setcommmask(comhnd,ev_rxchar);
 ln:=length(st);
 written:=0;
 writefile(comhnd,st[1],ln,written,@evtwr);
 repeat until getoverlappedresult(comhnd,evtwr,written,true);
end;

function comread:string;
type
 tbuffer=array[0..bfsize-1] of char;
var
 buffer:^tbuffer;
 readed:dword;
 st:string;
begin
 purgecomm(comhnd,purge_rxclear);
 setcommmask(comhnd,ev_rxchar);
 getmem(buffer,bfsize);
 write('data buffer: ');
 writeln(sizeof(buffer^));
 readfile(comhnd,buffer^,bfsize,readed,@evtrd);
 repeat until getoverlappedresult(comhnd,evtrd,readed,true);
 write('data readed: ');
 writeln(readed);
 readln;
 setlength(st,readed);
 move(buffer^,st[1],readed);
 freemem(buffer);
 comread:=st;
end;

procedure init();
begin
 clrscr;
 evtwr.offset:=0;
 evtwr.offsetHigh:=0;
 evtwr.hevent:=createevent(nil,true,false,nil);
 if(evtwr.hevent=0) then begin
  writeln('failed create write event');
  halt;
 end;
 evtrd.offset:=0;
 evtrd.offsetHigh:=0;
 evtrd.hevent:=createevent(nil,true,false,nil);
 if(evtwr.hevent=0) then begin
  writeln('failed create read event');
  closehandle(evtwr.hevent);
  halt;
 end;
 comhnd:=createfile(
  pchar('\\.\COM2'),
  generic_read or generic_write,0,nil,open_
  existing,file_attribute_normal or file_flag_overlapped,0
 );
 setcommmask(comhnd,ev_rxchar);
 setupcomm(comhnd,bfsize,bfsize);
 purgecomm(comhnd,
  purge_txabort or purge_rxabort or purge_txclear or purge_rxclear
 );
 // timeout
 tmo.readintervaltimeout:=300;
 tmo.readtotaltimeoutmultiplier:=1000;
 tmo.readtotaltimeoutconstant:=300;
 tmo.writetotaltimeoutmultiplier:=2;
 tmo.writetotaltimeoutconstant:=0;
 setcommtimeouts(comhnd,@tmo);
 // comm state
 dcb.dcblength:=sizeof(dcb);
 getcommstate(comhnd,@dcb);
 dcb.baudrate:=9600;
 dcb.bytesize:=8;
 dcb.parity:=noparity;
 dcb.stopbits:=1;
 setcommstate(comhnd,@dcb);
 // okeh
 escapecommfunction(comhnd,setdtr);
end;

procedure done();
begin
 comwrite(#27#48);
 setcommmask(comhnd,0);
 escapecommfunction(comhnd,clrdtr);
 purgecomm(comhnd,purge_txabort or purge_rxabort or purge_txclear or purge_rxclear);
 closehandle(comhnd);
 closehandle(evtwr.hevent);
 closehandle(evtrd.hevent);
 exitcode:=0;
end;

procedure run();
begin
 //comwrite(#27#48);
 comwrite(#27#66#84#27#106);
 writeln('read track command sended, hit return!');
 readln;
 writeln('waiting input...');
 writeln(comread);
 readln;
 //comwrite(#27#66#84#27#106);
 //readln;
end;

begin
 init;
 run;
 done;
end.

Tidak ada komentar:

Posting Komentar