diff --git a/hi-sle/Autodesk_Fusion_360_Designs/remote_controller_model.dxf b/hi-sle/Autodesk_Fusion_360_Designs/remote_controller_model.dxf
new file mode 100644
index 0000000000000000000000000000000000000000..a33403a3e742340713ed05d755acb08a66ae0c29
--- /dev/null
+++ b/hi-sle/Autodesk_Fusion_360_Designs/remote_controller_model.dxf
@@ -0,0 +1,620 @@
+0
+SECTION
+2
+HEADER
+9
+$INSUNITS
+70
+4
+9
+$ACADVER
+1
+AC1014
+9
+$HANDSEED
+5
+FFFF
+0
+ENDSEC
+0
+SECTION
+2
+TABLES
+0
+TABLE
+2
+VPORT
+5
+8
+100
+AcDbSymbolTable
+0
+ENDTAB
+0
+TABLE
+2
+LTYPE
+5
+5
+100
+AcDbSymbolTable
+0
+LTYPE
+5
+14
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+2
+BYBLOCK
+70
+0
+0
+LTYPE
+5
+15
+100
+AcDbSymbolTableRecord
+100
+AcDbLinetypeTableRecord
+2
+BYLAYER
+70
+0
+0
+ENDTAB
+0
+TABLE
+2
+LAYER
+5
+2
+100
+AcDbSymbolTable
+70
+2
+0
+LAYER
+5
+50
+100
+AcDbSymbolTableRecord
+100
+AcDbLayerTableRecord
+2
+0
+70
+0
+6
+CONTINUOUS
+0
+ENDTAB
+0
+TABLE
+2
+STYLE
+5
+3
+100
+AcDbSymbolTable
+70
+1
+0
+STYLE
+5
+11
+100
+AcDbSymbolTableRecord
+100
+AcDbTextStyleTableRecord
+2
+STANDARD
+70
+0
+0
+ENDTAB
+0
+TABLE
+2
+VIEW
+5
+6
+100
+AcDbSymbolTable
+70
+0
+0
+ENDTAB
+0
+TABLE
+2
+UCS
+5
+7
+100
+AcDbSymbolTable
+70
+0
+0
+ENDTAB
+0
+TABLE
+2
+APPID
+5
+9
+100
+AcDbSymbolTable
+70
+2
+0
+APPID
+5
+12
+100
+AcDbSymbolTableRecord
+100
+AcDbRegAppTableRecord
+2
+ACAD
+70
+0
+0
+ENDTAB
+0
+TABLE
+2
+DIMSTYLE
+5
+A
+100
+AcDbSymbolTable
+70
+1
+0
+ENDTAB
+0
+TABLE
+2
+BLOCK_RECORD
+5
+1
+100
+AcDbSymbolTable
+70
+1
+0
+BLOCK_RECORD
+5
+1F
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+2
+*MODEL_SPACE
+0
+BLOCK_RECORD
+5
+1B
+100
+AcDbSymbolTableRecord
+100
+AcDbBlockTableRecord
+2
+*PAPER_SPACE
+0
+ENDTAB
+0
+ENDSEC
+0
+SECTION
+2
+BLOCKS
+0
+BLOCK
+5
+20
+100
+AcDbEntity
+100
+AcDbBlockBegin
+2
+*MODEL_SPACE
+0
+ENDBLK
+5
+21
+100
+AcDbEntity
+100
+AcDbBlockEnd
+0
+BLOCK
+5
+1C
+100
+AcDbEntity
+100
+AcDbBlockBegin
+2
+*PAPER_SPACE
+0
+ENDBLK
+5
+1D
+100
+AcDbEntity
+100
+AcDbBlockEnd
+0
+ENDSEC
+0
+SECTION
+2
+ENTITIES
+0
+LWPOLYLINE
+5
+100
+100
+AcDbEntity
+8
+0
+100
+AcDbPolyline
+90
+22
+70
+1
+43
+0.0
+10
+40.442226373456592
+20
+23.95073538178648
+42
+0.24171376600242628
+10
+40.024999636689998
+20
+23.138100578409038
+10
+40.024999636689998
+20
+0.37502041741000852
+42
+-0.4142135623730947
+10
+37.824999636690002
+20
+-1.8249795825899942
+10
+-37.824999636692013
+20
+-1.8249795825899922
+42
+-0.4142135623730952
+10
+-40.024999636692009
+20
+0.37502041741000669
+10
+-40.024999636692009
+20
+23.138100578406899
+42
+0.24171376600254765
+10
+-40.442226373458965
+20
+23.9507353817846
+42
+-0.084684859904792825
+10
+-42.100439826245264
+20
+25.627979904149804
+10
+-44.92037124742847
+20
+29.656453362980379
+42
+0.24473544024323177
+10
+-50.64458978696301
+20
+32.636799593589998
+10
+-75.936979930133006
+20
+32.63679959359137
+42
+0.49013302976303491
+10
+-89.482166728216001
+20
+15.160587172
+10
+-80.854252072462955
+20
+-18.336016840902005
+42
+0.34216204865823896
+10
+-61.498714761561999
+20
+-33.337800355600997
+10
+61.498717300760021
+20
+-33.337800355600315
+42
+0.34216204865820105
+10
+80.854252072257879
+20
+-18.336016841682451
+10
+89.482166728211098
+20
+15.160587171999715
+42
+0.49013302976299639
+10
+75.936979930129993
+20
+32.636799593589998
+10
+50.644589786960012
+20
+32.636799593595896
+42
+0.24473544024342697
+10
+44.920371247420007
+20
+29.656453362979999
+10
+42.100439826240276
+20
+25.627979904149814
+42
+-0.084684859904677542
+0
+CIRCLE
+5
+101
+100
+AcDbEntity
+8
+0
+100
+AcDbCircle
+10
+80.000010160020011
+20
+22.855326390649999
+30
+0
+40
+1.5000000000000036
+210
+0
+220
+0
+230
+1
+0
+CIRCLE
+5
+102
+100
+AcDbEntity
+8
+0
+100
+AcDbCircle
+10
+-80.000010160020011
+20
+22.855326390649999
+30
+0
+40
+1.5000000000000036
+210
+0
+220
+0
+230
+1
+0
+CIRCLE
+5
+103
+100
+AcDbEntity
+8
+0
+100
+AcDbCircle
+10
+63.000000000000007
+20
+-25.144673609347002
+30
+0
+40
+1.5000000000000036
+210
+0
+220
+0
+230
+1
+0
+CIRCLE
+5
+104
+100
+AcDbEntity
+8
+0
+100
+AcDbCircle
+10
+-63.000000000000007
+20
+-25.144673609347002
+30
+0
+40
+1.4999999999999947
+210
+0
+220
+0
+230
+1
+0
+CIRCLE
+5
+105
+100
+AcDbEntity
+8
+0
+100
+AcDbCircle
+10
+36.000071120139999
+20
+-11.99997279214376
+30
+0
+40
+6.4999999999999991
+210
+0
+220
+0
+230
+1
+0
+CIRCLE
+5
+106
+100
+AcDbEntity
+8
+0
+100
+AcDbCircle
+10
+-58.800131691628003
+20
+4.2000235642760009
+30
+0
+40
+14.500000000000002
+210
+0
+220
+0
+230
+1
+0
+CIRCLE
+5
+107
+100
+AcDbEntity
+8
+0
+100
+AcDbCircle
+10
+61.200107068841007
+20
+4.2000235642760009
+30
+0
+40
+14.500000000000002
+210
+0
+220
+0
+230
+1
+0
+CIRCLE
+5
+108
+100
+AcDbEntity
+8
+0
+100
+AcDbCircle
+10
+-36.000071120142003
+20
+-11.99997279214376
+30
+0
+40
+6.4999999999999991
+210
+0
+220
+0
+230
+1
+0
+ENDSEC
+0
+SECTION
+2
+OBJECTS
+0
+DICTIONARY
+5
+C
+100
+AcDbDictionary
+3
+ACAD_GROUP
+350
+D
+3
+ACAD_MLINESTYLE
+350
+17
+0
+DICTIONARY
+5
+D
+100
+AcDbDictionary
+0
+DICTIONARY
+5
+1A
+330
+C
+100
+AcDbDictionary
+0
+DICTIONARY
+5
+17
+100
+AcDbDictionary
+0
+ENDSEC
+0
+EOF
diff --git a/hi-sle/Autodesk_Fusion_360_Designs/remote_controller_model.f3d b/hi-sle/Autodesk_Fusion_360_Designs/remote_controller_model.f3d
new file mode 100644
index 0000000000000000000000000000000000000000..1eb17c6f1ccabac51695e83db41e15c179fcf0c5
Binary files /dev/null and b/hi-sle/Autodesk_Fusion_360_Designs/remote_controller_model.f3d differ
diff --git a/hi-sle/Bill_of_Materials/material_description.txt b/hi-sle/Bill_of_Materials/material_description.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1921d8582f828f4e6c04bf0505880e44db02b5b2
--- /dev/null
+++ b/hi-sle/Bill_of_Materials/material_description.txt
@@ -0,0 +1,8 @@
+【开源之夏】
+1. 摇杆帽:用于摇杆操控
+2. 亚克力板:用于遥控器整体面板(eulercarboard.dxf轮廓文件)
+3. 焊锡膏:用于贴片原件焊料
+4. 704硅橡胶用于PCB电池盒固定
+5. 18650:用于遥控板供电
+6. PCB:用于遥控板整体电路
+7. PCB电子元器件套件:PCB电路BOM表(BOM_Board1_EulerCar.xlsx)所有电子元器件
diff --git a/hi-sle/Bill_of_Materials/material_purchase.xlsx b/hi-sle/Bill_of_Materials/material_purchase.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..cdcea3817b64bc31734437619024c21f3dbf51ce
Binary files /dev/null and b/hi-sle/Bill_of_Materials/material_purchase.xlsx differ
diff --git a/hi-sle/EulerCar_Host_Computer_EulerPi_Source_Code/ws63_ws73_ros2.c b/hi-sle/EulerCar_Host_Computer_EulerPi_Source_Code/ws63_ws73_ros2.c
new file mode 100644
index 0000000000000000000000000000000000000000..b604659df3f93caaf70472c0997461d5f7e19a93
--- /dev/null
+++ b/hi-sle/EulerCar_Host_Computer_EulerPi_Source_Code/ws63_ws73_ros2.c
@@ -0,0 +1,954 @@
+/**
+ * Copyright (c) @CompanyNameMagicTag 2022. All rights reserved.
+ *
+ * Description: SLE private service register sample of client.
+ */
+#include "securec.h"
+#include "sle_device_discovery.h"
+#include "sle_connection_manager.h"
+#include "sle_ssap_client.h"
+#include "sle_uuid_client.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#undef THIS_FILE_ID
+#define THIS_FILE_ID BTH_GLE_SAMPLE_UUID_CLIENT
+
+// 定义日志前缀
+#define SLE_RCU_DONGLE_LOG "[sle ws73]"
+
+// 定义默认MTU大小
+#define SLE_MTU_SIZE_DEFAULT 300
+
+// 定义默认查找间隔
+#define SLE_SEEK_INTERVAL_DEFAULT 100
+
+// 定义默认查找窗口
+#define SLE_SEEK_WINDOW_DEFAULT 100
+
+// 定义16位UUID长度
+#define UUID_16BIT_LEN 2
+
+// 定义128位UUID长度
+#define UUID_128BIT_LEN 16
+
+// 定义键码和键值的全局变量
+char key_code = 0;
+char key_value = 0;
+
+// 定义全局回调结构体
+sle_announce_seek_callbacks_t g_seek_cbk = {0};
+sle_connection_callbacks_t g_connect_cbk = {0};
+ssapc_callbacks_t g_ssapc_cbk = {0};
+
+// 定义全局远程地址结构体
+sle_addr_t g_remote_addr = {0};
+
+// 定义全局连接ID
+uint16_t g_conn_id = 0;
+
+// 定义全局查找服务结果结构体
+ssapc_find_service_result_t g_find_service_result = {0};
+
+// 定义测试套件UART发送函数的宏
+#define test_suite_uart_sendf(fmt, arg...) NULL
+
+// 定义SLE客户端地址
+#define CONFIG_SLE_MULTICON_CLIENT_ADDR0 0xb0
+#define CONFIG_SLE_MULTICON_CLIENT_ADDR1 0x66
+#define CONFIG_SLE_MULTICON_CLIENT_ADDR2 0x00
+#define CONFIG_SLE_MULTICON_CLIENT_ADDR3 0x00
+#define CONFIG_SLE_MULTICON_CLIENT_ADDR4 0x7A
+#define CONFIG_SLE_MULTICON_CLIENT_ADDR5 0x00
+
+// 定义USB RCU报告长度
+#define USB_RCU_KEYBOARD_REPORTER_LEN 9
+#define USB_RCU_MOUSE_REPORTER_LEN 5
+#define USB_RCU_CONSUMER_REPORTER_LEN 3
+
+// 定义USB HID RCU最大按键长度
+#define USB_HID_RCU_MAX_KEY_LENTH 6
+typedef struct usb_hid_rcu_keyboard_report
+{
+ uint8_t kind;
+ uint8_t special_key; /*!< 8bit special key(Lctrl Lshift Lalt Lgui Rctrl Rshift Ralt Rgui) */
+ uint8_t reserve;
+ uint8_t key[USB_HID_RCU_MAX_KEY_LENTH]; /*!< Normal key */
+} usb_hid_rcu_keyboard_report_t;
+
+void send_data(int fd, char *data)
+{
+ int bytes_written = write(fd, data, strlen(data));
+ if (bytes_written == -1)
+ {
+ perror("Error occurred while writing data to the serial port");
+ }
+ else
+ {
+ printf("Write %d bytes of data success : %s\n", bytes_written, data);
+ }
+}
+
+int send_data_to_serial(char *data)
+{
+ char *serial_port = "/dev/ttyAMA3";
+ speed_t baud_rate = B9600;
+
+ int fd = open(serial_port, O_RDWR | O_NOCTTY);
+ if (fd == -1)
+ {
+ perror("Open serial port fail\n");
+ return -1;
+ }
+
+ struct termios options;
+ if (tcgetattr(fd, &options) != 0)
+ {
+ perror("Error from tcgetattr");
+ close(fd);
+ return -1;
+ }
+
+ // Set baud rate
+ cfsetispeed(&options, baud_rate);
+ cfsetospeed(&options, baud_rate);
+
+ // Set serial port parameters
+ options.c_cflag |= (CLOCAL | CREAD);
+ options.c_cflag &= ~PARENB;
+ options.c_cflag &= ~CSTOPB;
+ options.c_cflag &= ~CSIZE;
+ options.c_cflag |= CS8;
+
+ options.c_iflag &= ~(INPCK | ISTRIP);
+ options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
+ options.c_oflag &= ~OPOST;
+
+ tcflush(fd, TCIFLUSH);
+ // Apply settings
+ if (tcsetattr(fd, TCSANOW, &options) != 0)
+ {
+ perror("Error from tcsetattr");
+ close(fd);
+ return -1;
+ }
+ send_data(fd, data);
+
+ close(fd);
+ return 0;
+}
+
+/**
+ * @brief SLE启用回调函数
+ *
+ * 该函数在SLE启用时被调用。它设置本地地址并启动扫描。
+ *
+ * @param status 启用SLE的状态码。0表示成功,非0表示失败。
+ */
+void sle_sample_sle_enable_cbk(errcode_t status)
+{
+ errcode_t ret; // 定义返回值变量
+ uint8_t local_addr[SLE_ADDR_LEN] = {CONFIG_SLE_MULTICON_CLIENT_ADDR0, CONFIG_SLE_MULTICON_CLIENT_ADDR1,
+ CONFIG_SLE_MULTICON_CLIENT_ADDR2, CONFIG_SLE_MULTICON_CLIENT_ADDR3,
+ CONFIG_SLE_MULTICON_CLIENT_ADDR4, CONFIG_SLE_MULTICON_CLIENT_ADDR5}; // 定义本地地址数组
+ sle_addr_t local_address; // 定义本地地址结构体
+ local_address.type = 0; // 设置地址类型为0
+ memcpy_s(local_address.addr, SLE_ADDR_LEN, local_addr, SLE_ADDR_LEN); // 将本地地址数组复制到地址结构体中
+
+ if (status == 0) // 如果SLE启用成功
+ {
+ ret = sle_set_local_addr(&local_address); // 设置本地地址
+ printf("sle_set_local_addr %d\n", ret); // 打印设置本地地址的结果
+ sle_start_scan(); // 启动扫描
+ }
+}
+
+void sle_sample_seek_enable_cbk(errcode_t status)
+{
+ if (status == 0)
+ {
+ return;
+ }
+}
+
+void sle_sample_seek_disable_cbk(errcode_t status)
+{
+ if (status == 0)
+ {
+ sle_connect_remote_device(&g_remote_addr);
+ }
+}
+
+/**
+ * @brief SLE查找结果信息回调函数
+ *
+ * 该函数在SLE查找过程中被调用,用于处理查找结果。当查找结果不为空时,
+ * 将查找到的设备地址复制到全局变量 `g_remote_addr` 中,并停止查找过程。
+ *
+ * @param seek_result_data 指向查找结果信息结构体的指针
+ */
+void sle_sample_seek_result_info_cbk(sle_seek_result_info_t *seek_result_data)
+{
+ // 检查查找结果是否不为空
+ if (seek_result_data != NULL)
+ {
+ // 将查找到的设备地址复制到全局变量 g_remote_addr 中
+ (void)memcpy_s(&g_remote_addr, sizeof(sle_addr_t), &seek_result_data->addr, sizeof(sle_addr_t));
+
+ // 停止查找过程
+ sle_stop_seek();
+ }
+}
+
+/**
+ * @brief 注册样本查找回调函数
+ *
+ * 该函数用于将样本查找相关的回调函数注册到全局回调结构体 `g_seek_cbk` 中。
+ * 这些回调函数包括启用SLE、启用查找、禁用查找和查找结果处理。
+ */
+void sle_sample_seek_cbk_register(void)
+{
+ // 注册启用SLE的回调函数
+ g_seek_cbk.sle_enable_cb = sle_sample_sle_enable_cbk;
+
+ // 注册启用查找的回调函数
+ g_seek_cbk.seek_enable_cb = sle_sample_seek_enable_cbk;
+
+ // 注册禁用查找的回调函数
+ g_seek_cbk.seek_disable_cb = sle_sample_seek_disable_cbk;
+
+ // 注册查找结果处理的回调函数
+ g_seek_cbk.seek_result_cb = sle_sample_seek_result_info_cbk;
+}
+
+/**
+ * @brief 连接状态变化回调函数
+ *
+ * 该函数在连接状态变化时被调用。它处理连接状态、配对状态和断开原因。
+ * 当连接状态变为已连接时,如果未配对,则启动配对过程,并保存连接ID。
+ *
+ * @param conn_id 连接ID
+ * @param addr 指向远程设备地址的指针
+ * @param conn_state 当前连接状态
+ * @param pair_state 当前配对状态
+ * @param disc_reason 断开连接的原因
+ */
+void sle_sample_connect_state_changed_cbk(uint16_t conn_id, const sle_addr_t *addr,
+ sle_acb_state_t conn_state, sle_pair_state_t pair_state, sle_disc_reason_t disc_reason)
+{
+ // 打印连接状态变化信息,包括连接ID和远程设备地址
+ // test_suite_uart_sendf("[ssap client] conn state changed conn_id:%d, addr:%02x***%02x%02x\n", conn_id, addr->addr[0],
+ // addr->addr[4], addr->addr[5]); /* 0 4 5: addr index */
+ test_suite_uart_sendf("[ssap client] pair complete conn_id:%d, addr:%02x%02x%02x%02x%02x%02x\n", conn_id, addr->addr[0], addr->addr[1], addr->addr[2], addr->addr[3], addr->addr[4], addr->addr[5]);
+ printf("[ssap client] pair complete conn_id:%d, addr:%02x%02x%02x%02x%02x%02x\n", conn_id, addr->addr[0], addr->addr[1], addr->addr[2], addr->addr[3], addr->addr[4], addr->addr[5]);
+
+ // 打印断开连接的原因
+ test_suite_uart_sendf("[ssap client] conn state changed disc_reason:0x%x\n", disc_reason);
+
+ // 如果连接状态为已连接
+ if (conn_state == SLE_ACB_STATE_CONNECTED)
+ {
+ // 如果配对状态为未配对
+ if (pair_state == SLE_PAIR_NONE)
+ {
+ // 启动配对过程
+ sle_pair_remote_device(&g_remote_addr);
+ }
+ // 保存连接ID
+ g_conn_id = conn_id;
+ }
+}
+
+/**
+ * @brief 配对完成回调函数
+ *
+ * 该函数在配对完成时被调用。它处理配对完成后的操作,包括打印配对信息和
+ * 发送SSAP交换信息请求。当配对成功时,设置MTU大小和版本信息,并发送交换信息请求。
+ *
+ * @param conn_id 连接ID
+ * @param addr 指向远程设备地址的指针
+ * @param status 配对状态码。0表示成功,非0表示失败。
+ */
+void sle_sample_pair_complete_cbk(uint16_t conn_id, const sle_addr_t *addr, errcode_t status)
+{
+ // 打印配对完成信息,包括连接ID和远程设备地址
+ // test_suite_uart_sendf("[ssap client] pair complete conn_id:%d, addr:%02x***%02x%02x\n", conn_id, addr->addr[0],
+ // addr->addr[4], addr->addr[5]); /* 0 4 5: addr index */
+
+ test_suite_uart_sendf("[ssap client] pair complete conn_id:%d, addr:%02x%02x%02x%02x%02x%02x\n", conn_id, addr->addr[0], addr->addr[1], addr->addr[2], addr->addr[3], addr->addr[4], addr->addr[5]);
+ printf("[ssap client] pair complete conn_id:%d, addr:%02x:%02x:%02x:%02x:%02x:%02x\n", conn_id, addr->addr[0], addr->addr[1], addr->addr[2], addr->addr[3], addr->addr[4], addr->addr[5]);
+ // 如果配对成功
+ if (status == 0)
+ {
+ // 定义并初始化SSAP交换信息结构体
+ ssap_exchange_info_t info = {0};
+ info.mtu_size = SLE_MTU_SIZE_DEFAULT; // 设置MTU大小
+ info.version = 1; // 设置版本信息
+ // 发送SSAP交换信息请求
+ ssapc_exchange_info_req(1, g_conn_id, &info);
+ }
+}
+
+/**
+ * @brief 注册样本连接回调函数
+ *
+ * 该函数用于将样本连接相关的回调函数注册到全局回调结构体 `g_connect_cbk` 中。
+ * 这些回调函数包括连接状态变化回调函数和配对完成回调函数。
+ */
+void sle_sample_connect_cbk_register(void)
+{
+ // 注册连接状态变化回调函数
+ g_connect_cbk.connect_state_changed_cb = sle_sample_connect_state_changed_cbk;
+
+ // 注册配对完成回调函数
+ g_connect_cbk.pair_complete_cb = sle_sample_pair_complete_cbk;
+}
+
+/**
+ * @brief SSAP交换信息回调函数
+ *
+ * 该函数在SSAP交换信息完成时被调用。它处理交换信息的结果,包括打印交换信息和
+ * 启动查找结构过程。当交换信息成功时,打印MTU大小和版本信息,并启动查找主服务结构。
+ *
+ * @param client_id 客户端ID
+ * @param conn_id 连接ID
+ * @param param 指向SSAP交换信息参数结构体的指针
+ * @param status 交换信息状态码。0表示成功,非0表示失败。
+ */
+void sle_sample_exchange_info_cbk(uint8_t client_id, uint16_t conn_id, ssap_exchange_info_t *param,
+ errcode_t status)
+{
+ // 打印配对完成信息,包括客户端ID和状态码
+ test_suite_uart_sendf("[ssap client] pair complete client id:%d status:%d\n", client_id, status);
+
+ // 打印交换信息,包括MTU大小和版本信息
+ test_suite_uart_sendf("[ssap client] exchange mtu, mtu size: %d, version: %d.\n",
+ param->mtu_size, param->version);
+
+ // 定义并初始化查找结构参数结构体
+ ssapc_find_structure_param_t find_param = {0};
+ find_param.type = SSAP_FIND_TYPE_PRIMARY_SERVICE; // 设置查找类型为主服务
+ find_param.start_hdl = 1; // 设置查找起始句柄
+ find_param.end_hdl = 0xFFFF; // 设置查找结束句柄
+
+ // 启动查找结构过程
+
+ ssapc_find_structure(0, conn_id, &find_param);
+}
+
+/**
+ * @brief 查找结构回调函数
+ *
+ * 该函数在查找结构完成时被调用。它处理查找结构的结果,包括打印查找信息和
+ * 保存查找结果。当查找结果的UUID长度为16位时,打印16位UUID;否则,打印128位UUID。
+ *
+ * @param client_id 客户端ID
+ * @param conn_id 连接ID
+ * @param service 指向查找服务结果结构体的指针
+ * @param status 查找状态码。0表示成功,非0表示失败。
+ */
+void sle_sample_find_structure_cbk(uint8_t client_id, uint16_t conn_id, ssapc_find_service_result_t *service,
+ errcode_t status)
+{
+ // 打印查找结构回调信息,包括客户端ID、连接ID和状态码
+ test_suite_uart_sendf("[ssap client] find structure cbk client: %d conn_id:%d status: %d \n",
+ client_id, conn_id, status);
+
+ // 打印查找结构的起始句柄、结束句柄和UUID长度
+ test_suite_uart_sendf("[ssap client] find structure start_hdl:[0x%02x], end_hdl:[0x%02x], uuid len:%d\r\n",
+ service->start_hdl, service->end_hdl, service->uuid.len);
+
+ // 如果UUID长度为16位
+ if (service->uuid.len == UUID_16BIT_LEN)
+ {
+ // 打印16位UUID
+ test_suite_uart_sendf("[ssap client] structure uuid:[0x%02x][0x%02x]\r\n",
+ service->uuid.uuid[14], service->uuid.uuid[15]); /* 14 15: uuid index */
+ }
+ else
+ {
+ // 打印128位UUID
+ for (uint8_t idx = 0; idx < UUID_128BIT_LEN; idx++)
+ {
+ test_suite_uart_sendf("[ssap client] structure uuid[%d]:[0x%02x]\r\n", idx, service->uuid.uuid[idx]);
+ }
+ }
+
+ // 保存查找结果的起始句柄和结束句柄
+ g_find_service_result.start_hdl = service->start_hdl;
+ g_find_service_result.end_hdl = service->end_hdl;
+
+ // 将查找结果的UUID复制到全局变量 g_find_service_result.uuid 中
+ memcpy_s(&g_find_service_result.uuid, sizeof(sle_uuid_t), &service->uuid, sizeof(sle_uuid_t));
+}
+
+/**
+ * @brief 查找结构完成回调函数
+ *
+ * 该函数在查找结构完成时被调用。它处理查找结构的结果,包括打印查找信息和
+ * 发送写请求。当查找结果的UUID长度为16位时,打印16位UUID;否则,打印128位UUID。
+ * 最后,发送写请求,将数据写入查找到的结构中。
+ *
+ * @param client_id 客户端ID
+ * @param conn_id 连接ID
+ * @param structure_result 指向查找结构结果结构体的指针
+ * @param status 查找状态码。0表示成功,非0表示失败。
+ */
+void sle_sample_find_structure_cmp_cbk(uint8_t client_id, uint16_t conn_id,
+ ssapc_find_structure_result_t *structure_result, errcode_t status)
+{
+ // 打印查找结构完成回调信息,包括客户端ID、状态码、类型和UUID长度
+ test_suite_uart_sendf("[ssap client] find structure cmp cbk client id:%d status:%d type:%d uuid len:%d \r\n",
+ client_id, status, structure_result->type, structure_result->uuid.len);
+
+ // 如果UUID长度为16位
+ if (structure_result->uuid.len == UUID_16BIT_LEN)
+ {
+ // 打印16位UUID
+ test_suite_uart_sendf("[ssap client] find structure cmp cbk structure uuid:[0x%02x][0x%02x]\r\n",
+ structure_result->uuid.uuid[14], structure_result->uuid.uuid[15]); /* 14 15: uuid index */
+ }
+ else
+ {
+ // 打印128位UUID
+ for (uint8_t idx = 0; idx < UUID_128BIT_LEN; idx++)
+ {
+ test_suite_uart_sendf("[ssap client] find structure cmp cbk structure uuid[%d]:[0x%02x]\r\n", idx,
+ structure_result->uuid.uuid[idx]);
+ }
+ }
+
+ // 定义要写入的数据
+ uint8_t data[] = {0x11, 0x22, 0x33, 0x44};
+ uint8_t len = sizeof(data);
+
+ // 定义并初始化写请求参数结构体
+ ssapc_write_param_t param = {0};
+ param.handle = g_find_service_result.start_hdl; // 设置句柄为查找结果的起始句柄
+ param.type = SSAP_PROPERTY_TYPE_VALUE; // 设置属性类型为值
+ param.data_len = len; // 设置数据长度
+ param.data = data; // 设置数据指针
+
+ // 发送写请求
+ ssapc_write_req(0, conn_id, ¶m);
+}
+
+/**
+ * @brief SSAP客户端查找属性回调函数
+ *
+ * 该函数在SSAP客户端查找属性操作完成后被调用。它处理查找属性的结果,并将相关信息通过UART发送出去。
+ *
+ * @param client_id 客户端ID
+ * @param conn_id 连接ID
+ * @param property 指向查找属性结果结构体的指针
+ * @param status 操作状态码。0表示成功,非0表示失败。
+ */
+void sle_sample_find_property_cbk(uint8_t client_id, uint16_t conn_id,
+ ssapc_find_property_result_t *property, errcode_t status)
+{
+ // 通过UART发送查找属性回调的基本信息,包括客户端ID、连接ID、操作指示和描述符数量
+ test_suite_uart_sendf("[ssap client] find property cbk, client id: %d, conn id: %d, operate ind: %d, "
+ "descriptors count: %d status:%d.\n",
+ client_id, conn_id, property->operate_indication,
+ property->descriptors_count, status);
+
+ // 遍历所有描述符,并通过UART发送每个描述符的类型
+ for (uint16_t idx = 0; idx < property->descriptors_count; idx++)
+ {
+ test_suite_uart_sendf("[ssap client] find property cbk, descriptors type [%d]: 0x%02x.\n",
+ idx, property->descriptors_type[idx]);
+ }
+
+ // 根据UUID的长度,分别处理16位和128位UUID
+ if (property->uuid.len == UUID_16BIT_LEN)
+ {
+ // 如果UUID长度为16位,通过UART发送UUID的最后两个字节
+ test_suite_uart_sendf("[ssap client] find property cbk, uuid: %02x %02x.\n",
+ property->uuid.uuid[14], property->uuid.uuid[15]); /* 14 15: uuid index */
+ }
+ else if (property->uuid.len == UUID_128BIT_LEN)
+ {
+ // 如果UUID长度为128位,遍历UUID的每个字节,并通过UART发送
+ for (uint16_t idx = 0; idx < UUID_128BIT_LEN; idx++)
+ {
+ test_suite_uart_sendf("[ssap client] find property cbk, uuid [%d]: %02x.\n",
+ idx, property->uuid.uuid[idx]);
+ }
+ }
+}
+
+/**
+ * @brief 写确认回调函数
+ *
+ * 该函数在写操作完成时被调用。它处理写操作的结果,并发送读请求以读取写入的数据。
+ *
+ * @param client_id 客户端ID
+ * @param conn_id 连接ID
+ * @param write_result 指向写操作结果结构体的指针
+ * @param status 写操作状态码。0表示成功,非0表示失败。
+ */
+void sle_sample_write_cfm_cbk(uint8_t client_id, uint16_t conn_id, ssapc_write_result_t *write_result,
+ errcode_t status)
+{
+ // 打印写操作确认信息,包括客户端ID和状态码
+ test_suite_uart_sendf("[ssap client] write cfm cbk, client id: %d status:%d.\n", client_id, status);
+
+ // 发送读请求以读取写入的数据
+ ssapc_read_req(0, conn_id, write_result->handle, write_result->type);
+}
+
+/**
+ * @brief 读确认回调函数
+ *
+ * 该函数在读操作完成时被调用。它处理读操作的结果,并打印读取的数据。
+ *
+ * @param client_id 客户端ID
+ * @param conn_id 连接ID
+ * @param read_data 指向读操作结果结构体的指针
+ * @param status 读操作状态码。0表示成功,非0表示失败。
+ */
+void sle_sample_read_cfm_cbk(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *read_data,
+ errcode_t status)
+{
+ // 打印读操作确认信息,包括客户端ID、连接ID和状态码
+ test_suite_uart_sendf("[ssap client] read cfm cbk client id: %d conn id: %d status: %d\n",
+ client_id, conn_id, status);
+
+ // 打印读操作的句柄、类型和数据长度
+ test_suite_uart_sendf("[ssap client] read cfm cbk handle: %d, type: %d , len: %d\n",
+ read_data->handle, read_data->type, read_data->data_len);
+
+ // 打印读取的数据
+ for (uint16_t idx = 0; idx < read_data->data_len; idx++)
+ {
+ test_suite_uart_sendf("[ssap client] read cfm cbk[%d] 0x%02x\r\n", idx, read_data->data[idx]);
+ }
+}
+
+char key_code_switch(char key_code)
+{
+ switch (key_code)
+ {
+ case 5:
+ key_code = 48;
+ break;
+ case 7:
+ key_code = 32;
+ break;
+ case 82:
+ key_code = 103;
+ break;
+ case 80:
+ key_code = 105;
+ break;
+ case 40:
+ key_code = 28;
+ break;
+ case 79:
+ key_code = 106;
+ break;
+ case 81:
+ key_code = 108;
+ break;
+ case 41:
+ key_code = 1;
+ break;
+ case 101:
+ key_code = 127;
+ break;
+ case 74:
+ key_code = 102;
+ break;
+ case 30:
+ case 31:
+ case 32:
+ case 33:
+ case 34:
+ case 35:
+ case 36:
+ case 37:
+ case 38:
+ case 39:
+ case 42:
+ key_code = key_code - 28;
+ break;
+ default:
+ break;
+ }
+ return key_code;
+}
+
+/**
+ * @brief 将键码和键值发送到ROS2
+ *
+ * 该函数将键码和键值通过消息队列发送到ROS2。它首先检查键值是否为1,如果是则直接返回。
+ * 然后,它创建或打开一个消息队列,并设置消息队列的属性。如果消息队列已满,则接收并删除
+ * 一个最旧的消息来腾出空间。最后,它将键码发送到消息队列,并关闭消息队列。
+ *
+ * @param keycode 键码
+ * @param keyvalue 键值
+ */
+void send_to_ros2(char keycode, char keyvalue)
+{
+ char recbuffer[2] = {0}; // 定义接收缓冲区
+ char sendbuffer[2] = {0}; // 定义发送缓冲区
+ mqd_t nearlink_mq = {0}; // 定义消息队列描述符
+ unsigned int nearlink_mq_prio = 10; // 定义消息队列优先级
+ struct mq_attr nearlink_mq_attr; // 定义消息队列属性结构体
+
+ // 设置消息队列属性
+ nearlink_mq_attr.mq_flags = O_NONBLOCK; // 设置非阻塞标志
+ nearlink_mq_attr.mq_maxmsg = 10; // 设置最大消息数
+ nearlink_mq_attr.mq_msgsize = 1; // 设置消息大小
+ nearlink_mq_attr.mq_curmsgs = 0; // 设置当前消息数
+
+ // 如果键值为1,直接返回
+ if (keyvalue == 1)
+ {
+ return;
+ }
+ sendbuffer[0] = keycode; // 将键码存入发送缓冲区
+
+ // 创建或打开消息队列
+ nearlink_mq = mq_open("/nearlink_mq", O_CREAT | O_WRONLY, 0644, &nearlink_mq_attr);
+ if (nearlink_mq == (mqd_t)-1)
+ {
+ // 打印消息队列打开失败的错误信息
+ printf("%s mq_open nearlink_mq failed,%s\r\n", SLE_RCU_DONGLE_LOG, strerror(errno));
+ return;
+ }
+
+ // 设置消息队列属性
+ if (mq_setattr(nearlink_mq, &nearlink_mq_attr, NULL) == -1)
+ {
+ // 打印设置消息队列属性失败的错误信息
+ printf("%s mq_setattr nearlink_mq failed,%s\r\n", SLE_RCU_DONGLE_LOG, strerror(errno));
+ mq_close(nearlink_mq); // 关闭消息队列
+ return;
+ }
+
+ // 获取消息队列属性
+ struct mq_attr attr;
+ if (mq_getattr(nearlink_mq, &attr) == -1)
+ {
+ // 打印获取消息队列属性失败的错误信息
+ printf("%s mq_getattr nearlink_mq failed,%s\r\n", SLE_RCU_DONGLE_LOG, strerror(errno));
+ mq_close(nearlink_mq); // 关闭消息队列
+ return;
+ }
+ // 打印消息队列属性信息
+ printf("%s nearlink_mq attr mq_curmsgs %ld mq_maxmsg %ld \r\n", SLE_RCU_DONGLE_LOG, attr.mq_curmsgs, attr.mq_maxmsg);
+
+ // 如果消息队列已满,接收并删除一个最旧的消息来腾出空间
+ if (attr.mq_curmsgs == attr.mq_maxmsg)
+ {
+ if (mq_receive(nearlink_mq, recbuffer, nearlink_mq_attr.mq_msgsize, NULL) < 0)
+ {
+ // 打印接收消息失败的错误信息
+ printf("%s mq_receive nearlink_mq failed,%s\r\n", SLE_RCU_DONGLE_LOG, strerror(errno));
+ mq_close(nearlink_mq); // 关闭消息队列
+ return;
+ }
+ // 打印删除最旧消息的信息
+ printf("%s old message dequeued to make space\r\n", SLE_RCU_DONGLE_LOG);
+ }
+
+ // 发送键码到消息队列
+ if (mq_send(nearlink_mq, sendbuffer, nearlink_mq_attr.mq_msgsize, 0) == -1)
+ {
+ // 打印发送消息失败的错误信息
+ printf("%s mq_send nearlink_mq failed,%s\r\n", SLE_RCU_DONGLE_LOG, strerror(errno));
+ mq_close(nearlink_mq); // 关闭消息队列
+ return;
+ }
+
+ // 关闭消息队列
+ mq_close(nearlink_mq);
+}
+
+/**
+ * @brief SLE RCU通知回调函数
+ *
+ * 该函数在接收到SLE RCU通知时被调用。它处理接收到的数据,并根据数据内容
+ * 进行相应的操作。如果接收到的是键盘报告数据,则解析并打印键盘报告信息,
+ * 并将键码和键值发送到ROS2。
+ *
+ * @param client_id 客户端ID
+ * @param conn_id 连接ID
+ * @param data 指向接收到的数据结构体的指针
+ * @param status 接收状态码。0表示成功,非0表示失败。
+ */
+static void sle_rcu_notification_cb(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data, errcode_t status)
+{
+ char data_to_send[30]; // 定义要发送的数据缓冲区
+ int key_code = 0; // 键码
+ int key_value = 0; // 键值
+
+ // 检查接收到的数据是否为空或数据长度为0
+ if (data == NULL || data->data_len == 0 || data->data == NULL)
+ {
+ // 如果数据为空或数据长度为0,打印错误信息并返回
+ printf("%s sle_rcu_notification_cb fail, recv data is null!\r\n", SLE_RCU_DONGLE_LOG);
+ return;
+ }
+
+ // 打印接收成功的信息
+ printf("%s sle_rcu_notification_cb ok\n", SLE_RCU_DONGLE_LOG);
+
+ // 检查接收到的数据长度是否为键盘报告长度
+ if (data->data_len == USB_RCU_KEYBOARD_REPORTER_LEN)
+ {
+ // 定义接收键盘报告的指针
+ usb_hid_rcu_keyboard_report_t *recv_usb_hid_rcu_keyboard = NULL;
+ printf("%s sle rcu recive notification\r\n", SLE_RCU_DONGLE_LOG);
+
+ // 将接收到的数据转换为键盘报告结构体
+ recv_usb_hid_rcu_keyboard = (usb_hid_rcu_keyboard_report_t *)data->data;
+
+ // 打印键盘报告的各个字段
+ printf("%s recv_usb_hid_rcu_keyboard.kind = [%d]\r\n", SLE_RCU_DONGLE_LOG,
+ recv_usb_hid_rcu_keyboard->kind);
+ printf("%s recv_usb_hid_rcu_keyboard.special_key = [%d]\r\n", SLE_RCU_DONGLE_LOG,
+ recv_usb_hid_rcu_keyboard->special_key);
+ printf("%s recv_usb_hid_rcu_keyboard.reversed = [%d]\r\n", SLE_RCU_DONGLE_LOG,
+ recv_usb_hid_rcu_keyboard->reserve);
+ printf("%s recv_usb_hid_rcu_keyboard.key = ", SLE_RCU_DONGLE_LOG);
+
+ // 打印键盘报告中的按键值
+ for (uint8_t i = 0; i < USB_HID_RCU_MAX_KEY_LENTH; i++)
+ {
+ printf("0x%02x ", recv_usb_hid_rcu_keyboard->key[i]);
+ }
+
+ // 根据键盘报告中的按键值设置键码和键值
+ if (recv_usb_hid_rcu_keyboard->key[0] != 0)
+ {
+ key_code = key_code_switch(recv_usb_hid_rcu_keyboard->key[0]);
+ key_value = 1;
+ }
+ else
+ {
+ key_value = 0;
+ }
+ printf("\r\n");
+
+ // 清空数据缓冲区并格式化要发送的数据
+ memset(data_to_send, 0, sizeof(char) * 30);
+ snprintf(data_to_send, 30, "code:%d,value:%d\r\n", key_code, key_value);
+ printf("code:0x%x,value:%d\r\n", key_code, key_value);
+
+ // 将键码和键值发送到ROS2
+ send_to_ros2(key_code, key_value);
+ sleep(1);
+ send_to_ros2(0x67, 0);
+ }
+ else
+ {
+ // 如果接收到的数据不是键盘数据,打印提示信息
+ printf("[%s]this is not keyboard data\r\n", __func__);
+ }
+}
+
+/**
+ * @brief SLE RCU指示回调函数
+ *
+ * 该函数在接收到SLE RCU指示时被调用。它处理接收到的数据,并根据数据内容
+ * 进行相应的操作。如果接收到的是键盘报告数据,则解析并打印键盘报告信息。
+ *
+ * @param client_id 客户端ID
+ * @param conn_id 连接ID
+ * @param data 指向接收到的数据结构体的指针
+ * @param status 接收状态码。0表示成功,非0表示失败。
+ */
+
+static void sle_rcu_indication_cb(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data, errcode_t status)
+{
+ // 检查接收到的数据是否为空或数据长度为0
+ if (data == NULL || data->data_len == 0 || data->data == NULL)
+ {
+ // 如果数据为空或数据长度为0,打印错误信息并返回
+ printf("%s sle_rcu_notification_cb fail, recv data is null!\r\n", SLE_RCU_DONGLE_LOG);
+ return;
+ }
+
+ // 检查接收到的数据长度是否为键盘报告长度
+ if (data->data_len == USB_RCU_KEYBOARD_REPORTER_LEN)
+ {
+ // 定义接收键盘报告的指针
+ usb_hid_rcu_keyboard_report_t *recv_usb_hid_rcu_keyboard = NULL;
+ printf("%s sle rcu recive notification\r\n", SLE_RCU_DONGLE_LOG);
+
+ // 将接收到的数据转换为键盘报告结构体
+ recv_usb_hid_rcu_keyboard = (usb_hid_rcu_keyboard_report_t *)data->data;
+
+ // 打印键盘报告的各个字段
+ printf("%s recv_usb_hid_rcu_keyboard.kind = [%d]\r\n", SLE_RCU_DONGLE_LOG,
+ recv_usb_hid_rcu_keyboard->kind);
+ printf("%s recv_usb_hid_rcu_keyboard.special_key = [%d]\r\n", SLE_RCU_DONGLE_LOG,
+ recv_usb_hid_rcu_keyboard->special_key);
+ printf("%s recv_usb_hid_rcu_keyboard.reversed = [%d]\r\n", SLE_RCU_DONGLE_LOG,
+ recv_usb_hid_rcu_keyboard->reserve);
+ printf("%s recv_usb_hid_rcu_keyboard.key = ", SLE_RCU_DONGLE_LOG);
+
+ // 打印键盘报告中的按键值
+ for (uint8_t i = 0; i < USB_HID_RCU_MAX_KEY_LENTH; i++)
+ {
+ printf("0x%02x ", recv_usb_hid_rcu_keyboard->key[i]);
+ }
+ printf("\r\n");
+ }
+ else
+ {
+ // 如果接收到的数据不是键盘数据,打印提示信息
+ printf("[%s]this is not keyboard data\r\n", __func__);
+ }
+}
+
+/**
+ * @brief 注册SSAP客户端回调函数
+ *
+ * 该函数用于将SSAP客户端相关的回调函数注册到全局回调结构体 `g_ssapc_cbk` 中。
+ * 这些回调函数包括交换信息回调、查找结构回调、查找结构完成回调、查找属性回调、
+ * 通知回调、指示回调、写确认回调和读确认回调。
+ *
+ * @param notification_cb 通知回调函数
+ * @param indication_cb 指示回调函数
+ */
+void sle_sample_ssapc_cbk_register(ssapc_notification_callback notification_cb,
+ ssapc_notification_callback indication_cb)
+{
+ // 注册交换信息回调函数
+ g_ssapc_cbk.exchange_info_cb = sle_sample_exchange_info_cbk;
+
+ // 注册查找结构回调函数
+ g_ssapc_cbk.find_structure_cb = sle_sample_find_structure_cbk;
+
+ // 注册查找结构完成回调函数
+ g_ssapc_cbk.find_structure_cmp_cb = sle_sample_find_structure_cmp_cbk;
+
+ // 注册查找属性回调函数
+ g_ssapc_cbk.ssapc_find_property_cbk = sle_sample_find_property_cbk;
+
+ // 注册通知回调函数
+ g_ssapc_cbk.notification_cb = notification_cb;
+
+ // 注册指示回调函数
+ g_ssapc_cbk.indication_cb = indication_cb;
+
+ // 注册写确认回调函数
+ g_ssapc_cbk.write_cfm_cb = sle_sample_write_cfm_cbk;
+
+ // 注册读确认回调函数
+ g_ssapc_cbk.read_cfm_cb = sle_sample_read_cfm_cbk;
+}
+
+/**
+ * @brief 初始化SLE客户端
+ *
+ * 该函数用于初始化SLE客户端,注册各种回调函数,并启用SLE功能。
+ * 它依次调用多个注册函数,将回调函数与相应的事件关联起来。
+ */
+void sle_client_init()
+{
+ // 注册样本查找回调函数
+ sle_sample_seek_cbk_register();
+
+ // 注册样本连接回调函数
+ sle_sample_connect_cbk_register();
+
+ // 注册SSAP客户端回调函数,包括通知和指示回调
+ sle_sample_ssapc_cbk_register(sle_rcu_notification_cb, sle_rcu_indication_cb);
+
+ // 注册查找回调函数
+ sle_announce_seek_register_callbacks(&g_seek_cbk);
+
+ // 注册连接回调函数
+ sle_connection_register_callbacks(&g_connect_cbk);
+
+ // 注册SSAP客户端回调函数
+ ssapc_register_callbacks(&g_ssapc_cbk);
+
+ // 启用SLE功能
+ enable_sle();
+}
+
+/**
+ * @brief 启动SLE扫描
+ *
+ * 该函数用于启动SLE扫描过程。它首先设置扫描参数,然后开始扫描。
+ * 扫描参数包括地址类型、重复过滤、扫描过滤策略、扫描物理层、扫描类型、扫描间隔和扫描窗口。
+ */
+void sle_start_scan()
+{
+ // 定义并初始化扫描参数结构体
+ sle_seek_param_t param = {0};
+
+ // 设置扫描参数
+ param.own_addr_type = 0; // 本地地址类型
+ param.filter_duplicates = 0; // 是否过滤重复设备
+ param.seek_filter_policy = 0; // 扫描过滤策略
+ param.seek_phys = 1; // 扫描物理层
+ param.seek_type[0] = 0; // 扫描类型
+ param.seek_interval[0] = SLE_SEEK_INTERVAL_DEFAULT; // 扫描间隔
+ param.seek_window[0] = SLE_SEEK_WINDOW_DEFAULT; // 扫描窗口
+
+ // 设置扫描参数
+ sle_set_seek_param(¶m);
+
+ // 开始扫描
+ sle_start_seek();
+}
+/**
+ * @brief SIGINT信号处理函数
+ *
+ * 当程序接收到SIGINT信号(如用户按下Ctrl+C)时,该函数会被调用。
+ * 该函数用于处理程序的清理工作,例如断开与远程设备的连接。
+ *
+ * @param sig 接收到的信号编号
+ */
+void sigintHandler(int sig)
+{
+ // 避免未使用参数警告
+ sig = sig;
+
+ // 关闭与远程设备的连接
+ errcode_t ret = sle_disconnect_remote_device(&g_remote_addr);
+
+ // 打印断开连接的结果
+ printf("*****sle disconnect remote device(ret %u) ****\n\n", ret);
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+ ret = uapi_gle_init();
+ if (ret != 0)
+ {
+ printf("init fail.\n\n");
+ goto mainend;
+ }
+ // 创建信号处理函数
+ signal(SIGINT, sigintHandler);
+ // start业务功
+ sle_client_init();
+ // end业务功能(进入无限循环,保持程序运行)
+ while (1)
+ {
+ send_to_ros2(0x67, 1);
+ printf("点击小车前进指令\r\n");
+ sleep(1);
+ send_to_ros2(0x67, 0);
+ printf("释放小车前进指令\r\n");
+ sleep(5);
+ }
+mainend:
+ printf("main start. 00\n\n");
+ printf("main end.\n\n");
+ return ret;
+}
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/out/target.bin b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/out/target.bin
new file mode 100644
index 0000000000000000000000000000000000000000..5518375fe54ac3d4ee2bf11be45a4ff8d9e5f686
Binary files /dev/null and b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/out/target.bin differ
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/adc_demo.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/adc_demo.c
new file mode 100644
index 0000000000000000000000000000000000000000..75a32c38b75ff70e88a661e97b17709f8c58613e
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/adc_demo.c
@@ -0,0 +1,28 @@
+#include "adc_demo.h"
+#include "main.h"
+#include "debug.h"
+
+/**
+ * @brief ADC single channel sample without DMA and interrupt.
+ * @param None.
+ * @retval None.
+ */
+void ADC_SingleTrigger(void)
+{
+ DBG_PRINTF("ADC_SingleTrigger begin\r\n");
+
+ HAL_ADC_SoftTrigSample(&g_adc0, ADC_SOC_NUM0); /* Software trigger ADC sampling */
+
+ BASE_FUNC_DELAY_MS(10); /* delay 10 ms */
+
+ if (HAL_ADC_CheckSocFinish(&g_adc0, ADC_SOC_NUM0) == BASE_STATUS_ERROR) {
+ DBG_PRINTF("ADC did not complete sampling and conversion\r\n");
+ return;
+ }
+
+ unsigned int ret = HAL_ADC_GetConvResult(&g_adc0, ADC_SOC_NUM0); /* Software trigger ADC sampling */
+ DBG_PRINTF("Sampling completed, result: %d\r\n", ret);
+ float voltage = (float)ret / (float)4096 * 3.3; /* 4096 and 3.3 are for Sample Value Conversion */
+ DBG_PRINTF("voltage: %f\r\n", voltage);
+ return;
+}
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/adc_demo.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/adc_demo.h
new file mode 100644
index 0000000000000000000000000000000000000000..e485616c19b85df42e0444e9a17722cfc12c653b
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/adc_demo.h
@@ -0,0 +1,7 @@
+#ifndef ADC_DEMO_H
+#define ADC_DEMO_H
+
+
+void ADC_SingleTrigger(void);
+
+#endif
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/beep.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/beep.c
new file mode 100644
index 0000000000000000000000000000000000000000..c0965f8c0b15a30d9f1ac8ef773c472ff03f8f4b
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/beep.c
@@ -0,0 +1,22 @@
+#include "beep.h"
+#include "main.h"
+#include "debug.h"
+
+/**
+ * @brief GPT run and modify period and duty during running.
+ * @param None.
+ * @retval None.
+ */
+void GPT_SampleMain(void)
+{
+ DBG_PRINTF("GPT Continued Run begin\r\n");
+ HAL_GPT_Start(&g_gpt3);
+ // BASE_FUNC_DelaySeconds(10); /* Delay 10 seconds */
+ // DBG_PRINTF("Change the duty to 50%%\r\n");
+
+ // HAL_GPT_GetConfig(&g_gpt3);
+ // g_gpt3.period = 59999; /* 59999 is the number of GPT counting cycles. */
+ // g_gpt3.refA0.refdot = 20000; /* 20000 is the value of PWM reference point A. */
+ // g_gpt3.refB0.refdot = 50000; /* 50000 is the value of PWM reference point A. */
+ // HAL_GPT_Config(&g_gpt3);
+}
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/beep.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/beep.h
new file mode 100644
index 0000000000000000000000000000000000000000..a69aef4b29d46ae4e528dd9a6de7b0f434440908
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/beep.h
@@ -0,0 +1,7 @@
+#ifndef BEEP_H
+#define BEEP_H
+
+
+void GPT_SampleMain(void);
+
+#endif
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/button.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/button.c
new file mode 100644
index 0000000000000000000000000000000000000000..46b6fa51f37b4fc646b9acffe27282bc53b69da7
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/button.c
@@ -0,0 +1,124 @@
+#include "debug.h"
+#include "gpio.h"
+#include "main.h"
+#include "button.h"
+#include "user_motor_control.h"
+
+#define PREVENT_SWIPE_SCREEN_TIME 50
+#define CYCLE_INTERVAL_TIME 500
+
+int g_button1State = 0;
+int g_button2State = 0;
+
+//按键滤波计数器
+int g_button1_count = 0;
+int g_button2_count = 0;
+
+unsigned int g_testIndex = 2;
+unsigned int g_testAngles = ADJUST_PLUS_90;
+
+static unsigned int g_angleDate[][2] = {
+ {1, 76},
+ {1, 151},
+ {1, 226},
+ {1, 301},
+ {1, 376}
+};
+
+void AngleAdjustment(unsigned int index, unsigned int angles)
+{
+ if (angles > ADJUST_PLUS_90) {
+ return;
+ }
+
+ GPT_ReferCfg refer;
+ refer.refA0.refAction = GPT_ACTION_OUTPUT_HIGH;
+ refer.refB0.refAction = GPT_ACTION_OUTPUT_LOW;
+ refer.refA0.refdot = g_angleDate[angles][0];
+ refer.refA0.refdot = g_angleDate[angles][1];
+ switch (index) {
+ case 0:
+ HAL_GPT_SetReferCounterAndAction(&g_gpt0, &refer);
+ break;
+ case 1:
+ HAL_GPT_SetReferCounterAndAction(&g_gpt1, &refer);
+ break;
+ case 2:
+ HAL_GPT_SetReferCounterAndAction(&g_gpt2, &refer);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * @brief GPIO register interrupt callback function.
+ * @param param Value of @ref GPIO_Handle.
+ * @retval None
+ */
+
+
+void GPIO1_0_CallbackFunc(void *param)
+{
+ BASE_FUNC_UNUSED(param);
+ if((g_button1State == 0) && (g_button1_count == 0))
+ {
+ //g_button1State = !g_button1State;
+ g_button1State = 1;
+ g_button1_count = 1; //在10ms定时中断里处理按键滤波业务逻辑
+ }
+}
+
+void GPIO1_1_CallbackFunc(void *param)
+{
+ BASE_FUNC_UNUSED(param);
+ if((g_button2State == 0) && (g_button2_count == 0))
+ {
+ //g_button2State = !g_button2State;
+ g_button2State = 1;
+ g_button2_count = 1; //在10ms定时中断里处理按键滤波业务逻辑
+ }
+}
+
+void InitButtonFunction(void)
+{
+ HAL_GPT_Start(&g_gpt0);
+ HAL_GPT_Start(&g_gpt1);
+ HAL_GPT_Start(&g_gpt2);
+}
+
+
+BASE_StatusType ButtonPrintSample(void)
+{
+ while (1) {
+ BASE_FUNC_DELAY_MS(1);
+ if (g_button1State) {
+ g_button1State = !g_button1State;
+ DBG_PRINTF("g_button1State Evnet\r\n");
+ }
+
+ if (g_button2State) {
+ g_button2State = !g_button2State;
+ DBG_PRINTF("g_button2State Evnet\r\n");
+ }
+ }
+ return BASE_STATUS_OK;
+}
+
+BASE_StatusType GPIO_KeySample(void)
+{
+ HAL_GPT_Start(&g_gpt0);
+ HAL_GPT_Start(&g_gpt1);
+ HAL_GPT_Start(&g_gpt2);
+ while (1) {
+ BASE_FUNC_DELAY_MS(100);
+ if (g_button1State) {
+ g_button1State = !g_button1State;
+ startMotor();
+ MotorForwardRotation();
+ BASE_FUNC_DELAY_MS(3000);
+ stopMotor();
+ }
+ }
+ return BASE_STATUS_OK;
+}
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/button.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/button.h
new file mode 100644
index 0000000000000000000000000000000000000000..1cab4a32df33d5a8297d733b9e7edc9cea3b2382
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/button.h
@@ -0,0 +1,16 @@
+#ifndef BUTTON_H
+#define BUTTON_H
+
+#define ADJUST_MINUS_90 0
+#define ADJUST_MINUS_45 1
+#define ADJUST_MINUS_0 2
+#define ADJUST_PLUS_45 3
+#define ADJUST_PLUS_90 4
+
+void AngleAdjustment(unsigned int index, unsigned int angles);
+void AngleAdjuseProcess(void);
+void InitButtonFunction(void);
+BASE_StatusType GPIO_KeySample(void);
+BASE_StatusType ButtonPrintSample(void);
+
+#endif /* GPIO_KEY_SAMPLE_H */
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/can_demo.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/can_demo.c
new file mode 100644
index 0000000000000000000000000000000000000000..054cd47896129b01e33792101f64c6533ee6cc74
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/can_demo.c
@@ -0,0 +1,123 @@
+/**
+ * @copyright Copyright (c) 2022, HiSilicon (Shanghai) Technologies Co., Ltd. All rights reserved.
+ * 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 the copyright holder 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.
+ * @file sample_can_send_receive.c
+ * @author MCU Driver Team
+ * @brief can sample module.
+ * @details This file provides sample code for users to help use
+ * the filtering function of the CAN.
+ */
+#include "can_demo.h"
+#include "main.h"
+#include "debug.h"
+
+/**
+ * @brief User-defined read completion callback function.
+ * @param UART_Handle UART handle.
+ * @retval None.
+ */
+void CAN_ReadFinish(void *handle)
+{
+ CAN_Handle *canHandle = (CAN_Handle *)handle;
+ DBG_PRINTF("CAN Read Finish\r\n");
+ DBG_PRINTF("data[0]: %d \r\n", canHandle->rxFrame->frame[0]); /* frame[0] data */
+ DBG_PRINTF("data[1]: %d \r\n", canHandle->rxFrame->frame[1]); /* frame[1] data */
+ DBG_PRINTF("data[2]: %d \r\n", canHandle->rxFrame->frame[2]); /* frame[2] data */
+ DBG_PRINTF("data[3]: %d \r\n", canHandle->rxFrame->frame[3]); /* frame[3] data */
+ DBG_PRINTF("data[4]: %d \r\n", canHandle->rxFrame->frame[4]); /* frame[4] data */
+ DBG_PRINTF("data[5]: %d \r\n", canHandle->rxFrame->frame[5]); /* frame[5] data */
+ DBG_PRINTF("data[6]: %d \r\n", canHandle->rxFrame->frame[6]); /* frame[6] data */
+ DBG_PRINTF("data[7]: %d \r\n", canHandle->rxFrame->frame[7]); /* frame[7] data */
+ DBG_PRINTF("ID: 0x%x \r\n", canHandle->rxFrame->CANId);
+ DBG_PRINTF("len: %d \r\n", canHandle->rxFrame->dataLength);
+ DBG_PRINTF("type: %d \r\n", canHandle->rxFrame->type);
+ BASE_FUNC_UNUSED(canHandle);
+ return;
+}
+
+/**
+ * @brief User-defined write completion callback function.
+ * @param CAN_Handle CAN handle.
+ * @retval None.
+ */
+void CAN_WriteFinish(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ DBG_PRINTF("CAN Write Finish\r\n");
+ return;
+}
+/**
+ * Sample Note:
+ * baund rate : 100k Bit/s
+ * To-be-received data frame : Extended Data Frame, ID = 0x1314
+ *
+ * There are two filtering methods:
+ * 1. Receive only the specified ID:
+ * rxFilter.receiveType = CAN_FilterFrame_EXT_DATA;
+ * rxFilter.filterID = 0x1314;
+ * rxFilter.filterMask = 0xFFFFFFFF;
+ *
+ * 2. Use mask to receive:
+ * rxFilter.receiveType = CAN_FilterFrame_EXT_DATA;
+ * rxFilter.filterID = 0x131_;
+ * rxFilter.filterMask = 0xFFFFFFF0;
+ *
+ * rxFilter.receiveType = CAN_FilterFrame_EXT_DATA;
+ * rxFilter.filterID = 0x13_4;
+ * rxFilter.filterMask = 0xFFFFFF0F;
+ *
+ * rxFilter.receiveType = CAN_FilterFrame_EXT_DATA;
+ * rxFilter.filterID = 0x1_14;
+ * rxFilter.filterMask = 0xFFFFF0FF;
+ *
+ * rxFilter.receiveType = CAN_FilterFrame_EXT_DATA;
+ * rxFilter.filterID = 0x_314;
+ * rxFilter.filterMask = 0xFFFF0FFF;
+ *
+ * The value of the ID mask bit, which is not used for filtering.
+ *
+ * Do not filter by ID:
+ * rxFilter.filterMask = 0x00000000;
+ *
+ * Both standard frames and extended frames can be received:
+ * rxFilter.receiveType = CAN_FilterFrame_STD_EXT_DATA;
+ */
+/**
+ * @brief CAN sample code for configuring the filtering function and can send and receive packets.
+ * @param None.
+ * @retval None.
+ */
+CANFrame g_sendFrame;
+CANFrame g_receiveFrame;
+int CAN_ReceiveFilter(void)
+{
+ SystemInit();
+ DBG_PRINTF("CAN Init \r\n");
+ CAN_FilterConfigure rxFilter;
+ g_can.rxFrame = &g_receiveFrame; /* Address for storing received frame data */
+ DBG_PRINTF("CAN interrupt register \r\n");
+ g_sendFrame.type = CAN_TYPEFRAME_EXT_DATA; /* Transmit extended data frame */
+ g_sendFrame.CANId = 0x1314; /* 0x1314 is ID of transmitted data frames */
+ g_sendFrame.dataLength = 1; /* 1 is length of the sent frame */
+ g_sendFrame.frame[0] = '0';
+ HAL_CAN_Write(&g_can, &g_sendFrame);
+ rxFilter.receiveType = CAN_FILTERFRAME_EXT_DATA;
+ rxFilter.filterID = 0x1014; /* 0x1014 and 0xFFFFF0FF constitute filtering rules */
+ rxFilter.filterMask = 0xFFFFF0FF; /* 0xFFFFF0FF is filter ID mask */
+ HAL_CAN_ReadIT(&g_can, &g_receiveFrame, &rxFilter);
+ return 0;
+}
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/can_demo.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/can_demo.h
new file mode 100644
index 0000000000000000000000000000000000000000..b7e0015f6f764a721ab85d4fd8bfc3ad3cc3e085
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/can_demo.h
@@ -0,0 +1,8 @@
+#ifndef CAN_DEMO_H
+#define CAN_DEMO_H
+
+int CAN_ReceiveFilter(void);
+void CAN_ReadFinish(void *handle);
+void CAN_WriteFinish(void *handle);
+
+#endif /* GPIO_KEY_SAMPLE_H */
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/encoder.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/encoder.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ff7eaca28c1cabd80b73f34e616dc7965487c53
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/encoder.c
@@ -0,0 +1,129 @@
+#include "qdm.h"
+#include "debug.h"
+#include "encoder.h"
+#include "main.h"
+#include "eulercar_control.h"
+
+
+//系统10ms中断计数器
+extern unsigned int g_TimerInterruptCount;
+
+/**
+ * @brief QDM sample use M method
+ * @param none.
+ * @retval none.
+ */
+
+//用于pid算法的速度,即MOTOR_PID_CONTROL_PERIOD周期内的速度
+Gear_Motor_handle pidRightMotor;
+Gear_Motor_handle pidLeftMotor;
+
+//用于ODOM里程计的平均速度,即EULER_CAR_DATA_SEND_PERIOD周期内的速度
+Gear_Motor_handle aveRightMotor;
+Gear_Motor_handle aveLeftMotor;
+
+//编码器读取周期内最大差值
+unsigned int g_maxEncodePidDeltaValue;
+unsigned int g_maxEncodeAveDeltaValue;
+
+void InitGearMotor(void)
+{
+ pidRightMotor.motorSide = MOTOR_RIGHT;
+ pidRightMotor.curNumber = 0; /* 当前计数器 */
+ pidRightMotor.lastNumber = 0; /* 上一次计数器 */
+ pidRightMotor.speedRps = 0; /* 电机转速,单位每秒多少圈 */
+ pidRightMotor.speed = 0; /* 电机速度,单位mm/s,由转速和轮胎直径计算 */
+ pidRightMotor.calPeriod = MOTOR_PID_CONTROL_PERIOD;
+
+ pidLeftMotor.motorSide = MOTOR_LEFT;
+ pidLeftMotor.curNumber = 0; /* 当前计数器 */
+ pidLeftMotor.lastNumber = 0; /* 上一次计数器 */
+ pidLeftMotor.speedRps = 0; /* 电机转速,单位每秒多少圈 */
+ pidLeftMotor.speed = 0; /* 电机速度,单位mm/s,由转速和轮胎直径计算 */
+ pidLeftMotor.calPeriod = MOTOR_PID_CONTROL_PERIOD;
+
+
+ aveRightMotor.motorSide = MOTOR_RIGHT;
+ aveRightMotor.curNumber = 0; /* 当前计数器 */
+ aveRightMotor.lastNumber = 0; /* 上一次计数器 */
+ aveRightMotor.speedRps = 0; /* 电机转速,单位每秒多少圈 */
+ aveRightMotor.speed = 0; /* 电机速度,单位mm/s,由转速和轮胎直径计算 */
+ aveRightMotor.calPeriod = EULER_CAR_DATA_SEND_PERIOD;
+
+ aveLeftMotor.motorSide = MOTOR_LEFT;
+ aveLeftMotor.curNumber = 0; /* 当前计数器 */
+ aveLeftMotor.lastNumber = 0; /* 上一次计数器 */
+ aveLeftMotor.speedRps = 0; /* 电机转速,单位每秒多少圈 */
+ aveLeftMotor.speed = 0; /* 电机速度,单位mm/s,由转速和轮胎直径计算 */
+ aveLeftMotor.calPeriod = EULER_CAR_DATA_SEND_PERIOD;
+
+
+ //编码器在一个PID周期内最大差值,电机转速的2倍,主要用于容错处理
+ g_maxEncodePidDeltaValue = (int)(g_motorMaxSpeed / MOTOR_TIRE_DIAMETER / PI * g_motorLineNum / (1000.0/MOTOR_PID_CONTROL_PERIOD) * 2.0);
+ //编码器在一个底盘数据上报周期内最大差值,电机转速的2倍,主要用于容错处理
+ g_maxEncodeAveDeltaValue = (int)(g_motorMaxSpeed / MOTOR_TIRE_DIAMETER / PI * g_motorLineNum / (1000.0/EULER_CAR_DATA_SEND_PERIOD) * 2.0);
+
+ //DBG_PRINTF("g_maxEncodeDeltaValue = %d\r\n", g_maxEncodeDeltaValue);
+}
+
+
+
+void QDM_CalMotorSpeed(Gear_Motor_handle *pMotor)
+{
+ unsigned int qdm_cnt, qdm_dir;
+ unsigned int deltaValue;
+ if(pMotor->motorSide == MOTOR_RIGHT )
+ HAL_QDM_ReadPosCountAndDir(&g_qdm0, &qdm_cnt, &qdm_dir);
+ else
+ HAL_QDM_ReadPosCountAndDir(&g_qdm1, &qdm_cnt, &qdm_dir);
+
+ /* 计算车轮速度 */
+ pMotor->curNumber = qdm_cnt;
+ if(qdm_dir == 1){ //电机正转
+ if(pMotor->curNumber >= pMotor->lastNumber) {
+ deltaValue = pMotor->curNumber - pMotor->lastNumber;
+ }else{ //过零点后的计算编码器差值
+ deltaValue = (pMotor->curNumber +g_motorLineNum) - pMotor->lastNumber;
+ }
+ }else{ //电机反转
+ if(pMotor->curNumber <= pMotor->lastNumber) {
+ deltaValue = pMotor->lastNumber - pMotor->curNumber;
+ }else{ //过零点后的计算编码器差值
+ deltaValue = (pMotor->lastNumber + g_motorLineNum) - pMotor->curNumber ;
+ }
+ }
+
+ /* 电机正反转切换时,会出现编码器差值计算错误,设置编码器差值为0 */
+ if(pMotor->calPeriod == MOTOR_PID_CONTROL_PERIOD){
+ if(deltaValue > g_maxEncodePidDeltaValue) {
+ DBG_PRINTF("===Motor Encode Error = %d, motor side:%d, calculate period %dms===\r\n", deltaValue,pMotor->motorSide,pMotor->calPeriod);
+ deltaValue = 0;
+ }
+ }else{
+ if(deltaValue > g_maxEncodeAveDeltaValue) {
+ DBG_PRINTF("===Motor Encode Error = %d, motor side:%d, calculate period %dms===\r\n", deltaValue,pMotor->motorSide,pMotor->calPeriod);
+ deltaValue = 0;
+ }
+ }
+
+
+ /* 计算右轮电机每秒转速 */
+ pMotor->speedRps = ((float)deltaValue * (1000.0 / (float)pMotor->calPeriod))/g_motorLineNum;
+ pMotor->speed = pMotor->speedRps * MOTOR_TIRE_DIAMETER * PI;
+ pMotor->lastNumber = pMotor->curNumber;
+ pMotor->deltaValue = deltaValue;
+ if(qdm_dir == 0){ //电机反转
+ pMotor->speed = -pMotor->speed;
+ }
+
+ /*每10ms打印一次编码器实际数值和计算出来的速度
+ if(pMotor->motorSide == MOTOR_LEFT){
+ if((g_TimerInterruptCount % 100) == 0) {
+ if((deltaValue != 0) ) { //编码器数值有变化才进行打印
+ DBG_PRINTF("T:%d|qc:%d,d:%d,dr:%d,crs:%.02f,rs:%.01f\r\n",
+ g_TimerInterruptCount,qdm_cnt,pMotor->deltaValue,qdm_dir,pMotor->speedRps,pMotor->speed);
+ }
+ }
+ }*/
+
+}
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/encoder.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/encoder.h
new file mode 100644
index 0000000000000000000000000000000000000000..0ee1864fe38014b86825e0fcb41b893c24f32f45
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/encoder.h
@@ -0,0 +1,26 @@
+#ifndef ENCODER_H
+#define ENCODER_H
+
+#define PI 3.1415927
+
+#define MOTOR_LEFT 0
+#define MOTOR_RIGHT 1
+
+#define MOTOR_PID_CONTROL_PERIOD 10 //编码器读取周期,单位ms
+#define EULER_CAR_DATA_SEND_PERIOD 200 //底盘数据上报上位机的周期,单位ms
+
+typedef struct _Gear_Motor_handle {
+ unsigned int motorSide; /* 当前是那个轮子*/
+ unsigned int curNumber; /* 当前计数器 */
+ unsigned int lastNumber; /* 上一次计数器 */
+ float speedRps; /* 电机转速,单位每秒多少圈 */
+ float speed; /* 电机速度,单位mm/s,由转速和轮胎直径计算 */
+ unsigned int calPeriod; /* 轮速计算周期, 单位ms */
+ unsigned int deltaValue; /* 编码器差值 */
+} Gear_Motor_handle;
+
+
+void InitGearMotor(void);
+void QDM_CalMotorSpeed(Gear_Motor_handle *pMotor);
+
+#endif
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/eulercar_control.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/eulercar_control.c
new file mode 100644
index 0000000000000000000000000000000000000000..34198690430bda2dc83e3505ebe9d97d48b4c3b4
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/eulercar_control.c
@@ -0,0 +1,457 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "user_motor_control.h"
+#include "eulercar_control.h"
+#include "uart.h"
+#include "pid.h"
+#include "button.h"
+#include "encoder.h"
+
+unsigned char g_MotorState; //电机状态
+
+EulerCarSendData g_SendData; //串口发送数据
+EulerCarRecvData g_ReceiveData; //串口接收数据
+static unsigned char g_ReceiveDataCount = 0;
+
+extern unsigned int g_pid_count;
+extern PidEulerCar g_pidEulerCarRight;
+extern PidEulerCar g_pidEulerCarLeft;
+extern Gear_Motor_handle pidRightMotor;
+extern Gear_Motor_handle pidLeftMotor;
+extern Gear_Motor_handle aveRightMotor;
+extern Gear_Motor_handle aveLeftMotor;
+
+
+//按键状态
+extern int g_button1State;
+extern int g_button2State;
+
+//按键滤波计数器
+extern int g_button1_count;
+extern int g_button2_count;
+
+//通过按键调整PID参数的步进参数
+extern float g_KP_Step;
+extern float g_KI_Step;
+extern float g_KD_Step;
+
+/* 接收完成标志 */
+static volatile bool g_RxInterruptflag = true;
+/* 发送完成标志 */
+static volatile bool g_TxInterruptFlag = true;
+
+/* 定时器中断计数器 */
+unsigned int g_TimerInterruptCount = 0;
+
+/* 上报数据给上位机计数器 */
+static unsigned int g_SendCount = 0;
+
+/* 上位机下发命令计数器 */
+static unsigned int g_RecvCount = 0;
+
+//小车三轴目标运动速度,单位:m/s
+float Move_X, Move_Y, Move_Z;
+
+#define EULERCAR_WHEEL_TRACK 120.0 //EulerCar小车两个轮子之间的轮距,单位mm
+float modelCalLeftSpeed = 0.0; //根据两轮差速小车模型计算出的左轮速度
+float modelCalRightSpeed = 0.0; //根据两轮差速小车模型计算出的右轮速度
+
+#define IS_SUPPORT_PID 1
+
+/* 串口发送的数据进行赋值 */
+static void data_transition(void)
+{
+ float A_Move_X,A_Move_Z;
+
+ g_SendData.SensorStr.Frame_Header = FRAME_HEADER; //帧头
+ g_SendData.SensorStr.Frame_Tail = FRAME_TAIL; //帧尾
+
+ //从各车轮当前速度求出三轴当前速度
+ A_Move_X = (aveRightMotor.speed + aveLeftMotor.speed) / 2.0; //小车x轴速度,单位mm/s
+ A_Move_Z = (aveRightMotor.speed - aveLeftMotor.speed) / (EULERCAR_WHEEL_TRACK * 2.0) * 1000.0; //小车角速度, 单位mrad/s
+
+ g_SendData.SensorStr.X_speed = (short)(round(A_Move_X)); //小车x轴速度,单位mm/s
+ g_SendData.SensorStr.Y_speed = 0;
+ g_SendData.SensorStr.Z_speed = (short)(round(A_Move_Z)); //小车角速度,单位mm/s
+
+/*
+ DBG_PRINTF("ActualeftSpeed:%.2fmm/s,ActualRightSpeed:%.2fmm/s,A_Move_X=%.2fmm/s,A_Move_Z=%.2fmrad/s\r\n",
+ aveLeftMotor.speed,aveRightMotor.speed,A_Move_X,A_Move_Z);
+*/
+
+ //加速度计三轴加速度
+ g_SendData.SensorStr.Accelerometer.X_data = 1; //加速度计Y轴转换到ROS坐标X轴
+ g_SendData.SensorStr.Accelerometer.Y_data = 1; //加速度计X轴转换到ROS坐标Y轴
+ g_SendData.SensorStr.Accelerometer.Z_data = 1; //加速度计Z轴转换到ROS坐标Z轴
+
+ //角速度计三轴角速度
+ g_SendData.SensorStr.Gyroscope.X_data = 2; //角速度计Y轴转换到ROS坐标X轴
+ g_SendData.SensorStr.Gyroscope.Y_data = 2; //角速度计X轴转换到ROS坐标Y轴
+ if (g_MotorState == 0)
+ //如果电机控制位使能状态,那么正常发送Z轴角速度
+ g_SendData.SensorStr.Gyroscope.Z_data = 1;
+ else
+ //如果机器人是静止的(电机控制位失能),那么发送的Z轴角速度为0
+ g_SendData.SensorStr.Gyroscope.Z_data = 0;
+
+ //电池电压(这里将浮点数放大一千倍传输,相应的在接收端在接收到数据后也会缩小一千倍)
+ g_SendData.SensorStr.Power_Voltage = 90;
+
+ g_SendData.buffer[0] = g_SendData.SensorStr.Frame_Header; // 帧头
+ g_SendData.buffer[1] = g_MotorState; // 小车软件失能标志位
+
+ //小车三轴速度,各轴都拆分为两个8位数据再发送
+ g_SendData.buffer[2] = g_SendData.SensorStr.X_speed >> 8;
+ g_SendData.buffer[3] = g_SendData.SensorStr.X_speed;
+ g_SendData.buffer[4] = g_SendData.SensorStr.Y_speed >> 8;
+ g_SendData.buffer[5] = g_SendData.SensorStr.Y_speed;
+ g_SendData.buffer[6] = g_SendData.SensorStr.Z_speed >> 8;
+ g_SendData.buffer[7] = g_SendData.SensorStr.Z_speed;
+
+ //IMU加速度计三轴加速度,各轴都拆分为两个8位数据再发送
+ g_SendData.buffer[8] = g_SendData.SensorStr.Accelerometer.X_data >> 8;
+ g_SendData.buffer[9] = g_SendData.SensorStr.Accelerometer.X_data;
+ g_SendData.buffer[10] = g_SendData.SensorStr.Accelerometer.Y_data >> 8;
+ g_SendData.buffer[11] = g_SendData.SensorStr.Accelerometer.Y_data;
+ g_SendData.buffer[12] = g_SendData.SensorStr.Accelerometer.Z_data >> 8;
+ g_SendData.buffer[13] = g_SendData.SensorStr.Accelerometer.Z_data;
+
+ //IMU角速度计三轴角速度,各轴都拆分为两个8位数据再发送
+ g_SendData.buffer[14] = g_SendData.SensorStr.Gyroscope.X_data >> 8;
+ g_SendData.buffer[15] = g_SendData.SensorStr.Gyroscope.X_data;
+ g_SendData.buffer[16] = g_SendData.SensorStr.Gyroscope.Y_data >> 8;
+ g_SendData.buffer[17] = g_SendData.SensorStr.Gyroscope.Y_data;
+ g_SendData.buffer[18] = g_SendData.SensorStr.Gyroscope.Z_data >> 8;
+ g_SendData.buffer[19] = g_SendData.SensorStr.Gyroscope.Z_data;
+
+ //电池电压,拆分为两个8位数据发送
+ g_SendData.buffer[20] = g_SendData.SensorStr.Power_Voltage >> 8;
+ g_SendData.buffer[21] = g_SendData.SensorStr.Power_Voltage;
+
+ //数据校验位计算
+ unsigned char check_sum = 0, k;
+ for (k = 0; k < 22; k++) {
+ check_sum = check_sum ^ g_SendData.buffer[k];
+ }
+ g_SendData.buffer[22] = check_sum;
+ g_SendData.buffer[23] = g_SendData.SensorStr.Frame_Tail; //帧尾
+}
+
+void debug_send_buffer(unsigned int count)
+{
+ DBG_PRINTF("-----------------send_count=%u-----------------\r\n", count);
+ for (size_t i = 0; i < SEND_DATA_SIZE; i++) {
+ DBG_PRINTF("0x%x ", g_SendData.buffer[i]);
+ }
+ DBG_PRINTF(" \r\n");
+}
+
+void UART3WriteInterruptCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ //DBG_PRINTF("\r\nUART Write Finish\r\n");
+ g_TxInterruptFlag = true;
+ return;
+}
+
+void UART3ReadInterruptCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ g_RxInterruptflag = 1;
+ return;
+}
+
+// 定时器10ms产生一个中断
+void TIMER0_InterruptProcess(void *handle)
+{
+ BASE_StatusType ret;
+ /* USER CODE BEGIN TIMER0_InterruptProcess */
+ TIMER_Handle *timerHandle = (TIMER_Handle *)handle;
+ BASE_FUNC_UNUSED(timerHandle);
+ g_TimerInterruptCount++;
+
+ //按键滤波,500毫秒内算一次按键
+ if(g_button1_count > 0)
+ {
+ g_button1_count ++;
+ if(g_button1_count > 50){
+ g_button1_count = 0;
+ //DBG_PRINTF("Button1 Count Reset 0\r\n");
+ }
+ }
+
+ if(g_button2_count > 0)
+ {
+ g_button2_count ++;
+ if(g_button2_count > 50){
+ g_button2_count = 0;
+ //DBG_PRINTF("Button2 Count Reset 0\r\n");
+ }
+ }
+
+ //按设置周期上报底盘数据
+ if ((g_TimerInterruptCount % (EULER_CAR_DATA_SEND_PERIOD/10)) == 0) {
+ if (g_TxInterruptFlag) {
+ g_TxInterruptFlag = false;
+ //获取小车要发送的数据
+ QDM_CalMotorSpeed(&aveLeftMotor); //计算左轮平均速度
+ QDM_CalMotorSpeed(&aveRightMotor); //计算右轮平均速度
+ data_transition();
+
+ ret = HAL_UART_WriteIT(&g_uart3, g_SendData.buffer, SEND_DATA_SIZE);
+
+ if(ret == BASE_STATUS_OK) {
+ //DBG_PRINTF("Data send OK, send count = %d\r\n",g_SendCount);
+ }else{
+ DBG_PRINTF("Data send error, code = %d\r\n",ret);
+ }
+ g_SendCount++;
+ }
+ }
+
+ //每间隔10毫秒进行一次PID电机控制
+ if (g_TimerInterruptCount % (MOTOR_PID_CONTROL_PERIOD / 10) == 0) {
+ //获取小车运行实际速度
+ QDM_CalMotorSpeed(&pidLeftMotor); //计算一个PID周期内左轮速度
+ QDM_CalMotorSpeed(&pidRightMotor); //计算一个PID周期内右轮速度
+
+ g_pidEulerCarLeft.ActualSpeed = pidLeftMotor.speed;
+ g_pidEulerCarRight.ActualSpeed = pidRightMotor.speed;
+
+ //如果上位机下发速度大于0.1mm/s,则启动PID控制
+ if ((fabsf(modelCalLeftSpeed) > 0.1) || (fabsf(modelCalRightSpeed) > 0.1)) {
+ Pid_Process();
+ }
+ }
+
+}
+
+static float XYZ_transition(unsigned char High, unsigned char Low)
+{
+ short transition = ((High << 8) + Low); //将高8位和低8位整合成一个16位的short型数据
+ //return transition / 1000 + (transition % 1000) * 0.001; //单位转换, mm/s->m/s
+ return (float)transition;
+}
+
+int EulerCarSpeedCtrlLeft(float LeftSpeed)
+{
+
+ unsigned int duty = (abs)((int)(LeftSpeed/g_motorMaxSpeed * 100));
+ if (duty > 99) {
+ duty = 35;
+ }
+ //DBG_PRINTF("left wheel duty:%d\r\n", duty);
+ HAL_APT_SetPWMDutyByNumber(&g_apt1, duty);
+
+ //如果电机小于0.1mm/s,则停止电机转动
+ if (fabsf(LeftSpeed) < 0.1) {
+ HAL_APT_StopModule(RUN_APT1);
+ return 0;
+ }
+ if (LeftSpeed > 0) {
+ User_APTPwmARecovery(g_apt1.baseAddress);
+ User_APTForcePWMBOutputLow(g_apt1.baseAddress);
+ } else {
+ User_APTPwmBRecovery(g_apt1.baseAddress);
+ User_APTForcePWMAOutputLow(g_apt1.baseAddress);
+ }
+ HAL_APT_StartModule(RUN_APT1);
+ //DBG_PRINTF("Left wheel set duty:%d, run ok!\r\n",duty);
+
+ return 0;
+}
+
+int EulerCarSpeedCtrlRight(float rightSpeed)
+{
+ unsigned int duty = (abs)((int)(rightSpeed/g_motorMaxSpeed * 100));
+ if (duty > 99) {
+ duty = 35;
+ }
+ HAL_APT_SetPWMDutyByNumber(&g_apt0, duty);
+
+ //如果电机小于0.1mm/s,则停止电机转动
+ if (fabsf(rightSpeed) < 0.1) {
+ HAL_APT_StopModule(RUN_APT0);
+ return 0;
+ }
+ if (rightSpeed > 0) {
+ User_APTPwmARecovery(g_apt0.baseAddress);
+ User_APTForcePWMBOutputLow(g_apt0.baseAddress);
+ } else {
+ User_APTPwmBRecovery(g_apt0.baseAddress);
+ User_APTForcePWMAOutputLow(g_apt0.baseAddress);
+ }
+ HAL_APT_StartModule(RUN_APT0);
+ //DBG_PRINTF("Right wheel set duty:%d, run ok!\r\n",duty);
+
+ return 0;
+}
+
+void Pid_Process(void)
+{
+ float pidTargetSpeed;
+ g_pid_count++;
+
+ /* 通过PID算法计算右轮目标速度 */
+ pidTargetSpeed = Pid_Ctrl(&g_pidEulerCarRight);
+ EulerCarSpeedCtrlRight(pidTargetSpeed);
+
+ /* 通过PID算法计算左轮目标速度 */
+ pidTargetSpeed = Pid_Ctrl(&g_pidEulerCarLeft);
+ EulerCarSpeedCtrlLeft(pidTargetSpeed);
+
+ /*
+ //左右轮同时打印
+ if((g_TimerInterruptCount % 10) == 0) {
+ DBG_PRINTF("N=%d,P=%.02f,I=%.02f,D=%.02f|L-SS:%.1f,AS:%.1f,err:%.1f,nr:%.1f,lr:%.1f,in:%.1f,TS:%.1f,dt:%d|R-SS:%.1f,AS:%.1f,err:%.1f,nr:%.1f,lr:%.1f,in:%.f,TS:%.1f,dt:%d\r\n",
+ g_pid_count,g_KP,g_KI,g_KD,g_pidEulerCarRight.SetSpeed,g_pidEulerCarRight.ActualSpeed,
+ g_pidEulerCarRight.err,g_pidEulerCarRight.err_next,g_pidEulerCarRight.err_last,g_pidEulerCarRight.IncSpeed,
+ g_pidEulerCarRight.TargetIncSpeed,g_pidEulerCarRight.duty,
+ g_pidEulerCarLeft.SetSpeed,g_pidEulerCarLeft.ActualSpeed,
+ g_pidEulerCarLeft.err,g_pidEulerCarLeft.err_next,g_pidEulerCarLeft.err_last,g_pidEulerCarLeft.IncSpeed,
+ g_pidEulerCarLeft.TargetIncSpeed,g_pidEulerCarLeft.duty);
+ }
+
+ //打印电机运行情况
+ if((g_TimerInterruptCount % 10) == 0) {
+ DBG_PRINTF("N=%d|L-SS:%.1f,AS:%.1f,err:%.1f,nr:%.1f,in:%.1f,TS:%.1f,dt:%d|R-SS:%.1f,AS:%.1f,err:%.1f,nr:%.1f,in:%.f,TS:%.1f,dt:%d\r\n",
+ g_pid_count,g_pidEulerCarRight.SetSpeed,g_pidEulerCarRight.ActualSpeed,
+ g_pidEulerCarRight.err,g_pidEulerCarRight.err_next,g_pidEulerCarRight.IncSpeed,
+ g_pidEulerCarRight.TargetIncSpeed,g_pidEulerCarRight.duty,
+ g_pidEulerCarLeft.SetSpeed,g_pidEulerCarLeft.ActualSpeed,
+ g_pidEulerCarLeft.err,g_pidEulerCarLeft.err_next,g_pidEulerCarLeft.IncSpeed,
+ g_pidEulerCarLeft.TargetIncSpeed,g_pidEulerCarLeft.duty);
+ }
+
+
+ //左右轮同时打印
+ if((g_TimerInterruptCount % 10) == 0) {
+ DBG_PRINTF("N=%d,P=%.02f,I=%.02f,D=%.02f|L-SS:%.1f,AS:%.1f,err:%.1f,nr:%.1f,lr:%.1f,in:%.1f,TS:%.1f,dt:%d|R-SS:%.1f,AS:%.1f,err:%.1f,nr:%.1f,lr:%.1f,in:%.f,TS:%.1f,dt:%d\r\n",
+ g_pid_count,g_KP,g_KI,g_KD,g_pidEulerCarRight.SetSpeed,g_pidEulerCarRight.ActualSpeed,
+ g_pidEulerCarRight.err,g_pidEulerCarRight.err_next,g_pidEulerCarRight.err_last,g_pidEulerCarRight.IncSpeed,
+ g_pidEulerCarRight.TargetIncSpeed,g_pidEulerCarRight.duty,
+ g_pidEulerCarLeft.SetSpeed,g_pidEulerCarLeft.ActualSpeed,
+ g_pidEulerCarLeft.err,g_pidEulerCarLeft.err_next,g_pidEulerCarLeft.err_last,g_pidEulerCarLeft.IncSpeed,
+ g_pidEulerCarLeft.TargetIncSpeed,g_pidEulerCarLeft.duty);
+ }
+
+ //只打印右轮
+ if((g_TimerInterruptCount % 10) == 0) {
+ DBG_PRINTF("N=%d,P=%.02f,I=%.02f,D=%.02f|R-SS:%.1f,AS:%.1f,err:%.1f,nr:%.1f,lr:%.1f,in:%.1f,TS:%.1f,dt:%d\r\n",
+ g_pid_count,g_KP,g_KI,g_KD,g_pidEulerCarRight.SetSpeed,
+ g_pidEulerCarRight.ActualSpeed,g_pidEulerCarRight.err,g_pidEulerCarRight.err_next,g_pidEulerCarRight.err_last,
+ g_pidEulerCarRight.IncSpeed,g_pidEulerCarRight.TargetIncSpeed,g_pidEulerCarRight.duty);
+ }
+
+ //只打印左轮
+ if((g_TimerInterruptCount % 100) == 0) {
+ DBG_PRINTF("N=%d,P=%.02f,I=%.02f,D=%.02f|L-SS:%.1f,AS:%.1f,err:%.1f,nr:%.1f,lr:%.1f,in:%.1f,TS:%.1f,dt:%d\r\n",
+ g_pid_count,g_KP,g_KI,g_KD,g_pidEulerCarLeft.SetSpeed,
+ g_pidEulerCarLeft.ActualSpeed,g_pidEulerCarLeft.err,g_pidEulerCarLeft.err_next,g_pidEulerCarLeft.err_last,
+ g_pidEulerCarLeft.IncSpeed,g_pidEulerCarLeft.TargetIncSpeed,g_pidEulerCarLeft.duty);
+ } */
+}
+
+void recv_data_cal(void)
+{
+ float x_linear,z_angular;
+
+ g_ReceiveData.ControlStr.X_speed = Move_X;
+ g_ReceiveData.ControlStr.Y_speed = Move_Y;
+ g_ReceiveData.ControlStr.Z_speed = Move_Z;
+ x_linear = g_ReceiveData.ControlStr.X_speed;
+ z_angular = g_ReceiveData.ControlStr.Z_speed;
+ //DBG_PRINTF("x_speed:%.02f, Z_speed:%.02f\r\n", g_ReceiveData.ControlStr.X_speed, g_ReceiveData.ControlStr.Z_speed);
+ //差分轮运动学模型求解
+ modelCalLeftSpeed = x_linear - z_angular * EULERCAR_WHEEL_TRACK / 2.0 / 1000.0; //左轮速度,单位mm/s
+ modelCalRightSpeed = x_linear + z_angular * EULERCAR_WHEEL_TRACK / 2.0 / 1000.0; //右轮速度,单位mm/s
+ DBG_PRINTF("modelCalLeftSpeed:%.2fmm/s, modelCalRightSpeed:%.2fmm/s\r\n", modelCalLeftSpeed, modelCalRightSpeed);
+
+ //将上位机设置轮速存到PID控制结构体
+ g_pidEulerCarLeft.SetSpeed = modelCalLeftSpeed;
+ g_pidEulerCarRight.SetSpeed = modelCalRightSpeed;
+
+ //如果上位机下发速度小于0.1mm/s,小车停止运动
+ if((fabsf(modelCalLeftSpeed) < 0.1) && (fabsf(modelCalRightSpeed) < 0.1))
+ {
+ EulerCarSpeedCtrlRight(0);
+ EulerCarSpeedCtrlLeft(0);
+ //DBG_PRINTF("EulerCar stoped!!!\r\n");
+ }
+}
+
+void UART3_INTRxSimultaneously(void)
+{
+ float tmp_X,tmp_Y,tmp_Z;
+ unsigned char k,Usart_Receive,check_sum;
+
+ while (1) {
+ if (g_RxInterruptflag) {
+ g_RxInterruptflag = false;
+ HAL_UART_ReadIT(&g_uart3, &Usart_Receive, 1); // 读取数据
+ g_ReceiveData.buffer[g_ReceiveDataCount] = Usart_Receive;
+ //确保数组第一个数据为FRAME_HEADER
+ if (Usart_Receive == FRAME_HEADER || g_ReceiveDataCount > 0) {
+ g_ReceiveDataCount++;
+ }
+ else {
+ g_ReceiveDataCount = 0;
+ }
+ // 验证数据包的长度
+ if (g_ReceiveDataCount == RECEIVE_DATA_SIZE) {
+ g_ReceiveDataCount = 0; //为串口数据重新填入数组做准备
+ //验证数据包的帧尾
+ if (g_ReceiveData.buffer[10] == FRAME_TAIL) {
+ check_sum = 0;
+ for (k = 0; k < 9; k++) {
+ check_sum = check_sum ^ g_ReceiveData.buffer[k];
+ }
+ //数据异或位校验计算,模式0是发送数据校验
+ if (g_ReceiveData.buffer[9] == check_sum) {
+ g_RecvCount++;
+ //从串口数据求三轴目标速度, 单位mm/s
+ tmp_X = XYZ_transition(g_ReceiveData.buffer[3], g_ReceiveData.buffer[4]);
+ tmp_Y = XYZ_transition(g_ReceiveData.buffer[5], g_ReceiveData.buffer[6]);
+ tmp_Z = XYZ_transition(g_ReceiveData.buffer[7], g_ReceiveData.buffer[8]);
+ //合法性检查,设置速度必须小于当前电机支持的最高速度
+ if( (fabsf(tmp_X) < g_motorMaxSpeed) && (fabsf(tmp_Y) < g_motorMaxSpeed) && (fabsf(tmp_Z) < MOTOR_MAX_ANGULAR_SPEED) ) {
+ Move_X = tmp_X;
+ Move_Y = tmp_Y;
+ Move_Z = tmp_Z;
+ DBG_PRINTF("\r\ng_TimerCount=%d,g_RecvCount=%d,Move_X=%.2fmm/s,Move_Y=%.2fmm/s,Move_Z=%.2fmrad/s\r\n",
+ g_TimerInterruptCount,g_RecvCount, Move_X, Move_Y, Move_Z);
+ recv_data_cal();
+ }
+ else{
+ DBG_PRINTF("\r\ng_TimerCount=%d,g_RecvCount=%d",g_TimerInterruptCount,g_RecvCount);
+ if((fabsf(tmp_X) > g_motorMaxSpeed) || (fabsf(tmp_Y) > g_motorMaxSpeed))
+ DBG_PRINTF("\r\nLinear speed set error: X=%.2fmm/s Y=%.2fmm/s, must less %.2fmm/s\r\n", tmp_X, tmp_Y,g_motorMaxSpeed);
+ if((fabsf(tmp_Z) > MOTOR_MAX_ANGULAR_SPEED))
+ DBG_PRINTF("\r\nAngular speed set error: Z=%.2fmrad/s, must less %.1fmrad/s\r\n", tmp_Z, MOTOR_MAX_ANGULAR_SPEED);
+ }
+ }
+ }
+ }
+ }
+
+ //检测按键是否按下,修改PID参数
+ if (g_button1State == 1) {
+ g_button1State = 0;
+ g_KP = g_KP + g_KP_Step;
+ DBG_PRINTF("Button1 Evnet, g_KP + %f\r\n",g_KP_Step);
+ DBG_PRINTF("g_KP=%f g_KI=%f g_KD=%f\r\n", g_KP, g_KI, g_KD);
+ }
+
+ if (g_button2State == 1) {
+ g_button2State = 0;
+ g_KI = g_KI + g_KI_Step;
+ DBG_PRINTF("Button2 Evnet, g_KI + %f\r\n",g_KI_Step);
+ DBG_PRINTF("g_KP=%f g_KI=%f g_KD=%f\r\n", g_KP, g_KI, g_KD);
+ }
+ }
+}
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/eulercar_control.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/eulercar_control.h
new file mode 100644
index 0000000000000000000000000000000000000000..16d047b35ce76610b58cfa3c69c60be6e5c49b99
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/eulercar_control.h
@@ -0,0 +1,67 @@
+#ifndef EULERCAR_TIMER_H
+#define EULERCAR_TIMER_H
+
+#include "debug.h"
+#include "timer.h"
+#include "main.h"
+
+#define REQUIRE_TIME_IT 5000
+
+#define FRAME_HEADER 0X7B // Frame_header //帧头
+#define FRAME_TAIL 0X7D // Frame_tail //帧尾
+
+#define SEND_DATA_SIZE 24
+#define RECEIVE_DATA_SIZE 11
+
+/* 用于存放陀螺仪加速度计三轴数据的结构体 */
+typedef struct __Mpu6050_Data_
+{
+ short X_data; // 2 bytes //2个字节
+ short Y_data; // 2 bytes //2个字节
+ short Z_data; // 2 bytes //2个字节
+} Mpu6050_Data;
+
+typedef struct _EulerCarSendData_
+{
+ unsigned char buffer[SEND_DATA_SIZE];
+ struct _SensorStr_
+ {
+ unsigned char Frame_Header; // 帧头
+ short X_speed; // 运动模型的X轴
+ short Y_speed; // 运动模型的Y轴
+ short Z_speed; // 运动模型的Z轴
+ short Power_Voltage; // 电池电压
+ Mpu6050_Data Accelerometer; // 加速度计的三轴加速度
+ Mpu6050_Data Gyroscope; // 角速度计的三轴角速度
+ unsigned char Frame_Tail; // 帧尾
+ } SensorStr;
+} EulerCarSendData;
+
+typedef struct _MotorData_
+{
+ float leftSpeed; // 使用M法获取当前左轮的旋转速度
+ float rightSpeed; //使用M法获取当前右轮的旋转速度
+ unsigned int count; // 当前位置计数器的值
+ unsigned int dir;// 和旋转的方向
+} Motor_Data;
+
+typedef struct _RECEIVE_DATA_
+{
+ unsigned char buffer[RECEIVE_DATA_SIZE];
+ struct _ControlStr_
+ {
+ unsigned char Frame_Header; // 1 bytes //1个字节
+ float X_speed; // 4 bytes //4个字节
+ float Y_speed; // 4 bytes //4个字节
+ float Z_speed; // Z轴角速度4 bytes //4个字节
+ unsigned char Frame_Tail; // 1 bytes //1个字节
+ } ControlStr;
+} EulerCarRecvData;
+
+void Pid_Process(void);
+void recv_data_cal(void);
+int EulerCarSpeedCtrlLeft(float LeftSpeed);
+int EulerCarSpeedCtrlRight(float rightSpeed);
+void UART3_INTRxSimultaneously(void);
+void debug_send_buffer(unsigned int count);
+#endif
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/generatecode/feature.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/generatecode/feature.h
new file mode 100644
index 0000000000000000000000000000000000000000..e8e6b1405e2a2d2ab0bbe44408ad13414ea290a8
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/generatecode/feature.h
@@ -0,0 +1,116 @@
+/**
+ * @copyright Copyright (c) 2022, HiSilicon (Shanghai) Technologies Co., Ltd. All rights reserved.
+ * 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 the copyright holder 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.
+ * @file feature.h
+ * @author MCU Driver Team
+ * @brief This file contains macro configurations related to the project. This file is generated by the IDE tool.
+ */
+
+#ifndef McuMagicTag_FEATURE_H
+#define McuMagicTag_FEATURE_H
+
+/* Macro definitions --------------------------------------------------------- */
+#define CHIP_ZDU3061MNPICA MACRO_ENABLE
+
+#define MACRO_ENABLE 1
+#define MACRO_DISABLE 0
+
+/* Macro switch */
+#define BASE_DEFINE_USE_ASSERT MACRO_ENABLE
+#ifndef FLASH_CRC_CONFIG
+#define FLASH_CRC_CONFIG
+#endif /* #ifndef FLASH_CRC_CONFIG */
+#define BASE_MATH_SINCOS_MIDDLE_TABLE MACRO_ENABLE /**< This macro is used to control the table type when the
+ BASE_MATH_GetSinCos() queries the table. When the value of
+ this macro is MACRO_ENABLE, the error value obtained by the
+ BASE_MATH_GetSinCos() is relatively small, and the return
+ value of the function may be greater than or less than the
+ actual value. When the value of this macro is MACRO_DISABLE,
+ the error value obtained by the BASE_MATH_GetSinCos() is
+ relatively large. However, in the range [0°, 180°) and
+ [180°, 360°), the return value of the function is either
+ greater than or less than the actual value. */
+
+#define MCS_PARAM_CHECK MACRO_ENABLE
+#define APT_PARAM_CHECK MACRO_ENABLE
+#define ADC_PARAM_CHECK MACRO_ENABLE
+#define CAPM_PARAM_CHECK MACRO_ENABLE
+#define CRG_PARAM_CHECK MACRO_ENABLE
+#define I2C_PARAM_CHECK MACRO_ENABLE
+#define UART_PARAM_CHECK MACRO_ENABLE
+#define SPI_PARAM_CHECK MACRO_ENABLE
+#define TIMER_PARAM_CHECK MACRO_ENABLE
+#define IWDG_PARAM_CHECK MACRO_ENABLE
+#define WWDG_PARAM_CHECK MACRO_ENABLE
+#define GPIO_PARAM_CHECK MACRO_ENABLE
+#define GPT_PARAM_CHECK MACRO_ENABLE
+#define DMA_PARAM_CHECK MACRO_ENABLE
+#define CRC_PARAM_CHECK MACRO_ENABLE
+#define CFD_PARAM_CHECK MACRO_ENABLE
+#define CMM_PARAM_CHECK MACRO_ENABLE
+#define CAN_PARAM_CHECK MACRO_ENABLE
+#define FLASH_PARAM_CHECK MACRO_ENABLE
+#define PMC_PARAM_CHECK MACRO_ENABLE
+#define ACMP_PARAM_CHECK MACRO_ENABLE
+#define DAC_PARAM_CHECK MACRO_ENABLE
+#define PGA_PARAM_CHECK MACRO_ENABLE
+#define USER_MODE_ENABLE MACRO_ENABLE
+#define IOCMG_PARAM_CHECK MACRO_ENABLE
+#define QDM_PARAM_CHECK MACRO_ENABLE
+
+/* Peripheral module macro switch--------------------------------------------- */
+#define BOARD_DIM_NUM 1 /**< Number of dimming handle arrays. */
+
+#define BOARD_KEY_NUM 10 /**< Number of key handle arrays. */
+#define BOARD_KEY_PRESS_ON GPIO_HIGH_LEVEL /**< GPIO status corresponding to long press valid. */
+#define BOARD_KEY_PRESS_OFF GPIO_LOW_LEVEL /**< GPIO status corresponding to short press valid. */
+
+#define BOARD_LED_SEG_NUM 4 /**< Number of segments. */
+#define BOARD_LED_SEGMENT_ON GPIO_HIGH_LEVEL /**< GPIO level status corresponding to valid segments. */
+#define BOARD_LED_SEGMENT_OFF GPIO_LOW_LEVEL /**< GPIO level status corresponding to invalid segments. */
+
+#define BOARD_MKEY_SCHEME_NUMBER BOARD_MKEY_SCHEME_NUMBER_ONE /**< Define the scheme to be adopted. */
+#define BOARD_MKEY_OUT_NUM 4 /**< Number of GPIO pins used as output during scanning. */
+#define BOARD_MKEY_IN_NUM 4 /**< Number of GPIO pins used as input during scanning. */
+#define BOARD_MKEY_OUT_PIN_VALID GPIO_LOW_LEVEL /**< GPIO level status corresponding to the valid \
+ status of the output GPIO in the key matrix. */
+#define BOARD_MKEY_OUT_PIN_INVALID GPIO_HIGH_LEVEL /**< GPIO level status corresponding to the \
+ invalid status of the output GPIO in the key matrix. */
+#define BOARD_MKEY_IN_PIN_VALID GPIO_LOW_LEVEL /**< Indicates the GPIO level corresponding to the \
+ valid status of the input GPIO in the key matrix. */
+#define BOARD_MKEY_IN_PIN_INVALID GPIO_HIGH_LEVEL /**< Indicates the GPIO level corresponding to the \
+ invalid status of the input GPIO in the key matrix. */
+
+#define BOARD_PULSES_NUM 2 /**< Number of pulse handles. */
+
+#define BASE_DEFINE_SLIPAVERAGE_NUM 2 /**< Sliding average array length. */
+
+#define LISTNODE_MAX 20
+
+#define BASE_DEFINE_DMA_QUICKSTART
+
+#define XTRAIL_FREQ 30000000U
+
+#define DBG_USE_NO_PRINTF 0U
+#define DBG_USE_UART_PRINTF 1U
+
+#define DBG_PRINTF_USE DBG_USE_UART_PRINTF
+#if (DBG_PRINTF_USE == DBG_USE_UART_PRINTF)
+#define DBG_PRINTF_UART_PORT UART2
+#endif
+
+#endif /* McuMagicTag_FEATURE_H */
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/generatecode/main.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/generatecode/main.h
new file mode 100644
index 0000000000000000000000000000000000000000..5fddda212f9fcb30931cac43a22cc674fb1f7aa0
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/generatecode/main.h
@@ -0,0 +1,140 @@
+/**
+ * @copyright Copyright (c) 2022, HiSilicon (Shanghai) Technologies Co., Ltd. All rights reserved.
+ * 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 the copyright holder 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.
+ * @file main.h
+ * @author MCU Driver Team
+ * @brief This file contains driver init functions.
+ */
+
+/* Define to prevent recursive inclusion ------------------------------------- */
+#ifndef McuMagicTag_SYSTEM_INIT_H
+#define McuMagicTag_SYSTEM_INIT_H
+
+#include "adc.h"
+#include "adc_ex.h"
+#include "apt.h"
+#include "uart.h"
+#include "uart_ex.h"
+#include "i2c.h"
+#include "i2c_ex.h"
+#include "can.h"
+#include "qdm.h"
+#include "gpio.h"
+#include "gpt.h"
+#include "gpt_ex.h"
+#include "timer.h"
+#include "timer_ex.h"
+#include "crg.h"
+#include "iocmg.h"
+
+#define IO_SPEED_FAST 0x00U
+#define IO_SPEED_SLOW 0x01U
+
+#define IO_DRV_LEVEL4 0x00U
+#define IO_DRV_LEVEL3 0x01U
+#define IO_DRV_LEVEL2 0x02U
+#define IO_DRV_LEVEL1 0x03U
+
+#define XTAL_DRV_LEVEL4 0x03U
+#define XTAL_DRV_LEVEL3 0x02U
+#define XTAL_DRV_LEVEL2 0x01U
+#define XTAL_DRV_LEVEL1 0x00U
+
+#define MOTOR_TYPE_GEAR_HALL_45 0
+#define MOTOR_TYPE_GEAR_GMR_45 1
+#define MOTOR_TYPE_GEAR_HALL_90 2
+#define MOTOR_TYPE_GEAR_GMR_90 3
+
+#define MOTOR_LINE_NUM_HALL_45 585
+#define MOTOR_LINE_NUM_GMR_45 22500
+#define MOTOR_LINE_NUM_HALL_90 1170
+#define MOTOR_LINE_NUM_GMR_90 45000
+
+#define MOTOR_TIRE_DIAMETER 67.0 //轮胎直径67mm
+
+#define MOTOR_MAX_ANGULAR_SPEED 100000.0 //最大角速度,单位mrad/s
+#define MOTOR_MAX_SPEED_GEAR_90 650.0 //空载情况下减速比为1:90的电机,带直径为67mm的轮胎,最高速度650mm/s
+#define MOTOR_MAX_SPEED_GEAR_45 1280.0 //空载情况下减速比为1:45的电机,带直径为67mm的轮胎,最高速度1280mm/s
+
+extern GPT_Handle g_gpt0;
+extern GPT_Handle g_gpt1;
+extern GPT_Handle g_gpt2;
+extern GPT_Handle g_gpt3;
+extern CAN_Handle g_can;
+extern QDM_Handle g_qdm0;
+extern QDM_Handle g_qdm1;
+extern TIMER_Handle g_timer0;
+extern UART_Handle g_uart0;
+extern UART_Handle g_uart2;
+extern UART_Handle g_uart3;
+extern I2C_Handle g_i2c0;
+extern I2C_Handle g_i2c1;
+extern APT_Handle g_apt0;
+extern APT_Handle g_apt1;
+extern ADC_Handle g_adc0;
+
+extern GPIO_Handle g_gpio1;
+extern GPIO_Handle g_gpio2;
+extern GPIO_Handle g_gpio5;
+
+extern float g_motorMaxSpeed; //电机最大速度
+extern unsigned int g_curMotorType; //电机类型
+extern unsigned int g_motorLineNum; //电机编码器线数
+
+extern unsigned int g_dataSendPeriod; //向上位机发送数据的周期
+
+extern float g_KP;
+extern float g_KI;
+extern float g_KD;
+
+BASE_StatusType CRG_Config(CRG_CoreClkSelect *coreClkSelect);
+void SystemInit(void);
+
+void UART2WriteInterruptCallback(void *handle);
+void UART2ReadInterruptCallback(void *handle);
+void UART3WriteInterruptCallback(void *handle);
+void UART3ReadInterruptCallback(void *handle);
+
+void UART2InterruptErrorCallback(void *handle);
+void UART3InterruptErrorCallback(void *handle);
+void QDM1PTUCycleCallback(void *handle);
+void QDM1SpeedLoseCallback(void *handle);
+void QDM1ZIndexLockedCallback(void *handle);
+void QDM1PositionCompareMatchCallback(void *handle);
+void QDM1PositionCompareReadyCallback(void *handle);
+void QDM1PositionCounterOverflowCallback(void *handle);
+void QDM1PositionCounterUnderflowCallback(void *handle);
+void QDM1QuadratureDirectionChangeCallback(void *handle);
+void QDM1QuadraturePhaseErrorCallback(void *handle);
+void QDM1PositionCounterErrorCallback(void *handle);
+void TIMER0_InterruptProcess(void *handle);
+void TIMER0_DMAOverFlow_InterruptProcess(void *handle);
+void QDM0PTUCycleCallback(void *handle);
+void QDM0SpeedLoseCallback(void *handle);
+void QDM0ZIndexLockedCallback(void *handle);
+void QDM0PositionCompareMatchCallback(void *handle);
+void QDM0PositionCompareReadyCallback(void *handle);
+void QDM0PositionCounterOverflowCallback(void *handle);
+void QDM0PositionCounterUnderflowCallback(void *handle);
+void QDM0QuadratureDirectionChangeCallback(void *handle);
+void QDM0QuadraturePhaseErrorCallback(void *handle);
+void QDM0PositionCounterErrorCallback(void *handle);
+
+void GPIO1_0_CallbackFunc(void *param);
+void GPIO1_1_CallbackFunc(void *param);
+
+#endif /* McuMagicTag_SYSTEM_INIT_H */
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/generatecode/system_init.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/generatecode/system_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..aebeb05c405d8ecdec5c3789f96e3d2a95f42a81
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/generatecode/system_init.c
@@ -0,0 +1,830 @@
+/**
+ * @copyright Copyright (c) 2022, HiSilicon (Shanghai) Technologies Co., Ltd. All rights reserved.
+ * 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 the copyright holder 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.
+ * @file system_init.c
+ * @author MCU Driver Team
+ * @brief This file contains driver init functions.
+ */
+
+#include "main.h"
+#include "ioconfig.h"
+#include "iocmg_ip.h"
+#include "debug.h"
+
+#define UART0_BAND_RATE 115200
+#define UART2_BAND_RATE 115200
+#define UART3_BAND_RATE 9600
+
+BASE_StatusType CRG_Config(CRG_CoreClkSelect *coreClkSelect)
+{
+ CRG_Handle crg;
+ crg.baseAddress = CRG;
+ crg.pllRefClkSelect = CRG_PLL_REF_CLK_SELECT_HOSC;
+ crg.pllPreDiv = CRG_PLL_PREDIV_4;
+ crg.pllFbDiv = 48; /* PLL Multiplier 48 */
+ crg.pllPostDiv = CRG_PLL_POSTDIV_2;
+ crg.coreClkSelect = CRG_CORE_CLK_SELECT_PLL;
+ crg.handleEx.pllPostDiv2 = CRG_PLL_POSTDIV2_3;
+ crg.handleEx.clk1MSelect = CRG_1M_CLK_SELECT_HOSC;
+ crg.handleEx.clk1MDiv = (25 - 1); /* The 1 MHz freq is equal to the input clock frequency / (clk_1m_div + 1). */
+
+ if (HAL_CRG_Init(&crg) != BASE_STATUS_OK) {
+ return BASE_STATUS_ERROR;
+ }
+ *coreClkSelect = crg.coreClkSelect;
+ return BASE_STATUS_OK;
+}
+
+static void ADC0_Init(void)
+{
+ HAL_CRG_IpEnableSet(ADC0_BASE, IP_CLK_ENABLE);
+ HAL_CRG_IpClkSelectSet(ADC0_BASE, CRG_ADC_CLK_ASYN_PLL_DIV);
+ HAL_CRG_IpClkDivSet(ADC0_BASE, CRG_ADC_DIV_1);
+
+ g_adc0.baseAddress = ADC0;
+ g_adc0.socPriority = ADC_PRIMODE_ALL_ROUND;
+
+ HAL_ADC_Init(&g_adc0);
+
+ SOC_Param socParam = {0};
+ socParam.adcInput = ADC_CH_ADCINA12; /* PIN10(ADC AIN12) */
+ socParam.sampleTotalTime = ADC_SOCSAMPLE_5CLK; /* adc sample total time 5 adc_clk */
+ socParam.trigSource = ADC_TRIGSOC_SOFT;
+ socParam.continueMode = BASE_CFG_DISABLE;
+ socParam.finishMode = ADC_SOCFINISH_NONE;
+ HAL_ADC_ConfigureSoc(&g_adc0, ADC_SOC_NUM1, &socParam);
+}
+
+static void APT0_Init(void)
+{
+ HAL_CRG_IpEnableSet(APT0_BASE, IP_CLK_ENABLE);
+
+ g_apt0.baseAddress = APT0;
+
+ /* Clock Settings */
+ g_apt0.waveform.dividerFactor = 1 - 1;
+ /* Timer Settings */
+ g_apt0.waveform.timerPeriod = 1500;
+ g_apt0.waveform.cntMode = APT_COUNT_MODE_UP_DOWN;
+
+ /* Wave Form */
+ g_apt0.waveform.basicType = APT_PWM_BASIC_A_HIGH_B_LOW;
+ g_apt0.waveform.chAOutType = APT_PWM_OUT_BASIC_TYPE;
+ g_apt0.waveform.chBOutType = APT_PWM_OUT_BASIC_TYPE;
+ g_apt0.waveform.divInitVal = 0;
+ g_apt0.waveform.cntInitVal = 0;
+ g_apt0.waveform.cntCmpLeftEdge = 250;
+ g_apt0.waveform.cntCmpRightEdge = 250;
+ g_apt0.waveform.cntCmpLoadMode = APT_BUFFER_DISABLE;
+ g_apt0.waveform.cntCmpLoadEvt = APT_COMPARE_LOAD_EVENT_ZERO;
+ g_apt0.waveform.deadBandCnt = 10;
+
+ HAL_APT_PWMInit(&g_apt0);
+}
+
+static void APT1_Init(void)
+{
+ HAL_CRG_IpEnableSet(APT1_BASE, IP_CLK_ENABLE);
+
+ g_apt1.baseAddress = APT1;
+
+ /* Clock Settings */
+ g_apt1.waveform.dividerFactor = 1 - 1;
+ /* Timer Settings */
+ g_apt1.waveform.timerPeriod = 1500;
+ g_apt1.waveform.cntMode = APT_COUNT_MODE_UP_DOWN;
+
+ /* Wave Form */
+ g_apt1.waveform.basicType = APT_PWM_BASIC_A_HIGH_B_LOW;
+ g_apt1.waveform.chAOutType = APT_PWM_OUT_BASIC_TYPE;
+ g_apt1.waveform.chBOutType = APT_PWM_OUT_BASIC_TYPE;
+ g_apt1.waveform.divInitVal = 0;
+ g_apt1.waveform.cntInitVal = 0;
+ g_apt1.waveform.cntCmpLeftEdge = 250;
+ g_apt1.waveform.cntCmpRightEdge = 250;
+ g_apt1.waveform.cntCmpLoadMode = APT_BUFFER_DISABLE;
+ g_apt1.waveform.cntCmpLoadEvt = APT_COMPARE_LOAD_EVENT_ZERO;
+ g_apt1.waveform.deadBandCnt = 10;
+
+ HAL_APT_PWMInit(&g_apt1);
+}
+
+static void CAN_Init(void){
+ HAL_CRG_IpEnableSet(CAN_BASE, IP_CLK_ENABLE);
+
+ g_can.baseAddress = CAN;
+
+ g_can.typeMode = CAN_MODE_NORMAL;
+ g_can.seg1Phase = CAN_SEG1_6TQ;
+ g_can.seg2Phase = CAN_SEG2_3TQ;
+ g_can.sjw = CAN_SJW_2TQ;
+ g_can.prescalser = 25; /* 25 is frequency division coefficient */
+ g_can.rxFIFODepth = 4; /* A maximum of 4 packet objects are in RX FIFO */
+ g_can.autoRetrans = BASE_CFG_ENABLE;
+ HAL_CAN_Init(&g_can);
+}
+
+__weak void GPIO1_0_CallbackFunc(void *param)
+{
+ GPIO_Handle *handle = (GPIO_Handle *)param;
+ BASE_FUNC_UNUSED(handle);
+}
+__weak void GPIO1_1_CallbackFunc(void *param)
+{
+ GPIO_Handle *handle = (GPIO_Handle *)param;
+ BASE_FUNC_UNUSED(handle);
+}
+
+static void GPIO_Init(void)
+{
+ HAL_CRG_IpEnableSet(GPIO1_BASE, IP_CLK_ENABLE);
+ g_gpio1.baseAddress = GPIO1;
+
+ g_gpio1.pins = GPIO_PIN_0 | GPIO_PIN_1;
+ HAL_GPIO_Init(&g_gpio1);
+ HAL_GPIO_SetDirection(&g_gpio1, g_gpio1.pins, GPIO_INPUT_MODE);
+ HAL_GPIO_SetValue(&g_gpio1, g_gpio1.pins, GPIO_LOW_LEVEL);
+ HAL_GPIO_SetIrqType(&g_gpio1, g_gpio1.pins, GPIO_INT_TYPE_RISE_EDGE);
+
+ HAL_CRG_IpEnableSet(GPIO2_BASE, IP_CLK_ENABLE);
+ g_gpio2.baseAddress = GPIO2;
+
+ g_gpio2.pins = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
+ HAL_GPIO_Init(&g_gpio2);
+ HAL_GPIO_SetDirection(&g_gpio2, g_gpio2.pins, GPIO_OUTPUT_MODE);
+ HAL_GPIO_SetValue(&g_gpio2, g_gpio2.pins, GPIO_LOW_LEVEL);
+ HAL_GPIO_SetIrqType(&g_gpio2, g_gpio2.pins, GPIO_INT_TYPE_NONE);
+
+ HAL_CRG_IpEnableSet(GPIO5_BASE, IP_CLK_ENABLE);
+ g_gpio5.baseAddress = GPIO5;
+
+ g_gpio5.pins = GPIO_PIN_1;
+ HAL_GPIO_Init(&g_gpio5);
+ HAL_GPIO_SetDirection(&g_gpio5, g_gpio5.pins, GPIO_OUTPUT_MODE);
+ HAL_GPIO_SetValue(&g_gpio5, g_gpio5.pins, GPIO_LOW_LEVEL);
+ HAL_GPIO_SetIrqType(&g_gpio5, g_gpio5.pins, GPIO_INT_TYPE_NONE);
+
+ HAL_GPIO_RegisterCallBack(&g_gpio1, GPIO_PIN_0, GPIO1_0_CallbackFunc);
+ HAL_GPIO_RegisterCallBack(&g_gpio1, GPIO_PIN_1, GPIO1_1_CallbackFunc);
+ IRQ_Register(IRQ_GPIO1, HAL_GPIO_IrqHandler, &g_gpio1);
+ IRQ_SetPriority(IRQ_GPIO1, 1); /* set gpio1 interrupt priority to 1, 1~15 */
+ IRQ_EnableN(IRQ_GPIO1); /* gpio interrupt enable */
+
+ return;
+}
+
+static void GPT0_Init(void)
+{
+ HAL_CRG_IpEnableSet(GPT0_BASE, IP_CLK_ENABLE);
+
+ g_gpt0.baseAddress = GPT0;
+ g_gpt0.clockDiv = 1000 - 1; /* 1000 is the internal frequency division of GPT */
+ g_gpt0.period = 2996; /* 2996 is the number of GPT counting cycles. */
+ g_gpt0.refA0.refdot = 1; /* 1 is the value of PWM reference point A. */
+ g_gpt0.refA0.refAction = GPT_ACTION_OUTPUT_HIGH; /* GPT Action High */
+ g_gpt0.refB0.refdot = 76; /* 76 is the value of PWM reference point B. */
+ g_gpt0.refB0.refAction = GPT_ACTION_OUTPUT_LOW; /* GPT Action Low */
+ g_gpt0.bufLoad = BASE_CFG_ENABLE;
+ g_gpt0.pwmKeep = BASE_CFG_ENABLE;
+ g_gpt0.handleEx.periodIntEnable = BASE_CFG_DISABLE;
+ g_gpt0.handleEx.outputFinIntEnable = BASE_CFG_DISABLE;
+ g_gpt0.triggleAdcOutFinish = BASE_CFG_DISABLE;
+ g_gpt0.triggleAdcPeriod = BASE_CFG_DISABLE;
+
+ HAL_GPT_Init(&g_gpt0);
+}
+
+static void GPT1_Init(void)
+{
+ HAL_CRG_IpEnableSet(GPT1_BASE, IP_CLK_ENABLE);
+
+ g_gpt1.baseAddress = GPT1;
+ g_gpt1.clockDiv = 1000 - 1; /* 1000 is the internal frequency division of GPT */
+ g_gpt1.period = 49999; /* 49999 is the number of GPT counting cycles. */
+ g_gpt1.refA0.refdot = 10000; /* 10000 is the value of PWM reference point A. */
+ g_gpt1.refA0.refAction = GPT_ACTION_OUTPUT_HIGH; /* GPT Action High */
+ g_gpt1.refB0.refdot = 30000; /* 30000 is the value of PWM reference point B. */
+ g_gpt1.refB0.refAction = GPT_ACTION_OUTPUT_LOW; /* GPT Action Low */
+ g_gpt1.bufLoad = BASE_CFG_ENABLE;
+ g_gpt1.pwmKeep = BASE_CFG_ENABLE;
+ g_gpt1.handleEx.periodIntEnable = BASE_CFG_DISABLE;
+ g_gpt1.handleEx.outputFinIntEnable = BASE_CFG_DISABLE;
+ g_gpt1.triggleAdcOutFinish = BASE_CFG_DISABLE;
+ g_gpt1.triggleAdcPeriod = BASE_CFG_DISABLE;
+
+ HAL_GPT_Init(&g_gpt1);
+}
+
+static void GPT2_Init(void)
+{
+ HAL_CRG_IpEnableSet(GPT2_BASE, IP_CLK_ENABLE);
+
+ g_gpt2.baseAddress = GPT2;
+ g_gpt2.clockDiv = 1000 - 1; /* 1000 is the internal frequency division of GPT */
+ g_gpt2.period = 49999; /* 49999 is the number of GPT counting cycles. */
+ g_gpt2.refA0.refdot = 10000; /* 10000 is the value of PWM reference point A. */
+ g_gpt2.refA0.refAction = GPT_ACTION_OUTPUT_HIGH; /* GPT Action High */
+ g_gpt2.refB0.refdot = 30000; /* 30000 is the value of PWM reference point B. */
+ g_gpt2.refB0.refAction = GPT_ACTION_OUTPUT_LOW; /* GPT Action Low */
+ g_gpt2.bufLoad = BASE_CFG_ENABLE;
+ g_gpt2.pwmKeep = BASE_CFG_ENABLE;
+ g_gpt2.handleEx.periodIntEnable = BASE_CFG_DISABLE;
+ g_gpt2.handleEx.outputFinIntEnable = BASE_CFG_DISABLE;
+ g_gpt2.triggleAdcOutFinish = BASE_CFG_DISABLE;
+ g_gpt2.triggleAdcPeriod = BASE_CFG_DISABLE;
+
+ HAL_GPT_Init(&g_gpt2);
+}
+
+static void GPT3_Init(void)
+{
+ HAL_CRG_IpEnableSet(GPT3_BASE, IP_CLK_ENABLE);
+
+ g_gpt3.baseAddress = GPT3;
+ g_gpt3.clockDiv = 1000 - 1; /* 1000 is the internal frequency division of GPT */
+ g_gpt3.period = 300; /* 300 is the number of GPT counting cycles. */
+ g_gpt3.refA0.refdot = 100; /* 100 is the value of PWM reference point A. */
+ g_gpt3.refA0.refAction = GPT_ACTION_OUTPUT_HIGH; /* GPT Action High */
+ g_gpt3.refB0.refdot = 200; /* 200 is the value of PWM reference point B. */
+ g_gpt3.refB0.refAction = GPT_ACTION_OUTPUT_LOW; /* GPT Action Low */
+ g_gpt3.bufLoad = BASE_CFG_ENABLE;
+ g_gpt3.pwmKeep = BASE_CFG_ENABLE;
+ g_gpt3.handleEx.periodIntEnable = BASE_CFG_DISABLE;
+ g_gpt3.handleEx.outputFinIntEnable = BASE_CFG_DISABLE;
+ g_gpt3.triggleAdcOutFinish = BASE_CFG_DISABLE;
+ g_gpt3.triggleAdcPeriod = BASE_CFG_DISABLE;
+
+ HAL_GPT_Init(&g_gpt3);
+}
+
+static void I2C0_Init(void)
+{
+ HAL_CRG_IpEnableSet(I2C0_BASE, IP_CLK_ENABLE);
+ HAL_CRG_IpClkSelectSet(I2C0_BASE, CRG_AHB_CLK_NO_PREDV);
+
+ g_i2c0.baseAddress = I2C0;
+
+ g_i2c0.functionMode = I2C_MODE_SELECT_MASTER_ONLY;
+ g_i2c0.addrMode = I2C_7_BITS;
+ g_i2c0.sdaHoldTime = 10;
+ g_i2c0.freq = 400000;
+ g_i2c0.transferBuff = NULL;
+ g_i2c0.ignoreAckFlag = BASE_CFG_DISABLE;
+ g_i2c0.handleEx.spikeFilterTime = 0;
+ g_i2c0.handleEx.sdaDelayTime = 0;
+ g_i2c0.timeout = 10000;
+ g_i2c0.state = I2C_STATE_RESET;
+ HAL_I2C_Init(&g_i2c0);
+}
+
+static void I2C1_Init(void)
+{
+ HAL_CRG_IpEnableSet(I2C1_BASE, IP_CLK_ENABLE);
+ HAL_CRG_IpClkSelectSet(I2C1_BASE, CRG_AHB_CLK_NO_PREDV);
+
+ g_i2c1.baseAddress = I2C1;
+
+ g_i2c1.functionMode = I2C_MODE_SELECT_MASTER_ONLY;
+ g_i2c1.addrMode = I2C_7_BITS;
+ g_i2c1.sdaHoldTime = 10;
+ g_i2c1.freq = 200000;
+ g_i2c1.transferBuff = NULL;
+ g_i2c1.ignoreAckFlag = BASE_CFG_DISABLE;
+ g_i2c1.handleEx.spikeFilterTime = 0;
+ g_i2c1.handleEx.sdaDelayTime = 0;
+ g_i2c1.timeout = 10000;
+ g_i2c1.state = I2C_STATE_RESET;
+ HAL_I2C_Init(&g_i2c1);
+}
+
+__weak void QDM0PTUCycleCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE BEGIN QDM0_TSU_CYCLE */
+ /* USER CODE END QDM0_TSU_CYCLE */
+}
+
+__weak void QDM0ZIndexLockedCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE BEGIN QDM0_INDEX_LOCKED */
+ /* USER CODE END QDM0_INDEX_LOCKED */
+}
+
+__weak void QDM0QuadraturePhaseErrorCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE QDM0_PHASE_ERROR */
+ /* USER CODE QDM0_PHASE_ERROR */
+}
+
+static void QDM0_Init(void)
+{
+ HAL_CRG_IpEnableSet(QDM0_BASE, IP_CLK_ENABLE);
+
+ g_qdm0.baseAddress = QDM0_BASE;
+
+ /* emulation config */
+ g_qdm0.emuMode = QDM_EMULATION_MODE_STOP_IMMEDIATELY;
+ /* input config */
+ g_qdm0.ctrlConfig.decoderMode = QDM_QUADRATURE_COUNT;
+ g_qdm0.ctrlConfig.polarity = 0;
+ g_qdm0.ctrlConfig.resolution = QDM_1X_RESOLUTION;
+ g_qdm0.ctrlConfig.trgLockMode = QDM_TRG_BY_CYCLE;
+ g_qdm0.ctrlConfig.swap = QDM_SWAP_DISABLE;
+ g_qdm0.ctrlConfig.ptuMode = QDM_PTU_MODE_CYCLE;
+ /* filter config */
+ g_qdm0.inputFilter.qdmAFilterLevel = 0;
+ g_qdm0.inputFilter.qdmBFilterLevel = 0;
+ g_qdm0.inputFilter.qdmZFilterLevel = 0;
+ /* other config */
+ g_qdm0.lock_mode = QDM_LOCK_RESERVE;
+ g_qdm0.pcntMode = QDM_PCNT_MODE_BY_DIR;
+ //g_qdm0.pcntRstMode = QDM_PCNT_RST_BY_PTU;
+ g_qdm0.pcntRstMode = QDM_PCNT_RST_OVF; // 单独调试脉冲数
+ g_qdm0.pcntIdxInitMode = QDM_IDX_INIT_DISABLE;
+ g_qdm0.qcMax = 4294967295;
+ g_qdm0.subModeEn = true;
+ g_qdm0.tsuPrescaler = 0;
+ g_qdm0.cevtPrescaler = QDM_CEVT_PRESCALER_DIVI1;
+ //g_qdm0.posMax = 4294967295;
+ g_qdm0.posMax = g_motorLineNum;
+ g_qdm0.posInit = 0;
+ g_qdm0.period = 150000000;
+
+ g_qdm0.motorLineNum = g_motorLineNum; /* 设置编码器线数 */
+ //DBG_PRINTF("g_qdm0.motorLineNum:%d\r\n", g_qdm0.motorLineNum);
+ g_qdm0.interruptEn = QDM_INT_WATCHDOG |
+ QDM_INT_INDEX_EVNT_LATCH |
+ QDM_INT_UNIT_TIME_OUT;
+
+ HAL_QDM_Init(&g_qdm0);
+
+ HAL_QDM_RegisterCallback(&g_qdm0, QDM_TSU_CYCLE, QDM0PTUCycleCallback);
+ HAL_QDM_RegisterCallback(&g_qdm0, QDM_INDEX_LOCKED, QDM0ZIndexLockedCallback);
+ HAL_QDM_RegisterCallback(&g_qdm0, QDM_PHASE_ERROR, QDM0QuadraturePhaseErrorCallback);
+ IRQ_Register(IRQ_QDM0, HAL_QDM_IrqHandler, &g_qdm0);
+ IRQ_SetPriority(IRQ_QDM0, 1);
+ IRQ_EnableN(IRQ_QDM0);
+}
+
+__weak void QDM1PTUCycleCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE BEGIN QDM1_TSU_CYCLE */
+ /* USER CODE END QDM1_TSU_CYCLE */
+}
+
+__weak void QDM1ZIndexLockedCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE BEGIN QDM1_INDEX_LOCKED */
+ /* USER CODE END QDM1_INDEX_LOCKED */
+}
+
+__weak void QDM1QuadraturePhaseErrorCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE QDM1_PHASE_ERROR */
+ /* USER CODE QDM1_PHASE_ERROR */
+}
+
+static void QDM1_Init(void)
+{
+ HAL_CRG_IpEnableSet(QDM1_BASE, IP_CLK_ENABLE);
+
+ g_qdm1.baseAddress = QDM1_BASE;
+
+ /* emulation config */
+ g_qdm1.emuMode = QDM_EMULATION_MODE_STOP_IMMEDIATELY;
+ /* input config */
+ g_qdm1.ctrlConfig.decoderMode = QDM_QUADRATURE_COUNT;
+ g_qdm1.ctrlConfig.polarity = 0;
+ g_qdm1.ctrlConfig.resolution = QDM_1X_RESOLUTION; /* 1倍频:只统计A相上升沿,4倍频:统计A、B两项上升沿和下降沿 */
+ g_qdm1.ctrlConfig.trgLockMode = QDM_TRG_BY_CYCLE;
+ g_qdm1.ctrlConfig.swap = QDM_SWAP_DISABLE;
+ g_qdm1.ctrlConfig.ptuMode = QDM_PTU_MODE_CYCLE;
+ /* filter config */
+ g_qdm1.inputFilter.qdmAFilterLevel = 0;
+ g_qdm1.inputFilter.qdmBFilterLevel = 0;
+ g_qdm1.inputFilter.qdmZFilterLevel = 0;
+ /* other config */
+ g_qdm1.lock_mode = QDM_LOCK_RESERVE;
+ g_qdm1.pcntMode = QDM_PCNT_MODE_BY_DIR;
+ //g_qdm1.pcntRstMode = QDM_PCNT_RST_BY_PTU;
+ g_qdm1.pcntRstMode = QDM_PCNT_RST_OVF;
+ g_qdm1.pcntIdxInitMode = QDM_IDX_INIT_DISABLE;
+ g_qdm1.qcMax = 4294967295;
+ g_qdm1.subModeEn = true;
+ g_qdm1.tsuPrescaler = 0U;
+ g_qdm1.cevtPrescaler = QDM_CEVT_PRESCALER_DIVI1;
+ //g_qdm1.posMax = 4294967295;
+ g_qdm1.posMax = g_motorLineNum;
+ g_qdm1.posInit = 0;
+ g_qdm1.period = 150000000;
+
+ g_qdm1.motorLineNum = g_motorLineNum; /* 设置编码器线数 */
+ //DBG_PRINTF("g_qdm0.motorLineNum:%d\r\n", g_qdm0.motorLineNum);
+
+ g_qdm1.interruptEn = QDM_INT_WATCHDOG |
+ QDM_INT_INDEX_EVNT_LATCH |
+ QDM_INT_UNIT_TIME_OUT;
+
+ HAL_QDM_Init(&g_qdm1);
+
+ HAL_QDM_RegisterCallback(&g_qdm1, QDM_TSU_CYCLE, QDM1PTUCycleCallback);
+ HAL_QDM_RegisterCallback(&g_qdm1, QDM_INDEX_LOCKED, QDM1ZIndexLockedCallback);
+ HAL_QDM_RegisterCallback(&g_qdm1, QDM_PHASE_ERROR, QDM1QuadraturePhaseErrorCallback);
+ IRQ_Register(IRQ_QDM1, HAL_QDM_IrqHandler, &g_qdm1);
+ IRQ_SetPriority(IRQ_QDM1, 1);
+ IRQ_EnableN(IRQ_QDM1);
+}
+
+__weak void TIMER0_InterruptProcess(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE BEGIN TIMER0_InterruptProcess */
+ /* USER CODE END TIMER0_InterruptProcess */
+}
+
+static void TIMER0_Init(void)
+{
+
+ HAL_CRG_IpEnableSet(TIMER0_BASE, IP_CLK_ENABLE);
+ HAL_CRG_IpClkSelectSet(TIMER0_BASE, CRG_AHB_CLK_NO_PREDV);
+
+ unsigned int load = (HAL_CRG_GetIpFreq((void *)TIMER0) / (1u << (TIMERPRESCALER_NO_DIV * 4)) / 1000000u) * 10000;
+
+ g_timer0.baseAddress = TIMER0;
+ g_timer0.load = load - 1; /* Set timer value immediately */
+ g_timer0.bgLoad = load - 1; /* Set timer value */
+ g_timer0.mode = TIMER_MODE_RUN_PERIODIC; /* Run in period mode */
+ g_timer0.prescaler = TIMERPRESCALER_NO_DIV; /* Don't frequency division */
+ g_timer0.size = TIMER_SIZE_32BIT; /* 1 for 32bit, 0 for 16bit */
+ g_timer0.interruptEn = BASE_CFG_ENABLE;
+ g_timer0.adcSocReqEnable = BASE_CFG_DISABLE;
+ g_timer0.dmaReqEnable = BASE_CFG_DISABLE;
+ HAL_TIMER_Init(&g_timer0);
+ IRQ_Register(IRQ_TIMER0, HAL_TIMER_IrqHandler, &g_timer0);
+
+ HAL_TIMER_RegisterCallback(&g_timer0, TIMER_PERIOD_FIN, TIMER0_InterruptProcess);
+ IRQ_SetPriority(IRQ_TIMER0, 1);
+ IRQ_EnableN(IRQ_TIMER0);
+}
+
+static void UART0_Init(void)
+{
+ HAL_CRG_IpEnableSet(UART0_BASE, IP_CLK_ENABLE);
+ HAL_CRG_IpClkSelectSet(UART0_BASE, CRG_AHB_CLK_NO_PREDV);
+
+ g_uart0.baseAddress = UART0;
+
+ g_uart0.baudRate = UART0_BAND_RATE;
+ g_uart0.dataLength = UART_DATALENGTH_8BIT;
+ g_uart0.stopBits = UART_STOPBITS_ONE;
+ g_uart0.parity = UART_PARITY_NONE;
+ g_uart0.txMode = UART_MODE_BLOCKING;
+ g_uart0.rxMode = UART_MODE_BLOCKING;
+ g_uart0.fifoMode = BASE_CFG_ENABLE;
+ g_uart0.fifoTxThr = UART_FIFODEPTH_SIZE8;
+ g_uart0.fifoRxThr = UART_FIFODEPTH_SIZE8;
+ g_uart0.hwFlowCtr = BASE_CFG_DISABLE;
+ g_uart0.handleEx.overSampleMultiple = UART_OVERSAMPLING_16X;
+ g_uart0.handleEx.msbFirst = BASE_CFG_DISABLE;
+ HAL_UART_Init(&g_uart0);
+}
+
+__weak void UART2InterruptErrorCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE BEGIN UART2_TRNS_IT_ERROR */
+ /* USER CODE END UART2_TRNS_IT_ERROR */
+}
+
+__weak void UART2WriteInterruptCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE BEGIN UART2_WRITE_IT_FINISH */
+ /* USER CODE END UART2_WRITE_IT_FINISH */
+}
+
+__weak void UART2ReadInterruptCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE BEGIN UART2_READ_IT_FINISH */
+ /* USER CODE END UART2_READ_IT_FINISH */
+}
+
+static void UART2_Init(void)
+{
+ HAL_CRG_IpEnableSet(UART2_BASE, IP_CLK_ENABLE);
+ HAL_CRG_IpClkSelectSet(UART2_BASE, CRG_AHB_CLK_NO_PREDV);
+
+ g_uart2.baseAddress = UART2;
+
+ g_uart2.baudRate = UART2_BAND_RATE;
+ g_uart2.dataLength = UART_DATALENGTH_8BIT;
+ g_uart2.stopBits = UART_STOPBITS_ONE;
+ g_uart2.parity = UART_PARITY_NONE;
+ g_uart2.txMode = UART_MODE_INTERRUPT;
+ g_uart2.rxMode = UART_MODE_INTERRUPT;
+ g_uart2.fifoMode = BASE_CFG_ENABLE;
+ g_uart2.fifoTxThr = UART_FIFODEPTH_SIZE4;
+ g_uart2.fifoRxThr = UART_FIFODEPTH_SIZE4;
+ g_uart2.hwFlowCtr = BASE_CFG_DISABLE;
+ g_uart2.handleEx.overSampleMultiple = UART_OVERSAMPLING_16X;
+ g_uart2.handleEx.msbFirst = BASE_CFG_DISABLE;
+ HAL_UART_Init(&g_uart2);
+ HAL_UART_RegisterCallBack(&g_uart2, UART_TRNS_IT_ERROR, (UART_CallbackType)UART2InterruptErrorCallback);
+ HAL_UART_RegisterCallBack(&g_uart2, UART_WRITE_IT_FINISH, (UART_CallbackType)UART2WriteInterruptCallback);
+ HAL_UART_RegisterCallBack(&g_uart2, UART_READ_IT_FINISH, (UART_CallbackType)UART2ReadInterruptCallback);
+
+ IRQ_Register(IRQ_UART2, HAL_UART_IrqHandler, &g_uart2);
+ IRQ_SetPriority(IRQ_UART2, 1);
+ IRQ_EnableN(IRQ_UART2);
+}
+
+__weak void UART3InterruptErrorCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE BEGIN UART3InterruptErrorCallback */
+ /* USER CODE END UART3InterruptErrorCallback */
+}
+
+__weak void UART3WriteInterruptCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE BEGIN UART3WriteInterruptCallback */
+ /* USER CODE END UART3WriteInterruptCallback */
+}
+
+__weak void UART3ReadInterruptCallback(void *handle)
+{
+ BASE_FUNC_UNUSED(handle);
+ /* USER CODE BEGIN UART3ReadInterruptCallback */
+ /* USER CODE END UART3ReadInterruptCallback */
+}
+
+static void UART3_Init(void)
+{
+ HAL_CRG_IpEnableSet(UART3_BASE, IP_CLK_ENABLE);
+ HAL_CRG_IpClkSelectSet(UART3_BASE, CRG_AHB_CLK_NO_PREDV);
+
+ g_uart3.baseAddress = UART3;
+
+ g_uart3.baudRate = UART3_BAND_RATE;
+ g_uart3.dataLength = UART_DATALENGTH_8BIT;
+ g_uart3.stopBits = UART_STOPBITS_ONE;
+ g_uart3.parity = UART_PARITY_NONE;
+ g_uart3.txMode = UART_MODE_INTERRUPT;
+ g_uart3.rxMode = UART_MODE_INTERRUPT;
+ g_uart3.fifoMode = BASE_CFG_ENABLE;
+ g_uart3.fifoTxThr = UART_FIFODEPTH_SIZE4;
+ g_uart3.fifoRxThr = UART_FIFODEPTH_SIZE4;
+ g_uart3.hwFlowCtr = BASE_CFG_DISABLE;
+ g_uart3.handleEx.overSampleMultiple = UART_OVERSAMPLING_16X;
+ g_uart3.handleEx.msbFirst = BASE_CFG_DISABLE;
+ HAL_UART_Init(&g_uart3);
+ HAL_UART_RegisterCallBack(&g_uart3, UART_TRNS_IT_ERROR, (UART_CallbackType)UART3InterruptErrorCallback);
+ HAL_UART_RegisterCallBack(&g_uart3, UART_WRITE_IT_FINISH, (UART_CallbackType)UART3WriteInterruptCallback);
+ HAL_UART_RegisterCallBack(&g_uart3, UART_READ_IT_FINISH, (UART_CallbackType)UART3ReadInterruptCallback);
+
+ IRQ_Register(IRQ_UART3, HAL_UART_IrqHandler, &g_uart3);
+ IRQ_SetPriority(IRQ_UART3, 1);
+ IRQ_EnableN(IRQ_UART3);
+}
+
+static void IOConfig(void)
+{
+ HAL_IOCMG_SetPinAltFuncMode(GPIO2_2_AS_UART0_TXD); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO2_2_AS_UART0_TXD, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO2_2_AS_UART0_TXD, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO2_2_AS_UART0_TXD, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO2_2_AS_UART0_TXD, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO2_3_AS_UART0_RXD); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO2_3_AS_UART0_RXD, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO2_3_AS_UART0_RXD, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO2_3_AS_UART0_RXD, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO2_3_AS_UART0_RXD, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO3_0_AS_APT0_PWMA); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO3_0_AS_APT0_PWMA, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO3_0_AS_APT0_PWMA, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO3_0_AS_APT0_PWMA, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO3_0_AS_APT0_PWMA, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO4_0_AS_APT0_PWMB); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO4_0_AS_APT0_PWMB, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO4_0_AS_APT0_PWMB, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO4_0_AS_APT0_PWMB, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO4_0_AS_APT0_PWMB, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO3_1_AS_APT1_PWMA); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO3_1_AS_APT1_PWMA, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO3_1_AS_APT1_PWMA, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO3_1_AS_APT1_PWMA, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO3_1_AS_APT1_PWMA, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO4_1_AS_APT1_PWMB); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO4_1_AS_APT1_PWMB, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO4_1_AS_APT1_PWMB, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO4_1_AS_APT1_PWMB, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO4_1_AS_APT1_PWMB, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO2_0_AS_QDM1_A); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO2_0_AS_QDM1_A, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO2_0_AS_QDM1_A, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO2_0_AS_QDM1_A, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO2_0_AS_QDM1_A, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO2_1_AS_QDM1_B); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO2_1_AS_QDM1_B, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO2_1_AS_QDM1_B, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO2_1_AS_QDM1_B, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO2_1_AS_QDM1_B, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO5_0_AS_QDM1_INDEX); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO5_0_AS_QDM1_INDEX, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO5_0_AS_QDM1_INDEX, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO5_0_AS_QDM1_INDEX, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO5_0_AS_QDM1_INDEX, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO1_7_AS_I2C1_SCL); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO1_7_AS_I2C1_SCL, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO1_7_AS_I2C1_SCL, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO1_7_AS_I2C1_SCL, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO1_7_AS_I2C1_SCL, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO4_7_AS_I2C1_SDA); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO4_7_AS_I2C1_SDA, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO4_7_AS_I2C1_SDA, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO4_7_AS_I2C1_SDA, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO4_7_AS_I2C1_SDA, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO1_5_AS_UART2_TXD); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO1_5_AS_UART2_TXD, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO1_5_AS_UART2_TXD, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO1_5_AS_UART2_TXD, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO1_5_AS_UART2_TXD, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO1_6_AS_UART2_RXD); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO1_6_AS_UART2_RXD, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO1_6_AS_UART2_RXD, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO1_6_AS_UART2_RXD, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO1_6_AS_UART2_RXD, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO5_2_AS_GPT2_PWM); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO5_2_AS_GPT2_PWM, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO5_2_AS_GPT2_PWM, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO5_2_AS_GPT2_PWM, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO5_2_AS_GPT2_PWM, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO0_5_AS_GPT1_PWM); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO0_5_AS_GPT1_PWM, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO0_5_AS_GPT1_PWM, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO0_5_AS_GPT1_PWM, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO0_5_AS_GPT1_PWM, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO2_4_AS_GPT0_PWM); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO2_4_AS_GPT0_PWM, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO2_4_AS_GPT0_PWM, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO2_4_AS_GPT0_PWM, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO2_4_AS_GPT0_PWM, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO1_0_AS_GPIO1_0); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO1_0_AS_GPIO1_0, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO1_0_AS_GPIO1_0, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO1_0_AS_GPIO1_0, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO1_0_AS_GPIO1_0, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO1_1_AS_GPIO1_1); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO1_1_AS_GPIO1_1, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO1_1_AS_GPIO1_1, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO1_1_AS_GPIO1_1, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO1_1_AS_GPIO1_1, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO2_5_AS_GPIO2_5); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO2_5_AS_GPIO2_5, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO2_5_AS_GPIO2_5, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO2_5_AS_GPIO2_5, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO2_5_AS_GPIO2_5, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO2_6_AS_GPIO2_6); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO2_6_AS_GPIO2_6, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO2_6_AS_GPIO2_6, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO2_6_AS_GPIO2_6, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO2_6_AS_GPIO2_6, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO2_7_AS_GPIO2_7); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO2_7_AS_GPIO2_7, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO2_7_AS_GPIO2_7, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO2_7_AS_GPIO2_7, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO2_7_AS_GPIO2_7, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO5_1_AS_GPIO5_1); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO5_1_AS_GPIO5_1, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO5_1_AS_GPIO5_1, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO5_1_AS_GPIO5_1, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO5_1_AS_GPIO5_1, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO1_4_AS_UART3_RXD); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO1_4_AS_UART3_RXD, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO1_4_AS_UART3_RXD, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO1_4_AS_UART3_RXD, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO1_4_AS_UART3_RXD, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO1_3_AS_UART3_TXD); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO1_3_AS_UART3_TXD, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO1_3_AS_UART3_TXD, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO1_3_AS_UART3_TXD, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO1_3_AS_UART3_TXD, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO4_2_AS_I2C0_SCL); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO4_2_AS_I2C0_SCL, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO4_2_AS_I2C0_SCL, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO4_2_AS_I2C0_SCL, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO4_2_AS_I2C0_SCL, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO4_3_AS_I2C0_SDA); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO4_3_AS_I2C0_SDA, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO4_3_AS_I2C0_SDA, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO4_3_AS_I2C0_SDA, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO4_3_AS_I2C0_SDA, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO3_7_AS_GPT3_PWM); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO3_7_AS_GPT3_PWM, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO3_7_AS_GPT3_PWM, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO3_7_AS_GPT3_PWM, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO3_7_AS_GPT3_PWM, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO5_3_AS_ADC_AIN12); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO5_3_AS_ADC_AIN12, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO5_3_AS_ADC_AIN12, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO5_3_AS_ADC_AIN12, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO5_3_AS_ADC_AIN12, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO3_6_AS_CAN_RX); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO3_6_AS_CAN_RX, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO3_6_AS_CAN_RX, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO3_6_AS_CAN_RX, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO3_6_AS_CAN_RX, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO3_5_AS_CAN_TX); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO3_5_AS_CAN_TX, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO3_5_AS_CAN_TX, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO3_5_AS_CAN_TX, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO3_5_AS_CAN_TX, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO4_5_AS_QDM0_A); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO4_5_AS_QDM0_A, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO4_5_AS_QDM0_A, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO4_5_AS_QDM0_A, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO4_5_AS_QDM0_A, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+ HAL_IOCMG_SetPinAltFuncMode(GPIO4_6_AS_QDM0_B); /* Check function selection */
+ HAL_IOCMG_SetPinPullMode(GPIO4_6_AS_QDM0_B, PULL_NONE); /* Pull-up and pull-down */
+ HAL_IOCMG_SetPinSchmidtMode(GPIO4_6_AS_QDM0_B, SCHMIDT_DISABLE); /* Schmitt input on/off */
+ HAL_IOCMG_SetPinLevelShiftRate(GPIO4_6_AS_QDM0_B, LEVEL_SHIFT_RATE_SLOW); /* Output drive capability */
+ HAL_IOCMG_SetPinDriveRate(GPIO4_6_AS_QDM0_B, DRIVER_RATE_2); /* Output signal edge fast/slow */
+
+}
+
+void SystemInit(void)
+{
+ IOConfig();
+ UART0_Init();
+ UART2_Init();
+ UART3_Init();
+ APT0_Init();
+ APT1_Init();
+ ADC0_Init();
+ CAN_Init();
+ GPT0_Init();
+ GPT1_Init();
+ GPT2_Init();
+ GPT3_Init();
+ TIMER0_Init();
+ I2C0_Init();
+ I2C1_Init();
+ QDM0_Init();
+ QDM1_Init();
+ GPIO_Init();
+
+ /* USER CODE BEGIN system_init */
+ /* USER CODE END system_init */
+}
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/gyro.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/gyro.c
new file mode 100644
index 0000000000000000000000000000000000000000..5f6cf916542f7213578e843a55eb7c4300ea5b7d
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/gyro.c
@@ -0,0 +1,311 @@
+#include
+#include
+#include // For memcpy
+#include
+#include
+
+#include "main.h"
+#include "debug.h"
+#include "i2c.h"
+#include "ssd1306.h"
+#include "ssd1306_fonts.h"
+#include "gyro.h"
+
+#define gyroKp (20.0f) // 比例增益支配率收敛到加速度计/磁强计
+#define gyroKi (0.0004f) // 积分增益支配率的陀螺仪偏见的衔接
+#define gyroHalfT (0.005f) // 采样周期的一半
+#define PAI 3.14
+#define DEGREES 180
+
+float q0 = 1, q1 = 0, q2 = 0, q3 = 0; // 四元数的元素,代表估计方向
+float exInt = 0, eyInt = 0, ezInt = 0; // 按比例缩小积分误差
+float g_gyro_yaw, g_gyro_pitch, g_gyro_roll; // 偏航角,俯仰角,翻滚角
+static float yaw_conv = 0.0f;
+
+
+/**
+ * @berf i2c read
+ * @param hi_u8 reg_high_8bit_cmd:Transmit register value 8 bits high
+ * @param hi_u8 reg_low_8bit_cmd:Transmit register value low 8 bits
+ * @param hi_u8* recv_data:Receive data buff
+ * @param hi_u8 send_len:Sending data length
+ * @param hi_u8 read_len:Length of received data
+*/
+uint32_t LSM6DS_WriteRead(uint8_t reg_high_8bit_cmd, uint8_t send_len, uint8_t read_len)
+{
+ uint8_t recvData[12] = {0};
+ uint32_t ret = 0;
+ uint8_t send_user_cmd[1] = {reg_high_8bit_cmd};
+ ret= HAL_I2C_MasterWriteBlocking(&g_i2c0, LSM6DS_WRITE_ADDR, send_user_cmd, send_len, 10000);
+ if (ret != BASE_STATUS_OK) {
+ DBG_PRINTF("LINE:%d,write Data Fail,ret:%d\r\n", __LINE__, ret);
+ return ret;
+ }
+ /* Read data from eeprom. */
+ ret = HAL_I2C_MasterReadBlocking(&g_i2c0, LSM6DS_READ_ADDR, recvData, read_len, 10000);
+ if (ret != BASE_STATUS_OK) {
+ DBG_PRINTF("LINE:%d,Read Data Fail,ret:%d\r\n", __LINE__, ret);
+ return ret;
+ }
+ DBG_PRINTF("LSM6DS read ndef data\r\n");
+ for (int i = 0; i < read_len; i++) {
+ DBG_PRINTF("0x%x ", recvData[i]);
+ }
+ ret = recvData[0];
+ return ret;
+}
+
+uint32_t LSM6DS_ReadCont(uint8_t reg_addr, uint8_t* buffer, uint16_t read_len)
+{
+ uint32_t ret = 0;
+ uint8_t send_user_cmd[1] = {reg_addr};
+ ret= HAL_I2C_MasterWriteBlocking(&g_i2c0, LSM6DS_WRITE_ADDR, send_user_cmd, 1, 10000);
+ if (ret != BASE_STATUS_OK) {
+ DBG_PRINTF("LINE:%d,write Data Fail,ret:%d\r\n", __LINE__, ret);
+ return ret;
+ }
+ /* Read data from eeprom. */
+ ret = HAL_I2C_MasterReadBlocking(&g_i2c0, LSM6DS_READ_ADDR, buffer, read_len, 10000);
+ if (ret != BASE_STATUS_OK) {
+ DBG_PRINTF("LINE:%d,Read Data Fail,ret:%d\r\n", __LINE__, ret);
+ return ret;
+ }
+ DBG_PRINTF("LSM6DS read ndef data\r\n");
+ for (int i = 0; i < read_len; i++) {
+ DBG_PRINTF("0x%x ", buffer[i]);
+ }
+ return ret;
+}
+
+uint32_t LSM6DS_Write(uint8_t addr, uint8_t writedata, uint32_t buffLen)
+{
+ uint8_t buffer[2] = {addr, writedata};
+ uint32_t retval = HAL_I2C_MasterWriteBlocking(&g_i2c0, LSM6DS_WRITE_ADDR, buffer, buffLen, 10000);
+ if (retval != BASE_STATUS_OK) {
+ DBG_PRINTF("LSM6DS_Write: IoTI2cWrite(%02X) failed, %0X!\n", buffer[0], retval);
+ return retval;
+ }
+ DBG_PRINTF("IoTI2cWrite(%02X)\r\n", buffer[0]);
+ return BASE_STATUS_OK;
+}
+
+void IMU_YAW_CAL(float gyroZ)
+{
+ int ret = 0;
+ static char Pitchline[32] = { 0 };
+ static char Rollline[32] = { 0 };
+ static char Yawline[32] = { 0 };
+ static float dt = 0.03; // 0.03代表300ms读取陀螺仪数据
+ static float yaw = 0.0f, temp = 0.0f;
+ // 除去零偏
+ #if 0
+ static int a = 0;
+ a++;
+ if (hi_get_seconds() <= 5) { // 5s
+ printf("---------times-----------:%d\n", a);
+ }
+ #endif
+ if (fabs(gyroZ) < 0.04) { // 0.04标准值
+ temp = 0;
+ } else {
+ temp = gyroZ * dt;
+ }
+ yaw += temp;
+ yaw_conv = yaw * 57.32; // 57.32 初始值
+ // 360°一个循环
+ if (fabs(yaw_conv) > 360.0f) {
+ if ((yaw_conv) < 0) {
+ yaw_conv += 360.0f;
+ } else {
+ yaw_conv -= 360.0f;
+ }
+ }
+ DBG_PRINTF("Pitch:%.02f, Roll:%.02f, yaw:%.2f\n", g_gyro_pitch, g_gyro_roll, yaw_conv);
+ ssd1306_SetCursor(0, 15); // 0为横坐标,15为纵坐标
+ ret = sprintf(Pitchline, "Pitch: %.2f", g_gyro_pitch);
+ if (ret < 0) {
+ printf("Pitch failed\r\n");
+ }
+ ssd1306_DrawString(Pitchline, Font_7x10, White);
+ ssd1306_SetCursor(0, 30); // 0为横坐标,30为纵坐标
+ ret = sprintf(Rollline, "roll: %.2f", g_gyro_roll);
+ if (ret < 0) {
+ printf("roll failed\r\n");
+ }
+ ssd1306_DrawString(Rollline, Font_7x10, White);
+ ssd1306_SetCursor(0, 0); // 0为横坐标,0为纵坐标
+ ret = sprintf(Yawline, "roll: %.2f", yaw_conv);
+ if (ret < 0) {
+ printf("yaw failed\r\n");
+ }
+ ssd1306_DrawString(Yawline, Font_7x10, White);
+ ssd1306_UpdateScreen();
+}
+
+void GetRoll(float atan2x, float atan2y)
+{
+ float atan2_x = atan2x;
+ float atan2_y = atan2y;
+ if (atan2_x > 0) {
+ g_gyro_roll = atan(atan2_y / atan2_x) * DEGREES / PAI;
+ } else if (atan2_x < 0 && atan2_y >= 0) {
+ g_gyro_roll = atan(atan2_y / atan2_x) * DEGREES / PAI + DEGREES;
+ } else if (atan2_x < 0 && atan2_y < 0) {
+ g_gyro_roll = atan(atan2_y / atan2_x) * DEGREES / PAI - DEGREES;
+ } else if (atan2_y > 0 && fabsf(atan2_x) < 0.001) {
+ g_gyro_roll = 90; // 90°
+ } else if (atan2_y < 0 && fabsf(atan2_x) < 0.001) {
+ g_gyro_roll = -90; // -90°
+ } else {
+ printf("undefined\n");
+ }
+}
+
+void GetPitch(float atan2x, float atan2y)
+{
+ float atan2_x = atan2x;
+ float atan2_y_pitch = atan2y;
+ if (atan2_x > 0) {
+ g_gyro_pitch = atan(atan2_y_pitch / atan2_x) * DEGREES / PAI;
+ } else if (atan2_x < 0 && atan2_y_pitch >= 0) {
+ g_gyro_pitch = atan(atan2_y_pitch / atan2_x) * DEGREES / PAI + DEGREES;
+ } else if (atan2_x < 0 && atan2_y_pitch < 0) {
+ g_gyro_pitch = atan(atan2_y_pitch / atan2_x) * DEGREES / PAI - DEGREES;
+ } else if (atan2_y_pitch > 0 && fabsf(atan2_x) < 0.001) {
+ g_gyro_pitch = 90; // 90°
+ } else if (atan2_y_pitch < 0 && fabsf(atan2_x) < 0.001) {
+ g_gyro_pitch = -90; // -90°
+ } else {
+ printf("undefined\n");
+ }
+}
+
+void IMU_Attitude_cal(float gcx, float gcy, float gcz, float acx, float acy, float acz)
+{
+ float norm;
+ float vx, vy, vz;
+ float ex, ey, ez;
+ float atan2_x, atan2_y;
+ float atan2_y_pitch;
+ float ax = acx, ay = acy, az = acz;
+ float gx = gcx, gy = gcy, gz = gcz;
+
+ // 把采集到的三轴加速度转化为单位向量,即向量除以模
+ norm = (float)sqrt((float)(ax * ax + ay * ay + az * az));
+ if (fabsf(norm) < 0.001) {
+ printf("norm = 0,failed\n");
+ }
+ ax = ax / norm;
+ ay = ay / norm;
+ az = az / norm;
+
+ // 把四元素换算成方向余弦中的第三行的三个元素
+ // vx、vy、vz其实就是上一次的欧拉角(四元数)机体参考坐标系换算出来的重力的单位向量
+ vx = 2 * (q1 * q3 - q0 * q2); // 2计算系数
+ vy = 2 * (q0 * q1 + q2 * q3); // 2计算系数
+ vz = q0 * q0 - q1 * q1 - q2 * q2 + q3 * q3;
+
+ // 对向量叉乘,求出姿态误差
+ // ex、ey、ez为三轴误差元素
+ ex = (ay * vz - az * vy);
+ ey = (az * vx - ax * vz);
+ ez = (ax * vy - ay * vx);
+
+ // 叉乘向量仍旧是机体坐标系上的,而陀螺仪积分误差也是机体坐标系
+ // 而且叉积的大小与陀螺仪误差成正比,正好拿来纠正陀螺
+ exInt = exInt + ex * gyroKi;
+ eyInt = eyInt + ey * gyroKi;
+ ezInt = ezInt + ez * gyroKi;
+
+ // 调整后的陀螺仪测量
+ gx = gx + gyroKp * ex + exInt;
+ gy = gy + gyroKp * ey + eyInt;
+ gz = gz + gyroKp * ez + ezInt;
+
+ // 使用一阶龙格库塔解四元数微分方程
+ q0 = q0 + (-q1 * gx - q2 * gy - q3 * gz) * gyroHalfT;
+ q1 = q1 + (q0 * gx + q2 * gz - q3 * gy) * gyroHalfT;
+ q2 = q2 + (q0 * gy - q1 * gz + q3 * gx) * gyroHalfT;
+ q3 = q3 + (q0 * gz + q1 * gy - q2 * gx) * gyroHalfT;
+
+ // 四元数归一化
+ norm = sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
+ if (fabsf(norm) < 0.001) {
+ printf("norm = 0,failed\n");
+ }
+ q0 = q0 / norm;
+ q1 = q1 / norm;
+ q2 = q2 / norm;
+ q3 = q3 / norm;
+
+ // 计算姿态角,本文Roll为横滚角,Pitch为俯仰角
+ atan2_x = -2 * q1 * q1 - 2 * q2 * q2 + 1; // 2 计算参数
+ atan2_y = 2 * q2 * q3 + 2 * q0 * q1; // 2 计算参数
+ GetRoll(atan2_x, atan2_y);
+ // 俯仰角
+ atan2_y_pitch = -2 * q1 * q3 + 2 * q0 * q2; // 2 计算参数
+ GetPitch(atan2_x, atan2_y_pitch);
+}
+
+void Lsm_Get_RawAcc(void)
+{
+ uint8_t buf[12] = {0};
+ int16_t acc_x = 0, acc_y = 0, acc_z = 0;
+ float acc_x_conv = 0, acc_y_conv = 0, acc_z_conv = 0;
+ int16_t ang_rate_x = 0, ang_rate_y = 0, ang_rate_z = 0;
+ float ang_rate_x_conv = 0, ang_rate_y_conv = 0, ang_rate_z_conv = 0;
+
+ if ((LSM6DS_WriteRead(LSM6DSL_STATUS_REG, 1, 1) & 0x03)!=0) {
+ if (BASE_STATUS_OK != LSM6DS_ReadCont(LSM6DSL_OUTX_L_G, buf, 12)) {
+ DBG_PRINTF("i2c read error!\n");
+ }
+ else {
+ ang_rate_x = (buf[1] << 8) + buf[0];
+ ang_rate_y = (buf[3] << 8) + buf[2];
+ ang_rate_z = (buf[5] << 8) + buf[4];
+ acc_x = (buf[7] << 8) + buf[6];
+ acc_y = (buf[9] << 8) + buf[8];
+ acc_z = (buf[11] << 8) + buf[10];
+
+ // DBG_PRINTF("lsm acc: %d, %d, %d \n ang: %d, %d, %d\n ",
+ // acc_x, acc_y, acc_z, ang_rate_x, ang_rate_y, ang_rate_z);
+ ang_rate_x_conv = 3.14 / 180.0 * ang_rate_x / 14.29;
+ ang_rate_y_conv = 3.14 / 180.0 * ang_rate_y / 14.29;
+ ang_rate_z_conv = 3.14 / 180.0 * ang_rate_z / 14.29;
+
+ acc_x_conv = acc_x / 4098.36;
+ acc_y_conv = acc_y / 4098.36;
+ acc_z_conv = acc_z / 4098.36;
+ // DBG_PRINTF("lsm trans acc: %.2f, %.2f, %.2f \n ang: %.2f, %.2f, %.2f\n ",
+ // acc_x_conv, acc_y_conv, acc_z_conv, ang_rate_x_conv, ang_rate_y_conv, ang_rate_z_conv);
+ IMU_Attitude_cal(ang_rate_x_conv, ang_rate_y_conv, ang_rate_z_conv, acc_x_conv, acc_y_conv, acc_z_conv);
+ IMU_YAW_CAL(ang_rate_z_conv);
+ }
+ }
+}
+
+void LSM6DS_Init()
+{
+ LSM6DS_Write(LSM6DSL_CTRL3_C, 0x34, 2);
+ LSM6DS_Write(LSM6DSL_CTRL2_G , 0X4C, 2); // 角速度陀螺仪配置2000dps ,104Hz
+ LSM6DS_Write(LSM6DSL_CTRL10_C, 0x38, 2); // timer en, pedo en, tilt en ??
+ LSM6DS_Write(LSM6DSL_CTRL1_XL, 0x4F, 2); // 加速度配置量程为8g,104Hz, lpf1_bw_sel=1, bw0_xl=1;
+
+ LSM6DS_Write(LSM6DSL_TAP_CFG, 0x10, 2);
+ LSM6DS_Write(LSM6DSL_WAKE_UP_DUR, 0x00, 2);
+ LSM6DS_Write(LSM6DSL_WAKE_UP_THS, 0x02, 2);
+ LSM6DS_Write(LSM6DSL_TAP_THS_6D, 0x40, 2);
+ LSM6DS_Write(LSM6DSL_CTRL8_XL, 0x01, 2);
+}
+
+void InitGyro(void)
+{
+ uint32_t ret;
+ ret = LSM6DS_WriteRead(LSM6DSL_WHO_AM_I, 1, 1);
+ DBG_PRINTF("who am i: %X\n", ret);
+ LSM6DS_Init();
+ while (1) {
+ Lsm_Get_RawAcc();
+ BASE_FUNC_DELAY_MS(10); // 延时10ms
+ }
+}
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/gyro.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/gyro.h
new file mode 100644
index 0000000000000000000000000000000000000000..140111b4e68e65470c92b0ef3d709b94248b2aae
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/gyro.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef GYRO_H
+#define GYRO_H
+
+#define LSM6DS_WRITE_ADDR (0XD6)
+#define LSM6DS_READ_ADDR (0XD7)
+#define WRITELEN 2
+
+/* sensor output data */
+#define LSM6DSL_OUTX_L_G 0X22
+#define LSM6DSL_OUTX_H_G 0X23
+#define LSM6DSL_OUTY_L_G 0X24
+#define LSM6DSL_OUTY_H_G 0X25
+#define LSM6DSL_OUTZ_L_G 0X26
+#define LSM6DSL_OUTZ_H_G 0X27
+
+#define LSM6DSL_OUTX_L_XL 0X28
+#define LSM6DSL_OUTX_H_XL 0X29
+#define LSM6DSL_OUTY_L_XL 0X2A
+#define LSM6DSL_OUTY_H_XL 0X2B
+#define LSM6DSL_OUTZ_L_XL 0X2C
+#define LSM6DSL_OUTZ_H_XL 0X2D
+/* sensor control reg */
+#define LSM6DSL_CTRL1_XL 0X10
+#define LSM6DSL_CTRL2_G 0X11
+#define LSM6DSL_CTRL3_C 0X12
+#define LSM6DSL_CTRL8_XL 0X17
+#define LSM6DSL_CTRL9_XL 0X18
+#define LSM6DSL_CTRL10_C 0X19
+#define LSM6DSL_INT2_CTRL 0X0E
+#define LSM6DSL_WHO_AM_I 0x0F // get id
+#define LSM6DSL_STATUS_REG 0x1E
+
+#define LSM6DSL_SENSORHUB11_REG 0X38
+#define LSM6DSL_TAP_CFG 0X58
+#define LSM6DSL_TAP_THS_6D 0X59
+#define LSM6DSL_INT_DUR2 0X5A
+#define LSM6DSL_WAKE_UP_THS 0X5B
+#define LSM6DSL_WAKE_UP_DUR 0X5C
+#define LSM6DSL_FREE_FALL 0X5D
+#define LSM6DSL_MD1_CFG 0X5E
+#define PAI 3.14
+#define DEGREES 180
+
+void InitGyro(void);
+void Lsm_Get_RawAcc(void);
+void LSM6DS_Init(void);
+float GetPitchValue(void);
+
+void IMU_YAW_CAL(float gyroZ);
+void GetRoll(float atan2x, float atan2y);
+void GetPitch(float atan2x, float atan2y);
+void IMU_Attitude_cal(float gcx, float gcy, float gcz, float acx, float acy, float acz);
+
+uint32_t LSM6DS_ReadCont(uint8_t reg_addr, uint8_t* buffer, uint16_t read_len);
+uint32_t LSM6DS_Write(uint8_t addr, uint8_t writedata, uint32_t buffLen);
+uint32_t LSM6DS_WriteRead(uint8_t reg_high_8bit_cmd, uint8_t send_len, uint8_t read_len);
+
+#endif // AHT20_H
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/led.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/led.c
new file mode 100644
index 0000000000000000000000000000000000000000..0147324670cc704c0896095fdd3da0ef8ada2792
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/led.c
@@ -0,0 +1,29 @@
+#include "debug.h"
+#include "gpio.h"
+#include "main.h"
+#include "led.h"
+
+#define CYCLE_INTERVAL_TIME 500
+
+/* ---------------------------------- Sample Parameters -------------------------------- */
+/**
+ * @brief Test GPIO PIN control LED.
+ * @param None
+ * @retval Value of @ref BASE_StatusType.
+ */
+BASE_StatusType GPIO_LedSample(void)
+{
+ /* Cycle control LED on and off. */
+ while (1) {
+ BASE_FUNC_DELAY_MS(2000);
+ HAL_GPIO_TogglePin(&g_gpio2, GPIO_PIN_5);
+ BASE_FUNC_DELAY_MS(2000);
+ HAL_GPIO_TogglePin(&g_gpio2, GPIO_PIN_6);
+ BASE_FUNC_DELAY_MS(2000);
+ HAL_GPIO_TogglePin(&g_gpio2, GPIO_PIN_7);
+ BASE_FUNC_DELAY_MS(2000);
+ HAL_GPIO_TogglePin(&g_gpio5, GPIO_PIN_1);
+ DBG_PRINTF("LED Stata reverse! \r\n");
+ }
+ return BASE_STATUS_OK;
+}
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/led.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/led.h
new file mode 100644
index 0000000000000000000000000000000000000000..9537887fea0ac3710e07d16f1c6e493f43594c42
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/led.h
@@ -0,0 +1,6 @@
+#ifndef LED_H
+#define LED_H
+
+BASE_StatusType GPIO_LedSample(void);
+
+#endif /* GPIO_LED_SAMPLE_H */
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/main.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..a77cad1513681a37373189a418e60e3e93426cc1
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/main.c
@@ -0,0 +1,129 @@
+/**
+ * @copyright Copyright (c) 2022, HiSilicon (Shanghai) Technologies Co., Ltd. All rights reserved.
+ * 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 the copyright holder 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.
+ * @file main.c
+ * @author MCU Driver Team
+ * @brief Main program body.
+ */
+
+#include "typedefs.h"
+#include "feature.h"
+#include "main.h"
+/* USER CODE BEGIN 0 */
+/* USER CODE 区域内代码不会被覆盖,区域外会被生成的默认代码覆盖(其余USER CODE 区域同理) */
+#include "debug.h"
+#include "ssd1306.h"
+#include "ssd1306_fonts.h"
+#include "uart.h"
+#include "user_motor_control.h"
+#include "button.h"
+#include "adc_demo.h"
+#include "beep.h"
+#include "gyro.h"
+#include "encoder.h"
+#include "eulercar_control.h"
+#include "debug.h"
+#include "pid.h"
+/* 建议用户放置头文件 */
+/* USER CODE END 0 */
+
+/* USER CODE BEGIN 1 */
+CAN_Handle g_can;
+QDM_Handle g_qdm0;
+QDM_Handle g_qdm1;
+GPT_Handle g_gpt0;
+GPT_Handle g_gpt1;
+GPT_Handle g_gpt2;
+GPT_Handle g_gpt3;
+TIMER_Handle g_timer0;
+UART_Handle g_uart0;
+UART_Handle g_uart2;
+UART_Handle g_uart3;
+I2C_Handle g_i2c0;
+I2C_Handle g_i2c1;
+APT_Handle g_apt0;
+APT_Handle g_apt1;
+ADC_Handle g_adc0;
+GPIO_Handle g_gpio1;
+GPIO_Handle g_gpio2;
+GPIO_Handle g_gpio5;
+
+char g_motorTypeStr[4][20] = {
+ "1:45 HALL",
+ "1:45 GMR",
+ "1:90 HALL",
+ "1:90 GMR",
+};
+
+/*
+//减速比为1:90的霍尔传感器电机
+float g_motorMaxSpeed = MOTOR_MAX_SPEED_GEAR_90;
+unsigned int g_curMotorType = MOTOR_TYPE_GEAR_HALL_90;
+unsigned int g_motorLineNum = MOTOR_LINE_NUM_HALL_90;
+
+//减速比为1:90的GMR传感器电机
+float g_motorMaxSpeed = MOTOR_MAX_SPEED_GEAR_90;
+unsigned int g_curMotorType = MOTOR_TYPE_GEAR_GMR_90;
+unsigned int g_motorLineNum = MOTOR_LINE_NUM_GMR_90;
+
+//减速比为1:45的霍尔传感器电机
+float g_motorMaxSpeed = MOTOR_MAX_SPEED_GEAR_45;
+unsigned int g_curMotorType = MOTOR_TYPE_GEAR_HALL_45;
+unsigned int g_motorLineNum = MOTOR_LINE_NUM_HALL_45;
+
+//减速比为1:45的GMR传感器电机
+float g_motorMaxSpeed = MOTOR_MAX_SPEED_GEAR_45;
+unsigned int g_curMotorType = MOTOR_TYPE_GEAR_GMR_45;
+unsigned int g_motorLineNum = MOTOR_LINE_NUM_GMR_45;
+*/
+
+//减速比为1:90的GMR传感器电机
+float g_motorMaxSpeed = MOTOR_MAX_SPEED_GEAR_90;
+unsigned int g_curMotorType = MOTOR_TYPE_GEAR_GMR_90;
+unsigned int g_motorLineNum = MOTOR_LINE_NUM_GMR_90;
+
+/* 建议用户定义全局变量、结构体、宏定义或函数声明等 */
+/* USER CODE END 1 */
+
+int main(void)
+{
+ SystemInit();
+ InitGearMotor();
+ Pid_Init();
+ DBG_PRINTF("==============================================================\r\n");
+ DBG_PRINTF(" • EulerCar Controller 1.0 • \r\n");
+ DBG_PRINTF(" \r\n");
+ DBG_PRINTF(" ➤ System Information: \r\n");
+ DBG_PRINTF(" • Motor Type:%s\r\n",g_motorTypeStr[g_curMotorType]);
+ DBG_PRINTF(" • Motor Encode Line Number:%05d\r\n",g_motorLineNum);
+ DBG_PRINTF(" • Motor Max Speed:%.02fmm/s\r\n", g_motorMaxSpeed);
+ DBG_PRINTF(" • EulerCar Data Send Period:%dms,%dHZ\r\n", EULER_CAR_DATA_SEND_PERIOD, 1000/EULER_CAR_DATA_SEND_PERIOD);
+ DBG_PRINTF(" \r\n");
+ DBG_PRINTF(" ➤ PID Information: \r\n");
+ DBG_PRINTF(" • KP:%.02f • KI:%.02f • KD:%.02f\r\n",g_KP,g_KI,g_KD);
+ DBG_PRINTF(" • PID Control Period:%dms\r\n",MOTOR_PID_CONTROL_PERIOD);
+ DBG_PRINTF("==============================================================\r\n");
+ DBG_PRINTF("EulerCar MCU init success!!!\r\n");
+ HAL_TIMER_Start(&g_timer0);
+ DBG_PRINTF("TIMER start\r\n");
+ InitButtonFunction();
+
+ UART3_INTRxSimultaneously();
+
+ /* USER CODE END 5 */
+ return BASE_STATUS_OK;
+}
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/pid.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/pid.c
new file mode 100644
index 0000000000000000000000000000000000000000..5bec0f05558481a98eb38aa4cdd3ae11dfeff0a9
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/pid.c
@@ -0,0 +1,114 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "debug.h"
+#include "gpio.h"
+#include "main.h"
+#include "pid.h"
+
+extern unsigned int g_TimerInterruptCount;
+unsigned int g_pid_count =0;
+
+/* 增量式PID控制结构体 */
+PidEulerCar g_pidEulerCarRight;
+PidEulerCar g_pidEulerCarLeft;
+
+//增量式PID参数
+float g_KP = 1.2;
+float g_KI = 15.0;
+float g_KD = 0.0;
+
+//通过按键调整PID参数的步进增量参数
+float g_KP_Step = 0.1;
+float g_KI_Step = 0.1;
+float g_KD_Step = 0;
+
+void Pid_Init(void)
+{
+ g_pidEulerCarRight.SetSpeed = 0;
+ g_pidEulerCarRight.ActualSpeed = 0;
+ g_pidEulerCarRight.duty = 0;
+ g_pidEulerCarRight.err = 0;
+ g_pidEulerCarRight.err_next = 0;
+ g_pidEulerCarRight.err_last = 0;
+ g_pidEulerCarRight.IncSpeed = 0;
+ g_pidEulerCarRight.TargetIncSpeed = 0;
+ //DBG_PRINTF("pid right init success\r\n");
+
+ g_pidEulerCarLeft.SetSpeed = 0;
+ g_pidEulerCarLeft.ActualSpeed = 0;
+ g_pidEulerCarLeft.duty = 0;
+ g_pidEulerCarLeft.err = 0;
+ g_pidEulerCarLeft.err_next = 0;
+ g_pidEulerCarLeft.err_last = 0;
+ g_pidEulerCarLeft.IncSpeed = 0;
+ g_pidEulerCarLeft.TargetIncSpeed = 0;
+ //DBG_PRINTF("pid left init success\r\n");
+}
+
+
+float Pid_Ctrl(PidEulerCar *pMotor)
+{
+ float IncrementSpeed;
+ unsigned int duty;
+
+ //计算当前误差
+ pMotor->err = pMotor->SetSpeed - pMotor->ActualSpeed;
+
+ //增量式PID算法计算出增量,越接近目标速度,增量越接近零
+ //增量式PID算法参数设定策略,先确定KI,再调KP,最后式KD
+ IncrementSpeed = g_KP * (pMotor->err - pMotor->err_next)
+ + g_KI * pMotor->err
+ + g_KD * (pMotor->err - 2 * pMotor->err_next + pMotor->err_last);
+ pMotor->TargetIncSpeed = pMotor->TargetIncSpeed + IncrementSpeed;
+
+
+/*
+ err = state.target - state.actual;;
+ integral += (err * time_delta);
+ derivative = (error - previous_error) / time_delta;
+ state.output = ( (kp * err) + (ki * integral) + (kd * derivative) );
+ state.previous_error = error;
+ return state;
+*/
+
+
+ pMotor->IncSpeed = IncrementSpeed;
+
+
+ //限制幅度
+ if(pMotor->SetSpeed > 0){
+ if (pMotor->TargetIncSpeed > g_motorMaxSpeed){
+ pMotor->TargetIncSpeed = g_motorMaxSpeed;
+ }
+ if (pMotor->TargetIncSpeed < 0){
+ pMotor->TargetIncSpeed = 0;
+ }
+ }
+
+ if(pMotor->SetSpeed < 0){
+ if (pMotor->TargetIncSpeed < -g_motorMaxSpeed){
+ pMotor->TargetIncSpeed = -g_motorMaxSpeed;
+ }
+ if (pMotor->TargetIncSpeed > 0){
+ pMotor->TargetIncSpeed = 0;
+ }
+ }
+
+ //电机需要设置的占空比
+ duty = (abs)((int)(pMotor->TargetIncSpeed/g_motorMaxSpeed * 100.0));
+ if (duty > 99) {
+ duty = 99;
+ }
+ pMotor->duty = duty;
+
+ pMotor->err_last = pMotor->err_next;
+ pMotor->err_next = pMotor->err;
+
+
+ return pMotor->TargetIncSpeed;
+}
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/pid.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/pid.h
new file mode 100644
index 0000000000000000000000000000000000000000..6521d1d2ad78720b6679981dc26b83df841a632a
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/pid.h
@@ -0,0 +1,19 @@
+#ifndef PID_H
+#define PID_H
+
+//增量式PID控制算法结构体
+typedef struct {
+ float SetSpeed; //上位机设定速度
+ float ActualSpeed; //编码器实际测试速度
+ float err; //偏差值
+ float err_next; //上一个偏差值
+ float err_last; //上上一个偏差值
+ float IncSpeed; //增量式PID算法计算出的增量速度
+ float TargetIncSpeed; //增量式PID算法目标增量速度
+ unsigned int duty; //电机PWM占空比
+} PidEulerCar;
+
+void Pid_Init(void);
+float Pid_Ctrl(PidEulerCar *pMotor);
+
+#endif
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306.c
new file mode 100644
index 0000000000000000000000000000000000000000..c9cd0317e0210ab07379122fe083a1a741a0a461
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306.c
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include // For memcpy
+#include
+#include
+#include
+#include
+#include "i2c.h"
+#include "main.h"
+#include "debug.h"
+#include "ssd1306.h"
+
+#define I2C_SLAVE2_ADDR 0x78
+#define SSD1306_CTRL_CMD 0x00
+#define SSD1306_CTRL_DATA 0x40
+#define SSD1306_MASK_CONT (0x1 << 7)
+#define DOUBLE 2
+
+
+void ssd1306_Reset(void)
+{
+ /* for I2C - do nothing */
+}
+
+static uint32_t ssd1306_SendData(uint8_t* buffer, uint32_t size)
+{
+ uint16_t dev_addr = I2C_SLAVE2_ADDR;
+ uint32_t retval = HAL_I2C_MasterWriteBlocking(&g_i2c1, dev_addr, buffer, size, 10000);
+ if (retval != BASE_STATUS_OK) {
+ DBG_PRINTF("I2cWrite(0x%X) failed, 0x%X!\n", buffer[1], retval);
+ return retval;
+ }
+ return 0;
+}
+
+static uint32_t ssd1306_WiteByte(uint8_t regAddr, uint8_t byte)
+{
+ uint8_t buffer[] = {regAddr, byte};
+ return ssd1306_SendData(buffer, sizeof(buffer));
+}
+
+// Send a byte to the command register
+void ssd1306_WriteCommand(uint8_t byte)
+{
+ ssd1306_WiteByte(SSD1306_CTRL_CMD, byte);
+}
+
+// Send data
+void ssd1306_WriteData(uint8_t* buffer, uint32_t buff_size)
+{
+ uint8_t data[SSD1306_WIDTH * DOUBLE] = {0};
+ for (uint32_t i = 0; i < buff_size; i++) {
+ data[i * DOUBLE] = SSD1306_CTRL_DATA | SSD1306_MASK_CONT;
+ data[i * DOUBLE + 1] = buffer[i];
+ }
+ data[(buff_size - 1) * DOUBLE] = SSD1306_CTRL_DATA;
+ ssd1306_SendData(data, sizeof(data));
+}
+
+// Screenbuffer
+static uint8_t SSD1306_Buffer[SSD1306_BUFFER_SIZE];
+
+// Screen object
+static SSD1306_t SSD1306;
+
+/* Fills the Screenbuffer with values from a given buffer of a fixed length */
+SSD1306_Error_t ssd1306_FillBuffer(uint8_t* buf, uint32_t len)
+{
+ SSD1306_Error_t ret = SSD1306_ERR;
+ if (len <= SSD1306_BUFFER_SIZE) {
+ memcpy_s(SSD1306_Buffer, len + 1, buf, len);
+ ret = SSD1306_OK;
+ }
+ return ret;
+}
+
+void ssd1306_Init_CMD(void)
+{
+ ssd1306_WriteCommand(0xA4); // 0xa4,Output follows RAM content;0xa5,Output ignores RAM content
+
+ ssd1306_WriteCommand(0xD3); // -set display offset - CHECK
+ ssd1306_WriteCommand(0x00); // -not offset
+
+ ssd1306_WriteCommand(0xD5); // --set display clock divide ratio/oscillator frequency
+ ssd1306_WriteCommand(0xF0); // --set divide ratio
+
+ ssd1306_WriteCommand(0xD9); // --set pre-charge period
+ ssd1306_WriteCommand(0x11); // 0x22 by default
+
+ ssd1306_WriteCommand(0xDA); // --set com pins hardware configuration - CHECK
+#if (SSD1306_HEIGHT == 32)
+ ssd1306_WriteCommand(0x02);
+#elif (SSD1306_HEIGHT == 64)
+ ssd1306_WriteCommand(0x12);
+#elif (SSD1306_HEIGHT == 128)
+ ssd1306_WriteCommand(0x12);
+#else
+#error "Only 32, 64, or 128 lines of height are supported!"
+#endif
+
+ ssd1306_WriteCommand(0xDB); // --set vcomh
+ ssd1306_WriteCommand(0x30); // 0x20,0.77xVcc, 0x30,0.83xVcc
+
+ ssd1306_WriteCommand(0x8D); // --set DC-DC enable
+ ssd1306_WriteCommand(0x14); //
+ ssd1306_SetDisplayOn(1); // --turn on SSD1306 panel
+}
+
+// Initialize the oled screen
+void ssd1306_Init(void)
+{
+ // Reset OLED
+ ssd1306_Reset();
+
+ // Wait for the screen to boot
+ BASE_FUNC_DELAY_MS(10); // 10000us The delay here is very important
+
+ // Init OLED
+ ssd1306_SetDisplayOn(0); // display off
+
+ ssd1306_WriteCommand(0x20); // Set Memory Addressing Mode
+ ssd1306_WriteCommand(0x00); // 00b,Horizontal Addressing Mode; 01b,Vertical Addressing Mode;
+ // 10b,Page Addressing Mode (RESET); 11b,Invalid
+
+ ssd1306_WriteCommand(0xB0); // Set Page Start Address for Page Addressing Mode,0-7
+
+#ifdef SSD1306_MIRROR_VERT
+ ssd1306_WriteCommand(0xC0); // Mirror vertically
+#else
+ ssd1306_WriteCommand(0xC8); // Set COM Output Scan Direction
+#endif
+
+ ssd1306_WriteCommand(0x00); // ---set low column address
+ ssd1306_WriteCommand(0x10); // ---set high column address
+
+ ssd1306_WriteCommand(0x40); // --set start line address - CHECK
+
+ ssd1306_SetContrast(0xFF);
+
+#ifdef SSD1306_MIRROR_HORIZ
+ ssd1306_WriteCommand(0xA0); // Mirror horizontally
+#else
+ ssd1306_WriteCommand(0xA1); // --set segment re-map 0 to 127 - CHECK
+#endif
+
+#ifdef SSD1306_INVERSE_COLOR
+ ssd1306_WriteCommand(0xA7); // --set inverse color
+#else
+ ssd1306_WriteCommand(0xA6); // --set normal color
+#endif
+
+// Set multiplex ratio.
+#if (SSD1306_HEIGHT == 128)
+ // Found in the Luma Python lib for SH1106.
+ ssd1306_WriteCommand(0xFF);
+#else
+ ssd1306_WriteCommand(0xA8); // --set multiplex ratio(1 to 64) - CHECK
+#endif
+
+#if (SSD1306_HEIGHT == 32)
+ ssd1306_WriteCommand(0x1F); //
+#elif (SSD1306_HEIGHT == 64)
+ ssd1306_WriteCommand(0x3F); //
+#elif (SSD1306_HEIGHT == 128)
+ ssd1306_WriteCommand(0x3F); // Seems to work for 128px high displays too.
+#else
+#error "Only 32, 64, or 128 lines of height are supported!"
+#endif
+ ssd1306_Init_CMD();
+ // Clear screen
+ ssd1306_Fill(Black);
+
+ // Flush buffer to screen
+ ssd1306_UpdateScreen();
+
+ // Set default values for screen object
+ SSD1306.CurrentX = 0;
+ SSD1306.CurrentY = 0;
+
+ SSD1306.Initialized = 1;
+}
+
+// Fill the whole screen with the given color
+void ssd1306_Fill(SSD1306_COLOR color)
+{
+ /* Set memory */
+ uint32_t i;
+
+ for (i = 0; i < sizeof(SSD1306_Buffer); i++) {
+ SSD1306_Buffer[i] = (color == Black) ? 0x00 : 0xFF;
+ }
+}
+
+// Write the screenbuffer with changed to the screen
+void ssd1306_UpdateScreen(void)
+{
+ // Write data to each page of RAM. Number of pages
+ // depends on the screen height:
+ //
+ // * 32px == 4 pages
+ // * 64px == 8 pages
+ // * 128px == 16 pages
+
+ uint8_t cmd[] = {
+ 0X21, // 设置列起始和结束地址
+ 0X00, // 列起始地址 0
+ 0X7F, // 列终止地址 127
+ 0X22, // 设置页起始和结束地址
+ 0X00, // 页起始地址 0
+ 0X07, // 页终止地址 7
+ };
+ uint32_t count = 0;
+ uint8_t data[sizeof(cmd) * DOUBLE + SSD1306_BUFFER_SIZE + 1] = {};
+
+ // copy cmd
+ for (uint32_t i = 0; i < sizeof(cmd) / sizeof(cmd[0]); i++) {
+ data[count++] = SSD1306_CTRL_CMD | SSD1306_MASK_CONT;
+ data[count++] = cmd[i];
+ }
+
+ // copy frame data
+ data[count++] = SSD1306_CTRL_DATA;
+ memcpy_s(&data[count], SSD1306_BUFFER_SIZE + 1, SSD1306_Buffer, SSD1306_BUFFER_SIZE);
+ count += sizeof(SSD1306_Buffer);
+
+ // send to i2c bus
+ uint32_t retval = ssd1306_SendData(data, count);
+ if (retval != 0) {
+ DBG_PRINTF("ssd1306_UpdateScreen send frame data filed: %d!\r\n", retval);
+ }
+}
+
+// Draw one pixel in the screenbuffer
+// X => X Coordinate
+// Y => Y Coordinate
+// color => Pixel color
+void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color)
+{
+ if (x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT) {
+ // Don't write outside the buffer
+ return;
+ }
+ SSD1306_COLOR color1 = color;
+ // Check if pixel should be inverted
+ if (SSD1306.Inverted) {
+ color1 = (SSD1306_COLOR)!color1;
+ }
+
+ // Draw in the right color
+ uint32_t c = 8; // 8
+ if (color == White) {
+ SSD1306_Buffer[x + (y / c) * SSD1306_WIDTH] |= 1 << (y % c);
+ } else {
+ SSD1306_Buffer[x + (y / c) * SSD1306_WIDTH] &= ~(1 << (y % c));
+ }
+}
+
+// Draw 1 char to the screen buffer
+// ch => char om weg te schrijven
+// Font => Font waarmee we gaan schrijven
+// color => Black or White
+char ssd1306_DrawChar(char ch, FontDef Font, SSD1306_COLOR color)
+{
+ uint32_t i, b, j;
+
+ // Check if character is valid
+ uint32_t ch_min = 32; // 32
+ uint32_t ch_max = 126; // 126
+ if ((uint32_t)ch < ch_min || (uint32_t)ch > ch_max) {
+ return 0;
+ }
+
+ // Check remaining space on current line
+ if (SSD1306_WIDTH < (SSD1306.CurrentX + Font.FontWidth) ||
+ SSD1306_HEIGHT < (SSD1306.CurrentY + Font.FontHeight)) {
+ // Not enough space on current line
+ return 0;
+ }
+
+ // Use the font to write
+ for (i = 0; i < Font.FontHeight; i++) {
+ b = Font.data[(ch - ch_min) * Font.FontHeight + i];
+ for (j = 0; j < Font.FontWidth; j++) {
+ if ((b << j) & 0x8000) {
+ ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR) color);
+ } else {
+ ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR)!color);
+ }
+ }
+ }
+
+ // The current space is now taken
+ SSD1306.CurrentX += Font.FontWidth;
+
+ // Return written char for validation
+ return ch;
+}
+
+// Write full string to screenbuffer
+char ssd1306_DrawString(char* str, FontDef Font, SSD1306_COLOR color)
+{
+ // Write until null-byte
+ char* str1 = str;
+ while (*str1) {
+ if (ssd1306_DrawChar(*str1, Font, color) != *str1) {
+ // Char could not be written
+ return *str1;
+ }
+ // Next char
+ str1++;
+ }
+
+ // Everything ok
+ return *str1;
+}
+
+// Position the cursor
+void ssd1306_SetCursor(uint8_t x, uint8_t y)
+{
+ SSD1306.CurrentX = x;
+ SSD1306.CurrentY = y;
+}
+
+// Draw line by Bresenhem's algorithm
+void ssd1306_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color)
+{
+ uint8_t x = x1;
+ uint8_t y = y1;
+ int32_t deltaX = abs(x2 - x1);
+ int32_t deltaY = abs(y2 - y1);
+ int32_t signX = ((x1 < x2) ? 1 : -1);
+ int32_t signY = ((y1 < y2) ? 1 : -1);
+ int32_t error = deltaX - deltaY;
+ int32_t error2;
+ ssd1306_DrawPixel(x2, y2, color);
+ while ((x1 != x2) || (y1 != y2)) {
+ ssd1306_DrawPixel(x1, y1, color);
+ error2 = error * DOUBLE;
+ if (error2 > -deltaY) {
+ error -= deltaY;
+ x += signX;
+ } else {
+ /* nothing to do */
+ }
+ if (error2 < deltaX) {
+ error += deltaX;
+ y += signY;
+ } else {
+ /* nothing to do */
+ }
+ }
+}
+
+// Draw polyline
+void ssd1306_DrawPolyline(const SSD1306_VERTEX *par_vertex, uint16_t par_size, SSD1306_COLOR color)
+{
+ uint16_t i;
+ if (par_vertex != 0) {
+ for (i = 1; i < par_size; i++) {
+ ssd1306_DrawLine(par_vertex[i - 1].x, par_vertex[i - 1].y, par_vertex[i].x, par_vertex[i].y, color);
+ }
+ } else {
+ /* nothing to do */
+ }
+ return;
+}
+
+// Draw circle by Bresenhem's algorithm
+void ssd1306_DrawCircle(uint8_t par_x, uint8_t par_y, uint8_t par_r, SSD1306_COLOR par_color)
+{
+ int32_t x = -par_r;
+ int32_t y = 0;
+ int32_t b = 2;
+ int32_t err = b - b * par_r;
+ int32_t e2;
+
+ if (par_x >= SSD1306_WIDTH || par_y >= SSD1306_HEIGHT) {
+ return;
+ }
+
+ do {
+ ssd1306_DrawPixel(par_x - x, par_y + y, par_color);
+ ssd1306_DrawPixel(par_x + x, par_y + y, par_color);
+ ssd1306_DrawPixel(par_x + x, par_y - y, par_color);
+ ssd1306_DrawPixel(par_x - x, par_y - y, par_color);
+ e2 = err;
+ if (e2 <= y) {
+ y++;
+ err = err + (y * b + 1);
+ if (-x == y && e2 <= x) {
+ e2 = 0;
+ } else {
+ /* nothing to do */
+ }
+ } else {
+ /* nothing to do */
+ }
+ if (e2 > x) {
+ x++;
+ err = err + (x * b + 1);
+ } else {
+ /* nothing to do */
+ }
+ } while (x <= 0);
+
+ return;
+}
+
+// Draw rectangle
+void ssd1306_DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color)
+{
+ ssd1306_DrawLine(x1, y1, x2, y1, color);
+ ssd1306_DrawLine(x2, y1, x2, y2, color);
+ ssd1306_DrawLine(x2, y2, x1, y2, color);
+ ssd1306_DrawLine(x1, y2, x1, y1, color);
+}
+
+void ssd1306_DrawBitmap(const uint8_t* bitmap, uint32_t size)
+{
+ unsigned int c = 8;
+ uint8_t rows = size * c / SSD1306_WIDTH;
+ if (rows > SSD1306_HEIGHT) {
+ rows = SSD1306_HEIGHT;
+ }
+ for (uint8_t y = 0; y < rows; y++) {
+ for (uint8_t x = 0; x < SSD1306_WIDTH; x++) {
+ uint8_t byte = bitmap[(y * SSD1306_WIDTH / c) + (x / c)];
+ uint8_t bit = byte & (0x80 >> (x % c));
+ ssd1306_DrawPixel(x, y, bit ? White : Black);
+ }
+ }
+}
+
+void ssd1306_DrawRegion(uint8_t x, uint8_t y, uint8_t w, const uint8_t* data, uint32_t size)
+{
+ uint32_t stride = w;
+ uint8_t h = w; // 字体宽高一样
+ uint8_t width = w;
+ if (x + w > SSD1306_WIDTH || y + h > SSD1306_HEIGHT || w * h == 0) {
+ DBG_PRINTF("%dx%d @ %d,%d out of range or invalid!\r\n", w, h, x, y);
+ return;
+ }
+
+ width = (width <= SSD1306_WIDTH ? width : SSD1306_WIDTH);
+ h = (h <= SSD1306_HEIGHT ? h : SSD1306_HEIGHT);
+ stride = (stride == 0 ? w : stride);
+ unsigned int c = 8;
+
+ uint8_t rows = size * c / stride;
+ for (uint8_t i = 0; i < rows; i++) {
+ uint32_t base = i * stride / c;
+ for (uint8_t j = 0; j < width; j++) {
+ uint32_t idx = base + (j / c);
+ uint8_t byte = idx < size ? data[idx] : 0;
+ uint8_t bit = byte & (0x80 >> (j % c));
+ ssd1306_DrawPixel(x + j, y + i, bit ? White : Black);
+ }
+ }
+}
+
+void ssd1306_SetContrast(const uint8_t value)
+{
+ const uint8_t kSetContrastControlRegister = 0x81;
+ ssd1306_WriteCommand(kSetContrastControlRegister);
+ ssd1306_WriteCommand(value);
+}
+
+void ssd1306_SetDisplayOn(const uint8_t on)
+{
+ uint8_t value;
+ if (on) {
+ value = 0xAF; // Display on
+ SSD1306.DisplayOn = 1;
+ } else {
+ value = 0xAE; // Display off
+ SSD1306.DisplayOn = 0;
+ }
+ ssd1306_WriteCommand(value);
+}
+
+uint8_t ssd1306_GetDisplayOn(void)
+{
+ return SSD1306.DisplayOn;
+}
+
+void *memcpy_custom(void *dest, const void *src, size_t n)
+{
+ char *d = (char *)dest;
+ const char *s = (const char *)src;
+
+ // 逐字节复制源字符串到目标字符串
+ for (size_t i = 0; i < n; i++) {
+ d[i] = s[i];
+ }
+
+ return dest;
+}
+
+#define SSD_MAX_LENGTH 12
+void ssd1306_print(char *str) // 每行最多11个字节,最多三行,Y轴20
+{
+ int str_length = strlen(str);
+ if (str_length > 33)
+ {
+ DBG_PRINTF("ssd1306_print len %d \r\n",str_length);
+ return;
+ }
+ ssd1306_Fill(Black);
+
+ if (str_length <= 11) //1行
+ {
+ ssd1306_SetCursor(1, 0);
+ ssd1306_DrawString(str, Font_11x18, White);
+ ssd1306_UpdateScreen();
+ return;
+ }
+
+ if ((str_length > 11) && (str_length <= 22)) //2行
+ {
+ ssd1306_SetCursor(1, 0);
+ char buff[SSD_MAX_LENGTH] = {0};
+ memcpy_custom(buff,str,11);
+ ssd1306_DrawString(buff, Font_11x18, White);
+ ssd1306_SetCursor(1, 20);
+ ssd1306_DrawString(str+11, Font_11x18, White);
+ ssd1306_UpdateScreen();
+ return;
+ }
+
+ if (str_length > 22) //3行
+ {
+ ssd1306_SetCursor(1, 0);
+ char buff[SSD_MAX_LENGTH] = {0};
+ memcpy_custom(buff,str,11);
+ ssd1306_DrawString(buff, Font_11x18, White);
+ ssd1306_SetCursor(1, 20);
+ memcpy_custom(buff,str+11,11);
+ ssd1306_DrawString(buff, Font_11x18, White);
+
+ ssd1306_SetCursor(1, 40);
+ ssd1306_DrawString(str+22, Font_11x18, White);
+ ssd1306_UpdateScreen();
+ return;
+ }
+}
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306.h
new file mode 100644
index 0000000000000000000000000000000000000000..bf6f82874848b74b4a87c62a2469210f725eecfb
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SSD1306_H
+#define SSD1306_H
+
+#include
+#include
+#include "ssd1306_fonts.h"
+
+/* vvv I2C config vvv */
+
+#define SSD1306_USE_I2C
+#ifndef SSD1306_I2C_PORT
+#define SSD1306_I2C_PORT hi2c1
+#endif
+
+// #ifndef SSD1306_I2C_ADDR
+// #define SSD1306_I2C_ADDR (0x3C << 1)
+// #endif
+
+/* ^^^ I2C config ^^^ */
+
+/* vvv SPI config vvv */
+
+#ifndef SSD1306_SPI_PORT
+#define SSD1306_SPI_PORT hspi2
+#endif
+
+#ifndef SSD1306_CS_Port
+#define SSD1306_CS_Port GPIOB
+#endif
+#ifndef SSD1306_CS_Pin
+#define SSD1306_CS_Pin GPIO_PIN_12
+#endif
+
+#ifndef SSD1306_DC_Port
+#define SSD1306_DC_Port GPIOB
+#endif
+#ifndef SSD1306_DC_Pin
+#define SSD1306_DC_Pin GPIO_PIN_14
+#endif
+
+#ifndef SSD1306_Reset_Port
+#define SSD1306_Reset_Port GPIOA
+#endif
+#ifndef SSD1306_Reset_Pin
+#define SSD1306_Reset_Pin GPIO_PIN_8
+#endif
+
+/* ^^^ SPI config ^^^ */
+
+#if defined(SSD1306_USE_I2C)
+#elif defined(SSD1306_USE_SPI)
+extern SPI_HandleTypeDef SSD1306_SPI_PORT;
+#else
+#error "You should define SSD1306_USE_SPI or SSD1306_USE_I2C macro!"
+#endif
+
+// SSD1306 OLED height in pixels
+#ifndef SSD1306_HEIGHT
+#define SSD1306_HEIGHT 64
+#endif
+
+// SSD1306 width in pixels
+#ifndef SSD1306_WIDTH
+#define SSD1306_WIDTH 128
+#endif
+
+// some LEDs don't display anything in first two columns
+
+#ifndef SSD1306_BUFFER_SIZE
+#define SSD1306_BUFFER_SIZE (SSD1306_WIDTH * SSD1306_HEIGHT / 8)
+#endif
+
+// Enumeration for screen colors
+typedef enum {
+ Black = 0x00, // Black color, no pixel
+ White = 0x01 // Pixel is set. Color depends on OLED
+} SSD1306_COLOR;
+
+typedef enum {
+ SSD1306_OK = 0x00,
+ SSD1306_ERR = 0x01 // Generic error.
+} SSD1306_Error_t;
+
+// Struct to store transformations
+typedef struct {
+ uint16_t CurrentX;
+ uint16_t CurrentY;
+ uint8_t Inverted;
+ uint8_t Initialized;
+ uint8_t DisplayOn;
+} SSD1306_t;
+typedef struct {
+ uint8_t x;
+ uint8_t y;
+} SSD1306_VERTEX;
+
+// Procedure definitions
+void ssd1306_Init(void);
+void ssd1306_Fill(SSD1306_COLOR color);
+void ssd1306_SetCursor(uint8_t x, uint8_t y);
+void ssd1306_UpdateScreen(void);
+
+char ssd1306_DrawChar(char ch, FontDef Font, SSD1306_COLOR color);
+char ssd1306_DrawString(char* str, FontDef Font, SSD1306_COLOR color);
+
+void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color);
+void ssd1306_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color);
+void ssd1306_DrawPolyline(const SSD1306_VERTEX *par_vertex, uint16_t par_size, SSD1306_COLOR color);
+void ssd1306_DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color);
+void ssd1306_DrawCircle(uint8_t par_x, uint8_t par_y, uint8_t par_r, SSD1306_COLOR par_color);
+void ssd1306_DrawBitmap(const uint8_t* bitmap, uint32_t size);
+void ssd1306_DrawRegion(uint8_t x, uint8_t y, uint8_t w, const uint8_t* data, uint32_t size);
+void *memcpy_custom(void *dest, const void *src, size_t n);
+
+/**
+ * @brief Sets the contrast of the display.
+ * @param[in] value contrast to set.
+ * @note Contrast increases as the value increases.
+ * @note RESET = 7Fh.
+ */
+void ssd1306_SetContrast(const uint8_t value);
+/**
+ * @brief Set Display ON/OFF.
+ * @param[in] on 0 for OFF, any for ON.
+ */
+void ssd1306_SetDisplayOn(const uint8_t on);
+/**
+ * @brief Reads DisplayOn state.
+ * @return 0: OFF.
+ * 1: ON.
+ */
+uint8_t ssd1306_GetDisplayOn(void);
+
+void HAL_Delay(uint32_t ms);
+
+uint32_t HAL_GetTick(void); // in ms
+
+// Low-level procedures
+void ssd1306_Init_CMD(void);
+void ssd1306_Reset(void);
+void ssd1306_WriteCommand(uint8_t byte);
+void ssd1306_WriteData(uint8_t* buffer, size_t buff_size);
+SSD1306_Error_t ssd1306_FillBuffer(uint8_t* buf, uint32_t len);
+void ssd1306_ClearOLED(void);
+void ssd1306_printf(char *fmt, ...);
+void ssd1306_print(char *str);
+
+#endif // __SSD1306_H__
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306_fonts.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306_fonts.c
new file mode 100644
index 0000000000000000000000000000000000000000..725489259f7eef0f72ae7a71269ea9311f798eaf
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306_fonts.c
@@ -0,0 +1,915 @@
+/*
+ MIT License
+
+ Copyright (c) 2018-2019, Alexey Dynda
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+/*
+ * ssd1306xled_font6x8 is by Neven Boyanov
+ * ssd1306xled_font8x16 is by Neven Boyanov
+ *
+ * @created: 2014-08-12
+ * @author: Neven Boyanov
+ *
+ * Copyright (c) 2015 Neven Boyanov, Tinusaur Team. All Rights Reserved.
+ * Distributed as open source software under MIT License, see LICENSE.txt file.
+ * Please, as a favour, retain the link http://tinusaur.org to The Tinusaur Project.
+ *
+ * Source code available at: https://bitbucket.org/tinusaur/ssd1306xled
+ *
+ */
+
+#include "ssd1306_fonts.h"
+
+/************************************6*8的点阵************************************/
+const unsigned char g_f6X8[][6] = {
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp
+ { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, // !
+ { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, // "
+ { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // #
+ { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $
+ { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, // %
+ { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, // &
+ { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, // '
+ { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, // (
+ { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, // )
+ { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, // *
+ { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, // +
+ { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, // ,
+ { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, // -
+ { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, // .
+ { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, // /
+ { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0
+ { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1
+ { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2
+ { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3
+ { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4
+ { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5
+ { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6
+ { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7
+ { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8
+ { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9
+ { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, // :
+ { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, // ;号
+ { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, // <
+ { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, // =
+ { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, // >
+ { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, // ?
+ { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, // @
+ { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A
+ { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B
+ { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C
+ { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D
+ { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E
+ { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F
+ { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G
+ { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H
+ { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I
+ { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J
+ { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K
+ { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L
+ { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M
+ { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N
+ { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O
+ { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P
+ { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q
+ { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R
+ { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, // S
+ { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T
+ { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U
+ { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V
+ { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W
+ { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, // X
+ { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y
+ { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z
+ { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [
+ { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // 55
+ { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ]
+ { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^
+ { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, // _
+ { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, // '
+ { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, // a
+ { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b
+ { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, // c
+ { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, // d
+ { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, // e
+ { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f
+ { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g
+ { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h
+ { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i
+ { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j
+ { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k
+ { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l
+ { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m
+ { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n
+ { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, // o
+ { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p
+ { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, // q
+ { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r
+ { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, // s
+ { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t
+ { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u
+ { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v
+ { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w
+ { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, // x
+ { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y
+ { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z
+ { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }, // horiz lines
+};
+
+/****************************************8*16的点阵************************************/
+const unsigned char g_f8X16[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0
+ 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00, // ! 1
+ 0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // " 2
+ 0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00, 0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00, // # 3
+ 0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00, 0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00, // $ 4
+ 0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00, 0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00, // % 5
+ 0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10, // & 6
+ 0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ' 7
+ 0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00, // ( 8
+ 0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, // ) 9
+ 0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00, 0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00, // * 10
+ 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00, // + 11
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, // , 12
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // - 13
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, // . 14
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04, 0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, // / 15
+ 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00, // 0 16
+ 0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // 1 17
+ 0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00, // 2 18
+ 0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // 3 19
+ 0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00, // 4 20
+ 0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00, // 5 21
+ 0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // 6 22
+ 0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, // 7 23
+ 0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00, // 8 24
+ 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00, // 9 25
+ 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, // : 26
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, // ;号 27
+ 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, // < 28
+ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, // = 29
+ 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, // > 30
+ 0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00, // ? 31
+ 0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00, 0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00, // @ 32
+ 0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20, // A 33
+ 0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // B 34
+ 0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, // C 35
+ 0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // D 36
+ 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00, // E 37
+ 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, // F 38
+ 0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00, // G 39
+ 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20, // H 40
+ 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // I 41
+ 0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00, // J 42
+ 0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00, 0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00, // K 43
+ 0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00, // L 44
+ 0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00, // M 45
+ 0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00, // N 46
+ 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // O 47
+ 0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00, // P 48
+ 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00, // Q 49
+ 0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20, // R 50
+ 0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00, // S 51
+ 0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // T 52
+ 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // U 53
+ 0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00, // V 54
+ 0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00, 0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00, // W 55
+ 0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08, 0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20, // X 56
+ 0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // Y 57
+ 0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00, // Z 58
+ 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00, // [ 59
+ 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00, // \ 60
+ 0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00, // ] 61
+ 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ^ 62
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // _ 63
+ 0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ` 64
+ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20, // a 65
+ 0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // b 66
+ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00, // c 67
+ 0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20, // d 68
+ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00, // e 69
+ 0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // f 70
+ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00, // g 71
+ 0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // h 72
+ 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // i 73
+ 0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, // j 74
+ 0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00, // k 75
+ 0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // l 76
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F, // m 77
+ 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // n 78
+ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // o 79
+ 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00, // p 80
+ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80, // q 81
+ 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00, // r 82
+ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00, // s 83
+ 0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00, // t 84
+ 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20, // u 85
+ 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00, // v 86
+ 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, 0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00, // w 87
+ 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00, // x 88
+ 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00, // y 89
+ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00, // z 90
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40, // { 91
+ 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, // | 92
+ 0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, // } 93
+ 0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ~ 94
+};
+
+
+static const unsigned short Font7x10 [] = {
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp
+0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // !
+0x2800, 0x2800, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // "
+0x2400, 0x2400, 0x7C00, 0x2400, 0x4800, 0x7C00, 0x4800, 0x4800, 0x0000, 0x0000, // #
+0x3800, 0x5400, 0x5000, 0x3800, 0x1400, 0x5400, 0x5400, 0x3800, 0x1000, 0x0000, // $
+0x2000, 0x5400, 0x5800, 0x3000, 0x2800, 0x5400, 0x1400, 0x0800, 0x0000, 0x0000, // %
+0x1000, 0x2800, 0x2800, 0x1000, 0x3400, 0x4800, 0x4800, 0x3400, 0x0000, 0x0000, // &
+0x1000, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // '
+0x0800, 0x1000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x1000, 0x0800, // (
+0x2000, 0x1000, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x1000, 0x2000, // )
+0x1000, 0x3800, 0x1000, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // *
+0x0000, 0x0000, 0x1000, 0x1000, 0x7C00, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, // +
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // ,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3800, 0x0000, 0x0000, 0x0000, 0x0000, // -
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // .
+0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x0000, 0x0000, // /
+0x3800, 0x4400, 0x4400, 0x5400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 0
+0x1000, 0x3000, 0x5000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // 1
+0x3800, 0x4400, 0x4400, 0x0400, 0x0800, 0x1000, 0x2000, 0x7C00, 0x0000, 0x0000, // 2
+0x3800, 0x4400, 0x0400, 0x1800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 3
+0x0800, 0x1800, 0x2800, 0x2800, 0x4800, 0x7C00, 0x0800, 0x0800, 0x0000, 0x0000, // 4
+0x7C00, 0x4000, 0x4000, 0x7800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 5
+0x3800, 0x4400, 0x4000, 0x7800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 6
+0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x2000, 0x2000, 0x0000, 0x0000, // 7
+0x3800, 0x4400, 0x4400, 0x3800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 8
+0x3800, 0x4400, 0x4400, 0x4400, 0x3C00, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 9
+0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // :
+0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // ;
+0x0000, 0x0000, 0x0C00, 0x3000, 0x4000, 0x3000, 0x0C00, 0x0000, 0x0000, 0x0000, // <
+0x0000, 0x0000, 0x0000, 0x7C00, 0x0000, 0x7C00, 0x0000, 0x0000, 0x0000, 0x0000, // =
+0x0000, 0x0000, 0x6000, 0x1800, 0x0400, 0x1800, 0x6000, 0x0000, 0x0000, 0x0000, // >
+0x3800, 0x4400, 0x0400, 0x0800, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // ?
+0x3800, 0x4400, 0x4C00, 0x5400, 0x5C00, 0x4000, 0x4000, 0x3800, 0x0000, 0x0000, // @
+0x1000, 0x2800, 0x2800, 0x2800, 0x2800, 0x7C00, 0x4400, 0x4400, 0x0000, 0x0000, // A
+0x7800, 0x4400, 0x4400, 0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x0000, 0x0000, // B
+0x3800, 0x4400, 0x4000, 0x4000, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // C
+0x7000, 0x4800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4800, 0x7000, 0x0000, 0x0000, // D
+0x7C00, 0x4000, 0x4000, 0x7C00, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // E
+0x7C00, 0x4000, 0x4000, 0x7800, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // F
+0x3800, 0x4400, 0x4000, 0x4000, 0x5C00, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // G
+0x4400, 0x4400, 0x4400, 0x7C00, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // H
+0x3800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3800, 0x0000, 0x0000, // I
+0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // J
+0x4400, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // K
+0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // L
+0x4400, 0x6C00, 0x6C00, 0x5400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // M
+0x4400, 0x6400, 0x6400, 0x5400, 0x5400, 0x4C00, 0x4C00, 0x4400, 0x0000, 0x0000, // N
+0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // O
+0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // P
+0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x5400, 0x3800, 0x0400, 0x0000, // Q
+0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // R
+0x3800, 0x4400, 0x4000, 0x3000, 0x0800, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // S
+0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // T
+0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // U
+0x4400, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x1000, 0x0000, 0x0000, // V
+0x4400, 0x4400, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // W
+0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, // X
+0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // Y
+0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // Z
+0x1800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1800, // [
+0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x0000, 0x0000, /* \ */
+0x3000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3000, // ]
+0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFE00, // _
+0x2000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // `
+0x0000, 0x0000, 0x3800, 0x4400, 0x3C00, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // a
+0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x0000, 0x0000, // b
+0x0000, 0x0000, 0x3800, 0x4400, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // c
+0x0400, 0x0400, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // d
+0x0000, 0x0000, 0x3800, 0x4400, 0x7C00, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // e
+0x0C00, 0x1000, 0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // f
+0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x7800, // g
+0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // h
+0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // i
+0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0xE000, // j
+0x4000, 0x4000, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4400, 0x0000, 0x0000, // k
+0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // l
+0x0000, 0x0000, 0x7800, 0x5400, 0x5400, 0x5400, 0x5400, 0x5400, 0x0000, 0x0000, // m
+0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // n
+0x0000, 0x0000, 0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // o
+0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x4000, 0x4000, // p
+0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x0400, // q
+0x0000, 0x0000, 0x5800, 0x6400, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // r
+0x0000, 0x0000, 0x3800, 0x4400, 0x3000, 0x0800, 0x4400, 0x3800, 0x0000, 0x0000, // s
+0x2000, 0x2000, 0x7800, 0x2000, 0x2000, 0x2000, 0x2000, 0x1800, 0x0000, 0x0000, // t
+0x0000, 0x0000, 0x4400, 0x4400, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // u
+0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x0000, 0x0000, // v
+0x0000, 0x0000, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // w
+0x0000, 0x0000, 0x4400, 0x2800, 0x1000, 0x1000, 0x2800, 0x4400, 0x0000, 0x0000, // x
+0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x6000, // y
+0x0000, 0x0000, 0x7C00, 0x0800, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // z
+0x1800, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1800, // {
+0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, // |
+0x3000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x3000, // }
+0x0000, 0x0000, 0x0000, 0x7400, 0x4C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~
+};
+
+static const unsigned short Font11x18 [] = {
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp
+0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00,
+0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // !
+0x0000, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // "
+0x0000, 0x1980, 0x1980, 0x1980, 0x1980, 0x7FC0, 0x7FC0, 0x1980, 0x3300,
+0x7FC0, 0x7FC0, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, 0x0000, 0x0000, // #
+0x0000, 0x1E00, 0x3F00, 0x7580, 0x6580, 0x7400, 0x3C00, 0x1E00, 0x0700,
+0x0580, 0x6580, 0x6580, 0x7580, 0x3F00, 0x1E00, 0x0400, 0x0400, 0x0000, // $
+0x0000, 0x7000, 0xD800, 0xD840, 0xD8C0, 0xD980, 0x7300, 0x0600, 0x0C00,
+0x1B80, 0x36C0, 0x66C0, 0x46C0, 0x06C0, 0x0380, 0x0000, 0x0000, 0x0000, // %
+0x0000, 0x1E00, 0x3F00, 0x3300, 0x3300, 0x3300, 0x1E00, 0x0C00, 0x3CC0,
+0x66C0, 0x6380, 0x6180, 0x6380, 0x3EC0, 0x1C80, 0x0000, 0x0000, 0x0000, // &
+0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // '
+0x0080, 0x0100, 0x0300, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x0C00,
+0x0C00, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0300, 0x0100, 0x0080, // (
+0x2000, 0x1000, 0x1800, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0600,
+0x0600, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x1800, 0x1000, 0x2000, // )
+0x0000, 0x0C00, 0x2D00, 0x3F00, 0x1E00, 0x3300, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // *
+0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0xFFC0, 0xFFC0,
+0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // +
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // ,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x1E00, 0x1E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // -
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // .
+0x0000, 0x0300, 0x0300, 0x0300, 0x0600, 0x0600, 0x0600, 0x0600, 0x0C00,
+0x0C00, 0x0C00, 0x0C00, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // /
+0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6D80, 0x6D80,
+0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 0
+0x0000, 0x0600, 0x0E00, 0x1E00, 0x3600, 0x2600, 0x0600, 0x0600, 0x0600,
+0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 1
+0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6180, 0x0180, 0x0300, 0x0600,
+0x0C00, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // 2
+0x0000, 0x1C00, 0x3E00, 0x6300, 0x6300, 0x0300, 0x0E00, 0x0E00, 0x0300,
+0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 3
+0x0000, 0x0600, 0x0E00, 0x0E00, 0x1E00, 0x1E00, 0x1600, 0x3600, 0x3600,
+0x6600, 0x7F80, 0x7F80, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 4
+0x0000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x6380,
+0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 5
+0x0000, 0x1E00, 0x3F00, 0x3380, 0x6180, 0x6000, 0x6E00, 0x7F00, 0x7380,
+0x6180, 0x6180, 0x6180, 0x3380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 6
+0x0000, 0x7F80, 0x7F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0600, 0x0C00,
+0x0C00, 0x0C00, 0x0800, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // 7
+0x0000, 0x1E00, 0x3F00, 0x6380, 0x6180, 0x6180, 0x2100, 0x1E00, 0x3F00,
+0x6180, 0x6180, 0x6180, 0x6180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 8
+0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80,
+0x1D80, 0x0180, 0x6180, 0x7300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 9
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // :
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // ;
+0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0380, 0x0E00, 0x3800, 0x6000,
+0x3800, 0x0E00, 0x0380, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // <
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7F80, 0x7F80, 0x0000, 0x0000,
+0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // =
+0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x7000, 0x1C00, 0x0700, 0x0180,
+0x0700, 0x1C00, 0x7000, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // >
+0x0000, 0x1F00, 0x3F80, 0x71C0, 0x60C0, 0x00C0, 0x01C0, 0x0380, 0x0700,
+0x0E00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // ?
+0x0000, 0x1E00, 0x3F00, 0x3180, 0x7180, 0x6380, 0x6F80, 0x6D80, 0x6D80,
+0x6F80, 0x6780, 0x6000, 0x3200, 0x3E00, 0x1C00, 0x0000, 0x0000, 0x0000, // @
+0x0000, 0x0E00, 0x0E00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x3180, 0x3180,
+0x3F80, 0x3F80, 0x3180, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // A
+0x0000, 0x7C00, 0x7E00, 0x6300, 0x6300, 0x6300, 0x6300, 0x7E00, 0x7E00,
+0x6300, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x0000, 0x0000, 0x0000, // B
+0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6000,
+0x6000, 0x6000, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // C
+0x0000, 0x7C00, 0x7F00, 0x6300, 0x6380, 0x6180, 0x6180, 0x6180, 0x6180,
+0x6180, 0x6180, 0x6300, 0x6300, 0x7E00, 0x7C00, 0x0000, 0x0000, 0x0000, // D
+0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00,
+0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // E
+0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00,
+0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // F
+0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6380,
+0x6380, 0x6180, 0x6180, 0x3180, 0x3F80, 0x1E00, 0x0000, 0x0000, 0x0000, // G
+0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x7F80, 0x7F80,
+0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // H
+0x0000, 0x3F00, 0x3F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00,
+0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3F00, 0x3F00, 0x0000, 0x0000, 0x0000, // I
+0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180,
+0x0180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // J
+0x0000, 0x60C0, 0x6180, 0x6300, 0x6600, 0x6600, 0x6C00, 0x7800, 0x7C00,
+0x6600, 0x6600, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // K
+0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000,
+0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // L
+0x0000, 0x71C0, 0x71C0, 0x7BC0, 0x7AC0, 0x6AC0, 0x6AC0, 0x6EC0, 0x64C0,
+0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // M
+0x0000, 0x7180, 0x7180, 0x7980, 0x7980, 0x7980, 0x6D80, 0x6D80, 0x6D80,
+0x6580, 0x6780, 0x6780, 0x6780, 0x6380, 0x6380, 0x0000, 0x0000, 0x0000, // N
+0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180,
+0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // O
+0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6180, 0x6380, 0x7F00,
+0x7E00, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // P
+0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180,
+0x6180, 0x6580, 0x6780, 0x3300, 0x3F80, 0x1E40, 0x0000, 0x0000, 0x0000, // Q
+0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00,
+0x6600, 0x6300, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // R
+0x0000, 0x0E00, 0x1F00, 0x3180, 0x3180, 0x3000, 0x3800, 0x1E00, 0x0700,
+0x0380, 0x6180, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // S
+0x0000, 0xFFC0, 0xFFC0, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00,
+0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // T
+0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180,
+0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // U
+0x0000, 0x60C0, 0x60C0, 0x60C0, 0x3180, 0x3180, 0x3180, 0x1B00, 0x1B00,
+0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x0400, 0x0000, 0x0000, 0x0000, // V
+0x0000, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xCCC0, 0x4C80, 0x4C80,
+0x5E80, 0x5280, 0x5280, 0x7380, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // W
+0x0000, 0xC0C0, 0x6080, 0x6180, 0x3300, 0x3B00, 0x1E00, 0x0C00, 0x0C00,
+0x1E00, 0x1F00, 0x3B00, 0x7180, 0x6180, 0xC0C0, 0x0000, 0x0000, 0x0000, // X
+0x0000, 0xC0C0, 0x6180, 0x6180, 0x3300, 0x3300, 0x1E00, 0x1E00, 0x0C00,
+0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // Y
+0x0000, 0x3F80, 0x3F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0C00, 0x0C00,
+0x1800, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // Z
+0x0F00, 0x0F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00,
+0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0F00, 0x0F00, // [
+0x0000, 0x1800, 0x1800, 0x1800, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0600,
+0x0600, 0x0600, 0x0600, 0x0300, 0x0300, 0x0300, 0x0000, 0x0000, 0x0000, /* \ */
+0x1E00, 0x1E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600,
+0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x1E00, 0x1E00, // ]
+0x0000, 0x0C00, 0x0C00, 0x1E00, 0x1200, 0x3300, 0x3300, 0x6180, 0x6180,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFE0, 0x0000, // _
+0x0000, 0x3800, 0x1800, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // `
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F00, 0x3F80, 0x6180, 0x0180,
+0x1F80, 0x3F80, 0x6180, 0x6380, 0x7F80, 0x38C0, 0x0000, 0x0000, 0x0000, // a
+0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x7380, 0x6180,
+0x6180, 0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x0000, 0x0000, 0x0000, // b
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180,
+0x6000, 0x6000, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // c
+0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x1D80, 0x3F80, 0x7380, 0x6180,
+0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0000, 0x0000, 0x0000, // d
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180,
+0x7F80, 0x7F80, 0x6000, 0x7180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // e
+0x0000, 0x07C0, 0x0FC0, 0x0C00, 0x0C00, 0x7F80, 0x7F80, 0x0C00, 0x0C00,
+0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // f
+0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180,
+0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x6380, 0x7F00, 0x3E00, // g
+0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6F00, 0x7F80, 0x7180, 0x6180,
+0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // h
+0x0000, 0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600,
+0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // i
+0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600,
+0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x4600, 0x7E00, 0x3C00, // j
+0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6180, 0x6300, 0x6600, 0x6C00,
+0x7C00, 0x7600, 0x6300, 0x6300, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // k
+0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600,
+0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // l
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xFFC0, 0xCEC0, 0xCCC0,
+0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0x0000, 0x0000, 0x0000, // m
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6F00, 0x7F80, 0x7180, 0x6180,
+0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // n
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180,
+0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // o
+0x0000, 0x0000, 0x0000, 0x0000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180,
+0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x6000, 0x6000, 0x6000, 0x6000, // p
+0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180,
+0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x0180, 0x0180, 0x0180, // q
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6700, 0x3F80, 0x3900, 0x3000,
+0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, // r
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F80, 0x6180, 0x6000,
+0x7F00, 0x3F80, 0x0180, 0x6180, 0x7F00, 0x1E00, 0x0000, 0x0000, 0x0000, // s
+0x0000, 0x0000, 0x0800, 0x1800, 0x1800, 0x7F00, 0x7F00, 0x1800, 0x1800,
+0x1800, 0x1800, 0x1800, 0x1800, 0x1F80, 0x0F80, 0x0000, 0x0000, 0x0000, // t
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x6180, 0x6180,
+0x6180, 0x6180, 0x6180, 0x6380, 0x7F80, 0x3D80, 0x0000, 0x0000, 0x0000, // u
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x60C0, 0x3180, 0x3180, 0x3180,
+0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0600, 0x0000, 0x0000, 0x0000, // v
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xDD80, 0xDD80, 0x5500,
+0x5500, 0x5500, 0x7700, 0x7700, 0x2200, 0x2200, 0x0000, 0x0000, 0x0000, // w
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x3300, 0x3300, 0x1E00,
+0x0C00, 0x0C00, 0x1E00, 0x3300, 0x3300, 0x6180, 0x0000, 0x0000, 0x0000, // x
+0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x3180, 0x3300, 0x3300,
+0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x1C00, 0x7C00, 0x7000, // y
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FC0, 0x0180, 0x0300,
+0x0600, 0x0C00, 0x1800, 0x3000, 0x7FC0, 0x7FC0, 0x0000, 0x0000, 0x0000, // z
+0x0380, 0x0780, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0E00, 0x1C00,
+0x1C00, 0x0E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0780, 0x0380, // {
+0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600,
+0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, // |
+0x3800, 0x3C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0E00, 0x0700,
+0x0700, 0x0E00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3C00, 0x3800, // }
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3880, 0x7F80,
+0x4700, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~
+};
+static const unsigned short Font16x26 [] = {
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [ ]
+0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03C0,
+0x03C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x0000, 0x0000, 0x0000,
+0x03E0, 0x03E0, 0x03E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [!]
+0x1E3C, 0x1E3C, 0x1E3C, 0x1E3C, 0x1E3C, 0x1E3C, 0x1E3C, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = ["]
+0x01CE, 0x03CE, 0x03DE, 0x039E, 0x039C, 0x079C, 0x3FFF, 0x7FFF, 0x0738,
+0x0F38, 0x0F78, 0x0F78, 0x0E78, 0xFFFF, 0xFFFF, 0x1EF0, 0x1CF0, 0x1CE0,
+0x3CE0, 0x3DE0, 0x39E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [#]
+0x03FC, 0x0FFE, 0x1FEE, 0x1EE0, 0x1EE0, 0x1EE0, 0x1EE0, 0x1FE0, 0x0FE0,
+0x07E0, 0x03F0, 0x01FC, 0x01FE, 0x01FE, 0x01FE, 0x01FE, 0x01FE, 0x01FE,
+0x3DFE, 0x3FFC, 0x0FF0, 0x01E0, 0x01E0, 0x0000, 0x0000, 0x0000, // Ascii = [$]
+0x3E03, 0xF707, 0xE78F, 0xE78E, 0xE39E, 0xE3BC, 0xE7B8, 0xE7F8, 0xF7F0,
+0x3FE0, 0x01C0, 0x03FF, 0x07FF, 0x07F3, 0x0FF3, 0x1EF3, 0x3CF3, 0x38F3,
+0x78F3, 0xF07F, 0xE03F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [%]
+0x07E0, 0x0FF8, 0x0F78, 0x1F78, 0x1F78, 0x1F78, 0x0F78, 0x0FF0, 0x0FE0,
+0x1F80, 0x7FC3, 0xFBC3, 0xF3E7, 0xF1F7, 0xF0F7, 0xF0FF, 0xF07F, 0xF83E,
+0x7C7F, 0x3FFF, 0x1FEF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [&]
+0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03C0, 0x01C0, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [']
+0x003F, 0x007C, 0x01F0, 0x01E0, 0x03C0, 0x07C0, 0x0780, 0x0780, 0x0F80,
+0x0F00, 0x0F00, 0x0F00, 0x0F00, 0x0F00, 0x0F00, 0x0F80, 0x0780, 0x0780,
+0x07C0, 0x03C0, 0x01E0, 0x01F0, 0x007C, 0x003F, 0x000F, 0x0000, // Ascii = [(]
+0x7E00, 0x1F00, 0x07C0, 0x03C0, 0x01E0, 0x01F0, 0x00F0, 0x00F0, 0x00F8,
+0x0078, 0x0078, 0x0078, 0x0078, 0x0078, 0x0078, 0x00F8, 0x00F0, 0x00F0,
+0x01F0, 0x01E0, 0x03C0, 0x07C0, 0x1F00, 0x7E00, 0x7800, 0x0000, // Ascii = [)]
+0x03E0, 0x03C0, 0x01C0, 0x39CE, 0x3FFF, 0x3F7F, 0x0320, 0x0370, 0x07F8,
+0x0F78, 0x1F3C, 0x0638, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [*]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x01C0, 0x01C0, 0x01C0,
+0x01C0, 0x01C0, 0x01C0, 0x01C0, 0xFFFF, 0xFFFF, 0x01C0, 0x01C0, 0x01C0,
+0x01C0, 0x01C0, 0x01C0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [+]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03E0,
+0x03E0, 0x03E0, 0x03E0, 0x01E0, 0x01E0, 0x01E0, 0x01C0, 0x0380, // Ascii = [,]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x3FFE, 0x3FFE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [-]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03E0,
+0x03E0, 0x03E0, 0x03E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [.]
+0x000F, 0x000F, 0x001E, 0x001E, 0x003C, 0x003C, 0x0078, 0x0078, 0x00F0,
+0x00F0, 0x01E0, 0x01E0, 0x03C0, 0x03C0, 0x0780, 0x0780, 0x0F00, 0x0F00,
+0x1E00, 0x1E00, 0x3C00, 0x3C00, 0x7800, 0x7800, 0xF000, 0x0000, // Ascii = [/]
+0x07F0, 0x0FF8, 0x1F7C, 0x3E3E, 0x3C1E, 0x7C1F, 0x7C1F, 0x780F, 0x780F,
+0x780F, 0x780F, 0x780F, 0x780F, 0x780F, 0x7C1F, 0x7C1F, 0x3C1E, 0x3E3E,
+0x1F7C, 0x0FF8, 0x07F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [0]
+0x00F0, 0x07F0, 0x3FF0, 0x3FF0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0,
+0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0,
+0x01F0, 0x3FFF, 0x3FFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [1]
+0x0FE0, 0x3FF8, 0x3C7C, 0x003C, 0x003E, 0x003E, 0x003E, 0x003C, 0x003C,
+0x007C, 0x00F8, 0x01F0, 0x03E0, 0x07C0, 0x0780, 0x0F00, 0x1E00, 0x3E00,
+0x3C00, 0x3FFE, 0x3FFE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [2]
+0x0FF0, 0x1FF8, 0x1C7C, 0x003E, 0x003E, 0x003E, 0x003C, 0x003C, 0x00F8,
+0x0FF0, 0x0FF8, 0x007C, 0x003E, 0x001E, 0x001E, 0x001E, 0x001E, 0x003E,
+0x1C7C, 0x1FF8, 0x1FE0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [3]
+0x0078, 0x00F8, 0x00F8, 0x01F8, 0x03F8, 0x07F8, 0x07F8, 0x0F78, 0x1E78,
+0x1E78, 0x3C78, 0x7878, 0x7878, 0xFFFF, 0xFFFF, 0x0078, 0x0078, 0x0078,
+0x0078, 0x0078, 0x0078, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [4]
+0x1FFC, 0x1FFC, 0x1FFC, 0x1E00, 0x1E00, 0x1E00, 0x1E00, 0x1E00, 0x1FE0,
+0x1FF8, 0x00FC, 0x007C, 0x003E, 0x003E, 0x001E, 0x003E, 0x003E, 0x003C,
+0x1C7C, 0x1FF8, 0x1FE0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [5]
+0x01FC, 0x07FE, 0x0F8E, 0x1F00, 0x1E00, 0x3E00, 0x3C00, 0x3C00, 0x3DF8,
+0x3FFC, 0x7F3E, 0x7E1F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3E0F, 0x1E1F,
+0x1F3E, 0x0FFC, 0x03F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [6]
+0x3FFF, 0x3FFF, 0x3FFF, 0x000F, 0x001E, 0x001E, 0x003C, 0x0038, 0x0078,
+0x00F0, 0x00F0, 0x01E0, 0x01E0, 0x03C0, 0x03C0, 0x0780, 0x0F80, 0x0F80,
+0x0F00, 0x1F00, 0x1F00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [7]
+0x07F8, 0x0FFC, 0x1F3E, 0x1E1E, 0x3E1E, 0x3E1E, 0x1E1E, 0x1F3C, 0x0FF8,
+0x07F0, 0x0FF8, 0x1EFC, 0x3E3E, 0x3C1F, 0x7C1F, 0x7C0F, 0x7C0F, 0x3C1F,
+0x3F3E, 0x1FFC, 0x07F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [8]
+0x07F0, 0x0FF8, 0x1E7C, 0x3C3E, 0x3C1E, 0x7C1F, 0x7C1F, 0x7C1F, 0x7C1F,
+0x3C1F, 0x3E3F, 0x1FFF, 0x07EF, 0x001F, 0x001E, 0x001E, 0x003E, 0x003C,
+0x38F8, 0x3FF0, 0x1FE0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [9]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03E0, 0x03E0, 0x03E0,
+0x03E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03E0,
+0x03E0, 0x03E0, 0x03E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [:]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03E0, 0x03E0, 0x03E0,
+0x03E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03E0,
+0x03E0, 0x03E0, 0x03E0, 0x01E0, 0x01E0, 0x01E0, 0x03C0, 0x0380, // Ascii = [;]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003, 0x000F, 0x003F,
+0x00FC, 0x03F0, 0x0FC0, 0x3F00, 0xFE00, 0x3F00, 0x0FC0, 0x03F0, 0x00FC,
+0x003F, 0x000F, 0x0003, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [<]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [=]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xE000, 0xF800, 0x7E00,
+0x1F80, 0x07E0, 0x01F8, 0x007E, 0x001F, 0x007E, 0x01F8, 0x07E0, 0x1F80,
+0x7E00, 0xF800, 0xE000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [>]
+0x1FF0, 0x3FFC, 0x383E, 0x381F, 0x381F, 0x001E, 0x001E, 0x003C, 0x0078,
+0x00F0, 0x01E0, 0x03C0, 0x03C0, 0x07C0, 0x07C0, 0x0000, 0x0000, 0x0000,
+0x07C0, 0x07C0, 0x07C0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [?]
+0x03F8, 0x0FFE, 0x1F1E, 0x3E0F, 0x3C7F, 0x78FF, 0x79EF, 0x73C7, 0xF3C7,
+0xF38F, 0xF38F, 0xF38F, 0xF39F, 0xF39F, 0x73FF, 0x7BFF, 0x79F7, 0x3C00,
+0x1F1C, 0x0FFC, 0x03F8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [@]
+0x0000, 0x0000, 0x0000, 0x03E0, 0x03E0, 0x07F0, 0x07F0, 0x07F0, 0x0F78,
+0x0F78, 0x0E7C, 0x1E3C, 0x1E3C, 0x3C3E, 0x3FFE, 0x3FFF, 0x781F, 0x780F,
+0xF00F, 0xF007, 0xF007, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [A]
+0x0000, 0x0000, 0x0000, 0x3FF8, 0x3FFC, 0x3C3E, 0x3C1E, 0x3C1E, 0x3C1E,
+0x3C3E, 0x3C7C, 0x3FF0, 0x3FF8, 0x3C7E, 0x3C1F, 0x3C1F, 0x3C0F, 0x3C0F,
+0x3C1F, 0x3FFE, 0x3FF8, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [B]
+0x0000, 0x0000, 0x0000, 0x01FF, 0x07FF, 0x1F87, 0x3E00, 0x3C00, 0x7C00,
+0x7800, 0x7800, 0x7800, 0x7800, 0x7800, 0x7C00, 0x7C00, 0x3E00, 0x3F00,
+0x1F83, 0x07FF, 0x01FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [C]
+0x0000, 0x0000, 0x0000, 0x7FF0, 0x7FFC, 0x787E, 0x781F, 0x781F, 0x780F,
+0x780F, 0x780F, 0x780F, 0x780F, 0x780F, 0x780F, 0x780F, 0x781F, 0x781E,
+0x787E, 0x7FF8, 0x7FE0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [D]
+0x0000, 0x0000, 0x0000, 0x3FFF, 0x3FFF, 0x3E00, 0x3E00, 0x3E00, 0x3E00,
+0x3E00, 0x3E00, 0x3FFE, 0x3FFE, 0x3E00, 0x3E00, 0x3E00, 0x3E00, 0x3E00,
+0x3E00, 0x3FFF, 0x3FFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [E]
+0x0000, 0x0000, 0x0000, 0x1FFF, 0x1FFF, 0x1E00, 0x1E00, 0x1E00, 0x1E00,
+0x1E00, 0x1E00, 0x1FFF, 0x1FFF, 0x1E00, 0x1E00, 0x1E00, 0x1E00, 0x1E00,
+0x1E00, 0x1E00, 0x1E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [F]
+0x0000, 0x0000, 0x0000, 0x03FE, 0x0FFF, 0x1F87, 0x3E00, 0x7C00, 0x7C00,
+0x7800, 0xF800, 0xF800, 0xF87F, 0xF87F, 0x780F, 0x7C0F, 0x7C0F, 0x3E0F,
+0x1F8F, 0x0FFF, 0x03FE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [G]
+0x0000, 0x0000, 0x0000, 0x7C1F, 0x7C1F, 0x7C1F, 0x7C1F, 0x7C1F, 0x7C1F,
+0x7C1F, 0x7C1F, 0x7FFF, 0x7FFF, 0x7C1F, 0x7C1F, 0x7C1F, 0x7C1F, 0x7C1F,
+0x7C1F, 0x7C1F, 0x7C1F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [H]
+0x0000, 0x0000, 0x0000, 0x3FFF, 0x3FFF, 0x03E0, 0x03E0, 0x03E0, 0x03E0,
+0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0,
+0x03E0, 0x3FFF, 0x3FFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [I]
+0x0000, 0x0000, 0x0000, 0x1FFC, 0x1FFC, 0x007C, 0x007C, 0x007C, 0x007C,
+0x007C, 0x007C, 0x007C, 0x007C, 0x007C, 0x007C, 0x007C, 0x0078, 0x0078,
+0x38F8, 0x3FF0, 0x3FC0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [J]
+0x0000, 0x0000, 0x0000, 0x3C1F, 0x3C1E, 0x3C3C, 0x3C78, 0x3CF0, 0x3DE0,
+0x3FE0, 0x3FC0, 0x3F80, 0x3FC0, 0x3FE0, 0x3DF0, 0x3CF0, 0x3C78, 0x3C7C,
+0x3C3E, 0x3C1F, 0x3C0F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [K]
+0x0000, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x3E00, 0x3E00, 0x3E00, 0x3E00,
+0x3E00, 0x3E00, 0x3E00, 0x3E00, 0x3E00, 0x3E00, 0x3E00, 0x3E00, 0x3E00,
+0x3E00, 0x3FFF, 0x3FFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [L]
+0x0000, 0x0000, 0x0000, 0xF81F, 0xFC1F, 0xFC1F, 0xFE3F, 0xFE3F, 0xFE3F,
+0xFF7F, 0xFF77, 0xFF77, 0xF7F7, 0xF7E7, 0xF3E7, 0xF3E7, 0xF3C7, 0xF007,
+0xF007, 0xF007, 0xF007, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [M]
+0x0000, 0x0000, 0x0000, 0x7C0F, 0x7C0F, 0x7E0F, 0x7F0F, 0x7F0F, 0x7F8F,
+0x7F8F, 0x7FCF, 0x7BEF, 0x79EF, 0x79FF, 0x78FF, 0x78FF, 0x787F, 0x783F,
+0x783F, 0x781F, 0x781F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [N]
+0x0000, 0x0000, 0x0000, 0x07F0, 0x1FFC, 0x3E3E, 0x7C1F, 0x780F, 0x780F,
+0xF80F, 0xF80F, 0xF80F, 0xF80F, 0xF80F, 0xF80F, 0x780F, 0x780F, 0x7C1F,
+0x3E3E, 0x1FFC, 0x07F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [O]
+0x0000, 0x0000, 0x0000, 0x3FFC, 0x3FFF, 0x3E1F, 0x3E0F, 0x3E0F, 0x3E0F,
+0x3E0F, 0x3E1F, 0x3E3F, 0x3FFC, 0x3FF0, 0x3E00, 0x3E00, 0x3E00, 0x3E00,
+0x3E00, 0x3E00, 0x3E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [P]
+0x0000, 0x0000, 0x0000, 0x07F0, 0x1FFC, 0x3E3E, 0x7C1F, 0x780F, 0x780F,
+0xF80F, 0xF80F, 0xF80F, 0xF80F, 0xF80F, 0xF80F, 0x780F, 0x780F, 0x7C1F,
+0x3E3E, 0x1FFC, 0x07F8, 0x007C, 0x003F, 0x000F, 0x0003, 0x0000, // Ascii = [Q]
+0x0000, 0x0000, 0x0000, 0x3FF0, 0x3FFC, 0x3C7E, 0x3C3E, 0x3C1E, 0x3C1E,
+0x3C3E, 0x3C3C, 0x3CFC, 0x3FF0, 0x3FE0, 0x3DF0, 0x3CF8, 0x3C7C, 0x3C3E,
+0x3C1E, 0x3C1F, 0x3C0F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [R]
+0x0000, 0x0000, 0x0000, 0x07FC, 0x1FFE, 0x3E0E, 0x3C00, 0x3C00, 0x3C00,
+0x3E00, 0x1FC0, 0x0FF8, 0x03FE, 0x007F, 0x001F, 0x000F, 0x000F, 0x201F,
+0x3C3E, 0x3FFC, 0x1FF0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [S]
+0x0000, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0x03E0, 0x03E0, 0x03E0, 0x03E0,
+0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0,
+0x03E0, 0x03E0, 0x03E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [T]
+0x0000, 0x0000, 0x0000, 0x7C0F, 0x7C0F, 0x7C0F, 0x7C0F, 0x7C0F, 0x7C0F,
+0x7C0F, 0x7C0F, 0x7C0F, 0x7C0F, 0x7C0F, 0x7C0F, 0x7C0F, 0x3C1E, 0x3C1E,
+0x3E3E, 0x1FFC, 0x07F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [U]
+0x0000, 0x0000, 0x0000, 0xF007, 0xF007, 0xF807, 0x780F, 0x7C0F, 0x3C1E,
+0x3C1E, 0x3E1E, 0x1E3C, 0x1F3C, 0x1F78, 0x0F78, 0x0FF8, 0x07F0, 0x07F0,
+0x07F0, 0x03E0, 0x03E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [V]
+0x0000, 0x0000, 0x0000, 0xE003, 0xF003, 0xF003, 0xF007, 0xF3E7, 0xF3E7,
+0xF3E7, 0x73E7, 0x7BF7, 0x7FF7, 0x7FFF, 0x7F7F, 0x7F7F, 0x7F7E, 0x3F7E,
+0x3E3E, 0x3E3E, 0x3E3E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [W]
+0x0000, 0x0000, 0x0000, 0xF807, 0x7C0F, 0x3E1E, 0x3E3E, 0x1F3C, 0x0FF8,
+0x07F0, 0x07E0, 0x03E0, 0x03E0, 0x07F0, 0x0FF8, 0x0F7C, 0x1E7C, 0x3C3E,
+0x781F, 0x780F, 0xF00F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [X]
+0x0000, 0x0000, 0x0000, 0xF807, 0x7807, 0x7C0F, 0x3C1E, 0x3E1E, 0x1F3C,
+0x0F78, 0x0FF8, 0x07F0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0, 0x03E0,
+0x03E0, 0x03E0, 0x03E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [Y]
+0x0000, 0x0000, 0x0000, 0x7FFF, 0x7FFF, 0x000F, 0x001F, 0x003E, 0x007C,
+0x00F8, 0x00F0, 0x01E0, 0x03E0, 0x07C0, 0x0F80, 0x0F00, 0x1E00, 0x3E00,
+0x7C00, 0x7FFF, 0x7FFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [Z]
+0x07FF, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780,
+0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780,
+0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x07FF, 0x07FF, 0x0000, // Ascii = [[]
+0x7800, 0x7800, 0x3C00, 0x3C00, 0x1E00, 0x1E00, 0x0F00, 0x0F00, 0x0780,
+0x0780, 0x03C0, 0x03C0, 0x01E0, 0x01E0, 0x00F0, 0x00F0, 0x0078, 0x0078,
+0x003C, 0x003C, 0x001E, 0x001E, 0x000F, 0x000F, 0x0007, 0x0000, // Ascii = [\]
+0x7FF0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0,
+0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0,
+0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x00F0, 0x7FF0, 0x7FF0, 0x0000, // Ascii = []]
+0x00C0, 0x01C0, 0x01C0, 0x03E0, 0x03E0, 0x07F0, 0x07F0, 0x0778, 0x0F78,
+0x0F38, 0x1E3C, 0x1E3C, 0x3C1E, 0x3C1E, 0x380F, 0x780F, 0x7807, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [^]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, // Ascii = [_]
+0x00F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [`]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0FF8, 0x3FFC, 0x3C7C,
+0x003E, 0x003E, 0x003E, 0x07FE, 0x1FFE, 0x3E3E, 0x7C3E, 0x783E, 0x7C3E,
+0x7C7E, 0x3FFF, 0x1FCF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [a]
+0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3DF8, 0x3FFE, 0x3F3E,
+0x3E1F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C1F, 0x3C1E,
+0x3F3E, 0x3FFC, 0x3BF0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [b]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03FE, 0x0FFF, 0x1F87,
+0x3E00, 0x3E00, 0x3C00, 0x7C00, 0x7C00, 0x7C00, 0x3C00, 0x3E00, 0x3E00,
+0x1F87, 0x0FFF, 0x03FE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [c]
+0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x001F, 0x07FF, 0x1FFF, 0x3E3F,
+0x3C1F, 0x7C1F, 0x7C1F, 0x7C1F, 0x781F, 0x781F, 0x7C1F, 0x7C1F, 0x3C3F,
+0x3E7F, 0x1FFF, 0x0FDF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [d]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x03F8, 0x0FFC, 0x1F3E,
+0x3E1E, 0x3C1F, 0x7C1F, 0x7FFF, 0x7FFF, 0x7C00, 0x7C00, 0x3C00, 0x3E00,
+0x1F07, 0x0FFF, 0x03FE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [e]
+0x01FF, 0x03E1, 0x03C0, 0x07C0, 0x07C0, 0x07C0, 0x7FFF, 0x7FFF, 0x07C0,
+0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0, 0x07C0,
+0x07C0, 0x07C0, 0x07C0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [f]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07EF, 0x1FFF, 0x3E7F,
+0x3C1F, 0x7C1F, 0x7C1F, 0x781F, 0x781F, 0x781F, 0x7C1F, 0x7C1F, 0x3C3F,
+0x3E7F, 0x1FFF, 0x0FDF, 0x001E, 0x001E, 0x001E, 0x387C, 0x3FF8, // Ascii = [g]
+0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3DFC, 0x3FFE, 0x3F9E,
+0x3F1F, 0x3E1F, 0x3C1F, 0x3C1F, 0x3C1F, 0x3C1F, 0x3C1F, 0x3C1F, 0x3C1F,
+0x3C1F, 0x3C1F, 0x3C1F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [h]
+0x01F0, 0x01F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FE0, 0x7FE0, 0x01E0,
+0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0,
+0x01E0, 0x01E0, 0x01E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [i]
+0x00F8, 0x00F8, 0x0000, 0x0000, 0x0000, 0x0000, 0x3FF8, 0x3FF8, 0x00F8,
+0x00F8, 0x00F8, 0x00F8, 0x00F8, 0x00F8, 0x00F8, 0x00F8, 0x00F8, 0x00F8,
+0x00F8, 0x00F8, 0x00F8, 0x00F8, 0x00F8, 0x00F0, 0x71F0, 0x7FE0, // Ascii = [j]
+0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C1F, 0x3C3E, 0x3C7C,
+0x3CF8, 0x3DF0, 0x3DE0, 0x3FC0, 0x3FC0, 0x3FE0, 0x3DF0, 0x3CF8, 0x3C7C,
+0x3C3E, 0x3C1F, 0x3C1F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [k]
+0x7FF0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0,
+0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0, 0x01F0,
+0x01F0, 0x01F0, 0x01F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [l]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF79E, 0xFFFF, 0xFFFF,
+0xFFFF, 0xFBE7, 0xF9E7, 0xF1C7, 0xF1C7, 0xF1C7, 0xF1C7, 0xF1C7, 0xF1C7,
+0xF1C7, 0xF1C7, 0xF1C7, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [m]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3DFC, 0x3FFE, 0x3F9E,
+0x3F1F, 0x3E1F, 0x3C1F, 0x3C1F, 0x3C1F, 0x3C1F, 0x3C1F, 0x3C1F, 0x3C1F,
+0x3C1F, 0x3C1F, 0x3C1F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [n]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07F0, 0x1FFC, 0x3E3E,
+0x3C1F, 0x7C1F, 0x780F, 0x780F, 0x780F, 0x780F, 0x780F, 0x7C1F, 0x3C1F,
+0x3E3E, 0x1FFC, 0x07F0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [o]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3DF8, 0x3FFE, 0x3F3E,
+0x3E1F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C0F, 0x3C1F, 0x3E1E,
+0x3F3E, 0x3FFC, 0x3FF8, 0x3C00, 0x3C00, 0x3C00, 0x3C00, 0x3C00, // Ascii = [p]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07EE, 0x1FFE, 0x3E7E,
+0x3C1E, 0x7C1E, 0x781E, 0x781E, 0x781E, 0x781E, 0x781E, 0x7C1E, 0x7C3E,
+0x3E7E, 0x1FFE, 0x0FDE, 0x001E, 0x001E, 0x001E, 0x001E, 0x001E, // Ascii = [q]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F7F, 0x1FFF, 0x1FE7,
+0x1FC7, 0x1F87, 0x1F00, 0x1F00, 0x1F00, 0x1F00, 0x1F00, 0x1F00, 0x1F00,
+0x1F00, 0x1F00, 0x1F00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [r]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x07FC, 0x1FFE, 0x1E0E,
+0x3E00, 0x3E00, 0x3F00, 0x1FE0, 0x07FC, 0x00FE, 0x003E, 0x001E, 0x001E,
+0x3C3E, 0x3FFC, 0x1FF0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [s]
+0x0000, 0x0000, 0x0000, 0x0780, 0x0780, 0x0780, 0x7FFF, 0x7FFF, 0x0780,
+0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780, 0x0780,
+0x07C0, 0x03FF, 0x01FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [t]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3C1E, 0x3C1E, 0x3C1E,
+0x3C1E, 0x3C1E, 0x3C1E, 0x3C1E, 0x3C1E, 0x3C1E, 0x3C1E, 0x3C3E, 0x3C7E,
+0x3EFE, 0x1FFE, 0x0FDE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [u]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF007, 0x780F, 0x780F,
+0x3C1E, 0x3C1E, 0x3E1E, 0x1E3C, 0x1E3C, 0x0F78, 0x0F78, 0x0FF0, 0x07F0,
+0x07F0, 0x03E0, 0x03E0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [v]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF003, 0xF1E3, 0xF3E3,
+0xF3E7, 0xF3F7, 0xF3F7, 0x7FF7, 0x7F77, 0x7F7F, 0x7F7F, 0x7F7F, 0x3E3E,
+0x3E3E, 0x3E3E, 0x3E3E, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [w]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7C0F, 0x3E1E, 0x3E3C,
+0x1F3C, 0x0FF8, 0x07F0, 0x07F0, 0x03E0, 0x07F0, 0x07F8, 0x0FF8, 0x1E7C,
+0x3E3E, 0x3C1F, 0x781F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [x]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xF807, 0x780F, 0x7C0F,
+0x3C1E, 0x3C1E, 0x1E3C, 0x1E3C, 0x1F3C, 0x0F78, 0x0FF8, 0x07F0, 0x07F0,
+0x03E0, 0x03E0, 0x03C0, 0x03C0, 0x03C0, 0x0780, 0x0F80, 0x7F00, // Ascii = [y]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3FFF, 0x3FFF, 0x001F,
+0x003E, 0x007C, 0x00F8, 0x01F0, 0x03E0, 0x07C0, 0x0F80, 0x1F00, 0x1E00,
+0x3C00, 0x7FFF, 0x7FFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [z]
+0x01FE, 0x03E0, 0x03C0, 0x03C0, 0x03C0, 0x03C0, 0x01E0, 0x01E0, 0x01E0,
+0x01C0, 0x03C0, 0x3F80, 0x3F80, 0x03C0, 0x01C0, 0x01E0, 0x01E0, 0x01E0,
+0x03C0, 0x03C0, 0x03C0, 0x03C0, 0x03E0, 0x01FE, 0x007E, 0x0000, // Ascii = [{]
+0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0,
+0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0,
+0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x01C0, 0x0000, // Ascii = [|]
+0x3FC0, 0x03E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01C0, 0x03C0, 0x03C0,
+0x01C0, 0x01E0, 0x00FE, 0x00FE, 0x01E0, 0x01C0, 0x03C0, 0x03C0, 0x01C0,
+0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x03E0, 0x3FC0, 0x3F00, 0x0000, // Ascii = [}]
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+0x0000, 0x0000, 0x3F07, 0x7FC7, 0x73E7, 0xF1FF, 0xF07E, 0x0000, 0x0000,
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // Ascii = [~]
+};
+static const unsigned short Font6x8 [] = {
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp
+0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x2000, 0x0000, // !
+0x5000, 0x5000, 0x5000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // "
+0x5000, 0x5000, 0xf800, 0x5000, 0xf800, 0x5000, 0x5000, 0x0000, // #
+0x2000, 0x7800, 0xa000, 0x7000, 0x2800, 0xf000, 0x2000, 0x0000, // $
+0xc000, 0xc800, 0x1000, 0x2000, 0x4000, 0x9800, 0x1800, 0x0000, // %
+0x4000, 0xa000, 0xa000, 0x4000, 0xa800, 0x9000, 0x6800, 0x0000, // &
+0x3000, 0x3000, 0x2000, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, // '
+0x1000, 0x2000, 0x4000, 0x4000, 0x4000, 0x2000, 0x1000, 0x0000, // (
+0x4000, 0x2000, 0x1000, 0x1000, 0x1000, 0x2000, 0x4000, 0x0000, // )
+0x2000, 0xa800, 0x7000, 0xf800, 0x7000, 0xa800, 0x2000, 0x0000, // *
+0x0000, 0x2000, 0x2000, 0xf800, 0x2000, 0x2000, 0x0000, 0x0000, // +
+0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x2000, 0x0000, // ,
+0x0000, 0x0000, 0x0000, 0xf800, 0x0000, 0x0000, 0x0000, 0x0000, // -
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x0000, // .
+0x0000, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x0000, 0x0000, // /
+0x7000, 0x8800, 0x9800, 0xa800, 0xc800, 0x8800, 0x7000, 0x0000, // 0
+0x2000, 0x6000, 0x2000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // 1
+0x7000, 0x8800, 0x0800, 0x7000, 0x8000, 0x8000, 0xf800, 0x0000, // 2
+0xf800, 0x0800, 0x1000, 0x3000, 0x0800, 0x8800, 0x7000, 0x0000, // 3
+0x1000, 0x3000, 0x5000, 0x9000, 0xf800, 0x1000, 0x1000, 0x0000, // 4
+0xf800, 0x8000, 0xf000, 0x0800, 0x0800, 0x8800, 0x7000, 0x0000, // 5
+0x3800, 0x4000, 0x8000, 0xf000, 0x8800, 0x8800, 0x7000, 0x0000, // 6
+0xf800, 0x0800, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x0000, // 7
+0x7000, 0x8800, 0x8800, 0x7000, 0x8800, 0x8800, 0x7000, 0x0000, // 8
+0x7000, 0x8800, 0x8800, 0x7800, 0x0800, 0x1000, 0xe000, 0x0000, // 9
+0x0000, 0x0000, 0x2000, 0x0000, 0x2000, 0x0000, 0x0000, 0x0000, // :
+0x0000, 0x0000, 0x2000, 0x0000, 0x2000, 0x2000, 0x4000, 0x0000, // ;
+0x0800, 0x1000, 0x2000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0000, // <
+0x0000, 0x0000, 0xf800, 0x0000, 0xf800, 0x0000, 0x0000, 0x0000, // =
+0x4000, 0x2000, 0x1000, 0x0800, 0x1000, 0x2000, 0x4000, 0x0000, // >
+0x7000, 0x8800, 0x0800, 0x3000, 0x2000, 0x0000, 0x2000, 0x0000, // ?
+0x7000, 0x8800, 0xa800, 0xb800, 0xb000, 0x8000, 0x7800, 0x0000, // @
+0x2000, 0x5000, 0x8800, 0x8800, 0xf800, 0x8800, 0x8800, 0x0000, // A
+0xf000, 0x8800, 0x8800, 0xf000, 0x8800, 0x8800, 0xf000, 0x0000, // B
+0x7000, 0x8800, 0x8000, 0x8000, 0x8000, 0x8800, 0x7000, 0x0000, // C
+0xf000, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0xf000, 0x0000, // D
+0xf800, 0x8000, 0x8000, 0xf000, 0x8000, 0x8000, 0xf800, 0x0000, // E
+0xf800, 0x8000, 0x8000, 0xf000, 0x8000, 0x8000, 0x8000, 0x0000, // F
+0x7800, 0x8800, 0x8000, 0x8000, 0x9800, 0x8800, 0x7800, 0x0000, // G
+0x8800, 0x8800, 0x8800, 0xf800, 0x8800, 0x8800, 0x8800, 0x0000, // H
+0x7000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // I
+0x3800, 0x1000, 0x1000, 0x1000, 0x1000, 0x9000, 0x6000, 0x0000, // J
+0x8800, 0x9000, 0xa000, 0xc000, 0xa000, 0x9000, 0x8800, 0x0000, // K
+0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0xf800, 0x0000, // L
+0x8800, 0xd800, 0xa800, 0xa800, 0xa800, 0x8800, 0x8800, 0x0000, // M
+0x8800, 0x8800, 0xc800, 0xa800, 0x9800, 0x8800, 0x8800, 0x0000, // N
+0x7000, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x7000, 0x0000, // O
+0xf000, 0x8800, 0x8800, 0xf000, 0x8000, 0x8000, 0x8000, 0x0000, // P
+0x7000, 0x8800, 0x8800, 0x8800, 0xa800, 0x9000, 0x6800, 0x0000, // Q
+0xf000, 0x8800, 0x8800, 0xf000, 0xa000, 0x9000, 0x8800, 0x0000, // R
+0x7000, 0x8800, 0x8000, 0x7000, 0x0800, 0x8800, 0x7000, 0x0000, // S
+0xf800, 0xa800, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, // T
+0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x7000, 0x0000, // U
+0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x5000, 0x2000, 0x0000, // V
+0x8800, 0x8800, 0x8800, 0xa800, 0xa800, 0xa800, 0x5000, 0x0000, // W
+0x8800, 0x8800, 0x5000, 0x2000, 0x5000, 0x8800, 0x8800, 0x0000, // X
+0x8800, 0x8800, 0x5000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, // Y
+0xf800, 0x0800, 0x1000, 0x7000, 0x4000, 0x8000, 0xf800, 0x0000, // Z
+0x7800, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x7800, 0x0000, // [
+0x0000, 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0000, 0x0000, /* \ */
+0x7800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x7800, 0x0000, // ]
+0x2000, 0x5000, 0x8800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^
+0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf800, 0x0000, // _
+0x6000, 0x6000, 0x2000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, // `
+0x0000, 0x0000, 0x6000, 0x1000, 0x7000, 0x9000, 0x7800, 0x0000, // a
+0x8000, 0x8000, 0xb000, 0xc800, 0x8800, 0xc800, 0xb000, 0x0000, // b
+0x0000, 0x0000, 0x7000, 0x8800, 0x8000, 0x8800, 0x7000, 0x0000, // c
+0x0800, 0x0800, 0x6800, 0x9800, 0x8800, 0x9800, 0x6800, 0x0000, // d
+0x0000, 0x0000, 0x7000, 0x8800, 0xf800, 0x8000, 0x7000, 0x0000, // e
+0x1000, 0x2800, 0x2000, 0x7000, 0x2000, 0x2000, 0x2000, 0x0000, // f
+0x0000, 0x0000, 0x7000, 0x9800, 0x9800, 0x6800, 0x0800, 0x0000, // g
+0x8000, 0x8000, 0xb000, 0xc800, 0x8800, 0x8800, 0x8800, 0x0000, // h
+0x2000, 0x0000, 0x6000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // i
+0x1000, 0x0000, 0x1000, 0x1000, 0x1000, 0x9000, 0x6000, 0x0000, // j
+0x8000, 0x8000, 0x9000, 0xa000, 0xc000, 0xa000, 0x9000, 0x0000, // k
+0x6000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // l
+0x0000, 0x0000, 0xd000, 0xa800, 0xa800, 0xa800, 0xa800, 0x0000, // m
+0x0000, 0x0000, 0xb000, 0xc800, 0x8800, 0x8800, 0x8800, 0x0000, // n
+0x0000, 0x0000, 0x7000, 0x8800, 0x8800, 0x8800, 0x7000, 0x0000, // o
+0x0000, 0x0000, 0xb000, 0xc800, 0xc800, 0xb000, 0x8000, 0x0000, // p
+0x0000, 0x0000, 0x6800, 0x9800, 0x9800, 0x6800, 0x0800, 0x0000, // q
+0x0000, 0x0000, 0xb000, 0xc800, 0x8000, 0x8000, 0x8000, 0x0000, // r
+0x0000, 0x0000, 0x7800, 0x8000, 0x7000, 0x0800, 0xf000, 0x0000, // s
+0x2000, 0x2000, 0xf800, 0x2000, 0x2000, 0x2800, 0x1000, 0x0000, // t
+0x0000, 0x0000, 0x8800, 0x8800, 0x8800, 0x9800, 0x6800, 0x0000, // u
+0x0000, 0x0000, 0x8800, 0x8800, 0x8800, 0x5000, 0x2000, 0x0000, // v
+0x0000, 0x0000, 0x8800, 0x8800, 0xa800, 0xa800, 0x5000, 0x0000, // w
+0x0000, 0x0000, 0x8800, 0x5000, 0x2000, 0x5000, 0x8800, 0x0000, // x
+0x0000, 0x0000, 0x8800, 0x8800, 0x7800, 0x0800, 0x8800, 0x0000, // y
+0x0000, 0x0000, 0xf800, 0x1000, 0x2000, 0x4000, 0xf800, 0x0000, // z
+0x1000, 0x2000, 0x2000, 0x4000, 0x2000, 0x2000, 0x1000, 0x0000, // {
+0x2000, 0x2000, 0x2000, 0x0000, 0x2000, 0x2000, 0x2000, 0x0000, // |
+0x4000, 0x2000, 0x2000, 0x1000, 0x2000, 0x2000, 0x4000, 0x0000, // }
+0x4000, 0xa800, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~
+};
+
+FontDef Font_7x10 = {7,10,Font7x10};
+FontDef Font_6x8 = {6, 8, Font6x8};
+FontDef Font_11x18 = {11, 18, Font11x18};
+FontDef Font_16x26 = {16, 26, Font16x26};
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306_fonts.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306_fonts.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d26f31adbfca2c5d03d7d041b07a3b465bfebc7
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/ssd1306_fonts.h
@@ -0,0 +1,58 @@
+/*
+ MIT License
+
+ Copyright (c) 2018, Alexey Dynda
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+/**
+ * @file ssd1306_fonts.h Fonts for monochrome/rgb oled display
+ */
+
+#ifndef SSD1306_FONTS_H
+#define SSD1306_FONTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup LCD_FONTS FONTS: Supported LCD fonts
+ * @{
+ */
+
+extern const unsigned char g_f6X8[][6];
+extern const unsigned char g_f8X16[];
+
+typedef struct {
+ const unsigned char FontWidth; /*!< Font width in pixels */
+ unsigned char FontHeight; /*!< Font height in pixels */
+ const unsigned short *data; /*!< Pointer to data font data array */
+} FontDef;
+
+extern FontDef Font_7x10;
+extern FontDef Font_6x8;
+extern FontDef Font_11x18;
+extern FontDef Font_16x26;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SSD1306_FONTS_H
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/user_motor_control.c b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/user_motor_control.c
new file mode 100644
index 0000000000000000000000000000000000000000..0425d3c4716fb92a1749a6fec2d86e40db8d1151
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/user_motor_control.c
@@ -0,0 +1,170 @@
+#include "main.h"
+#include "debug.h"
+#include "user_motor_control.h"
+
+unsigned int g_aptDutyCur = 50;
+unsigned int g_aptDutySet = 50;
+unsigned int g_aptFreqCntCur =1500;
+unsigned int g_aptFreqCntSet =1500;
+unsigned int g_rotationDirectionStatus = 0;
+unsigned int g_rotationDirectionStatusSet = 0;
+
+unsigned int g_testCount = 0;
+unsigned int g_testNum = 0;
+
+void User_APTForcePWMAOutputLow(APT_RegStruct *aptx)
+{
+ /* Enable force output. */
+
+
+ aptx->PG_OUT_FRC.BIT.rg_pga_frc_act = APT_PWM_CONTINUOUS_ACTION_LOW; /* if not invert, set low */
+ aptx->PG_OUT_FRC.BIT.rg_pga_frc_en = BASE_CFG_ENABLE;
+ /* if PWMA invert */
+ return;
+}
+
+void User_APTForcePWMBOutputLow(APT_RegStruct *aptx)
+{
+ aptx->PG_OUT_FRC.BIT.rg_pgb_frc_act = APT_PWM_CONTINUOUS_ACTION_HIGH; /* if not invert, set low */
+ /* Enable force output. */
+ aptx->PG_OUT_FRC.BIT.rg_pgb_frc_en = BASE_CFG_ENABLE;
+ return;
+}
+
+
+void User_APTPwmARecovery(APT_RegStruct *aptx)
+{
+ /* Enable force output. */
+ aptx->PG_OUT_FRC.BIT.rg_pga_frc_en = BASE_CFG_DISABLE;
+ return;
+}
+
+void User_APTPwmBRecovery(APT_RegStruct *aptx)
+{
+ /* Enable force output. */
+ aptx->PG_OUT_FRC.BIT.rg_pgb_frc_en = BASE_CFG_DISABLE;
+ return;
+}
+
+/* 电机启动 */
+void startMotor(void)
+{
+ HAL_APT_StartModule(RUN_APT0|RUN_APT1);
+}
+
+/* 电机停止 */
+void stopMotor(void)
+{
+ HAL_APT_StopModule(RUN_APT0|RUN_APT1);
+}
+
+/* 电机正转 */
+void MotorForwardRotation(void)
+{
+ User_APTPwmARecovery(g_apt0.baseAddress); // 左转,右轮子前进
+ User_APTForcePWMBOutputLow(g_apt0.baseAddress);
+ User_APTForcePWMAOutputLow(g_apt1.baseAddress); // 右转,左轮子前进
+ User_APTPwmBRecovery(g_apt1.baseAddress);
+}
+
+/* 电机反转 */
+void MotorReverse(void)
+{
+ User_APTForcePWMAOutputLow(g_apt0.baseAddress);
+ User_APTPwmBRecovery(g_apt0.baseAddress);
+
+ User_APTPwmARecovery(g_apt1.baseAddress);
+ User_APTForcePWMBOutputLow(g_apt1.baseAddress);
+}
+
+/* 电机左转 */
+void MotorLeft(void)
+{
+ User_APTPwmARecovery(g_apt0.baseAddress); // 左转,右轮子前进
+ User_APTForcePWMBOutputLow(g_apt0.baseAddress);
+ HAL_APT_StopModule(RUN_APT1);
+}
+
+/* 电机右转 */
+void MotorRight(void)
+{
+ HAL_APT_StopModule(RUN_APT0);
+ User_APTForcePWMAOutputLow(g_apt1.baseAddress); // 右转,左轮子前进
+ User_APTPwmBRecovery(g_apt1.baseAddress);
+}
+
+/* 通过占空比调节电机速度 */
+void MotorSpeedAdjustmentByDuty(unsigned int duty, unsigned int directions)
+{
+ /* 正转 */
+ if (directions == 0) {
+ HAL_APT_SetPWMDutyByNumber(&g_apt0, duty);
+ HAL_APT_SetPWMDutyByNumber(&g_apt1, duty);
+ } else {
+ /* 反转 */
+ HAL_APT_SetPWMDutyByNumber(&g_apt0, (100 - duty));
+ HAL_APT_SetPWMDutyByNumber(&g_apt1, (100 - duty));
+ }
+}
+
+/* 通过修改频率调节电机速度 */
+void MotorSpeedAdjustmentByFreq(unsigned int freq)
+{
+ DCL_APT_SetTimeBasePeriod(g_apt0.baseAddress, freq);
+ DCL_APT_SetTimeBasePeriod(g_apt1.baseAddress, freq);
+}
+
+void initMotor()
+{
+ MotorSpeedAdjustmentByDuty(g_aptDutyCur, g_rotationDirectionStatus);
+}
+
+void MotorProcess()
+{
+
+ //MotorSpeedAdjustmentByFreq(g_aptFreqCntCur);
+ // HAL_APT_StartModule(RUN_APT0|RUN_APT1);
+
+ // while (1) {
+ /* 改变转动方向 */
+ g_testCount ++;
+
+ /*if (g_rotationDirectionStatus != g_rotationDirectionStatusSet) {
+ g_rotationDirectionStatus = g_rotationDirectionStatusSet;
+ if (g_rotationDirectionStatus == 0) {
+ MotorForwardRotation(); //电机正转
+ } else {
+ MotorReverse(); //电机反转
+ }
+ } */
+
+ if (g_testCount > 200) {
+ if (g_rotationDirectionStatus == 1)
+ {
+ MotorForwardRotation(); /* 电机正转 */
+ g_rotationDirectionStatus = 0;
+ }
+ else
+ {
+ MotorReverse(); /* 电机反转 */
+ g_rotationDirectionStatus = 1;
+ }
+
+ DBG_PRINTF("Test Num = %d\r\n",g_testNum++);
+ g_testCount =0;
+ }
+
+
+ /* 改变速度 */
+ if (g_aptDutyCur != g_aptDutySet) {
+ g_aptDutyCur = g_aptDutySet;
+ MotorSpeedAdjustmentByDuty(g_aptDutyCur, g_rotationDirectionStatus);
+ }
+
+ if (g_aptFreqCntCur != g_aptFreqCntSet) {
+ g_aptFreqCntCur = g_aptFreqCntSet;
+ MotorSpeedAdjustmentByFreq(g_aptFreqCntCur);
+ }
+ // }
+
+}
\ No newline at end of file
diff --git a/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/user_motor_control.h b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/user_motor_control.h
new file mode 100644
index 0000000000000000000000000000000000000000..df4fffd914a0806803315303815b5e284bed5ff1
--- /dev/null
+++ b/hi-sle/EulerCar_Slave_Computer_Hi3061_Source_Code/user/user_motor_control.h
@@ -0,0 +1,21 @@
+#ifndef USER_MOTOR_CONTROL_H
+#define USER_MOTOR_CONTROL_H
+
+#include
+
+void initMotor(void);
+void startMotor(void);
+void stopMotor(void);
+void MotorForwardRotation(void);
+void MotorReverse(void);
+void MotorSpeedAdjustmentByDuty(unsigned int duty, unsigned int directions);
+void MotorSpeedAdjustmentByFreq(unsigned int freq);
+void MotorProcess(void);
+void MotorRight(void);
+void MotorLeft(void);
+void User_APTForcePWMAOutputLow(APT_RegStruct *aptx);
+void User_APTForcePWMBOutputLow(APT_RegStruct *aptx);
+void User_APTPwmARecovery(APT_RegStruct *aptx);
+void User_APTPwmBRecovery(APT_RegStruct *aptx);
+
+#endif
\ No newline at end of file
diff --git a/hi-sle/JLCPCB_Files/BOM_Board1_EulerCar.xlsx b/hi-sle/JLCPCB_Files/BOM_Board1_EulerCar.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..8ba4be5de55f9b7557787edeaa7f0bf1b1b8b1da
Binary files /dev/null and b/hi-sle/JLCPCB_Files/BOM_Board1_EulerCar.xlsx differ
diff --git a/hi-sle/JLCPCB_Files/Gerber_eulercar_2024-09-15.zip b/hi-sle/JLCPCB_Files/Gerber_eulercar_2024-09-15.zip
new file mode 100644
index 0000000000000000000000000000000000000000..2b36ef2a6f88781d81b9604aed2f1bb1aeed1208
Binary files /dev/null and b/hi-sle/JLCPCB_Files/Gerber_eulercar_2024-09-15.zip differ
diff --git a/hi-sle/JLCPCB_Files/pin_func.md b/hi-sle/JLCPCB_Files/pin_func.md
new file mode 100644
index 0000000000000000000000000000000000000000..cf8def09afdddcffed2ed4e0f659ade32f37fb99
--- /dev/null
+++ b/hi-sle/JLCPCB_Files/pin_func.md
@@ -0,0 +1,21 @@
+- 左摇杆
+ - X IO9
+ - Y IO8
+ - Z IO14
+- 右摇杆
+ - X IO10
+ - Y IO7
+ - Z IO6
+
+- 左按键 u13
+ - IO2
+- 右按键 u14
+ - IO4
+
+- 左钮子 SW8
+ - IO5
+- 右钮子 SW9
+ - IO3
+
+- 震动马达
+ - IO11
diff --git a/hi-sle/README.md b/hi-sle/README.md
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..750993f39b1543cc0e325af04eecfcab40fecc4e 100644
--- a/hi-sle/README.md
+++ b/hi-sle/README.md
@@ -0,0 +1,484 @@
+# 基于openEuler Embedded的星闪开源应用案例开发
+
+本开源项目是一款「基于NearLink_DK_WS63星闪开发板制作的遥控手柄」,无缝互联并操作「集成星闪WS73的智能小车」(小车可兼容Open Euler与Ros2系统)
+
+> 星光熠熠,科技浪潮涌动!"Euler星闪耀·万物智联" —— 星闪+OpenEuler Embedded,一场关于智能交互的盛宴,让未来触手可及!
+
+
+
+
+
+
+
+
+
+
+
「星闪 · 遥控手柄」
+
+ 「星闪:短距新赛道」: 不止于控,更在于“速”
+
+
+ 查看Demo
+ ·
+ 报告Bug
+ ·
+ 提出新特性
+
+
+
+---
+
+- [基于openEuler Embedded的星闪开源应用案例开发](#基于openeuler-embedded的星闪开源应用案例开发)
+ - [项目介绍](#项目介绍)
+ - [目录结构](#目录结构)
+ - [软件指南](#软件指南)
+ - [1. 环境搭建](#1-环境搭建)
+ - [2. 编译烧录](#2-编译烧录)
+ - [2.1 Ws63主控](#21-ws63主控)
+ - [2.2 EulerPi](#22-eulerpi)
+ - [2.3 Hi3061M](#23-hi3061m)
+ - [ws63代码文件详解](#ws63代码文件详解)
+ - [EulerCar控制核心代码](#eulercar控制核心代码)
+ - [硬件指南](#硬件指南)
+ - [1. 电路设计](#1-电路设计)
+ - [2. PCBlayout](#2-pcblayout)
+ - [3. 主体建模](#3-主体建模)
+ - [4. 物料购买](#4-物料购买)
+ - [5. 焊接说明](#5-焊接说明)
+ - [6. 测试说明](#6-测试说明)
+ - [7. 硬件总装](#7-硬件总装)
+ - [8. 软硬件调试](#8-软硬件调试)
+ - [星闪手柄实操展示](#星闪手柄实操展示)
+ - [作者](#作者)
+ - [特别鸣谢 「梅科尔工作室」](#特别鸣谢-梅科尔工作室)
+
+
+## 项目介绍
+
+这是一个完整的星闪手柄开源项目,包含星闪手柄主控源码、星闪手柄结构设计、 星闪手柄电子硬件设计等多个部分,完成了以下内容:
+
+- 使用 Autodesk Fusion 360 完成的星闪手柄模型设计
+- 使用 嘉立创EDA完成的星闪手柄PCB设计
+- 基于 Hispark Studio完成润和ws63星闪开发板(主控)嵌入式软件设计
+- 基于 Ubuntu-vm22.04 完成ws73星闪模组代码编译
+
+整个星闪手柄从一个ieda到真正实现、从前期部分投入到最后全身心投入经历了约三个月的时间,这个经历也让我更明白技术无止境,只有不停地学习、分享、复盘才能进步更快。所以我更希望把对制作星闪手柄过程中的困难和思考分享给大家。
+
+
+所以呢,整个开源项目最重要的不是星闪手柄本身(当然落地是非常困难的),而是,这是一套非常详细的开发教程,甚至可以说是手把手产品开发教程。从一个需求开始,到提取重点、外设选型、原理图设计、PCBlayout、代码编写、调试、烧录、结构设计、安装。如果本项目能对正在观看的你引起对星闪的兴趣和帮助,将是对我极大的鼓励和慰藉。
+
+### 目录结构
+
+如果刚刚开始接触这个项目,那么您可以看看本项目的文件结构,这样您可以更好的理解这个项目。
+```
+hi-sle
+├── Autodesk_Fusion_360_Designs/ # Autodesk Fusion 360 模型设计文件夹
+├── Bill_of_Materials/ # 物料清单
+├── JLCPCB_Files/ # 立创PCB文件夹
+│── RemoteController_WS63E_Source_Code/ # NearLink_DK_WS63源代码
+│ ├── /SLE_OSPP_SERVER/
+│ │ ├── inc/ # 头文件
+│ │ └── src/ # 源文件
+├── EulerCar_Host_Computer_EulerPi_Source_Code # 上位机EulerPi源代码文件夹
+├── EulerCar_Slave_Computer_Hi3061_Source_Code # 下位机Hi3061源代码文件夹
+├── Images # 图片文件夹
+└── README.md # 项目说明文件
+
+```
+
+## 软件指南
+
+### 1. 环境搭建
+
+工欲善其事,必先利其器。在开始项目之前,我们需要搭建好开发环境。本项目的开发环境主要分为两个部分:**星闪遥控手柄** 开发环境 和 **EulerCar星闪遥控小车** 开发环境。由于官方基本上都有相对应的搭建教程,在本文档中就不再过多赘述。同时当然,如果您在真实开发过程中确实遇到了问题,无论问题简单与否,请大胆询问,摒弃掉学生思维。任何问题也欢迎在issue中提出,或者联系我,我会尽力解答。
+
+1. **星闪遥控手柄**
+
+ 星闪遥控手柄的主控是**NearLink_DK_WS63**,海思官方和小熊派团队都提供了开发环境搭建教程。
+ - [海思Hispark Gitee组织提供的基于Windows搭建的开发环境教程](https://gitee.com/HiSpark/fbb_ws63/tree/master/tools#windows-%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA)
+ - [小熊派团队提供的基于Window环境下开发环境搭建教程](https://www.bearpi.cn/core_board/bearpi/pico/h3863/software/%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BAwindows_IDE.html)
+
+2. **EulerCar星闪遥控小车**
+
+ EulerCar是基于 Eulerpi主控板 和 Hi3061M控制板构建,那么我们需要搭建的环境主要分为两个部分:**EulerPi主控板** 开发环境 和 **Hi3061M控制板** 开发环境。
+
+3. **EulerCar星闪遥控小车-EulerPi主控板**
+
+ 易百纳官方提供了[海欧派开发及使用一指禅](https://gitee.com/HiEuler/doc/blob/master/EulerPi%20Compile%20using%20One%20Finger%20Zen.md),同时也可观看官方文档提供的[海鸥派Euler Pi 快速体验手册.pdf](https://github.com/Abrillant-Lee/Abrillant-Lee.github.io/blob/main/Summer-OSPP2024/EulerPi_Quick%20_Experience.pdf) 进行快速体验。
+ >注意事项:
+ >1. 固件来源有很多种:官方网盘中给的固件、gitee中下载固件、自己构建的固件,我选择使用wsl构建固件,如果对Linux不熟悉的同学可以直接使用官方提供的VM虚拟机
+ >2. PD电源输入端供电不支持电脑USB接口或者5v供电,12v供电最佳。
+ 1. 电脑USB接口的标准电压为5V,标准电流为500mA。
+ 2. 否则网口无法正常工作💢😠
+ >3. 注意烧录固件大小,4G使用4G的固件,8G使用8G的固件
+
+4. **EulerCar星闪遥控小车-Hi3061M主控板**
+
+ 官方教程:[eulercar mcu底盘代码和MCU开发IDE、MCU开发板指导手册](https://gitee.com/HiEuler/eulercar_controller)
+
+### 2. 编译烧录
+
+1. 将本项目clone到本地
+
+ ```bash
+ git clone https://gitee.com/AbrillantLee/yocto-embedded-tools.git
+ ```
+
+2. 切换到hieuler分支
+
+ ```bash
+ git switch hieuler
+ ```
+
+#### 2.1 Ws63主控
+
+1. 进入到项目目录下,将`RemoteController_WS63E_Source_Code`目录下`SLE_OSPP_Server`的拷贝到您的hispark studio 开发环境`xxx\src\application\samples\peripheral\`目录下。
+
+ ```bash
+ cd hi-sle
+ cp -r RemoteController_WS63E_Source_Code xxx\src\application\samples\peripheral\
+ ```
+
+2. 在xxx\src\application\samples\peripheral\CMakeLists.txt文件中新增编译案例(如果不知道在哪个地方加的,可以在“set(SOURCES "${SOURCES}" PARENT_SCOPE)”上面一行添加)。
+
+ ```
+ if(DEFINED CONFIG_SAMPLE_SUPPORT_SLE_OSPP)
+ add_subdirectory_if_exist(sle_ospp)
+ endif()
+ ```
+
+3. 在xxx\src\application\samples\peripheral\Kconfig文件中新增编译案例,具体如下图所示(如果不知道在哪个地方加,可以在最后一行添加)。
+
+ ```
+ config SAMPLE_SUPPORT_SLE_OSPP
+ bool
+ prompt "使能星闪遥控器"
+ default n
+ depends on ENABLE_PERIPHERAL_SAMPLE
+ help
+ This option means support SLE_OSPP Sample.
+ ```
+
+4. 选择”**系统配置**“,具体选择路径“Application/Enable the Sample of peripheral”,在弹出框中选择“使能星闪遥控器”,点击Save,关闭弹窗。
+
+5. 点击“build”或者“rebuild”编译
+
+6. 编译完成之后,在HiSpark Studio工具中点击“工程配置”按钮,选择“程序加载”,传输方式选择“serial”,端口选择“comxxx”,com口在设备管理器中查看。
+
+7. 配置完成后,点击工具“程序加载”按钮烧录。
+
+8. 出现“Connecting, please reset device...”字样时,复位开发板,等待烧录结束。
+
+#### 2.2 EulerPi
+
+- EulerPi官方Gitee仓库提供教程,可以参考[EulerPi Gitee仓库 教程 ](https://gitee.com/HiEuler/doc/blob/master/Vm-Ubuntu22.04-ROSSDK.md)。
+
+- 注意在在`先从gitee网站上,将项目代码下载到到ubuntu环境,普通目录/home/robot下` 这一步时:
+
+- 将`xxx/eulercar/sle_control/src/bs21_ws73_ros2.c`文件替换为本目录下的`EulerCar_Host_Computer_EulerPi_Source_Code\ws63_ws73_ros2.c`文件
+
+#### 2.3 Hi3061M
+
+- 使用HisparkStudio打开Hi3061M的工程,将User目录下的文件替换为本目录下`EulerCar_Slave_Computer_Hi3061_Source_Code`文件编译烧录即可。
+
+- 还有一种最为简单的方式就是将`Hispark`配置中的`Bin`文案金更换为`EulerCar_Slave_Computer_Hi3061_Source_Code/out/target.bin`文件,然后直接烧录即可。
+
+
+
+
+
+### ws63代码文件详解
+
+```
+│ ├── /SLE_OSPP_SERVER/
+│ │ ├── inc/
+│ │ │ │ ├── button.h # 按钮模块的头文件
+│ │ │ │ ├── shake.h # 震动传感器模块的头文件
+│ │ │ │ ├── eulercar_control.h # EulerCar控制模块的头文件
+│ │ │ │ ├── sle_ospp_server.h
+│ │ └── src/
+│ │ │ │ ├── button.c # 按钮/扭子开关模块的实现文件
+│ │ │ │ ├── shake.c # 震动传感器模块的实现文件
+│ │ │ │ ├── eulercar_control.c # EulerCar控控制模块的实现文件,
+│ │ │ │ ├── sle_ospp_server_adv.c
+│ │ │ │ ├── sle_ospp_server.c # SLE OSPP服务器的主实现文件
+│ │ │ ├── CMakeLists.txt # CMake 构建系统的配置文件
+│ │ │ ├── Kconfig # Kconfig 配置文件
+
+```
+#### EulerCar控制核心代码
+
+```
+// 键盘报告结构体定义
+typedef struct
+{
+ uint8_t kind; // 键盘报告类型
+ uint8_t special_key; // 特殊按键
+ uint8_t reserve; // 保留字段
+ uint8_t key[6]; // 按键值数组
+} usb_hid_rcu_keyboard_report_t;
+
+// 向上键报告
+usb_hid_rcu_keyboard_report_t EulerCarUp = {
+ .kind = 1, // 键盘报告类型
+ .special_key = 0, // 特殊按键
+ .reserve = 0, // 保留字段
+ .key = {0x52, 0x00, 0x00, 0x00, 0x00, 0x00} // 按键值数组
+};
+
+// 释放键报告
+usb_hid_rcu_keyboard_report_t EulerCarRelease = {
+ .kind = 1, // 键盘报告类型
+ .special_key = 0, // 特殊按键
+ .reserve = 0, // 保留字段
+ .key = {0x0, 0x00, 0x00, 0x00, 0x00, 0x00} // 按键值数组
+};
+
+// 辅助函数:发送键盘报告通知
+void send_keyboard_report(usb_hid_rcu_keyboard_report_t *report)
+{
+ ssaps_ntf_ind_t param = {0}; // 初始化通知参数结构体
+ param.handle = g_property_handle; // 设置通知的句柄
+ param.type = 0; // 设置通知类型为0
+ param.value = (uint8_t *)report; // 将键盘报告数据转换为 uint8_t 指针
+ param.value_len = sizeof(*report); // 设置通知数据的长度
+ ssaps_notify_indicate(g_server_id, g_conn_id, ¶m); // 发送通知
+}
+
+/**
+ * @brief 控制小车前进
+ *
+ * 该函数通过发送键盘报告通知来控制小车前进。首先发送前进键报告,
+ * 然后延时一段时间,再发送释放键报告。最后打印一条日志信息并延时一段时间。
+ */
+void eulercar_control_forward(void)
+{
+ send_keyboard_report(&EulerCarUp); // 发送前进键报告
+ (void)osal_msleep(PRESS_RELEASE_INTERVAL); // 延时
+ send_keyboard_report(&EulerCarRelease); // 发送释放键报告
+ Vibration_CarControl();
+ PRINT("[SLE Server] 星闪小车前进! \r\n");
+ (void)osal_msleep(LONG_PRESS_INTERVAL); // 延时,等待响应
+}
+
+...... # 向左、右、后代码查看源代码即可,注释非常详细
+
+```
+
+
+## 硬件指南
+硬件主要由底板,PCB主板和亚克力板组成
+
+
+
+
+以下是PCB主板主要功能图示
+
+
+
+
+
+
+
+### 1. 电路设计
+
+> 本硬件电路主要分为电源管理电路,震动马达驱动电路和控制模块电路构成
+
+
+
+
+1. 电源管理电路以IP5306(产品资料🔗)为核心。IP5306是一款集成升压转换器、锂电池充电管理、电池电量指示的多功能电源管理 SOC,为移动电源提供完整的电源解决方案。
+ - 可同步开关充放电,支持4LED电量显示
+ - 自动检测充电器插拔,自适应充电电流调节
+ - 按键功能:
+ - 短按(持续时间长于 50ms,但小于 2s)会打开电量显示灯和升压输出。
+ - 连续两次短按键( 1s 内),会关闭电量显示和升压输出
+
+
+
+
+
+
+
+2. 震动马达驱动电路以微型震动马达为核心,在这个电路中,场效应管能够通过控制门极电压来开启或关闭电流,从而控制电机的工作状态。肖特基二极管防止电机在停止时产生的反向电流对电路造成损坏,起到保护作用。
+
+
+
+
+
+3. 控制模块电路以WS63E为核心,用于各个引脚与传感器或执行器之间的通信。
+
+### 2. PCBlayout
+
+
+以下是PCB设计🔗
+
+
+
+
+
+为了方便硬件焊接测试与软件调试,我们将各个摇杆等主要功能按键导出为markdown文件🔗
+以供快速参考
+
+### 3. 主体建模
+1. 遥控器底板模型🔗总体按照PCB轮廓构建,使用Autodesk Fusion进行建模。
+ - 整体参考游戏手柄与遥控手柄设计
+ - 底板前端突起为外置天线座,可以搭载外设SLE天线
+ - 预留四个M3空位,用于与PCB和顶板的连接固定
+
+
+
+
+
+
+
+2. 顶层亚克力板轮廓🔗由底板模型轮廓构建,使用Fusion进行导出
+ - 顶板设计需要考虑按键与摇杆等传感器加上键帽配件等的总体高度
+ - 预留四个M3空位,用于与PCB和顶板的连接固定
+ - 六角铜柱需要的最小高度为:PCB插排高度+WS63E最大高度 = 16mm
+
+
+
+
+
+### 4. 物料购买
+
+PDB电子元器件物料可直接由嘉立创EDA导出
+BOM表单🔗,交由专业配件商家购买。
+
+除此之外,完成总体装配还需要其他配件或耗材🔗。
+
+
+1. 摇杆帽:用于摇杆操控(注意底孔是小孔型号哦)
+2. 亚克力板:用于遥控器整体面板(dxf亚克力轮廓图🔗)
+3. 焊锡膏:用于贴片原件焊料
+4. 704硅橡胶:用于PCB电池盒固定
+5. 18650电池:用于遥控板供电
+6. 六角铜柱:用于整体连接
+
+
+### 5. 焊接说明
+
+1. 准备好PCB、元器件、电烙铁或热风枪、锡膏或锡丝、镊子。
+2. 打开BOM表或EDA,从贴片元器件开始,找到要焊接的元器件型号。
+
+
+
+
+
+3. 按照元器件位置进行分区,使用热风枪时对邻近贴片元器件一起焊接。
+
+
+
+
+
+4. 每个模块焊接完成后,可以对照PCB工程图,用万用表逐个检查是否存在焊错、短路、虚焊、脱焊等情况。
+5. 按上述的步骤,完成所有元器件的焊接即可。也可使用洗板水确保焊后的美观。
+
+
+
+
+
+
+
+
+
+### 6. 测试说明
+
+> 焊接完成后,要先目测、用万用表检测下,有没有焊接错的地方。尤其确保没有短路。第一次上电时也要第一时间观察下有没有异常,有异常迅速拔掉电源。
+
+可能遇到的问题:
+1. IP5306相关问题
+ - [x] 1. 输出电压很低,只有2-3V,没有了升压。
+ - 原因
+ 是芯片底部GND与PCB之间脱焊所致。
+ - 解决方案
+ IP5306底部的焊盘为GND,在焊接时建议为底盘加锡进行焊接
+ - [x] 2. 开机半分钟自动休眠
+ - 原因
+ - 是电流过低,可以检查是否有元器件虚焊脱焊现象。当一段时间内芯片负载电流持续小于45mA左右时,芯片会自动进入休眠状态。 但在实际应用中,此芯片个体差异很大,有部分芯片负载电流需要达到70mA以上才不会自动休眠
+ - 解决方案
+ - 检查元器件是否脱焊、虚焊,重新焊接。
+ - [x] 不断关机重启
+ - 原因
+ - 可能是芯片检测到过流或者短路引起的
+ - 可能是散热不足触发过温保护导致的
+ - 解决方案
+ - 检查是否短路,进行重新焊接;
+ - 检查是否由过温导致,检查工作温度是否符合要求,增加散热片等散热措施;
+
+
+
+
+ - [x] 芯片烧毁
+ - 原因
+ - 电池持续放电或温度过高等原因导致芯片烧毁
+ - 解决方案
+ - 检查电池质量与焊接质量,进行重新焊接,更换芯片。
+2. 其他问题
+ - [x] 传感器失灵
+ - 原因
+ - 传感器元器件与PCB脱焊或虚焊
+ - 解决方案
+ - 检查元器件是否脱焊、虚焊,重新焊接。
+
+### 7. 硬件总装
+注意三个组件从底部往上装配。
+1. 从底版底部拧入螺丝,在底版上部放入垫片与螺帽。在确保与PCB孔位对齐的情况下固定好底板与螺丝。
+2. 在底板上部侧放入PCB,注意对准螺孔,在上侧放入垫片与六角铜柱拧紧。
+3. 在螺柱顶部放入亚克力板,对齐后加上垫片拧入螺丝
+4. 您的第一个星闪遥控器大功告成
+
+
+
+
+
+### 8. 软硬件调试
+
+启动遥控器,检查是否有异常现象,如有异常现象,及时断电检查。正常情况下,遥控器应该可以正常工作。
+
+同时启动EulerCar小车sle和ros节点即可。
+
+
+## 星闪手柄实操展示
+>
+
+手柄操作方法:
+1. 左摇杆:控制EulerCar前进、后退、左转、右转
+2. 右摇杆:控制EulerCar夹爪:张开、闭合
+3. 左右扭子开关:切换不同EulerCar小车
+前进
+
+左转
+
+右转
+
+后退
+
+
+
+
+
+
+## 作者
+
+Github: [AbrillantLee](https://github.com/Abrillant-Lee) 、[pete](https://github.com/Pete-Young)
+
+## 特别鸣谢 「梅科尔工作室」
+大一入学时我是一个对计算机一无所知的小白,更别提海思开发;一切的转机发生在加入梅科尔工作室这个大家庭后,受到了李老师和学长们的用心培养。
+
+在这里 我怀着崇敬之心真诚地感谢梅科尔工作室! 感谢感谢杨阳学长的信任、感谢杨瑞学弟与我共同奋斗。
+
+同时,感谢杨帆工程师、杨红亮导师的耐心指导。
+
+工作室也时刻激励着我,做一件事,就得用心做好,无论是学习、项目、还是为人。
diff --git a/hi-sle/RelevantDetails/IP5306_datasheet_v1.01.pdf b/hi-sle/RelevantDetails/IP5306_datasheet_v1.01.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..cb968e06b592716a00d1305526b82cad503fef39
Binary files /dev/null and b/hi-sle/RelevantDetails/IP5306_datasheet_v1.01.pdf differ
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/SLE_OSPP_Server.h b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/SLE_OSPP_Server.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca56a47cbf15cff2be40f68cb5aff41def12b4ac
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/SLE_OSPP_Server.h
@@ -0,0 +1,25 @@
+
+/**
+ * @defgroup
+ * @ingroup
+ * @{
+ */
+#ifndef SLE_LED_SERVER_H
+#define SLE_LED_SERVER_H
+
+#include "sle_ssap_server.h"
+// #include "gpio.h" // GPIO操作相关的头文件
+// #include "pinctrl_porting.h"
+
+// 这些UUID的值是如何确定的?
+
+/* Service UUID 服务UUID*/
+#define SLE_UUID_SERVER_SERVICE 0xABCD
+
+/* Notify Repoert UUID 通知报告UUID*/
+#define SLE_UUID_SERVER_NTF_REPORT 0x1122
+
+/* Property UUID 特征信息UUID*/
+#define SLE_UUID_SERVER_PROPERTY 0x3344
+
+#endif
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/SLE_OSPP_Server_adv.h b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/SLE_OSPP_Server_adv.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0222d3e0a97c60eff32469cd4d06cc17a69ed74
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/SLE_OSPP_Server_adv.h
@@ -0,0 +1,96 @@
+/*
+# 版权所有 (C) 2024 HiHope 开源组织。
+# 根据 Apache 许可证 2.0 版(“许可证”)授权;
+# 除非遵守许可证,否则您不得使用此文件。
+# 您可以在以下位置获取许可证的副本
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# 除非适用法律要求或书面同意,否则根据许可证分发的软件
+# 以“原样”分发,
+# 不附带任何明示或暗示的保证或条件。
+# 请参阅许可证,了解许可证下管理权限和
+# 限制的特定语言。
+*/
+
+/** 这个注释是 Doxygen 风格的注释,用于生成文档
+ * @defgroup
+ * @ingroup
+ * @{
+ */
+
+#ifndef SLE_LED_SERVER_ADV_H
+#define SLE_LED_SERVER_ADV_H
+
+/**
+ * @if Eng
+ * @brief Definitaion of BLE ADV 通用广播结构.
+ * @else
+ * @brief SLE 广播普通数据结构。
+ * @endif
+ */
+struct sle_adv_common_value {
+ uint8_t length;
+ uint8_t type;
+ uint8_t value;
+};
+
+/**
+ * @if Eng
+ * @brief Definitaion of BLE ADV Channel mapping.
+ * @else
+ * @brief SLE 广播信道映射。
+ * @endif
+ */
+typedef enum {
+ SLE_ADV_CHANNEL_MAP_77 = 0x01,
+ SLE_ADV_CHANNEL_MAP_78 = 0x02,
+ SLE_ADV_CHANNEL_MAP_79 = 0x04,
+ SLE_ADV_CHANNEL_MAP_DEFAULT = 0x07
+} sle_adv_channel_map;
+
+/**
+ * @if Eng
+ * @brief Definitaion of SLE ADV Data Type.
+ * @else
+ * @brief SLE 广播数据类型
+ * @endif
+ */
+typedef enum {
+ SLE_ADV_DATA_TYPE_DISCOVERY_LEVEL = 0x01, /*!< 发现等级 */
+ SLE_ADV_DATA_TYPE_ACCESS_MODE = 0x02, /*!< 接入层能力 */
+ SLE_ADV_DATA_TYPE_SERVICE_DATA_16BIT_UUID = 0x03, /*!< 标准服务数据信息 */
+ SLE_ADV_DATA_TYPE_SERVICE_DATA_128BIT_UUID = 0x04, /*!< 自定义服务数据信息 */
+ SLE_ADV_DATA_TYPE_COMPLETE_LIST_OF_16BIT_SERVICE_UUIDS = 0x05, /*!< 完整标准服务标识列表 */
+ SLE_ADV_DATA_TYPE_COMPLETE_LIST_OF_128BIT_SERVICE_UUIDS = 0x06, /*!< 完整自定义服务标识列表 */
+ SLE_ADV_DATA_TYPE_INCOMPLETE_LIST_OF_16BIT_SERVICE_UUIDS = 0x07, /*!< 部分标准服务标识列表 */
+ SLE_ADV_DATA_TYPE_INCOMPLETE_LIST_OF_128BIT_SERVICE_UUIDS = 0x08, /*!< 部分自定义服务标识列表 */
+ SLE_ADV_DATA_TYPE_SERVICE_STRUCTURE_HASH_VALUE = 0x09, /*!< 服务结构散列值 */
+ SLE_ADV_DATA_TYPE_SHORTENED_LOCAL_NAME = 0x0A, /*!< 设备缩写本地名称 */
+ SLE_ADV_DATA_TYPE_COMPLETE_LOCAL_NAME = 0x0B, /*!< 设备完整本地名称 */
+ SLE_ADV_DATA_TYPE_TX_POWER_LEVEL = 0x0C, /*!< 广播发送功率 */
+ SLE_ADV_DATA_TYPE_SLB_COMMUNICATION_DOMAIN = 0x0D, /*!< SLB通信域域名 */
+ SLE_ADV_DATA_TYPE_SLB_MEDIA_ACCESS_LAYER_ID = 0x0E, /*!< SLB媒体接入层标识 */
+ SLE_ADV_DATA_TYPE_EXTENDED = 0xFE, /*!< 数据类型扩展 */
+ SLE_ADV_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF /*!< 厂商自定义信息 */
+} sle_adv_data_type;
+
+/**
+ * @if Eng
+ * @brief sle adv config and announce.
+ * @attention NULL
+ * @retval ERRCODE_SLE_SUCCESS Excute successfully
+ * @retval ERRCODE_SLE_FAIL Execute fail
+ * @par Dependency:
+ * @li NULL
+ * @else
+ * @brief sle广播配置和公开。
+ * @attention NULL
+ * @retval ERRCODE_SLE_SUCCESS 执行成功
+ * @retval ERRCODE_SLE_FAIL 执行失败
+ * @par 依赖:
+ * @li NULL
+ * @endif
+ */
+errcode_t example_sle_server_adv_init(void);
+#endif
\ No newline at end of file
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/button.h b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/button.h
new file mode 100644
index 0000000000000000000000000000000000000000..3eb03f8228809aba6c38936da10d9dccd7a87b1b
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/button.h
@@ -0,0 +1,19 @@
+#ifndef BUTTON_H
+#define BUTTON_H
+
+#include "pinctrl.h"
+#include "hal_gpio.h"
+#include "gpio.h"
+#include "osal_task.h"
+
+// 定义按键引脚
+#define LEFT_BUTTON_PIN 2
+#define RIGHT_BUTTON_PIN 4
+#define LEFT_TOGGLE_PIN 5
+#define RIGHT_TOGGLE_PIN 3
+
+// 初始化按键
+void Key_Init(void);
+
+
+#endif // KEY_H
\ No newline at end of file
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/eulercar_control.h b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/eulercar_control.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b645b66af10e874e41d873b346f7d52f79e8df2
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/eulercar_control.h
@@ -0,0 +1,26 @@
+#ifndef EULERCAR_CONTROL_H
+#define EULERCAR_CONTROL_H
+
+#include
+
+// 宏定义延时参数(毫秒)
+#define PRESS_RELEASE_INTERVAL 50
+#define LONG_PRESS_INTERVAL 100
+
+// 键盘报告结构体定义
+typedef struct
+{
+ uint8_t kind; // 键盘报告类型
+ uint8_t special_key; // 特殊按键
+ uint8_t reserve; // 保留字段
+ uint8_t key[6]; // 按键值数组
+} usb_hid_rcu_keyboard_report_t;
+
+// 函数声明
+void eulercar_control_forward(void);
+void eulercar_control_backward(void);
+void eulercar_control_left(void);
+void eulercar_control_right(void);
+void eulercar_control_stop(void);
+
+#endif // EULERCAR_CONTROL_H
\ No newline at end of file
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/shake.h b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/shake.h
new file mode 100644
index 0000000000000000000000000000000000000000..2a9379b6bfced0e91686768e68e8327988b035cf
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/inc/shake.h
@@ -0,0 +1,70 @@
+#ifndef SHAKE_H
+#define SHAKE_H
+
+#define SHAKE_PIN 11
+
+// 震动时长定义(单位:毫秒)
+#define VIBRATION_DURATION_POWER_ON 250 // 开发板上电震动时长
+#define VIBRATION_DURATION_CONN_CHANGE 500 // 星闪连接状态改变震动时长
+#define VIBRATION_DURATION_GRIPPER_LIMIT 100 // 夹爪行程极限震动时长
+#define VIBRATION_DURATION_CAR_CONTROL 100 // 控制小车震动时长
+
+/**
+ * @brief 开发板上电震动函数
+ *
+ * 该函数用于在开发板上电时触发震动马达震动。
+ */
+void Vibration_PowerOn(void);
+
+/**
+ * @brief 星闪连接状态改变震动函数
+ *
+ * 该函数用于在星闪连接状态改变(连接上或断连)时触发震动马达震动。
+ */
+void Vibration_ConnChange(void);
+
+/**
+ * @brief 夹爪行程极限震动函数
+ *
+ * 该函数用于在夹爪达到行程极限时触发震动马达震动。
+ */
+void Vibration_GripperLimit(void);
+
+/**
+ * @brief 控制小车震动函数
+ *
+ * 该函数用于在控制小车前进、后退、左转或右转时触发震动马达震动。
+ */
+void Vibration_CarControl(void);
+
+/**
+ * @brief 震动马达初始化函数
+ *
+ * 该函数用于初始化震动马达的相关硬件和软件资源。
+ */
+void Shake_Init(void);
+
+/**
+ * @brief 启动震动马达函数
+ *
+ * 该函数用于启动震动马达,使其开始震动。
+ */
+void Shake_Start(void);
+
+/**
+ * @brief 停止震动马达函数
+ *
+ * 该函数用于停止震动马达,使其停止震动。
+ */
+void Shake_Stop(void);
+
+/**
+ * @brief 震动马达震动函数
+ *
+ * @param duration 震动时长(单位:毫秒)
+ *
+ * 该函数用于使震动马达震动指定时长。
+ */
+void Shake_Buzz(unsigned int duration);
+
+#endif // SHAKE_H
\ No newline at end of file
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/log/log b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/log/log
new file mode 100644
index 0000000000000000000000000000000000000000..c71b80f23a83cbf807e32a5312c02d1684793713
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/log/log
@@ -0,0 +1,548 @@
+./service.sh
+[INFO] [launch]: All log files can be found below /root/.ros/log/2018-03-09-12-45-23-878167-hieulerpi1-2403
+[INFO] [launch]: Default logging verbosity is set to INFO
+[INFO] [nearlink_robot_node-1]: process started with pid [2404]
+[INFO] [bs21_ws73_ros2-2]: process started with pid [2406]
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.412] [uapi gle_init]
+[bs21_ws73_ros2-2] [bts][info] btsrv_task_init btsrv_init: task create success
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.412] ssapc client init
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.412] ssapc register inter cbk
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] [uapi gle_enable]
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] [gle manger enable]enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle dd init
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle cm init enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] [GLE DM][DM init] transmission management module init
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] [GLE TM][TM init] transmission management module init
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle ssap init ok
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] [GLE SM] start init
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] [GLE DM][DM init] security management module init
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hadm init enter.
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle factory init enter.
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle glp init enter.
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] [gle manager_enable]enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle read maximum adv data len
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] read access filter list size
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] [GLE SM] read support cryptography algorithm
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001450, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hci struct to stream opcode:0xc06, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] hci command encode send tl paramlen=0x0 opcode:0xc06
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hci internal command send core send opcode=0xc06
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hci internal command send core send opcode=0x40a
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hci internal command send core send opcode=0x406
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hci internal command send core send opcode=0x402
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.413] gle hci internal command send core send opcode=0x1c07
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001450
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] gle execute command cbk evindex:c06
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] opcode = 0x0c06, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] max_adv_data_len = 0x00fb
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] gle read maximum adv data len
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001450, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] gle hci struct to stream opcode:0x40a, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] hci command encode send tl paramlen=0x0 opcode:0x40a
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] [HCI]gle hci internal evt cbk unreg table->id = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] gle hci internal command send core send opcode=0xc07
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.414] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001450
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] gle execute command cbk evindex:40a
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] opcode = 0x040a, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] read access filter list size = 16
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] [TIMRE_ADD][STACK_TIMER] TIMER=0xb00011e0, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] gle hci struct to stream opcode:0x406, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] hci command encode send tl paramlen=0x0 opcode:0x406
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] [HCI]gle hci internal evt cbk unreg table->id = 0x18a0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] [TIMER_DEL][STACK_TIMER] TIMER=0xb00011e0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] gle execute command cbk evindex:406
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] opcode = 0x0406, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] get addr:0xb0:66:**:**:**:00
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001290, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] gle hci struct to stream opcode:0x402, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] hci command encode send tl paramlen=0x0 opcode:0x402
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.415] [HCI]gle hci internal evt cbk unreg table->id = 0x18a0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001290
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] gle execute command cbk evindex:402
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] gle hci read buffer size cfm result:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] [gle manger enable]result = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] [GLE DM] event = 0x0
+[bs21_ws73_ros2-2] [ACore] sle enable cbk in, result:0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] dev enable ret:0.
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] recover key fail, there is no key
+[bs21_ws73_ros2-2] sle enable
+[bs21_ws73_ros2-2] [ACore] sle device discovery in, action:0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.416] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] sle_set_local_addr 0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] [gle hci read buffer size] result = 0x0, opindex: 0x00000402
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] [gle hci read buffer size] acb data len: 254 num: 5, icb data len: 0 num: 0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001340, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] gle hci struct to stream opcode:0x1c07, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] hci command encode send tl paramlen=0x0 opcode:0x1c07
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] [HCI]gle hci internal evt cbk unreg table->id = 0x18a0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] gle hci internal command send core send opcode=0x405
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.420] gle hci internal command send core send opcode=0x1001
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.437] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001340
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.437] gle execute command cbk evindex:1c07
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.437] opcode = 0x1c07, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.437] [GLE SM] algo: 0x02 0x02 0x02 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.437] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001760, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.437] gle hci struct to stream opcode:0xc07, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.438] hci command encode send tl paramlen=0x0 opcode:0xc07
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.438] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.438] [HCI]gle hci internal evt cbk unreg table->id = 0x18a0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.438] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001760
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.438] gle execute command cbk evindex:c07
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.438] opcode = 0x0c07, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.438] supported_adv_sets_num = 0x8
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.439] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001130, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.439] gle hci struct to stream opcode:0x405, stream_len=0x6
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.439] hci command encode send tl paramlen=0x6 opcode:0x405
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.439] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.439] [HCI]gle hci internal evt cbk unreg table->id = 0x18a0
+
+
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.439] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001130
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.439] gle execute command cbk evindex:405
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.439] opcode = 0x0405, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.439] gle set public address status success.
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.440] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001760, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.440] gle hci struct to stream opcode:0x1001, stream_len=0x8
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.440] hci command encode send tl paramlen=0x8 opcode:0x1001
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.440] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.440] [HCI]gle hci internal evt cbk unreg table->id = 0x405
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.440] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.440] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.440] gle hci internal command send core send opcode=0x406
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.457] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001760
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.457] gle execute command cbk evindex:1001
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.457] opcode = 0x1001, cmd_result = 0xb
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.457] [dd]event = 0x8
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.457] [SLE SCAN CBK] event: 8.
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.457] start device seek.
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.457] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001290, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.457] gle hci struct to stream opcode:0x406, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.457] hci command encode send tl paramlen=0x0 opcode:0x406
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.457] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] [HCI]gle hci internal evt cbk unreg table->id = 0x1400
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] scan_enable = 0x1, filter_duplicates = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] gle hci internal command send core send opcode=0x1002
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001290
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] gle execute command cbk evindex:406
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] opcode = 0x0406, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] get addr:0xb0:66:**:**:**:00
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001370, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] gle hci struct to stream opcode:0x1002, stream_len=0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] hci command encode send tl paramlen=0x2 opcode:0x1002
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.458] [HCI]gle hci internal evt cbk unreg table->id = 0x1400
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.459] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001370
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.459] gle execute command cbk evindex:1002
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.459] opcode = 0x1002, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.459] gle dd set scan enable cfm scan enabled
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.459] [dd]event = 0x9
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.459] [SLE SCAN CBK] event: 9.
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.459] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:45:24.459] [HCI]gle hci internal evt cbk unreg table->id = 0x1002
+[bs21_ws73_ros2-2] [ACore] sle device discovery in, action:5
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.23] op_ev = 0x180B
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.23] cfm_type = 0x1e
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.23] [dd]event = 0xb
+[bs21_ws73_ros2-2] [adv_report] event_type: 0x03, addr_type: 0x0000, addr: 3c:**:**:**:4e:33
+[bs21_ws73_ros2-2] [adv_report] data length: 6, data: 0x02 0x01 0x01 0x02 0x02 0x00
+[bs21_ws73_ros2-2] [ACore] sle device discovery in, action:7
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.23] stop device seek.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.23] scan_enable = 0x0, filter_duplicates = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.23] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.23] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001290, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.23] gle hci struct to stream opcode:0x1002, stream_len=0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.23] hci command encode send tl paramlen=0x2 opcode:0x1002
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.23] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.23] gle hci internal command send core send opcode=0x1002
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.37] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001290
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.37] gle execute command cbk evindex:1002
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.37] opcode = 0x1002, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] gle dd set scan enable cfm scan disabled
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] [dd]event = 0xa
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] [SLE SCAN CBK] event: 10.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] [HCI]gle hci internal evt cbk unreg table->id = 0x0
+[bs21_ws73_ros2-2] [ACore] sle device discovery in, action:6
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] create conn node, addr 3c:4a:xx:xx:xx:33
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] gle device link add node->status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] [GLE HCI] free hci cbk
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001760, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] gle hci struct to stream opcode:0x1401, stream_len=0x1b
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] hci command encode send tl paramlen=0x1b opcode:0x1401
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] gle hci internal command send core send opcode=0x1401
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] [HCI]gle hci ev command status num_hci_command_packets(0x1) command_opcode:0x1401 status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] gle hci ev command status restart ertx opcode=0x1401, timeout:0x2710
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.38] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001760
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.39] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001760, TIME=10000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.39] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.39] gle hci ev command status in opcode=0x1401, status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001760
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] gle access link status report in
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] [gle connect cfm] result:0x0 status = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] [GLE TM][LCID init] LCID = 0x0000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] [GLE SM] init new remote device.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] gle ssap create tl link by addr add dev onaddr:0x3c:**:**:**:4e:33
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] [cm]event = 0x0
+[bs21_ws73_ros2-2] [Connected]
+[bs21_ws73_ros2-2] addr:3c:**:**:**:4e:33, handle:00
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] [GLE HCI] free hci cbk
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] remote(0x3c:**:**:**:4e:33) conn_id(0)
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] remote(0x3c:**:**:**:4e:33) state(1)
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001760, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] gle hci struct to stream opcode:0x1801, stream_len=0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] hci command encode send tl paramlen=0x2 opcode:0x1801
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] gle hci internal command send core send opcode=0x1801
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.84] [GLE SM] pairing start, role: 0x0.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.94] [GLE SM] sm pairing request.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.94] [GLE SM] io_ability: 3, oob_flag 0, psk_flag: 0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] [TIMRE_ADD][STACK_TIMER] TIMER=0xa8000da0, TIME=30000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] [GLE AA] controller data send, co_hdl: 0x0000, data_index: 0x0134, len: 10.[2018-03-09 12:46:03.95] [HCI]gle hci ev command status num_hci_command_packets(0x1) command_opcode:0x1801 status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] gle hci ev command status restart ertx opcode=0x1801, timeout:0x2904
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001760
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001760, TIME=10500
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] gle hci ev command status in opcode=0x1801, status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001450, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] gle hci struct to stream opcode:0x1812, stream_len=0xf
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] hci command encode send tl paramlen=0xf opcode:0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.95] gle hci internal command send core send opcode=0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.96] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001450
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.96] gle read remote cs caps status(18)
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.96] [GLE DM] event = 0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.96] [ACore] gle manager general event report opcode[05]
+[bs21_ws73_ros2-2] general event report opcode[05]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.96] gle execute command cbk evindex:1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.96] opcode = 0x1812, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.96] gle send controller data cfm, co_handle: 0x0000, data_index: 0x0134.[2018-03-09 12:46:03.96] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.96] [HCI]gle hci internal evt cbk unreg table->id = 0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.100] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001760
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.100] gle read remote features complete.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.100] cfm_type = 0x11
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.100] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.100] gle set data len, lcid: 0x0000, tx octets: 0xfe
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.100] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.100] [GLE HCI] free hci cbk
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.101] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001760, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.101] gle hci struct to stream opcode:0x1802, stream_len=0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.102] hci command encode send tl paramlen=0x2 opcode:0x1802
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.102] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.102] gle hci internal command send core send opcode=0x1802
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.102] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.102] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.102] gle hci internal command send core send opcode=0x1804
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.102] [HCI]gle hci ev command status num_hci_command_packets(0x1) command_opcode:0x1802 status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.102] gle hci ev command status restart ertx opcode=0x1802, timeout:0x2904
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.102] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001760
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.103] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001760, TIME=10500
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.103] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001450, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.103] gle hci struct to stream opcode:0x1804, stream_len=0x4
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.103] hci command encode send tl paramlen=0x4 opcode:0x1804
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.103] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.103] gle hci ev command status in opcode=0x1802, status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.104] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001450
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.104] gle execute command cbk evindex:1804
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.104] [GLE HCI] set data len result = 0x0, opindex: 0x1804
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.104] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.104] [HCI]gle hci internal evt cbk unreg table->id = 0x1804
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.125] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001760
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.125] gle read remote version complete.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.125] cfm_type = 0x12
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.125] [cm]event = 0x7
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.125] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.138] gle access controller data cbk in
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.138] [GLE SM] data recv, lcid: 0x0000, len: 10, opcode: 0x0135
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.138] [GLE SM] algorithm negotiate: 2 2 2 0[2018-03-09 12:46:03.138] [GLE SM] sm pairing confirm, authentication method: 1.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.138] [TIMER_DEL][STACK_TIMER] TIMER=0xa8000da0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.138] [TIMRE_ADD][STACK_TIMER] TIMER=0xa8000da0, TIME=30000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.138] [GLE AA] controller data send, co_hdl: 0x0000, data_index: 0x0136, len: 70.[2018-03-09 12:46:03.138] [GLE SM] event = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.138] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.138] [TIMRE_ADD][STACK_TIMER] TIMER=0xb00011e0, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.138] gle hci struct to stream opcode:0x1812, stream_len=0x4b
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.139] hci command encode send tl paramlen=0x4b opcode:0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.139] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.139] gle hci internal command send core send opcode=0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.139] [TIMER_DEL][STACK_TIMER] TIMER=0xb00011e0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.139] gle read remote cs caps status(18)
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.139] [GLE DM] event = 0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.140] [ACore] gle manager general event report opcode[05]
+[bs21_ws73_ros2-2] general event report opcode[05]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.140] gle execute command cbk evindex:1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.140] opcode = 0x1812, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.140] gle send controller data cfm, co_handle: 0x0000, data_index: 0x0136.[2018-03-09 12:46:03.140] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.140] [HCI]gle hci internal evt cbk unreg table->id = 0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.163] gle access controller data cbk in
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.163] [GLE SM] data recv, lcid: 0x0000, len: 64, opcode: 0x0137
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] gle access controller data cbk in
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] [GLE SM] data recv, lcid: 0x0000, len: 16, opcode: 0x0138
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] [GLE SM] gle sm authentication procedure in, method: 0x1.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] [TIMER_DEL][STACK_TIMER] TIMER=0xa8000da0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] [TIMRE_ADD][STACK_TIMER] TIMER=0xa8000da0, TIME=30000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] [GLE AA] controller data send, co_hdl: 0x0000, data_index: 0x0139, len: 16.[2018-03-09 12:46:03.175] [GLE SM] authentication pdu send, opcode 0x0139.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001760, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] gle hci struct to stream opcode:0x1812, stream_len=0x15
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] hci command encode send tl paramlen=0x15 opcode:0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.175] gle hci internal command send core send opcode=0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.176] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001760
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.176] gle read remote cs caps status(18)
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.176] [GLE DM] event = 0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.176] [ACore] gle manager general event report opcode[05]
+[bs21_ws73_ros2-2] general event report opcode[05]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.176] gle execute command cbk evindex:1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.176] opcode = 0x1812, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.176] gle send controller data cfm, co_handle: 0x0000, data_index: 0x0139.[2018-03-09 12:46:03.176] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.176] [HCI]gle hci internal evt cbk unreg table->id = 0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.225] gle access controller data cbk in
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.225] [GLE SM] data recv, lcid: 0x0000, len: 16, opcode: 0x013a
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.225] [GLE SM] gle sm authentication procedure in, method: 0x1.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.234] [TIMER_DEL][STACK_TIMER] TIMER=0xa8000da0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] [TIMRE_ADD][STACK_TIMER] TIMER=0xa8000da0, TIME=30000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] [GLE AA] controller data send, co_hdl: 0x0000, data_index: 0x0141, len: 16.[2018-03-09 12:46:03.235] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001290, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] gle hci struct to stream opcode:0x1812, stream_len=0x15
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] hci command encode send tl paramlen=0x15 opcode:0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] gle hci internal command send core send opcode=0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001290
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] gle read remote cs caps status(18)
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] [GLE DM] event = 0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] [ACore] gle manager general event report opcode[05]
+[bs21_ws73_ros2-2] general event report opcode[05]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] gle execute command cbk evindex:1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] opcode = 0x1812, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] gle send controller data cfm, co_handle: 0x0000, data_index: 0x0141.[2018-03-09 12:46:03.235] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.235] [HCI]gle hci internal evt cbk unreg table->id = 0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] gle access controller data cbk in
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] [GLE SM] data recv, lcid: 0x0000, len: 16, opcode: 0x0142
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] [GLE SM] gle sm authentication procedure in, method: 0x1.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] [GLE SM] event = 0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] gle acore config data write:1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] gle acore set product type sys_config 0x:0!
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] gle acore save sm key write_index:00!
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] gle acore config data write:2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] [GLE SM] enable encryption
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] [GLE AA] enable encryption, crypt 1, key_deriv 1, integr_chk 0.
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] remote(0x3c:**:**:**:0x4e:0x33) conn_id(0)
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.250] [2018-03-09 12:46:03.250] [GLE HCI] free hci cbk
+[bs21_ws73_ros2-2] auth status:0, crypto algo:2, key deriv algo:2, integr chk ind:0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.251] [TIMRE_ADD][STACK_TIMER] TIMER=0xa8000fb0, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.251] gle hci struct to stream opcode:0x1c03, stream_len=0x15
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.251] hci command encode send tl paramlen=0x15 opcode:0x1c03
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.251] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.251] gle hci internal command send core send opcode=0x1c03
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.252] [HCI]gle hci ev command status num_hci_command_packets(0x1) command_opcode:0x1c03 status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.252] gle hci ev command status restart ertx opcode=0x1c03, timeout:0x2904
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.252] [TIMER_DEL][STACK_TIMER] TIMER=0xa8000fb0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.252] [TIMRE_ADD][STACK_TIMER] TIMER=0xa8000fb0, TIME=10500
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.252] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.252] gle hci ev command status in opcode=0x1c03, status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] [TIMER_DEL][STACK_TIMER] TIMER=0xa8000fb0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] op_ev = 0x0011
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] cfm_type = 0x27
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] [GLE SM] encrypt change, lcid: 0x0000, status: 0x0, encryption change: 0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] [TIMER_DEL][STACK_TIMER] TIMER=0xa8000da0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] [GLE SM] timer repeated attempts, job: 1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] [GLE SM] event = 0x3
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] conn_id(0) pair result:3
+[bs21_ws73_ros2-2] [ssap client] pair complete conn_id:0, addr:3c:4a:83:2f:4e:33
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] [uapi ssapc_exchange_info_req]mtu = 300
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] [gle ssapc_exchange_mtu]mtu = 0x12c
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] [ssapc exchange_info_req_handle]mtu = 300, version = 0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] task create tl connection tl->status = 0x2, tl->mask = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] mtu = 300, version = 0x0001
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.312] need wait for response
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.313] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001290, TIME=12000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.325] tl task[1] trans done
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.325] tl trans done trans->op:[0x03]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.325] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001290
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.325] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.325] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.325] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x52 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] tl task[1] trans done
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] op_code[0x03], control_code[0x03], mtu[300], version[0x0001]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] tl->mtu[300]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] task[1] complete, err_code:[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] task[0x01] complete, err_code = 0x00
+[bs21_ws73_ros2-2] ssapc exchange info, conn_id:0, err_code:0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] tl done err_code:[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] ssapc handle msg type:7
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] sample ssapc indication cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] ssapc find structure conn_id:0, type:1, start hdl:1, end hdl:ffff
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] ssapc find structure uuid len:0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] addr:3c:**:**:**:4e:33, type = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] ssap discovery service all
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] ssapc discovery services conn_handle = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] task->type = 0x1, task->hdl = 0x1ffff, task->uuid.len = 0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] task create tl connection tl->status = 0x2, tl->mask = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] task_id = 0x82, task_type = 0x1, op_code = 0x04
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] dicovery task send uuid.len = 0, uuid:0x0000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] dicovery task send start_hdl: 0x0001, end_hdl: 0xffff
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] data_len = 6
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] need wait for response
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.337] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001130, TIME=12000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.362] ssap check type by opcode trans->op:0x05
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.362] tl task[130] trans done
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.362] tl trans done trans->op:[0x05]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001130
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] data_len = 9
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] control_code.fragment:0x03, mode:0x00, task->type:0x01, task_id:0x82, task->uuid.len:0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] curent_idx:0, data_len:7
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] uuid_len: 2, service->uuid.len: 2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] ssapc discovery service event handle
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] con_hdl:[0x00], hdl:[0x01], end_hdl:[0x02], svc->type_indication:[0x02]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] [disc_srv_rsp]start_hdl:[0x01], end_hdl:[0x02]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] uuid:[0x00][0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] discovery service start hdl:1, end hdl:2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] sample ssapc discovery services cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] uuid_len = 2, last_hdl = 0x0002, idx = 7
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] cur_hdl:[0x0001ffff], last_hdl:[0x0002]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] task[130] complete, err_code:[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] task[0x82] complete, err_code = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] ssapc handle msg type:0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] sample ssapc discovery service cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] op_code:0x04, type:0x01, uuid.len:0, err_code:0x00
+[bs21_ws73_ros2-2] discovery character cbk complete in
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] [internal_discovery_services] op_code:0x04, type:0x01, uuid.len:0, err_code:0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] ssapc handle msg type:2
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] sample ssapc discovery service cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] [ssap client] ssapc_write_req, conn_id:0 data_len:4
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] ssapc write req conn_id:0, hdl:1, data len:4
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] ssapc write req addr:0x3c:**:**:**:0x4e:0x33
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] handle = 0x01, type = 0x00, len = 4
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] tl done err_code:[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] [ssapc write_value_req]data_type = 0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] task create tl connection tl->status = 0x2, tl->mask = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] write_data_len = 4, data_len = 4, mtu = 295
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] need wait for response
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.363] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001370, TIME=12000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] ssap check type by opcode trans->op:0x0e
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] tl task[8] trans done
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] tl trans done trans->op:[0x0e]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001370
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] [write rsp]hdl[0x0001], data_type[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] ssapc write rsp op_code[0x0e], control_code[0x03], value_len[7]
+[bs21_ws73_ros2-2] ssapc write rsp handle:1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] task[8] complete, err_code:[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] task[0x08] complete, err_code = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] [write_req_complete]err_code:0x00
+[bs21_ws73_ros2-2] [sle write_req_complete_cbk]conn_id:0, err_code:0
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] ssapc handle msg type:5
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] [2018-03-09 12:46:03.387] tl done err_code:[0x00]
+[bs21_ws73_ros2-2] sample ssapc write cfm cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] ssapc read req conn_id:0, hdl:1, type:0
+
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] ssapc read req addr:0x3c:**:**:**:0x4e:0x33
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.387] handle = 0x01, type = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.388] need wait for response
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.388] [TIMRE_ADD][STACK_TIMER] TIMER=0xb0001290, TIME=12000
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.412] ssap check type by opcode trans->op:0x09
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.412] tl trans done trans->op:[0x09]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.412] [TIMER_DEL][STACK_TIMER] TIMER=0xb0001290
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.412] op_code[0x09], control_code[0x03], data_len[4]
+[bs21_ws73_ros2-2] ssapc read rsp handle:0, data len:4
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.412] ssapc handle msg type:4
+[bs21_ws73_ros2-2] [2018-03-09 12:46:03.412] sample ssapc read cfm cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:46:05.337] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:05.337] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:46:05.337] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x52 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:07.362] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:07.362] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:46:07.362] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x52 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:09.350] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:09.350] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:46:09.350] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x52 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:11.362] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:11.362] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:46:11.362] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x52 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:13.375] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:13.375] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:46:13.375] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x52 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:1
+[bs21_ws73_ros2-2] [2018-03-09 12:46:15.387] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:46:15.387] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:46:15.387] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
\ No newline at end of file
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/log/log_old b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/log/log_old
new file mode 100644
index 0000000000000000000000000000000000000000..ea0f0649dff899505c80e437376f26aa7fd131a5
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/log/log_old
@@ -0,0 +1,549 @@
+ ./service.sh
+[INFO] [launch]: All log files can be found below /root/.ros/log/2018-03-09-12-40-15-200889-hieulerpi1-2216
+[INFO] [launch]: Default logging verbosity is set to INFO
+[INFO] [nearlink_robot_node-1]: process started with pid [2219]
+[INFO] [bs21_ws73_ros2-2]: process started with pid [2221]
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.753] [uapi gle_init]
+[bs21_ws73_ros2-2] [bts][info] btsrv_task_init btsrv_init: task create success
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] ssapc client init
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] ssapc register inter cbk
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] [uapi gle_enable]
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] [gle manger enable]enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle dd init
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle cm init enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] [GLE DM][DM init] transmission management module init
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] [GLE TM][TM init] transmission management module init
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle ssap init ok
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] [GLE SM] start init
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] [GLE DM][DM init] security management module init
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hadm init enter.
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle factory init enter.
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle glp init enter.
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] [gle manager_enable]enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle read maximum adv data len
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] read access filter list size
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] [GLE SM] read support cryptography algorithm
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001450, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hci struct to stream opcode:0xc06, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] hci command encode send tl paramlen=0x0 opcode:0xc06
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hci internal command send core send opcode=0xc06
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hci internal command send core send opcode=0x40a
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hci internal command send core send opcode=0x406
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hci internal command send core send opcode=0x402
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.754] gle hci internal command send core send opcode=0x1c07
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.755] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001450
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.755] gle execute command cbk evindex:c06
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.755] opcode = 0x0c06, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.755] max_adv_data_len = 0x00fb
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.755] gle read maximum adv data len
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.755] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001450, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.755] gle hci struct to stream opcode:0x40a, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] hci command encode send tl paramlen=0x0 opcode:0x40a
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] [HCI]gle hci internal evt cbk unreg table->id = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] gle hci internal command send core send opcode=0xc07
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001450
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] gle execute command cbk evindex:40a
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] opcode = 0x040a, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] read access filter list size = 16
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] [TIMRE_ADD][STACK_TIMER] TIMER=0xa00011e0, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] gle hci struct to stream opcode:0x406, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] hci command encode send tl paramlen=0x0 opcode:0x406
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] [HCI]gle hci internal evt cbk unreg table->id = 0x18a0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] [TIMER_DEL][STACK_TIMER] TIMER=0xa00011e0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] gle execute command cbk evindex:406
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] opcode = 0x0406, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.756] get addr:0xb0:66:**:**:**:00
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001290, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] gle hci struct to stream opcode:0x402, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] hci command encode send tl paramlen=0x0 opcode:0x402
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] [HCI]gle hci internal evt cbk unreg table->id = 0x18a0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001290
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] gle execute command cbk evindex:402
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] gle hci read buffer size cfm result:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] [gle hci read buffer size] result = 0x0, opindex: 0x00000402
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] [gle hci read buffer size] acb data len: 254 num: 5, icb data len: 0 num: 0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001340, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] gle hci struct to stream opcode:0x1c07, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] hci command encode send tl paramlen=0x0 opcode:0x1c07
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.757] [HCI]gle hci internal evt cbk unreg table->id = 0x18a0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.758] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001340
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.758] gle execute command cbk evindex:1c07
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.758] opcode = 0x1c07, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.758] [GLE SM] algo: 0x02 0x02 0x02 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.758] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001340, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.758] gle hci struct to stream opcode:0xc07, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.758] hci command encode send tl paramlen=0x0 opcode:0xc07
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.758] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.758] [HCI]gle hci internal evt cbk unreg table->id = 0x1c07
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.759] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001340
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.759] gle execute command cbk evindex:c07
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.759] opcode = 0x0c07, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.759] supported_adv_sets_num = 0x8
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.759] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.759] [HCI]gle hci internal evt cbk unreg table->id = 0xc07
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] [gle manger enable]result = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] [GLE DM] event = 0x0
+[bs21_ws73_ros2-2] [ACore] sle enable cbk in, result:0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] dev enable ret:0.
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] recover key fail, there is no key
+[bs21_ws73_ros2-2] sle enable
+[bs21_ws73_ros2-2] [ACore] sle device discovery in, action:0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle acore smp keys memcmp err, data all zero!
+[bs21_ws73_ros2-2] sle_set_local_addr 0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001790, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle hci struct to stream opcode:0x405, stream_len=0x6
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] hci command encode send tl paramlen=0x6 opcode:0x405
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle hci internal command send core send opcode=0x405
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.763] gle hci internal command send core send opcode=0x1001
+
+
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001790
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] gle execute command cbk evindex:405
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] opcode = 0x0405, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] gle set public address status success.
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001790, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] gle hci struct to stream opcode:0x1001, stream_len=0x8
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] hci command encode send tl paramlen=0x8 opcode:0x1001
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] [HCI]gle hci internal evt cbk unreg table->id = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.764] gle hci internal command send core send opcode=0x406
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001790
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] gle execute command cbk evindex:1001
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] opcode = 0x1001, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] [dd]event = 0x8
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] [SLE SCAN CBK] event: 8.
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] start device seek.
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001290, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] gle hci struct to stream opcode:0x406, stream_len=0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] hci command encode send tl paramlen=0x0 opcode:0x406
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] [HCI]gle hci internal evt cbk unreg table->id = 0x1710
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] scan_enable = 0x1, filter_duplicates = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] gle hci internal command send core send opcode=0x1002
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001290
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] gle execute command cbk evindex:406
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] opcode = 0x0406, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] get addr:0xb0:66:**:**:**:00
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.765] [TIMRE_ADD][STACK_TIMER] TIMER=0xbf65e9a0, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] gle hci struct to stream opcode:0x1002, stream_len=0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] hci command encode send tl paramlen=0x2 opcode:0x1002
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] [HCI]gle hci internal evt cbk unreg table->id = 0x1710
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] [TIMER_DEL][STACK_TIMER] TIMER=0xbf65e9a0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] gle execute command cbk evindex:1002
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] opcode = 0x1002, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] gle dd set scan enable cfm scan enabled
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] [dd]event = 0x9
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] [SLE SCAN CBK] event: 9.
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:40:15.766] [HCI]gle hci internal evt cbk unreg table->id = 0x0
+[bs21_ws73_ros2-2] [ACore] sle device discovery in, action:5
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.843] op_ev = 0x180B
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.843] cfm_type = 0x1e
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.843] [dd]event = 0xb
+[bs21_ws73_ros2-2] [adv_report] event_type: 0x03, addr_type: 0x0000, addr: 3c:**:**:**:4e:33
+[bs21_ws73_ros2-2] [adv_report] data length: 6, data: 0x01 0x02 0x01 0x02 0x02 0x00
+[bs21_ws73_ros2-2] [ACore] sle device discovery in, action:7
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.843] stop device seek.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.844] scan_enable = 0x0, filter_duplicates = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.844] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.844] [TIMRE_ADD][STACK_TIMER] TIMER=0xbf65e9a0, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.844] gle hci struct to stream opcode:0x1002, stream_len=0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.844] hci command encode send tl paramlen=0x2 opcode:0x1002
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.844] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.844] gle hci internal command send core send opcode=0x1002
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] [TIMER_DEL][STACK_TIMER] TIMER=0xbf65e9a0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] gle execute command cbk evindex:1002
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] opcode = 0x1002, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] gle dd set scan enable cfm scan disabled
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] [dd]event = 0xa
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] [SLE SCAN CBK] event: 10.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] [HCI]gle hci internal evt cbk unreg table->id = 0x0
+[bs21_ws73_ros2-2] [ACore] sle device discovery in, action:6
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] create conn node, addr 3c:4a:xx:xx:xx:33
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] gle device link add node->status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] [GLE HCI] free hci cbk
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001790, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] gle hci struct to stream opcode:0x1401, stream_len=0x1b
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] hci command encode send tl paramlen=0x1b opcode:0x1401
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.858] gle hci internal command send core send opcode=0x1401
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.859] [HCI]gle hci ev command status num_hci_command_packets(0x1) command_opcode:0x1401 status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.859] gle hci ev command status restart ertx opcode=0x1401, timeout:0x2710
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.859] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001790
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.859] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001790, TIME=10000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.859] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.859] gle hci ev command status in opcode=0x1401, status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001790
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] gle access link status report in
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] [gle connect cfm] result:0x0 status = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] [GLE TM][LCID init] LCID = 0x0000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] [GLE SM] init new remote device.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] gle ssap create tl link by addr add dev onaddr:0x3c:**:**:**:4e:33
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] [cm]event = 0x0
+[bs21_ws73_ros2-2] [Connected]
+[bs21_ws73_ros2-2] addr:3c:**:**:**:4e:33, handle:00
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] [GLE HCI] free hci cbk
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] remote(0x3c:**:**:**:4e:33) conn_id(0)
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] remote(0x3c:**:**:**:4e:33) state(1)
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001790, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] gle hci struct to stream opcode:0x1801, stream_len=0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] hci command encode send tl paramlen=0x2 opcode:0x1801
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] gle hci internal command send core send opcode=0x1801
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.880] [GLE SM] pairing start, role: 0x0.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.890] [GLE SM] sm pairing request.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.890] [GLE SM] io_ability: 3, oob_flag 0, psk_flag: 0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] [TIMRE_ADD][STACK_TIMER] TIMER=0x98000da0, TIME=30000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] [GLE AA] controller data send, co_hdl: 0x0000, data_index: 0x0134, len: 10.[2018-03-09 12:41:40.891] [HCI]gle hci ev command status num_hci_command_packets(0x1) command_opcode:0x1801 status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] gle hci ev command status restart ertx opcode=0x1801, timeout:0x2904
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001790
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001790, TIME=10500
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] gle hci ev command status in opcode=0x1801, status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001450, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] gle hci struct to stream opcode:0x1812, stream_len=0xf
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] hci command encode send tl paramlen=0xf opcode:0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.891] gle hci internal command send core send opcode=0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.897] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001450
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.897] gle read remote cs caps status(18)
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.897] [GLE DM] event = 0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.897] [ACore] gle manager general event report opcode[05]
+[bs21_ws73_ros2-2] general event report opcode[05]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.897] gle execute command cbk evindex:1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.897] opcode = 0x1812, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.897] gle send controller data cfm, co_handle: 0x0000, data_index: 0x0134.[2018-03-09 12:41:40.897] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.897] [HCI]gle hci internal evt cbk unreg table->id = 0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.912] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001790
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.912] gle read remote features complete.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.912] cfm_type = 0x11
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.912] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.912] gle set data len, lcid: 0x0000, tx octets: 0xfe
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.912] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.912] [GLE HCI] free hci cbk
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.912] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001790, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.913] gle hci struct to stream opcode:0x1802, stream_len=0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.913] hci command encode send tl paramlen=0x2 opcode:0x1802
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.913] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.913] gle hci internal command send core send opcode=0x1802
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.913] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.913] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.913] gle hci internal command send core send opcode=0x1804
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.913] [HCI]gle hci ev command status num_hci_command_packets(0x1) command_opcode:0x1802 status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.913] gle hci ev command status restart ertx opcode=0x1802, timeout:0x2904
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.914] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001790
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.914] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001790, TIME=10500
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.914] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001450, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.914] gle hci struct to stream opcode:0x1804, stream_len=0x4
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.914] hci command encode send tl paramlen=0x4 opcode:0x1804
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.914] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.914] gle hci ev command status in opcode=0x1802, status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.915] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001450
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.915] gle execute command cbk evindex:1804
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.915] [GLE HCI] set data len result = 0x0, opindex: 0x1804
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.915] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.915] [HCI]gle hci internal evt cbk unreg table->id = 0x1804
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.937] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001790
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.937] gle read remote version complete.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.937] cfm_type = 0x12
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.937] [cm]event = 0x7
+[bs21_ws73_ros2-2] [2018-03-09 12:41:40.937] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.474] gle access controller data cbk in
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.474] [GLE SM] data recv, lcid: 0x0000, len: 10, opcode: 0x0135
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.474] [GLE SM] algorithm negotiate: 2 2 2 0[2018-03-09 12:41:41.474] [GLE SM] sm pairing confirm, authentication method: 1.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.474] [TIMER_DEL][STACK_TIMER] TIMER=0x98000da0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.474] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001790, TIME=30000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.474] [GLE AA] controller data send, co_hdl: 0x0000, data_index: 0x0136, len: 70.[2018-03-09 12:41:41.474] [GLE SM] event = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.474] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.474] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001450, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.474] gle hci struct to stream opcode:0x1812, stream_len=0x4b
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.475] hci command encode send tl paramlen=0x4b opcode:0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.475] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.475] gle hci internal command send core send opcode=0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.475] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001450
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.475] gle read remote cs caps status(18)
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.475] [GLE DM] event = 0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.475] [ACore] gle manager general event report opcode[05]
+[bs21_ws73_ros2-2] general event report opcode[05]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.475] gle execute command cbk evindex:1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.475] opcode = 0x1812, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.475] gle send controller data cfm, co_handle: 0x0000, data_index: 0x0136.[2018-03-09 12:41:41.475] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.475] [HCI]gle hci internal evt cbk unreg table->id = 0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.500] gle access controller data cbk in
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.500] [GLE SM] data recv, lcid: 0x0000, len: 64, opcode: 0x0137
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] gle access controller data cbk in
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] [GLE SM] data recv, lcid: 0x0000, len: 16, opcode: 0x0138
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] [GLE SM] gle sm authentication procedure in, method: 0x1.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001790
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001790, TIME=30000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] [GLE AA] controller data send, co_hdl: 0x0000, data_index: 0x0139, len: 16.[2018-03-09 12:41:41.537] [GLE SM] authentication pdu send, opcode 0x0139.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] [TIMRE_ADD][STACK_TIMER] TIMER=0xbf65e9a0, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] gle hci struct to stream opcode:0x1812, stream_len=0x15
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] hci command encode send tl paramlen=0x15 opcode:0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.537] gle hci internal command send core send opcode=0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.538] [TIMER_DEL][STACK_TIMER] TIMER=0xbf65e9a0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.538] gle read remote cs caps status(18)
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.538] [GLE DM] event = 0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.538] [ACore] gle manager general event report opcode[05]
+[bs21_ws73_ros2-2] general event report opcode[05]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.538] gle execute command cbk evindex:1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.538] opcode = 0x1812, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.538] gle send controller data cfm, co_handle: 0x0000, data_index: 0x0139.[2018-03-09 12:41:41.538] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:41.538] [HCI]gle hci internal evt cbk unreg table->id = 0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.624] gle access controller data cbk in
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.624] [GLE SM] data recv, lcid: 0x0000, len: 16, opcode: 0x013a
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.624] [GLE SM] gle sm authentication procedure in, method: 0x1.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.634] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001790
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.634] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001790, TIME=30000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.634] [GLE AA] controller data send, co_hdl: 0x0000, data_index: 0x0141, len: 16.[2018-03-09 12:41:42.634] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.634] [TIMRE_ADD][STACK_TIMER] TIMER=0xa00011e0, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.634] gle hci struct to stream opcode:0x1812, stream_len=0x15
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.634] hci command encode send tl paramlen=0x15 opcode:0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.634] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.634] gle hci internal command send core send opcode=0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.635] [TIMER_DEL][STACK_TIMER] TIMER=0xa00011e0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.635] gle read remote cs caps status(18)
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.635] [GLE DM] event = 0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.635] [ACore] gle manager general event report opcode[05]
+[bs21_ws73_ros2-2] general event report opcode[05]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.635] gle execute command cbk evindex:1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.635] opcode = 0x1812, cmd_result = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.635] gle send controller data cfm, co_handle: 0x0000, data_index: 0x0141.[2018-03-09 12:41:42.635] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.635] [HCI]gle hci internal evt cbk unreg table->id = 0x1812
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] gle access controller data cbk in
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] [GLE SM] data recv, lcid: 0x0000, len: 16, opcode: 0x0142
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] [GLE SM] gle sm authentication procedure in, method: 0x1.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] [GLE SM] event = 0x2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] gle acore config data write:1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] gle acore set product type sys_config 0x:0!
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] gle acore save sm key write_index:00!
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] gle acore config data write:2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] [GLE SM] enable encryption
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] [GLE AA] enable encryption, crypt 1, key_deriv 1, integr_chk 0.
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] gle execute command send enter
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] [GLE HCI] free hci cbk
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] remote(0x3c:**:**:**:0x4e:0x33) conn_id(0)
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] auth status:0, crypto algo:2, key deriv algo:2, integr chk ind:0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] [TIMRE_ADD][STACK_TIMER] TIMER=0x98000f60, TIME=2000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] gle hci struct to stream opcode:0x1c03, stream_len=0x15
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] hci command encode send tl paramlen=0x15 opcode:0x1c03
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] gle hci command check send check and send, cmd_num:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.725] gle hci internal command send core send opcode=0x1c03
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.726] [HCI]gle hci ev command status num_hci_command_packets(0x1) command_opcode:0x1c03 status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.726] gle hci ev command status restart ertx opcode=0x1c03, timeout:0x2904
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.726] [TIMER_DEL][STACK_TIMER] TIMER=0x98000f60
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.726] [TIMRE_ADD][STACK_TIMER] TIMER=0x98000f60, TIME=10500
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.726] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.726] gle hci ev command status in opcode=0x1c03, status:0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] [TIMER_DEL][STACK_TIMER] TIMER=0x98000f60
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] op_ev = 0x0011
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] cfm_type = 0x27
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] [GLE SM] encrypt change, lcid: 0x0000, status: 0x0, encryption change: 0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001790
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] [GLE SM] timer repeated attempts, job: 1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] [GLE SM] event = 0x3
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] gle hci command check send check and send, cmd_num:0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] conn_id(0) pair result:3
+[bs21_ws73_ros2-2] [ssap client] pair complete conn_id:0, addr:3c:4a:83:2f:4e:33
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] [uapi ssapc_exchange_info_req]mtu = 300
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] [gle ssapc_exchange_mtu]mtu = 0x12c
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] [ssapc exchange_info_req_handle]mtu = 300, version = 0x1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] task create tl connection tl->status = 0x2, tl->mask = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] mtu = 300, version = 0x0001
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.799] need wait for response
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.800] [TIMRE_ADD][STACK_TIMER] TIMER=0xa00011e0, TIME=12000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] ssap check type by opcode trans->op:0x03
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] tl task[1] trans done
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] tl trans done trans->op:[0x03]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] [TIMER_DEL][STACK_TIMER] TIMER=0xa00011e0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] op_code[0x03], control_code[0x03], mtu[300], version[0x0001]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] tl->mtu[300]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] task[1] complete, err_code:[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] task[0x01] complete, err_code = 0x00
+[bs21_ws73_ros2-2] ssapc exchange info, conn_id:0, err_code:0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] tl done err_code:[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] ssapc handle msg type:7
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] sample ssapc indication cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] ssapc find structure conn_id:0, type:1, start hdl:1, end hdl:ffff
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] ssapc find structure uuid len:0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] addr:3c:**:**:**:4e:33, type = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] ssap discovery service all
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] ssapc discovery services conn_handle = 0x0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] task->type = 0x1, task->hdl = 0x1ffff, task->uuid.len = 0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] task create tl connection tl->status = 0x2, tl->mask = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] task_id = 0x82, task_type = 0x1, op_code = 0x04
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] dicovery task send uuid.len = 0, uuid:0x0000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] dicovery task send start_hdl: 0x0001, end_hdl: 0xffff
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] data_len = 6
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] need wait for response
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.824] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001340, TIME=12000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.849] ssap check type by opcode trans->op:0x05
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.849] tl task[130] trans done
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.849] tl trans done trans->op:[0x05]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001340
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] data_len = 9
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] control_code.fragment:0x03, mode:0x00, task->type:0x01, task_id:0x82, task->uuid.len:0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] curent_idx:0, data_len:7
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] uuid_len: 2, service->uuid.len: 2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] ssapc discovery service event handle
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] con_hdl:[0x00], hdl:[0x01], end_hdl:[0x02], svc->type_indication:[0x02]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] [disc_srv_rsp]start_hdl:[0x01], end_hdl:[0x02]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] uuid:[0x00][0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] discovery service start hdl:1, end hdl:2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] sample ssapc discovery services cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] uuid_len = 2, last_hdl = 0x0002, idx = 7
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] cur_hdl:[0x0001ffff], last_hdl:[0x0002]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] task[130] complete, err_code:[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] task[0x82] complete, err_code = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] ssapc handle msg type:0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] sample ssapc discovery service cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] op_code:0x04, type:0x01, uuid.len:0, err_code:0x00
+[bs21_ws73_ros2-2] discovery character cbk complete in
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] [internal_discovery_services] op_code:0x04, type:0x01, uuid.len:0, err_code:0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] tl done err_code:[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] ssapc handle msg type:2
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] sample ssapc discovery service cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] [ssap client] ssapc_write_req, conn_id:0 data_len:4
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] ssapc write req conn_id:0, hdl:1, data len:4
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] ssapc write req addr:0x3c:**:**:**:0x4e:0x33
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] handle = 0x01, type = 0x00, len = 4
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] [ssapc write_value_req]data_type = 0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] task create tl connection tl->status = 0x2, tl->mask = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] write_data_len = 4, data_len = 4, mtu = 295
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] need wait for response
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.850] [TIMRE_ADD][STACK_TIMER] TIMER=0xa0001130, TIME=12000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] ssap check type by opcode trans->op:0x0e
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] tl task[8] trans done
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] tl trans done trans->op:[0x0e]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] [TIMER_DEL][STACK_TIMER] TIMER=0xa0001130
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] [write rsp]hdl[0x0001], data_type[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] ssapc write rsp op_code[0x0e], control_code[0x03], value_len[7]
+[bs21_ws73_ros2-2] ssapc write rsp handle:1
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] task[8] complete, err_code:[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] task[0x08] complete, err_code = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] [write_req_complete]err_code:0x00
+[bs21_ws73_ros2-2] [sle write_req_complete_cbk]conn_id:0, err_code:0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] tl done err_code:[0x00]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] ssapc handle msg type:5
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] sample ssapc write cfm cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] ssapc read req conn_id:0, hdl:1, type:0
+
+[nearlink_robot_node-1] [INFO] [1520599455.450516387] [nearlink_robot]: recv ws73 keycode 0x67
+[nearlink_robot_node-1] [INFO] [1520599469.713003727] [nearlink_robot]: recv ws73 keycode 0x67
+[nearlink_robot_node-1] [INFO] [1520599470.612993769] [nearlink_robot]: recv ws73 keycode 0x67
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] ssapc read req addr:0x3c:**:**:**:0x4e:0x33
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] handle = 0x01, type = 0x00
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.874] need wait for response
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.875] [TIMRE_ADD][STACK_TIMER] TIMER=0xa00011e0, TIME=12000
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.899] ssap check type by opcode trans->op:0x09
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.899] tl trans done trans->op:[0x09]
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.900] [TIMER_DEL][STACK_TIMER] TIMER=0xa00011e0
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.900] op_code[0x09], control_code[0x03], data_len[4]
+[bs21_ws73_ros2-2] ssapc read rsp handle:0, data len:4
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.900] ssapc handle msg type:4
+[bs21_ws73_ros2-2] [2018-03-09 12:41:42.900] sample ssapc read cfm cbk success
+[bs21_ws73_ros2-2] [2018-03-09 12:44:15.275] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:44:15.275] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:44:15.275] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x52 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:1
+[bs21_ws73_ros2-2] [2018-03-09 12:44:15.450] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:44:15.450] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:44:15.450] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x00 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:0
+[bs21_ws73_ros2-2] [sle ws73] nearlink_mq attr mq_curmsgs 0 mq_maxmsg 10
+[bs21_ws73_ros2-2] [2018-03-09 12:44:29.512] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:44:29.512] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:44:29.512] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x52 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:1
+[bs21_ws73_ros2-2] [2018-03-09 12:44:29.712] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:44:29.712] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:44:29.712] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x00 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:0
+[bs21_ws73_ros2-2] [sle ws73] nearlink_mq attr mq_curmsgs 0 mq_maxmsg 10
+[bs21_ws73_ros2-2] [2018-03-09 12:44:30.400] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:44:30.400] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:44:30.400] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x52 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:1
+[bs21_ws73_ros2-2] [2018-03-09 12:44:30.612] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:44:30.612] ssapc handle msg type:8
+[bs21_ws73_ros2-2] [2018-03-09 12:44:30.612] sample ssapc notification cbk success
+[bs21_ws73_ros2-2] [sle ws73] sle_rcu_notification_cb ok
+[bs21_ws73_ros2-2] [sle ws73] sle rcu recive notification
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.kind = [1]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.special_key = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.reversed = [0]
+[bs21_ws73_ros2-2] [sle ws73] recv_usb_hid_rcu_keyboard.key = 0x00 0x00 0x00 0x00 0x00 0x00
+[bs21_ws73_ros2-2] code:0x67,value:0
+[bs21_ws73_ros2-2] [sle ws73] nearlink_mq attr mq_curmsgs 0 mq_maxmsg 10
+[bs21_ws73_ros2-2] [2018-03-09 12:44:31.775] op_code[0x0f], control_code[0x03], data_len[13]
+[bs21_ws73_ros2-2] [2018-03-09 12:44:31.775] ssapc handle msg type:8
+[nearlink_robot_node-1] [INFO] [1520599471.938074520] [nearlink_robot]: recv ws73 keycode 0x67
\ No newline at end of file
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/SLE_OSPP_Server.c b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/SLE_OSPP_Server.c
new file mode 100644
index 0000000000000000000000000000000000000000..c81bf10fb4727d1bbab3d50670c282f8d8ba9c0a
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/SLE_OSPP_Server.c
@@ -0,0 +1,783 @@
+#include "securec.h" // 安全C库,提供安全的字符串和内存操作函数
+#include "errcode.h" // 错误码定义,提供错误码的定义和处理函数
+#include "osal_addr.h" // OS抽象层地址管理,提供地址相关的操作函数
+#include "sle_common.h" // SLE通用定义,包含SLE协议的通用数据结构和宏定义
+#include "sle_errcode.h" // SLE错误码定义,提供SLE协议的错误码定义和处理函数
+#include "sle_ssap_server.h" // SLE SSAP服务端,提供SSAP服务端的实现和接口
+#include "sle_connection_manager.h" // SLE连接管理,提供连接管理的实现和接口
+#include "sle_device_discovery.h" // SLE设备发现,提供设备发现的实现和接口
+#include "../inc/SLE_OSPP_Server_adv.h" // SLE LED Server 广播,提供LED Server的广播相关函数
+#include "../inc/SLE_OSPP_Server.h" // SLE LED Server,提供LED Server的主要功能实现
+
+#include "cmsis_os2.h" // CMSIS-RTOS v2 API,提供RTOS的API接口
+#include "debug_print.h" // 调试打印,提供调试信息的打印函数
+#include "soc_osal.h" // SOC OS抽象层,提供SOC相关的操作函数
+#include "app_init.h" // 应用初始化,提供应用初始化相关的函数
+#include "common_def.h" // 通用定义,包含通用的数据结构和宏定义
+#include "i2c.h" // I2C接口,提供I2C通信的实现和接口
+#include "osal_debug.h" // OS抽象层调试,提供调试相关的操作函数
+#include "cmsis_os2.h" // CMSIS-RTOS v2 API,提供RTOS的API接口(重复包含)
+
+#include "adc.h"
+#include "adc_porting.h"
+
+// 这两个头文件顺序不能更改
+#include "pinctrl.h" // 引脚控制相关的头文件
+#include "gpio.h" // GPIO操作相关的头文件
+
+// chuan'gan
+#include "../inc/eulercar_control.h" // 小车控制,提供小车控制相关的函数
+#include "../inc/shake.h"
+#include "../inc/button.h"
+
+#define OCTET_BIT_LEN 8 // 八位字节长度
+#define UUID_LEN_2 2 // UUID 长度为 2 字节
+// 定义左摇杆引脚
+#define LEFT_JOYSTICK_X_PIN 9
+#define LEFT_JOYSTICK_Y_PIN 8
+#define LEFT_JOYSTICK_Z_PIN 14
+// 定义右摇杆引脚
+#define RIGHT_JOYSTICK_X_PIN 10
+#define RIGHT_JOYSTICK_Y_PIN 7
+#define RIGHT_JOYSTICK_Z_PIN 6
+// 定义ADC通道
+#define LEFT_JOYSTICK_X_Channel 1
+#define LEFT_JOYSTICK_Y_Channel 3 //2
+#define RIGHT_JOYSTICK_X_Channel 0
+#define RIGHT_JOYSTICK_Y_Channel 3
+
+#define ADC_AUTO_SAMPLE_TEST_TIMES 500
+#define FILTER_WINDOW_SIZE 10 // 定义滤波窗口大小
+
+#define ADC_TASK_STACK_SIZE 0x1000
+#define ADC_TASK_PRIO (osPriority_t)(15)
+/**
+ * @brief 将数据编码为小端格式的 2 字节
+ * @param _ptr 指向目标存储位置的指针
+ * @param data 要编码的数据
+ */
+#define encode2byte_little(_ptr, data) \
+ do \
+ { \
+ *(uint8_t *)((_ptr) + 1) = (uint8_t)((data) >> 8); \
+ *(uint8_t *)(_ptr) = (uint8_t)(data); \
+ } while (0)
+
+/* SLE 服务应用 UUID 示例 */
+static char g_sle_uuid_app_uuid[UUID_LEN_2] = {0x0, 0x0};
+/* 服务属性值示例 */
+static char g_sle_property_value[OCTET_BIT_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+/* SLE 连接 ID */
+uint16_t g_conn_id = 0;
+/* SLE 服务 ID */
+uint8_t g_server_id = 0;
+/* SLE 服务句柄 */
+uint16_t g_service_handle = 0;
+/* SLE 通知属性句柄 */
+uint16_t g_property_handle = 0;
+
+// 初始化摇杆引脚
+void Joystick_Init(void)
+{
+ // 配置左摇杆Z轴引脚为GPIO模式并设置为输入
+ uapi_pin_set_mode(LEFT_JOYSTICK_Z_PIN, HAL_PIO_FUNC_GPIO);
+ uapi_gpio_set_dir(LEFT_JOYSTICK_Z_PIN, GPIO_DIRECTION_INPUT);
+ uapi_pin_set_pull(LEFT_JOYSTICK_Z_PIN, PIN_PULL_TYPE_DOWN);
+
+ // 配置右摇杆Z轴引脚为GPIO模式并设置为输入
+ uapi_pin_set_mode(RIGHT_JOYSTICK_Z_PIN, HAL_PIO_FUNC_GPIO);
+ uapi_gpio_set_dir(RIGHT_JOYSTICK_Z_PIN, GPIO_DIRECTION_INPUT);
+ uapi_pin_set_pull(RIGHT_JOYSTICK_Z_PIN, PIN_PULL_TYPE_DOWN);
+}
+
+gpio_level_t Left_Joystick_Read_Z(void)
+{
+ return uapi_gpio_get_val(LEFT_JOYSTICK_Z_PIN);
+}
+
+// typedef struct
+// {
+// int xStatus; // 0: 暂停, 1: 左转, 2: 右转
+// int yStatus; // 0: 暂停, 1: 前进, 2: 后退
+// int lastXStatus; // 上次的X轴状态
+// int lastYStatus; // 上次的Y轴状态
+// } JoystickStatus;
+
+// void updateJoystickStatus(JoystickStatus *joystick, uint16_t xValue, uint16_t yValue)
+// {
+// // 更新X轴状态
+// if (xValue < 1000)
+// {
+// joystick->xStatus = 1; // 左转
+// printf("X轴左推\n");
+// }
+// else if (xValue > 2000)
+// {
+// joystick->xStatus = 2; // 右转
+// printf("X轴右推\n");
+// }
+// else
+// {
+// joystick->xStatus = 0; // 暂停
+// }
+
+// // 更新Y轴状态
+// if (yValue < 1000)
+// {
+// joystick->yStatus = 1; // 前进
+// printf("Y轴上推\n");
+// }
+// else if (yValue > 2000)
+// {
+// joystick->yStatus = 2; // 后退
+// printf("Y轴下推\n");
+// }
+// else
+// {
+// joystick->yStatus = 0; // 暂停
+// }
+
+// // 处理X轴状态变化
+// if (joystick->xStatus != joystick->lastXStatus)
+// {
+// if (joystick->xStatus == 1)
+// {
+// eulercar_control_left();
+// }
+// else if (joystick->xStatus == 2)
+// {
+// eulercar_control_right();
+// }
+// joystick->lastXStatus = joystick->xStatus;
+// }
+
+// // 处理Y轴状态变化
+// if (joystick->yStatus != joystick->lastYStatus)
+// {
+// if (joystick->yStatus == 1)
+// {
+// eulercar_control_forward();
+// }
+// else if (joystick->yStatus == 2)
+// {
+// eulercar_control_backward();
+// }
+// joystick->lastYStatus = joystick->yStatus;
+// }
+
+// // 检查是否需要暂停
+// if (joystick->xStatus == 0 && joystick->yStatus == 0 &&
+// (joystick->lastXStatus != 0 || joystick->lastYStatus != 0))
+// {
+// eulercar_control_stop();
+// joystick->lastXStatus = 0;
+// joystick->lastYStatus = 0;
+// }
+// }
+// void test_adc_callback(uint8_t ch, uint32_t *buffer, uint32_t length, bool *next)
+// {
+// UNUSED(next); // 未使用的参数
+
+// static JoystickStatus leftJoystick = {0, 0, -1, -1};
+// static JoystickStatus rightJoystick = {0, 0, -1, -1};
+
+// uint16_t value = buffer[length - 1];
+// printf("channel: %d, Filtered voltage: %dmv\n", ch, value);
+
+// if (ch == LEFT_JOYSTICK_X_Channel)
+// {
+// updateJoystickStatus(&leftJoystick, value, leftJoystick.yStatus);
+// }
+// else if (ch == LEFT_JOYSTICK_Y_Channel)
+// {
+// updateJoystickStatus(&leftJoystick, leftJoystick.xStatus, value);
+// }
+// else if (ch == RIGHT_JOYSTICK_X_Channel)
+// {
+// updateJoystickStatus(&rightJoystick, value, rightJoystick.yStatus);
+// }
+// else if (ch == RIGHT_JOYSTICK_Y_Channel)
+// {
+// updateJoystickStatus(&rightJoystick, rightJoystick.xStatus, value);
+// }
+// }
+// typedef struct
+// {
+// int xStatus; // 0: 暂停, 1: 左转, 2: 右转
+// int lastXStatus; // 上次的X轴状态
+// } JoystickStatus;
+
+// void updateJoystickStatus(JoystickStatus *joystick, uint16_t xValue, int joystickType)
+// {
+// // 更新X轴状态
+// if (xValue < 1000)
+// {
+// joystick->xStatus = 1; // 左转
+// printf("X轴左推\n");
+// }
+// else if (xValue > 2000)
+// {
+// joystick->xStatus = 2; // 右转
+// printf("X轴右推\n");
+// }
+// else
+// {
+// joystick->xStatus = 0; // 暂停
+// }
+
+// // 处理X轴状态变化
+// if (joystick->xStatus != joystick->lastXStatus)
+// {
+// if (joystickType == 0) // 左摇杆
+// {
+// if (joystick->xStatus == 1)
+// {
+// eulercar_control_left();
+// }
+// else if (joystick->xStatus == 2)
+// {
+// eulercar_control_right();
+// }
+// }
+// else if (joystickType == 1) // 右摇杆
+// {
+// if (joystick->xStatus == 1)
+// {
+// eulercar_control_forward();
+// }
+// else if (joystick->xStatus == 2)
+// {
+// eulercar_control_backward();
+// }
+// }
+// joystick->lastXStatus = joystick->xStatus;
+// }
+
+// // 检查是否需要暂停
+// if (joystick->xStatus == 0 && joystick->lastXStatus != 0)
+// {
+// eulercar_control_stop();
+// joystick->lastXStatus = 0;
+// }
+// }
+
+// void test_adc_callback_X(uint8_t ch, uint32_t *buffer, uint32_t length, bool *next)
+// {
+// UNUSED(next); // 未使用的参数
+
+// // static JoystickStatus leftJoystick = {0, -1};
+
+// uint16_t value = buffer[length - 1];
+// printf("channel: %d, Filtered voltage: %dmv\n", ch, value);
+
+// if (ch == LEFT_JOYSTICK_X_Channel)
+// {
+// // updateJoystickStatus(&leftJoystick, value, 0); // 左摇杆
+// // // 更新X轴状态
+// if (value < 1000)
+// {
+// printf("X轴左推\n");
+// eulercar_control_left();
+// }
+// else if (value > 2000)
+// {
+// printf("X轴右推\n");
+// eulercar_control_right();
+// }
+// else
+// {
+// eulercar_control_stop();
+// }
+// }
+// // else if (ch == RIGHT_JOYSTICK_X_Channel)
+// // {
+// // updateJoystickStatus(&rightJoystick, value, 1); // 右摇杆
+// // }
+// }
+
+#define ACTION 1
+#define NONE 0
+
+int sum;
+int num;
+int fil_buffer = 0;
+
+int j = 1;
+int *num_buff;
+
+int stop_x =0;
+int stop_y = 0;
+int stop = 1;
+
+void test_adc_callback_X(uint8_t ch, uint32_t *buffer, uint32_t length, bool *next)
+{
+ UNUSED(next); // 未使用的参数
+ // static JoystickStatus rightJoystick = {0, -1};
+ sum = 0;
+ num = 0;
+ if (ch == LEFT_JOYSTICK_X_Channel)
+ {
+ for (uint32_t i = 0; i < length; i++)
+ {
+
+ // 打印ADC通道和电压值
+ if(length > 2)
+ {
+ if((buffer[i] < 1500 || buffer[i] > 1900) && buffer[i] != 0)
+ {
+ sum += buffer[i];
+ num +=1;
+ // osal_printk("[IRQ]channel: %d, voltage: %dmv\r\n", ch, buffer[i]);
+ }
+ }
+ }
+ if(num >= (signed int)length / 2)
+ {
+ fil_buffer = sum / num;
+ if(fil_buffer < 1)
+ {
+ fil_buffer = 0;
+ }
+ }
+ else
+ {
+ printf(" -number- \n");
+ fil_buffer = 0;
+ }
+ printf("channel: %d, ---XXX-Filtered voltage: %dmv\n", ch, fil_buffer);
+ printf("length = %d\n",length);
+
+ if (fil_buffer < 1000 && fil_buffer !=0 )
+ {
+ printf("X轴左推\n");
+ eulercar_control_left();
+ stop = 0;
+ }
+ else if (fil_buffer > 2000 && fil_buffer !=0)
+ {
+ printf("X轴右推\n");
+ eulercar_control_right();
+ stop = 0;
+ }
+ else
+ {
+ // eulercar_control_stop();
+ stop_x =1;
+ }
+
+ }
+}
+
+
+void test_adc_callback_Y(uint8_t ch, uint32_t *buffer, uint32_t length, bool *next)
+{
+ UNUSED(next); // 未使用的参数
+ // static JoystickStatus rightJoystick = {0, -1};
+ sum = 0;
+ num = 0;
+ if (ch == LEFT_JOYSTICK_Y_Channel)
+ {
+ for (uint32_t i = 0; i < length; i++)
+ {
+
+ // 打印ADC通道和电压值
+ // osal_printk("[IRQ]channel: %d, voltage: %dmv\r\n", ch, buffer[i]);
+ if(length > 2)
+ {
+ if((buffer[i] < 1000 || buffer[i] > 2000) && buffer[i] != 0)
+ {
+ sum += buffer[i];
+ num +=1;
+ osal_printk("[IRQ]channel: %d, voltage: %dmv\r\n", ch, buffer[i]);
+ }
+ }
+ }
+ if(num >= (signed int)length / 2)
+ {
+ fil_buffer = sum / num;
+ if(fil_buffer < 1)
+ {
+ fil_buffer = 0;
+ }
+ }
+ else
+ {
+ printf(" -number- \n");
+ fil_buffer = 0;
+ }
+ printf("channel: %d, ---YYY--Filtered voltage: %dmv\n", ch, fil_buffer);
+ printf("length = %d\n",length);
+
+
+
+ if (fil_buffer < 1000 && fil_buffer !=0 )
+ {
+ printf("Y轴上推\n");
+ eulercar_control_forward();
+ stop = 0;
+ }
+ else if (fil_buffer > 2000 && fil_buffer !=0)
+ {
+ printf("Y轴下推\n");
+ eulercar_control_backward();
+ stop = 0;
+ }
+ else
+ {
+ // eulercar_control_stop();
+ stop_y =1;
+ }
+ }
+
+
+
+}
+
+
+void joystick_task(const char *arg)
+{
+ UNUSED(arg);
+ osal_printk("start adc sample test");
+ uapi_adc_init(ADC_CLOCK_500KHZ);
+ uapi_adc_power_en(AFE_SCAN_MODE_MAX_NUM, true);
+ adc_scan_config_t config = {
+ .type = 0,
+ .freq = 1,
+ };
+
+ while (1)
+ {
+ uapi_adc_auto_scan_ch_enable(LEFT_JOYSTICK_Y_Channel, config, test_adc_callback_Y);
+ uapi_adc_auto_scan_ch_disable(LEFT_JOYSTICK_Y_Channel);
+
+ uapi_adc_auto_scan_ch_enable(LEFT_JOYSTICK_X_Channel, config, test_adc_callback_X);
+ uapi_adc_auto_scan_ch_disable(LEFT_JOYSTICK_X_Channel);
+
+ if(stop == 0)
+ {
+ if(stop_x == 1 && stop_y == 1)
+ {
+
+ eulercar_control_stop();
+ printf("星闪小车停止!");
+ stop_x = 0;
+ stop_y = 0;
+ stop = 1;
+ }
+ }
+
+
+ // if (Left_Joystick_Read_Z() == 1)
+ // {
+ // eulercar_control_stop();
+ // osal_mdelay(10);
+ // }
+
+ osal_msleep(ADC_AUTO_SAMPLE_TEST_TIMES);
+ }
+}
+
+static void joystick_entry(void)
+{
+ osal_task *task_handle = NULL; // 任务句柄初始化为NULL
+ osal_kthread_lock(); // 锁定内核线程,防止任务创建过程中被打断
+ task_handle = osal_kthread_create((osal_kthread_handler)joystick_task, 0, "LedControlTask",
+ ADC_TASK_STACK_SIZE);
+ if (task_handle != NULL) // 如果任务创建成功
+ {
+ osal_kthread_set_priority(task_handle, ADC_TASK_PRIO); // 设置任务优先级
+ osal_kfree(task_handle); // 释放任务句柄内存
+ }
+ osal_kthread_unlock(); // 解锁内核线程
+}
+
+// 系统初始化函数,汇总所有初始化操作
+void Controller_System_Init(void)
+{
+ Shake_Init(); // 初始化摇动传感器
+ Joystick_Init(); // 初始化摇杆
+ Key_Init(); // 初始化按键
+}
+// SLE UUID基准数组
+static uint8_t sle_uuid_base[] = {0x37, 0xBE, 0xA8, 0x80, 0xFC, 0x70, 0x11, 0xEA,
+ 0xB7, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // UUID基准值,用于标识SLE服务
+
+/* 设置 UUID 基础部分的函数 */
+static void example_sle_uuid_set_base(sle_uuid_t *out)
+{
+ // 使用安全的 memcpy 函数将 sle_uuid_base 的内容复制到 out->uuid 中
+ // (void) 用于显式忽略 memcpy_s 的返回值
+ (void)memcpy_s(out->uuid, SLE_UUID_LEN, sle_uuid_base, SLE_UUID_LEN);
+
+ // 设置 UUID 的长度为 2 字节
+ out->len = UUID_LEN_2;
+}
+
+/* 设置 UUID 的函数 */
+static void example_sle_uuid_setu2(uint16_t u2, sle_uuid_t *out)
+{
+ // 调用函数设置 UUID 基础部分
+ example_sle_uuid_set_base(out);
+
+ // 设置 UUID 长度为 2 字节
+ out->len = UUID_LEN_2;
+
+ // 将 2 字节的 u2 编码为小端格式,并存储在 UUID 的第 14 和 15 字节位置
+ encode2byte_little(&out->uuid[14], u2);
+}
+
+// 读取请求的回调函数
+static void
+example_ssaps_read_request_cbk(uint8_t server_id,
+ uint16_t conn_id,
+ ssaps_req_read_cb_t *read_cb_para,
+ errcode_t status)
+{
+ // 打印读取请求的详细信息,包括服务器ID、连接ID、句柄、类型和状态
+ PRINT("[SLE Server] ssaps read request cbk server_id:0x%x, conn_id:0x%x, handle:0x%x, type:0x%x, status:0x%x\r\n",
+ server_id, conn_id, read_cb_para->handle, read_cb_para->type, status);
+}
+
+// 写入请求的回调函数
+static void example_ssaps_write_request_cbk(uint8_t server_id,
+ uint16_t conn_id,
+ ssaps_req_write_cb_t *write_cb_para,
+ errcode_t status)
+{
+ // 打印写入请求的详细信息,包括服务器ID、连接ID、句柄和状态
+ PRINT("[SLE Server] ssaps write request cbk server_id:0x%x, conn_id:0x%x, handle:0x%x, status:0x%x\r\n", server_id,
+ conn_id, write_cb_para->handle, status);
+
+ // 打印写入请求的数据,每个字节的索引和值
+ for (uint16_t idx = 0; idx < write_cb_para->length; idx++)
+ {
+ PRINT("[SLE Server] write request cbk[0x%x] 0x%02x\r\n", idx, write_cb_para->value[idx]);
+ }
+}
+
+/*
+MTU(Maximum Transmission Unit,最大传输单元)是指在网络通信中,单个数据包或帧的最大字节数。
+MTU的大小决定了一个数据包在网络上传输时的最大尺寸
+*/
+// MTU(最大传输单元)改变的回调函数
+static void example_ssaps_mtu_changed_cbk(uint8_t server_id,
+ uint16_t conn_id,
+ ssap_exchange_info_t *mtu_size,
+ errcode_t status)
+{
+ // 打印MTU改变的详细信息,包括服务器ID、连接ID、MTU大小和状态
+ PRINT("[SLE Server] ssaps mtu changed cbk server_id:0x%x, conn_id:0x%x, mtu_size:0x%x, status:0x%x\r\n", server_id,
+ conn_id, mtu_size->mtu_size, status);
+}
+
+// 服务启动的回调函数
+static void example_ssaps_start_service_cbk(uint8_t server_id, uint16_t handle, errcode_t status)
+{
+ // 打印服务启动的详细信息,包括服务器ID、句柄和状态
+ PRINT("[SLE Server] start service cbk server_id:0x%x, handle:0x%x, status:0x%x\r\n", server_id, handle, status);
+}
+
+// 注册所有的SSAPS回调函数
+static errcode_t example_sle_ssaps_register_cbks(void)
+{
+ ssaps_callbacks_t ssaps_cbk = {0}; // 初始化回调函数结构体
+ ssaps_cbk.start_service_cb = example_ssaps_start_service_cbk; // 注册服务启动回调函数
+ ssaps_cbk.mtu_changed_cb = example_ssaps_mtu_changed_cbk; // 注册MTU改变回调函数
+ ssaps_cbk.read_request_cb = example_ssaps_read_request_cbk; // 注册读取请求回调函数
+ ssaps_cbk.write_request_cb = example_ssaps_write_request_cbk; // 注册写入请求回调函数
+ return ssaps_register_callbacks(&ssaps_cbk); // 注册所有回调函数并返回状态
+}
+
+/* 添加 SLE 服务 */
+static errcode_t example_sle_server_service_add(void)
+{
+ sle_uuid_t service_uuid = {0}; // 初始化服务 UUID
+
+ // 设置服务 UUID
+ example_sle_uuid_setu2(SLE_UUID_SERVER_SERVICE, &service_uuid);
+
+ // 同步添加服务
+ ssaps_add_service_sync(g_server_id, &service_uuid, true, &g_service_handle);
+
+ // 打印调试信息,表示服务添加成功
+ PRINT("[SLE Server] sle uuid add service service_handle: %u\r\n", g_service_handle);
+
+ return ERRCODE_SUCC; // 返回成功错误码
+}
+
+static errcode_t example_sle_server_property_add(void)
+{
+ ssaps_property_info_t property = {0}; // 初始化属性信息结构体
+ ssaps_desc_info_t descriptor = {0}; // 初始化描述符信息结构体
+ uint8_t ntf_value[] = {0x01, 0x0}; // 通知值
+
+ // 设置属性的权限为可读和可写
+ property.permissions = SSAP_PERMISSION_READ | SSAP_PERMISSION_WRITE;
+ // 设置属性的 UUID
+ example_sle_uuid_setu2(SLE_UUID_SERVER_PROPERTY, &property.uuid);
+ // 为属性值分配内存
+ osal_vmalloc(sizeof(g_sle_property_value));
+
+ // 将全局属性值复制到属性的值中
+ memcpy_s(property.value, sizeof(g_sle_property_value), g_sle_property_value, sizeof(g_sle_property_value));
+
+ // 同步添加属性
+ ssaps_add_property_sync(g_server_id, g_service_handle, &property, &g_property_handle);
+ // 打印调试信息,表示属性添加成功
+ PRINT("[SLE Server] sle uuid add property property_handle: %u\r\n", g_property_handle);
+
+ // 设置描述符的权限为可读和可写
+ descriptor.permissions = SSAP_PERMISSION_READ | SSAP_PERMISSION_WRITE;
+ // 为描述符值分配内存
+ osal_vmalloc(sizeof(ntf_value));
+
+ // 将通知值复制到描述符的值中
+ memcpy_s(descriptor.value, sizeof(ntf_value), ntf_value, sizeof(ntf_value));
+
+ // 同步添加描述符
+ ssaps_add_descriptor_sync(g_server_id, g_service_handle, g_property_handle, &descriptor);
+
+ // 释放已分配的属性和描述符内存
+ osal_vfree(property.value);
+ osal_vfree(descriptor.value);
+
+ return ERRCODE_SUCC; // 返回成功错误码
+}
+
+/* 添加 SLE 服务器 */
+static errcode_t example_sle_server_add(void)
+{
+ /*
+ UUID(Universally Unique Identifier,通用唯一标识符)是一种用于标识信息的标准。UUID 的目的是在分布式系统中使得所有元素都能有一个唯一的标识符,而不需要中央协调。
+ 0.app uuid
+ 1.服务(Service)uuid
+ 2.特性(Characteristic)uuid
+ 3.属性(Property)uuid
+ */
+
+ sle_uuid_t app_uuid = {0}; // 初始化应用 UUID
+
+ PRINT("[SLE Server] sle uuid add service in\r\n"); // 打印调试信息,表示开始添加服务
+ app_uuid.len = sizeof(g_sle_uuid_app_uuid); // 设置 UUID 长度
+ memcpy_s(app_uuid.uuid, app_uuid.len, g_sle_uuid_app_uuid, sizeof(g_sle_uuid_app_uuid));
+
+ // 注册服务器
+ ssaps_register_server(&app_uuid, &g_server_id);
+ // 添加服务
+ example_sle_server_service_add();
+ // 添加属性
+ example_sle_server_property_add();
+ // 启动服务
+ ssaps_start_service(g_server_id, g_service_handle);
+ // 打印调试信息,表示服务添加完成
+ PRINT("[SLE Server] sle uuid add service out\r\n");
+ return ERRCODE_SUCC; // 返回成功错误码
+}
+
+typedef void (*sle_connect_state_changed_callback)(uint16_t conn_id, const sle_addr_t *addr,
+ sle_acb_state_t conn_state, sle_pair_state_t pair_state, sle_disc_reason_t disc_reason);
+
+// 连接状态改变的回调函数
+static void example_sle_connect_state_changed_cbk(uint16_t conn_id,
+ const sle_addr_t *addr,
+ sle_acb_state_t conn_state,
+ sle_pair_state_t pair_state,
+ sle_disc_reason_t disc_reason)
+{
+ // 打印连接状态改变的详细信息,包括连接ID、连接状态、配对状态和断开原因
+ PRINT(
+ "[SLE Server] connect state changed conn_id:0x%02x, conn_state:0x%x, pair_state:0x%x, \
+ disc_reason:0x%x\r\n",
+ conn_id, conn_state, pair_state, disc_reason);
+ // 打印连接设备的地址
+ PRINT("[SLE Server] connect state changed addr:%02x:**:**:**:%02x:%02x\r\n", addr->addr[0], addr->addr[4],
+ addr->addr[5]);
+ g_conn_id = conn_id; // 更新全局连接ID
+ Vibration_ConnChange();
+}
+
+// 配对完成的回调函数
+static void example_sle_pair_complete_cbk(uint16_t conn_id, const sle_addr_t *addr, errcode_t status)
+{
+ // 打印配对完成的详细信息,包括连接ID和状态
+ PRINT("[SLE Server] pair complete conn_id:0x%02x, status:0x%x\r\n", conn_id, status);
+ // 打印配对设备的地址
+ PRINT("[SLE Server] pair complete addr:%02x:%02x:%02x:%02x:%02x:%02x\r\n", addr->addr[0], addr->addr[4], addr->addr[5]);
+
+ if (status == ERRCODE_SUCC) // 如果配对成功
+ {
+ joystick_entry();
+ }
+}
+
+// 注册连接相关的回调函数/
+static errcode_t example_sle_conn_register_cbks(void)
+{
+ // 初始化连接回调函数结构体
+ sle_connection_callbacks_t conn_cbks = {0};
+ // 注册连接状态改变回调函数
+ conn_cbks.connect_state_changed_cb = example_sle_connect_state_changed_cbk;
+ // 注册配对完成回调函数
+ conn_cbks.pair_complete_cb = example_sle_pair_complete_cbk;
+ // 注册所有连接回调函数并返回状态
+
+ return sle_connection_register_callbacks(&conn_cbks);
+}
+
+static int example_sle_ospp_server_task(const char *arg)
+{
+ unused(arg);
+ Controller_System_Init(); // 摇杆系统初始化(摇杆、震动马达、按键)
+ Vibration_PowerOn(); // 上电震动
+ (void)osal_msleep(4999); // 延时5s,等待SLE初始化完毕
+ PRINT("[SLE Server] try enable.\r\n");
+
+ /* 使能SLE */
+ enable_sle();
+ /*注册连接管理回调函数 */
+ example_sle_conn_register_cbks();
+ /* 注册 SSAP server 回调函数 */
+ example_sle_ssaps_register_cbks();
+ /* 注册Server, 添加Service和property, 启动Service */
+ example_sle_server_add();
+ /* 设置设备公开,并公开设备 */
+ example_sle_server_adv_init();
+
+ PRINT("[SLE Server] init ok\r\n");
+
+ return 0;
+}
+
+// 定义任务优先级
+#define SLE_OSPP_SER_TASK_PRIO 24
+// 定义任务堆栈大小
+#define SLE_OSPP_SER_STACK_SIZE 0x2000
+
+// 静态函数,创建并配置一个内核线程
+static void example_sle_ospp_server_entry(void)
+{
+ osal_task *task_handle = NULL; // 定义一个指向 osal_task 类型的指针,并初始化为 NULL
+ osal_kthread_lock(); // 锁定内核线程,防止在创建任务期间发生竞态条件
+
+ // 创建一个新的内核线程
+ // 参数包括:
+ // - 任务处理函数,类型转换为 osal_kthread_handler
+ // - 传递给任务处理函数的数据,这里传递的是 0
+ // - 任务名称
+ // - 任务堆栈大小
+ task_handle = osal_kthread_create((osal_kthread_handler)example_sle_ospp_server_task, 0, "SLEOSPPServerTask",
+ SLE_OSPP_SER_STACK_SIZE);
+
+ // 检查任务是否成功创建(task_handle 不为 NULL)
+ if (task_handle != NULL)
+ {
+ // LiteOS中,任务优先级的范围通常是从0到31(或0到30),其中0表示最高优先级,31(或30)表示最低优先级。优先级数值越小,任务的优先级越高,调度器会优先执行优先级较高的任务。
+ // 设置任务的优先级为 SLE_LED_SER_TASK_PRIO
+ osal_kthread_set_priority(task_handle, SLE_OSPP_SER_TASK_PRIO);
+ osal_kfree(task_handle); // 释放任务句柄
+ }
+ osal_kthread_unlock(); // 解锁内核线程,允许其他线程继续执行
+}
+
+/* Run the example_sle_led_server_entry. */
+app_run(example_sle_ospp_server_entry);
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/SLE_OSPP_Server.c.bak2 b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/SLE_OSPP_Server.c.bak2
new file mode 100644
index 0000000000000000000000000000000000000000..53c45f9036eeb5e5bf7f31249c824ebd270710e3
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/SLE_OSPP_Server.c.bak2
@@ -0,0 +1,521 @@
+#include "securec.h" // 安全C库,提供安全的字符串和内存操作函数
+#include "errcode.h" // 错误码定义,提供错误码的定义和处理函数
+#include "osal_addr.h" // OS抽象层地址管理,提供地址相关的操作函数
+#include "sle_common.h" // SLE通用定义,包含SLE协议的通用数据结构和宏定义
+#include "sle_errcode.h" // SLE错误码定义,提供SLE协议的错误码定义和处理函数
+#include "sle_ssap_server.h" // SLE SSAP服务端,提供SSAP服务端的实现和接口
+#include "sle_connection_manager.h" // SLE连接管理,提供连接管理的实现和接口
+#include "sle_device_discovery.h" // SLE设备发现,提供设备发现的实现和接口
+#include "../inc/SLE_OSPP_Server_adv.h" // SLE LED Server 广播,提供LED Server的广播相关函数
+#include "../inc/SLE_OSPP_Server.h" // SLE LED Server,提供LED Server的主要功能实现
+
+#include "cmsis_os2.h" // CMSIS-RTOS v2 API,提供RTOS的API接口
+#include "debug_print.h" // 调试打印,提供调试信息的打印函数
+#include "soc_osal.h" // SOC OS抽象层,提供SOC相关的操作函数
+#include "app_init.h" // 应用初始化,提供应用初始化相关的函数
+#include "common_def.h" // 通用定义,包含通用的数据结构和宏定义
+#include "i2c.h" // I2C接口,提供I2C通信的实现和接口
+#include "osal_debug.h" // OS抽象层调试,提供调试相关的操作函数
+#include "cmsis_os2.h" // CMSIS-RTOS v2 API,提供RTOS的API接口(重复包含)
+#include "watchdog.h"
+#include "adc.h"
+#include "adc_porting.h"
+
+// 这两个头文件顺序不能更改
+#include "pinctrl.h" // 引脚控制相关的头文件
+#include "gpio.h" // GPIO操作相关的头文件
+
+// chuan'gan
+#include "../inc/eulercar_control.h" // 小车控制,提供小车控制相关的函数
+#include "../inc/shake.h"
+#include "../inc/button.h"
+
+#define OCTET_BIT_LEN 8 // 八位字节长度
+#define UUID_LEN_2 2 // UUID 长度为 2 字节
+
+#define LEFT_JOYSTICK_X_PIN 9
+#define LEFT_JOYSTICK_Y_PIN 8
+#define LEFT_JOYSTICK_Z_PIN 14
+// 定义右摇杆引脚
+#define RIGHT_JOYSTICK_X_PIN 10
+#define RIGHT_JOYSTICK_Y_PIN 7
+#define RIGHT_JOYSTICK_Z_PIN 6
+// 定义ADC通道
+#define LEFT_JOYSTICK_X_Channel 1
+#define LEFT_JOYSTICK_Y_Channel 2
+#define RIGHT_JOYSTICK_X_Channel 3
+#define RIGHT_JOYSTICK_Y_Channel 0
+
+#define ADC_AUTO_SAMPLE_TEST_TIMES 100
+#define FILTER_WINDOW_SIZE 10 // 定义滤波窗口大小
+
+#define ADC_TASK_STACK_SIZE 0x1000
+#define ADC_TASK_PRIO (osPriority_t)(15)
+/**
+ * @brief 将数据编码为小端格式的 2 字节
+ * @param _ptr 指向目标存储位置的指针
+ * @param data 要编码的数据
+ */
+#define encode2byte_little(_ptr, data) \
+ do \
+ { \
+ *(uint8_t *)((_ptr) + 1) = (uint8_t)((data) >> 8); \
+ *(uint8_t *)(_ptr) = (uint8_t)(data); \
+ } while (0)
+
+/* SLE 服务应用 UUID 示例 */
+static char g_sle_uuid_app_uuid[UUID_LEN_2] = {0x0, 0x0};
+/* 服务属性值示例 */
+static char g_sle_property_value[OCTET_BIT_LEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+/* SLE 连接 ID */
+uint16_t g_conn_id = 0;
+/* SLE 服务 ID */
+uint8_t g_server_id = 0;
+/* SLE 服务句柄 */
+uint16_t g_service_handle = 0;
+/* SLE 通知属性句柄 */
+uint16_t g_property_handle = 0;
+
+// 初始化摇杆引脚
+void Joystick_Init(void)
+{
+ // 配置左摇杆Z轴引脚为GPIO模式并设置为输入
+ uapi_pin_set_mode(LEFT_JOYSTICK_Z_PIN, HAL_PIO_FUNC_GPIO);
+ uapi_gpio_set_dir(LEFT_JOYSTICK_Z_PIN, GPIO_DIRECTION_INPUT);
+ uapi_pin_set_pull(LEFT_JOYSTICK_Z_PIN, PIN_PULL_TYPE_DOWN);
+
+ // 配置右摇杆Z轴引脚为GPIO模式并设置为输入
+ uapi_pin_set_mode(RIGHT_JOYSTICK_Z_PIN, HAL_PIO_FUNC_GPIO);
+ uapi_gpio_set_dir(RIGHT_JOYSTICK_Z_PIN, GPIO_DIRECTION_INPUT);
+ uapi_pin_set_pull(RIGHT_JOYSTICK_Z_PIN, PIN_PULL_TYPE_DOWN);
+}
+
+// 全局变量,用于存储LED的状态
+static int g_ledState = 0;
+
+// GPIO中断回调函数,当按钮被按下时调用
+static void gpio_callback_func(pin_t pin, uintptr_t param)
+{
+ UNUSED(param); // 未使用的参数
+ if (pin == LEFT_JOYSTICK_Z_PIN)
+ {
+ g_ledState = 1;
+ eulercar_control_stop();
+ printf("中断信号:%d\n", g_ledState);
+ }
+ else if (pin == LEFT_BUTTON_PIN)
+ {
+ g_ledState = 2;
+ eulercar_control_forward();
+ printf("中断信号:%d\n", g_ledState);
+ }
+ else if (pin == RIGHT_BUTTON_PIN)
+ {
+ g_ledState = 3;
+ eulercar_control_backward();
+ printf("中断信号:%d\n", g_ledState);
+ }
+ else if (pin == LEFT_TOGGLE_PIN)
+ {
+ g_ledState = 4;
+ eulercar_control_left();
+ printf("中断信号:%d\n", g_ledState);
+ }
+ else if (pin == RIGHT_TOGGLE_PIN)
+ {
+ g_ledState = 5;
+ eulercar_control_right();
+ printf("中断信号:%d\n", g_ledState);
+ }
+ printf("Button pressed.\r\n"); // 打印按钮按下的信息
+}
+
+// 按钮任务函数
+static void *button_task(const char *arg)
+{
+ unused(arg); // 未使用的参数
+
+ // 注册GPIO中断回调函数,当按钮引脚检测到下降沿时触发中断
+ // 注册GPIO中断服务函数
+ errcode_t ret0 = uapi_gpio_register_isr_func(14, GPIO_INTERRUPT_RISING_EDGE, gpio_callback_func);
+ if (ret0 != 0)
+ {
+ printf("Failed to register ISR for 14\n");
+ }
+ errcode_t ret1 = uapi_gpio_register_isr_func(LEFT_BUTTON_PIN, GPIO_INTERRUPT_RISING_EDGE, gpio_callback_func);
+ if (ret1 != 0)
+ {
+ printf("Failed to register ISR for LEFT_BUTTON_PIN\n");
+ }
+
+ errcode_t ret2 = uapi_gpio_register_isr_func(RIGHT_BUTTON_PIN, GPIO_INTERRUPT_RISING_EDGE, gpio_callback_func);
+ if (ret2 != 0)
+ {
+ printf("Failed to register ISR for RIGHT_BUTTON_PIN\n");
+ }
+
+ errcode_t ret3 = uapi_gpio_register_isr_func(LEFT_TOGGLE_PIN, GPIO_INTERRUPT_FALLING_EDGE, gpio_callback_func);
+ if (ret3 != 0)
+ {
+ printf("Failed to register ISR for LEFT_TOGGLE_PIN\n");
+ }
+
+ errcode_t ret4 = uapi_gpio_register_isr_func(RIGHT_TOGGLE_PIN, GPIO_INTERRUPT_RISING_EDGE, gpio_callback_func);
+ if (ret4 != 0)
+ {
+ printf("Failed to register ISR for RIGHT_TOGGLE_PIN\n");
+ }
+
+ // 无限循环,持续执行任务
+ while (1)
+ {
+ uapi_watchdog_kick(); // 喂狗,防止程序出现异常系统挂死
+ }
+ return NULL; // 返回NULL表示任务结束
+}
+// void joystick_task(const char *arg)
+// {
+// UNUSED(arg);
+
+// while (1)
+// {
+
+// gpio_level_t z_button_state = uapi_gpio_get_val(LEFT_JOYSTICK_Z_PIN);
+// gpio_level_t left_button_state = uapi_gpio_get_val(LEFT_BUTTON_PIN);
+// gpio_level_t right_button_state = uapi_gpio_get_val(RIGHT_BUTTON_PIN);
+// gpio_level_t left_toggle_state = uapi_gpio_get_val(LEFT_TOGGLE_PIN);
+// gpio_level_t right_toggle_state = uapi_gpio_get_val(LEFT_TOGGLE_PIN);
+
+// printf("z Button State: %d\n", z_button_state);
+// printf("Left Button State: %d\n", left_button_state);
+// printf("Right Button State: %d\n", right_button_state);
+// printf("Left Toggle State: %d\n", left_toggle_state);
+// printf("Right Toggle State: %d\n", right_toggle_state);
+// osal_mdelay(1000);
+// // if (uapi_gpio_get_val(LEFT_JOYSTICK_Z_PIN) == 1)
+// // {
+// // eulercar_control_stop();
+// // }
+// // else if (uapi_gpio_get_val(LEFT_BUTTON_PIN) == 1)
+// // {
+// // eulercar_control_forward();
+// // }
+// // else if (uapi_gpio_get_val(RIGHT_BUTTON_PIN) == 1)
+// // {
+// // eulercar_control_backward();
+// // }
+// // else if (uapi_gpio_get_val(LEFT_TOGGLE_PIN) == 1)
+// // {
+// // eulercar_control_left();
+// // }
+// // else if (uapi_gpio_get_val(RIGHT_TOGGLE_PIN) == 1)
+// // {
+// // eulercar_control_right();
+// // }
+// }
+// }
+
+static void joystick_entry(void)
+{
+ osal_task *task_handle = NULL; // 任务句柄初始化为NULL
+ osal_kthread_lock(); // 锁定内核线程,防止任务创建过程中被打断
+ task_handle = osal_kthread_create((osal_kthread_handler)button_task, 0, "LedControlTask",
+ ADC_TASK_STACK_SIZE);
+ if (task_handle != NULL) // 如果任务创建成功
+ {
+ osal_kthread_set_priority(task_handle, ADC_TASK_PRIO); // 设置任务优先级
+ osal_kfree(task_handle); // 释放任务句柄内存
+ }
+ osal_kthread_unlock(); // 解锁内核线程
+}
+
+// 系统初始化函数,汇总所有初始化操作
+void Controller_System_Init(void)
+{
+ Shake_Init(); // 初始化摇动传感器
+ Joystick_Init(); // 初始化摇杆
+ Key_Init(); // 初始化按键
+}
+// SLE UUID基准数组
+static uint8_t sle_uuid_base[] = {0x37, 0xBE, 0xA8, 0x80, 0xFC, 0x70, 0x11, 0xEA,
+ 0xB7, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // UUID基准值,用于标识SLE服务
+
+/* 设置 UUID 基础部分的函数 */
+static void example_sle_uuid_set_base(sle_uuid_t *out)
+{
+ // 使用安全的 memcpy 函数将 sle_uuid_base 的内容复制到 out->uuid 中
+ // (void) 用于显式忽略 memcpy_s 的返回值
+ (void)memcpy_s(out->uuid, SLE_UUID_LEN, sle_uuid_base, SLE_UUID_LEN);
+
+ // 设置 UUID 的长度为 2 字节
+ out->len = UUID_LEN_2;
+}
+
+/* 设置 UUID 的函数 */
+static void example_sle_uuid_setu2(uint16_t u2, sle_uuid_t *out)
+{
+ // 调用函数设置 UUID 基础部分
+ example_sle_uuid_set_base(out);
+
+ // 设置 UUID 长度为 2 字节
+ out->len = UUID_LEN_2;
+
+ // 将 2 字节的 u2 编码为小端格式,并存储在 UUID 的第 14 和 15 字节位置
+ encode2byte_little(&out->uuid[14], u2);
+}
+
+// 读取请求的回调函数
+static void
+example_ssaps_read_request_cbk(uint8_t server_id,
+ uint16_t conn_id,
+ ssaps_req_read_cb_t *read_cb_para,
+ errcode_t status)
+{
+ // 打印读取请求的详细信息,包括服务器ID、连接ID、句柄、类型和状态
+ PRINT("[SLE Server] ssaps read request cbk server_id:0x%x, conn_id:0x%x, handle:0x%x, type:0x%x, status:0x%x\r\n",
+ server_id, conn_id, read_cb_para->handle, read_cb_para->type, status);
+}
+
+// 写入请求的回调函数
+static void example_ssaps_write_request_cbk(uint8_t server_id,
+ uint16_t conn_id,
+ ssaps_req_write_cb_t *write_cb_para,
+ errcode_t status)
+{
+ // 打印写入请求的详细信息,包括服务器ID、连接ID、句柄和状态
+ PRINT("[SLE Server] ssaps write request cbk server_id:0x%x, conn_id:0x%x, handle:0x%x, status:0x%x\r\n", server_id,
+ conn_id, write_cb_para->handle, status);
+
+ // 打印写入请求的数据,每个字节的索引和值
+ for (uint16_t idx = 0; idx < write_cb_para->length; idx++)
+ {
+ PRINT("[SLE Server] write request cbk[0x%x] 0x%02x\r\n", idx, write_cb_para->value[idx]);
+ }
+}
+
+/*
+MTU(Maximum Transmission Unit,最大传输单元)是指在网络通信中,单个数据包或帧的最大字节数。
+MTU的大小决定了一个数据包在网络上传输时的最大尺寸
+*/
+// MTU(最大传输单元)改变的回调函数
+static void example_ssaps_mtu_changed_cbk(uint8_t server_id,
+ uint16_t conn_id,
+ ssap_exchange_info_t *mtu_size,
+ errcode_t status)
+{
+ // 打印MTU改变的详细信息,包括服务器ID、连接ID、MTU大小和状态
+ PRINT("[SLE Server] ssaps mtu changed cbk server_id:0x%x, conn_id:0x%x, mtu_size:0x%x, status:0x%x\r\n", server_id,
+ conn_id, mtu_size->mtu_size, status);
+}
+
+// 服务启动的回调函数
+static void example_ssaps_start_service_cbk(uint8_t server_id, uint16_t handle, errcode_t status)
+{
+ // 打印服务启动的详细信息,包括服务器ID、句柄和状态
+ PRINT("[SLE Server] start service cbk server_id:0x%x, handle:0x%x, status:0x%x\r\n", server_id, handle, status);
+}
+
+// 注册所有的SSAPS回调函数
+static errcode_t example_sle_ssaps_register_cbks(void)
+{
+ ssaps_callbacks_t ssaps_cbk = {0}; // 初始化回调函数结构体
+ ssaps_cbk.start_service_cb = example_ssaps_start_service_cbk; // 注册服务启动回调函数
+ ssaps_cbk.mtu_changed_cb = example_ssaps_mtu_changed_cbk; // 注册MTU改变回调函数
+ ssaps_cbk.read_request_cb = example_ssaps_read_request_cbk; // 注册读取请求回调函数
+ ssaps_cbk.write_request_cb = example_ssaps_write_request_cbk; // 注册写入请求回调函数
+ return ssaps_register_callbacks(&ssaps_cbk); // 注册所有回调函数并返回状态
+}
+
+/* 添加 SLE 服务 */
+static errcode_t example_sle_server_service_add(void)
+{
+ sle_uuid_t service_uuid = {0}; // 初始化服务 UUID
+
+ // 设置服务 UUID
+ example_sle_uuid_setu2(SLE_UUID_SERVER_SERVICE, &service_uuid);
+
+ // 同步添加服务
+ ssaps_add_service_sync(g_server_id, &service_uuid, true, &g_service_handle);
+
+ // 打印调试信息,表示服务添加成功
+ PRINT("[SLE Server] sle uuid add service service_handle: %u\r\n", g_service_handle);
+
+ return ERRCODE_SUCC; // 返回成功错误码
+}
+
+static errcode_t example_sle_server_property_add(void)
+{
+ ssaps_property_info_t property = {0}; // 初始化属性信息结构体
+ ssaps_desc_info_t descriptor = {0}; // 初始化描述符信息结构体
+ uint8_t ntf_value[] = {0x01, 0x0}; // 通知值
+
+ // 设置属性的权限为可读和可写
+ property.permissions = SSAP_PERMISSION_READ | SSAP_PERMISSION_WRITE;
+ // 设置属性的 UUID
+ example_sle_uuid_setu2(SLE_UUID_SERVER_PROPERTY, &property.uuid);
+ // 为属性值分配内存
+ osal_vmalloc(sizeof(g_sle_property_value));
+
+ // 将全局属性值复制到属性的值中
+ memcpy_s(property.value, sizeof(g_sle_property_value), g_sle_property_value, sizeof(g_sle_property_value));
+
+ // 同步添加属性
+ ssaps_add_property_sync(g_server_id, g_service_handle, &property, &g_property_handle);
+ // 打印调试信息,表示属性添加成功
+ PRINT("[SLE Server] sle uuid add property property_handle: %u\r\n", g_property_handle);
+
+ // 设置描述符的权限为可读和可写
+ descriptor.permissions = SSAP_PERMISSION_READ | SSAP_PERMISSION_WRITE;
+ // 为描述符值分配内存
+ osal_vmalloc(sizeof(ntf_value));
+
+ // 将通知值复制到描述符的值中
+ memcpy_s(descriptor.value, sizeof(ntf_value), ntf_value, sizeof(ntf_value));
+
+ // 同步添加描述符
+ ssaps_add_descriptor_sync(g_server_id, g_service_handle, g_property_handle, &descriptor);
+
+ // 释放已分配的属性和描述符内存
+ osal_vfree(property.value);
+ osal_vfree(descriptor.value);
+
+ return ERRCODE_SUCC; // 返回成功错误码
+}
+
+/* 添加 SLE 服务器 */
+static errcode_t example_sle_server_add(void)
+{
+ /*
+ UUID(Universally Unique Identifier,通用唯一标识符)是一种用于标识信息的标准。UUID 的目的是在分布式系统中使得所有元素都能有一个唯一的标识符,而不需要中央协调。
+ 0.app uuid
+ 1.服务(Service)uuid
+ 2.特性(Characteristic)uuid
+ 3.属性(Property)uuid
+ */
+
+ sle_uuid_t app_uuid = {0}; // 初始化应用 UUID
+
+ PRINT("[SLE Server] sle uuid add service in\r\n"); // 打印调试信息,表示开始添加服务
+ app_uuid.len = sizeof(g_sle_uuid_app_uuid); // 设置 UUID 长度
+ memcpy_s(app_uuid.uuid, app_uuid.len, g_sle_uuid_app_uuid, sizeof(g_sle_uuid_app_uuid));
+
+ // 注册服务器
+ ssaps_register_server(&app_uuid, &g_server_id);
+ // 添加服务
+ example_sle_server_service_add();
+ // 添加属性
+ example_sle_server_property_add();
+ // 启动服务
+ ssaps_start_service(g_server_id, g_service_handle);
+ // 打印调试信息,表示服务添加完成
+ PRINT("[SLE Server] sle uuid add service out\r\n");
+ return ERRCODE_SUCC; // 返回成功错误码
+}
+
+typedef void (*sle_connect_state_changed_callback)(uint16_t conn_id, const sle_addr_t *addr,
+ sle_acb_state_t conn_state, sle_pair_state_t pair_state, sle_disc_reason_t disc_reason);
+
+// 连接状态改变的回调函数
+static void example_sle_connect_state_changed_cbk(uint16_t conn_id,
+ const sle_addr_t *addr,
+ sle_acb_state_t conn_state,
+ sle_pair_state_t pair_state,
+ sle_disc_reason_t disc_reason)
+{
+ // 打印连接状态改变的详细信息,包括连接ID、连接状态、配对状态和断开原因
+ PRINT(
+ "[SLE Server] connect state changed conn_id:0x%02x, conn_state:0x%x, pair_state:0x%x, \
+ disc_reason:0x%x\r\n",
+ conn_id, conn_state, pair_state, disc_reason);
+ // 打印连接设备的地址
+ PRINT("[SLE Server] connect state changed addr:%02x:**:**:**:%02x:%02x\r\n", addr->addr[0], addr->addr[4],
+ addr->addr[5]);
+ g_conn_id = conn_id; // 更新全局连接ID
+ Vibration_ConnChange();
+}
+
+// 配对完成的回调函数
+static void example_sle_pair_complete_cbk(uint16_t conn_id, const sle_addr_t *addr, errcode_t status)
+{
+ // 打印配对完成的详细信息,包括连接ID和状态
+ PRINT("[SLE Server] pair complete conn_id:0x%02x, status:0x%x\r\n", conn_id, status);
+ // 打印配对设备的地址
+ PRINT("[SLE Server] pair complete addr:%02x:%02x:%02x:%02x:%02x:%02x\r\n", addr->addr[0], addr->addr[4], addr->addr[5]);
+
+ if (status == ERRCODE_SUCC) // 如果配对成功
+ {
+ joystick_entry();
+ }
+}
+
+// 注册连接相关的回调函数/
+static errcode_t example_sle_conn_register_cbks(void)
+{
+ // 初始化连接回调函数结构体
+ sle_connection_callbacks_t conn_cbks = {0};
+ // 注册连接状态改变回调函数
+ conn_cbks.connect_state_changed_cb = example_sle_connect_state_changed_cbk;
+ // 注册配对完成回调函数
+ conn_cbks.pair_complete_cb = example_sle_pair_complete_cbk;
+ // 注册所有连接回调函数并返回状态
+
+ return sle_connection_register_callbacks(&conn_cbks);
+}
+
+static int example_sle_ospp_server_task(const char *arg)
+{
+ unused(arg);
+ Controller_System_Init(); // 摇杆系统初始化(摇杆、震动马达、按键)
+ Vibration_PowerOn(); // 上电震动
+ (void)osal_msleep(4999); // 延时5s,等待SLE初始化完毕
+ PRINT("[SLE Server] try enable.\r\n");
+
+ /* 使能SLE */
+ enable_sle();
+ /*注册连接管理回调函数 */
+ example_sle_conn_register_cbks();
+ /* 注册 SSAP server 回调函数 */
+ example_sle_ssaps_register_cbks();
+ /* 注册Server, 添加Service和property, 启动Service */
+ example_sle_server_add();
+ /* 设置设备公开,并公开设备 */
+ example_sle_server_adv_init();
+
+ PRINT("[SLE Server] init ok\r\n");
+
+ return 0;
+}
+
+// 定义任务优先级
+#define SLE_OSPP_SER_TASK_PRIO 24
+// 定义任务堆栈大小
+#define SLE_OSPP_SER_STACK_SIZE 0x2000
+
+// 静态函数,创建并配置一个内核线程
+static void example_sle_ospp_server_entry(void)
+{
+ osal_task *task_handle = NULL; // 定义一个指向 osal_task 类型的指针,并初始化为 NULL
+ osal_kthread_lock(); // 锁定内核线程,防止在创建任务期间发生竞态条件
+
+ // 创建一个新的内核线程
+ // 参数包括:
+ // - 任务处理函数,类型转换为 osal_kthread_handler
+ // - 传递给任务处理函数的数据,这里传递的是 0
+ // - 任务名称
+ // - 任务堆栈大小
+ task_handle = osal_kthread_create((osal_kthread_handler)example_sle_ospp_server_task, 0, "SLEOSPPServerTask",
+ SLE_OSPP_SER_STACK_SIZE);
+
+ // 检查任务是否成功创建(task_handle 不为 NULL)
+ if (task_handle != NULL)
+ {
+ // LiteOS中,任务优先级的范围通常是从0到31(或0到30),其中0表示最高优先级,31(或30)表示最低优先级。优先级数值越小,任务的优先级越高,调度器会优先执行优先级较高的任务。
+ // 设置任务的优先级为 SLE_LED_SER_TASK_PRIO
+ osal_kthread_set_priority(task_handle, SLE_OSPP_SER_TASK_PRIO);
+ osal_kfree(task_handle); // 释放任务句柄
+ }
+ osal_kthread_unlock(); // 解锁内核线程,允许其他线程继续执行
+}
+
+/* Run the example_sle_led_server_entry. */
+app_run(example_sle_ospp_server_entry);
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/SLE_OSPP_Server_adv.c b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/SLE_OSPP_Server_adv.c
new file mode 100644
index 0000000000000000000000000000000000000000..4246e1c6b214aa6f9a3615e6b2ee81de55bbfb09
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/SLE_OSPP_Server_adv.c
@@ -0,0 +1,292 @@
+/*
+# Copyright (C) 2024 HiHope Open Source Organization .
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+ */
+#include "securec.h" // 安全C库,用于安全的内存操作
+#include "errcode.h" // 错误码定义
+#include "osal_addr.h" // OS抽象层地址操作
+#include "sle_common.h" // SLE通用定义
+#include "sle_device_discovery.h" // SLE设备发现功能
+#include "sle_errcode.h" // SLE错误码定义
+#include "../inc/SLE_OSPP_Server_adv.h" // SLE LED服务器广播头文件
+
+#include "cmsis_os2.h" // CMSIS-RTOS API
+#include "debug_print.h" // 调试打印功能
+
+/* sle device name */
+#define NAME_MAX_LENGTH 16 // 设备名称的最大长度
+/* 连接调度间隔12.5ms,单位125us */
+#define SLE_CONN_INTV_MIN_DEFAULT 0x64 // 最小连接间隔默认值
+/* 连接调度间隔12.5ms,单位125us */
+#define SLE_CONN_INTV_MAX_DEFAULT 0x64 // 最大连接间隔默认值
+/* 连接调度间隔25ms,单位125us */
+#define SLE_ADV_INTERVAL_MIN_DEFAULT 0xC8 // 最小广播间隔默认值
+/* 连接调度间隔25ms,单位125us */
+#define SLE_ADV_INTERVAL_MAX_DEFAULT 0xC8 // 最大广播间隔默认值
+/* 超时时间5000ms,单位10ms */
+#define SLE_CONN_SUPERVISION_TIMEOUT_DEFAULT 0x1F4 // 连接监督超时默认值
+/* 超时时间4990ms,单位10ms */
+#define SLE_CONN_MAX_LATENCY 0x1F3 // 最大连接延迟默认值
+/* 广播发送功率 */
+#define SLE_ADV_TX_POWER 10 // 广播发送功率
+/* 广播ID */
+#define SLE_ADV_HANDLE_DEFAULT 1 // 广播句柄默认值
+/* 最大广播数据长度 */
+#define SLE_ADV_DATA_LEN_MAX 251 // 最大广播数据长度
+/* 广播名称 */
+static uint8_t sle_local_name[NAME_MAX_LENGTH] = {'S', 'L', 'E', '_', 'O', 'S', 'P', 'P', '_',
+ 'S', 'E', 'R', 'V', 'E', 'R', '\0'}; // 本地设备名称
+
+// 设置广播本地名称
+static uint16_t example_sle_set_adv_local_name(uint8_t *adv_data, uint16_t max_len)
+{
+ errno_t ret = -1; // 错误码初始化为-1
+ uint8_t index = 0; // 广播数据索引初始化为0
+
+ uint8_t *local_name = sle_local_name; // 获取本地设备名称
+ uint8_t local_name_len = (uint8_t)strlen((char *)local_name); // 获取本地设备名称长度
+ for (uint8_t i = 0; i < local_name_len; i++)
+ {
+ PRINT("[SLE Adv] local_name[%d] = 0x%02x\r\n", i, local_name[i]); // 打印本地设备名称的每个字符
+ }
+
+ adv_data[index++] = local_name_len + 1; // 设置广播数据长度
+ adv_data[index++] = SLE_ADV_DATA_TYPE_COMPLETE_LOCAL_NAME; // 设置广播数据类型为完整本地名称
+ ret = memcpy_s(&adv_data[index], max_len - index, local_name, local_name_len); // 复制本地名称到广播数据中
+ if (ret != EOK)
+ { // 检查复制是否成功
+ PRINT("[SLE Adv] memcpy fail\r\n"); // 打印复制失败信息
+ return 0; // 返回0表示失败
+ }
+ return (uint16_t)index + local_name_len; // 返回广播数据的总长度
+}
+
+// 设置广播数据
+static uint16_t example_sle_set_adv_data(uint8_t *adv_data)
+{
+ size_t len = 0; // 数据长度初始化为0
+ uint16_t idx = 0; // 广播数据索引初始化为0
+ errno_t ret = 0; // 错误码初始化为0
+
+ len = sizeof(struct sle_adv_common_value); // 获取通用广播数据结构体的长度
+ struct sle_adv_common_value adv_disc_level = {
+ .length = len - 1, // 设置数据长度
+ .type = SLE_ADV_DATA_TYPE_DISCOVERY_LEVEL, // 设置数据类型为发现级别
+ .value = SLE_ANNOUNCE_LEVEL_NORMAL, // 设置数据值为正常级别
+ };
+ ret = memcpy_s(&adv_data[idx], SLE_ADV_DATA_LEN_MAX - idx, &adv_disc_level, len); // 复制发现级别数据到广播数据中
+ if (ret != EOK)
+ { // 检查复制是否成功
+ PRINT("[SLE Adv] adv_disc_level memcpy fail\r\n"); // 打印复制失败信息
+ return 0; // 返回0表示失败
+ }
+ idx += len; // 更新广播数据索引
+
+ len = sizeof(struct sle_adv_common_value); // 获取通用广播数据结构体的长度
+ struct sle_adv_common_value adv_access_mode = {
+ .length = len - 1, // 设置数据长度
+ .type = SLE_ADV_DATA_TYPE_ACCESS_MODE, // 设置数据类型为访问模式
+ .value = 0, // 设置数据值为0
+ };
+ ret = memcpy_s(&adv_data[idx], SLE_ADV_DATA_LEN_MAX - idx, &adv_access_mode, len); // 复制访问模式数据到广播数据中
+ if (ret != EOK)
+ { // 检查复制是否成功
+ PRINT("[SLE Adv] memcpy fail\r\n"); // 打印复制失败信息
+ return 0; // 返回0表示失败
+ }
+ idx += len; // 更新广播数据索引
+ return idx; // 返回广播数据的总长度
+}
+
+// 设置扫描响应数据
+static uint16_t example_sle_set_scan_response_data(uint8_t *scan_rsp_data)
+{
+ uint16_t idx = 0; // 扫描响应数据索引初始化为0
+ errno_t ret = -1; // 错误码初始化为-1
+ size_t scan_rsp_data_len = sizeof(struct sle_adv_common_value); // 获取通用广播数据结构体的长度
+
+ struct sle_adv_common_value tx_power_level = {
+ .length = scan_rsp_data_len - 1, // 设置数据长度
+ .type = SLE_ADV_DATA_TYPE_TX_POWER_LEVEL, // 设置数据类型为发送功率级别
+ .value = SLE_ADV_TX_POWER, // 设置数据值为广播发送功率
+ };
+ ret = memcpy_s(scan_rsp_data, SLE_ADV_DATA_LEN_MAX, &tx_power_level, scan_rsp_data_len); // 复制发送功率级别数据到扫描响应数据中
+ if (ret != EOK)
+ { // 检查复制是否成功
+ PRINT("[SLE Adv] sle scan response data memcpy fail\r\n"); // 打印复制失败信息
+ return 0; // 返回0表示失败
+ }
+ idx += scan_rsp_data_len; // 更新扫描响应数据索引
+
+ /* set local name */
+ idx += example_sle_set_adv_local_name(&scan_rsp_data[idx], SLE_ADV_DATA_LEN_MAX - idx); // 设置本地名称到扫描响应数据中
+ return idx; // 返回扫描响应数据的总长度
+}
+
+static uint8_t g_sle_local_addr[SLE_ADDR_LEN] = {0x3c, 0x4a, 0x83, 0x2f, 0x4e, 0x33}; // 要遥控器设备地址
+
+// 设置本地设备地址
+static void example_sle_set_addr(void)
+{
+ uint8_t *addr = g_sle_local_addr; // 获取本地设备地址
+
+ sle_addr_t sle_addr = {0}; // 初始化SLE地址结构体
+ sle_addr.type = 0; // 设置地址类型为0
+ if (memcpy_s(sle_addr.addr, SLE_ADDR_LEN, addr, SLE_ADDR_LEN) != EOK)
+ { // 复制本地设备地址到SLE地址结构体中
+ PRINT("[SLE Adv] addr memcpy fail \r\n"); // 打印复制失败信息
+ }
+
+ if (sle_set_local_addr(&sle_addr) == ERRCODE_SUCC)
+ { // 设置本地设备地址并检查是否成功
+ PRINT("[SLE Adv] set sle addr SUCC \r\n"); // 打印设置成功信息
+ }
+}
+
+static uint8_t g_local_device_name[] = {'s', 'l', 'e', '_', 'l', 'e', 'd', '_', 's', 'e', 'r', 'v', 'e', 'r'}; // 本地设备名称
+
+// 设置本地设备名称
+static void example_sle_set_name(void)
+{
+ errcode_t ret = ERRCODE_SUCC; // 错误码初始化为成功
+ ret = sle_set_local_name(g_local_device_name, sizeof(g_local_device_name)); // 设置本地设备名称并获取返回码
+ if (ret != ERRCODE_SUCC)
+ { // 检查设置是否成功
+ PRINT("[SLE Adv] set local name fail, ret:%x\r\n", ret); // 打印设置失败信息
+ }
+}
+
+// 设置默认的广播参数
+static errcode_t example_sle_set_default_announce_param(void)
+{
+ sle_announce_param_t param = {0}; // 初始化广播参数结构体
+ param.announce_mode = SLE_ANNOUNCE_MODE_CONNECTABLE_SCANABLE; // 设置广播模式为可连接可扫描
+ param.announce_handle = SLE_ADV_HANDLE_DEFAULT; // 设置广播句柄为默认值
+ param.announce_gt_role = SLE_ANNOUNCE_ROLE_T_CAN_NEGO; // 设置广播角色为可协商
+ param.announce_level = SLE_ANNOUNCE_LEVEL_NORMAL; // 设置广播级别为正常
+ param.announce_channel_map = SLE_ADV_CHANNEL_MAP_DEFAULT; // 设置广播信道映射为默认值
+ param.announce_interval_min = SLE_ADV_INTERVAL_MIN_DEFAULT; // 设置最小广播间隔为默认值
+ param.announce_interval_max = SLE_ADV_INTERVAL_MAX_DEFAULT; // 设置最大广播间隔为默认值
+ param.conn_interval_min = SLE_CONN_INTV_MIN_DEFAULT; // 设置最小连接间隔为默认值
+ param.conn_interval_max = SLE_CONN_INTV_MAX_DEFAULT; // 设置最大连接间隔为默认值
+ param.conn_max_latency = SLE_CONN_MAX_LATENCY; // 设置最大连接延迟为默认值
+ param.conn_supervision_timeout = SLE_CONN_SUPERVISION_TIMEOUT_DEFAULT; // 设置连接监督超时为默认值
+
+ if (memcpy_s(param.own_addr.addr, SLE_ADDR_LEN, g_sle_local_addr, SLE_ADDR_LEN) != EOK)
+ { // 复制本地设备地址到广播参数中
+ PRINT("[SLE Adv] set sle adv param addr memcpy fail\r\n"); // 打印复制失败信息
+ return ERRCODE_MEMCPY; // 返回内存复制错误码
+ }
+
+ return sle_set_announce_param(param.announce_handle, ¶m); // 设置广播参数并返回状态码
+}
+
+// 设置默认的广播数据
+static errcode_t example_sle_set_default_announce_data(void)
+{
+ errcode_t ret = ERRCODE_FAIL; // 错误码初始化为失败
+ uint8_t announce_data_len = 0; // 广播数据长度初始化为0
+ uint8_t seek_data_len = 0; // 扫描响应数据长度初始化为0
+ sle_announce_data_t data = {0}; // 初始化广播数据结构体
+ uint8_t adv_handle = SLE_ADV_HANDLE_DEFAULT; // 广播句柄初始化为默认值
+ uint8_t announce_data[SLE_ADV_DATA_LEN_MAX] = {0}; // 初始化广播数据数组
+ uint8_t seek_rsp_data[SLE_ADV_DATA_LEN_MAX] = {0}; // 初始化扫描响应数据数组
+
+ PRINT("[SLE Adv] set adv data default\r\n"); // 打印设置默认广播数据信息
+ announce_data_len = example_sle_set_adv_data(announce_data); // 设置广播数据并获取长度
+ data.announce_data = announce_data; // 设置广播数据
+ data.announce_data_len = announce_data_len; // 设置广播数据长度
+
+ seek_data_len = example_sle_set_scan_response_data(seek_rsp_data); // 设置扫描响应数据并获取长度
+ data.seek_rsp_data = seek_rsp_data; // 设置扫描响应数据
+ data.seek_rsp_data_len = seek_data_len; // 设置扫描响应数据长度
+
+ ret = sle_set_announce_data(adv_handle, &data); // 设置广播数据并获取返回码
+ if (ret == ERRCODE_SUCC)
+ { // 检查设置是否成功
+ PRINT("[SLE Adv] set announce data success."); // 打印设置成功信息
+ }
+ else
+ {
+ PRINT("[SLE Adv] set adv param fail."); // 打印设置失败信息
+ }
+ return ERRCODE_SUCC; // 返回成功码
+}
+
+// 广播启用回调函数
+void example_sle_announce_enable_cbk(uint32_t announce_id, errcode_t status)
+{
+ PRINT("[SLE Adv] sle announce enable id:%02x, state:%02x\r\n", announce_id, status); // 打印广播启用信息
+}
+
+// 广播禁用回调函数
+void example_sle_announce_disable_cbk(uint32_t announce_id, errcode_t status)
+{
+ PRINT("[SLE Adv] sle announce disable id:%02x, state:%02x\r\n", announce_id, status); // 打印广播禁用信息
+}
+
+// 广播终止回调函数
+void example_sle_announce_terminal_cbk(uint32_t announce_id)
+{
+ PRINT("[SLE Adv] sle announce terminal id:%02x\r\n", announce_id); // 打印广播终止信息
+}
+
+// SLE启用回调函数
+void example_sle_enable_cbk(errcode_t status)
+{
+ PRINT("[SLE Adv] sle enable status:%02x\r\n", status); // 打印SLE启用状态信息
+}
+
+// 注册广播相关的回调函数
+// 注册SLE广播相关的回调函数
+void example_sle_announce_register_cbks(void)
+{
+ sle_announce_seek_callbacks_t seek_cbks = {0}; // 初始化广播回调函数结构体
+
+ // 注册广播启用回调函数
+ seek_cbks.announce_enable_cb = example_sle_announce_enable_cbk;
+
+ // 注册广播禁用回调函数
+ seek_cbks.announce_disable_cb = example_sle_announce_disable_cbk;
+
+ // 注册广播终止回调函数
+ seek_cbks.announce_terminal_cb = example_sle_announce_terminal_cbk;
+
+ // 注册SLE启用回调函数
+ seek_cbks.sle_enable_cb = example_sle_enable_cbk;
+
+ // 注册所有广播回调函数
+ sle_announce_seek_register_callbacks(&seek_cbks);
+}
+
+// 初始化SLE服务器广播的函数
+errcode_t example_sle_server_adv_init(void)
+{
+ PRINT("[SLE Adv] example_sle_server_adv_init in\r\n"); // 打印初始化开始信息
+
+ example_sle_announce_register_cbks(); // 注册广播相关的回调函数
+
+ example_sle_set_default_announce_param(); // 设置默认的广播参数
+
+ example_sle_set_default_announce_data(); // 设置默认的广播数据
+
+ example_sle_set_addr(); // 设置设备地址
+
+ example_sle_set_name(); // 设置设备名称
+
+ sle_start_announce(SLE_ADV_HANDLE_DEFAULT); // 启动广播
+
+ PRINT("[SLE Adv] example_sle_server_adv_init out\r\n"); // 打印初始化结束信息
+
+ return ERRCODE_SUCC; // 返回成功码
+}
\ No newline at end of file
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/button.c b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/button.c
new file mode 100644
index 0000000000000000000000000000000000000000..d07ee44ca507563ca1bfc772e7ede7a01534ca2f
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/button.c
@@ -0,0 +1,31 @@
+#include "../inc/button.h"
+
+// 定义按键引脚
+#define LEFT_BUTTON_PIN 2
+#define RIGHT_BUTTON_PIN 4
+#define LEFT_TOGGLE_PIN 5
+#define RIGHT_TOGGLE_PIN 3
+
+#define DEBOUNCE_DELAY 5 // 消抖延时,单位为毫秒
+#define DEBOUNCE_READS 5 // 消抖读取次数
+
+// 初始化按键引脚
+void Key_Init(void)
+{
+ // 配置左按钮引脚为GPIO模式并设置为输入
+ uapi_pin_set_mode(LEFT_BUTTON_PIN, HAL_PIO_FUNC_GPIO);
+ gpio_select_core(LEFT_BUTTON_PIN, CORES_APPS_CORE);
+ uapi_gpio_set_dir(LEFT_BUTTON_PIN, GPIO_DIRECTION_INPUT);
+
+ // 配置右按钮引脚为GPIO模式并设置为输入
+ uapi_pin_set_mode(RIGHT_BUTTON_PIN, HAL_PIO_FUNC_GPIO);
+ uapi_gpio_set_dir(RIGHT_BUTTON_PIN, GPIO_DIRECTION_INPUT);
+
+ // 配置左切换开关引脚为GPIO模式并设置为输入
+ uapi_pin_set_mode(LEFT_TOGGLE_PIN, HAL_PIO_FUNC_GPIO);
+ uapi_gpio_set_dir(LEFT_TOGGLE_PIN, GPIO_DIRECTION_INPUT);
+
+ // 配置右切换开关引脚为GPIO模式并设置为输入
+ uapi_pin_set_mode(RIGHT_TOGGLE_PIN, HAL_PIO_FUNC_GPIO);
+ uapi_gpio_set_dir(RIGHT_TOGGLE_PIN, GPIO_DIRECTION_INPUT);
+}
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/eulercar_control.c b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/eulercar_control.c
new file mode 100644
index 0000000000000000000000000000000000000000..f3f3115551a43696d0cbf03cb16774ad0478eb46
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/eulercar_control.c
@@ -0,0 +1,148 @@
+#include "../inc/eulercar_control.h"
+#include "debug_print.h"
+#include "sle_ssap_server.h" // SLE SSAP服务端,提供SSAP服务端的实现和接口
+#include "osal_task.h"
+#include "../inc/shake.h"
+
+extern uint16_t g_property_handle;
+extern uint16_t g_server_id;
+extern uint16_t g_conn_id;
+
+// 向上键报告
+usb_hid_rcu_keyboard_report_t EulerCarUp = {
+ .kind = 1, // 键盘报告类型
+ .special_key = 0, // 特殊按键
+ .reserve = 0, // 保留字段
+ .key = {0x52, 0x00, 0x00, 0x00, 0x00, 0x00} // 按键值数组
+};
+
+// 向下键报告
+usb_hid_rcu_keyboard_report_t EulerCarDown = {
+ .kind = 1, // 键盘报告类型
+ .special_key = 0, // 特殊按键
+ .reserve = 0, // 保留字段
+ .key = {0x51, 0x00, 0x00, 0x00, 0x00, 0x00} // 按键值数组
+};
+
+// 向左键报告
+usb_hid_rcu_keyboard_report_t EulerCarLeft = {
+ .kind = 1, // 键盘报告类型
+ .special_key = 0, // 特殊按键
+ .reserve = 0, // 保留字段
+ .key = {0x50, 0x00, 0x00, 0x00, 0x00, 0x00} // 按键值数组
+};
+
+// 向右键报告
+usb_hid_rcu_keyboard_report_t EulerCarRight = {
+ .kind = 1, // 键盘报告类型
+ .special_key = 0, // 特殊按键
+ .reserve = 0, // 保留字段
+ .key = {0x4f, 0x00, 0x00, 0x00, 0x00, 0x00} // 按键值数组
+};
+
+// 释放键报告
+usb_hid_rcu_keyboard_report_t EulerCarStop = {
+ .kind = 1, // 键盘报告类型
+ .special_key = 0, // 特殊按键
+ .reserve = 0, // 保留字段
+ .key = {0x28, 0x00, 0x00, 0x00, 0x00, 0x00} // 按键值数组
+};
+
+// 释放键报告
+usb_hid_rcu_keyboard_report_t EulerCarRelease = {
+ .kind = 1, // 键盘报告类型
+ .special_key = 0, // 特殊按键
+ .reserve = 0, // 保留字段
+ .key = {0x0, 0x00, 0x00, 0x00, 0x00, 0x00} // 按键值数组
+};
+
+// 辅助函数:发送键盘报告通知
+void send_keyboard_report(usb_hid_rcu_keyboard_report_t *report)
+{
+ ssaps_ntf_ind_t param = {0}; // 初始化通知参数结构体
+ param.handle = g_property_handle; // 设置通知的句柄
+ param.type = 0; // 设置通知类型为0
+ param.value = (uint8_t *)report; // 将键盘报告数据转换为 uint8_t 指针
+ param.value_len = sizeof(*report); // 设置通知数据的长度
+ ssaps_notify_indicate(g_server_id, g_conn_id, ¶m); // 发送通知
+}
+
+/**
+ * @brief 控制小车前进
+ *
+ * 该函数通过发送键盘报告通知来控制小车前进。首先发送前进键报告,
+ * 然后延时一段时间,再发送释放键报告。最后打印一条日志信息并延时一段时间。
+ */
+void eulercar_control_forward(void)
+{
+ send_keyboard_report(&EulerCarUp); // 发送前进键报告
+ (void)osal_msleep(PRESS_RELEASE_INTERVAL); // 延时
+ send_keyboard_report(&EulerCarRelease); // 发送释放键报告
+ Vibration_CarControl();
+ PRINT("[SLE Server] 星闪小车前进! \r\n");
+ (void)osal_msleep(LONG_PRESS_INTERVAL); // 延时,等待响应
+}
+
+/**
+ * @brief 控制小车后退
+ *
+ * 该函数通过发送键盘报告通知来控制小车后退。首先发送后退键报告,
+ * 然后延时一段时间,再发送释放键报告。最后打印一条日志信息并延时一段时间。
+ */
+void eulercar_control_backward(void)
+{
+ send_keyboard_report(&EulerCarDown); // 发送后退键报告
+ (void)osal_msleep(PRESS_RELEASE_INTERVAL); // 延时
+ send_keyboard_report(&EulerCarRelease); // 发送释放键报告
+ Vibration_CarControl();
+ PRINT("[SLE Server] 星闪小车后退! \r\n");
+ (void)osal_msleep(LONG_PRESS_INTERVAL); // 延时,等待响应
+}
+
+/**
+ * @brief 控制小车左转
+ *
+ * 该函数通过发送键盘报告通知来控制小车左转。首先发送左转键报告,
+ * 然后延时一段时间,再发送释放键报告。最后打印一条日志信息并延时一段时间。
+ */
+void eulercar_control_left(void)
+{
+ send_keyboard_report(&EulerCarLeft); // 发送左转键报告
+ (void)osal_msleep(PRESS_RELEASE_INTERVAL); // 延时
+ send_keyboard_report(&EulerCarRelease); // 发送释放键报告
+ Vibration_CarControl();
+ PRINT("[SLE Server] 星闪小车左转! \r\n");
+ (void)osal_msleep(LONG_PRESS_INTERVAL); // 延时,等待响应
+}
+
+/**
+ * @brief 控制小车右转
+ *
+ * 该函数通过发送键盘报告通知来控制小车右转。首先发送右转键报告,
+ * 然后延时一段时间,再发送释放键报告。最后打印一条日志信息并延时一段时间。
+ */
+void eulercar_control_right(void)
+{
+ send_keyboard_report(&EulerCarRight); // 发送右转键报告
+ (void)osal_msleep(PRESS_RELEASE_INTERVAL); // 延时
+ send_keyboard_report(&EulerCarRelease); // 发送释放键报告
+ Vibration_CarControl();
+ PRINT("[SLE Server] 星闪小车右转! \r\n");
+ (void)osal_msleep(LONG_PRESS_INTERVAL); // 延时,等待响应
+}
+
+/**
+ * @brief 控制小车暂停
+ *
+ * 该函数通过发送键盘报告通知来控制小车暂停。发送释放键报告,
+ * 然后打印一条日志信息并延时一段时间。
+ */
+void eulercar_control_stop(void)
+{
+ send_keyboard_report(&EulerCarStop); // 发送停止键报告
+ (void)osal_msleep(PRESS_RELEASE_INTERVAL); // 延时
+ send_keyboard_report(&EulerCarRelease); // 发送释放键报告
+ Vibration_CarControl();
+ PRINT("[SLE Server] 星闪小车暂停! \r\n");
+ (void)osal_msleep(LONG_PRESS_INTERVAL); // 延时,等待响应
+}
diff --git a/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/shake.c b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/shake.c
new file mode 100644
index 0000000000000000000000000000000000000000..7f25251c029d7dfa850f8ef94a5ca1f5960742fc
--- /dev/null
+++ b/hi-sle/RemoteController_WS63E_Source_Code/SLE_OSPP_Server/src/shake.c
@@ -0,0 +1,57 @@
+#include "../inc/shake.h"
+#include "pinctrl.h"
+#include "hal_gpio.h"
+#include "gpio.h"
+#include "tcxo.h"
+
+
+void Shake_Init(void)
+{
+ // 配置SHAKE_PIN为输出,默认不震动
+ uapi_pin_set_mode(SHAKE_PIN, HAL_PIO_FUNC_GPIO);
+ uapi_gpio_set_dir(SHAKE_PIN, GPIO_DIRECTION_OUTPUT);
+ uapi_gpio_set_val(SHAKE_PIN, GPIO_LEVEL_LOW);
+}
+
+void Shake_Start(void)
+{
+ // 设置SHAKE_PIN为高电平,启动震动马达
+ uapi_gpio_set_val(SHAKE_PIN, GPIO_LEVEL_HIGH);
+}
+
+void Shake_Stop(void)
+{
+ // 设置SHAKE_PIN为低电平,停止震动马达
+ uapi_gpio_set_val(SHAKE_PIN, GPIO_LEVEL_LOW);
+}
+
+void Shake_Buzz(unsigned int duration)
+{
+ Shake_Start();
+ uapi_tcxo_delay_ms((uint32_t)duration);// 延时指定的毫秒数
+ Shake_Stop();
+}
+
+// 开发板上电震动函数
+void Vibration_PowerOn(void)
+{
+ Shake_Buzz(VIBRATION_DURATION_POWER_ON);
+}
+
+// 星闪连接状态改变震动函数
+void Vibration_ConnChange(void)
+{
+ Shake_Buzz(VIBRATION_DURATION_CONN_CHANGE);
+}
+
+// 夹爪行程极限震动函数
+void Vibration_GripperLimit(void)
+{
+ Shake_Buzz(VIBRATION_DURATION_GRIPPER_LIMIT);
+}
+
+// 控制小车震动函数
+void Vibration_CarControl(void)
+{
+ Shake_Buzz(VIBRATION_DURATION_CAR_CONTROL);
+}
\ No newline at end of file
diff --git a/hi-sle/images/EDA1.png b/hi-sle/images/EDA1.png
new file mode 100644
index 0000000000000000000000000000000000000000..ef9a5b71df7c79513fb2e38663dee4743c48c831
Binary files /dev/null and b/hi-sle/images/EDA1.png differ
diff --git a/hi-sle/images/EDA2.png b/hi-sle/images/EDA2.png
new file mode 100644
index 0000000000000000000000000000000000000000..531b260c622499be6f0876bac9321c5688c201ac
Binary files /dev/null and b/hi-sle/images/EDA2.png differ
diff --git a/hi-sle/images/EDA3.png b/hi-sle/images/EDA3.png
new file mode 100644
index 0000000000000000000000000000000000000000..cc7d397140c89b92771edbcf94693841188438da
Binary files /dev/null and b/hi-sle/images/EDA3.png differ
diff --git a/hi-sle/images/IP5306_design.png b/hi-sle/images/IP5306_design.png
new file mode 100644
index 0000000000000000000000000000000000000000..0e46ed59dd46561aa93cacf1391068d3bf30ebfd
Binary files /dev/null and b/hi-sle/images/IP5306_design.png differ
diff --git a/hi-sle/images/IP5306_pin.png b/hi-sle/images/IP5306_pin.png
new file mode 100644
index 0000000000000000000000000000000000000000..65f3c130eb0f53fccbe61044285bcf5253347209
Binary files /dev/null and b/hi-sle/images/IP5306_pin.png differ
diff --git a/hi-sle/images/Intro1.jpg b/hi-sle/images/Intro1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..4c94d6a714bba60ccfc24b29244bd9bd6acdf8c3
Binary files /dev/null and b/hi-sle/images/Intro1.jpg differ
diff --git a/hi-sle/images/Intro2.jpg b/hi-sle/images/Intro2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..9a644f30c70bfaa9256bf819d4a481351b04a6e9
Binary files /dev/null and b/hi-sle/images/Intro2.jpg differ
diff --git a/hi-sle/images/board.png b/hi-sle/images/board.png
new file mode 100644
index 0000000000000000000000000000000000000000..e88aa9b19818fed24fad360d765ac342d345a5c6
Binary files /dev/null and b/hi-sle/images/board.png differ
diff --git a/hi-sle/images/checkout1.jpg b/hi-sle/images/checkout1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..aacc895deb8ab9566d79c9e1c6b54ec776f9fa86
Binary files /dev/null and b/hi-sle/images/checkout1.jpg differ
diff --git a/hi-sle/images/checkout2.jpg b/hi-sle/images/checkout2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..499a7bece0772ec4de55f1b2052e6d751f40983a
Binary files /dev/null and b/hi-sle/images/checkout2.jpg differ
diff --git a/hi-sle/images/checkout3.jpg b/hi-sle/images/checkout3.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..ce9199ab2f57cb8ee4f7a304ff5bb6e5538809b7
Binary files /dev/null and b/hi-sle/images/checkout3.jpg differ
diff --git a/hi-sle/images/fusion1.png b/hi-sle/images/fusion1.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa15be8c70d62e93d634a8db7292a591810f1746
Binary files /dev/null and b/hi-sle/images/fusion1.png differ
diff --git a/hi-sle/images/fusion2.png b/hi-sle/images/fusion2.png
new file mode 100644
index 0000000000000000000000000000000000000000..11af04f14c0d1b482fa52c4435c73b0f562542eb
Binary files /dev/null and b/hi-sle/images/fusion2.png differ
diff --git a/hi-sle/images/fusion3.png b/hi-sle/images/fusion3.png
new file mode 100644
index 0000000000000000000000000000000000000000..f4a336b14c5eb306338c89318ba1af47ec54d1da
Binary files /dev/null and b/hi-sle/images/fusion3.png differ
diff --git a/hi-sle/images/fusion4.png b/hi-sle/images/fusion4.png
new file mode 100644
index 0000000000000000000000000000000000000000..02b6678006bc4522feeefa66143060e39ad20894
Binary files /dev/null and b/hi-sle/images/fusion4.png differ
diff --git a/hi-sle/images/hi3061_upload.png b/hi-sle/images/hi3061_upload.png
new file mode 100644
index 0000000000000000000000000000000000000000..68fdb20364d7029df013f7db82a8481178188d0e
Binary files /dev/null and b/hi-sle/images/hi3061_upload.png differ
diff --git a/hi-sle/images/i.png b/hi-sle/images/i.png
new file mode 100644
index 0000000000000000000000000000000000000000..d9bdf30e8cc2772aece68898363e38128324f00c
Binary files /dev/null and b/hi-sle/images/i.png differ
diff --git a/hi-sle/images/logo.png b/hi-sle/images/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..d9bdf30e8cc2772aece68898363e38128324f00c
Binary files /dev/null and b/hi-sle/images/logo.png differ
diff --git a/hi-sle/images/logo2.png b/hi-sle/images/logo2.png
new file mode 100644
index 0000000000000000000000000000000000000000..c5dd5917cb5211f4239e1fcd655785367d6c7104
Binary files /dev/null and b/hi-sle/images/logo2.png differ
diff --git a/hi-sle/images/logo3.jpg b/hi-sle/images/logo3.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..329a129c9f3b487a86008a64aa05c66ed565c7ca
Binary files /dev/null and b/hi-sle/images/logo3.jpg differ
diff --git a/hi-sle/images/logo4.jpg b/hi-sle/images/logo4.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..a7a93fb8f86bc8e151cccd9e56ae50e22666246b
Binary files /dev/null and b/hi-sle/images/logo4.jpg differ
diff --git a/hi-sle/images/solder.gif b/hi-sle/images/solder.gif
new file mode 100644
index 0000000000000000000000000000000000000000..04996aacc20f9f4ec19ef0632f8926a24c378101
Binary files /dev/null and b/hi-sle/images/solder.gif differ
diff --git a/hi-sle/images/stuff.gif b/hi-sle/images/stuff.gif
new file mode 100644
index 0000000000000000000000000000000000000000..738ed22fffcadd9ba7f82c96eb9cb0ab2444264f
Binary files /dev/null and b/hi-sle/images/stuff.gif differ