「気になった事を・・・」カテゴリーアーカイブ

日常、気になった事、どうでもよい話題などをつぶやく。

シェーバーの充電池を何とかする

充電池が消耗してる・・・

最近、充電しても、直ぐに電池切れになる。
このシェーバーは3年前くらいに買ったもの。
自分は、そんなに髭が濃い方では無いので、そんなに使用頻度は多く無いと思うが、1日でそれなりに伸びる。
多い時で、1日1回は使うかも・・・
外出しない場合や、忘れていると、使わない事もある。

現在の状況は、満充電になって1回使うと、次の日には電池切れになる。
充電は、8時間くらいはかかり、使いたい時に使えないのはストレスが溜まる。
又、このシェーバーは、充電アダプタを挿しても、満充電にならないと使う事が出来ない。


とりあえず、新品は注文した

まぁ、2~3年で買い替えしてもらわないと、メーカーにしてみれば商売にならないだろうと思う。

以前はamazonで買ったが、値段を観ると1万超えで、えーーー高いってなって、ビックカメラを観たら8千円くらいだったので、納得はしなかったが、ビックで注文した。
※前買った時は5000円くらいだと思ったけどなぁー
※替え刃だけでも3000円くらいのコスト

ただ、とりあえず、ヘッドや刃は問題なく、動けば、使えるので、分解してみた。


分解するー

分解は、非常にトリッキーで、爪を折らないように慎重に行った。
けっこう難儀したー

最初は、充電池を交換して、使えるようにしようかとも思ったが、タブ付き充電池(ニッケル水素充電池)を買う必要もあり、外部に「直」にエネループを接続すれば良いのでは?
と思い、配線を加工する事にした。

充電コネクタ周辺のラインをカットして、そこから直に、充電池の端子に接続した。

充電アダプタのケーブルを切り、単三2本の電池ボックスを接続した。


動かない・・・

電源ボタンを「ON」にするー
オレンジのLEDが点滅して、言う事を聞かない・・・

色々調べたら、どうも、内部の充電池マネージメントが働き、外部電源から充電を行い、正常な状態に初期化しないと、モーターを起動しないようだった
まぁ、安全装置と言えば聞こえが良いが、魔改造を受け付けない合理的な機構なのだろうと思う。
そもそも、充電に8時間とかかかるのが、おかしいよなぁーと思う。


こうなったらダイレクトにモーターに接続

基板の写真を撮らなかったが、結局、外部端子からのラインをモーターに直接接続して強制的に動かしたw

ちょっと、スマートとは言えない結果にはなったが、とりあえず、使えるので良しとするw
それに、新品も買ったしねw

次、充電池が消耗したら、魔改造で使い倒す!w
※同じシェーバーを持っている人は、今回の記事を参考にしてもらいたいw

format、input クラスの更新

はじめに

これらクラスは、printf(format)、scanf(input)に代わる組み込み向け C++ コードで、ヘッダーをインクルードするだけで、他の環境でも利用可能となっている。
※自分は、clang64 などの環境でも便利に利用している。   

  • C++17 コンパイラが必須
  • 元々、printf、scanf などの可変引数の安全性に疑問があり、それを避ける為に実装を始めたもの
  • C++ 環境なので、C 言語の関数を利用するメリットがない
  • C++ には、安全性を意識した実装が色々あるが、「組み込み」マイコンで使うには、巨大になる為、使えない場合が多々ある
  • 「巨大」になる理由として、std::iostream クラスの存在がある
  • 組み込みマイコン環境で使っても、意外とコンパクトになるし、ヘッダーをインクルードするだけで使えて便利!
  • 実装は、あまり巨大ではなく、適当に難解で、C++ のスキルを磨くのにも重宝している
  • 仕様的にイマイチな部分もあるけど、現状、それなりに歴史があるので、大きな仕様変更を行う事が出来ない
  • テスト環境も充実してきており、問題無く利用可能となっている
  • 以前は、「%g」の仕様が満足に実装されていなかったが、それも実装され、ほぼ困る事が無くなった
  • 浮動小数点のパースでは、主に整数計算を利用しており、FPU を持たない CPU でもリソースを多く消費しない
  • 64 ビット浮動小数点のパースは基本出来ない(floatにキャストする)のだが、困る事はすくない
  • 64 ビット浮動小数点をサポートしない為、コンパクトになる
  • int64_t、uint64_t などの 64 ビット整数は扱えるように改修した
  • 「if constexpr」を使う事で、コードをシンプル、ダイエットする事が出来た(C++17)
  • github ディレクトリには、全体テストを行うソースが含まれている
  • format クラスでは、printf の出力と比較される
  • input クラスでは、入力された文字列と、実際の数値などが比較される
  • 使い方など詳しくは、github のリンクを参照して下さい

format クラス

Github format class で公開しているコードを更新した。

