RX66T、RX72Tのオーバークロック

RX66T、RX72T について

  • RX66T は最大 160MHz
  • RX72T は最大 200MHz
  • 共に RXv3 コア(DFPU は内蔵しない)

同じ RXv3 コアの RX72N、RX72M などは最大 240MHz 動作となっている。

  • RX66T、RX72T は、主にモーター制御などに特化したデバイスで、高クロックで MTU、GPTW などのタイマーを駆動出来る。
  • また、タイマー出力を微妙に遅延させて、より細かい PWM 波形を作る事が出来る機能を内蔵する。
  • CAN を内蔵する事から、ハイブリッドや電気自動車のコントローラーとして需要が大きいのかもしれない。

RX66T は RXv3 コアとして初めての製品なので、160MHz と言う能力は何となく判るが、同時期に出た RX72T の 200MHz は何故なのか疑問を持っていた。
モーター制御としては、下位に RX24T(80MHz) などがあり、それに比べて能力が格段に上がっている。

周波数が高ければ、1個のデバイスで複数のモーターを同時にケア出来る。

普通に考えて、RXv3 コアは共通なのだから、RX66T や RX72T 用に専用のコアを設計する事は考えにくい。
RX66T は、RX72T の選別漏れでは無いかと思っている。(周波数以外は機能は同じ)
多分中身のコアベースは、RX72N と遜色無いのだろうと思える。
ただ、動作周波数が最大 120MHz のRX66N(RX72N の低速版)があり、RX72N として作ったが、選別で落ちて、低速版として再利用しているのは考えられるので、一概に、動作周波数を制限しているのかは、何とも言えない部分でもある。


オーバークロックしてみる

自分の C++ フレームワークでは、クロック設定は、「clock_profile.hpp」に、希望のクロックテーブルを実装すれば、自動で設定されるようにしてある。
SCI、CAN、I2C、タイマーの周期なども、各クラスが、「clock_profile」の設定を継承して、各クラス内で自動で計算するので、気にする必要は無いよう工夫されている。

そこで、まず、RX66T をオーバークロックしてみた。

少しづつ上げて、レイトレースプログラムで実験してみた(浮動小数点などの計算がかなり含まれる)。

結果から言うと、普通に 240MHz で動作するようだー

namespace device {

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    /*!
        @brief  クロック・プロファイル・クラス @n
                ・分周器の仕様を超える値を指定しない事 @n
                ・PLL_BASE は、0.5 倍単位 @n
                ・他は、PLL_BASE を基数とする整数除算値 @n
                ・詳細はハードウェアーマニュアル参照の事
    */
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    class clock_profile {
    public:
    #if defined(USE_USB)
        static constexpr bool       TURN_USB    = true;             ///< USB を使う場合「true」
        static constexpr uint32_t   BASE        =  12'000'000;        ///< 外部接続クリスタル
        static constexpr uint32_t   PLL_BASE    = 144'000'000;        ///< PLL ベースクロック(最大160MHz)

        static constexpr uint32_t   ICLK        = 144'000'000;        ///< ICLK 周波数(最大160MHz)
        static constexpr uint32_t   PCLKA       =  72'000'000;        ///< PCLKA 周波数(最大120MHz)
        static constexpr uint32_t   PCLKB       =  36'000'000;        ///< PCLKB 周波数(最大60MHz)
        static constexpr uint32_t   PCLKC       = 144'000'000;        ///< PCLKC 周波数(最大160MHz)
        static constexpr uint32_t   PCLKD       =  36'000'000;        ///< PCLKD 周波数(最大60MHz)
        static constexpr uint32_t   FCLK        =  36'000'000;        ///< FCLK 周波数(最大60MHz)
        static constexpr uint32_t   BCLK        =  36'000'000;        ///< BCLK 周波数(最大60MHz)
    #else
        static constexpr bool       TURN_USB    = false;            ///< USB を使う場合「true」
        static constexpr uint32_t   BASE        =  10'000'000;        ///< 外部接続クリスタル
#if 0
        static constexpr uint32_t   PLL_BASE    = 160'000'000;        ///< PLL ベースクロック(最大160MHz)

        static constexpr uint32_t   ICLK        = 160'000'000;        ///< ICLK 周波数(最大160MHz)
        static constexpr uint32_t   PCLKA       =  80'000'000;        ///< PCLKA 周波数(最大120MHz)
        static constexpr uint32_t   PCLKB       =  40'000'000;        ///< PCLKB 周波数(最大60MHz)
        static constexpr uint32_t   PCLKC       = 160'000'000;        ///< PCLKC 周波数(最大160MHz)
        static constexpr uint32_t   PCLKD       =  40'000'000;        ///< PCLKD 周波数(最大60MHz)
        static constexpr uint32_t   FCLK        =  40'000'000;        ///< FCLK 周波数(最大60MHz)
        static constexpr uint32_t   BCLK        =  40'000'000;        ///< BCLK 周波数(最大60MHz)
#else
        // Over clock... 動く、動くぞ・・・
        static constexpr uint32_t   PLL_BASE    = 240'000'000;        ///< PLL ベースクロック(最大160MHz)

        static constexpr uint32_t   ICLK        = 240'000'000;        ///< ICLK 周波数(最大160MHz)
        static constexpr uint32_t   PCLKA       = 120'000'000;        ///< PCLKA 周波数(最大120MHz)
        static constexpr uint32_t   PCLKB       =  60'000'000;        ///< PCLKB 周波数(最大60MHz)
        static constexpr uint32_t   PCLKC       = 120'000'000;        ///< PCLKC 周波数(最大160MHz)
        static constexpr uint32_t   PCLKD       =  60'000'000;        ///< PCLKD 周波数(最大60MHz)
        static constexpr uint32_t   FCLK        =  60'000'000;        ///< FCLK 周波数(最大60MHz)
        static constexpr uint32_t   BCLK        =  60'000'000;        ///< BCLK 周波数(最大60MHz)
#endif
#endif
    };
}
RX66T Start for Ray Trace: 320, 240
# Render time: 371ms (1)

