デコーダの設定を変更するためのモードであるサービスモードでのパケットについてまとめます。
DCCのサービスモードについての規格はNMRA DCC StandardsのRecommended Practice RP-9.2.3 “DCC Service Mode”に書かれているのでそちらも参照してください。また、誤解している可能性があるので利用する場合は十分検証してください。
サービスモードとは、コマンドステーション等のプログラミング線路にデコーダを接続し、内部の設定(CV値)を書き換えるためのモードです。
とはいえ普通のパケットと通信規格に特別違いはないので(プリアンプル数がほんとは多い20個以上なのですが)既存のDCCパケット受信プログラムがそのまま使えます。
サービスモードへ入るには
デコーダはサービスモードパケットを電源投入後100ms以内に受信する事によってサービスモードに入ることができます。
またサービスモードはサービスモードパケット(0xffから始まるアイドルパケット等)でないパケットを受信するか、最後の受信から20ms経過したときに抜けます。
アイドルパケットを受信したらサービスモードに入ってはいけません。これを忘れると車両番号124番の列車へのパケットがDirモードのプログラミングパケットと重なるので誤動作を起こします。
ちなみにリセットパケットは全てが0x00の3バイトのパケットのことです。
またデコーダが応答する必要がある場合があります。そのときはデコーダは60mA以上の電流を6ms(+/-1ms)消費することによって応答とします。
サービスモードパケット
一般的なパケットは一バイト目にデコーダのアドレス情報がありますが、サービスパケットにはデコーダアドレスは存在しません。デコーダが受信したデータはすべてそのデコーダ向けのパケットとなります。
サービスパケットは1バイト目の上位4ビットが二進数で0111であるパケットです。
今回はいくつかプログラム方式のうちページモード(PAGE)とダイレクトモード(DIR)についてまとめます。
ページモードよりダイレクトモードのほうが簡単です。
その他には物理モード(PHYS)、アドレス設定専用モードとオペレーションモード(OPS)があります。が、物理モードは一部のCV値のみ、アドレス専用モードは名前の通りアドレスのみしかプログラミングできませんので普通は利用しないと思われます。またOPSモードはサービスモードではなく標準のパケットなのでとりあえず割愛します。
ダイレクトモード(Direct Mode)
ダイレクトモードはパケット一つだけで読み込みあるいは書き込みを行います。動作手順は次のようになります。
- 電源投入
- 3回以上のリセットパケット
- ダイレクトモードパケット(誤動作防止のため同じパケットを5回以上)
- 6回以上のリセットパケット(デコーダが処理するための時間稼ぎ)
- 電源切断
となります。なので説明するのはプログラミングパケットだけです。ダイレクトモードパケットは次のような4バイト構成です。プリアンプルは通常よりも多く20個以上です。
0 0111CCAA 0 AAAAAAAA 0 DDDDDDDD 0 EEEEEEEE 1
- C 動作モード指定 (01でベリファイ(読み込み)、11で書き込み、10ビット操作)
- A 操作するCV値の番号
- D 書き込んだりベリファイ(一致確認)するデータの中身,ビット操作の場合その内容
- E エラー検知用バイト
ベリファイのときは送られて来たデータとCV値が一致したときにのみ応答します。それによりコマンドステーションはCV値を読み込んだことになります。
(ビット操作については執筆中…気が向いたら(笑))
ページモード(Paged CV Addressing)
ページモードは少し複雑でダイレクトモードのように一回ののパケットでというわけにはいきません。
ちょっと説明が大変なので執筆中….実装したコードサンプルが下にあります。
実装
実際にサービスパケット受信をC言語でAVRに実装した例です。ただ以下の例は基本のサンプルであって必要な処理をすべて満たしている訳ではありません。例えばサービスモードに入ってはいけないかどうかの確認をしていない、連続で同じパケットを受信せずに一回だけで実行してしまう点など…
しかも実際に実装する時はswitchを使わずに書いた方がプログラムサイズを小さくできます。
あくまでも参考資料という事で許してください。
ダイレクトモード(Direct Mode)
if(size==4) switch(packet[0]&0xfc){ case 0x74: //Verify cv = packet[1] + ((packet[0]&0x03)<<8); //CV値番号 //ここでデコーダが保持しているCV値とpacket[2]の内容が一致したら電流を消費し応答 //応答 60mA以上を5から7ミリ秒消費 break; case 0x7C: //Write cv = packet[1] + ((packet[0]&0x03)<<8) + 1; //CV値番号」 //ここでデコーダはpacket[2]の内容をCV値として保存処理 //応答 60mA以上を5から7ミリ秒消費 break; case 0x78: //Bit操作 //未対応 break; }
ページモード(Paged CV Addressing)
page_r変数はグローバル
if(size==3) switch(packet[0]){ //ベリファイあるいは書き込み動作 case 0b01111000: case 0b01111001: case 0b01111010: case 0b01111011: case 0b01110000: case 0b01110001: case 0b01110010: case 0b01110011: data_r=packet[0]&0x03; //データレジスタの内容 rw = (packet[0]&0b00001000)>>3; //1なら書き込み、0ならベリファイ cv = (page_r-1)*4 + data_r+1; //CV値 //ここでベリファイあるいは書き込み動作を行う //ベリファイ時の動作は上と同じ break; case 0b01111101: case 0b01110101: page_r=packet[1]; //ページレジスタの内容を保管 break; }