目次
CAEN社V1718は、VME64xに対応した1幅6U高のVMEマスターで、USB2.0インターフェースを通して
PCから制御出来ます。詳しい説明はここ
をご参照下さい。
V1718にはライブラリ(Windows用、Linux用)、サンプルコード(同じく)が付いてきますが、
これだけで済まないときは、自分でライブラリにアクセスして制御するコードを書く必要があります。本欄では、
Embacardero Delphi XE3 (XE2でも)を使ってV1718を制御する方法を説明します。なお、
最低限必要な機能のみをimplementしただけなので、それ以上の機能が必要な方は、ご自分で御工夫お願い致します。
はじめにPCにCAEN社のライブラリをインストールする必要がありますが、
- 64ビットシステムには64ビット用ライブラリを
- 32ビットシステムには32ビット用ライブラリを
インストールする必要があります。逆はうまくいきません。また、何らかの
理由でうまくインストール出来なかったときは、心を入れ替えてやり直してもダメなことが
あるようです(未だに1台のWindowsXPマシンはインストールできない状態です)。
32ビットOSでは、全て32ビットで統一するしか他にやりようがないと思われますが、
64ビットOSでは、少なくともデバッグは64ビットターゲットでしか出来ません。私の
開発環境は
- Windows 7 Pro 64bit
- Delphi XE3 (XE2) Pro
- TeeChart 2012 VCL
で、自マシンでの動作、及び他のWindows7 Pro 64bitマシンでのexeファイルの動作
は確認していますが、32bit OSマシンでの試験はしていません。32ビットコードが
ちゃんと出来るかも確認出来ていません。
RAD studio XE3側の設定は64ビット版の時のTeeChart設定を除き必要ありません。ライブラリがちゃんと
インストール出来ていれば、souceディレクトリにDLLファイルがなくても大丈夫な
気もしますが、念のため
CAENVMElib.dll
があるようにして下さい。これを使うDelphi側のインターフェースユニットは
です。
CAENのアクセスとは全く関係ありませんが、64bit開発環境で、TeeChart(御本格版)をインストールして使用する場合、
TeeChartのライブラリパスがインストールしたままの設定ではコンパイル時にエラーが出て使用出来ません(XE2でも
XE3でも)。ツール-オプションで、64ビットWindowsを選び、ライブラリパスのなかにある、TeeChart 2012 for RAD
XE3\Delphi17.win64\libを一番上になるように持ってきます。(ついでに、灰色はパスが存在しないことを表して
います。というコメントを信じて不正なパスを削除、なんてするとエライ目にあいます。ご用心を)。

