【工事中】このサイトは現在作成中です。正式公開までしばらくお待ちください。

ソースコード&内部アーキテクチャ解説

 ワンコインデコーダX(WCH CH32V003マイコン搭載)のファームウェア内部構造と、ソースコードのアーキテクチャに関する技術解説ページです。
 本デコーダは、限られたメモリとリソースの中で「取りこぼしの許されないDCC信号の受信」と「滑らかなモーター・ライト制御」を両立するため、高精度な割り込み処理とステートマシン(状態遷移)を駆使して設計されています。

ソースコードのファイル構成と役割

 ファームウェアのソースコードは、機能ごとに明確にモジュール化されています。主要なファイルの役割は以下の通りです

  • main.c(メインエントリ) システム初期化(クロック、GPIO、タイマー等の設定)を行った後、メインループでDCCパケットの解釈や、各種タスクのスケジューリングを行います。
  • dcc_core.c / dcc_core.h(DCC信号・パケット処理) 本デコーダの心臓部です。線路からのDCC信号(パルス幅の違い)を外部割り込み(EXTI)でキャッチし、1ビットずつパケットとして組み立てるステートマシンが実装されています。
  • motor_ctrl.c / motor_ctrl.h(出力・モーター駆動・BEMF) タイマーを用いたPWMによるモーター駆動、キックスタートの制御、および20ピン版でのBEMF(逆起電力)測定とPID定速制御アルゴリズムを担当します。また、1msごとの定期タスクもここで処理されます。
  • cv_manager.c / cv_manager.h(CV値管理・Flash読み書き) デコーダの設定値(CV値)を管理します。CH32V003の内部Flashメモリの一部をEEPROMのように扱い、電源を切ってもCV値が保持される仕組み(Flashエミュレーション)を提供します。
  • decoder_config.h(条件付きコンパイル設定) 書き込むターゲット(8ピン車載、20ピン車載、8ピンファンクション、8ピンポイント)や、使用するモータードライバIC(TB67H450やBD6231など)の切り替えをマクロ定義で一括管理します。

内部アーキテクチャの全体像

本デコーダは、実質的に「超軽量なリアルタイムOS」のような2大駆動アーキテクチャで動いています。

DCC信号の1ビット受信(外部割り込み)と解析処理

① EXTI 割り込みハンドラ (最高優先度)
– パルスの時間を計測 → 1 / 0 判定
– パケット組み立てステートマシン

② main() メインループ
– 完成したDCCパケットの解析
– CV値のフラッシュへの読み書き処理

タイマー割り込み (1ms 定期タスク)

タイマー割り込み (1ms 定期タスク)
– 加減速 (モメンタム) の細かな演算
– キックスタート時間 / ポイント保護タイマーのカウントダウン

  • 最優先:DCC信号の1ビット受信(外部割り込み)
    DCC信号は1辺が数10〜100マイクロ秒という非常に高速な矩形波です。ワンコインデコーダXでは、DCC信号の立ち上がり・立ち下がりをマイコンの外部割り込み(EXTI)で捉え、タイマーのカウンタ値から「1」か「0」かを完全にリアルタイムで判別しています。 この処理はマイコン内で最高の優先度(WCHマイコン独自のFast Interrupt機能など)が与えられており、他のどんな処理をしていても、パルスを取りこぼさない設計になっています。
  • 制御の要:1msの定期タイマータスク
    モーターの速度を滑らかに変える(モメンタム)、キックスタートを一瞬だけ効かせる、ポイントマシンの通電時間を正確に測る、といった「時間管理」が必要な処理は、1msごとに正確に発生するタイマー割り込みタスク(Process_1ms_Timer_Tasks)に集約されています。 メインループ内で他の処理が走っていても、この1msタスクが割り込んでモーターの速度出力を滑らかに更新し続けます。

DCCパケット解析ステートマシンの仕組み

 外部割り込みによって切り出された「1」と「0」のビット列は、dcc_core.c 内のステートマシンによってパケットへと組み立てられます。
 DCCパケットは常に以下の順番で流れてくるため、プログラムはビットを読み進めながら状態(ステート)を遷移させていきます。

  • PREAMBLE(プリアンブル)状態: 「1」が10回以上連続して届くのを待ち、パケットの開始を検出します。
  • START_BIT(スタートビット)状態: プリアンブルの後に届く「0」を見つけ、ここからデータが始まることを認識します。
  • DATA_BYTE(データバイト)状態: 8ビットのデータを取得します。データが終わると、次に「データが続くか(0)」「パケットの終了か(1)」を判定するデータスタートビットをチェックします。
  • CHECKSUM(チェックサム)状態: 最後に届くエラーチェック用のバイトと、それまでに受信した全データのXOR(排他的論理和)を計算し、パケットがノイズで化けていないかを検証します。正常であれば、メインループに処理を引き渡します。