/* NXP PN512 initialization * this was obtained by sniffing the communication between the PN512 and the * CY7C64316 in the ReinerSCT Basisreader, and decoding it with the datasheet. * * (C) 2010 by Steve Markgraf * * All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #define CommandReg 0x01 #define CommIEnReg 0x02 #define DivIEnReg 0x03 #define CommIRqReg 0x04 #define ErrorReg 0x06 #define Status2Reg 0x08 #define FIFOLevelReg 0x0a #define ControlReg 0x0c #define ModeReg 0x11 #define TxControlReg 0x14 #define TxAutoReg 0x15 #define TxSelReg 0x16 #define RxSelReg 0x17 #define RxThresholdReg 0x18 #define DemodReg 0x19 #define MifNFCReg 0x1c #define ManualRCVReg 0x1d #define TypeBReg 0x1e #define ModWidthReg 0x24 #define RFCfgReg 0x26 #define GsNOnReg 0x27 #define CWGsPReg 0x28 #define ModGsPReg 0x29 #define WaterLevelReg 0xbh #define ControlReg 0xch #define TModeReg 0x2a #define TPrescalerReg 0x2b #define TReloadRegH 0x2c #define TReloadRegL 0x2d /* CommandReg bits */ #define RcvOff (1 << 5) #define PowerDown (1 << 4) /* CommIEnReg bits */ #define TimerIEn (1 << 0) /* DivIEnReg bits */ #define IRQPushPull (1 << 7) /* Status2Reg bits */ #define TempSensClear (1 << 7) /* FIFOLevelReg bits */ #define FlushBuffer (1 << 7) /* ControlReg bits */ #define TStopNow (1 << 7) #define TStartNow (1 << 6) #define WrNFCIDtoFIFO (1 << 5) #define Initiator (1 << 4) /* ModeReg bits */ #define TxWaitRF (1 << 5) #define PolSigin (1 << 3) #define CRCPreset (1 << 0) /* TxControlReg */ #define InvTx2RFOn (1 << 7) #define InvTx1RFOn (1 << 6) #define InvTx2RFOff (1 << 5) #define InvTx1RFOff (1 << 4) #define Tx2CW (1 << 3) #define CheckRF (1 << 2) #define Tx2RFEn (1 << 1) #define Tx1RFEn (1 << 0) /* TxAutoReg bits */ #define Force100ASK (1 << 6) unsigned int pn512_read(uint8_t reg) { /* spi_read() should handle 8-bit SPI-reads */ spi_write((1 << 7) | (reg << 1)); return spi_read(); } void pn512_write(uint8_t reg, uint8_t data) { /* spi_write() should handle 8-bit SPI-writes */ spi_write(reg << 1); spi_write(data); } void pn512_init(void) { pn512_write(CommIEnReg, 0x00); pn512_write(GsNOnReg, 0xfe); pn512_write(CWGsPReg, 0x3f); pn512_write(ModGsPReg, 0x12); pn512_write(TxControlReg, 0x00); /* turn off analog part of the receiver */ pn512_write(CommandReg, RcvOff); pn512_write(FIFOLevelReg, FlushBuffer); pn512_write(DivIEnReg, IRQPushPull); /* stop timer */ pn512_write(ControlReg, TStopNow | Initiator); /* write the timer prescaler, which is split in 2 registers */ pn512_write(TModeReg, 0x02); pn512_write(TPrescalerReg, 0x02); /* write the timer reload value */ pn512_write(TReloadRegH, 0x00); pn512_write(TReloadRegL, 0x34); /* route the timer interrupt to the IRQ pin */ pn512_write(CommIEnReg, TimerIEn) pn512_write(CommIRqReg, 0x7f); pn512_write(WaterLevelReg, 0x21); /* start timer */ pn512_write(ControlReg, TStartNow | Initiator); /* could be triggered by PN512 timer interrupt as well */ delay_ms(5); pn512_read(CommIRqReg); pn512_read(ErrorReg); pn512_write(Status2Reg, TempSensClear); pn512_write(ModeReg, TxWaitRF | PolSigin | CRCPreset); /* force ASK modulation */ pn512_write(TxAutoReg, Force100ASK); /* Tx1, Tx2 and SIGOUT pin = Modulation signal from internal encoder */ pn512_write(TxSelReg, 0x14); /* input of contactless UART = Modulation signal from analog part */ pn512_write(RxSelReg, 0x88); /* set bit decoder tresholds */ pn512_write(RxThresholdReg, 0x84); pn512_write(DemodReg, 0x4d); pn512_write(MifNFCReg, 0x62); pn512_write(ManualRCVReg, 0x00); pn512_write(TypeBReg, 0x00); pn512_write(ModWidthReg, 0x1d); /* rx gain 33dB, VRx [Vpp] ∼0.17 */ pn512_write(RFCfgReg, 0x48); /* start TXing the 13.56MHz energy carrier */ pn512_write(TXControlReg, InvTx2RFOn | Tx2RFEn | Tx1RFEn); pn512_write(ControlReg, TStopNow | Initiator); /* change the timer prescaler, which is split in 2 registers */ pn512_write(TModeReg, 0x02); pn512_write(TPrescalerReg, 0xa5); /* change the timer reload value */ pn512_write(TReloadRegH, 0x01); pn512_write(TReloadRegL, 0x38); pn512_write(CommIRqReg, 0x7f); pn512_write(ControlReg, TStartNow | Initiator); }