fc2ブログ

名張市つつじが丘おもちゃ病院

三重県名張市つつじが丘でおもちゃ病院を開院しています。年中無休で修理は無料、部品代のみ実費です。おもちゃの修理依頼は tutuji@cb4.so-net.ne.jp へメールにてご連絡下さい。なお、宅配便での受け付けは行っておりません。このブログにはおもちゃ等の修理事例やツール製作などを載せていきます。故障診断や修理方法の改善等、ご意見をお寄せ下さい。

CH32V電子オルゴールVer1_2(タッチセンスのサポート)

【前振り】

CH32V事始め(タッチセンスの再挑戦) で静電容量検知方式でのタッチセンスが上手く動作したので、CH32V電子オルゴールに組み込んだ。


【設計】

①タッチ検知方式

・CH32Vでは、ハードの構造がADCのサンプルコンデンサと外部ピンを直接繋いだり切ったりできないので、CVD方式によるタッチセンスが作れない。

・そのため、フツウの静電容量検知方式 でタッチセンスを作る。

②R8CでCVD方式のタッチセンスをサポートしているので、そのソースコードをベースに静電容量検知方式への変更を行う。

③極めて短時間にADCを実行しなければならないので、ADCのサンプルタイムは最小の3サイクルに設定する。

④ノイズによるADC結果のバラつきを抑えるために複数回のADCを実行して、それらを合算した結果を評価する。

⑤環境の変化に追随するため、移動平均値を参照値として、それとの乖離を評価する。

⑥ADC値が閾値近辺であるときに、判定のバタつきを防止するため、判定処理にヒステリシス特性を与える。


【実装】

①回路図とパッド形状は CH32V事始め(タッチセンスの再挑戦) を参照。

②ソースコードはダウンロードファイルの func_CVD.c を参照。

③タッチセンス機能を実装するときは下記を宣言する。

#define CVD_EN //CVDを実装するときに宣言する

④タッチセンスのポートとオプションは下記のように宣言する。

//CVDのポート定義
#define CVD0_PORT GPIOA //CVD0のポート
#define CVD0_BIT 1 //CVD0のビット
#define CVD0_An 1 //CVD0のAn
//以下のタイマーモードとリアルモードは択一
#define CVD0_TIMER //CVD0はタイマーモード
//#define CVD0_REAL //CVD0はリアルモード


【評価】

①R8CのCVD方式と同程度に、感度と安定性が得られた(と感じた)。


【ダウンロード】

設計資料と開発プロジェクト一式は ここから ダウンロードできる。

CH32V003F4P6では
プロジェクトディレクトリは SW_F4P6
プロジェクトは SW_F4P6.wvproj
根のソースコードは SW_F4P6\User\main.c

CH32V003J4M6では
プロジェクトディレクトリは SW_J4M6
プロジェクトは SW_J4M6.wvproj
根のソースコードは SW_J4M6\User\main.c

プロジェクトを利用する際は、目的に合わせてオプションの宣言を変えること。
スポンサーサイト



  1. 2023/11/08(水) 09:31:58|
  2. 電子オルゴール+音声再生
  3. | コメント:0

CH32V電子オルゴールVer1_2(内蔵I2Cモジュールの利用)

【前振り】

先日は、CH32V電子オルゴールで内蔵SPIモジュールを使うことを可能とした。今回は、内蔵I2Cモジュールも使用可能とした。

I2Cの転送速度はSPIに比べてかなり遅いので、内蔵I2Cモジュールを使うことはCPU負荷を軽減する効果が大きい。

8ksps8ビットの音声再生を行う場合、I2Cの転送レートをでは400kbpsとすると、ソフト実装では (概算)9ビット/400kbps/125us=0.18 となり、I2Cの転送に約2割のCPUを費やすことになる。


【設計】

①従前はのピン割り当てはI2Cに関しては内蔵モジュールのピン割り当てに合わせていたため、今回の機能改善でピン割り当ての変更は無い。

F4P6のピン割り当てはVer1_1から変更なし。

CH32V電子オルゴールVer1_2(内蔵I2Cモジュールの利用)F4P6ピン割り当て

②J4M6は内蔵I2Cモジュールの信号線が外部ピンに出ているので、J4M6でも内蔵I2Cモジュールの利用が可能である。ピン割り当てはVer1_1から変更なし。

CH32V電子オルゴールVer1_2(内蔵I2Cモジュールの利用)J4M6ピン割り当て

③EVTサンプルのEEPROMアクセスのプロジェクトからコピペするので独自の設計は殆ど無いのだが、サンプルは1バイトのアクセスしかやっていないので、複数バイトの読み込みと非同期な転送の中断のやり方は試行錯誤することになってしまった。

④I2Cをソフト実装する場合は下記を宣言する。宣言しなければ内蔵I2Cモジュールが使われる。

 #define I2C_SOFT //I2Cをソフト実装するときに宣言する


【実測】

①内蔵I2C転送時の信号観測

ch3(青)-デバグ信号でH期間が転送待ち時間
CH32V電子オルゴールVer1_2(内蔵I2Cモジュールの利用)I2C読み込み待ち

・8ksps(周期は125us)で転送待ちが発生している。

拡大
CH32V電子オルゴールVer1_2(内蔵I2Cモジュールの利用)I2C読み込み待ち拡大

・待ち時間は約1.5us。実際のI2Cバス上の転送はバックグラウンドで行われていて、I2Cペリフェラルのデータレジスタから受信データの取り出し時間である。転送待ち時間は発生していないことを示している。


【ダウンロード】

設計資料と開発プロジェクト一式は ここから ダウンロードできる。

CH32V003F4P6では
プロジェクトディレクトリは SW_F4P6
プロジェクトは SW_F4P6.wvproj
根のソースコードは SW_F4P6\User\main.c

CH32V003J4M6では
プロジェクトディレクトリは SW_J4M6
プロジェクトは SW_J4M6.wvproj
根のソースコードは SW_J4M6\User\main.c
  1. 2023/11/05(日) 16:20:06|
  2. 電子オルゴール+音声再生
  3. | コメント:0

CH32V電子オルゴールVer1_2(内蔵SPIモジュールの利用)

【前振り】

CH32VはCPU性能が高くて、電子オルゴールの音質がいい 4パート演奏や16kspsの音声再生も全くストレスが無い。しかし、天邪鬼なもので、そうなると更に性能改善をしたくなる。それで、今まではSPIをソフト実装していたが、内蔵SPIモジュールを使うことも可能とした。


【設計】

①従前はADC機能を持つポートをアプリでの使用に残すべく、SPI信号はADC機能のないポートに割り当てていた。しかし、内蔵SPIモジュールが使うピンは割り当てがほぼ決まっているので、従前のピン割り当てと異なってしまう。そのため、Ver1_1からVer1_2へリビジョンアップすることにした。

ピン割り当て
CH32V電子オルゴールVer1_2(内蔵SPIモジュールの利用)F4P6ピン割り当て

②J4M6は内蔵SPIモジュールの信号線が外部ピンに出ていないので、内蔵SPIモジュールの利用はM4P6のみとなる。J4M6のプロジェクトは改変しないで(但し、ソフト実装か否かの宣言は入れているが)Ver1_2に含める。

ピン割り当て(Ver1_1から変更なし)
CH32V電子オルゴールVer1_2(内蔵SPIモジュールの利用)J4M6ピン割り当て

③EVTサンプルをコピペするので、独自の設計は無い。

④内蔵SPIにより、高速のの転送速度が得られたので、割り込みやイベントドリブンの仕掛けは講じないこととした。

⑤SPIをソフト実装する場合は下記を宣言する。宣言しなければ内蔵SPIモジュールが使われる。

 #define SPI_SOFT //SPIをソフト実装するときに宣言する

【実測】

以下の波形表示は以下となっている。

ch1(赤)-SCK
ch2(黄)-MOSI
ch3(青)-MISO
ch4(紫)-SS

①SPIソフト実装時のSPI信号観測
CH32V電子オルゴールVer1_2(内蔵SPIモジュールの利用)ソフトSPI波形

