#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) 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\r\n", reason, DP1312EA_ReadRawRC(CommandReg), DP1312EA_ReadRawRC(ComIrqReg), DP1312EA_ReadRawRC(ErrorReg), DP1312EA_ReadRawRC(Status1Reg), DP1312EA_ReadRawRC(Status2Reg), DP1312EA_ReadRawRC(FIFOLevelReg)); } static void nfc_card_emulation_start(void) { DP1312EA_WriteRawRC(CommandReg, DP1312EA_IDLE); DP1312EA_WriteRawRC(ComIrqReg, 0x7F); DP1312EA_WriteRawRC(DivIrqReg, 0x7F); DP1312EA_SetBitMask(FIFOLevelReg, 0x80); DP1312EA_Simulate_Card(); nfc_card_emulation_log_status("started"); printf("NFC phase-1 target: ATQA=44 00, UID=08 AA BB CC, SAK=00\r\n"); } static void nfc_card_emulation_task(void) { 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_AUTOCOLL) { /* * AutoColl normally exits after selection or on an RF/error event. * Phase 1 has no ISO14443-4 handler yet, so allow the phone time to * finish its probe, then arm AutoColl again for the next tap. */ ql_rtos_task_sleep_ms(500); nfc_card_emulation_start(); last_command = DP1312EA_AUTOCOLL; } ql_rtos_task_sleep_ms(20); } } #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 1)\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