( 1) ( 1/ 1) output buffer size check.  Pass.
( 2) ( 1/10) decimal check.  Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
( 2) ( 2/10) decimal check.  Ref: 'form=-12345678' <-> Res: 'form=-12345678'  Pass.
( 2) ( 3/10) decimal check.  Ref: 'form=     12345678' <-> Res: 'form=     12345678'  Pass.
( 2) ( 4/10) decimal check.  Ref: 'form=    -12345678' <-> Res: 'form=    -12345678'  Pass.
( 2) ( 5/10) decimal check.  Ref: 'form=000012345678' <-> Res: 'form=000012345678'  Pass.
( 2) ( 6/10) decimal check.  Ref: 'form=-00012345678' <-> Res: 'form=-00012345678'  Pass.
( 2) ( 7/10) decimal check.  Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
( 2) ( 8/10) decimal check.  Ref: 'form=-12345678' <-> Res: 'form=-12345678'  Pass.
( 2) ( 9/10) decimal check.  Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
( 2) (10/10) decimal check.  Ref: 'form=-12345678' <-> Res: 'form=-12345678'  Pass.
( 3) ( 1/ 5) octal check.  Ref: 'form=1245667' <-> Res: 'form=1245667'  Pass.
( 3) ( 2/ 5) octal check.  Ref: 'form=   1245667' <-> Res: 'form=   1245667'  Pass.
( 3) ( 3/ 5) octal check.  Ref: 'form=001245667' <-> Res: 'form=001245667'  Pass.
( 3) ( 4/ 5) octal check.  Ref: 'form=1245667' <-> Res: 'form=1245667'  Pass.
( 3) ( 5/ 5) octal check.  Ref: 'form=1245667' <-> Res: 'form=1245667'  Pass.
( 4) ( 1/ 5) binary check.  Ref: 'form=10101110' <-> Res: 'form=10101110'  Pass.
( 4) ( 2/ 5) binary check.  Ref: 'form=    10101110' <-> Res: 'form=    10101110'  Pass.
( 4) ( 3/ 5) binary check.  Ref: 'form=0000010101110' <-> Res: 'form=0000010101110'  Pass.
( 4) ( 4/ 5) binary check.  Ref: 'form=10101110' <-> Res: 'form=10101110'  Pass.
( 4) ( 5/ 5) binary check.  Ref: 'form=10101110' <-> Res: 'form=10101110'  Pass.
( 5) ( 1/10) hex-decimal check.  Ref: 'form=12a4bf9c' <-> Res: 'form=12a4bf9c'  Pass.
( 5) ( 2/10) hex-decimal check.  Ref: 'form=  12a4bf9c' <-> Res: 'form=  12a4bf9c'  Pass.
( 5) ( 3/10) hex-decimal check.  Ref: 'form=012a4bf9c' <-> Res: 'form=012a4bf9c'  Pass.
( 5) ( 4/10) hex-decimal check.  Ref: 'form=12a4bf9c' <-> Res: 'form=12a4bf9c'  Pass.
( 5) ( 5/10) hex-decimal check.  Ref: 'form=12a4bf9c' <-> Res: 'form=12a4bf9c'  Pass.
( 5) ( 6/10) hex-decimal check.  Ref: 'form=12A4BF9C' <-> Res: 'form=12A4BF9C'  Pass.
( 5) ( 7/10) hex-decimal check.  Ref: 'form=  12A4BF9C' <-> Res: 'form=  12A4BF9C'  Pass.
( 5) ( 8/10) hex-decimal check.  Ref: 'form=012A4BF9C' <-> Res: 'form=012A4BF9C'  Pass.
( 5) ( 9/10) hex-decimal check.  Ref: 'form=12A4BF9C' <-> Res: 'form=12A4BF9C'  Pass.
( 5) (10/10) hex-decimal check.  Ref: 'form=12A4BF9C' <-> Res: 'form=12A4BF9C'  Pass.
( 6) ( 1/10) positive decimal check.  Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
( 6) ( 2/10) positive decimal check.  Ref: 'form=4282621618' <-> Res: 'form=4282621618'  Pass.
( 6) ( 3/10) positive decimal check.  Ref: 'form=     12345678' <-> Res: 'form=     12345678'  Pass.
( 6) ( 4/10) positive decimal check.  Ref: 'form=   4282621618' <-> Res: 'form=   4282621618'  Pass.
( 6) ( 5/10) positive decimal check.  Ref: 'form=000012345678' <-> Res: 'form=000012345678'  Pass.
( 6) ( 6/10) positive decimal check.  Ref: 'form=004282621618' <-> Res: 'form=004282621618'  Pass.
( 6) ( 7/10) positive decimal check.  Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
( 6) ( 8/10) positive decimal check.  Ref: 'form=4282621618' <-> Res: 'form=4282621618'  Pass.
( 6) ( 9/10) positive decimal check.  Ref: 'form=12345678' <-> Res: 'form=12345678'  Pass.
( 6) (10/10) positive decimal check.  Ref: 'form=4282621618' <-> Res: 'form=4282621618'  Pass.
( 7) ( 1/12) floating point check.  Ref: 'form=2.236068' <-> Res: 'form=2.236068'  Pass.
( 7) ( 2/12) floating point check.  Ref: 'form=-2.236068' <-> Res: 'form=-2.236068'  Pass.
( 7) ( 3/12) floating point check.  Ref: 'form=2.23606801' <-> Res: 'form=2.23606801'  Pass.
( 7) ( 4/12) floating point check.  Ref: 'form=-2.23606801' <-> Res: 'form=-2.23606801'  Pass.
( 7) ( 5/12) floating point check.  Ref: 'form=2.236068' <-> Res: 'form=2.236068'  Pass.
( 7) ( 6/12) floating point check.  Ref: 'form=-2.236068' <-> Res: 'form=-2.236068'  Pass.
( 7) ( 7/12) floating point check.  Ref: 'form=2.2361' <-> Res: 'form=2.2361'  Pass.
( 7) ( 8/12) floating point check.  Ref: 'form=-2.2361' <-> Res: 'form=-2.2361'  Pass.
( 7) ( 9/12) floating point check.  Ref: 'form=2.2361' <-> Res: 'form=2.2361'  Pass.
( 7) (10/12) floating point check.  Ref: 'form=-2.2361' <-> Res: 'form=-2.2361'  Pass.
( 7) (11/12) floating point check.  Ref: 'form=     2' <-> Res: 'form=     2'  Pass.
( 7) (12/12) floating point check.  Ref: 'form=    -2' <-> Res: 'form=    -2'  Pass.
( 8) ( 1/20) floating point (exponent) check.  Ref: 'form=1.025001e+05' <-> Res: 'form=1.025001e+05'  Pass.
( 8) ( 2/20) floating point (exponent) check.  Ref: 'form=3.250000e-08' <-> Res: 'form=3.250000e-08'  Pass.
( 8) ( 3/20) floating point (exponent) check.  Ref: 'form=-1.075001e+05' <-> Res: 'form=-1.075001e+05'  Pass.
( 8) ( 4/20) floating point (exponent) check.  Ref: 'form=-6.250000e-08' <-> Res: 'form=-6.250000e-08'  Pass.
( 8) ( 5/20) floating point (exponent) check.  Ref: 'form=1.025001e+05' <-> Res: 'form=1.025001e+05'  Pass.
( 8) ( 6/20) floating point (exponent) check.  Ref: 'form=3.250000e-08' <-> Res: 'form=3.250000e-08'  Pass.
( 8) ( 7/20) floating point (exponent) check.  Ref: 'form=-1.075001e+05' <-> Res: 'form=-1.075001e+05'  Pass.
( 8) ( 8/20) floating point (exponent) check.  Ref: 'form=-6.250000e-08' <-> Res: 'form=-6.250000e-08'  Pass.
( 8) ( 9/20) floating point (exponent) check.  Ref: 'form=1.025001e+05' <-> Res: 'form=1.025001e+05'  Pass.
( 8) (10/20) floating point (exponent) check.  Ref: 'form=3.250000e-08' <-> Res: 'form=3.250000e-08'  Pass.
( 8) (11/20) floating point (exponent) check.  Ref: 'form=-1.075001e+05' <-> Res: 'form=-1.075001e+05'  Pass.
( 8) (12/20) floating point (exponent) check.  Ref: 'form=-6.250000e-08' <-> Res: 'form=-6.250000e-08'  Pass.
( 8) (13/20) floating point (exponent) check.  Ref: 'form=1.0250e+05' <-> Res: 'form=1.0250e+05'  Pass.
( 8) (14/20) floating point (exponent) check.  Ref: 'form=3.2500e-08' <-> Res: 'form=3.2500e-08'  Pass.
( 8) (15/20) floating point (exponent) check.  Ref: 'form=-1.0750e+05' <-> Res: 'form=-1.0750e+05'  Pass.
( 8) (16/20) floating point (exponent) check.  Ref: 'form=-6.2500e-08' <-> Res: 'form=-6.2500e-08'  Pass.
( 8) (17/20) floating point (exponent) check.  Ref: 'form=1.0250e+05' <-> Res: 'form=1.0250e+05'  Pass.
( 8) (18/20) floating point (exponent) check.  Ref: 'form=3.2500e-08' <-> Res: 'form=3.2500e-08'  Pass.
( 8) (19/20) floating point (exponent) check.  Ref: 'form=-1.0750e+05' <-> Res: 'form=-1.0750e+05'  Pass.
( 8) (20/20) floating point (exponent) check.  Ref: 'form=-6.2500e-08' <-> Res: 'form=-6.2500e-08'  Pass.
( 9) ( 1/ 5) string format check.  Ref: 'AbcdEFG' <-> Res: 'AbcdEFG'  Pass.
( 9) ( 2/ 5) string format check.  Ref: '   AbcdEFG' <-> Res: '   AbcdEFG'  Pass.
( 9) ( 3/ 5) string format check.  Ref: '00AbcdEFG' <-> Res: '00AbcdEFG'  Pass.
( 9) ( 4/ 5) string format check.  Ref: 'AbcdEFG' <-> Res: 'AbcdEFG'  Pass.
( 9) ( 5/ 5) string format check.  Ref: 'AbcdEFG' <-> Res: 'AbcdEFG'  Pass.
(10) ( 1/ 1) format poniter to nullptr, error code check.   Pass.
(11) ( 1/ 5) different type (float): '%s' error check.   Pass.
(11) ( 2/ 5) different type (float): '%d' error check.   Pass.
(11) ( 3/ 5) different type (float): '%c' error check.   Pass.
(11) ( 4/ 5) different type (float): '%u' error check.   Pass.
(11) ( 5/ 5) different type (float): '%p' error check.   Pass.
(12) ( 1/ 1) pointer type check.  Ref: '000000A020F8F9B4' <-> Res: '000000A020F8F9B4'  Pass.
(13) ( 1/ 1) floating point 'inf' (infinity) check.  Ref: 'inf' <-> Res: 'inf'  Pass.
(14) ( 1/ 4) different type (int): '%s' error check.   Pass.
(14) ( 2/ 4) different type (int): '%f' error check.   Pass.
(14) ( 3/ 4) different type (int): '%p' error check.   Pass.
(14) ( 4/ 4) different type (int): '%g' error check.   Pass.
(15) ( 1/ 8) fixed point check.  Ref: '0.016' <-> Res: '0.016'  Pass.
(15) ( 2/ 8) fixed point check.  Ref: '0.059' <-> Res: '0.059'  Pass.
(15) ( 3/ 8) fixed point check.  Ref: '0.097' <-> Res: '0.097'  Pass.
(15) ( 4/ 8) fixed point check.  Ref: '0.488' <-> Res: '0.488'  Pass.
(15) ( 5/ 8) fixed point check.  Ref: '0.732' <-> Res: '0.732'  Pass.
(15) ( 6/ 8) fixed point check.  Ref: '0.875' <-> Res: '0.875'  Pass.
(15) ( 7/ 8) fixed point check.  Ref: '0.976' <-> Res: '0.976'  Pass.
(15) ( 8/ 8) fixed point check.  Ref: '1.000' <-> Res: '1.000'  Pass.
(16) ( 1/ 1) floating point '-1' check.  Ref: '-99.000000' <-> Res: '-99.000000'  Pass.
(17) ( 1/ 1) floating point '%-' check.  Ref: '-99.000000' <-> Res: '-99.000000'  Pass.
(18) ( 1/ 1) report pointer (char*) '%p' check.  Ref: '000000A020F8F9C0' <-> Res: '000000A020F8F9C0'  Pass.
(19) ( 1/ 1) report pointer (int*) '%p' check.  Ref: '00007FF6C43E3940' <-> Res: '00007FF6C43E3940'  Pass.
(20) ( 1/22) floating point '%g' check.  Ref: '1e+07' <-> Res: '1e+07'  Pass.
(20) ( 2/22) floating point '%g' check.  Ref: '1.41421E+07' <-> Res: '1.41421E+07'  Pass.
(20) ( 3/22) floating point '%g' check.  Ref: '1e+06' <-> Res: '1e+06'  Pass.
(20) ( 4/22) floating point '%g' check.  Ref: '1.41421E+06' <-> Res: '1.41421E+06'  Pass.
(20) ( 5/22) floating point '%g' check.  Ref: '100000' <-> Res: '100000'  Pass.
(20) ( 6/22) floating point '%g' check.  Ref: '141421' <-> Res: '141421'  Pass.
(20) ( 7/22) floating point '%g' check.  Ref: '-100000' <-> Res: '-100000'  Pass.
(20) ( 8/22) floating point '%g' check.  Ref: '-141421' <-> Res: '-141421'  Pass.
(20) ( 9/22) floating point '%g' check.  Ref: '1000' <-> Res: '1000'  Pass.
(20) (10/22) floating point '%g' check.  Ref: '1414.21' <-> Res: '1414.21'  Pass.
(20) (11/22) floating point '%g' check.  Ref: '1' <-> Res: '1'  Pass.
(20) (12/22) floating point '%g' check.  Ref: '1.41421' <-> Res: '1.41421'  Pass.
(20) (13/22) floating point '%g' check.  Ref: '0.001' <-> Res: '0.001'  Pass.
(20) (14/22) floating point '%g' check.  Ref: '0.00141421' <-> Res: '0.00141421'  Pass.
(20) (15/22) floating point '%g' check.  Ref: '-1e-05' <-> Res: '-1e-05'  Pass.
(20) (16/22) floating point '%g' check.  Ref: '-1.41421E-05' <-> Res: '-1.41421E-05'  Pass.
(20) (17/22) floating point '%g' check.  Ref: '1e-05' <-> Res: '1e-05'  Pass.
(20) (18/22) floating point '%g' check.  Ref: '1.41421E-05' <-> Res: '1.41421E-05'  Pass.
(20) (19/22) floating point '%g' check.  Ref: '1e-06' <-> Res: '1e-06'  Pass.
(20) (20/22) floating point '%g' check.  Ref: '1.41421E-06' <-> Res: '1.41421E-06'  Pass.
(20) (21/22) floating point '%g' check.  Ref: '1e-07' <-> Res: '1e-07'  Pass.
(20) (22/22) floating point '%g' check.  Ref: '1.41421E-07' <-> Res: '1.41421E-07'  Pass.
(21) ( 1/22) floating point '%8g' check.  Ref: '1.666e+07' <-> Res: '1.666e+07'  Pass.
(21) ( 2/22) floating point '%8g' check.  Ref: '1.41421E+07' <-> Res: '1.41421E+07'  Pass.
(21) ( 3/22) floating point '%8g' check.  Ref: '1.666e+06' <-> Res: '1.666e+06'  Pass.
(21) ( 4/22) floating point '%8g' check.  Ref: '1.41421E+06' <-> Res: '1.41421E+06'  Pass.
(21) ( 5/22) floating point '%8g' check.  Ref: '  166600' <-> Res: '  166600'  Pass.
(21) ( 6/22) floating point '%8g' check.  Ref: '  141421' <-> Res: '  141421'  Pass.
(21) ( 7/22) floating point '%8g' check.  Ref: ' -166600' <-> Res: ' -166600'  Pass.
(21) ( 8/22) floating point '%8g' check.  Ref: ' -141421' <-> Res: ' -141421'  Pass.
(21) ( 9/22) floating point '%8g' check.  Ref: '    1666' <-> Res: '    1666'  Pass.
(21) (10/22) floating point '%8g' check.  Ref: ' 1414.21' <-> Res: ' 1414.21'  Pass.
(21) (11/22) floating point '%8g' check.  Ref: '   1.666' <-> Res: '   1.666'  Pass.
(21) (12/22) floating point '%8g' check.  Ref: ' 1.41421' <-> Res: ' 1.41421'  Pass.
(21) (13/22) floating point '%8g' check.  Ref: '0.001666' <-> Res: '0.001666'  Pass.
(21) (14/22) floating point '%8g' check.  Ref: '0.00141421' <-> Res: '0.00141421'  Pass.
(21) (15/22) floating point '%8g' check.  Ref: '-1.666e-05' <-> Res: '-1.666e-05'  Pass.
(21) (16/22) floating point '%8g' check.  Ref: '-1.41421E-05' <-> Res: '-1.41421E-05'  Pass.
(21) (17/22) floating point '%8g' check.  Ref: '1.666e-05' <-> Res: '1.666e-05'  Pass.
(21) (18/22) floating point '%8g' check.  Ref: '1.41421E-05' <-> Res: '1.41421E-05'  Pass.
(21) (19/22) floating point '%8g' check.  Ref: '1.666e-06' <-> Res: '1.666e-06'  Pass.
(21) (20/22) floating point '%8g' check.  Ref: '1.41421E-06' <-> Res: '1.41421E-06'  Pass.
(21) (21/22) floating point '%8g' check.  Ref: '1.666e-07' <-> Res: '1.666e-07'  Pass.
(21) (22/22) floating point '%8g' check.  Ref: '1.41421E-07' <-> Res: '1.41421E-07'  Pass.
(22) ( 1/ 1) floating point 'nan' (not a number) check.  Ref: '   nan' <-> Res: '   nan'  Pass.
(23) ( 1/ 1) '%' check.  Ref: '1234abcdefg%ABCDEFG5678' <-> Res: '1234abcdefg%ABCDEFG5678'  Pass.
(24) ( 1/ 1) '%q' check.  Ref: 'aaa q bbb' <-> Res: 'aaa q bbb'  Error: unknown type.  Pass.
(25) ( 1/ 5) binary check.  Ref: 'form=110110011011011100101011010110101110' <-> Res: 'form=110110011011011100
101011010110101110'  Pass.
(25) ( 2/ 5) binary check.  Ref: 'form=   110110011011011100101011010110101110' <-> Res: 'form=   110110011011
011100101011010110101110'  Pass.
(25) ( 3/ 5) binary check.  Ref: 'form=00110110011011011100101011010110101110' <-> Res: 'form=0011011001101101
1100101011010110101110'  Pass.
(25) ( 4/ 5) binary check.  Ref: 'form= 110110011011011100101011010110101110' <-> Res: 'form= 1101100110110111
00101011010110101110'  Pass.
(25) ( 5/ 5) binary check.  Ref: 'form=110110011011011100101011010110101110' <-> Res: 'form=110110011011011100
101011010110101110'  Pass.
(26) ( 1/ 5) decimal 64 bits check.  Ref: 'form=37812750652850076' <-> Res: 'form=37812750652850076'  Pass.
(26) ( 2/ 5) decimal 64 bits check.  Ref: 'form=-37812750652850173' <-> Res: 'form=-37812750652850173'  Pass.
(26) ( 3/ 5) decimal 64 bits check.  Ref: 'form=   37812750652849979' <-> Res: 'form=   37812750652849979'  Pa
ss.
(26) ( 4/ 5) decimal 64 bits check.  Ref: 'form=  -37812750652850270' <-> Res: 'form=  -37812750652850270'  Pa
ss.
(26) ( 5/ 5) decimal 64 bits check.  Ref: 'form=0000000037812750652849882' <-> Res: 'form=00000000378127506528
49882'  Pass.
(26) ( 6/ 5) decimal 64 bits check.  Ref: 'form=-000000037812750652850367' <-> Res: 'form=-0000000378127506528
50367'  Pass.
(26) ( 7/ 5) decimal 64 bits check.  Ref: 'form=   37812750652849785' <-> Res: 'form=   37812750652849785'  Pa
ss.
(26) ( 8/ 5) decimal 64 bits check.  Ref: 'form=  -37812750652850464' <-> Res: 'form=  -37812750652850464'  Pa
ss.
(26) ( 9/ 5) decimal 64 bits check.  Ref: 'form=37812750652849688' <-> Res: 'form=37812750652849688'  Pass.
(26) (10/ 5) decimal 64 bits check.  Ref: 'form=-37812750652850561' <-> Res: 'form=-37812750652850561'  Pass.
(27) ( 1/10) hex-decimal 64 bits check.  Ref: 'form=567f12a4bf9c' <-> Res: 'form=567f12a4bf9c'  Pass.
(27) ( 2/10) hex-decimal 64 bits check.  Ref: 'form=  567f12a4bf9c' <-> Res: 'form=  567f12a4bf9c'  Pass.
(27) ( 3/10) hex-decimal 64 bits check.  Ref: 'form=000567f12a4bf9c' <-> Res: 'form=000567f12a4bf9c'  Pass.
(27) ( 4/10) hex-decimal 64 bits check.  Ref: 'form=567f12a4bf9c' <-> Res: 'form=567f12a4bf9c'  Pass.
(27) ( 5/10) hex-decimal 64 bits check.  Ref: 'form=567f12a4bf9c' <-> Res: 'form=567f12a4bf9c'  Pass.
(27) ( 6/10) hex-decimal 64 bits check.  Ref: 'form=567F12A4BF9C' <-> Res: 'form=567F12A4BF9C'  Pass.
(27) ( 7/10) hex-decimal 64 bits check.  Ref: 'form=  567F12A4BF9C' <-> Res: 'form=  567F12A4BF9C'  Pass.
(27) ( 8/10) hex-decimal 64 bits check.  Ref: 'form=000567F12A4BF9C' <-> Res: 'form=000567F12A4BF9C'  Pass.
(27) ( 9/10) hex-decimal 64 bits check.  Ref: 'form=567F12A4BF9C' <-> Res: 'form=567F12A4BF9C'  Pass.
(27) (10/10) hex-decimal 64 bits check.  Ref: 'form=567F12A4BF9C' <-> Res: 'form=567F12A4BF9C'  Pass.

