2.4.5. 单模鼠标

  • 标准的蓝牙BLE鼠标

  • 蓝牙鼠标支持 windows 系统,mac 系统、安卓系统、ios 系统连接。

2.4.5.1. 单模鼠标case使用

  • 使用快捷键Alt + g 打开app_config.h,配置CONFIG_APP_MOUSE_SINGLE使能

//app case 选择,只选1,要配置对应的board_config.h
#define CONFIG_APP_MOUSE_SINGLE        1//单模切换 需搭配CONFIG_BOARD_AW313A_MOUSE板级
  • 使用快捷键Alt + g 打开board_config.h,板级选择CONFIG_BOARD_AW313A_MOUSE

 // #define CONFIG_BOARD_AW31N_DEMO
// #define CONFIG_BOARD_AW31A_RC
#define CONFIG_BOARD_AW313A_MOUSE
  • 按照 :HID DEMO说明 编译下载代码、接线(接线参考下列)、复位设备,再使用手机搜索设备进行连接。

    KEY: key接线需要打开”board_aw313a_mouse_cfg.h”查看IO key接线。

    //*********************************************************************************//
    //                                 iokey 配置                                      //
    //*********************************************************************************//
    #define KEY_IO_EN                                 ENABLE                  //<IO按键使能
    #define MOUSE_KEY_SCAN_MODE                 ENABLE_THIS_MOUDLE
    
    #define KEY_LK_VAL          BIT(0)   //1
    #define KEY_RK_VAL          BIT(1)   //2
    #define KEY_HK_VAL          BIT(2)   //4
    #define KEY_FB_VAL          BIT(3)   //8
    #define KEY_BB_VAL          BIT(4)  //16
    #define KEY_CPI_VAL         BIT(5)  //32
    
    #define KEY_LK_RK_VAL       (KEY_LK_VAL | KEY_RK_VAL)             //3
    #define KEY_LK_HK_VAL       (KEY_LK_VAL | KEY_HK_VAL)             //5
    #define KEY_RK_HK_VAL       (KEY_RK_VAL | KEY_HK_VAL)             //6
    #define KEY_LK_RK_HK_VAL    (KEY_LK_VAL | KEY_RK_VAL | KEY_HK_VAL)//7
    
    #define TCFG_IOKEY_MOUSE_LK_PORT                      IO_PORTA_11
    #define TCFG_IOKEY_MOUSE_RK_PORT                      IO_PORTA_08
    #define TCFG_IOKEY_MOUSE_HK_PORT                      IO_PORTA_10
    #define TCFG_IOKEY_MOUSE_CPI_PORT                     IO_PORTA_09
    

    code switch: 打开”board_aw313a_mouse_cfg.h”查看编码开关接线

    //*********************************************************************************//
    //                                  code switch配置                                //
    //*********************************************************************************//
    #define TCFG_CODE_SWITCH_ENABLE                   ENABLE_THIS_MOUDLE
    #define TCFG_CODE_SWITCH_A_PHASE_PORT             IO_PORTA_07
    #define TCFG_CODE_SWITCH_B_PHASE_PORT             IO_PORTA_06
    

    optical mouse sensor: 打开”board_aw313a_mouse_cfg.h”查看鼠标位移传感器接线

    //*********************************************************************************//
    //                                  optical mouse sensor配置                       //
    //*********************************************************************************//
    #define TCFG_OMSENSOR_ENABLE
    #define TCFG_HAL3205_EN                           ENABLE
    
    #define TCFG_OPTICAL_SENSOR_SCLK_PORT             IO_PORTA_04
    #define TCFG_OPTICAL_SENSOR_DATA_PORT             IO_PORTA_05
    #define TCFG_OPTICAL_SENSOR_INT_PORT              IO_PORTA_02
    
    #define OPTICAL_SENSOR_SAMPLE_PERIOD              3 //ms
    
  • 开发者可以准备好相应硬件并进行连接进行调试。(demo默认使用AW313鼠标demo板进行开发使用,上电后长按左键+右键两秒开启广播既可进行连接配对)

