いま巷で話題の NFC で書き換えできる名札サイズの電子ペーパーのプロトコルを調べました。
- 画面サイズ:
400 x 300 - 色インデックス (2bit):
0 = Black1 = White2 = Yellow3 = Red
- 通信: ISO7816 APDU over NFC
- 認証
0020 00010420091210->9000
- 画像データ送信
F0D3 ...を複数回
- 画面更新開始
F0D4 858000->9000
- 更新完了ポーリング
- 送信:
F0DE 000001 - 応答:
01 9000= 更新中 - 応答:
00 9000= 更新完了
- 送信:
- 高さ 20 rows ごとに分割
- 総ブロック数:
300 rows / 20 rows = 15 blocks blockNo:0..14
- 1行あたり:
400 pixel / 4 pixel = 100 byte - 1ブロック:
100 byte * 20 rows = 2000 byte
1 byte に 4 pixel を詰める。
byte = p0 | (p1 << 2) | (p2 << 4) | (p3 << 6)p0..p3は 0..3 の色インデックス- 行内のbyte並びは右→左で扱う
- 各 2000 byteブロックを
LZO1X-1(lzo1x_1_compress) で圧縮する
- Header:
CLA INS P1 P2 Lc CLA:F0INS:D3P1:00P2:00: ブロック途中フラグメント01: ブロック最終フラグメント
Lc:2 + len(compressedFragment)- Data部:
blockNo(1 byte)fragNo(1 byte)compressedFragment(可変)
compressedFragmentの最大は 250 byte (0xFC - 2)- 1ブロックの圧縮データを複数
F0D3 ...に分割可能
- 同じ
blockNoごとにfragNo順に連結 P2=01が来たらそのblockNoは完了- 完了ブロックを LZO で展開して 2000 byte に戻す
F0D300011600000255555555552000000000000000B10000110000
分解:
F0 D3 00 01 16P2=01なのでこのAPDUがそのブロックの最終の断片Lc=0x16(22 byte)
- Data先頭2byte:
00=blockNo=000=fragNo=0
- 残り20byteが圧縮データ本体
F0D30000FC020002...
分解:
P2=00つまり、ブロックの途中の断片Lc=0xFC- Data先頭:
02=blockNo=200=fragNo=0
同じ blockNo=2 で fragNo=1,2,... が続き、最後だけ P2=01 になる。
以下のコマンド使って追加の情報を確認できる。
F0D8 000005000000000E: 画面種別、例えば"4_color Screen"00D1 000000: デバイス情報
9000: 成功6700: 長さ/形式エラー6D00: INS未対応6A86: P1/P2不正
更新完了判定は F0D4 ... の 9000 だけでは不十分。F0DE ... で 00 9000 を確認すること。
- ドキュメントに記載はないが、
NFCTagReaderSession.connect(to:)は開始から20秒で切断される。 F0D3 ...を送信し続けると20秒ちかくなり、F0D4 ...を送ってからF0DE ...で更新待ちをすると途中で切断されて更新が完了しない。- なので、
F0D3 ...で画像を送信したあと、一旦NFCTagReaderSession.restartPolling()をして再度0020 ...を送り、F0D4 ...で更新を開始させてF0DE ...で更新待ちをして追加の20秒の猶予を得る必要がある。