当前文档为 本地版本 (v0.1.0)，您可以访问当前页面的 在线版本 以获取最近可能的更新。

# PRF Dongle

## 1 功能概述

此sample为在`pan271x`上演示Dongle配合pan10xx作为鼠标端控制功能

## 2 环境要求

- 硬件设备与线材：

  - PAN271x EVB 核心板与底板各一块

  - JLink 仿真器（用于烧录例程程序）

  - USB-TypeC 线一条（用于底板供电和查看串口打印 Log）

  - 杜邦线数根或跳线帽数个（用于连接各个硬件设备）

- 硬件接线：

  - 将 EVB 核心板插到底板上

  - 连接串口转USB调试模块：

    - 使用 USB-TypeC 线，将 PC USB 插口与 EVB 底板 USB->UART 插口相连

    - 使用杜邦线或跳线帽将 EVB 底板 `J8` 排针对 (P06 & TXD) 和 `J9` 排针对 (P05 & RXD) 分别短接起来

  - 连接 Jlink，使用杜邦线将 JLink 仿真器的：

    - SWD_CLK 引脚与 EVB 底板的 P00 排针相连

    - SWD_DAT 引脚与 EVB 底板的 P01 排针相连

    - SWD_GND 引脚与 EVB 底板的 GND 排针相连

- PC 软件:

  - 串口调试助手（UartAssist）或终端工具（SecureCRT），波特率 115200（用于串口交互）

## 3 编译和烧录

例程位置：`01_SDK\samples\solutions\prf_dongle\keil\prf_dongle`

使用`keil`打开项目进行编译烧录。

## 4 演示说明

1. keil编译烧录`prf_dongle`程序，此时进入对码状态，dongle端在2412频点`{ 0x7b, 0x41, 0x29, 0x71 }`地址（PIPE0）进行扫描，并根据本地mac地址的后四位计算出私有的8个跳频地址。

2. pan10xx鼠标按下左中右三个按键进入配对模式，在2412频点`{ 0x7b, 0x41, 0x29, 0x71 }`发送鼠标端的mac地址。

3. pan271x dongle收到对码地址频点的鼠标端mac地址后，回复本地mac地址，并且把鼠标端mac地址后四位设置为PIPE1地址，如果在PIPE1地址上任意私有频点收取到数据，结束对码状态，如果没有收到私有地址频点的通信包，timeout中仍有机会切换到配对频点（鼠标端收到对码地址频点的dongle mac地址后，计算出私有的8个跳频地址，切换到鼠标mac地址后四位作为地址，跳频发送数据）。

4. 对码成功后鼠标可以控制PC。

   串口LOG如下所示：

       [11:27:05.484]收←◆CPU @ 48000000Hz
       usb_init
       plug in

       [11:27:05.535]收←◆get_mac_addr: 0x11 0x22 0x33 0x44 0x55 0x66
       calculate_combo_freq use 0x33 0x44 0x55 0x66
       x = 1 y = 5
       2464 abandon
       calculate private freq: 2428 2446 2466 2402 2420 2438 2456 2474

       [11:27:05.566]收←◆0x0 0x0 0x0 0x0 0x0 0x0
       0x0 0x0 0x0 0x0 0x0 0x0
       0x0 0x0 0x0 0x50
       USB isr in: Reset evt

       [11:27:05.637]收←◆USB isr in: Reset evt

       [11:27:14.782]收←◆hop end @ 2438

       [11:27:14.816]收←◆save new pair addr1: 0xE1 0xA0 0x0 0xA 0x1B 0x9B

## 5 开发说明

### 5.1 配对信息存储及接口说明

PAN271x使用EEPROM来保存配对信息，配对信息主要包含配对后的通信地址。EEPROM使用GPIO模拟IIC控制。

EEPROM读写接口：

    P24C02_ReadSequential(0x10, read_addr0, 6);
    P24C02_ReadSequential(0x20, read_addr1, 6);

    data_printf(read_addr0, 6);
    data_printf(read_addr1, 6);
    memcpy(&prf_state.pair_private_addr[0][0], read_addr0, 6);
    memcpy(&prf_state.pair_private_addr[1][0], read_addr1, 6);

    void write_pair_addr(void)
    {
    	if(pair_addr0_write) {
    		pair_addr0_write = false;
    		P24C02_WritePage(0x10, &prf_state.pair_private_addr[0][0], 6);
    		mini_printf("save new pair addr1: ");
    		data_printf(&prf_state.pair_private_addr[0][0], 6);
    	}

    	if(pair_addr1_write) {
    		pair_addr1_write = false;
    		P24C02_WritePage(0x20, &prf_state.pair_private_addr[1][0], 6);
    		mini_printf("save new pair addr2: ");
    		data_printf(&prf_state.pair_private_addr[1][0], 6);
    	}
    }