・転送時間は約7us/バイト

②内蔵SPIモジュール使用時のSPI信号観測
CH32V電子オルゴールVer1_2(内蔵SPIモジュールの利用)内蔵SPI波形1

拡大
CH32V電子オルゴールVer1_2(内蔵SPIモジュールの利用)内蔵SPI波形2

・転送時間は約1.4us/バイト

③(参考)16F1705のSPI波形

ソフト実装
CH32V電子オルゴールVer1_2(内蔵SPIモジュールの利用)参考16F1705ソフトSPI波形

内蔵SPIモジュール
CH32V電子オルゴールVer1_2(内蔵SPIモジュールの利用)参考16F1705内蔵SPI波形

④(参考)R8C/M11のSPI波形
CH32V電子オルゴールVer1_2(内蔵SPIモジュールの利用)参考R8CM11SPI波形

・比較したマイコンの中で最も性能が悪い。

・SCKが固まっている10usはPWM(タイマー)割り込み処理を実行している期間だ。割り込み処理はDC値をリングバッファからPWMレジスタへ転送しているだけなのだが、この時間が電子オルゴールでのアンダーラン発生の誘因になっている。これほど、R8Cの割り込みレイテンシーが悪いとは承知していなかったが、コンテキストの保存/回復をすべてソフトで行っていることが致命的だ。

【ダウンロード】

設計資料と開発プロジェクト一式は ここから ダウンロードできる。

CH32V003F4P6では
プロジェクトディレクトリは SW_F4P6
プロジェクトは SW_F4P6.wvproj
根のソースコードは SW_F4P6\User\main.c

CH32V003J4M6では
プロジェクトディレクトリは SW_J4M6
プロジェクトは SW_J4M6.wvproj
根のソースコードは SW_J4M6\User\main.c
  1. 2023/11/02(木) 13:15:24|
  2. 電子オルゴール+音声再生
  3. | コメント:0

CH32V電子オルゴールVer1_1(宝石箱への応用)

【宝石箱】

オルゴール付き宝石箱で、蓋を開けるとオルゴールが鳴り出し、閉じると止まる。必ずしも宝石を入れる必要は無いが、蓋の開け閉めでオルゴールを制御することがこの記事のテーマだ。

先日は PIC電子オルゴールに対して機能追加を行った のだが、今回はCH32V電子オルゴールにも同じ機能追加を行った。


【設計】

①CH32V電子オルゴールで、蓋の開け閉めをCdSで検知し、蓋を開けると鳴り出し、蓋を閉めると鳴り止むようにする。

②今までも、電子オルゴールはCdSで制御ができるようになっているが、それは「手を翳すとオンするスイッチ」として実装している。つまり、暗くなるとオンする。宝石箱では蓋を開けて明るくなるとオンしないといけない。

③明/暗の検知を反転させればよいのだが。。。

・PICとR8Cの電子オルゴールではCdSをローサイドに配置して、暗でポートがHになるようにしている。その理由は、ポートの内部ブルアップ機能を使ってCdSへの電源供給を制御することで省電力にするためだ。

・CdSをハイサイドに配置すると、暗でポートはLになって、明/暗の検知を反転させることができる。CH32Vにはポートを内部ブルダウンすることができるので、回路を宝石箱用にすれば明/暗の検知を反転させることができる。

・今回は、CdSをローサイドに配置したままで、プログラムを変更して明/暗の検知を反転させることも可能なようにした。

④タイマーモードでの検知の反転は

・CdSの評価にタイマーモードとリアルモードがある。タイマーモードでは、短オンで演奏/再生を開始し、長オンで演奏/再生を中断する。この短オンと長オンの区別は宝石箱の操作にはそぐわない。

・そのため、宝石箱の蓋の操作はリアルモードでのみ有効とする。

⑤実装方法

・明/暗の検知を宝石箱の蓋の操作にするには CdS_FUTA を宣言する。

・今までのCdSの評価では周囲の明るさの変化に追随するように、ADC結果の移動平均を計算して、それを閾値に反映している。宝石箱の蓋では周囲の明るさの変化に追随せずに、絶対的な評価が必要になる。そのため、固定閾値を CdS_THR で宣言することとした。

・宝石箱に応用するときの設定例

CH32V003F4P6では
//CdSのポート定義
#define CdS_GPIO GPIOA //CdSのポート
#define CdS_BIT 2 //CdSのビット
#define CdS_An 0 //CdSのAn
//#define CdS_INV //CdS入力は負論理(暗=L)
//以下のタイマーモードとリアルモードは択一
#define CdS_TIMER //CdSはタイマーモード
//#define CdS_REAL //CdSはリアルモード
//#define CdS_THR 100 //CdS評価の固定閾値[1/256]
//#define CdS_FUTA //CdS判定反転(明=オン)

CH32V003J4M6では
//CdSのポート定義
#if BTL==1 //コンプリ出力のとき
#define CdS_GPIO GPIOC //CdSのポート
#define CdS_BIT 4 //CdSのビット
#define CdS_An 2 //CdSのAn
#else //シングル・ブリッジ・ブレーキ出力のとき
#define CdS_GPIO GPIOA //CdSのポート
#define CdS_BIT 1 //CdSのビット
#define CdS_An 1 //CdSのAn
#endif
//#define CdS_INV //CdS入力は負論理(暗=L)
//以下のタイマーモードとリアルモードは択一
#define CdS_TIMER //CdSはタイマーモード
//#define CdS_REAL //CdSはリアルモード
//#define CdS_THR 100 //CdS評価の固定閾値[1/256]
//#define CdS_FUTA //CdSオルゴール箱のフタ判定(明=オン)する

・上記のコードは根のソースコードに置く。評価ロジックは、apl_SW.c に置く。


【ダウンロード】

設計資料と開発プロジェクト一式は ここから ダウンロードできる。

CH32V003F4P6では
プロジェクトディレクトリは SW_F4P6
プロジェクトは SW_F4P6.wvproj
根のソースコードは SW_F4P6\User\main.c

CH32V003J4M6では
プロジェクトディレクトリは SW_J4M6
プロジェクトは SW_J4M6.wvproj
根のソースコードは SW_J4M6\User\main.c
  1. 2023/10/26(木) 07:34:19|
  2. 電子オルゴール+音声再生
  3. | コメント:1

R8C電子オルゴールVer1_2(宝石箱への応用)

【宝石箱】

オルゴール付き宝石箱で、蓋を開けるとオルゴールが鳴り出し、閉じると止まる。必ずしも宝石を入れる必要は無いが、蓋の開け閉めでオルゴールを制御することがこの記事のテーマだ。

先日は PIC電子オルゴールに対して機能追加を行った のだが、今回はR8C電子オルゴールにも同じ機能追加を行った。


【設計】

①R8C電子オルゴールで、蓋の開け閉めをCdSで検知し、蓋を開けると鳴り出し、蓋を閉めると鳴り止むようにする。

②今までも、電子オルゴールはCdSで制御ができるようになっているが、それは「手を翳すとオンするスイッチ」として実装している。つまり、暗くなるとオンする。宝石箱では蓋を開けて明るくなるとオンしないといけない。

③明/暗の検知を反転させればよいのだが。。。

・今まではCdSをローサイドに配置して、暗でポートがHになるようにしている。その理由は、ポートの内部ブルアップ機能を使ってCdSへの電源供給を制御することで省電力にするためだ。

・CdSをハイサイドに配置すると、暗でポートはLになって、明/暗の検知を反転させることができる。しかし、プルダウンを制御するためのポートが必要になる。

・やはり、CdSはローサイドに配置して、プログラムを変更して明/暗の検知を反転させるのが合理的だ。

④タイマーモードでの検知の反転は

・CdSの評価にタイマーモードとリアルモードがある。タイマーモードでは、短オンで演奏/再生を開始し、長オンで演奏/再生を中断する。この短オンと長オンの区別は宝石箱の操作にはそぐわない。

・そのため、宝石箱の蓋の操作はリアルモードでのみ有効とする。