2.4.5.2. 主要代码说明

  • 支持进入软关机,可用 IO 触发唤醒(board_aw313a_mouse.c)

/************************** SOFTOFF IO PROTECT****************************/
void gpio_config_soft_poweroff(void)
{
    PORT_TABLE(g);
#if KEY_IO_EN
    PORT_PROTECT(TCFG_IOKEY_MOUSE_LK_PORT);
    PORT_PROTECT(TCFG_IOKEY_MOUSE_RK_PORT);
    PORT_PROTECT(TCFG_IOKEY_MOUSE_HK_PORT);
    PORT_PROTECT(TCFG_IOKEY_MOUSE_CPI_PORT);
#endif

#ifdef TCFG_OMSENSOR_ENABLE
    PORT_PROTECT(TCFG_OPTICAL_SENSOR_SCLK_PORT);
    PORT_PROTECT(TCFG_OPTICAL_SENSOR_DATA_PORT);
#endif
    __port_init((u32)gpio_config);
}
/************************** SOFTOFF IO PROTECT****************************/
  • 定时发送数据函数(app_mouse.c)

/*************************************************************************************************/
/*!
*  \brief     鼠标发数函数
*
*  \param      [in]
*
*  \return
*
*  \note
*/
/*************************************************************************************************/
static void mouse_timer_handler(void *priv)
{
    if (!mouse_info.mouse_is_paired) {
        return;
    }

    if (mouse_flag.button_send_flag == 0 || mouse_flag.wheel_send_flag == 0) {
        log_info_hexdump((uint8_t *)&mouse_first_packet.data, sizeof(mouse_first_packet.data));
        ble_hid_data_send(1, (uint8_t *)&mouse_first_packet.data, sizeof(mouse_first_packet.data));

        if (mouse_flag.button_send_flag == 0) {
            mouse_flag.button_send_flag = 1;
        }

        if (mouse_flag.wheel_send_flag == 0) {
            mouse_flag.wheel_send_flag = 1;
            mouse_first_packet.data[WHEEL_IDX] = 0;
        }
    }

    if (mouse_flag.sensor_send_flag == 0) {
        /* log_info_hexdump((uint8_t *)&mouse_second_packet.data, sizeof(mouse_second_packet.data)); */
        ble_hid_data_send(2, (uint8_t *)&mouse_second_packet.data, sizeof(mouse_second_packet.data));
        memset((void *)&mouse_second_packet.data, 0, sizeof(mouse_second_packet.data));
        mouse_flag.sensor_send_flag = 1;
    }
}
  • mouse sensor数据更新函数(app_mouse.c)

  /*************************************************************************************************/
/*!
*  \brief      更新gsensor位置
*
*  \param      [in] event:事件 x:x轴值 y:y轴值
*
*  \return
*
*  \note
*/
/*************************************************************************************************/
void mouse_optical_sensor_event(uint8_t event, s16 x, s16 y)
{
    static s16 delta_x = 0, delta_y = 0;
    if (mouse_flag.sensor_send_flag) {
        delta_x = 0;
        delta_y = 0;
    }

    if (event == 0) {
        if (((delta_x + x) >= -2047) && ((delta_x + x) <= 2047)) {
        } else {
            x = 0;
        }

        if (((delta_y + y) >= -2047) && ((delta_y + y) <= 2047)) {
        } else {
            y = 0;
        }

        //坐标调整
        delta_x += (-y);
        delta_y += (x);

        mouse_second_packet.data[SENSOR_XLSB_IDX] = delta_x & 0xFF;
        mouse_second_packet.data[SENSOR_YLSB_XMSB_IDX] = ((delta_y << 4) & 0xF0) | ((delta_x >> 8) & 0x0F);
        mouse_second_packet.data[SENSOR_YMSB_IDX] = (delta_y >> 4) & 0xFF;

        /* log_info("x = %d.\ty = %d.\n", event->u.axis.x, event->u.axis.y); */
    }
    mouse_flag.sensor_send_flag = 0;
}
  • mouse 滚轮数据更新函数(app_mouse.c)

