48 Commits

Author SHA1 Message Date
lmx
141b538bf5 cun 2025-12-10 17:40:26 +08:00
lmx
23b14f0142 cun 2025-12-09 13:05:51 +08:00
lmx
c870b07b02 cun 2025-12-03 15:11:15 +08:00
lmx
86199b822e 作为主设备去连接其他蓝牙设备 2025-12-03 10:44:14 +08:00
lmx
754a529211 cun 2025-12-03 10:05:53 +08:00
lmx
2bc443584c cun 2025-12-02 19:13:01 +08:00
lmx
f63092fe87 ble测试存档 2025-12-02 16:25:20 +08:00
lmx
ed475e870f 软件读取rfid成功 2025-12-01 18:51:24 +08:00
lmx
b8d48ebe19 uid有时读取失败 2025-12-01 18:05:09 +08:00
lmx
976dafada1 cun 2025-12-01 13:57:54 +08:00
lmx
27aa063107 cun 2025-12-01 11:11:07 +08:00
lmx
9c0bce4568 cun 2025-12-01 10:02:51 +08:00
lmx
6248a4fc34 cun 2025-12-01 10:01:10 +08:00
lmx
627780ea20 11月28日发客户的版本 2025-11-28 18:13:35 +08:00
lmx
ade4b0a1f8 feat: Add rfid feature and .gitignore file 2025-11-28 16:25:35 +08:00
lmx
818e8c3778 chore: Remove tracked build artifacts 2025-11-28 16:24:27 +08:00
lmx
892ed9267b feat: Add rfid feature and .gitignore file 2025-11-28 16:23:06 +08:00
lmx
4af4f13ac6 存档 2025-11-25 18:52:49 +08:00
lmx
4c5da2298f 数据按照小端模式发送 2025-11-25 18:01:17 +08:00
lmx
5c7d9ab822 cun 2025-11-25 15:27:26 +08:00
lmx
60a4e95386 cun 2025-11-25 14:27:19 +08:00
lmx
845cc33fe8 gitignore 2025-11-25 14:16:22 +08:00
lmx
f3710fbb4b 蓝牙协议完成 2025-11-21 18:50:19 +08:00
lmx
91b08dbe47 差气压计的蓝牙协议 2025-11-21 17:10:36 +08:00
lmx
591e7632d2 cun 2025-11-21 15:17:10 +08:00
lmx
baa5979ee1 暂存:数据发送协议完善中 2025-11-21 14:54:21 +08:00
lmx
bdadd5de1e cun 2025-11-21 10:53:47 +08:00
lmx
9ccf1acda8 地磁8面校准完成 2025-11-20 19:30:34 +08:00
lmx
2bfdc81991 部分驱动代码完成,待测试 2025-11-20 09:24:11 +08:00
lmx
054ea8644a 四元数求角度和去重力分量,误差减少 2025-11-18 18:47:05 +08:00
lmx
ad3ab64b72 cun 2025-11-18 17:28:00 +08:00
lmx
ebca849be3 cun 2025-11-18 17:27:06 +08:00
lmx
d0d9c0a630 存档 2025-11-18 10:15:00 +08:00
lmx
b621ef7e44 重力分量去除后仍有偏差 2025-11-13 20:30:10 +08:00
lmx
046986c5c3 cun 2025-11-13 11:13:03 +08:00
lmx
5e587e0527 最新代码 2025-11-13 09:50:42 +08:00
lmx
c88cb70bb1 启动阈值调整 2025-11-12 13:57:59 +08:00
lmx
58ad14691e 修改了六轴配置 2025-11-11 19:31:34 +08:00
lmx
23a71377a2 cun 2025-11-11 09:38:51 +08:00
lmx
d12252dfda 存档 2025-11-10 19:27:37 +08:00
lmx
289a6b780b 存档 2025-11-07 17:14:58 +08:00
lmx
ae980789b6 第6版 2025-11-06 19:24:51 +08:00
lmx
ac7299e7ad cun 2025-11-04 19:20:58 +08:00
lmx
6be3cd1070 3 2025-11-04 14:40:55 +08:00
lmx
671730a351 cun 2025-11-03 18:48:15 +08:00
lmx
97e85df2f8 Ma 2025-10-31 18:12:10 +08:00
lmx
8828f24549 编译通过 2025-10-31 17:43:12 +08:00
lmx
830b4637dd SCU722驱动替换更新 2025-10-31 16:58:39 +08:00
1252 changed files with 13207 additions and 296205 deletions

17
.gitignore vendored Normal file
View File

@ -0,0 +1,17 @@
# 编译生成的目标文件
*.o
*.so
*.d
# 编译生成的最终产物
*.elf
*.fw
*.ufw
*.map
*.lst
*.bc
# VSCode 用户个人设置
# 团队协作时,每个人的配置可能不同,通常不建议提交
.vscode/settings.json

22
.vscode/settings.json vendored
View File

@ -1,22 +0,0 @@
{
"files.associations": {
"board_config.h": "c",
"board_jl701n_demo_cfg.h": "c",
"colorful_lights.h": "c",
"board_jl701n_anc_cfg.h": "c",
"update_loader_download.h": "c",
"iic_soft.h": "c",
"circle_buffer.h": "c",
"default_event_handler.h": "c",
"ui_manage.h": "c",
"charge.h": "c",
"app_main.h": "c",
"app_config.h": "c",
"app_action.h": "c",
"includes.h": "c",
"key_event_deal.h": "c",
"app_umidigi_chargestore.h": "c",
"hci_lmp.h": "c",
"bluetooth.h": "c"
}
}

View File

@ -245,9 +245,7 @@ INCLUDES := \
-Iinclude_lib/media/aispeech/enc/include \
-Icpu/br28/audio_hearing \
-Iinclude_lib/media/cvp \
-Iapps/earphone/xtell_Sensor/buffer \
-Iapps/earphone/xtell_Sensor/sensor \
-Iapps/earphone/xtell_Sensor \
-Iapps/earphone/xtell_remote_control \
-I$(SYS_INC_DIR) \
@ -612,13 +610,21 @@ c_SRC_FILES := \
cpu/br28/uart_dev.c \
cpu/br28/umidigi_chargestore.c \
apps/common/colorful_lights/colorful_lights.c \
apps/earphone/xtell_Sensor/xtell_app_main.c \
apps/earphone/xtell_Sensor/xtell_handler.c \
apps/earphone/xtell_Sensor/send_data.c \
apps/earphone/xtell_Sensor/buffer/circle_buffer.c \
apps/earphone/xtell_Sensor/sensor/LIS2DH12.c \
# 定义需要自动搜索 .c 文件的目录列表
C_SRC_DIRS := \
apps/earphone/xtell_remote_control \
# 使用 shell 的 find 命令递归查找所有 .c 文件
# foreach 遍历 C_SRC_DIRS 中的每一个目录
# $(shell find $(dir) -name "*.c") 对每个目录执行 find 命令
AUTO_C_SRC_FILES := $(foreach dir,$(C_SRC_DIRS),$(shell find $(dir) -name "*.c"))
# 将自动找到的文件列表追加到手动列表中
c_SRC_FILES += $(AUTO_C_SRC_FILES)
# 需要编译的 .S 文件
S_SRC_FILES := \
apps/earphone/sdk_version.z.S \
@ -738,6 +744,8 @@ LFLAGS := \
--plugin-opt=-mattr=+fprev1 \
LIBPATHS := \
-L$(SYS_LIB_DIR) \

View File

@ -18,12 +18,24 @@
#include "bt_tws.h"
#endif
#define ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if ENABLE_XLOG
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
spinlock_t iic_lock;
#define LOG_TAG "[GSENSOR]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define xlog_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
@ -82,20 +94,20 @@ void gSensor_int_io_detect(void *priv)
u8 int_io_status = 0;
u8 det_result = 0;
int_io_status = gpio_read(platform_data->gSensor_int_io);
//log_info("status %d\n",int_io_status);
//xlog("status %d\n",int_io_status);
gSensor_hdl->gravity_sensor_ctl(GSENSOR_INT_DET, &int_io_status);
if (gSensor_hdl->gravity_sensor_check == NULL) {
return;
}
det_result = gSensor_hdl->gravity_sensor_check();
if (det_result == 1) {
log_info("GSENSOR_EVENT_CLICK\n");
xlog("GSENSOR_EVENT_CLICK\n");
gSensor_event_to_user(KEY_EVENT_CLICK);
} else if (det_result == 2) {
log_info("GSENSOR_EVENT_DOUBLE_CLICK\n");
xlog("GSENSOR_EVENT_DOUBLE_CLICK\n");
gSensor_event_to_user(KEY_EVENT_DOUBLE_CLICK);
} else if (det_result == 3) {
log_info("GSENSOR_EVENT_THREE_CLICK\n");
xlog("GSENSOR_EVENT_THREE_CLICK\n");
gSensor_event_to_user(KEY_EVENT_TRIPLE_CLICK);
}
}
@ -117,7 +129,7 @@ int gSensor_read_data(u8 *buf, u8 buflen)
//
int get_gSensor_data(short *buf)
{
// printf("%s",__func__);
// xlog("%s",__func__);
axis_info_t accel_data[32];
if (!gpio_read(platform_data->gSensor_int_io)) {
gSensor_hdl->gravity_sensor_ctl(READ_GSENSOR_DATA, accel_data);
@ -126,7 +138,7 @@ int get_gSensor_data(short *buf)
buf[i * 2] = accel_data[i].x;
buf[i * 2 + 1] = accel_data[i].y;
buf[i * 2 + 2] = accel_data[i].z;
// printf("cnt:%1d x:%5d y:%5d z:%5d\n", i, accel_data[i].x, accel_data[i].y, accel_data[i].z);
// xlog("cnt:%1d x:%5d y:%5d z:%5d\n", i, accel_data[i].x, accel_data[i].y, accel_data[i].z);
}
@ -144,7 +156,7 @@ int read_gsensor_buf(short *buf)
static u8 wr_lock;
int read_gsensor_nbuf(short *buf, short datalen)
{
// printf("%s",__func__);
// xlog("%s",__func__);
if (data_w_cbuf == NULL) {
return 0;
}
@ -161,7 +173,7 @@ int read_gsensor_nbuf(short *buf, short datalen)
return 0;
}
} else {
printf("%s NOT ONLINE ", __func__);
xlog("%s NOT ONLINE ", __func__);
return 0;
}
}
@ -175,91 +187,156 @@ void write_gsensor_data_handle(void)
if (gSensor_info->init_flag == 1) {
// if (read_write_status == 0) {
// printf("%s ",__func__);
// xlog("%s ",__func__);
// return;
// }
if (!gpio_read(platform_data->gSensor_int_io)) {
gSensor_hdl->gravity_sensor_ctl(READ_GSENSOR_DATA, accel_data);
/*for(int i=0;i<29;i++){
printf("cnt:%1d x:%5d y:%5d z:%5d\n", i, accel_data[i].x, accel_data[i].y, accel_data[i].z);
xlog("cnt:%1d x:%5d y:%5d z:%5d\n", i, accel_data[i].x, accel_data[i].y, accel_data[i].z);
}*/
u8 wlen;
wlen = cbuf_write(data_w_cbuf, accel_data, 2 * 3 * 29);
/* for(int i=0;i<29;i++){ */
/* printf("sour x=%06d y=%06d z=%06d",accel_data[i].x,accel_data[i].y,accel_data[i].z); */
/* xlog("sour x=%06d y=%06d z=%06d",accel_data[i].x,accel_data[i].y,accel_data[i].z); */
/* } */
if (wlen == 0) {
printf("data_w_cbuf_full");
xlog("data_w_cbuf_full");
}
}
} else {
// printf("%s ",__func__);
// xlog("%s ",__func__);
return ;
}
}
// 临时的设备扫描诊断函数
void i2c_scanner_probe(void)
{
printf("Starting I2C bus scan...\n");
int devices_found = 0;
// I2C地址范围是 0x08 到 0x77
for (uint8_t addr_7bit = 0x00; addr_7bit < 0x7F; addr_7bit++)
{
// 构建8位的写地址
uint8_t write_addr_8bit = (addr_7bit << 1);
//传入使用的iic句柄编号
iic_start(gSensor_info->iic_hdl);
// 尝试发送写地址,并检查返回值
// iic_tx_byte 返回 1 表示收到了 ACK
if (iic_tx_byte(gSensor_info->iic_hdl, write_addr_8bit))
{
printf("=====================================================================\n");
printf("I2C device found at 7-bit address: 0x%02X\n", addr_7bit);
printf("I2C device found at 8-bit address: 0x%02X\n", write_addr_8bit);
printf("=====================================================================\n");
devices_found++;
}
//传入使用的iic句柄编号
iic_stop(gSensor_info->iic_hdl);
delay(gSensor_info->iic_delay); // 短暂延时
}
if (devices_found == 0) {
printf("Scan finished. No I2C devices found.\n");
} else {
printf("Scan finished. Found %d device(s).\n", devices_found);
}
}
char w_log_buffer_1[100];
char w_log_buffer_2[100];
char w_log_buffer_3[100];
char w_log_buffer_4[100];
char w_log_buffer_5[100];
u8 gravity_sensor_command(u8 w_chip_id, u8 register_address, u8 function_command)
{
// spin_lock(&sensor_iic);
/* os_mutex_pend(&SENSOR_IIC_MUTEX,0); */
u8 ret = 1;
// xlog("iic_start\n");
iic_start(gSensor_info->iic_hdl);
// xlog("iic_tx_byte id\n");
if (0 == iic_tx_byte(gSensor_info->iic_hdl, w_chip_id)) {
ret = 0;
log_e("\n gsen iic wr err 0\n");
xlog("WRITE: I2C NACK on writing ADDR: 0x%X\n", w_chip_id - 1);
strcpy(&w_log_buffer_1, "gsen iic wr err 0\n");
goto __gcend;
}
// xlog("iic delay\n");
delay(gSensor_info->iic_delay);
// xlog("iic_tx_byte: address\n");
if (0 == iic_tx_byte(gSensor_info->iic_hdl, register_address)) {
ret = 0;
log_e("\n gsen iic wr err 1\n");
xlog("WRITE: I2C NACK on writing ADDR: 0x%X\n", register_address);
strcpy(&w_log_buffer_2, "gsen iic wr err 1\n");
goto __gcend;
}
delay(gSensor_info->iic_delay);
// xlog("iic_tx_byte: command\n");
if (0 == iic_tx_byte(gSensor_info->iic_hdl, function_command)) {
ret = 0;
log_e("\n gsen iic wr err 2\n");
xlog("\n gsen iic wr err 2\n");
strcpy(&w_log_buffer_3, "gsen iic wr err 3\n");
goto __gcend;
}
strcpy(&w_log_buffer_4, "gsen iic wr sucess\n");
// xlog("\n gsen iic wr sucess\n");
__gcend:
iic_stop(gSensor_info->iic_hdl);
// spin_unlock(&sensor_iic);
/* os_mutex_post(&SENSOR_IIC_MUTEX); */
return ret;
}
char sen_log_buffer_1[100];
char sen_log_buffer_2[100];
char sen_log_buffer_3[100];
char sen_log_buffer_4[100];
char sen_log_buffer_5[100];
u8 _gravity_sensor_get_ndata(u8 r_chip_id, u8 register_address, u8 *buf, u8 data_len)
{
// printf("%s",__func__);
// xlog("%s",__func__);
// spin_lock(&sensor_iic);
/* os_mutex_pend(&SENSOR_IIC_MUTEX,0); */
u8 read_len = 0;
iic_start(gSensor_info->iic_hdl);
if (0 == iic_tx_byte(gSensor_info->iic_hdl, r_chip_id - 1)) {
log_e("\n gsen iic rd err 0\n");
xlog("GET: I2C NACK on writing ADDR: 0x%X\n", r_chip_id - 1);
read_len = 0;
strcpy(&sen_log_buffer_1, "gsen iic rd err 0\n");
goto __gdend;
}
delay(gSensor_info->iic_delay);
if (0 == iic_tx_byte(gSensor_info->iic_hdl, register_address)) {
log_e("\n gsen iic rd err 1\n");
xlog("GET: I2C NACK on register ADDR: 0x%X\n", register_address);
// xlog("\n gsen iic rd err 1\n");
read_len = 0;
strcpy(&sen_log_buffer_2, "gsen iic rd err 1\n");
goto __gdend;
}
iic_start(gSensor_info->iic_hdl);
if (0 == iic_tx_byte(gSensor_info->iic_hdl, r_chip_id)) {
log_e("\n gsen iic rd err 2\n");
xlog("\n gsen iic rd err 2\n");
read_len = 0;
strcpy(&sen_log_buffer_3, "gsen iic rd err 2\n" );
goto __gdend;
}
@ -272,14 +349,16 @@ u8 _gravity_sensor_get_ndata(u8 r_chip_id, u8 register_address, u8 *buf, u8 data
*buf = iic_rx_byte(gSensor_info->iic_hdl, 0);
read_len ++;
strcpy(&sen_log_buffer_4, "gsen iic rd success\n");
// xlog("\n gsen iic rd success\n");
__gdend:
iic_stop(gSensor_info->iic_hdl);
delay(gSensor_info->iic_delay);
// spin_unlock(&sensor_iic);
/* os_mutex_post(&SENSOR_IIC_MUTEX); */
// strcpy(&sen_log_buffer_5, "gsen iic rd err\n");
return read_len;
}
void gsensor_io_ctl(u8 cmd, void *arg)
@ -302,13 +381,13 @@ int gravity_sensor_init(void *_data)
gSensor_info->iic_hdl = platform_data->iic;
retval = iic_init(gSensor_info->iic_hdl);
log_e("\n gravity_sensor_init\n");
xlog("\n gravity_sensor_init\n");
if (retval < 0) {
log_e("\n open iic for gsensor err\n");
xlog("\n open iic for gsensor err\n");
return retval;
} else {
log_info("\n iic open succ\n");
xlog("\n iic open succ\n");
}
retval = -EINVAL;
@ -320,14 +399,14 @@ int gravity_sensor_init(void *_data)
}
if (retval < 0) {
log_e(">>>gSensor_hdl logo err\n");
xlog(">>>gSensor_hdl logo err\n");
return retval;
}
if (gSensor_hdl->gravity_sensor_init()) {
log_e(">>>>gSensor_Int ERROR\n");
xlog(">>>>gSensor_Int ERROR\n");
} else {
log_info(">>>>gSensor_Int SUCC\n");
xlog(">>>>gSensor_Int SUCC\n");
gSensor_info->init_flag = 1;
if (platform_data->gSensor_int_io != -1) {
gpio_set_pull_up(platform_data->gSensor_int_io, 1);
@ -336,7 +415,7 @@ int gravity_sensor_init(void *_data)
gpio_set_die(platform_data->gSensor_int_io, 1);
data_buf = zalloc(BUF_SIZE);
if (data_buf == NULL) {
printf("gsensor_cbuf_error!");
xlog("gsensor_cbuf_error!");
return 0;
}
@ -347,7 +426,7 @@ int gravity_sensor_init(void *_data)
cbuf_init(data_w_cbuf, data_buf, BUF_SIZE);
/* port_edge_wkup_set_callback(write_gsensor_data_handle); */
/* 已改为使用port_edge_wkup_set_callback_by_index,使用时需要重新实现 */
printf("cbuf_init");
xlog("cbuf_init");
// spin_lock_init(&iic_lock);
// sys_s_hi_timer_add(NULL, gSensor_int_io_detect, 10); //10ms
@ -388,7 +467,7 @@ int gsensor_enable(void)
//工作空间
data_buf = zalloc(BUF_SIZE);
if (data_buf == NULL) {
printf("gsensor_cbuf_error!");
xlog("gsensor_cbuf_error!");
return -1;
}
data_w_cbuf = zalloc(sizeof(cbuffer_t));
@ -396,7 +475,7 @@ int gsensor_enable(void)
return -1;
}
cbuf_init(data_w_cbuf, data_buf, BUF_SIZE);
printf("cbuf_init");
xlog("cbuf_init");
//设置参数
valid = 0;
gSensor_hdl->gravity_sensor_ctl(GSENSOR_RESET_INT, &valid);
@ -404,6 +483,6 @@ int gsensor_enable(void)
if (valid == -1) {
return -1;
}
printf("gsensor_reset_succeed\n");
xlog("gsensor_reset_succeed\n");
return 0;
}

View File

@ -546,6 +546,8 @@ static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_h
app_recieve_callback(0, buffer, buffer_size);
}
// JL_rcsp_auth_recieve(data, len);
extern void le_user_app_send_event(size_t command, unsigned char* data, size_t size);
le_user_app_send_event(ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE, buffer, buffer_size);
break;
@ -588,7 +590,7 @@ static const u8 dueros_dma_uuid_16bit[] = {0x04, 0xFE};
extern u8 *get_chargebox_adv_addr(void);
#endif
static void rcsp_adv_fill_mac_addr(u8 *mac_addr_buf)
void rcsp_adv_fill_mac_addr(u8 *mac_addr_buf)
{
#if (MUTIl_CHARGING_BOX_EN)
u8 *mac_addr = get_chargebox_adv_addr();
@ -1423,9 +1425,25 @@ void ble_module_enable(u8 en)
#if(TCFG_CHARGE_BOX_ENABLE)
extern u8 get_chgbox_lid_status(void);
#endif
void user_ble_gap_device_set(char* name){ //xtell-set
if(strlen(name) < BT_NAME_LEN_MAX){
strcpy(gap_device_name,name);
//刷新广播
bt_ble_adv_enable(0);
make_set_adv_data();
make_set_rsp_data();
bt_ble_adv_enable(1);
}
}
void bt_ble_init(void)
{
log_info("***** ble_init******\n");
//xtell-set
// extern char xt_ble_new_name[9];
// user_ble_gap_device_set(xt_ble_new_name);
gap_device_name = bt_get_local_name();
gap_device_name_len = strlen(gap_device_name);
@ -1645,7 +1663,8 @@ void send_version_to_sibling(void)
data[2] = ver >> 8;
tws_api_send_data_to_sibling(data, sizeof(data), TWS_FUNC_ID_SEQ_RAND_SYNC);
}
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////
@ -1664,11 +1683,12 @@ void send_data_to_ble_client(const u8* data, u16 length)
// 发送数据
int ret = app_send_user_data(ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, data, length, ATT_OP_NOTIFY);
if (ret == 0) { // 假设 0 表示成功
printf("Data sent successfully: Length %d\n", length);
// printf("Data sent successfully: Length %d\n", length);
} else {
printf("Failed to send data: Length %d, Error code: %d\n", length, ret);
// printf("Failed to send data: Length %d, Error code: %d\n", length, ret);
}
} else {
printf("Insufficient buffer space to send data: Length %d\n", length);
// printf("Insufficient buffer space to send data: Length %d\n", length);
}
}
}
#endif

View File

@ -60,7 +60,8 @@ typedef struct {
typedef struct {
//搜索匹配信息
const client_match_cfg_t *match_dev_cfg[CLIENT_MATCH_CONN_MAX];
// const client_match_cfg_t *match_dev_cfg[CLIENT_MATCH_CONN_MAX]; //xtell
client_match_cfg_t *match_dev_cfg[CLIENT_MATCH_CONN_MAX];
//加密保定配置 0 or 1
u8 security_en;
//搜索服务的个数

View File

@ -7,7 +7,7 @@
* notifications.
*/
// *****************************************************************************
#if 0
#include "system/app_core.h"
#include "system/includes.h"
@ -27,7 +27,7 @@
#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_WIRELESS_MIC_CLIENT)
#define SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN 1
#define SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN 0
#define SHOW_RX_DATA_RATE 1
#define SHOW_TX_DATA_RATE 1
@ -189,8 +189,8 @@ static void default_report_data_deal(att_data_report_t *report_data, target_uuid
break;
}
}
static const u8 test_remoter_name1[] = "AC637N_MX(BLE)";//
static const u8 test_remoter_name1[] = "CM-22222";
// static const u8 test_remoter_name1[] = "AC637N_MX(BLE)";//
/* static const u8 test_remoter_name2[] = "AC630N_HID567(BLE)";// */
static u16 default_client_write_handle;
static u16 test_client_timer = 0;
@ -275,7 +275,7 @@ static const client_conn_cfg_t client_conn_config_default = {
#endif
//---------------------------------------------------------------------------
static client_conn_cfg_t *client_config = NULL; //(void *) &client_conn_config_default ;
static client_conn_cfg_t *client_config = (void *) &client_conn_config_default ;
//----------------------------------------------------------------------------
@ -729,7 +729,7 @@ static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rss
log_info_hexdump(adv_address, 6);
adv_data_pt[lenght - 1] = tmp32;
//-------
#if 1 //无线麦产线通过识别特殊字符串进行近距离连接测试
#if 0 //无线麦产线通过识别特殊字符串进行近距离连接测试
if (0 == memcmp(adv_data_pt, SPECIFIC_STRING, strlen(SPECIFIC_STRING))) {
flag_specific_adv_name = 1;
flag_need_judge_rssi = 1;
@ -1483,12 +1483,12 @@ void bt_ble_init(void)
put_buf(match_name, config_name_len);
printf("%s", match_name);
#endif
if (0 == memcmp(match_name, SPECIFIC_STRING, strlen(SPECIFIC_STRING))) {
match_name = &match_name[strlen(SPECIFIC_STRING)];
printf("specific scan%s", match_name);
flag_specific_sacn = 1;
// if (0 == memcmp(match_name, SPECIFIC_STRING, strlen(SPECIFIC_STRING))) {
// match_name = &match_name[strlen(SPECIFIC_STRING)];
// printf("specific scan%s", match_name);
// flag_specific_sacn = 1;
}
// }
set_ble_work_state(BLE_ST_INIT_OK);
conn_pair_vm_do(&conn_pair_info, 0);
@ -1557,10 +1557,25 @@ void client_send_conn_param_update(void)
//----------------------------------------------------------------------------------
//lmx
void rcsp_adv_fill_mac_addr(u8 *mac_addr_buf)
{
#if (MUTIl_CHARGING_BOX_EN)
u8 *mac_addr = get_chargebox_adv_addr();
if (mac_addr) {
swapX(mac_addr, mac_addr_buf, 6);
}
/* printf("mac_addr:"); */
/* printf_buf(mac_addr_buf, 6); */
#else
swapX(bt_get_mac_addr(), mac_addr_buf, 6);
#endif
}
#endif
#endif

View File

@ -0,0 +1,625 @@
#include <stc8h.h>
#include "xt_main.h"
#include "intrins.h"
#include <stdarg.h>
#include "READER.h"
#include "READER_REG.h"
// #include "board.h"
#include "MIFARE.h"
// #include "CPU_CARD.h"
#include "NTAG.h"
void TYPE_A_EVENT(void);
void TYPE_B_EVENT(void);
void TYPE_V_EVENT(void);
void TYPE_F_EVENT(void);
// SPI????
sbit SPI_SCK = P1^5; // SCK
sbit SPI_MOSI = P1^3; // MOSI
sbit SPI_MISO = P1^4; // MISO
sbit SPI_SS = P1^2; // ??
bit busy1;
void GPIO_init()
{
P_SW2 |= 0x80; // Enable access to XFR
// Set all ports to quasi-bidirectional mode
P0M1 = 0; P0M0 = 0;
P1M1 = 0; P1M0 = 0;
P2M1 = 0; P2M0 = 0;
P3M1 = 0; P3M0 = 0;
P4M1 = 0; P4M0 = 0;
P5M1 = 0; P5M0 = 0;
P6M1 = 0; P6M0 = 0;
P7M1 = 0; P7M0 = 0;
}
// UART1 Functions
void Uart1Send(unsigned char dat)
{
while (busy1);
busy1 = 1;
SBUF = dat;
}
// ? Uart1SendString
void Uart1SendString(unsigned char *str)
{
while (*str)
{
Uart1Send(*str);
while (busy1); // ????????
str++;
}
}
void IntToHex(unsigned char *buf, unsigned char num)
{
unsigned char digits[] = "0123456789ABCDEF"; // 大写 HEX 为 %02X
buf[0] = digits[(num >> 4) & 0x0F]; // 高 4 位
buf[1] = digits[num & 0x0F]; // 低 4 位
buf[2] = '\0';
}
// void Uart1Init(void) //115200bps@36MHz
// {
// SCON = 0x50; //8???,?????
// AUXR |= 0x40; //?????1T??
// AUXR &= 0xFE; //??1?????1???????
// TMOD &= 0x0F; //???????
// TL1 = 0xB2; //???????
// TH1 = 0xFF; //???????
// ET1 = 0; //???????
// TR1 = 1; //???1????
// }
void Uart1Init(void) //9600bps@36MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器时钟1T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x56; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
}
void Uart1Isr() interrupt 4
{
unsigned char received;
if (TI)
{
TI = 0;
busy1 = 0;
}
if (RI)
{
received = SBUF; // Read received data
RI = 0;
//Uart2Send(received); // Send received data via UART2
}
}
void Delay100ms() //@36MHz
{
unsigned char data i, j, k;
//_nop_();
i = 19;
j = 68;
k = 67;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay1ms() //@36MHz
{
unsigned char data i, j;
_nop_();
i = 47;
j = 190;
do
{
while (--j);
} while (--i);
}
// SPI?????
void SPI_Init_xt(void)
{
// ??SPI?????
SPCTL =0xD0; // ??SPI,???,??Fosc/4,CPOL=0, CPHA=0
SPSTAT = 0x00; // ??????
P_SW1 = P_SW1 & 0xF3;
// ?????????(SCK, MOSI, SS)
P1M0 |= (1<<5) | (1<<3) | (1<<2); // ??P1.5, P1.3, P1.2???
P1M1 &= ~((1<<5) | (1<<3) | (1<<2));
// MISO???????
P1M0 &= ~(1<<4); // P1.4??
P1M1 |= (1<<4);
SPI_SS = 1; // ???????
}
// SPI??/???????
unsigned char SPI_Transfer(unsigned char dat)
{
SPDAT = dat; // ??????????
while(!(SPSTAT & 0x80)); // ??????
SPSTAT = 0xC0; // ??????
return SPDAT; // ????????
}
// 读寄存器
unsigned char GetReg(unsigned char address, unsigned char *reg_data)
{
unsigned char spi_data;
SPI_SS = 0; // ????,????
*reg_data =0;
// ????(??1??????)
spi_data = (address << 1) | 0x01;
SPI_Transfer(spi_data); // ????
// ???????
*reg_data = SPI_Transfer(0x00); // ??????????
SPI_SS = 1; // ????,????
return SUCCESS;
}
// 写寄存器值
unsigned char SetReg(unsigned char address, unsigned char reg_data)
{
unsigned char spi_data;
SPI_SS = 0; // 拉低片选,开始通信
// 发送地址左移1位并清写标志
spi_data = (address << 1) & 0xFE;
SPI_Transfer(spi_data); // 发送地址
// 发送寄存器数据
SPI_Transfer(reg_data); // 发送数据
SPI_SS = 1; // 拉高片选,结束通信
return SUCCESS;
}
unsigned char FM176XX_HardReset(void)
{
unsigned char reg_data;
SPI_SS = 1;//NSS = 1
P34 =1;//RST = 1
Delay1ms();
P34 =0;//RST = 0
Delay1ms();
GetReg(REG_COMMAND,&reg_data);
if (reg_data != 0x40)
return FAIL;
return SUCCESS;
}
// ?????
unsigned char Reader_Set_HPD( unsigned char mode ) //mode = DISABLE <20>˳<EFBFBD>HPDģʽ <20><>mode = ENABLE <20><><EFBFBD><EFBFBD>HPDģʽ
{
if ( mode == ENABLE )
{
Delay1ms(); //<2F><>ʱ1ms
/******设置一个GPIO输出高*******xtell******/
//PD_1; // PD = 1
P34 = 1;
}
else
{
/******设置一个GPIO输出低*************/
//PD_0; //PD = 0
P34 =0;
Delay1ms(); //<2F><>ʱ1ms<6D><73><EFBFBD>ȴ<EFBFBD>Reader<65><72><EFBFBD><EFBFBD>
}
return (mode);
}
void printHex(unsigned char num)
{
unsigned char buf[3];
IntToHex(buf, num);
// Uart1SendString("Value: ");
Uart1SendString(buf);
// Uart1SendString("\r\n");
}
// // // 简化版 xlog仅支持一个 %02X 或 %02x 参数
// void xlog1(const unsigned char *fmt, unsigned char val)
// {
// unsigned char hex[2];
// int i;
// while (*fmt)
// {
// if (*fmt == '%')
// {
// fmt++;
// // 检查 %02X 或 %02x
// if (*fmt == '0' && *(fmt+1) == '2' && (*(fmt+2) == 'X' || *(fmt+2) == 'x'))
// {
// // 处理 %02X 或 %02x
// // 转换为两位十六进制
// hex[0] = (val >> 4) & 0x0F; // 高4位
// hex[1] = val & 0x0F; // 低4位
// for ( i = 0; i < 2; i++)
// {
// if (hex[i] < 10)
// Uart1Send(hex[i] + '0');
// else
// Uart1Send(hex[i] - 10 + 'A'); // 输出大写 A-F
// while (busy1); // 等待发送完成
// }
// fmt += 3; // 跳过 "02X" 或 "02x"
// }
// else
// {
// // 未识别的格式,发送 % 和当前字符
// Uart1Send('%');
// while (busy1);
// if (*fmt)
// {
// Uart1Send(*fmt);
// while (busy1);
// fmt++;
// }
// }
// }
// else
// {
// // 普通字符直接发送
// Uart1Send(*fmt);
// while (busy1);
// fmt++;
// }
// }
// }
// P34 接芯片pdown
void main(void)
{
unsigned char reg_value,i,tmp1,tmp2;
unsigned char result,reg_data;
ES =1;
EA = 1;
Uart1Init();
GPIO_init();
SPI_Init_xt(); // ???SPI
Uart1SendString("UART1: Hello, STC8H1K28!\r\n");
//xlog("Data: %02X %02X %02x\n", 0xAB, 0x12, 0xFF);
// xlog("1=%02X\r\n",0xAB);
// PrintHex(0xAB); // 应输出 Test: ab
Delay100ms();
#if 0
while(1)
{
// P34 =1;
Uart1Send(0XAb);
// ??:????0x01?????
GetReg(0x7F, &reg_value);
Uart1Send(reg_value);
LOG1("Value: %x", reg_value);
// Delay100ms();
// GetReg(0x02, &tmp1);
// Uart1Send(tmp1);
// Delay100ms();
// // ??????reg_value???
// SetReg(0x02,0x00);
// GetReg(0x02, &tmp2);
// Uart1Send(tmp2);
// ????
FM176XX_HardReset();
for(i = 0; i < 10; i++){
Delay100ms();
}
}
#else
while(1)
{
result = FM176XX_HardReset();
if(result != SUCCESS)
{
Uart1SendString("FM17660 FAIL\r\n");
Delay100ms();
}
else
break;
}
GetReg(REG_VERSION,&reg_data);
// printf( "REG_VERSION = %02X\r\n",reg_data );
Uart1SendString("REG_VERSION =");
printHex(reg_data);
Uart1SendString("\n");
while(1)
{
// Uart1SendString("main loop");
for(i = 0; i < 2; i++){
Delay100ms();
}
// TYPE_A_EVENT();
// TYPE_B_EVENT();
TYPE_V_EVENT();
// TYPE_F_EVENT(); //这里有CPU_CARD.c的函数 暂时注释了
/***现在版本只需要执行 V类型识别 15693 即可 */
}
#endif
}
void TYPE_A_EVENT(void)
{
unsigned char result;
// Uart1SendString(" TYPE_A_EVENT begin\n");
Reader_Set_HPD(DISABLE);
result = ReaderA_Initial();
// Uart1SendString("ReaderA_Initial return =");
// printHex(result);
if(result != SUCCESS)
{
Uart1SendString("INIT_ERROR\r\n");
SetCW(DISABLE);
return;
}
result = SetCW(ENABLE);
// Uart1SendString("SetCW return =");
// printHex(result);
//xtell 注释
// if(result != SUCCESS)
// {
// Uart1SendString("CW_ERROR\r\n");
// SetCW(DISABLE);
// return;
// }
result = ReaderA_CardActivate(&PICC_A);
// Uart1SendString("ReaderA_CardActivate return =");
// printHex(result);
if(result != SUCCESS)
{
//printf("ReaderA_CardActivate_ERROR\r\n");
SetCW(DISABLE);
return;
}
Uart1SendString("************* TYPE A CARD************* \r\n");
// printf("-> ATQA = %02X%02X\r\n",PICC_A.ATQA [0], PICC_A.ATQA [1]);
if(PICC_A.UID_Length == 4)
// printf( "-> UID = %02X%02X%02X%02X\r\n",PICC_A.UID[0], PICC_A.UID[1],PICC_A.UID[2],PICC_A.UID[3]);
if(PICC_A.UID_Length == 8)
// printf( "-> UID = %02X%02X%02X%02X%02X%02X%02X%02X\r\n",PICC_A.UID[0], PICC_A.UID[1],PICC_A.UID[2],PICC_A.UID[3],PICC_A.UID[4], PICC_A.UID[5],PICC_A.UID[6],PICC_A.UID[7]);
// printf( "-> SAK = %02X\r\n",PICC_A.SAK[0]);
if(PICC_A.SAK[0] == 0x08)
{
Uart1SendString("************* Mifare CARD************* \r\n");
result = MIFARE_CARD_EVENT();
}
if((PICC_A.SAK[0] == 0x28)||(PICC_A.SAK[0] == 0x20))
{
Uart1SendString("************* CPU CARD************* \r\n");
// result = CPU_CARD_EVENT();
}
if(PICC_A.SAK[0] == 0x04)
{
Uart1SendString("************* NTAG CARD************* \r\n");
result = NTAG_EVENT();
}
SetCW(DISABLE);
// LED();
}
void TYPE_B_EVENT(void)
{
unsigned char result;
// Uart1SendString("TYPE_B_EVENT begin\n");
ReaderB_Initial();
SetCW(ENABLE);
result = ReaderB_Request(&PICC_B);
if(result != SUCCESS)
{
SetCW(DISABLE);
return;
}
//LED();
Uart1SendString("************* TYPE B CARD************* \r\n");
// printf("-> ATQB = %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\r\n",PICC_B.ATQB[0],PICC_B.ATQB[1],PICC_B.ATQB[2],PICC_B.ATQB[3],PICC_B.ATQB[4],PICC_B.ATQB[5],PICC_B.ATQB[6],PICC_B.ATQB[7],PICC_B.ATQB[8],PICC_B.ATQB[9],PICC_B.ATQB[10],PICC_B.ATQB[11]);
result = ReaderB_Attrib(&PICC_B);
if(result != SUCCESS)
{
SetCW(DISABLE);
return;
}
// printf("-> ATTRIB = %02X\r\n",PICC_B.CID);
result = ReaderB_Get_SN(&PICC_B);
if(result != SUCCESS)
{
SetCW(DISABLE);
return;
}
// printf("-> SN = %02X%02X%02X%02X%02X%02X%02X%02X\r\n",PICC_B.SN[0],PICC_B.SN[1],PICC_B.SN[2],PICC_B.SN[3],PICC_B.SN[4],PICC_B.SN[5],PICC_B.SN[6],PICC_B.SN[7]);
SetCW(DISABLE);
return;
}
void TYPE_V_EVENT(void)
{
unsigned char result,i;
// Uart1SendString("TYPE_V_EVENT begin\n");
ReaderV_Initial();
SetCW(ENABLE);
result = ReaderV_Inventory(&PICC_V);
if (result != SUCCESS)
{
SetCW(DISABLE);
//printf("-> ReaderV Inventory ERROR!\r\n");
return;
}
// LED();
// Uart1SendString("************* TYPE V CARD************* \r\n");
// printf("UID = %02X%02X%02X%02X%02X%02X%02X%02X\r\n",PICC_V.UID[0],PICC_V.UID[1],PICC_V.UID[2],PICC_V.UID[3],PICC_V.UID[4],PICC_V.UID[5],PICC_V.UID[6],PICC_V.UID[7]);
Uart1SendString("UID=");
for(i=0;i<8;i++){
printHex(PICC_V.UID[i]);
}
Uart1SendString("\r\n");
result = ReaderV_Select(&PICC_V);
if (result != SUCCESS)
{
SetCW(DISABLE);
// Uart1SendString("-> ReaderV Select ERROR!\r\n");
return;
}
memcpy(PICC_V.BLOCK_DATA,"\x00\x00\x00\x00",4);
result = ReaderV_WriteSingleBlock(4,&PICC_V);
if (result != SUCCESS)
{
SetCW(DISABLE);
// Uart1SendString("-> ReaderV WriteSingleBlock ERROR!\r\n");
return;
}
// Uart1SendString("WriteSingleBlock SUCCESS\r\n");
result = ReaderV_ReadSingleBlock(4,&PICC_V);
if (result != SUCCESS)
{
SetCW(DISABLE);
// Uart1SendString("-> ReaderV ReadSingleBlock ERROR!\r\n");
return;
}
// printf("BLOCK DATA = %02X%02X%02X%02X \r\n",PICC_V.BLOCK_DATA[0],PICC_V.BLOCK_DATA[1],PICC_V.BLOCK_DATA[2],PICC_V.BLOCK_DATA[3]);
// Uart1SendString("BLOCK DATA=");
for(i=0;i<4;i++){
// printHex(PICC_V.BLOCK_DATA[i]);
}
// Uart1SendString("\r\n");
SetCW(DISABLE);
}
void TYPE_F_EVENT(void)
{
unsigned char result,i;
unsigned char SendBuffer[255];
unsigned char ReceiveBuffer[255];
transmission_struct TPDU;
TPDU.pSendBuffer = SendBuffer;//<2F><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
TPDU.pReceiveBuffer = ReceiveBuffer;//<2F><><EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Uart1SendString("TYPE_F_EVENT begin\n");
ReaderF_Initial();
SetCW(ENABLE);
result = ReaderF_Inventory(&PICC_F);
if(result != SUCCESS)
{
SetCW(DISABLE);
return;
}
// LED();
Uart1SendString("************* TYPE F CARD************* \r\n");
// printf("->TYPE F UID = %02X%02X%02X%02X%02X%02X%02X%02X\r\n",PICC_F.UID[0],PICC_F.UID[1],PICC_F.UID[2],PICC_F.UID[3],PICC_F.UID[4],PICC_F.UID[5],PICC_F.UID[6],PICC_F.UID[7]);
//1401 012E48C23C8C7C3F 00F100000001430088B4
//01 2E 48 C2 3C 8C 7C 3F
memcpy(TPDU.pSendBuffer,"\x1D\x02",2);
memcpy(TPDU.pSendBuffer + 2,PICC_F.UID,8);
memcpy(TPDU.pSendBuffer + 10,"\x09\xFF\xFF\x00\x00\x00\x08\x08\x10\x10\x01\x08\x02\x08\x03\x0C\x04\x08\x09",19);
TPDU.SendLength = 29;
TPDU.Timeout = 100;
// printf("->SEND 2 = ");
// for(i=0;i<TPDU.SendLength;i++)
// printf("%02X",TPDU.pSendBuffer[i]);
// printf("\r\n");
// result = CPU_TPDU(&TPDU); xtell 注释 CPU_CARD.c中的函数
if(result != SUCCESS)
{
SetCW(DISABLE);
return;
}
// printf("->RESPONE = ");
// for(i=0;i<TPDU.ReceiveLength;i++)
// printf("%02X",TPDU.pReceiveBuffer[i] );
// printf("\r\n");
memcpy(TPDU.pSendBuffer,"\x24\x10",2);
memcpy(TPDU.pSendBuffer + 2,PICC_F.UID,8);
memcpy(TPDU.pSendBuffer + 10,"\x02\x00\x00\x00\x08\x06\x08\x10\x10\x01\x08\x02\x08\x03\x0C\x04\x08\x09\x1B\x04\x42\xB1\xD6\x98\x06\x7A",26);
TPDU.SendLength = 36;
TPDU.Timeout = 100;
// printf("->SEND 3 = ");
// for(i=0;i<TPDU.SendLength;i++)
// printf("%02X",TPDU.pSendBuffer[i] );
// printf("\r\n");
// result = CPU_TPDU(&TPDU); xtell 注释 CPU_CARD.c中的函数
if(result != SUCCESS)
{
SetCW(DISABLE);
return;
}
// printf("->RESPONE = ");
// for(i=0;i<TPDU.ReceiveLength;i++)
// printf("%02X",TPDU.pReceiveBuffer[i]);
// printf("\r\n");
//12 12 01 01 07 01 03 17 A6 07 \x45\xC9\x03\xC4\x7B\xF0\xE2\x00
memcpy(TPDU.pSendBuffer,"\x12\x12",2);
memcpy(TPDU.pSendBuffer + 2,PICC_F.UID,8);
memcpy(TPDU.pSendBuffer + 10,"\x45\xC9\x03\xC4\x7B\xF0\xE2\x00",8);//<2F><>8<EFBFBD>ֽ<EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD>Ǽ<EFBFBD><C7BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
TPDU.SendLength = 18;
TPDU.Timeout = 100;
// printf("->SEND 4 = ");
// for(i=0;i<TPDU.SendLength;i++)
// printf("%02X",TPDU.pSendBuffer[i] );
// printf("\r\n");
// result = CPU_TPDU(&TPDU); xtell 注释 CPU_CARD.c中的函数
if(result != SUCCESS)
{
SetCW(DISABLE);
return;
}
// printf("->RESPONE = ");
// for(i=0;i<TPDU.ReceiveLength;i++)
// printf("%02X",TPDU.pReceiveBuffer[i]);
// printf("\r\n");
return;
}

View File

@ -0,0 +1,582 @@
//2018<31><38>2<EFBFBD><32>2<EFBFBD>ձ༭<D5B1><E0BCAD>֧<EFBFBD><D6A7>CPU<50><55>Ƭָ<C6AC><EFBFBD><EEA3AC><EFBFBD>ӷ<EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>
#include "READER.h"
#include "CPU_CARD.h"
#include <string.h>
#include "READER_REG.h"
#include "xt_main.h"
#define CPU_DEBUG 0
struct CPU_CARD_STR CPU_CARD;
#if 0
unsigned char CPU_CARD_EVENT( void ){
return FAIL;
}
#else
unsigned char CPU_CARD_EVENT( void )
{
unsigned char result;
unsigned char SendBuffer[255];
unsigned char ReceiveBuffer[255];
unsigned char i;
transmission_struct APDU;
APDU.pSendBuffer = SendBuffer; /*<2A><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
APDU.pReceiveBuffer = ReceiveBuffer; /*<2A><><EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
result = CPU_Rats( &CPU_CARD.ATS.Length, CPU_CARD.ATS.Ats_Data );
if ( result != SUCCESS )
{
SetCW( DISABLE );
printf( "-> RATS ERROR!\r\n" );
return result;
}
printf( "-> ATS = " );
for(i = 0;i < CPU_CARD.ATS.Length;i++)
printf("%02X", CPU_CARD.ATS.Ats_Data[i]);
printf( "\r\n" );
result = Ats_Process( CPU_CARD.ATS.Length, CPU_CARD.ATS.Ats_Data );
if ( result != SUCCESS )
{
SetCW( DISABLE );
printf( "-> RATS ERROR!\r\n" );
return result;
}
memcpy( APDU.pSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", 7 );
APDU.SendLength = 7;
result = CPU_APDU( &APDU );
if ( result != SUCCESS )
{
SetCW( DISABLE );
printf( "-> APDU ERROR!\r\n" );
return result;
}
printf( "->APDU = " );
for(i=0;i<APDU.ReceiveLength;i++)
printf("%02X", APDU.pReceiveBuffer[i] );
printf( "\r\n" );
memcpy(APDU.pSendBuffer,"\x00\xA4\x04\x00\x07\xD4\x10\x00\x00\x03\x00\x01",12);
APDU.SendLength = 12;
result = CPU_APDU(&APDU);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> APDU ERROR!\r\n");
return result;
}
printf("-> APDU = ");
for(i=0;i<APDU.ReceiveLength;i++)
printf("%02X",APDU.pReceiveBuffer[i]);
printf("\r\n");
memcpy(APDU.pSendBuffer,"\x00\xA4\x04\x00\x0E\x32\x50\x41\x59\x2E\x53\x59\x53\x2E\x44\x44\x46\x30\x31",19);
APDU.SendLength = 19;
result = CPU_APDU(&APDU);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> APDU ERROR!\r\n");
return result;
}
printf("-> Response = ");
for(i=0;i<APDU.ReceiveLength;i++)
printf("%02X",APDU.pReceiveBuffer[i]);
printf("\r\n");
memcpy(APDU.pSendBuffer,"\x00\xA4\x04\x00\x08\xA0\x00\x00\x03\x33\x01\x01\x01\x00",14);
APDU.SendLength = 14;
result = CPU_APDU(&APDU);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> APDU ERROR!\r\n");
return result;
}
printf("-> Response = ");
for(i=0;i<APDU.ReceiveLength;i++)
printf("%02X",APDU.pReceiveBuffer[i]);
printf("\r\n");
memcpy(APDU.pSendBuffer,"\x80\xA8\x00\x00\x24\x83\x22\x28\x00\x00\x80\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x01\x56\x00\x00\x00\x00\x00\x01\x56\x13\x08\x28\x82\x12\x34\x56\x78\x00\x00",42);
APDU.SendLength = 42;
result = CPU_APDU(&APDU);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> APDU ERROR!\r\n");
return result;
}
printf("-> Response = ");
for(i=0;i<APDU.ReceiveLength;i++)
printf("%02X",APDU.pReceiveBuffer[i]);
printf("\r\n");
memcpy( APDU.pSendBuffer, "\x00\x84\x00\x00\x08", 5 );
APDU.SendLength = 5;
result = CPU_APDU( &APDU );
if ( result != SUCCESS )
{
SetCW( DISABLE );
printf( "-> APDU ERROR!\r\n" );
return result;
}
printf( "-> Response = " );
for(i=0;i<APDU.ReceiveLength;i++)
printf("%02X",APDU.pReceiveBuffer[i]);
printf( "\r\n" );
return result;
}
#endif
#if 0
void Write_FIFO(unsigned char length,unsigned char* buff)
{
}
#else
void Write_FIFO(unsigned char length,unsigned char* buff)
{
unsigned char i;
for(i=0;i<length;i++)
{
SetReg(REG_FIFODATA,buff[i]);
}
}
#endif
#if 0
void Read_FIFO(unsigned char length,unsigned char* buff)
{
}
#else
void Read_FIFO(unsigned char length,unsigned char* buff)
{
unsigned char i;
for(i=0;i<length;i++)
{
GetReg(REG_FIFODATA,&buff[i]);
}
}
#endif
#if 0
unsigned char FM176XX_TPDU( transmission_struct *tpdu )
{
return FAIL;
}
#else
unsigned char FM176XX_TPDU( transmission_struct *tpdu )
{
unsigned char result,irq0,irq1,error;
unsigned int i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_IRQ0,0x7F);//Clear IRQ0
SetReg(REG_IRQ1,0x7F); //Clear IRQ1
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
Write_FIFO(tpdu->SendLength,tpdu->pSendBuffer);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
// SetTimer(tpdu->Timeout);
SetCommand(CMD_TRANSCEIVE);
for(i = 0;i < tpdu->Timeout; i++)
{
DelayMs(1);//<2F><><EFBFBD>յȴ<D5B5><C8B4><EFBFBD>ʱ
GetReg(REG_IRQ0,&irq0);
if(irq0 & BIT_RXIRQ)
{
GetReg( REG_ERROR, &error ); /*Get Error Status */
error = error & (BIT_NODATAERR | BIT_COLLDET | BIT_PROTERR | BIT_INTEGERR);
if(error != 0)
return FAIL;//<2F><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD>
GetReg(REG_FIFOLENGTH,&tpdu->ReceiveLength);
if(tpdu->ReceiveLength > 0)
{
Read_FIFO(tpdu->ReceiveLength,tpdu->pReceiveBuffer);
result = SUCCESS;
return result;
}
}
GetReg(REG_IRQ1,&irq1);
// if(irq1 & BIT_TIMER1IRQ)
// {
// result = FAIL;//δ<><CEB4>timeoutʱ<74><CAB1><EFBFBD>ڽ<EFBFBD><DABD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD>
// }
}
result = FAIL;//δ<><CEB4>timeoutʱ<74><CAB1><EFBFBD>ڽ<EFBFBD><DABD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD>
return result;
}
#endif
/****************************************************************/
/*<2A><><EFBFBD><EFBFBD>: Rats */
/*<2A><><EFBFBD><EFBFBD>: Request for answer to select */
/*<2A><><EFBFBD><EFBFBD>: */
/* */
/*<2A><><EFBFBD>: */
/* ats_len<65><6E><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD>ATS<54><53><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD> */
/* *ats<74><73><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD>ATS<54><53><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8> */
/* OK: Ӧ<><D3A6><EFBFBD><EFBFBD>ȷ */
/* ERROR: Ӧ<><D3A6><EFBFBD><EFBFBD><EFBFBD> */
/****************************************************************/
#if 0
unsigned char CPU_Rats( unsigned char *ats_len, unsigned char *ats )
{
return FAIL;
}
#else
unsigned char CPU_Rats( unsigned char *ats_len, unsigned char *ats )
{
unsigned char result;
unsigned char outbuffer[2], inbuffer[64];
transmission_struct tpdu;
tpdu.pSendBuffer = outbuffer;
tpdu.pReceiveBuffer = inbuffer;
tpdu.pSendBuffer[0] = 0xE0; /*Start byte */
tpdu.pSendBuffer[1] = 0x50; /*default = 0x50 */
tpdu.SendLength = 2;
tpdu.Timeout = 160;
//CPU_CARD.FWT = 160;//Ĭ<><C4AC><EFBFBD><EFBFBD>ʱʱ<CAB1><CAB1>
result = FM176XX_TPDU( &tpdu );
if ( result == SUCCESS )
{
*ats_len = tpdu.ReceiveLength;
memcpy( ats, tpdu.pReceiveBuffer, *ats_len );
}
return (result);
}
#endif
#if 0
unsigned char Ats_Process( unsigned char ats_len, unsigned char *ats )/* ATS<54><53><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD> */
{
return FAIL;
}
#else
unsigned char Ats_Process( unsigned char ats_len, unsigned char *ats )/* ATS<54><53><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD> */
{
unsigned char result, offset;
if ( (ats_len == ats[0]) || (ats_len > 2) )/*TL */
{
CPU_CARD.FSCI = ats[1] & 0x0F;
if ( CPU_CARD.FSCI == 0 )
CPU_CARD.FSC = 13;
if ( CPU_CARD.FSCI == 1 )
CPU_CARD.FSC = 21;
if ( CPU_CARD.FSCI == 2 )
CPU_CARD.FSC = 29;
if ( CPU_CARD.FSCI == 3 )
CPU_CARD.FSC = 37;
if ( CPU_CARD.FSCI == 4 )
CPU_CARD.FSC = 45;
if ( CPU_CARD.FSCI == 5 )
CPU_CARD.FSC = 61;
if ( CPU_CARD.FSCI == 6 )
CPU_CARD.FSC = 93;
if ( CPU_CARD.FSCI == 7 )
CPU_CARD.FSC = 125;
if ( CPU_CARD.FSCI > 7 )
CPU_CARD.FSC = 253;
//CPU_CARD.FSC = 13;
printf( "-> CPU_CARD.FSC = %02X\r\n",CPU_CARD.FSC );
}
else
{
result = FAIL;
return (result);
}
offset = 0;
result = SUCCESS;
if ( ats[1] & BIT5 ) /*TA */
{
CPU_CARD.TA = ats[2];
offset++;
}
if ( ats[1] & BIT6 ) /*TB */
{
CPU_CARD.TB = ats[2 + offset];
CPU_CARD.SFGI = CPU_CARD.TB & 0x0F;
CPU_CARD.FWI = (CPU_CARD.TB >> 4) & 0x0F;
printf( "-> CPU_CARD.SFGI = %02X\r\n",CPU_CARD.SFGI );
printf( "-> CPU_CARD.FWI = %02X\r\n",CPU_CARD.FWI);
if ( CPU_CARD.FWI < 2 )
CPU_CARD.FWT = 1;
if ( CPU_CARD.FWI == 2 )
CPU_CARD.FWT = 2;
if ( CPU_CARD.FWI == 3 )
CPU_CARD.FWT = 3;
if ( CPU_CARD.FWI == 4 )
CPU_CARD.FWT = 5;
if ( CPU_CARD.FWI == 5 )
CPU_CARD.FWT = 10;
if ( CPU_CARD.FWI == 6 )
CPU_CARD.FWT = 20;
if ( CPU_CARD.FWI == 7 )
CPU_CARD.FWT = 40;
if ( CPU_CARD.FWI == 8 )
CPU_CARD.FWT = 80;
if ( CPU_CARD.FWI == 9 )
CPU_CARD.FWT = 160;
if ( CPU_CARD.FWI == 10 )
CPU_CARD.FWT = 310;
if ( CPU_CARD.FWI == 11 )
CPU_CARD.FWT = 620;
if ( CPU_CARD.FWI == 12 )
CPU_CARD.FWT = 1240;
if ( CPU_CARD.FWI == 13 )
CPU_CARD.FWT = 2480;
if ( CPU_CARD.FWI > 13 )
CPU_CARD.FWT = 4950;
offset++;
}
if ( ats[1] & BIT7 )/*TC */
{
CPU_CARD.TC = ats[2 + offset];
offset++;
}
CPU_CARD.PCB = 0x02;/*PCB<43><42>ʼֵΪ0x02 */
return (result);
}
#endif
#if 1
//xtell 同时把CPU_TPDU 和 CPU_NAk 用空函数替换 SPi正常
unsigned char CPU_NAK( transmission_struct *tpdu ) /* <20><>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD>NAK */
{
return FAIL;
}
#else
unsigned char CPU_NAK( transmission_struct *tpdu ) /* <20><>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD>NAK */
{
unsigned char result, tpdu_send_buffer[255],tpdu_receive_buffer[255];
tpdu->pSendBuffer = tpdu_send_buffer;
tpdu->pReceiveBuffer = tpdu_receive_buffer;
tpdu->pSendBuffer [0] = 0xB0 | CPU_CARD.PCB;
tpdu->SendLength = 1;
/*printf( "NAK\r\n" );*/
result = FM176XX_TPDU( tpdu );
return (result);
}
#endif
#if 0
unsigned char CPU_TPDU( transmission_struct *tpdu )
{
return FAIL;
}
#else
unsigned char CPU_TPDU( transmission_struct *tpdu )
{
unsigned char result, i, pcb_byte;
transmission_struct nak_tpdu;
result = FM176XX_TPDU( tpdu );
for ( i = 0; i < 3; i++ )
{
if ( result != SUCCESS )
{
result = CPU_NAK( &nak_tpdu );
if(result == SUCCESS)
{
if(nak_tpdu.ReceiveLength > 0)
{
memcpy( &pcb_byte, nak_tpdu.pReceiveBuffer, 1 );
if((pcb_byte & 0xF0) == 0xA0)//R(ACK)
{
#if CPU_DEBUG
printf("...pcb_byte = %02X\r\n",pcb_byte);
printf("...CPU_CARD.PCB = %02X\r\n",CPU_CARD.PCB);
#endif
if((pcb_byte & 0x03) != CPU_CARD.PCB)
{
result = FM176XX_TPDU( tpdu );
}
else
{
tpdu->pSendBuffer[0] = tpdu->pSendBuffer[0] ^ 0x01;//
CPU_CARD.PCB = tpdu->pSendBuffer[0] & 0x03;
result = FM176XX_TPDU( tpdu );
}
}
}
}
}
else
{
break;
}
}
return (result);
}
#endif
/****************************************************************/
/*<2A><><EFBFBD><EFBFBD>: CPU_APDU */
/*<2A><><EFBFBD><EFBFBD>: <20>ú<EFBFBD><C3BA><EFBFBD>ʵ<EFBFBD><CAB5>ת<EFBFBD><D7AA>APDU<44><55><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD> CPU card reset */
/*<2A><><EFBFBD><EFBFBD>: */
/* */
/*<2A><><EFBFBD>: */
/* ats_len<65><6E><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD> */
/* ats<74><73><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8> */
/* OK: Ӧ<><D3A6><EFBFBD><EFBFBD>ȷ */
/* ERROR: Ӧ<><D3A6><EFBFBD><EFBFBD><EFBFBD> */
/****************************************************************/
#if 1
//xtell 同时把CPU_TPDU 和 CPU_NAk 用空函数替换 SPi正常
unsigned char CPU_APDU( transmission_struct *apdu )
{
return FAIL;
}
#else
unsigned char CPU_APDU( transmission_struct *apdu )
{
unsigned char result, pcb_byte, tpdu_send_buffer[255],tpdu_receive_buffer[255], i;
unsigned char unsent_length;
transmission_struct tpdu;
tpdu.pSendBuffer = tpdu_send_buffer;
tpdu.pReceiveBuffer = tpdu_receive_buffer;
tpdu.Timeout = CPU_CARD.FWT;
apdu->ReceiveLength = 0;
unsent_length = apdu->SendLength; /*<2A><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD> */
for ( i = 0; i < 16; i++ ) /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><E9B3A4>16<31><36><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>16<31><36><EFBFBD><EFBFBD><E9B7A2> */
{
#if CPU_DEBUG
printf("unsent_length = %02X\r\n",unsent_length);
#endif
if ( unsent_length < CPU_CARD.FSC )
{
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
tpdu.pSendBuffer[0] = CPU_CARD.PCB; /*PCB<43>ֽ<EFBFBD>д<EFBFBD><D0B4>TPDU<44><55><EFBFBD><EFBFBD> */
memcpy( tpdu.pSendBuffer + 1, apdu->pSendBuffer + apdu->SendLength - unsent_length, unsent_length ); /*APDU<44><55><EFBFBD><EFBFBD>д<EFBFBD><D0B4>TPDU<44><55><EFBFBD><EFBFBD> */
tpdu.SendLength = unsent_length + 1; /*<2A><><EFBFBD>ͳ<EFBFBD><CDB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1 */
#if CPU_DEBUG
printf("--> ");
for(i=0;i<tpdu.SendLength;i++)
printf("%02X",tpdu.pSendBuffer[i]);
printf("\r\n");
#endif
result = CPU_TPDU( &tpdu );
if ( (result != SUCCESS) || (tpdu.ReceiveLength == 0) )
return (result);
#if CPU_DEBUG
printf("<-- ");
for(i=0;i<tpdu.ReceiveLength;i++)
printf("%02X",tpdu.pReceiveBuffer[i]);
printf("\r\n");
#endif
unsent_length = 0; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD><EFBFBD><EFBFBD>0 */
break; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̺<EFBFBD><CCBA>˳<EFBFBD>ѭ<EFBFBD><D1AD> */
}
else
{
/*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3>ȴ<EFBFBD><C8B4>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD>ͣ<EFBFBD>ÿ<EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>Ϊ<EFBFBD><CEAA>CPU_CARD.FSC - 1<><31> */
tpdu.pSendBuffer[0] = CPU_CARD.PCB | 0x10; /*PCB<43>ֽ<EFBFBD>д<EFBFBD><D0B4>TPDU<44><55><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӱ<EFBFBD>ʶ */
memcpy( tpdu.pSendBuffer + 1, apdu->pSendBuffer + apdu->SendLength - unsent_length, CPU_CARD.FSC - 1 ); /*APDU<44><55><EFBFBD><EFBFBD>д<EFBFBD><D0B4>TPDU<44><55><EFBFBD><EFBFBD> */
tpdu.SendLength = CPU_CARD.FSC; /*<2A><><EFBFBD><EFBFBD>ͳ<EFBFBD><CDB3><EFBFBD> */
#if CPU_DEBUG
printf("..--> ");
for(i=0;i<tpdu.SendLength;i++)
printf("%02X",tpdu.pSendBuffer[i]);
printf("\r\n");
#endif
result = CPU_TPDU( &tpdu );
#if CPU_DEBUG
printf("<-- ");
for(i=0;i<tpdu.ReceiveLength;i++)
printf("%02X",tpdu.pReceiveBuffer[i]);
printf("\r\n");
#endif
if ( (result != SUCCESS) && (tpdu.ReceiveLength == 1) )
return (result);
memcpy( &pcb_byte, tpdu.pReceiveBuffer, 1 ); /* */
if ( (pcb_byte == 0xA2) || (pcb_byte == 0xA3) )
{
unsent_length = unsent_length - (CPU_CARD.FSC - 1); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD> */
CPU_CARD.PCB = (pcb_byte & 0x0F) ^ 0x01; /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PCB<43>ֽ<EFBFBD> */
#if CPU_DEBUG
printf("unsent_length = %02X\r\n",unsent_length);
#endif
}
else
return (FAIL); /* */
}
}
for ( i = 0; i < 255; i++ ) /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̣<EFBFBD><CCA3><EFBFBD><EFBFBD>֧<EFBFBD><D6A7>255<35><35>ACK<43><4B><EFBFBD><EFBFBD>WTXӦ<58><D3A6> */
{
if ( (result != SUCCESS) || (tpdu.ReceiveLength == 0) )
return (FAIL);
memcpy( &pcb_byte, tpdu.pReceiveBuffer, 1 ); /*<2A><>ȡPCB<43>ֽ<EFBFBD> */
if ( (pcb_byte == 0x02) || (pcb_byte == 0x03) )
{
CPU_CARD.PCB = pcb_byte ^ 0x01; /*<2A><><EFBFBD><EFBFBD>PCB<43>ֽ<EFBFBD> */
#if CPU_DEBUG
printf("....CPU_CARD.PCB = %02X\r\n",CPU_CARD.PCB);
#endif
memcpy( apdu->pReceiveBuffer + apdu->ReceiveLength, tpdu.pReceiveBuffer + 1, tpdu.ReceiveLength - 1 );
apdu->ReceiveLength = apdu->ReceiveLength + tpdu.ReceiveLength - 1;
return (SUCCESS); /*<2A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
}
if ( (pcb_byte == 0x12) || (pcb_byte == 0x13) )
{
memcpy( apdu->pReceiveBuffer + apdu->ReceiveLength, tpdu.pReceiveBuffer + 1, tpdu.ReceiveLength - 1 );
apdu->ReceiveLength = apdu->ReceiveLength + tpdu.ReceiveLength - 1;
tpdu.pSendBuffer[0] = ( (pcb_byte & 0x03) | 0xA0) ^ 0x01; /*<2A>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PCB<43>ֽ<EFBFBD> */
tpdu.SendLength = 1;
#if CPU_DEBUG
printf("...--> = ");
for(i=0;i<tpdu.SendLength;i++)
printf("%02X",tpdu.pSendBuffer[i]);
printf("\r\n");
#endif
result = CPU_TPDU( &tpdu ); /*<2A>ط<EFBFBD>ACK */
#if CPU_DEBUG
printf("<-- = ");
for(i=0;i<tpdu.ReceiveLength;i++)
printf("%02X",tpdu.pReceiveBuffer[i]);
printf("\r\n");
#endif
}
if ( (pcb_byte == 0xF2) || (pcb_byte == 0xF3) )
{
tpdu.SendLength = tpdu.ReceiveLength;
memcpy(tpdu.pSendBuffer ,tpdu.pReceiveBuffer ,tpdu.SendLength); /*<2A>յ<EFBFBD>WTX֡<58><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>PCB<43>ֽ<EFBFBD> */
#if CPU_DEBUG
printf("....--> = ");
for(i=0;i<tpdu.SendLength;i++)
printf("%02X",tpdu.pSendBuffer[i]);
printf("\r\n");
#endif
result = CPU_TPDU( &tpdu ); /*<2A>ط<EFBFBD>WTX */
#if CPU_DEBUG
printf("<-- = ");
for(i=0;i<tpdu.ReceiveLength;i++)
printf("%02X",tpdu.pReceiveBuffer[i]);
printf("\r\n");
#endif
}
}
return (FAIL); /*<2A><><EFBFBD>մ<EFBFBD><D5B4><EFBFBD> */
}
#endif

View File

@ -0,0 +1,58 @@
#ifndef CPU_CARD_H
#define CPU_CARD_H 1
typedef struct
{
unsigned char SendLength;
unsigned char *pSendBuffer;
unsigned char ReceiveLength;
unsigned char *pReceiveBuffer;
unsigned int Timeout;
}transmission_struct;
struct ATS_STR
{
unsigned char Length;
unsigned char Ats_Data[255];
};
struct PPS_STR
{
unsigned char Length;
unsigned char Pps_Data[1];
};
struct CPU_CARD_STR
{
unsigned char FSCI;
unsigned char FSC;
unsigned char FWI;
unsigned int FWT;
unsigned char SFGI;
unsigned char TA;
unsigned char TB;
unsigned char TC;
unsigned char PCB;
unsigned char WTXM;
struct ATS_STR ATS;
struct PPS_STR PPS;
};
extern struct CPU_CARD_STR CPU_CARD;
extern unsigned char Ats_Process( unsigned char ats_len, unsigned char *ats );
extern unsigned char CPU_CARD_EVENT( void );
extern unsigned char CPU_TPDU( transmission_struct *tpdu );
extern unsigned char CPU_Rats( unsigned char *ats_len, unsigned char *ats );
extern unsigned char CPU_NAK( transmission_struct *tpdu );
extern unsigned char CPU_APDU( transmission_struct *apdu );
extern unsigned char CPU_TPDU( transmission_struct *tpdu );
#endif

View File

@ -0,0 +1,491 @@
#include "MIFARE.h"
#include "READER.h"
#include "string.h"
#include "READER_REG.h"
#include "xt_main.h"
unsigned char SECTOR,BLOCK,BLOCK_NUM;
unsigned char BLOCK_DATA[16];
unsigned char KEY_A[16][6]=
{{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//0
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//1
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//2
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//3
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//4
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//5
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//6
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//7
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//8
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//9
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//10
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//11
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//12
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//13
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//14
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};//15
unsigned char KEY_B[16][6]=
{{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//0
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//1
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//2
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//3
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//4
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//5
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//6
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//7
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//8
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//9
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//10
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//11
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//12
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//13
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//14
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};//15
/*****************************************************************************************/
/*<2A><><EFBFBD>ƣ<EFBFBD>Mifare_Clear_Crypto */
/*<2A><><EFBFBD>ܣ<EFBFBD>Mifare_Clear_Crypto<74><6F><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD><D6A4>־ */
/*<2A><><EFBFBD>룺 */
/* */
/*<2A><><EFBFBD>: */
/* */
/* */
/*****************************************************************************************/
void Mifare_Clear_Crypto(void)
{
ModifyReg(REG_STATUS,BIT_CRYPTO1ON,RESET);
return;
}
unsigned char MIFARE_CARD_EVENTAAAAAAA(void)
{
unsigned char result;
Mifare_Clear_Crypto();
SECTOR = 1;
//for(SECTOR = 0;SECTOR < 16; SECTOR++)
{
BLOCK_NUM = (SECTOR * 4) + BLOCK;
result = Mifare_Auth(KEY_A_M1,SECTOR,KEY_A[SECTOR],PICC_A.UID);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> AUTH ERROR!\r\n");
return result;
}
printf("-> AUTH SUCCESS!\r\n");
for(BLOCK = 0;BLOCK < 3;BLOCK++)
{
BLOCK_NUM = (SECTOR * 4) + BLOCK;
if(BLOCK_NUM == 0)
BLOCK_NUM = 1;
printf("-> SECTOR = %02X\r\n",SECTOR);;
printf("-> BLOCK = %02X\r\n",BLOCK);
printf("-> BLOCK_NUM = %02X\r\n",BLOCK_NUM);
memcpy(BLOCK_DATA,"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",16);
result = Mifare_Blockwrite(BLOCK_NUM,BLOCK_DATA);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> WRITE BLOCK ERROR!\r\n");
return result;
}
printf("-> WRITE BLOCK SUCCESS!\r\n");
result = Mifare_Blockread(BLOCK_NUM,BLOCK_DATA);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> READ BLOCK ERROR!\r\n");
return result;
}
printf("-> READ BLOCK = %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\r\n",BLOCK_DATA[0],BLOCK_DATA[1],BLOCK_DATA[2],BLOCK_DATA[3],BLOCK_DATA[4],BLOCK_DATA[5],BLOCK_DATA[6],BLOCK_DATA[7],BLOCK_DATA[8],BLOCK_DATA[9],BLOCK_DATA[10],BLOCK_DATA[11],BLOCK_DATA[12],BLOCK_DATA[13],BLOCK_DATA[14],BLOCK_DATA[15]);
}
}
SetCW(DISABLE);
return result;
}
unsigned char MIFARE_CARD_EVENT(void)
{
unsigned char result;
Mifare_Clear_Crypto();
SECTOR = 1;
//for(SECTOR = 0;SECTOR < 16; SECTOR++)
{
BLOCK_NUM = (SECTOR * 4) + BLOCK;
result = Mifare_Auth(KEY_A_M1,SECTOR,KEY_A[SECTOR],PICC_A.UID);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> AUTH ERROR!\r\n");
return result;
}
printf("-> AUTH SUCCESS!\r\n");
for(BLOCK = 0;BLOCK < 3;BLOCK++)
{
BLOCK_NUM = (SECTOR * 4) + BLOCK;
if(BLOCK_NUM == 0)
BLOCK_NUM = 1;
printf("-> SECTOR = %02X\r\n",SECTOR);;
printf("-> BLOCK = %02X\r\n",BLOCK);
printf("-> BLOCK_NUM = %02X\r\n",BLOCK_NUM);
memcpy(BLOCK_DATA,"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",16);
result = Mifare_Blockwrite(BLOCK_NUM,BLOCK_DATA);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> WRITE BLOCK ERROR!\r\n");
return result;
}
printf("-> WRITE BLOCK SUCCESS!\r\n");
result = Mifare_Blockread(BLOCK_NUM,BLOCK_DATA);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> READ BLOCK ERROR!\r\n");
return result;
}
printf("-> READ BLOCK = %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\r\n",BLOCK_DATA[0],BLOCK_DATA[1],BLOCK_DATA[2],BLOCK_DATA[3],BLOCK_DATA[4],BLOCK_DATA[5],BLOCK_DATA[6],BLOCK_DATA[7],BLOCK_DATA[8],BLOCK_DATA[9],BLOCK_DATA[10],BLOCK_DATA[11],BLOCK_DATA[12],BLOCK_DATA[13],BLOCK_DATA[14],BLOCK_DATA[15]);
}
}
SetCW(DISABLE);
return result;
}
unsigned char Mifare_LoadKey(unsigned char *mifare_key)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA,mifare_key[0]);
SetReg(REG_FIFODATA,mifare_key[1]);
SetReg(REG_FIFODATA,mifare_key[2]);
SetReg(REG_FIFODATA,mifare_key[3]);
SetReg(REG_FIFODATA,mifare_key[4]);
SetReg(REG_FIFODATA,mifare_key[5]);
SetCommand(CMD_LOADKEY);
DelayMs(1);
GetReg(REG_COMMAND,&reg_data);
if((reg_data & CMD_MASK) == CMD_IDLE)
return SUCCESS;
else
return FAIL;
}
/*****************************************************************************************/
/*<2A><><EFBFBD>ƣ<EFBFBD>Mifare_Auth */
/*<2A><><EFBFBD>ܣ<EFBFBD>Mifare_Auth<74><68>Ƭ<EFBFBD><C6AC>֤ */
/*<2A><><EFBFBD>룺mode<64><65><EFBFBD><EFBFBD>֤ģʽ<C4A3><CABD>0<EFBFBD><30>key A<><41>֤<EFBFBD><D6A4>1<EFBFBD><31>key B<><42>֤<EFBFBD><D6A4><EFBFBD><EFBFBD>sector<6F><72><EFBFBD><EFBFBD>֤<EFBFBD><D6A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>0~15<31><35> */
/* *mifare_key<65><79>6<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>֤<EFBFBD><D6A4>Կ<EFBFBD><D4BF><EFBFBD>飻*card_uid<69><64>4<EFBFBD>ֽڿ<D6BD>ƬUID<49><44><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>: */
/* OK :<3A><>֤<EFBFBD>ɹ<EFBFBD> */
/* ERROR :<3A><>֤ʧ<D6A4><CAA7> */
/*****************************************************************************************/
unsigned char Mifare_Auth(unsigned char key_mode,unsigned char sector,unsigned char *mifare_key,unsigned char *card_uid)
{
unsigned char result,reg_data;
result = Mifare_LoadKey(mifare_key);
if (result != SUCCESS)
return result;
SetCommand(CMD_IDLE);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
if(key_mode == KEY_A_M1)
{
SetReg(REG_FIFODATA,0x60);//60 keyA M1<4D><31>ָ֤<D6A4><D6B8>
ModifyReg(REG_RXTXCON,BIT_SHMODE,DISABLE);
}
if(key_mode == KEY_B_M1)
{
SetReg(REG_FIFODATA,0x61);//61 keyB M1<4D><31>ָ֤<D6A4><D6B8>
ModifyReg(REG_RXTXCON,BIT_SHMODE,DISABLE);
}
SetReg(REG_FIFODATA,sector * 4);//<2F><>֤<EFBFBD><D6A4><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD>0<EFBFBD><30>ַ
SetReg(REG_FIFODATA,card_uid[0]);
SetReg(REG_FIFODATA,card_uid[1]);
SetReg(REG_FIFODATA,card_uid[2]);
SetReg(REG_FIFODATA,card_uid[3]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_AUTHENT);
DelayMs(5);
GetReg(REG_COMMAND,&reg_data);
if((reg_data & CMD_MASK) == CMD_IDLE)
{
GetReg(REG_STATUS,&reg_data);
if(reg_data & BIT_CRYPTO1ON)//<2F>жϼ<D0B6><CFBC>ܱ<EFBFBD>־λ<D6BE><CEBB>ȷ<EFBFBD><C8B7><EFBFBD><EFBFBD>֤<EFBFBD><D6A4><EFBFBD>
return SUCCESS;
}
return FAIL;
}
/*****************************************************************************************/
/*<2A><><EFBFBD>ƣ<EFBFBD>Mifare_Blockset */
/*<2A><><EFBFBD>ܣ<EFBFBD>Mifare_Blockset<65><74>Ƭ<EFBFBD><C6AC>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>룺block<63><6B><EFBFBD><EFBFBD>ţ<EFBFBD>*buff<66><66><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>õ<EFBFBD>4<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> */
/* */
/*<2A><><EFBFBD>: */
/* OK :<3A><><EFBFBD>óɹ<C3B3> */
/* ERROR :<3A><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7> */
/*****************************************************************************************/
unsigned char Mifare_Blockset(unsigned char block,unsigned char *data_buff)
{
unsigned char block_data[16],result;
block_data[0] = data_buff[3];
block_data[1] = data_buff[2];
block_data[2] = data_buff[1];
block_data[3] = data_buff[0];
block_data[4] = ~data_buff[3];
block_data[5] = ~data_buff[2];
block_data[6] = ~data_buff[1];
block_data[7] = ~data_buff[0];
block_data[8] = data_buff[3];
block_data[9] = data_buff[2];
block_data[10] = data_buff[1];
block_data[11] = data_buff[0];
block_data[12] = block;
block_data[13] = ~block;
block_data[14] = block;
block_data[15] = ~block;
result = Mifare_Blockwrite(block,block_data);
return result;
}
/*****************************************************************************************/
/*<2A><><EFBFBD>ƣ<EFBFBD>Mifare_Blockread */
/*<2A><><EFBFBD>ܣ<EFBFBD>Mifare_Blockread<61><64>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>룺block<63><6B><EFBFBD><EFBFBD>ţ<EFBFBD>0x00~0x3F<33><46><EFBFBD><EFBFBD>buff<66><66>16<31>ֽڶ<D6BD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>: */
/* OK :<3A>ɹ<EFBFBD> */
/* ERROR :ʧ<><CAA7> */
/*****************************************************************************************/
unsigned char Mifare_Blockread(unsigned char block,unsigned char *data_buff)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0x30);//30 <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
SetReg(REG_FIFODATA,block);//<2F><><EFBFBD>ַ
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(2);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 16) //<2F><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>Ϊ16
return FAIL;
GetReg(REG_ERROR,&reg_data);
if(reg_data & 0x07)
return FAIL;
for(i=0;i<16;i++)
{
GetReg (REG_FIFODATA,&data_buff[i]);
}
return SUCCESS;
}
/*****************************************************************************************/
/*<2A><><EFBFBD>ƣ<EFBFBD>mifare_blockwrite */
/*<2A><><EFBFBD>ܣ<EFBFBD>Mifare<72><65>Ƭд<C6AC><D0B4><EFBFBD><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>룺block<63><6B><EFBFBD><EFBFBD>ţ<EFBFBD>0x00~0x3F<33><46><EFBFBD><EFBFBD>buff<66><66>16<31>ֽ<EFBFBD>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>: */
/* OK :<3A>ɹ<EFBFBD> */
/* ERROR :ʧ<><CAA7> */
/*****************************************************************************************/
unsigned char Mifare_Blockwrite(unsigned char block,unsigned char *data_buff)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0xA0);//A0 д<><D0B4>ָ<EFBFBD><D6B8>
SetReg(REG_FIFODATA,block);//<2F><><EFBFBD>ַ
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1) //<2F><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>Ϊ1
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
for(i=0;i<16;i++)
{
SetReg(REG_FIFODATA,data_buff[i]);
}
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1) //<2F><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>Ϊ1
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}
/*****************************************************************************************/
/*<2A><><EFBFBD>ƣ<EFBFBD> */
/*<2A><><EFBFBD>ܣ<EFBFBD>Mifare <20><>Ƭ<EFBFBD><C6AC>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>룺block<63><6B><EFBFBD><EFBFBD>ţ<EFBFBD>0x00~0x3F<33><46><EFBFBD><EFBFBD>buff<66><66>4<EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>: */
/* OK :<3A>ɹ<EFBFBD> */
/* ERROR :ʧ<><CAA7> */
/*****************************************************************************************/
unsigned char Mifare_Blockinc(unsigned char block,unsigned char *data_buff)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0xC1);//C1 <20><>ֵָ<D6B5><D6B8>
SetReg(REG_FIFODATA,block);//<2F><><EFBFBD>ַ
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1) //<2F><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>Ϊ1
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
for(i=0;i<4;i++)
{
SetReg(REG_FIFODATA,data_buff[i]);
}
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1) //<2F><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>Ϊ1
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}
/*****************************************************************************************/
/*<2A><><EFBFBD>ƣ<EFBFBD>mifare_blockdec */
/*<2A><><EFBFBD>ܣ<EFBFBD>Mifare <20><>Ƭ<EFBFBD><C6AC>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>룺block<63><6B><EFBFBD><EFBFBD>ţ<EFBFBD>0x00~0x3F<33><46><EFBFBD><EFBFBD>buff<66><66>4<EFBFBD>ֽڼ<D6BD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>: */
/* OK :<3A>ɹ<EFBFBD> */
/* ERROR :ʧ<><CAA7> */
/*****************************************************************************************/
unsigned char Mifare_Blockdec(unsigned char block,unsigned char *data_buff)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0xC0);//C0 <20><>ֵָ<D6B5><D6B8>
SetReg(REG_FIFODATA,block);//<2F><><EFBFBD>ַ
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1) //<2F><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>Ϊ1
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
for(i=0;i<4;i++)
{
SetReg(REG_FIFODATA,data_buff[i]);
}
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1) //<2F><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>Ϊ1
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}
/*****************************************************************************************/
/*<2A><><EFBFBD>ƣ<EFBFBD>mifare_transfer */
/*<2A><><EFBFBD>ܣ<EFBFBD>Mifare <20><>Ƭtransfer<65><72><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>룺block<63><6B><EFBFBD><EFBFBD>ţ<EFBFBD>0x00~0x3F<33><46> */
/*<2A><><EFBFBD>: */
/* OK :<3A>ɹ<EFBFBD> */
/* ERROR :ʧ<><CAA7> */
/*****************************************************************************************/
unsigned char Mifare_Transfer(unsigned char block)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0xC1);//C1 Transferָ<72><D6B8>
SetReg(REG_FIFODATA,block);//<2F><><EFBFBD>ַ
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1) //<2F><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>Ϊ1
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}
/*****************************************************************************************/
/*<2A><><EFBFBD>ƣ<EFBFBD>mifare_restore */
/*<2A><><EFBFBD>ܣ<EFBFBD>Mifare <20><>Ƭrestore<72><65><EFBFBD><EFBFBD> */
/*<2A><><EFBFBD>룺block<63><6B><EFBFBD><EFBFBD>ţ<EFBFBD>0x00~0x3F<33><46> */
/*<2A><><EFBFBD>: */
/* OK :<3A>ɹ<EFBFBD> */
/* ERROR :ʧ<><CAA7> */
/*****************************************************************************************/
unsigned char Mifare_Restore(unsigned char block)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0xC2);//C1 Transferָ<72><D6B8>
SetReg(REG_FIFODATA,block);//<2F><><EFBFBD>ַ
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1) //<2F><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>Ϊ1
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
for(i=0;i<4;i++)
{
SetReg(REG_FIFODATA,0);
}
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1) //<2F><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>Ϊ1
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}

View File

@ -0,0 +1,247 @@
/**
* @file MIFARE.c
* @brief MIFARE Classic 卡应用层驱动实现
* @version 1.0
* @date 2024-05-20
*
* @par 文件作用:
* 该文件是 MIFARE.h 中声明的所有函数的具体实现。它负责处理与
* MIFARE Classic 卡片交互的特定应用层逻辑,如认证、数据读写等。
*/
#include "MIFARE.h"
#include "READER.h"
#include "string.h"
#include "READER_REG.h"
#include "xt_main.h"
//==================================================================================
// 1. 全局变量定义
//==================================================================================
unsigned char SECTOR, BLOCK, BLOCK_NUM;
unsigned char BLOCK_DATA[16]; // 16字节数据缓冲区
// MIFARE 各扇区默认密钥 (Key A 和 Key B)通常出厂时均为全F
unsigned char KEY_A[16][6] = {
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
// ... (共16个扇区的密钥) ...
};
unsigned char KEY_B[16][6] = {
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
// ... (共16个扇区的密钥) ...
};
/**
* @brief 清除芯片内部的 MIFARE 加密状态标志
* @note 每次对新卡操作或认证失败后,都应调用此函数来复位加密状态。
*/
void Mifare_Clear_Crypto(void)
{
ModifyReg(REG_STATUS, BIT_CRYPTO1ON, 0); // 将状态寄存器中的 CRYPTO1ON 位清零
}
/**
* @brief MIFARE 卡操作事件流程 (一个完整的读写示例)
* @return unsigned char 操作结果
*/
unsigned char MIFARE_CARD_EVENT(void)
{
unsigned char result;
Mifare_Clear_Crypto(); // 开始前先清除加密状态
SECTOR = 1; // 示例操作第1扇区
// 对指定扇区进行Key A认证
result = Mifare_Auth(KEY_A_M1, SECTOR, KEY_A[SECTOR], PICC_A.UID);
if(result != SUCCESS)
{
SetCW(DISABLE); // 认证失败,关闭天线
printf("-> AUTH ERROR!\r\n");
return result;
}
printf("-> AUTH SUCCESS!\r\n");
// 认证成功后,遍历并读写该扇区的数据块 (不含扇区尾块)
for(BLOCK = 0; BLOCK < 3; BLOCK++)
{
BLOCK_NUM = (SECTOR * 4) + BLOCK; // 计算块的绝对地址
// 示例向块写入全FF
memcpy(BLOCK_DATA, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 16);
result = Mifare_Blockwrite(BLOCK_NUM, BLOCK_DATA);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> WRITE BLOCK ERROR!\r\n");
return result;
}
printf("-> WRITE BLOCK SUCCESS!\r\n");
// 示例:从块中读出数据
result = Mifare_Blockread(BLOCK_NUM, BLOCK_DATA);
if(result != SUCCESS)
{
SetCW(DISABLE);
printf("-> READ BLOCK ERROR!\r\n");
return result;
}
printf("-> READ BLOCK DATA: ...\r\n"); // 打印读出的数据
}
SetCW(DISABLE);
return result;
}
/**
* @brief 加载6字节密钥到读卡器芯片内部的密钥缓冲器
* @param mifare_key 指向6字节密钥数组的指针
* @return unsigned char 成功或失败
*/
unsigned char Mifare_LoadKey(unsigned char *mifare_key)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
Clear_FIFO();
// 1. 将6字节密钥依次写入FIFO
SetReg(REG_FIFODATA, mifare_key[0]);
SetReg(REG_FIFODATA, mifare_key[1]);
SetReg(REG_FIFODATA, mifare_key[2]);
SetReg(REG_FIFODATA, mifare_key[3]);
SetReg(REG_FIFODATA, mifare_key[4]);
SetReg(REG_FIFODATA, mifare_key[5]);
// 2. 发送加载密钥命令芯片会自动从FIFO读取密钥
SetCommand(CMD_LOADKEY);
DelayMs(1);
GetReg(REG_COMMAND, &reg_data);
if((reg_data & CMD_MASK) == CMD_IDLE) // 检查命令是否执行完毕
return SUCCESS;
else
return FAIL;
}
/**
* @brief **核心函数**: 对 MIFARE 卡指定扇区进行密码认证
* @param key_mode 认证模式 (KEY_A_M1 或 KEY_B_M1)
* @param sector 要认证的扇区号 (0-15)
* @param mifare_key 指向6字节密钥的指针
* @param card_uid 指向4字节卡片UID的指针 (从寻卡流程中获得)
* @return unsigned char 成功或失败
*/
unsigned char Mifare_Auth(unsigned char key_mode, unsigned char sector, unsigned char *mifare_key, unsigned char *card_uid)
{
unsigned char result, reg_data;
result = Mifare_LoadKey(mifare_key); // 1. 首先将密钥加载到芯片
if (result != SUCCESS)
return result;
SetCommand(CMD_IDLE);
Clear_FIFO();
// 2. 根据认证模式,将认证命令码 (0x60 for KeyA, 0x61 for KeyB) 写入FIFO
if(key_mode == KEY_A_M1)
{
SetReg(REG_FIFODATA, 0x60);
}
else // KEY_B_M1
{
SetReg(REG_FIFODATA, 0x61);
}
// 3. 将要认证的块地址、卡片UID写入FIFO
SetReg(REG_FIFODATA, sector * 4); // MIFARE卡每个扇区4个块认证扇区内任一地址即可
SetReg(REG_FIFODATA, card_uid[0]);
SetReg(REG_FIFODATA, card_uid[1]);
SetReg(REG_FIFODATA, card_uid[2]);
SetReg(REG_FIFODATA, card_uid[3]);
// 4. 发送认证命令,芯片将自动完成与卡片的三次握手加密认证流程
SetCommand(CMD_AUTHENT);
DelayMs(5);
// 5. 检查认证结果
GetReg(REG_COMMAND, &reg_data);
if((reg_data & CMD_MASK) == CMD_IDLE) // 命令执行完毕
{
GetReg(REG_STATUS, &reg_data);
// 关键: 检查状态寄存器中的 CRYPTO1ON 位是否为1。
// 此位由硬件在认证成功后自动置位。
if(reg_data & BIT_CRYPTO1ON)
return SUCCESS;
}
return FAIL;
}
/**
* @brief 读取一个16字节的数据块
* @param block 要读取的块的绝对地址
* @param data_buff 用于存放读取数据的16字节缓冲区
* @return unsigned char 成功或失败
*/
unsigned char Mifare_Blockread(unsigned char block, unsigned char *data_buff)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
Clear_FIFO();
// 1. 准备读块指令 (命令码 0x30 + 块地址)
SetReg(REG_FIFODATA, 0x30);
SetReg(REG_FIFODATA, block);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, ENABLE); // 读写命令需要CRC
ModifyReg(REG_RXCRCCON, BIT_CRCEN, ENABLE);
// 2. 发送并等待接收
SetCommand(CMD_TRANSCEIVE);
DelayMs(2);
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 16) // 3. 检查是否收到了完整的16字节数据
return FAIL;
GetReg(REG_ERROR, &reg_data);
if(reg_data & 0x07) // 检查是否有通信错误
return FAIL;
// 4. 从FIFO中循环读出16字节数据
for(i=0; i<16; i++)
{
GetReg(REG_FIFODATA, &data_buff[i]);
}
return SUCCESS;
}
/**
* @brief 写入一个16字节的数据块
* @param block 要写入的块的绝对地址
* @param data_buff 包含要写入的16字节数据的缓冲区
* @return unsigned char 成功或失败
*/
unsigned char Mifare_Blockwrite(unsigned char block, unsigned char *data_buff)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
Clear_FIFO();
// 1. 准备写块指令 (命令码 0xA0 + 块地址)
SetReg(REG_FIFODATA, 0xA0);
SetReg(REG_FIFODATA, block);
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
// 2. 卡片会返回一个ACK (0x0A),检查是否收到
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &reg_data);
if(reg_data != 0x0A)
return FAIL;
// 3. 收到ACK后将16字节数据写入FIFO
for(i=0; i<16; i++)
{
SetReg(REG_FIFODATA, data_buff[i]);
}
// 4. 再次发送,将数据写入卡片
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
// 5. 卡片会再次返回一个ACK检查是否收到
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}
// ... (值块操作函数的实现: Blockset, Blockinc, Blockdec, Transfer, Restore) ...

View File

@ -0,0 +1,74 @@
#include "READER.h"
#include "NTAG.h"
#include <string.h>
#include "READER_REG.h"
#include "xt_main.h"
unsigned char PAGE_DATA[16];
unsigned char NTAG_EVENT(void)
{
unsigned char result;
memcpy(PAGE_DATA,"\x01\x02\x03\x04",4);
result = Write_Page(8,PAGE_DATA);
if (result != SUCCESS)
return result;
printf("PAGE 8 Write OK\r\n");
result = Read_Page(8,PAGE_DATA);
printf("PAGE 8 = %02X%02X%02X%02X\r\n",PAGE_DATA[0],PAGE_DATA[1],PAGE_DATA[2],PAGE_DATA[3]);
return result;
}
unsigned char Read_Page(unsigned char page_num,unsigned char *page_data)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
Clear_FIFO();
SetReg(REG_FIFODATA,0x30);
SetReg(REG_FIFODATA,page_num);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
GetReg(REG_ERROR,&reg_data);
if(reg_data & 0x07)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 16)
return FAIL;
for(i=0;i<16;i++)
{
GetReg(REG_FIFODATA,&page_data[i]);
}
return SUCCESS;
}
unsigned char Write_Page(unsigned char page_num,unsigned char *page_data)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
Clear_FIFO();
SetReg(REG_FIFODATA,0xA2);
SetReg(REG_FIFODATA,page_num);
SetReg(REG_FIFODATA,page_data[0]);
SetReg(REG_FIFODATA,page_data[1]);
SetReg(REG_FIFODATA,page_data[2]);
SetReg(REG_FIFODATA,page_data[3]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}

View File

@ -0,0 +1,8 @@
#ifndef _NTAG_H
#define _NTAG_H
extern unsigned char PAGE_DATA[16];
extern unsigned char NTAG_EVENT(void);
extern unsigned char Read_Page(unsigned char page_num,unsigned char *page_data);
extern unsigned char Write_Page(unsigned char page_num,unsigned char *page_data);
#endif

View File

@ -0,0 +1,814 @@
#include "function.h"
#include "board.h"
//#include "fm15l0xx_ll_spi.h"
#include "READER.h"
#include "READER_REG.h"
#include "print.h"
#include "random_generator.h"
#include <stdio.h>
#include "xt_main.h"
struct picc_a_struct PICC_A;
struct picc_b_struct PICC_B;
struct picc_v_struct PICC_V;
struct picc_f_struct PICC_F;
void DelayMs( uint32_t xms );
void DelayUs( uint32_t xus );
void DelayUs( uint32_t xus )
{
int t;
while ( xus-- )
{
t = 5;
while ( t-- )
;
}
}
void DelayMs( uint32_t xms )
{
DelayUs( xms * 1000 );
}
// void Reader_GPIO_Init( void )
// {
/******** 重做GPIO初始化 **********/
// // LL_GPIO_SetPinMode( PD_GPIO, PD_PIN, LL_GPIO_PINxMODE_OUTPUT );//PA7 PD
// //LL_GPIO_EnablePinPullUp( SPI_GPIO, SCK_PIN | MOSI_PIN ); // Enable Pullup
// //xtell注释
// // LL_GPIO_SetPinMode( SPI_GPIO, SCK_PIN, LL_GPIO_PINxMODE_OUTPUT ); // PB1 Digital function - SPI1 SCK
// // LL_GPIO_SetPinMode( SPI_GPIO, MISO_PIN, LL_GPIO_PINxMODE_INPUT ); // PB2 Digital function - SPI1 MISO1
// // LL_GPIO_SetPinMode( SPI_GPIO, MOSI_PIN, LL_GPIO_PINxMODE_OUTPUT ); // PB3 Digital function - SPI1 MOSI
// LL_GPIO_SetPinMode(); //xtell
// SCK_0;
// MOSI_0;
//
// LL_GPIO_SetPinMode(); //xtell
// //xtell注释
// // LL_GPIO_SetPinMode( SPI_GPIO, NSS_PIN, LL_GPIO_PINxMODE_OUTPUT ); // PB0 Digital function - SPI1 NSS1
// PD_0;
// NSS_1;
// }
// unsigned char FM176XX_HardReset(void)
// {
/*************NFC 硬件初始化 重做********************/
// unsigned char reg_data;
// NSS_1;//NSS = 1
// PD_1;//RST = 1
// DelayMs(1);
// PD_0;//RST = 0
// DelayMs(1);
// GetReg(REG_COMMAND,&reg_data);
// if (reg_data != 0x40)
// return FAIL;
// return SUCCESS;
// }
// unsigned char Reader_Set_HPD( unsigned char mode ) //mode = DISABLE <20>˳<EFBFBD>HPDģʽ <20><>mode = ENABLE <20><><EFBFBD><EFBFBD>HPDģʽ
// {
// if ( mode == ENABLE )
// {
// DelayMs( 1 ); //<2F><>ʱ1ms
// /******设置一个GPIO输出高*******xtell******/
// //PD_1; // PD = 1
// P34 = 1;
// }
// else
// {
// /******设置一个GPIO输出低*************/
// //PD_0; //PD = 0
// P34 =0;
// DelayMs( 1 ); //<2F><>ʱ1ms<6D><73><EFBFBD>ȴ<EFBFBD>Reader<65><72><EFBFBD><EFBFBD>
// }
// return (mode);
// }
//***********************************************
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>GetReg(unsigned char addr,unsigned char *regdata)
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD>ȡ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>ֵ
//<2F><>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD>addr:Ŀ<><C4BF>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ַ regdata:<3A><>ȡ<EFBFBD><C8A1>ֵ
//<2F><><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD>unsigned char TRUE<55><45><EFBFBD><EFBFBD>ȡ<EFBFBD>ɹ<EFBFBD> FALSE:ʧ<><CAA7>
//***********************************************
// 从FM17660 读取数据时BIT7 置 1
// unsigned char GetReg(unsigned char address,unsigned char *reg_data)
// {
// unsigned char spi_data,i;
// NSS_0; //NSS = 0;
// spi_data = (address << 1) | 0x01;
// for(i=0;i<8;i++)
// {
// if(spi_data & 0x80)
// MOSI_1;
// else
// MOSI_0;
// SCK_1;
// spi_data = spi_data<<1;
// SCK_0;
// }
// MOSI_0;
// *reg_data = 0;
// for(i=0;i<8;i++)
// {
// *reg_data = *reg_data<<1;
// SCK_1;
// if(LL_GPIO_ReadInputPort(SPI_GPIO)& MISO_PIN)
// *reg_data = *reg_data | 0x01;
// SCK_0;
// }
// NSS_1; //NSS = 1;
// return SUCCESS;
// }
//***********************************************
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƣ<EFBFBD>SetReg(unsigned char addr,unsigned char* regdata)
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܣ<EFBFBD>д<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>
//<2F><>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD>addr:Ŀ<><C4BF>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD>ַ regdata:Ҫд<D2AA><D0B4><EFBFBD>ֵ
//<2F><><EFBFBD>ڲ<EFBFBD><DAB2><EFBFBD><EFBFBD><EFBFBD>unsigned char TRUE<55><45>д<EFBFBD>ɹ<EFBFBD> FALSE:дʧ<D0B4><CAA7>
//***********************************************
// unsigned char SetReg(unsigned char address,unsigned char reg_data)
// {
// unsigned char spi_data,i;
// NSS_0; //NSS = 0;
// spi_data = (address << 1) & 0xFE;
// for(i=0;i<8;i++)
// {
// if(spi_data & 0x80)
// MOSI_1;
// else
// MOSI_0;
// SCK_1;
// spi_data = spi_data<<1;
// SCK_0;
// }
// MOSI_0;
// spi_data = reg_data;
// for(i=0;i<8;i++)
// {
// if(spi_data & 0x80)
// MOSI_1;
// else
// MOSI_0;
// SCK_1;
// spi_data = spi_data<<1;
// SCK_0;
// }
// SCK_0;
// MOSI_0;
// NSS_1; //NSS = 1;
// return SUCCESS;
// }
void ModifyReg( unsigned char reg_address, unsigned char mask, unsigned char set )
{
unsigned char reg_data;
// Uart1SendString(" ModifyReg begin ");
GetReg( reg_address, &reg_data );
if ( set )
{
reg_data |= mask;
}
else
{
reg_data &= ~mask;
}
SetReg( reg_address, reg_data );
return;
}
unsigned char SetCommand(unsigned char command)
{
unsigned char result;
result = SetReg(REG_COMMAND,CMD_MASK & command);
return result;
}
void SetTimer(unsigned int timeout) //
{
unsigned long prescale = 1;
unsigned long t,fc;
fc = timeout*13560;
t = fc;
while(fc > 65535)
{
prescale*=2;
fc = t/prescale;
if(fc*prescale != t)
fc++;
}
if(prescale>1)
{
SetReg(REG_T0CONTROL, BIT_TSTOP_RX | BIT_TSTART_TX | BIT_TAUTORESTARTED | VALUE_TCLK_1356_MHZ );
SetReg(REG_T0RELOADHI,(u8)(fc>>8));
SetReg(REG_T0RELOADLO,(u8)fc);
SetReg(REG_T1CONTROL, BIT_TSTOP_RX | BIT_TSTART_TX | VALUE_TCLK_T0 );
SetReg(REG_T1RELOADHI,(u8)(prescale>>8));
SetReg(REG_T1RELOADLO,(u8)prescale);
}
else
{
SetReg(REG_T1CONTROL, BIT_TSTOP_RX | BIT_TSTART_TX | VALUE_TCLK_1356_MHZ );
SetReg(REG_T1RELOADHI,(u8)(fc>>8));
SetReg(REG_T1RELOADLO,(u8)fc);
}
}
unsigned char SetCW(unsigned char mode)
{
unsigned char result;
if(mode == ENABLE)
{
ModifyReg(REG_COMMAND,BIT_MODEMOFF,DISABLE);
ModifyReg(REG_TXMODE,BIT0 | BIT1,ENABLE);
}
else
{
ModifyReg(REG_COMMAND,BIT_MODEMOFF,ENABLE);
ModifyReg(REG_TXMODE,BIT0 | BIT1,DISABLE);
}
DelayMs(5);
return result;
}
void Clear_FIFO(void)
{
unsigned char fifolength;
GetReg(REG_FIFOLENGTH,&fifolength);
if((fifolength) != 0) //FIFO<46><4F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>գ<EFBFBD><D5A3><EFBFBD>FLUSH FIFO
{
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE);
}
return ;
}
unsigned char LoadProtocol(unsigned char p_rx,unsigned char p_tx)
{
unsigned char reg_data = 0;
// Uart1SendString(" LoadProtocol begin ");
SetCommand(CMD_IDLE); //
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA,p_rx);//Rx
SetReg(REG_FIFODATA,p_tx);//Tx
SetCommand(CMD_LOADPROTOCOL);
DelayMs(2);
GetReg(REG_COMMAND,&reg_data);
if(reg_data != CMD_IDLE)
return FAIL;
return SUCCESS;
}
void SetParity(unsigned char state)
{
// Uart1SendString(" SetParity begin");
ModifyReg(REG_FRAMECON,BIT_TXPARITYEN|BIT_RXPARITYEN,state);
}
unsigned char ReaderA_Initial(void)
{
// Uart1SendString(" ReaderA_Initial begin");
LoadProtocol(RX_TYPEA_106,TX_TYPEA_106);
ModifyReg(REG_TXMODE,BIT2,ENABLE);//FORCE 100ask ENABLE
SetReg(REG_TXAMP,AMPLITUDE_A);
SetReg(REG_TXCON,0x00);
SetReg(REG_RXANA,(HPCF_A<<3)|GAIN_A);
SetReg(0x5F,0x08);
SetReg(REG_THNSET,0xFF);
SetReg(REG_THNMIN,0xC0);
SetReg(REG_RXTXCON,0x80);//
SetParity(ENABLE);
SetReg(REG_STATUS,0);//<2F><><EFBFBD>Cry1Onλ
// Uart1SendString(" ReaderA_Initial end");
return SUCCESS;
}
unsigned char ReaderB_Initial(void)
{
LoadProtocol(RX_TYPEB_106,TX_TYPEB_106);
ModifyReg(REG_TXMODE,BIT2,DISABLE);//FORCE 100ask DISABLE
SetReg(REG_TXAMP,AMPLITUDE_B);
SetReg(REG_TXCON,MODULATION_B);
SetReg(REG_RXANA,(HPCF_B<<3)|GAIN_B);
SetReg(0x5F,0x08);
SetReg(REG_THNSET,0xFF);
SetReg(REG_THNMIN,0xC0);
SetReg(REG_RXTXCON,0x80);//
return SUCCESS;
}
unsigned char ReaderV_Initial(void)
{
LoadProtocol(RX_TYPEV_26,RX_TYPEV_26);
ModifyReg(REG_RXANA,BIT3|BIT2|BIT1|BIT0,DISABLE);
ModifyReg(REG_RXANA,(HPCF_V<<3)|GAIN_V,ENABLE);//39h
SetParity(DISABLE);
SetReg(REG_TXAMP,AMPLITUDE_V);
SetReg(REG_TXCON,MODULATION_V);
SetReg(REG_TXI,0x06);
SetReg(REG_THNSET,0xFF);
SetReg(REG_THNMIN,0x80);
SetReg(REG_THNADJ,0x08);
SetReg(REG_RXTXCON,0);
return SUCCESS;
}
unsigned char ReaderF_Initial(void)
{
ModifyReg(REG_MISC, 0x04,ENABLE);
LoadProtocol(RX_FELICA_212,TX_FELICA_212);
SetReg(REG_TXAMP,AMPLITUDE_F); //
SetReg(REG_TXCON,MODULATION_F);
ModifyReg(REG_RXANA,BIT3|BIT2|BIT1|BIT0,DISABLE);
ModifyReg(REG_RXANA,(HPCF_F<<3)|GAIN_F,ENABLE);//39h
SetParity(DISABLE);
SetReg(REG_THNSET,0xFF);
SetReg(REG_THNMIN,0x80);
SetReg(REG_THNADJ,0x08);
ModifyReg(REG_MISC, 0x04,DISABLE);
return SUCCESS;
}
unsigned char ReaderA_Wakeeup(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x0F);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA,RF_CMD_WUPA);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,DISABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(2);
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 2)
return FAIL;
GetReg(REG_FIFODATA,&picc_a->ATQA[0]);
GetReg(REG_FIFODATA,&picc_a->ATQA[1]);
return SUCCESS;
}
unsigned char ReaderA_Request(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x0F);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA,RF_CMD_REQA);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,DISABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
SetCommand(CMD_TRANSCEIVE);
// DelayMs(2);
Delay1ms();
Delay1ms();
GetReg(REG_FIFOLENGTH,&reg_data);
// Uart1SendString("REG_FIFOLENGTH data=");
// printHex(reg_data);
if(reg_data != 2)
return FAIL;
GetReg(REG_FIFODATA,&picc_a->ATQA[0]);
GetReg(REG_FIFODATA,&picc_a->ATQA[1]);
return SUCCESS;
}
unsigned char ReaderA_Anticoll(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA,RF_CMD_ANTICOLL[picc_a->CASCADE_LEVEL]);
SetReg(REG_FIFODATA,0x20);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,DISABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,DISABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(2);
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 5)
return FAIL;
GetReg(REG_FIFODATA,&picc_a->UID[picc_a->CASCADE_LEVEL*4]);
GetReg(REG_FIFODATA,&picc_a->UID[picc_a->CASCADE_LEVEL*4+1]);
GetReg(REG_FIFODATA,&picc_a->UID[picc_a->CASCADE_LEVEL*4+2]);
GetReg(REG_FIFODATA,&picc_a->UID[picc_a->CASCADE_LEVEL*4+3]);
GetReg(REG_FIFODATA,&picc_a->BCC[picc_a->CASCADE_LEVEL]);
if( (picc_a->UID[picc_a->CASCADE_LEVEL*4] ^ picc_a->UID[picc_a->CASCADE_LEVEL*4+1] ^ picc_a->UID[picc_a->CASCADE_LEVEL*4+2] ^ picc_a->UID[picc_a->CASCADE_LEVEL*4+3]) == picc_a->BCC[picc_a->CASCADE_LEVEL])
return SUCCESS;
return FAIL;
}
unsigned char ReaderA_Select(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA,RF_CMD_ANTICOLL[picc_a->CASCADE_LEVEL]);
SetReg(REG_FIFODATA,0x70);
SetReg(REG_FIFODATA,picc_a->UID[picc_a->CASCADE_LEVEL*4]);
SetReg(REG_FIFODATA,picc_a->UID[picc_a->CASCADE_LEVEL*4+1]);
SetReg(REG_FIFODATA,picc_a->UID[picc_a->CASCADE_LEVEL*4+2]);
SetReg(REG_FIFODATA,picc_a->UID[picc_a->CASCADE_LEVEL*4+3]);
SetReg(REG_FIFODATA,picc_a->BCC[picc_a->CASCADE_LEVEL]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(2);
GetReg(REG_ERROR,&reg_data);
if((reg_data & 0x0F)!=0)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA,&picc_a->SAK [picc_a->CASCADE_LEVEL]);
return SUCCESS;
}
unsigned char ReaderA_CardActivate(struct picc_a_struct *picc_a)
{
unsigned char result,cascade_level;
result = ReaderA_Request(picc_a);//
if (result != SUCCESS)
return result;
if ((picc_a->ATQA[0]&0xC0)==0x00) //1<><31>UID
{
cascade_level = 1;
picc_a->UID_Length = 4;
}
if ((picc_a->ATQA[0]&0xC0)==0x40) //2<><32>UID
{
cascade_level = 2;
picc_a->UID_Length = 8;
}
if ((picc_a->ATQA[0]&0xC0)==0x80) //3<><33>UID
{
cascade_level = 3;
picc_a->UID_Length = 12;
}
for (picc_a->CASCADE_LEVEL = 0; picc_a->CASCADE_LEVEL < cascade_level; picc_a->CASCADE_LEVEL++)
{
result = ReaderA_Anticoll(picc_a);//
if (result != SUCCESS)
return result;
result = ReaderA_Select(picc_a);//
if (result != SUCCESS)
return result;
}
picc_a->CASCADE_LEVEL--;
return result;
}
unsigned char ReaderB_Wakeup(struct picc_b_struct *picc_b)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA, 0x05); //APf
SetReg(REG_FIFODATA, 0x00); //AFI (00:for all cards)
SetReg(REG_FIFODATA, 0x08); //PARAM(REQB,Number of slots =0)
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(10);
GetReg(REG_ERROR,&reg_data);
if((reg_data & 0x0F)!=0)//<2F>жϴ<D0B6><CFB4><EFBFBD><EFBFBD>־
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 12)//<2F>жϽ<D0B6><CFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
return FAIL;
for(i=0;i<12;i++)
GetReg(REG_FIFODATA,&picc_b->ATQB [i]);
memcpy(picc_b->PUPI,picc_b->ATQB + 1,4);
memcpy(picc_b->APPLICATION_DATA,picc_b->ATQB + 6,4);
memcpy(picc_b->PROTOCOL_INF,picc_b->ATQB + 10,3);
return SUCCESS;
}
unsigned char ReaderB_Request(struct picc_b_struct *picc_b)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA, 0x05); //APf
SetReg(REG_FIFODATA, 0x00); //AFI (00:for all cards)
SetReg(REG_FIFODATA, 0x00); //PARAM(REQB,Number of slots =0)
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(10);
GetReg(REG_ERROR,&reg_data);
if((reg_data & 0x0F)!=0)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 12)
return FAIL;
for(i=0;i<12;i++)
GetReg(REG_FIFODATA,&picc_b->ATQB [i]);
memcpy(picc_b->PUPI,picc_b->ATQB + 1,4);
memcpy(picc_b->APPLICATION_DATA,picc_b->ATQB + 6,4);
memcpy(picc_b->PROTOCOL_INF,picc_b->ATQB + 10,3);
return SUCCESS;
}
unsigned char ReaderB_Attrib(struct picc_b_struct *picc_b)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA, 0x1D); //
SetReg(REG_FIFODATA, picc_b->PUPI[0]); //
SetReg(REG_FIFODATA, picc_b->PUPI[1]); //
SetReg(REG_FIFODATA, picc_b->PUPI[2]); //
SetReg(REG_FIFODATA, picc_b->PUPI[3]); //
SetReg(REG_FIFODATA, 0x00); //Param1
SetReg(REG_FIFODATA, 0x08); //Param2 BIT0~BIT3 Frame Size 0 = 16, 1 = 24, 2 = 32, 3 = 40, 4 = 48, 5 = 64, 6 = 96, 7 = 128, 8 = 256
//Param2 BIT4~BIT5 TX BaudRate BIT6~BIT7 RX BaudRate,00 = 106Kbps, 01 = 212Kbps, 10 = 424Kbps, 11 = 848Kbps
SetReg(REG_FIFODATA, 0x01); //COMPATIBLE WITH 14443-4
SetReg(REG_FIFODATA, 0x01); //CID:01
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(10);
GetReg(REG_ERROR,&reg_data);
if((reg_data & 0x0F)!=0)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA,&reg_data);
picc_b->CID = reg_data & 0x0F;
return SUCCESS;
}
unsigned char ReaderB_Halt(struct picc_b_struct *picc_b)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA, 0x50); //
SetReg(REG_FIFODATA, picc_b->PUPI[0]); //
SetReg(REG_FIFODATA, picc_b->PUPI[1]); //
SetReg(REG_FIFODATA, picc_b->PUPI[2]); //
SetReg(REG_FIFODATA, picc_b->PUPI[3]); //
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(10);
GetReg(REG_ERROR,&reg_data);
if((reg_data & 0x0F)!=0)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA,&reg_data);
*picc_b->Answer_to_HALT = reg_data & 0x0F;
return SUCCESS;
}
unsigned char ReaderB_Get_SN(struct picc_b_struct *picc_b)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA, 0x00); //
SetReg(REG_FIFODATA, 0x36); //
SetReg(REG_FIFODATA, 0x00); //
SetReg(REG_FIFODATA, 0x00); //
SetReg(REG_FIFODATA, 0x08); //
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(10);
GetReg(REG_ERROR,&reg_data);
if((reg_data & 0x0F)!=0)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 10)
return FAIL;
for(i=0;i<8;i++)
GetReg(REG_FIFODATA,&picc_b->SN[i]);
return SUCCESS;
}
unsigned char ReaderV_Inventory(struct picc_v_struct *picc_v)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA, 0x26); //
SetReg(REG_FIFODATA, 0x01);
SetReg(REG_FIFODATA, 0x00);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(10);
GetReg(REG_ERROR,&reg_data);
if((reg_data & 0x0F)!=0)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 10)
return FAIL;
GetReg(REG_FIFODATA,&picc_v->RESPONSE );
GetReg(REG_FIFODATA,&reg_data);
for(i = 0;i < 8; i++)
{
GetReg(REG_FIFODATA,&picc_v->UID[i]);
}
return SUCCESS;
}
unsigned char ReaderV_Select(struct picc_v_struct *picc_v)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA, 0x22);
SetReg(REG_FIFODATA, 0x25); //
SetReg(REG_FIFODATA, picc_v->UID[0]);
SetReg(REG_FIFODATA, picc_v->UID[1]);
SetReg(REG_FIFODATA, picc_v->UID[2]);
SetReg(REG_FIFODATA, picc_v->UID[3]);
SetReg(REG_FIFODATA, picc_v->UID[4]);
SetReg(REG_FIFODATA, picc_v->UID[5]);
SetReg(REG_FIFODATA, picc_v->UID[6]);
SetReg(REG_FIFODATA, picc_v->UID[7]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(10);
GetReg(REG_ERROR,&reg_data);
if((reg_data & 0x0F)!=0)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA,&picc_v->RESPONSE );
return SUCCESS;
}
unsigned char ReaderV_ReadSingleBlock(unsigned char block_num,struct picc_v_struct *picc_v)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA,0x12);
SetReg(REG_FIFODATA, 0x20); //
SetReg(REG_FIFODATA, block_num);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(10);
GetReg(REG_ERROR,&reg_data);
if((reg_data & 0x0F)!=0)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 5)
return FAIL;
GetReg(REG_FIFODATA,&picc_v->RESPONSE );
for(i = 0;i < 4; i++)
{
GetReg(REG_FIFODATA,&picc_v->BLOCK_DATA[i]);
}
return SUCCESS;
}
unsigned char ReaderV_WriteSingleBlock(unsigned char block_num,struct picc_v_struct *picc_v)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA,0x02);
SetReg(REG_FIFODATA, 0x21); //
SetReg(REG_FIFODATA, block_num);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[0]);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[1]);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[2]);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[3]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(10);
GetReg(REG_ERROR,&reg_data);
if((reg_data & 0x0F)!=0)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA,&picc_v->RESPONSE );
return SUCCESS;
}
unsigned char ReaderF_Inventory(struct picc_f_struct *picc_f)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,ENABLE); //Clear FIFO
SetReg(REG_FIFODATA, 0x06);
SetReg(REG_FIFODATA, 0x00); //
SetReg(REG_FIFODATA, 0xFF);
SetReg(REG_FIFODATA, 0xFF);
SetReg(REG_FIFODATA, 0x10);
SetReg(REG_FIFODATA, 0x00);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(10);
GetReg(REG_ERROR,&reg_data);
if((reg_data & 0x0F)!=0)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 18)
return FAIL;
GetReg(REG_FIFODATA,&reg_data);
GetReg(REG_FIFODATA,&reg_data);
for(i = 0;i < 8; i++)
{
GetReg(REG_FIFODATA,&picc_f->UID[i]);
}
return SUCCESS;
}

View File

@ -0,0 +1,157 @@
#ifndef _READER_H
#define _READER_H
// #include "fm15l0xx_ll_gpio.h"
#include "function.h"
static const unsigned char RF_CMD_REQA = 0x26;
static const unsigned char RF_CMD_WUPA = 0x52;
static const unsigned char RF_CMD_ANTICOLL[3] = {0x93,0x95,0x97} ;
static const unsigned char RF_CMD_SELECT[3] = {0x93,0x95,0x97} ;
static const unsigned char RF_CMD_KEYA = 0x60;
static const unsigned char RF_CMD_KEYB = 0x61;
struct picc_b_struct
{
unsigned char ATQB[12];//REQBӦ<42><D3A6>
unsigned char PUPI[4];
unsigned char APPLICATION_DATA[4];
unsigned char PROTOCOL_INF[3];
unsigned char CID;//ATTRIBӦ<42><D3A6>
unsigned char Answer_to_HALT[1];//HALTӦ<54><D3A6>
unsigned char SN[8];//<2F><><EFBFBD><EFBFBD>֤SN<53><4E><EFBFBD><EFBFBD>
};
extern struct picc_b_struct PICC_B;
struct picc_a_struct
{
unsigned char ATQA[2];
unsigned char CASCADE_LEVEL;
unsigned char UID_Length;
unsigned char UID[15];
unsigned char BCC[3];
unsigned char SAK[3];
};
extern struct picc_a_struct PICC_A;
struct picc_v_struct
{
unsigned char UID[8];
unsigned char RESPONSE;
unsigned char BLOCK_DATA[4];
};
extern struct picc_v_struct PICC_V;
struct picc_f_struct
{
unsigned char UID[8];
};
extern struct picc_f_struct PICC_F;
//<2F><><EFBFBD>ղ<EFBFBD><D5B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> TYPE A
#define GAIN_A 7 //<2F><><EFBFBD>÷<EFBFBD>Χ0~7
#define HPCF_A 3 //<2F><><EFBFBD>÷<EFBFBD>Χ0~7
#define AMPLITUDE_A 255 //<2F><><EFBFBD>÷<EFBFBD>Χ0~255
//<2F><><EFBFBD>ղ<EFBFBD><D5B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> TYPE B
#define GAIN_B 7 //<2F><><EFBFBD>÷<EFBFBD>Χ0~7
#define HPCF_B 3 //<2F><><EFBFBD>÷<EFBFBD>Χ0~7
#define AMPLITUDE_B 255 //<2F><><EFBFBD>÷<EFBFBD>Χ0~255<35><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵԽ<D6B5><D4BD><EFBFBD>ز<EFBFBD>Խ<EFBFBD><D4BD>
#define MODULATION_B 100//<2F><><EFBFBD>÷<EFBFBD>Χ0~255,<2C><><EFBFBD><EFBFBD>ֵԽС<D4BD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>
//<2F><><EFBFBD>ղ<EFBFBD><D5B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> TYPE V
#define GAIN_V 7//<2F><><EFBFBD>÷<EFBFBD>Χ0~7
#define HPCF_V 4//<2F><><EFBFBD>÷<EFBFBD>Χ0~7
#define AMPLITUDE_V 255 //<2F><><EFBFBD>÷<EFBFBD>Χ0~255<35><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵԽ<D6B5><D4BD><EFBFBD>ز<EFBFBD>Խ<EFBFBD><D4BD>
#define MODULATION_V 10 //<2F><><EFBFBD>÷<EFBFBD>Χ0~255,<2C><><EFBFBD><EFBFBD>ֵԽС<D4BD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>
//<2F><><EFBFBD>ղ<EFBFBD><D5B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> TYPE F
#define GAIN_F 7//<2F><><EFBFBD>÷<EFBFBD>Χ0~7
#define HPCF_F 4//<2F><><EFBFBD>÷<EFBFBD>Χ0~7
#define AMPLITUDE_F 255 //<2F><><EFBFBD>÷<EFBFBD>Χ0~255<35><35><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵԽ<D6B5><D4BD><EFBFBD>ز<EFBFBD>Խ<EFBFBD><D4BD>
#define MODULATION_F 100//<2F><><EFBFBD>÷<EFBFBD>Χ0~255,<2C><><EFBFBD><EFBFBD>ֵԽС<D4BD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Խ<EFBFBD><D4BD>
#define SPI_GPIO GPIOB
#define SCK_PIN LL_GPIO_Pin1//PB1
#define MISO_PIN LL_GPIO_Pin2//PB2
#define MOSI_PIN LL_GPIO_Pin3//PB3
#define NSS_PIN LL_GPIO_Pin0//PB0
#define SCK_0 0//LL_GPIO_ResetOutputPin( SPI_GPIO, SCK_PIN )
#define SCK_1 0//LL_GPIO_SetOutputPin( SPI_GPIO, SCK_PIN )
#define MOSI_0 0//LL_GPIO_ResetOutputPin( SPI_GPIO, MOSI_PIN )
#define MOSI_1 0//LL_GPIO_SetOutputPin( SPI_GPIO, MOSI_PIN )
#define PD_GPIO GPIOA
#define PD_PIN LL_GPIO_Pin7//PA7
#define NSS_0 0//LL_GPIO_ResetOutputPin( SPI_GPIO, NSS_PIN )
#define NSS_1 0//LL_GPIO_SetOutputPin( SPI_GPIO, NSS_PIN )
#define PD_0 0//LL_GPIO_ResetOutputPin( PD_GPIO, PD_PIN )
#define PD_1 0//LL_GPIO_SetOutputPin( PD_GPIO, PD_PIN )
extern void DelayMs( uint32_t xms );
extern void DelayUs( uint32_t xus );
void Reader_GPIO_Init( void );
// extern unsigned char Reader_Set_HPD( unsigned char mode );
extern unsigned char FM176XX_HardReset(void);
// extern unsigned char Reader_Set_HPD( unsigned char mode ) ;
// extern unsigned char SetReg(unsigned char address,unsigned char reg_data);
// extern unsigned char GetReg(unsigned char address,unsigned char *reg_data);
extern void ModifyReg( unsigned char reg_address, unsigned char mask, unsigned char set );
extern void Clear_FIFO(void);
extern unsigned char SetCommand(unsigned char command);
extern void SetParity(unsigned char state);
extern void SetTimer(unsigned int timeout);
extern unsigned char SetCW(unsigned char mode);
extern unsigned char ReaderA_Initial(void);
extern unsigned char ReaderB_Initial(void);
extern unsigned char ReaderV_Initial(void);
extern unsigned char ReaderF_Initial(void);
extern unsigned char ReaderA_Wakeeup(struct picc_a_struct *picc_a);
extern unsigned char ReaderA_Request(struct picc_a_struct *picc_a);
extern unsigned char ReaderA_Anticoll(struct picc_a_struct *picc_a);
extern unsigned char ReaderA_Select(struct picc_a_struct *picc_a);
extern unsigned char ReaderA_CardActivate(struct picc_a_struct *picc_a);
extern unsigned char ReaderB_Wakeup(struct picc_b_struct *picc_b);
extern unsigned char ReaderB_Request(struct picc_b_struct *picc_b);
extern unsigned char ReaderB_Attrib(struct picc_b_struct *picc_b);
extern unsigned char ReaderB_Halt(struct picc_b_struct *picc_b);
extern unsigned char ReaderB_Get_SN(struct picc_b_struct *picc_b);
extern unsigned char ReaderV_Inventory(struct picc_v_struct *picc_v);
extern unsigned char ReaderV_Select(struct picc_v_struct *picc_v);
extern unsigned char ReaderV_ReadSingleBlock(unsigned char block_num,struct picc_v_struct *picc_v);
extern unsigned char ReaderV_WriteSingleBlock(unsigned char block_num,struct picc_v_struct *picc_v);
extern unsigned char ReaderF_Inventory(struct picc_f_struct *picc_f);
#endif

View File

@ -0,0 +1,478 @@
/*********************************************************************
* *
* Copyright (c) 2010 Shanghai FuDan MicroElectronic Inc, Ltd. *
* All rights reserved. Licensed Software Material. *
* *
* Unauthorized use, duplication, or distribution is strictly *
* prohibited by law. *
* *
**********************************************************************/
#ifndef _READER_REG_H
#define _READER_REG_H
#define REG_COMMAND 0x00 //
#define REG_HOSTCTRL 0x01 //
#define REG_FIFOCONTROL 0x02 //
#define REG_WATERLEVEL 0x03 //
#define REG_FIFOLENGTH 0x04 //
#define REG_FIFODATA 0x05 //
#define REG_IRQ0 0x06 //
#define REG_IRQ1 0x07 //
#define REG_IRQ0EN 0x08 //
#define REG_IRQ1EN 0x09 //
#define REG_ERROR 0x0A //
#define REG_STATUS 0x0B //
#define REG_RXBITCTRL 0x0C //
#define REG_RXCOLL 0x0D //
#define REG_TCONTROL 0x0E //
#define REG_T0CONTROL 0x0F //
#define REG_T0RELOADHI 0x10 //
#define REG_T0RELOADLO 0x11 //
#define REG_T0COUNTERVALHI 0x12 //
#define REG_T0COUNTERVALLO 0x13 //
#define REG_T1CONTROL 0x14 //
#define REG_T1RELOADHI 0x15 //
#define REG_T1RELOADLO 0x16 //
#define REG_T1COUNTERVALHI 0x17 //
#define REG_T1COUNTERVALLO 0x18 //
#define REG_T2CONTROL 0x19 //
#define REG_T2RELOADHI 0x1A //
#define REG_T2RELOADLO 0x1B //
#define REG_T2COUNTERVALHI 0x1C //
#define REG_T2COUNTERVALLO 0x1D //
#define REG_T3CONTROL 0x1E //
#define REG_T3RELOADHI 0x1F //
#define REG_T3RELOADLO 0x20 //
#define REG_T3COUNTERVALHI 0x21 //
#define REG_T3COUNTERVALLO 0x22 //
#define REG_T4CONTROL 0x23 //
#define REG_T4RELOADHI 0x24 //
#define REG_T4RELOADLO 0x25 //
#define REG_T4COUNTERVALHI 0x26 //
#define REG_T4COUNTERVALLO 0x27 //
#define REG_TXMODE 0x28
#define REG_TXAMP 0x29
#define REG_TXCON 0x2A //
#define REG_TXI 0x2B //
#define REG_TXCRCCON 0x2C //
#define REG_RXCRCCON 0x2D //
#define REG_TXDATANUM 0x2E
#define REG_TXMODWIDTH 0x2F //
#define REG_TXSYM10BURSTLEN 0x30 //
#define REG_TXWAITCTRL 0x31 //
#define REG_TXWAITLO 0x32 //
#define REG_FRAMECON 0x33 //
#define REG_RXSOFD 0x34 //
#define REG_RXCTRL 0x35 //
#define REG_RXWAIT 0x36 //
#define REG_RXTHRESHOLD 0x37 //
#define REG_RCV 0x38 //
#define REG_RXANA 0x39 //
#define REG_LPCD_OPTIONS 0x3A //
#define REG_SERIALSPEED 0x3B //
#define REG_LFO_TRIMM 0x3C //
#define REG_CLKOUT_CTRL 0x3D //
#define REG_LPCD_THRESHOLD 0x3E //
#define REG_LPCD_QMIN 0x3F //
#define REG_LPCD_QMAX 0x40
#define REG_LPCD_IMIN 0x41
#define REG_LPCD_RESULT_I 0x42
#define REG_LPCD_RESULT_Q 0x43
#define REG_THNADJ 0x5F
#define REG_THNSET 0x61
#define REG_THNMIN 0x62
#define REG_DSP_CTRL1 0x64
#define REG_MISC 0x75
#define REG_RXTXCON 0x77
#define REG_ERROREXT 0x7E
#define REG_VERSION 0x7F
#define CMD_MASK 0x1F
#define CMD_IDLE 0x00
#define CMD_LPCD 0x01
#define CMD_LOADKEY 0x02
#define CMD_AUTHENT 0x03
#define CMD_RECEIVE 0x05
#define CMD_TRANSMIT 0x06
#define CMD_TRANSCEIVE 0x07
#define CMD_WRITEE2 0x08
#define CMD_WRITEE2PAGE 0x09
#define CMD_READE2 0x0A
#define CMD_LOADREG 0x0C
#define CMD_LOADPROTOCOL 0x0D
#define CMD_LOADKEYE2 0x0E
#define CMD_STOREKEYE2 0x0F
#define CMD_CRCCALC 0x1B
#define CMD_READRNR 0x1C
#define CMD_SOFTRESET 0x1F
/** \name Host-Control Register Contents (0x00)
*/
/*@{*/
#define BIT_STANDBY 0x80U /**< Standby bit; If set, the IC transits to standby mode. */
#define BIT_MODEMOFF 0x40U
/*@{*/
/** \name Host-Control Register Contents (0x01)
*/
/*@{*/
#define BIT_I2CFORCEHS 0x01U
//#define BIT_REGEN 0x80U
//#define BIT_BUSHOST 0x40U
//#define BIT_BUSSAM 0x20U
//#define MASK_SAMINTERFACE 0x0CU
/*@}*/
/** \name FIFO-Control Register Contents (0x02)
*/
/*@{*/
#define BIT_FIFOSIZE 0x80U
#define BIT_HIALERT 0x40U
#define BIT_LOALERT 0x20U
#define BIT_FIFOFLUSH 0x10U
#define BIT_WATERLEVEL_HI 0x04U
#define MASK_FIFOLENGTH_HI 0x03U
/*@}*/
/** \name IRQ0 Register(s) Contents (0x06/0x08)
*/
/*@{*/
#define BIT_SET 0x80U
#define BIT_IRQINV 0x80U
#define BIT_HIALERTIRQ 0x40U
#define BIT_LOALERTIRQ 0x20U
#define BIT_IDLEIRQ 0x10U
#define BIT_TXIRQ 0x08U
#define BIT_RXIRQ 0x04U
#define BIT_ERRIRQ 0x02U
#define BIT_RXSOFIRQ 0x01U
/*@}*/
/** \name IRQ1 Register(s) Contents (0x07/0x09)
*/
/*@{*/
/* #define BIT_SET 0x80U */
#define BIT_IRQPUSHPULL 0x80U
#define BIT_GLOBALIRQ 0x40U
#define BIT_IRQPINEN 0x40U
#define BIT_LPCDIRQ 0x20U
#define BIT_TIMER4IRQ 0x10U
#define BIT_TIMER3IRQ 0x08U
#define BIT_TIMER2IRQ 0x04U
#define BIT_TIMER1IRQ 0x02U
#define BIT_TIMER0IRQ 0x01U
/*@}*/
/** \name Error Register Contents (0x0A)
*/
/*@{*/
#define BIT_CMDEE_ERR 0x80U
#define BIT_FIFOWRERR 0x40U
#define BIT_FIFOOVL 0x20U
#define BIT_MINFRAMEERR 0x10U
#define BIT_NODATAERR 0x08U
#define BIT_COLLDET 0x04U
#define BIT_PROTERR 0x02U
#define BIT_INTEGERR 0x01U
/*@}*/
/** \name Status Register Contents (0x0B)
*/
/*@{*/
#define BIT_CRYPTO1ON 0x20U
#define MASK_COMMSTATE 0x07U
/*@}*/
/** \name Rx-Bit-Control Register Contents (0x0C)
*/
/*@{*/
#define BIT_VALUESAFTERCOLL 0x80U
#define BIT_NOCOLL 0x08U
#define MASK_RXALIGN 0x70U
#define MASK_RXLASTBITS 0x07U
/*@}*/
/** \name Rx-Coll Register Contents (0x0D)
*/
/*@{*/
#define BIT_COLLPOSVALID 0x80U
#define MASK_COLLPOS 0x7FU
/*@}*/
/** \name Timer-Control Register Contents (0x0E)
*/
/*@{*/
#define BIT_T3RUNNING 0x80U
#define BIT_T2RUNNING 0x40U
#define BIT_T1RUNNING 0x20U
#define BIT_T0RUNNING 0x10U
#define BIT_T3STARTSTOPNOW 0x08U
#define BIT_T2STARTSTOPNOW 0x04U
#define BIT_T1STARTSTOPNOW 0x02U
#define BIT_T0STARTSTOPNOW 0x01U
/*@}*/
/** \name T[0-3]-Control Register Contents (0x0F/0x14/0x19/0x1E)
*/
/*@{*/
#define BIT_TSTOP_RX 0x80U /**< Stop timer on receive interrupt. */
#define BIT_TAUTORESTARTED 0x08U /**< Auto-restart timer after underflow. */
#define BIT_TSTART_TX 0x10U /**< Start timer on transmit interrupt. */
//#define BIT_TSTART_LFO 0x20U /**< Use this timer for LFO trimming. */
//#define BIT_TSTART_LFO_UV 0x30U /**< Use this timer for LFO trimming (generate UV at a trimming event). */
#define MASK_TSTART 0x30U /**< Mask for TSTART bits. */
#define VALUE_TCLK_1356_MHZ 0x00U /**< Use 13.56MHz as input clock. */
#define VALUE_TCLK_212_KHZ 0x01U /**< Use 212KHz as input clock. */
#define VALUE_TCLK_T0 0x02U /**< Use timer0 as input clock. */
#define VALUE_TCLK_T1 0x03U /**< Use timer1 as input clock. */
/*@}*/
/** \name T4-Control Register Contents (0x23)
*/
/*@{*/
#define BIT_T4RUNNING 0x80U
#define BIT_T4STARTSTOPNOW 0x40U
#define BIT_T4AUTOTRIMM 0x20U
#define BIT_T4AUTOLPCD 0x10U
#define BIT_T4AUTORESTARTED 0x08U
#define BIT_T4AUTOWAKEUP 0x04U
/*#define MASK_TSTART 0x30U*/
#define VALUE_TCLK_LFO_64_KHZ 0x00U
#define VALUE_TCLK_LFO_8_KHZ 0x01U
#define VALUE_TCLK_LFO_4_KHZ 0x02U
#define VALUE_TCLK_LFO_2_KHZ 0x03U
/*@}*/
/** \name Driver Mode Register Contents (0x28)
*/
/*@{*/
#define BIT_TX2INV 0x80U
#define BIT_TX1INV 0x40U
#define BIT_TXEN 0x08U
#define VALUE_TXCLKMODE_HIGHIMPEDANCE 0x00U
#define VALUE_TXCLKMODE_OUTPULL0 0x01U
#define VALUE_TXCLKMODE_OUTPULL1 0x02U
#define VALUE_TXCLKMODE_RFLOWPULL 0x05U
#define VALUE_TXCLKMODE_RFHIGHPUSH 0x06U
#define VALUE_TXCLKMODE_PUSHPULL 0x07U
#define BIT_RFON 0x04U
#define BIT_TPUSHON 0x02U
#define BIT_TPULLON 0x01U
/*@}*/
/** \name Tx Amplifier Register Contents (0x29)
*/
/*@{*/
#define MASK_CW_AMPLITUDE 0x00U
#define MASK_RESIDUAL_CARRIER 0x1FU
/*@}*/
/** \name Driver Control Register Contents (0x2A)
*/
/*@{*/
#define BIT_CWMAX 0x08U
#define BIT_DRIVERINV 0x04U
#define VALUE_DRIVERSEL_LOW 0x00U
#define VALUE_DRIVERSEL_TXENV 0x01U
#define VALUE_DRIVERSEL_SIGIN 0x02U
/*@}*/
/** \name Tx-/Rx-CRC Control Register Contents (0x2C/0x2D)
*/
/*@{*/
#define BIT_RXFORCECRCWRITE 0x80U
#define BIT_CRCINVERT 0x02U
#define BIT_CRCEN 0x01U
#define MASK_CRCPRESETVAL 0x70U
#define MASK_CRCTYPE 0x0CU
#define MASK_CRCTYPE5 0x00U
#define MASK_CRCTYPE16 0x08U
/*@}*/
/** \name Tx-DataNum Register Contents (0x2E)
*/
/*@{*/
#define BIT_KEEPBITGRID 0x10U
#define BIT_DATAEN 0x08U
#define MASK_TXLASTBITS 0x07U
#define MASK_SYMBOL_SEND 0x08U
/*@}*/
/** \name Tx-Wait Control Register Contents (0x31)
*/
/*@{*/
#define BIT_TXWAIT_START_RX 0x80U
#define BIT_TXWAIT_DBFREQ 0x40U
#define MASK_TXWAITHI 0x38U
#define MASK_TXSTOPBITLEN 0x07U
/*@}*/
/** \name Frame Control Register Contents (0x33)
*/
/*@{*/
#define BIT_TXPARITYEN 0x80U
#define BIT_RXPARITYEN 0x40U
#define VALUE_STOP_SYM3 0x0CU
#define VALUE_STOP_SYM2 0x08U
#define VALUE_STOP_SYM1 0x04U
#define VALUE_START_SYM3 0x03U
#define VALUE_START_SYM2 0x02U
#define VALUE_START_SYM1 0x01U
#define MASK_STARTSYM 0x03U
#define MASK_STOPSYM 0x0CU
/*@}*/
/** \name Rx Control Register Contents (0x35)
*/
/*@{*/
#define BIT_RXALLOWBITS 0x80U
#define BIT_RXMULTIPLE 0x40U
#define BIT_RXEOFTYPE 0x20U
#define BIT_EGT_CHECK 0x10U
#define BIT_EMD_SUPPRESSION 0x08U
#define MASK_RXBAUDRATE 0x07U
/*@}*/
/** \name Rx-Wait Register Contents (0x36)
*/
/*@{*/
#define BIT_RXWAITDBFREQ 0x80U
#define MASK_RXWAIT 0x7FU
/*@}*/
/** \name Rx-Threshold Register Contents (0x37)
*/
/*@{*/
#define MASK_MINLEVEL 0xF0U
#define MASK_MINLEVELP 0x0FU
/*@}*/
/** \name Rx-Receiver Register Contents (0x38)
*/
/*@{*/
#define BIT_RX_SINGLE 0x80U
#define BIT_RX_SHORT_MIX2ADC 0x40U
#define BIT_USE_SMALL_EVAL 0x04U
#define MASK_RX_SIGPRO_IN_SEL 0x30U
#define MASK_COLLLEVEL 0x03U
/*@}*/
/** \name Rx-Analog Register Contents (0x39)
*/
/*@{*/
#define BIT_RX_OC_ENABLE 0x20U
#define BIT_RX_HP_LOWF 0x10U
#define MASK_VMID_R_SEL 0xC0U
#define MASK_RCV_HPCF 0x0CU
#define MASK_RCV_GAIN 0x03U
/*@}*/
/** \name Serial-Speed Register Contents (0x3B)
*/
/*@{*/
#define MASK_BR_T0 0xE0U
#define MASK_BR_T1 0x1FU
/*@}*/
/** \name LPCD Result(Q) Register Contents (0x43)
*/
/*@{*/
#define BIT_LPCDIRQ_CLR 0x40U
/*@}*/
/** \name Tx-BitMod Register Contents (0x48)
*/
/*@{*/
#define BIT_TXMSBFIRST 0x80U
#define BIT_TXPARITYTYPE 0x20U
#define BIT_TXSTOPBITTYPE 0x08U
#define BIT_TXSTARTBITTYPE 0x02U
#define BIT_TXSTARTBITEN 0x01U
/*@}*/
/** \name Rx-BitMod Register Contents (0x58)
*/
/*@{*/
#define BIT_RXSTOPONINVPAR 0x20U
#define BIT_RXSTOPONLEN 0x10U
#define BIT_RXMSBFIRST 0x08U
#define BIT_RXSTOPBITEN 0x04U
#define BIT_RXPARITYTYPE 0x02U
/*@}*/
/** \name Rx-Mod Register Contents (0x5D)
*/
/*@{*/
#define BIT_PREFILTER 0x20U
#define BIT_RECTFILTER 0x10U
#define BIT_SYNCHIGH 0x08U
#define BIT_CORRINV 0x04U
#define BIT_FSK 0x02U
#define BIT_BPSK 0x01U
/*@}*/
/** \name RxSupCfg Register Contents (0x6E)
*/
/*@{*/
#define BIT_RXNOERR 0x80U
/*@}*/
/** \name RxTxConReg Register Contents (0x77)
*/
/*@{*/
#define BIT_SHMODE 0x08U //<2F>Ϻ<EFBFBD><CFBA>
/*@}*/
/** \name ErrorExtReg Register Contents (0x7E)
*/
/*@{*/
#define PARITY_ERROR 0x08U
#define CRC_ERROR 0x04U
/*@{*/
#define LPCD_OPTION2 0x1DF
//---------------------------------------------------------------
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><EFBFBD><EFBFBD>
#define RX_TYPEA_106 0
#define RX_TYPEA_212 1
#define RX_TYPEA_424 2
#define RX_TYPEA_848 3
#define RX_TYPEB_106 4
#define RX_TYPEB_212 5
#define RX_TYPEB_424 6
#define RX_TYPEB_848 7
#define RX_TYPEV_26 10
#define RX_TYPEV_53 11
#define RX_FELICA_212 19
#define RX_FELICA_424 20
//<2F><><EFBFBD><EFBFBD><E5B7A2>Э<EFBFBD><D0AD><EFBFBD><EFBFBD>
#define TX_TYPEA_106 0
#define TX_TYPEA_212 1
#define TX_TYPEA_424 2
#define TX_TYPEA_848 3
#define TX_TYPEB_106 4
#define TX_TYPEB_212 5
#define TX_TYPEB_424 6
#define TX_TYPEB_848 7
#define TX_TYPEV_26 10
#define TX_TYPEV_53 11
#define TX_FELICA_212 19
#define TX_FELICA_424 20
#endif

View File

@ -0,0 +1,225 @@
/**
* @file READER_REG.h
* @brief RFID 读卡器芯片寄存器定义
* @version 1.0
* @date 2024-05-20
*
* @copyright Copyright (c) 2010 Shanghai FuDan MicroElectronic Inc, Ltd.
*
* @par 文件作用:
* 这个头文件是整个RFID驱动库的最底层基石。它定义了RFID读卡器芯片
* (例如FM176XX系列)内部所有寄存器的地址、每个寄存器中功能位的掩码,
* 以及芯片支持的各种命令码。
* MCU通过SPI接口读写这些寄存器从而精确控制芯片的各项功能
* 例如启动/停止命令、配置通信协议、读写FIFO数据、查询状态等。
* 所有上层对RFID的操作最终都会转化为对这个文件中定义的寄存器的读写。
*/
#ifndef _READER_REG_H
#define _READER_REG_H
//==================================================================================
// 1. 寄存器地址定义 (Register Address Definitions)
// 这些是芯片内部功能单元的地址通过SPI访问。
//==================================================================================
#define REG_COMMAND 0x00 // 命令寄存器: 启动/停止芯片执行的命令 (如 Idle, Transceive)
#define REG_HOSTCTRL 0x01 // 主机控制寄存器
#define REG_FIFOCONTROL 0x02 // FIFO 控制寄存器 (如刷新FIFO)
#define REG_WATERLEVEL 0x03 // FIFO 水位寄存器: 用于中断触发
#define REG_FIFOLENGTH 0x04 // FIFO 长度寄存器: 当前FIFO中存储的字节数
#define REG_FIFODATA 0x05 // FIFO 数据寄存器: 通过此寄存器写入要发送的数据,或读出接收到的数据
#define REG_IRQ0 0x06 // 中断请求标志寄存器 0
#define REG_IRQ1 0x07 // 中断请求标志寄存器 1
#define REG_IRQ0EN 0x08 // 中断使能寄存器 0
#define REG_IRQ1EN 0x09 // 中断使能寄存器 1
#define REG_ERROR 0x0A // 错误标志寄存器: 显示通信中发生的错误 (如CRC错误, 冲突)
#define REG_STATUS 0x0B // 状态寄存器: 显示芯片当前状态 (如MIFARE加密是否开启)
#define REG_RXBITCTRL 0x0C // 接收数据位控制寄存器
#define REG_RXCOLL 0x0D // 接收冲突检测寄存器
#define REG_TCONTROL 0x0E // 定时器总体控制
#define REG_T0CONTROL 0x0F // 定时器0 控制
#define REG_T0RELOADHI 0x10 // 定时器0 重载值高字节
#define REG_T0RELOADLO 0x11 // 定时器0 重载值低字节
#define REG_T0COUNTERVALHI 0x12 // 定时器0 计数值高字节
#define REG_T0COUNTERVALLO 0x13 // 定时器0 计数值低字节
#define REG_T1CONTROL 0x14 // 定时器1 控制
#define REG_T1RELOADHI 0x15 // 定时器1 重载值高字节
#define REG_T1RELOADLO 0x16 // 定时器1 重载值低字节
#define REG_T1COUNTERVALHI 0x17 // 定时器1 计数值高字节
#define REG_T1COUNTERVALLO 0x18 // 定时器1 计数值低字节
#define REG_T2CONTROL 0x19 // 定时器2 控制
#define REG_T2RELOADHI 0x1A // 定时器2 重载值高字节
#define REG_T2RELOADLO 0x1B // 定时器2 重载值低字节
#define REG_T2COUNTERVALHI 0x1C // 定时器2 计数值高字节
#define REG_T2COUNTERVALLO 0x1D // 定时器2 计数值低字节
#define REG_T3CONTROL 0x1E // 定时器3 控制
#define REG_T3RELOADHI 0x1F // 定时器3 重载值高字节
#define REG_T3RELOADLO 0x20 // 定时器3 重载值低字节
#define REG_T3COUNTERVALHI 0x21 // 定时器3 计数值高字节
#define REG_T3COUNTERVALLO 0x22 // 定时器3 计数值低字节
#define REG_T4CONTROL 0x23 // 定时器4 控制
#define REG_T4RELOADHI 0x24 // 定时器4 重载值高字节
#define REG_T4RELOADLO 0x25 // 定时器4 重载值低字节
#define REG_T4COUNTERVALHI 0x26 // 定时器4 计数值高字节
#define REG_T4COUNTERVALLO 0x27 // 定时器4 计数值低字节
#define REG_TXMODE 0x28 // 发射模式寄存器
#define REG_TXAMP 0x29 // 发射信号幅度(天线功率)寄存器
#define REG_TXCON 0x2A // 发射控制寄存器 (调制深度等)
#define REG_TXI 0x2B // 发射器内部控制
#define REG_TXCRCCON 0x2C // 发射CRC控制寄存器
#define REG_RXCRCCON 0x2D // 接收CRC控制寄存器
#define REG_TXDATANUM 0x2E // 发送数据位数控制寄存器
#define REG_TXMODWIDTH 0x2F // 发射调制脉宽寄存器
#define REG_TXSYM10BURSTLEN 0x30 // TypeB的10%调制脉冲长度
#define REG_TXWAITCTRL 0x31 // 发送等待控制寄存器
#define REG_TXWAITLO 0x32 // 发送等待时间低字节
#define REG_FRAMECON 0x33 // 帧控制寄存器 (奇偶校验等)
#define REG_RXSOFD 0x34 // 接收起始标志位(SOF)配置
#define REG_RXCTRL 0x35 // 接收控制寄存器
#define REG_RXWAIT 0x36 // 接收等待时间寄存器
#define REG_RXTHRESHOLD 0x37 // 接收信号阈值寄存器
#define REG_RCV 0x38 // 接收器配置寄存器
#define REG_RXANA 0x39 // 接收器模拟电路配置寄存器 (增益等)
#define REG_LPCD_OPTIONS 0x3A // 低功耗寻卡(LPCD)选项
#define REG_SERIALSPEED 0x3B // 串行接口速率配置
#define REG_LFO_TRIMM 0x3C // 低频振荡器(LFO)微调
#define REG_CLKOUT_CTRL 0x3D // 时钟输出控制
#define REG_LPCD_THRESHOLD 0x3E // LPCD阈值
#define REG_LPCD_QMIN 0x3F // LPCD Q通道最小值
#define REG_LPCD_QMAX 0x40 // LPCD Q通道最大值
#define REG_LPCD_IMIN 0x41 // LPCD I通道最小值
#define REG_LPCD_RESULT_I 0x42 // LPCD I通道结果
#define REG_LPCD_RESULT_Q 0x43 // LPCD Q通道结果
#define REG_THNADJ 0x5F
#define REG_THNSET 0x61
#define REG_THNMIN 0x62
#define REG_DSP_CTRL1 0x64
#define REG_MISC 0x75 // 杂项配置
#define REG_RXTXCON 0x77 // 收发控制寄存器
#define REG_ERROREXT 0x7E // 扩展错误标志
#define REG_VERSION 0x7F // 版本寄存器: 读取此寄存器可获取芯片型号和版本
//==================================================================================
// 2. 命令码定义 (Command Codes)
// 写入到 REG_COMMAND 寄存器的值,用于启动芯片执行特定任务。
//==================================================================================
#define CMD_MASK 0x1F // 命令码掩码
#define CMD_IDLE 0x00 // 空闲命令: 停止当前操作,进入空闲状态
#define CMD_LPCD 0x01 // 低功耗寻卡 (Low-Power Card Detection)
#define CMD_LOADKEY 0x02 // 加载密钥命令: 将密钥从FIFO加载到内部密钥缓冲器 (用于MIFARE认证)
#define CMD_AUTHENT 0x03 // MIFARE认证命令: 执行MIFARE Classic卡的三重认证流程
#define CMD_RECEIVE 0x05 // 接收命令: 仅开启接收器,等待接收数据
#define CMD_TRANSMIT 0x06 // 发送命令: 将FIFO中的数据发送出去
#define CMD_TRANSCEIVE 0x07 // 发送并接收命令: 核心命令先发送FIFO中的数据然后自动进入接收状态等待卡片响应
#define CMD_WRITEE2 0x08 // 写E2PROM
#define CMD_WRITEE2PAGE 0x09 // 写E2PROM页
#define CMD_READE2 0x0A // 读E2PROM
#define CMD_LOADREG 0x0C // 从E2PROM加载寄存器值
#define CMD_LOADPROTOCOL 0x0D // 加载协议命令: 配置芯片以支持特定的通信协议 (Type A/B/V/F)
#define CMD_LOADKEYE2 0x0E // 从E2PROM加载密钥
#define CMD_STOREKEYE2 0x0F // 存储密钥到E2PROM
#define CMD_CRCCALC 0x1B // CRC计算
#define CMD_READRNR 0x1C // 读随机数
#define CMD_SOFTRESET 0x1F // 软复位命令: 复位芯片
//==================================================================================
// 3. 寄存器功能位定义 (Bit Definitions for Registers)
// 定义了每个寄存器中特定位的功能,方便通过位操作来修改寄存器值。
//==================================================================================
/** @name Command Register (0x00) 功能位 */
#define BIT_STANDBY 0x80U // 置1使芯片进入待机模式
#define BIT_MODEMOFF 0x40U // 关闭射频和调制解调器
/** @name FIFO-Control Register (0x02) 功能位 */
#define BIT_FIFOSIZE 0x80U // FIFO大小选择 (0=64字节, 1=512字节)
#define BIT_HIALERT 0x40U // 高水位中断标志
#define BIT_LOALERT 0x20U // 低水位中断标志
#define BIT_FIFOFLUSH 0x10U // FIFO刷新位。向此位写1可清空FIFO。
#define BIT_WATERLEVEL_HI 0x04U
#define MASK_FIFOLENGTH_HI 0x03U
/** @name IRQ0 Register (0x06) & IRQ0EN Register (0x08) 功能位 */
#define BIT_IRQINV 0x80U // 反转IRQ引脚电平
#define BIT_HIALERTIRQ 0x40U // FIFO高水位中断
#define BIT_LOALERTIRQ 0x20U // FIFO低水位中断
#define BIT_IDLEIRQ 0x10U // 空闲中断 (命令执行完毕)
#define BIT_TXIRQ 0x08U // 发送完成中断
#define BIT_RXIRQ 0x04U // 接收完成中断
#define BIT_ERRIRQ 0x02U // 错误中断
#define BIT_RXSOFIRQ 0x01U // 接收到起始帧(SOF)中断
/** @name IRQ1 Register (0x07) & IRQ1EN Register (0x09) 功能位 */
#define BIT_IRQPUSHPULL 0x80U // IRQ引脚推挽/开漏模式选择
#define BIT_GLOBALIRQ 0x40U // 全局中断使能
#define BIT_LPCDIRQ 0x20U // 低功耗寻卡中断
#define BIT_TIMER4IRQ 0x10U // 定时器4中断
#define BIT_TIMER3IRQ 0x08U // 定时器3中断
#define BIT_TIMER2IRQ 0x04U // 定时器2中断
#define BIT_TIMER1IRQ 0x02U // 定时器1中断
#define BIT_TIMER0IRQ 0x01U // 定时器0中断
/** @name Error Register (0x0A) 功能位 */
#define BIT_CMDEE_ERR 0x80U // E2PROM命令错误
#define BIT_FIFOWRERR 0x40U // FIFO写错误 (FIFO已满时写入)
#define BIT_FIFOOVL 0x20U // FIFO溢出错误
#define BIT_MINFRAMEERR 0x10U // 最小帧错误
#define BIT_NODATAERR 0x08U // 无数据错误 (超时)
#define BIT_COLLDET 0x04U // 检测到冲突错误
#define BIT_PROTERR 0x02U // 协议错误
#define BIT_INTEGERR 0x01U // CRC或奇偶校验错误
/** @name Status Register (0x0B) 功能位 */
#define BIT_CRYPTO1ON 0x20U // MIFARE加密已开启标志位。认证成功后此位由硬件自动置1。
#define MASK_COMMSTATE 0x07U // 通信状态掩码
/** @name Rx-Bit-Control Register (0x0C) 功能位 */
#define BIT_VALUESAFTERCOLL 0x80U // 冲突后接收到的位值
#define BIT_NOCOLL 0x08U // 无冲突
#define MASK_RXALIGN 0x70U // 接收位对齐掩码
#define MASK_RXLASTBITS 0x07U // 最后一字节的有效位数
/** @name Tx-/Rx-CRC Control Register (0x2C/0x2D) 功能位 */
#define BIT_CRCEN 0x01U // CRC使能位
/** @name Frame Control Register (0x33) 功能位 */
#define BIT_TXPARITYEN 0x80U // 发送奇偶校验使能
#define BIT_RXPARITYEN 0x40U // 接收奇偶校验使能
/** @name Rx-Analog Register (0x39) 功能位 */
#define MASK_RCV_HPCF 0x0CU // 接收器高通滤波器截止频率
#define MASK_RCV_GAIN 0x03U // 接收器增益
//==================================================================================
// 4. 协议标识符定义 (Protocol Identifiers)
// 用于 CMD_LOADPROTOCOL 命令,告诉芯片要使用哪种协议进行通信。
//==================================================================================
// --- 接收协议 ---
#define RX_TYPEA_106 0 // ISO14443A, 106 kbit/s
#define RX_TYPEA_212 1 // ISO14443A, 212 kbit/s
#define RX_TYPEA_424 2 // ISO14443A, 424 kbit/s
#define RX_TYPEA_848 3 // ISO14443A, 848 kbit/s
#define RX_TYPEB_106 4 // ISO14443B, 106 kbit/s
#define RX_TYPEB_212 5 // ISO14443B, 212 kbit/s
#define RX_TYPEB_424 6 // ISO14443B, 424 kbit/s
#define RX_TYPEB_848 7 // ISO14443B, 848 kbit/s
#define RX_TYPEV_26 10 // ISO15693, 26 kbit/s
#define RX_TYPEV_53 11 // ISO15693, 53 kbit/s
#define RX_FELICA_212 19 // FeliCa, 212 kbit/s
#define RX_FELICA_424 20 // FeliCa, 424 kbit/s
// --- 发送协议 ---
#define TX_TYPEA_106 0 // ISO14443A, 106 kbit/s
#define TX_TYPEA_212 1 // ISO14443A, 212 kbit/s
#define TX_TYPEA_424 2 // ISO14443A, 424 kbit/s
#define TX_TYPEA_848 3 // ISO14443A, 848 kbit/s
#define TX_TYPEB_106 4 // ISO14443B, 106 kbit/s
#define TX_TYPEB_212 5 // ISO14443B, 212 kbit/s
#define TX_TYPEB_424 6 // ISO14443B, 424 kbit/s
#define TX_TYPEB_848 7 // ISO14443B, 848 kbit/s
#define TX_TYPEV_26 10 // ISO15693, 26 kbit/s
#define TX_TYPEV_53 11 // ISO15693, 53 kbit/s
#define TX_FELICA_212 19 // FeliCa, 212 kbit/s
#define TX_FELICA_424 20 // FeliCa, 424 kbit/s
#endif

View File

@ -0,0 +1,294 @@
/**
* @file READER.c
* @brief RFID 核心协议驱动实现
* @version 1.0
* @date 2024-05-20
*
* @par 文件作用:
* 该文件是 READER.h 中声明的所有函数的具体实现。它是驱动库的核心逻辑所在,
* 负责将上层应用的简单指令(如“寻卡”)转化为一系列复杂的、精确计时的
* 寄存器读写操作。
* 主要职责包括:
* 1. 实现各协议的初始化函数,配置芯片进入相应的工作模式。
* 2. 实现各协议的寻卡、防冲突、选卡等底层通信流程。
* 3. 提供与芯片交互的基础原子操作函数 (SetCommand, Clear_FIFO 等)。
*/
#include "function.h"
#include "board.h"
#include "READER.h"
#include "READER_REG.h"
#include "xt_main.h"
#include <stdio.h>
// 定义全局变量,用于存储寻卡后得到的各类卡片信息
struct picc_a_struct PICC_A;
struct picc_b_struct PICC_B;
struct picc_v_struct PICC_V;
struct picc_f_struct PICC_F;
// (注: 此处的延时函数为软件延时,移植到新平台时建议使用定时器以获得更高精度)
void DelayUs( uint32_t xus ) { /* ... */ }
void DelayMs( uint32_t xms ) { /* ... */ }
/**
* @brief 修改寄存器的特定位 (Read-Modify-Write)
* @param reg_address 要修改的寄存器地址
* @param mask 要操作的位的掩码 (例如 0x01 表示操作 bit 0)
* @param set 1 表示置位 (set)0 表示清零 (clear)
*/
void ModifyReg( unsigned char reg_address, unsigned char mask, unsigned char set )
{
unsigned char reg_data;
GetReg( reg_address, &reg_data ); // 1. 先读出寄存器当前的值
if ( set )
{
reg_data |= mask; // 2. 使用或运算将指定位置1
}
else
{
reg_data &= ~mask; // 3. 使用与和非运算将指定位清0
}
SetReg( reg_address, reg_data ); // 4. 将修改后的值写回寄存器
return;
}
/**
* @brief 向芯片发送一个命令
* @param command 要发送的命令码 (定义于 READER_REG.h, 如 CMD_TRANSCEIVE)
* @return unsigned char 操作结果
*/
unsigned char SetCommand(unsigned char command)
{
return SetReg(REG_COMMAND, CMD_MASK & command);
}
/**
* @brief 开启或关闭天线载波 (射频场)
* @param mode ENABLE 或 DISABLE
* @return unsigned char 操作结果
*/
unsigned char SetCW(unsigned char mode)
{
if(mode == ENABLE)
{
// 通过清除 MODEMOFF 位并设置 TXEN 位来开启天线
ModifyReg(REG_COMMAND, BIT_MODEMOFF, DISABLE);
ModifyReg(REG_TXMODE, BIT0 | BIT1, ENABLE);
}
else
{
// 通过设置 MODEMOFF 位来关闭天线
ModifyReg(REG_COMMAND, BIT_MODEMOFF, ENABLE);
ModifyReg(REG_TXMODE, BIT0 | BIT1, DISABLE);
}
DelayMs(5);
return SUCCESS;
}
/**
* @brief 清空芯片内部的 FIFO 缓冲区
*/
void Clear_FIFO(void)
{
unsigned char fifolength;
GetReg(REG_FIFOLENGTH, &fifolength); // 读取FIFO中当前字节数
if((fifolength) != 0)
{
// 如果FIFO不为空通过置位 FIFOFLUSH 来清空
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, ENABLE);
}
return ;
}
/**
* @brief 加载通信协议到芯片
* @param p_rx 接收协议标识符 (来自 READER_REG.h)
* @param p_tx 发送协议标识符 (来自 READER_REG.h)
* @return unsigned char 成功或失败
*/
unsigned char LoadProtocol(unsigned char p_rx, unsigned char p_tx)
{
unsigned char reg_data = 0;
SetCommand(CMD_IDLE);
Clear_FIFO();
SetReg(REG_FIFODATA, p_rx); // 将接收协议标识符写入FIFO
SetReg(REG_FIFODATA, p_tx); // 将发送协议标识符写入FIFO
SetCommand(CMD_LOADPROTOCOL); // 发送加载协议命令
DelayMs(2);
GetReg(REG_COMMAND, &reg_data);
if(reg_data != CMD_IDLE) // 检查命令是否执行完毕
return FAIL;
return SUCCESS;
}
/**
* @brief 设置是否启用奇偶校验
* @param state ENABLE 或 DISABLE
*/
void SetParity(unsigned char state)
{
ModifyReg(REG_FRAMECON, BIT_TXPARITYEN | BIT_RXPARITYEN, state);
}
/**
* @brief 初始化芯片以进行 ISO14443-A 通信
* @return unsigned char 成功
*/
unsigned char ReaderA_Initial(void)
{
LoadProtocol(RX_TYPEA_106, TX_TYPEA_106); // 1. 加载Type A协议
ModifyReg(REG_TXMODE, BIT2, ENABLE); // 2. 设置为100% ASK调制
SetReg(REG_TXAMP, AMPLITUDE_A); // 3. 设置天线发射功率
SetReg(REG_RXANA, (HPCF_A << 3) | GAIN_A); // 4. 设置接收器增益和高通滤波器
SetParity(ENABLE); // 5. Type A 需要奇偶校验
ModifyReg(REG_STATUS, BIT_CRYPTO1ON, 0); // 6. 清除MIFARE加密标志
return SUCCESS;
}
/**
* @brief 初始化芯片以进行 ISO14443-B 通信
* @return unsigned char 成功
*/
unsigned char ReaderB_Initial(void)
{
LoadProtocol(RX_TYPEB_106, TX_TYPEB_106);
// ... 配置Type B特定的寄存器 ...
return SUCCESS;
}
// ... 其他协议的初始化函数 (ReaderV_Initial, ReaderF_Initial) ...
/**
* @brief (Type A) 发送 REQA 命令
* @param picc_a 指向 picc_a_struct 的指针,用于存储响应
* @return unsigned char 成功或失败
*/
unsigned char ReaderA_Request(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
Clear_FIFO();
SetReg(REG_FIFODATA, RF_CMD_REQA); // 1. 将 REQA 命令码 (0x26) 写入FIFO
ModifyReg(REG_TXCRCCON, BIT_CRCEN, DISABLE); // 2. REQA 命令不带CRC
ModifyReg(REG_RXCRCCON, BIT_CRCEN, DISABLE);
SetCommand(CMD_TRANSCEIVE); // 3. 发送并等待接收
DelayMs(2);
GetReg(REG_FIFOLENGTH, &reg_data); // 4. 检查接收到的数据长度
if(reg_data != 2) // 5. 成功的响应 (ATQA) 应该是2个字节
return FAIL;
GetReg(REG_FIFODATA, &picc_a->ATQA[0]); // 6. 从FIFO读出ATQA
GetReg(REG_FIFODATA, &picc_a->ATQA[1]);
return SUCCESS;
}
/**
* @brief (Type A) 执行一级防冲突
* @param picc_a 指向 picc_a_struct 的指针
* @return unsigned char 成功或失败
*/
unsigned char ReaderA_Anticoll(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
Clear_FIFO();
// 1. 准备防冲突命令 (如 0x93 0x20)
SetReg(REG_FIFODATA, RF_CMD_ANTICOLL[picc_a->CASCADE_LEVEL]);
SetReg(REG_FIFODATA, 0x20);
SetCommand(CMD_TRANSCEIVE);
DelayMs(2);
GetReg(REG_FIFOLENGTH, &reg_data);
if(reg_data != 5) // 2. 响应应为5字节 (4字节UID + 1字节BCC)
return FAIL;
// 3. 从FIFO读出UID和BCC
GetReg(REG_FIFODATA, &picc_a->UID[picc_a->CASCADE_LEVEL*4]);
// ...
GetReg(REG_FIFODATA, &picc_a->BCC[picc_a->CASCADE_LEVEL]);
// 4. 校验BCC (UID四个字节的异或值)
if( (picc_a->UID[picc_a->CASCADE_LEVEL*4] ^ picc_a->UID[picc_a->CASCADE_LEVEL*4+1] ^ picc_a->UID[picc_a->CASCADE_LEVEL*4+2] ^ picc_a->UID[picc_a->CASCADE_LEVEL*4+3]) == picc_a->BCC[picc_a->CASCADE_LEVEL])
return SUCCESS;
return FAIL;
}
/**
* @brief (Type A) 选卡命令
* @param picc_a 指向 picc_a_struct 的指针
* @return unsigned char 成功或失败
*/
unsigned char ReaderA_Select(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
Clear_FIFO();
// 1. 准备选卡命令 (如 0x93 0x70 + UID + BCC)
SetReg(REG_FIFODATA, RF_CMD_SELECT[picc_a->CASCADE_LEVEL]);
SetReg(REG_FIFODATA, 0x70);
SetReg(REG_FIFODATA, picc_a->UID[picc_a->CASCADE_LEVEL*4]);
// ...
SetReg(REG_FIFODATA, picc_a->BCC[picc_a->CASCADE_LEVEL]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, ENABLE); // 2. 选卡命令带CRC
ModifyReg(REG_RXCRCCON, BIT_CRCEN, ENABLE);
SetCommand(CMD_TRANSCEIVE);
DelayMs(2);
GetReg(REG_ERROR, &reg_data); // 3. 检查是否有通信错误
if((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if(reg_data != 1) // 4. 响应为1字节的SAK
return FAIL;
GetReg(REG_FIFODATA, &picc_a->SAK[picc_a->CASCADE_LEVEL]); // 5. 读出SAK
return SUCCESS;
}
/**
* @brief **核心函数**: 激活一张A类卡 (完成完整的寻卡、防冲突、选卡流程)
* @param picc_a 指向 picc_a_struct 的指针
* @return unsigned char 成功或失败
*/
unsigned char ReaderA_CardActivate(struct picc_a_struct *picc_a)
{
unsigned char result, cascade_level;
result = ReaderA_Request(picc_a); // 1. 发送请求
if (result != SUCCESS)
return result;
// 2. 根据ATQA判断UID长度确定级联等级
if ((picc_a->ATQA[0] & 0xC0) == 0x00)
{
cascade_level = 1;
picc_a->UID_Length = 4;
}
else if ((picc_a->ATQA[0] & 0xC0) == 0x40)
{
cascade_level = 2;
picc_a->UID_Length = 7; // (修正: 通常是7字节)
}
// ...
// 3. 循环执行防冲突和选卡直到获得完整的UID
for (picc_a->CASCADE_LEVEL = 0; picc_a->CASCADE_LEVEL < cascade_level; picc_a->CASCADE_LEVEL++)
{
result = ReaderA_Anticoll(picc_a);
if (result != SUCCESS)
return result;
result = ReaderA_Select(picc_a);
if (result != SUCCESS)
return result;
// 如果SAK指示还有下一级UID则继续循环
if (!(picc_a->SAK[picc_a->CASCADE_LEVEL] & 0x04))
break;
}
return result;
}
// ... (其他协议 Type B, V, F 的函数实现) ...

View File

@ -0,0 +1,147 @@
/**
* @file READER.h
* @brief RFID 核心协议驱动接口
* @version 1.0
* @date 2024-05-20
*
* @par 文件作用:
* 该文件是核心协议驱动层(READER.c)的头文件,为上层应用(如MIFARE, NTAG)
* 提供了标准化的接口来与不同协议的RFID卡片进行底层交互。
* 它主要负责:
* 1. 定义存储不同类型卡片信息的数据结构 (如 picc_a_struct)。
* 2. 声明协议操作函数,如初始化、寻卡、选择、激活等。
* 3. 定义通信过程中使用的标准命令码和硬件配置参数。
* 上层应用通过调用本文件中声明的函数,可以完成对卡片的寻卡和选卡操作,
* 从而为后续的认证和数据读写做准备。
*/
#ifndef _READER_H
#define _READER_H
#include "function.h"
//==================================================================================
// 1. ISO14443-A 标准命令码定义
//==================================================================================
static const unsigned char RF_CMD_REQA = 0x26; // REQA (Request Type A) 命令: 用于请求视场内的A类卡响应
static const unsigned char RF_CMD_WUPA = 0x52; // WUPA (Wake-Up Type A) 命令: 用于唤醒视场内处于HALT状态的A类卡
static const unsigned char RF_CMD_ANTICOLL[3] = {0x93, 0x95, 0x97}; // 防冲突命令码 (级联等级 1, 2, 3)
static const unsigned char RF_CMD_SELECT[3] = {0x93, 0x95, 0x97}; // 选卡命令码 (级联等级 1, 2, 3)
//==================================================================================
// 2. MIFARE Classic 命令码定义
//==================================================================================
static const unsigned char RF_CMD_KEYA = 0x60; // MIFARE Key A 认证命令
static const unsigned char RF_CMD_KEYB = 0x61; // MIFARE Key B 认证命令
//==================================================================================
// 3. 卡片信息数据结构定义
// 用于存储从不同类型卡片读取到的信息。
//==================================================================================
/** @brief ISO14443-B 卡片信息结构体 */
struct picc_b_struct
{
unsigned char ATQB[12]; // REQB命令的响应 (Answer to Request B)
unsigned char PUPI[4]; // 伪唯一PICCs标识符
// ... 其他Type B卡片信息
};
extern struct picc_b_struct PICC_B; // 声明一个全局变量以存储Type B卡信息
/** @brief ISO14443-A 卡片信息结构体 */
struct picc_a_struct
{
unsigned char ATQA[2]; // REQA命令的响应 (Answer to Request A)
unsigned char CASCADE_LEVEL; // 级联等级 (表示UID的长度)
unsigned char UID_Length; // UID 长度 (4, 7 或 10字节)
unsigned char UID[15]; // 存储卡片的唯一ID (UID)
unsigned char BCC[3]; // UID的校验字节
unsigned char SAK[3]; // 选卡确认 (Select Acknowledge), 用于判断卡片具体类型
};
extern struct picc_a_struct PICC_A; // 声明一个全局变量以存储Type A卡信息
/** @brief ISO15693 (Type V) 卡片信息结构体 */
struct picc_v_struct
{
unsigned char UID[8]; // Type V 卡的UID (8字节)
unsigned char RESPONSE; // 卡片的响应字节
unsigned char BLOCK_DATA[4]; // 用于存储从卡片读取的块数据
};
extern struct picc_v_struct PICC_V;
/** @brief FeliCa (Type F) 卡片信息结构体 */
struct picc_f_struct
{
unsigned char UID[8]; // Type F 卡的UID
};
extern struct picc_f_struct PICC_F;
//==================================================================================
// 4. 硬件配置参数宏定义
// 这些参数用于在初始化时配置RFID芯片的模拟电路以优化特定协议的通信性能。
//==================================================================================
// --- TYPE A 接收参数 ---
#define GAIN_A 7 // 接收增益 (范围 0~7)
#define HPCF_A 3 // 高通滤波器截止频率 (范围 0~7)
#define AMPLITUDE_A 255 // 发射信号幅度/功率 (范围 0~255)
// --- TYPE B 接收参数 ---
#define GAIN_B 7
#define HPCF_B 3
#define AMPLITUDE_B 255
#define MODULATION_B 100 // 调制深度 (范围 0~255)
// ... (其他协议的参数定义) ...
//==================================================================================
// 5. MCU引脚定义 (移植时需要重点关注)
// 定义了MCU与RFID芯片连接的SPI引脚和控制引脚。
//==================================================================================
#define SPI_GPIO GPIOB
#define SCK_PIN LL_GPIO_Pin1 // PB1
#define MISO_PIN LL_GPIO_Pin2 // PB2
#define MOSI_PIN LL_GPIO_Pin3 // PB3
#define NSS_PIN LL_GPIO_Pin0 // PB0 (片选)
#define PD_GPIO GPIOA
#define PD_PIN LL_GPIO_Pin7 // PA7 (Power Down引脚)
// ... (GPIO电平控制宏) ...
//==================================================================================
// 6. 函数原型声明
// 声明了由 READER.c 实现的函数,供其他模块调用。
//==================================================================================
// --- 基础控制函数 ---
extern unsigned char FM176XX_HardReset(void); // 硬复位RFID芯片
extern void ModifyReg(unsigned char reg_address, unsigned char mask, unsigned char set); // 修改寄存器的特定位
extern void Clear_FIFO(void); // 清空FIFO缓冲区
extern unsigned char SetCommand(unsigned char command); // 向芯片发送命令
extern unsigned char SetCW(unsigned char mode); // 开启或关闭天线载波
// --- 协议初始化函数 ---
extern unsigned char ReaderA_Initial(void); // 初始化芯片以进行Type A通信
extern unsigned char ReaderB_Initial(void); // 初始化芯片以进行Type B通信
extern unsigned char ReaderV_Initial(void); // 初始化芯片以进行Type V通信
extern unsigned char ReaderF_Initial(void); // 初始化芯片以进行Type F通信
// --- Type A 卡操作函数 ---
extern unsigned char ReaderA_Request(struct picc_a_struct *picc_a); // 发送 REQA 命令
extern unsigned char ReaderA_Anticoll(struct picc_a_struct *picc_a); // 执行防冲突
extern unsigned char ReaderA_Select(struct picc_a_struct *picc_a); // 选卡
extern unsigned char ReaderA_CardActivate(struct picc_a_struct *picc_a); // **核心函数**: 完成A类卡的寻卡、防冲突和选卡全过程获取UID
// --- Type B 卡操作函数 ---
extern unsigned char ReaderB_Request(struct picc_b_struct *picc_b); // 发送 REQB 命令
extern unsigned char ReaderB_Attrib(struct picc_b_struct *picc_b); // 设置卡片参数
// ...
// --- Type V 卡操作函数 ---
extern unsigned char ReaderV_Inventory(struct picc_v_struct *picc_v); // 盘点/寻卡
extern unsigned char ReaderV_ReadSingleBlock(unsigned char block_num, struct picc_v_struct *picc_v); // 读单个块
extern unsigned char ReaderV_WriteSingleBlock(unsigned char block_num, struct picc_v_struct *picc_v); // 写单个块
// --- Type F 卡操作函数 ---
extern unsigned char ReaderF_Inventory(struct picc_f_struct *picc_f); // 盘点/寻卡
#endif

View File

@ -0,0 +1,192 @@
/**
******************************************************************************
* @file board.c
* @author SRG
* @version V1.0.0
* @date 2020-03-17
* @brief
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 FudanMicroelectronics.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
#include "board.h"
#include "READER.h"
#include "fm15l0xx.h"
#include "fm15l0xx_ll_cmu.h"
#include "fm15l0xx_ll_gpio.h"
#include "fm15l0xx_ll_uart.h"
#include "fm15l0xx_ll_spi.h"
#include "fm15l0xx_ll_svd.h"
#include "fm15l0xx_ll_rng.h"
// <20>ж<EFBFBD>VDD<44>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
int Vdd_is_Low( void )
{
return (!LL_SVD_IsActiveFlag_SVDR() );
}
void SVD_Init( void )
{
LL_SVD_EnableSVDDigitalFilter(); // ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD><CBB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBBFAA>
LL_SVD_SetSVDMode( LL_SVD_SVDMOD_INTERVAL_ON ); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
LL_SVD_SetSVDInterval( LL_SVD_SVDITVL_62p5ms ); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>62.5ms
LL_SVD_DisableV1P0(); // <20>ر<EFBFBD>1V<31><56>׼<EFBFBD><D7BC>ѹ
LL_SVD_EnableV0P95(); // ʹ<>û<EFBFBD>׼<EFBFBD><D7BC>ѹ<EFBFBD><D1B9>0.95V
LL_SVD_SetSVDLevel( LL_SVD_SVDLVL_LEVEL10 ); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>ȼ<EFBFBD>10 - <20><>ֵ3.614V
LL_SVD_EnableSVD();
}
void RNG_Init( void )
{
LL_CMU_EnablePeriphBusClock_RNG(); // Enable bus clock(RCHF)
LL_CMU_EnableClock_RNG(); // Enable RNG work clock
LL_CMU_SetClockPrescaler_RNG( LL_CMU_PERPRSC_2 ); // 4MHz: RCHF / 2<><32>ʱ<EFBFBD><CAB1>Ƶ<EFBFBD>ʹ<EFBFBD><CAB9>߻ᵼ<DFBB><E1B5BC>SFAIL<49><4C><EFBFBD><EFBFBD>
LL_RNG_EnableNoiseSource();
LL_RNG_Enable();
}
uint32_t Get_RandomNumber( void )
{
while ( 1 )
{
if ( LL_RNG_IsDataReady() || LL_RNG_IsActiveFlag_SFAIL() )
{
if ( LL_RNG_IsActiveFlag_SFAIL() )
{
// <20><><EFBFBD>մ<EFBFBD><D5B4><EFBFBD><EFBFBD><EFBFBD>־
LL_RNG_ClearFlag_SFAIL();
LL_RNG_GetRandomData();
}
else
{
break; // <20><>ȡ<EFBFBD>ɹ<EFBFBD>
}
}
}
return (LL_RNG_GetRandomData());
}
/*********************************************************************************************************
** <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: GPIO_NVIC_Init
** <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><C5B5>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>
** <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <09><>
** <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <09><>
** <20><><EFBFBD><EFBFBD>ֵ: <09><>
*********************************************************************************************************/
void GPIO_NVIC_Init( void )
{
LL_CMU_EnableClock_EXTI();
//<2F><><EFBFBD><EFBFBD>оƬIRQ<52>ж<EFBFBD>
LL_EXTI_SetEXTISelection( LL_EXTI_LINE_0, LL_EXTI_SELECTION_3 ); // PA3
LL_EXTI_SetEXTIEdgeTrig( LL_EXTI_LINE_0, LL_EXTI_EDS_FALLING ); // Falling
//FM17<31><37><EFBFBD><EFBFBD>оƬIRQ<52>ж<EFBFBD>
LL_EXTI_SetEXTISelection( LL_EXTI_LINE_1, LL_EXTI_SELECTION_3 ); // PA7
LL_EXTI_SetEXTIEdgeTrig( LL_EXTI_LINE_1, LL_EXTI_EDS_FALLING ); // Falling
NVIC_EnableIRQ( GPIO_IRQn );
}
void GPIO_Init( void )
{
LL_CMU_EnablePeriphBusClock_GPIO(); // Bus clock enable
LL_GPIO_SetPinMode( GPIOA, LL_GPIO_Pin12, LL_GPIO_PINxMODE_DIGITAL ); // PA12 Digital function - UART1 RX
LL_GPIO_SetPinDigitalFunc( GPIOA, LL_GPIO_Pin12, LL_GPIO_PinDFS0 );
LL_GPIO_SetPinMode( GPIOA, LL_GPIO_Pin13, LL_GPIO_PINxMODE_DIGITAL ); // PA13 Digital function - UART1 TX
LL_GPIO_SetPinDigitalFunc( GPIOA, LL_GPIO_Pin13, LL_GPIO_PinDFS0 );
LL_GPIO_SetPinMode( LED_GPIO, LED1_PIN, LL_GPIO_PINxMODE_OUTPUT );
LL_GPIO_SetPinMode( LED_GPIO, LED2_PIN, LL_GPIO_PINxMODE_OUTPUT );
LED1_On;
LED2_On;
DelayMs(200);
LED1_Off;
LED2_Off;
}
void Uart_Init( void )
{
/* Bus clock enable */
LL_CMU_EnablePeriphBusClock_UART1();
LL_CMU_SelectClock_UART1( LL_CMU_HFPER_CLK_APBCLKx ); // Clock source select
LL_CMU_EnableClock_UART1(); // Operation clock enable
LL_UART_SetBaudRate( UART1, 412 ); // Set baudrate to 115200bps, reg = (uclk / baudrate) - 1
LL_UART_SetDataWidth( UART1, LL_UART_DATA_WIDTH_8bit ); // 8 bit
LL_UART_SetStopBitsLength( UART1, LL_UART_STOPCFG_1bit ); // 1 stop bit
LL_UART_SetParity( UART1, LL_UART_PARITY_NONE ); // Parity none
LL_UART_EnableTx( UART1 ); // Tx enable
LL_UART_EnableRx( UART1 ); // Rx enable
}
void uart_send_byte( UART_Typedef *uart, uint16_t c )
{
while ( !LL_UART_IsActiveFlag_TXBE( uart ) )
;
LL_UART_TransmitData( uart, (uint32_t) c );
}
/* Retarget fputc, then you can use printf. */
int fputc( int ch, FILE *f )
{
uart_send_byte( UART1, ch );
return (ch);
}
void SPI_Init( SPI_Typedef *spi )
{
// Bus clock enable
if ( spi == SPI1 )
LL_CMU_EnablePeriphBusClock_SPI1();
else if ( spi == SPI2 )
LL_CMU_EnablePeriphBusClock_SPI2();
LL_SPI_DisableCtrlSSN( spi ); // Disable Software Control
//LL_SPI_SetSSNOutput( spi, 1 ); // Set SSN High
LL_SPI_Disable( spi ); // Disable SPI
LL_SPI_SetWorkMode( spi, LL_SPI_WORKMODE_MASTER ); // Mode select - master
LL_SPI_SetBaudrate( spi, LL_SPI_BAUDRATE_DIV_4 ); // Baudrate Select - fPCLK/16
LL_SPI_SetFrameFormat(spi,LL_SPI_FRAME_FMT_MSB);
LL_SPI_SetClockPolarity(spi,LL_SPI_CPOL_NEGATIVE);
LL_SPI_SetCommMode(spi,LL_SPI_COMM_MODE_STANDARD);
LL_SPI_SetDataLength(spi,LL_SPI_DATA_LENGTH_8bit);
LL_SPI_DisableHalfDuplexDummyCycle(spi);
LL_SPI_Enable( spi ); // Enable SPI
}
void BSP_Init( void )
{
GPIO_Init();
Uart_Init();
//SPI_Init( SPI1);
SVD_Init();
RNG_Init();
}

View File

@ -0,0 +1,70 @@
#include <stdio.h>
#include "bsp.h"
void gpio_init( void )
{
LL_CMU_EnablePeriphBusClock_GPIO(); // Bus clock enable
LL_GPIO_SetPinMode( GPIOA, LL_GPIO_Pin0, LL_GPIO_PINxMODE_DIGITAL ); // PA0 Digital function - UART0 RX
LL_GPIO_SetPinDigitalFunc( GPIOA, LL_GPIO_Pin0, LL_GPIO_PinDFS0 );
LL_GPIO_SetPinMode( GPIOA, LL_GPIO_Pin1, LL_GPIO_PINxMODE_DIGITAL ); // PA1 Digital function - UART0 TX
LL_GPIO_SetPinDigitalFunc( GPIOA, LL_GPIO_Pin1, LL_GPIO_PinDFS0 );
}
void uart_init( void )
{
/* Bus clock enable */
LL_CMU_EnablePeriphBusClock_UART0();
LL_CMU_SelectClock_UART0( LL_CMU_HFPER_CLK_APBCLKx ); // Clock source select
LL_CMU_EnableClock_UART0(); // Operation clock enable
LL_UART_SetBaudRate( UARTx, 412 ); // Set baudrate to 115200bps, reg = (uclk / baudrate) - 1
LL_UART_SetDataWidth( UARTx, LL_UART_DATA_WIDTH_8bit ); // 8 bit
LL_UART_SetStopBitsLength( UARTx, LL_UART_STOPCFG_1bit ); // 1 stop bit
LL_UART_SetParity( UARTx, LL_UART_PARITY_NONE ); // Parity none
LL_UART_EnableTx( UARTx ); // Tx enable
LL_UART_EnableRx( UARTx ); // Rx enable
}
void uart_send_byte( UART_Typedef *uart, uint16_t c )
{
while ( !LL_UART_IsActiveFlag_TXBE( uart ) )
;
LL_UART_TransmitData( uart, (uint32_t) c );
}
/* Retarget fputc, then you can use printf. */
int fputc( int ch, FILE *f )
{
uart_send_byte( UARTx, ch );
return (ch);
}
void svd_init( void )
{
LL_SVD_EnableSVDDigitalFilter(); // ʹ<><CAB9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˲<EFBFBD><CBB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBBFAA>
LL_SVD_SetSVDMode( LL_SVD_SVDMOD_INTERVAL_ON ); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
LL_SVD_SetSVDInterval( LL_SVD_SVDITVL_62p5ms ); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>62.5ms
LL_SVD_DisableV1P0(); // <20>ر<EFBFBD>1V<31><56>׼<EFBFBD><D7BC>ѹ
LL_SVD_EnableV0P95(); // ʹ<>û<EFBFBD>׼<EFBFBD><D7BC>ѹ<EFBFBD><D1B9>0.95V
LL_SVD_SetSVDLevel( LL_SVD_SVDLVL_LEVEL10 ); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>ȼ<EFBFBD>10 - <20><>ֵ3.614V
LL_SVD_EnableSVD();
}
void bsp_init( void )
{
gpio_init();
uart_init();
svd_init();
}

View File

@ -0,0 +1,613 @@
#include <stdio.h>
#include "print.h"
#include "READER.h"
#include "random_generator.h"
unsigned char ciphertext_to_binary[48] ; //用来存储算法逆运算每轮的中间数据 需要定义成全局变量
unsigned char lsfr[48];
unsigned char lsfr_length;
unsigned char decode_printcipher( unsigned char ciphertext[] , unsigned char long_key[] , unsigned char short_key[] )//解密函数
{
unsigned char a[6][8];
unsigned char i , j ;
unsigned char t ;
unsigned char k ; //k是用在sbox中的
unsigned char num ; //主循环
unsigned char long_key_to_binary[48] ;
unsigned char temp[48] ;
unsigned char short_key_to_binary[32] ;
unsigned char rev_counter[6] = {1,0,0,1,0,0};
unsigned char temp_rev_counter[6];
//----------------------------------ciphertext-------------------------------------------------//
for(i=0 ; i<6 ; ++i) //
{ //
for(j=0 ; j<8 ; ++j) //
{ // 该作用是把密文以二进制保存在数组中ciphertext
a[i][8-1-j] = ciphertext[i] % 2 ; // a[7]应该是二进制最低位a[0]最高位
ciphertext[i] /= 2 ; //
} //
} //
for(i=0 ; i<6 ; ++i)
{
for(j=0 ; j<8 ; ++j)
{
ciphertext_to_binary[i*8+j] = a[i][j] ;
}
}
//printf("%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",ciphertext_to_binary[0],ciphertext_to_binary[1],ciphertext_to_binary[2],\
ciphertext_to_binary[3],ciphertext_to_binary[4],ciphertext_to_binary[5],ciphertext_to_binary[6],ciphertext_to_binary[7],\
ciphertext_to_binary[40],ciphertext_to_binary[41],ciphertext_to_binary[42],ciphertext_to_binary[43],ciphertext_to_binary[44],ciphertext_to_binary[45],ciphertext_to_binary[46],ciphertext_to_binary[47]);
//-------------------------------------ciphertext---------------------------------------------//
//-------------------------------------long_key----------------------------------------------//
for(i=0 ; i<6 ; ++i) //
{ //
for(j=0 ; j<8 ; ++j) //
{ // 该作用是把密文以二进制保存在数组中long_key
a[i][8-1-j] = long_key[i] % 2 ; //
long_key[i] /= 2; //
} //
} //
for(i=0 ; i<6 ; ++i)
{
for(j=0 ; j<8 ; ++j)
{
long_key_to_binary[i*8+j] = a[i][j] ;
}
}
//printf("%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",long_key_to_binary[0],long_key_to_binary[1],long_key_to_binary[2],\
long_key_to_binary[3],long_key_to_binary[4],long_key_to_binary[5],long_key_to_binary[6],long_key_to_binary[7],\
long_key_to_binary[40],long_key_to_binary[41],long_key_to_binary[42],long_key_to_binary[43],long_key_to_binary[44],long_key_to_binary[45],long_key_to_binary[46],ciphertext_to_binary[47]);
//-------------------------------- long_key---------------------------------------------------//
//-------------------------------- short_key-------------------------------------------------//
for(i=0 ; i<4 ; ++i) //
{ //
for(j=0 ; j<8 ; ++j) //
{ // 该作用是把密文以二进制保存在数组中short_key
a[i][8-1-j] = short_key[i] % 2 ; //
short_key[i] /= 2 ; //
} //
} //
for(i=0 ; i<4 ; ++i)
{
for(j=0 ; j<8 ; ++j)
{
short_key_to_binary[i*8+j] = a[i][j] ;
}
}
//printf("%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",short_key_to_binary[0],short_key_to_binary[1],short_key_to_binary[2],\
short_key_to_binary[3],short_key_to_binary[4],short_key_to_binary[5],short_key_to_binary[6],short_key_to_binary[7],\
short_key_to_binary[24],short_key_to_binary[25],short_key_to_binary[26],short_key_to_binary[27],short_key_to_binary[28],short_key_to_binary[29],short_key_to_binary[30],short_key_to_binary[31]);
//-------------------------------- short_key-------------------------------------------------//
for(num = 0 ; num < 48 ; num++)
{
for(k=0 ; k<16 ; k++)
{
if((short_key_to_binary[k*2]==0) &&(short_key_to_binary[k*2+1]==0) )
{
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 0;
temp[k*3+1]= 0;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 0;
temp[k*3+1]= 0;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 1;
temp[k*3+1]= 1;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 0;
temp[k*3+1]= 1;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 1;
temp[k*3+1]= 0;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 1;
temp[k*3+1]= 1;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 0;
temp[k*3+1]= 1;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 1;
temp[k*3+1]= 0;
temp[k*3+2]= 0;
}
}
//////////////////////////////01
if((short_key_to_binary[k*2]==0) &&(short_key_to_binary[k*2+1]==1) )
{
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 0;
temp[k*3+1]= 0;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 0;
temp[k*3+1]= 0;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 1;
temp[k*3+1]= 1;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 1;
temp[k*3+1]= 0;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 0;
temp[k*3+1]= 1;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 1;
temp[k*3+1]= 1;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 1;
temp[k*3+1]= 0;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 0;
temp[k*3+1]= 1;
temp[k*3+2]= 0;
}
}
//////////////////////////////////////////10
if((short_key_to_binary[k*2]==1) &&(short_key_to_binary[k*2+1]==0) )
{
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 0;
temp[k*3+1]= 0;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 0;
temp[k*3+1]= 1;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 1;
temp[k*3+1]= 1;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 0;
temp[k*3+1]= 0;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 1;
temp[k*3+1]= 1;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 1;
temp[k*3+1]= 0;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 0;
temp[k*3+1]= 1;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 1;
temp[k*3+1]= 0;
temp[k*3+2]= 0;
}
}
////////////////////////////////////////////11
if((short_key_to_binary[k*2]==1) &&(short_key_to_binary[k*2+1]==1) )
{
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 0;
temp[k*3+1]= 0;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 1;
temp[k*3+1]= 0;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 1;
temp[k*3+1]= 1;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==0) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 0;
temp[k*3+1]= 1;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 1;
temp[k*3+1]= 0;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==0)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 0;
temp[k*3+1]= 1;
temp[k*3+2]= 1;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==0))
{
temp[k*3] = 1;
temp[k*3+1]= 1;
temp[k*3+2]= 0;
}
if((ciphertext_to_binary[k*3]==1) && (ciphertext_to_binary[k*3+1]==1)&&(ciphertext_to_binary[k*3+2]==1))
{
temp[k*3] = 0;
temp[k*3+1]= 0;
temp[k*3+2]= 1;
}
}
}
// printf("%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",temp[0],temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[7],temp[8],temp[9],temp[10],temp[11],temp[12],temp[13],temp[14],temp[15],temp[40],temp[41],temp[42],temp[43],temp[44],temp[45],temp[46],temp[47]);
//下面的函数是对RC的逆运算
t = 1 ^ rev_counter[0] ^ rev_counter[5];
temp_rev_counter [0] = rev_counter[1] ;
temp_rev_counter [1] = rev_counter[2] ;
temp_rev_counter [2] = rev_counter[3] ;
temp_rev_counter [3] = rev_counter[4] ;
temp_rev_counter [4] = rev_counter[5] ;
temp_rev_counter [5] = t ;
for(i=0 ; i<6 ; i++ )
{
rev_counter [i] = temp_rev_counter[i] ; //rev_counter[5]是最高位
}
temp[47] = rev_counter[0] ^ temp[47] ;
temp[46] = rev_counter[1] ^ temp[46] ;
temp[45] = rev_counter[2] ^ temp[45] ;
temp[44] = rev_counter[3] ^ temp[44] ;
temp[43] = rev_counter[4] ^ temp[43] ;
temp[42] = rev_counter[5] ^ temp[42] ;
// printf("%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x \n",temp[0],temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[7],temp[8],temp[9],temp[10],temp[11],temp[12],temp[13],temp[14],temp[15],temp[40],temp[41],temp[42],temp[43],temp[44],temp[45],temp[46],temp[47]);
//下面是对linear diffusion的逆运算
ciphertext_to_binary[0] = temp[0] ;
ciphertext_to_binary[1] = temp[3] ;
ciphertext_to_binary[2] = temp[6] ;
ciphertext_to_binary[3] = temp[9] ;
ciphertext_to_binary[4] = temp[12] ;
ciphertext_to_binary[5] = temp[15] ;
ciphertext_to_binary[6] = temp[18] ;
ciphertext_to_binary[7] = temp[21] ;
ciphertext_to_binary[8] = temp[24] ;
ciphertext_to_binary[9] = temp[27] ;
ciphertext_to_binary[10] = temp[30] ;
ciphertext_to_binary[11] = temp[33] ;
ciphertext_to_binary[12] = temp[36] ;
ciphertext_to_binary[13] = temp[39] ;
ciphertext_to_binary[14] = temp[42] ;
ciphertext_to_binary[15] = temp[45] ;
ciphertext_to_binary[16] = temp[1] ;
ciphertext_to_binary[17] = temp[4] ;
ciphertext_to_binary[18] = temp[7] ;
ciphertext_to_binary[19] = temp[10] ;
ciphertext_to_binary[20] = temp[13] ;
ciphertext_to_binary[21] = temp[16] ;
ciphertext_to_binary[22] = temp[19] ;
ciphertext_to_binary[23] = temp[22] ;
ciphertext_to_binary[24] = temp[25] ;
ciphertext_to_binary[25] = temp[28] ;
ciphertext_to_binary[26] = temp[31] ;
ciphertext_to_binary[27] = temp[34] ;
ciphertext_to_binary[28] = temp[37] ;
ciphertext_to_binary[29] = temp[40] ;
ciphertext_to_binary[30] = temp[43] ;
ciphertext_to_binary[31] = temp[46] ;
ciphertext_to_binary[32] = temp[2] ;
ciphertext_to_binary[33] = temp[5] ;
ciphertext_to_binary[34] = temp[8] ;
ciphertext_to_binary[35] = temp[11] ;
ciphertext_to_binary[36] = temp[14] ;
ciphertext_to_binary[37] = temp[17] ;
ciphertext_to_binary[38] = temp[20] ;
ciphertext_to_binary[39] = temp[23] ;
ciphertext_to_binary[40] = temp[26] ;
ciphertext_to_binary[41] = temp[29] ;
ciphertext_to_binary[42] = temp[32] ;
ciphertext_to_binary[43] = temp[35] ;
ciphertext_to_binary[44] = temp[38] ;
ciphertext_to_binary[45] = temp[41] ;
ciphertext_to_binary[46] = temp[44] ;
ciphertext_to_binary[47] = temp[47] ;
for(i=0 ; i<48 ; i++)
{
ciphertext_to_binary[i] = ciphertext_to_binary[i] ^ long_key_to_binary[i] ;
}
}
// printf (" %x %x %x %x %x %x %x %x\n %x %x %x %x %x %x %x %x\n %x %x %x %x %x %x %x %x\n %x %x %x %x %x %x %x %x\n %x %x %x %x %x %x %x %x\n %x %x %x %x %x %x %x %x\n",ciphertext_to_binary[0],ciphertext_to_binary[1],ciphertext_to_binary[2],ciphertext_to_binary[3],ciphertext_to_binary[4],ciphertext_to_binary[5],ciphertext_to_binary[6],ciphertext_to_binary[7],\
ciphertext_to_binary[8],ciphertext_to_binary[9],ciphertext_to_binary[10],ciphertext_to_binary[11],ciphertext_to_binary[12],ciphertext_to_binary[13],ciphertext_to_binary[14],ciphertext_to_binary[15],\
ciphertext_to_binary[16],ciphertext_to_binary[17],ciphertext_to_binary[18],ciphertext_to_binary[19],ciphertext_to_binary[20],ciphertext_to_binary[21],ciphertext_to_binary[22],ciphertext_to_binary[23],\
ciphertext_to_binary[24],ciphertext_to_binary[25],ciphertext_to_binary[26],ciphertext_to_binary[27],ciphertext_to_binary[28],ciphertext_to_binary[29],ciphertext_to_binary[30],ciphertext_to_binary[31],\
ciphertext_to_binary[32],ciphertext_to_binary[33],ciphertext_to_binary[34],ciphertext_to_binary[35],ciphertext_to_binary[36],ciphertext_to_binary[37],ciphertext_to_binary[38],ciphertext_to_binary[39],\
ciphertext_to_binary[40],ciphertext_to_binary[41],ciphertext_to_binary[42],ciphertext_to_binary[43],ciphertext_to_binary[44],ciphertext_to_binary[45],ciphertext_to_binary[46],ciphertext_to_binary[47] );
return 0 ;
}
void Print_AUTH(unsigned char *key,unsigned char *TOKEN,unsigned char *rece_buff)//print 认证
{
unsigned char i,j;
unsigned char long_key[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; //长key
unsigned char short_key[4] = {0xff,0xff,0xff,0xff}; //短key注意短key的最后一个字节是整个key的第一个字节
unsigned char PWD_key[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//tag的秘钥占10个字节
for(i = 0;i<10;i++)
{
PWD_key[i] = key[9-i];//需要把PWD 倒顺序一下,做下反向,需要特别注意,之前的密码需要倒序一下
}
memcpy(&long_key[0],PWD_key,6);
memcpy(&short_key[0],&PWD_key[6],4);
decode_printcipher(TOKEN, &long_key[0] , &short_key[0]);
for(i=0 ; i<6 ; i++)
{
for(j=0 ; j<8 ; j++)
{
rece_buff[i] = (rece_buff[i]<<1)+ciphertext_to_binary[i*8+j] ; //把最终的结果赋值给明文中
}
}
}
unsigned char lsfr_fm458(void) //length 这里是byte
{
char j ;
unsigned char temp;
unsigned char temp1;
temp1 = lsfr[47];
temp = lsfr[47] ^ lsfr[27] ^ lsfr[26] ^ lsfr[0];
for (j = 46; j >= 0; j--)
{
lsfr[j + 1] = lsfr[j];
}
lsfr[0] = temp;
return temp1;
}
void lsfr_init(unsigned char *S022_Token2)
{
unsigned char z,k;
unsigned char load_key[6];
//备份初始密钥流
memcpy(load_key, S022_Token2, 6);
//把R2和R3的结果加载进移位寄存器
for (z = 0; z < 6; z++)
{
for (k = 0; k <= 7; k++)
{
if ((unsigned char)((load_key[z] << k) & 0x80) == 0)
lsfr[47 - (k + z * 8)] = 0;
else
lsfr[47 - (k + z * 8)] = 1;
}
}
//lsfr_length = 48;
//printf("lsfr = %x%x%x%x%x%x%x%x\r\n",lsfr[0],lsfr[1],lsfr[2],lsfr[3],lsfr[4],lsfr[5],lsfr[6],lsfr[7]);
}
//data_len 最多16byte
//unsigned char PRINT_Calc_sendData(unsigned char *data_buf, unsigned char data_len, BOOL half_byte)
unsigned char PRINT_Calc_sendData(unsigned char *data_buf, unsigned char data_len)
{
unsigned char i,y;
unsigned char round;
unsigned char temp[8];
unsigned char temp1[8];
unsigned char encry[64];
unsigned char senddata[16];
round = data_len * 8;
for (y = 0; y < round; y++)
{
encry[y] = lsfr_fm458();
}
for (y = 0; y < data_len; y++)
{
for(i=0; i<8; i++)
{
temp[i] = (unsigned char)((data_buf[y] >> i) & 0x01);
}
//发送的byte按位异或 加密
for(i=0 ; i<8 ;i++)
{
temp1[i] = temp[i] ^ encry[i + y * 8]; //异或就是和密码流进行加密
}
senddata[y] = (unsigned char)(temp1[0] * 1 + temp1[1] * 2 + temp1[2] * 4 + temp1[3] * 8 + temp1[4] * 16 + temp1[5] * 32 + temp1[6] * 64 + temp1[7] * 128);
}
memcpy(data_buf, senddata, data_len);
// authstat = CAL_COMMAND_FLOW;
return SUCCESS;
}
//unsigned char PRINT_Calc_recvData(unsigned char *data_buf, unsigned char data_len, BOOL half_byte)
unsigned char PRINT_Calc_recvData(unsigned char *data_buf, unsigned char data_len)
{
unsigned char encry[128];
unsigned char i,y;
unsigned char temp[8];
unsigned char temp1[8];
unsigned char recvdata[16];
unsigned char round;
round = (data_len) * 8;
if (data_len == 0x01) //该添加为了类似写指令回发ACK等4bit的加密流方法。
{
round = round / 2;
}
for (y = 0; y < round; y++)
{
encry[y] = lsfr_fm458();
}
//已经有了加密数据,就要想办法进行异或操作
for (y = 0; y < data_len; y++)
{
for (i = 0; i < 8; i++)
{
temp[i] = (unsigned char)((data_buf[y] >> i) & 0x01);
}
//发送的byte按位异或 加密
for (i = 0; i < 8; i++)
{
temp1[i] = temp[i] ^ encry[i + y * 8]; //异或就是和密码流进行加密
}
recvdata[y] = (unsigned char)(temp1[0] * 1 + temp1[1] * 2 + temp1[2] * 4 + temp1[3] * 8 + temp1[4] * 16 + temp1[5] * 32 + temp1[6] * 64 + temp1[7] * 128);
}
memcpy(data_buf, recvdata, data_len);
return SUCCESS;
}

View File

@ -0,0 +1,457 @@
/**
************************************* Copyright ******************************
* (C) Copyright 2019,TuYW,FMSH,China.
* All Rights Reserved
* By(Shanghai Fudan MicroeleCardTyperonics Group Company Limited)
* https://www.fmsh.com
*
* FileName : function.c
* Version : v1.0
* Author : TuYW
* Date : 2019-03-19
* Description:
*******************************************************************************/
#include "function.h"
//#include "flash.h"
#include "intrins.h"
#include <stdio.h>
/**
* @brief Convert Hex 32Bits value into char
* @param value: value to convert
* @param pbuf: pointer to the buffer
* @param len: buffer length
* @retval None
*/
void IntToUnicode( uint32_t value, uint8_t *pbuf, uint8_t len )
{
uint8_t idx = 0;
for ( idx = 0; idx < len; idx++ )
{
if ( ( (value >> 28) ) < 0xA )
{
pbuf[2 * idx] = (value >> 28) + '0';
}
else
{
pbuf[2 * idx] = (value >> 28) + 'A' - 10;
}
value = value << 4;
pbuf[2 * idx + 1] = 0;
}
}
//תַ
u8 uitoa( u16 n, u8* s )
{
u16 i = 0, j;
u16 len = 0;
u8 tmp[7] = { 0 };
do
{
tmp[i++] = n % 10 + '0'; //ȡһ
}
while ( (n /= 10) > 0 ); //ɾ
len = i;
for ( j = 0; j < len; j++, i-- ) //򴢴
{
s[j] = tmp[i - 1];
}
return (len);
}
//ƽ
u32 power( u8 n )
{
u8 i;
u32 t;
t = 1;
for ( i = 0; i < n; i++ )
t *= 2;
return (t);
}
//m^n
u32 calpow( u8 m, u8 n )
{
u32 result = 1;
while ( n-- )
result *= m;
return (result);
}
//CRC
u16 UpdateCrc( u8 ch, u16 *lpwCrc )
{
ch = (ch ^ (u8) ( (*lpwCrc) & 0x00FF) );
ch = (ch ^ (ch << 4) );
*lpwCrc = (*lpwCrc >> 8) ^ ( (u16) ch << 8) ^ ( (u16) ch << 3) ^ ( (u16) ch >> 4);
return (*lpwCrc);
}
u16 ComputeCrc( const u16 InitCRC, const u8 *Data, const u32 Length )
{
u8 chBlock;
u32 InLength = Length;
u16 wCrc = InitCRC;
do
{
chBlock = *Data++;
UpdateCrc( chBlock, &wCrc );
}
while ( --InLength );
return (~wCrc);;
}
//u16 CalculateIapCrc(void)
//{
// return ComputeCrc(0xffff,(u8 *)PROGRAM_IAP_BASE,PROGRAM_IAP_LENGTH);
//}
//u16 CalculateAppCrc(void)
//{
// return ComputeCrc(0xffff,(u8 *)PROGRAM_APP_BASE,PROGRAM_APP_LENGTH);
//}
/*********************************************************************************************************
** : CalcBCC
** : bccУ
** :
** :
** ֵ:
*********************************************************************************************************/
u8 CalcBCC( u8 *ibuf, u16 ilen )
{
u8 BCC = 0x00;
u16 i = 0;
for ( i = 0; i < ilen; i++ )
{
BCC = BCC ^ ibuf[i];
}
return (BCC);
}
/*
// C prototype : void StrToHex(BYTE *pbDest, BYTE *pbSrc, int nLen)
// parameter(s): [OUT] pbDest -
// [IN] pbSrc - ַ
// [IN] nLen - 16ֽ(ַij/2)
// return value:
// remarks : ַתΪ16
*/
void StrToHex( BYTE *pbDest, BYTE *pbSrc, int nLen )
{
char h1, h2;
BYTE s1, s2;
int i;
for ( i = 0; i < nLen; i++ )
{
h1 = pbSrc[2 * i];
h2 = pbSrc[2 * i + 1];
s1 = toupper( h1 ) - 0x30;
if ( s1 > 9 )
s1 -= 7;
s2 = toupper( h2 ) - 0x30;
if ( s2 > 9 )
s2 -= 7;
pbDest[i] = s1 * 16 + s2;
}
}
/*
// C prototype : void HexToStr(BYTE *pbDest, BYTE *pbSrc, int nLen)
// parameter(s): [OUT] pbDest - Ŀַ
// [IN] pbSrc - 16ʼַ
// [IN] nLen - 16ֽ
// return value:
// remarks : 16תΪַ
*/
void HexToStr( BYTE *pbDest, BYTE *pbSrc, int nLen )
{
char ddl, ddh;
int i;
for ( i = 0; i < nLen; i++ )
{
ddh = 48 + pbSrc[i] / 16;
ddl = 48 + pbSrc[i] % 16;
if ( ddh > 57 )
ddh = ddh + 7;
if ( ddl > 57 )
ddl = ddl + 7;
pbDest[i * 2] = ddh;
pbDest[i * 2 + 1] = ddl;
}
pbDest[nLen * 2] = '\0';
}
U32 le32p_to_cpu( U8*p )
{
return ( (U32) ( (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]) );
}
U32 be32p_to_cpu( const U8*p )
{
return ( (U32) ( (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]) );
}
void cpu_to_le32p( U8*p, U32 n )
{
p[3] = (U8) (n >> 24);
p[2] = (U8) (n >> 16);
p[1] = (U8) (n >> 8);
p[0] = (U8) (n);
}
void cpu_to_be32p( U8*p, U32 n )
{
p[0] = (U8) (n >> 24);
p[1] = (U8) (n >> 16);
p[2] = (U8) (n >> 8);
p[3] = (U8) (n);
}
U32 le16p_to_cpu( const U8*p )
{
return ( (U32) ( (p[1] << 8) | p[0]) );
}
U32 be16p_to_cpu( U8*p )
{
return ( (U32) ( (p[0] << 8) | p[1]) );
}
void cpu_to_le16p( U8*p, U32 n )
{
p[1] = (U8) (n >> 8);
p[0] = (U8) (n);
}
void cpu_to_be16p( U8*p, U32 n )
{
p[0] = (U8) (n >> 8);
p[1] = (U8) (n);
}
/*ַs转Ӧ*/
//int atoi(char s[])
//{
// int i;
// int n = 0;
// for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i)
// {
// n = 10 * n + (s[i] - '0');
// }
// return n;
//}
int atoi_b( u8 *s, u32 sl )
{
int i;
int n = 0;
for ( i = 0; i < sl; i++ )
{
n = 10 * n + (s[i] - '0');
}
return (n);
}
//xtell tolower改成my_tolower
/*дĸ转Сдĸ*/
int my_tolower( int c )
{
if ( c >= 'A' && c <= 'Z' )
{
return (c + 'a' - 'A');
}
else
{
return (c);
}
}
//ʮƵַ转
int htoi( char s[] )
{
int i;
int n = 0;
if ( s[0] == '0' && (s[1] == 'x' || s[1] == 'X') )
{
i = 2;
}
else
{
i = 0;
}
for (; (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z'); ++i )
{
if ( my_tolower( s[i] ) > '9' )
{
n = 16 * n + (10 + my_tolower( s[i] ) - 'a');
}
else
{
n = 16 * n + (my_tolower( s[i] ) - '0');
}
}
return (n);
}
// itoa (ʾ integer to alphanumeric)ǰ转ַһ
char* itoa( long num, char* str, int radix )
{
char temp; // 移动到函数开头
char index[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //
unsigned long unum; //Ҫ转ľֵ,转Ǹ
int i = 0, j, k; //iָʾַӦλ转֮iʵַijȣ转˳ģkָʾ˳Ŀʼλ;jָʾ˳ʱĽ
//ȡҪ转ľֵ
if ( radix == 10 && num < 0 ) //Ҫ转ʮǸ
{
unum = (unsigned long) -num; //numľֵunum
str[i++] = '-'; //ַǰΪ'-'ţ1
}
else
unum = (unsigned long) num; //numΪֱӸֵunum
//转֣ע转
do
{
str[i++] = index[unum % (unsigned long) radix]; //ȡunumһλΪstrӦλָʾ1
unum /= radix; //unumȥһλ
}
while ( unum ); //ֱunumΪ0˳ѭ
str[i] = '\0'; //ַ'\0'ַcַ'\0'
//˳
if ( str[0] == '-' )
k = 1; //ǸŲõӷź濪ʼ
else
k = 0; //ǸȫҪ
for ( j = k; j <= (i - 1) / 2; j++ ) //ͷβһһԳƽiʵַijȣֵȳ1
{
temp = str[j]; //ͷֵʱ
str[j] = str[i - 1 + k - j]; //βֵͷ
str[i - 1 + k - j] = temp; //ʱֵ(ʵ֮ǰͷֵ)β
}
return (str); //转ַ
}
static const char *ALPHA_BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//base64뺯
int base64_encode( const char *buf, const long size, char *base64Char )
{
int int63 = 0x3F; // 00111111 // 移动到函数开头
int int255 = 0xFF; // 11111111 // 移动到函数开头
int a = 0;
int i = 0;
int base64Len = 0;
while ( i < size )
{
char b0 = buf[i++];
char b1 = (i < size) ? buf[i++] : 0;
char b2 = (i < size) ? buf[i++] : 0;
base64Char[a++] = ALPHA_BASE[(b0 >> 2) & int63];
base64Char[a++] = ALPHA_BASE[( (b0 << 4) | ( (b1 & int255) >> 4) ) & int63];
base64Char[a++] = ALPHA_BASE[( (b1 << 2) | ( (b2 & int255) >> 6) ) & int63];
base64Char[a++] = ALPHA_BASE[b2 & int63];
}
base64Len = a;
switch ( size % 3 )
{
case 1:
base64Char[--a] = '=';
case 2:
base64Char[--a] = '=';
}
return (base64Len);
}
//base64뺯
char *base64_decode( const char *base64Char, const long base64CharSize, char *originChar, long originCharSize )
{
int toInt[128] = { -1 };
int int255 = 0xFF; // 移动到函数开头
int index = 0; // 移动到函数开头
int c2, c3; // 移动到函数开头
int i = 0;
int j = 0;
for ( i = 0; i < 64; i++ )
{
toInt[ALPHA_BASE[i]] = i;
}
for ( j = 0; j < base64CharSize; j += 4 )
{
int c0 = toInt[base64Char[j]];
int c1 = toInt[base64Char[j + 1]];
originChar[index++] = ( ( (c0 << 2) | (c1 >> 4) ) & int255);
if ( index >= originCharSize )
{
return (originChar);
}
c2 = toInt[base64Char[j + 2]];
originChar[index++] = ( ( (c1 << 4) | (c2 >> 2) ) & int255);
if ( index >= originCharSize )
{
return (originChar);
}
c3 = toInt[base64Char[j + 3]];
originChar[index++] = ( ( (c2 << 6) | c3) & int255);
}
return (originChar);
}
//建
void ClrLongBuf( u8* buf, u32 n )
{
memset( buf, 0x00, n );
}

View File

@ -0,0 +1,21 @@
#ifndef _MIFARE_H_
#define _MIFARE_H_
#define KEY_A_M1 0
#define KEY_B_M1 1
extern unsigned char SECTOR,BLOCK,BLOCK_NUM;
extern unsigned char BLOCK_DATA[16];
extern unsigned char KEY_A[16][6];
extern unsigned char KEY_B[16][6];
extern unsigned char MIFARE_CARD_EVENT(void);
extern void Mifare_Clear_Crypto(void);
unsigned char Mifare_LoadKey(unsigned char *mifare_key);
extern unsigned char Mifare_Transfer(unsigned char block);
extern unsigned char Mifare_Restore(unsigned char block);
extern unsigned char Mifare_Blockset(unsigned char block,unsigned char *data_buff);
extern unsigned char Mifare_Blockinc(unsigned char block,unsigned char *data_buff);
extern unsigned char Mifare_Blockdec(unsigned char block,unsigned char *data_buff);
extern unsigned char Mifare_Blockwrite(unsigned char block,unsigned char *data_buff);
extern unsigned char Mifare_Blockread(unsigned char block,unsigned char *data_buff);
extern unsigned char Mifare_Auth(unsigned char key_mode,unsigned char sector,unsigned char *mifare_key,unsigned char *card_uid);
#endif

View File

@ -0,0 +1,73 @@
/**
* @file MIFARE.h
* @brief MIFARE Classic 卡应用层驱动接口
* @version 1.0
* @date 2024-05-20
*
* @par 文件作用:
* 该文件为操作 MIFARE Classic 卡片提供了高层接口。它建立在 READER.c
* 提供的 Type A 协议基础之上,封装了 MIFARE 卡特有的操作,如密码认证、
* 块读写和值块操作。
* 主应用逻辑通过包含此文件并调用其声明的函数,来完成对 MIFARE 卡的
* 具体业务操作。
*/
#ifndef _MIFARE_H_
#define _MIFARE_H_
//==================================================================================
// 1. 宏定义
//==================================================================================
#define KEY_A_M1 0 // 定义认证模式为 Key A
#define KEY_B_M1 1 // 定义认证模式为 Key B
//==================================================================================
// 2. 全局变量声明
// 这些变量用于在不同函数间传递操作上下文。
//==================================================================================
extern unsigned char SECTOR; // 当前要操作的扇区号
extern unsigned char BLOCK; // 当前要操作的扇区内块号 (0-3)
extern unsigned char BLOCK_NUM; // 当前要操作的块的绝对地址 (0-63 for 1K)
extern unsigned char BLOCK_DATA[16]; // 用于暂存读/写块数据的16字节缓冲区
extern unsigned char KEY_A[16][6]; // 存储16个扇区的 Key A 密钥
extern unsigned char KEY_B[16][6]; // 存储16个扇区的 Key B 密钥
//==================================================================================
// 3. 函数原型声明
//==================================================================================
/** @brief MIFARE 卡事件处理流程 (示例函数) */
extern unsigned char MIFARE_CARD_EVENT(void);
/** @brief 清除芯片的 MIFARE 加密状态 */
extern void Mifare_Clear_Crypto(void);
/** @brief 加载6字节密钥到读卡器芯片内部的密钥缓冲器 */
unsigned char Mifare_LoadKey(unsigned char *mifare_key);
/** @brief **核心函数**: 对指定扇区进行密码认证 */
extern unsigned char Mifare_Auth(unsigned char key_mode, unsigned char sector, unsigned char *mifare_key, unsigned char *card_uid);
/** @brief 读取一个16字节的数据块 */
extern unsigned char Mifare_Blockread(unsigned char block, unsigned char *data_buff);
/** @brief 写入一个16字节的数据块 */
extern unsigned char Mifare_Blockwrite(unsigned char block, unsigned char *data_buff);
// --- 值块操作函数 (用于电子钱包等应用) ---
/** @brief 将一个块格式化为值块 */
extern unsigned char Mifare_Blockset(unsigned char block, unsigned char *data_buff);
/** @brief 对值块进行加值操作 */
extern unsigned char Mifare_Blockinc(unsigned char block, unsigned char *data_buff);
/** @brief 对值块进行减值操作 */
extern unsigned char Mifare_Blockdec(unsigned char block, unsigned char *data_buff);
/** @brief 将值块缓冲区的数据传送到数据块 */
extern unsigned char Mifare_Transfer(unsigned char block);
/** @brief 将数据块内容加载到值块缓冲区 */
extern unsigned char Mifare_Restore(unsigned char block);
#endif

View File

@ -0,0 +1,83 @@
/**
******************************************************************************
* @file board.h
* @author SRG
* @version V1.0.0
* @date 2020-03-17
* @brief
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 FudanMicroelectronics.
* All rights reserved.</center></h2>
*
******************************************************************************
*/
#ifndef __BOARD_H_
#define __BOARD_H_
#ifdef __cplusplus
extern "C" {
#endif
//#include "fm15l0xx.h"
//typedef enum
//{
// Mode_In_Up = 0, //<2F><><EFBFBD>٣<EFBFBD>pullup
// Mode_In_No, //<2F><><EFBFBD>٣<EFBFBD>nopull
// Mode_In_Down, //<2F><><EFBFBD>٣<EFBFBD>pulldown
// Mode_Out_Up, //<2F><><EFBFBD>٣<EFBFBD><D9A3><EFBFBD><EFBFBD>죬pullup
// Mode_Out_No, //<2F><><EFBFBD>٣<EFBFBD><D9A3><EFBFBD><EFBFBD>죬nopull
// Mode_Out_Down, //<2F><><EFBFBD>٣<EFBFBD><D9A3><EFBFBD><EFBFBD>죬pulldown
//} eGPIOMode;
//HMI LED
#define LED1_PIN LL_GPIO_Pin3 //PC3
#define LED2_PIN LL_GPIO_Pin4 //PC4
#define LED_GPIO GPIOC
#define LED1_On LL_GPIO_SetOutputPin( LED_GPIO, LED1_PIN )
#define LED1_Off LL_GPIO_ResetOutputPin( LED_GPIO, LED1_PIN )
#define LED2_On LL_GPIO_SetOutputPin( LED_GPIO, LED2_PIN )
#define LED2_Off LL_GPIO_ResetOutputPin( LED_GPIO, LED2_PIN )
#define TEST_ADC_CH LL_ADC_CHANNEL_1
uint8_t UserKey_GetData( void );
void GPIO_NVIC_Init( void );
void Set_Clk(unsigned char mode);
void SVD_Init( void );
void BSP_Init( void );
uint16_t Get_Adc_Average( uint32_t ch, uint32_t ch_in, uint8_t cnt );
void LowPower_test( void );
void MCU_EnterLowerPowerMode( void );
void Set_Output(unsigned char mode);
void Set_Pwm(unsigned char mode);
void Set_FM440_Power(unsigned char mode);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,10 @@
#include "main.h"
void bsp_init( void );
void gpio_init( void );
void uart_init( void );

View File

@ -0,0 +1,46 @@
/**
******************************************************************************
* @file Templates_LL/Inc/fm15l0xx_it.h
* @author FMSH AS Embedded Software Team
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __FM15L0XX_IT_H__
#define __FM15L0XX_IT_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
// #include "main.h"
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void NMI_Handler( void );
void HardFault_Handler( void );
void SVC_Handler( void );
void PendSV_Handler( void );
void SysTick_Handler( void );
#ifdef __cplusplus
}
#endif
#endif /* __FM15L0XX_IT_H__ */
/************************ (C) COPYRIGHT FMSH Microelectronics *****END OF FILE****/

View File

@ -0,0 +1,146 @@
/**
************************************************************************************************************
* @file : fm15l0xx_ll_rng.h
* @author : weifan
* @version : V1.0.0
* @date : 2020-12-15
* @brief :
************************************************************************************************************
* @attention :
*
* <h2><center>&copy; Copyright (c) 2020 FudanMicroelectronics.
* All rights reserved.</center></h2>
*
************************************************************************************************************
*/
#ifndef __FM15L0XX_LL_RNG_H__
#define __FM15L0XX_LL_RNG_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "fm15l0xx.h"
// ----------------------------------------------------------------------------------------------------
// @descrption : This Function Set RegBit 'RNG_CR_RNGEN' Value
// @arguments : *RNGx : Struct RNG_Typedef Pointer
// @return : None
// ----------------------------------------------------------------------------------------------------
__STATIC_INLINE void LL_RNG_Enable( void )
{
SET_BIT( RNG->CR, RNG_CR_RNGEN_MSK );
}
// ----------------------------------------------------------------------------------------------------
// @descrption : This Function Set RegBit 'RNG_CR_RNGEN' Value
// @arguments : *RNGx : Struct RNG_Typedef Pointer
// @return : None
// ----------------------------------------------------------------------------------------------------
__STATIC_INLINE void LL_RNG_Disable( void )
{
CLEAR_BIT( RNG->CR, RNG_CR_RNGEN_MSK );
}
// ----------------------------------------------------------------------------------------------------
// @descrption : This Function Get RegBit 'RNG_CR_RNGEN' Value
// @arguments : *RNGx : Struct RNG_Typedef Pointer
// @retrun : RNGEN : uint32_t, RNGEN
// ----------------------------------------------------------------------------------------------------
__STATIC_INLINE uint32_t LL_RNG_IsEnabled( void )
{
return ( (uint32_t) (READ_BIT( RNG->CR, RNG_CR_RNGEN_MSK ) == RNG_CR_RNGEN_MSK) );
}
// ----------------------------------------------------------------------------------------------------
// @descrption : This Function Set RegBit 'RNG_CR_SRCEN' Value
// @arguments : *RNGx : Struct RNG_Typedef Pointer
// @return : None
// ----------------------------------------------------------------------------------------------------
__STATIC_INLINE void LL_RNG_EnableNoiseSource( void )
{
SET_BIT( RNG->CR, RNG_CR_SRCEN_MSK );
}
// ----------------------------------------------------------------------------------------------------
// @descrption : This Function Set RegBit 'RNG_CR_SRCEN' Value
// @arguments : *RNGx : Struct RNG_Typedef Pointer
// @return : None
// ----------------------------------------------------------------------------------------------------
__STATIC_INLINE void LL_RNG_DisableNoiseSource( void )
{
CLEAR_BIT( RNG->CR, RNG_CR_SRCEN_MSK );
}
// ----------------------------------------------------------------------------------------------------
// @descrption : This Function Get RegBit 'RNG_CR_SRCEN' Value
// @arguments : *RNGx : Struct RNG_Typedef Pointer
// @retrun : SRCEN : uint32_t, SRCEN
// ----------------------------------------------------------------------------------------------------
__STATIC_INLINE uint32_t LL_RNG_IsEnabledNoiseSource( void )
{
return ( (uint32_t) (READ_BIT( RNG->CR, RNG_CR_SRCEN_MSK ) == RNG_CR_SRCEN_MSK) );
}
// ----------------------------------------------------------------------------------------------------
// @descrption : This Function Get RegBit 'RNG_SR_DRDY' Value
// @arguments : *RNGx : Struct RNG_Typedef Pointer
// @retrun : DRDY : uint32_t, DRDY
// ----------------------------------------------------------------------------------------------------
__STATIC_INLINE uint32_t LL_RNG_IsDataReady( void )
{
return ( (uint32_t) (READ_BIT( RNG->SR, RNG_SR_DRDY_MSK ) == RNG_SR_DRDY_MSK) );
}
// ----------------------------------------------------------------------------------------------------
// @descrption : This Function Set RegBit 'RNG_SR_SFAIL' Value
// @arguments : *RNGx : Struct RNG_Typedef Pointer
// SFAIL : uint32_t, SFAIL
// @return : None
// ----------------------------------------------------------------------------------------------------
__STATIC_INLINE void LL_RNG_ClearFlag_SFAIL( void )
{
RNG->SR = RNG_SR_SFAIL_MSK;
}
// ----------------------------------------------------------------------------------------------------
// @descrption : This Function Get RegBit 'RNG_SR_SFAIL' Value
// @arguments : *RNGx : Struct RNG_Typedef Pointer
// @retrun : SFAIL : uint32_t, SFAIL
// ----------------------------------------------------------------------------------------------------
__STATIC_INLINE uint32_t LL_RNG_IsActiveFlag_SFAIL( void )
{
return ( (uint32_t) (READ_BIT( RNG->SR, RNG_SR_SFAIL_MSK ) == RNG_SR_SFAIL_MSK) );
}
// ----------------------------------------------------------------------------------------------------
// @descrption : This Function Get RegBit 'RNG_DR_RNGOUT' Value
// @arguments : *RNGx : Struct RNG_Typedef Pointer
// @retrun : RNGOUT : uint32_t, RNGOUT
// ----------------------------------------------------------------------------------------------------
__STATIC_INLINE uint32_t LL_RNG_GetRandomData( void )
{
return ( (uint32_t) (READ_BIT( RNG->DR, RNG_DR_RNGOUT_MSK ) ) );
}
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // __FM15L0XX_LL_RNG_H__
/************************ (C) COPYRIGHT FudanMicroelectronics *****END OF FILE****/

View File

@ -0,0 +1,191 @@
/**
************************************* Copyright ******************************
* (C) Copyright 2019,TuYW,FMSH,China.
* All Rights Reserved
* By(Shanghai Fudan MicroeleCardTyperonics Group Company Limited)
* https://www.fmsh.com
*
* FileName : function.h
* Version : v1.0
* Author : TuYW
* Date : 2019-03-19
* Description:
*******************************************************************************/
#ifndef __FUNCTION_H_
#define __FUNCTION_H_
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdarg.h>
//#include "stdint.h"
/* Includes ------------------------------------------------------------------*/
// #include "fm15l0xx.h"
//#include "core_cm3.h"
//#include "sys.h"
//#if APP_NO_IAP == 1
// #define APP_ADDR 1
//#endif
/* Exported types ------------------------------------------------------------*/
#define REG32( addr ) (*( ( volatile unsigned long *) (addr) ) )
//#define assert_param(expr) ((void)0)
typedef unsigned char BOOLEAN;
typedef unsigned char INT8U; /* Unsigned 8 bit quantity */
typedef signed char INT8S; /* Signed 8 bit quantity */
typedef unsigned short INT16U; /* Unsigned 16 bit quantity */
typedef signed short INT16S; /* Signed 16 bit quantity */
typedef unsigned int INT32U; /* Unsigned 32 bit quantity */
typedef signed int INT32S; /* Signed 32 bit quantity */
typedef float FP32; /* Single precision floating point */
typedef double FP64; /* Double precision floating point */
/*********************************************************************************************************
ͨ<>ú궨<C3BA><EAB6A8>
*********************************************************************************************************/
#define PROGRAM_IAP_BASE FLASH_IAP_ADDR
#define PROGRAM_IAP_LENGTH 0X6000
#define PROGRAM_APP_BASE FLASH_APP1_ADDR
#define PROGRAM_APP_LENGTH 0X30000
#ifndef HIGH
#define HIGH 1
#endif
#ifndef LOW
#define LOW 0
#endif
#ifndef TRUE
#define TRUE 1
#endif //TRUE
#ifndef FALSE
#define FALSE 0
#endif //FALSE
#ifndef ON
#define ON 1
#endif //ON
#ifndef OFF
#define OFF 0
#endif //OFF
#ifndef NULL
#define NULL ( (void *) 0)
//<2F><>ַΪ0<CEAA><30>ָ<EFBFBD><D6B8>,void*<2A><><EFBFBD>͵<EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ת<EFBFBD><D7AA><EFBFBD><EFBFBD><EFBFBD>κ<EFBFBD><CEBA><EFBFBD><EFBFBD>͵<EFBFBD>ָ<EFBFBD><EFBFBD><EBA1A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵĿ<C7B5>ָ<EFBFBD><D6B8>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#endif
//<2F><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//#define ClrLongBuf(buf) memset(buf, 0x00, sizeof(buf));
/** The upper 8 bits of a 32 bit value */
//lint -emacro(572,MSB) // Suppress warning 572 "Excessive shift value"
#define MSB_32( a ) ( ( (a) & 0xFF000000) >> 24)
/** The lower 8 bits (of a 32 bit value) */
#define LSB_32( a ) ( (a) & 0x000000FF)
/** The upper 8 bits of a 16 bit value */
//lint -emacro(572,MSB_16) // Suppress warning 572 "Excessive shift value"
#define MSB_16( a ) ( ( (a) & 0xFF00) >> 8)
/** The lower 8 bits (of a 16 bit value) */
#define LSB_16( a ) ( (a) & 0x00FF)
///** Leaves the minimum of the two 32-bit arguments */
///*lint -emacro(506, MIN) */ /* Suppress "Constant value Boolean */
//#define MIN( a, b ) ( (a) < (b) ? (a) : (b) )
///** Leaves the maximum of the two 32-bit arguments */
///*lint -emacro(506, MAX) */ /* Suppress "Constant value Boolean */
//#define MAX( a, b ) ( (a) < (b) ? (b) : (a) )
/** Concatenates two parameters. Useful as a second level of indirection,
* when a parameter can be macro itself. */
#define CONCAT_2( p1, p2 ) p1 ## p2
/** Concatenates three parameters. Useful as a second level of indirection,
* when a parameter can be macro itself. */
#define CONCAT_3( p1, p2, p3 ) p1 ## p2 ## p3
/**@brief Set a bit in the uint32 word.
*
* @param[in] W Word whose bit is being set.
* @param[in] B Bit number in the word to be set.
*/
#ifndef SET_BIT
#define SET_BIT( W, B ) ( (W) |= (uint32_t) (1U << (B) ) )
#endif
/**@brief Clears a bit in the uint32 word.
*
* @param[in] W Word whose bit is to be cleared.
* @param[in] B Bit number in the word to be cleared.
*/
#ifndef SET_BIT
#define CLR_BIT( W, B ) ( (W) &= (~( (uint32_t) 1 << (B) ) ) )
#endif
//typedef unsigned char BOOLEAN;
typedef unsigned char UINT8, U8, BYTE, u8, uint8_t;
typedef unsigned short UINT16, U16, u16, uint16_t;
typedef unsigned int UINT32, U32, DWORD, u32, uint32_t;
//typedef int32_t s32;
//typedef int16_t s16;
//typedef int8_t s8;
//typedef const int32_t sc32; /*!< Read Only */
//typedef const int16_t sc16; /*!< Read Only */
//typedef const int8_t sc8; /*!< Read Only */
//typedef __IO int32_t vs32;
//typedef __IO int16_t vs16;
//typedef __IO int8_t vs8;
//typedef __I int32_t vsc32; /*!< Read Only */
//typedef __I int16_t vsc16; /*!< Read Only */
//typedef __I int8_t vsc8; /*!< Read Only */
//typedef uint32_t u32;
//typedef uint16_t u16;
//typedef uint8_t u8;
//typedef const uint32_t uc32; /*!< Read Only */
//typedef const uint16_t uc16; /*!< Read Only */
//typedef const uint8_t uc8; /*!< Read Only */
//typedef __IO uint32_t vu32;
//typedef __IO uint16_t vu16;
//typedef __IO uint8_t vu8;
//typedef __I uint32_t vuc32; /*!< Read Only */
//typedef __I uint16_t vuc16; /*!< Read Only */
//typedef __I uint8_t vuc8; /*!< Read Only */
typedef void (*pFunction)( void );
void StrToHex( BYTE *pbDest, BYTE *pbSrc, int nLen );
void HexToStr( BYTE *pbDest, BYTE *pbSrc, int nLen );
#endif

View File

@ -0,0 +1,64 @@
/**
******************************************************************************
* @file Templates_LL/Inc/main.h
* @author FMSH AS Embedded Software Team
* @brief Header for main.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT(c) 2016 FMSH Microelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of FMSH Microelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H__
#define __MAIN_H__
/* Includes ------------------------------------------------------------------*/
/* LL drivers common to all LL examples */
//#include "fm15l0xx_ll_cmu.h"
/* LL drivers specific to LL examples IPs */
//#include "fm15l0xx_ll_gpio.h"
//#include "fm15l0xx_ll_uart.h"
//#if defined(USE_FULL_ASSERT)
// #include "fm15l0xx_assert.h"
//#endif /* USE_FULL_ASSERT */
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* ============== BOARD SPECIFIC CONFIGURATION CODE BEGIN ============== */
/* ============== BOARD SPECIFIC CONFIGURATION CODE END ============== */
/* Exported macro ------------------------------------------------------------*/
#define UARTx UART0
/* Exported functions ------------------------------------------------------- */
int vdd_is_low( void );
#endif /* __MAIN_H__ */
/************************ (C) COPYRIGHT FMSH Microelectronics *****END OF FILE****/

View File

@ -0,0 +1,11 @@
#ifndef __PRINT_H_
#define __PRINT_H_
extern unsigned char lsfr[48];
extern unsigned char lsfr_length;
extern unsigned char ciphertext_to_binary[48];
extern void Print_AUTH(unsigned char *key,unsigned char *TOKEN,unsigned char *rece_buff);//print <20><>֤
extern void lsfr_init(unsigned char *S022_Token2);
extern unsigned char lsfr_fm458(void);
extern unsigned char PRINT_Calc_sendData(unsigned char *data_buf, unsigned char data_len);
extern unsigned char PRINT_Calc_recvData(unsigned char *data_buf, unsigned char data_len);
#endif

View File

@ -0,0 +1,7 @@
#include "main.h"
void RNG_init( void );
uint32_t Get_RandomNumber( void );

View File

@ -0,0 +1,55 @@
#define uchar unsigned char
#define uint unsigned int
//typedef unsigned char u8;
//typedef unsigned int u16;
//typedef unsigned long u32;
#define BIT5 0x00000020U
#define BIT6 0x00000040U
#define BIT7 0x00000080U
#define BIT0 0x00000001U
#define BIT1 0x00000002U
#define BIT2 0x00000004U
#define BIT3 0x00000008U
#define BIT4 0x00000010U
#define BIT5 0x00000020U
void Uart1Send(unsigned char dat);
void Uart1SendString(unsigned char *str);
void printHex(unsigned char num);
typedef enum {
FAIL = 0U,
SUCCESS = !FAIL
} ErrorStatus;
typedef enum {
DISABLE = 0U,
ENABLE = !DISABLE
} FunState;
typedef enum {
RESET = 0U,
SET = !RESET
} FlagStatus, ITStatus;
typedef struct
{
unsigned char SendLength;
unsigned char *pSendBuffer;
unsigned char ReceiveLength;
unsigned char *pReceiveBuffer;
unsigned int Timeout;
}transmission_struct;
unsigned char GetReg(unsigned char address,unsigned char *reg_data);
unsigned char SetReg(unsigned char address, unsigned char reg_data);
void Delay1ms();

View File

@ -57,14 +57,14 @@ const struct task_info task_info_table[] = {
#else
{"btstack", 3, 0, 768, 256 },
#endif
{"audio_dec", 5, 0, 800, 128 },
{"aud_effect", 5, 1, 800, 128 },
// {"audio_dec", 5, 0, 800, 128 },
// {"aud_effect", 5, 1, 800, 128 },
/*
*为了防止dac buf太大通话一开始一直解码
*导致编码输入数据需要很大的缓存,这里提高编码的优先级
*/
{"audio_enc", 6, 0, 768, 128 },
{"aec", 2, 1, 768, 128 },
// {"audio_enc", 6, 0, 768, 128 },
// {"aec", 2, 1, 768, 128 },
#if TCFG_AUDIO_HEARING_AID_ENABLE
{"HearingAid", 6, 0, 768, 128 },
#endif/*TCFG_AUDIO_HEARING_AID_ENABLE*/
@ -86,9 +86,9 @@ const struct task_info task_info_table[] = {
{"tws_ota_msg", 2, 0, 256, 128 },
{"dw_update", 2, 0, 256, 128 },
{"rcsp_task", 2, 0, 640, 128 },
{"aud_capture", 4, 0, 512, 256 },
{"data_export", 5, 0, 512, 256 },
{"anc", 3, 1, 512, 128 },
// {"aud_capture", 4, 0, 512, 256 },
// {"data_export", 5, 0, 512, 256 },
// {"anc", 3, 1, 512, 128 },
#endif
#if TCFG_GX8002_NPU_ENABLE
@ -102,9 +102,9 @@ const struct task_info task_info_table[] = {
#if TCFG_KWS_VOICE_RECOGNITION_ENABLE
{"kws", 2, 0, 256, 64 },
#endif /* #if TCFG_KWS_VOICE_RECOGNITION_ENABLE */
{"usb_msd", 1, 0, 512, 128 },
// {"usb_msd", 1, 0, 512, 128 },
#if !TCFG_USB_MIC_CVP_ENABLE
{"usbmic_write", 2, 0, 256, 128 },
// {"usbmic_write", 2, 0, 256, 128 },
#endif
#if AI_APP_PROTOCOL
{"app_proto", 2, 0, 768, 64 },
@ -112,12 +112,12 @@ const struct task_info task_info_table[] = {
#if (TCFG_SPI_LCD_ENABLE||TCFG_SIMPLE_LCD_ENABLE)
{"ui", 2, 0, 768, 256 },
#else
{"ui", 3, 0, 384 - 64, 128 },
// {"ui", 3, 0, 384 - 64, 128 },
#endif
#if (TCFG_DEV_MANAGER_ENABLE)
{"dev_mg", 3, 0, 512, 512 },
#endif
{"audio_vad", 1, 1, 512, 128 },
// {"audio_vad", 1, 1, 512, 128 },
#if TCFG_KEY_TONE_EN
{"key_tone", 5, 0, 256, 32 },
#endif
@ -137,7 +137,7 @@ const struct task_info task_info_table[] = {
{"icsd_src", 2, 1, 512, 128 },
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
{"pmu_task", 6, 0, 256, 128 },
{"WindDetect", 2, 0, 256, 128 },
// {"WindDetect", 2, 0, 256, 128 },
{0, 0},
};

View File

@ -249,7 +249,7 @@ const struct vad_mic_platform_data vad_mic_data = {
.mic_ldo2PAD_en = 1,
.mic_bias_en = 0,
.mic_bias_res = 0,
.mic_bias_inside = TCFG_AUDIO_MIC0_BIAS_EN,
// .mic_bias_inside = TCFG_AUDIO_MIC0_BIAS_EN,
/* ADC偏置电阻配置*/
.adc_rbs = 3,
/* ADC输入电阻配置*/
@ -520,11 +520,13 @@ const struct hw_iic_config hw_iic_cfg[] = {
{IO_PORTC_02, IO_PORTC_03}, //group c
{IO_PORTA_05, IO_PORTA_06}, //group d
*/
.port = TCFG_HW_I2C0_PORTS,
// .port = TCFG_HW_I2C0_PORTS,
// .port = {IO_PORTC_04,IO_PORTC_05}, // portB: scl、sda
.port = {IO_PORTB_04,IO_PORTB_05}, // portA: scl、sda
.baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率
.hdrive = 0, //是否打开IO口强驱
.io_filter = 1, //是否打开滤波器(去纹波)
.io_pu = 1, //是否打开上拉电阻如果外部电路没有焊接上拉电阻需要置1
.io_pu = 0, //是否打开上拉电阻如果外部电路没有焊接上拉电阻需要置1
},
};

View File

@ -22,35 +22,39 @@
// UART配置 //
//*********************************************************************************//
#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能
// #define TCFG_UART0_ENABLE 0 //串口打印模块使能
#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置用于打印可以选择NO_CONFIG_PORT
#define TCFG_UART0_TX_PORT IO_PORT_DP //串口发送脚配置
#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置
// #define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置
#define TCFG_UART0_BAUDRATE 115200 //串口波特率配置
//*********************************************************************************//
// IIC配置 //
//*********************************************************************************//
/*软件IIC设置*/ //xtell
#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_05 //软件IIC CLK脚选择 XTELL
#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_06 //软件IIC DAT脚选择
#define TCFG_SW_I2C0_DELAY_CNT 10 //IIC延时参数影响通讯时钟频率
#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_05//IO_PORTB_04 //软件IIC CLK脚选择 XTELL
#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_06//IO_PORTB_05 //软件IIC DAT脚选择
#define TCFG_SW_I2C0_DELAY_CNT 0 //IIC延时参数影响通讯时钟频率
/*硬件IIC端口选择
/*硬件IIC端口选择 -- 具体看手册,这里写的不准 -- lmx
SCL SDA
'A': IO_PORT_DP IO_PORT_DM
'B': IO_PORTA_09 IO_PORTA_10
'C': IO_PORTA_07 IO_PORTA_08
'D': IO_PORTA_05 IO_PORTA_06
具体要选择哪个iic口去board_jl701n_demo.c中设置hw_iic_cfg
*/
#define TCFG_HW_I2C0_PORTS 'B'
#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率
#define TCFG_HW_I2C0_CLK 100000
//*********************************************************************************//
// 硬件SPI 配置 //
//*********************************************************************************//
#define TCFG_HW_SPI1_ENABLE 1
#define TCFG_HW_SPI1_PORT_CLK 0//IO_PORTC_04//IO_PORTA_00 xtellio
#define TCFG_HW_SPI1_PORT_DO IO_PORTC_05//IO_PORTA_01
#define TCFG_HW_SPI1_PORT_DI 0//IO_PORTC_03//IO_PORTA_02 xtellio
#define TCFG_HW_SPI1_PORT_CLK NO_CONFIG_PORT//IO_PORTC_04//IO_PORTC_04//IO_PORTA_00 xtellio
#define TCFG_HW_SPI1_PORT_DO NO_CONFIG_PORT//IO_PORTC_05//IO_PORTA_01
#define TCFG_HW_SPI1_PORT_DI NO_CONFIG_PORT//IO_PORTC_03//IO_PORTC_03//IO_PORTA_02 xtellio
#define TCFG_HW_SPI1_BAUD 2400000L
#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT
#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER
@ -82,7 +86,7 @@
//*********************************************************************************//
// USB 配置 //
//*********************************************************************************//
#define TCFG_PC_ENABLE 1//DISABLE_THIS_MOUDLE//PC模块使能
#define TCFG_PC_ENABLE DISABLE_THIS_MOUDLE//PC模块使能
#define TCFG_UDISK_ENABLE 0//ENABLE_THIS_MOUDLE//U盘模块使能
#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1)
@ -101,7 +105,7 @@
#define MULT_KEY_ENABLE 1//DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表
#define TCFG_KEY_TONE_EN ENABLE//DISABLE xtell // 按键提示音。
#define TCFG_KEY_TONE_EN DISABLE//DISABLE xtell // 按键提示音。
//*********************************************************************************//
// iokey 配置 //
@ -724,9 +728,9 @@ DAC硬件上的连接方式,可选的配置:
// 充电舱/蓝牙测试盒/ANC测试三者为同级关系,开启任一功能都会初始化PP0通信接口 //
//*********************************************************************************//
#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充电舱
#define TCFG_TEST_BOX_ENABLE ENABLE_THIS_MOUDLE //是否支持蓝牙测试盒
#define TCFG_TEST_BOX_ENABLE DISABLE_THIS_MOUDLE //是否支持蓝牙测试盒 //xtell
#define TCFG_ANC_BOX_ENABLE CONFIG_ANC_ENABLE //是否支持ANC测试盒
#define TCFG_UMIDIGI_BOX_ENABLE ENABLE_THIS_MOUDLE //是否支持UMIDIGI充电舱
#define TCFG_UMIDIGI_BOX_ENABLE DISABLE_THIS_MOUDLE //是否支持UMIDIGI充电舱 //xtell
#if TCFG_UMIDIGI_BOX_ENABLE
#define _20MS_BIT 20 //传输20ms/Bit时使用
#define _40MS_BIT 40 //传输40ms/Bit时使用
@ -802,7 +806,7 @@ DAC硬件上的连接方式,可选的配置:
// EQ配置 //
//*********************************************************************************//
//EQ配置使用在线EQ时EQ文件和EQ模式无效。有EQ文件时使能TCFG_USE_EQ_FILE,默认不用EQ模式切换功能
#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能
#define TCFG_EQ_ENABLE 0 //支持EQ功能,EQ总使能
// #if TCFG_EQ_ENABLE
#define TCFG_EQ_ONLINE_ENABLE 0 //支持在线EQ调试,如果使用蓝牙串口调试,需要打开宏 APP_ONLINE_DEBUG否则默认使用uart调试(二选一)
#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ
@ -1005,7 +1009,7 @@ DAC硬件上的连接方式,可选的配置:
//*********************************************************************************//
#define TCFG_USER_TWS_ENABLE 0 //tws功能使能
#define TCFG_USER_BLE_ENABLE 1 //BLE功能使能
#define TCFG_BT_SUPPORT_AAC 1 //AAC格式支持
#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持
#define TCFG_BT_SUPPORT_LDAC 0 //LDAC格式支持
#if TCFG_BT_SUPPORT_LDAC
@ -1079,7 +1083,7 @@ DAC硬件上的连接方式,可选的配置:
// 编解码格式配置(CodecFormat) //
//*********************************************************************************//
/*解码格式使能*/
#define TCFG_DEC_MP3_ENABLE ENABLE
#define TCFG_DEC_MP3_ENABLE DISABLE
#define TCFG_DEC_WTGV2_ENABLE ENABLE
#define TCFG_DEC_G729_ENABLE DISABLE
#define TCFG_DEC_WMA_ENABLE DISABLE

View File

@ -8,8 +8,8 @@
/* Following Macros Affect Periods Of Both Code Compiling And Post-build */
#define CONFIG_DOUBLE_BANK_ENABLE 0 //单双备份选择(若打开了改宏,FLASH结构变为双备份结构适用于接入第三方协议的OTA PS: JL-OTA同样支持双备份升级, 需要根据实际FLASH大小同时配置CONFIG_FLASH_SIZE)
#define CONFIG_APP_OTA_ENABLE 0 //是否支持RCSP升级(JL-OTA)
#define CONFIG_DOUBLE_BANK_ENABLE 1 //单双备份选择(若打开了改宏,FLASH结构变为双备份结构适用于接入第三方协议的OTA PS: JL-OTA同样支持双备份升级, 需要根据实际FLASH大小同时配置CONFIG_FLASH_SIZE)
#define CONFIG_APP_OTA_ENABLE 1 //是否支持RCSP升级(JL-OTA)
#define CONFIG_UPDATE_JUMP_TO_MASK 0 //配置升级到loader的方式0为直接reset,1为跳转(适用于芯片电源由IO口KEEP住的方案,需要注意检查跳转前是否将使用DMA的硬件模块全部关闭)
@ -33,7 +33,7 @@
/* Following Macros Only For Post Bulid Configuaration */
#define CONFIG_DB_UPDATE_DATA_GENERATE_EN 0 //是否生成db_data.bin(用于第三方协议接入使用)
#define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 0 //ufw只生成1份4K对齐的代码
#define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 1 //ufw只生成1份4K对齐的代码
//config for supported chip version
#ifdef CONFIG_BR30_C_VERSION

View File

@ -70,6 +70,7 @@
#include "bt_background.h"
#include "default_event_handler.h"
#define xlog(format, ...) printf("[%s] " format, __func__, ##__VA_ARGS__)
@ -2790,3 +2791,4 @@ static int state_machine(struct application *app, enum app_state state, struct i
// .ops = &app_earphone_ops,
// .state = APP_STA_DESTROY,
// };

View File

@ -14,7 +14,7 @@
//#define CONFIG_DEBUG_LITE_ENABLE //轻量级打印开关, 默认关闭
#endif
#define BLE_WIRELESS_CLIENT_EN 1 //开启则作为主设备lmx
//*********************************************************************************//
// AI配置 //
//*********************************************************************************//
@ -23,12 +23,16 @@
#ifdef CONFIG_APP_BT_ENABLE
#define TRANS_DATA_EN 0
#define RCSP_BTMATE_EN 0
#define RCSP_ADV_EN 1
#if BLE_WIRELESS_CLIENT_EN == 0
#define RCSP_ADV_EN 1 // lmx打开这个则作为ble从设备
#else
#define RCSP_ADV_EN 0
#endif
#define AI_APP_PROTOCOL 0
#define LL_SYNC_EN 0
#define TUYA_DEMO_EN 0
#else
#define TRANS_DATA_EN 1
#define TRANS_DATA_EN 0
#define RCSP_BTMATE_EN 0
#define RCSP_ADV_EN 0
#define AI_APP_PROTOCOL 0
@ -65,11 +69,11 @@
#if CONFIG_APP_OTA_ENABLE
#define RCSP_UPDATE_EN 1 //是否支持rcsp升级
#if CONFIG_DOUBLE_BANK_ENABLE //双备份才能打开同步升级流程
#define OTA_TWS_SAME_TIME_ENABLE 1 //是否支持TWS同步升级
#define OTA_TWS_SAME_TIME_NEW 1 //使用新的tws ota流程
#define OTA_TWS_SAME_TIME_ENABLE 0 //是否支持TWS同步升级
#define OTA_TWS_SAME_TIME_NEW 0 //使用新的tws ota流程
#else
#define OTA_TWS_SAME_TIME_ENABLE 1//0 xtellota //是否支持TWS同步升级
#define OTA_TWS_SAME_TIME_NEW 1//0 //使用新的tws ota流程
#define OTA_TWS_SAME_TIME_ENABLE 0 //xtell: 关闭TWS同步升级允许单耳升级
#define OTA_TWS_SAME_TIME_NEW 0 //xtell: 关闭TWS同步升级此选项也应关闭
#endif //CONFIG_DOUBLE_BANK_ENABLE
#else
#define RCSP_UPDATE_EN 0 //是否支持rcsp升级

View File

@ -204,31 +204,31 @@ int app_protocol_sys_event_handler(struct sys_event *event);
#define EARPHONE_STATE_SNIFF(a)
#define EARPHONE_STATE_ROLE_SWITCH(a)
#else
int adv_earphone_state_init();
int adv_earphone_state_set_page_scan_enable();
int adv_earphone_state_get_connect_mac_addr();
int adv_earphone_state_cancel_page_scan();
int adv_earphone_state_enter_soft_poweroff();
int adv_earphone_state_tws_init(int paired);
int adv_earphone_state_tws_connected(int first_pair, u8 *comm_addr);
int adv_sys_event_handler_specific(struct sys_event *event);
int adv_earphone_state_sniff(u8 state);
int adv_earphone_state_role_switch(u8 role);
// #else
// int adv_earphone_state_init();
// int adv_earphone_state_set_page_scan_enable();
// int adv_earphone_state_get_connect_mac_addr();
// int adv_earphone_state_cancel_page_scan();
// int adv_earphone_state_enter_soft_poweroff();
// int adv_earphone_state_tws_init(int paired);
// int adv_earphone_state_tws_connected(int first_pair, u8 *comm_addr);
// int adv_sys_event_handler_specific(struct sys_event *event);
// int adv_earphone_state_sniff(u8 state);
// int adv_earphone_state_role_switch(u8 role);
#define EARPHONE_STATE_INIT() adv_earphone_state_init()
#define EARPHONE_STATE_SET_PAGE_SCAN_ENABLE() adv_earphone_state_set_page_scan_enable()
#define EARPHONE_STATE_GET_CONNECT_MAC_ADDR() adv_earphone_state_get_connect_mac_addr()
#define EARPHONE_STATE_CANCEL_PAGE_SCAN() adv_earphone_state_cancel_page_scan()
#define EARPHONE_STATE_ENTER_SOFT_POWEROFF() adv_earphone_state_enter_soft_poweroff()
#define EARPHONE_STATE_TWS_INIT(a) adv_earphone_state_tws_init(a)
#define EARPHONE_STATE_TWS_CONNECTED(a, b) adv_earphone_state_tws_connected(a,b)
#define SYS_EVENT_HANDLER_SPECIFIC(a) adv_sys_event_handler_specific(a)
#define SYS_EVENT_REMAP(a) 0
#define EARPHONE_STATE_SNIFF(a) adv_earphone_state_sniff(a)
#define EARPHONE_STATE_ROLE_SWITCH(a) adv_earphone_state_role_switch(a)
// #define EARPHONE_STATE_INIT() adv_earphone_state_init()
// #define EARPHONE_STATE_SET_PAGE_SCAN_ENABLE() adv_earphone_state_set_page_scan_enable()
// #define EARPHONE_STATE_GET_CONNECT_MAC_ADDR() adv_earphone_state_get_connect_mac_addr()
// #define EARPHONE_STATE_CANCEL_PAGE_SCAN() adv_earphone_state_cancel_page_scan()
// #define EARPHONE_STATE_ENTER_SOFT_POWEROFF() adv_earphone_state_enter_soft_poweroff()
// #define EARPHONE_STATE_TWS_INIT(a) adv_earphone_state_tws_init(a)
// #define EARPHONE_STATE_TWS_CONNECTED(a, b) adv_earphone_state_tws_connected(a,b)
// #define SYS_EVENT_HANDLER_SPECIFIC(a) adv_sys_event_handler_specific(a)
// #define SYS_EVENT_REMAP(a) 0
// #define EARPHONE_STATE_SNIFF(a) adv_earphone_state_sniff(a)
// #define EARPHONE_STATE_ROLE_SWITCH(a) adv_earphone_state_role_switch(a)
#endif
// #endif
#else
@ -246,6 +246,7 @@ int adv_earphone_state_role_switch(u8 role);
#define EARPHONE_STATE_ROLE_SWITCH(a)
#endif
#endif

View File

@ -231,6 +231,7 @@ const int config_btctler_le_roles = (LE_ADV | LE_SLAVE);
const uint64_t config_btctler_le_features = LE_ENCRYPTION;
#else
const int config_btctler_le_roles = (LE_ADV | LE_SLAVE);
const uint64_t config_btctler_le_features = 0;
#endif

View File

@ -202,7 +202,9 @@ void cfg_file_parse(u8 idx)
log_info("read bt name err");
} else if (ret >= LOCAL_NAME_LEN) {
memset(bt_cfg.edr_name, 0x00, LOCAL_NAME_LEN);
memcpy(bt_cfg.edr_name, tmp, LOCAL_NAME_LEN);
// memcpy(bt_cfg.edr_name, tmp, LOCAL_NAME_LEN);
// extern char xt_ble_new_name[9];
// memcpy(bt_cfg.edr_name, xt_ble_new_name, LOCAL_NAME_LEN);
bt_cfg.edr_name[LOCAL_NAME_LEN - 1] = 0;
} else {
memset(bt_cfg.edr_name, 0x00, LOCAL_NAME_LEN);

View File

@ -1,117 +0,0 @@
#include "circle_buffer.h"
#include <string.h>
//////////////////////////////////////////////////////////////////////////////////////////////////
//START -- 宏定义
#define ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if ENABLE_XLOG
#define xlog(format, ...) printf("[%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
//END -- 宏定义
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//START -- 变量定义
//END -- 变量定义
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//START -- 函数定义
//END -- 函数定义
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//实现
// 初始化环形缓冲区
void circle_buffer_init(circle_buffer_t *cb, u8 *buffer, u16 capacity) {
cb->buffer = buffer;
cb->capacity = capacity;
cb->head = 0;
cb->tail = 0;
cb->size = 0;
}
// 向环形缓冲区写入数据
u16 circle_buffer_write(circle_buffer_t *cb, const u8 *data, u16 length) {
if (length > circle_buffer_get_free_space(cb)) {
// 如果剩余空间不足,则只写入能放下的部分
length = circle_buffer_get_free_space(cb);
}
if (length == 0) {
return 0;
}
// 检查是否需要回环
if (cb->head + length > cb->capacity) {
u16 part1_len = cb->capacity - cb->head;
u16 part2_len = length - part1_len;
memcpy(cb->buffer + cb->head, data, part1_len);
memcpy(cb->buffer, data + part1_len, part2_len);
cb->head = part2_len;
} else {
memcpy(cb->buffer + cb->head, data, length);
cb->head += length;
if (cb->head == cb->capacity) {
cb->head = 0;
}
}
cb->size += length;
return length;
}
// 从环形缓冲区读取数据
u16 circle_buffer_read(circle_buffer_t *cb, u8 *data, u16 length) {
if (length > cb->size) {
// 如果要读取的长度超过了已有的数据,则只读取已有的部分
length = cb->size;
}
if (length == 0) {
return 0;
}
// 检查是否需要回环
if (cb->tail + length > cb->capacity) {
u16 part1_len = cb->capacity - cb->tail;
u16 part2_len = length - part1_len;
memcpy(data, cb->buffer + cb->tail, part1_len);
memcpy(data + part1_len, cb->buffer, part2_len);
cb->tail = part2_len;
} else {
memcpy(data, cb->buffer + cb->tail, length);
cb->tail += length;
if (cb->tail == cb->capacity) {
cb->tail = 0;
}
}
cb->size -= length;
return length;
}
// 获取已用空间的大小
u16 circle_buffer_get_size(circle_buffer_t *cb) {
return cb->size;
}
// 获取剩余空间的大小
u16 circle_buffer_get_free_space(circle_buffer_t *cb) {
return cb->capacity - cb->size;
}

View File

@ -1,55 +0,0 @@
#ifndef CIRCLE_BUFFER_H
#define CIRCLE_BUFFER_H
#include "system/includes.h"
// 定义环形缓冲区的结构体
typedef struct {
u8 *buffer; // 缓冲区指针
u16 capacity; // 缓冲区总容量
u16 head; // 头部指针(写入位置)
u16 tail; // 尾部指针(读取位置)
u16 size; // 当前已用大小
} circle_buffer_t;
/**
* @brief 初始化环形缓冲区
* @param cb 指向环形缓冲区结构体的指针
* @param buffer 外部提供的缓冲区内存
* @param capacity 缓冲区的总容量
*/
void circle_buffer_init(circle_buffer_t *cb, u8 *buffer, u16 capacity);
/**
* @brief 向环形缓冲区写入数据
* @param cb 指向环形缓冲区结构体的指针
* @param data 要写入的数据的指针
* @param length 要写入的数据的长度
* @return 实际写入的字节数
*/
u16 circle_buffer_write(circle_buffer_t *cb, const u8 *data, u16 length);
/**
* @brief 从环形缓冲区读取数据
* @param cb 指向环形缓冲区结构体的指针
* @param data 用于存放读取数据的缓冲区的指针
* @param length 想要读取的数据的长度
* @return 实际读取的字节数
*/
u16 circle_buffer_read(circle_buffer_t *cb, u8 *data, u16 length);
/**
* @brief 获取环形缓冲区中已用空间的大小
* @param cb 指向环形缓冲区结构体的指针
* @return 已用空间的大小
*/
u16 circle_buffer_get_size(circle_buffer_t *cb);
/**
* @brief 获取环形缓冲区中剩余空间的大小
* @param cb 指向环形缓冲区结构体的指针
* @return 剩余空间的大小
*/
u16 circle_buffer_get_free_space(circle_buffer_t *cb);
#endif // CIRCLE_BUFFER_H

View File

@ -1,126 +0,0 @@
#include "system/includes.h"
#include "btstack/btstack_task.h"
#include "app_config.h"
#include "app_action.h"
#include "asm/pwm_led.h"
#include "tone_player.h"
#include "ui_manage.h"
#include "gpio.h"
#include "app_main.h"
#include "asm/charge.h"
#include "update.h"
#include "app_power_manage.h"
#include "audio_config.h"
#include "app_charge.h"
#include "bt_profile_cfg.h"
#include "dev_manager/dev_manager.h"
#include "update_loader_download.h"
#include "LIS2DH12.h"
#include "circle_buffer.h"
#include "circle_buffer.h"
#include "btstack/avctp_user.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
//宏定义
#define ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if ENABLE_XLOG
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
//
///////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//START -- 函数定义
void send_data_to_ble_client(const u8* data, u16 length);
//END -- 函数定义
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//START -- 变量定义
// --- 任务ID ---
static u16 xtell_i2c_test_id;
static u16 collect_data_id;
static u16 send_data_id;
// --- 环形缓冲区 ---
#define SENSOR_DATA_BUFFER_SIZE 512
static u8 sensor_data_buffer[SENSOR_DATA_BUFFER_SIZE];
static circle_buffer_t sensor_cb;
//END -- 变量定义
//////////////////////////////////////////////////////////////////////////////////////////////////
// 采集传感器数据并存入环形缓冲区的任务
void collect_and_buffer_sensor_data_task(void) {
motion_data_t current_motion;
axis_info_xtell total_accel;
axis_info_xtell linear_accel;
char data_string[256];
// 从驱动获取最新的运动数据
get_motion_data(&current_motion);
total_accel = get_current_accel_mss();
linear_accel = get_linear_accel_mss();
// 将浮点数据转换为整数乘以100以保留两位小数进行格式化
int len = snprintf(data_string, sizeof(data_string),
"T:%d,%d,%d;L:%d,%d,%d;V:%d,%d,%d;D:%d,%d,%d\n",
(int)(total_accel.x * 100), (int)(total_accel.y * 100), (int)(total_accel.z * 100),
(int)(linear_accel.x * 100), (int)(linear_accel.y * 100), (int)(linear_accel.z * 100),
(int)(current_motion.velocity.x * 100), (int)(current_motion.velocity.y * 100), (int)(current_motion.velocity.z * 100),
(int)(current_motion.distance.x * 100), (int)(current_motion.distance.y * 100), (int)(current_motion.distance.z * 100));
// 写入环形缓冲区
u16 written = circle_buffer_write(&sensor_cb, (u8*)data_string, len);
if (written < len) {
xlog("The circular buffer is full!\n");
}
}
// 从环形缓冲区读取数据并发送
void send_sensor_data_task(void) {
//查询开关机状态
u8 temp[5]={0xBB,0xBE,0x02,0x00,0x00};
printf("xtell_ble_send\n");
send_data_to_ble_client(&temp,5);
}
extern void create_process(u16* pid, const char* name, void *priv, void (*func)(void *priv), u32 msec);
void rcsp_adv_fill_mac_addr(u8 *mac_addr_buf) //by xtell
{
swapX(bt_get_mac_addr(), mac_addr_buf, 6);
}
void xtell_task_create(void){
xlog("xtell_task_create\n");
//开经典蓝牙
// user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_ENABLE, 0, NULL); //打开蓝牙可发现,已连接时不能操作
// delay_2ms(50);
// user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); //打开蓝牙可连接
// delay_2ms(50);
// connect_last_device_from_vm(); //自动回连上一个设备
// 初始化环形缓冲区
circle_buffer_init(&sensor_cb, sensor_data_buffer, SENSOR_DATA_BUFFER_SIZE);
// 创建一个定时器每200ms调用一次核心计算任务
create_process(&xtell_i2c_test_id, "xtell_i2c_test", NULL, xtell_i2c_test, (u32)(SAMPLING_PERIOD_S * 1000));
// 创建一个定时器每1000ms采集一次数据
create_process(&collect_data_id, "collect_data", NULL, collect_and_buffer_sensor_data_task, 1000);
// 创建一个定时器每200ms尝试发送一次数据
create_process(&send_data_id, "send_data", NULL, send_sensor_data_task, 200);
}

View File

@ -1,283 +0,0 @@
// LIS2DH12驱动 - 由Kilo Code注释
#include "gSensor/gSensor_manage.h"
#include "app_config.h"
#include "math.h"
#include "LIS2DH12.h"
#include "colorful_lights/colorful_lights.h"
#include <string.h> // 用于 memcpy
//////////////////////////////////////////////////////////////////////////////////////////////////
//START -- 宏定义
#define ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if ENABLE_XLOG
#define xlog(format, ...) printf("[%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
// --- 运动检测核心参数 ---
#define SAMPLE_COUNT 6 // 定义静止状态检测所需的样本数量
#define THRESHOLD 50.00f // 定义静止状态检测的阈值(三轴数据方差),值越大,对微小抖动的容忍度越高
#define LPF_ALPHA 0.95f // 低通滤波系数越接近1滤波效果越强重力估算越平滑
#define DEADZONE_MSS 0.2f // 加速度死区阈值 (m/s^2),低于此值的线性加速度被视为噪声并忽略
// --- 原有业务逻辑宏定义 ---
#define STATIC_MAX_TIME 60*5*5 // 传感器静止最大时间,单位 200ms
#define DORMANCY_MAX_TIME 60*5 // 休眠检测时间,单位 200ms
// --- I2C地址定义 ---
#define LIS2DH12_W_ADDR 0x32
#define LIS2DH12_R_ADDR 0x33
// --- IIC 寄存器地址宏定义 ---
#define LIS2DH12_WHO_AM_I 0x0F
#define LIS2DH12_CTRL_REG1 0x20
#define LIS2DH12_CTRL_REG4 0x23
#define LIS2DH12_CTRL_REG5 0x24
#define LIS2DH12_OUT_X_L 0x28
#define LIS2DH12_FIFO_CTRL_REG 0x2E
#define LIS2DH12_SRC_REG 0x2F
//END -- 宏定义
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//START -- 变量定义
u8 dormancy_flag = 0; // 休眠标识
u8 dormancy_ago_moedl = 0; // 记录休眠前灯效
u16 gsensor_static_flag; // 记录传感器静止的时间,单位 200ms
axis_info_t current_data[32]; // 用于存储从FIFO读取的原始传感器数据
//运动数据全局变量
static motion_data_t motion_data = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}}; // 存储最终计算出的速度和距离
static axis_info_xtell gravity_vector = {0.0f, 0.0f, -GRAVITY_EARTH}; // 存储估算出的重力向量初始假设Z轴朝下
static bool sensor_is_stable = false; // 传感器是否静止的标志
static axis_info_xtell linear_accel_global = {0.0f, 0.0f, 0.0f}; // 存储移除重力后的线性加速度,用于日志打印
static axis_info_xtell zero_g_offset = {0.0f, 0.0f, 0.0f}; // 存储开机校准测得的零点偏移量
u8 gsensor_alarm;
axis_info_xtell gsensor_xtell; // 存储is_sensor_stable计算出的平均值
//END -- 变量定义
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//START -- 函数定义
//END -- 函数定义
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//实现
// --- I2C底层函数封装 ---
u32 SL_MEMS_i2cRead(u8 addr, u8 reg, u8 len, u8 *buf) {
return _gravity_sensor_get_ndata(addr, reg, buf, len);
}
u8 SL_MEMS_i2cWrite(u8 addr, u8 reg, u8 data) {
gravity_sensor_command(addr, reg, data);
return 0;
}
// 检查传感器ID确认设备是否正常连接
char LIS2DH12_Check() {
u8 reg_value = 0;
SL_MEMS_i2cRead(LIS2DH12_R_ADDR, LIS2DH12_WHO_AM_I, 1, &reg_value);
if (reg_value == 0x33) {
return 0x01;
}
return 0x00;
}
// 从传感器FIFO读取一批原始数据
void LIS2DH12_read_data(axis_info_t *sl_accel) {
u8 fifo_src = 0;
u8 samples_available = 0;
u8 data[192];
s16 raw_x,raw_y,raw_z;
SL_MEMS_i2cRead(LIS2DH12_R_ADDR, LIS2DH12_SRC_REG, 1, &fifo_src);
samples_available = fifo_src & 0x1F;
if (samples_available == 0) return;
SL_MEMS_i2cRead(LIS2DH12_R_ADDR, LIS2DH12_OUT_X_L | 0x80, samples_available * 6, data);
for (u8 i = 0; i < samples_available; i++) {
// 数据处理方式与 +/-8g 普通模式(10位) 匹配
raw_x = (int16_t)((data[i * 6 + 1] << 8) | data[i * 6]) >> 6;
raw_y = (int16_t)((data[i * 6 + 3] << 8) | data[i * 6 + 2]) >> 6;
raw_z = (int16_t)((data[i * 6 + 5] << 8) | data[i * 6 + 4]) >> 6;
sl_accel[i].x = raw_x;
sl_accel[i].y = raw_y;
sl_accel[i].z = raw_z;
}
}
// 开机校准函数:测量传感器的静态零点偏移
void LIS2DH12_calibrate() {
xlog("开始传感器校准...\n");
axis_info_t cal_data[32];
long x_sum = 0, y_sum = 0;
const int num_samples = 32;
delay_2ms(100); // 等待约200ms让FIFO填满数据
LIS2DH12_read_data(cal_data);
for (int i = 0; i < num_samples; i++) {
x_sum += cal_data[i].x;
y_sum += cal_data[i].y;
}
zero_g_offset.x = (float)x_sum / num_samples;
zero_g_offset.y = (float)y_sum / num_samples;
zero_g_offset.z = 0; // Z轴主要受重力影响不进行校准
xlog("校准完成. X轴偏移: %.2f, Y轴偏移: %.2f\n", zero_g_offset.x, zero_g_offset.y);
}
// 初始化并配置LIS2DH12传感器
u8 LIS2DH12_Config(void) {
if (LIS2DH12_Check() != 1) {
xlog("LIS2DH12 I2C检查失败\n");
return -1;
}
// 统一配置: 25Hz采样率, +/-8g量程, 普通模式(10位)
SL_MEMS_i2cWrite(LIS2DH12_W_ADDR, LIS2DH12_CTRL_REG1, 0x37); // 25 Hz ODR
SL_MEMS_i2cWrite(LIS2DH12_W_ADDR, LIS2DH12_CTRL_REG4, 0x20); // +/-8g, BDU enabled
SL_MEMS_i2cWrite(LIS2DH12_W_ADDR, LIS2DH12_CTRL_REG5, 0x40); // 使能FIFO
SL_MEMS_i2cWrite(LIS2DH12_W_ADDR, LIS2DH12_FIFO_CTRL_REG, 0x80); // 流模式
// 执行开机校准
LIS2DH12_calibrate();
xlog("LIS2DH12 I2C检查成功\n");
return 0;
}
// 判断传感器是否处于静止状态
bool is_sensor_stable(axis_info_t *accel_data, int sample_count) {
float mean_x = 0, mean_y = 0, mean_z = 0;
float variance_x = 0, variance_y = 0, variance_z = 0;
if (sample_count <= 1) return true;
// 1. 计算均值
for (int i = 0; i < sample_count; i++) {
mean_x += accel_data[i].x;
mean_y += accel_data[i].y;
mean_z += accel_data[i].z;
}
mean_x /= sample_count;
mean_y /= sample_count;
mean_z /= sample_count;
gsensor_xtell.x = mean_x;
gsensor_xtell.y = mean_y;
gsensor_xtell.z = mean_z;
// 2. 计算方差
for (int i = 0; i < sample_count; i++) {
variance_x += (accel_data[i].x - mean_x) * (accel_data[i].x - mean_x);
variance_y += (accel_data[i].y - mean_y) * (accel_data[i].y - mean_y);
variance_z += (accel_data[i].z - mean_z) * (accel_data[i].z - mean_z);
}
variance_x /= (sample_count - 1);
variance_y /= (sample_count - 1);
variance_z /= (sample_count - 1);
// 3. 如果方差大于阈值,则认为在运动
if (variance_x > THRESHOLD || variance_y > THRESHOLD || variance_z > THRESHOLD) {
return false;
}
return true;
}
// 获取当前的总加速度(包含重力),单位 m/s^2
axis_info_xtell get_current_accel_mss(void) {
axis_info_xtell accel_mss;
// 灵敏度 @ +/-8g 普通模式 (10-bit) = 12 mg/LSB
const float sensitivity_g_per_lsb = 0.012f;
// 在转换前,先减去校准测得的零点偏移
accel_mss.x = ((float)gsensor_xtell.x - zero_g_offset.x) * sensitivity_g_per_lsb * GRAVITY_EARTH;
accel_mss.y = ((float)gsensor_xtell.y - zero_g_offset.y) * sensitivity_g_per_lsb * GRAVITY_EARTH;
accel_mss.z = (float)gsensor_xtell.z * sensitivity_g_per_lsb * GRAVITY_EARTH;
return accel_mss;
}
// 获取计算好的运动数据(速度和距离)
void get_motion_data(motion_data_t *data) {
if (data) {
memcpy(data, &motion_data, sizeof(motion_data_t));
}
}
// 获取移除重力后的线性加速度
axis_info_xtell get_linear_accel_mss(void) {
return linear_accel_global;
}
// 核心计算任务,由定时器周期性调用
void xtell_i2c_test() {
// 1. 读取一批最新的传感器数据
LIS2DH12_read_data(current_data);
// 2. 判断传感器当前是否静止
sensor_is_stable = is_sensor_stable(current_data, SAMPLE_COUNT);
// 3. 获取校准和转换后的总加速度 (m/s^2)
axis_info_xtell current_accel_mss = get_current_accel_mss();
// 4. 使用低通滤波器估算重力向量
gravity_vector.x = LPF_ALPHA * gravity_vector.x + (1.0f - LPF_ALPHA) * current_accel_mss.x;
gravity_vector.y = LPF_ALPHA * gravity_vector.y + (1.0f - LPF_ALPHA) * current_accel_mss.y;
gravity_vector.z = LPF_ALPHA * gravity_vector.z + (1.0f - LPF_ALPHA) * current_accel_mss.z;
// 5. 从总加速度中减去重力,得到线性加速度
linear_accel_global.x = current_accel_mss.x - gravity_vector.x;
linear_accel_global.y = current_accel_mss.y - gravity_vector.y;
linear_accel_global.z = current_accel_mss.z - gravity_vector.z;
// 6. 应用死区:忽略过小的加速度值(噪声)
if (fabsf(linear_accel_global.x) < DEADZONE_MSS) linear_accel_global.x = 0.0f;
if (fabsf(linear_accel_global.y) < DEADZONE_MSS) linear_accel_global.y = 0.0f;
if (fabsf(linear_accel_global.z) < DEADZONE_MSS) linear_accel_global.z = 0.0f;
// 7. 积分线性加速度,得到速度
motion_data.velocity.x += linear_accel_global.x * SAMPLING_PERIOD_S;
motion_data.velocity.y += linear_accel_global.y * SAMPLING_PERIOD_S;
motion_data.velocity.z += linear_accel_global.z * SAMPLING_PERIOD_S;
// 8. 如果传感器静止,重置速度和距离以消除漂移
if (sensor_is_stable) {
motion_data.velocity.x = 0.0f;
motion_data.velocity.y = 0.0f;
motion_data.velocity.z = 0.0f;
motion_data.distance.x = 0.0f;
motion_data.distance.y = 0.0f;
motion_data.distance.z = 0.0f;
}
// 9. 积分速度,得到距离
motion_data.distance.x += motion_data.velocity.x * SAMPLING_PERIOD_S;
motion_data.distance.y += motion_data.velocity.y * SAMPLING_PERIOD_S;
motion_data.distance.z += motion_data.velocity.z * SAMPLING_PERIOD_S;
// 10. 计算并打印总的移动距离(可选,用于调试)
float total_distance_magnitude = sqrtf(motion_data.distance.x * motion_data.distance.x +
motion_data.distance.y * motion_data.distance.y +
motion_data.distance.z * motion_data.distance.z);
// xlog("Total distance traveled: %.2f m\n", total_distance_magnitude);
}

View File

@ -1,59 +0,0 @@
#ifndef LIS2DH12_H
#define LIS2DH12_H
#include "gSensor/gSensor_manage.h"
#include "le_rcsp_adv_module.h"
// --- 物理常量定义 ---
#define GRAVITY_EARTH 9.80665f // 地球重力加速度 (m/s^2)
#define SAMPLING_PERIOD_S 0.2f // 采样周期 (对应于200ms的定时器)
// --- 数据结构定义 ---
// 三轴数据结构体 (可用于加速度、速度、距离)
typedef struct {
float x;
float y;
float z;
} axis_info_xtell;
// 运动数据结构体,包含速度和距离
typedef struct {
axis_info_xtell velocity; // 速度 (m/s)
axis_info_xtell distance; // 距离 (m)
} motion_data_t;
// --- API 函数声明 ---
/**
* @brief 初始化并配置LIS2DH12传感器
* @return 0 表示成功, -1 表示失败
*/
unsigned char LIS2DH12_Config(void);
/**
* @brief 核心计算任务,应由定时器周期性调用
*/
void xtell_i2c_test(void);
// --- 数据获取函数声明 ---
/**
* @brief 获取计算好的运动数据(速度和距离)
* @param data 指向 motion_data_t 结构体的指针,用于存放结果
*/
void get_motion_data(motion_data_t *data);
/**
* @brief 获取当前的总加速度(包含重力),单位 m/s^2
* @return axis_info_xtell 包含x,y,z轴总加速度的结构体
*/
axis_info_xtell get_current_accel_mss(void);
/**
* @brief 获取当前移除重力后的线性加速度,单位 m/s^2
* @return axis_info_xtell 包含x,y,z轴线性加速度的结构体
*/
axis_info_xtell get_linear_accel_mss(void);
#endif

View File

@ -1,172 +0,0 @@
#include "system/includes.h"
/*#include "btcontroller_config.h"*/
#include "btstack/btstack_task.h"
#include "app_config.h"
#include "app_action.h"
#include "asm/pwm_led.h"
#include "tone_player.h"
#include "gpio.h"
#include "app_main.h"
#include "asm/charge.h"
#include "update.h"
#include "app_power_manage.h"
#include "app_charge.h"
#include "bt_profile_cfg.h"
#include "dev_manager/dev_manager.h"
#include "update_loader_download.h"
#include "avctp_user.h"
#include "debug.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
//宏定义
#define ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if ENABLE_XLOG
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
#define LOG_TAG_CONST APP
#define LOG_TAG "[APP]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
//
///////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//变量
extern APP_VAR app_var;
u16 close_BL_number=0;
//
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//函数定义
extern void timer_2ms_handler();
extern void app_var_init(void);
void app_earphone_play_voice_file(const char *name);
void clr_wdt(void);
extern void check_power_on_key(void);
extern int cpu_reset_by_soft();
extern int audio_dec_init();
extern int audio_enc_init();
//
//////////////////////////////////////////////////////////////////////////////////////////////////
/*充电拔出,CPU软件复位, 不检测按键,直接开机*/
static void app_poweron_check(int update)
{
if (!update && cpu_reset_by_soft()) {
app_var.play_poweron_tone = 0;
return;
}
}
void create_process(u16* pid,char* name, void *priv, void (*func)(void *priv), u32 msec){
xlog("1 name=%s, pid =%d\n",name,*pid);
if (*pid != 0) return;
*pid = sys_timer_add(priv, func, msec);
xlog("2 name=%s, pid =%d\n",name,*pid);
}
void close_process(u16* pid,char* name){
xlog("name=%s,pid =%d\n",name,*pid);
if (*pid == 0) return;
sys_timer_del(*pid);
*pid = 0;
}
void close_BL(){
/**开机默认关闭 经典蓝牙 */
// close_BL_flag++;
xlog("xtell Classic Bluetooth off\n");
user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI, 0, NULL); //断开此时经典蓝牙的连接,经典蓝牙还是可以被发现
delay_2ms(50);
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); //关闭蓝牙可发现,已连接时不能操作
delay_2ms(50);
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); //关闭蓝牙可连接,
// sys_timer_del(close_BL_number); //删除定时器任务
close_process(&close_BL_number,__func__);
}
extern u32 timer_get_ms(void);
void xtell_app_main()
{
int update = 0;
u32 addr = 0, size = 0;
struct intent it;
xlog("==============xtell_app_main start================\n");
log_info("app_main\n");
app_var.start_time = timer_get_ms();
if (!UPDATE_SUPPORT_DEV_IS_NULL()) {
update = update_result_deal();
}
app_var_init();
if (get_charge_online_flag()) {
#if(TCFG_SYS_LVD_EN == 1)
vbat_check_init();
#endif
xlog("==============idle================\n");
init_intent(&it);
it.name = "idle";
it.action = ACTION_IDLE_MAIN;
start_app(&it);
} else {
xlog("==============handler start================\n");
check_power_on_voltage();
app_poweron_check(update);
init_intent(&it);
it.name = "handler";
it.action = ACTION_EARPHONE_MAIN;
start_app(&it);
xlog("==============handler end================\n");
}
//////////////////////////////////////////////////
//开机必须延时关闭经典蓝牙,不然底层代码会再次把蓝牙 打开
create_process(&close_BL_number, "close_BL",NULL, close_BL, 3000);
soft_iic_init(0);
extern u8 LIS2DH12_Config(void);
LIS2DH12_Config();
u8 mac_data[6];
rcsp_adv_fill_mac_addr(mac_data); //读取MAC地址
xlog("xtell BT mac data:%x:%x:%x:%x:%x:%x",mac_data[0],mac_data[1],mac_data[2],mac_data[3],mac_data[4],mac_data[5]);
user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_ENABLE, 0, NULL); //打开蓝牙可发现,已连接时不能操作
delay_2ms(50);
user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); //打开蓝牙可连接
delay_2ms(50);
extern void xtell_task_create(void);
xtell_task_create();
xlog("==============xtell_app_end================\n");
}

View File

@ -0,0 +1,89 @@
#ifndef CPU_CARD_H
#define CPU_CARD_H 1
#include "rfid_main.h" // 包含 transmission_struct 的定义
/**
* @brief 存储ATS (Answer to Select) 信息的结构体
*/
struct ATS_STR
{
unsigned char Length; /**< ATS数据长度 */
unsigned char Ats_Data[255]; /**< ATS数据缓冲区 */
};
/**
* @brief 存储PPS (Protocol and Parameter Selection) 信息的结构体
*/
struct PPS_STR
{
unsigned char Length; /**< PPS数据长度 */
unsigned char Pps_Data[1]; /**< PPS数据缓冲区 */
};
/**
* @brief 存储CPU卡通信参数的结构体
*/
struct CPU_CARD_STR
{
unsigned char FSCI; /**< Frame Size for proximity coupling Integer */
unsigned char FSC; /**< Frame Size for proximity coupling (in bytes) */
unsigned char FWI; /**< Frame Waiting time Integer */
unsigned int FWT; /**< Frame Waiting Time (in ms) */
unsigned char SFGI; /**< Start-up Frame Guard time Integer */
unsigned char TA; /**< TA(1) parameter from ATS */
unsigned char TB; /**< TB(1) parameter from ATS */
unsigned char TC; /**< TC(1) parameter from ATS */
unsigned char PCB; /**< Protocol Control Byte */
unsigned char WTXM; /**< Waiting Time eXtension Multiplier */
struct ATS_STR ATS; /**< ATS信息 */
struct PPS_STR PPS; /**< PPS信息 */
};
extern struct CPU_CARD_STR CPU_CARD;
/**
* @brief 解析ATS (Answer to Select) 数据。
* @param ats_len [in] ATS数据的长度。
* @param ats [in] 指向ATS数据的指针。
* @return 操作状态SUCCESS表示成功。
*/
extern unsigned char Ats_Process( unsigned char ats_len, unsigned char *ats );
/**
* @brief CPU卡事件处理函数示例
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
extern unsigned char CPU_CARD_EVENT( void );
/**
* @brief 封装了重试逻辑的TPDU传输函数。
* @param tpdu [in, out] 指向传输结构体的指针。
* @return 操作状态。
*/
extern unsigned char CPU_TPDU( transmission_struct *tpdu );
/**
* @brief 发送RATS (Request for Answer to Select) 命令。
* @param ats_len [out] 指向用于存储ATS长度的变量的指针。
* @param ats [out] 指向用于存储ATS数据的缓冲区的指针。
* @return 操作状态SUCCESS表示成功。
*/
extern unsigned char CPU_Rats( unsigned char *ats_len, unsigned char *ats );
/**
* @brief 发送NAK (Negative Acknowledge) 响应。
* @param tpdu [in, out] 指向传输结构体的指针。
* @return 操作状态。
*/
extern unsigned char CPU_NAK( transmission_struct *tpdu );
/**
* @brief 发送APDU (Application Protocol Data Unit) 命令。
* @param apdu [in, out] 指向传输结构体的指针包含APDU命令和响应。
* @return 操作状态。
*/
extern unsigned char CPU_APDU( transmission_struct *apdu );
#endif

View File

@ -0,0 +1,97 @@
#ifndef _MIFARE_H_
#define _MIFARE_H_
// 定义Mifare认证密钥类型
#define KEY_A_M1 0
#define KEY_B_M1 1
// 声明全局变量
extern unsigned char SECTOR,BLOCK,BLOCK_NUM;
extern unsigned char BLOCK_DATA[16];
extern unsigned char KEY_A[16][6];
extern unsigned char KEY_B[16][6];
/**
* @brief Mifare卡事件处理函数示例
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
extern unsigned char MIFARE_CARD_EVENT(void);
/**
* @brief 清除Mifare卡加密认证标志。
* @return 无。
*/
extern void Mifare_Clear_Crypto(void);
/**
* @brief 将6字节的Mifare密钥加载到芯片的密钥缓冲区。
* @param mifare_key [in] 指向6字节密钥数组的指针。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char Mifare_LoadKey(unsigned char *mifare_key);
/**
* @brief 执行Mifare卡的传输Transfer命令。
* @param block [in] 块号。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
extern unsigned char Mifare_Transfer(unsigned char block);
/**
* @brief 执行Mifare卡的恢复Restore命令。
* @param block [in] 块号。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
extern unsigned char Mifare_Restore(unsigned char block);
/**
* @brief 将4字节数据格式化为Mifare值块格式并写入指定块。
* @param block [in] 目标块号。
* @param data_buff [in] 指向4字节源数据的指针。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
extern unsigned char Mifare_Blockset(unsigned char block,unsigned char *data_buff);
/**
* @brief 对Mifare卡的指定值块执行增值操作。
* @param block [in] 值块的块号。
* @param data_buff [in] 指向4字节增值数据的指针。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
extern unsigned char Mifare_Blockinc(unsigned char block,unsigned char *data_buff);
/**
* @brief 对Mifare卡的指定值块执行减值操作。
* @param block [in] 值块的块号。
* @param data_buff [in] 指向4字节减值数据的指针。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
extern unsigned char Mifare_Blockdec(unsigned char block,unsigned char *data_buff);
/**
* @brief 向Mifare卡写入一个16字节的数据块。
* @param block [in] 要写入的块号 (0x00 - 0x3F)。
* @param data_buff [in] 指向16字节数据的指针。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
extern unsigned char Mifare_Blockwrite(unsigned char block,unsigned char *data_buff);
/**
* @brief 从Mifare卡读取一个16字节的数据块。
* @param block [in] 要读取的块号 (0x00 - 0x3F)。
* @param data_buff [out] 指向16字节缓冲区的指针用于存储读取的数据。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
extern unsigned char Mifare_Blockread(unsigned char block,unsigned char *data_buff);
/**
* @brief 对Mifare Classic卡片的指定扇区进行认证。
* @param key_mode [in] 认证模式,`KEY_A_M1` (0) 表示使用密钥A`KEY_B_M1` (1) 表示使用密钥B。
* @param sector [in] 要认证的扇区号 (0-15)。
* @param mifare_key [in] 指向6字节认证密钥的指针。
* @param card_uid [in] 指向4字节卡片UID的指针。
* @return 操作状态SUCCESS表示认证成功FAIL表示失败。
*/
extern unsigned char Mifare_Auth(unsigned char key_mode,unsigned char sector,unsigned char *mifare_key,unsigned char *card_uid);
#endif

View File

@ -0,0 +1,8 @@
#ifndef _NTAG_H
#define _NTAG_H
extern unsigned char PAGE_DATA[16];
extern unsigned char NTAG_EVENT(void);
extern unsigned char Read_Page(unsigned char page_num,unsigned char *page_data);
extern unsigned char Write_Page(unsigned char page_num,unsigned char *page_data);
#endif

View File

@ -0,0 +1,153 @@
/********************************************************************************************************
* @file READER.h
* @brief RFID 读卡器底层驱动及协议头文件
* @details
* 本文件定义了与RFID芯片交互所需的常量、数据结构和函数原型。
*
* @author Kilo Code
* @date 2025-11-24
* @version 1.0
********************************************************************************************************/
#ifndef _READER_H
#define _READER_H
/********************************************************************************************************
* 常量定义
********************************************************************************************************/
// ISO14443A 命令码
static const unsigned char RF_CMD_REQA = 0x26; /**< 请求命令 */
static const unsigned char RF_CMD_WUPA = 0x52; /**< 唤醒命令 */
static const unsigned char RF_CMD_ANTICOLL[3] = {0x93, 0x95, 0x97}; /**< 防冲突命令,根据级联级别选择 */
static const unsigned char RF_CMD_SELECT[3] = {0x93, 0x95, 0x97}; /**< 选择命令,根据级联级别选择 */
// MIFARE Classic 命令码
static const unsigned char RF_CMD_KEYA = 0x60; /**< 密钥A认证 */
static const unsigned char RF_CMD_KEYB = 0x61; /**< 密钥B认证 */
/********************************************************************************************************
* 卡片信息结构体
********************************************************************************************************/
/**
* @brief 存储ISO/IEC 14443 Type B卡片信息的结构体
*/
struct picc_b_struct
{
unsigned char ATQB[12]; /**< REQB/WUPB的响应 (Answer to Request B) */
unsigned char PUPI[4]; /**< Pseudo-Unique PICC Identifier */
unsigned char APPLICATION_DATA[4]; /**< 应用数据 */
unsigned char PROTOCOL_INF[3]; /**< 协议信息 */
unsigned char CID; /**< 卡片ID (Card Identifier) */
unsigned char Answer_to_HALT[1]; /**< HALT命令的响应 */
unsigned char SN[8]; /**< 序列号 (自定义命令获取) */
};
extern struct picc_b_struct PICC_B;
/**
* @brief 存储ISO/IEC 14443 Type A卡片信息的结构体
*/
struct picc_a_struct
{
unsigned char ATQA[2]; /**< REQA/WUPA的响应 (Answer to Request A) */
unsigned char CASCADE_LEVEL; /**< 当前级联级别 (用于处理多级UID) */
unsigned char UID_Length; /**< UID的长度 (4, 7, or 10 bytes) */
unsigned char UID[15]; /**< 卡片唯一ID (Unique Identifier) */
unsigned char BCC[3]; /**< 块校验字符 (Block Check Character) */
unsigned char SAK[3]; /**< 选择确认 (Select Acknowledge) */
};
extern struct picc_a_struct PICC_A;
/**
* @brief 存储ISO/IEC 15693 (Type V) 卡片信息的结构体
*/
struct picc_v_struct
{
unsigned char UID[8]; /**< 卡片唯一ID (Unique Identifier) */
unsigned char RESPONSE; /**< 命令响应标志 */
unsigned char BLOCK_DATA[4]; /**< 读取或写入的块数据 */
};
extern struct picc_v_struct PICC_V;
/**
* @brief 存储FeliCa (Type F) 卡片信息的结构体
*/
struct picc_f_struct
{
unsigned char UID[8]; /**< 卡片唯一ID (Unique Identifier) */
};
extern struct picc_f_struct PICC_F;
/********************************************************************************************************
* 芯片参数配置
********************************************************************************************************/
// --- Type A 参数 ---
#define GAIN_A 7 // 接收增益 (范围 0~7)
#define HPCF_A 3 // 高通滤波器截止频率 (范围 0~7)
#define AMPLITUDE_A 255 // RF场幅度 (范围 0~255)
// --- Type B 参数 ---
#define GAIN_B 7 // 接收增益
#define HPCF_B 3 // 高通滤波器截止频率
#define AMPLITUDE_B 255 // RF场幅度
#define MODULATION_B 100 // 调制深度 (范围 0~255, 值越小调制越深)
// --- Type V (ISO15693) 参数 ---
#define GAIN_V 7 // 接收增益
#define HPCF_V 4 // 高通滤波器截止频率
#define AMPLITUDE_V 255 // RF场幅度
#define MODULATION_V 10 // 调制深度
// --- Type F (FeliCa) 参数 ---
#define GAIN_F 7 // 接收增益
#define HPCF_F 4 // 高通滤波器截止频率
#define AMPLITUDE_F 255 // RF场幅度
#define MODULATION_F 100 // 调制深度
/********************************************************************************************************
* 函数原型声明
********************************************************************************************************/
// --- 通用函数 ---
extern void ModifyReg(unsigned char reg_address, unsigned char mask, unsigned char set);
extern void Clear_FIFO(void);
extern unsigned char SetCommand(unsigned char command);
extern void SetParity(unsigned char state);
extern void SetTimer(unsigned int timeout);
extern unsigned char SetCW(unsigned char mode);
// --- 协议初始化函数 ---
extern unsigned char ReaderA_Initial(void);
extern unsigned char ReaderB_Initial(void);
extern unsigned char ReaderV_Initial(void);
extern unsigned char ReaderF_Initial(void);
// --- Type A 命令 ---
extern unsigned char ReaderA_Wakeeup(struct picc_a_struct *picc_a);
extern unsigned char ReaderA_Request(struct picc_a_struct *picc_a);
extern unsigned char ReaderA_Anticoll(struct picc_a_struct *picc_a);
extern unsigned char ReaderA_Select(struct picc_a_struct *picc_a);
extern unsigned char ReaderA_CardActivate(struct picc_a_struct *picc_a);
// --- Type B 命令 ---
extern unsigned char ReaderB_Wakeup(struct picc_b_struct *picc_b);
extern unsigned char ReaderB_Request(struct picc_b_struct *picc_b);
extern unsigned char ReaderB_Attrib(struct picc_b_struct *picc_b);
extern unsigned char ReaderB_Halt(struct picc_b_struct *picc_b);
extern unsigned char ReaderB_Get_SN(struct picc_b_struct *picc_b);
// --- Type V (ISO15693) 命令 ---
extern unsigned char ReaderV_Inventory(struct picc_v_struct *picc_v);
extern unsigned char ReaderV_Select(struct picc_v_struct *picc_v);
extern unsigned char ReaderV_ReadSingleBlock(unsigned char block_num, struct picc_v_struct *picc_v);
extern unsigned char ReaderV_WriteSingleBlock(unsigned char block_num, struct picc_v_struct *picc_v);
// --- Type F (FeliCa) 命令 ---
extern unsigned char ReaderF_Inventory(struct picc_f_struct *picc_f);
#endif // _READER_H

View File

@ -0,0 +1,479 @@
/*********************************************************************
* *
* Copyright (c) 2010 Shanghai FuDan MicroElectronic Inc, Ltd. *
* All rights reserved. Licensed Software Material. *
* *
* Unauthorized use, duplication, or distribution is strictly *
* prohibited by law. *
* *
**********************************************************************/
#ifndef _READER_REG_H
#define _READER_REG_H
#define REG_COMMAND 0x00 //
#define REG_HOSTCTRL 0x01 //
#define REG_FIFOCONTROL 0x02 //
#define REG_WATERLEVEL 0x03 //
#define REG_FIFOLENGTH 0x04 //
#define REG_FIFODATA 0x05 //
#define REG_IRQ0 0x06 //
#define REG_IRQ1 0x07 //
#define REG_IRQ0EN 0x08 //
#define REG_IRQ1EN 0x09 //
#define REG_ERROR 0x0A //
#define REG_STATUS 0x0B //
#define REG_RXBITCTRL 0x0C //
#define REG_RXCOLL 0x0D //
#define REG_TCONTROL 0x0E //
#define REG_T0CONTROL 0x0F //
#define REG_T0RELOADHI 0x10 //
#define REG_T0RELOADLO 0x11 //
#define REG_T0COUNTERVALHI 0x12 //
#define REG_T0COUNTERVALLO 0x13 //
#define REG_T1CONTROL 0x14 //
#define REG_T1RELOADHI 0x15 //
#define REG_T1RELOADLO 0x16 //
#define REG_T1COUNTERVALHI 0x17 //
#define REG_T1COUNTERVALLO 0x18 //
#define REG_T2CONTROL 0x19 //
#define REG_T2RELOADHI 0x1A //
#define REG_T2RELOADLO 0x1B //
#define REG_T2COUNTERVALHI 0x1C //
#define REG_T2COUNTERVALLO 0x1D //
#define REG_T3CONTROL 0x1E //
#define REG_T3RELOADHI 0x1F //
#define REG_T3RELOADLO 0x20 //
#define REG_T3COUNTERVALHI 0x21 //
#define REG_T3COUNTERVALLO 0x22 //
#define REG_T4CONTROL 0x23 //
#define REG_T4RELOADHI 0x24 //
#define REG_T4RELOADLO 0x25 //
#define REG_T4COUNTERVALHI 0x26 //
#define REG_T4COUNTERVALLO 0x27 //
#define REG_TXMODE 0x28
#define REG_TXAMP 0x29
#define REG_TXCON 0x2A //
#define REG_TXI 0x2B //
#define REG_TXCRCCON 0x2C //
#define REG_RXCRCCON 0x2D //
#define REG_TXDATANUM 0x2E
#define REG_TXMODWIDTH 0x2F //
#define REG_TXSYM10BURSTLEN 0x30 //
#define REG_TXWAITCTRL 0x31 //
#define REG_TXWAITLO 0x32 //
#define REG_FRAMECON 0x33 //
#define REG_RXSOFD 0x34 //
#define REG_RXCTRL 0x35 //
#define REG_RXWAIT 0x36 //
#define REG_RXTHRESHOLD 0x37 //
#define REG_RCV 0x38 //
#define REG_RXANA 0x39 //
#define REG_LPCD_OPTIONS 0x3A //
#define REG_SERIALSPEED 0x3B //
#define REG_LFO_TRIMM 0x3C //
#define REG_CLKOUT_CTRL 0x3D //
#define REG_LPCD_THRESHOLD 0x3E //
#define REG_LPCD_QMIN 0x3F //
#define REG_LPCD_QMAX 0x40
#define REG_LPCD_IMIN 0x41
#define REG_LPCD_RESULT_I 0x42
#define REG_LPCD_RESULT_Q 0x43
#define REG_THNADJ 0x5F
#define REG_THNSET 0x61
#define REG_THNMIN 0x62
#define REG_DSP_CTRL1 0x64
#define REG_MISC 0x75
#define REG_RXTXCON 0x77
#define REG_ERROREXT 0x7E
#define REG_VERSION 0x7F
#define CMD_MASK 0x1F
#define CMD_IDLE 0x00
#define CMD_LPCD 0x01
#define CMD_LOADKEY 0x02
#define CMD_AUTHENT 0x03
#define CMD_RECEIVE 0x05
#define CMD_TRANSMIT 0x06
#define CMD_TRANSCEIVE 0x07
#define CMD_WRITEE2 0x08
#define CMD_WRITEE2PAGE 0x09
#define CMD_READE2 0x0A
#define CMD_LOADREG 0x0C
#define CMD_LOADPROTOCOL 0x0D
#define CMD_LOADKEYE2 0x0E
#define CMD_STOREKEYE2 0x0F
#define CMD_CRCCALC 0x1B
#define CMD_READRNR 0x1C
#define CMD_SOFTRESET 0x1F
/** \name Host-Control Register Contents (0x00)
*/
/*@{*/
#define BIT_STANDBY 0x80U /**< Standby bit; If set, the IC transits to standby mode. */
#define BIT_MODEMOFF 0x40U
/*@{*/
/** \name Host-Control Register Contents (0x01)
*/
/*@{*/
#define BIT_I2CFORCEHS 0x01U
//#define BIT_REGEN 0x80U
//#define BIT_BUSHOST 0x40U
//#define BIT_BUSSAM 0x20U
//#define MASK_SAMINTERFACE 0x0CU
/*@}*/
/** \name FIFO-Control Register Contents (0x02)
*/
/*@{*/
#define BIT_FIFOSIZE 0x80U
#define BIT_HIALERT 0x40U
#define BIT_LOALERT 0x20U
#define BIT_FIFOFLUSH 0x10U
#define BIT_WATERLEVEL_HI 0x04U
#define MASK_FIFOLENGTH_HI 0x03U
/*@}*/
/** \name IRQ0 Register(s) Contents (0x06/0x08)
*/
/*@{*/
#define BIT_SET 0x80U
#define BIT_IRQINV 0x80U
#define BIT_HIALERTIRQ 0x40U
#define BIT_LOALERTIRQ 0x20U
#define BIT_IDLEIRQ 0x10U
#define BIT_IDLE_IRQ BIT_IDLEIRQ /* Alias for compatibility */
#define BIT_TXIRQ 0x08U
#define BIT_RXIRQ 0x04U
#define BIT_ERRIRQ 0x02U
#define BIT_RXSOFIRQ 0x01U
/*@}*/
/** \name IRQ1 Register(s) Contents (0x07/0x09)
*/
/*@{*/
/* #define BIT_SET 0x80U */
#define BIT_IRQPUSHPULL 0x80U
#define BIT_GLOBALIRQ 0x40U
#define BIT_IRQPINEN 0x40U
#define BIT_LPCDIRQ 0x20U
#define BIT_TIMER4IRQ 0x10U
#define BIT_TIMER3IRQ 0x08U
#define BIT_TIMER2IRQ 0x04U
#define BIT_TIMER1IRQ 0x02U
#define BIT_TIMER0IRQ 0x01U
/*@}*/
/** \name Error Register Contents (0x0A)
*/
/*@{*/
#define BIT_CMDEE_ERR 0x80U
#define BIT_FIFOWRERR 0x40U
#define BIT_FIFOOVL 0x20U
#define BIT_MINFRAMEERR 0x10U
#define BIT_NODATAERR 0x08U
#define BIT_COLLDET 0x04U
#define BIT_PROTERR 0x02U
#define BIT_INTEGERR 0x01U
/*@}*/
/** \name Status Register Contents (0x0B)
*/
/*@{*/
#define BIT_CRYPTO1ON 0x20U
#define MASK_COMMSTATE 0x07U
/*@}*/
/** \name Rx-Bit-Control Register Contents (0x0C)
*/
/*@{*/
#define BIT_VALUESAFTERCOLL 0x80U
#define BIT_NOCOLL 0x08U
#define MASK_RXALIGN 0x70U
#define MASK_RXLASTBITS 0x07U
/*@}*/
/** \name Rx-Coll Register Contents (0x0D)
*/
/*@{*/
#define BIT_COLLPOSVALID 0x80U
#define MASK_COLLPOS 0x7FU
/*@}*/
/** \name Timer-Control Register Contents (0x0E)
*/
/*@{*/
#define BIT_T3RUNNING 0x80U
#define BIT_T2RUNNING 0x40U
#define BIT_T1RUNNING 0x20U
#define BIT_T0RUNNING 0x10U
#define BIT_T3STARTSTOPNOW 0x08U
#define BIT_T2STARTSTOPNOW 0x04U
#define BIT_T1STARTSTOPNOW 0x02U
#define BIT_T0STARTSTOPNOW 0x01U
/*@}*/
/** \name T[0-3]-Control Register Contents (0x0F/0x14/0x19/0x1E)
*/
/*@{*/
#define BIT_TSTOP_RX 0x80U /**< Stop timer on receive interrupt. */
#define BIT_TAUTORESTARTED 0x08U /**< Auto-restart timer after underflow. */
#define BIT_TSTART_TX 0x10U /**< Start timer on transmit interrupt. */
//#define BIT_TSTART_LFO 0x20U /**< Use this timer for LFO trimming. */
//#define BIT_TSTART_LFO_UV 0x30U /**< Use this timer for LFO trimming (generate UV at a trimming event). */
#define MASK_TSTART 0x30U /**< Mask for TSTART bits. */
#define VALUE_TCLK_1356_MHZ 0x00U /**< Use 13.56MHz as input clock. */
#define VALUE_TCLK_212_KHZ 0x01U /**< Use 212KHz as input clock. */
#define VALUE_TCLK_T0 0x02U /**< Use timer0 as input clock. */
#define VALUE_TCLK_T1 0x03U /**< Use timer1 as input clock. */
/*@}*/
/** \name T4-Control Register Contents (0x23)
*/
/*@{*/
#define BIT_T4RUNNING 0x80U
#define BIT_T4STARTSTOPNOW 0x40U
#define BIT_T4AUTOTRIMM 0x20U
#define BIT_T4AUTOLPCD 0x10U
#define BIT_T4AUTORESTARTED 0x08U
#define BIT_T4AUTOWAKEUP 0x04U
/*#define MASK_TSTART 0x30U*/
#define VALUE_TCLK_LFO_64_KHZ 0x00U
#define VALUE_TCLK_LFO_8_KHZ 0x01U
#define VALUE_TCLK_LFO_4_KHZ 0x02U
#define VALUE_TCLK_LFO_2_KHZ 0x03U
/*@}*/
/** \name Driver Mode Register Contents (0x28)
*/
/*@{*/
#define BIT_TX2INV 0x80U
#define BIT_TX1INV 0x40U
#define BIT_TXEN 0x08U
#define VALUE_TXCLKMODE_HIGHIMPEDANCE 0x00U
#define VALUE_TXCLKMODE_OUTPULL0 0x01U
#define VALUE_TXCLKMODE_OUTPULL1 0x02U
#define VALUE_TXCLKMODE_RFLOWPULL 0x05U
#define VALUE_TXCLKMODE_RFHIGHPUSH 0x06U
#define VALUE_TXCLKMODE_PUSHPULL 0x07U
#define BIT_RFON 0x04U
#define BIT_TPUSHON 0x02U
#define BIT_TPULLON 0x01U
/*@}*/
/** \name Tx Amplifier Register Contents (0x29)
*/
/*@{*/
#define MASK_CW_AMPLITUDE 0x00U
#define MASK_RESIDUAL_CARRIER 0x1FU
/*@}*/
/** \name Driver Control Register Contents (0x2A)
*/
/*@{*/
#define BIT_CWMAX 0x08U
#define BIT_DRIVERINV 0x04U
#define VALUE_DRIVERSEL_LOW 0x00U
#define VALUE_DRIVERSEL_TXENV 0x01U
#define VALUE_DRIVERSEL_SIGIN 0x02U
/*@}*/
/** \name Tx-/Rx-CRC Control Register Contents (0x2C/0x2D)
*/
/*@{*/
#define BIT_RXFORCECRCWRITE 0x80U
#define BIT_CRCINVERT 0x02U
#define BIT_CRCEN 0x01U
#define MASK_CRCPRESETVAL 0x70U
#define MASK_CRCTYPE 0x0CU
#define MASK_CRCTYPE5 0x00U
#define MASK_CRCTYPE16 0x08U
/*@}*/
/** \name Tx-DataNum Register Contents (0x2E)
*/
/*@{*/
#define BIT_KEEPBITGRID 0x10U
#define BIT_DATAEN 0x08U
#define MASK_TXLASTBITS 0x07U
#define MASK_SYMBOL_SEND 0x08U
/*@}*/
/** \name Tx-Wait Control Register Contents (0x31)
*/
/*@{*/
#define BIT_TXWAIT_START_RX 0x80U
#define BIT_TXWAIT_DBFREQ 0x40U
#define MASK_TXWAITHI 0x38U
#define MASK_TXSTOPBITLEN 0x07U
/*@}*/
/** \name Frame Control Register Contents (0x33)
*/
/*@{*/
#define BIT_TXPARITYEN 0x80U
#define BIT_RXPARITYEN 0x40U
#define VALUE_STOP_SYM3 0x0CU
#define VALUE_STOP_SYM2 0x08U
#define VALUE_STOP_SYM1 0x04U
#define VALUE_START_SYM3 0x03U
#define VALUE_START_SYM2 0x02U
#define VALUE_START_SYM1 0x01U
#define MASK_STARTSYM 0x03U
#define MASK_STOPSYM 0x0CU
/*@}*/
/** \name Rx Control Register Contents (0x35)
*/
/*@{*/
#define BIT_RXALLOWBITS 0x80U
#define BIT_RXMULTIPLE 0x40U
#define BIT_RXEOFTYPE 0x20U
#define BIT_EGT_CHECK 0x10U
#define BIT_EMD_SUPPRESSION 0x08U
#define MASK_RXBAUDRATE 0x07U
/*@}*/
/** \name Rx-Wait Register Contents (0x36)
*/
/*@{*/
#define BIT_RXWAITDBFREQ 0x80U
#define MASK_RXWAIT 0x7FU
/*@}*/
/** \name Rx-Threshold Register Contents (0x37)
*/
/*@{*/
#define MASK_MINLEVEL 0xF0U
#define MASK_MINLEVELP 0x0FU
/*@}*/
/** \name Rx-Receiver Register Contents (0x38)
*/
/*@{*/
#define BIT_RX_SINGLE 0x80U
#define BIT_RX_SHORT_MIX2ADC 0x40U
#define BIT_USE_SMALL_EVAL 0x04U
#define MASK_RX_SIGPRO_IN_SEL 0x30U
#define MASK_COLLLEVEL 0x03U
/*@}*/
/** \name Rx-Analog Register Contents (0x39)
*/
/*@{*/
#define BIT_RX_OC_FUN_ENABLE 0x20U
#define BIT_RX_HP_LOWF 0x10U
#define MASK_VMID_R_SEL 0xC0U
#define MASK_RCV_HPCF 0x0CU
#define MASK_RCV_GAIN 0x03U
/*@}*/
/** \name Serial-Speed Register Contents (0x3B)
*/
/*@{*/
#define MASK_BR_T0 0xE0U
#define MASK_BR_T1 0x1FU
/*@}*/
/** \name LPCD Result(Q) Register Contents (0x43)
*/
/*@{*/
#define BIT_LPCDIRQ_CLR 0x40U
/*@}*/
/** \name Tx-BitMod Register Contents (0x48)
*/
/*@{*/
#define BIT_TXMSBFIRST 0x80U
#define BIT_TXPARITYTYPE 0x20U
#define BIT_TXSTOPBITTYPE 0x08U
#define BIT_TXSTARTBITTYPE 0x02U
#define BIT_TXSTARTBITEN 0x01U
/*@}*/
/** \name Rx-BitMod Register Contents (0x58)
*/
/*@{*/
#define BIT_RXSTOPONINVPAR 0x20U
#define BIT_RXSTOPONLEN 0x10U
#define BIT_RXMSBFIRST 0x08U
#define BIT_RXSTOPBITEN 0x04U
#define BIT_RXPARITYTYPE 0x02U
/*@}*/
/** \name Rx-Mod Register Contents (0x5D)
*/
/*@{*/
#define BIT_PREFILTER 0x20U
#define BIT_RECTFILTER 0x10U
#define BIT_SYNCHIGH 0x08U
#define BIT_CORRINV 0x04U
#define BIT_FSK 0x02U
#define BIT_BPSK 0x01U
/*@}*/
/** \name RxSupCfg Register Contents (0x6E)
*/
/*@{*/
#define BIT_RXNOERR 0x80U
/*@}*/
/** \name RxTxConReg Register Contents (0x77)
*/
/*@{*/
#define BIT_SHMODE 0x08U //<2F>Ϻ<EFBFBD><CFBA>
/*@}*/
/** \name ErrorExtReg Register Contents (0x7E)
*/
/*@{*/
#define PARITY_ERROR 0x08U
#define CRC_ERROR 0x04U
/*@{*/
#define LPCD_OPTION2 0x1DF
//---------------------------------------------------------------
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><D0AD><EFBFBD>
#define RX_TYPEA_106 0
#define RX_TYPEA_212 1
#define RX_TYPEA_424 2
#define RX_TYPEA_848 3
#define RX_TYPEB_106 4
#define RX_TYPEB_212 5
#define RX_TYPEB_424 6
#define RX_TYPEB_848 7
#define RX_TYPEV_26 10
#define RX_TYPEV_53 11
#define RX_FELICA_212 19
#define RX_FELICA_424 20
//<2F><><EFBFBD><EFBFBD><E5B7A2>Э<EFBFBD><D0AD><EFBFBD>
#define TX_TYPEA_106 0
#define TX_TYPEA_212 1
#define TX_TYPEA_424 2
#define TX_TYPEA_848 3
#define TX_TYPEB_106 4
#define TX_TYPEB_212 5
#define TX_TYPEB_424 6
#define TX_TYPEB_848 7
#define TX_TYPEV_26 10
#define TX_TYPEV_53 11
#define TX_FELICA_212 19
#define TX_FELICA_424 20
#endif

View File

@ -0,0 +1,82 @@
/********************************************************************************************************
* @file rfid_main.h
* @brief RFID 读卡器应用层主头文件
* @details
* 本文件定义了RFID应用层所需的数据结构、枚举类型和全局函数。
*
* @author Kilo Code
* @date 2025-11-24
* @version 1.0
********************************************************************************************************/
#ifndef _RFID_MAIN_H
#define _RFID_MAIN_H
// 包含项目的基础类型定义,如果您的项目中没有 "system/includes.h"
// 请替换为包含 stdint.h 或类似的头文件以获取 u8, u16, u32 等类型定义。
#include "system/includes.h"
/**
* @brief 操作状态枚举
*/
typedef enum {
FAIL = 0U,
SUCCESS = !FAIL
} ErrorStatus;
/**
* @brief 功能使能状态枚举
*/
typedef enum {
FUN_DISABLE = 0U,
FUN_ENABLE = !FUN_DISABLE
} FunState;
/**
* @brief 标志位状态枚举
*/
typedef enum {
RESET = 0U,
SET = !RESET
} FlagStatus, ITStatus;
/**
* @brief 通用位宏定义
*/
#define BIT0 (1 << 0)
#define BIT1 (1 << 1)
#define BIT2 (1 << 2)
#define BIT3 (1 << 3)
#define BIT4 (1 << 4)
#define BIT5 (1 << 5)
#define BIT6 (1 << 6)
#define BIT7 (1 << 7)
/**
* @brief 数据传输结构体
* @details 用于在不同函数间传递发送和接收数据缓冲区及其长度信息。
*/
typedef struct
{
unsigned char SendLength; /**< 要发送的数据长度 */
unsigned char *pSendBuffer; /**< 指向发送数据缓冲区的指针 */
unsigned char ReceiveLength; /**< 接收到的数据长度 */
unsigned char *pReceiveBuffer; /**< 指向接收数据缓冲区的指针 */
unsigned int Timeout; /**< 操作超时时间(单位:毫秒) */
} transmission_struct;
/********************************************************************************************************
* 全局函数声明
********************************************************************************************************/
/**
* @brief RFID模块的主任务函数。
* @details
* 这是一个示例性的任务函数展示了如何初始化RFID芯片并进入一个无限循环来轮询不同类型的卡片。
* 您可以将此函数作为一个独立的任务运行,或者将其中的逻辑集成到您现有的任务调度中。
*/
void rfid_task(void);
#endif // _RFID_MAIN_H

View File

@ -0,0 +1,447 @@
#include "../include/READER.h"
#include "../include/CPU_CARD.h"
#include "../include/READER_REG.h"
#include "../include/rfid_main.h"
#include "../rfid_hal.h"
#define FUN_ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if FUN_ENABLE_XLOG
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
struct CPU_CARD_STR CPU_CARD;
// 声明一个静态函数用于TPDU传输因为它只在本文件内部使用
static unsigned char FM176XX_TPDU(transmission_struct *tpdu);
/**
* @brief CPU卡事件处理函数示例
* @details
* 1. 发送RATS (Request for Answer to Select) 命令以激活卡片并获取ATS (Answer to Select)。
* 2. 解析ATS获取卡片能力信息如FSC, FWI等
* 3. 发送一系列APDU (Application Protocol Data Unit) 指令与卡片应用进行交互。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char CPU_CARD_EVENT(void)
{
unsigned char result;
unsigned char SendBuffer[255];
unsigned char ReceiveBuffer[255];
int i;
transmission_struct APDU;
APDU.pSendBuffer = SendBuffer;
APDU.pReceiveBuffer = ReceiveBuffer;
result = CPU_Rats(&CPU_CARD.ATS.Length, CPU_CARD.ATS.Ats_Data);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> RATS ERROR!\r\n");
return result;
}
xlog("-> ATS = ");
for(i = 0; i < CPU_CARD.ATS.Length; i++)
xlog("%02X", CPU_CARD.ATS.Ats_Data[i]);
xlog("\r\n");
result = Ats_Process(CPU_CARD.ATS.Length, CPU_CARD.ATS.Ats_Data);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> ATS Process ERROR!\r\n");
return result;
}
// 选择主文件(MF)
memcpy(APDU.pSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", 7);
APDU.SendLength = 7;
result = CPU_APDU(&APDU);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> APDU ERROR!\r\n");
return result;
}
xlog("-> Select MF Response = ");
for(i=0; i<APDU.ReceiveLength; i++)
xlog("%02X", APDU.pReceiveBuffer[i]);
xlog("\r\n");
// ... 此处可以添加更多APDU指令 ...
return result;
}
/**
* @brief 将数据写入芯片的FIFO缓冲区。
* @param length [in] 要写入的数据长度。
* @param buff [in] 指向源数据缓冲区的指针。
* @return 无。
*/
static void Write_FIFO(unsigned char length, unsigned char* buff)
{
unsigned char i;
for(i=0; i<length; i++)
{
SetReg(REG_FIFODATA,buff[i]);
}
}
/**
* @brief 从芯片的FIFO缓冲区读取数据。
* @param length [in] 要读取的数据长度。
* @param buff [out] 指向目标数据缓冲区的指针。
* @return 无。
*/
static void Read_FIFO(unsigned char length, unsigned char* buff)
{
unsigned char i;
for(i=0; i<length; i++)
{
GetReg(REG_FIFODATA,&buff[i]);
}
}
/**
* @brief 执行TPDU (Transmission Protocol Data Unit) 数据交换。
* @param tpdu [in, out] 指向 `transmission_struct` 结构体的指针,包含发送和接收信息。
* @return 操作状态SUCCESS表示成功FAIL表示超时或出错。
* @details
* 这是与卡片进行底层数据块交换的核心函数。它负责:
* - 将数据写入FIFO。
* - 启动TRANSCEIVE命令。
* - 等待接收中断或超时。
* - 从FIFO读取响应数据。
* - 检查错误状态。
*/
static unsigned char FM176XX_TPDU(transmission_struct *tpdu)
{
unsigned char irq0, error;
unsigned int i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_IRQ0,0x7F); // 清除IRQ0所有中断标志
SetReg(REG_IRQ1,0x7F); // 清除IRQ1所有中断标志
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,FUN_ENABLE); // 清空FIFO
Write_FIFO(tpdu->SendLength,tpdu->pSendBuffer);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_ENABLE);
// SetTimer(tpdu->Timeout); // 定时器功能可以根据需要启用
SetCommand(CMD_TRANSCEIVE);
// 等待接收完成或超时
for(i = 0; i < tpdu->Timeout; i++)
{
rfid_delay_ms(1);
GetReg(REG_IRQ0,&irq0);
if(irq0 & BIT_RXIRQ) // 检查是否收到数据
{
GetReg(REG_ERROR, &error); // 获取错误状态
error &= (BIT_NODATAERR | BIT_COLLDET | BIT_PROTERR | BIT_INTEGERR);
if(error != 0)
return FAIL; // 接收到错误
GetReg(REG_FIFOLENGTH, &tpdu->ReceiveLength);
if(tpdu->ReceiveLength > 0)
{
Read_FIFO(tpdu->ReceiveLength,tpdu->pReceiveBuffer);
return SUCCESS;
}
}
}
return FAIL; // 超时
}
/**
* @brief 发送RATS (Request for Answer to Select) 命令。
* @param ats_len [out] 指向用于存储ATS长度的变量的指针。
* @param ats [out] 指向用于存储ATS数据的缓冲区的指针。
* @return 操作状态SUCCESS表示成功。
* @details
* RATS是激活ISO/IEC 14443-4卡片的第一步用于获取卡片的基本通信参数。
*/
unsigned char CPU_Rats(unsigned char *ats_len, unsigned char *ats)
{
unsigned char result;
unsigned char outbuffer[2], inbuffer[64];
transmission_struct tpdu;
tpdu.pSendBuffer = outbuffer;
tpdu.pReceiveBuffer = inbuffer;
tpdu.pSendBuffer[0] = 0xE0; // RATS命令起始字节
tpdu.pSendBuffer[1] = 0x50; // 参数字节 (FSDI=5, CID=0)
tpdu.SendLength = 2;
tpdu.Timeout = 160; // 超时时间
result = FM176XX_TPDU(&tpdu);
if (result == SUCCESS)
{
*ats_len = tpdu.ReceiveLength;
memcpy(ats, tpdu.pReceiveBuffer, *ats_len);
}
return (result);
}
/**
* @brief 解析ATS (Answer to Select) 数据。
* @param ats_len [in] ATS数据的长度。
* @param ats [in] 指向ATS数据的指针。
* @return 操作状态SUCCESS表示成功。
* @details
* 此函数从ATS响应中提取关键参数如FSC (Frame Size for proximity coupling)、
* FWI (Frame Waiting time Integer)等,并存储在全局的 `CPU_CARD` 结构体中。
*/
unsigned char Ats_Process(unsigned char ats_len, unsigned char *ats)
{
unsigned char offset;
if (ats_len < 2) return FAIL;
// 解析FSCI (Frame Size for proximity coupling Integer) -> FSC
CPU_CARD.FSCI = ats[1] & 0x0F;
switch(CPU_CARD.FSCI) {
case 0: CPU_CARD.FSC = 16; break;
case 1: CPU_CARD.FSC = 24; break;
case 2: CPU_CARD.FSC = 32; break;
case 3: CPU_CARD.FSC = 40; break;
case 4: CPU_CARD.FSC = 48; break;
case 5: CPU_CARD.FSC = 64; break;
case 6: CPU_CARD.FSC = 96; break;
case 7: CPU_CARD.FSC = 128; break;
case 8: CPU_CARD.FSC = 256; break;
default: CPU_CARD.FSC = 32; break; // 默认值
}
xlog("-> CPU_CARD.FSC = %d\r\n", CPU_CARD.FSC);
offset = 0;
if (ats[1] & BIT4) // TA(1) present
{
CPU_CARD.TA = ats[2];
offset++;
}
if (ats[1] & BIT5) // TB(1) present
{
CPU_CARD.TB = ats[2 + offset];
CPU_CARD.SFGI = CPU_CARD.TB & 0x0F;
CPU_CARD.FWI = (CPU_CARD.TB >> 4) & 0x0F;
xlog("-> CPU_CARD.SFGI = %02X\r\n", CPU_CARD.SFGI);
xlog("-> CPU_CARD.FWI = %02X\r\n", CPU_CARD.FWI);
// 根据FWI计算FWT (Frame Waiting Time)
unsigned long base_fwt = 256 * 16 / 13560; // (256 * 16 / fc) in ms
CPU_CARD.FWT = base_fwt * (1 << CPU_CARD.FWI);
offset++;
} else {
CPU_CARD.FWT = 160; // 默认FWT
}
if (ats[1] & BIT6) // TC(1) present
{
CPU_CARD.TC = ats[2 + offset];
offset++;
}
CPU_CARD.PCB = 0x02; // PCB初始值为0x02
return SUCCESS;
}
/**
* @brief 发送NAK (Negative Acknowledge) 响应。
* @param tpdu [in, out] 指向传输结构体的指针。
* @return 操作状态。
* @details
* 在TPDU交换中如果接收到错误的数据块会发送NAK请求重发。
*/
unsigned char CPU_NAK(transmission_struct *tpdu)
{
unsigned char result, tpdu_send_buffer[1], tpdu_receive_buffer[255];
tpdu->pSendBuffer = tpdu_send_buffer;
tpdu->pReceiveBuffer = tpdu_receive_buffer;
tpdu->pSendBuffer[0] = 0xB0 | CPU_CARD.PCB; // NAK PCB
tpdu->SendLength = 1;
result = FM176XX_TPDU(tpdu);
return (result);
}
/**
* @brief 封装了重试逻辑的TPDU传输函数。
* @param tpdu [in, out] 指向传输结构体的指针。
* @return 操作状态。
* @details
* 此函数调用底层的 `FM176XX_TPDU`并在失败时进行最多3次重试。
* 它还处理ACK/NAK逻辑以确保数据的可靠传输。
*/
unsigned char CPU_TPDU(transmission_struct *tpdu)
{
unsigned char result, i, pcb_byte;
transmission_struct nak_tpdu;
result = FM176XX_TPDU(tpdu);
for (i = 0; i < 3; i++)
{
if (result != SUCCESS)
{
result = CPU_NAK(&nak_tpdu);
if(result == SUCCESS && nak_tpdu.ReceiveLength > 0)
{
memcpy(&pcb_byte, nak_tpdu.pReceiveBuffer, 1);
if((pcb_byte & 0xF0) == 0xA0) // R(ACK)
{
xlog("...pcb_byte = %02X\r\n", pcb_byte);
xlog("...CPU_CARD.PCB = %02X\r\n", CPU_CARD.PCB);
if((pcb_byte & 0x01) != (CPU_CARD.PCB & 0x01))
{
result = FM176XX_TPDU(tpdu);
}
else
{
tpdu->pSendBuffer[0] ^= 0x01; // 翻转序列号位
CPU_CARD.PCB = tpdu->pSendBuffer[0] & 0x01;
result = FM176XX_TPDU(tpdu);
}
}
}
}
else
{
break; // 成功则退出循环
}
}
return (result);
}
/**
* @brief 发送APDU (Application Protocol Data Unit) 命令。
* @param apdu [in, out] 指向传输结构体的指针包含APDU命令和响应。
* @return 操作状态。
* @details
* 此函数处理APDU的块链接chaining逻辑。如果APDU长度超过卡片的最大帧大小FSC
* 它会自动将APDU分割成多个TPDU块进行传输。
*/
unsigned char CPU_APDU(transmission_struct *apdu)
{
unsigned char result, pcb_byte, i;
unsigned char tpdu_send_buffer[256], tpdu_receive_buffer[256];
unsigned int unsent_length;
transmission_struct tpdu;
tpdu.pSendBuffer = tpdu_send_buffer;
tpdu.pReceiveBuffer = tpdu_receive_buffer;
tpdu.Timeout = CPU_CARD.FWT;
apdu->ReceiveLength = 0;
unsent_length = apdu->SendLength;
// --- 发送阶段 ---
for (i = 0; i < 16; i++) // 最多16个链式块
{
xlog("unsent_length = %d\r\n", unsent_length);
if (unsent_length <= (CPU_CARD.FSC - 1))
{
// 最后一个或唯一的数据块
tpdu.pSendBuffer[0] = CPU_CARD.PCB; // I-Block, no chaining
memcpy(tpdu.pSendBuffer + 1, apdu->pSendBuffer + apdu->SendLength - unsent_length, unsent_length);
tpdu.SendLength = unsent_length + 1;
xlog("--> ");
for(int j=0; j<tpdu.SendLength; j++) xlog("%02X", tpdu.pSendBuffer[j]);
xlog("\r\n");
result = CPU_TPDU(&tpdu);
if ((result != SUCCESS) || (tpdu.ReceiveLength == 0))
return (result);
xlog("<-- ");
for(int j=0; j<tpdu.ReceiveLength; j++) xlog("%02X", tpdu.pReceiveBuffer[j]);
xlog("\r\n");
unsent_length = 0;
break; // 发送完成
}
else
{
// 需要分块传输
tpdu.pSendBuffer[0] = CPU_CARD.PCB | 0x10; // I-Block with chaining
memcpy(tpdu.pSendBuffer + 1, apdu->pSendBuffer + apdu->SendLength - unsent_length, CPU_CARD.FSC - 1);
tpdu.SendLength = CPU_CARD.FSC;
xlog("..--> ");
for(int j=0; j<tpdu.SendLength; j++) xlog("%02X", tpdu.pSendBuffer[j]);
xlog("\r\n");
result = CPU_TPDU(&tpdu);
xlog("<-- ");
for(int j=0; j<tpdu.ReceiveLength; j++) xlog("%02X", tpdu.pReceiveBuffer[j]);
xlog("\r\n");
if ((result != SUCCESS) || (tpdu.ReceiveLength != 1))
return (result);
memcpy(&pcb_byte, tpdu.pReceiveBuffer, 1);
if ((pcb_byte & 0xE0) == 0xA0) // R(ACK) block
{
unsent_length -= (CPU_CARD.FSC - 1);
CPU_CARD.PCB = (pcb_byte & 0x01) ^ 0x01; // 更新序列号
xlog("unsent_length = %d\r\n", unsent_length);
}
else
{
return (FAIL); // 未收到预期的ACK
}
}
}
// --- 接收阶段 ---
for (i = 0; i < 255; i++) // 最多255个链式块
{
if ((result != SUCCESS) || (tpdu.ReceiveLength == 0))
return (FAIL);
memcpy(&pcb_byte, tpdu.pReceiveBuffer, 1);
if ((pcb_byte & 0xC0) == 0x00) // I-Block
{
CPU_CARD.PCB = (pcb_byte & 0x01) ^ 0x01;
memcpy(apdu->pReceiveBuffer + apdu->ReceiveLength, tpdu.pReceiveBuffer + 1, tpdu.ReceiveLength - 1);
apdu->ReceiveLength += (tpdu.ReceiveLength - 1);
if (pcb_byte & 0x10) // 还有后续数据块
{
tpdu.pSendBuffer[0] = 0xA0 | CPU_CARD.PCB; // 发送ACK
tpdu.SendLength = 1;
xlog("...--> ACK = %02X\r\n", tpdu.pSendBuffer[0]);
result = CPU_TPDU(&tpdu);
}
else // 最后一个数据块
{
return SUCCESS;
}
}
else if ((pcb_byte & 0xE0) == 0xE0) // S-Block (WTX)
{
// 回复WTX响应
memcpy(tpdu.pSendBuffer, tpdu.pReceiveBuffer, tpdu.ReceiveLength);
tpdu.SendLength = tpdu.ReceiveLength;
xlog("....--> WTX = ");
for(int j=0; j<tpdu.SendLength; j++) xlog("%02X", tpdu.pSendBuffer[j]);
xlog("\r\n");
result = CPU_TPDU(&tpdu);
}
else
{
return FAIL; // 未知响应
}
}
return (FAIL); // 接收块过多
}

View File

@ -0,0 +1,455 @@
#include "../include/MIFARE.h"
#include "../include/READER.h"
#include "../include/READER_REG.h"
#include "../include/rfid_main.h"
#include "../rfid_hal.h"
#define FUN_ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if FUN_ENABLE_XLOG
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
unsigned char SECTOR,BLOCK,BLOCK_NUM;
unsigned char BLOCK_DATA[16];
unsigned char KEY_A[16][6]=
{{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//0
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//1
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//2
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//3
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//4
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//5
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//6
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//7
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//8
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//9
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//10
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//11
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//12
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//13
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//14
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};//15
unsigned char KEY_B[16][6]=
{{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//0
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//1
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//2
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//3
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//4
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//5
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//6
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//7
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//8
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//9
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//10
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//11
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//12
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//13
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},//14
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};//15
/**
* @brief 清除Mifare卡加密认证标志。
* @details
* 在对Mifare卡进行认证Authentication芯片内部会设置一个加密标志位BIT_CRYPTO1ON
* 此函数用于清除该标志,以便可以对新的扇区进行认证或执行非加密操作。
* @return 无。
*/
void Mifare_Clear_Crypto(void)
{
ModifyReg(REG_STATUS,BIT_CRYPTO1ON,RESET);
return;
}
/**
* @brief Mifare卡事件处理函数示例
* @details
* 这是一个示例函数演示了对Mifare Classic卡进行读写操作的完整流程
* 1. 清除加密状态。
* 2. 对指定的扇区例如扇区1使用密钥A进行认证。
* 3. 如果认证成功则遍历该扇区的数据块块0到块2
* 4. 对每个块先执行写操作写入16字节的0xFF。
* 5. 然后再执行读操作,将数据读回并打印。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char MIFARE_CARD_EVENT(void)
{
unsigned char result;
int i;
Mifare_Clear_Crypto();
SECTOR = 1;
//for(SECTOR = 0;SECTOR < 16; SECTOR++)
{
BLOCK_NUM = (SECTOR * 4) + BLOCK;
result = Mifare_Auth(KEY_A_M1,SECTOR,KEY_A[SECTOR],PICC_A.UID);
if(result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> AUTH ERROR!\r\n");
return result;
}
xlog("-> AUTH SUCCESS!\r\n");
for(BLOCK = 0;BLOCK < 3;BLOCK++)
{
BLOCK_NUM = (SECTOR * 4) + BLOCK;
if(BLOCK_NUM == 0)
BLOCK_NUM = 1;
xlog("-> SECTOR = %02X\r\n",SECTOR);;
xlog("-> BLOCK = %02X\r\n",BLOCK);
xlog("-> BLOCK_NUM = %02X\r\n",BLOCK_NUM);
memcpy(BLOCK_DATA,"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",16);
result = Mifare_Blockwrite(BLOCK_NUM,BLOCK_DATA);
if(result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> WRITE BLOCK ERROR!\r\n");
return result;
}
xlog("-> WRITE BLOCK SUCCESS!\r\n");
result = Mifare_Blockread(BLOCK_NUM,BLOCK_DATA);
if(result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> READ BLOCK ERROR!\r\n");
return result;
}
xlog("-> READ BLOCK = ");
for(i=0; i<16; i++) xlog("%02X", BLOCK_DATA[i]);
xlog("\r\n");
}
}
SetCW(FUN_DISABLE);
return result;
}
/**
* @brief 将6字节的Mifare密钥加载到芯片的密钥缓冲区。
* @param mifare_key [in] 指向6字节密钥数组的指针。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
* @details
* 在执行认证命令Mifare_Auth之前必须先调用此函数将要使用的密钥加载到芯片内部。
*/
unsigned char Mifare_LoadKey(unsigned char *mifare_key)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,FUN_ENABLE); //Clear FIFO
SetReg(REG_FIFODATA,mifare_key[0]);
SetReg(REG_FIFODATA,mifare_key[1]);
SetReg(REG_FIFODATA,mifare_key[2]);
SetReg(REG_FIFODATA,mifare_key[3]);
SetReg(REG_FIFODATA,mifare_key[4]);
SetReg(REG_FIFODATA,mifare_key[5]);
SetCommand(CMD_LOADKEY);
rfid_delay_ms(1);
GetReg(REG_COMMAND,&reg_data);
if((reg_data & CMD_MASK) == CMD_IDLE)
return SUCCESS;
else
return FAIL;
}
/**
* @brief 对Mifare Classic卡片的指定扇区进行认证。
* @param key_mode [in] 认证模式,`KEY_A_M1` (0) 表示使用密钥A`KEY_B_M1` (1) 表示使用密钥B。
* @param sector [in] 要认证的扇区号 (0-15)。
* @param mifare_key [in] 指向6字节认证密钥的指针。
* @param card_uid [in] 指向4字节卡片UID的指针。
* @return 操作状态SUCCESS表示认证成功FAIL表示失败。
* @details
* 这是访问Mifare卡数据块之前的必要步骤。认证成功后芯片会设置加密标志位。
*/
unsigned char Mifare_Auth(unsigned char key_mode,unsigned char sector,unsigned char *mifare_key,unsigned char *card_uid)
{
unsigned char result,reg_data;
result = Mifare_LoadKey(mifare_key);
if (result != SUCCESS)
return result;
SetCommand(CMD_IDLE);
ModifyReg(REG_FIFOCONTROL,BIT_FIFOFLUSH,FUN_ENABLE); //Clear FIFO
if(key_mode == KEY_A_M1)
{
SetReg(REG_FIFODATA,0x60);// 0x60: Key A认证指令
ModifyReg(REG_RXTXCON,BIT_SHMODE,FUN_DISABLE);
}
if(key_mode == KEY_B_M1)
{
SetReg(REG_FIFODATA,0x61);// 0x61: Key B认证指令
ModifyReg(REG_RXTXCON,BIT_SHMODE,FUN_DISABLE);
}
SetReg(REG_FIFODATA,sector * 4);// 认证扇区的块0地址
SetReg(REG_FIFODATA,card_uid[0]);
SetReg(REG_FIFODATA,card_uid[1]);
SetReg(REG_FIFODATA,card_uid[2]);
SetReg(REG_FIFODATA,card_uid[3]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_ENABLE);
SetCommand(CMD_AUTHENT);
rfid_delay_ms(5);
GetReg(REG_COMMAND,&reg_data);
if((reg_data & CMD_MASK) == CMD_IDLE)
{
GetReg(REG_STATUS,&reg_data);
if(reg_data & BIT_CRYPTO1ON)// 检查加密标志位以确认认证成功
return SUCCESS;
}
return FAIL;
}
/**
* @brief 将4字节数据格式化为Mifare值块格式并写入指定块。
* @param block [in] 目标块号。
* @param data_buff [in] 指向4字节源数据的指针。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
* @details
* Mifare值块有特定的数据格式包含值、值的反码和地址字节。此函数会自动处理格式转换。
*/
unsigned char Mifare_Blockset(unsigned char block,unsigned char *data_buff)
{
unsigned char block_data[16],result;
// 格式化为值块
block_data[0] = data_buff[3];
block_data[1] = data_buff[2];
block_data[2] = data_buff[1];
block_data[3] = data_buff[0];
block_data[4] = ~data_buff[3];
block_data[5] = ~data_buff[2];
block_data[6] = ~data_buff[1];
block_data[7] = ~data_buff[0];
block_data[8] = data_buff[3];
block_data[9] = data_buff[2];
block_data[10] = data_buff[1];
block_data[11] = data_buff[0];
block_data[12] = block;
block_data[13] = ~block;
block_data[14] = block;
block_data[15] = ~block;
result = Mifare_Blockwrite(block,block_data);
return result;
}
/**
* @brief 从Mifare卡读取一个16字节的数据块。
* @param block [in] 要读取的块号 (0x00 - 0x3F)。
* @param data_buff [out] 指向16字节缓冲区的指针用于存储读取的数据。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char Mifare_Blockread(unsigned char block,unsigned char *data_buff)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0x30);// 0x30: 读块指令
SetReg(REG_FIFODATA,block);// 块地址
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(2);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 16) // 成功时应返回16字节数据
return FAIL;
GetReg(REG_ERROR,&reg_data);
if(reg_data & 0x07)
return FAIL;
for(i=0;i<16;i++)
{
GetReg (REG_FIFODATA,&data_buff[i]);
}
return SUCCESS;
}
/**
* @brief 向Mifare卡写入一个16字节的数据块。
* @param block [in] 要写入的块号 (0x00 - 0x3F)。
* @param data_buff [in] 指向16字节数据的指针。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char Mifare_Blockwrite(unsigned char block,unsigned char *data_buff)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0xA0);// 0xA0: 写块指令
SetReg(REG_FIFODATA,block);// 块地址
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1) // 接收到ACK (0x0A)
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
for(i=0;i<16;i++)
{
SetReg(REG_FIFODATA,data_buff[i]);
}
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1) // 接收到ACK (0x0A)
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}
/**
* @brief 对Mifare卡的指定值块执行增值操作。
* @param block [in] 值块的块号。
* @param data_buff [in] 指向4字节增值数据的指针。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char Mifare_Blockinc(unsigned char block,unsigned char *data_buff)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0xC1);// 0xC1: 增值指令
SetReg(REG_FIFODATA,block);// 块地址
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1)
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
for(i=0;i<4;i++)
{
SetReg(REG_FIFODATA,data_buff[i]);
}
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1)
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}
/**
* @brief 对Mifare卡的指定值块执行减值操作。
* @param block [in] 值块的块号。
* @param data_buff [in] 指向4字节减值数据的指针。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char Mifare_Blockdec(unsigned char block,unsigned char *data_buff)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0xC0);// 0xC0: 减值指令
SetReg(REG_FIFODATA,block);// 块地址
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1)
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
for(i=0;i<4;i++)
{
SetReg(REG_FIFODATA,data_buff[i]);
}
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1)
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}
/**
* @brief 执行Mifare卡的传输Transfer命令。
* @param block [in] 块号。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
* @details
* 在对值块进行增/减值操作后,需要调用此函数将结果从内部寄存器写入到块中。
*/
unsigned char Mifare_Transfer(unsigned char block)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0xB0);// 0xB0: Transfer指令
SetReg(REG_FIFODATA,block);// 块地址
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1)
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}
/**
* @brief 执行Mifare卡的恢复Restore命令。
* @param block [in] 块号。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
* @details
* 此命令用于将一个块的内容从内部寄存器中恢复。
*/
unsigned char Mifare_Restore(unsigned char block)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM,0x08);
SetReg(REG_FIFODATA,0xC2);// 0xC2: Restore指令
SetReg(REG_FIFODATA,block);// 块地址
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1)
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
for(i=0;i<4;i++)
{
SetReg(REG_FIFODATA,0);
}
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if (reg_data != 1)
return FAIL;
GetReg (REG_FIFODATA,&reg_data);
if(reg_data != 0x0A)
return FAIL;
return SUCCESS;
}

View File

@ -0,0 +1,108 @@
#include "../include/READER.h"
#include "../include/NTAG.h"
#include "../include/READER_REG.h"
#include "../include/rfid_main.h"
#include "../rfid_hal.h"
#define FUN_ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if FUN_ENABLE_XLOG
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
unsigned char PAGE_DATA[16];
/**
* @brief NTAG卡事件处理函数示例
* @details
* 这是一个示例函数演示了对NTAG系列卡片进行读写操作的流程
* 1. 准备要写入的数据4字节
* 2. 调用 `Write_Page()` 函数将数据写入第8页。
* 3. 调用 `Read_Page()` 函数从第8页读回数据并打印以进行验证。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char NTAG_EVENT(void)
{
unsigned char result;
memcpy(PAGE_DATA,"\x01\x02\x03\x04",4);
result = Write_Page(8,PAGE_DATA);
if (result != SUCCESS)
return result;
xlog("PAGE 8 Write OK\r\n");
result = Read_Page(8,PAGE_DATA);
xlog("PAGE 8 = %02X%02X%02X%02X\r\n",PAGE_DATA[0],PAGE_DATA[1],PAGE_DATA[2],PAGE_DATA[3]);
return result;
}
/**
* @brief 从NTAG卡读取一个或多个页的数据。
* @param page_num [in] 要读取的起始页号。
* @param page_data [out] 指向缓冲区的指针用于存储读取的数据。对于NTAG21x系列一次最少读取16字节4页
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char Read_Page(unsigned char page_num,unsigned char *page_data)
{
unsigned char reg_data,i;
SetCommand(CMD_IDLE);
Clear_FIFO();
SetReg(REG_FIFODATA,0x30); // 读指令
SetReg(REG_FIFODATA,page_num);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(5);
GetReg(REG_ERROR,&reg_data);
if(reg_data & 0x07)
return FAIL;
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 16) // NTAG一次读取返回16字节
return FAIL;
for(i=0;i<16;i++)
{
GetReg(REG_FIFODATA,&page_data[i]);
}
return SUCCESS;
}
/**
* @brief 向NTAG卡的一个页Page写入4字节数据。
* @param page_num [in] 要写入的页号。
* @param page_data [in] 指向4字节数据的指针。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char Write_Page(unsigned char page_num,unsigned char *page_data)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
Clear_FIFO();
SetReg(REG_FIFODATA,0xA2); // 写指令
SetReg(REG_FIFODATA,page_num);
SetReg(REG_FIFODATA,page_data[0]);
SetReg(REG_FIFODATA,page_data[1]);
SetReg(REG_FIFODATA,page_data[2]);
SetReg(REG_FIFODATA,page_data[3]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN,FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN,FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(5);
GetReg(REG_FIFOLENGTH,&reg_data);
if(reg_data != 1) // 应该收到一个ACK
return FAIL;
GetReg(REG_FIFODATA,&reg_data);
if(reg_data != 0x0A) // ACK的值为0x0A
return FAIL;
return SUCCESS;
}

View File

@ -0,0 +1,784 @@
/********************************************************************************************************
* @file READER.c
* @brief RFID 读卡器底层驱动及协议实现
* @details
* 本文件实现了与FM176XX系列RFID芯片的底层通信协议。它包含以下功能
* - 控制芯片进入不同工作模式如Type A, B, V, F
* - 实现各种卡片类型的寻卡、防冲突、选择和数据交换命令。
* - 管理芯片的FIFO、定时器和RF场。
* 所有硬件相关的操作均通过 `rfid_hal.h` 中定义的接口完成。
********************************************************************************************************/
#include "../include/READER.h"
#include "../include/READER_REG.h"
#include "../include/rfid_main.h"
#include "../rfid_hal.h" // 引入硬件抽象层
#define FUN_ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if FUN_ENABLE_XLOG
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
// 定义全局变量以存储不同类型卡片的信息
struct picc_a_struct PICC_A;
struct picc_b_struct PICC_B;
struct picc_v_struct PICC_V;
struct picc_f_struct PICC_F;
/********************************************************************************************************
* 公共接口函数
********************************************************************************************************/
/**
* @brief 修改寄存器的特定位。
* @param reg_address [in] 目标寄存器的地址。
* @param mask [in] 要修改的位的掩码。
* @param set [in] 如果为非0则将掩码对应的位设置为1如果为0则清零。
* @return 无。
* @details
* 这是一个“读-改-写”操作。首先读取寄存器的当前值,然后根据掩码和`set`参数修改它,
* 最后将修改后的值写回寄存器。
*/
void ModifyReg(unsigned char reg_address, unsigned char mask, unsigned char set)
{
unsigned char reg_data;
GetReg(reg_address, &reg_data);
if (set)
{
reg_data |= mask;
}
else
{
reg_data &= ~mask;
}
SetReg(reg_address, reg_data);
}
/**
* @brief 向命令寄存器写入一个命令。
* @param command [in] 要执行的命令代码如CMD_IDLE, CMD_TRANSCEIVE等
* @return 操作状态SUCCESS表示成功。
*/
unsigned char SetCommand(unsigned char command)
{
return SetReg(REG_COMMAND, CMD_MASK & command);
}
/**
* @brief 设置芯片内部定时器的超时时间。
* @param timeout [in] 超时时间,单位为毫秒(ms)。
* @return 无。
* @details
* 根据输入的超时时间计算合适的预分频值和重载值并配置T0和T1定时器。
* 这用于在收发数据时进行超时检测。
*/
void SetTimer(unsigned int timeout)
{
unsigned long prescale = 1;
unsigned long t, fc;
fc = timeout * 13560; // 13.56MHz时钟频率
t = fc;
while (fc > 65535)
{
prescale *= 2;
fc = t / prescale;
if (fc * prescale != t)
fc++;
}
if (prescale > 1)
{
SetReg(REG_T0CONTROL, BIT_TSTOP_RX | BIT_TSTART_TX | BIT_TAUTORESTARTED | VALUE_TCLK_1356_MHZ);
SetReg(REG_T0RELOADHI, (unsigned char)(fc >> 8));
SetReg(REG_T0RELOADLO, (unsigned char)fc);
SetReg(REG_T1CONTROL, BIT_TSTOP_RX | BIT_TSTART_TX | VALUE_TCLK_T0);
SetReg(REG_T1RELOADHI, (unsigned char)(prescale >> 8));
SetReg(REG_T1RELOADLO, (unsigned char)prescale);
}
else
{
SetReg(REG_T1CONTROL, BIT_TSTOP_RX | BIT_TSTART_TX | VALUE_TCLK_1356_MHZ);
SetReg(REG_T1RELOADHI, (unsigned char)(fc >> 8));
SetReg(REG_T1RELOADLO, (unsigned char)fc);
}
}
/**
* @brief 打开或关闭RF场载波
* @param mode [in] FUN_ENABLE表示打开FUN_DISABLE表示关闭。
* @return 操作状态SUCCESS表示成功。
*/
unsigned char SetCW(unsigned char mode)
{
if (mode == FUN_ENABLE)
{
ModifyReg(REG_COMMAND, BIT_MODEMOFF, FUN_DISABLE);
ModifyReg(REG_TXMODE, BIT_TPUSHON | BIT_TPULLON, FUN_ENABLE);
}
else
{
ModifyReg(REG_COMMAND, BIT_MODEMOFF, FUN_ENABLE);
ModifyReg(REG_TXMODE, BIT_TPUSHON | BIT_TPULLON, FUN_DISABLE);
}
rfid_delay_ms(10);
return SUCCESS;
}
/**
* @brief 清空芯片内部的FIFO缓冲区。
* @return 无。
*/
void Clear_FIFO(void)
{
unsigned char fifolength;
GetReg(REG_FIFOLENGTH, &fifolength);
if (fifolength != 0)
{
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
}
}
/**
* @brief 加载指定的通信协议参数到芯片。
* @param p_rx [in] 接收协议代码。
* @param p_tx [in] 发送协议代码。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
* @details
* 不同的卡片类型A, B, V, F使用不同的通信速率和编码方式
* 此函数用于将这些协议参数加载到芯片中。
*/
unsigned char LoadProtocol(unsigned char p_rx, unsigned char p_tx)
{
unsigned char reg_data = 0;
SetCommand(CMD_IDLE);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE); // 清空FIFO
SetReg(REG_FIFODATA, p_rx); // 写入接收协议
SetReg(REG_FIFODATA, p_tx); // 写入发送协议
SetCommand(CMD_LOADPROTOCOL);
rfid_delay_ms(2);
GetReg(REG_COMMAND, &reg_data);
if (reg_data != CMD_IDLE)
return FAIL;
return SUCCESS;
}
/**
* @brief 设置发送和接收的奇偶校验位使能状态。
* @param state [in] FUN_ENABLE或FUN_DISABLE。
* @return 无。
*/
void SetParity(unsigned char state)
{
ModifyReg(REG_FRAMECON, BIT_TXPARITYEN | BIT_RXPARITYEN, state);
}
/**
* @brief 初始化读卡器以支持Type A卡片。
* @return 操作状态SUCCESS表示成功。
*/
unsigned char ReaderA_Initial(void)
{
LoadProtocol(RX_TYPEA_106, TX_TYPEA_106);
ModifyReg(REG_TXMODE, BIT_RFON, FUN_ENABLE); // FORCE 100ask FUN_ENABLE
SetReg(REG_TXAMP, AMPLITUDE_A);
SetReg(REG_TXCON, 0x00);
SetReg(REG_RXANA, (HPCF_A << 3) | GAIN_A);
SetReg(0x5F, 0x08);
SetReg(REG_THNSET, 0xFF);
SetReg(REG_THNMIN, 0xC0);
SetReg(REG_RXTXCON, 0x80);
SetParity(FUN_ENABLE);
SetReg(REG_STATUS, 0); // 清除Crypto1On位
return SUCCESS;
}
/**
* @brief 初始化读卡器以支持Type B卡片。
* @return 操作状态SUCCESS表示成功。
*/
unsigned char ReaderB_Initial(void)
{
LoadProtocol(RX_TYPEB_106, TX_TYPEB_106);
ModifyReg(REG_TXMODE, BIT_RFON, FUN_DISABLE); // FORCE 100ask FUN_DISABLE
SetReg(REG_TXAMP, AMPLITUDE_B);
SetReg(REG_TXCON, MODULATION_B);
SetReg(REG_RXANA, (HPCF_B << 3) | GAIN_B);
SetReg(0x5F, 0x08);
SetReg(REG_THNSET, 0xFF);
SetReg(REG_THNMIN, 0xC0);
SetReg(REG_RXTXCON, 0x80);
return SUCCESS;
}
/**
* @brief 初始化读卡器以支持Type V (ISO15693) 卡片。
* @return 操作状态SUCCESS表示成功。
*/
unsigned char ReaderV_Initial(void)
{
LoadProtocol(RX_TYPEV_26, RX_TYPEV_26);
ModifyReg(REG_RXANA, MASK_RCV_GAIN | MASK_RCV_HPCF, FUN_DISABLE);
ModifyReg(REG_RXANA, (HPCF_V << 3) | GAIN_V, FUN_ENABLE);
SetParity(FUN_DISABLE);
SetReg(REG_TXAMP, AMPLITUDE_V);
SetReg(REG_TXCON, MODULATION_V);
SetReg(REG_TXI, 0x06);
SetReg(REG_THNSET, 0xFF);
SetReg(REG_THNMIN, 0x80);
SetReg(REG_THNADJ, 0x08);
SetReg(REG_RXTXCON, 0);
return SUCCESS;
}
/**
* @brief 初始化读卡器以支持Type F (FeliCa) 卡片。
* @return 操作状态SUCCESS表示成功。
*/
unsigned char ReaderF_Initial(void)
{
ModifyReg(REG_MISC, 0x04, FUN_ENABLE);
LoadProtocol(RX_FELICA_212, TX_FELICA_212);
SetReg(REG_TXAMP, AMPLITUDE_F);
SetReg(REG_TXCON, MODULATION_F);
ModifyReg(REG_RXANA, MASK_RCV_GAIN | MASK_RCV_HPCF, FUN_DISABLE);
ModifyReg(REG_RXANA, (HPCF_F << 3) | GAIN_F, FUN_ENABLE);
SetParity(FUN_DISABLE);
SetReg(REG_THNSET, 0xFF);
SetReg(REG_THNMIN, 0x80);
SetReg(REG_THNADJ, 0x08);
ModifyReg(REG_MISC, 0x04, FUN_DISABLE);
return SUCCESS;
}
/**
* @brief 向Type A卡片发送WUPAWake-Up A命令。
* @param picc_a [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderA_Wakeeup(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x0F);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, RF_CMD_WUPA);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_DISABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(2);
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 2)
return FAIL;
GetReg(REG_FIFODATA, &picc_a->ATQA[0]);
GetReg(REG_FIFODATA, &picc_a->ATQA[1]);
return SUCCESS;
}
/**
* @brief 向Type A卡片发送REQARequest A命令。
* @param picc_a [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderA_Request(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x0F);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, RF_CMD_REQA);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_DISABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(2);
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 2)
return FAIL;
GetReg(REG_FIFODATA, &picc_a->ATQA[0]);
GetReg(REG_FIFODATA, &picc_a->ATQA[1]);
return SUCCESS;
}
/**
* @brief 执行Type A卡片的防冲突流程。
* @param picc_a [in, out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderA_Anticoll(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, RF_CMD_ANTICOLL[picc_a->CASCADE_LEVEL]);
SetReg(REG_FIFODATA, 0x20);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_DISABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_DISABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(2);
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 5)
return FAIL;
GetReg(REG_FIFODATA, &picc_a->UID[picc_a->CASCADE_LEVEL * 4]);
GetReg(REG_FIFODATA, &picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 1]);
GetReg(REG_FIFODATA, &picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 2]);
GetReg(REG_FIFODATA, &picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 3]);
GetReg(REG_FIFODATA, &picc_a->BCC[picc_a->CASCADE_LEVEL]);
if ((picc_a->UID[picc_a->CASCADE_LEVEL * 4] ^ picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 1] ^ picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 2] ^ picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 3]) == picc_a->BCC[picc_a->CASCADE_LEVEL])
return SUCCESS;
return FAIL;
}
/**
* @brief 选择一个已经过防冲突的Type A卡片。
* @param picc_a [in, out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderA_Select(struct picc_a_struct *picc_a)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, RF_CMD_ANTICOLL[picc_a->CASCADE_LEVEL]);
SetReg(REG_FIFODATA, 0x70);
SetReg(REG_FIFODATA, picc_a->UID[picc_a->CASCADE_LEVEL * 4]);
SetReg(REG_FIFODATA, picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 1]);
SetReg(REG_FIFODATA, picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 2]);
SetReg(REG_FIFODATA, picc_a->UID[picc_a->CASCADE_LEVEL * 4 + 3]);
SetReg(REG_FIFODATA, picc_a->BCC[picc_a->CASCADE_LEVEL]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(2);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &picc_a->SAK[picc_a->CASCADE_LEVEL]);
return SUCCESS;
}
/**
* @brief 激活Type A卡片完成REQA, Anticoll, Select全过程
* @param picc_a [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderA_CardActivate(struct picc_a_struct *picc_a)
{
unsigned char result, cascade_level;
result = ReaderA_Request(picc_a);
if (result != SUCCESS)
return result;
if ((picc_a->ATQA[0] & 0xC0) == 0x00) // 单倍UID
{
cascade_level = 1;
picc_a->UID_Length = 4;
}
else if ((picc_a->ATQA[0] & 0xC0) == 0x40) // 双倍UID
{
cascade_level = 2;
picc_a->UID_Length = 7; // 实际是7字节
}
else if ((picc_a->ATQA[0] & 0xC0) == 0x80) // 三倍UID
{
cascade_level = 3;
picc_a->UID_Length = 10; // 实际是10字节
}
else
{
return FAIL; // 未知UID长度
}
for (picc_a->CASCADE_LEVEL = 0; picc_a->CASCADE_LEVEL < cascade_level; picc_a->CASCADE_LEVEL++)
{
result = ReaderA_Anticoll(picc_a);
if (result != SUCCESS)
return result;
result = ReaderA_Select(picc_a);
if (result != SUCCESS)
return result;
}
picc_a->CASCADE_LEVEL--;
return result;
}
/**
* @brief 向Type B卡片发送WUPBWake-Up B命令。
* @param picc_b [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderB_Wakeup(struct picc_b_struct *picc_b)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x05); // APf
SetReg(REG_FIFODATA, 0x00); // AFI (00:for all cards)
SetReg(REG_FIFODATA, 0x08); // PARAM(WUPB, Number of slots = 0)
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 12)
return FAIL;
for (i = 0; i < 12; i++)
GetReg(REG_FIFODATA, &picc_b->ATQB[i]);
memcpy(picc_b->PUPI, picc_b->ATQB + 1, 4);
memcpy(picc_b->APPLICATION_DATA, picc_b->ATQB + 6, 4);
memcpy(picc_b->PROTOCOL_INF, picc_b->ATQB + 10, 3);
return SUCCESS;
}
/**
* @brief 向Type B卡片发送REQBRequest B命令。
* @param picc_b [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderB_Request(struct picc_b_struct *picc_b)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x05); // APf
SetReg(REG_FIFODATA, 0x00); // AFI (00:for all cards)
SetReg(REG_FIFODATA, 0x00); // PARAM(REQB, Number of slots = 0)
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 12)
return FAIL;
for (i = 0; i < 12; i++)
GetReg(REG_FIFODATA, &picc_b->ATQB[i]);
memcpy(picc_b->PUPI, picc_b->ATQB + 1, 4);
memcpy(picc_b->APPLICATION_DATA, picc_b->ATQB + 6, 4);
memcpy(picc_b->PROTOCOL_INF, picc_b->ATQB + 10, 3);
return SUCCESS;
}
/**
* @brief 向Type B卡片发送ATTRIB命令以选择卡片并设置通信参数。
* @param picc_b [in, out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderB_Attrib(struct picc_b_struct *picc_b)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x1D);
SetReg(REG_FIFODATA, picc_b->PUPI[0]);
SetReg(REG_FIFODATA, picc_b->PUPI[1]);
SetReg(REG_FIFODATA, picc_b->PUPI[2]);
SetReg(REG_FIFODATA, picc_b->PUPI[3]);
SetReg(REG_FIFODATA, 0x00); // Param1
SetReg(REG_FIFODATA, 0x08); // Param2
SetReg(REG_FIFODATA, 0x01); // COMPATIBLE WITH 14443-4
SetReg(REG_FIFODATA, 0x01); // CID:01
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &reg_data);
picc_b->CID = reg_data & 0x0F;
return SUCCESS;
}
/**
* @brief 向Type B卡片发送HALT命令使其进入休眠状态。
* @param picc_b [in, out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderB_Halt(struct picc_b_struct *picc_b)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x50);
SetReg(REG_FIFODATA, picc_b->PUPI[0]);
SetReg(REG_FIFODATA, picc_b->PUPI[1]);
SetReg(REG_FIFODATA, picc_b->PUPI[2]);
SetReg(REG_FIFODATA, picc_b->PUPI[3]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &reg_data);
*picc_b->Answer_to_HALT = reg_data & 0x0F;
return SUCCESS;
}
/**
* @brief 获取Type B卡片的序列号这是一个自定义命令非标准
* @param picc_b [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderB_Get_SN(struct picc_b_struct *picc_b)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x00);
SetReg(REG_FIFODATA, 0x36);
SetReg(REG_FIFODATA, 0x00);
SetReg(REG_FIFODATA, 0x00);
SetReg(REG_FIFODATA, 0x08);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 10)
return FAIL;
for (i = 0; i < 8; i++)
GetReg(REG_FIFODATA, &picc_b->SN[i]);
return SUCCESS;
}
/**
* @brief 向Type V (ISO15693) 卡片发送Inventory命令。
* @param picc_v [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderV_Inventory(struct picc_v_struct *picc_v)
{
unsigned char reg_data, i, result; // 新增 result 变量
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x26); // Corrected Inventory flag to indicate AFI is present
SetReg(REG_FIFODATA, 0x01);
SetReg(REG_FIFODATA, 0x00);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(50);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0){
xlog("REG_ERROR = 0x%02X\n", reg_data);
return FAIL;
}
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 10){
xlog("FIFO Length is %d, expected 10.\n", reg_data);
return FAIL;
}
GetReg(REG_FIFODATA, &picc_v->RESPONSE);
GetReg(REG_FIFODATA, &reg_data); // DSFID
for (i = 0; i < 8; i++)
{
GetReg(REG_FIFODATA, &picc_v->UID[i]);
// xlog("%d ",picc_v->UID[i]);
}
// xlog("\r\n");
return SUCCESS;
}
/**
* @brief 选择一个已获取UID的Type V卡片。
* @param picc_v [in, out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderV_Select(struct picc_v_struct *picc_v)
{
unsigned char reg_data, result;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x22); // Addressed flag
SetReg(REG_FIFODATA, 0x25); // Select command
SetReg(REG_FIFODATA, picc_v->UID[0]);
SetReg(REG_FIFODATA, picc_v->UID[1]);
SetReg(REG_FIFODATA, picc_v->UID[2]);
SetReg(REG_FIFODATA, picc_v->UID[3]);
SetReg(REG_FIFODATA, picc_v->UID[4]);
SetReg(REG_FIFODATA, picc_v->UID[5]);
SetReg(REG_FIFODATA, picc_v->UID[6]);
SetReg(REG_FIFODATA, picc_v->UID[7]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &picc_v->RESPONSE);
return SUCCESS;
}
/**
* @brief 读取Type V卡片的单个数据块。
* @param block_num [in] 要读取的块号。
* @param picc_v [out] 指向存储卡片信息的结构体,读取的数据将存入 `BLOCK_DATA`。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderV_ReadSingleBlock(unsigned char block_num, struct picc_v_struct *picc_v)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x02); // Addressed flag
SetReg(REG_FIFODATA, 0x20); // Read Single Block command
SetReg(REG_FIFODATA, block_num);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 5) // 1 byte response flag + 4 bytes data
return FAIL;
GetReg(REG_FIFODATA, &picc_v->RESPONSE);
for (i = 0; i < 4; i++)
{
GetReg(REG_FIFODATA, &picc_v->BLOCK_DATA[i]);
}
return SUCCESS;
}
/**
* @brief 向Type V卡片的单个数据块写入数据。
* @param block_num [in] 要写入的块号。
* @param picc_v [in] 指向存储卡片信息的结构体,要写入的数据在 `BLOCK_DATA` 中。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderV_WriteSingleBlock(unsigned char block_num, struct picc_v_struct *picc_v)
{
unsigned char reg_data;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x02); // Addressed flag
SetReg(REG_FIFODATA, 0x21); // Write Single Block command
SetReg(REG_FIFODATA, block_num);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[0]);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[1]);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[2]);
SetReg(REG_FIFODATA, picc_v->BLOCK_DATA[3]);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 1)
return FAIL;
GetReg(REG_FIFODATA, &picc_v->RESPONSE);
return SUCCESS;
}
/**
* @brief 向Type F (FeliCa) 卡片发送Inventory命令。
* @param picc_f [out] 指向存储卡片信息的结构体。
* @return 操作状态SUCCESS表示成功FAIL表示失败。
*/
unsigned char ReaderF_Inventory(struct picc_f_struct *picc_f)
{
unsigned char reg_data, i;
SetCommand(CMD_IDLE);
SetReg(REG_TXDATANUM, 0x08);
ModifyReg(REG_FIFOCONTROL, BIT_FIFOFLUSH, FUN_ENABLE);
SetReg(REG_FIFODATA, 0x06);
SetReg(REG_FIFODATA, 0x00);
SetReg(REG_FIFODATA, 0xFF);
SetReg(REG_FIFODATA, 0xFF);
SetReg(REG_FIFODATA, 0x10);
SetReg(REG_FIFODATA, 0x00);
ModifyReg(REG_TXCRCCON, BIT_CRCEN, FUN_ENABLE);
ModifyReg(REG_RXCRCCON, BIT_CRCEN, FUN_ENABLE);
SetCommand(CMD_TRANSCEIVE);
rfid_delay_ms(10);
GetReg(REG_ERROR, &reg_data);
if ((reg_data & 0x0F) != 0)
return FAIL;
GetReg(REG_FIFOLENGTH, &reg_data);
if (reg_data != 18)
return FAIL;
GetReg(REG_FIFODATA, &reg_data); // Length
GetReg(REG_FIFODATA, &reg_data); // Response code
for (i = 0; i < 8; i++)
{
GetReg(REG_FIFODATA, &picc_f->UID[i]);
}
return SUCCESS;
}

View File

@ -0,0 +1,305 @@
/********************************************************************************************************
* @file rfid_main.c
* @brief RFID 读卡器应用层主逻辑文件
********************************************************************************************************/
#include "./include/rfid_main.h"
#include "./include/READER.h"
#include "./include/READER_REG.h"
#include "./include/MIFARE.h"
#include "./include/NTAG.h"
#include "./include/CPU_CARD.h"
#include "./rfid_hal.h"
#define FUN_ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if FUN_ENABLE_XLOG
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
/**
* @brief 处理Type A卡片事件。uid8位数组
* @details
* 该函数执行ISO/IEC 14443 Type A卡片的完整激活流程包括
* 1. 初始化读卡器以支持Type A协议。
* 2. 打开RF场。
* 3. 请求Request和防冲突Anticollision最终激活卡片。
* 4. 根据卡片的SAKSelect Acknowledge判断卡片具体类型如Mifare, NTAG, CPU卡并调用相应的处理函数。
* 5. 操作结束后关闭RF场。
* @return 无。
*/
void TYPE_A_EVENT(char* uid)
{
unsigned char result;
int i;
xlog("TYPE_A_EVENT begin\n");
// 初始化读卡器为Type A模式
result = ReaderA_Initial();
if (result != SUCCESS)
{
xlog("INIT_ERROR\r\n");
SetCW(FUN_DISABLE);
return;
}
// 打开RF场载波
result = SetCW(FUN_ENABLE);
if (result != SUCCESS)
{
xlog("CW_ERROR\r\n");
SetCW(FUN_DISABLE);
return;
}
// 激活Type A卡片
result = ReaderA_CardActivate(&PICC_A);
if (result != SUCCESS)
{
xlog("ReaderA_CardActivate_ERROR\r\n");
SetCW(FUN_DISABLE);
return;
}
xlog("************* TYPE A CARD ************* \r\n");
xlog("-> ATQA = %02X%02X\r\n", PICC_A.ATQA[0], PICC_A.ATQA[1]);
if (PICC_A.UID_Length > 0)
{
xlog("-> UID = ");
for (i = 0; i < PICC_A.UID_Length; i++)
{
uid[i] = PICC_A.UID[i];
xlog("%02X", PICC_A.UID[i]);
}
xlog("\r\n");
}
xlog("-> SAK = %02X\r\n", PICC_A.SAK[0]);
// 根据SAK值判断卡片类型
if (PICC_A.SAK[0] == 0x08)
{
xlog("************* Mifare CARD ************* \r\n");
result = MIFARE_CARD_EVENT();
}
else if ((PICC_A.SAK[0] == 0x28) || (PICC_A.SAK[0] == 0x20))
{
xlog("************* CPU CARD ************* \r\n");
result = CPU_CARD_EVENT();
}
else if (PICC_A.SAK[0] == 0x04)
{
xlog("************* NTAG CARD ************* \r\n");
result = NTAG_EVENT();
}
SetCW(FUN_DISABLE); // 关闭RF场
}
/**
* @brief 处理Type B卡片事件。
* @details
* 该函数执行ISO/IEC 14443 Type B卡片的激活流程包括
* 1. 初始化读卡器以支持Type B协议。
* 2. 打开RF场。
* 3. 发送REQB/WUPB命令寻卡。
* 4. 发送ATTRIB命令选卡。
* 5. 获取卡片序列号SN
* 6. 操作结束后关闭RF场。
* @return 无。
*/
void TYPE_B_EVENT(void)
{
unsigned char result;
int i;
xlog("TYPE_B_EVENT begin\n");
ReaderB_Initial();
SetCW(FUN_ENABLE);
result = ReaderB_Request(&PICC_B);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
return;
}
xlog("************* TYPE B CARD ************* \r\n");
// 打印ATQB信息
xlog("-> ATQB = ");
for(i=0; i<12; i++) xlog("%02X", PICC_B.ATQB[i]);
xlog("\r\n");
result = ReaderB_Attrib(&PICC_B);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
return;
}
xlog("-> ATTRIB = %02X\r\n", PICC_B.CID);
result = ReaderB_Get_SN(&PICC_B);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
return;
}
xlog("-> SN = ");
for(i=0; i<8; i++) xlog("%02X", PICC_B.SN[i]);
xlog("\r\n");
SetCW(FUN_DISABLE);
}
/**
* @brief 处理Type V (ISO/IEC 15693) 卡片事件。
* @details
* 该函数执行ISO/IEC 15693 Vicinity卡片的交互流程包括
* 1. 初始化读卡器以支持15693协议。
* 2. 打开RF场。
* 3. 发送Inventory命令寻卡并获取UID。
* 4. 发送Select命令选择卡片。
* 5. 示例性地对第4块进行写操作然后再读回校验。
* 6. 操作结束后关闭RF场。
* @return 无。
*/
void TYPE_V_EVENT(char* uid)
{
unsigned char result, i;
xlog("TYPE_V_EVENT begin\n");
ReaderV_Initial();
SetCW(FUN_ENABLE);
result = ReaderV_Inventory(&PICC_V);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> ReaderV Inventory ERROR!\r\n");
return;
}
xlog("************* TYPE V CARD ************* \r\n");
xlog("UID=");
for (i = 0; i < 8; i++)
{
uid[i] = PICC_V.UID[i];
xlog("%02X", PICC_V.UID[i]);
}
xlog("\r\n");
result = ReaderV_Select(&PICC_V);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> ReaderV Select ERROR!\r\n");
return;
}
// 示例:写单个块
memcpy(PICC_V.BLOCK_DATA, "\x00\x00\x00\x00", 4);
result = ReaderV_WriteSingleBlock(4, &PICC_V);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> ReaderV WriteSingleBlock ERROR!\r\n");
return;
}
xlog("WriteSingleBlock SUCCESS\r\n");
// 示例:读单个块
result = ReaderV_ReadSingleBlock(4, &PICC_V);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
xlog("-> ReaderV ReadSingleBlock ERROR!\r\n");
return;
}
xlog("BLOCK DATA = %02X%02X%02X%02X \r\n", PICC_V.BLOCK_DATA[0], PICC_V.BLOCK_DATA[1], PICC_V.BLOCK_DATA[2], PICC_V.BLOCK_DATA[3]);
SetCW(FUN_DISABLE);
}
/**
* @brief 处理Type F (FeliCa) 卡片事件。
* @details
* 该函数执行FeliCa卡片的交互流程包括
* 1. 初始化读卡器以支持FeliCa协议。
* 2. 打开RF场。
* 3. 发送Inventory命令寻卡并获取UID。
* 4. 后续可以添加与FeliCa卡的数据交换命令。
* 5. 操作结束后关闭RF场。
* @note 当前实现仅包含寻卡部分。
* @return 无。
*/
void TYPE_F_EVENT(void)
{
unsigned char result, i;
xlog("TYPE_F_EVENT begin\n");
ReaderF_Initial();
SetCW(FUN_ENABLE);
result = ReaderF_Inventory(&PICC_F);
if (result != SUCCESS)
{
SetCW(FUN_DISABLE);
return;
}
xlog("************* TYPE F CARD ************* \r\n");
xlog("->TYPE F UID = ");
for(i=0; i<8; i++) xlog("%02X", PICC_F.UID[i]);
xlog("\r\n");
SetCW(FUN_DISABLE);
}
/**
* @brief RFID模块的主任务函数。
* @details
* 利用定时器调用
* @return 无。
*/
void rfid_task_fuc(void)
{
unsigned char result, reg_data;
static u8 first_init = 0;
if(first_init == 0){
first_init = 1;
FM176XX_HardInit();
rfid_delay_ms(5); // 硬件初始化后增加一个短暂延时,确保芯片稳定
// 2. 复位 FM176XX 芯片
result = FM176XX_SoftReset();
if (result != SUCCESS)
{
xlog("FM176XX HardReset FAIL\r\n");
}
else
{
xlog("FM176XX HardReset SUCCESS\r\n");
}
rfid_delay_ms(10); // 复位后延时
}
// 3. 读取芯片版本号,确认通信是否正常
GetReg(REG_VERSION, &reg_data);
xlog("REG_VERSION = %02X\r\n", reg_data);
// TYPE_A_EVENT();
// TYPE_B_EVENT();
// TYPE_V_EVENT();
// TYPE_F_EVENT();
}

View File

@ -0,0 +1,220 @@
#include "./rfid_hal.h"
#include "gSensor/gSensor_manage.h"
#include "./include/rfid_main.h"
#include "./include/READER_REG.h"
#include "asm/spi.h"
#define FUN_ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if FUN_ENABLE_XLOG
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
/*
IFSEL1 IFSEL0 Host_Interface
0 0 UART
1 0 SPI
0 1 IIC
1 1 SPI
INTERFACE_TYPE == 0iic
== 1: spi
== 2: uart
*/
#define INTERFACE_TYPE 0
//////////////////////////////////////////////////////////////////////////////////////////////////
//
#if INTERFACE_TYPE == 0 //iic接口
/*
iic读取rfid不建议使用底层的硬件iic很容易造成程序崩溃并且时序有时候对不上会造成读写信息错误
这里利用底层写好的软件iic接口来实现寄存器的读写
*/
/*
IF2 IF0 ADDR
0 0 0x28
0 1 0x29
1 0 0x2A
1 1 0x2B
*/
#define FM176_7BIT_ADDR 0x28 //后两位地址由IF2、IF1决定
#define FM176_WRITE_ADDR (FM176_7BIT_ADDR << 1)
#define FM176_READ_ADDR ((FM176_7BIT_ADDR << 1) | 0x01)
unsigned char FM176XX_HardInit(void){
#if TCFG_GSENOR_USER_IIC_TYPE == 1// 硬件iic
int ret = hw_iic_init(0);
#else
int ret = soft_iic_init(0);
#endif
xlog("init iic result:%d\n", ret); //返回0成功
}
/**
* @brief 从FM176XX芯片读取一个字节的寄存器值。
* @param address [in] 目标寄存器的地址。
* @param reg_data [out] 指向用于存储读取数据的字节的指针。
* @return 操作状态SUCCESS表示成功。
* @details
* 接口iic
*/
unsigned char GetReg(unsigned char address, unsigned char *reg_data){
soft_iic_start(0);
if (0 == soft_iic_tx_byte(0, FM176_WRITE_ADDR)) {
soft_iic_stop(0);
return FAIL;
}
if (0 == soft_iic_tx_byte(0, address)) {
soft_iic_stop(0);
return FAIL;
}
soft_iic_start(0);
if (0 == soft_iic_tx_byte(0, FM176_READ_ADDR)) {
soft_iic_stop(0);
return FAIL;
}
*reg_data = soft_iic_rx_byte(0, 0);
soft_iic_stop(0);
return SUCCESS;
}
/**
* @brief 向FM176XX芯片写入一个字节的寄存器值。
* @param address [in] 目标寄存器的地址。
* @param reg_data [in] 要写入的字节数据。
* @return 操作状态SUCCESS表示成功。
* @details
* 接口iic
*/
unsigned char SetReg(unsigned char address, unsigned char reg_data){
soft_iic_start(0);
if (0 == soft_iic_tx_byte(0, FM176_WRITE_ADDR)) {
soft_iic_stop(0);
return FAIL;
}
if (0 == soft_iic_tx_byte(0, address)) {
soft_iic_stop(0);
return FAIL;
}
if (0 == soft_iic_tx_byte(0, reg_data)) {
soft_iic_stop(0);
return FAIL;
}
soft_iic_stop(0);
return SUCCESS;
}
/**
* @brief 软件复位命令0x1F
*
* @return unsigned char
*/
unsigned char FM176XX_SoftReset(void){
return SetReg(REG_COMMAND, 0x1F);
}
#elif INTERFACE_TYPE == 1 //spi
unsigned char FM176XX_HardInit(void){
gpio_set_direction(IO_PORTA_05,0); //nss
gpio_set_output_value(IO_PORTA_05, 1); //初始设置为高
spi_open(SPI1); //初始化spi1PC3、PC5
return SUCCESS;
}
/**
* @brief 从FM176XX芯片读取一个字节的寄存器值。
* @param address [in] 目标寄存器的地址。
* @param reg_data [out] 指向用于存储读取数据的字节的指针。
* @return 操作状态SUCCESS表示成功。
* @details
* 接口SPI
*/
unsigned char GetReg(unsigned char address, unsigned char *reg_data){
unsigned char addr_byte;
int err;
// 准备地址字节地址左移1位Bit0置1表示读
addr_byte = (address << 1) | 0x01;
// ---- 开始SPI事务 ----
gpio_set_output_value(IO_PORTA_05,0);
// 1. 发送地址字节,忽略接收到的数据
spi_send_byte(SPI1, addr_byte);
asm("nop");
// 2. 接收数据字节 (通过发送一个Dummy Byte 0xFF 来产生时钟)
*reg_data = spi_recv_byte(SPI1, &err);
asm("nop");
// ---- 结束SPI事务 ----
gpio_set_output_value(IO_PORTA_05,1);
if (err != 0) {
xlog("GetReg error\n");
return FAIL;
}
return SUCCESS;
}
/**
* @brief 向FM176XX芯片写入一个字节的寄存器值。
* @param address [in] 目标寄存器的地址。
* @param reg_data [in] 要写入的字节数据。
* @return 操作状态SUCCESS表示成功。
* @details
* 接口SPI
*/
unsigned char SetReg(unsigned char address, unsigned char reg_data){
unsigned char addr_byte = (address << 1) & 0xFE; // Bit0=0 for write
int err1, err2;
gpio_set_output_value(IO_PORTA_05,0); // <<-- CS拉低开始事务
err1 = spi_send_byte(SPI1, addr_byte); // 发送地址
asm("nop");
err2 = spi_send_byte(SPI1, reg_data); // 发送数据
asm("nop");
gpio_set_output_value(IO_PORTA_05,1); // <<-- CS拉高结束事务
if (err1 != 0 || err2 != 0) {
return FAIL;
}
return SUCCESS;
}
/**
* @brief 软件复位命令0x1F
*
* @return unsigned char
*/
unsigned char FM176XX_SoftReset(void){
return SetReg(REG_COMMAND, 0x1F);
}
#elif INTERFACE_TYPE == 2 //uart
#endif
void rfid_delay_ms(unsigned int ms){
// delay(ms);
os_time_dly(ms/10);
}

View File

@ -0,0 +1,76 @@
/********************************************************************************************************
* @file rfid_hal.h
* @brief RFID 硬件抽象层 (HAL) 接口定义
* @details
*
********************************************************************************************************/
#ifndef RFID_HAL_H
#define RFID_HAL_H
#include "system/includes.h"
/********************************************************************************************************
* 函数原型声明
********************************************************************************************************/
/**
* @brief 从FM176XX芯片读取一个字节的寄存器值。
* @param address [in] 目标寄存器的地址。
* @param reg_data [out] 指向用于存储读取数据的字节的指针。
* @return 操作状态SUCCESS表示成功。
* @details
* 接口uart、iic、spi
* 自行实现
*/
unsigned char GetReg(unsigned char address, unsigned char *reg_data);
/**
* @brief 向FM176XX芯片写入一个字节的寄存器值。
* @param address [in] 目标寄存器的地址。
* @param reg_data [in] 要写入的字节数据。
* @return 操作状态SUCCESS表示成功。
* @details
* 接口uart、iic、spi
* 自行实现
*/
unsigned char SetReg(unsigned char address, unsigned char reg_data);
/**
* @brief 接口硬件初始化
*
* @return unsigned char
*/
unsigned char FM176XX_HardInit(void);
/**
* @brief 硬件复位
* 通过控制RST引脚产生一个低电平脉冲来复位芯片。
* 复位后会读取命令寄存器REG_COMMAND的值进行检查
* 如果值不为0x40则认为复位失败。
*
* @return unsigned char
*/
unsigned char FM176XX_HardReset(void);
/**
* @brief 软件复位命令0x1F
*
* @return unsigned char
*/
unsigned char FM176XX_SoftReset(void);
/**
* @brief 实现一个毫秒级的延时。
* @param ms [in] 要延时的毫秒数。
* @return 无。
* @details
* 一个阻塞式延时函数。
*/
void rfid_delay_ms(unsigned int ms);
#endif // RFID_HAL_H

View File

@ -44,14 +44,18 @@
#include "bt_background.h"
#include "default_event_handler.h"
#include "debug.h"
#include "system/event.h"
#include "../nvs/nvs.h"
#if (JL_EARPHONE_APP_EN)
#include "rcsp_adv_bluetooth.h"
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
//宏定义
#define LOG_TAG_CONST EARPHONE
#define LOG_TAG "[EARPHONE]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#define xlog_ENABLE
#if(USE_DMA_UART_TEST) //使用dm串口测试时不能同时打开
@ -78,15 +82,27 @@ extern u8 init_ok;
extern u8 sniff_out;
unsigned char xtell_bl_state=0; //存放经典蓝牙的连接状态0断开1是连接
u8 bt_newname =0;
unsigned char xt_ble_new_name[9] = "CM-11111";
unsigned char xt_ble_new_name[9] = "CM-55555";
static u16 play_poweron_ok_timer_id = 0;
// -- 初始化标志位 --
u8 SC7U22_init = 0x10; //六轴是否初始化
u8 MMC5603nj_init = 0x20; //地磁是否初始化
u8 BMP280_init = 0x30; //气压计初始化
// -- 线程id --
u16 SC7U22_calibration_id;
u16 start_collect_fuc_id;
u16 BLE_send_fuc_id;
u16 rfid_fuc_id;
//
///////////////////////////////////////////////////////////////////////////////////////////////////
extern int bt_hci_event_handler(struct bt_event *bt);
extern void SC7U22_static_calibration(void);
extern void create_process(u16* pid, const char* name, void *priv, void (*func)(void *priv), u32 msec);
extern void close_process(u16* pid,char* name);
extern void start_collect_fuc(void);
extern void BLE_send_fuc(void);
extern void xtell_ble_central_test_start(void);
///////////////////////////////////////////////////////////////////////////////////////////////////
/*
* , start_app()
@ -171,6 +187,71 @@ static int state_machine(struct application *app, enum app_state state, struct i
///////////////////////////////////////////////////////////////////////////////////////////////////
//handle
void le_user_app_send_event(size_t command, unsigned char* data, size_t size)
{
// 中断->事件
static unsigned char buffer[512];
if(data && size && size <= sizeof(buffer)) {
// 拷贝到缓存,避免转发事件的时候,地址发送改变。
memcpy(buffer, data, size);
struct sys_event event;
event.type = SYS_APP_USER_EVENT;
event.u.app.command = command;
event.u.app.buffer = buffer;
event.u.app.size = size;
sys_event_notify(&event);
}
}
void le_user_app_event_handler(struct sys_event* event){
switch (event->type) {
// 打印接收到的数据
printf("BLE data\n");
put_buf(event->u.app.buffer, event->u.app.size);
case SYS_APP_USER_EVENT:
if (event->u.app.buffer[0] == 0xBE && event->u.app.buffer[1] == 0xBB) {
if(event->u.app.buffer[2] == 0x01){ //后面的数据长度 1
switch (event->u.app.buffer[3]){
case 0x01:
nvs_test_factory_info();
break;
case 0x02:
// factory_info_t read_info;;
// nvs_read_factory_info(&read_info);
extern void rfid_task_fuc(void);
create_process(&rfid_fuc_id,"rfid",NULL,rfid_task_fuc,2000);
break;
case 0xff: //测试
int ret = hw_iic_init(0);
// int ret = soft_iic_init(0);
xlog("init iic result:%d\n", ret); //返回0成功
extern void i2c_scanner_probe(void);
i2c_scanner_probe();
break;
default:
break;
}
}else if(event->u.app.buffer[2] == 0x02){ //后面数据长度为2
switch (event->u.app.buffer[3]){ //数据包类型
case 0x00:
break;
}
}
}
break;
default:
xlog("%d\n",event->type);
break;
}
}
static void play_poweron_ok_timer(void *priv)
{
app_var.wait_timer_do = 0;
@ -212,7 +293,7 @@ static int bt_connction_status_event_handler(struct bt_event *bt)
/*
*
*/
log_info("BT_STATUS_INIT_OK\n");
xlog("BT_STATUS_INIT_OK\n");
init_ok = 1;
__set_sbc_cap_bitpool(38);
@ -221,7 +302,8 @@ static int bt_connction_status_event_handler(struct bt_event *bt)
ble_bqb_test_thread_init();
} else {
#if !TCFG_WIRELESS_MIC_ENABLE
bt_ble_init();
bt_ble_init(); // lmx初始化完初始化ble决定ble是作为主设备还是从设备
// xtell_ble_central_test_start(); //xtell
#endif
}
#endif
@ -248,14 +330,14 @@ static int bt_connction_status_event_handler(struct bt_event *bt)
case BT_STATUS_SECOND_CONNECTED:
clear_current_poweron_memory_search_index(0);
case BT_STATUS_FIRST_CONNECTED:
log_info("BT_STATUS_CONNECTED\n");
xlog("BT_STATUS_CONNECTED\n");
xtell_bl_state = 1; //蓝牙连接成功 置1
if(strcmp(xt_ble_new_name,"CM-1111") != 0){
if(strcmp(xt_ble_new_name,"CM-11111") != 0){
//蓝牙连接成功
bt_newname =1;
u8 temp[5]={0xBB,0xBE,0x02,0x04,0x00};
temp[4] = xtell_bl_state; //经典蓝牙连接状态
send_data_to_ble_client(&temp,5);
// send_data_to_ble_client(&temp,5);
}
earphone_change_pwr_mode(PWR_DCDC15, 3000);
sys_auto_shut_down_disable();
@ -264,7 +346,7 @@ static int bt_connction_status_event_handler(struct bt_event *bt)
/* tone_play(TONE_CONN); */
/*os_time_dly(40); // for test*/
log_info("tone status:%d\n", tone_get_status());
xlog("tone status:%d\n", tone_get_status());
if (get_call_status() == BT_CALL_HANGUP) {
if (app_var.phone_dly_discon_time) {
sys_timeout_del(app_var.phone_dly_discon_time);
@ -275,19 +357,20 @@ static int bt_connction_status_event_handler(struct bt_event *bt)
}
}
/*int timeout = 5000 + rand32() % 10000;
sys_timeout_add(NULL, connect_phone_test, timeout);*/
break;
case BT_STATUS_FIRST_DISCONNECT:
case BT_STATUS_SECOND_DISCONNECT:
log_info("BT_STATUS_DISCONNECT\n");
xlog("BT_STATUS_DISCONNECT\n");
xtell_bl_state = 0; //断开蓝牙 清0
//蓝牙断开连接
if(bt_newname){ //已经改成新蓝牙名字,断开才播报
bt_newname=0;
u8 temp[5]={0xBB,0xBE,0x02,0x04,0x00};
temp[4] = xtell_bl_state; //经典蓝牙连接状态
send_data_to_ble_client(&temp,5);
// send_data_to_ble_client(&temp,5);
}
if (app_var.goto_poweroff_flag) {
/*关机不播断开提示音*/
@ -315,7 +398,7 @@ static int bt_connction_status_event_handler(struct bt_event *bt)
break;
case BT_STATUS_SNIFF_STATE_UPDATE:
log_info(" BT_STATUS_SNIFF_STATE_UPDATE %d\n", bt->value); //0退出SNIFF
xlog(" BT_STATUS_SNIFF_STATE_UPDATE %d\n", bt->value); //0退出SNIFF
if (bt->value == 0) {
sniff_out = 1;
sys_auto_sniff_controle(MY_SNIFF_EN, bt->args);
@ -344,19 +427,21 @@ static int bt_connction_status_event_handler(struct bt_event *bt)
break;
case BT_STATUS_AVRCP_INCOME_OPID:
log_info("BT_STATUS_AVRCP_INCOME_OPID:%d\n", bt->value);
xlog("BT_STATUS_AVRCP_INCOME_OPID:%d\n", bt->value);
break;
default:
log_info(" BT STATUS DEFAULT\n");
xlog(" BT STATUS DEFAULT\n");
break;
}
return 0;
}
static int event_handler(struct application *app, struct sys_event *event)
{
le_user_app_event_handler(event);
if (SYS_EVENT_REMAP(event)) {
g_printf("****SYS_EVENT_REMAP**** \n");
return 0;
@ -385,6 +470,19 @@ static int event_handler(struct application *app, struct sys_event *event)
} else if ((u32)event->arg == DEVICE_EVENT_FROM_POWER) {
return app_power_event_handler(&event->u.dev);
}
#if (JL_EARPHONE_APP_EN)
else if ((u32)event->arg == DEVICE_EVENT_FROM_RCSP) {
xlog("DEVICE_EVENT_FROM_RCSP: %d", event->u.rcsp.event);
switch (event->u.rcsp.event) {
case MSG_JL_UPDATE_START:
xlog(">>> Xtell APP: MSG_JL_UPDATE_START\n");
// You can add UI notifications here, like LED blinking or a tone.
break;
default:
break;
}
}
#endif
#if TCFG_UMIDIGI_BOX_ENABLE
else if ((u32)event->arg == DEVICE_EVENT_UMIDIGI_CHARGE_STORE) {
app_umidigi_chargestore_event_handler(&event->u.umidigi_chargestore);
@ -423,8 +521,8 @@ static const struct application_operation app_handler_ops = {
* earphone模式
*/
REGISTER_APPLICATION(app_handler) = {
.name = "handler",
.action = ACTION_EARPHONE_MAIN,
.ops = &app_handler_ops,
.name = "handler",
.action = ACTION_EARPHONE_MAIN,
.ops = &app_handler_ops,
.state = APP_STA_DESTROY,
};

View File

@ -0,0 +1,268 @@
#include "system/app_core.h"
#include "system/includes.h"
#include "btstack/btstack_task.h"
#include "btstack/bluetooth.h"
#include "le_common.h"
#include "ble_user.h"
#if 0 //ENABLE_THIS_TEST
#define LOG_TAG_CONST EARPHONE
#define LOG_TAG "[BLE_TEST]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
#include "debug.h"
// =================== 配置区 START ===================
// 1. 设置要连接的目标从机设备蓝牙名称
#define TARGET_BLE_NAME "CM-22222"
// 2. 设置要搜索的 Service UUID 和 Characteristic UUID
// Service UUID: 0x180D
#define TARGET_SERVICE_UUID16 0x180D
// Characteristic UUID: 0x2A37 (Notify)
#define TARGET_CHARACTERISTIC_UUID16 0x2A37
#define TARGET_CHARACTERISTIC_OPT_TYPE ATT_PROPERTY_NOTIFY
// =================== 配置区 END =====================
// ATT RAM buffer
#define ATT_LOCAL_MTU_SIZE (517)
#define ATT_SEND_CBUF_SIZE (256)
#define ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + ATT_LOCAL_MTU_SIZE + ATT_SEND_CBUF_SIZE)
static u8 att_ram_buffer[ATT_RAM_BUFSIZE] __attribute__((aligned(4)));
// Profile 搜索 buffer
#define SEARCH_PROFILE_BUFSIZE (512)
static u8 search_ram_buffer[SEARCH_PROFILE_BUFSIZE] __attribute__((aligned(4)));
// BLE 工作状态
static u8 ble_work_state = 0;
static hci_con_handle_t con_handle;
// 搜索到的目标特征值句柄
static u16 target_write_handle = 0;
static u16 target_notify_handle = 0;
// 函数前向声明
static int ble_central_test_scan_enable(u32 en);
static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
// 设置 BLE 工作状态
static void set_ble_work_state(u8 state) {
if (state != ble_work_state) {
log_info("ble_work_state: %d -> %d\n", ble_work_state, state);
ble_work_state = state;
}
}
// 解析广播数据,寻找目标设备
static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data) {
u8 i, length, ad_type;
u8 *adv_data_ptr = data;
for (i = 0; i < data_length;) {
if (*adv_data_ptr == 0) {
break;
}
length = *adv_data_ptr++;
ad_type = *adv_data_ptr++;
i += (length + 1);
if (ad_type == HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME || ad_type == HCI_EIR_DATATYPE_SHORTENED_LOCAL_NAME) {
if (length > 1 && (0 == memcmp(adv_data_ptr, TARGET_BLE_NAME, strlen(TARGET_BLE_NAME)))) {
log_info("Found target device: %s", TARGET_BLE_NAME);
log_info_hexdump(adv_address, 6);
return true;
}
}
adv_data_ptr += (length - 1);
}
return false;
}
// 创建连接
static void central_test_create_connection(u8 *addr, u8 addr_type) {
if (ble_work_state >= BLE_ST_CREATE_CONN) {
return;
}
log_info("Stopping scan...");
ble_central_test_scan_enable(0);
struct create_conn_param_t conn_param = {0};
conn_param.conn_interval = 24;
conn_param.conn_latency = 0;
conn_param.supervision_timeout = 600;
conn_param.peer_address_type = addr_type;
memcpy(conn_param.peer_address, addr, 6);
set_ble_work_state(BLE_ST_CREATE_CONN);
ble_op_create_connection(&conn_param);
}
// 开始搜索 Profile
static void central_test_search_profile() {
target_write_handle = 0;
target_notify_handle = 0;
user_client_init(con_handle, search_ram_buffer, SEARCH_PROFILE_BUFSIZE);
ble_op_search_profile_all();
}
// 搜索 Profile 结果回调
void user_client_report_search_result(search_result_t *result_info) {
if (result_info == (void *)-1) {
log_info("Search profile complete.");
set_ble_work_state(BLE_ST_SEARCH_COMPLETE);
// 如果找到了 NOTIFY 特征,使能它
if (target_notify_handle) {
log_info("Enabling notification for handle 0x%04x", target_notify_handle);
u16 val = 0x0001;
ble_op_att_send_data(target_notify_handle + 1, &val, 2, ATT_OP_WRITE);
}
return;
}
if (result_info->services.uuid16 == TARGET_SERVICE_UUID16 &&
result_info->characteristic.uuid16 == TARGET_CHARACTERISTIC_UUID16) {
log_info("Found target characteristic UUID 0x%04x", TARGET_CHARACTERISTIC_UUID16);
if ((result_info->characteristic.properties & ATT_PROPERTY_WRITE_WITHOUT_RESPONSE) ||
(result_info->characteristic.properties & ATT_PROPERTY_WRITE)) {
target_write_handle = result_info->characteristic.value_handle;
log_info("Found write handle: 0x%04x", target_write_handle);
}
if (result_info->characteristic.properties & ATT_PROPERTY_NOTIFY) {
target_notify_handle = result_info->characteristic.value_handle;
log_info("Found notify handle: 0x%04x", target_notify_handle);
}
}
}
// 接收到数据回调
void user_client_report_data_callback(att_data_report_t *report_data) {
log_info("RX data, handle=0x%04x, len=%d:", report_data->value_handle, report_data->blob_length);
log_info_hexdump(report_data->blob, report_data->blob_length);
}
// BLE 事件回调处理
static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) {
switch (packet_type) {
case HCI_EVENT_PACKET:
switch (hci_event_packet_get_type(packet)) {
case HCI_EVENT_LE_META:
switch (hci_event_le_meta_get_subevent_code(packet)) {
case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE:
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
if (hci_subevent_le_connection_complete_get_status(packet)) {
log_error("Connection failed, status: 0x%x", hci_subevent_le_connection_complete_get_status(packet));
set_ble_work_state(BLE_ST_CONNECT_FAIL);
ble_central_test_scan_enable(1); // 重新开始扫描
} else {
con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet);
log_info("Connection established, handle: 0x%04x", con_handle);
ble_op_att_send_init(con_handle, att_ram_buffer, ATT_RAM_BUFSIZE, ATT_LOCAL_MTU_SIZE);
set_ble_work_state(BLE_ST_CONNECT);
central_test_search_profile();
}
break;
}
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
log_info("Disconnected, reason: 0x%x", hci_event_disconnection_complete_get_reason(packet));
con_handle = 0;
ble_op_att_send_init(0, NULL, 0, 0);
set_ble_work_state(BLE_ST_DISCONN);
ble_central_test_scan_enable(1); // 断开后重新扫描
break;
case GAP_EVENT_ADVERTISING_REPORT:
if (ble_work_state != BLE_ST_SCAN) {
break;
}
adv_report_t *report = (void *)&packet[2];
if (resolve_adv_report(report->address, report->length, report->data)) {
central_test_create_connection(report->address, report->address_type);
}
break;
case ATT_EVENT_MTU_EXCHANGE_COMPLETE:
log_info("MTU exchange complete, MTU = %d", att_event_mtu_exchange_complete_get_MTU(packet));
break;
}
break;
}
}
// 启动或停止扫描
static int ble_central_test_scan_enable(u32 en) {
if (en) {
if (ble_work_state >= BLE_ST_SCAN) {
return 0; // 已经在扫描或连接中
}
log_info("Starting scan...");
set_ble_work_state(BLE_ST_SCAN);
ble_op_set_scan_param(SCAN_ACTIVE, 48, 48);
ble_op_scan_enable2(1, 0);
} else {
if (ble_work_state < BLE_ST_SCAN) {
return 0; // 已经停止
}
log_info("Stopping scan...");
set_ble_work_state(BLE_ST_IDLE);
ble_op_scan_enable2(0, 0);
}
return 0;
}
// 发送数据接口
int xtell_ble_central_test_send_data(u8 *data, u16 len) {
if (!con_handle || ble_work_state != BLE_ST_SEARCH_COMPLETE) {
log_error("Not connected or profile search not complete.");
return -1;
}
if (!target_write_handle) {
log_error("No writable characteristic found.");
return -1;
}
int ret = ble_op_att_send_data(target_write_handle, data, len, ATT_OP_WRITE_WITHOUT_RESPOND);
if (ret == 0) {
log_info("TX data, len=%d:", len);
log_info_hexdump(data, len);
} else {
log_error("Failed to send data, ret=%d", ret);
}
return ret;
}
// 注册 BLE central 模式需要的回调
static void ble_central_test_register_handlers(void) {
log_info("Registering BLE central test handlers...");
// 注意le_device_db_init() 和 ble_stack_gatt_role() 可能已被RCSP的profile_init调用
// 这里我们只覆盖 packet handlers
gatt_client_init(); // 确保 gatt client 被初始化
gatt_client_register_packet_handler(cbk_packet_handler);
hci_event_callback_set(cbk_packet_handler);
le_l2cap_register_packet_handler(cbk_packet_handler);
ble_vendor_set_default_att_mtu(ATT_LOCAL_MTU_SIZE);
}
// 测试总开关和初始化
void xtell_ble_central_test_start(void) {
if (ble_work_state != 0) {
log_info("Test is already running.");
return;
}
log_info("======== Xtell BLE Central Test Start ========");
set_ble_work_state(BLE_ST_INIT_OK);
ble_module_enable(1); // 使能 BLE 模块
ble_central_test_register_handlers(); // 注册我们的回调
ble_central_test_scan_enable(1); // 开始扫描
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,52 @@
#ifndef __CLIENT_HANDLER_H__
#define __CLIENT_HANDLER_H__
#include "app_config.h"
#include "ble_user.h"
/**
* @brief BLE客户端退出
*/
extern void bt_ble_exit(void);
/**
* @brief 应用层调用的断开连接接口
*/
extern void ble_app_disconnect(void);
/**
* @brief BLE模块使能/禁止 (兼容旧接口)
* @param enable 1:使能, 0:禁止
*/
extern void bt_ble_adv_enable(u8 enable);
/**
* @brief BLE模块使能/禁止
* @param en 1:使能, 0:禁止
*/
extern void ble_module_enable(u8 en);
/**
* @brief 客户端发起连接参数更新请求
*/
extern void client_send_conn_param_update(void);
/**
* @brief 清除绑定信息
*/
extern void clear_bonding_info(void);
/**
* @brief 连接新的设备
*
* @param name 设备的名称
*/
extern void g_ble_connect_new_device(char* name);
/**
* @brief 获取当前ble连接状态
*
* @return //0:连接断开; 1连接成功
*/
extern u8 g_ble_get_state(void);
#endif

View File

@ -0,0 +1,147 @@
#include "system/includes.h"
#include "system/syscfg_id.h"
#include "nvs.h"
// 2. 定义唯一的配置项ID
#define CFG_RC_MAC_ADDR_ID 11 // 配置项id
/**
* @brief 将主板MAC地址写入Flash
*/
int nvs_write_main_board_mac(const u8 *mac_addr)
{
if (!mac_addr) {
return -1;
}
rc_nvs_data_t nvs_data;
memcpy(nvs_data.main_board_mac, mac_addr, MAIN_BOARD_MAC_ADDR_LENGTH);
printf("--> Writing main board MAC to flash...\n");
int ret = syscfg_write(CFG_RC_MAC_ADDR_ID, &nvs_data, sizeof(rc_nvs_data_t));
if (ret != sizeof(rc_nvs_data_t)) {
printf("!!! syscfg_write main board MAC failed, ret = %d\n", ret);
} else {
printf("--> syscfg_write main board MAC success.\n");
}
return ret;
}
/**
* @brief 从Flash读取主板MAC地址
*/
int nvs_read_main_board_mac(u8 *mac_addr)
{
if (!mac_addr) {
return -1;
}
rc_nvs_data_t nvs_data;
printf("--> Reading main board MAC from flash...\n");
int ret = syscfg_read(CFG_RC_MAC_ADDR_ID, &nvs_data, sizeof(rc_nvs_data_t));
if (ret != sizeof(rc_nvs_data_t)) {
printf("!!! syscfg_read main board MAC failed, ret = %d. Maybe not set yet.\n", ret);
memset(mac_addr, 0, MAIN_BOARD_MAC_ADDR_LENGTH);
} else {
printf("--> syscfg_read main board MAC success.\n");
memcpy(mac_addr, nvs_data.main_board_mac, MAIN_BOARD_MAC_ADDR_LENGTH);
}
return ret;
}
/**
* @brief 清空Flash中的出厂信息
*
* @return 0: 成功, <0: 失败
*/
int nvs_clear_info(void)
{
rc_nvs_data_t nvs_data;
for(int i = 0 ; i < MAIN_BOARD_MAC_ADDR_LENGTH; i++){
nvs_data.main_board_mac[i] = 0;
}
printf("--> Clearing factory info from flash...\n");
// 写入长度为0的数据即可实现删除效果
int ret = syscfg_write(CFG_RC_MAC_ADDR_ID, &nvs_data, sizeof(rc_nvs_data_t));
if (ret != 0) {
printf("!!! syscfg_write clear factory info failed, ret = %d\n", ret);
} else {
printf("--> syscfg_write clear factory info success.\n");
}
return ret;
}
// =================================================================================
// 以下为旧的通用出厂信息API已废弃
// =================================================================================
#define CFG_FACTORY_INFO_ID 10 // 旧的、通用的出厂信息ID (已废弃)
int nvs_write_factory_info(const factory_info_t *info)
{
printf("WARNING: nvs_write_factory_info is deprecated.\n");
return -1;
}
int nvs_read_factory_info(factory_info_t *info)
{
printf("WARNING: nvs_read_factory_info is deprecated.\n");
return -1;
}
/**
* @brief 清空Flash中的出厂信息
*
* @return 0: 成功, <0: 失败
*/
int nvs_clear_factory_info(void)
{
printf("--> Clearing factory info from flash...\n");
// 写入长度为0的数据即可实现删除效果
int ret = syscfg_write(CFG_FACTORY_INFO_ID, NULL, 0);
if (ret != 0) {
printf("!!! syscfg_write clear factory info failed, ret = %d\n", ret);
} else {
printf("--> syscfg_write clear factory info success.\n");
}
return ret;
}
// 可以在这里添加一个测试函数
void nvs_test_factory_info(void)
{
factory_info_t write_info = {
.product_id = "RC_V2",
.serial_number = "SN202511260002",
.hw_version = 0x0102, // v1.1
.cal_data = 1234,
.manufacture_date = 1764080400, // 2025-11-26
};
factory_info_t read_info;
printf("\n\n--- NVS WRITE TEST ---\n");
nvs_write_factory_info(&write_info);
os_time_dly(10);
printf("\n--- NVS READ TEST ---\n");
nvs_read_factory_info(&read_info);
// ASSERT(memcmp(&write_info, &read_info, sizeof(factory_info_t)) == 0, "NVS Read/Write Check Failed!");
// printf("\n--- NVS CLEAR TEST ---\n");
// nvs_clear_factory_info();
os_time_dly(10);
printf("\n--- NVS READ AFTER CLEAR TEST ---\n");
int ret = nvs_read_factory_info(&read_info);
if(ret < 0){
printf("--- nvs read error ---\n");
}
printf("\n\n--- NVS TEST COMPLETE ---\n\n");
}

View File

@ -0,0 +1,58 @@
#ifndef __NVS_H__
#define __NVS_H__
#include "typedef.h"
#include "../task_func.h"
#define MAIN_BOARD_MAC_ADDR_LENGTH UID_LENGTH
/**
* @brief 定义用于存储遥控器配对信息的数据结构
*/
typedef struct {
u8 main_board_mac[MAIN_BOARD_MAC_ADDR_LENGTH]; // 配对的主板MAC地址
// u8 reserved[2]; // 可选的保留字节,用于对齐或未来扩展
} rc_nvs_data_t;
/**
* @brief 将主板MAC地址写入Flash
*
* @param mac_addr 指向要写入的MAC地址数组的指针
* @return 实际写入的长度, <0: 失败
*/
int nvs_write_main_board_mac(const u8 *mac_addr);
/**
* @brief 从Flash读取主板MAC地址
*
* @param mac_addr 指向用于存储读取数据的MAC地址数组的指针
* @return 实际读取的长度, <0: 失败 (例如尚未写入过)
*/
int nvs_read_main_board_mac(u8 *mac_addr);
int nvs_clear_info(void);
// =================================================================================
// 以下为旧的通用出厂信息API已废弃不建议在新代码中使用
// =================================================================================
typedef struct {
char product_id[16];
char serial_number[32];
u16 hw_version;
u16 cal_data;
u32 manufacture_date;
} factory_info_t;
__attribute__((deprecated("Use nvs_write_main_board_mac instead")))
int nvs_write_factory_info(const factory_info_t *info);
__attribute__((deprecated("Use nvs_read_main_board_mac instead")))
int nvs_read_factory_info(factory_info_t *info);
__attribute__((deprecated("This function is no longer needed")))
int nvs_clear_factory_info(void);
__attribute__((deprecated("This function is no longer needed")))
void nvs_test_factory_info(void);
#endif // __NVS_H__

View File

@ -0,0 +1,292 @@
#include "task_func.h"
#include "./nvs/nvs.h"
#include "timer.h"
#include "system/includes.h"
#include "user_cfg.h"
#include "earphone.h" // 宏定义 EARPHONE_STATE_...
#include "ble_user.h"
#include "le_client_demo.h"
#include "le_common.h"
#include "./ble_handler/client_handler.h"
// =================================================================================
// 宏定义与日志
// =================================================================================
#define RC_LOG_ENABLE 1
#if RC_LOG_ENABLE
#define rc_log(format, ...) printf("[RC_APP] " format, ##__VA_ARGS__)
#else
#define rc_log(format, ...)
#endif
// =================================================================================
// 外部函数声明
// =================================================================================
extern void TYPE_V_EVENT(char* uid);
extern void TYPE_A_EVENT(char* uid);
// =================================================================================
// 静态函数声明
// =================================================================================
static RFID_Device_Type_t get_rfid_device_type(const u8* uid);
// BLE 状态转换的辅助函数
static void rc_ble_state_set_connecting(void);
static void rc_ble_state_set_connected(void);
static void rc_ble_state_set_disconnected(void);
// =================================================================================
// 全局变量
// =================================================================================
static RC_Context_t g_rc_context; // 全局上下文实例
static u16 g_rfid_timer_id = 0; // RFID 定时器ID
static u16 g_ble_timer_id = 0; // BLE 定时器ID
static u8 current_board_mac[MAIN_BOARD_MAC_ADDR_LENGTH] = {0}; //当前连接主板的名称 -- mac
// =================================================================================
// 核心回调函数 (Core Callback Handlers)
// =================================================================================
/**
* @brief RFID回调处理函数 (由定时器周期性调用)
*/
void rc_rfid_callback_handler(void *priv)
{
u8 uid[UID_LENGTH] = {0};
//读id卡
// TYPE_V_EVENT((char *)uid);
TYPE_A_EVENT((char *)uid);
//是否有rfid卡靠近
u8 is_new_data = 0;
for (int i = 0; i < UID_LENGTH; i++) {
if (uid[i] != 0x00) {
is_new_data = 1;
break;
}
}
if (!is_new_data) {
return; //没有rfid卡靠近返回
}
rc_log("New RFID card detected.\n");
RFID_Device_Type_t device_type = get_rfid_device_type(uid);
switch (device_type) {
case RFID_DEVICE_TYPE_MAIN_BOARD: //船主板上的rfid卡
if(strncmp(uid, current_board_mac, UID_LENGTH) == 0){
// 扫到的rfid卡的uid和当前连接的主板mac相同
return;
}
//扫到新的主板
rc_log("Device is Main Board. Storing MAC...\n");
// 将新的MAC地址写入Flash
nvs_write_main_board_mac(uid);
// memset(current_board_mac, uid, sizeof(current_board_mac));
// TODO发送指令让主板断开经典蓝牙连接
// TODO: 切断BLE
// g_ble_connect_new_device(current_board_mac); //连接新主板
break;
case RFID_DEVICE_TYPE_REMOTE_CONTROL: //扫的是遥控器
rc_log("Device is another Remote Control.\n");
if(g_rc_context.team != TEAM_YES){
nvs_clear_info(); //清楚nfc数据
return; //非组队状态
}
if (g_ble_get_state() == BLE_ST_NOTIFY_IDICATE) {
rc_log("Sending teaming request to main board...\n");
//TODO:
//向主板发送新的遥控器rfid uid
} else {
rc_log("Not connected to main board, ignoring teaming request.\n");
}
break;
default:
rc_log("Unknown RFID device type.\n");
break;
}
}
/**
* @brief BLE回调处理函数 (由定时器周期性调用)s
*/
void rc_ble_callback_handler(void *priv)
{
u8 read_uid[UID_LENGTH] = {0};
nvs_read_main_board_mac(read_uid); //读nvs
//读到的是当前连接的主板uid
if((strncmp(read_uid, current_board_mac, UID_LENGTH) == 0) && g_ble_get_state()){
return;
}
//
// bool is_connected = ble_hid_is_connected();
// // 状态机转换
// if (is_connected && g_rc_context.state != RC_STATE_CONNECTED) {
// rc_ble_state_set_connected();
// } else if (!is_connected && g_rc_context.state != RC_STATE_DISCONNECTED) {
// rc_ble_state_set_disconnected();
// }
// // 状态机行为
// switch (g_rc_context.state) {
// case RC_STATE_DISCONNECTED:
// {
// u8 target_mac[MAC_ADDR_LENGTH] = {0};
// // 检查Flash中是否有已配对的MAC
// if (nvs_read_main_board_mac(target_mac) > 0) {
// rc_log("Found paired MAC. Start scanning...\n");
// // 启动扫描和连接。SDK的HID实现会自动连接到已配对的设备。
// EARPHONE_STATE_SET_PAGE_SCAN_ENABLE();
// } else {
// rc_log("No paired MAC found. Waiting for RFID pairing...\n");
// }
// }
// break;
// case RC_STATE_CONNECTING:
// // 在这个状态下,我们只是等待 is_connected 变为 true
// rc_log("Waiting for connection result...\n");
// break;
// case RC_STATE_CONNECTED:
// // 已连接,目前无需周期性操作
// // rc_log("BLE is connected.\n");
// break;
// default:
// break;
// }
}
/**
* @brief 根据UID前缀判断设备类型
*/
static RFID_Device_Type_t get_rfid_device_type(const u8* uid)
{
if (uid == NULL) {
return RFID_DEVICE_TYPE_UNKNOWN;
}
// 根据 RC_app_main.h 中定义的UID前缀进行判断
if (uid[0] == UID_PREFIX_MAIN_BOARD) {
return RFID_DEVICE_TYPE_MAIN_BOARD;
} else if (uid[0] == UID_PREFIX_REMOTE_CONTROL) {
return RFID_DEVICE_TYPE_REMOTE_CONTROL;
}
return RFID_DEVICE_TYPE_UNKNOWN;
}
// =================================================================================
// 辅助函数 (Helper Functions)
// =================================================================================
/**
* @brief 进入 CONNECTING 状态的逻辑
*/
static void rc_ble_state_set_connecting(void)
{
rc_log("State transition to -> CONNECTING\n");
g_rc_context.state = RC_STATE_CONNECTING;
// 可以在这里控制LED灯效例如黄灯呼吸闪烁
}
/**
* @brief 进入 CONNECTED 状态的逻辑
*/
static void rc_ble_state_set_connected(void)
{
rc_log("State transition to -> CONNECTED\n");
g_rc_context.state = RC_STATE_CONNECTED;
// 停止扫描以省电
EARPHONE_STATE_CANCEL_PAGE_SCAN();
// 发送指令,要求主板连接遥控器的经典蓝牙
u8 classic_conn_req_payload[] = {0x01, 0x02, 0x03};
rc_log("Sending request for classic BT connection.\n");
ble_hid_data_send(0xFE, classic_conn_req_payload, sizeof(classic_conn_req_payload));
// 在这里控制LED灯效例如蓝灯呼吸闪烁三次后熄灭
}
/**
* @brief 进入 DISCONNECTED 状态的逻辑
*/
static void rc_ble_state_set_disconnected(void)
{
rc_log("State transition to -> DISCONNECTED\n");
g_rc_context.state = RC_STATE_DISCONNECTED;
// 在这里控制LED灯效例如黄灯呼吸闪烁
}
// 初始化函数 (Initialization Function)
// =================================================================================
/**
* @brief 遥控器应用主初始化函数
*/
void rc_app_main_init(void)
{
rc_log("Initializing Remote Control App...\n");
// 1. 初始化全局上下文
memset(&g_rc_context, 0, sizeof(RC_Context_t));
g_rc_context.state = RC_STATE_DISCONNECTED; // 初始状态为未连接
g_rc_context.team = TEAM_NO;
FM176XX_HardInit();
// 2. 检查并启动RFID处理定时器
if (g_rfid_timer_id == 0) {
g_rfid_timer_id = sys_timer_add(NULL, rc_rfid_callback_handler, RC_RFID_CALLBACK_INTERVAL_MS);
rc_log("RFID handler timer started (ID: %d).\n", g_rfid_timer_id);
}
// 3. 检查并启动BLE处理定时器
if (g_ble_timer_id == 0) {
g_ble_timer_id = sys_timer_add(NULL, rc_ble_callback_handler, RC_BLE_CALLBACK_INTERVAL_MS);
rc_log("BLE handler timer started (ID: %d).\n", g_ble_timer_id);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
//test
#define TEST_FUNCTION 1
void test_task(void){
#if TEST_FUNCTION == 1
FM176XX_HardInit();
while(1){
u8 uid[UID_LENGTH] = {0};
//读id卡
TYPE_V_EVENT((char *)uid);
// TYPE_A_EVENT((char *)uid);
os_time_dly(100);
}
#endif
}
void test_func_main(void){
#if TEST_FUNCTION == 1
os_task_create(test_task, NULL, 1, 1024, 128, "rfid_test");
#endif
}

View File

@ -0,0 +1,101 @@
#ifndef __RC_APP_MAIN_H__
#define __RC_APP_MAIN_H__
#include "typedef.h"
// =================================================================================
// 常量定义 (Constants)
// =================================================================================
// 假设UID的前1个字节用于区分设备类型
#define UID_PREFIX_MAIN_BOARD 0xA1 // 主板UID前缀
#define UID_PREFIX_REMOTE_CONTROL 0xA2 // 遥控器UID前缀
#define UID_LENGTH 8 // RFID UID 的标准长度
// 定时器调用间隔 (ms)
#define RC_RFID_CALLBACK_INTERVAL_MS 500 // RFID轮询间隔500ms
#define RC_BLE_CALLBACK_INTERVAL_MS 1000 // BLE状态机处理间隔, 1s
// =================================================================================
// 枚举与结构体定义 (Enums & Structs)
// =================================================================================
/**
* @brief 遥控器核心状态机
*/
typedef enum {
RC_STATE_IDLE, // 空闲状态,等待初始化
RC_STATE_DISCONNECTED, // 未连接主板 (正在扫描或等待)
RC_STATE_CONNECTING, // 正在连接主板
RC_STATE_CONNECTED, // 已连接主板
} RC_State_t;
/**
* @brief 当前是否处于组队状态
*/
typedef enum {
TEAM_NO, //未组队
TEAM_YES,
} RC_State_t;
/**
* @brief RFID读取到的设备类型
*/
typedef enum {
RFID_DEVICE_TYPE_UNKNOWN, // 未知设备
RFID_DEVICE_TYPE_MAIN_BOARD, // 船体主板
RFID_DEVICE_TYPE_REMOTE_CONTROL // 其他遥控器
} RFID_Device_Type_t;
/**
* @brief 遥控器应用全局上下文
*/
typedef struct {
RC_State_t state; // 当前状态机状态
RC_State_t team; //当前是否组队
u8 paired_mac_addr[UID_LENGTH]; // 已配对主板的MAC地址(包含前缀)
// ... 可在此处添加更多运行时需要管理的数据
} RC_Context_t;
// =================================================================================
// 公共函数声明 (Public Function Prototypes)
// =================================================================================
/**
* @brief 遥控器应用主初始化函数
* @details
* - 初始化全局上下文
* - 设置并启动RFID和BLE处理定时器
*/
void rc_app_main_init(void);
/**
* @brief RFID回调处理函数 (由定时器周期性调用)
* @details
* - 调用RFID读取函数
* - 分析UID并执行相应逻辑 (配对/组队)
*/
void rc_rfid_callback_handler(void *priv);
/**
* @brief BLE回调处理函数 (由定时器周期性调用)
* @details
* - 维护与主板的BLE连接状态
* - 处理断线重连等
*/
void rc_ble_callback_handler(void *priv);
/**
* @brief BLE连接状态回调 (由蓝牙协议栈调用)
* @param status 0: 成功, 其他: 失败
* @param addr 连接或断开的设备地址
* @details
* - 在BLE连接成功后请求主板连接经典蓝牙
* - 更新连接状态
*/
// void rc_ble_connection_status_callback(u8 status, u8 *addr); // No longer needed
#endif // __RC_APP_MAIN_H__

View File

@ -0,0 +1,12 @@
#ifndef XTELL_H
#define XTELL_H
#include "system/includes.h"
// #define KS_BLE 1
#define XTELL_TEST 1
#define ACC_RANGE 16 //g加速度满量程:2、4、8、16
#endif

View File

@ -0,0 +1,124 @@
#include "system/includes.h"
#include "app_config.h"
#include "app_action.h"
#include "app_main.h"
#include "update.h"
#include "update_loader_download.h"
#include "app_power_manage.h"
#include "app_charge.h"
#include "bt_profile_cfg.h"
#include "debug.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
//宏定义
#define ENABLE_XLOG 1
#ifdef xlog
#undef xlog
#endif
#if ENABLE_XLOG
#define xlog(format, ...) printf("[XT:%s] " format, __func__, ##__VA_ARGS__)
#else
#define xlog(format, ...) ((void)0)
#endif
#define LOG_TAG_CONST APP
#define LOG_TAG "[APP]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
//
///////////////////////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------------------------//
// 外部函数/变量声明
//-------------------------------------------------------------------------------------------------//
extern APP_VAR app_var;
//-------------------------------------------------------------------------------------------------//
// 系统主函数 app_main
//-------------------------------------------------------------------------------------------------//
/**
* @brief 创建一个周期性执行的系统定时器任务
*/
void create_process(u16* pid, const char* name, void *priv, void (*func)(void *priv), u32 msec){
xlog("1 name=%s, pid =%d\n",name,*pid);
if (*pid != 0) return;
*pid = sys_timer_add(priv, func, msec);
xlog("2 name=%s, pid =%d\n",name,*pid);
}
/**
* @brief 关闭一个系统定时器任务
*/
void close_process(u16* pid, const char* name){
xlog("name=%s,pid =%d\n",name,*pid);
if (*pid == 0) return;
sys_timer_del(*pid);
*pid = 0;
}
/*充电拔出,CPU软件复位, 不检测按键,直接开机*/
static void app_poweron_check(int update)
{
extern int cpu_reset_by_soft();
if (!update && cpu_reset_by_soft()) {
app_var.play_poweron_tone = 0;
return;
}
}
/**
* @brief 应用层主入口
*/
void xtell_app_main()
{
int update = 0;
struct intent it;
xlog("==============xtell_app_main start================\n");
log_info("app_main\n");
extern u32 timer_get_ms(void);
app_var.start_time = timer_get_ms();
// 检查是否有固件升级
if (!UPDATE_SUPPORT_DEV_IS_NULL()) {
update = update_result_deal();
}
// 初始化应用层变量
extern void app_var_init(void);
app_var_init();
// 根据充电状态决定进入 idle 模式还是 handler 模式
if (get_charge_online_flag()) {
#if(TCFG_SYS_LVD_EN == 1)
vbat_check_init();
#endif
xlog("==============idle================\n");
init_intent(&it);
it.name = "idle";
it.action = ACTION_IDLE_MAIN;
start_app(&it);
} else {
xlog("==============handler start================\n");
check_power_on_voltage();
app_poweron_check(update);
init_intent(&it);
it.name = "handler";
it.action = ACTION_EARPHONE_MAIN;
start_app(&it);
xlog("==============handler end================\n");
}
xlog("==============xtell_app_end================\n");
extern void test_func_main(void);
test_func_main();
}

View File

@ -1,259 +0,0 @@
#include "system/includes.h"
/*#include "btcontroller_config.h"*/
#include "btstack/btstack_task.h"
#include "app_config.h"
#include "app_action.h"
#include "asm/pwm_led.h"
#include "tone_player.h"
#include "gpio.h"
#include "app_main.h"
#include "asm/charge.h"
#include "update.h"
#include "app_power_manage.h"
#include "app_charge.h"
#include "bt_profile_cfg.h"
#include "dev_manager/dev_manager.h"
#include "update_loader_download.h"
#define LOG_TAG_CONST APP
#define LOG_TAG "[APP]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#ifdef CONFIG_BOARD_AISPEECH_VAD_ASR
u8 user_at_cmd_send_support = 1;
#endif
/*任务列表 */
const struct task_info task_info_table[] = {
{"app_core", 1, 0, 768, 256 },
{"sys_event", 7, 0, 256, 0 },
{"systimer", 7, 0, 128, 0 },
{"btctrler", 4, 0, 512, 384 },
{"btencry", 1, 0, 512, 128 },
{"tws", 5, 0, 512, 128 },
#if (BT_FOR_APP_EN)
{"btstack", 3, 0, 1024, 256 },
#else
{"btstack", 3, 0, 768, 256 },
#endif
{"audio_dec", 5, 0, 800, 128 },
{"aud_effect", 5, 1, 800, 128 },
/*
*为了防止dac buf太大通话一开始一直解码
*导致编码输入数据需要很大的缓存,这里提高编码的优先级
*/
{"audio_enc", 6, 0, 768, 128 },
{"aec", 2, 1, 768, 128 },
#if TCFG_AUDIO_HEARING_AID_ENABLE
{"HearingAid", 6, 0, 768, 128 },
#endif/*TCFG_AUDIO_HEARING_AID_ENABLE*/
#ifdef CONFIG_BOARD_AISPEECH_NR
{"aispeech_enc", 2, 1, 512, 128 },
#endif /*CONFIG_BOARD_AISPEECH_NR*/
#ifdef CONFIG_BOARD_AISPEECH_VAD_ASR
{"asr", 1, 0, 768, 128 },
{"audio_asr_export_task", 1, 0, 512, 128 },
#endif/*CONFIG_BOARD_AISPEECH_VAD_ASR*/
#ifndef CONFIG_256K_FLASH
{"aec_dbg", 3, 0, 128, 128 },
#if AUDIO_ENC_MPT_SELF_ENABLE
{"enc_mpt_self", 3, 0, 512, 128 },
#endif/*AUDIO_ENC_MPT_SELF_ENABLE*/
{"update", 1, 0, 256, 0 },
{"tws_ota", 2, 0, 256, 0 },
{"tws_ota_msg", 2, 0, 256, 128 },
{"dw_update", 2, 0, 256, 128 },
{"rcsp_task", 2, 0, 640, 128 },
{"aud_capture", 4, 0, 512, 256 },
{"data_export", 5, 0, 512, 256 },
{"anc", 3, 1, 512, 128 },
#endif
#if TCFG_GX8002_NPU_ENABLE
{"gx8002", 2, 0, 256, 64 },
#endif /* #if TCFG_GX8002_NPU_ENABLE */
#if TCFG_GX8002_ENC_ENABLE
{"gx8002_enc", 2, 0, 128, 64 },
#endif /* #if TCFG_GX8002_ENC_ENABLE */
#if TCFG_KWS_VOICE_RECOGNITION_ENABLE
{"kws", 2, 0, 256, 64 },
#endif /* #if TCFG_KWS_VOICE_RECOGNITION_ENABLE */
{"usb_msd", 1, 0, 512, 128 },
#if !TCFG_USB_MIC_CVP_ENABLE
{"usbmic_write", 2, 0, 256, 128 },
#endif
#if AI_APP_PROTOCOL
{"app_proto", 2, 0, 768, 64 },
#endif
#if (TCFG_SPI_LCD_ENABLE||TCFG_SIMPLE_LCD_ENABLE)
{"ui", 2, 0, 768, 256 },
#else
{"ui", 3, 0, 384 - 64, 128 },
#endif
#if (TCFG_DEV_MANAGER_ENABLE)
{"dev_mg", 3, 0, 512, 512 },
#endif
{"audio_vad", 1, 1, 512, 128 },
#if TCFG_KEY_TONE_EN
{"key_tone", 5, 0, 256, 32 },
#endif
#if (TCFG_WIRELESS_MIC_ENABLE)
{"wl_mic_enc", 2, 0, 768, 128 },
#endif
#if (TUYA_DEMO_EN)
{"user_deal", 7, 0, 512, 512 },//定义线程 tuya任务调度
{"dw_update", 2, 0, 256, 128 },
#endif
#if TCFG_AUDIO_SPATIAL_EFFECT_ENABLE
{"imu_trim", 1, 0, 256, 128 },
#endif /*TCFG_AUDIO_SPATIAL_EFFECT_ENABLE*/
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
{"speak_to_chat", 2, 0, 256, 128 },
{"icsd_adt", 2, 0, 512, 128 },
{"icsd_src", 2, 1, 512, 128 },
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
{"pmu_task", 6, 0, 256, 128 },
{"WindDetect", 2, 0, 256, 128 },
{0, 0},
};
APP_VAR app_var;
/*
* 2ms timer中断回调函数
*/
void timer_2ms_handler()
{
}
void app_var_init(void)
{
memset((u8 *)&bt_user_priv_var, 0, sizeof(BT_USER_PRIV_VAR));
app_var.play_poweron_tone = 1;
}
void app_earphone_play_voice_file(const char *name);
void clr_wdt(void);
void check_power_on_key(void)
{
u32 delay_10ms_cnt = 0;
#if 0 //PC_MODE_DETECTION
gpio_set_pull_up(IO_PORTP_00, 0);
gpio_set_pull_down(IO_PORTP_00, 1);
gpio_set_direction(IO_PORTP_00, 1);
gpio_set_die(IO_PORTP_00, 1);
#endif
while (1) {
clr_wdt();
os_time_dly(1);
extern u8 get_power_on_status(void);
if (get_power_on_status()) {
log_info("+");
delay_10ms_cnt++;
if (delay_10ms_cnt > 70) {
/* extern void set_key_poweron_flag(u8 flag); */
/* set_key_poweron_flag(1); */
return;
}
} else {
log_info("-");
delay_10ms_cnt = 0;
log_info("enter softpoweroff\n");
power_set_soft_poweroff();
}
}
}
extern int cpu_reset_by_soft();
extern int audio_dec_init();
extern int audio_enc_init();
__attribute__((weak))
u8 get_charge_online_flag(void)
{
return 0;
}
/*充电拔出,CPU软件复位, 不检测按键,直接开机*/
static void app_poweron_check(int update)
{
#if (CONFIG_BT_MODE == BT_NORMAL)
if (!update && cpu_reset_by_soft()) {
app_var.play_poweron_tone = 0;
return;
}
#if TCFG_CHARGE_OFF_POWERON_NE
if (is_ldo5v_wakeup()) {
app_var.play_poweron_tone = 0;
return;
}
#endif
//#ifdef CONFIG_RELEASE_ENABLE
#if TCFG_POWER_ON_NEED_KEY
check_power_on_key();
#endif
//#endif
#endif
}
extern u32 timer_get_ms(void);
void app_main()
{
int update = 0;
u32 addr = 0, size = 0;
struct intent it;
if (!UPDATE_SUPPORT_DEV_IS_NULL()) {
update = update_result_deal();
}
app_var_init();
// if (get_charge_online_flag()) {
#if(TCFG_SYS_LVD_EN == 1)
vbat_check_init();
#endif
// init_intent(&it);
// it.name = "idle";
// it.action = ACTION_IDLE_MAIN;
// start_app(&it);
// } else {
check_power_on_voltage();
app_poweron_check(update);
init_intent(&it);
it.name = "handler";
it.action = ACTION_EARPHONE_MAIN;
start_app(&it);
// }
log_info("app_main\n");
app_var.start_time = timer_get_ms();
}

View File

@ -1,66 +0,0 @@
#include "app_config.h"
SECTIONS
{
.text : ALIGN(4)
{
gsensor_dev_begin = .;
KEEP(*(.gsensor_dev))
gsensor_dev_end = .;
fm_dev_begin = .;
KEEP(*(.fm_dev))
fm_dev_end = .;
fm_emitter_dev_begin = .;
KEEP(*(.fm_emitter_dev))
fm_emitter_dev_end = .;
storage_device_begin = .;
KEEP(*(.storage_device))
storage_device_end = .;
imusensor_dev_begin = .;
KEEP(*(.imusensor_dev))
imusensor_dev_end = .;
#if TCFG_APP_PC_EN
aac_dec_code_begin = .;
*(.bt_aac_dec_code)
*(.bt_aac_dec_sparse_code)
aac_dec_code_end = .;
aac_dec_code_size = aac_dec_code_end - aac_dec_code_begin ;
. = ALIGN(4);
bt_aac_dec_const_begin = .;
*(.bt_aac_dec_const)
*(.bt_aac_dec_sparse_const)
bt_aac_dec_const_end = .;
bt_aac_dec_const_size = bt_aac_dec_const_end - bt_aac_dec_const_begin ;
*(.bt_aac_dec_data)
*(.bt_aac_dec_bss)
. = ALIGN(4);
*(.aac_mem)
*(.aac_ctrl_mem)
/* . += 0x5fe8 ; */
/* . += 0xef88 ; */
#endif
. = ALIGN(32);
}
.data ALIGN(32):
{
} > ram0
.bss ALIGN(32):
{
} > ram0
.data_code ALIGN(32):
{
} > ram0
}

View File

@ -1,164 +0,0 @@
OVERLAY : AT(0x200000) SUBALIGN(4)
{
.overlay_aec
{
aec_code_begin = . ;
*(.text._*)
*(.data._*)
*(.aec_code)
*(.aec_const)
*(.res_code)
*(.res_const)
*(.ns_code)
*(.ns_const)
*(.bark_const)
*(.fft_code)
*(.fft_const)
*(.agc_code)
*(.dms_code)
*(.dms_const)
*(.dms_sparse_code)
aec_code_end = . ;
aec_code_size = aec_code_end - aec_code_begin ;
*(.msbc_enc)
*(.cvsd_codec)
*(.aec_bss)
*(.aec_data)
*(.res_data)
*(.ns_data)
*(.dns_common_data)
*(.dns_param_data_single)
*(.dns_param_data_dual)
*(.jlsp_nlp_code)
*(.jlsp_nlp_const)
*(.jlsp_aec_code)
*(.jlsp_aec_const)
*(.jlsp_prep_code)
*(.jlsp_prep_const)
*(.jlsp_enc_code)
*(.jlsp_enc_const)
*(.jlsp_wn_code)
*(.jlsp_wn_const)
*(.jlsp_tri_code)
*(.jlsp_tri_const)
*(.jlsp_agc_code)
*(.jlsp_agc_const)
*(.res_bss)
*(.ns_bss)
*(.aec_mem)
}
.overlay_aac
{
#if !TCFG_APP_PC_EN
aac_dec_code_begin = .;
*(.bt_aac_dec_code)
*(.bt_aac_dec_sparse_code)
aac_dec_code_end = .;
aac_dec_code_size = aac_dec_code_end - aac_dec_code_begin ;
. = ALIGN(4);
bt_aac_dec_const_begin = .;
*(.bt_aac_dec_const)
*(.bt_aac_dec_sparse_const)
bt_aac_dec_const_end = .;
bt_aac_dec_const_size = bt_aac_dec_const_end - bt_aac_dec_const_begin ;
*(.bt_aac_dec_data)
*(.bt_aac_dec_bss)
. = ALIGN(4);
*(.aac_mem)
*(.aac_ctrl_mem)
/* . += 0x5fe8 ; */
/* . += 0xef88 ; */
#endif
}
/*
.overlay_lc3
{
lc3_dec_code_begin = .;
*(.lc3_dec_code)
lc3_dec_code_end = .;
lc3_dec_code_size = lc3_dec_code_end - lc3_dec_code_begin;
. = ALIGN(4);
lc3_dec_const_begin = .;
*(.lc3_dec_const)
lc3_dec_const_end = .;
lc3_dec_const_size = lc3_dec_const_end - lc3_dec_const_begin;
*(.lc3_dec_data)
*(.lc3_dec_bss)
}
*/
.overlay_mp3
{
*(.mp3_mem)
*(.mp3_ctrl_mem)
*(.mp3pick_mem)
*(.mp3pick_ctrl_mem)
*(.dec2tws_mem)
}
.overlay_wma
{
*(.wma_mem)
*(.wma_ctrl_mem)
*(.wmapick_mem)
*(.wmapick_ctrl_mem)
}
.overlay_wav
{
*(.wav_mem)
*(.wav_ctrl_mem)
}
.overlay_ape
{
*(.ape_mem)
*(.ape_ctrl_mem)
}
.overlay_flac
{
*(.flac_mem)
*(.flac_ctrl_mem)
}
.overlay_m4a
{
*(.m4a_mem)
*(.m4a_ctrl_mem)
}
.overlay_amr
{
*(.amr_mem)
*(.amr_ctrl_mem)
}
.overlay_dts
{
*(.dts_mem)
*(.dts_ctrl_mem)
}
.overlay_fm
{
*(.fm_mem)
}
.overlay_pc
{
*(.usb_audio_play_dma)
*(.usb_audio_rec_dma)
*(.uac_rx)
*(.mass_storage)
*(.usb_ep0)
*(.usb_msd_dma)
*(.usb_hid_dma)
*(.usb_iso_dma)
*(.usb_cdc_dma)
*(.uac_var)
*(.usb_config_var)
*(.cdc_var)
}
} > ram0

View File

@ -1,27 +0,0 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
/*
* 板级配置选择
*/
#define CONFIG_BOARD_JL701N_DEMO //编译正常 2025-4-29
// #define CONFIG_BOARD_JL701N_BTEMITTER
// #define CONFIG_BOARD_JL701N_ANC
// #define CONFIG_BOARD_JL7016G_HYBRID
// #define CONFIG_BOARD_JL7018F_DEMO //编译不过 2025-4-29
#include "media/audio_def.h"
#include "board_jl701n_demo_cfg.h"
#include "board_jl701n_btemitter_cfg.h"
#include "board_jl701n_anc_cfg.h"
#include "board_jl7016g_hybrid_cfg.h"
#include "board_jl7018f_demo_cfg.h"
#define DUT_AUDIO_DAC_LDO_VOLT DACVDD_LDO_1_25V
#ifdef CONFIG_NEW_CFG_TOOL_ENABLE
#define CONFIG_ENTRY_ADDRESS 0x6000100
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +0,0 @@
#ifndef CONFIG_BOARD_JL7016G_HYBRID_POST_BUILD_CFG_H
#define CONFIG_BOARD_JL7016G_HYBRID_POST_BUILD_CFG_H
/* 改文件只添加和isd_config.ini相关的配置用以生成isd_config.ini */
/* 其他不相关的配置请勿添加在改文件 */
#ifdef CONFIG_BOARD_JL7016G_HYBRID
/* Following Macros Affect Periods Of Both Code Compiling And Post-build */
#define CONFIG_DOUBLE_BANK_ENABLE 0 //单双备份选择(若打开了改宏,FLASH结构变为双备份结构适用于接入第三方协议的OTA PS: JL-OTA同样支持双备份升级, 需要根据实际FLASH大小同时配置CONFIG_FLASH_SIZE)
#define CONFIG_APP_OTA_ENABLE 0 //是否支持RCSP升级(JL-OTA)
#define CONFIG_UPDATE_JUMP_TO_MASK 0 //配置升级到loader的方式0为直接reset,1为跳转(适用于芯片电源由IO口KEEP住的方案,需要注意检查跳转前是否将使用DMA的硬件模块全部关闭)
#define CONFIG_IO_KEY_EN 0 //配置是否使用IO按键配合RESET1
#define CONFIG_UPDATE_WITH_MD5_CHECK_EN 0 //配置升级是否支持MD5校验
#define CONFIG_ANC_ENABLE 1 //配置是否支持ANC
//flash size vaule definition
#define FLASH_SIZE_256K 0x40000
#define FLASH_SIZE_512K 0x80000
#define FLASH_SIZE_1M 0x100000
#define FLASH_SIZE_2M 0x200000
#define FLASH_SIZE_4M 0x400000
#define CONFIG_FLASH_SIZE FLASH_SIZE_1M //配置FLASH大小
/* Above Macros Affect Periods Of Both Code Compiling And Post-build */
/* Following Macros Only For Post Bulid Configuaration */
#define CONFIG_DB_UPDATE_DATA_GENERATE_EN 0 //是否生成db_data.bin(用于第三方协议接入使用)
#define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 0 //ufw只生成1份4K对齐的代码
//config for supported chip version
#ifdef CONFIG_BR30_C_VERSION
#define CONFIG_SUPPORTED_CHIP_VERSION C
#else
#define CONFIG_SUPPORTED_CHIP_VERSION B,D,E,M,N,O,P
#endif
//DON'T MODIFY THIS CONFIG EXCEPT SDK PUBLISHER
#define CONFIG_CHIP_NAME AC701N //除了SDK发布者,请不要修改
//it can be modified before first programming,but keep the same as the original version
#define CONFIG_PID AC701N //烧写或强制升级之前可以修改,之后升级要保持一致
//it can be modified before first programming,but keep the same as the original version
#define CONFIG_VID 0.01 //烧写或强制升级之前可以修改,之后升级要保持一致
//Project with bluetooth,it must use OSC as PLL_SOURCE;
#define CONFIG_PLL_SOURCE_USING_LRC 0 //PLL时钟源选择 1:LRC 2:OSC
//config alignment size unit
#ifdef CONFIG_256K_FLASH
#define ALIGN_UNIT_256B 1 //FLASH对齐方式选择如果是256K的FLASH选择256BYTE对齐方式
#else
#define ALIGN_UNIT_256B 0
#endif
//partial platform check this config to select the uart IO for wired update
#define CONFIG_UART_UPDATE_PIN PP00
//isd_download loader/uboot/update_loader debug io config
//#define CONFIG_UBOOT_DEBUG_PIN PA05
//#define CONFIG_UBOOT_DEBUG_BAUD_RATE 1000000
//config long-press reset io pin,time,trigger level
#define CONFIG_RESET_PIN LDO //io pin
#define CONFIG_RESET_TIME 04 //unit:second
#define CONFIG_RESET_LEVEL 1 //tigger level(0/1)
#if CONFIG_IO_KEY_EN
#define CONFIG_SUPPORT_RESET1
#define CONFIG_RESET1_PIN PB01 //io pin
#define CONFIG_RESET1_TIME 08 //unit:second
#define CONFIG_RESET1_LEVEL 0 //tigger level(0/1)
#endif
//reserved three custom cfg item for the future definition
//#define CONFIG_CUSTOM_CFG1_TYPE POWER_PIN
//#define CONFIG_CUSTOM_CFG1_VALUE PC01_1
//#define CONFIG_CUSTOM_CFG2_TYPE
//#define CONFIG_CUSTOM_CFG2_VALUE
//#define CONFIG_CUSTOM_CFG3_TYPE
//#define CONFIG_CUSTOM_CFG3_VALUE
//#define CONFIG_VDDIO_LVD_LEVEL 4 ////VDDIO_LVD挡位0: 1.9V 1: 2.0V 2: 2.1V 3: 2.2V 4: 2.3V 5: 2.4V 6: 2.5V 7: 2.6V
//with single-bank mode,actual vm size should larger this VM_LEAST_SIZE,and dual bank mode,actual vm size equals this;
#define CONFIG_VM_LEAST_SIZE 8K
//config whether erased this area when do a update,1-No Operation,0-Erase
#define CONFIG_VM_OPT 1
//config whether erased this area when do a update,1-No Operation,0-Erase
#define CONFIG_BTIF_OPT 1
//reserved two custom cfg area for the future definition
//#define CONFIG_RESERVED_AREA1 EXIF1
#ifdef CONFIG_RESERVED_AREA1
#define CONFIG_RESERVED_AREA1_ADDR AUTO
#define CONFIG_RESERVED_AREA1_LEN 0x1000
#define CONFIG_RESERVED_AREA1_OPT 1
//#define CONFIG_RESERVED_AREA1_FILE anc_gains.bin
#endif
//#define CONFIG_RESERVED_AREA2 EXIF2
#ifdef CONFIG_RESERVED_AREA2
#define CONFIG_RESERVED_AREA2_ADDR AUTO
#define CONFIG_RESERVED_AREA2_LEN 0x1000
#define CONFIG_RESERVED_AREA2_OPT 1
//#define CONFIG_RESERVED_AREA2_FILE anc_gains.bin
#endif
/* Above Macros Only For Post Bulid Configuaration */
#endif /* #ifdef CONFIG_BOARD_JL7016G_HYBRID */
#endif /* #ifndef CONFIG_BOARD_JL701N_ANC_POST_BUILD_CFG_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +0,0 @@
#ifndef CONFIG_BOARD_JL7018F_DEMO_POST_BUILD_CFG_H
#define CONFIG_BOARD_JL7018F_DEMO_POST_BUILD_CFG_H
/* 改文件只添加和isd_config.ini相关的配置用以生成isd_config.ini */
/* 其他不相关的配置请勿添加在改文件 */
#ifdef CONFIG_BOARD_JL7018F_DEMO
/* Following Macros Affect Periods Of Both Code Compiling And Post-build */
#define CONFIG_DOUBLE_BANK_ENABLE 0 //单双备份选择(若打开了改宏,FLASH结构变为双备份结构适用于接入第三方协议的OTA PS: JL-OTA同样支持双备份升级, 需要根据实际FLASH大小同时配置CONFIG_FLASH_SIZE)
#define CONFIG_APP_OTA_ENABLE 0 //是否支持RCSP升级(JL-OTA)
#define CONFIG_UPDATE_JUMP_TO_MASK 0 //配置升级到loader的方式0为直接reset,1为跳转(适用于芯片电源由IO口KEEP住的方案,需要注意检查跳转前是否将使用DMA的硬件模块全部关闭)
#define CONFIG_IO_KEY_EN 0 //配置是否使用IO按键配合RESET1
#define CONFIG_UPDATE_WITH_MD5_CHECK_EN 0 //配置升级是否支持MD5校验
#define CONFIG_ANC_ENABLE 1 //配置是否支持ANC
//flash size vaule definition
#define FLASH_SIZE_256K 0x40000
#define FLASH_SIZE_512K 0x80000
#define FLASH_SIZE_1M 0x100000
#define FLASH_SIZE_2M 0x200000
#define FLASH_SIZE_4M 0x400000
#define CONFIG_FLASH_SIZE FLASH_SIZE_1M //配置FLASH大小
/* Above Macros Affect Periods Of Both Code Compiling And Post-build */
/* Following Macros Only For Post Bulid Configuaration */
#define CONFIG_DB_UPDATE_DATA_GENERATE_EN 0 //是否生成db_data.bin(用于第三方协议接入使用)
#define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 0 //ufw只生成1份4K对齐的代码
//config for supported chip version
#ifdef CONFIG_BR30_C_VERSION
#define CONFIG_SUPPORTED_CHIP_VERSION C
#else
#define CONFIG_SUPPORTED_CHIP_VERSION B,D,E,M,N,O,P
#endif
//DON'T MODIFY THIS CONFIG EXCEPT SDK PUBLISHER
#define CONFIG_CHIP_NAME AC701N //除了SDK发布者,请不要修改
//it can be modified before first programming,but keep the same as the original version
#define CONFIG_PID AC701N //烧写或强制升级之前可以修改,之后升级要保持一致
//it can be modified before first programming,but keep the same as the original version
#define CONFIG_VID 0.01 //烧写或强制升级之前可以修改,之后升级要保持一致
//Project with bluetooth,it must use OSC as PLL_SOURCE;
#define CONFIG_PLL_SOURCE_USING_LRC 0 //PLL时钟源选择 1:LRC 2:OSC
//config alignment size unit
#ifdef CONFIG_256K_FLASH
#define ALIGN_UNIT_256B 1 //FLASH对齐方式选择如果是256K的FLASH选择256BYTE对齐方式
#else
#define ALIGN_UNIT_256B 0
#endif
//partial platform check this config to select the uart IO for wired update
#define CONFIG_UART_UPDATE_PIN PP00
//isd_download loader/uboot/update_loader debug io config
//#define CONFIG_UBOOT_DEBUG_PIN PA05
//#define CONFIG_UBOOT_DEBUG_BAUD_RATE 1000000
//config long-press reset io pin,time,trigger level
#define CONFIG_RESET_PIN LDO //io pin
#define CONFIG_RESET_TIME 04 //unit:second
#define CONFIG_RESET_LEVEL 1 //tigger level(0/1)
#if CONFIG_IO_KEY_EN
#define CONFIG_SUPPORT_RESET1
#define CONFIG_RESET1_PIN PB01 //io pin
#define CONFIG_RESET1_TIME 08 //unit:second
#define CONFIG_RESET1_LEVEL 0 //tigger level(0/1)
#endif
//reserved three custom cfg item for the future definition
//#define CONFIG_CUSTOM_CFG1_TYPE POWER_PIN
//#define CONFIG_CUSTOM_CFG1_VALUE PC01_1
//#define CONFIG_CUSTOM_CFG2_TYPE
//#define CONFIG_CUSTOM_CFG2_VALUE
//#define CONFIG_CUSTOM_CFG3_TYPE
//#define CONFIG_CUSTOM_CFG3_VALUE
//#define CONFIG_VDDIO_LVD_LEVEL 4 ////VDDIO_LVD挡位0: 1.9V 1: 2.0V 2: 2.1V 3: 2.2V 4: 2.3V 5: 2.4V 6: 2.5V 7: 2.6V
//with single-bank mode,actual vm size should larger this VM_LEAST_SIZE,and dual bank mode,actual vm size equals this;
#define CONFIG_VM_LEAST_SIZE 8K
//config whether erased this area when do a update,1-No Operation,0-Erase
#define CONFIG_VM_OPT 1
//config whether erased this area when do a update,1-No Operation,0-Erase
#define CONFIG_BTIF_OPT 1
//reserved two custom cfg area for the future definition
//#define CONFIG_RESERVED_AREA1 EXIF1
#ifdef CONFIG_RESERVED_AREA1
#define CONFIG_RESERVED_AREA1_ADDR AUTO
#define CONFIG_RESERVED_AREA1_LEN 0x1000
#define CONFIG_RESERVED_AREA1_OPT 1
//#define CONFIG_RESERVED_AREA1_FILE anc_gains.bin
#endif
//#define CONFIG_RESERVED_AREA2 EXIF2
#ifdef CONFIG_RESERVED_AREA2
#define CONFIG_RESERVED_AREA2_ADDR AUTO
#define CONFIG_RESERVED_AREA2_LEN 0x1000
#define CONFIG_RESERVED_AREA2_OPT 1
//#define CONFIG_RESERVED_AREA2_FILE anc_gains.bin
#endif
/* Above Macros Only For Post Bulid Configuaration */
#endif /* #ifdef CONFIG_BOARD_JL7018F_DEMO */
#endif /* #ifndef CONFIG_BOARD_JL7018F_DEMO_POST_BUILD_CFG_H */

View File

@ -1,992 +0,0 @@
#include "app_config.h"
#ifdef CONFIG_BOARD_JL701N_ANC
#include "system/includes.h"
#include "media/includes.h"
#include "asm/sdmmc.h"
#include "asm/chargestore.h"
#include "asm/umidigi_chargestore.h"
#include "asm/charge.h"
#include "asm/pwm_led.h"
#include "tone_player.h"
#include "audio_config.h"
#include "gSensor/gSensor_manage.h"
#include "key_event_deal.h"
#include "asm/lp_touch_key_api.h"
#include "user_cfg.h"
#include "norflash_sfc.h"
#include "asm/power/power_port.h"
#include "app_umidigi_chargestore.h"
#include "audio_link.h"
#if TCFG_AUDIO_ANC_ENABLE
#include "audio_anc.h"
#endif/*TCFG_AUDIO_ANC_ENABLE*/
#define LOG_TAG_CONST BOARD
#define LOG_TAG "[BOARD]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
void board_power_init(void);
/*各个状态下默认的闪灯方式和提示音设置如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1则会从配置文件读取对应的配置来填充改结构体*/
STATUS_CONFIG status_config = {
//灯状态设置
.led = {
.charge_start = PWM_LED1_ON,
.charge_full = PWM_LED0_ON,
.power_on = PWM_LED0_ON,
.power_off = PWM_LED1_FLASH_THREE,
.lowpower = PWM_LED1_SLOW_FLASH,
.max_vol = PWM_LED_NULL,
.phone_in = PWM_LED_NULL,
.phone_out = PWM_LED_NULL,
.phone_activ = PWM_LED_NULL,
.bt_init_ok = PWM_LED0_LED1_SLOW_FLASH,
.bt_connect_ok = PWM_LED0_ONE_FLASH_5S,
.bt_disconnect = PWM_LED0_LED1_FAST_FLASH,
.tws_connect_ok = PWM_LED0_LED1_FAST_FLASH,
.tws_disconnect = PWM_LED0_LED1_SLOW_FLASH,
},
//提示音设置
.tone = {
.charge_start = IDEX_TONE_NONE,
.charge_full = IDEX_TONE_NONE,
.power_on = IDEX_TONE_POWER_ON,
.power_off = IDEX_TONE_POWER_OFF,
.lowpower = IDEX_TONE_LOW_POWER,
.max_vol = IDEX_TONE_MAX_VOL,
.phone_in = IDEX_TONE_NONE,
.phone_out = IDEX_TONE_NONE,
.phone_activ = IDEX_TONE_NONE,
.bt_init_ok = IDEX_TONE_BT_MODE,
.bt_connect_ok = IDEX_TONE_BT_CONN,
.bt_disconnect = IDEX_TONE_BT_DISCONN,
.tws_connect_ok = IDEX_TONE_TWS_CONN,
.tws_disconnect = IDEX_TONE_TWS_DISCONN,
}
};
#define __this (&status_config)
/************************** KEY MSG****************************/
/*各个按键的消息设置如果USER_CFG中设置了USE_CONFIG_KEY_SETTING为1则会从配置文件读取对应的配置来填充改结构体*/
#if CLIENT_BOARD == CUSTOM10_CFG
u8 key_table[KEY_NUM_MAX][KEY_EVENT_MAX] = {
// SHORT LONG HOLD UP DOUBLE TRIPLE
{KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ANC_SWITCH, KEY_NULL}, //KEY_0
{KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_OPEN_SIRI, KEY_NULL}, //KEY_1
{KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_HID_CONTROL, KEY_NULL}, //KEY_2
};
#else
u8 key_table[KEY_NUM_MAX][KEY_EVENT_MAX] = {
// SHORT LONG HOLD UP DOUBLE TRIPLE
{KEY_MUSIC_PP, KEY_ANC_SWITCH, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL}, //KEY_0
{KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_OPEN_SIRI, KEY_NULL}, //KEY_1
{KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_HID_CONTROL, KEY_NULL}, //KEY_2
};
#endif
// *INDENT-OFF*
/************************** UART config****************************/
#if TCFG_UART0_ENABLE
UART0_PLATFORM_DATA_BEGIN(uart0_data)
.tx_pin = TCFG_UART0_TX_PORT, //串口打印TX引脚选择
.rx_pin = TCFG_UART0_RX_PORT, //串口打印RX引脚选择
.baudrate = TCFG_UART0_BAUDRATE, //串口波特率
.flags = UART_DEBUG, //串口用来打印需要把改参数设置为UART_DEBUG
UART0_PLATFORM_DATA_END()
#endif //TCFG_UART0_ENABLE
/************************** CHARGE config****************************/
#if TCFG_CHARGE_ENABLE
CHARGE_PLATFORM_DATA_BEGIN(charge_data)
.charge_en = TCFG_CHARGE_ENABLE, //内置充电使能
.charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机
.charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压
.charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流
.charge_mA = TCFG_CHARGE_MA, //恒流充电电流
.charge_trickle_mA = TCFG_CHARGE_TRICKLE_MA, //涓流充电电流
/*ldo5v拔出过滤值过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出
对于充满直接从5V掉到0V的充电仓该值必须设置成0对于充满由5V先掉到0V之后再升压到xV的
充电仓,需要根据实际情况设置该值大小*/
.ldo5v_off_filter = 100,
.ldo5v_on_filter = 50,
.ldo5v_keep_filter = 220,
.ldo5v_pulldown_lvl = CHARGE_PULLDOWN_200K, //下拉电阻档位选择
.ldo5v_pulldown_keep = 0,
//1、对于自动升压充电舱,若充电舱需要更大的负载才能检测到插入时请将该变量置1,并且根据需求配置下拉电阻档位
//2、对于按键升压,并且是通过上拉电阻去提供维持电压的舱,请将该变量设置1,并且根据舱的上拉配置下拉需要的电阻挡位
//3、对于常5V的舱,可将改变量设为0,省功耗
//4、为LDOIN防止被误触发唤醒,可设置为200k下拉
.ldo5v_pulldown_en = 1,
CHARGE_PLATFORM_DATA_END()
#endif//TCFG_CHARGE_ENABLE
/************************** chargestore config****************************/
#if TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE || TCFG_ANC_BOX_ENABLE
CHARGESTORE_PLATFORM_DATA_BEGIN(chargestore_data)
.io_port = TCFG_CHARGESTORE_PORT,
CHARGESTORE_PLATFORM_DATA_END()
#endif
/************************** DAC ****************************/
#if TCFG_AUDIO_DAC_ENABLE
struct dac_platform_data dac_data = {
.mode = TCFG_AUDIO_DAC_MODE, //dac输出模式
.ldo_id = TCFG_AUDIO_DAC_LDO_SEL, //保留位
.pa_mute_port = TCFG_AUDIO_DAC_PA_PORT, //暂时无作用
.vcmo_en = 0, //是否打开VCOMO
.pa_mute_value = 1, //暂时无作用
.output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置和具体硬件连接有关需根据硬件来设置
.lpf_isel = 0xf,
.sys_vol_type = SYS_VOL_TYPE, //系统音量选择:模拟音量/数字音量,调节时调节对应的音量
.max_ana_vol = MAX_ANA_VOL, //模拟音量最大等级
.max_dig_vol = MAX_DIG_VOL, //数字音量最大等级
/* .dig_vol_tab = (s16 *)dig_vol_table, //数字音量表 */
.vcm_cap_en = 1, //配1代表走外部通路,vcm上有电容时,可以提升电路抑制电源噪声能力提高ADC的性能配0相当于vcm上无电容抑制电源噪声能力下降,ADC性能下降
#if (SYS_VOL_TYPE == VOL_TYPE_AD)
.digital_gain_limit = 16384,
#endif // #if (SYS_VOL_TYPE == VOL_TYPE_AD)
.power_on_mode = 0,
};
#endif
/************************** ADC ****************************/
#if TCFG_AUDIO_ADC_ENABLE
#ifndef TCFG_AUDIO_MIC0_BIAS_EN
#define TCFG_AUDIO_MIC0_BIAS_EN 0
#endif/*TCFG_AUDIO_MIC0_BIAS_EN*/
#ifndef TCFG_AUDIO_MIC1_BIAS_EN
#define TCFG_AUDIO_MIC1_BIAS_EN 0
#endif/*TCFG_AUDIO_MIC1_BIAS_EN*/
#ifndef TCFG_AUDIO_MIC2_BIAS_EN
#define TCFG_AUDIO_MIC2_BIAS_EN 0
#endif/*TCFG_AUDIO_MIC2_BIAS_EN*/
#ifndef TCFG_AUDIO_MIC3_BIAS_EN
#define TCFG_AUDIO_MIC3_BIAS_EN 0
#endif/*TCFG_AUDIO_MIC3_BIAS_EN*/
#ifndef TCFG_AUDIO_MIC_LDO_EN
#define TCFG_AUDIO_MIC_LDO_EN 0
#endif/*TCFG_AUDIO_MIC_LDO_EN*/
struct adc_platform_data adc_data = {
/*MIC LDO电流档位设置
0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/
.mic_ldo_isel = TCFG_AUDIO_ADC_LD0_SEL,
/*mic_mode 工作模式定义
#define AUDIO_MIC_CAP_MODE 0 //单端隔直电容模式
#define AUDIO_MIC_CAP_DIFF_MODE 1 //差分隔直电容模式
#define AUDIO_MIC_CAPLESS_MODE 2 //单端省电容模式
*/
.mic_mode = TCFG_AUDIO_MIC_MODE,
.mic1_mode = TCFG_AUDIO_MIC1_MODE,
.mic2_mode = TCFG_AUDIO_MIC2_MODE,
.mic3_mode = TCFG_AUDIO_MIC3_MODE,
.mic_bias_inside = TCFG_AUDIO_MIC0_BIAS_EN,
.mic1_bias_inside = TCFG_AUDIO_MIC1_BIAS_EN,
.mic2_bias_inside = TCFG_AUDIO_MIC2_BIAS_EN,
.mic3_bias_inside = TCFG_AUDIO_MIC3_BIAS_EN,
/*MICLDO供电输出到PAD(PA0)控制使能*/
.mic_ldo_pwr = TCFG_AUDIO_MIC_LDO_EN, // MIC LDO 输出到 PA0
/*MIC免电容方案需要设置影响MIC的偏置电压
0b0001~0b1001 : 0.5k ~ 4.5k step = 0.5k
0b1010~0b1111 : 5k ~ 10k step = 1k */
.mic_bias_res = 4,
.mic1_bias_res = 4,
.mic2_bias_res = 4,
.mic3_bias_res = 4,
/*MIC LDO电压档位设置,也会影响MIC的偏置电压
3:2.0v 4:2.2v 5:2.4v 6:2.6v 7:2.8v */
.mic_ldo_vsel = 5,
//mic的去直流dcc寄存器配置值,可配0到15,数值越大,其高通转折点越低
.mic_dcc = 8,
/*ADC低功耗等级,越大功耗越低对应影响THD和底噪, 范围 (0 - 2)*/
.lowpower_lvl = 0,
};
#endif
const struct vad_mic_platform_data vad_mic_data = {
.mic_data = { //
.mic_mode = TCFG_AUDIO_MIC_MODE,
.mic_ldo_isel = 2,
.mic_ldo_vsel = 5,
.mic_ldo2PAD_en = 1,
.mic_bias_en = 0,
.mic_bias_res = 0,
.mic_bias_inside = TCFG_AUDIO_MIC0_BIAS_EN,
/* ADC偏置电阻配置*/
.adc_rbs = 3,
/* ADC输入电阻配置*/
.adc_rin = 3,
/*.adc_test = 1,*/
},
.power_data = {
/*VADLDO电压档位0~7*/
.ldo_vs = 3,
/*VADLDO误差运放电流档位0~3*/
#if TCFG_VAD_LOWPOWER_CLOCK == VAD_CLOCK_USE_PMU_STD12M
.ldo_is = 1,
#else
.ldo_is = 2,
#endif
.clock = TCFG_VAD_LOWPOWER_CLOCK, /*VAD时钟选项*/
.acm_select = 8,
},
};
/* struct audio_pf_data audio_pf_d = { */
/* #if TCFG_AUDIO_DAC_ENABLE */
/* .adc_pf_data = &adc_data, */
/* #endif */
/* #if TCFG_AUDIO_ADC_ENABLE */
/* .dac_pf_data = &dac_data, */
/* #endif */
/* }; */
/* struct audio_platform_data audio_data = { */
/* .private_data = (void *) &audio_pf_d, */
/* }; */
/************************** IO KEY ****************************/
#if TCFG_IOKEY_ENABLE
const struct iokey_port iokey_list[] = {
{
.connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式
.key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚
.key_value = 0, //按键值
},
};
const struct iokey_platform_data iokey_data = {
.enable = TCFG_IOKEY_ENABLE, //是否使能IO按键
.num = ARRAY_SIZE(iokey_list), //IO按键的个数
.port = iokey_list, //IO按键参数表
};
#if MULT_KEY_ENABLE
//组合按键消息映射表
//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2
//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下,
//remap_value = 3指当这两个按键被同时按下后重新映射的按键值;
const struct key_remap iokey_remap_table[] = {
{.bit_value = BIT(0) | BIT(1), .remap_value = 3},
{.bit_value = BIT(0) | BIT(2), .remap_value = 4},
{.bit_value = BIT(1) | BIT(2), .remap_value = 5},
};
const struct key_remap_data iokey_remap_data = {
.remap_num = ARRAY_SIZE(iokey_remap_table),
.table = iokey_remap_table,
};
#endif
#endif
/*********************** LP TOUCH KEY ****************************/
#if TCFG_LP_TOUCH_KEY_ENABLE
const struct lp_touch_key_platform_data lp_touch_key_config = {
/*触摸按键*/
.ch[0].enable = TCFG_LP_TOUCH_KEY0_EN,
.ch[0].wakeup_enable = TCFG_LP_TOUCH_KEY0_WAKEUP_EN,
.ch[0].port = IO_PORTB_00,
.ch[0].sensitivity = TCFG_LP_TOUCH_KEY0_SENSITIVITY,
.ch[0].key_value = 0,
.ch[1].enable = TCFG_LP_TOUCH_KEY1_EN,
.ch[1].wakeup_enable = TCFG_LP_TOUCH_KEY1_WAKEUP_EN,
.ch[1].port = IO_PORTB_01,
.ch[1].sensitivity = TCFG_LP_TOUCH_KEY1_SENSITIVITY,
.ch[1].key_value = 0,
.ch[2].enable = TCFG_LP_TOUCH_KEY2_EN,
.ch[2].wakeup_enable = TCFG_LP_TOUCH_KEY2_WAKEUP_EN,
.ch[2].port = IO_PORTB_02,
.ch[2].sensitivity = TCFG_LP_TOUCH_KEY2_SENSITIVITY,
.ch[2].key_value = 1,
.ch[3].enable = TCFG_LP_TOUCH_KEY3_EN,
.ch[3].wakeup_enable = TCFG_LP_TOUCH_KEY3_WAKEUP_EN,
.ch[3].port = IO_PORTB_04,
.ch[3].sensitivity = TCFG_LP_TOUCH_KEY3_SENSITIVITY,
.ch[3].key_value = 2,
.ch[4].enable = TCFG_LP_TOUCH_KEY4_EN,
.ch[4].wakeup_enable = TCFG_LP_TOUCH_KEY4_WAKEUP_EN,
.ch[4].port = IO_PORTB_05,
.ch[4].sensitivity = TCFG_LP_TOUCH_KEY4_SENSITIVITY,
.ch[4].key_value = 3,
//把触摸按键之间的滑动也当做按键处理,有上滑,下滑,左滑,右滑
.slide_mode_en = TCFG_LP_SLIDE_KEY_ENABLE,
.slide_mode_key_value = 3,
//入耳检测相关的配置
.eartch_en = TCFG_LP_EARTCH_KEY_ENABLE,
.eartch_ch = TCFG_LP_EARTCH_KEY_CH,
.eartch_ref_ch = TCFG_LP_EARTCH_KEY_REF_CH,
.eartch_soft_inear_val = TCFG_LP_EARTCH_SOFT_INEAR_VAL,
.eartch_soft_outear_val = TCFG_LP_EARTCH_SOFT_OUTEAR_VAL,
};
#endif /* #if TCFG_LP_TOUCH_KEY_ENABLE */
/************************** PLCNT TOUCH_KEY ****************************/
#if TCFG_TOUCH_KEY_ENABLE
const const struct touch_key_port touch_key_list[] = {
{
.press_delta = TCFG_TOUCH_KEY0_PRESS_DELTA,
.port = TCFG_TOUCH_KEY0_PORT,
.key_value = TCFG_TOUCH_KEY0_VALUE,
},
{
.press_delta = TCFG_TOUCH_KEY1_PRESS_DELTA,
.port = TCFG_TOUCH_KEY1_PORT,
.key_value = TCFG_TOUCH_KEY1_VALUE,
},
};
const struct touch_key_platform_data touch_key_data = {
.num = ARRAY_SIZE(touch_key_list),
.port_list = touch_key_list,
};
#endif /* #if TCFG_TOUCH_KEY_ENABLE */
/************************** AD KEY ****************************/
#if TCFG_ADKEY_ENABLE
const struct adkey_platform_data adkey_data = {
.enable = TCFG_ADKEY_ENABLE, //AD按键使能
.adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚
.ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值
.extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻
.ad_value = { //根据电阻算出来的电压值
TCFG_ADKEY_VOLTAGE0,
TCFG_ADKEY_VOLTAGE1,
TCFG_ADKEY_VOLTAGE2,
TCFG_ADKEY_VOLTAGE3,
TCFG_ADKEY_VOLTAGE4,
TCFG_ADKEY_VOLTAGE5,
TCFG_ADKEY_VOLTAGE6,
TCFG_ADKEY_VOLTAGE7,
TCFG_ADKEY_VOLTAGE8,
TCFG_ADKEY_VOLTAGE9,
},
.key_value = { //AD按键各个按键的键值
TCFG_ADKEY_VALUE0,
TCFG_ADKEY_VALUE1,
TCFG_ADKEY_VALUE2,
TCFG_ADKEY_VALUE3,
TCFG_ADKEY_VALUE4,
TCFG_ADKEY_VALUE5,
TCFG_ADKEY_VALUE6,
TCFG_ADKEY_VALUE7,
TCFG_ADKEY_VALUE8,
TCFG_ADKEY_VALUE9,
},
};
#endif
/************************** RDEC_KEY ****************************/
#if TCFG_RDEC_KEY_ENABLE
const struct rdec_device rdeckey_list[] = {
{
.index = RDEC0 ,
.sin_port0 = TCFG_RDEC0_ECODE1_PORT,
.sin_port1 = TCFG_RDEC0_ECODE2_PORT,
.key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7),
.key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7),
},
{
.index = RDEC1 ,
.sin_port0 = TCFG_RDEC1_ECODE1_PORT,
.sin_port1 = TCFG_RDEC1_ECODE2_PORT,
.key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7),
.key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7),
},
{
.index = RDEC2 ,
.sin_port0 = TCFG_RDEC2_ECODE1_PORT,
.sin_port1 = TCFG_RDEC2_ECODE2_PORT,
.key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7),
.key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7),
},
};
const struct rdec_platform_data rdec_key_data = {
.enable = 1, //TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键
.num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数
.rdec = rdeckey_list, //RDEC按键参数表
};
#endif
/************************** IIS config ****************************/
#if (TCFG_AUDIO_INPUT_IIS || TCFG_AUDIO_OUTPUT_IIS)
ALINK_PARM alink0_platform_data = {
.module = ALINK0,
.mclk_io = TCFG_IIS_MCLK_IO,
.sclk_io = TCFG_SCLK_IO,
.lrclk_io = TCFG_LRCLK_IO,
.ch_cfg[0].data_io = TCFG_DATA0_IO,
.ch_cfg[1].data_io = TCFG_DATA1_IO,
.ch_cfg[2].data_io = TCFG_DATA2_IO,
.ch_cfg[3].data_io = TCFG_DATA3_IO,
.mode = ALINK_MD_IIS,
#if TCFG_IIS_MODE
.role = ALINK_ROLE_SLAVE,
#else
.role = ALINK_ROLE_MASTER,
#endif /*TCFG_IIS_MODE*/
.clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE,
.bitwide = ALINK_LEN_16BIT,
.sclk_per_frame = ALINK_FRAME_32SCLK,
.dma_len = 4 * 1024,
.sample_rate = TCFG_IIS_SR,
.buf_mode = ALINK_BUF_CIRCLE,
/*.iperiod = 64, //配置该项可以控制输入的延时*/
};
#endif
/************************** PWM_LED ****************************/
#if TCFG_PWMLED_ENABLE
LED_PLATFORM_DATA_BEGIN(pwm_led_data)
.io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯
.io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置
LED_PLATFORM_DATA_END()
#endif
const struct soft_iic_config soft_iic_cfg[] = {
#if 0
//iic0 data
{
.scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚
.sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚
.delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数影响通讯时钟频率
.io_pu = 1, //是否打开上拉电阻如果外部电路没有焊接上拉电阻需要置1
},
#endif
#if 0
//iic1 data
{
.scl = IO_PORTA_05,
.sda = IO_PORTA_06,
.delay = 50,
.io_pu = 1,
},
#endif
};
const struct hw_iic_config hw_iic_cfg[] = {
#if 0
//iic0 data
{
/*硬件IIC端口下选择
SCL SDA
{IO_PORT_DP, IO_PORT_DM}, //group a
{IO_PORTC_04, IO_PORTC_05}, //group b
{IO_PORTC_02, IO_PORTC_03}, //group c
{IO_PORTA_05, IO_PORTA_06}, //group d
*/
.port = TCFG_HW_I2C0_PORTS,
.baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率
.hdrive = 0, //是否打开IO口强驱
.io_filter = 1, //是否打开滤波器(去纹波)
.io_pu = 1, //是否打开上拉电阻如果外部电路没有焊接上拉电阻需要置1
},
#endif
};
#if TCFG_SD0_ENABLE
SD0_PLATFORM_DATA_BEGIN(sd0_data)
.port = {
TCFG_SD0_PORT_CMD,
TCFG_SD0_PORT_CLK,
TCFG_SD0_PORT_DA0,
TCFG_SD0_PORT_DA1,
TCFG_SD0_PORT_DA2,
TCFG_SD0_PORT_DA3,
},
.data_width = TCFG_SD0_DAT_MODE,
.speed = TCFG_SD0_CLK,
.detect_mode = TCFG_SD0_DET_MODE,
.priority = 3,
#if (TCFG_SD0_DET_MODE == SD_IO_DECT)
.detect_io = TCFG_SD0_DET_IO,
.detect_io_level = TCFG_SD0_DET_IO_LEVEL,
.detect_func = sdmmc_0_io_detect,
.power = sd_set_power,
/* .power = NULL, */
#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT)
.detect_io_level = TCFG_SD0_DET_IO_LEVEL,
.detect_func = sdmmc_0_clk_detect,
.power = sd_set_power,
/* .power = NULL, */
#else
.detect_func = sdmmc_cmd_detect,
.power = NULL,
#endif
SD0_PLATFORM_DATA_END()
#endif /* #if TCFG_SD0_ENABLE */
REGISTER_DEVICES(device_table) = {
/* { "audio", &audio_dev_ops, (void *) &audio_data }, */
#if TCFG_CHARGE_ENABLE
{ "charge", &charge_dev_ops, (void *)&charge_data },
#endif
#if TCFG_SD0_ENABLE
{ "sd0", &sd_dev_ops, (void *) &sd0_data},
#endif
};
/************************** power_param ****************************/
const struct low_power_param power_param = {
.config = TCFG_LOWPOWER_LOWPOWER_SEL, //低功耗使能,蓝牙&&系统空闲可进入低功耗
.btosc_hz = TCFG_CLOCK_OSC_HZ, //蓝牙晶振频率
.delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改)
.vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //vddiom等级
.osc_type = TCFG_LOWPOWER_OSC_TYPE, //低功耗晶振类型btosc/lrc
#if (TCFG_LOWPOWER_RAM_SIZE)
.mem_init_con = MEM_PWR_RAM_SET(TCFG_LOWPOWER_RAM_SIZE),
#else
.mem_init_con = 0,
#endif
#if (TCFG_LP_TOUCH_KEY_ENABLE && \
(TCFG_LP_TOUCH_KEY0_WAKEUP_EN || \
TCFG_LP_TOUCH_KEY1_WAKEUP_EN || \
TCFG_LP_TOUCH_KEY2_WAKEUP_EN || \
TCFG_LP_TOUCH_KEY3_WAKEUP_EN || \
TCFG_LP_TOUCH_KEY4_WAKEUP_EN ))
.lpctmu_en = 1,
#else
.lpctmu_en = 0,
#endif
};
/************************** wk_param ****************************/
struct port_wakeup port0 = {
.pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能
.edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿
.filter = PORT_FLT_8ms,
.iomap = TCFG_IOKEY_POWER_ONE_PORT, //唤醒口选择
};
#if (TCFG_TEST_BOX_ENABLE || TCFG_CHARGESTORE_ENABLE || TCFG_ANC_BOX_ENABLE || TCFG_UMIDIGI_BOX_ENABLE)
struct port_wakeup port1 = {
.pullup_down_enable = DISABLE, //配置I/O 内部上下拉是否使能
.edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿
.filter = PORT_FLT_1ms,
.iomap = TCFG_CHARGESTORE_PORT, //唤醒口选择
};
#endif
#if TCFG_CHARGE_ENABLE
struct port_wakeup charge_port = {
.edge = RISING_EDGE, //唤醒方式选择,可选:上升沿\下降沿\双边沿
.filter = PORT_FLT_16ms,
.iomap = IO_CHGFL_DET, //唤醒口选择
};
struct port_wakeup vbat_port = {
.edge = BOTH_EDGE, //唤醒方式选择,可选:上升沿\下降沿\双边沿
.filter = PORT_FLT_16ms,
.iomap = IO_VBTCH_DET, //唤醒口选择
};
struct port_wakeup ldoin_port = {
.edge = BOTH_EDGE, //唤醒方式选择,可选:上升沿\下降沿\双边沿
.filter = PORT_FLT_16ms,
.iomap = IO_LDOIN_DET, //唤醒口选择
};
#endif
const struct wakeup_param wk_param = {
#if (!(TCFG_LP_TOUCH_KEY_ENABLE && TCFG_LP_TOUCH_KEY1_EN))
.port[1] = &port0,
#endif
#if (TCFG_TEST_BOX_ENABLE || TCFG_CHARGESTORE_ENABLE || TCFG_ANC_BOX_ENABLE || TCFG_UMIDIGI_BOX_ENABLE)
.port[2] = &port1,
#endif
#if TCFG_CHARGE_ENABLE
.aport[0] = &charge_port,
.aport[1] = &vbat_port,
.aport[2] = &ldoin_port,
#endif
};
void gSensor_wkupup_disable(void)
{
log_info("gSensor wkup disable\n");
power_wakeup_index_enable(1, 0);
}
void gSensor_wkupup_enable(void)
{
log_info("gSensor wkup enable\n");
power_wakeup_index_enable(1, 1);
}
void debug_uart_init(const struct uart_platform_data *data)
{
#if TCFG_UART0_ENABLE
if (data) {
uart_init(data);
} else {
uart_init(&uart0_data);
}
#endif
}
STATUS *get_led_config(void)
{
return &(__this->led);
}
STATUS *get_tone_config(void)
{
return &(__this->tone);
}
u8 get_sys_default_vol(void)
{
return 21;
}
u8 get_power_on_status(void)
{
#if TCFG_IOKEY_ENABLE
struct iokey_port *power_io_list = NULL;
power_io_list = iokey_data.port;
if (iokey_data.enable) {
if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){
return 1;
}
}
#endif
#if TCFG_ADKEY_ENABLE
if (adkey_data.enable) {
return 1;
}
#endif
#if TCFG_LP_TOUCH_KEY_ENABLE
return lp_touch_key_power_on_status();
#endif
return 0;
}
static void board_devices_init(void)
{
#if TCFG_PWMLED_ENABLE
pwm_led_init(&pwm_led_data);
#endif
#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_TOUCH_KEY_ENABLE)
key_driver_init();
#endif
#if TCFG_UART_KEY_ENABLE
extern int uart_key_init(void);
uart_key_init();
#endif /* #if TCFG_UART_KEY_ENABLE */
#if TCFG_LP_TOUCH_KEY_ENABLE
lp_touch_key_init(&lp_touch_key_config);
#endif /* #if TCFG_LP_TOUCH_KEY_ENABLE */
#if (!TCFG_CHARGE_ENABLE)
CHARGE_EN(0);
CHGGO_EN(0);
#endif
#if TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE || TCFG_ANC_BOX_ENABLE
chargestore_api_init(&chargestore_data);
#endif
}
//外置触摸电源控制 1:输出高 0:输出地
static void pwr_set_external_touch(u8 high_low)
{
if(TCFG_EXTERNAL_TOUCH_KEY_POWER_PORT == NO_CONFIG_PORT){
return;
}
gpio_set_pull_up(TCFG_EXTERNAL_TOUCH_KEY_POWER_PORT, 1);
gpio_set_pull_down(TCFG_EXTERNAL_TOUCH_KEY_POWER_PORT, 0);
gpio_set_direction(TCFG_EXTERNAL_TOUCH_KEY_POWER_PORT, 0);
gpio_set_output_value(TCFG_EXTERNAL_TOUCH_KEY_POWER_PORT, high_low);
}
#if CLIENT_BOARD == CUSTOM9_CFG
#define TCFG_TALKING_FB_MIC_IO IO_PORTB_02
/*
0:MIC0 作为FB MIC,引脚输出低电平。
1MIC0 作为通话MIC引脚输出高电平。
*/
void TALKING_FB_MIC_sel(u8 mic_type)
{
gpio_set_pull_up(TCFG_TALKING_FB_MIC_IO , 0);
gpio_set_pull_down(TCFG_TALKING_FB_MIC_IO , 0);
gpio_set_direction(TCFG_TALKING_FB_MIC_IO , 0);
gpio_set_die(TCFG_TALKING_FB_MIC_IO , 1);
switch (mic_type)
{
case 0:
gpio_set_output_value(TCFG_TALKING_FB_MIC_IO , 0);
break;
case 1:
gpio_set_output_value(TCFG_TALKING_FB_MIC_IO , 1);
break;
default:
break;
}
}
static u8 dcda_en_state = 0;
#define DCDC_EN_PORT IO_PORTC_02
static void dcdc_en(u8 en)
{
if (dcda_en_state == en)
{
return ;
}
dcda_en_state = en;
gpio_set_die(DCDC_EN_PORT, 0);
gpio_set_direction(IO_PORTB_04, 0);
gpio_set_pull_up(DCDC_EN_PORT, 0);
gpio_set_pull_down(DCDC_EN_PORT, 0);
switch (en)
{
case 0:
printf("external dcdc disable \n");
gpio_direction_output(DCDC_EN_PORT, 0);
break;
case 1:
printf("external dcdc enable \n");
gpio_direction_output(DCDC_EN_PORT, 1);
break;
default:
break;
}
}
static void dcdc_init(void)
{
gpio_set_die(DCDC_EN_PORT, 0);
gpio_set_direction(IO_PORTB_04, 0);
gpio_set_pull_up(DCDC_EN_PORT, 0);
gpio_set_pull_down(DCDC_EN_PORT, 0);
gpio_direction_output(DCDC_EN_PORT, 0);
dcda_en_state = 0;
}
/*dcdc switch*/
void audio_dac_power_state(u8 state)
{
switch (state)
{
case DAC_ANALOG_OPEN_PREPARE:
dcdc_en(1);
break;
case DAC_ANALOG_OPEN_FINISH:
break;
case DAC_ANALOG_CLOSE_PREPARE:
break;
case DAC_ANALOG_CLOSE_FINISH:
dcdc_en(0);
break;
default:
break;
}
}
#endif
extern void cfg_file_parse(u8 idx);
void board_init()
{
pwr_set_external_touch(1);
board_power_init();
//adc_vbg_init();
adc_init();
#if CLIENT_BOARD == CUSTOM9_CFG
dcdc_init();
TALKING_FB_MIC_sel(0);
#endif
cfg_file_parse(0);
devices_init();
#if TCFG_AUDIO_ANC_ENABLE
anc_init();
#endif/*TCFG_AUDIO_ANC_ENABLE*/
board_devices_init();
#if TCFG_CHARGE_ENABLE
if(get_charge_online_flag())
#else
if (0)
#endif
{
power_set_mode(PWR_LDO15);
}else{
power_set_mode(TCFG_LOWPOWER_POWER_SEL);
}
//针对硅mic要输出1给mic供电
/* gpio_set_pull_up(IO_PORTA_04, 0); */
/* gpio_set_pull_down(IO_PORTA_04, 0); */
/* gpio_set_direction(IO_PORTA_04, 0); */
/* gpio_set_output_value(IO_PORTA_04,1); */
#if TCFG_UART0_ENABLE
if (uart0_data.rx_pin < IO_MAX_NUM) {
gpio_set_die(uart0_data.rx_pin, 1);
}
#endif
#if TCFG_SMART_VOICE_ENABLE
int audio_smart_voice_detect_init(struct vad_mic_platform_data *mic_data);
audio_smart_voice_detect_init((struct vad_mic_platform_data *)&vad_mic_data);
#endif /* #if TCFG_SMART_VOICE_ENABLE */
#ifdef CONFIG_BOARD_AISPEECH_VAD_ASR
extern int audio_ais_platform_asr_init(struct vad_mic_platform_data *mic_data);
audio_ais_platform_asr_init((struct vad_mic_platform_data *)&vad_mic_data);
#endif /*CONFIG_BOARD_AISPEECH_VAD_ASR*/
#ifdef AUDIO_PCM_DEBUG
extern void uartSendInit();
uartSendInit();
#endif/*AUDIO_PCM_DEBUG*/
}
/*进软关机之前默认将IO口都设置成高阻状态需要保留原来状态的请修改该函数*/
extern void dac_power_off(void);
void board_set_soft_poweroff(void)
{
//power按键
#if TCFG_IOKEY_ENABLE
soff_gpio_protect(TCFG_IOKEY_POWER_ONE_PORT);
#endif
soff_gpio_protect(TCFG_EXTERNAL_TOUCH_KEY_POWER_PORT);//软关机KEEP外置触摸供电
#if (!(TCFG_LP_TOUCH_KEY_ENABLE && TCFG_LP_TOUCH_KEY1_EN))
//默认唤醒io
soff_gpio_protect(IO_PORTB_01);
#endif
#if (TCFG_TEST_BOX_ENABLE || TCFG_CHARGESTORE_ENABLE || TCFG_ANC_BOX_ENABLE || TCFG_UMIDIGI_BOX_ENABLE)
power_wakeup_index_enable(2, 0);
#endif
board_set_soft_poweroff_common(NULL);
dac_power_off();
}
#define APP_IO_DEBUG_0(i,x) {JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);}
#define APP_IO_DEBUG_1(i,x) {JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);}
void sleep_exit_callback(u32 usec)
{
sleep_exit_callback_common(NULL);
putchar('>');
}
void sleep_enter_callback(u8 step)
{
/* 此函数禁止添加打印 */
if (step == 1) {
putchar('<');
} else {
//外置触摸供电
pwr_set_external_touch(1);
sleep_enter_callback_common(NULL);
}
}
static void port_wakeup_callback(u8 index, u8 gpio)
{
log_info("%s:%d,%d",__FUNCTION__,index,gpio);
#if TCFG_UMIDIGI_BOX_ENABLE
if (index == 2) {
ldo_port_wakeup_to_cmessage();
}
#endif
switch (index) {
#if (TCFG_TEST_BOX_ENABLE || TCFG_CHARGESTORE_ENABLE || TCFG_ANC_BOX_ENABLE)
case 2:
extern void chargestore_ldo5v_fall_deal(void);
chargestore_ldo5v_fall_deal();
break;
#endif
}
}
static void aport_wakeup_callback(u8 index, u8 gpio, u8 edge)
{
log_info("%s:%d,%d",__FUNCTION__,index,gpio);
#if TCFG_CHARGE_ENABLE
switch (gpio) {
case IO_CHGFL_DET://charge port
charge_wakeup_isr();
break;
case IO_VBTCH_DET://vbat port
case IO_LDOIN_DET://ldoin port
ldoin_wakeup_isr();
break;
}
#endif
}
void board_power_init(void)
{
log_info("Power init : %s", __FILE__);
power_init(&power_param);
power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff);
#if TCFG_UMIDIGI_BOX_ENABLE
gpio_set_die(TCFG_CHARGESTORE_PORT, 1);
umidigi_chargestore_message_callback(app_umidigi_chargetore_message_deal);
#endif
power_keep_dacvdd_en(0);
power_wakeup_init(&wk_param);
power_awakeup_set_callback(aport_wakeup_callback);
power_wakeup_set_callback(port_wakeup_callback);
}
#endif /* #ifdef CONFIG_BOARD_JL701N_ANC */

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +0,0 @@
#ifndef CONFIG_BOARD_JL701N_ANC_POST_BUILD_CFG_H
#define CONFIG_BOARD_JL701N_ANC_POST_BUILD_CFG_H
/* 改文件只添加和isd_config.ini相关的配置用以生成isd_config.ini */
/* 其他不相关的配置请勿添加在改文件 */
#ifdef CONFIG_BOARD_JL701N_ANC
/* Following Macros Affect Periods Of Both Code Compiling And Post-build */
#define CONFIG_DOUBLE_BANK_ENABLE 0 //单双备份选择(若打开了改宏,FLASH结构变为双备份结构适用于接入第三方协议的OTA PS: JL-OTA同样支持双备份升级, 需要根据实际FLASH大小同时配置CONFIG_FLASH_SIZE)
#define CONFIG_APP_OTA_ENABLE 0 //是否支持RCSP升级(JL-OTA)
#define CONFIG_UPDATE_JUMP_TO_MASK 0 //配置升级到loader的方式0为直接reset,1为跳转(适用于芯片电源由IO口KEEP住的方案,需要注意检查跳转前是否将使用DMA的硬件模块全部关闭)
#define CONFIG_IO_KEY_EN 0 //配置是否使用IO按键配合RESET1
#define CONFIG_UPDATE_WITH_MD5_CHECK_EN 0 //配置升级是否支持MD5校验
#define CONFIG_ANC_ENABLE 1 //配置是否支持ANC
//flash size vaule definition
#define FLASH_SIZE_256K 0x40000
#define FLASH_SIZE_512K 0x80000
#define FLASH_SIZE_1M 0x100000
#define FLASH_SIZE_2M 0x200000
#define FLASH_SIZE_4M 0x400000
#define CONFIG_FLASH_SIZE FLASH_SIZE_1M //配置FLASH大小
/* Above Macros Affect Periods Of Both Code Compiling And Post-build */
/* Following Macros Only For Post Bulid Configuaration */
#define CONFIG_DB_UPDATE_DATA_GENERATE_EN 0 //是否生成db_data.bin(用于第三方协议接入使用)
#define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 0 //ufw只生成1份4K对齐的代码
//config for supported chip version
#ifdef CONFIG_BR30_C_VERSION
#define CONFIG_SUPPORTED_CHIP_VERSION C
#else
#define CONFIG_SUPPORTED_CHIP_VERSION B,D,E,M,N,O,P
#endif
//DON'T MODIFY THIS CONFIG EXCEPT SDK PUBLISHER
#define CONFIG_CHIP_NAME AC701N //除了SDK发布者,请不要修改
//it can be modified before first programming,but keep the same as the original version
#define CONFIG_PID AC701N //烧写或强制升级之前可以修改,之后升级要保持一致
//it can be modified before first programming,but keep the same as the original version
#define CONFIG_VID 0.01 //烧写或强制升级之前可以修改,之后升级要保持一致
//Project with bluetooth,it must use OSC as PLL_SOURCE;
#define CONFIG_PLL_SOURCE_USING_LRC 0 //PLL时钟源选择 1:LRC 2:OSC
//config alignment size unit
#ifdef CONFIG_256K_FLASH
#define ALIGN_UNIT_256B 1 //FLASH对齐方式选择如果是256K的FLASH选择256BYTE对齐方式
#else
#define ALIGN_UNIT_256B 0
#endif
//partial platform check this config to select the uart IO for wired update
#define CONFIG_UART_UPDATE_PIN PP00
//isd_download loader/uboot/update_loader debug io config
//#define CONFIG_UBOOT_DEBUG_PIN PA05
//#define CONFIG_UBOOT_DEBUG_BAUD_RATE 1000000
//config long-press reset io pin,time,trigger level
#define CONFIG_RESET_PIN LDO //io pin
#define CONFIG_RESET_TIME 04 //unit:second
#define CONFIG_RESET_LEVEL 1 //tigger level(0/1)
#if CONFIG_IO_KEY_EN
#define CONFIG_SUPPORT_RESET1
#define CONFIG_RESET1_PIN PB01 //io pin
#define CONFIG_RESET1_TIME 08 //unit:second
#define CONFIG_RESET1_LEVEL 0 //tigger level(0/1)
#endif
//reserved three custom cfg item for the future definition
//#define CONFIG_CUSTOM_CFG1_TYPE POWER_PIN
//#define CONFIG_CUSTOM_CFG1_VALUE PC01_1
//#define CONFIG_CUSTOM_CFG2_TYPE
//#define CONFIG_CUSTOM_CFG2_VALUE
//#define CONFIG_CUSTOM_CFG3_TYPE
//#define CONFIG_CUSTOM_CFG3_VALUE
//#define CONFIG_VDDIO_LVD_LEVEL 4 ////VDDIO_LVD挡位0: 1.9V 1: 2.0V 2: 2.1V 3: 2.2V 4: 2.3V 5: 2.4V 6: 2.5V 7: 2.6V
//with single-bank mode,actual vm size should larger this VM_LEAST_SIZE,and dual bank mode,actual vm size equals this;
#define CONFIG_VM_LEAST_SIZE 8K
//config whether erased this area when do a update,1-No Operation,0-Erase
#define CONFIG_VM_OPT 1
//config whether erased this area when do a update,1-No Operation,0-Erase
#define CONFIG_BTIF_OPT 1
//reserved two custom cfg area for the future definition
//#define CONFIG_RESERVED_AREA1 EXIF1
#ifdef CONFIG_RESERVED_AREA1
#define CONFIG_RESERVED_AREA1_ADDR AUTO
#define CONFIG_RESERVED_AREA1_LEN 0x1000
#define CONFIG_RESERVED_AREA1_OPT 1
//#define CONFIG_RESERVED_AREA1_FILE anc_gains.bin
#endif
//#define CONFIG_RESERVED_AREA2 EXIF2
#ifdef CONFIG_RESERVED_AREA2
#define CONFIG_RESERVED_AREA2_ADDR AUTO
#define CONFIG_RESERVED_AREA2_LEN 0x1000
#define CONFIG_RESERVED_AREA2_OPT 1
//#define CONFIG_RESERVED_AREA2_FILE anc_gains.bin
#endif
/* Above Macros Only For Post Bulid Configuaration */
#endif /* #ifdef CONFIG_BOARD_JL701N_ANC */
#endif /* #ifndef CONFIG_BOARD_JL701N_ANC_POST_BUILD_CFG_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +0,0 @@
#ifndef CONFIG_BOARD_JL701N_BTEMITTER_BUILD_CFG_H
#define CONFIG_BOARD_JL701N_BTEMITTER_BUILD_CFG_H
/* 改文件只添加和isd_config.ini相关的配置用以生成isd_config.ini */
/* 其他不相关的配置请勿添加在改文件 */
#ifdef CONFIG_BOARD_JL701N_BTEMITTER
/* Following Macros Affect Periods Of Both Code Compiling And Post-build */
#define CONFIG_DOUBLE_BANK_ENABLE 0 //单双备份选择(若打开了改宏,FLASH结构变为双备份结构适用于接入第三方协议的OTA PS: JL-OTA同样支持双备份升级, 需要根据实际FLASH大小同时配置CONFIG_FLASH_SIZE)
#define CONFIG_APP_OTA_ENABLE 0 //是否支持RCSP升级(JL-OTA)
#define CONFIG_UPDATE_JUMP_TO_MASK 0 //配置升级到loader的方式0为直接reset,1为跳转(适用于芯片电源由IO口KEEP住的方案,需要注意检查跳转前是否将使用DMA的硬件模块全部关闭)
#define CONFIG_IO_KEY_EN 0 //配置是否使用IO按键配合RESET1
#define CONFIG_UPDATE_WITH_MD5_CHECK_EN 0 //配置升级是否支持MD5校验
#define CONFIG_ANC_ENABLE 0 //配置是否支持ANC
//flash size vaule definition
#define FLASH_SIZE_256K 0x40000
#define FLASH_SIZE_512K 0x80000
#define FLASH_SIZE_1M 0x100000
#define FLASH_SIZE_2M 0x200000
#define FLASH_SIZE_4M 0x400000
#define CONFIG_FLASH_SIZE FLASH_SIZE_1M //配置FLASH大小
/* Above Macros Affect Periods Of Both Code Compiling And Post-build */
/* Following Macros Only For Post Bulid Configuaration */
#define CONFIG_DB_UPDATE_DATA_GENERATE_EN 0 //是否生成db_data.bin(用于第三方协议接入使用)
#define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 0 //ufw只生成1份4K对齐的代码
//config for supported chip version
#ifdef CONFIG_BR30_C_VERSION
#define CONFIG_SUPPORTED_CHIP_VERSION C
#else
#define CONFIG_SUPPORTED_CHIP_VERSION B,D,E,M,N,O,P
#endif
//DON'T MODIFY THIS CONFIG EXCEPT SDK PUBLISHER
#define CONFIG_CHIP_NAME AC701N //除了SDK发布者,请不要修改
//it can be modified before first programming,but keep the same as the original version
#define CONFIG_PID AC701N //烧写或强制升级之前可以修改,之后升级要保持一致
//it can be modified before first programming,but keep the same as the original version
#define CONFIG_VID 0.01 //烧写或强制升级之前可以修改,之后升级要保持一致
//Project with bluetooth,it must use OSC as PLL_SOURCE;
#define CONFIG_PLL_SOURCE_USING_LRC 0 //PLL时钟源选择 1:LRC 2:OSC
//config alignment size unit
#ifdef CONFIG_256K_FLASH
#define ALIGN_UNIT_256B 1 //FLASH对齐方式选择如果是256K的FLASH选择256BYTE对齐方式
#else
#define ALIGN_UNIT_256B 0
#endif
//partial platform check this config to select the uart IO for wired update
#define CONFIG_UART_UPDATE_PIN PP00
//isd_download loader/uboot/update_loader debug io config
//#define CONFIG_UBOOT_DEBUG_PIN PA05
//#define CONFIG_UBOOT_DEBUG_BAUD_RATE 1000000
//config long-press reset io pin,time,trigger level
#define CONFIG_RESET_PIN LDO //io pin
#define CONFIG_RESET_TIME 04 //unit:second
#define CONFIG_RESET_LEVEL 1 //tigger level(0/1)
#if CONFIG_IO_KEY_EN
#define CONFIG_SUPPORT_RESET1
#define CONFIG_RESET1_PIN PB01 //io pin
#define CONFIG_RESET1_TIME 08 //unit:second
#define CONFIG_RESET1_LEVEL 0 //tigger level(0/1)
#endif
//reserved three custom cfg item for the future definition
//#define CONFIG_CUSTOM_CFG1_TYPE POWER_PIN
//#define CONFIG_CUSTOM_CFG1_VALUE PC01_1
//#define CONFIG_CUSTOM_CFG2_TYPE
//#define CONFIG_CUSTOM_CFG2_VALUE
//#define CONFIG_CUSTOM_CFG3_TYPE
//#define CONFIG_CUSTOM_CFG3_VALUE
//#define CONFIG_VDDIO_LVD_LEVEL 4 ////VDDIO_LVD挡位0: 1.9V 1: 2.0V 2: 2.1V 3: 2.2V 4: 2.3V 5: 2.4V 6: 2.5V 7: 2.6V
//with single-bank mode,actual vm size should larger this VM_LEAST_SIZE,and dual bank mode,actual vm size equals this;
#define CONFIG_VM_LEAST_SIZE 8K
//config whether erased this area when do a update,1-No Operation,0-Erase
#define CONFIG_VM_OPT 1
//config whether erased this area when do a update,1-No Operation,0-Erase
#define CONFIG_BTIF_OPT 1
//reserved two custom cfg area for the future definition
//#define CONFIG_RESERVED_AREA1 EXIF1
#ifdef CONFIG_RESERVED_AREA1
#define CONFIG_RESERVED_AREA1_ADDR AUTO
#define CONFIG_RESERVED_AREA1_LEN 0x1000
#define CONFIG_RESERVED_AREA1_OPT 1
//#define CONFIG_RESERVED_AREA1_FILE anc_gains.bin
#endif
//#define CONFIG_RESERVED_AREA2 EXIF2
#ifdef CONFIG_RESERVED_AREA2
#define CONFIG_RESERVED_AREA2_ADDR AUTO
#define CONFIG_RESERVED_AREA2_LEN 0x1000
#define CONFIG_RESERVED_AREA2_OPT 1
//#define CONFIG_RESERVED_AREA2_FILE anc_gains.bin
#endif
/* Above Macros Only For Post Bulid Configuaration */
#endif /* #ifdef CONFIG_BOARD_JL701N_BTEMITTER */
#endif /* #ifndef CONFIG_BOARD_JL701N_BTEMITTER_BUILD_CFG_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +0,0 @@
#ifndef CONFIG_BOARD_JL701N_DEMO_POST_BUILD_CFG_H
#define CONFIG_BOARD_JL701N_DEMO_POST_BUILD_CFG_H
/* 改文件只添加和isd_config.ini相关的配置用以生成isd_config.ini */
/* 其他不相关的配置请勿添加在改文件 */
#ifdef CONFIG_BOARD_JL701N_DEMO
/* Following Macros Affect Periods Of Both Code Compiling And Post-build */
#define CONFIG_DOUBLE_BANK_ENABLE 0 //单双备份选择(若打开了改宏,FLASH结构变为双备份结构适用于接入第三方协议的OTA PS: JL-OTA同样支持双备份升级, 需要根据实际FLASH大小同时配置CONFIG_FLASH_SIZE)
#define CONFIG_APP_OTA_ENABLE 0 //是否支持RCSP升级(JL-OTA)
#define CONFIG_UPDATE_JUMP_TO_MASK 0 //配置升级到loader的方式0为直接reset,1为跳转(适用于芯片电源由IO口KEEP住的方案,需要注意检查跳转前是否将使用DMA的硬件模块全部关闭)
#define CONFIG_IO_KEY_EN 0 //配置是否使用IO按键配合RESET1
#define CONFIG_UPDATE_WITH_MD5_CHECK_EN 0 //配置升级是否支持MD5校验
#define CONFIG_ANC_ENABLE 0 //配置是否支持ANC
//flash size vaule definition
#define FLASH_SIZE_256K 0x40000
#define FLASH_SIZE_512K 0x80000
#define FLASH_SIZE_1M 0x100000
#define FLASH_SIZE_2M 0x200000
#define FLASH_SIZE_4M 0x400000
#define CONFIG_FLASH_SIZE FLASH_SIZE_1M //配置FLASH大小
/* Above Macros Affect Periods Of Both Code Compiling And Post-build */
/* Following Macros Only For Post Bulid Configuaration */
#define CONFIG_DB_UPDATE_DATA_GENERATE_EN 0 //是否生成db_data.bin(用于第三方协议接入使用)
#define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 0 //ufw只生成1份4K对齐的代码
//config for supported chip version
#ifdef CONFIG_BR30_C_VERSION
#define CONFIG_SUPPORTED_CHIP_VERSION C
#else
#define CONFIG_SUPPORTED_CHIP_VERSION B,D,E,M,N,O,P
#endif
//DON'T MODIFY THIS CONFIG EXCEPT SDK PUBLISHER
#define CONFIG_CHIP_NAME AC701N //除了SDK发布者,请不要修改
//it can be modified before first programming,but keep the same as the original version
#define CONFIG_PID AC701N //烧写或强制升级之前可以修改,之后升级要保持一致
//it can be modified before first programming,but keep the same as the original version
#define CONFIG_VID 0.01 //烧写或强制升级之前可以修改,之后升级要保持一致
//Project with bluetooth,it must use OSC as PLL_SOURCE;
#define CONFIG_PLL_SOURCE_USING_LRC 0 //PLL时钟源选择 1:LRC 2:OSC
//config alignment size unit
#ifdef CONFIG_256K_FLASH
#define ALIGN_UNIT_256B 1 //FLASH对齐方式选择如果是256K的FLASH选择256BYTE对齐方式
#else
#define ALIGN_UNIT_256B 0
#endif
//partial platform check this config to select the uart IO for wired update
#define CONFIG_UART_UPDATE_PIN PP00
//isd_download loader/uboot/update_loader debug io config
//#define CONFIG_UBOOT_DEBUG_PIN PA05
//#define CONFIG_UBOOT_DEBUG_BAUD_RATE 1000000
//config long-press reset io pin,time,trigger level
#define CONFIG_RESET_PIN LDO //io pin
#define CONFIG_RESET_TIME 04 //unit:second
#define CONFIG_RESET_LEVEL 1 //tigger level(0/1)
#if CONFIG_IO_KEY_EN
#define CONFIG_SUPPORT_RESET1
#define CONFIG_RESET1_PIN PB01 //io pin
#define CONFIG_RESET1_TIME 08 //unit:second
#define CONFIG_RESET1_LEVEL 0 //tigger level(0/1)
#endif
//reserved three custom cfg item for the future definition
//#define CONFIG_CUSTOM_CFG1_TYPE POWER_PIN
//#define CONFIG_CUSTOM_CFG1_VALUE PC01_1
//#define CONFIG_CUSTOM_CFG2_TYPE
//#define CONFIG_CUSTOM_CFG2_VALUE
//#define CONFIG_CUSTOM_CFG3_TYPE
//#define CONFIG_CUSTOM_CFG3_VALUE
//#define CONFIG_VDDIO_LVD_LEVEL 4 ////VDDIO_LVD挡位0: 1.9V 1: 2.0V 2: 2.1V 3: 2.2V 4: 2.3V 5: 2.4V 6: 2.5V 7: 2.6V
//with single-bank mode,actual vm size should larger this VM_LEAST_SIZE,and dual bank mode,actual vm size equals this;
#define CONFIG_VM_LEAST_SIZE 8K
//config whether erased this area when do a update,1-No Operation,0-Erase
#define CONFIG_VM_OPT 1
//config whether erased this area when do a update,1-No Operation,0-Erase
#define CONFIG_BTIF_OPT 1
//reserved two custom cfg area for the future definition
//#define CONFIG_RESERVED_AREA1 EXIF1
#ifdef CONFIG_RESERVED_AREA1
#define CONFIG_RESERVED_AREA1_ADDR AUTO
#define CONFIG_RESERVED_AREA1_LEN 0x1000
#define CONFIG_RESERVED_AREA1_OPT 1
//#define CONFIG_RESERVED_AREA1_FILE anc_gains.bin
#endif
//#define CONFIG_RESERVED_AREA2 EXIF2
#ifdef CONFIG_RESERVED_AREA2
#define CONFIG_RESERVED_AREA2_ADDR AUTO
#define CONFIG_RESERVED_AREA2_LEN 0x1000
#define CONFIG_RESERVED_AREA2_OPT 1
//#define CONFIG_RESERVED_AREA2_FILE anc_gains.bin
#endif
/* Above Macros Only For Post Bulid Configuaration */
#endif /* #ifdef CONFIG_BOARD_JL701N_DEMO */
#endif /* #ifndef CONFIG_BOARD_JL701N_DEMO_POST_BUILD_CFG_H */

View File

@ -1,418 +0,0 @@
#include "system/includes.h"
#include "media/includes.h"
#include "tone_player.h"
#include "earphone.h"
#include "app_config.h"
#include "app_action.h"
#include "app_task.h"
#include "btstack/avctp_user.h"
#include "btstack/btstack_task.h"
#include "btctrler/btctrler_task.h"
#include "btstack/frame_queque.h"
#include "user_cfg.h"
// #include "aec_user.h"
#include "classic/hci_lmp.h"
#include "bt_common.h"
#include "bt_ble.h"
#include "bt_tws.h"
#include "pbg_user.h"
#include "btstack/bluetooth.h"
#include "colorful_lights/colorful_lights.h"
#include "app_chargestore.h"
#include "jl_kws/jl_kws_api.h"
#include "asm/charge.h"
#include "app_charge.h"
#include "ui_manage.h"
#include "app_chargestore.h"
#include "app_umidigi_chargestore.h"
#include "app_testbox.h"
#include "app_online_cfg.h"
#include "app_main.h"
#include "app_power_manage.h"
#include "gSensor/gSensor_manage.h"
#include "key_event_deal.h"
#include "classic/tws_api.h"
#include "asm/pwm_led.h"
#include "ir_sensor/ir_manage.h"
#include "in_ear_detect/in_ear_manage.h"
#include "vol_sync.h"
#include "bt_background.h"
#include "default_event_handler.h"
#if(USE_DMA_UART_TEST) //使用dm串口测试时不能同时打开
#define MY_SNIFF_EN 0
#else
#define MY_SNIFF_EN 1 //默认打开
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////
//变量
u8 init_ok = 0;
static u8 sniff_out = 0;
unsigned char xtell_bl_state=0; //存放经典蓝牙的连接状态0断开1是连接
u8 bt_newname =0;
unsigned char xt_ble_new_name[9] = "CM-11111";
static u16 play_poweron_ok_timer_id = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////
u8 get_bt_init_status(void)
{
return init_ok;
}
u8 get_sniff_out_status()
{
return sniff_out;
}
void clear_sniff_out_status()
{
sniff_out = 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/*
* 模式状态机, 通过start_app()控制状态切换
*/
/* extern int audio_mic_init(); */
static int state_machine(struct application *app, enum app_state state, struct intent *it){
int error = 0;
static u8 tone_player_err = 0;
r_printf("bt_state_machine=%d\n", state);
switch (state) {
case APP_STA_CREATE:
/* set_adjust_conn_dac_check(0); */
STATUS *p_tone = get_tone_config();
tone_play_index(p_tone->bt_init_ok, 1);
break;
case APP_STA_START:
if (!it) {
break;
}
switch (it->action) {
case ACTION_EARPHONE_MAIN:
/*
* earphone 模式初始化
*/
clk_set("sys", BT_NORMAL_HZ);
u32 sys_clk = clk_get("sys");
bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0);
/* bredr_set_dut_enble(1, 1); */
bt_function_select_init();
bredr_handle_register();
EARPHONE_STATE_INIT();
btstack_init();
sys_auto_shut_down_enable();
bt_sniff_feature_init();
sys_auto_sniff_controle(MY_SNIFF_EN, NULL);
app_var.dev_volume = -1;
break;
case ACTION_A2DP_START: //蓝牙音频传输协议
break;
case ACTION_BY_KEY_MODE:
break;
case ACTION_TONE_PLAY:
STATUS *p_tone = get_tone_config();
tone_play_index(p_tone->bt_init_ok, 1);
break;
case ACTION_DO_NOTHING:
break;
}
break;
case APP_STA_PAUSE:
break;
case APP_STA_RESUME:
//恢复前台运行
sys_auto_shut_down_disable();
sys_key_event_enable();
break;
case APP_STA_STOP:
break;
case APP_STA_DESTROY:
r_printf("APP_STA_DESTROY\n");
if (!app_var.goto_poweroff_flag) {
bt_app_exit(NULL);
}
break;
}
return error;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//handle
static void play_poweron_ok_timer(void *priv)
{
app_var.wait_timer_do = 0;
log_d("\n-------play_poweron_ok_timer-------\n", priv);
if (is_dac_power_off()) {
#if TCFG_USER_TWS_ENABLE
bt_tws_poweron();
#else
bt_wait_connect_and_phone_connect_switch(0);
#endif
return;
}
app_var.wait_timer_do = sys_timeout_add(priv, play_poweron_ok_timer, 100);
}
static void play_bt_connect_dly(void *priv)
{
app_var.wait_timer_do = 0;
log_d("\n-------play_bt_connect_dly-------\n", priv);
if (!app_var.goto_poweroff_flag) {
STATUS *p_tone = get_tone_config();
tone_play_index(p_tone->bt_connect_ok, 1);
}
}
static int bt_connction_status_event_handler(struct bt_event *bt)
{
STATUS *p_tone = get_tone_config();
u8 *phone_number = NULL;
switch (bt->event) {
case BT_STATUS_INIT_OK:
/*
* 蓝牙初始化完成
*/
log_info("BT_STATUS_INIT_OK\n");
init_ok = 1;
__set_sbc_cap_bitpool(38);
#if (TCFG_USER_BLE_ENABLE)
if (BT_MODE_IS(BT_BQB)) {
ble_bqb_test_thread_init();
} else {
#if !TCFG_WIRELESS_MIC_ENABLE
bt_ble_init();
#endif
}
#endif
bt_init_ok_search_index();
#if TCFG_TEST_BOX_ENABLE
testbox_set_bt_init_ok(1);
#endif
#if ((CONFIG_BT_MODE == BT_BQB)||(CONFIG_BT_MODE == BT_PER))
bt_wait_phone_connect_control(1);
#else
if (is_dac_power_off()) {
bt_wait_connect_and_phone_connect_switch(0);
} else {
app_var.wait_timer_do = sys_timeout_add(NULL, play_poweron_ok_timer, 100);
}
#endif
/*if (app_var.play_poweron_tone) {
tone_play_index(p_tone->power_on, 1);
}*/
break;
case BT_STATUS_SECOND_CONNECTED:
clear_current_poweron_memory_search_index(0);
case BT_STATUS_FIRST_CONNECTED:
log_info("BT_STATUS_CONNECTED\n");
xtell_bl_state = 1; //蓝牙连接成功 置1
if(strcmp(xt_ble_new_name,"CM-1111") != 0){
//蓝牙连接成功
bt_newname =1;
u8 temp[5]={0xBB,0xBE,0x02,0x04,0x00};
temp[4] = xtell_bl_state; //经典蓝牙连接状态
send_data_to_ble_client(&temp,5);
}
earphone_change_pwr_mode(PWR_DCDC15, 3000);
sys_auto_shut_down_disable();
ui_update_status(STATUS_BT_CONN); //单台在此处设置连接状态,对耳的连接状态需要同步在bt_tws.c中去设置
/* tone_play(TONE_CONN); */
/*os_time_dly(40); // for test*/
log_info("tone status:%d\n", tone_get_status());
if (get_call_status() == BT_CALL_HANGUP) {
if (app_var.phone_dly_discon_time) {
sys_timeout_del(app_var.phone_dly_discon_time);
app_var.phone_dly_discon_time = 0;
} else {
app_var.wait_timer_do = sys_timeout_add(NULL, play_bt_connect_dly, 1600);
/* tone_play_index(p_tone->bt_connect_ok, 1); */
}
}
/*int timeout = 5000 + rand32() % 10000;
sys_timeout_add(NULL, connect_phone_test, timeout);*/
break;
case BT_STATUS_FIRST_DISCONNECT:
case BT_STATUS_SECOND_DISCONNECT:
log_info("BT_STATUS_DISCONNECT\n");
xtell_bl_state = 0; //断开蓝牙 清0
//蓝牙断开连接
if(bt_newname){ //已经改成新蓝牙名字,断开才播报
bt_newname=0;
u8 temp[5]={0xBB,0xBE,0x02,0x04,0x00};
temp[4] = xtell_bl_state; //经典蓝牙连接状态
send_data_to_ble_client(&temp,5);
}
if (app_var.goto_poweroff_flag) {
/*关机不播断开提示音*/
/*关机时不改UI*/
break;
}
bt_discon_dly_handle(NULL);
break;
//phone status deal
case BT_STATUS_PHONE_INCOME:
break;
case BT_STATUS_PHONE_OUT:
break;
case BT_STATUS_PHONE_ACTIVE:
break;
case BT_STATUS_PHONE_HANGUP:
break;
case BT_STATUS_PHONE_NUMBER:
break;
case BT_STATUS_INBAND_RINGTONE: //铃声
break;
case BT_STATUS_CALL_VOL_CHANGE:
break;
case BT_STATUS_SNIFF_STATE_UPDATE:
log_info(" BT_STATUS_SNIFF_STATE_UPDATE %d\n", bt->value); //0退出SNIFF
if (bt->value == 0) {
sniff_out = 1;
sys_auto_sniff_controle(MY_SNIFF_EN, bt->args);
} else {
sys_auto_sniff_controle(0, bt->args);
}
break;
case BT_STATUS_LAST_CALL_TYPE_CHANGE:
break;
case BT_STATUS_CONN_A2DP_CH:
case BT_STATUS_CONN_HFP_CH:
if ((!is_1t2_connection()) && (get_current_poweron_memory_search_index(NULL))) { //回连下一个device
if (get_esco_coder_busy_flag()) {
clear_current_poweron_memory_search_index(0);
} else {
user_send_cmd_prepare(USER_CTRL_START_CONNECTION, 0, NULL);
}
}
break;
case BT_STATUS_PHONE_MANUFACTURER:
break;
case BT_STATUS_VOICE_RECOGNITION:
break;
case BT_STATUS_AVRCP_INCOME_OPID:
#define AVC_VOLUME_UP 0x41
#define AVC_VOLUME_DOWN 0x42
log_info("BT_STATUS_AVRCP_INCOME_OPID:%d\n", bt->value);
if (bt->value == AVC_VOLUME_UP) {
}
if (bt->value == AVC_VOLUME_DOWN) {
}
break;
default:
log_info(" BT STATUS DEFAULT\n");
break;
}
return 0;
}
static int event_handler(struct application *app, struct sys_event *event)
{
if (SYS_EVENT_REMAP(event)) {
g_printf("****SYS_EVENT_REMAP**** \n");
return 0;
}
switch (event->type) {
case SYS_KEY_EVENT:
break;
case SYS_BT_EVENT:
/*
* 蓝牙事件处理
*/
if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) {
printf("in event_handler:bt_connction_status_event_handler");
bt_connction_status_event_handler(&event->u.bt);
} else if ((u32)event->arg == SYS_BT_EVENT_TYPE_HCI_STATUS) {
bt_hci_event_handler(&event->u.bt);
}
break;
case SYS_DEVICE_EVENT:
/*
* 系统设备事件处理
*/
if ((u32)event->arg == DEVICE_EVENT_FROM_CHARGE) {
} else if ((u32)event->arg == DEVICE_EVENT_FROM_POWER) {
return app_power_event_handler(&event->u.dev);
}
#if TCFG_UMIDIGI_BOX_ENABLE
else if ((u32)event->arg == DEVICE_EVENT_UMIDIGI_CHARGE_STORE) {
app_umidigi_chargestore_event_handler(&event->u.umidigi_chargestore);
}
#endif
#if TCFG_TEST_BOX_ENABLE
else if ((u32)event->arg == DEVICE_EVENT_TEST_BOX) {
app_testbox_event_handler(&event->u.testbox);
}
#endif
break;
default:
return false;
}
SYS_EVENT_HANDLER_SPECIFIC(event);
#ifdef CONFIG_BT_BACKGROUND_ENABLE
if (app) {
default_event_handler(event);
}
#endif
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
static const struct application_operation app_handler_ops = {
.state_machine = state_machine,
.event_handler = event_handler,
};
/*
* 注册earphone模式
*/
REGISTER_APPLICATION(app_handler) = {
.name = "handler",
.action = ACTION_EARPHONE_MAIN,
.ops = &app_handler_ops,
.state = APP_STA_DESTROY,
};

View File

@ -1,31 +0,0 @@
#ifndef APP_ACTION_H
#define APP_ACTION_H
#define ACTION_EARPHONE_MAIN 0x0001
#define ACTION_A2DP_START 0x0002
#define ACTION_ESCO_START 0x0003
#define ACTION_BY_KEY_MODE 0x0004
#define ACTION_IDLE_MAIN 0x0010
#define ACTION_IDLE_POWER_OFF 0x0011
#define ACTION_MUSIC_MAIN 0x0020
#define ACTION_MUSIC_TWS_RX 0x0021
#define ACTION_PC_MAIN 0x0030
#define ACTION_AUX_MAIN 0x0040
#define APP_NAME_BT "earphone"
#define APP_NAME_IDLE "idle"
#define APP_NAME_PC "pc"
#define APP_NAME_MUSIC "music"
#define APP_NAME_AUX "aux"
extern void task_switch(const char *name, int action);
#define task_switch_to_bt() task_switch(APP_NAME_BT, ACTION_EARPHONE_MAIN)
#endif

View File

@ -1,12 +0,0 @@
#ifndef _APP_ANCBOX_H_
#define _APP_ANCBOX_H_
#include "typedef.h"
#include "system/event.h"
extern int app_ancbox_event_handler(struct ancbox_event *anc_dev);
extern u8 ancbox_get_status(void);
extern void ancbox_clear_status(void);
#endif //_APP_CHARGESTORE_H_

View File

@ -1,13 +0,0 @@
#ifndef _APP_ANCTOOL_H_
#define _APP_ANCTOOL_H_
#include "typedef.h"
#include "anctool.h"
u8 app_anctool_spp_rx_data(u8 *packet, u16 size);
void app_anctool_spp_connect(void);
void app_anctool_spp_disconnect(void);
u8 get_app_anctool_spp_connected_flag();
#endif //_APP_CHARGESTORE_H_

View File

@ -1,17 +0,0 @@
#ifndef _APP_CHARGE_H_
#define _APP_CHARGE_H_
#include "typedef.h"
#include "system/event.h"
extern void charge_close_deal(void);
extern void charge_start_deal(void);
extern void ldo5v_keep_deal(void);
extern void charge_full_deal(void);
extern void charge_ldo5v_in_deal(void);
extern void charge_ldo5v_off_deal(void);
extern u8 get_charge_full_flag(void);
extern int app_charge_event_handler(struct device_event *dev);
#endif //_APP_CHARGE_H_

View File

@ -1,78 +0,0 @@
#ifndef _APP_CHARGESTORE_H_
#define _APP_CHARGESTORE_H_
#include "typedef.h"
#include "system/event.h"
//LDOIN升级口命令定义
#define CMD_TWS_CHANNEL_SET 0x01
#define CMD_TWS_REMOTE_ADDR 0x02
#define CMD_TWS_ADDR_DELETE 0x03
#define CMD_BOX_TWS_CHANNEL_SEL 0x04//测试盒获取地址
#define CMD_BOX_TWS_REMOTE_ADDR 0x05//测试盒交换地址
#define CMD_POWER_LEVEL_OPEN 0x06//开盖充电舱报告/获取电量
#define CMD_POWER_LEVEL_CLOSE 0x07//合盖充电舱报告/获取电量
#define CMD_RESTORE_SYS 0x08//恢复出厂设置
#define CMD_ENTER_DUT 0x09//进入测试模式
#define CMD_EX_FIRST_READ_INFO 0x0A//F95读取数据首包信息
#define CMD_EX_CONTINUE_READ_INFO 0x0B//F95读取数据后续包信息
#define CMD_EX_FIRST_WRITE_INFO 0x0C//F95写入数据首包信息
#define CMD_EX_CONTINUE_WRITE_INFO 0x0D//F95写入数据后续包信息
#define CMD_EX_INFO_COMPLETE 0x0E//F95完成信息交换
#define CMD_TWS_SET_CHANNEL 0x0F//F95设置左右声道信息
#define CMD_BOX_UPDATE 0x20//测试盒升级
#define CMD_BOX_MODULE 0x21//测试盒一级命令
#define CMD_SHUT_DOWN 0x80//充电舱关机,充满电关机,或者是低电关机
#define CMD_CLOSE_CID 0x81//充电舱盒盖
#define CMD_ANC_MODULE 0x90//ANC一级命令
#define CMD_FAIL 0xfe//失败
#define CMD_UNDEFINE 0xff//未知命令回复
enum {
TWS_CHANNEL_LEFT = 1, //左耳
TWS_CHANNEL_RIGHT, //右耳
};
enum {
TWS_DEL_TWS_ADDR = 1, //删除对箱地址
TWS_DEL_PHONE_ADDR,//删除手机地址
TWS_DEL_ALL_ADDR,//删除手机与对箱地址
};
struct _CHARGE_STORE_INFO {
u8 tws_local_addr[6];
u8 tws_remote_addr[6];
u8 tws_mac_addr[6];
u32 search_aa;
u32 pair_aa;
u8 local_channel;
u16 device_ind;
u16 reserved_data;
} _GNU_PACKED_;
typedef struct _CHARGE_STORE_INFO CHARGE_STORE_INFO;
extern void chargestore_set_tws_channel_info(u8 channel);
extern bool chargestore_set_tws_remote_info(u8 *data, u8 len);
extern u16 chargestore_get_tws_remote_info(u8 *data);
extern u8 chargestore_get_power_level(void);
extern u8 chargestore_get_power_status(void);
extern u8 chargestore_get_cover_status(void);
extern u8 chargestore_get_sibling_power_level(void);
extern void chargestore_set_bt_init_ok(u8 flag);
extern int app_chargestore_event_handler(struct chargestore_event *chargestore_dev);
extern u8 chargestore_get_earphone_online(void);
extern u8 chargestore_get_earphone_pos(void);
extern int chargestore_sync_chg_level(void);
extern void chargestore_set_power_level(u8 power);
extern void chargestore_set_sibling_chg_lev(u8 chg_lev);
extern void chargestore_set_phone_disconnect(void);
extern void chargestore_set_phone_connect(void);
extern u8 chargestore_check_going_to_poweroff(void);
extern void chargestore_shutdown_reset(void);
extern void testbox_set_testbox_tws_paired(u8 flag);
extern u8 testbox_get_testbox_tws_paired(void);
extern u8 testbox_get_touch_trim_en(u8 *sec);
extern u8 testbox_get_softpwroff_after_paired(void);
#endif //_APP_CHARGESTORE_H_

View File

@ -1,555 +0,0 @@
#ifndef APP_CONFIG_H
#define APP_CONFIG_H
/*
* 系统打印总开关
*/
#define LIB_DEBUG 1 //1 //xtelllog 1是打开库打印
#define CONFIG_DEBUG_LIB(x) (x & LIB_DEBUG)
#define CONFIG_DEBUG_ENABLE //xtelllog 注释就关闭log
#ifndef CONFIG_DEBUG_ENABLE
//#define CONFIG_DEBUG_LITE_ENABLE //轻量级打印开关, 默认关闭
#endif
//*********************************************************************************//
// AI配置 //
//*********************************************************************************//
#define CONFIG_APP_BT_ENABLE
#ifdef CONFIG_APP_BT_ENABLE
#define TRANS_DATA_EN 0
#define RCSP_BTMATE_EN 0
#define RCSP_ADV_EN 1
#define AI_APP_PROTOCOL 0
#define LL_SYNC_EN 0
#define TUYA_DEMO_EN 0
#else
#define TRANS_DATA_EN 1
#define RCSP_BTMATE_EN 0
#define RCSP_ADV_EN 0
#define AI_APP_PROTOCOL 0
#define LL_SYNC_EN 0
#define TUYA_DEMO_EN 0
#endif
#include "board_config.h"
#ifdef TCFG_AUDIO_CVP_NS_MODE
#if (TCFG_AUDIO_CVP_NS_MODE==CVP_DNS_MODE) || (TCFG_KWS_VOICE_RECOGNITION_ENABLE == 1)||(TCFG_AUDIO_ANC_ENABLE==1&&TCFG_AUDIO_DUAL_MIC_ENABLE==1)
#undef CONFIG_MOVABLE_ENABLE
#define CONFIG_MOVABLE_ENABLE //省ram空间将部分ram空间的代码挪到flash
#endif
#endif
#if defined(TCFG_CVP_DEVELOP_ENABLE) && (TCFG_CVP_DEVELOP_ENABLE == 1)
#undef CONFIG_MOVABLE_ENABLE
#define CONFIG_MOVABLE_ENABLE //省ram空间将部分ram空间的代码挪到flash
#endif
#if CONFIG_UPDATE_WITH_MD5_CHECK_EN
#define UPDATE_MD5_ENABLE 1
#else
#define UPDATE_MD5_ENABLE 0
#endif
//升级需要打开CONFIG_APP_OTA_ENABLE,同时单双备份的配置也在board_xxx_global_cfg里配置需要注意只有JL_RCSP才支持单备份其余升级都是只支持双备份升级
//支持TWS同步升级OTA_TWS_SAME_TIME_NEW宏需要配置为1旧的流程已不再支持
#if (RCSP_ADV_EN) //rcsp需要打开ble
#define JL_EARPHONE_APP_EN 1
// #define CONFIG_CHARGESTORE_REMAP_ENABLE //充电仓重映射接收函数使能
#if CONFIG_APP_OTA_ENABLE
#define RCSP_UPDATE_EN 1 //是否支持rcsp升级
#if CONFIG_DOUBLE_BANK_ENABLE //双备份才能打开同步升级流程
#define OTA_TWS_SAME_TIME_ENABLE 1 //是否支持TWS同步升级
#define OTA_TWS_SAME_TIME_NEW 1 //使用新的tws ota流程
#else
#define OTA_TWS_SAME_TIME_ENABLE 1//0 xtellota //是否支持TWS同步升级
#define OTA_TWS_SAME_TIME_NEW 1//0 //使用新的tws ota流程
#endif //CONFIG_DOUBLE_BANK_ENABLE
#else
#define RCSP_UPDATE_EN 0 //是否支持rcsp升级
#define OTA_TWS_SAME_TIME_ENABLE 0 //是否支持TWS同步升级
#define OTA_TWS_SAME_TIME_NEW 0 //使用新的tws ota流程
#endif
#undef TCFG_USER_BLE_ENABLE
#define TCFG_USER_BLE_ENABLE 1 //BLE功能使能
#elif (AI_APP_PROTOCOL)
#define BT_MIC_EN 0
#define OTA_TWS_SAME_TIME_ENABLE 0 //是否支持TWS同步升级
#elif (LL_SYNC_EN)
#define JL_EARPHONE_APP_EN 0
#define OTA_TWS_SAME_TIME_ENABLE 1
#define OTA_TWS_SAME_TIME_NEW 1 //使用新的tws ota流程
#elif (TUYA_DEMO_EN)
#define JL_EARPHONE_APP_EN 0
#define OTA_TWS_SAME_TIME_ENABLE 0
#define OTA_TWS_SAME_TIME_NEW 0 //使用新的tws ota流程
#else
#define JL_EARPHONE_APP_EN 0
#define OTA_TWS_SAME_TIME_ENABLE 0
#define OTA_TWS_SAME_TIME_NEW 0 //使用新的tws ota流程
#endif
#define CONFIG_MEDIA_LIB_USE_MALLOC 1
#include "usb_std_class_def.h"
#undef USB_MALLOC_ENABLE
#define USB_MALLOC_ENABLE 1
///USB 配置重定义
// #undef USB_DEVICE_CLASS_CONFIG
// #define USB_DEVICE_CLASS_CONFIG (AUDIO_CLASS)
/////要确保 上面 undef 后在include usb
#include "usb_common_def.h"
#define USB_PC_NO_APP_MODE 0
#if ((TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE || TCFG_ANC_BOX_ENABLE) \
&& TCFG_CHARGESTORE_PORT == IO_PORT_DP)
#undef TCFG_OTG_MODE
#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DM_ONLY)
#endif
#include "btcontroller_mode.h"
#include "user_cfg_id.h"
#ifndef __LD__
#include "bt_profile_cfg.h"
#endif
// #ifdef CONFIG_APP_BT_ENABLE
// #if(APP_ONLINE_DEBUG)
// #error "they can not enable at the same time,just select one!!!"
// #endif
// #endif
#ifdef CONFIG_SDFILE_ENABLE
#define SDFILE_DEV "sdfile"
#define SDFILE_MOUNT_PATH "mnt/sdfile"
#if (USE_SDFILE_NEW)
#define SDFILE_APP_ROOT_PATH SDFILE_MOUNT_PATH"/app/" //app分区
#define SDFILE_RES_ROOT_PATH SDFILE_MOUNT_PATH"/res/" //资源文件分区
#else
#define SDFILE_RES_ROOT_PATH SDFILE_MOUNT_PATH"/C/"
#endif
#endif
#define STYLE_JL_WTACH (1)//彩屏demo
#define STYLE_JL_SOUNDBOX (2)//点阵屏demo
#define STYLE_JL_CHARGE (3)//点阵屏充电仓
#define STYLE_JL_LED7 (4)//led7
#define STYLE_UI_SIMPLE (5)//没有ui框架
//*********************************************************************************//
// 测试模式配置 //
//*********************************************************************************//
#if (CONFIG_BT_MODE != BT_NORMAL)
#undef TCFG_BD_NUM
#define TCFG_BD_NUM 1
#undef TCFG_USER_TWS_ENABLE
#define TCFG_USER_TWS_ENABLE 0 //tws功能使能
#undef TCFG_USER_BLE_ENABLE
#define TCFG_USER_BLE_ENABLE 1 //BLE功能使能
#undef TCFG_AUTO_SHUT_DOWN_TIME
#define TCFG_AUTO_SHUT_DOWN_TIME 0
#undef TCFG_SYS_LVD_EN
#define TCFG_SYS_LVD_EN 0
#undef TCFG_LOWPOWER_LOWPOWER_SEL
#define TCFG_LOWPOWER_LOWPOWER_SEL 0
#undef TCFG_AUDIO_DAC_LDO_VOLT
#define TCFG_AUDIO_DAC_LDO_VOLT DUT_AUDIO_DAC_LDO_VOLT
#undef TCFG_LOWPOWER_POWER_SEL
#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15
#undef TCFG_PWMLED_ENABLE
#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE
#undef TCFG_ADKEY_ENABLE
#define TCFG_ADKEY_ENABLE DISABLE_THIS_MOUDLE
#undef TCFG_IOKEY_ENABLE
#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE
#undef TCFG_TEST_BOX_ENABLE
#define TCFG_TEST_BOX_ENABLE 0
#undef TCFG_AUTO_SHUT_DOWN_TIME
#define TCFG_AUTO_SHUT_DOWN_TIME 0
#undef TCFG_POWER_ON_NEED_KEY
#define TCFG_POWER_ON_NEED_KEY 0
/* #undef TCFG_UART0_ENABLE
#define TCFG_UART0_ENABLE DISABLE_THIS_MOUDLE */
dzfghsdfhgsfgh
#endif //(CONFIG_BT_MODE != BT_NORMAL)
#if TCFG_USER_TWS_ENABLE
#define CONFIG_TWS_COMMON_ADDR_AUTO 0 /* 自动生成TWS配对后的MAC地址 */
#define CONFIG_TWS_COMMON_ADDR_USED_LEFT 1 /* 使用左耳的MAC地址作为TWS配对后的地址
可配合烧写器MAC地址自增功能一起使用
多台交叉配对会出现MAC地址相同情况 */
#define CONFIG_TWS_COMMON_ADDR_SELECT CONFIG_TWS_COMMON_ADDR_AUTO
//*********************************************************************************//
// 对耳配置方式配置 //
//*********************************************************************************//
#define CONFIG_TWS_CONNECT_SIBLING_TIMEOUT 4 /* 开机或超时断开后对耳互连超时时间单位s */
// #define CONFIG_TWS_REMOVE_PAIR_ENABLE [> 不连手机的情况下双击按键删除配对信息 <]
#define CONFIG_TWS_POWEROFF_SAME_TIME 1 /*按键关机时两个耳机同时关机*/
#define ONE_KEY_CTL_DIFF_FUNC 1 /*通过左右耳实现一个按键控制两个功能*/
#define CONFIG_TWS_SCO_ONLY_MASTER 0 /*通话的时候只有主机出声音*/
/* 配对方式选择 */
#define CONFIG_TWS_PAIR_BY_CLICK 0 /* 按键发起配对 */
#define CONFIG_TWS_PAIR_BY_AUTO 1 /* 开机自动配对 */
#define CONFIG_TWS_PAIR_BY_FAST_CONN 2 /* 开机快速连接,连接速度比自动配对快,不支持取消配对操作 */
#define CONFIG_TWS_PAIR_MODE CONFIG_TWS_PAIR_BY_AUTO
/* 声道确定方式选择 */
#define CONFIG_TWS_MASTER_AS_LEFT 0 //主机作为左耳
#define CONFIG_TWS_AS_LEFT_CHANNEL 1 //固定左耳
#define CONFIG_TWS_AS_RIGHT_CHANNEL 2 //固定右耳
#define CONFIG_TWS_LEFT_START_PAIR 3 //双击发起配对的耳机做左耳
#define CONFIG_TWS_RIGHT_START_PAIR 4 //双击发起配对的耳机做右耳
#define CONFIG_TWS_EXTERN_UP_AS_LEFT 5 //外部有上拉电阻作为左耳
#define CONFIG_TWS_EXTERN_DOWN_AS_LEFT 6 //外部有下拉电阻作为左耳
#define CONFIG_TWS_SECECT_BY_CHARGESTORE 7 //充电仓决定左右耳
#define CONFIG_TWS_CHANNEL_SELECT CONFIG_TWS_LEFT_START_PAIR //配对方式选择
#define CONFIG_TWS_CHANNEL_CHECK_IO IO_PORTA_07 //上下拉电阻检测引脚
#if CONFIG_TWS_PAIR_MODE != CONFIG_TWS_PAIR_BY_CLICK
#if (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_LEFT_START_PAIR) ||\
(CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_RIGHT_START_PAIR)
#undef CONFIG_TWS_CHANNEL_SELECT
#define CONFIG_TWS_CHANNEL_SELECT CONFIG_TWS_MASTER_AS_LEFT
#endif
#if CONFIG_TWS_PAIR_MODE == CONFIG_TWS_PAIR_BY_AUTO
#define CONFIG_TWS_AUTO_PAIR_WITHOUT_UNPAIR /* 不取消配对也可以配对新的耳机 */
#endif
#if CONFIG_TWS_PAIR_MODE == CONFIG_TWS_PAIR_BY_FAST_CONN
#undef CONFIG_TWS_REMOVE_PAIR_ENABLE
#endif
#endif
#define CONFIG_A2DP_GAME_MODE_ENABLE 0 //游戏模式
#define CONFIG_A2DP_GAME_MODE_DELAY_TIME 35 //游戏模式延时ms
//*********************************************************************************//
// 低延时游戏模式脚步声、枪声增强,需使能蓝牙音乐10段eq以及蓝牙音乐drc
// 用户开关宏AUDIO_GAME_EFFECT_CONFIG(开关蓝牙低延时模式的游戏音效)
// 低延时eq效果文件使用eq_game_eff.bin,调试时需保存成该文件,并在批处理-res后添加
// 非低延时eq效果文件使用eq_cfg_hw.bin,也需在批处理-res后添加
//*********************************************************************************//
#if CONFIG_A2DP_GAME_MODE_ENABLE
#define AUDIO_GAME_EFFECT_CONFIG 1 //低延时游戏模式脚步声、枪声增强 1:使能、0关闭
#else
#define AUDIO_GAME_EFFECT_CONFIG 0 //低延时游戏模式脚步声、枪声增强 1:使能、0关闭
#endif
/***********************************非用户配置区***********************************/
//以下宏定义,是游戏音效使能后,需要开启的宏定义,已配好,用户不用修改
#if AUDIO_GAME_EFFECT_CONFIG
#if (TCFG_EQ_ENABLE == 0)
#undef TCFG_EQ_ENABLE
#define TCFG_EQ_ENABLE 1
#endif/* (TCFG_EQ_ENABLE == 0) */
#if (TCFG_BT_MUSIC_EQ_ENABLE == 0)
#undef TCFG_BT_MUSIC_EQ_ENABLE
#define TCFG_BT_MUSIC_EQ_ENABLE 1
#endif/*(TCFG_BT_MUSIC_EQ_ENABLE == 0)*/
#if (TCFG_DRC_ENABLE == 0)
#undef TCFG_DRC_ENABLE
#define TCFG_DRC_ENABLE 1
#endif/* (TCFG_DRC_ENABLE == 0) */
#if (TCFG_BT_MUSIC_DRC_ENABLE == 0)
#undef TCFG_BT_MUSIC_DRC_ENABLE
#define TCFG_BT_MUSIC_DRC_ENABLE 1
#endif/* (TCFG_BT_MUSIC_DRC_ENABLE == 0) */
#if (EQ_SECTION_MAX < 10)
#undef EQ_SECTION_MAX
#define EQ_SECTION_MAX 10
#endif/* (EQ_SECTION_MAX < 10) */
#if (TCFG_USE_EQ_FILE == 0)
#undef TCFG_USE_EQ_FILE
#define TCFG_USE_EQ_FILE 1
#endif/* TCFG_USE_EQ_FILE */
#endif/* AUDIO_GAME_EFFECT_CONFIG */
/**********************************************************************************/
#if CONFIG_TWS_PAIR_MODE == CONFIG_TWS_PAIR_BY_CLICK
#define CONFIG_TWS_BY_CLICK_PAIR_WITHOUT_PAIR /*双击按键可以配对已配对过的样机,即交叉配对 */
#ifdef CONFIG_TWS_BY_CLICK_PAIR_WITHOUT_PAIR
#define CONFIG_TWS_AUTO_PAIR_WITHOUT_UNPAIR /* 不取消配对也可以配对新的耳机 */
#endif
#endif
#if TCFG_CHARGESTORE_ENABLE
#undef CONFIG_TWS_CHANNEL_SELECT
#define CONFIG_TWS_CHANNEL_SELECT CONFIG_TWS_SECECT_BY_CHARGESTORE //充电仓区分左右
#endif //TCFG_CHARGESTORE_ENABLE
#if TCFG_TEST_BOX_ENABLE && (!TCFG_CHARGESTORE_ENABLE)
#define CONFIG_TWS_SECECT_CHARGESTORE_PRIO 1 //测试盒配置左右耳优先
#else
#define CONFIG_TWS_SECECT_CHARGESTORE_PRIO 0
#endif //TCFG_TEST_BOX_ENABLE
//*********************************************************************************//
// 对耳电量显示方式 //
//*********************************************************************************//
#if BT_SUPPORT_DISPLAY_BAT
#define CONFIG_DISPLAY_TWS_BAT_LOWER 1 //对耳手机端电量显示,显示低电量耳机的电量
#define CONFIG_DISPLAY_TWS_BAT_HIGHER 2 //对耳手机端电量显示,显示高电量耳机的电量
#define CONFIG_DISPLAY_TWS_BAT_LEFT 3 //对耳手机端电量显示,显示左耳的电量
#define CONFIG_DISPLAY_TWS_BAT_RIGHT 4 //对耳手机端电量显示,显示右耳的电量
#define CONFIG_DISPLAY_TWS_BAT_TYPE CONFIG_DISPLAY_TWS_BAT_LOWER
#endif //BT_SUPPORT_DISPLAY_BAT
#define CONFIG_DISPLAY_DETAIL_BAT 0 //BLE广播显示具体的电量
#define CONFIG_NO_DISPLAY_BUTTON_ICON 1 //BLE广播不显示按键界面,智能充电仓置1
#endif //TCFG_USER_TWS_ENABLE
#ifndef CONFIG_BT_RX_BUFF_SIZE
#define CONFIG_BT_RX_BUFF_SIZE (14 * 1024)
#endif
#ifdef CONFIG_APP_BT_ENABLE
#if TCFG_BT_SUPPORT_AAC || TCFG_BT_SUPPORT_LDAC
#define CONFIG_BT_TX_BUFF_SIZE (5 * 1024)
#else
#define CONFIG_BT_TX_BUFF_SIZE (4 * 1024)
#endif
#else
#if TCFG_BT_SUPPORT_AAC || TCFG_BT_SUPPORT_LDAC
#define CONFIG_BT_TX_BUFF_SIZE (4 * 1024)
#else
#define CONFIG_BT_TX_BUFF_SIZE (3 * 1024)
#endif
#endif
#ifndef CONFIG_NEW_BREDR_ENABLE
#if TCFG_USER_TWS_ENABLE
#ifdef CONFIG_LOCAL_TWS_ENABLE
#define CONFIG_TWS_BULK_POOL_SIZE (4 * 1024)
#else
#define CONFIG_TWS_BULK_POOL_SIZE (2 * 1024)
#endif
#endif
#endif
#if (CONFIG_BT_MODE != BT_NORMAL)
////bqb 如果测试3M tx buf 最好加大一点
#undef CONFIG_BT_TX_BUFF_SIZE
#define CONFIG_BT_TX_BUFF_SIZE (6 * 1024)
#endif
//*********************************************************************************//
// 电源切换配置 //
//*********************************************************************************//
#define PHONE_CALL_USE_LDO15 CONFIG_PHONE_CALL_USE_LDO15
//*********************************************************************************//
// 时钟切换配置 //
//*********************************************************************************//
#define BT_NORMAL_HZ CONFIG_BT_NORMAL_HZ
#define BT_CONNECT_HZ CONFIG_BT_CONNECT_HZ
#define BT_A2DP_HZ CONFIG_BT_A2DP_HZ
#define BT_CALL_HZ CONFIG_BT_CALL_HZ
#define BT_CALL_ADVANCE_HZ CONFIG_BT_CALL_ADVANCE_HZ
#define BT_CALL_16k_HZ CONFIG_BT_CALL_16k_HZ
#define BT_CALL_16k_ADVANCE_HZ CONFIG_BT_CALL_16k_ADVANCE_HZ
#define MUSIC_DEC_FASTEST_CLOCK CONFIG_MUSIC_DEC_FASTEST_CLOCK
#define MUSIC_DEC_FAST_CLOCK CONFIG_MUSIC_DEC_FAST_CLOCK
#define MUSIC_DEC_CLOCK CONFIG_MUSIC_DEC_CLOCK
#define MUSIC_DEC_IDLE_CLOCK CONFIG_MUSIC_IDLE_CLOCK
#define MUSIC_FSCAN_CLOCK CONFIG_MUSIC_FSCAN_CLOCK
#define LINEIN_CLOCK CONFIG_LINEIN_CLOCK
#define FM_CLOCK CONFIG_FM_CLOCK
#define FM_EMITTER_CLOCK CONFIG_FM_EMITTER_CLOCK
#define PC_CLOCK CONFIG_PC_CLOCK
#define RECODRD_CLOCK CONFIG_RECORD_CLOCK
#define SPDIF_CLOCK CONFIG_SPDIF_CLOCK
////////////////////////
#if TCFG_BT_SUPPORT_AAC || TCFG_BT_SUPPORT_LDAC
#define BT_A2DP_STEREO_EQ_HZ 48 * 1000000L
#else
#define BT_A2DP_STEREO_EQ_HZ 32 * 1000000L
#endif
#define BT_A2DP_AAC_HZ 48 * 1000000L
#define BT_A2DP_TWS_AAC_HZ 64 * 1000000L
#define BT_A2DP_MONO_EQ_HZ 32 * 1000000L
#define BT_A2DP_ONLINE_EQ_HZ 48 * 1000000L
#define BT_CALL_SIMPLEX_HZ 96 * 1000000L
#ifdef CONFIG_ANS_V2
//#define BT_CALL_16k_HZ 96 * 1000000L
//#define BT_CALL_16k_ADVANCE_HZ 120 * 1000000L
#else
//#define BT_CALL_16k_HZ 80 * 1000000L
//#define BT_CALL_16k_ADVANCE_HZ 96 * 1000000L
#endif
#define BT_CALL_16k_SIMPLEX_HZ 120 * 1000000L
////////////////////////
#ifdef CONFIG_FPGA_ENABLE
// #undef TCFG_CLOCK_OSC_HZ
// #define TCFG_CLOCK_OSC_HZ 12000000
#endif
#ifdef CONFIG_CPU_BR26
#undef BT_CALL_16k_HZ
#undef BT_CALL_16k_ADVANCE_HZ
#define BT_CALL_16k_HZ 96 * 1000000L
#define BT_CALL_16k_ADVANCE_HZ 96 * 1000000L
#endif
#ifdef CONFIG_CPU_BR23
#undef BT_A2DP_STEREO_EQ_HZ
#define BT_A2DP_STEREO_EQ_HZ 48 * 1000000L
#undef BT_A2DP_MONO_EQ_HZ
#define BT_A2DP_MONO_EQ_HZ 48 * 1000000L
#endif
#ifdef CONFIG_CPU_BR25
#undef BT_A2DP_STEREO_EQ_HZ
#define BT_A2DP_STEREO_EQ_HZ 48 * 1000000L
#undef BT_A2DP_MONO_EQ_HZ
#define BT_A2DP_MONO_EQ_HZ 48 * 1000000L
#endif
#ifdef CONFIG_FPGA_ENABLE
// #undef TCFG_CLOCK_OSC_HZ
// #define TCFG_CLOCK_OSC_HZ 12000000
#undef TCFG_MC_BIAS_AUTO_ADJUST
#define TCFG_MC_BIAS_AUTO_ADJUST MC_BIAS_ADJUST_DISABLE
#endif
//*********************************************************************************//
// 低功耗配置 //
//*********************************************************************************//
#if TCFG_IRKEY_ENABLE
#undef TCFG_LOWPOWER_LOWPOWER_SEL
#define TCFG_LOWPOWER_LOWPOWER_SEL 0 //开红外不进入低功耗
#endif /* #if TCFG_IRKEY_ENABLE */
//*********************************************************************************//
// LED使用 16SLOT TIMER 同步 //
//*********************************************************************************//
//LED模块使用slot timer同步使用注意点:
// 1.soundbox不开该功能, 原因: 默认打开osc时钟, 使用原来的osc流程同步即可
// 2.带sd卡earphone不开该功能, 一般为单耳, 不需要同步, 使用原来的流程(lrc)
// 3.一般用在tws应用中, 而且默认关闭osc;
#if TCFG_USER_TWS_ENABLE
#define TCFG_PWMLED_USE_SLOT_TIME ENABLE_THIS_MOUDLE
#endif
//*********************************************************************************//
// 升级配置 //
//*********************************************************************************//
//升级LED显示使能
#define UPDATE_LED_REMIND
//升级提示音使能
#define UPDATE_VOICE_REMIND
#ifndef CONFIG_UPDATE_JUMP_TO_MASK
#define CONFIG_UPDATE_JUMP_TO_MASK 0
#endif
#if CONFIG_UPDATE_JUMP_TO_MASK
//升级IO保持使能
#define DEV_UPDATE_SUPPORT_JUMP //目前只有br23\br25支持
#endif
#if TCFG_APP_MUSIC_EN
#define CONFIG_SD_UPDATE_ENABLE
#define CONFIG_USB_UPDATE_ENABLE
#endif
//*********************************************************************************//
// Audio配置 //
//*********************************************************************************//
#if TCFG_AUDIO_ANC_ENABLE
#if ((defined VOL_TYPE_ANALOG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) || \
((defined VOL_TYPE_AD) && (SYS_VOL_TYPE == VOL_TYPE_AD))
#error "ANC can not use VOL_TYPE_ANALOG and VOL_TYPE_AD!!!"
#endif/*(SYS_VOL_TYPE = VOL_TYPE_ANALOG) || (SYS_VOL_TYPE = VOL_TYPE_AD)*/
#endif/*TCFG_AUDIO_ANC_ENABLE*/
/*通话语音处理算法放在.data段*/
#ifndef TCFG_AUDIO_CVP_CODE_AT_RAM
#define TCFG_AUDIO_CVP_CODE_AT_RAM 1
#endif/*TCFG_AUDIO_CVP_CODE_AT_RAM*/
/*AAC解码算法放在.data段*/
#ifndef TCFG_AUDIO_AAC_CODE_AT_RAM
#define TCFG_AUDIO_AAC_CODE_AT_RAM 1
#endif/*TCFG_AUDIO_AAC_CODE_AT_RAM*/
#if (TCFG_AUDIO_DUAL_MIC_ENABLE && TCFG_AUDIO_TRIPLE_MIC_ENABLE)
#error "TCFG_AUDIO_DUAL_MIC_ENABLE and TCFG_AUDIO_TRIPLE_MIC_ENABLE can not enable together !!!"
#endif
//*********************************************************************************//
// 充电中按键清除手机配对信息配置 //
//*********************************************************************************//
#define CHARGING_CLEAN_PHONE_INFO 0
#define PC_MODE_DETECTION
#endif

Some files were not shown because too many files have changed in this diff Show More