hira のすべての投稿

RL78/G13の gcc での最適化に関するトラブル

LCDに表示するプログラムを実装するようになって、何か、正しく動かない事
が、頻発してきた。
※実際は、以前から、あったのだが、何かの拍子に直ったりする為、原因を究明
出来ないでいた。
よくよく調べると、最適化オプション「-Os」を使う場合に、起こる事がある事が
判った。
-O1、-O2 では発生しない為、とりあえず、-O2 を使っていたのだが、プログラム
の容量が増してくると、そうもいかなくなってくる。

そこで、コードを簡単に追ってみると、スタック領域に配置された変数にアクセス
する場合に、スタックのアドレス計算を間違っているような挙動だった。

これは、コンパイラの問題のように思うが、RL78のコード生成部分を追って、
修正するには、スキルと時間が足りないように思う。
それと、コンパイラのバグと思っていた事が、実際には、実装の問題である事は、
良くある話でもある。
そこで、回避策を色々試してみた結果、コンパイラオプション「-flto」を追加す
る事で回避出来ているように思う。

詳細に調べた結果、RAMの初期状態に依存していただけだった。
通常「.bss」セクションは「0」クリアするが、「.data」セクションは、何かの
値をロードするので、そのままな状態になっている、これが、問題のようで、
ロードしない場所は「0」クリアする必要がある。
そこで、リセット時、全てのRAMを全て「0」クリアするコードを追加した。

;; clear all RAM
    sel     rb0    ; bank 0
    movw    hl, #__datastart
LC0:
    movw    ax, #0
    movw    [hl], ax
    incw    hl
    incw    hl
    movw    ax, hl
    cmpw    ax, #__stack
    bnz	    $LC0

※レジスタ・バンクは触らない。
この変更で、怪しい挙動は、無くなったようではある。

ただ、コンパイラを作りなおす必要がある。
コンパイラは作り直さなくても大丈夫と判った、でも、4.9.4 の方が、ほんの
少しは、最適化が良いのかもしれないので、4.9.4 にするのはやぶさかでは無い。

※最近、gcc-4.9.3 から、gcc-4.9.4 に移ったので、その過程で、ビルドオプシ
ョンを精査した。

--enable-multilib --enable-lto

を追加する。
※「multilib」は以前は「disable」であったが一応「enable」とした。

「-flto」は、LTO(Link Time Optimization)を有効にするオプションで、これによ
り翻訳単位を超えた最適化が可能になる。
これは、gcc-4.8.x から、追加された機能のようだが、RL78 と、gcc-4.9.4 の場
合は、常に「有効」にする必要があるのかもしれない。
※指定しないと、「有効」になっているようである。

とりあえず、現状で、これで回避できているようではある・・・

RL78/G13にモノクログラフィックスLCDを接続する

以前に Aitendo さんで買った LCD は、色々イマイチの部分があり、どうしようか悩
んでいたが、RSオンラインで、新品のLCDでもをそこそこの値段で売っている事
を発見して、試しに買ってみた。

小規模なマイコンで、簡単なユーザーインターフェースを実装する場合、何か表示装
置が必要で、グラフィックス液晶は、その候補の一つと思う。
RL78では、メモリーがそこそこあるので、128×64ピクセル程度のモノカラ
ー液晶なら、漢字も表示できるので、大抵のアプリケーションにマッチする。

今回実験した液晶は、バックライトは無いものの、850円くらいで購入でき、(
2000円くらいで、表示面積が大きいタイプもある)3.3V動作が可能なタイプ
で、消費電力も少ない。

128×64(バックライト無し)@833円

128×64(バックライト有り)@917円

接続ピンのピッチが1.27mmだったので、変換基板と追加回路を組み込んだ。
img_0827s

コントローラーは、ST7565Rで、データバスが8ビットだけど、シリアル変換
モードがあり、SPI通信で接続出来る。
RSオンラインで用意されている資料では、不明な点が多かったが、ネットを探して、
表示に必要な外部回路(主にコンデンサの接続方法等)を探して、接続した。

SPI通信、参考回路:
64128

以前に作成した、サンプルコードを、多少修正(主に制御ポートの定義)したら、問
題無く動作した。
ST7565のコードは、ネットで見つけた物を改造したもので、Aitendo の液晶で
は不安定で、正しく動作しなかったが、この液晶では、何の問題も無く綺麗に動作す
る。
※やはり、ジャンクは、ジャンクと言う事なのかもしれない。

