const rpio = require("rpio") const pins = { NRSTPD: 25, // GPIO 25 MAX_LEN: 16, PCD_IDLE: 0x00, PCD_AUTHENT: 0x0E, PCD_RECEIVE: 0x08, PCD_TRANSMIT: 0x04, PCD_TRANSCEIVE: 0x0C, PCD_RESETPHASE: 0x0F, PCD_CALCCRC: 0x03, PICC_REQIDL: 0x26, PICC_REQALL: 0x52, PICC_ANTICOLL: 0x93, PICC_SELECTTAG: 0x93, PICC_AUTHENT1A: 0x60, PICC_AUTHENT1B: 0x61, PICC_READ: 0x30, PICC_WRITE: 0xA0, PICC_DECREMENT: 0xC0, PICC_INCREMENT: 0xC1, PICC_RESTORE: 0xC2, PICC_TRANSFER: 0xB0, PICC_HALT: 0x50, MI_OK: 0, MI_NOTAGERR: 1, MI_ERR: 2, Reserved00: 0x00, CommandReg: 0x01, CommIEnReg: 0x02, DivlEnReg: 0x03, CommIrqReg: 0x04, DivIrqReg: 0x05, ErrorReg: 0x06, Status1Reg: 0x07, Status2Reg: 0x08, FIFODataReg: 0x09, FIFOLevelReg: 0x0A, WaterLevelReg: 0x0B, ControlReg: 0x0C, BitFramingReg: 0x0D, CollReg: 0x0E, Reserved01: 0x0F, Reserved10: 0x10, ModeReg: 0x11, TxModeReg: 0x12, RxModeReg: 0x13, TxControlReg: 0x14, TxAutoReg: 0x15, TxSelReg: 0x16, RxSelReg: 0x17, RxThresholdReg: 0x18, DemodReg: 0x19, Reserved11: 0x1A, Reserved12: 0x1B, MifareReg: 0x1C, Reserved13: 0x1D, Reserved14: 0x1E, SerialSpeedReg: 0x1F, Reserved20: 0x20, CRCResultRegM: 0x21, CRCResultRegL: 0x22, Reserved21: 0x23, ModWidthReg: 0x24, Reserved22: 0x25, RFCfgReg: 0x26, GsNReg: 0x27, CWGsPReg: 0x28, ModGsPReg: 0x29, TModeReg: 0x2A, TPrescalerReg: 0x2B, TReloadRegH: 0x2C, TReloadRegL: 0x2D, TCounterValueRegH: 0x2E, TCounterValueRegL: 0x2F, Reserved30: 0x30, TestSel1Reg: 0x31, TestSel2Reg: 0x32, TestPinEnReg: 0x33, TestPinValueReg: 0x34, TestBusReg: 0x35, AutoTestReg: 0x36, VersionReg: 0x37, AnalogTestReg: 0x38, TestDAC1Reg: 0x39, TestDAC2Reg: 0x3A, TestADCReg: 0x3B, Reserved31: 0x3C, Reserved32: 0x3D, Reserved33: 0x3E, Reserved34: 0x3F } class MFRC { constructor() { rpio.spiBegin(); rpio.spiChipSelect(0); rpio.spiSetClockDivider(250); rpio.open(pins.NRSTPD, rpio.OUTPUT); rpio.write(pins.NRSTPD, rpio.HIGH); this.MFRC_init(); } MFRC_reset() { this.write_MFRC(pins.CommandReg, pins.PCD_RESETPHASE); } write_MFRC(addr, val) { const txb = new Buffer((addr << 1) & 0x7E, val) rpio.spiTransfer(txb, 2); } read_MFRC(addr) { const txb = new Buffer(((addr << 1) & 0x7E) | 0x80, 0) let rxb = new Buffer(2); rpio.spiTransfer(txb, rxb, 2); return rxb[1]; } setBitMask(reg, mask) { let tmp = this.read_MFRC(reg); this.write_MFRC(reg, tmp | mask); } clearBitMask(reg, mask) { let tmp = this.read_MFRC(reg); this.write_MFRC(reg, tmp & (~mask)); } antennaOn() { let tmp = this.read_MFRC(pins.TxControlReg); if (~(temp & 0x03) != 0) { this.setBitMask(this.TxControlReg, 0x03); } } antennaOff() { this.clearBitMask(this.TxControlReg, 0x03); } MFRC_toCard(command, sendData) { let backData = []; let backLen = 0; let status = pins.MI_ERR; let irqEn = 0x00; let waitIRq = 0x00; let lastBits = null; let n = 0; let i = 0; if (command === pins.PCD_AUTHENT) { irqEn = 0x12; waitIRq = 0x10; } if (command === pins.PCD_TRANSCEIVE) { irqEn = 0x77; waitIRq = 0x30; } this.write_MFRC(pins.CommIEnReg, irqEn | 0x80); this.clearBitMask(pins.CommIrqReg, 0x80); this.setBitMask(pins.FIFOLevelReg, 0x80); this.write_MFRC(pins.CommandReg, pins.PCD_IDLE); while (i < sendData.length) { this.write_MFRC(pins.FIFODataReg, sendData[i]); i++; } this.write_MFRC(pins.CommandReg, command); if (command == pins.PCD_TRANSCEIVE) { this.setBitMask(pins.BitFramingReg, 0x80); } i = 2000; while (true) { n = this.read_MFRC(pins.CommIrqReg); i--; if (~((i !== 0) && ~(n & 0x01) && ~(n & waitIRq)) !== 0) { break; } } this.clearBitMask(pins.BitFramingReg, 0x80); if (i != 0) { if ((this.read_MFRC(pins.ErrorReg) & 0x1B) === 0x00) { status = pins.MI_OK; if ((n & irqEn & 0x01) !== 0) { status = pins.MI_NOTAGERR; } if (command === pins.PCD_TRANSCEIVE) { n = this.read_MFRC(pins.FIFOLevelReg); lastBits = this.read_MFRC(pins.ControlReg) & 0x07; if (lastBits !== 0) { backLen = (n - 1) * 8 + lastBits; } else { backLen = n * 8; } if (n === 0) { n = 1; } if (n > pins.MAX_LEN) { n = pins.MAX_LEN; } i = 0; while (i < n) { backData.push(this.read_MFRC(pins.FIFODataReg)); i++; } } } else { status = pins.MI_ERR; } } return { status, backData, backLen } } MFRC_request(reqMode) { let tagType = []; this.write_MFRC(pins.BitFramingReg, 0x07); tagType.push(reqMode); let {status, backData, backLen} = this.MFRC_toCard(pins.PCD_TRANSCEIVE, tagType); if ((status !== pins.MI_OK) || (backLen !== 0x10)) { status = pins.MI_ERR; } return { status, backLen }; } MFRC_anticoll() { let serNumCheck = 0; let serNum = []; this.write_MFRC(pins.BitFramingReg, 0x00); serNum.push(pins.PICC_ANTICOLL); serNum.push(0x20); let { status, backData, backLen } = this.MFRC_toCard(pins.PCD_TRANSCEIVE, serNum); if (status === pins.MI_OK) { let i = 0; if (backData.length === 5) { while (i < 4) { serNumCheck = serNumCheck ^ backData[i]; i++ } if (serNumCheck !== backData[i]) { status = pins.MI_ERR; } } else { status = pins.MI_ERR; } } return { status, backData }; } calculateCRC(pinData) { this.clearBitMask(pins.DivIrqReg, 0x04); this.setBitMask(pins.FIFOLevelReg, 0x80); let i = 0; while (i < pinData.length) { this.write_MFRC(pins.FIFODataReg, pinData[i]); i++; } this.write_MFRC(pins.CommandReg, pins.PCD_CALCCRC); i = 0xFF; while (true) { let n = this.read_MFRC(pins.DivIrqReg); i--; if (!((i !== 0) && !((n & 0x04) !== 0))) { break; } } let pOutData = []; pOutData.push(this.read_MFRC(pins.CRCResultRegL)); pOutData.push(this.read_MFRC(pins.CRCResultRegM)); return pOutData; } MFRC_selectTag(serNum) { let buf = []; buf.push(pins.PICC_SELECTTAG); buf.push(0x70); let i = 0; while (i < 5) { buf.push(serNum[i]); i++; } let pOut = this.calculateCRC(buf); buf.push(pOut[0]); buf.push(pOut[1]); let { status, backData, backLen } = this.MFRC_toCard(pins.PCD_TRANSCEIVE, buf); if (status === pins.MI_OK && backLen === 0x18) { console.log("Size: " + backData[0]); return backData[0]; } else { return 0; } } MFRC_auth(authMode, blockAddr, sectorKey, serNum) { let buf = []; buf.push(authMode); buf.push(blockAddr); let i = 0; while (i < sectorKey.length) { buf.push(sectorKey[i]); i++; } i = 0; while (i < 4) { buf.push(serNum[i]); i++; } let { status, backData, backLen } = this.MFRC_toCard(pins.PCD_AUTHENT, buf); if (!(status === pins.MI_OK)) { console.log("AUTH ERROR!!"); } if (!(this.read_MFRC(pins.Status2Reg) & 0x08) !== 0) { console.log("AUTH ERROR(status2reg & 0x08) !=== 0"); } return status; } MFRC_stopCrypto1() { this.clearBitMask(pins.Status2Reg, 0x08); } MFRC_read(blockAddr) { let recvData = []; recvData.push(pins.PICC_READ); recvData.push(blockAddr); let pOut = this.calculateCRC(recvData); recvData.push(pOut[0]); recvData.push(pOut[1]); let { status, backData, backLen } = this.MFRC_toCard(pins.PCD_TRANSCEIVE, recvData); if (!(status === pins.MI_OK)) { console.log("Error while reading!"); } let i = 0; if (backData.length === 16) { console.log("Sector " + blockAddr + " " + backData); } } MFRC_write(blockAddr, writeData) { let buf = []; buf.push(pins.PICC_WRITE); buf.push(blockAddr); let crc = this.calculateCRC(buf); buf.push(crc[0]); buf.push(crc[1]); //(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buff) let { status, backData, backLen } = this.MFRC_toCard(pins.PCD_TRANSCEIVE, buf); if (!(status == pins.MI_OK) || !(backLen == 4) || !((backData[0] & 0x0F) == 0x0A)) { status = pins.MI_ERR; } console.log(backLen + " backdata &0x0F == 0x0A " + backData[0] & 0x0F); if (status == pins.MI_OK) { let i = 0; let buff = []; while (i < 16) { buff.push(writeData[i]); i++ } crc = this.calculateCRC(buff); buff.push(crc[0]) buff.push(crc[1]) //(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,buf) let { status, backData, backLen } = this.MFRC_toCard(pins.PCD_TRANSCEIVE, buf); if (!(status == pins.MI_OK) || !(backLen == 4) || !((backData[0] & 0x0F) == 0x0A)) { console.log("Error while writing"); } if (status == pins.MI_OK) { console.log("Data written"); } } } MFRC_dumpClassic1K(key, uid) { let i = 0; while (i < 64) { let status = this.MFRC_auth(pins.PICC_AUTHENT1A, i, key, uid); if (status === pins.MI_OK) { pins.MFRC_read(i); } else { console.log("Authentication Error"); } i++ } } MFRC_init() { rpio.write(pins.NRSTPD, rpio.HIGH); this.MFRC_reset(); this.write_MFRC(pins.TModeReg, 0x8D) this.write_MFRC(pins.TPrescalerReg, 0x3E) this.write_MFRC(pins.TReloadRegL, 30) this.write_MFRC(pins.TReloadRegH, 0) this.write_MFRC(pins.TxAutoReg, 0x40) this.write_MFRC(pins.ModeReg, 0x3D) this.antennaOn(); } } module.exports = MFRC;