format class Version: 121
All Pass: 27/27

input クラス

Github input class で公開しているコードを更新した。

( 1) ( 1/ 2) Integer input (type int): '123456789' ---> 123456789  Pass.
( 1) ( 2/ 2) Integer input (type int): '-123456789' ---> -123456789  Pass.
( 2) ( 1/ 2) Floating point input (type float exponent): '2.5439e3' ---> 2.543900e+03  Pass.
( 2) ( 2/ 2) Floating point input (type float exponent): '-2.5439e3' ---> -2.543900e+03  Pass.
( 3) ( 1/ 1) Integer (uint32_t) max value conversion: '4294967295' ---> 4294967295  Pass.
( 4) ( 1/ 1) Fail conversion state check, initial value hold: '8o0173476' 123456789 ---> 123456789  Pass.
( 5) ( 1/ 1) Multi scan for integer (%d[, ]%x[, ]%d): '-98516 105aBd3,21369871' (3) -98516, 105abd3, 21369871
 Pass.
( 6) ( 1/ 1) Multi scan for integer (%d[, ]%x,%d): '-9577463,fa4c57ab,23645687' (3) -9577463, fa4c57ab, 236456
87  Pass.
( 7) ( 1/ 1) Multi scan for (%d,%f,%c): '-17743347,-1273.75941,Z' (3) -17743347, -1273.759399, Z  Pass.
( 8) ( 1/ 1) Multi scan for (%f,%d,%x,%o): '101.945678,-76437583,7fdcab5f,7453642341' (4) 101.945679, -7643758
3, 7fdcab5f, 7453642341  Pass.
( 9) ( 1/ 1) Multi scan for 'int' at spacing ( %d %d %d): ' 100 250 300' (3) 100, 250, 300  Pass.
(10) ( 1/ 1) Multi scan for 'auto' (%a %a %a %a): '100 0x9a 0b1101 0o775' (4) 100, 154, 13, 509  Pass.
(11) ( 1/ 1) Multi scan for 'auto' (%a %a %a %a %a): '100 x9a b1101 o775 -123.4567' (5) 100, 154, 13, 509, -12
3.456703  Pass.
(12) ( 1/ 1) Multi scan for (%b %o %d %x %f %c): '11011 0625 -985 4a7Bc 1.025 Y' (6) 27, 405, -985, 4a7bc, 1.0
25000, Y  Pass.
(13) ( 1/ 1) Check signed integer error (%d): '-8964743' ---> 0  Pass.
(14) ( 1/ 1) Check hexa-decimal conversion for signed integer (%x): '-7ffe9283' ---> 80016d7d  Pass.
(15) ( 1/ 1) Check signed type error (%d): '-8967464' ---> 0  Pass.
(16) ( 1/ 1) Integer input 'std::string' as (%d): '56789' ---> 56789  Pass.
(17) ( 1/ 1) Overflowed floting point input as (%f): '0.555555555555' ---> 0.555556  Pass.
(18) ( 1/ 1) Overflowed integer32 '2147483647' (%d) error check input as '2147483648' ---> -2147483648  Pass.
(19) ( 1/ 1) Overflowed floting point input as (%f): '987643214321' ---> 987643200.000000  Pass.
(20) ( 1/ 1) Overflowed binary error check input (%b): '101010101010101010101010101010101' ---> 0xaaaaaaaa  Pa
ss.
(21) ( 1/ 1) Overflowed hexa-decimal error check input (%x): 'a290fc4b1' ---> 0xa290fc4b  Pass.
(22) ( 1/ 1) Overflowed octal error check input (%o): '65234223514' ---> 354e24e9  Pass.
(23) ( 1/ 1) Special character separator (%d\%%d\[%d\]%d): '123%456[789]5678' (4) 123, 456, 789, 5678  Pass.
(24) ( 1/ 1) Floating point conversion for (%f): '123456789' ---> 123456792.000000  Pass.
(25) ( 1/ 1) Floating point conversion (%f): '.123456789) ---> 0.123457  Pass.
(26) ( 1/ 1) Floating point conversion (%f): '-.123456789' ---> -0.123457  Pass.
(27) ( 1/ 1) Floating point conversion (%f): '.123456789e-3' ---> 0.000123  Pass.
(28) ( 1/ 1) Floating point conversion (%f): '-.123456789e-3' ---> -0.000123  Pass.
(29) ( 1/ 1) Integer (uint64_t) max value conversion: '18446744073709551615' ---> 18446744073709551615  Pass.
(30) ( 1/ 1) Overflowed int64_t at '9223372036854775807' (%d) error check input as '9223372036854775808' --->
-9223372036854775808  Pass.
(31) ( 1/ 2) Integer input (type short): '23456' ---> 23456  Pass.
(31) ( 2/ 2) Integer input (type short): '-23456' ---> -23456  Pass.
(32) ( 1/ 2) Integer input (type uint16_t): '45678' ---> 45678  Pass.
(32) ( 2/ 2) Integer input (type uint16_t): '56789' ---> 56789  Pass.