⑤実装方法

・明/暗の検知を宝石箱の蓋の操作にするには CdS_FUTA を宣言する。

・今までのCdSの評価では周囲の明るさの変化に追随するように、ADC結果の移動平均を計算して、それを閾値に反映している。宝石箱の蓋では周囲の明るさの変化に追随せずに、絶対的な評価が必要になる。そのため、固定閾値を CdS_THR で宣言することとした。

・宝石箱に応用するときの設定例

//CdSのポート定義
#define CdS_ADINSEL 0b01000000 //CdSのADINSEL値
#define CdS_ADMOD 0b00000011 //CdSのADMOD値
#define CdS_ADn ad0 //CdSのADレジスタ
#define CdS_PU pu1_2 //CdSのプルアップビット
//#define CdS_INV //CdS入力は負論理(暗=L)
//以下のタイマーモードとリアルモードは択一
#define CdS_TIMER //CdSはタイマーモード
//#define CdS_REAL //CdSはリアルモード
//#define CdS_THR 100 //CdS評価の固定閾値[1/256]
//#define CdS_FUTA //CdSオルゴール箱のフタ判定(明=オン)する

・上記のコードは根のソースコードに置く。評価ロジックは、apl_SW.c に置く。


【ダウンロード】

設計資料と開発プロジェクト一式は ここから ダウンロードできる。

ワークスペースは orgel.hws
プロジェクトは orgel_SW_M11
根のソースコードは orgel_SW_M11.c
  1. 2023/10/26(木) 07:20:24|
  2. 電子オルゴール+音声再生
  3. | コメント:0

PIC電子オルゴールVer7_6(宝石箱への応用)

【宝石箱】

オルゴール付き宝石箱で、蓋を開けるとオルゴールが鳴り出し、閉じると止まる。必ずしも宝石を入れる必要は無いが、蓋の開け閉めでオルゴールを制御することがこの記事のテーマだ。

この宝石箱の蓋の機能は随分昔に作り込んだと思うのだが、いつの間にか揮発してしまっていた。


【設計】

①PIC電子オルゴールで、蓋の開け閉めをCdSで検知し、蓋を開けると鳴り出し、蓋を閉めると鳴り止むようにする。

②今までも、電子オルゴールはCdSで制御ができるようになっているが、それは「手を翳すとオンするスイッチ」として実装している。つまり、暗くなるとオンする。宝石箱では蓋を開けて明るくなるとオンしないといけない。

③明/暗の検知を反転させればよいのだが。。。

・今まではCdSをローサイドに配置して、暗でポートがHになるようにしている。その理由は、ポートの内部ブルアップ機能を使ってCdSへの電源供給を制御することで省電力にするためだ。

・CdSをハイサイドに配置すると、暗でポートはLになって、明/暗の検知を反転させることができる。しかし、プルダウンを制御するためのポートが必要になる。

・やはり、CdSはローサイドに配置して、プログラムを変更して明/暗の検知を反転させるのが合理的だ。

④タイマーモードでの検知の反転は

・CdSの評価にタイマーモードとリアルモードがある。タイマーモードでは、短オンで演奏/再生を開始し、長オンで演奏/再生を中断する。この短オンと長オンの区別は宝石箱の操作にはそぐわない。

・そのため、宝石箱の蓋の操作はリアルモードでのみ有効とする。

⑤実装方法

・明/暗の検知を宝石箱の蓋の操作にするには CdS_FUTA を宣言する。

・今までのCdSの評価では周囲の明るさの変化に追随するように、ADC結果の移動平均を計算して、それを閾値に反映している。宝石箱の蓋では周囲の明るさの変化に追随せずに、絶対的な評価が必要になる。そのため、固定閾値を CdS_THR で宣言することとした。

・宝石箱に応用するときの設定例

//CdSのポート定義
#define CdS_TRIS TRISC //CdSのTRISレジスタ
#define CdS_WPU WPUC //CdSのWPUレジスタ
#define CdS_ANSEL ANSELC //CdSのANSELレジスタ
#define CdS_BIT 3 //CdSのビット番号(RC3)
#define CdS_CHS 7 //CdSのADCチャネル番号(RC3)
//#define CdS_INV //CdS入力は負論理(暗=L)
//以下のタイマーモードとリアルモードは択一
//#define CdS_TIMER //CdSはタイマーモード
#define CdS_REAL //CdSはリアルモード
#define CdS_THR 100 //CdS評価の固定閾値[1/256]
#define CdS_FUTA //CdSオルゴール箱のフタ判定(明=オン)する

・上記のコードは根のソースコードに置く。評価ロジックは、apl_SW.c に置く。


【ダウンロード】
orgel7_6の設計資料と開発プロジェクト一式は ここから ダウンロードできる。
  1. 2023/10/25(水) 19:57:42|
  2. 電子オルゴール+音声再生
  3. | コメント:0

CH32V電子オルゴールVer1_1(J4M6もサポート)

【前振り】
CH32V電子オルゴールはPIC電子オルゴールから 全曲の移行が終わって 一段落したのだが、サポートデバイスがF4P6だけだった。J4M6も比較的廉価に流通していて、これもサポートすることにした。


【設計】

①F4P6での複数のピンがJ4M6では一つのピンに集約されている。イメージとしては、内部の複数のピンが一つの外部ピンへ繋がれていると見られる。そのため、出力が競合しないように、ピンのポート構成(CFGLR)を適切に設定しないといけない。

②J4M6は、メモリ容量はF4P6と同じだが、8ピンなので機能面で制約が生じる。

・F4P6では出力タイプ(BTL)を変えてもPWMの正相および逆相の出力ピンが変わらないようにピン割り当てを行うことができたが、J4M6ではそれは無理だった。

・ブリッジ・ブレ―キ出力時はSW・CdS・NOISEをフル実装できない。

・SPIのピン数を節約するため、2線SPIでの接続とする。

・機能設定に因っては、デバグ情報出力ピンの割り当てを替える必要がある。


【ダウンロード】

設計資料と開発プロジェクト一式は ここから ダウンロードできる。

プロジェクトディレクトリは SW_J4M6
プロジェクトは SW_J4M6.wvproj
根のソースコードは SW_J4M6\User\main.c

ポート割り当てなどのハード情報は根のソースコードに含まれている。

songデータとonpuデータは 最上位ディレクトリにある。


【カスタマイズ】

①オルゴール演奏と音声再生のカスタマイズ項目(BTL、PART_Nなど)は SW_J4M6\User\orgel_cnf.h にある。

②曲の収容を設定するソングインデックスは SW_J4M6\User\song_idx.s にある。

③収容する音声を設定する音声インデックスは SW_J4M6\User\main.c にある。
  1. 2023/09/23(土) 12:03:32|
  2. 電子オルゴール+音声再生
  3. | コメント:0

R8C電子オルゴールVer1_2(songファイルとonpuファイルの標準化)

【標準化】

・今までPIC、LPC、STM32、R8C、CH32Vといろんなマイコンに電子オルゴールを載せて来たが、songデータとonpuデータがそれぞれのマイコン毎にインプリメントが異なってきている。

・それぞれの時点で最善と思うようにやってきたのだが、結果として、てんでんばらばらな状況になってしまった。

・これまでの経験から各マイコンの事情が判ってきて、直近のCH32V003でのインプリメント を標準として、他のマイコンへ横展開していく。一言でいえば、各マイコンで同じsongファイルとonpuファイルを使う、ってことだ。

・今回は、R8C電子オルゴールに適用した。Ver1_1に対して機能の変更はないが、songファイルとonpuファイルが全面的に更改となるので、Ver1_2とした。

【設計】

①変更はsongファイルとonpuファイルのみとする。

②標準化されたsongファイルとonpuファイルをpic-asで期待通りに解釈させるために、下記の宣言を行う。

//==============================================
//songデータとonpuデータの標準化のための設定
//==============================================
#define bgn_mac #pragma asm //アセンブラコードの始まり
#define end_mac #pragma endasm //アセンブラコードの終わり
#define asb_mac #pragma asm //アセンブラコードの始まり(onpuコードの途中)
#define ase_mac #pragma endasm //アセンブラコードの終わり(onpuコードの途中)
#define NULL 0 //NULLを0とする

