1 | #include "../spi/spi.h"
|
2 | #include "mfrc522.h"
|
3 | #include "../defines.h"
|
4 | #include <util/delay.h>
|
5 |
|
6 | /**
|
7 | * Initializes the MFRC522 chip.
|
8 | */
|
9 | void pcd_init()
|
10 | {
|
11 | pcd_reset();
|
12 |
|
13 |
|
14 | // Reset baud rates
|
15 | pcd_writeRegister(TxModeReg, 0x00);
|
16 | pcd_writeRegister(RxModeReg, 0x00);
|
17 | // Reset ModWidthReg
|
18 | pcd_writeRegister(ModWidthReg, 0x26);
|
19 |
|
20 | pcd_writeRegister(TModeReg, 0x80); // TAuto=1; timer starts automatically at the end of the transmission in all communication modes at all speeds
|
21 | pcd_writeRegister(TPrescalerReg, 0xA9); // TPreScaler = TModeReg[3..0]:TPrescalerReg, ie 0x0A9 = 169 => f_timer=40kHz, ie a timer period of 25?s.
|
22 | pcd_writeRegister(TReloadRegH, 0x03); // Reload timer with 0x3E8 = 1000, ie 25ms before timeout.
|
23 | pcd_writeRegister(TReloadRegL, 0xE8);
|
24 |
|
25 | pcd_writeRegister(TxASKReg, 0x40); // Default 0x00. Force a 100 % ASK modulation independent of the ModGsPReg register setting
|
26 | pcd_writeRegister(ModeReg, 0x3D); // Default 0x3F. Set the preset value for the CRC coprocessor for the CalcCRC command to 0x6363 (ISO 14443-3 part 6.2.4)
|
27 | pcd_antennaOn(); // Enable the antenna driver pins TX1 and TX2 (they were disabled by the reset)
|
28 |
|
29 | }
|
30 |
|
31 | /**
|
32 | * Performs a soft reset on the MFRC522 chip and waits for it to be ready again.
|
33 | */
|
34 | void pcd_reset()
|
35 | {
|
36 | pcd_writeRegister(CommandReg, PCD_SoftReset); // Issue the SoftReset command.
|
37 | // The datasheet does not mention how long the SoftRest command takes to complete.
|
38 | // But the MFRC522 might have been in soft power-down mode (triggered by bit 4 of CommandReg)
|
39 | // Section 8.8.2 in the datasheet says the oscillator start-up time is the start up time of the crystal + 37,74?s. Let us be generous: 50ms.
|
40 | uint8_t count = 0;
|
41 | do {
|
42 | // Wait for the PowerDown bit in CommandReg to be cleared (max 3x50ms)
|
43 | _delay_ms(50);
|
44 | } while ((pcd_readRegister(CommandReg) & (1 << 4)) && (++count) < 3);
|
45 | }
|
46 |
|
47 | /**
|
48 | * Writes a byte to the specified register in the MFRC522 chip.
|
49 | * The interface is described in the datasheet section 8.1.2.
|
50 | */
|
51 | void pcd_writeRegister( uint8_t reg, ///< The register to write to. One of the PCD_Register enums.
|
52 | uint8_t value ///< The value to write.
|
53 | ) {
|
54 | ENABLE_CHIP();
|
55 | spi_transmit(reg); // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
|
56 | spi_transmit(value);
|
57 | DISABLE_CHIP();
|
58 | }
|
59 |
|
60 | /**
|
61 | * Reads a byte from the specified register in the MFRC522 chip.
|
62 | * The interface is described in the datasheet section 8.1.2.
|
63 | */
|
64 | uint8_t pcd_readRegister( uint8_t reg ///< The register to read from. One of the PCD_Register enums.
|
65 | ) {
|
66 | uint8_t value;
|
67 | ENABLE_CHIP();
|
68 | spi_transmit(0x80 | reg); // MSB == 1 is for reading. LSB is not used in address. Datasheet section 8.1.2.3.
|
69 | value = spi_transmit(0); // Read the value back. Send 0 to stop reading.
|
70 | DISABLE_CHIP();
|
71 | return value;
|
72 | }
|
73 |
|
74 | /**
|
75 | * Turns the antenna on by enabling pins TX1 and TX2.
|
76 | * After a reset these pins are disabled.
|
77 | */
|
78 | void pcd_antennaOn() {
|
79 | uint8_t value = pcd_readRegister(TxControlReg);
|
80 | if ((value & 0x03) != 0x03) {
|
81 | pcd_writeRegister(TxControlReg, value | 0x03);
|
82 | }
|
83 | }
|
84 |
|
85 | /**
|
86 | * Turns the antenna off by disabling pins TX1 and TX2.
|
87 | */
|
88 | void pcd_antennaOff() {
|
89 | pcd_clearRegisterBitMask(TxControlReg, 0x03);
|
90 | }
|