続いて、RX72T、こちらも、問題無く動くw

namespace device {

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    /*!
        @brief  クロック・プロファイル・クラス @n
                ・分周器の仕様を超える値を指定しない事 @n
                ・PLL_BASE は、0.5 倍単位 @n
                ・他は、PLL_BASE を基数とする整数除算値 @n
                ・詳細はハードウェアーマニュアル参照の事
    */
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    class clock_profile {
    public:
#if 0
#ifdef USE_USB
        static constexpr bool       TURN_USB    = true;             ///< USB を使う場合「true」
        static constexpr uint32_t   BASE        =  16'000'000;        ///< 外部接続クリスタル
        static constexpr uint32_t   PLL_BASE    = 192'000'000;        ///< PLL ベースクロック(最大200MHz)

        static constexpr uint32_t   ICLK        = 192'000'000;        ///< ICLK 周波数(最大200MHz)
        static constexpr uint32_t   PCLKA       =  96'000'000;        ///< PCLKA 周波数(最大120MHz)
        static constexpr uint32_t   PCLKB       =  48'000'000;        ///< PCLKB 周波数(最大60MHz)
        static constexpr uint32_t   PCLKC       = 192'000'000;        ///< PCLKC 周波数(最大200MHz)
        static constexpr uint32_t   PCLKD       =  48'000'000;        ///< PCLKD 周波数(最大60MHz)
        static constexpr uint32_t   FCLK        =  48'000'000;        ///< FCLK 周波数(最大60MHz)
        static constexpr uint32_t   BCLK        =  48'000'000;        ///< BCLK 周波数(最大60MHz)
#else
        static constexpr bool       TURN_USB    = false;            ///< USB を利用しない場合「false」
        static constexpr uint32_t   BASE        =  16'000'000;        ///< 外部接続クリスタル
        static constexpr uint32_t   PLL_BASE    = 200'000'000;        ///< PLL ベースクロック

        static constexpr uint32_t   ICLK        = 200'000'000;        ///< ICLK 周波数
        static constexpr uint32_t   PCLKA       = 100'000'000;        ///< PCLKA 周波数
        static constexpr uint32_t   PCLKB       =  50'000'000;        ///< PCLKB 周波数
        static constexpr uint32_t   PCLKC       = 200'000'000;        ///< PCLKC 周波数
        static constexpr uint32_t   PCLKD       =  50'000'000;        ///< PCLKD 周波数
        static constexpr uint32_t   FCLK        =  50'000'000;        ///< FCLK 周波数
        static constexpr uint32_t   BCLK        =  50'000'000;        ///< BCLK 周波数
#endif
#else
        static constexpr bool       TURN_USB    = true;             ///< USB を使う場合「true」
        static constexpr uint32_t   BASE        =  16'000'000;        ///< 外部接続クリスタル
        static constexpr uint32_t   PLL_BASE    = 240'000'000;        ///< PLL ベースクロック(最大200MHz)

        static constexpr uint32_t   ICLK        = 240'000'000;        ///< ICLK 周波数(最大200MHz)
        static constexpr uint32_t   PCLKA       = 120'000'000;        ///< PCLKA 周波数(最大120MHz)
        static constexpr uint32_t   PCLKB       =  60'000'000;        ///< PCLKB 周波数(最大60MHz)
        static constexpr uint32_t   PCLKC       = 240'000'000;        ///< PCLKC 周波数(最大200MHz)
        static constexpr uint32_t   PCLKD       =  60'000'000;        ///< PCLKD 周波数(最大60MHz)
        static constexpr uint32_t   FCLK        =  60'000'000;        ///< FCLK 周波数(最大60MHz)
        static constexpr uint32_t   BCLK        =  60'000'000;        ///< BCLK 周波数(最大60MHz)
#endif
    };
}
RX72T Start for Ray Trace: 320, 240
# Render time: 371ms (1)

