338 lines
9.7 KiB
C
338 lines
9.7 KiB
C
#if 1
|
|
#include <stdio.h>
|
|
#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 <stdio.h>
|
|
#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
|