img_0830s

SSD1306コントローラー使用のOLED:
img_0831s

RL78との接続:

    /CS  ---> P53       (36)
    A0   ---> P50       (33)
    SD   ---> P13/SO20  (43)
    SCL  ---> P15/SCK20 (41) 
    /RES ---> /RESET    ( 6)

※ソースコードには、ST7565、SSD1306どちらか片方を有効にする定義
がある。

LCD サンプル

format クラスでの IEEE754 フォーマットの表示

C++ では、printf を使わない文化がある。

これは、スタックベースの可変引数では、安全性が確保出来ない事に由来する。

その為、C++ では、printf が便利な事は判っていても、それから離れて、std::cout
関係のクラスを実装する事となったと思う。
ただ、典型的な C のプログラマーは、C++ 上でのプログラムでも、「std::cout」
が使いにくいと言い、printf を使い続ける輩が後を絶たない。
「std::cout」も馴れてしまえば、そうそう使いにくいものでも無いと思うが、それ
でも、printf にある、柔軟性やコンビニエンス的な使いかってには、敵わない。

boost では、printf の使いやすさと安全性を網羅した format クラスが作られた。
これにより、C++ でも、printf と遜色無い、利便性を手に入れたと思える。

小規模な組み込みマイコンでも、やはり、安全性が無い printf は使いたくは無い。
※printf のフォーマットと引数の不整合は、最悪の場合、プログラムがクラッシュ
する、ある程度は、コンパイラが不整合を検証しているが、完全には出来ないので、
多くの組み込みメーカーではデバッグ以外では使わない事が普通で、リリースビルド
では、「#define」を使って「printf」を消している。

boost::format クラスは、iostream に依存していて、非常に多くのリソースを消費
してしまう為、限られたメモリーしか無いようなマイコンでは、使う事が出来ない。
また、「float、double」を使わない場合に余分なコードを節約したい等、カスタム
したい場合もある。

組み込みでも、C 言語ベースのシステムでは、printf も多くのメモリーを消費する
為、多くの人が、廉価版の printf を実装して使う事が多いが、それに習って、C++
なので、boost::format の廉価版を実装してみた。
C++ では、演算子をオーバーロードして、全く別の機能として使う事が出来る。
これを利用して、「%」記号(通常は、整数の剰余)をオーバーロードして、引数を
受け取るようにしている。

不整合が起こった場合は、「例外」をスローするのが普通であるが、それは、別の問
題を含んでしまう為、エラーステータスによる処理を行なっている。

独自 format なので、拡張して、固定小数点の表示、二進数表示などを取り入れている。
又、内部から、sprintf を呼ぶような事も行なわない、純粋な物を実装したい。

以前は、整数表示や文字列表示などの機能しか実装していなかったが、float の表示
が必要な事は結構ある。
そこで、IEEE754 の表示が出来るように拡張してみたのだが、仕様が複雑で、難解
な部分が多く、現状では、全ての仕様を満足するまでには完成度は高く無いものの、
ある程度は、正しく表示できるのようになった。
以下のような方針で実装してみた。

・内部で float の計算を行なわない。(整数のみの計算で行なう)
・なるべくメモリーの消費を抑える。
・なるべく printf の仕様に準拠する。

printf では、float、double の区別は無く、基本的に、float は double にキャス
トされて内部処理される。
newlib の該当する部分を読んでみたが、あまりに複雑で、部分を抜き出して簡単に
使えそうも無い事から、自分で考えながら実装してみた。
その為、無駄な部分や間違いがあるかもしれない。

固定小数点表示:
組み込みでは、A/D 変換した値や温度など表示する場合など、シフトしたり掛けたり
割ったりして、実数部と小数部を分けて整数で表示する事が良くある。
そこで、もっと簡単に扱えるように固定小数点表示をサポートしている。

    int32_t val = 4096;
    utils::format("FixedPoint: %5.3:12y\n") % val;
    val = 6372;
    utils::format("FixedPoint: %5.3:12y\n") % val;
    utils::format("FixedPoint: %5.2:12y\n") % val;

FixedPoint:  1.000
FixedPoint:  1.556
FixedPoint:  1.56

・上の例では、全体5桁(小数点含む)、小数部3桁、小数点以下12ビットとして
表示する。
・内部では、小数部+1桁目を四捨五入して丸めて表示する。(この仕様は、printf
の IEEE754 表示に準拠している)

