当前文档版本为 v1.0.1,您可以访问当前页面的 开发中 版本以获取最近可能的更新。

Solution: Multimode Keyboard

重要

此例程仅存在于特殊版本的SDK中,如有需要请联系Panchip。

1 功能概述

此sample为pan108xxb5(64pin芯片)在实体键盘板下的应用

具体支持的feature如下:

  • 通用功能:

    1. 按键模块:支持75%的配列布局,支持标准按键/无冲按键

      image

    2. 多层按键映射:目前默认添加FN 层,实现F1 - F12多媒体按键,以及用户自定义事件,可扩展其它层。

    3. QDEC滚轮模块:支持去抖的正交解码器,正反转实现快速音量大小调节

    4. LED模块:键盘右上角从上到下四个LED分别为CAPS LOCK/USB/2.4G/BLE指示灯,分别指示各模式下的连接状态

    5. 电量检测:ADC采集电量信息,低电量时默认左上角第一个LED(ESC键底部)红色闪烁

    6. 供电及模式切换:

      ​ a. 电池供电:底部按键可以切换2.4G模式与蓝牙模式,开关拨到中间中间为断电状态

      ​ b. USB仅供电:底部按键可以切换2.4G模式与蓝牙模式,中间为USB模式

  • 2.4G模式(PRF增强型模式)

    1. 跳频:在信号质量不好(连续FREQ_HOP_NOACK_THREHOLD=15个ack未收到)/对码前在8个频点进行跳频

    2. 对码:上电跳频找到dongle端的频点后,通信互发对端的MAC地址后2字节,之后切换到私有地址进行通信

    3. 重传:丢包时会进行重传,以最快速度进行重传直到收到对端回复

    4. ACK:可解析的ACK,具有演示代码

    5. 性能:默认上报率1000的情况下,近距离稳定在990包以上,8-9米稳定在960包以上

    6. 测试模式(可选):宏控制自动画圈(需要在prj.conf文件中设置宏定义CONFIG_TEST_REPORT_RATE=y,键盘按FN + 8

  • BLE模式

    1. 蓝牙白名单,分时连接

    2. 配对,保存

    3. 连接,重连功能:

    4. OTA(未使能):与mcuboot配合通过NRF工具进行升级

    5. 性能:133HZ上报率

    6. 性能:兼容性

  • USB模式

    1. 性能:USB2.0最高速率1000hz

    2. 电脑的休眠唤醒(未做)

    3. 升级:与mcuboot配合通过USB工具进行升级

  • EMI测试

2 环境要求

  • board: pan108xxb5(芯片型号)键盘板

  • USB升级工具(USB升级工具获取:https://docs.panchip.com/pan1080dk-doc/latest/docs-zdk/06_dev_tools/pan108x_toolbox_intro.html)

  • 鼠标测试工具:KEYTEST.exe

3 编译和烧录

例程位置:zephyr\samples_panchip\solutions\multimode_keyboard

使用 ZAL 工具可以对其进行编译、烧录、打开 VS Code 调试等操作。关于 ZAL 工具的详细介绍请参考:Zephyr APP Launcher 工具介绍

4 演示说明

芯片全部擦除还原默认状态,准备好烧录multimode_keyboard_dongle的接收器

4.1 电池供电模式

硬件支持锂电池供电

1、电池供电模式下3.6V低压报警(键盘左上角第一个RGB红色快闪),3.4V进入休眠状态,在不同的灯效下可能会提前进入低压报警状态

2、电池供电模式下,无任何按键按下的情况下,30S后关闭RGB灯光,2.4G模式60S后进入休眠,BLE模式保持连接状态,10分钟后进入休眠

4.2 USB供电模式

​ USB供电后,键盘不进入休眠状态

4.3 模式切换说明

  1. 2.4G模式:将键盘背部的拨动开关向左拨,键盘进入2.4G模式,如果键盘处于配对状态,键盘对应的2.4G指示灯快闪,此时插入dongle,键盘对应的2.4G指示灯常亮,代表键盘连接成功。拔掉dongle,指示灯慢闪,说明键盘处于断连状态。处于2.4G模式时,任意时刻可通过长按FN+4 3秒,让键盘进入强制配对状态。

  2. BLE模式:将键盘背部的拨动开关向右拨,键盘进入BLE模式,如果键盘处于配对状态,键盘对应的BLE指示灯快闪,电脑端弹出名称为keyboard[0/1/2]的设备,连接成功后,指示灯长亮。如果键盘处于断连状态,指示灯慢闪。

    键盘处于BLE模式时,通过短按 FN+1 切换到1通道,通过短按 FN+2 切换到2通道,通过短按 FN+3 切换到3通道。在任一通道上,通过长按FN+通道号 3秒进入强制配对状态。

  3. USB模式:将键盘背部的拨动开关拨到中间,插入USB线,键盘进入USB模式,键盘对应的USB指示灯亮起。

4.4 测试模式

4.4.1 组合按键测试

组合按键说明

组合键

基础键

功能

FN

F1

我的电脑(多媒体快捷键)

FN

F2

主页(多媒体快捷键)

FN

F3

计算器(多媒体快捷键)

FN

F4

多媒体(多媒体快捷键)

FN

F5

上一曲(多媒体快捷键)

FN

F6

下一曲(多媒体快捷键)

FN

F7

暂停/播放(多媒体快捷键)

FN

F8

停止(多媒体快捷键)

FN

F9

静音(多媒体快捷键)

FN

F10

音量降低(多媒体快捷键)

FN

F11

音量提高(多媒体快捷键)

FN

F12

邮件(多媒体快捷键)

FN

空格键

打开/关闭RGB背光

FN

背光亮度提高

FN

背光亮度降低

FN

灯光速度减缓(暂未添加)

FN

灯光速度加快(暂未添加)

FN

1

蓝牙模式下短按切换蓝牙通道1,长按3秒进入配对

FN

2

蓝牙模式下短按切换蓝牙通道2,长按3秒进入配对

FN

3

蓝牙模式下短按切换蓝牙通道3,长按3秒进入配对

FN

4

2.4G模式下长按3秒进入配对

FN

5

任意模式下长按3秒进入EMI测试模式(暂未添加)

FN

6

EMI模式下短按切换测试模式

FN

7

EMI模式下短按切换测试频点

FN

8

上报率测试打开/关闭(模拟鼠标画圈)

4.4.2 EMI测试(RF测试模式)

环境要求:

  • PAN1080 键盘板

  • USB TYPE-C线

  • PAN1080 ToolBox下载

测试说明:

  • TX模式,如下图所示:

    image

    RF TEST TX模式

    发包数必须设为0,当前不支持发包数的设置

  • RX模式,如下图所示:

    image

    RF TEST RX模式

  • TX单载波模式,如下图所示:

    image

    RF TEST 单载波模式

5 开发说明

5.1 架构说明

multimode_keyboard基于zephyr架构,进行多线程编程,线程静态初始化后,根据优先级进行先后初始化,之后各个线程运行至while(1)等待相应的信号量,以此通过控制信号量控制各个线程的调度关系

架构中应用层主要包含

  • 8个线程

    • MAIN

    • 电量检测

    • EMI测试

    • 按键扫描

    • 跳频

    • RF发包

    • USB发包

    • BLE发包

    • 上报率测试(默认关闭)

  • 4个中断

    • TIMER0中断(触发组包)

    • TIMER1中断(255us周期,灯效值处理,按键端口状态扫描)

    • USB中断

    • PRF中断

  • 3个重要接口

    • BLE接口(Zephyr API):FRAME组包后通过调用蓝牙接口进入HOST层进行发包,非阻塞接口,会为ble host填充最多6包数据

      /** @brief Notify attribute value change no wait.
       *
       *  Send notification of attribute value change, if connection is NULL notify
       *  all peer that have notification enabled via CCC otherwise do a direct
       *  notification only the given connection.
       *
       *  The attribute object on the parameters can be the so called Characteristic
       *  Declaration, which is usually declared with BT_GATT_CHARACTERISTIC followed
       *  by BT_GATT_CCC, or the Characteristic Value Declaration which is
       *  automatically created after the Characteristic Declaration when using
       *  BT_GATT_CHARACTERISTIC.
       *
       *  @param conn Connection object.
       *  @param attr Characteristic or Characteristic Value attribute.
       *  @param data Pointer to Attribute data.
       *  @param len Attribute value length.
       *
       *  @return 0 in case of success or negative value in case of error.
       */
      static inline int bt_gatt_notify_no_wait(struct bt_conn *conn,
      				 const struct bt_gatt_attr *attr,
      				 const void *data, uint16_t len)
      
    • USB EP3接口(VENDOR DFU):通过USB中断进入进行DFU升级,EMI测试

      void usb_vendor_ep3_out(void)
      
    • 低功耗接口

      • 应用进入低功耗宏(长时间静止后进入Deepsleep)

        CONFIG_PM_MOUSE=y
        
      • 系统空闲进入Deepsleep宏,注意程序默认开启了CONFIG_PM=y,如果不用系统Deepsleep,需要以下四个宏一起屏蔽,蓝牙模式下生效

        开启 系统空闲进入Deepsleep 模式
        ### open CONFIG_PM ###
        CONFIG_PM=y
        #Clock Source is RCL
        CONFIG_BT_CTLR_SLEEP_CLOCK_SOURCE=1
        #Accuracy is 2000ppm
        CONFIG_BT_CTLR_SLEEP_TIMER_ACCURACY=2000
        #Enable RCL Force CALIBRATION
        CONFIG_SOC_FORCE_CALIB_RCL_CLK=y
        ### open CONFIG_PM ###
        
        关闭 系统空闲进入Deepsleep 模式
        ### not open CONFIG_PM ###
        # CONFIG_PM=y
        # #Clock Source is RCL
        # CONFIG_BT_CTLR_SLEEP_CLOCK_SOURCE=1
        # #Accuracy is 2000ppm
        # CONFIG_BT_CTLR_SLEEP_TIMER_ACCURACY=2000
        # #Enable RCL Force CALIBRATION
        # CONFIG_SOC_FORCE_CALIB_RCL_CLK=y
        ### not open CONFIG_PM ###
        

5.2 线程说明

线程定义方式如下,选用静态线程的方式,由于包含多种reboot操作,实际单模式生效可对其他无用线程进行中止操作,线程之间通过信号量进行切换或者挂起

/**
 * @brief Statically define and initialize a thread.
 *
 * The thread may be scheduled for immediate execution or a delayed start.
 *
 * Thread options are architecture-specific, and can include K_ESSENTIAL,
 * K_FP_REGS, and K_SSE_REGS. Multiple options may be specified by separating
 * them using "|" (the logical OR operator).
 *
 * The ID of the thread can be accessed using:
 *
 * @code extern const k_tid_t <name>; @endcode
 *
 * @param name Name of the thread.
 * @param stack_size Stack size in bytes.
 * @param entry Thread entry function.
 * @param p1 1st entry point parameter.
 * @param p2 2nd entry point parameter.
 * @param p3 3rd entry point parameter.
 * @param prio Thread priority.
 * @param options Thread options.
 * @param delay Scheduling delay (in milliseconds), zero for no delay.
 *
 *
 * @internal It has been observed that the x86 compiler by default aligns
 * these _static_thread_data structures to 32-byte boundaries, thereby
 * wasting space. To work around this, force a 4-byte alignment.
 *
 */
#define K_THREAD_DEFINE(name, stack_size,                                \
			entry, p1, p2, p3,                               \
			prio, options, delay)                            \
	K_THREAD_STACK_DEFINE(_k_thread_stack_##name, stack_size);	 \
	struct k_thread _k_thread_obj_##name;				 \
	STRUCT_SECTION_ITERABLE(_static_thread_data, _k_thread_data_##name) = \
		Z_THREAD_INITIALIZER(&_k_thread_obj_##name,		 \
				    _k_thread_stack_##name, stack_size,  \
				entry, p1, p2, p3, prio, options, delay, \
				NULL, name);				 	 \
	const k_tid_t name = (k_tid_t)&_k_thread_obj_##name

根据线程定义,定义了如下几个线程,并在common.h统一管理线程优先级及栈大小

#define BATTERY_THREAD_PRIORITY                 7
#define BATTERY_THREAD_STACKSIZE                768

#define BLE_THREAD_PRIORITY                     3
#define BLE_THREAD_STACKSIZE                    1024

#define EMI_THREAD_PRIORITY                     2
#define EMI_THREAD_STACKSIZE                    512

#define KEY_SCAN_THREAD_PRIORITY                1
#define KEY_SCAN_THREAD_STACKSIZE               1024

#define FREQ_HOP_THREAD_PRIORITY                2
#define FREQ_HOP_THREAD_STACKSIZE               512

#define PRF_THREAD_PRIORITY                     1
#define PRF_THREAD_STACKSIZE                    512

#define TEST_REPORT_RATE_THREAD_PRIORITY        2
#define TEST_REPORT_RATE_THREAD_STACKSIZE       512

#define USB_THREAD_PRIORITY                     2
#define USB_THREAD_STACKSIZE                    512

5.2.1 BATTERY线程

电量监测线程,ADC_SCAN_INTERVAL_MS = 100 ms的间隔进行电量采集,判断电池低压情况,以及判断是否有模式发生切换。并同时进行WDT喂狗,蓝牙模式进行电量进行上报

5.2.2 MAIN线程

主线程,处理软件和硬件的初始化工作,例如GPIO/ADC/PWM/TIMER/QDEC等,进行工作模式检测,如果是2.4G模式,并且未配对,则进行配对处理

5.2.3 FREQ_HOP线程

跳频线程,初始化对码线程会触发进入,在收到ACK少的时候会触发,通过信号量与PRF线程存在互斥关系

5.2.4 PRF线程

2.4G主线程,会进行重传处理,在重传条件下收到ACK数量低于阈值进入跳频线程

5.2.5 USB线程

USB线程,USB插入PC时进入,获取组包并且上报

5.2.6 BLE线程

BLE线程,获取数据包进行上报

5.2.7 EMI线程

通过TIMER0触发EMI测试中发包相关逻辑

5.2.8 KEY线程

按键事件处理(基础按键组包,组合按键处理),在按键全部松开的时候,判断是否进入低功耗

5.2.9 TEST_REPORT线程(上报率测试线程,默认关闭)

模拟鼠标自动画圈,用于测试上报率,默认关闭

5.3 RF中断说明

5.3.1 RF中断

鼠标端为PRF TX端,增强型模式会在TX后自动转入RX, 中断中主要处理信号量sem_prf_isr的给出及ack_lost_cnt的计数

5.3.2 TIMER0中断

TIMER中断产生多线程的控制信号量,并且根据不同上报率切换timer中断间隔

5.3.3 TIMER1中断

TIMER1中断用来控制LED灯显示,每一次中断后点亮键盘矩阵中某一列的灯,灯的状态发生变化后在中断中刷新对应的buff数值。按键端口变化值在中断中获取,扫描完端口的变化后,释放按键处理信号量,在按键线程中完成键值的组包和处理。

5.4 主要数据结构说明

5.4.1 枚举状态

5.4.1.1 配对状态
enum prf_pair_stat_t {
	prf_pair_start,
	prf_pair_comm,
	prf_pair_addr,
	prf_pair_end,
	prf_paired_private,
	prf_paired_public,
};
5.4.1.2.连接状态
enum ble_connect_stat_t {
	ble_disconnect_stat,
	ble_connect_stat,
};
5.4.1.3 工作模式
enum keyboard_work_mode_t {
	keyboard_null_mode,
	keyboard_usb_mode,
	keyboard_prf_mode,
	keyboard_ble_mode,
};
5.4.1.4 2.4G RF状态
enum prf_trx_stat_t {
	prf_idle_stat,
	prf_tx_done_stat,
	prf_rx_done_stat,
	prf_rx_timeout_stat,
	prf_rx_crc_err_stat,
	prf_rx_pid_err_stat,
};
5.4.1.5 跳频状态
enum prf_freq_hop_stat_t {
	freq_hop_disconnect_stat,
	freq_hop_connecting_stat,
	freq_hop_done_stat,
};
5.4.1.6 USB状态
enum usb_plug_mode_t {
	usb_plug_in,
	usb_plug_out,
};
5.4.1.7 灯状态
enum keyboard_led_stat_t {
	led_unpair_stat,
	led_paired_stat,
	led_low_batt_stat,
	led_prf_connected,
	led_prf_disconnected,
	led_key_stat,
	led_usb_stat,
	led_ble_connected_stat,
	led_ble_disconnected_stat,
	led_ble_pairing_stat,
	led_emi_stat,
};
5.4.1.8 休眠唤醒低功耗状态
enum keyboard_low_power_stat_t {
	active_stat,
	prf_off_stat,
	deep_sleep_v1_stat,
	deep_sleep_v2_stat,
	standby_stat,
};

5.4.2 全局结构

5.4.2.1 组包ring_buf(zephyr)
/**
 * @brief A structure to represent a ring buffer
 */
struct ring_buf {
	uint32_t head;	 /**< Index in buf for the head element */
	uint32_t tail;	 /**< Index in buf for the tail element */
	union ring_buf_misc {
		struct ring_buf_misc_item_mode {
			uint32_t dropped_put_count; /**< Running tally of the
						     * number of failed put
						     * attempts.
						     */
		} item_mode;
		struct ring_buf_misc_byte_mode {
			uint32_t tmp_tail;
			uint32_t tmp_head;
		} byte_mode;
	} misc;
	uint32_t size;   /**< Size of buf in 32-bit chunks */

	union ring_buf_buffer {
		uint32_t *buf32; /**< Memory region for stored entries */
		uint8_t *buf8;
	} buf;
	uint32_t mask;   /**< Modulo mask if size is a power of 2 */

	struct k_spinlock lock;
};
5.4.2.2 packet格式结构体

键盘发送的2.4G帧格式如下

前导码

接入地址

signal

payload

crc

3B

4B

10bit

3/24B

2B

0x550f71

公共地址/私有地址

增强型的字段

跳频对码包/键盘数据包

16bit crc

其中键盘Payload为用户可以修改的数据段,Payload中又包含了3个字节的固定数据,其中3个字节的固定数据格式如下

Type

Addr

1B

2B

包的类型:对码跳频包/键盘数据包

己端MAC地址后两个字节

Type定义如下

#define PRF_PKT_TYPE_PAIR               (1 << 0)
#define PRF_PKT_TYPE_FREQ_HOP           (1 << 1)
#define PRF_PKT_TYPE_KEYBOARD_DATA      (1 << 2)
#define PRF_PKT_TYPE_LED_STATUS         (1 << 3)

跳频对码包:

header: PRF_PKT_TYPE_FREQ_HOP | PRF_PKT_TYPE_PAIR

跳频包:

header: PRF_PKT_TYPE_FREQ_HOP

数据包:

header: PRF_PKT_TYPE_KEYBOARD_DATA

键盘LED状态包:

header: PRF_PKT_TYPE_LED_STATUS

键盘LED状态包用于2.4G dongle端回发CAPS LOCK/NUM LOCK/SCROLL LOCK状态

另外包含21个字节应用层数据(ringbuf管理的数据结构)

key_type

key_value

header

sequence

rate_pkt_index

reserved

1B

16B

1B

1B

1B

1B

键值类型

按键值

包头

序列号

上报率

保留扩展位

#define KEYBOARD_KEY_SIZE                 16

struct keyboard_pkt_detect_t {
	uint8_t key_event;
	uint8_t key_value[KEYBOARD_KEY_SIZE];
	uint8_t header;
	uint8_t sequence;
	uint8_t rate_pkt_index;
	uint8_t reserved;
};

在dongle端根据key_type类型,对key_value数据进行解析,其中包含5中键值类型:

5.4.2.3 标准按键格式结构体
#define KEYBOARD_STANDARD_KEY_SIZE        8

typedef union {
	uint8_t buff[KEYBOARD_STANDARD_KEY_SIZE];
	struct {
		union {
			uint8_t specialKey;
			struct {
				uint8_t LCtrl : 1;
				uint8_t LShift : 1;
				uint8_t LAlt : 1;
				uint8_t LGUI : 1;
				uint8_t RCtrl : 1;
				uint8_t RShift : 1;
				uint8_t RAlt : 1;
				uint8_t RGUI : 1;
			};
		};
		uint8_t reserve;
		uint8_t code[6];
	};
} standard_report_s;
5.4.2.4 无冲按键格式结构体
#define KEYBOARD_BIT_KB_KEY_SIZE         16

typedef union {
	uint8_t buff[KEYBOARD_BIT_KB_KEY_SIZE];
	struct {
		uint8_t id;
		uint8_t code[15];
	};
} bit_kb_key_report_s;
5.4.2.5 媒体按键格式结构体
#define KEYBOARD_MEDIA_KEY_SIZE         3

typedef union {
	uint8_t buff[KEYBOARD_MEDIA_KEY_SIZE];
	struct {
		uint8_t id;
		uint8_t code[2];
	};
} media_key_report_s;
5.4.2.6 电源按键格式结构体
#define KEYBOARD_POWER_KEY_SIZE         2

typedef union {
	uint8_t buff[KEYBOARD_POWER_KEY_SIZE];
	struct {
		uint8_t id;
		union {
			uint8_t flag;
			struct {
				uint8_t shutdown : 1;
				uint8_t sleep : 1;
				uint8_t wakeup : 1;
				uint8_t reserve : 5;
			};
		};
	};
} power_key_report_s;
5.4.2.7 鼠标按键格式结构体
#define KEYBOARD_MOUSE_SIZE            8

typedef union {
	uint8_t buff[KEYBOARD_MOUSE_SIZE];
	struct {
		uint8_t id;
		union {
			uint8_t key_value;
			struct {
				uint8_t LeftBtn : 1;
				uint8_t RightBtn : 1;
				uint8_t MidBtn : 1;
				uint8_t BackBtn : 1;
				uint8_t ForwardBtn : 1;
				uint8_t reserve : 3;
			};
		};
		int16_t x_value;
		int16_t y_value;
		int8_t roll_value;
		int8_t tilt_roll_value;
	};
} mouse_report_s;

键盘接收的2.4G ACK数据帧格式如下

前导码

接入地址

signal

payload

crc

3B

4B

10bit

xB

2B

0x550f71

公共地址/私有地址

增强

ACK数据(长度自定义,默认数据长度为0)

16bit crc

用户可以根据需求扩展使用ACK数据

dongle回传LED状态信息数据帧格式如下

前导码

接入地址

signal

payload[0]

payload[1]

crc

3B

4B

10bit

1B

1B

2B

0x550f71

公共地址/私有地址

增强

LED指示灯类型

LED指示灯值

16bit crc

5.4.2.8 收包计数结构体
struct prf_pkt_cnt_t {
	uint32_t tx_cnt;
	uint32_t rx_cnt;
	uint8_t prf_repeat_cnt;
};
5.4.2.9 配对信息结构体
struct pair_ctrl_t {
	enum prf_pair_stat_t prf_pair_stat;
	uint32_t prf_pair_timeout;
	uint8_t pair_own_addr[2];
	uint8_t pair_peer_addr[2];
	bool paired_flag;
};

5.5 主要逻辑图示

5.5.1 键盘端多线程流程图

5.5.1.1 模式检测及中断、低功耗接口流程图
image

键盘主框架流程图

5.5.1.2 2.4G主要流程图
image

键盘2.4G流程图

5.5.1.3 USB主要流程图
image

USB主要流程图

5.5.2 2.4G对码重传跳频

5.5.2.1 对码逻辑
image

对码逻辑

5.5.2.2 重传逻辑
image

重传逻辑

5.5.2.3 跳频逻辑
image

跳频逻辑

6 键鼠套件(附)

键鼠套件由PAN1080做主设备,可能是鼠标(1000hz),大键盘(125hz),小键盘(125hz)

需要配合配套键盘及配套2628dongle(支持多pipe)使用,PAN2628参考固件及烧录工具可以从05_TOOLS\dev-tools\MouseSupportTool\PAN2628Dongle获取,源码可联系我司获取

键盘作为键鼠套件时,需要在commom.c中使能

#define KB_MOUSE_ONEDONLE                          1

6.1 配对过程

6.1.1 配对参数

  • 鼠标采用公共地址:0x7B, 0x41, 0x29, 0x79

  • 大键盘采用公共地址:0x7C, 0x41, 0x29, 0x79

  • 小键盘采用公共地址:0x7D, 0x41, 0x29, 0x79

  • 公共频点为:

u8 idata channel_list_public[8] =
{
    4, 12, 18, 30, 38, 44, 56, 74
};

dongle采用多pipe模式进行接收:

pipe0接收地址(鼠标):0x7B, 0x41, 0x29, 0x79

pipe1接收地址(大键盘):0x7C, 0x41, 0x29, 0x79

pipe2接收地址(小键盘):0x7D, 0x41, 0x29, 0x79

经以上配置后:

dongle从pipe0接收的数据认为是鼠标数据

dongle从pipe1接收的数据认为是大键盘数据

dongle从pipe2接收的数据认为是小键盘数据

6.1.2 配对时序

dongle上电后,配置完RF参数,再依次开启pipe0~pipe2开始接收公共地址的配对信息,dongle根据pipe号来区分是哪个设备发来的配对命令。 以mouse配对为例,mouse上电后,配置完RF参数后,设置RF地址为0x7B, 0x41, 0x29, 0x79,即鼠标的专用配对地址,并以channel_list_public为跳频地址表。之后mouse会发送配对请求包,请求包的格式为:

magic[4B]

命令[1B]

地址[6B]

0x31415926

0x01

mouse mac

dongle收到mouse的配对请求包后:

  1. 如果收到的配对请求命令不正确,则不回复任务消息。

  2. 如果配对请求命令校验正确无误,则回复以下响应:

magic[4B]

命令[1B]

地址[6B]

0x31415926

0x01

dongle mac

dongle收到正确的配对请求后,会将mouse的mac地址写入flash保存下来。

mouse收到dongle配对响应后,核对正确后,会将dongle的地址写入flash保存下来。

mouse写完dongle的mac地址后,会再次发送配对的检查命令,用于检查dongle端是否正确保存mouse的配对信息,命令格式如下:

magic[4B]

命令[1B]

0x31415926

0x02

dongle端收到mouse的检查命令后,如果命令核对不正确,则不回复任何消息。

如果命令核对正确,则回复以下消息:

magic[4B]

命令[1B]

地址[6B]

0x31415926

0x02

mouse mac

mouse端收到dongle的回复后,核对dongle地址无误后,则认为mouse配对过程结束,否则重新开始发送配对请求包,重新以上配对过程,直到配对成功。

以上配对流程总结如下图:

image-20230808135237514

套件配对逻辑

6.1.3 配对时间说明

  • dongle上电后,最长配对时间不超过20秒(当前配对时间窗口为3秒)

  • 如果mouse,keyboard都快速配对完成,则dongle不需要等待超时时间到达,提前进入通信流程

6.2 数据通信过程

6.2.1 私有地址

  • dongle Vs mouse:使用pipe0管道,采用mouse mac[5]和dongle mac[3]~mac[5]组成一个4字节的地址作为通信地址

  • dongle Vs 大键盘:使用pipe1管道,采用大键盘mac[5]和dongle mac[3]~mac[5]组成一个4字节的地址作为通信地址

  • dongle Vs 小键盘:使用pipe2管道,采用小键盘mac[5]和dongle mac[3]~mac[5]组成一个4字节的地址作为通信地址

6.2.2 跳频通道

根据dongle地址各自计算私有跳频列表,之后按私有跳频列表来进行跳频通信,跳频方式和之前相同。

6.2.3 跳频规则

  • dongle 若10ms内没有收到数据,则产生跳频,规则是切换至下一频道上监听10ms,10ms内没有收到数据,再切换至下一频道继续监听,直到在某个频道到收到数据包,则停止跳频,开始进行数据通信。

  • 设备(mouse,keyboard etc)若连续10包发送不成功,则产生跳频,规则是切换至下一频道并发送数据包,若没有收到ack,再切换至下一频道继续发送数据,直到收到ack,停止跳频。

6.2.4 超时时间

以鼠标为例,当鼠标配对完成后,进入数据通信模式,此时dongle可能因为大小键盘还没有完成配对,因此鼠标要设置一个最大数据发送超时时间T0,超出这个时间鼠标还不能进行正常数据通信,鼠标则要进入休眠模式,直到用户唤醒鼠标。

假如dongle设定的最长配对时间T1为5秒,则保证T1大于T0,量化下来T0 = T1 +1秒。

6.3 数据格式

6.3.1 通信包

键盘发送的2.4G帧格式如下

前导码

接入地址

signal

payload

crc

3B

4B

10bit

24B

2B

0x550f71

固定的

增强型的字段

跳频对码包/键盘数据包

16bit crc

其中鼠标Payload为用户可以修改的数据段,Payload中又包含了3个字节的固定数据,其中3个字节的固定数据格式如下

Type

Addr

1B

2B

包的类型:对码跳频包/鼠标包

己端MAC地址后两个字节

Type定义如下

#define PRF_PKT_TYPE_PAIR               (1 << 0)
#define PRF_PKT_TYPE_FREQ_HOP           (1 << 1)
#define PRF_PKT_TYPE_KEYBOARD_DATA      (1 << 2)
#define PRF_PKT_TYPE_LED_STATUS         (1 << 3)

跳频对码包:

header: PRF_PKT_TYPE_FREQ_HOP | PRF_PKT_TYPE_PAIR

跳频包:

header: PRF_PKT_TYPE_FREQ_HOP

数据包:

header: PRF_PKT_TYPE_KEYBOARD_DATA

键盘LED状态包:

header: PRF_PKT_TYPE_LED_STATUS

键盘LED状态包用于2.4G dongle端回发CAPS LOCK/NUM LOCK/SCROLL LOCK状态

另外包含21个字节应用层数据(ringbuf管理的数据结构)

key_type

key_value

header

sequence

rate_pkt_index

reserved

1B

16B

1B

1B

1B

1B

键值类型

按键值

包头

序列号

上报率

保留扩展位

#define KEYBOARD_KEY_SIZE               16

struct keyboard_pkt_detect_t {
	uint8_t sequence;
	uint8_t header;
	key_type_s key_type;
	uint8_t key_value[KEYBOARD_KEY_SIZE];
	uint8_t rate_pkt_index;
	uint8_t reserved;
} __packed;

键盘接收的2.4G ACK数据帧格式如下

前导码

接入地址

signal

payload

crc

3B

5B

10bit

xB

2B

0x550f71

固定的

增强

ACK数据(长度自定义,默认数据长度为0)

16bit crc

用户可以根据需求扩展使用ACK数据

dongle回传LED状态信息数据帧格式如下

前导码

接入地址

signal

payload[0]

payload[1]

crc

3B

4B

10bit

1B

1B

2B

0x550f71

公共地址/私有地址

增强

LED指示灯类型

LED指示灯值

16bit crc

6.4 操作说明

PAN2628dongle配套的固件及烧录工具说明可以从05_TOOLS\MouseSupportTool\PAN2628Dongle获取烧录

PAN2628源码部分可以联系我司获取

6.4.1 1080键盘代码宏定义键鼠套件 鼠标/键盘 说明

#define KB_MOUSE_ONEDONLE						0
#if KB_MOUSE_ONEDONLE
#define PAIR_MAGIC                                 0x31415926

struct pkt_pair_t {
	uint32_t magic;
	uint8_t cmd;
	uint8_t mac[6];
} __packed;

struct pkt_pair_ack_t {
	uint32_t magic;
	uint8_t cmd;
	uint8_t mac[6];
} __packed;

#define PRF_PUBLIC_ADDR                         { 0x7c, 0x41, 0x29, 0x79 }
#else
#define PRF_PUBLIC_ADDR                         { 0x7b, 0x41, 0x29, 0x71 }
#endif

KB_MOUSE_ONEDONLE:

  • 默认值为0代表原始单键盘套件,配对逻辑未修改,使用默认配对地址{ 0x7b, 0x41, 0x29, 0x71 }

  • 设置为1代表 键鼠套件125hz鼠标,配对逻辑已更新(可以通过此宏定义查看配对逻辑差异),使用默认配对地址{ 0x7c, 0x41, 0x29, 0x79 }

6.4.2 操作步骤

  1. 准备好2628dongle固件,烧录工程combo_usb_dongle固件,具有mac地址的使用MAC地址完成配对,否则使用默认值进行配对。

  2. 准备2块鼠标板,一块烧录 键鼠套件鼠标A,一块烧录 键鼠套件键盘B

  3. A和B同时进入配对快闪状态,复位dongle,观察AB灯效

  4. A快闪结束,进入断连状态,之后切换为呼吸灯效,B快闪结束,指示灯常亮

  5. A可以设置为自动画圈状态,同时发送B按键数据

7 补充说明

补充说明当前功耗测试情况,支持中遇到的问题(供参考)及已知仍可能存在的问题

7.1 功耗说明

LED开启的情况下,电流跟具体灯效有关,所以测试时默认关闭LED,按FN + 空格 打开/关闭LED

模式

全速上报(1000Hz )mA

无按键触发60s(休眠 deepsleep) uA

dongle未插入(休眠 standby) uA

2.4G

8.25

36.56

28.37

模式

全速上报(133Hz )mA

一级休眠(30S关灯后)mA

无按键10分钟(休眠 deepsleep) uA

BLE

5.1

跟设置的latency大小有关

38.27

7.2 已知问题

No

已知问题

目前状态

1

休眠模式下切换模式过快需要按键唤醒

由于键盘处于休眠状态,切换模式本应该经过断电状态,但如果切换过快,休眠状态放电不充分,芯片不能完全断电复位,仍处于休眠状态,此时唤醒可以恢复对应模式的正常运行状态

8 RAM/Flash资源使用情况

FLASH部分包含蓝牙controller固定资源120K,不包含初始位置开始的60K MCUBOOT程序

Memory region         Used Size  Region Size  %age Used
FLASH:      117692 B       384 KB     29.93%
SRAM:       42466 B        50 KB     82.94%