#include #include "stm32l4xx.h" #include "stm32l4xx_ll_gpio.h" #include "stm32l4xx_ll_spi.h" #include "nfc.h" #include "log.h" #include "util.h" #define SELECT() LL_GPIO_ResetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) #define UNSELECT() LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN) static struct { uint8_t max_frame_size; uint8_t cid; } NFC_STATE; static void flush_rx() { while(LL_SPI_IsActiveFlag_RXNE(SPI1) != 0) { LL_SPI_ReceiveData8(SPI1); } } static void wait_for_tx() { // while (LL_SPI_IsActiveFlag_BSY(SPI1) == 1) // ; while(LL_SPI_GetTxFIFOLevel(SPI1) != LL_SPI_TX_FIFO_EMPTY) ; } static void wait_for_rx() { while(LL_SPI_IsActiveFlag_RXNE(SPI1) == 0) ; } static void ams_print_device(AMS_DEVICE * dev) { printf1(TAG_NFC, "AMS_DEVICE:\r\n"); printf1(TAG_NFC, " io_conf: %02x\r\n",dev->regs.io_conf); printf1(TAG_NFC, " ic_conf0: %02x\r\n",dev->regs.ic_conf0); printf1(TAG_NFC, " ic_conf1: %02x\r\n",dev->regs.ic_conf1); printf1(TAG_NFC, " ic_conf2: %02x\r\n",dev->regs.ic_conf2); printf1(TAG_NFC, " rfid_status: %02x\r\n",dev->regs.rfid_status); printf1(TAG_NFC, " ic_status: %02x\r\n",dev->regs.ic_status); printf1(TAG_NFC, " mask_int0: %02x\r\n",dev->regs.mask_int0); printf1(TAG_NFC, " mask_int1: %02x\r\n",dev->regs.mask_int1); printf1(TAG_NFC, " int0: %02x\r\n",dev->regs.int0); printf1(TAG_NFC, " int1: %02x\r\n",dev->regs.int1); printf1(TAG_NFC, " buffer_status2: %02x\r\n",dev->regs.buffer_status2); printf1(TAG_NFC, " buffer_status1: %02x\r\n",dev->regs.buffer_status1); printf1(TAG_NFC, " last_nfc_addr: %02x\r\n",dev->regs.last_nfc_addr); printf1(TAG_NFC, " product_type: %02x\r\n",dev->regs.product_type); printf1(TAG_NFC, " product_subtype:%02x\r\n",dev->regs.product_subtype); printf1(TAG_NFC, " version_maj: %02x\r\n",dev->regs.version_maj); printf1(TAG_NFC, " version_min: %02x\r\n",dev->regs.version_min); } static uint8_t send_recv(uint8_t b) { wait_for_tx(); LL_SPI_TransmitData8(SPI1, b); wait_for_rx(); b = LL_SPI_ReceiveData8(SPI1); return b; } static void ams_write_reg(uint8_t addr, uint8_t tx) { send_recv(0x00| addr); send_recv(tx); UNSELECT(); SELECT(); } uint8_t ams_read_reg(uint8_t addr) { send_recv(0x20| (addr & 0x1f)); uint8_t data = send_recv(0); UNSELECT(); SELECT(); return data; } // data must be 14 bytes long void read_reg_block2(AMS_DEVICE * dev) { int i; for (i = 0; i < 0x20; i++) { dev->buf[i] = ams_read_reg(i); } } // data must be 14 bytes long void read_reg_block(AMS_DEVICE * dev) { int i; uint8_t mode = 0x20 | (0 ); flush_rx(); send_recv(mode); for (i = 0; i < 0x20; i++) { dev->buf[i] = send_recv(0); } UNSELECT(); SELECT(); } void ams_read_buffer(uint8_t * data, int len) { int i; send_recv(0xa0); while(len--) { *data++ = send_recv(0x00); } UNSELECT(); SELECT(); } void ams_write_buffer(uint8_t * data, int len) { int i; send_recv(0x80); while(len--) { send_recv(*data++); } UNSELECT(); SELECT(); } // data must be 4 bytes void ams_read_eeprom_block(uint8_t block, uint8_t * data) { int i; send_recv(0x7f); send_recv(block << 1); data[0] = send_recv(0); data[1] = send_recv(0); data[2] = send_recv(0); data[3] = send_recv(0); UNSELECT(); SELECT(); } // data must be 4 bytes void ams_write_eeprom_block(uint8_t block, uint8_t * data) { int i; send_recv(0x40); send_recv(block << 1); send_recv(data[0]); send_recv(data[1]); send_recv(data[2]); send_recv(data[3]); UNSELECT(); SELECT(); } void ams_write_command(uint8_t cmd) { send_recv(0xc0 | cmd); UNSELECT(); SELECT(); } const char * ams_get_state_string(uint8_t regval) { if (regval & AMS_STATE_INVALID) { return "STATE_INVALID"; } switch (regval & AMS_STATE_MASK) { case AMS_STATE_OFF: return "STATE_OFF"; case AMS_STATE_SENSE: return "STATE_SENSE"; case AMS_STATE_RESOLUTION: return "STATE_RESOLUTION"; case AMS_STATE_RESOLUTION_L2: return "STATE_RESOLUTION_L2"; case AMS_STATE_SELECTED: return "STATE_SELECTED"; case AMS_STATE_SECTOR2: return "STATE_SECTOR2"; case AMS_STATE_SECTORX_2: return "STATE_SECTORX_2"; case AMS_STATE_SELECTEDX: return "STATE_SELECTEDX"; case AMS_STATE_SENSEX_L2: return "STATE_SENSEX_L2"; case AMS_STATE_SENSEX: return "STATE_SENSEX"; case AMS_STATE_SLEEP: return "STATE_SLEEP"; } return "STATE_WRONG"; } void ams_print_int0(uint8_t int0) { uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); printf1(TAG_NFC," "); if (int0 & AMS_INT_XRF) printf1(tag," XRF"); if (int0 & AMS_INT_TXE) printf1(tag," TXE"); if (int0 & AMS_INT_RXE) printf1(tag," RXE"); if (int0 & AMS_INT_EER_RF) printf1(tag," EER_RF"); if (int0 & AMS_INT_EEW_RF) printf1(tag," EEW_RF"); if (int0 & AMS_INT_SLP) printf1(tag," SLP"); if (int0 & AMS_INT_WU_A) printf1(tag," WU_A"); if (int0 & AMS_INT_INIT) printf1(tag," INIT"); printf1(tag,"\r\n"); } void ams_print_int1(uint8_t int0) { uint32_t tag = (TAG_NFC)|(TAG_NO_TAG); printf1(TAG_NFC," "); if (int0 & AMS_INT_ACC_ERR) printf1(tag," ACC_ERR"); if (int0 & AMS_INT_EEAC_ERR) printf1(tag," EEAC_ERR"); if (int0 & AMS_INT_IO_EEWR) printf1(tag," IO_EEWR"); if (int0 & AMS_INT_BF_ERR) printf1(tag," BF_ERR"); if (int0 & AMS_INT_CRC_ERR) printf1(tag," CRC_ERR"); if (int0 & AMS_INT_PAR_ERR) printf1(tag," PAR_ERR"); if (int0 & AMS_INT_FRM_ERR) printf1(tag," FRM_ERR"); if (int0 & AMS_INT_RXS) printf1(tag," RXS"); printf1(tag,"\r\n"); } void nfc_init() { uint8_t block[4]; memset(&NFC_STATE,0,sizeof(NFC_STATE)); NFC_STATE.max_frame_size = 32; LL_GPIO_SetPinMode(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN,LL_GPIO_MODE_OUTPUT); LL_GPIO_SetOutputPin(SOLO_AMS_CS_PORT,SOLO_AMS_CS_PIN); LL_SPI_SetClockPolarity(SPI1,LL_SPI_POLARITY_LOW); LL_SPI_SetClockPhase(SPI1,LL_SPI_PHASE_2EDGE); LL_SPI_SetRxFIFOThreshold(SPI1,LL_SPI_RX_FIFO_TH_QUARTER); LL_SPI_Enable(SPI1); delay(10); SELECT(); delay(10); ams_write_command(AMS_CMD_DEFAULT); ams_write_command(AMS_CMD_CLEAR_BUFFER); // enable tunneling mode and RF configuration ams_write_reg(AMS_REG_IC_CONF2, AMS_RFCFG_EN | AMS_TUN_MOD); ams_read_eeprom_block(0, block); printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); ams_read_eeprom_block(0, block); printf1(TAG_NFC,"UID: "); dump_hex1(TAG_NFC,block,4); ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); uint8_t sense1 = 0x44; uint8_t sense2 = 0x00; uint8_t selr = 0x20; // SAK if(block[0] != sense1 || block[1] != sense2 || block[2] != selr) { printf1(TAG_NFC,"Writing config block 0\r\n"); block[0] = sense1; block[1] = sense2; block[2] = selr; block[3] = 0x00; ams_write_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); UNSELECT(); delay(10); SELECT(); delay(10); ams_read_eeprom_block(AMS_CONFIG_BLOCK0_ADDR, block); printf1(TAG_NFC,"conf0: "); dump_hex1(TAG_NFC,block,4); } ams_read_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); uint8_t ic_cfg1 = AMS_CFG1_OUTPUT_RESISTANCE_100 | AMS_CFG1_VOLTAGE_LEVEL_2V0; uint8_t ic_cfg2 = AMS_CFG2_TUN_MOD; if (block[0] != ic_cfg1 || block[1] != ic_cfg2) { printf1(TAG_NFC,"Writing config block 1\r\n"); // set IC_CFG1 block[0] = ic_cfg1; // set IC_CFG2 block[1] = ic_cfg2; // mask interrupt bits block[2] = 0x80; block[3] = 0; ams_write_eeprom_block(AMS_CONFIG_BLOCK1_ADDR, block); UNSELECT(); delay(10); SELECT(); delay(10); ams_read_eeprom_block(0x7F, block); printf1(TAG_NFC,"conf1: "); dump_hex1(TAG_NFC,block,4); } } void nfc_write_frame(uint8_t * data, uint8_t len) { if (len > 32) { len = 32; } ams_write_command(AMS_CMD_CLEAR_BUFFER); ams_write_buffer(data,len); ams_write_command(AMS_CMD_TRANSMIT_BUFFER); } int answer_rats(RATS_REQUEST * rats) { if (rats->start != 0xE0) { printf1(TAG_ERR, "Not a RATS request. Ignoring.\r\n"); return 1; } uint8_t fsdi = (rats->parameter & 0xf0) >> 4; uint8_t cid = (rats->parameter & 0x0f); // printf1(TAG_NFC, "fsdi: %x\r\n",fsdi); // printf1(TAG_NFC, "cid: %x\r\n",cid); if (fsdi == 0) NFC_STATE.max_frame_size = 16; else if (fsdi == 1) NFC_STATE.max_frame_size = 24; else NFC_STATE.max_frame_size = 32; uint8_t res[2]; res[0] = 2; res[1] = 2; // 2 FSCI == 32 byte frame size nfc_write_frame(res,2); return 0; } void nfc_loop() { const uint32_t interval = 200; static uint32_t t1 = 0; static uint32_t c = 0; uint8_t buf[32]; AMS_DEVICE ams,ams2; int len = 0; uint8_t def[] = "\x00\x00\x05\x40\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x02\x01\x00"; // if (millis() - t1 > interval) if (1) { t1 = millis(); read_reg_block(&ams); // if (memcmp(def,ams.buf,sizeof(AMS_DEVICE)) != 0) // { // printf1(TAG_NFC,"regs: "); dump_hex1(TAG_NFC,ams.buf,sizeof(AMS_DEVICE)); // } if (ams.regs.rfid_status) { uint8_t state = AMS_STATE_MASK & ams.regs.rfid_status; // if (state != AMS_STATE_SENSE) // printf1(TAG_NFC," %s %d\r\n", ams_get_state_string(ams.regs.rfid_status), millis()); } if (ams.regs.int0) { // ams_print_int0(ams.regs.int0); if (ams.regs.int0 & AMS_INT_XRF) { printf1(TAG_NFC," %d\r\n", millis()); } } if (ams.regs.int1) { // ams_print_int1(ams.regs.int1); } if (ams.regs.buffer_status2 && (ams.regs.int0 & AMS_INT_RXE)) { if (ams.regs.buffer_status2 & AMS_BUF_INVALID) { printf1(TAG_NFC,"Buffer being updated!\r\n"); } else { len = ams.regs.buffer_status2 & AMS_BUF_LEN_MASK; ams_read_buffer(buf, len); // printf1(TAG_NFC,"%d bytes in buffer\r\n", len); // dump_hex1(TAG_NFC, buf, len); } } if (len) { // printf1(TAG_NFC,"RATS %d\r\n",c++); // ams_write_command(AMS_CMD_TRANSMIT_ACK); t1 = millis(); answer_rats((RATS_REQUEST*)buf); printf1(TAG_NFC,"RATS answered %d (took %d)\r\n",millis(), millis() - t1); } } }