Raspberry Pi に FeliCa リーダー・ライター RC-S620/S を接続する

#はじめに

FeliCaの読み取りを行う場合、一般向けに販売されているPaSoRi(RC-S380など)を使うのがよくあるパターンだと思います。
しかし、ここでお勧めしたいのが、**業務用のRC-S620/S**。お勧めの理由は**飛距離**です。

![RC-S620S.jpg](https://qiita-image-store.s3.amazonaws.com/0/104360/43aedb74-f90e-e8f0-775e-f4b91638d7ba.jpeg)

一般向けのPaSoRiは、FeliCaを密着させないと読み取れないのは使ったことのある方は分かると思います。
それが、**RC-S620/Sなら1cmぐらい浮いていても読み取れるんです！！**（スペック上は2cm）

例えば、PaSoRiだとSuicaをケースに入れているだけでも、密着できず、読み取れなかったりしますよね？
なにか実用的なモノを作るとしたら、ラフに当てても読み取れることは非常に重要になってきます。

ぜひ、RC-S620/S の採用を検討しましょう！

#ハードウェア
##RC-S620/S を入手する

スイッチサイエンスさんから購入するのが楽だと思います。また、ピッチ変換基板もほぼ必須だと思います。

[FeliCa リーダー・ライター RC-S620S | スイッチサイエンス]
(https://www.switch-science.com/catalog/353/)

[FeliCa RC-S620S/RC-S730 ピッチ変換基板のセット(フラットケーブル付き)]
(https://www.switch-science.com/catalog/1029/)

##Raspberry Pi と配線する

電源プラマイとシリアル送受信の、計4本を配線するだけです。

1. VDD ⇔ 3.3V
2. RxD ⇔ TxD
3. TxD ⇔ RxD
4. GND ⇔ GND
5. Reserve
6. GND ⇔ GND

TxD(送信),RxD(受信)は同じ名前同士をつなぐのではなく、送信と受信がペアになるよう接続するところがミソです。

4と6は変換基板上でつないじゃってもいいかもしれません。

![DSC_0488.JPG](https://qiita-image-store.s3.amazonaws.com/0/104360/f6ad5251-94b6-39c8-a632-a07a13e3177d.jpeg)

ちなみに写真のケースは3Dプリンタで自作したものです。

#ソフトウェア

##シリアルログインを無効にする
Raspberry Pi のシリアルピンは、シリアル端末からログインできるようになっているので、まずそれを無効化しなければなりません。

まず、/boot/cmdline.txt から `console=ttyAMA0,115200` を削除します。


```/boot/cmdline.txt　編集前
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
```

 

```/boot/cmdline.txt　編集後
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
```

Raspberry Pi 3 の場合は /boot/config.txt に下記を追加する必要があります。（副作用としてbluetoothが使えなくなります）

```/boot/config.txt　最後に追記
dtoverlay=pi3-miniuart-bt
```

以上、raspbian jessie(2016-05-27版) での設定を書きましたが、プログラム側からシリアルを使えるようにする設定は、raspbianのバージョンによってころころ変わる傾向があるので、ご利用のバージョンに合わせてしっかり調べて設定してください。

##Arduino向けRC-S620/S制御ライブラリをraspbian環境へ移植する

ソニー様のご厚意により、RC-S620/S制御ライブラリが公開されているのですが、それがArduino向けなのです。

http://blog.felicalauncher.com/sdk_for_air/?p=2677

このライブラリを頑張ってRaspberryPiで使用できるようにします。（これがこの記事のメインコンテンツです）

ソースを見てみると、HardwareSerialクラスとdelay(),millis()関数があればビルドできそうです。

delay(),millis() は WiringPi から借用し、HardwareSerialクラスはWiringPiをラップする形で実装します。

```cpp:HardwareSerial.cpp
#include "HardwareSerial.h"

HardwareSerial::HardwareSerial()
{
	this->serialFd = serialOpen("/dev/ttyAMA0",115200);
}

HardwareSerial::~HardwareSerial()
{
	if(this->serialFd<0) return;
	
	serialClose(this->serialFd);
}

void HardwareSerial::write(const uint8_t* data, uint16_t len)
{
	if(this->serialFd<0) return;

    for(uint16_t i=0;i<len;i++)
	{
		serialPutchar(this->serialFd, data[i]);
	}
}

uint8_t HardwareSerial::read()
{
	if(this->serialFd<0) return 0;

	return serialGetchar(this->serialFd);
}

bool HardwareSerial::available()
{
	if(this->serialFd<0) return false;

	return serialDataAvail(this->serialFd) > 0;
}

void HardwareSerial::flush()
{
	if(this->serialFd<0) return;

	serialFlush(this->serialFd);
}

HardwareSerial Serial;
```

```cpp:HardwareSerial.h
#include <inttypes.h>
#include <wiringSerial.h>

class HardwareSerial
{
private:
	int serialFd;

	public:
	HardwareSerial();
	~HardwareSerial();

	void write(const uint8_t* data, uint16_t len);
	uint8_t read();
	bool available();
	void flush();
};

extern HardwareSerial Serial;
```

```cpp:Wprogram.h
#include <wiringPi.h>
```
↑`delay(),millis()`を使えるようにするため



```cpp:Print.h
```

↑`Print.h`はインクルードできないエラーを回避するための空のファイルです

##IDmを取得するサンプルプログラム

```cpp:getIDm.cpp
#include <stdio.h>

#include "RCS620S.h"

int main()
{
	RCS620S rcs620s;

	int ret = rcs620s.initDevice();
	if (!ret) {
		printf("can't open pasori\n");
		return 0;
	}

	ret = rcs620s.polling();
	if (ret)
	{
		uint8_t* idm = rcs620s.idm;
		printf( "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n" ,
				idm[ 0 ] , idm[ 1 ] , idm[ 2 ] , idm[ 3 ] ,
				idm[ 4 ] , idm[ 5 ] , idm[ 6 ] , idm[ 7 ] ) ;
	}
	rcs620s.rfOff();

	return 0;
}
```

##コンパイル・リンク

WiringPi が入っていない場合はインストールします。

```
$ sudo apt-get install wiringpi
```


ソニー様の[「Arduino向けRC-S620/S制御ライブラリ」](http://blog.felicalauncher.com/sdk_for_air/?page_id=2699)のzipを展開したファイルと、本記事のソースファイルをワークディレクトリに置きます。
全部置くと下記のようになります。

```
drwxr-xr-x 3 pi pi  4096 Jun 18 04:51 .
drwxr-xr-x 4 pi pi  4096 Jun 17 17:49 ..
-rw-r--r-- 1 pi pi   430 Jun 18 12:00 getIDm.cpp
-rw-r--r-- 1 pi pi   745 Jun 18 12:00 HardwareSerial.cpp
-rw-r--r-- 1 pi pi   279 Jun 18 12:00 HardwareSerial.h
-rw-r--r-- 1 pi pi     0 Jun 18 12:00 Print.h
-rw-r--r-- 1 pi pi  7791 Nov 26  2010 RCS620S.cpp
-rw-r--r-- 1 pi pi  1385 Nov  9  2010 RCS620S.h
-rw-r--r-- 1 pi pi  4028 Nov 26  2010 RCS620S-sjis.txt
-rw-r--r-- 1 pi pi    23 Jun 18 12:00 Wprogram.h
```

次のコマンドでコンパイル、リンクします。

```
$ cc -c -DUNICODE HardwareSerial.cpp
$ cc -c -DUNICODE RCS620S.cpp
$ cc -lwiringPi RCS620S.o HardwareSerial.o -DUNICODE getIDm.cpp -o getIDm
```

FeliCa（Suicaやおサイフケータイ）をRC-S620/SにかざしてgetIDmコマンドを実行すると IDm が表示されます。

```
$ ./getIDm
01:01:01:14:7b:0c:bb:11
```

ここまで出来れば、残高読み取りなどの応用も可能になってくるでしょう。（Arduinoでやっている例から持ってこれると思います）

#まとめ

- RC-S620/S は飛距離が出る
- 「Arduino向けRC-S620/S制御ライブラリ」をRaspberryPiで利用する方法を示した