feat(nfc): add phase-one card emulation mode

This commit is contained in:
chenjintao
2026-09-22 14:53:10 +08:00
parent 381db92214
commit d8b2114d0e
@@ -7,14 +7,30 @@
#include "ql_gpio.h" #include "ql_gpio.h"
#include "app_inc.h" #include "app_inc.h"
#include "ql_fs.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 fota_start;
extern int audio_packet_type; extern int audio_packet_type;
extern volatile int tts_playing; extern volatile int tts_playing;
extern int g_testmode; extern int g_testmode;
static ql_sem_t nfc_irq_sem = NULL; static ql_sem_t nfc_irq_sem = NULL;
#define DP1312EA_PIN_IRQ GPIO_PIN_NO_85
// NFC 任务状态 // NFC 任务状态
typedef enum { typedef enum {
@@ -25,7 +41,65 @@ typedef enum {
static volatile nfc_state_t g_nfc_state = NFC_STATE_LPCD_WAIT; static volatile nfc_state_t g_nfc_state = NFC_STATE_LPCD_WAIT;
static volatile int g_poll_fail_count = 0; static volatile int g_poll_fail_count = 0;
static volatile int g_nfc_irq_trigger = 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) static void nfc_irq_wake(void *args)
{ {
unsigned char level = 0; unsigned char level = 0;
@@ -41,10 +115,15 @@ static void nfc_irq_wake(void *args)
ql_rtos_semaphore_release(nfc_irq_sem); ql_rtos_semaphore_release(nfc_irq_sem);
} }
} }
#endif
void ql_nfc_task_thread(void *arvg) 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; s8 read_status;
while(1) while(1)
@@ -138,11 +217,13 @@ void ql_nfc_task_thread(void *arvg)
} }
} }
} }
#endif
} }
void DP1312EA_Init(void) void DP1312EA_Init(void)
{ {
#if (NFC_WORK_MODE == NFC_WORK_MODE_READER)
// 创建信号量 // 创建信号量
ql_rtos_semaphore_create(&nfc_irq_sem, 0); ql_rtos_semaphore_create(&nfc_irq_sem, 0);
@@ -150,14 +231,20 @@ void DP1312EA_Init(void)
ql_gpio_init(DP1312EA_PIN_IRQ, PIN_DIRECTION_IN, PIN_PULL_PD, PIN_LEVEL_LOW); 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_register(DP1312EA_PIN_IRQ, PIN_RISING_EDGE, PIN_PULL_PD, NULL, nfc_irq_wake);
ql_eint_enable_wakeup(DP1312EA_PIN_IRQ, PIN_RISING_EDGE); 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 和芯片初始化 // I2C 和芯片初始化
DP1312EA_Reset(); DP1312EA_Reset();
Check_Chip(); 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_nfc_state = NFC_STATE_LPCD_WAIT;
g_poll_fail_count = 0; g_poll_fail_count = 0;
#endif
// 创建任务 // 创建任务
ql_task_t nfcTaskRef = NULL; ql_task_t nfcTaskRef = NULL;