Files
banban/ql-application/threadx/interface/custom_app/nfc.c
T

497 lines
15 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)
#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;
/* Stop the AutoColl-created Transceive before starting a clean TX. */
DP1312EA_WriteRawRC(CommandReg, DP1312EA_IDLE);
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_WriteRawRC(CommandReg, DP1312EA_TRANSMIT);
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_start_receive(void)
{
DP1312EA_WriteRawRC(CommandReg, DP1312EA_IDLE);
DP1312EA_WriteRawRC(ComIrqReg, 0x7F);
DP1312EA_SetBitMask(FIFOLevelReg, 0x80);
DP1312EA_WriteRawRC(BitFramingReg, 0x00);
DP1312EA_WriteRawRC(CommandReg, DP1312EA_RECEIVE);
}
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));
nfc_card_emulation_start_receive();
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 <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