### 5.2 PRF说明

#### 5.2.1 初始化

    pan_prf_config_t __align(4) rf_config =
    {
    	.work_mode			= PRF_MODE_ENHANCE,//PRF_MODE_NORMAL,PRF_MODE_ENHANCE
    	.chip_mode			= PRF_CHIP_MODE_SEL_XN297,//PRF_CHIP_MODE_SEL_NRF,//PRF_CHIP_MODE_SEL_XN297,
    	.trx_mode			= PRF_RX_MODE,
    	.phy				= PRF_PHY_2M,//PRF_PHY_250K,//PRF_PHY_1M,PRF_PHY_2M
    	.crc				= PRF_CRC_SEL_CRC16,
    	.scr				= PRF_SCR_SEL_EN,
    	.mode_conf			= PRF_BLE_CONF,//PRF_BLE_CONF
    	.pipe				= PRF_PIPE0,
    	.rx_timeout			= 10000,			//us
    	.rf_channel			= PAIR_PUBLIC_CHANNEL,
    	.tx_no_ack			= DISABLE,
    	.rx_length			= 30,
    	.sync_length		= 4,
    	.sync				= PAIR_PUBLIC_ADDR,
    	.crc_include_sync	= ENABLE,
    	.scr_include_sync	= ENABLE,
    	.auto_pyl_flag		= ENABLE,
    	.pid_manual_flag	= ENABLE,
    	.endian				= PRF_BIG_ENDIAN,
    	.tx_power			= 8,
    };

    void dongle_prf_init(void)
    {
    	panchip_prf_init(&rf_config);

    	/* enable len err isr */
    	panchip_prf_rx_length_irq_cfg(rf_config.rx_length);

    	SYS_SET_MFP(P2,1,LL_DEBUG_0);		//tx_on
    	SYS_SET_MFP(P2,0,LL_DEBUG_1);		//rx_on
    	SYS_SET_MFP(P0,4,LL_DEBUG_9);		//match

    	dongle_prf_pair_init();

    	panchip_prf_trx_start();
    }

1. 全局变量`rf_config`基本包含了2.4g的所有配置，定义好后就可以使用`panchip_prf_init(&rf_config);`接口对RF初始化。

2. RF初始化完后，开启len err中断，rf状态可控，增强型模式下，一定会进行完成`r->t/timeout/crc/len err`状态，中断内控制好下一次trx start之前进行数据存储操作、状态控制，不会引起rf死机状态

3. LL DEBUG信号可以抓取rf工作中的时序，但需要注意，开启debug信号时会一定程度影响rf，crc率会变高。调试阶段可以打开，正常使用要关闭。

4. `dongle_prf_pair_init();`中获取dongle mac地址，计算出配对频点（通过dongle mac后四字节），并且设置可能存储过的配对地址作为rf 收取地址

        /* set PRI_RF_MODE_SEL_RX addr will set the rx addr & pipe */
        /* set PRI_RF_MODE_SEL_TX addr will set the single tx addr, no set tx will use init tx addr */
        /* set PRI_RF_MODE_SEL_TRX addr will set the trx addr both, no set tx will use init tx addr */
       panchip_prf_set_addr(addr_format, 4, PRF_PIPE1, PRI_RF_MODE_SEL_RX);
       panchip_prf_set_addr(addr_format, 4, PRF_PIPE2, PRI_RF_MODE_SEL_RX);

   设置PRI_RF_MODE_SEL_RX地址仅设置接收PIPE，不会设置发送地址

   rx isr中需要设置payload并且设置回复时的tx地址，设置发送地址参考

        /* set addr will set the tx addr, if want to ack data from dynamic rx pipe ,rx isr must set tx addr */
        CONFIG_RAM_CODE void app_prf_set_tx_addr(uint8_t *addr)
        {
        #if SET_TX_ADDR_DIRECT
        /* 1.25us */
        uint32_t tx_addr;

        tx_addr = (addr[0]) | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);

        PRI_RF_WRITE_REG_VALUE(PRI_RF, R05_TX_ADDR_L, L32B, tx_addr);
        #else
        /* 6us no used third param */
        panchip_prf_set_addr(addr, 4, PRF_PIPE0, PRI_RF_MODE_SEL_TX);
        #endif

}

