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

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 单载波模式

4.5 USB升级(DFU)

USB DFU 升级操作可以参考 05_TOOLS\量产烧录工具\Panchip DFU Tool 最新版本的帮助内容内的操作说明,以下说明升级需要注意的点及原理

关于boot的文档可以参考https://docs.panchip.com/pan1080dk-doc/latest/docs-zdk/04_dev_guides/zephyr_bootloader_guidance.html

4.5.1 升级原理

SDK 1.0.2 之前的版本,升级通过App程序区的USB EP3端点进行消息交互,联同上位机进行升级流程,可以升级鼠标和dongle程序,但是需要注意识别过程需要正确写入芯片VID PID扫描到已有设备,为保证升级兼容性,rebuild编译后的工程强烈建议app区和controller区同时升级,并且进行app升级进行controller升级

SDK 1.0.2 包括之后的版本,灵活开放了boot区的编译,并默认提供了一种方式,程序区先写入flash flag确保进入强制升级,未退出强制升级之前,芯片重新上电始终会停留在boot区域,确认好固件正确性后可以退出强制升级

SDK 1.1.0 包括之后的版本,编译了两种特殊mcuboot固件(存放于01_SDK\modules\hal\panchip\panplat\pan1080\bootloader),支持boot内DFU升级

  1. bootdfu_for_mouse:支持xxa1编译所有鼠标工程及键盘dongle工程,支持boot内usb升级,支持boot内4k dongle或者8k鼠标的spi透传升级

  2. bootdfu_for_keyboard:支持xxb1编译的keyboard工程,支持boot内usb升级

通过应用层宏CONFIG_MCUBOOT_IMAGE_TYPE可以直接控制编译链接的特殊mcuboot固件,值对应上述固件类型

4.5.2 boot自定义编译说明

如果需要自定义更新mcuboot固件,需要注意以下对应关系,建议操作步骤如下

编译mcuboot,注意控制好相关的宏(CONFIG_MCUBOOT_PAN_USB_DFU或者CONFIG_MCUBOOT_PAN_USB_SPI)开启及编译board的选择

以自定义编译键盘固件为例

ZAL工具编译mcuboot工程,编译board选择xxb1,提前修改01_SDK\bootloader\mcuboot\boot\zephyr\prj,conf内的宏,之后进行编译,编译后的mcuboot固件会自动替换原有的默认mcuboot固件(不包含任何升级功能)01_SDK\modules\hal\panchip\panplat\pan1080\bootloader\images

此时如果需要使用此编译固件,可以将APP工程内的CONFIG_MCUBOOT_IMAGE_TYPE宏屏蔽,使用默认的值即会使用被替换掉的mcuboot(也可以灵活处理保存到特殊文件夹通过扩展宏自己控制)

4.5.3 注意事项

使用具有保护功能的boot时,boot的VID为0x046D,PID为0xC055,usb name 为 boot dfu

通过上位机工具量产烧录工具\Panchip DFU Tool升级时,可以参考工具内文档说明的步骤进行升级,注意选择支持强制升级的版本

PS

​ 程序run在boot区时,点击重启芯片可以跳转到app区域,程序升级正常之前,重新上电即可继续升级正确固件

4.6 DeviceTool使用

配合上位机工具键鼠专用工具\PAN108x工具\MouseDeviceTool可以进行产线USB信息测试及单载波测试,具体操作可以参考工具内说明文档

默认界面支持自定义消息开发

显示界面可以切换到USB设置测试功能界面

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
        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
        # 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

跳频逻辑

5.6 键鼠套件(附)

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

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

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

#define KB_MOUSE_ONEDONLE                          1

5.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接收的数据认为是小键盘数据

5.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

套件配对逻辑

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

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

5.6.2 数据通信过程

5.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字节的地址作为通信地址

5.6.2.2 跳频通道

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

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

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

5.6.2.4 超时时间

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

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

5.6.3 数据格式

5.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

5.6.4 操作说明

PAN2628dongle配套的固件及烧录工具说明可以从05_TOOLS\键鼠专用工具\第三方工具\PAN2628固件工具获取烧录

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

5.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 }

5.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按键数据

6 补充说明

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

6.1 功耗说明

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

2.4G功耗

模式

全速上报(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

6.2 蓝牙启动时间说明

2.4G和蓝牙启动需要对controller进行初始化,controller初始化时间可以由log观测,目前测试启动时间为66ms

6.3 已知问题

No

已知问题

目前状态

1

休眠模式下切换模式过快需要复位

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

7 RAM/Flash资源使用情况

FLASH部分包含蓝牙controller固定资源120K,不包含初始位置开始的60K MCUBOOT程序,FLASH资源由于mcuboot内已支持升级功能,实际可用大小可以扩展384K

Memory region

Used Size

Region Size

%age Used

FLASH

119504 B

384 KB

30.39%

SRAM

43218 B

50 KB

84.41%