input class Version: 112
All Pass: 32/32

RXマイコンサポート(RX110、RX111、RX113)と、データフラッシュの操作系見直し

RX110, RX111, RX113 などをサポート

RX マイコン C++ フレームワークでは、なるべく多くの品種をサポートするべく作業を行っている。

これらの RX マイコンは、現行品で、比較的低価格のマイコンとなっている。
FPU が無いとか、5V で動かせない(1.8~3.6V)とか、色々と制限があるものの、特定の分野なら十分な能力があると思う。
動作周波数は 32MHz だが、8/16 ビット系に比べて、扱い易く、高性能だと思える。

  • FPU はアプリケーションによっては、無い事が不利益にならない場合がある
  • 32 ビット CPU なので、バンクを気にする必要が無く、プログラムの実装は、非常にやりやすいと思う
  • それでいて、十分低消費電力であり、コストパフォーマンスも良い
  • 必要十分なペリフェラル(MTU, RTC, SCI, I2C, RSPI)を内蔵しており、通常の用途では十分と思える
  • USB、LCD、静電タッチ機能を使える物など、そこそこバリエーションがある
  • 基本的に RX マイコンのリソースを再利用出来る

サポートと言っても、以前のリソースを集めたり、定義を少し書くだけなので、そんなに大げさなものでは無い。
ただ、デバイスを入手して、実験していないので、ちゃんと動作するかは判らない、近々にデバイスを入手して、簡単なテストは行いたい。

  • ROM 容量が 64K 以上ある RX140 が安価に入手出来れば良いのだが、チップワンストップには在庫が確認出来ない
  • ROM 容量が大きい RX140、海外の販売サイトには在庫があるようだが、単価が高いので、RX231とかの方が良いかもしれない
  • 上記 RX100 系は、動作電圧範囲が狭いので、A/D を使う場合に、ダイナミックレンジが狭く、色々と制限が多いのは、マイナスポイント
  • 当然、電源電圧が低いと、ノイズ耐性にも影響があるものと思う

チップワンストップ:

RX110: 64LQFP, RXv1, 32MHz, Code: 32K, RAM: 10K, DataFlash: 0K, R5F51101ADFM
1個:256円
10個:@190円
RX110 Github

RX111: 64LQFP, RXv1, 32MHz, USB2.0, Code: 128K, RAM: 16K, DataFlash: 8K, R5F51115ADFM
1個:368円
10個:@234円
RX111 Github

RX113: 64LQFP, RXv1, 32MHz, USB2.0, Code: 512K, RAM: 64K, DataFlash: 8K, R5F51138ADFM
1個:630円
10個:@483円
RX113 Github


データフラッシュの操作

今まで、RX64M 系、RX24T 系のデータフラッシュの操作は、実装して、試していたが、それとは異なる系統の場合、実装されていなかった。
構成が異なり、シーケンスも微妙に異なるグループがある。
これは、デバイスにより、内蔵フラッシュメモリの構造や特性が異なるのが要因と思う。
このデータフラッシュ操作は、RX220/RX621/RX62N/RX631/RX63N など、古いタイプの RX マイコンなのもある。
しかし、RX26T が、このグループに近い操作系となっており、ついでにサポートして実験した。

  • 消去は基本、バンク単位で行う
  • 1バイト単位で書き込め、消去後の値が 0xFF の場合、多分従来型の EEPROM に近いものと思う
    - 消去後の値が未定の場合は、新しいタイプ(E2?)のフラッシュメモリとなっている