IEEE754 サポートが必要無い場合は、ソースの頭で、以下のようにコメントアウトする
事で大幅にメモリーを節約できる。(その場合でも、固定小数点表示はサポートされる)

// #define WITH_FLOAT_FORMAT

※現状では、「double」の80ビットフォーマットをサポートしていない。

※R8C、RL78、RX マイコンで利用でき、もちろん、他のプラットホームでもコンパイル
できれば、利用可能と思う。

RL78/common/format.hpp

追記修正:
printf の桁数指定を勘違いしていた為、改めて、仕様を読み直し、printf に準拠する
ように修正を加えた。

RL78/G13でタッチセンサー実験

以前にSDカードを接続する実験をしていた時、入力ポートのプルアップ抵抗設定
を間違えて、オープン状態になっていた、配線チェックの為、配線に指を近づけた
らカードが検出され、LEDが点滅するような状態だった。
それで、バグに気がついた。

この件に伴い、「入力ポートのインピーダンスは高いなぁー」と感じた。
※あたりまえなんだけど・・・

この件で、静電容量の微小な変化を使ったタッチスイッチを実験してみる事にした。

原理は簡単で、微小な静電容量を積分時間によって判定するもので、RL78のル
ープカウントを積分時間とする方式。

・タッチパッドは、10mm四方の銅版を使い、上に絶縁の為、ポリイミドテープ
を貼ってある。
・この銅版に1Mオームの抵抗を繋ぎ、プルアップしておく。
・等価的には、この銅版は、微小なコンデンサと考える事が出来る。
・指で「触る」事で、微小な容量が変化するものと思われる。

評価方法:
・まず、ポートを出力に設定して、「0」を設定し、等価コンデンサを放電する。
・次に、ポートを入力に設定して、「1」になるまでのループ数をカウントする。
・このループ数の違いにより、開放された状態と、触っている状態を判断できる。
・電源投入時、開放状態のカウントを計り、基準にする。
※この値は、安定しているので、一度基準が判ればよい。

実験結果:
実験すると、開放時は「50」くらいで、触ると、80~300くらいまで変化す
る事を確認。
指を近づけると、「60」くらいになるので、60以下は無視する。

ただ、かなりバタつくので、触った瞬間と離した瞬間を正確に判断するには、多少
の工夫が必要。

IMG_0823s

静電容量は、タッチパッドの作り方で、変化し、微妙な値が大きく影響するので、
再現性は低いかもしれない。

タッチスイッチ・サンプル

RL78/G13でA/D変換を使う

RL78/G13には、10ビット(8ビット)のA/D変換が付いてる。
変換時間もかなり速くて、最大だと、2.125uS。

・入力は最大12チャネル(64ピン版の場合)
・サンプル&ホールド回路も内臓
・入力チャネルを、基準電圧源の「+」、「-」に切り替えが出来る
・内臓電圧リファレンス(1.45V)に切り替えできる
※1.023Vが便利だと思うが・・

経験的に、AVRより、国産のマイコン内臓のA/Dの方が、変換精度が高く、
ノイズに強いと思う。
※AVRは、サンプルホールドが無いので入力信号によっては変換誤差が大きい。
ただ、10ビットは多少物足りない、12ビットは欲しいところ。

少し意外なのは、ルネサス(日立)系では、A/D入力は、入力ポートにしか転用
出来ないものだが、RL78では、入出力に設定出来る点が、利便性が高い。

国産マイコンのA/D変換は、変換開始のトリガーを色々選べるとか、かなり細か
い設定が可能なので、クラスでそれらを全てサポートする場合は、設計が難しい。
今回は、チャネルを選んで、変換するだけの、淡白な機能しか実装していない。
※必要に応じて、メソッドを追加したいと思う。

IMG_0821s

A/D変換サンプル

RL78/G13で BMP180 温度、圧力センサーの値を読む

以前に、Amazon で買った、中華の安い Arduino 系モジュール。
I2C接続の温度、圧力センサー、BOSHのBMP180を買って、積んでいたのだけど、
気晴らしに、ちょっと動作確認をしてみた。

Arduino 系の I2C モジュールは、ピンアサインがまちまちで、以前に使った DS3231 RTC と
は違うアサインになってて、何とも言えない脱力感・・・

