RSS Twitter Facebook


« 2025年02月 | 2025年04月のアーカイブ |

2025/04/23

Seeed Studio XIAO RA4M1 でDAC出力(レジスタアクセスとDMA)


この間から触っている XIAO RA4M1 ですが、DAC を叩いてサイン波を出すサンプルを GitHub に置きました。

https://github.com/g200kg/arduino-r4-ra4m1-dac12-example

その1

RA4M1_DAC12_RegisterWrite


analogWrite() は内部で何か余計な処理をしているみたいなので、レジスタを直接叩いて波形を出力します。
サンプリングレート 44100Hz で 440Hz サイン波を出すサンプルです。

DAC は 12bit で 0~4095 のデータを右詰めで使用しています。タイマーは FspTimer の AGT1 を使用して割り込み処理内で DAC を叩きます。ついでに割り込み処理にどれくらいの時間がかかっているか D1 ピンに信号を出して確認しました。
HI = main loop
LO = interrupt

割り込み処理内の負荷は全体の10%くらいなので、これでもまあそこそこの波形生成処理はできそうではあります。

その2

RA4M1_DAC12_DMA


せっかくなのでペリフェラルにもう少し仕事をしてもらって DMA で出力バッファから直接 DAC を叩きます。
DMA はレジスタが多くて設定が面倒ですが、これで CPU の割り込み処理無しで出力バッファから勝手に DAC 出力されます。

DMA はノーマルモードのフリーラン状態にしておきタイマーイベントでキックする度に 16bit データを一つずつ DAC に送る形です。ポイントは出力バッファを「拡張リピート領域」と呼ばれる設定にする事で、転送元アドレスの下位ビットだけが更新されるようにしてリングバッファとして機能しています。なおこのため、出力バッファは 512byte 境界に配置する必要があるので下の宣言になっています。


uint16_t DACOut::buff[DACOut::buffSize] __attribute__((aligned(512)));

タイマーは RegisterWrite と同じく AGT1 を使用していますが ICU_DELSR0 レジスタにイベント AGT1_AGTI を設定する事で DMA へのトリガーとなります。

ライセンスは制限無しで好きなように使って良い Unlicense ライセンスにしていますので興味があればどうぞ。

posted by g200kg : 9:55 AM : PermaLink

2025/04/20

Seeed Studio XIAO RA4M1でDAC出力


今まで音系のガジェットを作る時にコントローラとして ATmega328P とか STM32F303 あたりを使っていたのだけど、そろそろ違うチップに手を出すかなという事で、今候補にしているのがルネサスの RA4M1。Arduino UNO R4 で採用されたチップです。
Seeed Studio から XIAO という非常に小さなモジュールがかなり安価に出回っているのでこのままガジェットに組み込んでしまうのに丁度よさそう。

という事で RP2040 とかに比べれば控え目ながら Arduino UNO R3 よりは CPU 性能も上がっているし 12bit DAC 内蔵なのでこれを出力系に使えば丁度良いかなと。

そんな訳で Arduino IDE 環境で DAC 周辺のチェックなんかをしています。
Arduino 用ライブラリとしては、周期波形生成用の analogWave クラスと DAC を直接叩く analogWrite クラスが準備されているので挙動を確認したりしていたのだけど、なんか思っていたのとは違う模様。

下の図が AnalogWave クラスを使用して 440Hz を生成したサイン波。どうやら 10kHz サンプリング相当くらいの階段になっていて、周波数を変えるとこの形のまま伸び縮みする感じで、テーブルに手を入れたとしてもあくまで固定の周期波形を出すイメージかな。

出力をバッファリングしつつリアルタイムに波形生成するなら analogWrite で DAC を叩くかぁ。と思ってやってみたのが下図。44100Hz で割り込みをかけつつ analogWrite で DAC を叩いています。

基本的には動いているのだけどなんか妙なスパイクが出る。拡大すると下の図。

analogWrite で DAC を叩く度にヒゲが出る。これは......。
DAC 関連のレジスタの挙動とかを見るに、どうやら analogWrite は呼び出しの度に毎回 DAC パラメータのセットアップ→値の出力→DACモジュールの停止、を行っている模様。

まあ DAC を動かしっぱなしで電力食うよりは analogWrite された瞬間だけ動かすという作戦なのでしょうね。アプリケーションによってはこの方が良いというのはわかるけど、これで音声信号を出力させたくはないな。という事でやっぱり DAC 周りのレジスタを直叩きして DAC を連続動作させつつ生成した波形データを送り込む必要があるようです。

ソースの整理が全然つかないけど、取り合えず 44100Hz 割り込みで 440Hz サイン波出力が出来る事は確認しました。下図。

posted by g200kg : 11:20 PM : PermaLink

« 2025年02月 | 2025年04月のアーカイブ |


-->

g200kg