CPU 容量 バンクサイズ 書き込み単位 消去後の値 ユニークID数
RX140 4K 256 1 0xFF 4
RX220 8K 2048 2 0x?? 4
RX231 8K 1024 1 0xFF 4
RX24T 8K 1024 1 0xFF 4
RX26T 16K 64 4 0x?? 3
RX62N 32K 2048 8 0x?? 0
RX631 32K 2048 4 0x?? 4
RX64M 64K 64 4 0x?? 3
RX71M 64K 64 4 0x?? 3
RX65N 32K 64 4 0x?? 4
RX72N 32K 64 4 0x?? 4
RX66T 32K 64 4 0x?? 3
RX72T 32K 64 4 0x?? 3

FLASH_sample: 各プロジェクト、データフラュシュ操作クラス、アプリケーションの動作確認

Project File flash_io 動作確認
RX140/Makefile RX24T/flash_io.hpp
RX220/Makefile RX62x/flash_io.hpp
RX231/Makefile RX24T/flash_io.hpp
RX24T/Makefile RX24T/flash_io.hpp
RX26T/Makefile RX62x/flash_io.hpp
RX62N/Makefile RX62x/flash_io.hpp
RX631/Makefile RX62x/flash_io.hpp
RX64M/Makefile RX600/flash_io.hpp
RX71M/Makefile RX600/flash_io.hpp
RX65N/Makefile RX600/flash_io.hpp
RX72N/Makefile RX600/flash_io.hpp
RX66T/Makefile RX600/flash_io.hpp
RX72T/Makefile RX600/flash_io.hpp

RX220/RX26T/RX62[1N]/RX63[1N] などサポート

これらグループは、ほぼ同じ操作系なのだが、微妙に異なる部分もあり、やりたくは無かったが、「#if defined(xxx)」でより分けている。
多少工夫すると、無くせなくも無いが、コードの見通しがもっと悪くなると思ったのもあって、とりあえず、制御文で別けている。

RX26T は、ほぼ同じとは言え、構成も異なるので、ソースを別けた方が良いかもしれないが、同じようなコードをコピペする事になる、コピー元を変更したら、コピー先に反映させなければならないしで、どうしたものか・・・
※まぁ、機能違いは、継承させて、分離する方が良いかもしれないが、それも複雑になるし、一長一短ではある・・・

  • RX62[1N]、RX63[1N]は、ファームの転送が必要
  • RX26T は、FACI コマンド発行アドレスが異なる
  • RX26T は、データフラッシュ操作アドレス用に、専用のレジスタがあり、適切な値を設定する必要がある
  • それぞれ、書き込みサイズ、バンクサイズ等が異なる場合があり、FLASH レジスタークラスで定義を行って、flash_io クラスからは参照するようにしている

まとめ

Start Data Flash sample for 'RX62N FRK-RX62N' 96 [MHz]
Flash drive clock: 48 [MHz]
Data Flash total size: 0x00008000
Data Flash block size: 2048 bytes
Data Flash word size: 8 byte
# check 2
Erase check: bank 2: 0x1000 to 0x17FF OK
# write 1000 123456789abcdef0 fa926534bcdea021
# r 1000 100f
0x1000: 123456789ABCDEF0 FA926534BCDEA021
# check 2
Erase check: bank 2: 0x1000 to 0x17FF NG
# erase 2
Erase OK: bank 2, 0x1000 to 0x17FF
# check 2
Erase check: bank 2: 0x1000 to 0x17FF OK
# r 1000 100f
0x1000: 1274567892BCDEF0 FA926514BCDEA021
#
  • RX220 は、RX62[1N]/RX63[1N] この系列なのだが、動作確認で失敗し、原因を調査・・・
  • RX220 は ROM ブロック領域の説明も実際と異なっている
  • データフラッシュのバンクサイズも128バイト、2048バイトと説明が2つあり、どちらが正解なのか判らない
  • 多分 2048 バイトだと思う
  • RX220 は保守外の品種なので、どうかと思うが、一応、ルネサスに質問しておこうと思う
  • RX220 のフラッシュ操作が動かない理由は、判ったー
  • FCU クロック通知を、データ領域では無く、コード領域に行う必要がある・・・
  • 「フラッシュ P/E モードエントリレジスタ(FENTRYR)」のアドレスがタイポしていた・・・
  • レジスタアドレスは、構成が同等の RX マイコンでも、微妙に異なっている場合がある・・・
  • それを修正して動作するようになった!(確認したつもりだったが・・・)
  • 消去後のデータが不定だと、消去されているか不明なので、ワード単位の消去チェックや消去操作が必要となる
  • これは、今後ワード単位の API を追加する(RX64M 系も同じように追加が必要)

iPhone6s のバッテリー交換

iPhone6s が懐妊

自分は大月の田舎に住んでいる、このような山沿いの集落では、あるあるなのだが、何かの時事会役員になる事になる。
今は、組長と、氏子総代の総務を担当しており、色々な仕事がある。(ボランティアなので、仕事の合間にこなす必要がある)

昨日、氏子関係の資料を配る為、近所の集落を回っていた。
昨日は、かなり暑かった・・
その時、携帯の google MAP を観ながら、目的の家を探していたのだが、あっとゆー間に携帯が膨らんできた・・

俗に言う「懐妊」とゆー現象だ、その状態でも、電源は切れずに、使えていたのだが、発火するのではと気が気では無かった。
と言っても、MAP が無いと、何も出来ないので、その状態で、何とか資料を配布した。

自宅に戻って、新バッテリーを注文した。

iPhone6s は、かなり古い携帯だが、十分な性能で満足している。


次の日にはバッテリーが到着

田舎でも、宅配便は、意外と遅延無く届くのがありがたい!
次の日の3時くらいに、先日注文したバッテリーが到着、早速交換作業を開始した。
※バッテリーの交換は二回目なので、手順は大体理解しているが、ネジが小さく、視力も落ちているので、難儀する・・

バッテリーの両面テープを抜くのが怖かったが、予め、無水エタノールをバッテリーとケースの隙間に入れておいたので、非常にスムーズに抜け、一番の懸念事項が解消された。
※一回目のバッテリー交換時に、もの凄く難儀し、無理やりバッテリーを剥がそうとして、バッテリーが発火して大きな事故になる処だった事は秘密にしているw


両面テープの残りを掃除

意外と大変なのが、残った両面テープのカスを掃除する作業だ・・
無水エタノール、キムワイプ、ピンセットなどを総動員して、掃除した、結構な時間を要したー


新バッテリーを組み込み

新バッテリーに両面テープを貼り、コネクターの位置を合わせて、組み込む。
コネクターの位置をちゃんと合わせておかないと、コネクターがちゃんと刺さらなくて、電源が繋がらない事がある。
※実際、それが起こったが、繋ぎ直して、電源が入る事を確認。


最終組み立て

ケースに両面テープを貼る。
※これが、又、意外と苦労する・・

液晶を元に戻して、ケースと合わせる前に、電源を入れてみるが・・
電源が入らない・・
ここで、電源コネクターの差し込みが不十分であったようで、挿しなおして、電源が入る事を確認。
ケースを閉めて、最後のネジを閉めた。


まとめ

iPhone6s はもうかなり古いので、もう少し新しい 8plus 位の中古が欲しいのだが・・・

この機会に、購入しようかとも考えている。
もう少し大きい画面が欲しい~

RXマイコン関数電卓、他


※ 120km を mi に変換 (74.56 mi)

関数電卓を考える

関数電卓は、丁度良いボリュームで、難易度も適当な事から、昔から興味の尽きないアプリケーションとなっている。

マイコンで作る電卓なら、大容量メモリや周辺機能を活かして、通常流通している物には無い機能を盛り込める。
前回、倍精度浮動小数点よりも高精度に計算が行える、gmp、mpfr ライブラリを使って、計算の核を実装している。

RX マイコン EnvisionKit の機能を活かして実現が出来るのもガジェットとして都合が良い。

最終的には、簡単に持ち運びが出来る形態で、実用的なハンドヘルド関数電卓を作りたいと考えている。

構成的には、タッチキーでは無く、物理ボタンが欲しい処ではあるけど、複雑な操作は GUI じゃないと作りずらい場合もある。
物理ボタンなら、フルキーボードが欲しい処ではあるけど、気軽に使えるような、小型のフルキーも少ない・・
市販されているボタンを組み合わせてキーアレイを構築するにしても、コストの割に良い物を作る事が難しい・・

それでも、手頃な RX マイコン、液晶、物理キーを組み合わせた、スクラッチの関数電卓も作ってみたい。

色々考えても、一長一短で最適解があるのか無いのか・・、とりあえず、ソフトで出来る事を地道に積み上げて、完成度を高めるのが良さそうだと感じている。

GUI が無くても、シリアル接続で、対話式に計算を行えるようにしてあり、殆どのRXマイコンで動作する。
※容量が 256K 品では不足するのが、多少問題で、最低でも 512K 品が必要・・


単位の換算機能

2進、16進の変換機能などを実装して、及第点にはなった感があるのだけど、自分としては前から欲しいと思った機能もある。
Qiita の記事:RXマイコンで動作する関数電卓
※上記記事は、2進、10進、16進の機能を追加したバージョンの記事で、内部の構成などを解説している。