【ダウンロード】

設計資料と開発プロジェクト一式は ここから ダウンロードできる。

ワークスペースは orgel.hws
プロジェクトは orgel_SW_M11
根のソースコードは orgel_SW_M11.c
  1. 2023/09/19(火) 12:54:04|
  2. 電子オルゴール+音声再生
  3. | コメント:0

PIC電子オルゴールVer7_6(songファイルとonpuファイルの標準化)

【標準化】

・今までPIC、LPC、STM32、R8C、CH32Vといろんなマイコンに電子オルゴールを載せて来たが、songデータとonpuデータがそれぞれのマイコン毎にインプリメントが異なってきている。

・それぞれの時点で最善と思うようにやってきたのだが、結果として、てんでんばらばらな状況になってしまった。

・これまでの経験から各マイコンの事情が判ってきて、直近のCH32V003でのインプリメント を標準として、他のマイコンへ横展開していく。一言でいえば、各マイコンで同じsongファイルとonpuファイルを使う、ってことだ。

・今回は、PIC電子オルゴールに適用した。Ver7_5に対して機能の変更はないが、songファイルとonpuファイルが全面的に更改となるので、Ver7_6とした。

【設計】

①標準化はsongファイルとonpuファイルのみとする。

②標準化されたsongファイルとonpuファイルをpic-asで期待通りに解釈させるために、下記の宣言を行う。

//==============================================
//songデータとonpuデータの標準化のための設定
//==============================================
#define bgn_mac //bgn_macを殺す
#define end_mac //end_macを殺す
#define asb_mac //asb_macを殺す
#define ase_mac //ase_macを殺す
#define NULL 0 //NULLを0とする

【ダウンロード】
orgel7_6の設計資料と開発プロジェクト一式は ここから ダウンロードできる。
  1. 2023/09/18(月) 10:52:28|
  2. 電子オルゴール+音声再生
  3. | コメント:0

CH32V電子オルゴールVer1_1(全曲の移行が完了)

【前振り】
先般は、CH32V003の電子オルゴールの初版を公開した。但し、実装したのは「AIAI」の1曲だけだった。

その後、PIC電子オルゴールの最新版から全曲の移行を実施してきた。それが完了したので、公開する。

移行作業の中でバグ改修とメモリ削減の改善も実施した。


【ダウンロード】

設計資料と開発プロジェクト一式は ここから ダウンロードできる。

プロジェクトディレクトリは SW_F4P6
プロジェクトは SW_F4P6.wvproj
根のソースコードは SW_F4P6\User\main.c

ポート割り当てなどのハード情報は根のソースコードに含まれている。

songデータとonpuデータは 最上位ディレクトリにある。


【カスタマイズ】

①オルゴール演奏と音声再生のカスタマイズ項目(BTL、PART_Nなど)は SW_F4P6\User\orgel_cnf.h にある。

②曲の収容を設定するソングインデックスは SW_F4P6\User\song_idx.s にある。

③収容する音声を設定する音声インデックスは SW_F4P6\User\main.c にある。


【今後の課題】

①songデータとonpuデータの標準化

・今までPIC、LPC、STM32、R8C、CH32Vといろんなマイコンに電子オルゴールを載せて来たが、songデータとonpuデータがそれぞれのマイコン毎にインプリメントが異なってきている。

・それぞれの時点で最善と思うようにやってきたのだが、結果として、てんでんばらばらな状況になってしまった。

・それで、マイコンの種類を超えて、songデータとonpuデータの標準化を行いたい。

・今回のCH32V003でのインプリメントを標準として、他のマイコンへ横展開していく。そうすれば、移行ツールは不要となる。
  1. 2023/09/17(日) 14:39:14|
  2. 電子オルゴール+音声再生
  3. | コメント:0

CH32V電子オルゴールVer1_1(初版)

【前振り】

鳴り物おもちゃのICが壊れたとき、殆どの場合は PIC電子オルゴール で換装している。しかし、新型コロナ感染拡大の影響で半導体の流通価格が高騰し、秋月のPICも値上がりが続いていておもちゃ修理には使い辛くなってきた。

PICに代わる廉価なマイコンで、秋月からR8C/M11Aが@50円で販売開始されたので、先般は、R8CにPIC電子オルゴールを移植した

その後、秋月からCH32V003F4P6が@50円で販売開始された。このマイコンは、AliExpressでは送料込み@28円だった。それで、これにも電子オルゴールを移植した。

これで、電子オルゴールを載せられるマイコンはPIC、LPC、STM32、R8C、CH32Vになった。いろんなマイコンをサポートしておけば、実際におもちゃの修理を行う時点で廉価なマイコンを選ぶことができる。


【設計】

①機能要件

PIC電子オルゴールと同等とする。

・4パートのオルゴール演奏、音符データの演奏とキーボード演奏の動作を可能とする。

・エンベロープ、ベロシティ、ピッチベンド、音源切り替えなどの演奏表現もPIC電子オルゴールとおなじ。

・8ビット8kspsの音声再生、音声データはプログラムメモリ・I2Cメモリ・SDカード・SPIメモリに置く。

・オルゴール演奏と音声再生、おもちゃの周辺回路(LED点滅やモーター駆動など)の制御をコンカレントに実行可能とする。

・オーディオ出力はPWMによるD/A変換で行う。

・修理対象のおもちゃに合わせたアプリ処理のカスタマイズが簡単にできる。

②開発言語と環境

・CPUはPICよりも速いので、C言語で開発する。

・R8C電子オルゴールがC言語で書かれているので、それをベースに改変する。R8C電子オルゴールはPIC電子オルゴールの最新機能が含まれている。

・開発環境は本家純正のMounRiverStudioとする。環境構築は ここを 参照。

③ソングデータの持ち方

・音符データ中にはリピートを実現するために分岐の記述が必要だが、C言語ではデータのオフセットを把握することができないので、分岐先を表現できない。そのため、onpuデータはアセンブラで書くしかない。

