RXマイコンで、DMACを使う

RX65NのLCDが中々進まない・・・
※もう少しな感じなのだが、初期化後に、表示はしている感じだが、謎の動作をす
る・・・

—–

LCDの制御でも使う事になるので、DMAC関係のテンプレートライブラリを実装
してる。
応用範囲が広いので、継続して機能追加、拡張する事になると思う、本来色々な利用
状況を想定して、必要な機能を実装しておくのが普通だが、他のテンプレートクラス
と連携して動作させる事が必須なので、どのような設計が適しているのか良い案が思
い浮かばないので、「仮」とする。

とりあえず、メモリー転送や、メモリーFillなど、DMAの起動をソフトで行う
物で、実験して動作を確認した。

実際には、DMACは、何かのペリフェラルデータ転送を行うハードとして利用する
のが普通なので、それらから利用できるような仕組みを盛り込む必要があるのだが、
どのような構成にしたら良いか迷うとこだ・・・

DMACで、fifo のような機能がソフトの介入無しに出来れば、かなり応用範囲が
広がると思えるのだが・・

とりあえず、D/AやA/D変換でDMACを使うような想定で、全体の構成を考え
るのが良さそうだ。
まず、タイマー割り込みでD/Aの値を書き換えて、サイン波を出力してみた。
これは、問題無くできた。
※サンプリングは48KHzとした。

※流石12ビットもあると、それなりの精度で出力出来る~

—–

次にDMA版、TPUタイマー起動でDMAをスタートして、D/Aのレジスタから、
メモリに転送する、バッファは有限なので、適切なサイズで、先頭に戻るようにする。
この時、DMACはリピート転送モードを使う。
リピート転送モードでは、最大でも1024ワードの転送しかサポートされないのが、
痛いところだ・・
※D/Aチャネル0、1が連続した32ビットデータなので、32ビット転送として
いる。

今回、48KHzをサンプリングとしたオーディオのストリーム再生を想定した、
48KHzで1024サンプルだと、21ms分なので、リングバッファの書き換えを
考えた場合、半分の10msくらいでサービスする必要がある。
今回の場合なら、100Hzの割り込み(10ms)を作成して、そのタイミングでサ
ービスすれば問題は無いが、もっと大きいバッファが必要な場合はどうするのか?
普通に考えて、DMAC終了割り込みで、ターゲットのアドレスを書き換えるなどのサ
ービスが必要となるなど、この仕様は色々痛い・・・
この場合、サービスにかかるオーバーヘッドが大きいと、次のDMA起動とオーバーラ
ップしてしまう場合が考えられる・・
その場合は、DMACをもう1チャネル使って、ピンポン式にすれば何とかなりそうで
はある・・
※何で、1024ワードに制限してるんだよぅ・・・