新たに追加した機能は「単位の変換」機能だ。

単位変換は、長さ、速度、重量など相互に変換したい場合があり、電卓の専用機能として実装すれば、利便性が格段に上がると思われる。

電卓では、単純に小数点の位置をオフセットして、10 の乗数で表す機能(ENG)があり、単位の変換は、これに近い機能。
そうすれば、元の値を保持したまま、自由に単位を変更出来るので、非常に便利。
※元の値を保持したまま変換出来る点が利便性が高い。

追加で、貨幣の変換も追加した、貨幣の場合、レートが日々変化するので、変換レートを更新する必要がある。
なので、貨幣レートのみ、変換レートを再設定出来るようにしてある。
※GUI版は、貨幣レートを入力するダイアログ関係を実装中で、現在、コマンド入力では再設定出来る。


GUI spinboxt

スピンボックスtは、登録された単語集を、左右の小さいボタンにより変更して、目的の機能を選択する。
※通常のスピンボックスは、数値を変化させて、定量的な値を得るもので、それとは少し異なるものだ。

  • ボタンを三等分して、左、右、中心で機能を別けているので、ある程度の幅が必要となる
  • 左右の小さい三角は、選択肢の有無を表している
  • メニューの方が良いかもしれないが、画面タッチでは、シンプルな操作性の方が使い易いと思う

レートの再設定

貨幣レート変換の場合、時間と共にレートが変わるので、レートを変更出来るようにする必要がある。
コマンドラインのインターフェースでは、その機能を入れてあるが、GUI は、現在実装中となっている。


RX231 のフラッシュ書き込みの不具合

RX231 を、rx_prog でフラッシュ書き込みを行った処、途中でストールして書き込めなくなった・・・
色々調べたが原因が良く判らない・・
とりあえず、「--write-page-wait=10000 --erase-page-wait=5000」書き込み時の遅延を大きくしたら、ストールしなくなったので、RX231 だけ遅延を再設定するように、common/makefile を修正した。


sci_io、rsci_io、scif_io クラスのエラーハンドリング

以前の実装では、オーバーランエラー、フレーミングエラー、パリティエラーが発生した場合、受信を受け付けなくなる不具合があった。

長い間、放置され修正を忘れていたものだった・・・
それを思い出し、ちゃんと実装した。

  • エラー割り込みを有効にして、エラーフラグを消去する
  • エラーの回数を記録する

まだ、緻密なテストを行っていないが、多分問題無いと思う。
エラーが発生した場合、受信データを捨てる事になるが、エラーをクリアして、正常に受信を行えば自動で復帰する。


RXマイコン GUI ダイアログ

ダイアログボックスは、優先度の高い GUI で、フォーカスを占有する。
現状、gui/widget_director は、これらの管理を全くしておらず、新規に実装する必要がある・・

しかし、ここにきて、行き当たりばったりで実装してきた事がかなり痛いー、ちゃんと良く考えないと管理が難しく複雑になる。
少し時間を取って、ゆっくり考えたい。
glfw3_app では、実装済みなのだが、昔実装した時には、かなり面倒だったと記憶している。
本来、こんなに高機能にするつもりが無かった、シンプルな構造で十分と思っていたのだが、関数電卓の GUI を実装する過程で、やっぱり、シンプルな機能だけでは、不可能な事案が出てきてしまった。

RX140ボード、RXマイコンC++フレームワークの整備など

最近ブログ書いて無かったので・・

RX140ボードは出来て、組み立て途中、クリスタルのフットプリントを間違えていた・・
新たに、USBシリアルとして安価なCH340、を採用した、それは動いている事は確認した。
@70円は、確かに安いが、どうだろうか・・・

クリスタルの表面実装品は取り付けが困難な事が判ったー、ハンダペーストは出来れば使いたく無い・・

1603サイズのLEDが見つからないので、動作検査はまだ出来ていないが、まぁ問題無いと思う。

今回、JLPCBを使った。

準備が出来たら、領府を行う予定、多分1000円位。


RX マイコンC++フレームワークの構成など、細かく見直した

まず、サポートしているRXマイコンの種別を増やした、ただ、実際にデバイスに書き込んで動作検査をしていない品種もある。
ChipOne ストップでの入手性、値段などから品種の追加等を行っている。
現行デバイスでは無いものでも、まだ流通している品種はそのまま残しているが、古いデバイスを新たに追加するかは未定。

又、各ディレクトリに「README.md」を置いて、特徴、リンカーファイルの構成、専用ファイル、基本ピンアサイン、フラッシュプログラマ関係の情報などを記述してコミットした。
これを観れば、デバイスを選択する際の要点などが判ると思う。


最近、秋月で、RX231 の販売を開始したようだが、値段が高く、フラッシュ容量も少ない品種で、中途半端な感じだ・・
※フラッシュ容量128Kは、USBが使えても、少ないと思う、それで580円、まぁCANが使える品種のようだが・・
それでも、一応、リンカーファイルは追加しておいた。
ChipOne ストップで、もっとフラッシュ容量が大きく、ピン数が多い品種を買った方が良いと思える。

CAN は自動車やバイクで使えるので、そのような用途に使えるかもしれない。
C++フレームワークでは、現在「RSCAN」は未サポートなので、早急に何とかしたい~


format_class を少しだけ更新

GitHub の format_class 関係、少しだけ修正した。

「make run」で、セルフテストを行うと、文字出力で、「ゼロサプレス」を使った場合にリファレンスと異なった動作をしていた。
それを修正した。
この評価は、clangコンパイラで行っており、「標準」的な動作なのだと思われる。

RXマイコン、クロック設定関係を更新

クロックのブーストを改修

俺俺C++フレームワークでは、クロックのブーストを独自に行っている。

RX64M、RX71M、RX65x、RX671、RX66N、RX72N、RX72M、RX66T、RX72T は、ほぼ共通のレジスタ構成で、共有化していた。
ただ、共有出来ない部分もあり、「#if、#endif」を使って、デバイス毎に、別けていた。

最近、新たな方法を導入して、これを、もっとスマートな方法で分ける方法を実装した。


無効なアクセスを行う定義

RX66T/RX72T には、サブクロック発信器が無いので、それに関係するレジスタは存在しない。

以前は、以下のようにしていた。

#if defined(SIG_RX66T) || defined(SIG_RX72T)
#else
            // サブクロック発信器制御
            device::SYSTEM::SOSCWTCR = 0b0'1010;
            device::SYSTEM::SOSCCR = device::SYSTEM::SOSCCR.SOSTP.b(!clock_profile::TURN_SBC);
#endif

この、「#if ~ #endif」で分ける実装は、一か所くらいなら、まだ良いが多くなると、読み辛くなるしスマートとは言えない、どうしたものかと考えていた。

そこで、根本に返り、レジスタクラスの定義をダミーにする事で、「#if ~ #endif」を除く事が出来る。
その代わり、見た目には、普通にレジスタをアクセスしているようにしか見えないのが問題ではある。
レジスタの定義を確認して、初めて、このアクセスがダミーで無効である事に気が付く。
一応、コメントには、そのように書いてあるが・・・

        template <uint32_t base>
        struct sosccr_null_t : public rw8_null_t<base> {
            typedef rw8_null_t<base> io_;
            using io_::operator =;
            using io_::operator ();
            using io_::operator |=;
            using io_::operator &=;

            bit_rw_t<io_, bitpos::B0> SOSTP;
        };
  • rw8_null_t は、中身は空で、アクセスが発生しても何もしない
  • これは、最適化により、完全に無くなる

この手法をとりあえず、system.hpp に導入し、関係レジスタの定義を見直した

#if defined(SIG_RX64M)
    typedef system_64m_t SYSTEM;
#elif defined(SIG_RX65N) || defined(SIG_RX651)
    typedef system_65x_t SYSTEM;
#elif defined(SIG_RX66N)
    typedef system_66n_t SYSTEM;
#elif defined(SIG_RX671)
    typedef system_671_t SYSTEM;
#elif defined(SIG_RX71M)
    typedef system_71m_t SYSTEM;
#elif defined(SIG_RX72N) || defined(SIG_RX72M)
    typedef system_72n_72m_t SYSTEM;
#elif defined(SIG_RX66T) || defined(SIG_RX72T)
    typedef system_66t_72t_t SYSTEM;
#endif
  • 各クラスは、共通では無い部分のみ定義を行い、共通部分(system_base_t)は、継承している
    struct system_66t_72t_t : public system_base_t {

        static constexpr bool NCRGx_reg    = false;
        static constexpr bool NCRCx_reg    = false;

        // オプション設定メモリ
        static inline spcc_t<0x0012'0040> SPCC;
        static inline ofs0_t<0x0012'0068> OFS0;
        static inline ofs1_t<0x0012'006C> OFS1;
        static inline mde_t <0x0012'0064> MDE;

        static inline memwait8_t<0x0008'101C> MEMWAIT;

        static inline romwt_null_t<0x0000'0000> ROMWT;

        static inline sosccr_null_t<0x0000'0000> SOSCCR;

        static inline soscwtcr_null_t<0x0000'0000> SOSCWTCR;
    };
  • 一応、コメントを入れてあるが、コメントはコードとは異なるので、多少問題があるとは思う・・
            // サブクロック発信器制御
            // サブクロックが RX66T/RX72T では、ダミーアクセスとなる。
            device::SYSTEM::SOSCWTCR = 0b0'1010;
            device::SYSTEM::SOSCCR = device::SYSTEM::SOSCCR.SOSTP.b(!clock_profile::TURN_SBC);

