//==================================================================== // Gid-ADC interface 16/32bitMode 数理設計研究所 1997/5/5 // ComMem2 = PC98のTx=1のときの不具合保証用 1998/7/16 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 //PCAT ComMem = ComMem2 = 0; Pola = BIPOLA; Ch = 0; SglDif = Singl; TrigaPola = 1; TrigaAuto = 0; ClkW = StbW = BlkW = 1; NCnvTime = 1.0; ReSetCliMode(); } //----------------------------------- //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 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 } //----------------------------------- /* 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 } //----------------------------------- //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; } 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 */ TxStat=0; 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 */ 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]; } //---------------------