目次
バンチ振動モニターメモリー(BOR-memory)は509MHzで動作する8ビットのメモリーボードです。メモリー自体は20Mb(5120バンチ×4096周)もっています。
- システムブロック図

- 通常はSYNC状態で、ビーム周回と同期した信号(revolutionをTD-4Vで適当にdelayした信号)で同期してビーム位置データをとり続けています。メモリー長をリングhermonic numberの整数倍にしてありますので、あるメモリーアドレスには常に同じbunch IDのデータが入ります。
- ストップ信号が入ると、メモリーボードはメモリーへの記録をその時点で停止し、停止アドレスを記録します。このとき、上位アドレスと下位アドレスの2種類のアドレスがあるので注意。ボード設定によってはこのときVMEにより割り込みをかけることも出来るが(BCMでは割り込みを使っている)、ここで紹介するデバイスサポートでは割り込みを使わない(割り込みを使うversionも存在し、動作している)。メモリー記録は停止するが、ADC及びFDMUXは動作を続けています。
- データ量自体が20MBありEPICSの世界を桁違いに逸脱しているので、データの記録は直接デバイスサポートからディスクに行います。KEKBではTFTPが通常なので、データを転送するスピードも速いとは言えず、ディスク上のデータの管理もIOC側からは一切できません。ディスクに書く、書かない及び書くときのファイル名はこのデバイスサポート内で管理しています。ディスクに書かないときも、20MBのデータをメモリーボードからVMEメモリーへの転送すること自体はおこなっており、先頭5120バンチのデータはEPICS waveformレコードになっています。
- すべての処理が終わっても自動復帰はせず、EPICSレコードを通してSYNC命令が来るまでそのまま待機しています。SYNC命令がくると、revolution信号でメモリーアドレスを同期をとり、データをとり続ける状態になります。
- メモリーボードへのアクセス法(PDF 21kB)
- メモリーボード内部の写真
- VMEファンクション
- アドレスはA32およびA24をサポートしますが、本デバイスサポートはA32(拡張)用です。
- AMコードは0x0D(拡張特権)と0x3D(標準特権)をサポートしますが、本デバイスサポートは0x0D用です。
- 本システム1台で4,194,304バイト空間を占有します。つまり、0x00400000ごとのアドレス設定となります。このうち下位0x00200000をデータメモリ用に、上位0x00200000をコントロール用に(とはいってもほんの4ロングワードのみ)使用します。基本的にFIRフィルターボードと同じ構造ですがアクセス方法は全く異なります。
メモリーボードのアドレスマップは以下の通りです。
- 0x**000000
データメモリ(R/W)。本システムには20Mbのメモリーが乗っていますが、VME上にアドレスマップされているのは2MBのみで(半分は同じデータ)、残りはメモリーバンクを切り換えて読みます。
- 0x**200000
コントロールレジスタ1。メモリーのstart/stop(ビット0)、カウンタークリア(ビット2)、動作(ビット3)等の機能があります。何種類かのビットパターンの組み合わせで動作します。
- 0x**200004
コントロールレジスタ2。データ転送方式の指定及び読み出しバンクの指定をします。
- 0x**200008
ストップビット1。意味はコードの部分で説明します。
- 0x**20000A
ストップビット2。
本デバイスサポートは、EPICS R313改訂版で開発したものです。EPICSそのものに対する説明、入門出家入道遁世については専門家に帰依するなり、コントロールグループのページをご参照なさるなり勝手になさってください。動作はPPC750のみで確認しています。
コードは以下の通りです。
変数定義
ファイル名、ファイルハンドル、File記録ON/OFF用の変数を定義します。
static char file_name[5][255];
FILE *FHAND;
static int fileflag[5];
configuration file
過去割り込みモードで動かしていた痕跡があり、interrupt level及びinterrput vectorを指定するようになっていますが、適当な数字を入れれば結構です。
int devVmemem2Config(ncards,a32base,intlevel,intvecbase)
初期化部
初期時には動作停止状態にしておきます。
logMsg("Found vmemem2 with cardNum= %d\n address= %x\n",cardNum,p);
cards[cardNum].card = p; /* Remember address of the board */
cards[cardNum].card->cntl1 = 0x01;
String out(SO)レコード
データ記録用ファイル名をデバイスサポートが覚えるために使います。ボードには何のアクセスもしません。
static long write_stringout(pstringout)
struct stringoutRecord *pstringout;
{
long status = 0;
short cardN;
cardN = pstringout->out.value.vmeio.card;
if (checkLink(cardN) == ERROR)
{
logMsg("Error--- No vmemem2 for card %d\n",cardN);
return(ERROR);
}
strcpy(file_name[cardN],FPATH);
strcat(file_name[cardN],pstringout->val);
return(status);
}
BOの動作
waveform読みとり
はじめに(念のため)ボードを読みとり状態に再設定し、ストップアドレス1、2をよみとります。
cards[cardN].card->cntl1 = 0x09;
s1=cards[cardN].card->stop1;
s2=cards[cardN].card->stop2;
s1=(s1 & 0x7fff);
s2=(s2 & 0x1f);
ファイルに記録するときは、fileをopenしてストップアドレス1、2をまず記録しておきます。このデバイスサポートはメモリーボード内データを一応時間順に並べ替えて記録しますが、メモリーの途中にあるストップポイントに関しては何の処理もしません。データ処理プログラム側で記録されているストップアドレス1、2を使って再ソートすることになります。全体のストップアドレスはstop1+stop2*32768です。詳しくは以下の文章(古いが間違ってはいないはず)を参照してください。
メモリーマップは以下のようになっています。
20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
|
---|
ボード切り換え | ボード内下位アドレス
|
D16アクセス時、ボード内アドレスはcntl2で0から19まで設定します。D16データは、[D15..D08][D07..D00]の上位、下位8バイトずつ、それぞれボード番号が0なら(0,2)、1なら(1,3)という風に入っています。ボード0とボード2のデータは全く同じ(フィルターボードとの互換性のためこうならざるをえなかった)です。そこで
ボード切り換え | 上位バイト | 下位バイト
|
---|
0 | 0 | 2
|
1 | 1 | 3
|
2 | 0 | 2
|
3 | 1 | 3
|
4 | 4 | 6
|
5 | 5 | 7
|
6 | 4 | 6
|
7 | 5 | 7
|
8 | 8 | 10
|
9 | 9 | 11
|
10 | 8 | 10
|
11 | 9 | 11
|
12 | 12 | 14
|
13 | 13 | 15
|
14 | 12 | 14
|
15 | 13 | 15
|
16 | 16 | 18
|
17 | 17 | 19
|
18 | 16 | 18
|
19 | 17 | 19
|
20 | 20 | 22
|
21 | 21 | 23
|
22 | 20 | 22
|
23 | 21 | 23
|
24 | 24 | 26
|
25 | 25 | 27
|
26 | 24 | 26
|
27 | 25 | 27
|
28 | 28 | 30
|
29 | 29 | 31
|
30 | 28 | 30
|
31 | 29 | 31
|
のようにデータが入っているので、これを並べ替えるため
static int isel(int i)
{
int sel[16] = {0,1,4,5,8,9,12,13,16,17,20,21,24,25,28,29};
return(sel[i]);
}
という関数を用意し、順番を並べ替えます。下位アドレス全部で1Mbなのでここまで読んだところでデータをファイルに書きます(実際はtftpなので結局最後にまとめて転送される)。
for (k=0;k<20;k++)
{
cards[cardN].card->cntl2 = (unsigned short)k;
for (i=0;i<32768; i++)
for (j=0; j<16; j++)
{
a1=cards[cardN].card->board[isel(j)][i];
if ((j%2)==0)
{
memory_data[j*2+2+i*32]=(unsigned char)(a1>>8);
memory_data[j*2+i*32]=(unsigned char)(a1 & 0xff);
}
else
{
memory_data[j*2+1+i*32]=(unsigned char)(a1>>8);
memory_data[j*2-1+i*32]=(unsigned char)(a1 & 0xff);
}
}
if (fileflag[cardN]!=0)
fwrite(memory_data,1,1048576,FHAND);
このあと、ファイルをcloseして待機します。
if (fileflag[cardN]!=0)
fclose(FHAND);
なお、D32アクセスをするときは、ボード切り替えはD16アクセス時と同じくA20-A16を使いますが、0〜7までしか使いません。
ボード切り換え | D31-D24 | D23-D16 | D15-D08 | D07-D00
|
---|
0 | 3 | 1 | 2 | 0
|
1 | 7 | 5 | 6 | 4
|
2 | 11 | 9 | 10 | 8
|
3 | 15 | 13 | 14 | 12
|
4 | 19 | 17 | 18 | 16
|
5 | 23 | 21 | 22 | 20
|
6 | 27 | 25 | 26 | 24
|
7 | 31 | 29 | 30 | 28
|
コードはバンチ電流モニター部を参照ください。
dbdファイル
dbdファイルの中で次のように定義します。
device(bo,VME_IO,devBoVmemem2,"VMEMEM2")
device(mbbiDirect,VME_IO,devMbbiVmemem2,"VMEMEM2")
device(waveform,VME_IO,devWfVmemem2,"VMEMEM2")
device(stringout,VME_IO,devSoVmemem2,"VMEMEM2")
初期化ファイルはdevVmeFIRCnfigで、ベースアドレスが0x20000000で3枚使うとすると、
devVmemem2Config(3,0x20000000,0x05,0xf0)
の様に指定します。
このデバイスサポートで使うデータベースをまとめると、以下の様になります。
DTYP | Record | Signal | Name | Function | Remarks
|
---|
VMEMEM2 | waveform | 0 | ($USER):BUNCH | Bunch oscillation data(0アドレスから5120) | このままでは表示等できないのでデータベースで分割する必要あり
|
VMEMEM2 | mbbiDirect | 0 | ($USER):status | ボードのステータス | データ転送中にscanが入るとデータが化けるボードがあるので通常読まない
|
VMEMEM2 | BO | 0 | ($USER):SYNC | ボードスタート | アクセスで起動
|
VMEMEM2 | BO | 1 | ($USER):STOP | ボードストップ | アクセスで起動
|
VMEMEM2 | BO | 2 | ($USER):FILEIO | ディスク記録ON/OFF | 1でdisk save ready
|
VMEMEM2 | SO | 0 | ($USER):FILENAME | 記録用ファイル名 |
|
現在ののスタートアップファイル(の関係部分)は次のようになります。
dbLoadRecords("fbppcApp/Db/FB_MEM.db","USER=FBL:MEMX , CHAN=C0")
dbLoadRecords("fbppcApp/Db/FB_MEM.db","USER=FBL:MEMY , CHAN=C1")
dbLoadRecords("fbppcApp/Db/FB_MEM.db","USER=FBL:MEMZ , CHAN=C2")
devVmemem2Config(3,0x20000000,0x05,0xf0)
iocInit
バンチ振動モニター用大容量メモリーボード用EPICSデバイスサポートについて紹介しました。saveされたデータの活用法についてはこちらをご参照ください。
Makoto Tobiyama
14/Mar/2001
Return to FB Home Page...