実装ミスがあり、RX66T/RX72T が起動しなかった・・・

  • 電卓プログラムを確認している時、RX66T が起動しなかった。
  • RX66T は RAM が少ないので、それが問題と思って、色々修正したが、動作しない。
  • あれ?と思い、LED 点滅を実験したら、やっぱり起動しない。
  • 調べると、上記のダミーアクセスコードに実装ミスがあり、それが原因だった。
  • 大きな変更をしたら、ちゃんと確認しないと駄目だと痛感した。

RX24T のクロック設定にも問題が・・・

  • 以前に、ソフトディレイループを、アセンブラコードにしたので、RX24T の微調整を行った。
  • クロックを落とすとソフトディレイの誤差が大きくなる。
  • 調べると、「SCKCR」の予約ビットの設定があり、それが抜けていたので修正した。
  • それで、クロックを落とした場合でも、ソフトディレイがある程度正確になった。
  • 最大速度(80MHz)で動かす場合には、問題無かった。

RX26TのPLLベースクロック不具合

RX26T の PLL ベースクロック

は、ハードウェアーマニュアルでは、120 ~ 240MHz となっている。

しかし、240MHz を設定すると動作しない状況だった。

120MHz なら動作するので、まぁ問題無いかと思っていたが、やはり気になるので、ルネサス社のサポートに問い合わせていた。

色々、やりとりをした結果、スマートコンフィギュレーターでプログラムを生成して試して下さいとの事だった・・
まぁ、そうなるよなぁーと思っていたが、やはり原因は究明しておかないとと思った。

しかし、オレオレフレームワークがある程度動作する環境だと、結構億劫で、門外漢が強く後回しになっていたが、ようやく作業を始めた。
※E2Studio は起動が遅いし、プロジェクト全体の構成などが複雑で、出来れば触りたく無い。

スマートコンフィギュレーターが生成したプログラムを眺めていて、以下の部分に気がついた。

    /* b19 to b16 should be set the same value as the ICK bit. */
    tmp2_clock = tmp_clock;
    tmp2_clock &= 0x0F000000;
    tmp2_clock >>= 8;
    tmp_clock |= tmp2_clock;

あっ・・・

ハードウェアーマニュアルを確認すると、予約ビットの扱いがひっそり書かれていた・・・

これは、罠だよなぁー・・・、そういえば、RX631でも同じような事があったよなぁー・・・
まぁ、自分のミスではあるのだが・・・
何でそこに気がつかなかったのか悔やまれる。

今回は、PLL ベースクロックが、228MHz なら動作していたもので、微妙な不具合で、デバイスの不良なのかと、ハードウェアーの問題だと思ってしまい、ソフトの問題に気が回らなかった。

今後、予約ビットの扱いは、最新の注意が必要だと痛感した・・・
※予約ビットに特定の値を設定する必要があるなら、「----」にしないで、特定の名称を割り当てるべきと思う。


GNU-RX 8.3.0 202305 バージョンの不具合?

RX26T では、TFUv2 が採用されている。

このサポートには、新しいコンパイラが必要と思われ、GNU-RX ツールチェインを最新にしておいた。

しかし、以下のオプションを使って、「cmath」 をインクルードした状態でコンパイルすると、エラーが出る・・・

-mtfu-version=v2 -mtfu=intrinsic,mathlib

※「mathlib」の部分
※「-mtfu-version」が追加されている。

c:\programdata\gcc for renesas rx 8.3.0.202305-gnurx-elf\rx-elf\rx-elf\rx-elf\include\c++\8.3.0.202305-gnurx\cmath:1122:11: error: ‘::hypotf’ has not been declared

 using ::hypotf;

GNU-RX 8.3.0 202004 とか一つ前のバージョンだと発生しない。

これは、現在、問い合わせ中だ。

mathlib は、通常の数学関数が、TFU を利用した高速版に置き換えられるものと思う。


まとめ

今回の騒動、素直に「スマートコンフィギュレーターを使ったらどうですか?」と言われそうだが、本当にそれが素晴らしいものなら初めから使っている。
色々と、ハードルがあっても、自分の信念は貫きたい、より一層の注意力が必要と思う一件だった。

glfw3_app C++ Mupdf ライブラリ用テストアプリ

Mupdf ライブラリ

以前(数年は前)に、glfw3_app のさらに前に、一度、試していた。

その時は、Mupdf のソースコードを取ってきて、自分でコンパイルして実装した覚えがある。

最近、Mupdf のリソースは MSYS2 でもサポートされ、pacman で簡単にインストール出来るようになっていた。

そんな事もあり、glfw3_app でも Mupdf ライブラリを再び試してみた。

構成が大きく異なる・・

最近のリリースは、以前の構成とはかなり異なっている、昔のコードはそのままではコンパイル出来ない。
サンプルを観たり、ヘッダーのプロトタイプを眺めたりしながら、コンパイルが通るようになった。

しかし、リンクで必要なライブラリが足りなくて失敗する・・

色々調べて、何とかリンクまで成功。

動かすが、クラッシュする・・

簡単なコードにして、PDF ファイルを食わせてみるが、クラッシュする・・

色々調べて、呼ぶ API が足りない事に気がつく。

  fz_register_document_handlers(context_);

コンテキストを生成したら、この API を呼ぶ事がマストのようだった。

描画されない・・

だが、ちゃんと描画がされない・・

良く調べると、良かれと思って追加したインスタンスが余計だった。

  fz_separations *seps = fz_new_separations(context_, 0);
  fz_pixmap* pix = fz_new_pixmap_with_data(context_, fz_device_rgb(context_), w, h, seps, alpha, stride, rgba);

上記「seps」は、使わない場合、必要無いようだ・・

  fz_pixmap* pix = fz_new_pixmap_with_data(context_, fz_device_rgb(context_), w, h, NULL, alpha, stride, rgba);

これで、普通に描画されるようになった。

まとめ

PDF を扱う実装は、RX マイコンのハードウェアーマニュアルから、色々と必要な情報を自動で取得する事を目指していて、その前段階。
その情報を使い、デバイス関係のソースコードを自動生成したり、テストコードを生成する事を考えている。

今回の実装は、その一歩となる。

詳細は、Qiitaに投稿してある。

pdfv アプリは、PDF をプレビューするアプリで、GUI を操作するメイン部は、俺俺フレームワークの助けを借りて 500 行くらいで実装出来ている。

Mupdf ライブラリ、便利!

RXマイコンC++フレームワーク、RX220をサポート開始

RX220 マイコンをサポートする

半導体不足は未だ解消の気配は無く、RXマイコンを買うにしても、以前のような価格では流通していないし、バックオーダーで、買う事も出来ない。

RX220は、機能と価格で、CPはそんなに良くないが、秋月さんで売っているので、入手はしやすいだろうと思う。

  • DIPスイッチを逆に取り付けてしまったバージョンの基板なら比較的安価に購入できる。(1250円)
  • 以前RX72T(200MHz、RXv3コア)が10個で@600円くらいだった事を考えると、最大32MHzでRXv1コアはあまり触手が伸びない。
  • RX220はFPUも内蔵していない・・
  • 既に購入済で、積みボードになっている人もいるかもしれない。

とりあえず、RXマイコン全制覇を目論んでいるし、200番台をサポートするのは、それなりに価値がある。


秋月RX220ボードの改造

秋月さんのRX220ボードは、そのままでは多少使いづらい・・
このボードでは、内蔵フラッシュを書き換えるには、シリアル書き込みがほぼ標準的となる。
その場合、SCI1を使う事になるが、そのままだと、RSー232Cのレベル変換ICに接続されている。
今や、PCとの通信でRSー232Cを使う事は「稀」で、FT232やCP2102NなどのUSB/シリアル変換モジュールを使って、ロジックレベルで行うのが標準的となっている。
そうすると、RXマイコンのTxDは出力なので問題無いとしても、Rxdは入力となっていて、レベル変換ICの出力が接続されているので、モジュールのロジック端子を繋ぐ事ができない。
そこで、ボードのパターンをカットして、接続できるように改造した。
※何かの記事で読んだが、この「カットをする意味が判らない」と綴っている人がいた・・、これは、本当にビックリした、その程度の知識でマイコンをやってる人がいる現実に驚くばかり。
まぁ、でもマイコン掲示板で、自分で何も調べないで、いきなり質問する人や、初歩的と思えるような質問をする人、様々な人がいる現実を考えると、まぁそんなものかもしれない。


ソフトディレイの調整