1. 最后进行panchip_prf_trx_start();开启tx；

#### 5.2.2 时间说明

为了适配pan10xx的键鼠，pan271x dongle的rx转tx的时间配置成30us。如果往大了调鼠标端会收不到ack。如下图所示：

rx isr中需要设置payload并且设置回复时的tx地址，设置地址时，可以快速设置4字节地址或者调用底层封装接口设置，分别占用1us或者6us，影响还好，就算当前次不能及时设置好地址，依然会在下次配对地址收到数据后在对应地址回复出

    /* set addr will set the tx addr, if want to ack data from dynamic rx pipe ,rx isr must set tx addr */
    CONFIG_RAM_CODE void app_prf_set_tx_addr(uint8_t *addr)
    {
     #if SET_TX_ADDR_DIRECT
     /* 1.25us */
     uint32_t tx_addr;

     tx_addr = (addr[0]) | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);

     PRI_RF_WRITE_REG_VALUE(PRI_RF, R05_TX_ADDR_L, L32B, tx_addr);
     #else
     /* 6us no used third param */
     panchip_prf_set_addr(addr, 4, PRF_PIPE0, PRI_RF_MODE_SEL_TX);
     #endif
    }

#### 5.2.3 多pipe使用说明

多pipe地址读取的功能，灵活使用可以实现配对地址和多通道地址同时可以收取回复数据，基于此feature可以扩展多个主机设备配对同一dongle，目前主机端最快速度在250us内可以完成发收，所以多设备自行处理的条件下，通过重传可以做到至少2个设备配对同一dongle后，可以达到1000hz上报率

演示说明：

1. 准备2个pan1080 8k鼠标，鼠标1下载默认程序，鼠标2下载 PAIR_COMBO_DG_DEV2=1的第二设备程序

2. 编译下载PAIR_ONLY_ONE=0的pan271x dongle程序

3. 鼠标1进入配对状态，复位pan271x，鼠标1配对成功，鼠标1不移动情况下鼠标2进入配对或者上电状态，鼠标2配对成功

4. 鼠标1可以达到1000hz上报率，鼠标2默认配对后125hz上报率

对码说明参考演示说明部分的第四点，补充说明鼠标1和鼠标2的区别在于，配对过程数据字段，回复的数据除了各自mac地址，还有额外的数据字段区分对应配对到哪一个pipe，pan271x rf中确认私有mac搜索到数据通信后不再添加其他地址，重新上电会重新进入可添加pipe地址状态

    	pkt_pair.magic = PAIR_MAGIC;
    	#if PAIR_COMBO_DG_DEV2
    	pkt_pair.type = 0x20;
    	#else
    	pkt_pair.type = PAIR_MOUSE_8K_FLAG;
    	#endif
    	memcpy(pkt_pair.mac, pair_ctrl.pair_own_addr, 6);
    	memcpy(tx_payload.data, &pkt_pair, 9);

### 5.3 USB说明

USB init软件过程基本与pan10xx一致，其他部分使用也一致

    void usb_init(void)
    {
    	uint32_t reg_tmp;

    	SYS->SYS_CTRL |= (SYS_CTRL_USB_PU_Msk | SYS_CTRL_USB_PU2_Msk | SYS_CTRL_USB_EN_Msk);
    	/*usb debounce time*/
    	SYS->SYS_CTRL = ((SYS->SYS_CTRL & ~SYS_CTRL_VALID_REMOVAL_CYCLES_Msk) | 100);

    	reg_tmp = READ_REG(USB->INT_USBE);
    	reg_tmp |= 0x10;
    	WRITE_REG(USB->INT_USBE,reg_tmp);

    //	NVIC_EnableIRQ(USB_IRQn);

    	mini_printf("usb_init\n");
    	NVIC_SetPriority(USB_IRQn, 1);
    	NVIC_EnableIRQ(USB_IRQn);
    }

## 6 RAM/Flash资源使用情况

PAN271x:

    - Flash Size:  14.79kB
    - RAM Size:  1.80kB

版本选择及下载 v: 0.1.0

版本选择
  latest
  0.1.0

下载
  PAN271x 开发套件文档（PDF）

相关链接
  PAN271x 系列产品 WIKI
  PAN271x 系列产品技术论坛
  上海磐启微电子有限公司