実用になるのか?

スペックを超えて動作させるのは、現場では決して行わないが、アマチュアの遊びとしては、それなりに面白い。

現在、デバイスの入手性が極めて悪く、RX72T、RX72N、RX72M などはほぼ入手が出来ない状況となっている。
RX66T については、多少割高だが入手出来るようだ。(自分が買った時の倍近い)
※RX66T と RX72T は値段の差が少ないので(以前、潤沢にデバイスが買えた時期には、逆転現象もあった)、RX72T 一択となるだろうと思える。

まだ、タイマーなど、高クロックで駆動するペリフェラルを評価していないので何とも言えない部分もあるし、連続で動かしている時に停止するとか、色々なアクシデントはあるかもしれないが、とりあえず、動作は確認出来た。

周波数を制限する要因が何なのか、想像でしか無い為、非常にグレーな部分が多いものの、240MHz で動くなら、色々と有利な面も多い。

最近の半導体は、昔に比べて、マージンが大きいし、基本的なスペックは、元々の能力では無く、営業的な側面から決められている事も考えると、動いて当たり前なのかもしれない。

自分としては、低価格で購入でき、高性能な RXxxT シリーズは前から好きなので、これからもこのシリーズには注力したいと思う。


それにしても半導体不足はいつまで続くのか・・・

RXマイコンGUI関係更新

GUI 更新

  • 本当は、GUI の前に、優先度が高いタスクが色々あるのだが・・・
  • 気軽に実装出来るのが「要」なので、色々修正、追加を行った。
  • ソースコードを精査すると、何でこんな実装になってるの?(自分で実装したのに)部分もあり、修正した。
  • GUI Widget は、プリミティブの組み合わせで描画するので、新規に何か作る場合、見た目や操作性を踏まえて修正が続く。
  • 描画は、ソフトレンダーと DRW2D エンジンを選べるが、バグがあり、その修正も行った。
  • 追加した widget は、「スピンボックス」、「トグルスイッチ」、「プログレスバー」となっている。
  • 同時に GUI_sample で実装も追加して、機能を試している。(もうそろそろ画面が一杯になった感じ・・)
  • まだ足りない物があると思うが、これくらいの種類があれば、アプリを作る場合に困らないと思える。

スピンボックス(spinbox.hpp)

  • 範囲の決まった数値を増減する機能を提供する。
  • 「長押し」で増減が加速するようにしたので、そこそこ大きい範囲でも設定出来る。
  • 他の widget とは異なり、フレームレスにしているが、やはり無いと統一性が無いので、どうするか検討中・・
  • 増減は、ボックスの左側、又は右側押すのだが、サインが、小さい四角なので、そこも甘い。
  • 三角を描画するには、描画 API を追加する必要があるので、とりあえず四角にしている。

トグルスイッチ(toggle.hpp)

  • 実際は「スライドスイッチ」だが、「トグル」の方が馴染みが良いと思ったので「toggle クラス」とした。
  • この widget は「チェックボックス」と同等の機能だが、見た目や動作がモダンなので、必要と考えた。
  • 実装は、そんなに複雑な部分は無いが、見た目や動作を考えて、試行錯誤した。

プログレスバー(progress.hpp)

  • 実装は、表示のみなので簡単だった。
  • 基本的に、輝度のみで状態を示すので、動かしてみて、吟味はした。

全体の見直し

  • widget_director クラスや、前に実装した widget も見直して、気にくわない部分を修正した。
  • API の名称なども、間際らしい部分があり、色々考えて変更した。

drw2d_mgr クラスの修正

  • フォントの描画で、クリッピング領域を設定する部分にバグがあり、修正した。
  • この修正で、ソフトレンダリングと drw2d エンジンによる描画がほぼ切り替えても同じような見た目になった。
  • 実際は、アンチエリアスの表現などが異なり、完全に一致しない。
  • drw2d エンジンによる描画の方が品質が高いので、ソフトレンダリングもモディファイしないとならない・・・

まとめ

  • GUI Widget 関係のドキュメント(使い方や仕様)が不十分なので、この辺りも強化が必要と感じている。
  • ただ、「GUI_sample/main.cpp」を観れば、使い方は判ると思う。
  • 現状では、GUI Widget の配置ツールが無いが、C++ 11 以降 constexpr などの機能を使えば、かなり複雑な配置でも精妙に出来るので、自分としては必要性を感じない。
  • widget の応答についても、「ラムダ式」で実装して、シンプルに出来るように配慮してある。
  • 組み込み機器で C 言語ベースの GUI ライブラリを使っている人が本当に気の毒でならない。(今時、良く C 言語で作るよなぁー)
  • 下に示したコードが全て、widget の表示とそれに伴う動作に必要な実装のみ、これで全てとなっている。