・CH32Vのインラインアセンブラの書き方が判らなかったので、純粋にアセンブラで書く。C言語と共有する宣言値はC言語とアセンブラで共有するヘッダファイルに置く。そのため、プリプロセッサ疑似命令(#define等)のみで書くこととする。

・CH32Vのアセンブラマクロの書き方が判らなかったので、プリプロセッサ疑似命令(#define等)で書くことにした。

・CH32V003F4P4はプログラムフラッシュが16kバイトあり、16F1705と同程度の曲数が収容可能。

④音符データの枠組み

CH32V電子オルゴールVer1_1(初版)音符データの枠組み

R8Cと同じ。

⑤ソースコードの構成

・MounRiverStudioではプロジェクトディレクトリ内のすべての .c と .s がbuildの対象にされてしまう。電子オルゴールでは個別のアプリによって必要なコードのみをbuild対象にしたい。そこで、アプリに固有のコードのみをプロジェクトディレクトリ内に置き、どのアプリにも共通に使うコードはプロジェクトディレクトリの一つ上のディレクトリ階層におき、適宜、#includeで呼び込むことにした。但し、MounRiverStudioで用意されるコードは元々の配置に従う。

 個別のアプリの根のソースコード main.c

 共通に使うコードは main.c以外のファイル(orgelエンジン、onpuファイル、songファイル、各種波形ファイル、共通のコードなど)

・ファイルの構成

main.c 個別のアプリの根のソースコードで、ファイル名はmain.cだがmain()は含まない。各種設定値の宣言と必要なコードの呼び込みを行う。

asm.h 音符データ(アセンブラ)用ヘッダファイル(C言語側とも共有する)

dev_xxx.c デバイス依存処理(PWM)

apl_xxx.c アプリケーション処理(Sleepを含む)

func_xxx.c 基本機能の処理(SW、CdS、CVD)

song_xxx.c ソングデータ

onpu_xxx.c 音符データ

wave_xxx.c 音源波形

enve_xxx.c エンベロープ波形

pitch_xxx.c ピッチベンド波形

voice_xxx.c 音声データ

orgel.c エンジン部の処理で、main()はここにある。

orgel.h C言語用ヘッダファイル

orgel.inc インラインアセンブラ用ヘッダファイル

⑤PWMの設定

・内部オシレータが48MHzなので、PWMの1ステップは1/48MHzの2のべき乗倍になる。

・ステップ数を1500にするとPWM周期は31.25usになる。

・サンプリングレートを8kspsに合わせるとDC更新周期は125usになり、上記のPWM周期をソフトで1/4にプリスケールすればよい。

・8ビットPCM値からDC値への変換で乗算が必要になるが、CH32Vは乗算命令を持っているのでCPU負荷を上げずに可能である。

⑥ピン割り当て

・出力タイプを変更してもPWMの出力ピンが変わらないようにする。その結果、正相はPC3、逆相はPC6の組み合わせしか無かった。

・アナログ入力ピンはアプリの個別の応用のためにできるだけ残しておく。

・SWIO機能はISPのために残しておき、デバグ信号の出力ピンに割り当てる。


【実装】

①実装の結果はダウンロードファイルのソースコードを参照。

・現時点では曲目は「AIAI」の1曲のみ。

・出力タイプはBTL=0、1、2、3。

・音声データはI2Cメモリ、SPIメモリ、SDカード。

・機械SWを1個(最大4個)、CdS入力を1個、ノイズセンスを1個(最大4個)実装。

②非稼働時の消費電流実測値は、機械SWのみの場合は12uA、CdS・ノイズセンスを実装する場合は30uAだった。

③設計資料と開発プロジェクト一式は ここから ダウンロードできる。

プロジェクトディレクトリは SW_F4P6
プロジェクトは SW_F4P6.wvproj
根のソースコードは SW_F4P6\User\main.c

④デモ演奏

28円のマイコンから出てくる音がこれ

CH32V003F4P6はコストパフォーマンスが素晴らしい。今すぐAliExpressで注文。


【今後の作業】

①songデータ、onpuデータ、波形データをPIC電子オルゴールVer7_5から移行する。

・今まで各種のマイコンへ移植を行ってきたが、onpuデータの書き方はそれぞれのやり方で、都度移行処理を行ってきた。その経緯から、プリプロセッサで書く方法がポータビリティが良いように思う。

・それで、PIC電子オルゴールで、onpuデータをプリプロセッサ式にできるかどうかの評価を行ってから、CH32Vへの移行を考えることとする。
  1. 2023/09/13(水) 19:21:03|
  2. 電子オルゴール+音声再生
  3. | コメント:0

R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)

【前振り】
R8C電子オルゴールでのsongインデックスの書き方に問題点を感じていて、改善を行った。


【従前の書き方】

・onpuデータは、その中で流れの分岐(リピート演奏)が必要だが、C言語でのデータの初期値設定では飛び先のオフセットを式で表せない。オフセット計算を言語処理でやってくれないと実用性が無い。そのため、onpuデータはオフセット計算ができるインラインアセンブラで記述するしかない。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)onpuデータ例
 上記の最下行のjp1_macが分岐のコードで、パラメータで分岐先のオフセットを指定している。

・songデータはパート数が不定であり可変長となるため、C言語の構造体では初期値設定ができず、インラインアセンブラで記述せざるを得ない。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)songデータ従前
上記はパート数が2のときのsongデータで、パート個別部が2つある。3パートの曲の場合はパート個別部が3つになる。

・songインデックスは、その中にソングデータへのポインタを含むため、インラインアセンブラで記述するのが効率的だ。

・songデータへのポインタ配列をインラインアセンブラで記述し、それを実体とするC言語の関数「song_idx()」を作った。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)songインデックスの書き方従前

 1曲毎に#defineを挿入しているが、これは後で纏めてsongファイルとonpuファイルの実体を#includeするための記述だ。

 son_macの定義は下記の通りで、songデータへのポインタを設定している。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)son_mac従前

・C言語からは、song_idx()をsongインデックスの構造体である「struct SONG_IDX」のポインタへキャストしてアクセスする。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)songインデックス構造体従前

・問題はsong_idx()の中にインラインアセンブラで記述したデータが「struct SONG_IDX」の定義通りに整然と隙間なく配置されることが保証されるのかどうかと言うことだ。コンパイラによって、関数の先頭部分に予期せぬコードが埋め込まれるようなことは無いのだろうか。


【改善のA案】

・その後、コンパイラのマニュアルに「アセンブリとのリンク方法」が説明されているのを見た。アセンブラのラベルをextern宣言すればC言語から参照できる。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)Cからアセンブラ呼出し

・上記の例に従って、song_idxの書き方を改善しようとしたが、問題点があった。extern宣言は前方参照が許されないため、参照する位置よりも上にextern宣言を書かないといけない。電子オルゴールでは、songインデックスの記述で収容曲と順番が決まる仕組みになっているので、songインデックスが書かれた後でないと必要なextern宣言が決まらない。これが矛盾してしまう。

・extern宣言は余分にあっても、極端に言えば実在しないラベルが書かれていてもコンパイルエラーにはならず、メモリリソースも消費しない。そこで、全曲分のexternを記述したsong.txtファイルを作って、songインデックスの上で#includeするようにした。

・song.txtの内容は下記の通り。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)song.txt改善案A

・その下にsongインデックスを書く。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)songインデックス改善案A

・songデータのラベルの先頭には’_’を付けておく。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)songデータ改善案A


【改善のB案】

・改善のA案では、新曲をサポートする都度、song.txtファイルにも追加することが必要になる。これまでも、song.hファイルとsong.cファイルを作り直す必要があったので五十歩百歩なのだが、できれば手入れは少なくできた方が良い。

・もう一つの事情があって、そもそもsongインデックスをC言語で書きたいのは実装曲数をsizeof()で表しかったからだ。先般、ランダム演奏・再生をサポートしたときに曲番号・音声番号を乱数で加算するようにした。加算後の曲番号・音声番号が実装数に収まるようにしなければならないが、その計算を早くするために乱数を予め実装数に応じたビット数でマスクしておくことを考えていた。このマスクパターンは実装数を#ifで切り分けて、#defineで静的に定義しようとしていたが、C言語仕様ではsizeof()は#ifの中で使えないことが判った。そのため、マスクパターンは実装数から動的な計算により定めるしかなく、期待した改善は見込めなくなった。

 下記コードの#ifはコンパイルエラーになる。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)改善案Aで失敗したマスクパターン定義

・それで、songインデックスの実体はインラインアセンブラで書くのだが、それをC言語の関数で包むのではなく、songインデックスの先頭をextern宣言でC言語からリンクする書き方にした。曲毎にexternを宣言する必要は無い。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)songインデックス改善案B
 上記コードの最後の行が、C言語からsongインデックスをアクセスする入り口になる。

・具体的には下記のコードでアクセスする。
R8C電子オルゴールVer1_1(songインデックスの持ち方の改善)songインデックスアクセス改善案B

・「改善」とは言え、初めからそうして置けばよかっただけのことだが。。。


【ダウンロード】

R8Cd遠視オルゴールの設計資料と開発プロジェクト一式は ここから ダウンロードできる。

ワークスペースは orgel.hws
プロジェクトは orgel_SW_M11
根のソースコードは orgel_SW_M11.c
  1. 2023/07/21(金) 09:23:11|
  2. 電子オルゴール+音声再生
  3. | コメント:0

PIC電子オルゴールVer7_5(音声出力のポップノイズ対策)

【前振り】

電子オルゴールや音声再生などでの音声出力では、非稼働時の消費電流を抑えるため、非稼働時はLレベルを出力している。稼働時のレベル(平均)は出力タイプによって異なり、例えばBTL=0(シングル出力)の場合はVdd/2になる。そのため、非稼働から稼働に移るとき、また、稼働から非稼働に移るときにポップノイズが発生する。そのポップノイズを抑えるやり方について整理した。