ネットを探すと、Arduino のスケッチが沢山見つかるので、それをコピペして、C++ のクラス
を実装した。
※必要な部分だけ浮動小数点を使い、他は整数計算で行なっているものや、全て浮動小数点で
行なっている物など、様々なスケッチ、さらに、スケッチはほぼC++なんだけど、C的に書
かれているとか、色々だった。
RL78/G13なので、なるべく計算負荷が少なくて、精度を確保してある物を切り貼りし
た。
※BMP180の、補正は、以外と複雑で難解

動かしてみると、温度は、大体合っているようなので、とりあえず、「良し」として、プッシ
ュした。

ただ、utils::format クラスでは、まだ浮動小数点の表示をサポートしていない為、結果が浮
動小数点で返ってくるものは確認していない。

IMG_0820s

BMP180 温度、圧力センサーサンプル

-----
IEEE754 のバイナリーパターンを、10進に変換する部分を独自に実装してみたい、これは、
「課題」みたいなもので、面白そうでもある。
・整数計算だけで行なう。
・「printf」で可能な表現を全て備えたい。
・コンパクトに実装したい。
以前に実装しようと試みたけど、中途になっている・・・
これにそろそろ本格的に挑まないといけない・・・

RL78/G13にVS1063をつないで音楽ファイル再生

PWMでの簡易再生は、それなりに良い音だったが、やはり不満が残る。

昔から、音楽プレイヤーを自作してみたいと思っていたが、なかなか機会が無かった。
車やバイクで音楽聴いたり、持ち歩けるタイプなど。
※売ってるものは、不満があり、買う気にならない(以前に色々買ったけど、結局、
不便なので、使わなくなった)

RL78/G13は、そのようなガジェットに丁度良く、昔にRXマイコンで実験した
VS1063を接続して、音を鳴らしてみた。

「積みIC」とゆーのが自宅に沢山あるwww、買ったけど、まだ実験もしていないも
ので、VS1001やVS1011もあった。
VS1001は古くて、制御ラインが、余分に必要みたいなので、肥やしになる事が決
定・・、VS1011は、LQFP48はキープしてあったけど、変換基板が無い。
確か、VS1011のSOP版もあったハズとかなり探したが、結局見つからない・・
仕方なく、RXマイコンで実験したVS1063を外して、今度もモジュールにした。
IMG_0816s
※最近、変換基板の表側のピンにバイパスコンデンサを付ける小技を覚えたww
※SOP版の方が配線が少なく、実験しやすい、LQFP版は、電源など沢山結線しな
いと動かないので、使いたくなかったが、SOPが見つからないので仕方なくモジュー
ルに組んだ。

VS1053は、I/O電源3.3V、コア電源1.8V、アナログ電源3.3Vが必
要で、1.8Vは、3.3Vからレギュレーターで作っている。
アナログ電源は、とりあえず、デジタル電源と共有している。(フェライトビーズを入
れてある)
本来、クリスタルは12.288MHzを使うが、手元に12MHzしか無かったので、
とりあえず、これを使う、内部設定で、補正を行なう事が出来る。

モジュールにした事で、マイコンとは、10Pのフラットケーブルで接続する、SPI
のクロックが高めなので、できるだけ短くする。

そして、ようやく接続が出来て、実験コードを書いて動かしてみる・・・
動かない・・・
RXマイコンで鳴らした事があるので、そうそう間違う事も無いと思い、色々確認する
ものの、問題無い・・・
オシロスコープで信号を確認していると、制御信号が出ていない?
結局良く調べたら、RL78/G13では、P62、P63は、出力にした場合、オー
プンドレイン専用ポート
で、ある事が判明した。
仕方なく、他のポートに繋ぎなおしてみたら、普通に鳴った・・・
※最近、くだらない理由で、「はまる」事が多いなぁー

IMG_0819s

VS1063との接続:

    ・P73/SO01 (26) ---> VS1063:SI     (29)
    ・P74/SI01 (25) ---> VS1063:SO     (30)
    ・P75/SCK01(24) ---> VS1063:SCLK   (28)
    ・P52      (35) ---> VS1063:/xCS   (23)
    ・P53      (36) ---> VS1063:/xDCS  (13) 
    ・P54      (37) ---> VS1063:/DREQ  ( 8)
    ・/RESET   ( 6) ---> VS1063:/xRESET( 3)

-----
プログラムは、鳴らすだけの機能しか実装していない。
VS1063は、色々なフォーマットに対応しているが、タグ情報をスキップするとか、
色々な細かいケアをしないと実用的には使えないので、プログラムはこれから充実させる
として、ここらで、スタート・ボードの設計なども進めておかないと・・

