最近RX64M関係の仕事で、忙しかったが、ようやく何とかなった感じで、
やっと、RX24T関係を再開する事ができた。
RX24T用の汎用基板を作ろうと、回路図を引いていて、そういえば、
MTU関係の実装が全く進んでいない事に気がつき、テンプレートを実装し
始めた。(なんか回路図引くのが、億劫)
MTU3は、非常に高機能なので、全てを網羅するような、汎用性の高い
テンプレートを作るのはかなり大変なので、必要な機能を少しづつ実装して
ゆき、その都度改修するしかないと思われる。
とりあえず、インプットキャプチャー機能を試してみた。
今回実装した「mtu_io.hpp」は、テンプレートパラメーターとして、
「mtu.hpp」テンプレートを内包する。
typedef device::MTU0 MTU0; typedef device::mtu_io<MTU0> MTU0_IO; MTU0_IO mtu0_io_;
MTUは、9チャネルあるが、全てが同じ機能ではなく、微妙に違う部分が
あり、それらを吸収する構造を考えるのはパズルのようだがそれなりに楽し
い。
※MTU5は、3相モーター用に特化しており、除外した。(指定すると
エラーになる)
「mtu.hpp」は、ルネサスのハードウェアーマニュアルに準拠したクラスな
ので、レジスターの名称は、マニュアルに準拠させている。
だが、割り込み、入出力ポートのマッピングなど、連携して動作する機構が
必要なので、それらの制御が簡潔に書けるように、ヘルパー関数を用意した。
※これは、SCIやI2C、SPIなどの知見を元に考えた構造で、さらに
MTU用に色々と拡張した。
uint8_t intr_level = 3; if(!mtu0_io_.start_capture(MTU0::channel::A, MTU0_IO::capture_type::positive, intr_level)) { utils::format("MTU0 input capture start fail...\n"); }
こんな感じで書けるようにした。
※チャネルとポートのマッピングは、現在の実装では、標準的ポート固定に
なっているので、変更できる仕組みを考えないといけないが、シンプルな方
法を思いつかないので、そのうちじっくり考える事にする・・
const auto& cap = mtu0_io_.get_capture(); float a = static_cast<float>(mtu0_io_.get_base_clock()) / static_cast<float>(cap.all_count_); utils::format("Capture: %7.2f [Hz]\n") % a;
こんな感じで、キャプチャーした周期を表示できる。
RX24Tでは、MTUモジュールの最大周波数は80MHzなので、精度
が高いと思ったのだが、かなりずれている・・、ただ、リファレンスの周波数
の精度が悪いだけかもしれないので調査が必要・・・
※R8C/M120ANで出力した信号(R8Cのクロックは内臓RCオシレーター)
※正確なオシレーターを持っていない・・
次は、単純な波形出力を実装してみようと思う。
出力も、ほぼ、キャプチャーと同等なので、実装してみた。
typedef device::MTU1 MTU1; typedef device::mtu_io<MTU1> MTU1_IO; MTU1_IO mtu1_io_;
※実験では、MTU1 を使った。
// MTU1 設定 { uint32_t frq = 1000; if(!mtu1_io_.start_output(MTU1::channel::A, MTU1_IO::output_type::toggle, frq)) { utils::format("MTU1 output start fail...\n"); } }
MTU1 の出力「PA5/MTIOC1A (36)」を「PB3/MTIOC0A (32)」に繋いで1000Hz
出力。
そしてキャプチャーしてみた。
概ね正確なようだ、昨日の「ズレ」は、R8C/M120ANの周期が不正確
なのが原因だったようだ・・
それでも、真っ当な信号発生器は買うか、作る必要があるようだ・・・
ソースコードは GitHub にプッシュした
インプット・キャプチャー、サンプル
※RX64MのMTUもほぼ同等な機能なので、そのまま使えそうだが、割り
込み関係のハンドリングがかなり異なるので、それを吸収する仕組みを考えな
いとならない。