/*************************************************************************************************/
/*!
*  \brief      更新鼠标滚轮器值
*
*  \param      [in] event:code_sw事件
*
*  \return
*
*  \note
*/
/*************************************************************************************************/
static void mouse_code_sw_event_handler(struct sys_event *event)
{
    static s8 sw_val = 0;

    if (mouse_flag.wheel_send_flag) {
        sw_val = 0;
    }

    if (event->u.codesw.event == 0) {
        sw_val += event->u.codesw.value;
        mouse_first_packet.data[WHEEL_IDX] = -sw_val;
    }

    mouse_flag.wheel_send_flag = 0;
}
  • mouse 按键控制函数(app_mouse.c)

static void mouse_key_event_handler(struct sys_event *event)
{
    if (event->arg == (void *)DEVICE_EVENT_FROM_KEY) {
        log_info("key_value = %d.\tevent_type = %d.\n", event->u.key.value, event->u.key.event);

        uint8_t event_type = event->u.key.event;

        // cpi选择
        if (event->u.key.value == KEY_CPI_VAL && event_type == KEY_EVENT_LONG) {
            mouse_cpi_mode++;
            if (mouse_cpi_mode >= (sizeof(mouse_cpi_value_table) / sizeof(uint16_t))) {
                mouse_cpi_mode = 0;
            }
#ifdef TCFG_OMSENSOR_ENABLE
            optical_mouse_sensor_set_cpi(mouse_cpi_value_table[mouse_cpi_mode]);
#endif
            return;
        }

        // left+right键, 长按数秒进入
#if (DOUBLE_KEY_HOLD_PAIR)
        if (3 == event->u.key.value && event_type == KEY_EVENT_LONG) {
            log_info("pair_start:double key6 hold:%d", mouse_double_key_long_cnt);
            if (++mouse_double_key_long_cnt >= DOUBLE_KEY_HOLD_CNT) {
                mouse_bt_pair_start();
                mouse_double_key_long_cnt = 0;
#if TEST_MOUSE_SIMULATION_ENABLE
                mouse_test_ctrl();
#endif
            }
            return;
        } else {
            mouse_double_key_long_cnt = 0;
        }
#endif

        mouse_first_packet.data[BUTTONS_IDX] = 0;
        if (event_type == KEY_EVENT_CLICK || \
            event_type == KEY_EVENT_LONG || \
            event_type == KEY_EVENT_HOLD) {
            mouse_first_packet.data[BUTTONS_IDX] |= event->u.key.value;
        }
    }

    if (mouse_flag.button_send_flag) {
        mouse_flag.button_send_flag = 0;
    }
}

2.4.5.3. case默认应用资源(默认使用AW313鼠标demo板)

Note

demo默认占用外设资源如下,具体可以查看board_aw313a_mouse_cfg.h

I/O口占用情况

PA口 I/O

默认占用情况

IODP

默认打印UART0引脚

PA2

mouse sensor唤醒口

PA4

mouse sensor iic scl口

PA5

mouse sensor iic sda口

PA6

TCFG_CODE_SWITCH_B_PHASE_PORT

PA7

TCFG_CODE_SWITCH_A_PHASE_PORT

PA8

TCFG_IOKEY_MOUSE_RK_PORT

PA9

TCFG_IOKEY_MOUSE_CPI_PORT

PA10

TCFG_IOKEY_MOUSE_HK_PORT

PA11

TCFG_IOKEY_MOUSE_LK_PORT

硬件定时器占用情况

定时器

默认占用情况

TIMER0

暂无使用

TIMER1

用作mouse sensor采集数据

TIMER2

暂无使用

TIMER3

暂无使用

串口占用情况

串口

默认占用情况

UART0

SDK打印

UART1

暂无使用

UART2

暂无使用

2.4.5.4. case默认应用功能现象

(默认使用AW313鼠标demo板)

操作

左键+右键长按2s,进入配对模式

左,中、右键

DPI切换键

滑轮

鼠标移动回包率最高到133

鼠标连续使用时是否稳定工作