diff --git a/ql-application/threadx/interface/custom_app/hal_key.c b/ql-application/threadx/interface/custom_app/hal_key.c index 6861c05..0441fda 100644 --- a/ql-application/threadx/interface/custom_app/hal_key.c +++ b/ql-application/threadx/interface/custom_app/hal_key.c @@ -30,9 +30,40 @@ extern int fota_start; #define KEY_LONG_PRESS_1_5S 1500/5 #define KEY_LONG_PRESS_3S 3000/5 #define KEY_LONG_PRESS_5S 5000/5 -#define KEY_LONG_PRESS_10S 10000/5 - -static unsigned char key_down_event = 0; +#define KEY_LONG_PRESS_10S 10000/5 +#define NFC_TX_CLICK_GAP 2000/5 +#define NFC_TX_CLICK_COUNT 5 + +static unsigned char key_down_event = 0; +static unsigned char nfc_tx_click_count = 0; +static u32 nfc_tx_last_click_time = 0; + +extern void app_nfc_tx_mode_start(void); + +static int key_mic_register_short_click(void) +{ + u32 now = ql_rtos_get_systicks(); + + if (nfc_tx_click_count == 0 || + (u32)(now - nfc_tx_last_click_time) > NFC_TX_CLICK_GAP) { + nfc_tx_click_count = 1; + } else { + nfc_tx_click_count++; + } + nfc_tx_last_click_time = now; + + printf("NFC TX key clicks:%u/%u\r\n", + nfc_tx_click_count, NFC_TX_CLICK_COUNT); + if (nfc_tx_click_count >= NFC_TX_CLICK_COUNT) { + nfc_tx_click_count = NFC_TX_CLICK_COUNT; + app_nfc_tx_mode_start(); + return 1; + } + + /* Keep the first click's existing voice action. Suppress clicks 2-4 so + * a rapid NFC gesture does not repeatedly start/interrupt voice work. */ + return nfc_tx_click_count > 1; +} static void key_press_mic(void *args) { @@ -114,31 +145,36 @@ static void key_thread_entry(void *parameter) if(level!=0){ //up key_press_mic_status = 0; - if(ql_rtos_get_systicks() - key_press_mic_time > KEY_LONG_PRESS_3S){ - //app_play_tips_file(10); + if(ql_rtos_get_systicks() - key_press_mic_time > KEY_LONG_PRESS_3S){ + nfc_tx_click_count = 0; + //app_play_tips_file(10); // power_down_status = 1; ql_rtos_task_sleep_s(3); ql_power_down(1); } - else if(ql_rtos_get_systicks() - key_press_mic_time > KEY_WAIT_TIME){ - //休眠唤醒其它线程 - if(app_get_app_sleep_flag()==0){ - app_set_app_operation(1); - } - - int mic_pdp = app_get_data_call_net_status(); - int mic_mqtt = get_mqtt_connect_status(); - printf("[NET-GATE] mic pdp=%d mqtt=%d action=%s\r\n", - mic_pdp, mic_mqtt, - !mic_pdp ? "blocked_no_pdp" : (mic_mqtt != 1 ? "blocked_mqtt_offline" : "start_voice")); - if(mic_pdp && mic_mqtt == 1){ - if(tts_play_interrupt_func()==-2){ - app_play_tips_file(2); - } - }else{ - app_play_tips_file(2); - } - } + else if(ql_rtos_get_systicks() - key_press_mic_time > KEY_WAIT_TIME){ + int nfc_click_handled = key_mic_register_short_click(); + + //休眠唤醒其它线程 + if(app_get_app_sleep_flag()==0){ + app_set_app_operation(1); + } + + if (!nfc_click_handled) { + int mic_pdp = app_get_data_call_net_status(); + int mic_mqtt = get_mqtt_connect_status(); + printf("[NET-GATE] mic pdp=%d mqtt=%d action=%s\r\n", + mic_pdp, mic_mqtt, + !mic_pdp ? "blocked_no_pdp" : (mic_mqtt != 1 ? "blocked_mqtt_offline" : "start_voice")); + if(mic_pdp && mic_mqtt == 1){ + if(tts_play_interrupt_func()==-2){ + app_play_tips_file(2); + } + }else{ + app_play_tips_file(2); + } + } + } key_press_mic_time = ql_rtos_get_systicks(); key_press_mic_counter = 0; @@ -148,8 +184,9 @@ static void key_thread_entry(void *parameter) key_press_mic_status = 1;//表示已经按下了 } - if(ql_rtos_get_systicks() - key_press_mic_time > KEY_LONG_PRESS_3S && power_down_status==0){ - power_down_status = 1; + if(ql_rtos_get_systicks() - key_press_mic_time > KEY_LONG_PRESS_3S && power_down_status==0){ + nfc_tx_click_count = 0; + power_down_status = 1; app_play_tips_file(10); power_down_status = 2; //ql_rtos_task_sleep_s(3); diff --git a/ql-application/threadx/interface/custom_app/nfc.c b/ql-application/threadx/interface/custom_app/nfc.c index ad76d95..2593afa 100644 --- a/ql-application/threadx/interface/custom_app/nfc.c +++ b/ql-application/threadx/interface/custom_app/nfc.c @@ -13,24 +13,18 @@ #include "LPCD.h" #include "hal_api.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 +#define NFC_TX_MODE_DURATION_MS 30000U +#define NFC_TICKS_PER_MS_DIVISOR 5U -#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; +extern uint8_t get_sleep_mode(void); +extern int get_mqtt_connect_status(void); +extern bool vad_audio_is_recording(void); +extern int xiaoice_get_play_counter(void); static ql_sem_t nfc_irq_sem = NULL; @@ -43,9 +37,9 @@ typedef enum { 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 +static volatile u8 g_nfc_tx_mode_requested = 0; +static volatile u32 g_nfc_tx_mode_deadline = 0; -#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 @@ -60,9 +54,40 @@ static volatile int g_nfc_irq_trigger = 0; #define NFC_IRQ_ERR 0x02 extern int hal_os_get_device_sn(char *pdevice_sn); +extern s8 Test_NTAG213(void); static u8 nfc_type2_memory[NFC_TYPE2_MEMORY_SIZE]; +static u8 nfc_tx_mode_is_active(void) +{ + u32 now; + + if (!g_nfc_tx_mode_requested) { + return 0; + } + + now = ql_rtos_get_systicks(); + if ((s32)(now - g_nfc_tx_mode_deadline) >= 0) { + g_nfc_tx_mode_requested = 0; + return 0; + } + + return 1; +} + +void app_nfc_tx_mode_start(void) +{ + g_nfc_tx_mode_deadline = ql_rtos_get_systicks() + + (NFC_TX_MODE_DURATION_MS / NFC_TICKS_PER_MS_DIVISOR); + g_nfc_tx_mode_requested = 1; + + if (nfc_irq_sem != NULL) { + ql_rtos_semaphore_release(nfc_irq_sem); + } + + printf("NFC TX mode requested for 30 seconds\r\n"); +} + 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", @@ -255,7 +280,7 @@ static void nfc_card_emulation_task(void) nfc_card_emulation_start(); - while (1) { + while (nfc_tx_mode_is_active()) { command = DP1312EA_ReadRawRC(CommandReg) & 0x0F; if (command != last_command) { @@ -265,7 +290,8 @@ static void nfc_card_emulation_task(void) if (command == DP1312EA_TRANSCEIVE) { frame_len = nfc_card_emulation_read_frame(frame, sizeof(frame)); - while (frame_len >= 2 && frame[0] == 0x30) { + while (nfc_tx_mode_is_active() && + frame_len >= 2 && frame[0] == 0x30) { nfc_card_emulation_log_frame("Type 2 READ RX", frame, frame_len); nfc_type2_read_pages(frame[1], response); @@ -279,7 +305,8 @@ static void nfc_card_emulation_task(void) DP1312EA_WriteRawRC(ComIrqReg, NFC_IRQ_TX); for (poll_count = 0; - poll_count < NFC_CARD_RX_POLLS; + poll_count < NFC_CARD_RX_POLLS && + nfc_tx_mode_is_active(); poll_count++) { u8 irq = DP1312EA_ReadRawRC(ComIrqReg); @@ -324,13 +351,16 @@ static void nfc_card_emulation_task(void) ql_rtos_task_sleep_ms(1); } -} -#endif -#if (NFC_WORK_MODE == NFC_WORK_MODE_READER) + DP1312EA_WriteRawRC(CommandReg, DP1312EA_IDLE); + DP1312EA_WriteRawRC(ComIrqReg, 0x7F); + DP1312EA_SetBitMask(FIFOLevelReg, 0x80); + printf("NFC TX mode expired, restoring reader mode\r\n"); +} + static void nfc_irq_wake(void *args) { - unsigned char level = 0; + PIN_LEVEL_E level = PIN_LEVEL_LOW; ql_eint_disable_wakeup(DP1312EA_PIN_IRQ); ql_gpio_get_level(DP1312EA_PIN_IRQ, &level); @@ -338,144 +368,121 @@ static void nfc_irq_wake(void *args) ql_eint_enable_wakeup(DP1312EA_PIN_IRQ, PIN_RISING_EDGE); + if (g_nfc_tx_mode_requested) { + return; + } + if(g_nfc_irq_trigger==0){ g_nfc_irq_trigger = 1; ql_rtos_semaphore_release(nfc_irq_sem); } } -#endif +static void nfc_reader_prepare(void) +{ + DP1312EA_Reset(); + Check_Chip(); + g_nfc_state = NFC_STATE_LPCD_WAIT; + g_poll_fail_count = 0; + g_nfc_irq_trigger = 0; +} + +static void nfc_reader_task_step(void) +{ + s8 read_status; + int can_read = 0; + + 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); + + if (g_nfc_tx_mode_requested) { + return; + } + + 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; + return; + } + + if (fota_start == 0 && + get_sleep_mode() != 1 && + get_mqtt_connect_status() == 1) { + if ((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) { + ql_rtos_task_sleep_ms(300); + return; + } + + read_status = Test_NTAG213(); + if (read_status == 0) { + printf("NFC read OK, 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); + return; + } + + g_poll_fail_count++; + printf("NFC read failed, fail_count=%d\r\n", g_poll_fail_count); + if (g_poll_fail_count >= 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); + } +} + void ql_nfc_task_thread(void *arvg) { -#if (NFC_WORK_MODE == NFC_WORK_MODE_CARD_EMULATION) - printf("NFC work mode: CARD_EMULATION (Type 2 NDEF)\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); - } - } + printf("NFC work mode: READER (5 clicks enable Type 2 TX)\r\n"); + + while (1) { + if (nfc_tx_mode_is_active()) { + printf("NFC TX mode enabled\r\n"); + DP1312EA_Reset(); + Check_Chip(); + nfc_card_emulation_task(); + nfc_reader_prepare(); + continue; } + + nfc_reader_task_step(); } -#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_task_t nfcTaskRef = NULL; ql_rtos_task_create(&nfcTaskRef, 1024*6, 100, "nfc_Task_Ref", ql_nfc_task_thread, NULL); } #endif