【出力タイプについて】

①音声出力の出力タイプは、機能改善により変わってきているが、現在は次のようになっている。

・BTL=0(シングル出力)
 Tr1石のバッファアンプでスピーカを駆動する。
 スピーカには直流成分が流れる。
 電力効率は悪い。

・BTL=1(コンプリ出力)
 正相出力と、そのコンプリ波形を出力する。音声レベルが0のときでも、50%デューティのPWMでスピーカが駆動される。電力効率はやや悪い。
 ハイサイドにバッファを置く場合にはコンプリ出力を使うと都合が良い。

・BTL=2(ブリッジ出力)
 正相と逆相のブリッジ回路を駆動する信号を出力する。
 音声レベルが0のときは、スピーカは駆動されず、電力効率が良い。
 高インピーダンススピーカや圧電スピーカをPICのポートで直接鳴らす場合には外付けアンプが要らず都合が良い。
 ベアなHブリッジを繋ぐと音質が悪い。

・BTL=3(ブレーキ出力)
 正相と逆相のブレーキング機能付きのブリッジ回路を駆動する信号を出力する。
 音声レベルが0のときはスピーカは駆動されず電力効率が良い上に、制動によって音質が良い。

②それぞれの出力タイプ毎にポップノイズ対策を行っている。

【当初のポップノイズ対策】

PIC電子オルゴールVer7_5(音声PWM出力でのポップノイズ対策)当初のやり方

①BTL=0(シングル出力)

・非稼働時はLレベル(DC=0%)を出力している。稼働時の音声レベルが0ではVdd/2(DC=50%)となる。

・音声出力の開始時にLレベルからVdd/2へ急激にレベルが変わることによってポップノイズが出る。

・そこで、DCを0%から50%まで徐々に変化させる、つまりランプ出力をさせることでレベルの変化が音として聴こえないようにするのがポップノイズ対策の考え方だ。

・音声出力の終了時はDC=50%から0%まで、徐々に変化させる。

②BTL=1(コンプリ出力)

・非稼働時は正転と逆転ともLレベルを出力している。稼働時は音声レベルが0では正転はVdd/2(DC=50%)、逆転は正転の相補波形となる。

・そこで、BTL=0と同様に、DCを0%から50%まで徐々に変化させる。

・音声出力の終了時はDC=50%から0%まで、徐々に変化させる。

③BTL=2(ブリッジ出力)

・非稼働時は正転と逆転ともLレベルを出力している。稼働時は音声レベルが0では非稼働時と同じに正転と逆転ともLレベルを出力する。

・つまり、ポップノイズ対策は不要である。

④BTL=3(ブレーキ出力)

・非稼働時は正転と逆転ともLレベルを出力している。稼働時は音声レベルが0では正転と逆転ともHレベルを出力する。

・そこで、BTL=0と同様に、DCを0%から100%まで徐々に変化させる。

・音声出力の終了時はDC=100%から0%まで、徐々に変化させる。

【現在のポップノイズ対策】

PIC電子オルゴールVer7_5(音声PWM出力でのポップノイズ対策)現在のやり方

①実は、BTL=1とBTL=3ではポップノイズ対策は不要だ。

・非稼働時と稼働時でレベルが大きく変化するのだが、正転と逆転が同じ変化となるので信号間には相対的な変化が現れない。

・つまり、非稼働から稼働に、また、稼働から非稼働に移るときに正転と逆転のレベルを階段状に変えてもポップノイズは発生しない。

②BTL=2では非稼働時と稼働時のレベルがともに0であるので、元々ポップノイズ対策は不要だ。

③纏めると、BTL=0(シングル出力)の場合だけポップノイズ対策が必要であり、そのやり方は従前どおりランプ出力によって行う。

④PICやR8Cなどデバイスの種類に関わらず、音声を出力するプロジェクトでは全般的にこのやり方を採っている。

⑤現在はこのやり方で開発しているが、古いプロジェクトでは「無用なランプ出力」が残っているものがあるかも知れない。
  1. 2023/07/15(土) 18:09:10|
  2. 電子オルゴール+音声再生
  3. | コメント:0

R8C電子オルゴールVer1_1(ランダム演奏・再生)

【前振り】

PIC電子オルゴール や R8C音声再生 でランダム演奏・再生をサポートしたので、R8C電子オルゴールでもランダム演奏・再生をサポートした。


【設計と実装】

①ランダマイズの種は、R8C音声再生と同じやり方で、ダミーのADCを実行した結果を使う。

②電源オンで自動開始する場合とSW等の操作で開始する場合の両方でランダマイズが可能とした。

③ランダマイズの要否は下記の宣言で指定する。

#define KYOKU_RAND //曲番号をランダマイズするときに宣言する
#define ONSEIN_RAND //音声N番号をランダマイズするときに宣言する
#define ONSEII_RAND //音声I番号をランダマイズするときに宣言する
#define ONSEIC_RAND //音声C番号をランダマイズするときに宣言する
#define ONSEIS_RAND //音声S番号をランダマイズするときに宣言する


【ダウンロード】

設計資料と開発プロジェクト一式は ここから ダウンロードできる。

ワークスペースは orgel.hws
プロジェクトは orgel_SW_M11
根のソースコードは orgel_SW_M11.c


【使い方のコツ】
①ランダマイズの種を取得するためのダミーのADCはポートを内部プルアップ・開放状態で実行している。適切なADCを得るためにはポートに若干の容量負荷があるとよい。また、抵抗負荷は避ける必要がある。

②SWなどを繋いでいる場合はその配線が容量負荷となる。真に開放状態である場合には10pF程度のコンデンサを付けるとよい。
  1. 2023/07/10(月) 18:36:55|
  2. 電子オルゴール+音声再生
  3. | コメント:0

モータードライバIC(L9110S)でスピーカ駆動

【前振り】
以前に、モータードライバICのTC118SとMX08でスピーカを駆動する ことの可否を評価した。

今回は、L9110Sを評価した。

【L9110Sについて】

・L9110の名前を冠したデバイスが各社から提供されていて、どれがオリジナルなのかも判らない。

・各社のデータシートを見ると、真理値表が、入力が共にLの状態で出力が共にLになったり、入力が共にHの状態で出力がともにHighZになったり、(僕の)常識から外れた仕様になっているものがある。

モータードライバIC(L9110S)でスピーカ駆動入出力論理L9110

モータードライバIC(L9110S)でスピーカ駆動入出力論理L9110B

モータードライバIC(L9110S)でスピーカ駆動入出力論理L9110S

・この記事では 「入力が共にLとなる動作形態をブリッジ出力」 「共にHとなる動作形態をブレーキ出力」 と区別している。L9110Sでは「ブレーキ出力」の入力状況でも出力の実態はブレーキにはならない。


【評価内容】
・出力ピンを100Ωの抵抗でGNDへ落とした回路で信号遅延を測定する。

・ブリッジ出力とブレーキ出力について測定する。

・貫通電流の発生の有無も確認する。

【評価結果】

①信号観測結果

・ブリッジ出力オン遅延
モータードライバIC(L9110S)でスピーカ駆動ブリッジ出力オン遅延
信号遅延は殆どない。

・ブリッジ出力オフ遅延
モータードライバIC(L9110S)でスピーカ駆動ブリッジ出力オフ遅延
信号遅延が4usもある。

・ブレーキ出力オン遅延
モータードライバIC(L9110S)でスピーカ駆動ブレーキ出力オン遅延
信号遅延は殆どない。

・ブレーキ出力オフ遅延
モータードライバIC(L9110S)でスピーカ駆動ブレーキ出力オフ遅延
信号遅延が4usもある。

②電源電流の観測結果

・ローサイドに電流センス用の抵抗として50Ωを挿入して、その両端の電圧を観測した。

・ブリッジ出力
モータードライバIC(L9110S)でスピーカ駆動ブリッジ出力電源電流
貫通電流は発生していない。

・ブレーキ出力
モータードライバIC(L9110S)でスピーカ駆動ブレーキ出力電源電流
貫通電流は発生していない。