C++ のテンプレートでファンクタ・クラスを引数としているので、割り込み内から呼ぶ
ユーザー作成のタスク呼び出しは、展開され、関数ポインターを使ったコールバックの
ようなオーバーヘッドを生まないのが救いだ。
※これは、非常に短いスパンで割り込みが発生するような場合に効果が大きい。

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    /*!
        @brief  TPU I/O クラス
        @param[in]  TPU チャネルクラス
        @param[in]  TASK    タイマー動作ファンクタ・クラス
    */
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    template <class TPU, class TASK = utils::null_task>
    class tpu_io {
    ...

—–
設定が悪くて、思ったように動作しなかったが、ようやく思った動作になった。

呼び出しのプロトタイプはこんな感じになった~

//-----------------------------------------------------------------//
/*!
    @brief  割り込み要因による開始
    @param[in]  trg     転送開始要因
    @param[in]  tft     転送タイプ
    @param[in]  src     元アドレス
    @param[in]  dst     先アドレス
    @param[in]  lim     転送リミット(※カウント数なので注意)
    @param[in]  ilvl    転送完了割り込みレベル(0以上)@n
                        ※無指定(0)なら割り込みを起動しない。
    @return 成功なら「true」
*/
//-----------------------------------------------------------------//
bool start(ICU::VECTOR trg, trans_type tft, uint32_t src, uint32_t dst, uint32_t lim,
           uint32_t ilvl = 0) noexcept

最後に、以前に紹介した、整数計算を使った三角関数クラスを使って、リアルタイムに
計算して、周波数ジェネレーター的な実装を行い連続的な再生ができるているかを検証
してみた。


    X' = X * COS(s) - Y * SIN(s)
    Y' = X * SIN(s) + Y * COS(s)
    ※角度「s」が十分小さい場合、以下のように近似できる。
    COS(s) ≒ 1
    SIN(s) ≒ s
    X' = X   - Y・s
    Y' = X'・s + Y

CH0、CH1でsin、cosを出力している。

ターミナルから、周波数を入力すると、その周波数を出力する。
※サンプリングが48KHzなので、高い周波数だとエイリアシングが目立つ。

RX64M D/A ストリーム・サンプル

RTK5RX65N、未実装部品、SDカードの利用

次はLCDと宣言してたが、その前に未実装部品についてまとめておきたい。
また、SDカードを使う為にカードソケットを追加で取り付けた。

このボード、未実装の部品がある。
(1)SDカードソケット「SD/MMCカードソケット:101-00565-64(AMPHENOL COMMERCIAL PRODUCTS製)」
(2)SDカード電源用ゲートIC「ISL61861BIBZ」
(3)JOYスティック「SW3(JOYSTICK):SKQUDBE010(ALPS製)」
(4)イーサーネットコネクタ「RJ45_J3011G21DNL」
(5)イーサーネットPHY「LAN8720A」
※主に、上記部品で、SDカードソケット、JOYスティックは、部品が判らなかったので、
ルネサスに問い合わせをした。

もちろん、自分で部品を実装したら、保障は受けられなくなるのだが、機能があるのに使わな
いのは勿体無い。
一番困難なのは、表面実装部品で、DNFパッケージだが、これは、後々、手順などを整理し
たいと思う。(基板の実装屋さんなら簡単だと思う)

多少問題なのは、上記部品で、SDカードソケット、JOYスティックは、製造が終了してお
り、現在部品の入手が難しい。(入手できても割高になってしまう)
※代替部品を探したが、適当な物を探せなかった、また、日本では、やはり入手が困難だと思
われる。

特に、SDカードは、このような機器では必須のI/Oなので、マイクロSDカードを使って
代用させる方法を考えた。
ソケットは、秋月電子製、マイクロSDカードスロットDIP化キットを使う。
多少細かい、配線は比較的簡単ではあるが、強引な方法なのでお勧めできないのだが、他に良
い方法を思いつかない。
また、RTK5RX65Nでは、SDカードの電源をマイコンによって制御しているのだが、
電源制御につかっているIC(インターシル製)は、入手できるが割高なので、とりあえず
直接接続しておく事にする。

※自分は、「セメダイン SuperX」で、基板を接着した。
※強力両面テープでも良いかもしれない。

※マイクロSDには、ライトプロテクトが無いのでオープンにしてある。
※ほぼ、ストレートな結線なので配線は簡単だが、電源系は、熱が拡散するので、容量の大
きいハンダコテが必要と思う。

SDカード関係のソフトSPIでの定義

    // カード電源制御は使わない場合、「device::NULL_PORT」を指定する。
//  typedef device::PORT<device::PORT6, device::bitpos::B4> SDC_POWER;
    typedef device::NULL_PORT SDC_POWER;

    // Soft SDC 用 SPI 定義(SPI)
    typedef device::PORT<device::PORT2, device::bitpos::B2> MISO;  // DAT0
    typedef device::PORT<device::PORT2, device::bitpos::B0> MOSI;  // CMD
    typedef device::PORT<device::PORT2, device::bitpos::B1> SPCK;  // CLK

    typedef device::spi_io2<MISO, MOSI, SPCK> SPI;  // Soft SPI 定義

    typedef device::PORT<device::PORT1, device::bitpos::B7> SDC_SELECT;  // DAT3 カード選択信号
    typedef device::PORT<device::PORT2, device::bitpos::B5> SDC_DETECT;  // CD   カード検出

    typedef fatfs::mmc_io<SPI, SDC_SELECT, SDC_POWER, SDC_DETECT> MMC;   // ハードウェアー定義

    MMC     sdh_(spi_, 20000000);

—–
以前に自作のRX64Mボードで、SDHIのドライバーを実装しようと、色々やったが、
どうやっても動作せず、また、ルネサスのサンプルも無いようだったので、あきらめていた。
だが、よくよく調べると、RX64Mマイコンには、SDHIインターフェース内臓版と、そう
では無いバージョンがある事がわかった。
実験で使ったデバイス「R5F64MFCFDC」は、SDHIは「無し」なので動くハズは
無い。
※SDHIインターフェースのバージョンを取得するレジスターは読めて、それらしい値だった
ので、てっきりSDHIがあるものと思っていた。

RTK5R65NボードのRXマイコン「R5F565NEDDFB」は、SDHI「あり」の
デバイスなので、SDHIインターフェースを使ってSDカードのアクセスを行う事が出来る。
4ビットモードを製品として使う場合は、SDアソシエーションとのライセンス締結が必要なよ
うだが、自分がリリースしているテンプレートドライバー、フレームワークは無保証なので、こ
れらには関知しない。
※SDHIには、ライセンスが必要無い1ビットモードもある。

現在、SDHIドライバーは開発中であり、とりあえず、動作確認の為、SPIのソフトウェア
SPIドライバーを使って、動作を確認してある。
RTK5 SD カードアクセス、サンプル