超高速?YMZ294いろいろ(アセンブリ読書)

YMZ294を秋月で買った。

YMZ294のデータシートは、昔はインタネットに存在していた模様だが、現存しない。

なので秋月で買ってみないことには使い方もわからんのだった。

そこで解説。

MSXのSOUNDコマンドと同一のレジスタ操作で発声できる。このレジスタについては、

AY-3-8910が元ネタらしい。わたしはH-1 MSXマシンの手引書を読んで学習したが、手に入らない場合はこれでよいだろう。YMZ284[alldatasheet.jp] 284は294と比べ、不要だった2つの端子が削られている。

294は、18pinで、順番に /WR(write enable) /CS A0(address mode) VDD(5V) SoundOut GND ΦM 4/8(clk select) /IC(reset) /TESTで、のこりはD[7:0]である。

秋月で買うといかつい水晶発振器がついてくる。これは4MHzであり、4/8はHiレベルに設定することで2分周して2MHzを生成し、これがLSI内のfscとして扱われる。このことは秋月のデータシートに明示しておらず、誤解を生みやすいので注意すること。

また、/TEST, 4/8, /ICは内部に60-260-600kΩというちょーてきとーなプルアップ抵抗が入っており、結線しなくても使えるようになっている。

さらに、その他のピンに於けるHiレベルが2.2Vからであるので、2.8Vや3.3Vで動作するマイコンやFPGAからも容易にアクセスできる。

さらにものぐさな事を言うと、/CSは、普通プルアップしっ放しでもとりあえずつかえるチップ(ex.SRAM)が多いように思うが、この場合、一回アクセスするごとに上げ下げせねばならないようで、読み込むわけでもないのに/WRも上げ下げせねばならないのだ。めんどくさい。

そうおもっていると、/CSと/WRはショートしても問題無いようだ。サンプルプログラムも同時に同じアクセスを行っているではないか。事実、隣のピンなので、芋はんだしてくっつけましたとさ。

こんどはソフトウェア層の話。

A0がLowで/WR(=/CS)がlowのときにD[7:0]をフェッチし、その後A0がLowのままで、/WRがHiレベルになるとレジスタ選択を行う。

その後A0が上がり、/WRが落ちるとD[7:0]を同じくフェッチし、/WRが上がることでそのレジスタにデータを書く。

#/WRすら操作せずにうごかしたいなあ (11/05追記-やってみたけどできません。)

情けないことに、この後僕はとんでもなくしょうもないことに2日間も悩むことになる。

それは ビ ッ ト オ ー ダ.

かっこよく(いやよくない)書けばそういうことなんだが、ようはデータシート嫁ということですな。

最終的にこうした。

assign { /WR, A0, D[7:0] } = GPIO4[9:0]; ///////-A

/*回路が

wire [9:0]temp;

assign temp = { D[7:0], /WR, A0 };///////-B状態だったため、なにも考えずに

assign GPIO4[9:0] = temp;としてしまったわけだが、良く考えると大間違え。

気持ち悪いが現状

assign temp = { GPIO4[7:0], GPIO4[9], GPIO4[8] }; ///////-Cとなっている。

ユニバーサル基板に載せる段階ではAよりB,Cの方が現状に近く綺麗に引き回せるのだ;-) */

そして、

void ymzwrite0(int frec,int adr){
int highbyte;
FIO4PIN=0x00;
FIO4PIN=adr;
FIO4PIN=0x200+adr;
FIO4PIN=0x100+(frec&0xFF);
FIO4PIN=0x300+(frec&0xFF);
FIO4PIN=adr+1;
FIO4PIN=0x201+adr;
highbyte=(frec>>8)&0xFF;
FIO4PIN=0x100+highbyte;
FIO4PIN=0x300+(frec>>8);
}
void ymzwrite1(int value,int adr){
FIO4PIN=0x00;
FIO4PIN=adr;
FIO4PIN=(0x200+adr);
FIO4PIN=(0x100+value);
FIO4PIN=(0x300+value);
}
という函数でI/Oアクセスをすることにした。ところで、これ以降ネタである。

この函数、Delayをはさんでいない。しかしCPUclkは72MHzである。

IOはCPUバスに直接つながっているため、CPU速度で動く。

\あれ?タイミングチャートに何て書いてある?あれ?タイミングチャートに何て書いてある?/

ライトパルスオフ時間 tWOFF 40ns<

あれ?こういうときはアセンブリを読めば良いんだよ

.global ymzwrite1
.type   ymzwrite1, %function
ymzwrite1:
@ Function supports interworking.
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
mvn     r3, #-1073741824@0x-40000000
sub     r3, r3, #12288@r3=0x-40003000
mov     r2, #0
str     r2, [r3, #-3947]@ 0 -400030F6B (FIO4PIN=0x00に対応
str     r1, [r3, #-3947]@FIO4PIN=adr; 1clkでアクセス
add     r1, r1, #512

str     r1, [r3, #-3947]@2clk分でtCSW<30ns<2clk分=28nsあれ?
add     r2, r0, #256
str     r2, [r3, #-3947]@余談だけどr2つかわずに済むよね
@またもや2clkでFIO4PIN=(0x100+value);
@はい先生!こんどこそtWOFF を満たしてないと思うんですが!
add     r0, r0, #768
str     r0, [r3, #-3947]
bx      lr
.size   ymzwrite1, .-ymzwrite1

…..。

データシートが知ってる定格中最速のYMZ294より1.4倍も高速にうごかせました。えっと…..

#実際、定格オーバーでも動くのは知ってるけど、こんなに速いのは面白いなあと思ったので、ネタとして。

時間が遅いのでネタアンプは次回。

Post a comment or leave a trackback: Trackback URL.

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です