Near Field Communication
10 Mar 2021Great news — it looks like NFC stickers are going to be the right path forward. Received a bundle today, stuck a sticker on the inside of a cartridge, and my iPhone can pick it up a centimeter away from the outside of the cartridge. Next step is to try to verify with a reader chip.
Unfortunately, the chip I got doesn’t have a datasheet. Thankfully, it’s a common enough model, there’s a guide to its use with the Raspberry Pi already. Lucky me, I’ve learned a little bit about the I2C protocol (which the EEPROMs use), and now I’m learning a bit about the SPI protocol.
After hooking up the RC522 chip via the breadboard and lovingly plagiarizing some code from the tutorial, I got things working. Mostly. While I could pull a unique ID from the NFC stickers, the library did announce an AUTH FAILURE
. It was reporting it on STDOUT, so I could have just tried to suppress the error, but it seems it’s related to the NFC stickers I have being an older standard. I came across this reported issue, and was able to cobble together a solution based around the workaround listed there (the relevant issue).
Remember: we don’t need to actually write any data to these stickers. We just need a unique serial number that the Raspberry Pi can use to drive its own behavior. Merging that with our existing app code, here’s where we’re at:
#!/usr/bin/env python3
import subprocess
import RPi.GPIO as GPIO
from mfrc522 import MFRC522
from time import sleep
ROM_DICT = {
'04:6c:6a:8a:92:4c:68:80:36:48:00:00:e1:10:3e:00': 'Super Mario World (USA).sfc',
'04:53:6c:b3:92:4c:68:81:37:48:00:00:e1:10:3e:00': 'Donkey Kong Country (U).smc'
}
def main():
try:
# Await power on
cartridge_id = get_nfc_id()
print("CARTRIDGE is %s"%cartridge_id)
rom = ROM_DICT[cartridge_id]
print("ROM is %s"%rom)
game = run_game(rom)
game.wait()
# On power off, kill the subprocess
# On reset, restart the subprocess
finally:
cleanup()
def run_game(rom):
return subprocess.Popen([
'/opt/retropie/emulators/retroarch/bin/retroarch',
'-L', '/opt/retropie/libretrocores/lr-snes9x2010/snes9x2010_libretro.so',
'--config', '/opt/retropie/configs/snes/retroarch.cfg',
'/home/pi/RetroPie/roms/snes/%s'%(rom),
'--appendconfig', '/dev/shm/retroarch.cfg'])
def get_nfc_id():
reader = MFRC522()
while True:
status, _ = reader.MFRC522_Request(reader.PICC_REQIDL)
if status != reader.MI_OK:
sleep(0.1)
continue
status, backData = reader.MFRC522_Anticoll()
buf = reader.MFRC522_Read(0)
reader.MFRC522_Request(reader.PICC_HALT)
if buf:
return(':'.join(format(n, '02x') for n in buf))
def cleanup():
GPIO.cleanup()
if __name__ == '__main__':
main()
I opened up a second cartridge to attach a second sticker, and gave it a whirl. Thrilled to report that it works as-expected! Assuming that we can mount the reader within a centimeter of the back of the SNES cartridge, we’re good to go!
We’ll revisit the script at a later point when we’ve moved a bit further on with the housing. We’ll want to wire up the power and reset buttons — as well as the power indicator light — to some of the remaining GPIO pins, and then update our script to support the interrupts.
Next we have a big decision on our hands: are we modding an existing console, or building ourselves something new?