③評価

・ブリッジ出力とブレーキ出力でオフ遅延が同じ程度になっていて、ドライバ段でオフ遅延が発生していると思われる。

・Tr(SS8050等)エミッタ接地のバッファ回路での遅延は2us以下である。

(参考)SS8050での遅延
モータードライバIC(L9110S)でスピーカ駆動SS8050遅延

L9110Sのオフ遅延の4usはSS8050よりも悪い。PWM周期(PIC電子オルゴールでは32us)に対して無視できるレベルではなく、音質に影響すると思われる。

・貫通電流は発生しないので、マイコン側でデッドバンドを設けなくても安全に使用できる。

・L9110Sはスピーカ駆動に使えなくはないが、MX08の方を推奨する。
  1. 2023/07/05(水) 19:55:40|
  2. 電子オルゴール+音声再生
  3. | コメント:0

PIC電子オルゴールVer7_5(ランダムに演奏・再生)

【前振り】

電子オルゴールや音声再生で、ランダムに演奏・再生する機能を要望されることがある。先日は 「R8Cで音声再生」 でランダマイズ機能を実装した。

今回は「PIC電子オルゴール」に実装した。

SWの場合はオンされている時間、タッチセンスや音声SWの場合はADC結果、などが都度変化するのでそれらをランダマイズの種として利用できるのだが、自動演奏・再生の場合には操作が無いので、そのような場合にランダム演奏・再生を実装する方法を検討した。


【設計】

①ランダムになり得るデータ

・「R8Cで音声再生」ではADC結果が揺らぐことを利用して、ランダマイズの種とした。

・「PIC電子オルゴール」のSWモデルでは、操作入力に使うポートはSW・CdS・CVDがそれぞれ1本ずつ割り当てられている。SWにはRA3が充てられていて、これはADCが使えない。CdSポートは外部に回路が繋がっているのでADC結果の揺らぎは期待できない。CVDポートはSPIのSSと共用していて、このポートをランダマイズの種として利用するには2線SPIにするしかない。

・ポートの割り当てを替えるとテストボードの変更が必要になるので避けたい。

・そこで、31kHz内部オシレータを使うことにする。ポート割り当てへの影響が無くなる。

②31kHz内部オシレータをTMR1の入力クロックにして、TMR1のカウント値をランダマイズの種とする。


【実装】

①PIC電子オルゴールVer7_5のSWモデルのプロジェクトに「ランダム再生」の機能を実装した。


【ダウンロード】

orgel7_5の設計資料と開発プロジェクト一式は ここから ダウンロードできる。
  1. 2023/06/27(火) 19:41:11|
  2. 電子オルゴール+音声再生
  3. | コメント:0

PIC電子オルゴールVer7_5(電子オルゴール開発の所感)

長年に渡りPIC電子オルゴールを開発してきているが、その取り組みでの所感を表しておきたい。

①PIC電子オルゴールの開発経緯

・鳴り物おもちゃの修理にPIC電子オルゴールを初めて適用したのは2006年だった。当時は廉価なPIC(16F648)にはPWMが内臓されていなかったので、ビープ音をそれぞれのポートに出力する2パート演奏だった。(orgel)

・2012年にPICエンハンスドコアが廉価に出回り始めたので、PWM出力に替えて音質が改善された。(orgel2)

・2015年には音源とエンベロープを波形ファイルで設定できるように改善し、演奏表現が強化された。(orgel5)

・その後、音源波形やエンベロープ波形の動的変更、転調機能などをサポートしてきている。(orgel7_5)

②演奏パート数

・PIC電子オルゴールの最大パート数は、設計上は4パートであるが、音声再生とコンカレント実行するとアンダーランが発生し、実質的に3パート演奏が上限になっている。

・おもちゃ修理への適用実績から必要なパート数は標準で2パート、多くしても3パートで十分と感じている。

・ネット上には無闇にパート数を多くしている電子オルゴールが発表されているが、サンプル音を聴くと雑音が重なり合っているようにしか聴こえない。

・パート数を増やすよりも、豊かな音色の音源と多彩な演奏表現が電子オルゴールには重要だと思う。

③PIC電子オルゴールのサンプル音

・糸魚川のDr.渡辺氏が作った「RAILWAY」を演奏したものだが、これは2パート演奏ながら素晴らしい演奏表現をしている。
RAILWAY
電子オルゴールはマイコンという器ではなく、それに入れるコンテンツが重要だということだ。この作品は鳴り物おもちゃの代替部品としてではなく、芸術作品としてのオルゴールと言ってよい。

・Dr.渡辺氏のその他の演奏曲は ここから 聴くことができる。
  1. 2023/05/08(月) 15:53:34|
  2. 電子オルゴール+音声再生
  3. | コメント:0

R8C電子オルゴールVer1_1(評価)

R8C電子オルゴール はPIC電子オルゴールからのデータ移行が完了して、一応完成と言うことにしたのだが、その出来栄えはPIC電子オルゴールと比較してどうだったのか、僕の評価を記しておきたい。下記でPICはPIC16エンハンスドコア、R8CはM11を指す。


①実行速度

・PICはCPUクロックが32MHzで、1命令は4サイクルで実行される。一方、R8CはCPUクロックが20MHzで、1命令は3~5サイクルで実行される。つまり、命令実行速度はR8Cが遅い。

・PICはメモリとWレジスタ間の演算に限られるが、R8Cではレジスタ・メモリ・リテラル間での演算が可能であり、処理の内容で評価するとR8Cの方が処理が速いと考えられる。

・PICはインデックスレジスタが無いので配列処理やポインタ変数の処理では一々FSRへの設定を伴うことになり、メモリが嵩張り処理時間も増大する。R8Cでは各パートの処理を配列やポインタ変数を使うことでスマートに記述でき、処理も軽い。これは電子オルゴールにとって優位である。

・乗算命令があり、波形演算が速く実行できる。

・R8CはSFRを含むメモリ全体がリニアな(バンク分けされていない)ので、SFRアクセスの効率が良い。

・総じてR8Cの方が処理速度は速いと評価できる。4パート演奏ではアンダーランが発生したが、C言語で書けることの方がメリットだと思う。

②メモリ

・PICでは1ワード(14ビット)に2つの波形データを詰め込んでいるので、1データは7ビットになってしまう。R8Cでは1データを8ビットで収容するので量子化ノイズが半分のレベルになっている。

・プログラムメモリが32kバイトで16F1705の倍以上あるので、曲と音声を多く収容できる。これだけでもR8Cを採用する価値がある。

③PWM機能

・R8Cにはデューティサイクルのバッファレジスタが1組しかなくステアリング制御機能もなく、相補波形出力機能もないので、コンプリ出力・ブリッジ出力・ブレーキ出力ではフルデューティの出力ができない。

・デューティサイクルの更新がPWM周期の終了時ではなく、一致BのタイミングであることがPWMによる音声出力では致命的な欠点で、デバイスの設計ミスだと思う。

・PWMクロック周波数・PWMステップ数・サンプリング周期の組み合わせがスンナリ行かない。結果としてサンプリング周期が長めの設定になってしまう。

④SPI・I2C通信機能

・R8CにはSPI・I2C通信機能がないので、ソフト実装することになる。内臓モジュールがあったとしても2線SPI、3線SPIでは内臓モジュールは使えないので、あまりハンデにはならないと思う。

⑤ピン割り当て

・機能モジュールで使えるピンが固定されていて代替ピンが少なく、ピン割り当ての自由度が極めて低い。PICのPPSに慣れているとR8Cは使い辛いと感じる。

・MODEピンはI/Oピンとして使えないので、同じピン数のPICと比べて1ピン損した気持ちになる。

・RESETピンは出力モードで使えるので、その点はR8Cに優位性がある。

⑥コスト

・流通価格は変動するので固定的な評価はし辛いが、現時点で@50円(2023年秋月)はPICを圧倒している。秋月の在庫状況は未だ「AAA」の表示になっていて、当面は入手可能と思われる。

⑦音質

