//============================================== #include #pragma hdrstop //============================================== /* Gid-DIO 拡張インターフェース 32bit BCB++ (C)Mathematical Assist Design Lab. (C)数理設計研究所 Hal.T 2000/4/5 マルチスレッドでデータ転送し、指定以外の入力パターンで即座に停止する イベントは同じ名の物をあっちこっちで開いて使う "GidDioTx" */ //============================================== #include "GidDIOE.h" //============================================== static bool TFlag; //TFlag=false 送信停止させる falseなら停止している //============================================== GidDIOE::GidDIOE(int Port, enum RSSPEED speed, enum DIOMODE mode, int DefaultData) : GidDIO(Port, speed, mode, DefaultData) { gtx = new GidDioTx(true, this); gtx->Priority = tpTimeCritical; gtx->Resume(); grx = new GidDioRx(true, this); grx->Resume(); TxEvent = new TEvent(0, true, false, "GidDioTx"); tbuf = 0; //送信ストリームバッファ } //============================================== //ボチボチべた送り void GidDIOE::PutDataAll(UC *d, int n) { int f; for(int m=n; m>0; ) { if((f=GidDIO::PutData(d, m))>=0) { m-=f; d+=f; } } } //============================================== /*Multi Theread Type 送信データをすべて自分のバッファに引き取ってから送信するので この関数を呼び出す側では即座に再利用できる 受信データがrdと違うと送信を停止する */ UC GidDIOE::PutDataForRxMask(UC *d, int n, UC rd, UC mask) { UC dm; //前の送信が終わっていないとポーリングループする while(TxEvent->WaitFor(100) == wrSignaled);// Sleep(100); rs->PurgeComm(); //あらかじめ送受信バッファをクリア //ダミーデータを送って検査する、最初から状態が違えば何も送らない if(((dm=PutGetWaitData()) & mask) != (rd & mask)) return dm; //この時点では送信が終わっているはずなのでコピーする tbuf = new UC [n]; memcpy(tbuf, d, n); gtx->txbuf = tbuf; gtx->txbufsize = n; //送信データの設定 grx->rd = rd; //受信停止比較データの設定 grx->rm = mask; //マスクの設定 TxEvent->SetEvent(); //送信+受信の開始 return 0; } //============================================== //送信中の強制停止状態を返す true=強制停止  // 送信開始できなければfalseのまま bool GidDIOE::GetAbortStat(void) { return grx->AbortStat; } //============================================== //送信中ならtrueを返事する bool GidDIOE::PutDataStat(void) { return gtx->GetTFlag(); } //============================================== //強制停止 void GidDIOE::Abort(void) { grx->Abort(); } //============================================== //============================================== __fastcall GidDioTx::GidDioTx(bool CreateSuspended, GidDIOE *p) : TThread(CreateSuspended) { TxEvent = new TEvent(0, true, false, "GidDioTx"); giddio = p; txbuf = 0; txbufsize = 0; atxbuf= 0; atxbufsize = 0; } //============================================== void __fastcall GidDioTx::Execute() { for(;;) { if(Terminated) { delete TxEvent; return; } //終了指示があった if(TxEvent->WaitFor(100) != wrSignaled) continue; //シグナルではない int m, f; UC *buf; for(TFlag = true, m=txbufsize, buf = txbuf; m>0 && TFlag; ) { if((f=giddio->PutData(buf, m))>=0) { m-=f; buf+=f; } } if(m==0) { //今のデータは終了したので追加データを調べる delete [] txbuf; txbuf = 0; //クリアしておく if(atxbufsize>0) { txbuf = new UC [atxbufsize]; memcpy(txbuf, atxbuf, txbufsize = atxbufsize); delete [] atxbuf; atxbufsize = 0; continue; } TxEvent->ResetEvent(); TFlag=false; //送信停止にしておく } } } //============================================== bool GidDioTx::GetTFlag(void) { return TFlag; } //============================================== __fastcall GidDioRx::GidDioRx(bool CreateSuspended, GidDIOE *p) : TThread(CreateSuspended) { TxEvent = new TEvent(0, true, false, "GidDioTx"); giddio = p; AbortStat = false; } //============================================== //強制停止 void __fastcall GidDioRx::Abort(void) { TxEvent->ResetEvent(); TFlag=false; giddio->rs->PurgeComm(); //送受信の強制的なクリア giddio->PutGetWaitData(); //デフォルトデータを設定しておく AbortStat = true; //強制停止した } //============================================== //受信データを待ち停止条件になっていれば送信を強引に停止させる //送信停止はQバッファのクリア、送信イベントのOFF void __fastcall GidDioRx::Execute() { #define RXB 1024 int d; for(;;) { if(Terminated) { delete TxEvent; return; } //終了指示があった if(TxEvent->WaitFor(100) != wrSignaled) continue; //シグナルではない AbortStat = false; //受信監視に入る while((d=giddio->GetData())>0) { if((d & rm) != (rd & rm)) { //送信停止 Abort(); break; } } } } //============================================== #pragma package(smart_init)