#if 1 #include #include "ql_rtos.h" #include "ql_application.h" #include "ql_audio.h" #include "ql_iic.h" #include "ql_gpio.h" #include "app_inc.h" #include "ql_fs.h" #include "DP1312EA.h" #include "TypeA.h" #include "LPCD.h" #define NFC_WORK_MODE_READER 0 #define NFC_WORK_MODE_CARD_EMULATION 1 /* * Phase-1 validation switch. * Set to NFC_WORK_MODE_READER to restore the original NTAG213 reader flow. */ #ifndef NFC_WORK_MODE #define NFC_WORK_MODE NFC_WORK_MODE_CARD_EMULATION #endif #define DP1312EA_PIN_IRQ GPIO_PIN_NO_85 #if (NFC_WORK_MODE == NFC_WORK_MODE_READER) extern int fota_start; extern int audio_packet_type; extern volatile int tts_playing; extern int g_testmode; static ql_sem_t nfc_irq_sem = NULL; // NFC 任务状态 typedef enum { NFC_STATE_LPCD_WAIT, // 低功耗等待中断 NFC_STATE_POLLING, // 500ms 轮询读卡中 } nfc_state_t; static volatile nfc_state_t g_nfc_state = NFC_STATE_LPCD_WAIT; static volatile int g_poll_fail_count = 0; static volatile int g_nfc_irq_trigger = 0; #endif #if (NFC_WORK_MODE == NFC_WORK_MODE_CARD_EMULATION) #define NFC_CARD_FRAME_MAX 64 #define NFC_CARD_TX_POLLS 20 #define NFC_CARD_RX_POLLS 200 #define NFC_CARD_SESSION_POLL_MS 1 #define NFC_IRQ_TX 0x40 #define NFC_IRQ_RX 0x20 #define NFC_IRQ_ERR 0x02 static void nfc_card_emulation_log_status(const char *reason) { printf("NFC card emulation %s: cmd=%02X irq=%02X err=%02X status1=%02X status2=%02X fifo=%02X txm=%02X rxm=%02X framing=%02X\r\n", reason, DP1312EA_ReadRawRC(CommandReg), DP1312EA_ReadRawRC(ComIrqReg), DP1312EA_ReadRawRC(ErrorReg), DP1312EA_ReadRawRC(Status1Reg), DP1312EA_ReadRawRC(Status2Reg), DP1312EA_ReadRawRC(FIFOLevelReg), DP1312EA_ReadRawRC(TxModeReg), DP1312EA_ReadRawRC(RxModeReg), DP1312EA_ReadRawRC(BitFramingReg)); } static u8 nfc_card_emulation_read_frame(u8 *frame, u8 capacity) { u8 fifo_len = DP1312EA_ReadRawRC(FIFOLevelReg) & 0x7F; u8 read_len = fifo_len; if (read_len > capacity) { read_len = capacity; } if (read_len > 0) { DP1312EA_ReadFIFO(frame, read_len); } while (read_len < fifo_len) { (void)DP1312EA_ReadRawRC(FIFODataReg); read_len++; } return fifo_len > capacity ? capacity : fifo_len; } static void nfc_card_emulation_log_frame(const char *prefix, const u8 *frame, u8 length) { u8 i; printf("NFC %s (%u):", prefix, length); for (i = 0; i < length; i++) { printf(" %02X", frame[i]); } printf("\r\n"); } static u8 nfc_card_emulation_send_frame(const u8 *frame, u8 length) { u16 poll_count; u8 irq; /* AutoColl has activated target mode and changed to Transceive. Keep it * active: writing Idle here clears TargetActivated in Status2Reg. */ DP1312EA_WriteRawRC(ComIrqReg, 0x7F); DP1312EA_SetBitMask(FIFOLevelReg, 0x80); DP1312EA_SetBitMask(TxModeReg, 0x80); DP1312EA_SetBitMask(RxModeReg, 0x80); DP1312EA_WriteRawRC(BitFramingReg, 0x00); DP1312EA_WriteFIFO((u8 *)frame, length); DP1312EA_SetBitMask(BitFramingReg, 0x80); for (poll_count = 0; poll_count < NFC_CARD_TX_POLLS; poll_count++) { irq = DP1312EA_ReadRawRC(ComIrqReg); if ((irq & NFC_IRQ_TX) != 0) { DP1312EA_WriteRawRC(BitFramingReg, 0x00); return 1; } if ((irq & NFC_IRQ_ERR) != 0) { break; } ql_rtos_task_sleep_ms(NFC_CARD_SESSION_POLL_MS); } DP1312EA_WriteRawRC(BitFramingReg, 0x00); nfc_card_emulation_log_status("ATS transmit failed"); return 0; } static void nfc_card_emulation_configure_iso_dep(void) { static const u8 card_config[] = { 0x44, 0x00, /* SENS_RES / ATQA */ 0xAA, 0xBB, 0xCC, /* NFCID1; first byte 08 is added by PN512 */ 0x20, /* SEL_RES / SAK: ISO-DEP supported */ 0x01, 0xFE, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xFF, 0xFF, 0x88 }; DP1312EA_PcdConfigISOType('K'); ql_rtos_task_sleep_ms(2); DP1312EA_WriteFIFO((u8 *)card_config, sizeof(card_config)); ql_rtos_task_sleep_ms(2); DP1312EA_WriteRawRC(CommandReg, DP1312EA_MEM); DP1312EA_WriteRawRC(CommandReg, DP1312EA_AUTOCOLL); } static void nfc_card_emulation_start(void) { DP1312EA_WriteRawRC(CommandReg, DP1312EA_IDLE); DP1312EA_WriteRawRC(ComIrqReg, 0x7F); DP1312EA_WriteRawRC(DivIrqReg, 0x7F); DP1312EA_SetBitMask(FIFOLevelReg, 0x80); nfc_card_emulation_configure_iso_dep(); nfc_card_emulation_log_status("started"); printf("NFC phase-2 probe: ATQA=44 00, UID=08 AA BB CC, SAK=20\r\n"); } static void nfc_card_emulation_task(void) { static const u8 ats[] = { 0x03, /* TL: three ATS bytes */ 0x24, /* TB(1) present, FSCI=4 (48-byte frame size) */ 0x80 /* FWI=8 (~77 ms frame waiting time), SFGI=0 */ }; u8 frame[NFC_CARD_FRAME_MAX]; u8 frame_len; u16 poll_count; u8 last_command = 0xFF; u8 command; nfc_card_emulation_start(); while (1) { command = DP1312EA_ReadRawRC(CommandReg) & 0x0F; if (command != last_command) { nfc_card_emulation_log_status("state changed"); last_command = command; } if (command == DP1312EA_TRANSCEIVE) { frame_len = nfc_card_emulation_read_frame(frame, sizeof(frame)); nfc_card_emulation_log_frame("activation RX", frame, frame_len); if (frame_len == 2 && frame[0] == 0xE0) { if (!nfc_card_emulation_send_frame(ats, sizeof(ats))) { nfc_card_emulation_log_status("session complete"); nfc_card_emulation_start(); last_command = DP1312EA_AUTOCOLL; ql_rtos_task_sleep_ms(1); continue; } nfc_card_emulation_log_frame("ATS TX complete", ats, sizeof(ats)); /* Transceive automatically switches from transmit to receive. * Only clear the completed TX interrupt; do not stop command. */ DP1312EA_WriteRawRC(ComIrqReg, NFC_IRQ_TX); for (poll_count = 0; poll_count < NFC_CARD_RX_POLLS; poll_count++) { u8 irq = DP1312EA_ReadRawRC(ComIrqReg); if ((irq & NFC_IRQ_ERR) != 0) { nfc_card_emulation_log_status("ISO-DEP receive error"); break; } if ((irq & NFC_IRQ_RX) != 0 && (DP1312EA_ReadRawRC(FIFOLevelReg) & 0x7F) != 0) { frame_len = nfc_card_emulation_read_frame( frame, sizeof(frame)); nfc_card_emulation_log_frame( "first ISO-DEP RX", frame, frame_len); break; } ql_rtos_task_sleep_ms(NFC_CARD_SESSION_POLL_MS); } if (poll_count == NFC_CARD_RX_POLLS) { nfc_card_emulation_log_status("ISO-DEP receive timeout"); } } else { printf("NFC activation frame is not RATS\r\n"); } nfc_card_emulation_log_status("session complete"); nfc_card_emulation_start(); last_command = DP1312EA_AUTOCOLL; } else if (command != DP1312EA_AUTOCOLL) { nfc_card_emulation_log_status("unexpected command"); nfc_card_emulation_start(); last_command = DP1312EA_AUTOCOLL; } ql_rtos_task_sleep_ms(1); } } #endif #if (NFC_WORK_MODE == NFC_WORK_MODE_READER) static void nfc_irq_wake(void *args) { unsigned char level = 0; ql_eint_disable_wakeup(DP1312EA_PIN_IRQ); ql_gpio_get_level(DP1312EA_PIN_IRQ, &level); printf("DP1312EA_PIN_IRQ level:%d\n", level); ql_eint_enable_wakeup(DP1312EA_PIN_IRQ, PIN_RISING_EDGE); if(g_nfc_irq_trigger==0){ g_nfc_irq_trigger = 1; ql_rtos_semaphore_release(nfc_irq_sem); } } #endif void ql_nfc_task_thread(void *arvg) { #if (NFC_WORK_MODE == NFC_WORK_MODE_CARD_EMULATION) printf("NFC work mode: CARD_EMULATION (phase 2 probe)\r\n"); nfc_card_emulation_task(); #else s8 read_status; while(1) { // ========== 状态1: 低功耗等待中断 ========== if (g_nfc_state == NFC_STATE_LPCD_WAIT) { DP1312EA_LPCD_Start(); // 进入低功耗检卡,等待中断 printf("NFC enter LPCD mode, waiting for IRQ...\r\n"); // 阻塞等待中断唤醒 ql_rtos_semaphore_wait(nfc_irq_sem, 0xFFFFFFFF); DP1312EA_CLEAR_IRQ(); ql_rtos_task_sleep_ms(10); // 防抖延迟 printf("NFC IRQ wake up, switch to polling mode\r\n"); // 切换到轮询模式,重置失败计数 g_nfc_state = NFC_STATE_POLLING; g_poll_fail_count = 0; // 立即执行第一次读卡(不等待200ms) continue; } // ========== 状态2: 200ms 轮询读卡 ========== if (g_nfc_state == NFC_STATE_POLLING) { // 检查是否允许读卡(业务条件) int can_read = 0; if (fota_start == 0 && get_sleep_mode() != 1 && get_mqtt_connect_status() == 1) { if ((get_mqtt_connect_status() == 1 && vad_audio_is_recording() != 1 && audio_packet_type == 0 && tts_playing == 0 && xiaoice_get_play_counter() == 0) || g_testmode == 1) { can_read = 1; } } if (!can_read) { // 当前业务状态不允许读卡,继续等待下次轮询 // printf("NFC business condition not met, keep polling\r\n"); ql_rtos_task_sleep_ms(300); continue; } // 执行读卡 // printf("NFC polling read, fail_count=%d\r\n", g_poll_fail_count); read_status = Test_NTAG213(); if (read_status == 0) { // ===== 读卡成功 ===== printf("NFC read OK, continue polling\r\n"); // 直接回到 LPCD,不再轮询 g_nfc_state = NFC_STATE_LPCD_WAIT; g_poll_fail_count = 0; g_nfc_irq_trigger = 0; ql_rtos_task_sleep_ms(10); continue; // 回到 LPCD 等待 } else { // ===== 读卡失败 ===== g_poll_fail_count++; printf("NFC read failed, fail_count=%d\r\n", g_poll_fail_count); if (g_poll_fail_count >= 3) { // 连续失败 3 次,认为卡已离开 printf("NFC fail 3 times, card removed, back to LPCD\r\n"); // 清理状态,回到低功耗 g_nfc_state = NFC_STATE_LPCD_WAIT; g_poll_fail_count = 0; g_nfc_irq_trigger = 0; // 短暂延迟确保硬件稳定 ql_rtos_task_sleep_ms(10); } else { // 继续轮询,可能卡只是位置偏移 ql_rtos_task_sleep_ms(300); } } } } #endif } void DP1312EA_Init(void) { #if (NFC_WORK_MODE == NFC_WORK_MODE_READER) // 创建信号量 ql_rtos_semaphore_create(&nfc_irq_sem, 0); // 配置中断引脚 ql_gpio_init(DP1312EA_PIN_IRQ, PIN_DIRECTION_IN, PIN_PULL_PD, PIN_LEVEL_LOW); ql_eint_register(DP1312EA_PIN_IRQ, PIN_RISING_EDGE, PIN_PULL_PD, NULL, nfc_irq_wake); ql_eint_enable_wakeup(DP1312EA_PIN_IRQ, PIN_RISING_EDGE); #else /* Poll IRQ/status registers during the phase-1 card-emulation test. */ ql_gpio_init(DP1312EA_PIN_IRQ, PIN_DIRECTION_IN, PIN_PULL_PD, PIN_LEVEL_LOW); #endif // I2C 和芯片初始化 DP1312EA_Reset(); Check_Chip(); // Reader mode starts in low-power card detection. #if (NFC_WORK_MODE == NFC_WORK_MODE_READER) g_nfc_state = NFC_STATE_LPCD_WAIT; g_poll_fail_count = 0; #endif // 创建任务 ql_task_t nfcTaskRef = NULL; ql_rtos_task_create(&nfcTaskRef, 1024*6, 100, "nfc_Task_Ref", ql_nfc_task_thread, NULL); } #endif #if 0 #include #include "ql_rtos.h" #include "ql_application.h" #include "ql_audio.h" #include "ql_iic.h" #include "ql_gpio.h" #include "app_inc.h" #include "ql_fs.h" #include "ql_rtos.h" extern int fota_start; static ql_sem_t nfc_irq_sem = NULL; extern int audio_packet_type; extern volatile int tts_playing; extern int g_testmode; #define DP1312EA_PIN_IRQ GPIO_PIN_NO_87 static void nfc_irq_wake(void *args) { unsigned char level = 0; ql_eint_disable_wakeup(DP1312EA_PIN_IRQ); ql_gpio_get_level(DP1312EA_PIN_IRQ, &level); printf("DP1312EA_PIN_IRQ level:%d\n", level); // ql_eint_enable_wakeup(DP1312EA_PIN_IRQ, PIN_RISING_EDGE); ql_rtos_semaphore_release(nfc_irq_sem); } void ql_nfc_task_thread(void *arvg) { while(1) { #if 0 DP1312EA_LPCD_Start();//进入低功耗检卡,并等待中断,开启之后打开对应读卡函数(模拟卡除外) ql_rtos_semaphore_wait(nfc_irq_sem, 0xFFFFFFFF); DP1312EA_CLEAR_IRQ(); ql_rtos_task_sleep_ms(30); #endif if(fota_start==0&&get_sleep_mode()!=1&&get_mqtt_connect_status()==1){ //在连上mqtt和后台 且非录音和播音状态下可以支持刷nfc if(get_xiaoice_connected_status()==2&&vad_audio_is_recording()!=1 \ &&audio_packet_type==0&&tts_playing==0&&xiaoice_get_play_counter()==0 \ || g_testmode==1 ){ Test_NTAG213(); } } ql_rtos_task_sleep_ms(2000); //ql_eint_enable_wakeup(DP1312EA_PIN_IRQ, PIN_RISING_EDGE); } } void DP1312EA_Init(void) { #if 0 ql_gpio_init(DP1312EA_PIN_IRQ,PIN_DIRECTION_IN,PIN_PULL_PD,PIN_LEVEL_LOW); ql_eint_register(DP1312EA_PIN_IRQ, PIN_RISING_EDGE, PIN_PULL_PD, NULL, nfc_irq_wake); ql_eint_enable_wakeup(DP1312EA_PIN_IRQ, PIN_RISING_EDGE); #endif //I2C初始化 DP1312EA_Reset(); Check_Chip(); ql_rtos_semaphore_create(&nfc_irq_sem, 0); ql_task_t nfcTaskRef = NULL; ql_rtos_task_create(&nfcTaskRef, 1024*6, 100, "nfc_Task_Ref", ql_nfc_task_thread, NULL); } #endif