・実際に演奏音を聴いた感じではR8CとPICでは音質の差は感じられない。

「RAILWAY(Dr.渡辺氏)」のR8C/M11での演奏
RAILWAY_R8C.mp3
この音が@50円のR8Cから出ていることに驚かれるだろう。
  1. 2023/05/08(月) 13:04:04|
  2. 電子オルゴール+音声再生
  3. | コメント:0

R8C電子オルゴールVer1_1(複数songの連続演奏)後日談

【前振り】

先日は、R8C電子オルゴールで 「複数songの連続演奏」の機能をサポート した。それが必要となったのは、onpuデータの規模が大きくなるとbuildで「input buffer overflow, can't enlarge buffer because scanner uses reject」のエラーが発生するので、1個のonpuファイルを小さくするため複数個のonpuファイルに分割して、それらを自動的に連続演奏するためだった。


【その後の検討】

①onpuファイルを分割していても、それらをすべて#includeしてコンパイルする訳で、その方法でエラーが回避できるのが不可思議だった。

・もしかして、#pragma asm ~ #pragma endasm の間の行数がトラブルの要因なのだろうか。

・そうであれば、onpuファイルの途中で#pragma endasm/#pragma asmを挿入して、連続するインラインアセンブラの行数を少なくすればよいのではないだろうか。

②それを実際にやってみたら、的中した。インラインアセンブラを分断するところは以下のとおり。

R8C電子オルゴールVer1_1(複数songの連続演奏)後日談ソースコード

・インラインアセンブラの500行程度毎に入れるとよさそうだ。

・結果はメデタシメデタシだが、マニュアルにはインラインアセンブラの制約についての記載が見当たらず、この対策の真偽は確認できない。

③連続演奏の仕掛けは作ってしまったので、機能の削除はしないでおく。今後のおもちゃ修理で使い道はあると思う。

④設計資料と開発プロジェクト一式は ここから ダウンロードできる。

ワークスペースは orgel.hws
プロジェクトは orgel_SW_M11
根のソースコードは orgel_SW_M11.c
  1. 2023/05/08(月) 12:36:31|
  2. 電子オルゴール+音声再生
  3. | コメント:0

R8C電子オルゴールVer1_1(複数songの連続演奏)

【前振り】

R8C電子オルゴールは PIC電子オルゴールから全曲の移行が完了した のだが、「RAILWAY」の曲がbuildできないことが判った。

その対応のため、「複数songの連続演奏」の機能をサポートした。


【不具合の発生状況】

①songインデックスに「RAILWAY(作 Dr.渡辺氏)」を含めてbuildすると、訳の判らないエラーが表示されて異常終了する。
R8C電子オルゴールVer1_1(複数songの連続演奏)RAILWAYbuildエラー

input buffer overflow, can't enlarge buffer because scanner uses reject

②このエラーメッセージをHEWのCコンパイラユーザーマニュアルで探したが、見付からなかった。エラー番号が表示されていないので、文法エラーのような想定されたエラーではないようだ。

③ネット検索するとHEWのCコンパイラに限らず、いろんなプログラムで表示されるもののようだ。勿論、プログラムによって指し示す意味は違うのだろうが、何らかの処理をするのにバッファが足りないことを主張している。

④Cコンパイラの動作環境の設定で回避できないかマニュアルを見たが、コンパイラの起動オプションには関連しそうなものが無かった。

⑤「付録C 翻訳限界」に「ソースファイルでの行数は最大65535行」との記載があるのだが、それには至っていない。


【対応】

①「RAILWAY」の特徴は他のsongと比較してonpuデータが極めて長いことだ。それでバッファが足りなくなったと思われる。しかし、Dr.渡辺氏はよくこんな大作を作ったもんだ。

②試しにonpuデータを半分にしてみたらbuildできた。しかし、残りの半分はエラーとなってしまった。

③試行錯誤して、onpuデータを3分割にしたところ、3つともbuildできた。

④3分割したsongを同時にsongインデックスに含めてもbuildできた。

・3分割したとは言え結局は全部を#includeするのでコンパイラが扱うソースコードの長さは同じになるが、それで、エラーが回避できるのが不可思議だ。コンパイラの気持ちが推し量れない。


【機能改善】

①従来の機能でも、演奏終了のコールバック関数で次のsongを演奏開始させれば複数のsongを連続再生することができる。しかし、コールバック関数側で連続演奏の要否と曲番号の指定が必要になるので、アプリが組み難い。

②連続演奏させるsongの組みは決まっていて、その情報をsongデータに含めておくことでエンジン側で自動的に連続演奏させるようにした。

・songデータに次のsongへのリンクを張っておく。連続演奏しないフツウの曲ではリンク情報にNULLを設定しておく。

・songの演奏終了時に次のsongへのリンク情報があれば、SONG_SEL()と同等の演奏制御データの設定を行う。これで次のsongが演奏開始される。

・但し、分割したonpuデータに跨る分岐は行えない。

・もしかして、#pragma asm ~ #pragma endasm の間の行数がトラブルの要因なのだろうか。

③既存songファイルの移行をやり直した。分割した「RAILWAY」のsongファイルには次のsongへのリンク情報を設定した。

④設計資料と開発プロジェクト一式は ここから ダウンロードできる。

ワークスペースは orgel.hws
プロジェクトは orgel_SW_M11
根のソースコードは orgel_SW_M11.c

但し、下記後日談にあるとおり対応方法を替えたので、ダウンロードファイルには今回の対応の結果は残っていない。


【後日談】

その後、buildエラーの回避策を再考した結果、onpuファイルを分割せずとも #pragma asm/#pragma endasm で区切ればよい ことが判った。
  1. 2023/05/07(日) 11:39:50|
  2. 電子オルゴール+音声再生
  3. | コメント:0
次のページ

プロフィール

大泉茂幸

Author:大泉茂幸
名張市つつじが丘おもちゃ病院
名張市つつじが丘南3番町129番地
mailto:tutuji@cb4.so-net.ne.jp

子どもの頃から趣味は電子工作一筋でやってきました。理科離れが進む中で科学技術に興味を持つ子どもが少しでも増えて行くことを願って、子ども達に電子工作の活動の場を提供しています。

1981年からおもちゃ病院の活動を始め、2014年に三重県名張市への移住を機に「つつじが丘おもちゃ病院」を開院しました。自分でおもちゃを設計し製作する【おもちゃ工房】と、マイコンを応用した電子工作を楽しむ【マイコンクラブ】も併設しています。新規参加メンバーを募集しています。

当ブログで公開している技術情報や成果物の複製、改変および再配布はフリーです。読者様のおもちゃ病院活動のお役に立てば幸いです。ご利用いただいた結果や感想等を記事へのコメントやメールでフィードバックしていただけると有難いです。なお、公開ファイルは最新版を載せているので、古い記事の内容から変わっている場合があります。

公開しているファームウェアについては 目次ページ か 全国のおもちゃ病院様での使用実績 をご覧下さい。


当ブログへのリンクはフリーです。

カテゴリ

おもちゃ修理技術 (287)
¦ ・電子オルゴール+音声再生 (121)
¦ ・音声再生・録音再生 (39)
¦ ・2.4GHzラジコン (91)
¦ ・レガシーラジコン (21)
¦ ・赤外線リモコン (4)
¦ ・タッチセンス (8)
¦ ・RFID (3)
ツール製作 (52)
¦ ・プログラマー (41)
¦ ・USB-シリアル変換 (5)
¦ ・その他のツール (6)
修理事例 (274)
¦ ・マイコン換装 (119)
¦ ・電子・電気修理 (112)
¦ ・メカ修理 (43)
製作記事 (20)
PIC開発 (15)
AVR開発 (4)
LPC開発 (3)
STM開発 (2)
R8C開発 (6)
CH32V開発 (12)
おもちゃ病院 (12)
ドクター研修会 (8)
未分類 (0)

最新記事

最新コメント

月別アーカイブ

訪問者数

検索フォーム

RSSリンクの表示

リンク

このブログをリンクに追加する

QRコード

QR