GUI サンプル、widget の定義:

    typedef gui::button BUTTON;
    BUTTON      button_(vtx::srect(10, 10, 80, 32), "Button");
    BUTTON      button_stall_(vtx::srect(100, 10, 80, 32), "Stall");
    typedef gui::check CHECK;
    CHECK       check_(vtx::srect(   10, 10+50, 0, 0), "Check");  // サイズ0指定で標準サイズ
    typedef gui::group<3> GROUP3;
    GROUP3      group_(vtx::srect(   10, 10+50+40, 0, 0));
    typedef gui::radio RADIO;
    RADIO       radioR_(vtx::srect(   0, 40*0, 0, 0), "Red");
    RADIO       radioG_(vtx::srect(   0, 40*1, 0, 0), "Green");
    RADIO       radioB_(vtx::srect(   0, 40*2, 0, 0), "Blue");
    typedef gui::slider SLIDER;
    SLIDER      sliderh_(vtx::srect(200, 20, 200, 0), 0.5f);
    SLIDER      sliderv_(vtx::srect(460, 20, 0, 200), 0.0f);
    typedef gui::menu MENU;
    MENU        menu_(vtx::srect(120, 70, 100, 0), "ItemA,ItemB,ItemC,ItemD");
    typedef gui::text TEXT;
    TEXT        text_(vtx::srect(240, 70, 150, 20), "16ピクセル漢字の表示サンプル~");
    typedef gui::textbox TEXTBOX;
    TEXTBOX     textbox_(vtx::srect(240, 100, 160, 80), "");
    typedef gui::spinbox SPINBOX;
    SPINBOX     spinbox_(vtx::srect(20, 220, 120, 0),
                    { .min = -100, .value = 0, .max = 100, .step = 1, .accel = true });
    typedef gui::toggle TOGGLE;
    TOGGLE      toggle_(vtx::srect(160, 220, 0, 0));
    typedef gui::progress PROGRESS;
    PROGRESS    progress_(vtx::srect(240, 220, 150, 0));

    float       progress_ratio_ = 0.0f;

GUI widget の応答部分:

    void setup_gui_()
    {
        button_.enable();
        button_.at_select_func() = [=](uint32_t id) {
            utils::format("Select Button: %d\n") % id;
            if(button_stall_.get_state() == BUTTON::STATE::STALL) {
                button_stall_.set_state(BUTTON::STATE::ENABLE);
                button_stall_.set_title("Active");
            } else if(button_stall_.get_state() == BUTTON::STATE::ENABLE) {
                button_stall_.set_state(BUTTON::STATE::STALL);
                button_stall_.set_title("Stall");
            }
        };
        button_stall_.enable();
        button_stall_.set_state(BUTTON::STATE::STALL);

        check_.enable();
        check_.at_select_func() = [=](bool ena) {
            utils::format("Select Check: %s\n") % (ena ? "On" : "Off");
            if(ena) {
                radioR_.set_base_color(DEF_COLOR::White);
                radioG_.set_base_color(DEF_COLOR::White);
                radioB_.set_base_color(DEF_COLOR::White);
                radioR_.set_font_color(DEF_COLOR::White);
                radioG_.set_font_color(DEF_COLOR::White);
                radioB_.set_font_color(DEF_COLOR::White);
            }
        };

        // グループにラジオボタンを登録
        group_ + radioR_ + radioG_ + radioB_;
        group_.enable();  // グループ登録された物が全て有効になる。
        radioR_.at_select_func() = [=](bool ena) {
            utils::format("Select Red: %s\n") % (ena ? "On" : "Off");
            if(ena) {
                radioR_.set_base_color(DEF_COLOR::Red);
                radioG_.set_base_color(DEF_COLOR::Red);
                radioB_.set_base_color(DEF_COLOR::Red);
                radioR_.set_font_color(DEF_COLOR::Red);
                radioG_.set_font_color(DEF_COLOR::Red);
                radioB_.set_font_color(DEF_COLOR::Red);
            }
        };
        radioG_.at_select_func() = [=](bool ena) {
            utils::format("Select Green: %s\n") % (ena ? "On" : "Off");
            if(ena) {
                radioR_.set_base_color(DEF_COLOR::Green);
                radioG_.set_base_color(DEF_COLOR::Green);
                radioB_.set_base_color(DEF_COLOR::Green);
                radioR_.set_font_color(DEF_COLOR::Green);
                radioG_.set_font_color(DEF_COLOR::Green);
                radioB_.set_font_color(DEF_COLOR::Green);
            }
        };
        radioB_.at_select_func() = [=](bool ena) {
            utils::format("Select Blue: %s\n") % (ena ? "On" : "Off");
            if(ena) {
                radioR_.set_base_color(DEF_COLOR::Blue);
                radioG_.set_base_color(DEF_COLOR::Blue);
                radioB_.set_base_color(DEF_COLOR::Blue);
                radioR_.set_font_color(DEF_COLOR::Blue);
                radioG_.set_font_color(DEF_COLOR::Blue);
                radioB_.set_font_color(DEF_COLOR::Blue);
            }
        };
        radioG_.exec_select();  // 最初に選択されるラジオボタン

        sliderh_.enable();
        sliderh_.at_select_func() = [=](float val) {
            utils::format("Slider H: %3.2f\n") % val;
        };
        sliderv_.enable();
        sliderv_.at_select_func() = [=](float val) {
            utils::format("Slider V: %3.2f\n") % val;
        };

        menu_.enable();
        menu_.at_select_func() = [=](uint32_t pos, uint32_t num) {
            char tmp[32];
            menu_.get_select_text(tmp, sizeof(tmp));
            utils::format("Menu: '%s', %u/%u\n") % tmp % pos % num;
        };

        text_.enable();

        textbox_.enable();
        textbox_.set_title("(1) 項目\n(2) GUI サンプルについて。\n(3) まとめ");
        textbox_.set_vertical_alignment(TEXTBOX::V_ALIGNMENT::CENTER);

        spinbox_.enable();
        spinbox_.at_select_func() = [=](SPINBOX::TOUCH_AREA area, int16_t value) {
            static const char* st[3] = { "Minus", "Stay", "Plus" };
            utils::format("Spinbox: %s Value: %d\n")
                % st[static_cast<uint8_t>(area)] % value;
        };

        toggle_.enable();
        toggle_.at_select_func() = [=](bool state) {
            utils::format("Toggle: %s\n") % (state ? "OFF" : "ON");
            if(!state) {
                progress_ratio_ = 0.0f;
            }
        };

        progress_.enable();
        progress_.at_update_func() = [=](float ratio) {
            if(toggle_.get_switch_state()) {
                ratio += 1.0f / 120.0f;  // 2 sec
                if(ratio > 1.0f) ratio = 1.0f;
            } else {
                ratio = 0.0f;
                progress_ratio_ = 0.0f;
            }
            return ratio;
        };
    }

