//==================================================================== /* Gid-ADC interface 16/32bitMode 数理設計研究所 1997/5/5 ComMem2 = PC98のTx=1のときの不具合保証用 1998/7/16 Hal.T SetTx(0); //BUG 2002/01/18; WinNT で動くように改造 矢澤 2003/03 void GidADC::Init(void)の //#ifdefをコメントアウト 2004/02/17 Hal.T */ //==================================================================== /*ADC 実測性能 P5-150 256S/sec 30msec, 117usec 8.5 kS/sec 25msec, 100usec 10 kS/sec */ //----------------------------------- #include #include #include #include #include #include #include #pragma hdrstp #include "gidadc.h" //=========================================================== //=========================================================== #ifndef __WIN32__ extern "C" { //---------------------------------- void cli(void) { asm cli; } //---------------------------------- void sti(void) { asm sti; } //---------------------------------- } #endif // not __WIN32__ //----------------------------------- void GidADC::Init(void){ #ifdef PCAT Comport = COM1_BASE; #endif //#ifdef PC98 よけいなおせわ、いつでもやるべき 2004/02/17 Hal.T ComMem = ComMem2 = 0; Pola = BIPOLA; Ch = 0; SglDif = Singl; TrigaPola = 1; TrigaAuto = 0; ClkW = StbW = BlkW = 1; NCnvTime = 1.0; ReSetCliMode(); //#endif } //----------------------------------- //150MHz P5 WIN95 Tested = 500 1クロック待ちループカウンタ void GidADC::ClkWait(void) { for(long n = ClkW; n>0; n--); } //----------------------------------- //ストローブ待ちループカウンタ void GidADC::StbWait(void) { for(long n = StbW; n>0; n--); } //----------------------------------- //データ間待ちループカウンタ void GidADC::BlkWait(void) { for(long n = BlkW; n>0; n--); } //----------------------------------- //return 1 or 0 int GidADC::SCLKD(void) { int rd; #ifdef PCAT //sclk 1 ClkWait(); outportb(Comport + SIO_MDM, SIO_MDM_RTS); //data in ClkWait(); rd = (inportb(Comport + SIO_MSR) & SIO_MDMS_RLSD)? 1 : 0; //sclk 0 ClkWait(); outportb(Comport + SIO_MDM, SIO_MDM_RTS | SIO_MDM_DTR); #endif #ifdef PC98 //sclk 1 ClkWait(); outportb(SIOC, ComMem2 | SIO_RTS); //data in ClkWait(); rd = (~(inportb(PPI1B)) & CD_MASK)? 1 : 0; //sclk 0 ClkWait(); outportb(SIOC, ComMem2 | SIO_RTS | SIO_DTR); #endif #ifdef WINNT //sclk 1 ClkWait(); ComADC->SetDTR(0); //data in ClkWait(); rd = (ComADC->GetDCD())? 1 : 0; //sclk 0 ClkWait(); ComADC->SetDTR(1); #endif return rd; } //----------------------------------- //DTR = ~SCLK, RTS = ~DIN void GidADC::SCLK(int Data) { #ifdef PCAT int d = (Data)? 0 : SIO_MDM_RTS; //data out ClkWait(); outportb(Comport + SIO_MDM, d | SIO_MDM_DTR); //sclk 1 ClkWait(); outportb(Comport + SIO_MDM, d); //sclk 0 ClkWait(); outportb(Comport + SIO_MDM, SIO_MDM_RTS | SIO_MDM_DTR); #endif #ifdef PC98 //data out ClkWait(); outportb(SIOC, ComMem2 | ((Data)? 0 : SIO_RTS) | SIO_DTR); //sclk 1 ClkWait(); outportb(SIOC, ComMem2 | ((Data)? 0 : SIO_RTS)); //sclk 0 ClkWait(); outportb(SIOC, ComMem2 | SIO_RTS | SIO_DTR); #endif #ifdef WINNT //data out ClkWait(); ComADC->SetRTS((Data)? 0:1); //sclk 1 ClkWait(); ComADC->SetDTR(0); //sclk 0 ClkWait(); ComADC->SetDTR(1); #endif } //----------------------------------- /* ADCにコマンド出力後の最終状態を設定する */ void GidADC::SetTxE(void) { #ifdef PCAT if(TxStat) { outportb(Comport + SIO_MDM, SIO_MDM_DTR); /*RTS=0*/ } else { outportb(Comport+SIO_MDM, SIO_MDM_RTS | SIO_MDM_DTR); /*RTS=1*/ } #endif /* PCAT */ #ifdef PC98 outportb(SIOC, ComMem); #endif #ifdef WINNT if(TxStat) {ComADC->SetRTS(0); /*RTS=0*/ } else { ComADC->SetRTS(1); /*RTS=1*/ } #endif /* WINNT */ } //----------------------------------- //1サンプルデータ取得 int GidADC::GetCnv(void) { int m, rd; m = 0x80 | Ch | Pola | SglDif | 0x01; //高速パワーダウン // m = 0x80 | Ch | Pola | SglDif | 0x10; //内部クロック rd = DOut(m); if(Pola == BIPOLA) { if(rd > 2047) rd = rd - 4096; } return rd; } //----------------------------------- //規定数のデータ取得 int GidADC::GetNCnv(int n, int *buf) { if(CliMode) cli(); for(; n>0; n--) *buf++ = GetCnv(); if(CliMode) sti(); return 0; } //----------------------------------- //規定数のデータ取得マルチチャンネル版 //n個のデータを取り込む buf[x]がNULL=0ポインタなら取り込まない int GidADC::GetMCnv(int n, int *buf[8]) { int ch; if(CliMode) cli(); for(; n>0; n--) { for(ch=0; ch<8; ch++) { SetCh(ch); if(buf[n]) *buf[ch]++ = GetCnv(); } } if(CliMode) sti(); return 0; } //----------------------------------- //規定数のデータ取得、トリガつき 規定回数待ってだめならエラーで戻る int GidADC::GetNTCnv(int v, int n, int wn, int *buf) { int w; if(TrigaAuto==TAuto && wn) w = n*2; else w = 10000; if(TrigaPola > 0 && TrigaAuto != TNone) { for(; GetCnv() > v && w > 0; w--); for(; GetCnv() < v && w > 0; w--); } else if(TrigaPola<0 && TrigaAuto != TNone) { for(; GetCnv() < v && w > 0; w--); for(; GetCnv() > v && w > 0; w--); } if(w<=0 && TrigaAuto == TNormal) return 1; GetNCnv(n, buf); return 0; } //----------------------------------- //GetNTCnv,GetNTCnv の1データあたりの時間を秒単位で調べる double GidADC::GetNCnvTime(void) { clock_t t0, t1; double d0, d1, ds; int n, fl; int climemo = CliMode; SetCliMode(0); #define TIME_TEST_BUF 4*4096 int *buf = new int [TIME_TEST_BUF]; t0 = clock(); GetNCnv(1, buf); t1 = clock(); d0 = (t1-t0)/CLK_TCK; for(fl=0, n = 2; n 0.95 && ds < 1.05) fl++; } delete buf; SetCliMode(climemo); return NCnvTime = d1; } //----------------------------------- //1から始まるCOMボート番号 #pragma argsused void GidADC::SetComport(int c) { #ifdef PCAT switch(c) { case 1: Comport = COM1_BASE; break; case 2: Comport = COM2_BASE; break; case 3: Comport = COM3_BASE; break; case 4: Comport = COM4_BASE; break; default : Comport = COM2_BASE; break; } #endif /* PCAT */ } //----------------------------------- //コマンドを出してデータを読み出す int GidADC::DOut(int Command) { int n, rd; //コマンド出力 for(n=8; n>0; n--) { SCLK(Command & 0x80); Command <<= 1; } #ifdef WINNT ComADC->SetRTS(1); #endif //WINNT StbWait(); //Get DATA for(rd = 0, n=13; n>0; n--) rd = (rd << 1) | SCLKD(); //Txの状態に応じて最終状態をきめる(負電源の維持のため) SetTxE(); BlkWait(); return rd & 0xFFF; } //--------------------- //1から始まるCOMボート番号 #pragma argsused void GidADC::InitPower(int ComNum) { #ifdef PC98 unsigned int tn; outportb(SIOC, 0); for(tn=0xffff; tn>0; tn--); outportb(SIOC, 0); for(tn=0xffff; tn>0; tn--); outportb(SIOC, SIO_RES); for(tn=0xffff; tn>0; tn--); outportb(SIOC, SIO_8N); for(tn=0xffff; tn>0; tn--); outportb(SIOC, ComMem = SIO_RTS | SIO_DTR); #endif /* PC98 */ #ifdef PCAT SetComport(ComNum); outportb(Comport + SIO_MDM, 0); outportb(Comport + SIO_MDM, SIO_MDM_RTS | SIO_MDM_DTR); #endif /* PCAT */ #ifdef WINNT ComADC = new RS232C(ComNum); if(ComADC->Check() != ComADC->READY){ AdcStatus = NG; return;} AdcStatus = READY; ComADC->dcb.fOutxCtsFlow = false; /* CTS出力フロー制御 */ ComADC->dcb.fOutxDsrFlow = false; /* DSR出力フロー制御 */ ComADC->dcb.fDtrControl = DTR_CONTROL_DISABLE ; /* DTR出力フロー制御 */ ComADC->dcb.fDsrSensitivity = true ; /* DSR信号の状態を認識するかどうか指定 */ ComADC->dcb.fRtsControl = RTS_CONTROL_DISABLE ; /* RTS出力フロー制御 */ ComADC->SetDCB(); ClkW = 100000; //暫定的な値 BlkW = 100000; StbW = 100000; #endif /* WINNT */ SetTx(0); //BUG 2002/01/18; for(int t = 1000; t>0; t--); //電源の立ち上がりを待つ DOut(0x86); //内部クロックモードの指定 // DOut(0x85); //高速パワーダウンモードの指定 }; //----------------------------------- //DINをマイナスに設定するので、変換途中にBIOS内部からは使えない //i=0 ノーマル状態 i!=0 Tx=HiLEVEL void GidADC::SetTx(int i) { #ifdef PCAT if(i) { outportb(Comport + SIO_LCR, SIO_BRK); //ブレーク信号の設定 outportb(Comport + SIO_MDM, SIO_MDM_DTR); //RTS=0 } else { outportb(Comport + SIO_LCR, 0); outportb(Comport + SIO_MDM, SIO_MDM_RTS | SIO_MDM_DTR); //RTS=1 } #endif /* PCAT */ #ifdef PC98 if(i) { ComMem = SIO_BRK | SIO_DTR; //ブレーク信号の設定 ComMem2 = SIO_BRK; } else { ComMem = SIO_DTR | SIO_RTS; //ブレーク信号の解除 ComMem2 = 0; } outportb(SIOC, ComMem); #endif /* PC98 */ #ifdef WINNT if(i) { ComADC->SetBreak(1); //ブレーク信号の設定 ComADC->SetRTS(0); //RTS=0 } else { ComADC->SetBreak(0); //ブレーク信号の解除 ComADC->SetRTS(1); //RTS=1 } #endif /* WINNNT */ TxStat = i; } //----------------------------------- //tループ時間(PC依拠)だけTx信号を1にする void GidADC::SetTxPulse(long t) { SetTx(1); for(; t>0; t--); SetTx(0); } //----------------------------------- //現在設定されているアナログチャンネルを読み出しながらdataを超えるまでTxを //1にする。設定値を超えたら0に戻して帰ってくる。最初にデータ取得して試験する //のでパルスを出さない場合もある。 void GidADC::SetTxPulseWait(int d) { if(d >= GetCnv()) { SetTx(1); while(d >= GetCnv()); SetTx(0); } } //--------------------- //0〜7のチャンネル番号で以後の操作を指定する void GidADC::SetCh(int ch) { static int chn[8] = { 0x00, 0x40, 0x10, 0x50, 0x20, 0x60, 0x30, 0x70 }; Ch = chn[ch & 0x07]; } //--------------------- #ifdef __WIN32__ bool GidADC::GetDSR(void) { #ifdef PCAT return (inportb(Comport + SIO_MSR) & SIO_MDMS_DSR)? 1 : 0; #endif #ifdef PC98 return (inportb(SIOC)) & DSR_MASK)? 0 : 1; #endif #ifdef WINNT return ComADC->GetDSR(); #endif } //--------------------- bool GidADC::GetCTS(void) { #ifdef PCAT return (inportb(Comport + SIO_MSR) & SIO_MDMS_CTS)? 1 : 0; #endif #ifdef PC98 return (inportb(PPI1B)) & CTS_MASK)? 1 : 0; #endif #ifdef WINNT return ComADC->GetCTS(); #endif } #endif __WIN32__ //--------------------------------------------------------------------------- #ifdef __WIN32__ #ifndef vcladcH //vcladc.hで定義している //COMポート、ClkWaitの設定がされる //ファイルや項目が存在しないときは作成する //ComPort=2, ClkWait=1000が既定値 void GidADC::InitFromProfile(char *FileName, char *Section) { int ComN, ClkW; int ComN1, ClkW1; Profile pro(FileName); ComN = pro.GetInt("GidADC", "ComPort", -1); //基本イニシャル if(ComN<=0) pro.SetInt("GidADC", "ComPort", ComN=2); ClkW = pro.GetInt("GidADC", "ClkWait", -1); if(ClkW<=0) pro.SetInt("GidADC", "ClkWait", ClkW=1000); //Sectionごとの再定義 ComN1 = pro.GetInt(Section, "ComPort", -1); if(ComN1<=0) pro.SetInt(Section, "ComPort", ComN1=ComN); ClkW1 = pro.GetInt(Section, "ClkWait", -1); if(ClkW1<=0) pro.SetInt(Section, "ClkWait", ClkW1=ClkW); InitPower(ComN1); SetClkWait(ClkW1); } #endif //__WIN32__ #endif //vcladcH //---------------------------------------------------------------------------