NFC Shield用ライブラリのソースコード(PN532_SPI)を読む(1)

2013-06-24   treby   技術メモ  , , このエントリーをはてなブックマークに追加

まあ長くもないし(ヘッダファイルで100行未満、実cppファイルで650行程度)、さっくり読めるでしょう、と高をくくったのが2週間前の話で。

実際にはPN532のユーザーマニュアルとか読まなくちゃ理解できないことに気づき、睡眠時間を削りつつ頑張ったここ数日。別にさぼってたわけじゃないです。一応。

かといってユーザーマニュアルを完全に読んだわけでもなく、まずはライブラリがどういうことをしているかを説明しようかと思います。全部いっぺんにやろうとしても大変ですから。実際の利用とか拡張とかはその後ですかね……。

ヘッダファイルの定数の意味

C++におかれましては、ヘッダファイルにプロトタイプ宣言と定数の定義などを行うのが基本と認識しておりますが、まずはここで書かれている定数を見てみましょう。おおまか以下のように分類できるのかな、といった感じです。

  • データリンク層で使われる定数
  • コマンドコードを表す定数
  • コマンドパラメータを表す定数
  • MIFAREカードのコマンドコードを表す定数
  • SPI接続のための定数

ひとまずはそんな認識でいたらいい感じかな?

データリンク層で使われる定数

PN532_PREAMBLEなどのことで、PN532がコマンドコードだと認識するのに必要な値となります。お約束といったところでしょうか根拠として、ユーザーマニュアルのp31(6.2.1.6 Preamble and Postamble)あたりですかね。

コマンドコードを表す定数

これはまさしくp65から載っているコマンドのコマンドコードですね。実際にはここで定義されている以上にコマンドの種類があるわけですが、ライブラリではそのうちの一部が書かれているようです。

コマンドパラメータを表す定数

PN532_MIFARE_ISO14443Aで定義されているのは、p115(7.3.5 InListPassiveTarget)のBrTyパラメータであることが分かります。

MIFAREカードのコマンドコードを表す定数

PN532_MIFARE_READやPN532_MIFARE_WRITEがこれにあたります。ここの値はMIFARE Classicのユーザーズマニュアルの中で見つけることができます。

SPI接続のための定数

PN532_SPI_STATREADあたりなんかは、PN532ユーザーマニュアルのp45(6.2.5 SPI communication details)にあるやつっぽいですね。

PN532のコマンドとNFC Shield用ライブラリでの実装状況

PN532で使えるホストコマンドはユーザーマニュアルにある通りですが、ライブラリのヘッダファイルの定数定義によると、そのうちで使えるコマンドは大分限られているようです。このあたりを以下の表にまとめてみました。

コマンド概要実装
一般用途
Diagnose自己診断を行う。
GetFirmwareVersionPN532に組み込まれているファームウェアのバージョンを取得する。
GetGeneralStatusPN532の特定の瞬間のPN532の完全な状況を取得する。
ReadRegisterPN532の内部レジスターの内容を読み込む。
WriteRegisterPN532の内部レジスターの内容を上書きする。
ReadGPIOそれぞれのポートの値を読み込んでホストコントローラーに情報を返す。
WriteGPIOホストコントローラーによって検証されたそれぞれのポートの値を受け入れる。
SetSerialBaudRateホストコントローラーとPN532間のシリアルリンクのボーレートを選択する(High Speed UART)。
SetParametersPN532の内部パラメータをセットし、異なる場合での振る舞いを設定する。
SAMConfiguration内部シリアルデータスイッチを設定することでデータフローの経路を選択する。
PowerDown電力消費を抑えるためにPN532をパワーダウンモードにする。
無線通信用
RFConfigurationコマンドの一部で記述されるようにPN532の異なる設定を構成する。
RFRegulationTest無線規則のテストを行う。
Initiator用
InJumpForDEPアクティブもしくはパッシブコミュニケーションモードつかっているtargetを活性化する。場にtargetがあれば、DEP交換の準備ができる。
InJumpForPSLアクティブもしくはパッシブコミュニケーションを使っているtargetを活性化する。場にtargetがあれば、PSLもしくはDEP交換の準備ができる。
InListPassiveTargetできる限りたくさんの(最大MaxTgパラメータ分)パッシブモードにあるtargetを検知する。
InATRパッシブモードのtargetの活性化を始める。
InPSLTPE targetかISO/IEC14443-4 targetのいずれかに定義されたビットレートを変更する。
InDataExchangeInitiatorとしてのPN532とtarget間でのプロトコルデータ交換を支援する。
InCommunicateThruPN532とtarget間の基本的なデータ交換を支援する。
InDeselectTgで指定されたtargetの選択を解除する。PN532はこのtargetに関係する全ての情報を保持する。
InReleaseTgで指定されたtargetを解放する。
InSelectTgで指定されたtargetを選択する。
InAutoPollRF場内に存在する特定のタイプのcard/targetを検出する。
Target用
TgInitAsTargetPN532をtargetとして設定する。
TgSetGeneralBytesGeneral Bytesを与えるため、TgInitAsTargetコマンドと一緒に使う。General BytesはPN532がInitiatorに送るATR_RESを構築するのに使われる。
TgGetDataInitiatorからPN532が受け取ったデータを取得する。
TgSetDataInitiatorに送り返したいデータをPN532に指定する。
TgSetMetaDataInitiatorに送り返したいデータをPN532に指定する。TgSetDataとの違いは、PN532からinitiatorに送られる最後のパケットで、PFB control byteを含むことである。
TgGetInitiatorCommandinitiatorからのデータパケットを取得し、それをホストコントローラーに戻す。
TgResponseToInitiatorinitiatorにレスポンスパケットを送る。
TgGetTargetStatusPN532の現在の状態を取得する。

準備だけでも大変だった

というわけでまずはヘッダファイル(の定数定義部分)をさらっと流しました。次は実際のメソッドとかを(普段C++書かないので言語仕様も含めて)書いていければ、と思います!