GUI_sample

久しぶりに format クラスを更新

format クラスの見直し

  • format クラスは、組み込みマイコン用に、危険な printf を置き換える為に、boost::format の縮小版のようなノリでコツコツ実装してきた。
  • 組み込みマイコンで C++ を使う場合に、重宝するものと思う。
  • 組み込みマイコンでは、リソースの問題で、iostream などを使う事が難しい。
  • かと言って、C++ で printf を使うのも気が引ける。
  • printf は可変引数を使っているので、致命的な欠点を持っている。
  • 通常、組み込みマイコンを使った製品では、内部で printf を使う事はない。
  • 自前 format クラスは、printf を使うよりコンパクトになるものと思う。
  • 細かい部分を見直し、常に品質を向上するようにしている。
  • 今まで、%g の対応をしていなかったので、今回は、それに注力した。
  • テストケースも同時にアップデートしてより広範囲に仕様を満足するようにした。

浮動小数点の扱い

  • printf の場合、浮動小数点は、内部的には double 扱いになっている。
  • format クラスは、リソースを節約する為、float 扱いだが、有効桁が8桁くらいなら精度も問題なく運用出来ると思う。
  • float は IEEE-754 32 ビットフォーマットとなっている。

何と言っても簡単に使える

  • format クラスは、「format.hpp」のヘッダーのみで、インクルードするだけで使える。
  • ライブラリのリンクも必要無い。
  • 名前空間として「utils」を使っている。
  • boost::format は、フォームとパラメーターが食い違う場合、例外を投げる、自前 format は、内部でエラーコードで対応している。
  • C++ のオペレーター機能を使い、パラメーターを与えているので、安全で、printf に近いコンビニエンス性がある。
#include "format.hpp"

int main()
{
    float value = 1.234f;
    utils::format("Value: %4.3f\n") % value;
}
Value: 1.234

拡張機能

  • 拡張機能として、二進表示「%b」を追加してある。
  • ポインターのアドレスを表示する場合「%p」を使う。

標準出力

  • format は、標準出力として、stdout を使う。
  • 組み込みマイコンでは、write 関数に対して、stdout のハンドルを使い出力する。
  • RX マイコンでは、syscalls.c にその実装があり、内部で put_char 関数に文字を出力するようになっている。
  • メイン部などで、put_char 関数を "C" 用に extern しておいて、その関数から、SCI などに送れば、シリアル出力できる。