プロジェクト・ソース・コード

RL78/G13でSDカードの速度比較

SDC_sample プロジェクトで、単純な空読みと書き込みで、どのくらいの
速度が出ているのか調べた。

メーカーや種類によってかなり違いがある。
※読み込むサイズは512バイト、これ以上大きい場合は、RL78の
RAMサイズから考えてあまり実用的では無いと思える。

WAVプレイヤーでは、読み込みで200キロバイト以下のカードでは、
16ビット、44.1KHz、ステレオファイルの再生は、ほぼ無理の
よう。
※300キロバイト近くないと十分とは言えない。
※1GB、8GBのカードは、十分使えた。

256MBのSDカード(Panasonic)

SD Write test...
Write frame: 739
Write: 85134 Bytes/Sec
Write: 83 KBytes/Sec
SD Read test...
Read frame: 186
Read: 338250 Bytes/Sec
Read: 330 KBytes/Sec

1GBのSDカード(Transcend 60x)

SD Write test...
Write frame: 214
Write: 293993 Bytes/Sec
Write: 287 KBytes/Sec
SD Read test...
Read frame: 225
Read: 279620 Bytes/Sec
Read: 273 KBytes/Sec

2GBのSDカード(Transcend class ?)

SD Write test...
Write frame: 954
Write: 65948 Bytes/Sec
Write: 64 KBytes/Sec
SD Read test...
Read frame: 309
Read: 203606 Bytes/Sec
Read: 198 KBytes/Sec

8GBのSDカード(Transcend class 6)

SD Write test...
Write frame: 541
Write: 116293 Bytes/Sec
Write: 113 KBytes/Sec
SD Read test...
Read frame: 180
Read: 349525 Bytes/Sec
Read: 341 KBytes/Sec

32GBのSDカード(FlashAir)

SD Write test...
Write frame: 583
Write: 107915 Bytes/Sec
Write: 105 KBytes/Sec
SD Read test...
Read frame: 347
Read: 181309 Bytes/Sec
Read: 177 KBytes/Sec

32GBのSDカード(ノーブランド class 10)

SD Write test...
Write frame: 417
Write: 150874 Bytes/Sec
Write: 147 KBytes/Sec
SD Read test...
Read frame: 212
Read: 296766 Bytes/Sec
Read: 289 KBytes/Sec

IMG_0815s

RL78/G13でWAVファイルのPWM再生

SDカードとPWMが出来たら、定番のWAV再生を行わない理由は無い。

また、SDカードアクセスのパフォーマンスを測る指針ともなる。

以前にR8Cで、トライした時は、色々な問題にぶつかって、実用性が薄い事
から、あまり深く掘り下げなかった。
・R8Cでは、UARTとSPIが共有している為、どちらか片方しか、利用
する事が出来ず、不満が残る。
※SPIをハードで行い、UARTをソフト処理する事も考えられるが、受信
動作は困難と思われる。
・R8CのPWMでは、コンペアレジスターがバッファされていない為、書き
込んだタイミングと、前の値との組み合わせにより、グリッチが発生する、そ
の為、「プツプツ」とノイズが気になる。

結局、SPIをソフトで処理して、実装してみたが、11.025KHz、8
ビット、ステレオが限界だった・・
これは、かなり微妙な結果だと言うしかない、UARTを諦めて、SPIをハ
ードで扱う事も考えたが、プツプツと発生するノイズ、PWMの仕様上の問題
をナチュラルに解決する方法を思いつけなかったので、中途半端だったが諦め
た。

RL78では、その全てを改善できるであろう事が判っていた、8ビットの
PWM変調に起因する音質以外は、ほぼ満足なものとなると思われる。

早速実装して、音を出してみたら、思った通りの結果だった、PWMのレジス
タ書き換えに起因するノイズも聞こえない、(RL78では、バッファされて
いる)48KHz、16ビット、ステレオのファイルも、難なく再生出来た。
※16ビットの下位8ビットは捨てている。
※つまり、他の処理も考え合わせると、ゆうに200キロバイト毎秒以上の
読み込み速度が出ていると思われる。

※SDカードの速度は次のブログを参照

-----
PWM周期は、8ビットの分解能が必要なので、カウンタのクロックを
16MHzとして、256で割った、62.5KHzとした。
これで、一応48KHzのサンプリング・レートに対応できる。

