更新说明文件,更新引用链接。
This commit is contained in:
parent
7ab9ac6f3c
commit
7622d91901
@ -1,5 +1,6 @@
|
||||
#include "cmd.h"
|
||||
bool high_baudrate = true;//high_baudrate=true
|
||||
#define high_baudrate
|
||||
|
||||
#include "Aime_Redaer.h"
|
||||
|
||||
void setup() {
|
||||
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
|
||||
@ -12,132 +13,83 @@ void setup() {
|
||||
FastLED.showColor(0);
|
||||
delay(500);
|
||||
}
|
||||
nfc.setPassiveActivationRetries(0x10);//设定等待次数
|
||||
nfc.setPassiveActivationRetries(0x10);
|
||||
nfc.SAMConfig();
|
||||
memset(&req, 0, sizeof(req.bytes));
|
||||
memset(&res, 0, sizeof(res.bytes));
|
||||
memset(req.bytes, 0, sizeof(req.bytes));
|
||||
memset(res.bytes, 0, sizeof(res.bytes));
|
||||
|
||||
SerialDevice.begin(high_baudrate ? 115200 : 38400);
|
||||
FastLED.showColor(high_baudrate ? 0x0000FF : 0x00FF00);
|
||||
SerialDevice.begin(baudrate);
|
||||
FastLED.showColor(BootColor);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
SerialCheck();
|
||||
packet_write();
|
||||
}
|
||||
|
||||
static uint8_t len, r, checksum;
|
||||
static bool escape = false;
|
||||
|
||||
static uint8_t packet_read() {
|
||||
|
||||
while (SerialDevice.available()) {
|
||||
r = SerialDevice.read();
|
||||
if (r == 0xE0) {
|
||||
req.frame_len = 0xFF;
|
||||
continue;
|
||||
}
|
||||
if (req.frame_len == 0xFF) {
|
||||
req.frame_len = r;
|
||||
len = 0;
|
||||
checksum = r;
|
||||
continue;
|
||||
}
|
||||
if (r == 0xD0) {
|
||||
escape = true;
|
||||
continue;
|
||||
}
|
||||
if (escape) {
|
||||
r++;
|
||||
escape = false;
|
||||
}
|
||||
req.bytes[++len] = r;
|
||||
if (len == req.frame_len && checksum == r) {
|
||||
return req.cmd;
|
||||
}
|
||||
checksum += r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void packet_write() {
|
||||
uint8_t checksum = 0, len = 0;
|
||||
if (res.cmd == 0) {
|
||||
return;
|
||||
}
|
||||
SerialDevice.write(0xE0);
|
||||
while (len <= res.frame_len) {
|
||||
uint8_t w;
|
||||
if (len == res.frame_len) {
|
||||
w = checksum;
|
||||
} else {
|
||||
w = res.bytes[len];
|
||||
checksum += w;
|
||||
}
|
||||
if (w == 0xE0 || w == 0xD0) {
|
||||
SerialDevice.write(0xD0);
|
||||
SerialDevice.write(--w);
|
||||
} else {
|
||||
SerialDevice.write(w);
|
||||
}
|
||||
len++;
|
||||
}
|
||||
res.cmd = 0;
|
||||
}
|
||||
|
||||
void SerialCheck() {
|
||||
switch (packet_read()) {
|
||||
case SG_NFC_CMD_RESET:
|
||||
sg_nfc_cmd_reset();
|
||||
break;
|
||||
case SG_NFC_CMD_GET_FW_VERSION:
|
||||
sg_nfc_cmd_get_fw_version();
|
||||
break;
|
||||
case SG_NFC_CMD_GET_HW_VERSION:
|
||||
sg_nfc_cmd_get_hw_version();
|
||||
break;
|
||||
case SG_NFC_CMD_POLL:
|
||||
sg_nfc_cmd_poll();
|
||||
break;
|
||||
case SG_NFC_CMD_MIFARE_READ_BLOCK:
|
||||
sg_nfc_cmd_mifare_read_block();
|
||||
break;
|
||||
case SG_NFC_CMD_FELICA_ENCAP:
|
||||
sg_nfc_cmd_felica_encap();
|
||||
break;
|
||||
case SG_NFC_CMD_AIME_AUTHENTICATE:
|
||||
sg_nfc_cmd_aime_authenticate();
|
||||
break;
|
||||
case SG_NFC_CMD_BANA_AUTHENTICATE:
|
||||
sg_nfc_cmd_bana_authenticate();
|
||||
break;
|
||||
case SG_NFC_CMD_MIFARE_SELECT_TAG:
|
||||
sg_nfc_cmd_mifare_select_tag();
|
||||
break;
|
||||
case SG_NFC_CMD_MIFARE_SET_KEY_AIME:
|
||||
sg_nfc_cmd_mifare_set_key_aime();
|
||||
break;
|
||||
case SG_NFC_CMD_MIFARE_SET_KEY_BANA:
|
||||
sg_nfc_cmd_mifare_set_key_bana();
|
||||
break;
|
||||
case SG_NFC_CMD_RADIO_ON:
|
||||
sg_nfc_cmd_radio_on();
|
||||
break;
|
||||
case SG_NFC_CMD_RADIO_OFF:
|
||||
sg_nfc_cmd_radio_off();
|
||||
break;
|
||||
case SG_RGB_CMD_RESET:
|
||||
sg_led_cmd_reset();
|
||||
break;
|
||||
case SG_RGB_CMD_GET_INFO:
|
||||
sg_led_cmd_get_info();
|
||||
break;
|
||||
case SG_RGB_CMD_SET_COLOR:
|
||||
sg_led_cmd_set_color();
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case CMD_TO_NORMAL_MODE:
|
||||
sys_to_normal_mode();
|
||||
break;
|
||||
case CMD_GET_FW_VERSION:
|
||||
sys_get_fw_version();
|
||||
break;
|
||||
case CMD_GET_HW_VERSION:
|
||||
sys_get_hw_version();
|
||||
break;
|
||||
|
||||
// Card read
|
||||
case CMD_START_POLLING:
|
||||
nfc_start_polling();
|
||||
break;
|
||||
case CMD_STOP_POLLING:
|
||||
nfc_stop_polling();
|
||||
break;
|
||||
case CMD_CARD_DETECT:
|
||||
nfc_card_detect();
|
||||
break;
|
||||
|
||||
// MIFARE
|
||||
case CMD_MIFARE_KEY_SET_A:
|
||||
memcpy(KeyA, req.key, 6);
|
||||
res_init();
|
||||
break;
|
||||
|
||||
case CMD_MIFARE_KEY_SET_B:
|
||||
res_init();
|
||||
memcpy(KeyB, req.key, 6);
|
||||
break;
|
||||
|
||||
case CMD_MIFARE_AUTHORIZE_A:
|
||||
nfc_mifare_authorize_a();
|
||||
break;
|
||||
|
||||
case CMD_MIFARE_AUTHORIZE_B:
|
||||
nfc_mifare_authorize_b();
|
||||
break;
|
||||
|
||||
case CMD_MIFARE_READ:
|
||||
nfc_mifare_read();
|
||||
break;
|
||||
|
||||
// FeliCa
|
||||
case CMD_FELICA_THROUGH:
|
||||
nfc_felica_through();
|
||||
break;
|
||||
|
||||
// LED
|
||||
case CMD_EXT_BOARD_LED_RGB:
|
||||
FastLED.showColor(CRGB(req.color_payload[0], req.color_payload[1], req.color_payload[2]));
|
||||
break;
|
||||
|
||||
case CMD_EXT_BOARD_INFO:
|
||||
sys_get_led_info();
|
||||
break;
|
||||
|
||||
case CMD_EXT_BOARD_LED_RGB_UNKNOWN:
|
||||
break;
|
||||
|
||||
default:
|
||||
sg_res_init();
|
||||
res_init();
|
||||
}
|
||||
packet_write();
|
||||
}
|
||||
|
46
README.md
46
README.md
@ -1,30 +1,30 @@
|
||||
# Arduino-Aime-Reader
|
||||
使用 Arduino + PN532 + WS2812B 制作的 Aime 兼容读卡器。
|
||||
**目前所有主要功能已经实现,如果没有 bug 应该不会再更新。**
|
||||
使用 Arduino + PN532 制作的 Aime 兼容读卡器。
|
||||
**当前更新内容未经过长时间测试,如果遇到问题可以回滚到[稳定的 v1.0 版本](https://github.com/Sucareto/Arduino-Aime-Reader/tree/v1.0)**
|
||||
English: [lawliuwuu/Arduino-Aime-Reader](https://github.com/lawliuwuu/Arduino-Aime-Reader)
|
||||
|
||||
支持卡片类型: [FeliCa](https://zh.wikipedia.org/wiki/FeliCa)(Amusement IC、Suica、八达通等)和 [MIFARE](https://zh.wikipedia.org/wiki/MIFARE)(Aime,Banapassport)。
|
||||
实现逻辑为官方读卡器串口数据对比 + 脑补,不保证正确实现。
|
||||
通信数据格式参考了 [Segatools]() 和官方读卡器抓包数据,可在 [Example.txt](doc/Example.txt) 和 [nfc.txt](doc/nfc.txt) 查看。
|
||||
一个使用例:[ESP32-CardReader](https://github.com/Sucareto/ESP32-CardReader)
|
||||
- 支持卡片类型: [FeliCa](https://zh.wikipedia.org/wiki/FeliCa)(Amusement IC、Suica、八达通等)和 [MIFARE](https://zh.wikipedia.org/wiki/MIFARE)(Aime,Banapassport)
|
||||
- 逻辑实现是通过对官方读卡器串口数据进行分析猜测出来的,并非逆向,不保证正确实现
|
||||
- 通信数据格式参考了 [Segatools](https://github.com/djhackersdev/segatools) 和官方读卡器抓包数据,可在 [Example.txt](doc/Example.txt) 和 [nfc.txt](https://github.com/djhackersdev/segatools/blob/master/doc/nfc.txt) 查看
|
||||
- 定制使用例(主要的开发测试环境):[ESP32-CardReader](https://github.com/Sucareto/ESP32-CardReader)
|
||||
|
||||
|
||||
### 使用方法:
|
||||
1. 按照 [PN532](https://github.com/elechouse/PN532) 的提示安装库
|
||||
2. 按照使用方式,在 Arduino 和 PN532 接好连接线(I2C 或 SPI),并调整 PN532 上的拨码开关
|
||||
3. 接上 WS2812B 灯条(可选)
|
||||
3. 接上 WS2812B 灯条(可选,不会影响正常读卡功能)
|
||||
4. 上传 [ReaderTest](tools/ReaderTest/ReaderTest.ino) 测试硬件是否工作正常
|
||||
5. 若读卡正常,可按照支持列表打开设备管理器设置 COM 端口号
|
||||
6. 按照游戏的波特率设置代码的`high_baudrate`选项,`115200`是`true`,`38400`是`false`
|
||||
7. 上传程序打开游戏测试
|
||||
8. 安装 [MifareClassicTool](https://github.com/ikarus23/MifareClassicTool),修改 [Aime 卡示例](doc/aime示例.mct) 后写入空白 MIFARE UID/CUID 卡
|
||||
7. 如果有使用 [Segatools](https://github.com/djhackersdev/segatools),参考 [segatools.ini 设置教程](https://github.com/djhackersdev/segatools/blob/master/doc/config/common.md#enable) 关闭 Aime 模拟读卡器
|
||||
8. 上传程序打开游戏测试
|
||||
|
||||
如果需要自定义 Aime 卡,安装 [MifareClassicTool](https://github.com/ikarus23/MifareClassicTool),修改 [Aime 卡示例](doc/aime示例.mct) 后写入空白 MIFARE UID/CUID 卡,即可刷卡使用。
|
||||
某些 Arduino 可能需要在游戏主程序连接前给串口以正确的波特率发送 DTR/RTS,需要先打开一次 Arduino 串口监视器再启动主程序。
|
||||
如果是 SDBT,可以在启动前运行一次 [DTR-RTS.exe](tools/DTR-RTS.exe) 以向 COM1 和 COM12 发送DTR/RTS。
|
||||
如果需要向其他端口和特定的波特率发送,可以修改 [DTR-RTS.c](tools/DTR-RTS.c) 然后编译。
|
||||
|
||||
|
||||
### 支持列表:
|
||||
| 游戏代号 | COM端口号 | 支持的卡 | 默认波特率 |
|
||||
### 支持游戏列表:
|
||||
| 代号 | 默认 COM 号 | 支持的卡 | 默认波特率 |
|
||||
| - | - | - | - |
|
||||
| SDDT/SDEZ | COM1 | FeliCa,MIFARE | 115200 |
|
||||
| SDEY | COM2 | MIFARE | 38400 |
|
||||
@ -35,23 +35,27 @@ English: [lawliuwuu/Arduino-Aime-Reader](https://github.com/lawliuwuu/Arduino-Ai
|
||||
- 如果读卡器没有正常工作,可以切换波特率试下
|
||||
- 有使用 amdaemon 的,可以参考 config_common.json 内 aime > unit > port 确认端口号
|
||||
- 如果 `"high_baudrate" : true` 则波特率是`115200`,否则就是`38400`
|
||||
- 在 `"high_baudrate" : true` 的情况下,本读卡器程序支持 emoney 功能,端末认证和刷卡支付均正常(需要游戏和服务器支持)
|
||||
|
||||
|
||||
### 已测试开发板:
|
||||
- SparkFun Pro Micro(ATmega32U4),需要发送 DTR/RTS
|
||||
- SparkFun SAMD21 Dev Breakout(ATSAMD21G18)
|
||||
- NodeMCU 1.0(ESP-12E + CP2102 & CH340),SDA=D2,SCL=D1
|
||||
- NodeMCU-32S(ESP32-S + CH340)
|
||||
### 开发板适配情况:
|
||||
| 开发板名 | 主控 | 备注 |
|
||||
| - | - | - |
|
||||
| SparkFun Pro Micro | ATmega32U4 | 需要发送 DTR/RTS,未完全测试 |
|
||||
| SparkFun SAMD21 Dev Breakout | ATSAMD21G18 | 未完全测试 |
|
||||
| NodeMCU 1.0 | ESP-12E + CP2102 & CH340 | SDA=D2,SCL=D1 |
|
||||
| NodeMCU-32S | ESP32-S + CH340 | 主要适配环境 |
|
||||
| Arduino Uno | ATmega328P + CH340 | 未实际测试,据反馈不可用 |
|
||||
|
||||
|
||||
### 已知问题:
|
||||
- 在 NDA_08 命令的写入 Felica 操作没有实现,因为未确认是否会影响卡片后续使用
|
||||
- 未确定`res.status`的意义,因此`res.status = 1;`可能是错误的
|
||||
- 未实现`mifare_select_tag`,未支持多卡选择,只会读到最先识别的卡片
|
||||
- 未确定`res.status`错误码的定义,因此`res.status`的值可能是错误的
|
||||
- 因为 PN532 库不支持同时读取多张卡片,所以未实现`mifare_select_tag`,只会读到最先识别的卡片
|
||||
|
||||
|
||||
### 引用库:
|
||||
- 驱动 WS2812B:[FastLED](https://github.com/FastLED/FastLED)
|
||||
- 驱动 PN532:[PN532](https://github.com/elechouse/PN532)
|
||||
- 驱动 PN532:[PN532](https://github.com/elechouse/PN532) 或 [Aime_Reader_PN532](https://github.com/Sucareto/Aime_Reader_PN532)
|
||||
- 读取 FeliCa 参考:[PN532を使ってArduinoでFeliCa学生証を読む方法](https://qiita.com/gpioblink/items/91597a5275862f7ffb3c)
|
||||
- 读取 FeliCa 数据的程序:[NFC TagInfo](https://play.google.com/store/apps/details?id=at.mroland.android.apps.nfctaginfo),[NFC TagInfo by NXP](https://play.google.com/store/apps/details?id=com.nxp.taginfolite)
|
||||
|
244
doc/nfc.txt
244
doc/nfc.txt
@ -1,244 +0,0 @@
|
||||
N.B. Quoted strings are NOT NUL-terminated unless otherwise noted.
|
||||
Useful reading: https://www.nxp.com/docs/en/data-sheet/MF1S50YYX_V1.pdf
|
||||
|
||||
(AiMe branded cards are Mifare Classic cards. Other technologies exist though)
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
Hardware:
|
||||
Assembly connector:
|
||||
5V Host in
|
||||
Tx;Rx;GND Host RS232 in
|
||||
Tx;Rx;GND Daisy-chain out
|
||||
Main board (probably LED controller):
|
||||
Silk "837-15084"
|
||||
CN1: Host 5V power in, ?V NFC-sub power out
|
||||
CN2: Host RS232 Tx;Rx;GND in, NFC-sub Tx;Rx out
|
||||
CN3: LED-Sub power and data(?) out
|
||||
DIPSW1: Set to hex nibble 8.
|
||||
Contains ADM3222 RS232 transceiver IC
|
||||
Contains ATMega32 MCU
|
||||
NFC subboard:
|
||||
Sticker: Model "TN32MSEC003S"
|
||||
CN1: ?V power and Tx;Rx;GND in, Tx;Rx;GND ass'y CN daisy out.
|
||||
DIPSW1: Set to hex nibble 0.
|
||||
Contains ATmega168 MCU
|
||||
Contains ADM3202A RS232 transceiver IC
|
||||
Contains shielded RF circuit
|
||||
Entire non-ground-plane PCB area is visible through the chassis
|
||||
torx screws lol
|
||||
LED subboard:
|
||||
Silk: "837-15120"
|
||||
CN1: ?V power and Tx;Rx;GND in.
|
||||
Five RGB LEDs and a bunch of resistors
|
||||
No visible logic ICs..?
|
||||
No DIPSW.
|
||||
|
||||
JVS framing:
|
||||
E0 sync
|
||||
D0 escape (+1 to unescape)
|
||||
Checksum is sum of bytes after unescaping
|
||||
|
||||
Frame header:
|
||||
Frame length (including length byte itself)
|
||||
Address
|
||||
Sequence no, hopefully loops before hitting esc byte...
|
||||
Command byte
|
||||
|
||||
Bus addressing:
|
||||
Low nibble set using DIPSWs
|
||||
High nibble ???
|
||||
Daisy chaining mechanism unknown (RS232 wires probably multi-tap)
|
||||
|
||||
Startup
|
||||
-------
|
||||
|
||||
Addr 00 Command 62:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Unknown. Reset?
|
||||
|
||||
Addr 00 Command 30:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
17 Payload length
|
||||
.. "TN32MSEC003S F/W Ver1.2E"
|
||||
Description:
|
||||
Get firmware version
|
||||
|
||||
Addr 00 Command 32:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
17 Payload length
|
||||
.. "TN32MSEC003S H/W Ver3.0J"
|
||||
Description:
|
||||
Get hardware version
|
||||
|
||||
Addr 08 Command f5:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
LED sub-board reset.
|
||||
Won't accept LED commands until you do this.
|
||||
|
||||
Addr 08 Command f0:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
09 Payload length
|
||||
.. "15084" (part nr for LED board)
|
||||
FF ??
|
||||
11 ??
|
||||
00 ??
|
||||
12 ??
|
||||
Description:
|
||||
Get board "info"
|
||||
|
||||
Addr 00 Command 54:
|
||||
Req:
|
||||
06 Payload length
|
||||
57 'W'
|
||||
43 'C'
|
||||
43 'C'
|
||||
46 'F'
|
||||
76 'v'
|
||||
32 '2'
|
||||
Resp:
|
||||
00 Status byte?
|
||||
00 ??
|
||||
Description:
|
||||
Set Mifare KeyA.
|
||||
"WCCF" might refer this this SEGA arcade game:
|
||||
https://en.wikipedia.org/wiki/World_Club_Champion_Football
|
||||
It's quite old and has AiMe readers, maybe where they first appeared?
|
||||
|
||||
Addr 00 Command 50:
|
||||
Req:
|
||||
06 Payload length
|
||||
60 ??
|
||||
90 ??
|
||||
D0 ?? (This is escaped of course)
|
||||
06 ??
|
||||
32 ??
|
||||
F5 ??
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Possibly Mifare KeyB.
|
||||
|
||||
Polling
|
||||
-------
|
||||
|
||||
Addr 00 Command 40:
|
||||
Req:
|
||||
01 Payload length
|
||||
03 ??
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Poll some other NFC technology?
|
||||
|
||||
Addr 00 Command 42:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp if no MiFare card:
|
||||
00 Status byte
|
||||
01 Payload length
|
||||
00 (represents nothing i guess)
|
||||
Resp if MiFare card:
|
||||
00 Status byte?
|
||||
07 Payload length
|
||||
01 Chunk length?
|
||||
10 ?? Block size maybe?
|
||||
04 Chunk length?
|
||||
.. Mifare UID, four bytes.
|
||||
Description:
|
||||
Check for Mifare card presence?
|
||||
|
||||
Addr 00 Command 41:
|
||||
Req:
|
||||
00 Payload length
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Unknown. Poll some other NFC technology?
|
||||
|
||||
Card read
|
||||
---------
|
||||
|
||||
Addr 00 Command 43:
|
||||
Req:
|
||||
04 Payload length
|
||||
.. Mifare UID, four bytes.
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Select MiFare by UID?
|
||||
|
||||
Addr 00 Command 55:
|
||||
Req:
|
||||
05 Payload length
|
||||
.. Mifare UID, four bytes.
|
||||
03 ??
|
||||
Resp:
|
||||
00 Status byte
|
||||
00 Payload length
|
||||
Description:
|
||||
Unknown.
|
||||
Block 3 on a Mifare sector contains keys and an access control list.
|
||||
It is generally not accessed directly (unless being provisioned?)
|
||||
|
||||
Addr 00 Command 52:
|
||||
Req:
|
||||
05 Payload length
|
||||
.. Mifare UID, four bytes.
|
||||
.. Block number, 1 or 2.
|
||||
Resp for Block 1:
|
||||
00 Status byte
|
||||
10 Payload length (1 block)
|
||||
.. "SBSD"
|
||||
00 00 00 00
|
||||
00 00 00 00
|
||||
00 4E C6 22
|
||||
Resp for Block 2:
|
||||
00 Status byte
|
||||
10 Payload length (1 block)
|
||||
.. 00 00 00 00 00 00 xx xx
|
||||
xx xx xx xx xx xx xx xx
|
||||
Description:
|
||||
Probably reads blocks 1 and 2 from Mifare sector 0.
|
||||
Block 0 contains the "vendor information" and UID.
|
||||
Block 1 contents are unknown, probably AiMe DB info.
|
||||
Block 2 last 10 bytes hex are printed on the card ("local unique id").
|
||||
(Block 3 contains encryption keys so is not allowed to be read)
|
||||
|
||||
LED
|
||||
---
|
||||
|
||||
Addr 08 Command 81:
|
||||
Req:
|
||||
03 Payload length
|
||||
ff Red intensity
|
||||
ff Green intensity
|
||||
ff Blue intensity
|
||||
Resp:
|
||||
None! Command is not acknowledged
|
||||
Description:
|
||||
Set LED color
|
Loading…
Reference in New Issue
Block a user