ターゲットROMを差すところを32ピンZIFソケットに置き換えました。こうするとツールとしてきれいにまとまって見えます。PLCCアダプタもこの上に載せればOK。
ところでこのZIFソケット。草色のボディ、レバーの形状といい3MのTEXTOOL(tm)そのものなんですけど某店で¥200で売ってるんです。ホンモノならそんな値段じゃないと思いますがどうなんでしょう。とりあえず機能的には問題なし
下準備ができてやっとAD1847の初期化になりますが、前述の通りバッファにコマンドワードを書き込むと勝手に送信されてしまいます。初期化コマンドチェインinit_cmds[14]を割込みごとに1ワードづつ送るために初期化のためだけの割込みルーチンframe_intの中でインデックスをインクリメントしています
SPORT0の割込みを許可することで初期化が開始され、ループカウンタafが0になるまで繰り返しています
14個のコマンドチェインを書き込んだ後、初期化の完了確認、後始末をしているようです。そして最後に大ワザ・・
SPORT0の割込みベクタに書かれていたJUMP frame_intをJUMP echoに上書きしてしまいます。これでそれ以降のフレーム割込みではechoが実行され入力信号をA/D変換したデータをそのままD/A出力する、という動作を繰り返すことになります
初期化時だけ実行される割込みルーチンと、その後の連続動作で実行される割込みルーチンを切替える巧妙なプログラムです。ただし自己書き換えしてしまってるので、リセット、コールドスタートしても再起動できません。もういちどDLLしてやる必要があります
これでいちおう全体的な流れは把握できました。このボードのプログラミングはこのループバックプログラムを雛型にして細部を修正していけば良さそうです
つづいてコーデックAD1847の初期化になりますが、これはシリアルで接続されているのでシリアルポートSPORT0からコントロールワードを送出することになります。いままでざっくりマニュアルを読んで理解したのは
「DSP側のメモリ上にバッファ領域を設け、autobufferingとMultichannelFunctionの設定をしておけばコーデックのフレーム同期割込みのたび、然るべきタイミング(time slot)で必要なデータを勝手に送信し、受信した返り値でバッファを勝手に更新してくれる」
ということみたいです(かなり雑)
これに一対一対応するADSP2101側のデータメモリ上のバッファ領域buf[6]の定義はこうなっています
ただslot0~5の順番とメモリ上の配置が微妙に異なります。自分も’the order here seems a little funny’・・・
ソースのコメントにその理由が書いてあるのですが、10回読んでも意味が分かりません。とりあえずこのままにしておきます。
コーデックがバスマスタになるのでコーデック側に送受信データがあるときフレーム同期をつかってDSPへ割込みをかけることになりますが、それに応答してDSP側で送受信プログラムを起動するのではなく、ハードウェアで循環バッファとの入出力を自動でやってくれるようです。(autobuffering)さらに1フレーム期間を32個のタイムスロットに分割してそのフレームで必要/発生したデータをブロックでやりとりします(Multichannel function)
ここらへんはマニュアルを読んだだけではさっぱり理解できませんが、幸いサンプルコードがあるのでその記述を見ていきます。
先ずはDSP側の初期化。autobufferingとMultichannel functionの設定は深く考えずサンプル通り。設定レジスタはデータメモリ空間にマップされているのでコーディングは容易です
その次は本質的なところではないですがメモリのウェイト、ペリフェラルの有効化。割込みフラグのクリアなどをやっています
最後まで残っていたΦ3.5イヤホンジャックを取り付けて部品実装は全て完了しました。
サンプルコードのリストを読んでコーデックの使い方を勉強しています。アセンブルはノーエラーで通ったのですが細かい修正は要りそうです。
まずサンプルコードはADSP-2181用に書かれているのですがこれをADSP-2101上で動作させるには機能制限があり、前回のようにインストラクションの他、割込み関係も違いがあるようです。
ADSP-2101の割込み要因とベクタアドレスは以下のようになっていますが
ADSP-2181では割込み要因が大幅に拡張されています。この中で使うのはRESETとSPORT0 Receiveだけなのでハード的には問題ないのですがベクタアドレスがズレています。本当ならアッパーコンパチで作ってくれればいいんですけど
ということで、サンプルコードのベクタテーブル部分を修正。これはブートROMに含まれプログラムエリアの0番地からロードされるオリジナルなベクタテーブルを中継ぎとして飛んでくる2段階目のベクタテーブルで0x800番地からロードされます
アプリケーションノートに書かれているサンプルコードをそのままコピペしてきました。単純なループバック(入力されたアナログ信号をA/DしたものをそのままD/Aに書き込んでアナログ信号を出力)なんですがコメント含めて約350行もあります。ただそのほとんどはDSPとコーデックのイニシャライズに費やされていてメインの処理はソース最後のこの部分だけです
talkthruで割込み待ちの永久ループをしていて、コーデックからシリアルのフレーム割込みがかかるとframe_intが実行されてその中でコントロールコマンド、アナログ入力、アナログ出力をしています。もしフィルタとか何らかの信号処理をしたい時はアナログ入力、アナログ出力の間に演算を挿入する、ということになります
さて、このソースを何も考えずアセンブルしてみると・・・・
asm21 loopback.dsp -l
以下のようなステータスのビット状態をチェックしている ax0 and 2 という行でエラーになってしまいます
これをマニュアルで調べてみるとどうもANDなどロジック2項演算子の右項に即値が使えるのはADSP-2181で拡張された機能のようです(即値といっても離散的な値のみですが)
このボードのADSP-2101ではレジスタ渡ししかないのでいったんAY1に即値代入するコードにして以下で通りました
(ADSP-2181用のコードを受け入れるにはオプション入れて
asm21 loopback.dsp -2181 -l とするらしい)