RX220は最大32MHz(内蔵発振器動作)で動作する。

  • クロックジェネレーターにはPLL回路が無い為、外部にクリスタルを接続して利用する場合は、最大20MHzとなる。
  • クリスタルの発信器は、20MHzを超えると、ちょっと特殊な回路にしないと発振が安定しない(発振しない)ので、そうなっていると思う。
  • ただ、外部クロック入力でも最大20MHzなので、その他の物理的な要因が関係しているのかもしれない。
  • 内部発信器だと、正確性やジッタの問題があるとも思うが、意外と安定していると思う。
  • 内部発信器は最大50MHzで発振する事も出来るので、50MHzオーバークロックで動かしてみたが、普通に動作はするようだ。

最初、1マイクロ秒のソフト遅延を行う為、NOP命令のループ回数を調整していたが、思うように調整出来ない・・・
ある値を境に、遅くなったり、速くなったり、不思議な現象が発生した。

                for(uint32_t n = 0; n < device::clock_profile::DELAY_MS; ++n) {
                    asm("nop");
                }

・・・

少し考えたら、理由は判った、今まで、最低速度は、RX24Tの80MHzだったので、ループ回数はそれなりの値で問題無かった。
しかし、32MHzだと、ループ回数は少なく、ある値を境に、「asm("nop");」が、インライン展開されてしまう。

そこで、RX220の場合は、専用のAPIにした。

        static void delay_us() noexcept
        {
            // 定数(DELAY_MS)で指定すると、ループ数が少なくインライン展開され、予想した時間にならない為、直で’NOP’数で調整する。
            if(ICLK == 32'000'000) {  // 32MHz 用
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
            } else if(ICLK == 20'000'000) { // 20MHz 用
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
                asm("nop"); asm("nop"); asm("nop");
            } else {
                for(volatile uint8_t i = 0; i < (ICLK / 1'000'000) - 10; ++i) {
                    asm("nop");
                }
            }
        }

rx_prog でも、RX220をサポート

最初、とりあえずルネサスフラッシュプログラマーで書き込みを行ったが、非常に不安定で、書き込みに失敗、そもそも接続も出来ないなどのトラブルが多発した。
この原因は追究していないが、USBシリアルデバイスがCP2102Nなのが問題なのかと思った。

  • CP2102Nは、FTDIより高速で、同じボーレートでも、転送にかかる遅延が非常に少ない為と思った。
  • RX200系は、RXマイコン初期の物なので、あまり枯れていないのかもと思った。
  • ルネサスフラッシュプログラマーの無料版は、ノークレームなので、改修を要求する事さえ出来ない。

そこで、まず、rx_prog にRX220のプロトコルを追加する事にした。
ブートモードの説明を斜め読みした感じでは、RX63Tとほぼ同じ感じで、そのまま行けると感じた。

「rx_prog.conf」に、RX220 デバイスのプロファイルを追加して、「rx220_protocol.hpp」を追加、説明と照らし合わせた。

R5F52206 {
    group = "RX220"
    clock = 3200
    divide_sys = 1
    divide_ext = 1
    rom = 256K
    ram = 16K
    data = 8K
    comment = "; RX220 Flash:256K DataFlash:8K RAM:16K"
    rom-area  = FFFC0000,FFFFFFFF
    data-area = 00100000,00101FFF
    ram-area  = 00000000,00003FFF
}

「rx63t_protocol.hpp」ほぼ同じでOKだったが、ファイルは別けておいた。

まず、コネクションを試してみた。

 % rx_prog -d RX220 --verbose
# Platform: 'Cygwin(MSYS2)'
# Configuration file path: '/usr/local/bin/rx_prog.conf'
# Group: 'RX220'
# Serial port path: 'COM7'
# Serial port speed: 230400
# Erase Page Wait: 2000 [uS]
# Write Page Wait: 5000 [uS]
# Serial port alias: COM7 ---> /dev/ttyS6
# Serial port path: '/dev/ttyS6'
# Device: R5F52206 (first find)
#   Master clock: 32.00 MHz
#   ICLK multiplier: 1 (32.00 MHz)
#   PCLK multiplier: 1 (32.00 MHz)
Connection OK. (RX62x)
#01/01: Device: RX200 Series (LittleEndian)
#01/01: Device ID: 0x33306A37
#01/01: Clock Mode: 0x00
#01/02: Multiplier: 1
#02/02: Multiplier: 1
#01/02: Frequency Min: 32 MHz, Max: 32 MHz
#02/02: Frequency Min: 32 MHz, Max: 32 MHz
#01/01: Change baud rate: 115200
#01/01: Boot Area: FF7FC000, FF7FFFFF
#01/01: Area: FFFC0000, FFFFFFFF
#01/26: Area: FFFFF000, FFFFFFFF
#02/26: Area: FFFFE000, FFFFEFFF
#03/26: Area: FFFFD000, FFFFDFFF
#04/26: Area: FFFFC000, FFFFCFFF
#05/26: Area: FFFFB000, FFFFBFFF
#06/26: Area: FFFFA000, FFFFAFFF
#07/26: Area: FFFF9000, FFFF9FFF
#08/26: Area: FFFF8000, FFFF8FFF
#09/26: Area: FFFF4000, FFFF7FFF
#10/26: Area: FFFF0000, FFFF3FFF
#11/26: Area: FFFEC000, FFFEFFFF
#12/26: Area: FFFE8000, FFFEBFFF
#13/26: Area: FFFE4000, FFFE7FFF
#14/26: Area: FFFE0000, FFFE3FFF
#15/26: Area: FFFDC000, FFFDFFFF
#16/26: Area: FFFD8000, FFFDBFFF
#17/26: Area: FFFD4000, FFFD7FFF
#18/26: Area: FFFD0000, FFFD3FFF
#19/26: Area: FFFCC000, FFFCFFFF
#20/26: Area: FFFC8000, FFFCBFFF
#21/26: Area: FFFC4000, FFFC7FFF
#22/26: Area: FFFC0000, FFFC3FFF
#23/26: Area: 00101800, 00101FFF
#24/26: Area: 00101000, 001017FF
#25/26: Area: 00100800, 00100FFF
#26/26: Area: 00100000, 001007FF
#01/01: Program size: 256 Bytes
#01/01: ID Protect: false

問題無い。

次に、書き込み、ベリファイも試して、問題無かった。
rx_prog は、多少書き込み速度が遅いものの、安定して書き込めるし、OS-X、Linux でも同じように動作する実績がある。
※RX220 は、OS-X、Linux では試していないけど・・

rx_prog -d RX220 --progress  --write --verify sci_sample.mot
Write:  #################################################
Verify: #################################################

これで、RX220を正式サポートした事になると思う。

Makefile は、以下の部分のみ異なるだけで良く、RX220 に移る事は簡単だ。

DEVICE      =   R5F52206

RX_DEF      =   SIG_RX220

まとめ

現状、サンプルプログラムは、「FIRST_sample」、「SCI_sample」のみだが、今後拡充してゆく予定。
※基本、各プロジェクトで、Makefileを用意すればOKだが、まだ、RSPIや、RIIC(I2C)ペリフェラルの追加などをしていない。

RX220 は浮動小数点を扱うとエミュレーションになってしまうが、「utils::format」の表示関係は、内部はほぼ整数を使っているし、速度以外はそれなりに使えると思う。
もう少し安価に入手できれば・・・
それでも、32ビットなので、RL78などの8ビット系に比べて大きなアドバンテージがあるのは言うまでも無い。

Start SCI (UART) sample for 'AE-RX220' 32[MHz]
SCI PCLK: 32000000 [Hz]
SCI Baud rate (set): 115200 [BPS]
  Baud rate (real): 117647 (2.08 [%])
  SEMR_BRME: false
  SEMR_BGDM: false
CMT Timer (set):  100 [Hz]
  Timer (real): 100 [Hz] (0.00 [%])
#

現在、RX631/RX63N もサポート中で、秋月ユーザーでも、C++ フレームワークを使ってみる機会がそれなりに増えると思う。

C++ に対する嫌悪感

主にC言語しか使わない人は、C++ に対する嫌悪感が半端ない事が多い。
また、C++ は判らないし、難しそうだから近寄らない人も多い。

しかしながら、マイコン初心者(プログラムの経験が全く無い人)に教える場合、C++ から始めても、そんなに敬遠したりしない事が判っている。
※もちろん、最初はあまり多くを示さないで、簡単な事、理解しやすい事、シンプルな事から始める。
むしろ、半端にプログラム出来る人より、飲み込みが速く、応用が利く人が多いように思う、これは、教え方次第のように思う。
年齢は関係無い、若い人は頭が柔らかく、吸収する力が大きいように感じる。

C++だと、コンパイラが教えてくれる事が多く、小さなミスは、ほぼ起きなくなるし、柔軟で応用範囲が広いライブラリなど、利便性が高い。

今回 RX220 をサポートしたが、アプリケーションレベルでは変更が全くなく、同じように動作する。

今後、勉強会や、講習会、YouTubeビデオなど、学べる機会や媒体を増やしていく予定でいる。