FormCreateなどで、V1718との通信設定を行います。
procedure TVMEF.FormCreate(Sender: TObject);
var i,rtn : integer;
link,un : shortint;
begin
un := 0;
link := 0;
rtn := vme_init(cvV1718,link,un,Handle1);
if rtn <> cvSucess then
showmessage('Device Error');
end;
ここで、Handle1はglobal変数で、
var
Handle1 : longint;
という風に定義してあります。
readの時は、VMEアドレス、戻り値変数、AMコードを与えて、
vme_readcycle(Handle, vme address, 戻り値, AMコード, データ幅)
を呼びます。たとえば、A32特権データアクセスをするときは、
procedure TVMEF.BtnReadClick(Sender: TObject);
var rtn : integer;
rdata : cardinal;
am : byte;
s : string;
begin
address := strtoint('$'+Eaddress.Text);
am := cvA32_S_DATA ;
case
Raddatawidth.ItemIndex of
0 : begin
rtn := vme_readcycle(Handle1,address,rdata,am,cvD8);
if rtn <> cvSucess then begin
s := inttostr(rtn);
showmessage('Error '+s);
end;
end;
1 : begin
rtn := vme_readcycle(Handle1,address,rdata,am,cvD16);
if rtn <> cvSucess then begin
s := inttostr(trn);
shwomessage('Error '+s);
end;
end;
2 : begin
rtn := vme_readcycle(Handle1,address,rdata,am,cvD32);
if rtn <> cvSucess then begin
s := inttostr(rtn);
showmessage('Error '+s);
end;
end;
end;
labdataread.Caption := system.SysUtils.inttohex(rdata,8);
end;
のような使い方になります。writeの時も同様で、
procedure TVMEF.BtnWriteClick(Sender: TObject);
var i, rtn : integer;
s : string;
wdata : cardinal;
am : byte;
begin
address := strtoint('$'+Eaddress.Text);
wdata := strtoint('$'+Edata.Text);
am := byte(cvA32_S_DATA) ;
case
Raddatawidth.ItemIndex of
0 : rtn := vme_writecycle(Handle1,address,wdata,am,cvD8);
1 : rtn := vme_writecycle(Handle1,address,wdata,am,cvD16);
2 : begin
rtn := vme_writecycle(Handle1,address,wdata,am,cvD32);
if rtn <> cvSucess then begin
s := inttostr(rtn);
showmessage('Error '+s);
i := rtn;
end;
end;
end;
end;
みたいにすれば動きます。なお、V1718の単発read/writeは多分USB部分から来る
ものすごいオーバーヘッドがあるようで、大きな(という程でなくても)データを
読み書きすると結構な時間がかかります。可能であれば、以下で説明する
ブロック転送を使った方がずっと早いです。もちろん、ボード側がブロック転送
に対応していなければダメですが。
現在のところ、V1718はBLT(32ビットデータ幅ブロック転送)とMBLT(64ビットデータ幅
ブロック転送)をサポートしています。BLTの場合
function VME_BLTReadCycle(Handle: longint; Address : longword; p: pointer; Size: integer; AM: integer; DW : integer; var count : integer): integer; stdcall;
function VME_BLTWriteCycle(Handle : longint; Address : longword; p: pointer; Size : integer; AM : integer; DW: integer; var count : integer) : integer; stdcall;
を、MBLTの場合
function VME_MBLTReadCycle(Handle : longint; Address : longword; p: pointer; size : integer; AM : integer; var count : integer): integer; stdcall;
function VME_MBLTWriteCycle(Handle: longint; Address : longword; p: pointer; Size : integer; AM : integer; var count : integer):integer; stdcall;
を使うことになります。
BLTでもMBLTでも基本的な使い方は同じです。VME64x規格上、ブロック転送は256回まで
となっていますが、ユーザー側がこれを意識して制御する必要はありません。例えば、
MBLTでデータを書き込む時は
procedure TVMEF.BtnMBLTWriteClick(Sender: TObject);
var rtn : integer;
i : integer;
add,rdata : cardinal;
am : byte;
size,count : integer;
p : pointer;
s : string;
begin
address := strtoint('$'+Eaddress.Text);
for i := 0 to memsize -1 do rd[i] := 0;
size := memsize*8; {データサイズ with byte}
am := cvA32_S_MBLT;
p := @rd[0];
rtn := VME_Mbltwritecycle(handle1,address,p,size,am,count);
if rtn <> cvSucess then begin
s := inttostr(rtn);
showmessage('Error '+s);
end;
end;
の様にしますし、MBLTでデータを読み込むときは
procedure TVMEF.BtnMBLTreadClick(Sender: TObject);
var rtn : integer;
i,j : integer;
add,rdata : cardinal;
am : byte;
size,count : integer;
p : pointer;
s : string;
begin
address := strtoint('$'+Eaddress.Text);
size := memsize*8;
am := cvA32_S_MBLT;
begin
p := @rd[0];
rtn := VME_Mbltreadcycle(handle1,address,p,size,am,count);
if rtn <> cvSucess then begin
s := inttostr(rtn);
showmessage('Error '+s);
end;
for i := 0 to memsize-1 do
begin
ch1[i] := rd[i] and $ffff;
ch3[i] := (rd[i] shr 16) and $ffff;
ch2[i] := (rd[i] shr 32) and $ffff;
ch4[i] := (rd[i] shr 48) and $ffff;
end;
end;
viewdataf.Series1.Clear;
viewdataf.Series2.Clear;
viewdataf.Series3.Clear;
viewdataf.Series4.Clear;
for i := 0 to memsize-1 do
begin
viewdataf.Series1.AddXY(i,ch1[i],'',clTeeColor);
viewdataf.series2.addxy(i,ch3[i],'',clTeeColor);
viewdataf.Series3.AddXY(i,ch2[i],'',clTeeColor);
viewdataf.series4.addxy(i,ch4[i],'',clTeeColor);
end;
viewdataf.Show;
end;
とかいった感じになります。ここでrdとかch1..ch4は
var
rd : array[0..262143] of uint64;
ch1,ch2,ch3,ch4 : array[0..262143] of word;
のように定義してあります。もちろん、書き込んだり、読み込んだりする
データ構造によって、コードの中身はすっかり変わるはずですが。
なお、BLT転送を行っている最中、規格上は必ずしもVMEアドレスを出す
必要は無いと思われますが、V1718は几帳面にアドレスを出しています。
これに対して誤動作するようなボードは(そもそもBLTの規格に合って
いないが)使えません。
V1718はVME割り込みにも対応しています。割り込み機能をenableするには
cmd := irqset;
rtn := VME_IRQEnable(handle1, cmd);
を使います。ここで、irqsetはタダの割り込み番号ではダメで、
procedure TVMEF.RadIRQClick(Sender: TObject);
begin
case radIRQ.ItemIndex of
1: irqset := cvIRQ1;
2: irqset := cvIRQ2;
3: irqset := cvIRQ3;
4: irqset := cvIRQ4;
5: irqset := cvIRQ5;
6: irqset := cvIRQ6;
7: irqset := cvIRQ7;
end;
end;
のように、cvIRQ1からcvIRQ7までのどれかである必要があります。
もちろん、決めうちでもかまいません。
割り込み番号、vectorは例えば以下の様に確認することが出来ます。
procedure TVMEF.BtnIRQCheckClick(Sender: TObject);
var rtn : integer;
mask ,lv: byte;
s : string;
begin
rtn := vme_irqcheck(handle1,mask);
rtn := vme_iackcycle(handle1,mask,lv,cvD8);
labdataread.Caption := 'IRQ'+inttohex(mask,2)+' '+inttohex(lv,2);
end;
具体的な割り込み機能を使ったprocedureとしては、
- 割り込みサイクルをはじめるとき、ボタンを押すとVME_IRQEnableを実行し、
timerをenableするようにする。
- timerの中では、はじめにvme_iackcheckを実行し、割り込み番号が一致
する現象が起きるまでループ
- 割り込み番号が一致したら、vme_iackcycleを行い、割り込みvectorが
一致するか確認。一致しないときは、自分じゃないので待つなり、くたばる
なりする。
- データの読み込みなど、割り込みに対応した動作を行う。ROAKなら、
はじめに該当レジスタにアクセスする必要がある。
- ボードを割り込み可の状態にする
といった感じになります。割り込みサイクルを止めるときは、
- ボタンを押すとvme_irqdisableを実行、
- ボード側も動作を止めるなどして
- timerをdisableする
といった操作になると思います。以下にtimerの例を示します。
procedure TVMEF.Timer1Timer(Sender: TObject);
var i,j : longint;
rtn : integer;
cmd : cardinal;
vector : byte;
size : integer;
s : string;
lv,lv1 : byte;
rdata : cardinal;
p : pointer;
count : integer;
sum1,sum2,sum3,sum4 : double;
begin
base := strtoint('$'+Ebase.Text);
size := memsize*8;
rtn := vme_irqcheck(handle1,lv);
lv1 := strtoint('$'+Evector.Text);
if lv = irqset then
begin
rtn := vme_iackcycle(handle1,cvIRq4,lv,cvD8);
if lv <> lv1 then
begin
labdataread.Caption := 'Invalid vecttor';
end
else
labdataread.Caption := inttohex(lv,2);
rtn := vme_readcycle(handle1,base+AD_STATUS,rdata,cvA32_S_DATA,cvD32);
p := @rd[0];
rtn := VME_Mbltreadcycle(handle1,base,p,size,cvA32_S_MBLT,count);
if rtn <> cvSucess then begin
s := inttostr(rtn);
showmessage('Error '+s);
end;
cmd := 1;
rtn := vme_writecycle(handle1,base+AD_start,cmd,cvA32_S_DATA ,cvD32);
end;
application.ProcessMessages;
end;
V1718をRAD Studio Delphi XE2/XE3で使うインターフェースライブラリについて
紹介しました。V1718は値段もそれほど高くなく(でも安いとは言いたくない)、
WindowsでもLinuxでも動作しますし、それなりにちゃんとしたライブラリと
(いまいちな)動作コードが付いてきますので、いまさらながらVME開発をせざるを
えない方にとっては魅力的なVMEコントローラーと思われます。
KEKBでは、VMEは基本的にVxWorksで動作させますので、V1718をそのまま
加速器制御に直接使うことはありませんし、データ転送スピードなど(瞬間最高
速は別にして平均速度ではめちゃ遅)問題もあります。しかし、開発したボード
をKEK外でデバッグするときなど、あほなマニュアルコントローラなどに比べ
ずっと有効ですし、Delphiでコードを書くことにより、簡単に上等な
制御プログラムを作ることが出来ており、皆様にもお勧めします
(と言って、Delphiにとりつかれた不幸な仲間を一人でも増やす企みかも)。
Makoto Tobiyama
9/May/2013
Return to FB Home Page...