多少難しい問題として、PWMのサンプルレート、62.5KHzと、ファイル
のサンプリングをどのようにマッチさせるか、この微妙な周期の違いを、簡潔に
解決する方法を考慮する必要がある。
62.5KHz毎に起動する割り込みで、波形値をバッファから取り出して、
PWMのコンペアレジスタに設定している。
バッファのポインター移動は、サンプリング周期/62.5KHzの分数で行い、
小数点以下の誤差が全く出ないように工夫した。
※簡単な整数計算だけで行なえるので、シンプル。

    device::TAU01::TDRL = buff_[pos_ + l_ofs_] + wofs_;
    device::TAU02::TDRL = buff_[pos_ + r_ofs_] + wofs_;
    inc_ += rate_;
    if(inc_ >= 6250) {
        inc_ -= 6250;
        pos_ += skip_;
        pos_ &= 1024 - 1;
    }

分数計算で、分子が、分母(6250)を超えたら、テーブルのポインターを進
める、また、分子から、6250を引く。
・6250は、62.5KHzの1/10で、「rate_」は、波形ファイルのサン
プリング周波数を1/10にしてある。
※つまり、48KHzなら4800、44.1KHzなら4410、
22.05KHzなら2205となる。
・1/10にするのは、計算レンジを16ビット以内に納まるようにする為の工夫。
・「skip_」は、8ビットモノラルなら「1」、8ビットステレオなら「2」、
16ビットモノラルは「2」、16ビットステレオなら「4」にする。
・8ビットファイルの場合、無音は「0x80」だが、16ビットファイルでは、
無音は「0x0000」となるので「wofs_」で調整する。
・WAVファイルは、リトルエンディアンなので、「l_ofs_、r_ofs_」で、掴む
位置を微調整する。
・バッファサイズは、SDカードの読み込みでは、512バイトの倍数が効率が
良いようなので、ピンポンバッファにする為、倍の1Kバイトとした。

-----
PWM出力は、適当なローパスフィルターを通す事で、アナログ出力を得られる。
今回は、2Kオームと、0.01uFのネットワークとした。
少し贅沢ではあるけども、フルスイング・オペアンプを使って、バッファーを組ん
でみたが、オペアンプを使わず、大きめのカップリングコンデンサを入れただけの
回路でも、問題無いだろう。
※RL78がリセット状態や、停止中は、出力に直流が乗るので注意。
IMG_0814s

・ターミナルからのコマンドで WAV ファイルを再生する。
・「dir」ディレクトリーリスト
・「play file-name」再生
・「play *」カード内の WAV 形式ファイルを全て再生
・再生中、「<」曲の先頭に戻る、「>」次の曲
・再生中「SPACE」を押す毎に、一時停止、再開
rl78_wav_play

※この写真は、オペアンプを使っていないRCフィルター
IMG_0813s

RL78/G13 WAV file player サンプル

参考回路とKiCADのプロジェクト:
WAV_Player KiCAD Project

WAV_Player_Sample

RL78/G13でPWM出力を出してみる

インターバル・タイマーの次は、PWM出力。

少し悩んだのは、少し構成が複雑になるので、どのようなAPIにするのが良いのか
・・・

RL78では、PWMを使う場合、マスターと、スレーブの2つのチャネルを組み合
わせる必要がある点が、少し厄介な為で、結局、PWMの設定関数は、テンプレート
関数とした、テンプレートの引数は、マスターチャネルのTAUを使う。

typedef device::tau_io<device::TAU00> master;
master master_;
device::tau_io pwm1_;
device::tau_io pwm2_;

bool init_pwm_()
{
    uint8_t intr_level = 0;
    if(!master_.start_interval(100000, intr_level)) {
        return false;
    }
    if(!pwm1_.start_pwm<master::tau_type>(0, intr_level)) {
        return false;
		}
    if(!pwm2_.start_pwm<master::tau_type>(0, intr_level)) {
        return false;
    }
    return true;
}

このサンプルでは、TAU01、TAU02をそれぞれPWM出力としている。
PWMの周期は、TAU0を使い、サンプルでは、100KHzとしている。
「TAU01」は、TO01(P16)40番ピン
「TAU02」は、TO02(P17)39番ピン

    auto val = master_.get_value();  // マスターチャネルのカウント最大値
    pwm1_.set_value(val / 4);  // PWM Duty 25%
    pwm2_.set_value(val * 3 / 4);  // PWM Duty 75%

サンプルでは、それぞれ、25%と75%のディーティーとしている。

IMG_0812s

PWMサンプル