他の使い方

    typedef basic_format<stdout_buffered_chaout<256> > format;
    typedef basic_format<stdout_chaout> nformat;
    typedef basic_format<memory_chaout> sformat;
    typedef basic_format<null_chaout> null_format;
    typedef basic_format<size_chaout> size_format;

上記のような「typedef」があり、文字列出力の他、サイズだけ取得するなど、色々な応用が出来る。

※通常、format は小さなバッファを通して、標準出力しているので、「改行」を送らない場合、明示的に「flush」を呼んで、バッファに残った文字を掃き出す必要がある。

今回のアップデートでは、%g(有効桁自動表示)対応がメイン

長い間、浮動小数点の「%g」(自動)フォームに対応していなかったので、それに対応した。
※「Test20」がその検査にあたる。

まだ、テストケースが不十分な感じがするので、バグがあるものと思うが、とりあえず大丈夫そうなので、Github にプッシュした。

Github: format_class

テストケースは、以下のように20パターンあるけど、まだ足りないので、追々追加して、強固なものにしようと思う。

Test01, output buffer size check: (0)  Ref: '0123456789' <-> Res: '0123456'  Pass.
Test02(0), decimal check. Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
Test02(1), decimal check. Ref: 'form=-12345678' <-> Res: 'form=-12345678'  Pass.
Test02(2), decimal check. Ref: 'form=     12345678' <-> Res: 'form=     12345678'  Pass.
Test02(3), decimal check. Ref: 'form=    -12345678' <-> Res: 'form=    -12345678'  Pass.
Test02(4), decimal check. Ref: 'form=000012345678' <-> Res: 'form=000012345678'  Pass.
Test02(5), decimal check. Ref: 'form=-00012345678' <-> Res: 'form=-00012345678'  Pass.
Test02(6), decimal check. Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
Test02(7), decimal check. Ref: 'form=-12345678' <-> Res: 'form=-12345678'  Pass.
Test02(8), decimal check. Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
Test02(9), decimal check. Ref: 'form=-12345678' <-> Res: 'form=-12345678'  Pass.
Test03(0), octal check. Ref: 'form=1245667' <-> Res: 'form=1245667'  Pass.
Test03(1), octal check. Ref: 'form=   1245667' <-> Res: 'form=   1245667'  Pass.
Test03(2), octal check. Ref: 'form=001245667' <-> Res: 'form=001245667'  Pass.
Test03(3), octal check. Ref: 'form=1245667' <-> Res: 'form=1245667'  Pass.
Test03(4), octal check. Ref: 'form=1245667' <-> Res: 'form=1245667'  Pass.
Test04(0), binary check. Ref: 'form=10101110' <-> Res: 'form=10101110'  Pass.
Test04(1), binary check. Ref: 'form=    10101110' <-> Res: 'form=    10101110'  Pass.
Test04(2), binary check. Ref: 'form=0000010101110' <-> Res: 'form=0000010101110'  Pass.
Test04(3), binary check. Ref: 'form=10101110' <-> Res: 'form=10101110'  Pass.
Test04(4), binary check. Ref: 'form=10101110' <-> Res: 'form=10101110'  Pass.
Test05(0), hex-dedcimal check. Ref: 'form=12a4bf9c' <-> Res: 'form=12a4bf9c'  Pass.
Test05(1), hex-dedcimal check. Ref: 'form=  12a4bf9c' <-> Res: 'form=  12a4bf9c'  Pass.
Test05(2), hex-dedcimal check. Ref: 'form=012a4bf9c' <-> Res: 'form=012a4bf9c'  Pass.
Test05(3), hex-dedcimal check. Ref: 'form=12a4bf9c' <-> Res: 'form=12a4bf9c'  Pass.
Test05(4), hex-dedcimal check. Ref: 'form=12a4bf9c' <-> Res: 'form=12a4bf9c'  Pass.
Test05(5), hex-dedcimal check. Ref: 'form=12A4BF9C' <-> Res: 'form=12A4BF9C'  Pass.
Test05(6), hex-dedcimal check. Ref: 'form=  12A4BF9C' <-> Res: 'form=  12A4BF9C'  Pass.
Test05(7), hex-dedcimal check. Ref: 'form=012A4BF9C' <-> Res: 'form=012A4BF9C'  Pass.
Test05(8), hex-dedcimal check. Ref: 'form=12A4BF9C' <-> Res: 'form=12A4BF9C'  Pass.
Test05(9), hex-dedcimal check. Ref: 'form=12A4BF9C' <-> Res: 'form=12A4BF9C'  Pass.
Test06(0), positive decimal check. Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
Test06(1), positive decimal check. Ref: 'form=4282621618' <-> Res: 'form=4282621618'  Pass.
Test06(2), positive decimal check. Ref: 'form=     12345678' <-> Res: 'form=     12345678'  Pass.
Test06(3), positive decimal check. Ref: 'form=   4282621618' <-> Res: 'form=   4282621618'  Pass.
Test06(4), positive decimal check. Ref: 'form=000012345678' <-> Res: 'form=000012345678'  Pass.
Test06(5), positive decimal check. Ref: 'form=004282621618' <-> Res: 'form=004282621618'  Pass.
Test06(6), positive decimal check. Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
Test06(7), positive decimal check. Ref: 'form=4282621618' <-> Res: 'form=4282621618'  Pass.
Test06(8), positive decimal check. Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
Test06(9), positive decimal check. Ref: 'form=4282621618' <-> Res: 'form=4282621618'  Pass.
Test07(0), floating point check. Ref: 'form=1.006250' <-> Res: 'form=1.006250'  Pass.
Test07(1), floating point check. Ref: 'form=-1.006250' <-> Res: 'form=-1.006250'  Pass.
Test07(2), floating point check. Ref: 'form=1.006250' <-> Res: 'form=1.006250'  Pass.
Test07(3), floating point check. Ref: 'form=-1.006250' <-> Res: 'form=-1.006250'  Pass.
Test07(4), floating point check. Ref: 'form=1.006250' <-> Res: 'form=1.006250'  Pass.
Test07(5), floating point check. Ref: 'form=-1.006250' <-> Res: 'form=-1.006250'  Pass.
Test07(6), floating point check. Ref: 'form=1.0063' <-> Res: 'form=1.0063'  Pass.
Test07(7), floating point check. Ref: 'form=-1.0063' <-> Res: 'form=-1.0063'  Pass.
Test07(8), floating point check. Ref: 'form=1.0063' <-> Res: 'form=1.0063'  Pass.
Test07(9), floating point check. Ref: 'form=-1.0063' <-> Res: 'form=-1.0063'  Pass.
Test07(10), floating point check. Ref: 'form=     1' <-> Res: 'form=     1'  Pass.
Test07(11), floating point check. Ref: 'form=    -1' <-> Res: 'form=    -1'  Pass.
Test08(0), floating point (exponent) check. Ref: 'form=1.025001e+05' <-> Res: 'form=1.025001e+05'  Pass.
Test08(1), floating point (exponent) check. Ref: 'form=3.250000e-08' <-> Res: 'form=3.250000e-08'  Pass.
Test08(2), floating point (exponent) check. Ref: 'form=-1.075001e+05' <-> Res: 'form=-1.075001e+05'  Pass.
Test08(3), floating point (exponent) check. Ref: 'form=-6.250000e-08' <-> Res: 'form=-6.250000e-08'  Pass.
Test08(4), floating point (exponent) check. Ref: 'form=1.025001e+05' <-> Res: 'form=1.025001e+05'  Pass.
Test08(5), floating point (exponent) check. Ref: 'form=3.250000e-08' <-> Res: 'form=3.250000e-08'  Pass.
Test08(6), floating point (exponent) check. Ref: 'form=-1.075001e+05' <-> Res: 'form=-1.075001e+05'  Pass.
Test08(7), floating point (exponent) check. Ref: 'form=-6.250000e-08' <-> Res: 'form=-6.250000e-08'  Pass.
Test08(8), floating point (exponent) check. Ref: 'form=1.025001e+05' <-> Res: 'form=1.025001e+05'  Pass.
Test08(9), floating point (exponent) check. Ref: 'form=3.250000e-08' <-> Res: 'form=3.250000e-08'  Pass.
Test08(10), floating point (exponent) check. Ref: 'form=-1.075001e+05' <-> Res: 'form=-1.075001e+05'  Pass.
Test08(11), floating point (exponent) check. Ref: 'form=-6.250000e-08' <-> Res: 'form=-6.250000e-08'  Pass.
Test08(12), floating point (exponent) check. Ref: 'form=1.0250e+05' <-> Res: 'form=1.0250e+05'  Pass.
Test08(13), floating point (exponent) check. Ref: 'form=3.2500e-08' <-> Res: 'form=3.2500e-08'  Pass.
Test08(14), floating point (exponent) check. Ref: 'form=-1.0750e+05' <-> Res: 'form=-1.0750e+05'  Pass.
Test08(15), floating point (exponent) check. Ref: 'form=-6.2500e-08' <-> Res: 'form=-6.2500e-08'  Pass.
Test08(16), floating point (exponent) check. Ref: 'form=1.0250e+05' <-> Res: 'form=1.0250e+05'  Pass.
Test08(17), floating point (exponent) check. Ref: 'form=3.2500e-08' <-> Res: 'form=3.2500e-08'  Pass.
Test08(18), floating point (exponent) check. Ref: 'form=-1.0750e+05' <-> Res: 'form=-1.0750e+05'  Pass.
Test08(19), floating point (exponent) check. Ref: 'form=-6.2500e-08' <-> Res: 'form=-6.2500e-08'  Pass.
Test09(0), text check. Ref: 'AbcdEFG' <-> Res: 'AbcdEFG'  Pass.
Test09(1), text check. Ref: '   AbcdEFG' <-> Res: '   AbcdEFG'  Pass.
Test09(2), text check. Ref: '  AbcdEFG' <-> Res: '  AbcdEFG'  Pass.
Test09(3), text check. Ref: 'AbcdEFG' <-> Res: 'AbcdEFG'  Pass.
Test09(4), text check. Ref: 'AbcdEFG' <-> Res: 'AbcdEFG'  Pass.
Test10, format poniter to nullptr, error code: (1)  Pass.
Test11, different type, error code: (3) '%s' (target float)  Pass.
Test11, different type, error code: (3) '%d' (target float)  Pass.
Test11, different type, error code: (3) '%c' (target float)  Pass.
Test11, different type, error code: (3) '%u' (target float)  Pass.
Test11, different type, error code: (3) '%p' (target float)  Pass.
Test12, pointer type check: (0)  Ref: '000000000064fcbc' <-> Res: '000000000064fcbc'  Pass.
Test13, floating point infinity check: (0) Ref: 'inf' <-> Res: 'inf'  Pass.
Test14, different type, error code: (3) '%s' (target integer)  Pass.
Test14, different type, error code: (3) '%f' (target integer)  Pass.
Test14, different type, error code: (3) '%p' (target integer)  Pass.
Test14, different type, error code: (3) '%g' (target integer)  Pass.
Test15(0), fixed point check. Ref: '0.10' <-> Res: '0.10'  Pass.
Test15(1), fixed point check. Ref: '0.49' <-> Res: '0.49'  Pass.
Test15(2), fixed point check. Ref: '0.73' <-> Res: '0.73'  Pass.
Test15(3), fixed point check. Ref: '0.98' <-> Res: '0.98'  Pass.
Test15(4), fixed point check. Ref: '1.00' <-> Res: '1.00'  Pass.
Test16 floating point '-1' check. Ref: '-99.000000' <-> Res: '-99.000000'  Pass.
Test17 floating point '%-' check. Ref: '-99.000000' <-> Res: '-99.000000'  Pass.
Test18 report pointer (char*) '%p' check. Ref: '000000000064fcc0' <-> Res: '000000000064fcc0'  Pass.
Test19 report pointer (int*) '%p' check. Ref: '000000000040f7a0' <-> Res: '000000000040f7a0'  Pass.
Test20(0), floating point auto check. Ref: '1e+06' <-> Res: '1e+06'  Pass.
Test20(1), floating point auto check. Ref: '1.41421e+06' <-> Res: '1.41421e+06'  Pass.
Test20(2), floating point auto check. Ref: '100000' <-> Res: '100000'  Pass.
Test20(3), floating point auto check. Ref: '141421' <-> Res: '141421'  Pass.
Test20(4), floating point auto check. Ref: '-100000' <-> Res: '-100000'  Pass.
Test20(5), floating point auto check. Ref: '-141421' <-> Res: '-141421'  Pass.
Test20(6), floating point auto check. Ref: '1000' <-> Res: '1000'  Pass.
Test20(7), floating point auto check. Ref: '1414.21' <-> Res: '1414.21'  Pass.
Test20(8), floating point auto check. Ref: '1' <-> Res: '1'  Pass.
Test20(9), floating point auto check. Ref: '1.41421' <-> Res: '1.41421'  Pass.
Test20(10), floating point auto check. Ref: '0.001' <-> Res: '0.001'  Pass.
Test20(11), floating point auto check. Ref: '0.00141421' <-> Res: '0.00141421'  Pass.
Test20(12), floating point auto check. Ref: '-1e-05' <-> Res: '-1e-05'  Pass.
Test20(13), floating point auto check. Ref: '-1.41421e-05' <-> Res: '-1.41421e-05'  Pass.
Test20(14), floating point auto check. Ref: '1e-05' <-> Res: '1e-05'  Pass.
Test20(15), floating point auto check. Ref: '1.41421e-05' <-> Res: '1.41421e-05'  Pass.
Test20(16), floating point auto check. Ref: '1e-06' <-> Res: '1e-06'  Pass.
Test20(17), floating point auto check. Ref: '1.41421e-06' <-> Res: '1.41421e-06'  Pass.

format class Version: 96
All Pass: 20/20

まとめ

  • C++17 対応のコンパイラなら、RX マイコンに限らず、他の環境でも使えると思う。
  • やった事は無いが、Arduino でも使えるものと思う。(C++17 がコンパイル出来れば・・)
  • CC-RX は C++11 さえ未対応なので使えない。