diff --git a/.DS_Store b/.DS_Store index 683c4e5..ff21cdc 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/BUILD_GUIDE.md b/BUILD_GUIDE.md new file mode 100644 index 0000000..7e1bcfb --- /dev/null +++ b/BUILD_GUIDE.md @@ -0,0 +1,131 @@ +# MRobot 打包说明 + +## 问题原因 + +之前使用 `--onefile` 模式和 `--add-data` 添加 assets 导致的问题: +1. `--onefile` 将所有文件打包进 exe,运行时解压到临时目录 `sys._MEIPASS` +2. 更新代码时下载到 `exe目录/assets` +3. 但读取时从 `sys._MEIPASS/assets` 读取(每次都是打包时的原始文件) +4. 结果:更新成功但读不到新文件 + +## 解决方案:使用 `--onedir` 模式 + +### 方法一:使用提供的脚本(推荐) + +**macOS/Linux:** +```bash +./build.sh +``` + +**Windows:** +```cmd +build.bat +``` + +### 方法二:手动执行命令 + +```bash +# 清理旧文件 +rm -rf build dist *.spec + +# 打包(不要添加 --add-data) +pyinstaller MRobot.py \ + --onedir \ + --windowed \ + --icon=assets/logo/M.ico \ + --name=MRobot \ + --clean +``` + +### 创建安装程序 + +打包完成后,使用 Inno Setup 编译 `MRobot.iss` 创建安装程序。 + +## 打包模式对比 + +### `--onedir` 模式(推荐)✅ +- **优点:** + - assets 文件夹在 exe 同级目录,可以被更新覆盖 + - 更新代码库后能正确读取新文件 + - 文件结构清晰,便于调试 +- **缺点:** + - 需要分发整个文件夹(但可以用 Inno Setup 打包成单个安装程序) + +### `--onefile` 模式(不推荐)❌ +- **优点:** + - 单个 exe 文件 +- **缺点:** + - 外部资源文件无法更新(因为每次都从 exe 内部解压) + - 启动较慢(需要解压) + - 不适合需要更新资源的应用 + +## 文件结构 + +### 打包后(onedir 模式) +``` +dist/MRobot/ +├── MRobot.exe # 主程序 +├── _internal/ # PyInstaller 依赖库 +└── assets/ # 由 Inno Setup 安装时复制 + ├── logo/ + ├── User_code/ + └── mech_lib/ +``` + +### 安装后 +``` +%APPDATA%\MRobot\ # 或 {userappdata}\MRobot +├── MRobot.exe +├── _internal/ +└── assets/ # 可以被更新覆盖 + ├── logo/ + ├── User_code/ # 👈 更新代码库会更新这里 + └── mech_lib/ +``` + +## 工作原理 + +1. **首次运行:** + - 代码检测到 `exe目录/assets` 不存在 + - 从 `sys._MEIPASS/assets` 复制初始资源(如果存在) + - 但在 onedir 模式下,Inno Setup 已经安装了 assets,所以直接使用 + +2. **更新代码库:** + - 下载最新代码到 `exe目录/assets/User_code` + - 清除缓存 + - 重新读取 `exe目录/assets/User_code`(能看到新模块如 oid) + +3. **重新打开软件:** + - 直接读取 `exe目录/assets`(包含更新后的文件) + +## 注意事项 + +1. **不要使用 `--add-data "assets;assets"`** + - 这会将 assets 打包进 exe,导致无法更新 + +2. **Inno Setup 负责安装 assets** + - ISS 文件会将 assets 复制到安装目录 + - 这样 assets 就在 exe 同级目录,可以被更新 + +3. **代码已经优化** + - `CodeGenerator.get_assets_dir()` 优先使用 `exe目录/assets` + - 更新和读取使用相同路径 + - 首次运行时自动初始化(如果需要) + +## 测试步骤 + +1. 运行 `build.bat` 或 `build.sh` 打包 +2. 使用 Inno Setup 编译 `MRobot.iss` 创建安装程序 +3. 安装并运行 MRobot +4. 点击"选择项目路径",选择一个 CubeMX 项目 +5. 点击"更新代码库" +6. 检查是否能看到新的模块(如 oid) +7. 关闭软件,重新打开 +8. 再次进入项目,确认新模块仍然存在 + +## 版本更新 + +修改 `MRobot.iss` 中的版本号: +```ini +AppVersion=1.0.9 ; 更新这里 +``` diff --git a/MRobot.iss b/MRobot.iss index f2ac647..8268548 100644 --- a/MRobot.iss +++ b/MRobot.iss @@ -1,17 +1,18 @@ [Setup] AppName=MRobot -AppVersion=1.0.1 +AppVersion=1.0.8 DefaultDirName={userappdata}\MRobot DefaultGroupName=MRobot OutputDir=. OutputBaseFilename=MRobotInstaller [Files] -Source: "dist\MRobot.exe"; DestDir: "{app}"; Flags: ignoreversion +; 复制整个 dist\MRobot 文件夹(onedir 模式生成的所有文件) +Source: "dist\MRobot\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs +; 复制 assets 资源文件到安装目录(支持后续更新) Source: "assets\logo\*"; DestDir: "{app}\assets\logo"; Flags: ignoreversion recursesubdirs Source: "assets\User_code\*"; DestDir: "{app}\assets\User_code"; Flags: ignoreversion recursesubdirs Source: "assets\mech_lib\*"; DestDir: "{app}\assets\mech_lib"; Flags: ignoreversion recursesubdirs -Source: "assets\logo\M.ico"; DestDir: "{app}\assets\logo"; Flags: ignoreversion [Icons] Name: "{group}\MRobot"; Filename: "{app}\MRobot.exe"; IconFilename: "{app}\assets\logo\M.ico" diff --git a/app/__pycache__/__init__.cpython-39.pyc b/app/__pycache__/__init__.cpython-39.pyc index 9dd2ee6..121d291 100644 Binary files a/app/__pycache__/__init__.cpython-39.pyc and b/app/__pycache__/__init__.cpython-39.pyc differ diff --git a/app/__pycache__/about_interface.cpython-39.pyc b/app/__pycache__/about_interface.cpython-39.pyc index 3490f28..12e5049 100644 Binary files a/app/__pycache__/about_interface.cpython-39.pyc and b/app/__pycache__/about_interface.cpython-39.pyc differ diff --git a/app/__pycache__/ai_interface.cpython-39.pyc b/app/__pycache__/ai_interface.cpython-39.pyc index aee47f8..8ee1332 100644 Binary files a/app/__pycache__/ai_interface.cpython-39.pyc and b/app/__pycache__/ai_interface.cpython-39.pyc differ diff --git a/app/__pycache__/batch_export_dialog.cpython-39.pyc b/app/__pycache__/batch_export_dialog.cpython-39.pyc new file mode 100644 index 0000000..04dfbb6 Binary files /dev/null and b/app/__pycache__/batch_export_dialog.cpython-39.pyc differ diff --git a/app/__pycache__/category_management_dialog.cpython-39.pyc b/app/__pycache__/category_management_dialog.cpython-39.pyc new file mode 100644 index 0000000..7dc1aba Binary files /dev/null and b/app/__pycache__/category_management_dialog.cpython-39.pyc differ diff --git a/app/__pycache__/code_configuration_interface.cpython-39.pyc b/app/__pycache__/code_configuration_interface.cpython-39.pyc index 42472b8..88528d7 100644 Binary files a/app/__pycache__/code_configuration_interface.cpython-39.pyc and b/app/__pycache__/code_configuration_interface.cpython-39.pyc differ diff --git a/app/__pycache__/code_generate_interface.cpython-39.pyc b/app/__pycache__/code_generate_interface.cpython-39.pyc index e239a45..7cb682c 100644 Binary files a/app/__pycache__/code_generate_interface.cpython-39.pyc and b/app/__pycache__/code_generate_interface.cpython-39.pyc differ diff --git a/app/__pycache__/data_interface.cpython-39.pyc b/app/__pycache__/data_interface.cpython-39.pyc index 7df10bd..3ee06cd 100644 Binary files a/app/__pycache__/data_interface.cpython-39.pyc and b/app/__pycache__/data_interface.cpython-39.pyc differ diff --git a/app/__pycache__/finance_interface.cpython-39.pyc b/app/__pycache__/finance_interface.cpython-39.pyc new file mode 100644 index 0000000..aba10e8 Binary files /dev/null and b/app/__pycache__/finance_interface.cpython-39.pyc differ diff --git a/app/__pycache__/function_fit_interface.cpython-39.pyc b/app/__pycache__/function_fit_interface.cpython-39.pyc index 886cba0..827a109 100644 Binary files a/app/__pycache__/function_fit_interface.cpython-39.pyc and b/app/__pycache__/function_fit_interface.cpython-39.pyc differ diff --git a/app/__pycache__/home_interface.cpython-39.pyc b/app/__pycache__/home_interface.cpython-39.pyc index 311a744..5c30dbd 100644 Binary files a/app/__pycache__/home_interface.cpython-39.pyc and b/app/__pycache__/home_interface.cpython-39.pyc differ diff --git a/app/__pycache__/main_window.cpython-39.pyc b/app/__pycache__/main_window.cpython-39.pyc index 8e971ac..386b8f7 100644 Binary files a/app/__pycache__/main_window.cpython-39.pyc and b/app/__pycache__/main_window.cpython-39.pyc differ diff --git a/app/__pycache__/mini_tool_interface.cpython-39.pyc b/app/__pycache__/mini_tool_interface.cpython-39.pyc index 79f3a2a..624bef0 100644 Binary files a/app/__pycache__/mini_tool_interface.cpython-39.pyc and b/app/__pycache__/mini_tool_interface.cpython-39.pyc differ diff --git a/app/__pycache__/part_library_interface.cpython-39.pyc b/app/__pycache__/part_library_interface.cpython-39.pyc index 74e20b5..235b83e 100644 Binary files a/app/__pycache__/part_library_interface.cpython-39.pyc and b/app/__pycache__/part_library_interface.cpython-39.pyc differ diff --git a/app/__pycache__/serial_terminal_interface.cpython-39.pyc b/app/__pycache__/serial_terminal_interface.cpython-39.pyc index 9671994..b65c683 100644 Binary files a/app/__pycache__/serial_terminal_interface.cpython-39.pyc and b/app/__pycache__/serial_terminal_interface.cpython-39.pyc differ diff --git a/app/code_page/__pycache__/bsp_interface.cpython-39.pyc b/app/code_page/__pycache__/bsp_interface.cpython-39.pyc index 397cf95..cb8cc0e 100644 Binary files a/app/code_page/__pycache__/bsp_interface.cpython-39.pyc and b/app/code_page/__pycache__/bsp_interface.cpython-39.pyc differ diff --git a/app/data_interface.py b/app/data_interface.py index c829085..d51d327 100644 --- a/app/data_interface.py +++ b/app/data_interface.py @@ -263,14 +263,24 @@ class DataInterface(QWidget): def update_user_template(self): from app.tools.update_code import update_code + from app.tools.code_generator import CodeGenerator def info_callback(parent): + # 清除 CodeGenerator 的缓存,强制重新读取更新后的文件 + CodeGenerator._assets_dir_cache = None + CodeGenerator._assets_dir_initialized = False + CodeGenerator._template_dir_logged = False + InfoBar.success( title="更新成功", content="用户模板已更新到最新版本!", parent=parent, duration=2000 ) + + # 如果当前在代码生成页面,刷新文件列表 + if self.stacked_layout.currentWidget() == self.codegen_page: + self.show_user_code_files() def error_callback(parent, msg): InfoBar.error( @@ -287,6 +297,10 @@ class DataInterface(QWidget): file_tree = self.codegen_page.file_tree file_tree.clear() base_dir = CodeGenerator.get_assets_dir("User_code") + print(f"显示用户代码文件:base_dir = {base_dir}") + print(f"目录是否存在: {os.path.exists(base_dir)}") + if os.path.exists(base_dir): + print(f"目录内容: {os.listdir(base_dir)}") user_dir = os.path.join(self.project_path, "User") sub_dirs = ["bsp", "component", "device", "module"] diff --git a/app/tools/__pycache__/analyzing_ioc.cpython-39.pyc b/app/tools/__pycache__/analyzing_ioc.cpython-39.pyc index 0310cdc..a219040 100644 Binary files a/app/tools/__pycache__/analyzing_ioc.cpython-39.pyc and b/app/tools/__pycache__/analyzing_ioc.cpython-39.pyc differ diff --git a/app/tools/__pycache__/auto_updater.cpython-39.pyc b/app/tools/__pycache__/auto_updater.cpython-39.pyc index a67e931..007de98 100644 Binary files a/app/tools/__pycache__/auto_updater.cpython-39.pyc and b/app/tools/__pycache__/auto_updater.cpython-39.pyc differ diff --git a/app/tools/__pycache__/check_update.cpython-39.pyc b/app/tools/__pycache__/check_update.cpython-39.pyc index 8f378d9..65d4b7a 100644 Binary files a/app/tools/__pycache__/check_update.cpython-39.pyc and b/app/tools/__pycache__/check_update.cpython-39.pyc differ diff --git a/app/tools/__pycache__/code_generator.cpython-39.pyc b/app/tools/__pycache__/code_generator.cpython-39.pyc index 390ddd7..80e4181 100644 Binary files a/app/tools/__pycache__/code_generator.cpython-39.pyc and b/app/tools/__pycache__/code_generator.cpython-39.pyc differ diff --git a/app/tools/__pycache__/code_task_config.cpython-39.pyc b/app/tools/__pycache__/code_task_config.cpython-39.pyc index 6aba332..9052484 100644 Binary files a/app/tools/__pycache__/code_task_config.cpython-39.pyc and b/app/tools/__pycache__/code_task_config.cpython-39.pyc differ diff --git a/app/tools/__pycache__/finance_manager.cpython-39.pyc b/app/tools/__pycache__/finance_manager.cpython-39.pyc new file mode 100644 index 0000000..dfb545a Binary files /dev/null and b/app/tools/__pycache__/finance_manager.cpython-39.pyc differ diff --git a/app/tools/__pycache__/part_download.cpython-39.pyc b/app/tools/__pycache__/part_download.cpython-39.pyc index dc02841..81d155e 100644 Binary files a/app/tools/__pycache__/part_download.cpython-39.pyc and b/app/tools/__pycache__/part_download.cpython-39.pyc differ diff --git a/app/tools/__pycache__/update_check_thread.cpython-39.pyc b/app/tools/__pycache__/update_check_thread.cpython-39.pyc index a77f001..b46ec3c 100644 Binary files a/app/tools/__pycache__/update_check_thread.cpython-39.pyc and b/app/tools/__pycache__/update_check_thread.cpython-39.pyc differ diff --git a/app/tools/__pycache__/update_code.cpython-39.pyc b/app/tools/__pycache__/update_code.cpython-39.pyc index cc982da..f7baf68 100644 Binary files a/app/tools/__pycache__/update_code.cpython-39.pyc and b/app/tools/__pycache__/update_code.cpython-39.pyc differ diff --git a/app/tools/code_generator.py b/app/tools/code_generator.py index 5549df1..654ccbd 100644 --- a/app/tools/code_generator.py +++ b/app/tools/code_generator.py @@ -100,26 +100,41 @@ class CodeGenerator: # 打包后的环境 print("检测到打包环境") - # 优先使用sys._MEIPASS(PyInstaller的临时解包目录) - if hasattr(sys, '_MEIPASS'): + # 优先使用可执行文件所在目录(支持更新后的文件) + exe_dir = os.path.dirname(sys.executable) + exe_assets = os.path.join(exe_dir, "assets") + + # 如果exe目录下不存在assets,但_MEIPASS中有,则首次复制过去 + if not os.path.exists(exe_assets) and hasattr(sys, '_MEIPASS'): + base_path = getattr(sys, '_MEIPASS') + meipass_assets = os.path.join(base_path, "assets") + if os.path.exists(meipass_assets): + try: + import shutil + print(f"首次运行:从 {meipass_assets} 复制到 {exe_assets}") + shutil.copytree(meipass_assets, exe_assets) + print("初始资源复制成功") + except Exception as e: + print(f"复制初始资源失败: {e}") + + # 优先使用exe目录下的assets(这样可以读取更新后的文件) + if os.path.exists(exe_assets): + assets_dir = exe_assets + print(f"使用可执行文件目录: {assets_dir}") + # 后备方案:使用PyInstaller的临时解包目录 + elif hasattr(sys, '_MEIPASS'): base_path = getattr(sys, '_MEIPASS') assets_dir = os.path.join(base_path, "assets") - print(f"使用PyInstaller临时目录: {assets_dir}") + print(f"后备:使用PyInstaller临时目录: {assets_dir}") + # 最后尝试工作目录 else: - # 后备方案:使用可执行文件所在目录 - exe_dir = os.path.dirname(sys.executable) - assets_dir = os.path.join(exe_dir, "assets") - print(f"使用可执行文件目录: {assets_dir}") - - # 如果都不存在,尝试其他可能的位置 - if not os.path.exists(assets_dir): - # 尝试从当前工作目录查找 cwd_assets = os.path.join(os.getcwd(), "assets") if os.path.exists(cwd_assets): assets_dir = cwd_assets print(f"从工作目录找到assets: {assets_dir}") else: - print(f"警告:无法找到assets目录,使用默认路径: {assets_dir}") + assets_dir = exe_assets # 即使不存在也使用exe目录,后续会创建 + print(f"使用默认路径(将创建): {assets_dir}") else: # 开发环境 current_dir = os.path.dirname(os.path.abspath(__file__)) diff --git a/app/tools/update_code.py b/app/tools/update_code.py index 283a53a..63b2ba5 100644 --- a/app/tools/update_code.py +++ b/app/tools/update_code.py @@ -10,21 +10,45 @@ import time def update_code(parent=None, info_callback=None, error_callback=None): url = "http://gitea.qutrobot.top/robofish/MRobot/archive/User_code.zip" - # 使用与CodeGenerator.get_assets_dir相同的逻辑确定assets目录 - if getattr(sys, 'frozen', False): - # 打包后的环境 - 使用可执行文件所在目录 - exe_dir = os.path.dirname(sys.executable) - assets_dir = os.path.join(exe_dir, "assets") - print(f"更新代码:打包环境,使用路径: {assets_dir}") - - # 如果exe_dir/assets不存在,尝试使用相对路径作为后备 - if not os.path.exists(assets_dir): - assets_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../assets") - print(f"更新代码:后备路径: {assets_dir}") - else: - # 开发环境 - assets_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../assets") - print(f"更新代码:开发环境,使用路径: {assets_dir}") + # 导入 CodeGenerator 以使用统一的路径获取逻辑 + try: + from app.tools.code_generator import CodeGenerator + # 直接使用 CodeGenerator 的路径获取方法,确保路径一致 + assets_dir = CodeGenerator.get_assets_dir("") + print(f"更新代码:使用 CodeGenerator 路径: {assets_dir}") + except Exception as e: + print(f"无法导入 CodeGenerator,使用后备路径逻辑: {e}") + # 后备方案:使用与CodeGenerator.get_assets_dir相同的逻辑确定assets目录 + if getattr(sys, 'frozen', False): + # 打包后的环境 + if hasattr(sys, '_MEIPASS'): + base_path = getattr(sys, '_MEIPASS') + assets_dir = os.path.join(base_path, "assets") + print(f"更新代码:使用PyInstaller临时目录: {assets_dir}") + else: + # 使用可执行文件所在目录 + exe_dir = os.path.dirname(sys.executable) + assets_dir = os.path.join(exe_dir, "assets") + print(f"更新代码:打包环境,使用路径: {assets_dir}") + + # 如果不存在,尝试工作目录 + if not os.path.exists(assets_dir): + cwd_assets = os.path.join(os.getcwd(), "assets") + if os.path.exists(cwd_assets): + assets_dir = cwd_assets + print(f"更新代码:使用工作目录: {assets_dir}") + else: + # 开发环境 + current_dir = os.path.dirname(os.path.abspath(__file__)) + while current_dir != os.path.dirname(current_dir): + if os.path.basename(current_dir) == 'MRobot': + break + parent_dir = os.path.dirname(current_dir) + if parent_dir == current_dir: + break + current_dir = parent_dir + assets_dir = os.path.join(current_dir, "assets") + print(f"更新代码:开发环境,使用路径: {assets_dir}") local_dir = os.path.join(assets_dir, "User_code") print(f"更新代码:最终目标目录: {local_dir}") @@ -93,6 +117,16 @@ def update_code(parent=None, info_callback=None, error_callback=None): if backup_dir and os.path.exists(backup_dir): shutil.rmtree(backup_dir, ignore_errors=True) + # 清除 CodeGenerator 的缓存,确保后续读取更新后的文件 + try: + from app.tools.code_generator import CodeGenerator + CodeGenerator._assets_dir_cache = None + CodeGenerator._assets_dir_initialized = False + CodeGenerator._template_dir_logged = False + print("已清除 CodeGenerator 缓存") + except Exception as e: + print(f"清除缓存失败(可忽略): {e}") + if info_callback: info_callback(parent) return True diff --git a/assets/Finance_Data/accounts/06266d34-8789-45e9-aff0-e42549c238ba/metadata.json b/assets/Finance_Data/accounts/06266d34-8789-45e9-aff0-e42549c238ba/metadata.json new file mode 100644 index 0000000..729b095 --- /dev/null +++ b/assets/Finance_Data/accounts/06266d34-8789-45e9-aff0-e42549c238ba/metadata.json @@ -0,0 +1,8 @@ +{ + "id": "06266d34-8789-45e9-aff0-e42549c238ba", + "name": "admin", + "description": "默认管理账户", + "categories": [], + "created_at": "2025-12-19T22:06:29.964929", + "updated_at": "2025-12-19T22:06:29.964938" +} \ No newline at end of file diff --git a/assets/User_code/config.csv b/assets/User_code/config.csv index 32290e1..d462c63 100644 --- a/assets/User_code/config.csv +++ b/assets/User_code/config.csv @@ -1,4 +1,4 @@ bsp,can,dwt,gpio,i2c,mm,spi,uart,pwm,time component,ahrs,capacity,cmd,crc8,crc16,error_detect,filter,FreeRTOS_CLI,limiter,mixer,pid,ui,user_math -device,dr16,bmi088,ist8310,motor,motor_rm,motor_dm,motor_vesc,motor_lk,motor_lz,motor_odrive,dm_imu,rc_can,servo,buzzer,led,ws2812,vofa,ops9 +device,dr16,bmi088,ist8310,motor,motor_rm,motor_dm,motor_vesc,motor_lk,motor_lz,motor_odrive,dm_imu,rc_can,servo,buzzer,led,ws2812,vofa,ops9,oid,lcd_driver module,config, \ No newline at end of file diff --git a/assets/User_code/device/config.yaml b/assets/User_code/device/config.yaml index a24a6f6..e240946 100644 --- a/assets/User_code/device/config.yaml +++ b/assets/User_code/device/config.yaml @@ -224,4 +224,23 @@ devices: thread_signals: [] files: header: "vofa.h" - source: "vofa.c" \ No newline at end of file + source: "vofa.c" + oid: + name: "oid编码器" + description: "oid编码器驱动" + dependencies: + bsp: ["time", "can", "mm"] + component: ["user_math"] + thread_signals: [] + files: + header: "oid.h" + source: "oid.c" + lcd_driver: + name: "lcd显示屏" + description: "lcd驱动(SPI)" + dependencies: + bsp: ["gpio", "spi"] + thread_signals: [] + files: + header: "lcd.h" + source: "lcd.c" \ No newline at end of file diff --git a/assets/User_code/device/lcd_driver/lcd.c b/assets/User_code/device/lcd_driver/lcd.c new file mode 100644 index 0000000..afb6ed6 --- /dev/null +++ b/assets/User_code/device/lcd_driver/lcd.c @@ -0,0 +1,743 @@ +/* + LCD驱动 + +高效: +--------控制引脚配置,屏幕属性配置完成后即可使用 +可扩展: +--------添加你喜欢的颜色, +--------在lcd_library.h添加你的自定义点阵库-使用LCD_DrawBitmap驱动任意位图 +兼容: +--------LSB与MSB顺序的字表 + +所有绘制函数使用示例: +LCD_DrawPoint(0,0,BLUE); +LCD_DrawChar(10, 10, 'A', RED, WHITE); +LCD_DrawLine(10, 10, 100, 50, RED); +LCD_DrawRectangle(10,10,50,100,GREEN); +LCD_DrawHollowCircle(200,50,16,RED); +LCD_DrawSolidCircle(200,100,16,RED); +LCD_DrawString(0,0,"MR16",MEDIUMORCHID,32,LSB); + +extern const unsigned char logo_M[]; +LCD_DrawBitmap(logo_M,70,70,64,64,MEDIUMORCHID,MSB); + +*/ + +/* Includes ----------------------------------------------------------------- */ +#include "device/lcd_driver/lcd.h" +#include "device/device.h" +#include "device/lcd_driver/lcd_lib.h" +#include "bsp/spi.h" + +#include +#include +/* USER INCLUDE BEGIN */ + +/* USER INCLUDE END */ +/* Private define ----------------------------------------------------------- */ + +/* USER DEFINE BEGIN */ + +/* USER DEFINE END */ +/* Private macro ------------------------------------------------------------ */ +/* Private typedef ---------------------------------------------------------- */ +/* Private variables -------------------------------------------------------- */ +static LCD_Orientation_t lcd_orientation = LCD_ORIENTATION_PORTRAIT; // 当前屏幕方向 + +/* Private function -------------------------------------------------------- */ +/** + * 写命令到LCD + * + * @param cmd 要写入的命令 + * + * @note 此函数用于向LCD发送控制命令。通过设置数据/命令选择引脚为命令模式, + * 并通过SPI接口发送命令。 + */ +static int8_t LCD_WriteCommand(uint8_t cmd) { + LCD_DC_LOW(); // 设置数据/命令选择引脚为命令模式 + LCD_CS_LOW(); // 使能SPI片选 + BSP_SPI_Transmit(BSP_SPI_LCD, &cmd, 1, false); // 通过SPI发送命令 + LCD_CS_HIGH(); // 禁用SPI片选 + return DEVICE_OK; +} + +/** + * 写数据到LCD + * + * @param data 要写入的数据 + * + * @note 此函数用于向LCD发送数据。通过设置数据/命令选择引脚为数据模式, + * 并通过SPI接口发送数据。 + */ +static int8_t LCD_WriteData(uint8_t data) { + LCD_DC_HIGH(); // 设置数据/命令选择引脚为数据模式 + LCD_CS_LOW(); // 使能SPI片选 + BSP_SPI_Transmit(BSP_SPI_LCD, &data, 1, false); // 通过SPI发送数据 + LCD_CS_HIGH(); // 禁用SPI片选 + return DEVICE_OK; +} + +/** + * 使用 DMA 写多个数据到 LCD + * + * @param data 数据缓冲区指针 + * @param size 数据大小(字节数) + * + * @note 此函数用于通过DMA快速发送大量数据到LCD。适用于数据量较大的场景, + * 提高传输效率。 + */ +static int8_t LCD_WriteDataBuffer_DMA(uint8_t *data, uint16_t size) { + LCD_DC_HIGH(); // 设置数据/命令选择引脚为数据模式 + LCD_CS_LOW(); // 使能SPI片选 + BSP_SPI_Transmit(BSP_SPI_LCD, data, size, true); // 通过SPI发送数据 + while(BSP_SPI_GetState(BSP_SPI_LCD) != HAL_SPI_STATE_READY); // 等待SPI传输完成 + LCD_CS_HIGH(); // 禁用SPI片选 + return DEVICE_OK; +} + +/** + * 修改原来的 LCD_WriteDataBuffer,增加 DMA 支持 + * + * @param data 数据缓冲区指针 + * @param size 数据大小(字节数) + * + * @note 此函数根据数据量大小选择使用DMA或普通SPI传输。如果数据量大于64字节, + * 使用DMA传输,否则使用普通SPI传输。 + */ +static int8_t LCD_WriteDataBuffer(uint8_t *data, uint16_t size) { + if (size > 64) { // 如果数据量较大,使用 DMA + LCD_WriteDataBuffer_DMA(data, size); + } else { // 否则使用普通传输 + LCD_DC_HIGH(); // 设置数据/命令选择引脚为数据模式 + LCD_CS_LOW(); // 使能SPI片选 + BSP_SPI_Transmit(BSP_SPI_LCD, data, size, false); // 通过SPI发送数据 + LCD_CS_HIGH(); // 禁用SPI片选 + } + return DEVICE_OK; +} + +/** + * 根据屏幕方向映射坐标 + * + * @param x 输入的X坐标 + * @param y 输入的Y坐标 + * @param mx 映射后的X坐标(输出) + * @param my 映射后的Y坐标(输出) + * + * @note 此函数根据当前屏幕方向,将输入的坐标映射到实际的屏幕坐标。 + */ +static int8_t LCD_MapCoords(uint16_t x, uint16_t y, uint16_t *mx, uint16_t *my) { + switch (lcd_orientation) { + case LCD_ORIENTATION_PORTRAIT: // 0° + *mx = x; + *my = y; + break; + case LCD_ORIENTATION_LANDSCAPE: // 90°顺时针 + *mx = y; + *my = LCD_HEIGHT - 1 - x; + break; + case LCD_ORIENTATION_LANDSCAPE_INVERTED: // 90°逆时针 + *mx = LCD_WIDTH - 1 - y; + *my = x; + break; + case LCD_ORIENTATION_PORTRAIT_INVERTED: // 180° + *mx = LCD_WIDTH - 1 - x; + *my = LCD_HEIGHT - 1 - y; + break; + default: + *mx = x; + *my = y; + break; + } + return DEVICE_OK; +} + +/** + * 设置LCD绘图窗口 + * + * @param x 窗口起始X坐标 + * @param y 窗口起始Y坐标 + * @param w 窗口宽度 + * @param h 窗口高度 + * + * @note 此函数用于设置LCD的绘图窗口,指定后续绘图操作的区域。 + */ +static int8_t LCD_SetAddressWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) { + uint16_t x_start = x + X_OFFSET; // 计算窗口起始X坐标 + uint16_t x_end = x_start + w - 1; // 计算窗口结束X坐标 + uint16_t y_start = y + Y_OFFSET; // 计算窗口起始Y坐标 + uint16_t y_end = y_start + h - 1; // 计算窗口结束Y坐标 + + LCD_WriteCommand(0x2A); // 列地址设置 + uint8_t data_x[] = {x_start >> 8, x_start & 0xFF, x_end >> 8, x_end & 0xFF}; + LCD_WriteDataBuffer(data_x, sizeof(data_x)); + + LCD_WriteCommand(0x2B); // 行地址设置 + uint8_t data_y[] = {y_start >> 8, y_start & 0xFF, y_end >> 8, y_end & 0xFF}; + LCD_WriteDataBuffer(data_y, sizeof(data_y)); + + LCD_WriteCommand(0x2C); // 内存写入 + + return DEVICE_OK; +} +/* Exported functions ------------------------------------------------------- */ + +/** + * 初始化LCD + * + * @param orientation 屏幕方向(竖屏、横屏等) + * + * @note 此函数用于初始化LCD显示屏,设置屏幕方向、像素格式、伽马校正等参数。 + * 根据传入的屏幕方向参数,调整屏幕的显示方向。 + */ +int8_t LCD_Init(LCD_Orientation_t orientation) { + lcd_orientation = orientation; // 设置屏幕方向 + + LCD_RST_LOW(); // 复位引脚低电平 + HAL_Delay(50); // 延时 + LCD_RST_HIGH(); // 复位引脚高电平 + HAL_Delay(50); // 延时 + + LCD_WriteCommand(0x36); // 内存数据访问控制 + switch (orientation) { + case LCD_ORIENTATION_PORTRAIT: // 竖屏模式 + LCD_WriteData(0x08); // MY=1, MX=0, MV=0, ML=0, BGR=0 + break; + case LCD_ORIENTATION_LANDSCAPE: // 横屏模式(90°顺时针旋转) + LCD_WriteData(0x60); // MY=0, MX=1, MV=1, ML=0, BGR=0 + break; + case LCD_ORIENTATION_LANDSCAPE_INVERTED: // 横屏模式(90°逆时针旋转) + LCD_WriteData(0xA0); // MY=1, MX=1, MV=1, ML=0, BGR=0 + break; + case LCD_ORIENTATION_PORTRAIT_INVERTED: // 竖屏模式(180°旋转) + LCD_WriteData(0xC8); // MY=1, MX=1, MV=0, ML=0, BGR=0 + break; + default: + // LCD_WriteData(0x08); // 默认竖屏模式 + break; + } + + LCD_WriteCommand(0x3A); // 接口像素格式 + LCD_WriteData(0x05); // 16位色 + + LCD_WriteCommand(0xB2); // 前廊设置 + uint8_t porch[] = {0x0C, 0x0C, 0x00, 0x33, 0x33}; + LCD_WriteDataBuffer(porch, sizeof(porch)); + + LCD_WriteCommand(0xB7); // 门控设置 + LCD_WriteData(0x35); + + LCD_WriteCommand(0xBB); // VCOM设置 + LCD_WriteData(0x19); + + LCD_WriteCommand(0xC0); // LCM控制 + LCD_WriteData(0x2C); + + LCD_WriteCommand(0xC2); // VDV和VRH命令使能 + LCD_WriteData(0x01); + + LCD_WriteCommand(0xC3); // VRH设置 + LCD_WriteData(0x12); + + LCD_WriteCommand(0xC4); // VDV设置 + LCD_WriteData(0x20); + + LCD_WriteCommand(0xC6); // 帧率控制 + LCD_WriteData(0x0F); + + LCD_WriteCommand(0xD0); // 电源控制1 + LCD_WriteData(0xA4); + LCD_WriteData(0xA1); + + LCD_WriteCommand(0xE0); // 正电压伽马控制 + uint8_t gamma_pos[] = {0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23}; + LCD_WriteDataBuffer(gamma_pos, sizeof(gamma_pos)); + + LCD_WriteCommand(0xE1); // 负电压伽马控制 + uint8_t gamma_neg[] = {0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23}; + LCD_WriteDataBuffer(gamma_neg, sizeof(gamma_neg)); + + LCD_WriteCommand(0x21); // 显示反转开启 + LCD_WriteCommand(0x11); // 退出睡眠模式 + HAL_Delay(120); // 延时 + LCD_WriteCommand(0x29); // 显示开启 + + return DEVICE_OK; +} + +/** + * 清屏函数 + * + * @param color 清屏颜色(RGB565格式) + * + * @note 此函数用于将整个LCD屏幕填充为指定颜色。 + */ +int8_t LCD_Clear(uint16_t color) { + uint8_t color_data[] = {color >> 8, color & 0xFF}; // 将颜色转换为字节数组 + LCD_SetAddressWindow(0, 0, LCD_WIDTH, LCD_HEIGHT); // 设置整个屏幕为绘制窗口 + + // 创建一个缓冲区,用于存储一行的颜色数据 + uint32_t row_size = LCD_WIDTH * 2; // 每行像素占用 2 字节 + uint8_t *row_buffer = (uint8_t *)malloc(row_size); + if (row_buffer == NULL) return DEVICE_ERR_NULL; // 分配失败,直接返回 + + // 填充缓冲区为目标颜色 + for (uint32_t i = 0; i < row_size; i += 2) { + row_buffer[i] = color_data[0]; + row_buffer[i + 1] = color_data[1]; + } + + // 按行传输数据,覆盖整个屏幕 + for (uint32_t y = 0; y < LCD_HEIGHT; y++) { + LCD_WriteDataBuffer_DMA(row_buffer, row_size); + } + + free(row_buffer); // 释放缓冲区 + + return DEVICE_OK; +} + +/** + * 绘制单个像素点 + * + * @param x X坐标 + * @param y Y坐标 + * @param color 像素颜色(RGB565格式) + * + * @note 此函数用于在指定位置绘制一个像素点。 + */ +int8_t LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t color) { + uint16_t mx, my; + LCD_MapCoords(x, y, &mx, &my); // 根据屏幕方向映射坐标 + LCD_SetAddressWindow(mx, my, 1, 1); // 设置绘制窗口为单个像素 + uint8_t color_data[] = { (uint8_t)(color >> 8), (uint8_t)(color & 0xFF) }; // 将颜色转换为字节数组 + LCD_WriteDataBuffer(color_data, 2); // 写入像素数据 + + return DEVICE_OK; +} + +/** + * 绘制直线 + * + * @param x0 起始X坐标 + * @param y0 起始Y坐标 + * @param x1 终止X坐标 + * @param y1 终止Y坐标 + * @param color 直线颜色(RGB565格式) + * + * @note 此函数使用Bresenham算法绘制直线。 + */ +int8_t LCD_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color) { + int dx = x1 - x0; // 计算X方向增量 + int dy = y1 - y0; // 计算Y方向增量 + int sx = (dx >= 0) ? 1 : -1; // X方向步长 + int sy = (dy >= 0) ? 1 : -1; // Y方向步长 + dx = dx >= 0 ? dx : -dx; // 取绝对值 + dy = dy >= 0 ? dy : -dy; // 取绝对值 + + if (dx == 0 && dy == 0) { // 单点 + LCD_DrawPoint((uint16_t)x0, (uint16_t)y0, color); + return DEVICE_OK; + } + + if (dx > dy) { // X方向增量大于Y方向增量 + int err = dx / 2; // 初始化误差 + int x = x0; + int y = y0; + for (int i = 0; i <= dx; i++) { + LCD_DrawPoint((uint16_t)x, (uint16_t)y, color); // 绘制当前点 + x += sx; // 更新X坐标 + err -= dy; // 更新误差 + if (err < 0) { + y += sy; // 更新Y坐标 + err += dx; // 更新误差 + } + } + } else { // Y方向增量大于X方向增量 + int err = dy / 2; // 初始化误差 + int x = x0; + int y = y0; + for (int i = 0; i <= dy; i++) { + LCD_DrawPoint((uint16_t)x, (uint16_t)y, color); // 绘制当前点 + y += sy; // 更新Y坐标 + err -= dx; // 更新误差 + if (err < 0) { + x += sx; // 更新X坐标 + err += dy; // 更新误差 + } + } + } + return DEVICE_OK; +} + +/** + * 绘制矩形 + * + * @param x1 矩形左上角X坐标 + * @param y1 矩形左上角Y坐标 + * @param x2 矩形右下角X坐标 + * @param y2 矩形右下角Y坐标 + * @param color 矩形颜色(RGB565格式) + * + * @note 此函数通过绘制四条边来绘制矩形。 + */ +int8_t LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { + LCD_DrawLine(x1, y1, x2, y1, color); // 上边 + LCD_DrawLine(x1, y1, x1, y2, color); // 左边 + LCD_DrawLine(x1, y2, x2, y2, color); // 下边 + LCD_DrawLine(x2, y1, x2, y2, color); // 右边 + return DEVICE_OK; +} + +int8_t LCD_DrawSolidRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { + int8_t a; + if(y1>y2) a=1; + else a=-1; + while(y1!=y2) { + LCD_DrawLine(x1, y1, x2, y1, color); // 上边 + LCD_DrawLine(x1, y2, x2, y2, color); // 下边 + y1-=a;y2+=a; + } + return DEVICE_OK; +} +/** + * 绘制空心圆 + * + * @param x0 圆心X坐标 + * @param y0 圆心Y坐标 + * @param r 圆的半径 + * @param color 圆的颜色(RGB565格式) + * + * @note 此函数使用中点圆算法绘制空心圆。 + */ +int8_t LCD_DrawHollowCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color) { + int a = 0; // X方向增量 + int b = r; // Y方向增量 + + while (a <= b) { + LCD_DrawPoint(x0 - b, y0 - a, color); // 第3象限 + LCD_DrawPoint(x0 + b, y0 - a, color); // 第0象限 + LCD_DrawPoint(x0 - a, y0 + b, color); // 第1象限 + LCD_DrawPoint(x0 - a, y0 - b, color); // 第2象限 + LCD_DrawPoint(x0 + b, y0 + a, color); // 第4象限 + LCD_DrawPoint(x0 + a, y0 - b, color); // 第5象限 + LCD_DrawPoint(x0 + a, y0 + b, color); // 第6象限 + LCD_DrawPoint(x0 - b, y0 + a, color); // 第7象限 + + a++; // 更新X方向增量 + if ((a * a + b * b) > (r * r)) { // 判断是否超出半径范围 + b--; // 更新Y方向增量 + } + } + return DEVICE_OK; +} + +/** + * 绘制实心圆 + * + * @param x0 圆心X坐标 + * @param y0 圆心Y坐标 + * @param r 圆的半径 + * @param color 圆的颜色(RGB565格式) + * + * @note 此函数使用中点圆算法绘制实心圆,通过填充水平线段实现。 + */ +int8_t LCD_DrawSolidCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color) { + int a = 0; // X方向增量 + int b = r; // Y方向增量 + int r2 = r * r; // 预计算半径的平方 + + while (a <= b) { + // 绘制8个对称点并填充水平线段 + LCD_DrawLine(x0 - b, y0 - a, x0 + b, y0 - a, color); // 第3象限 + LCD_DrawLine(x0 - b, y0 + a, x0 + b, y0 + a, color); // 第4象限 + LCD_DrawLine(x0 - a, y0 - b, x0 + a, y0 - b, color); // 第2象限 + LCD_DrawLine(x0 - a, y0 + b, x0 + a, y0 + b, color); // 第6象限 + + a++; // 更新X方向增量 + if ((a * a + b * b) > r2) { // 判断是否超出半径范围 + b--; // 更新Y方向增量 + } + } + return DEVICE_OK; +} + +/** + * 绘制字符 + * + * @param x 字符起始X坐标 + * @param y 字符起始Y坐标 + * @param ch 要绘制的字符 + * @param color 字符颜色(RGB565格式) + * @param font_size 字体大小(12或32) + * @param bit_order 位顺序(LSB或MSB) + * + * @note 此函数根据字体大小和位顺序绘制单个字符。 + */ +int8_t LCD_DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint8_t font_size, LCD_BitOrder_t bit_order) { + if (ch < ' ' || ch > '~') { // 检查字符是否在可打印范围内 + return DEVICE_ERR; + } + + uint8_t index = ch - ' '; // 计算字符索引 + + const uint8_t *font_data=NULL; + uint8_t char_width=0; + uint8_t char_height=0; + uint8_t bytesPerRow=0; + + switch (font_size) { + case 12:// 12x6 字体(ascii_1206,特殊位映射 bit5..bit0) + #ifdef ASCII_1206 + font_data = (const uint8_t *)ascii_1206[index]; + char_width = 6; + char_height = 12; + + for (uint8_t row = 0; row < char_height; row++) { + for (uint8_t col = 0; col < char_width; col++) { + uint16_t pixel_x = x + col; + uint16_t pixel_y = y + row; + uint8_t bit_value; + if (bit_order == MSB) { // MSB 优先,项目约定:6 位放在 bit5..bit0 + bit_value = (font_data[row] >> (5 - col)) & 0x01; + } else { // LSB 优先 + bit_value = (font_data[row] >> col) & 0x01; + } + if (bit_value) { + LCD_DrawPoint(pixel_x, pixel_y, color); + } + } + } + #endif + break; + case 16:// 16x8 字体(ascii_1608:按行存储,每行 1 字节,MSB-first 常规映射) + #ifdef ASCII_1608 + font_data = (const uint8_t *)ascii_1608[index]; + char_width = 8; + char_height = 16; + + for (uint8_t row = 0; row < char_height; row++) { + uint8_t row_byte = font_data[row]; + for (uint8_t col = 0; col < char_width; col++) { + uint16_t pixel_x = x + col; + uint16_t pixel_y = y + row; + uint8_t bit_value; + if (bit_order == MSB) { + bit_value = (row_byte >> (7 - col)) & 0x01; // MSB-first: bit7 -> col0 + } else { + bit_value = (row_byte >> col) & 0x01; // LSB-first + } + if (bit_value) { + LCD_DrawPoint(pixel_x, pixel_y, color); + } + } + } + #endif + break; + case 24:// 24x12 字体(ascii_2412:按行存储,每行 2 字节) + #ifdef ASCII_2412 + font_data = (const uint8_t *)ascii_2412[index]; + char_width = 12; + char_height = 24; + bytesPerRow = (char_width + 7) / 8; // =2 + + for (uint8_t row = 0; row < char_height; row++) { + for (uint8_t col = 0; col < char_width; col++) { + uint16_t pixel_x = x + col; + uint16_t pixel_y = y + row; + uint8_t byte_index = col / 8; + uint8_t b = font_data[row * bytesPerRow + byte_index]; + uint8_t bit_value; + if (bit_order == MSB) { + bit_value = (b >> (7 - (col % 8))) & 0x01; + } else { + bit_value = (b >> (col % 8)) & 0x01; + } + if (bit_value) { + LCD_DrawPoint(pixel_x, pixel_y, color); + } + } + } + #endif + break; + case 32:// 32x16 字体(ascii_3216:按行存储,每行 2 字节) + #ifdef ASCII_3216 + font_data = (const uint8_t *)ascii_3216[index]; + char_width = 16; + char_height = 32; + bytesPerRow = (char_width + 7) / 8; // =2 + + for (uint8_t row = 0; row < char_height; row++) { + for (uint8_t col = 0; col < char_width; col++) { + uint16_t pixel_x = x + col; + uint16_t pixel_y = y + row; + uint8_t byte_index = col / 8; + uint8_t b = font_data[row * bytesPerRow + byte_index]; + uint8_t bit_value; + if (bit_order == MSB) { + bit_value = (b >> (7 - (col % 8))) & 0x01; + } else { + bit_value = (b >> (col % 8)) & 0x01; + } + if (bit_value) { + LCD_DrawPoint(pixel_x, pixel_y, color); + } + } + } + #endif + break; + default: + return DEVICE_ERR; + } + + return DEVICE_OK; +} + +/** + * 绘制字符串 + * + * @param x 字符串起始X坐标 + * @param y 字符串起始Y坐标 + * @param str 要绘制的字符串 + * @param color 字符颜色(RGB565格式) + * @param font_size 字体大小(12或32) + * @param bit_order 位顺序(LSB或MSB) + * + * @note 此函数逐字符绘制字符串,支持换行。 + */ +int8_t LCD_DrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint8_t font_size, LCD_BitOrder_t bit_order) { + uint16_t cursor_x = x; + uint16_t cursor_y = y; + uint8_t char_width, char_height, x_spacing, y_spacing; + + switch (font_size) { + case 12: + #ifdef ASCII_1206 + char_width = 6; + char_height = 12; + x_spacing = 7; // 推荐间距:宽度+1 + y_spacing = 13; // 行间距:高度+1 + #endif + break; + case 16: + #ifdef ASCII_1608 + char_width = 8; + char_height = 16; + x_spacing = 9; + y_spacing = 17; + #endif + break; + case 24: + #ifdef ASCII_2412 + char_width = 12; + char_height = 24; + x_spacing = 13; + y_spacing = 25; + #endif + break; + case 32: + #ifdef ASCII_3216 + char_width = 16; + char_height = 32; + x_spacing = 17; + y_spacing = 33; + #endif + break; + default: + return DEVICE_ERR;// 不支持的字体大小 + } + + while (*str) { + if (*str == '\n') { + cursor_x = x; + cursor_y += y_spacing; + str++; + continue; + } + + LCD_DrawChar(cursor_x, cursor_y, *str, color, font_size, bit_order); + cursor_x += x_spacing; + str++; + } +} + +/** + * 绘制整数 + * + * @param x 起始X坐标 + * @param y 起始Y坐标 + * @param num 要绘制的整数 + * @param color 数字颜色(RGB565格式) + * @param font_size 字体大小(12或32) + * @param bit_order 位顺序(LSB或MSB) + * + * @note 此函数将整数转换为字符串后调用LCD_DrawString绘制。 + */ +int8_t LCD_DrawInteger(uint16_t x, uint16_t y, int32_t num, uint16_t color, uint8_t font_size, LCD_BitOrder_t bit_order) { + char buffer[12]; // 缓冲区,足够存储32位整数的字符串表示 + snprintf(buffer, sizeof(buffer), "%d", num); // 将整数转换为字符串 + LCD_DrawString(x, y, buffer, color, font_size, bit_order); // 调用字符串绘制函数 + return DEVICE_OK; +} + +/** + * 绘制浮点数 + * + * @param x 起始X坐标 + * @param y 起始Y坐标 + * @param num 要绘制的浮点数 + * @param decimal_places 小数点后保留的位数 + * @param color 数字颜色(RGB565格式) + * @param font_size 字体大小(12或32) + * @param bit_order 位顺序(LSB或MSB) + * + * @note 此函数将浮点数转换为字符串后调用LCD_DrawString绘制。 + */ +int8_t LCD_DrawFloat(uint16_t x, uint16_t y, float num, uint8_t decimal_places, uint16_t color, uint8_t font_size, LCD_BitOrder_t bit_order) { + char buffer[20]; // 缓冲区,足够存储浮点数的字符串表示 + snprintf(buffer, sizeof(buffer), "%.*f", decimal_places, num); // 将浮点数转换为字符串 + LCD_DrawString(x, y, buffer, color, font_size, bit_order); // 调用字符串绘制函数 + return DEVICE_OK; +} + +/** + * 绘制位图 + * + * @param bitmap 位图数据指针 + * @param x 位图起始X坐标 + * @param y 位图起始Y坐标 + * @param width 位图宽度(像素) + * @param height 位图高度(像素) + * @param color 绘制颜色(RGB565格式) + * + * @note 此函数逐像素绘制位图,适用于简单的位图显示。如果需要更高性能,可以优化为按行发送。 + */ +int8_t LCD_DrawBitmap(const uint8_t *bitmap, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color, LCD_BitOrder_t bit_order) { + if (bitmap == NULL) return DEVICE_ERR_NULL; // 检查位图指针是否为空 + uint16_t bytesPerRow = (width + 7) / 8; // 每行的字节数 + + for (uint16_t row = 0; row < height; row++) { // 遍历每一行 + const uint8_t *row_ptr = bitmap + (uint32_t)row * bytesPerRow; // 当前行的起始指针 + for (uint16_t byte_i = 0; byte_i < bytesPerRow; byte_i++) { // 遍历每一行的字节 + uint8_t b = row_ptr[byte_i]; // 当前字节 + for (uint8_t bit = 0; bit < 8; bit++) { // 遍历每个字节的位 + uint16_t col = (uint16_t)byte_i * 8 + bit; // 计算当前像素的列坐标 + if (col >= width) break; // 如果超出宽度范围,跳过 + + uint8_t pixel_on = 0; + if (bit_order == MSB) { + // MSB-first:字节内最高位(0x80)对应当前字节块的最左像素 + pixel_on = (b & (0x80 >> bit)) ? 1 : 0; + } else { + // LSB-first:字节内最低位(0x01)对应当前字节块的最左像素 + pixel_on = (b & (1U << bit)) ? 1 : 0; + } + + if (pixel_on) { // 如果当前位为1,则绘制像素 + LCD_DrawPoint((uint16_t)(x + col), (uint16_t)(y + row), color); + } + } + } + } + return DEVICE_OK; +} \ No newline at end of file diff --git a/assets/User_code/device/lcd_driver/lcd.h b/assets/User_code/device/lcd_driver/lcd.h new file mode 100644 index 0000000..930fe66 --- /dev/null +++ b/assets/User_code/device/lcd_driver/lcd.h @@ -0,0 +1,156 @@ +#ifndef __LCD_H +#define __LCD_H + +/* Includes ----------------------------------------------------------------- */ +#include "device/device.h" +#include "bsp/spi.h" +#include "bsp/gpio.h" + +/* USER INCLUDE BEGIN */ + +/* USER INCLUDE END */ + +/* USER DEFINE BEGIN */ + +/* USER DEFINE END */ + +/* Exported constants ------------------------------------------------------- */ +/* Exported macro ----------------------------------------------------------- */ +/* Exported types ----------------------------------------------------------- */ +/****************************************************************************** + 屏幕属性 +******************************************************************************/ +/* USER ATTRIBUTE BEGIN */ +#define LCD_WIDTH 135 +#define LCD_HEIGHT 240 + +#define X_OFFSET 52 +#define Y_OFFSET 40 +/* USER ATTRIBUTE END */ +/****************************************************************************** + 控制引脚 +******************************************************************************/ +/* USER PIN BEGIN */ +#define LCD_CS_LOW() HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET) +#define LCD_CS_HIGH() HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET) +#define LCD_DC_LOW() HAL_GPIO_WritePin(LCD_RS_GPIO_Port, LCD_RS_Pin, GPIO_PIN_RESET) +#define LCD_DC_HIGH() HAL_GPIO_WritePin(LCD_RS_GPIO_Port, LCD_RS_Pin, GPIO_PIN_SET) +#define LCD_RST_LOW() HAL_GPIO_WritePin(LCD_RES_GPIO_Port, LCD_RES_Pin, GPIO_PIN_RESET) +#define LCD_RST_HIGH() HAL_GPIO_WritePin(LCD_RES_GPIO_Port, LCD_RES_Pin, GPIO_PIN_SET) +/* USER PIN END */ +/****************************************************************************** + 常用颜色(RGB565) +******************************************************************************/ +/* USER COLOR BEGIN */ +#define ALICEBLUE 0xEFBF // 爱丽丝蓝 +#define ANTIQUEWHITE 0xF75A // 古董白 +#define AQUA 0x07FF // 水色 +#define AQUAMARINE 0x7FFA // 碧绿色 +#define AZURE 0xEFFF // 天蓝色 +#define BEIGE 0xF7BB // 米色 +#define BISQUE 0xFF18 // Bisque色 +#define BLACK 0x0000 // 黑色 +#define BLANCHEDALMOND 0xFF59 // 漂白的杏仁色 +#define BLUE 0x001F // 蓝色 +#define BROWN 0xA145 // 棕色 +#define BURLYWOOD 0xDDB0 // 木色 +#define CADETBLUE 0x64F3 // 军校蓝 +#define CHARTreuse 0x7FE0 // 鲜绿色 +#define CHOCOLATE 0xD344 // 巧克力色 +#define CORAL 0xFBEA // 珊瑚色 +#define CORNFLOWERBLUE 0x64BD // 矢车菊蓝 +#define CORNSILK 0xFFBB // 玉米丝色 +#define CRIMSON 0xD8A7 // 深红 +#define CYAN 0x07FF // 青色 +#define DARKBLUE 0x0011 // 深蓝色 +#define DARKCYAN 0x0451 // 深青色 +#define DARKGOLDENROD 0xB421 // 深金菊色 +#define DARKGRAY 0xAD55 // 深灰色 +#define DARKGREEN 0x0320 // 深绿色 +#define DARKGREY 0xAD55 // 深灰色(同DARKGRAY) +#define DARKOLIVEGREEN 0x5346 // 深橄榄绿 +#define DARKORANGE 0xFC60 // 深橙色 +#define DARKVIOLET 0x901A // 深紫罗兰色 +#define DEEPPINK 0xF8B2 // 深粉红色 +#define DEEPSKYBLUE 0x05FF // 深天蓝色 +#define DODGERBLUE 0x249F // 闪兰色 +#define FIREBRICK 0xB104 // 火砖色 +#define FUCHSIA 0xF81F // 紫红色 +#define GAINSBORO 0xDEDB // 增白 +#define GOLD 0xFEA0 // 金色 +#define GOLDENROD 0xDD24 // 金菊色 +#define GRAY 0x8410 // 灰色 +#define GREEN 0x0400 // 绿色 +#define GREENYELLOW 0xAFE6 // 绿黄色 +#define GREY 0x8410 // 灰色(同GRAY) +#define HONEYDEW 0xEFFD // 蜜色 +#define HOTPINK 0xFB56 // 热粉红色 +#define IVORY 0xFFFD // 象牙色 +#define KHAKI 0xEF31 // 卡其色 +#define LAVENDER 0xE73E // 淡紫色 +#define LIME 0x07E0 // 酸橙绿 +#define LIMEGREEN 0x3666 // 酸橙绿 +#define LINEN 0xF77C // 亚麻色 +#define MAGENTA 0xF81F // 洋红色 +#define MAROON 0x8000 // 褐红色 +#define MEDIUMAQUAMARINE 0x6675 // 中等碧绿色 +#define MEDIUMBLUE 0x0019 // 中等蓝色 +#define MEDIUMPURPLE 0x939b // 中等紫色 +#define MEDIUMSEAGREEN 0x3d8e // 中等海绿色 +#define MEDIUMSLATEBLUE 0x7b5d // 中等石板蓝 +#define MEDIUMSPRINGGREEN 0x07d3 // 中等春绿色 +#define MEDIUMTURQUOISE 0x4e99 // 中等青绿色 +#define MEDIUMVIOLETRED 0xC0B0 // 中等紫红色 +#define MIDNIGHTBLUE 0x18CE // 午夜蓝 +#define MINTCREAME 0xF7FE // 薄荷奶油色 +#define MISTYROSE 0xFF1B // 雾玫瑰色 +#define MOCCASIN 0xFF16 // 鹿皮色 +#define NAVAJOWHITE 0xFEF5 // Navajo白 +#define NAVY 0x0010 // 海军蓝 +#define OLDLACE 0xFFBC // 旧蕾丝色 +#define OLIVE 0x8400 // 橄榄色 +#define OLIVEDRAB 0x6C64 // 橄榄褐色 +#define ORANGE 0xFD20 // 橙色 +#define ORANGERED 0xFA20 // 橙红色 +#define ORCHID 0xDB9A // 兰花色 +#define PALE GOLDENROD 0xEF35 // 苍白金菊色 +#define PALEGREEN 0x97D2 // 苍白绿色 +#define MEDIUMORCHID 0xbaba // 中等紫罗兰色 +#define VIOLET 0xEC1D // 紫罗兰色 /--- *I LOVE VIOLET FOREVER!!T-T* ---/ +#define VIOLET_SOFT 0xE31F // 柔和的紫罗兰色 +/* USER COLOR END */ +/****************************************************************************** + end--常用颜色(RGB565) +******************************************************************************/ + +typedef enum { + LCD_ORIENTATION_PORTRAIT = 0, // 竖屏模式 + LCD_ORIENTATION_LANDSCAPE = 1, // 横屏模式(90°顺时针旋转) + LCD_ORIENTATION_LANDSCAPE_INVERTED = 2, // 横屏模式(90°逆时针旋转) + LCD_ORIENTATION_PORTRAIT_INVERTED = 3 // 竖屏模式(180°旋转) +} LCD_Orientation_t; + +typedef enum { + LSB=0, + MSB=1, +}LCD_BitOrder_t; + +/* Exported functions prototypes -------------------------------------------- */ +int8_t LCD_Init(LCD_Orientation_t orientation); +int8_t LCD_Clear(uint16_t color); + +int8_t LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t color); +int8_t LCD_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color); +int8_t LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,uint16_t color); +int8_t LCD_DrawHollowCircle(uint16_t x0,uint16_t y0,uint16_t r,uint16_t color); +int8_t LCD_DrawSolidCircle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color); +int8_t LCD_DrawChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint8_t font_size, LCD_BitOrder_t bit_order); +int8_t LCD_DrawString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint8_t font_size, LCD_BitOrder_t bit_order); +int8_t LCD_DrawInteger(uint16_t x, uint16_t y, int32_t num, uint16_t color, uint8_t font_size, LCD_BitOrder_t bit_order); +int8_t LCD_DrawFloat(uint16_t x, uint16_t y, float num, uint8_t decimal_places, uint16_t color, uint8_t font_size, LCD_BitOrder_t bit_order); +int8_t LCD_DrawBitmap(const uint8_t *bitmap, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color, LCD_BitOrder_t bit_order); + +/* USER FUNCTION BEGIN */ + +/* USER FUNCTION END */ +#endif // __LCD_H diff --git a/assets/User_code/device/lcd_driver/lcd_lib.h b/assets/User_code/device/lcd_driver/lcd_lib.h new file mode 100644 index 0000000..6d55836 --- /dev/null +++ b/assets/User_code/device/lcd_driver/lcd_lib.h @@ -0,0 +1,621 @@ +#pragma once + +#include + +// #define ASCII_1206 +#define ASCII_1608 +#define ASCII_2412 +#define ASCII_3216 +#define LOGO_M +// #define LOGO_R +// #define HUAJI + + +#ifdef ASCII_1206 +const unsigned char ascii_1206[][12]={ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/ + {0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x00,0x00,0x04,0x00,0x00},/*"!",1*/ + {0x14,0x14,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/ + {0x00,0x00,0x0A,0x0A,0x1F,0x0A,0x0A,0x1F,0x0A,0x0A,0x00,0x00},/*"#",3*/ + {0x00,0x04,0x0E,0x15,0x05,0x06,0x0C,0x14,0x15,0x0E,0x04,0x00},/*"$",4*/ + {0x00,0x00,0x12,0x15,0x0D,0x15,0x2E,0x2C,0x2A,0x12,0x00,0x00},/*"%",5*/ + {0x00,0x00,0x04,0x0A,0x0A,0x36,0x15,0x15,0x29,0x16,0x00,0x00},/*"&",6*/ + {0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/ + {0x10,0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x08,0x08,0x10,0x00},/*"(",8*/ + {0x02,0x04,0x04,0x08,0x08,0x08,0x08,0x08,0x04,0x04,0x02,0x00},/*")",9*/ + {0x00,0x00,0x00,0x04,0x15,0x0E,0x0E,0x15,0x04,0x00,0x00,0x00},/*"*",10*/ + {0x00,0x00,0x00,0x08,0x08,0x3E,0x08,0x08,0x00,0x00,0x00,0x00},/*"+",11*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x01,0x00},/*",",12*/ + {0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00},/*"-",13*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00},/*".",14*/ + {0x00,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x02,0x02,0x01,0x00},/*"/",15*/ + {0x00,0x00,0x0E,0x11,0x11,0x11,0x11,0x11,0x11,0x0E,0x00,0x00},/*"0",16*/ + {0x00,0x00,0x04,0x06,0x04,0x04,0x04,0x04,0x04,0x0E,0x00,0x00},/*"1",17*/ + {0x00,0x00,0x0E,0x11,0x11,0x08,0x04,0x02,0x01,0x1F,0x00,0x00},/*"2",18*/ + {0x00,0x00,0x0E,0x11,0x10,0x0C,0x10,0x10,0x11,0x0E,0x00,0x00},/*"3",19*/ + {0x00,0x00,0x08,0x0C,0x0C,0x0A,0x09,0x1F,0x08,0x1C,0x00,0x00},/*"4",20*/ + {0x00,0x00,0x1F,0x01,0x01,0x0F,0x11,0x10,0x11,0x0E,0x00,0x00},/*"5",21*/ + {0x00,0x00,0x0C,0x12,0x01,0x0D,0x13,0x11,0x11,0x0E,0x00,0x00},/*"6",22*/ + {0x00,0x00,0x1E,0x10,0x08,0x08,0x04,0x04,0x04,0x04,0x00,0x00},/*"7",23*/ + {0x00,0x00,0x0E,0x11,0x11,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00},/*"8",24*/ + {0x00,0x00,0x0E,0x11,0x11,0x19,0x16,0x10,0x09,0x06,0x00,0x00},/*"9",25*/ + {0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x04,0x00,0x00},/*":",26*/ + {0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x04,0x00},/*";",27*/ + {0x00,0x00,0x10,0x08,0x04,0x02,0x02,0x04,0x08,0x10,0x00,0x00},/*"<",28*/ + {0x00,0x00,0x00,0x00,0x3F,0x00,0x3F,0x00,0x00,0x00,0x00,0x00},/*"=",29*/ + {0x00,0x00,0x02,0x04,0x08,0x10,0x10,0x08,0x04,0x02,0x00,0x00},/*">",30*/ + {0x00,0x00,0x0E,0x11,0x11,0x08,0x04,0x04,0x00,0x04,0x00,0x00},/*"?",31*/ + {0x00,0x00,0x1C,0x22,0x29,0x2D,0x2D,0x1D,0x22,0x1C,0x00,0x00},/*"@",32*/ + {0x00,0x00,0x04,0x04,0x0C,0x0A,0x0A,0x1E,0x12,0x33,0x00,0x00},/*"A",33*/ + {0x00,0x00,0x0F,0x12,0x12,0x0E,0x12,0x12,0x12,0x0F,0x00,0x00},/*"B",34*/ + {0x00,0x00,0x1E,0x11,0x01,0x01,0x01,0x01,0x11,0x0E,0x00,0x00},/*"C",35*/ + {0x00,0x00,0x0F,0x12,0x12,0x12,0x12,0x12,0x12,0x0F,0x00,0x00},/*"D",36*/ + {0x00,0x00,0x1F,0x12,0x0A,0x0E,0x0A,0x02,0x12,0x1F,0x00,0x00},/*"E",37*/ + {0x00,0x00,0x1F,0x12,0x0A,0x0E,0x0A,0x02,0x02,0x07,0x00,0x00},/*"F",38*/ + {0x00,0x00,0x1C,0x12,0x01,0x01,0x39,0x11,0x12,0x0C,0x00,0x00},/*"G",39*/ + {0x00,0x00,0x33,0x12,0x12,0x1E,0x12,0x12,0x12,0x33,0x00,0x00},/*"H",40*/ + {0x00,0x00,0x1F,0x04,0x04,0x04,0x04,0x04,0x04,0x1F,0x00,0x00},/*"I",41*/ + {0x00,0x00,0x3E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x09,0x07},/*"J",42*/ + {0x00,0x00,0x37,0x12,0x0A,0x06,0x0A,0x12,0x12,0x37,0x00,0x00},/*"K",43*/ + {0x00,0x00,0x07,0x02,0x02,0x02,0x02,0x02,0x22,0x3F,0x00,0x00},/*"L",44*/ + {0x00,0x00,0x3B,0x1B,0x1B,0x1B,0x15,0x15,0x15,0x35,0x00,0x00},/*"M",45*/ + {0x00,0x00,0x3B,0x12,0x16,0x16,0x1A,0x1A,0x12,0x17,0x00,0x00},/*"N",46*/ + {0x00,0x00,0x0E,0x11,0x11,0x11,0x11,0x11,0x11,0x0E,0x00,0x00},/*"O",47*/ + {0x00,0x00,0x0F,0x12,0x12,0x0E,0x02,0x02,0x02,0x07,0x00,0x00},/*"P",48*/ + {0x00,0x00,0x0E,0x11,0x11,0x11,0x11,0x17,0x19,0x0E,0x18,0x00},/*"Q",49*/ + {0x00,0x00,0x0F,0x12,0x12,0x0E,0x0A,0x12,0x12,0x37,0x00,0x00},/*"R",50*/ + {0x00,0x00,0x1E,0x11,0x01,0x06,0x08,0x10,0x11,0x0F,0x00,0x00},/*"S",51*/ + {0x00,0x00,0x1F,0x15,0x04,0x04,0x04,0x04,0x04,0x0E,0x00,0x00},/*"T",52*/ + {0x00,0x00,0x33,0x12,0x12,0x12,0x12,0x12,0x12,0x0C,0x00,0x00},/*"U",53*/ + {0x00,0x00,0x33,0x12,0x12,0x0A,0x0A,0x0C,0x04,0x04,0x00,0x00},/*"V",54*/ + {0x00,0x00,0x15,0x15,0x15,0x15,0x0E,0x0A,0x0A,0x0A,0x00,0x00},/*"W",55*/ + {0x00,0x00,0x1B,0x0A,0x0A,0x04,0x04,0x0A,0x0A,0x1B,0x00,0x00},/*"X",56*/ + {0x00,0x00,0x1B,0x0A,0x0A,0x0A,0x04,0x04,0x04,0x0E,0x00,0x00},/*"Y",57*/ + {0x00,0x00,0x1F,0x09,0x08,0x04,0x04,0x02,0x12,0x1F,0x00,0x00},/*"Z",58*/ + {0x1C,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x1C,0x00},/*"[",59*/ + {0x00,0x02,0x02,0x04,0x04,0x04,0x08,0x08,0x08,0x10,0x10,0x00},/*"\",60*/ + {0x0E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0E,0x00},/*"]",61*/ + {0x04,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F},/*"_",63*/ + {0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/ + {0x00,0x00,0x00,0x00,0x00,0x0C,0x12,0x1C,0x12,0x3C,0x00,0x00},/*"a",65*/ + {0x00,0x03,0x02,0x02,0x02,0x0E,0x12,0x12,0x12,0x0E,0x00,0x00},/*"b",66*/ + {0x00,0x00,0x00,0x00,0x00,0x1C,0x12,0x02,0x12,0x0C,0x00,0x00},/*"c",67*/ + {0x00,0x18,0x10,0x10,0x10,0x1C,0x12,0x12,0x12,0x3C,0x00,0x00},/*"d",68*/ + {0x00,0x00,0x00,0x00,0x00,0x0C,0x12,0x1E,0x02,0x1C,0x00,0x00},/*"e",69*/ + {0x00,0x18,0x24,0x04,0x04,0x1E,0x04,0x04,0x04,0x1E,0x00,0x00},/*"f",70*/ + {0x00,0x00,0x00,0x00,0x00,0x3C,0x12,0x0C,0x02,0x1C,0x22,0x1C},/*"g",71*/ + {0x00,0x03,0x02,0x02,0x02,0x0E,0x12,0x12,0x12,0x37,0x00,0x00},/*"h",72*/ + {0x00,0x04,0x04,0x00,0x00,0x06,0x04,0x04,0x04,0x0E,0x00,0x00},/*"i",73*/ + {0x00,0x08,0x08,0x00,0x00,0x0C,0x08,0x08,0x08,0x08,0x08,0x07},/*"j",74*/ + {0x00,0x03,0x02,0x02,0x02,0x1A,0x0A,0x06,0x0A,0x13,0x00,0x00},/*"k",75*/ + {0x00,0x07,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x1F,0x00,0x00},/*"l",76*/ + {0x00,0x00,0x00,0x00,0x00,0x0F,0x15,0x15,0x15,0x15,0x00,0x00},/*"m",77*/ + {0x00,0x00,0x00,0x00,0x00,0x0F,0x12,0x12,0x12,0x37,0x00,0x00},/*"n",78*/ + {0x00,0x00,0x00,0x00,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00,0x00},/*"o",79*/ + {0x00,0x00,0x00,0x00,0x00,0x0F,0x12,0x12,0x12,0x0E,0x02,0x07},/*"p",80*/ + {0x00,0x00,0x00,0x00,0x00,0x1C,0x12,0x12,0x12,0x1C,0x10,0x38},/*"q",81*/ + {0x00,0x00,0x00,0x00,0x00,0x1B,0x06,0x02,0x02,0x07,0x00,0x00},/*"r",82*/ + {0x00,0x00,0x00,0x00,0x00,0x1E,0x02,0x0C,0x10,0x1E,0x00,0x00},/*"s",83*/ + {0x00,0x00,0x00,0x04,0x04,0x1E,0x04,0x04,0x04,0x1C,0x00,0x00},/*"t",84*/ + {0x00,0x00,0x00,0x00,0x00,0x1B,0x12,0x12,0x12,0x3C,0x00,0x00},/*"u",85*/ + {0x00,0x00,0x00,0x00,0x00,0x1B,0x0A,0x0A,0x04,0x04,0x00,0x00},/*"v",86*/ + {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x0E,0x0A,0x0A,0x00,0x00},/*"w",87*/ + {0x00,0x00,0x00,0x00,0x00,0x1B,0x0A,0x04,0x0A,0x1B,0x00,0x00},/*"x",88*/ + {0x00,0x00,0x00,0x00,0x00,0x33,0x12,0x12,0x0C,0x08,0x04,0x03},/*"y",89*/ + {0x00,0x00,0x00,0x00,0x00,0x1E,0x08,0x04,0x04,0x1E,0x00,0x00},/*"z",90*/ + {0x18,0x08,0x08,0x08,0x08,0x0C,0x08,0x08,0x08,0x08,0x18,0x00},/*"{",91*/ + {0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08},/*"|",92*/ + {0x06,0x04,0x04,0x04,0x04,0x08,0x04,0x04,0x04,0x04,0x06,0x00},/*"}",93*/ + {0x16,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",94*/ +}; +#endif // ASCII_1206 + +#ifdef ASCII_1608 +const unsigned char ascii_1608[][16]={ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/ +{0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x18,0x18,0x00,0x00},/*"!",1*/ +{0x00,0x48,0x6C,0x24,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/ +{0x00,0x00,0x00,0x24,0x24,0x24,0x7F,0x12,0x12,0x12,0x7F,0x12,0x12,0x12,0x00,0x00},/*"#",3*/ +{0x00,0x00,0x08,0x1C,0x2A,0x2A,0x0A,0x0C,0x18,0x28,0x28,0x2A,0x2A,0x1C,0x08,0x08},/*"$",4*/ +{0x00,0x00,0x00,0x22,0x25,0x15,0x15,0x15,0x2A,0x58,0x54,0x54,0x54,0x22,0x00,0x00},/*"%",5*/ +{0x00,0x00,0x00,0x0C,0x12,0x12,0x12,0x0A,0x76,0x25,0x29,0x11,0x91,0x6E,0x00,0x00},/*"&",6*/ +{0x00,0x06,0x06,0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/ +{0x00,0x40,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x40,0x00},/*"(",8*/ +{0x00,0x02,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x08,0x04,0x02,0x00},/*")",9*/ +{0x00,0x00,0x00,0x00,0x08,0x08,0x6B,0x1C,0x1C,0x6B,0x08,0x08,0x00,0x00,0x00,0x00},/*"*",10*/ +{0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x7F,0x08,0x08,0x08,0x08,0x00,0x00,0x00},/*"+",11*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x04,0x03},/*",",12*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"-",13*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x00,0x00},/*".",14*/ +{0x00,0x00,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x02,0x02,0x00},/*"/",15*/ +{0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00},/*"0",16*/ +{0x00,0x00,0x00,0x08,0x0E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"1",17*/ +{0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x20,0x20,0x10,0x08,0x04,0x42,0x7E,0x00,0x00},/*"2",18*/ +{0x00,0x00,0x00,0x3C,0x42,0x42,0x20,0x18,0x20,0x40,0x40,0x42,0x22,0x1C,0x00,0x00},/*"3",19*/ +{0x00,0x00,0x00,0x20,0x30,0x28,0x24,0x24,0x22,0x22,0x7E,0x20,0x20,0x78,0x00,0x00},/*"4",20*/ +{0x00,0x00,0x00,0x7E,0x02,0x02,0x02,0x1A,0x26,0x40,0x40,0x42,0x22,0x1C,0x00,0x00},/*"5",21*/ +{0x00,0x00,0x00,0x38,0x24,0x02,0x02,0x1A,0x26,0x42,0x42,0x42,0x24,0x18,0x00,0x00},/*"6",22*/ +{0x00,0x00,0x00,0x7E,0x22,0x22,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00},/*"7",23*/ +{0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00},/*"8",24*/ +{0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x64,0x58,0x40,0x40,0x24,0x1C,0x00,0x00},/*"9",25*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00},/*":",26*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x04},/*";",27*/ +{0x00,0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x20,0x40,0x00,0x00},/*"<",28*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00},/*"=",29*/ +{0x00,0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x00},/*">",30*/ +{0x00,0x00,0x00,0x3C,0x42,0x42,0x46,0x40,0x20,0x10,0x10,0x00,0x18,0x18,0x00,0x00},/*"?",31*/ +{0x00,0x00,0x00,0x1C,0x22,0x5A,0x55,0x55,0x55,0x55,0x2D,0x42,0x22,0x1C,0x00,0x00},/*"@",32*/ +{0x00,0x00,0x00,0x08,0x08,0x18,0x14,0x14,0x24,0x3C,0x22,0x42,0x42,0xE7,0x00,0x00},/*"A",33*/ +{0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x1E,0x22,0x42,0x42,0x42,0x22,0x1F,0x00,0x00},/*"B",34*/ +{0x00,0x00,0x00,0x7C,0x42,0x42,0x01,0x01,0x01,0x01,0x01,0x42,0x22,0x1C,0x00,0x00},/*"C",35*/ +{0x00,0x00,0x00,0x1F,0x22,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1F,0x00,0x00},/*"D",36*/ +{0x00,0x00,0x00,0x3F,0x42,0x12,0x12,0x1E,0x12,0x12,0x02,0x42,0x42,0x3F,0x00,0x00},/*"E",37*/ +{0x00,0x00,0x00,0x3F,0x42,0x12,0x12,0x1E,0x12,0x12,0x02,0x02,0x02,0x07,0x00,0x00},/*"F",38*/ +{0x00,0x00,0x00,0x3C,0x22,0x22,0x01,0x01,0x01,0x71,0x21,0x22,0x22,0x1C,0x00,0x00},/*"G",39*/ +{0x00,0x00,0x00,0xE7,0x42,0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"H",40*/ +{0x00,0x00,0x00,0x3E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"I",41*/ +{0x00,0x00,0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x0F},/*"J",42*/ +{0x00,0x00,0x00,0x77,0x22,0x12,0x0A,0x0E,0x0A,0x12,0x12,0x22,0x22,0x77,0x00,0x00},/*"K",43*/ +{0x00,0x00,0x00,0x07,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x42,0x7F,0x00,0x00},/*"L",44*/ +{0x00,0x00,0x00,0x77,0x36,0x36,0x36,0x36,0x2A,0x2A,0x2A,0x2A,0x2A,0x6B,0x00,0x00},/*"M",45*/ +{0x00,0x00,0x00,0xE3,0x46,0x46,0x4A,0x4A,0x52,0x52,0x52,0x62,0x62,0x47,0x00,0x00},/*"N",46*/ +{0x00,0x00,0x00,0x1C,0x22,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x22,0x1C,0x00,0x00},/*"O",47*/ +{0x00,0x00,0x00,0x3F,0x42,0x42,0x42,0x42,0x3E,0x02,0x02,0x02,0x02,0x07,0x00,0x00},/*"P",48*/ +{0x00,0x00,0x00,0x1C,0x22,0x41,0x41,0x41,0x41,0x41,0x4D,0x53,0x32,0x1C,0x60,0x00},/*"Q",49*/ +{0x00,0x00,0x00,0x3F,0x42,0x42,0x42,0x3E,0x12,0x12,0x22,0x22,0x42,0xC7,0x00,0x00},/*"R",50*/ +{0x00,0x00,0x00,0x7C,0x42,0x42,0x02,0x04,0x18,0x20,0x40,0x42,0x42,0x3E,0x00,0x00},/*"S",51*/ +{0x00,0x00,0x00,0x7F,0x49,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1C,0x00,0x00},/*"T",52*/ +{0x00,0x00,0x00,0xE7,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00},/*"U",53*/ +{0x00,0x00,0x00,0xE7,0x42,0x42,0x22,0x24,0x24,0x14,0x14,0x18,0x08,0x08,0x00,0x00},/*"V",54*/ +{0x00,0x00,0x00,0x6B,0x49,0x49,0x49,0x49,0x55,0x55,0x36,0x22,0x22,0x22,0x00,0x00},/*"W",55*/ +{0x00,0x00,0x00,0xE7,0x42,0x24,0x24,0x18,0x18,0x18,0x24,0x24,0x42,0xE7,0x00,0x00},/*"X",56*/ +{0x00,0x00,0x00,0x77,0x22,0x22,0x14,0x14,0x08,0x08,0x08,0x08,0x08,0x1C,0x00,0x00},/*"Y",57*/ +{0x00,0x00,0x00,0x7E,0x21,0x20,0x10,0x10,0x08,0x04,0x04,0x42,0x42,0x3F,0x00,0x00},/*"Z",58*/ +{0x00,0x78,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x78,0x00},/*"[",59*/ +{0x00,0x00,0x02,0x02,0x04,0x04,0x08,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x40,0x40},/*"\",60*/ +{0x00,0x1E,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1E,0x00},/*"]",61*/ +{0x00,0x38,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF},/*"_",63*/ +{0x00,0x06,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x78,0x44,0x42,0x42,0xFC,0x00,0x00},/*"a",65*/ +{0x00,0x00,0x00,0x03,0x02,0x02,0x02,0x1A,0x26,0x42,0x42,0x42,0x26,0x1A,0x00,0x00},/*"b",66*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x02,0x02,0x02,0x44,0x38,0x00,0x00},/*"c",67*/ +{0x00,0x00,0x00,0x60,0x40,0x40,0x40,0x78,0x44,0x42,0x42,0x42,0x64,0xD8,0x00,0x00},/*"d",68*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x7E,0x02,0x02,0x42,0x3C,0x00,0x00},/*"e",69*/ +{0x00,0x00,0x00,0xF0,0x88,0x08,0x08,0x7E,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"f",70*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x22,0x22,0x1C,0x02,0x3C,0x42,0x42,0x3C},/*"g",71*/ +{0x00,0x00,0x00,0x03,0x02,0x02,0x02,0x3A,0x46,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"h",72*/ +{0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x0E,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"i",73*/ +{0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x22,0x1E},/*"j",74*/ +{0x00,0x00,0x00,0x03,0x02,0x02,0x02,0x72,0x12,0x0A,0x16,0x12,0x22,0x77,0x00,0x00},/*"k",75*/ +{0x00,0x00,0x00,0x0E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"l",76*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x92,0x92,0x92,0x92,0x92,0xB7,0x00,0x00},/*"m",77*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x46,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"n",78*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00},/*"o",79*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0x26,0x42,0x42,0x42,0x22,0x1E,0x02,0x07},/*"p",80*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x44,0x42,0x42,0x42,0x44,0x78,0x40,0xE0},/*"q",81*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x4C,0x04,0x04,0x04,0x04,0x1F,0x00,0x00},/*"r",82*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x42,0x02,0x3C,0x40,0x42,0x3E,0x00,0x00},/*"s",83*/ +{0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x3E,0x08,0x08,0x08,0x08,0x08,0x30,0x00,0x00},/*"t",84*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x42,0x42,0x42,0x42,0x62,0xDC,0x00,0x00},/*"u",85*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0x42,0x24,0x24,0x14,0x08,0x08,0x00,0x00},/*"v",86*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEB,0x49,0x49,0x55,0x55,0x22,0x22,0x00,0x00},/*"w",87*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x24,0x18,0x18,0x18,0x24,0x6E,0x00,0x00},/*"x",88*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0x42,0x24,0x24,0x14,0x18,0x08,0x08,0x07},/*"y",89*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x22,0x10,0x08,0x08,0x44,0x7E,0x00,0x00},/*"z",90*/ +{0x00,0xC0,0x20,0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0x20,0x20,0xC0,0x00},/*"{",91*/ +{0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10},/*"|",92*/ +{0x00,0x06,0x08,0x08,0x08,0x08,0x08,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x00},/*"}",93*/ +{0x0C,0x32,0xC2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",94*/ +}; +#endif + +#ifdef ASCII_2412 +const unsigned char ascii_2412[][48]={ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/ +{0x00,0x00,0x00,0x00,0x60,0x06,0x60,0x06,0x30,0x03,0x98,0x01,0x88,0x00,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x02,0x10,0x02,0x10,0x02,0x10,0x02,0xFE,0x07,0xFE,0x07,0x08,0x02,0x08,0x01,0x08,0x01,0x08,0x01,0x08,0x01,0xFE,0x07,0xFE,0x07,0x04,0x01,0x04,0x01,0x04,0x01,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"#",3*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0xF0,0x01,0x58,0x03,0x4C,0x03,0xCC,0x03,0x4C,0x00,0x58,0x00,0x70,0x00,0xE0,0x00,0xC0,0x01,0xC0,0x01,0x40,0x03,0x4C,0x03,0x5C,0x03,0x4C,0x03,0x48,0x01,0xF0,0x00,0x40,0x00,0x40,0x00,0x00,0x00},/*"$",4*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x01,0x0A,0x01,0x91,0x00,0x91,0x00,0x91,0x00,0x51,0x00,0x51,0x00,0x3A,0x00,0xAE,0x03,0xA0,0x02,0x50,0x04,0x50,0x04,0x48,0x04,0x48,0x04,0x48,0x04,0x84,0x02,0x84,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"%",5*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x2C,0x00,0x98,0x07,0x1C,0x01,0x1A,0x01,0x33,0x01,0x33,0x01,0x63,0x01,0xE3,0x00,0xC3,0x08,0xC6,0x09,0x3C,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*"&",6*/ +{0x00,0x00,0x00,0x00,0x0C,0x00,0x1C,0x00,0x10,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/ +{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x40,0x00,0x40,0x00,0x80,0x00,0x80,0x00,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x00},/*"(",8*/ +{0x00,0x00,0x00,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x20,0x00,0x20,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x10,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x00,0x00},/*")",9*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0xC0,0x00,0x40,0x00,0x46,0x0C,0x4E,0x0F,0xD0,0x01,0xF0,0x01,0x5E,0x0F,0x46,0x0C,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"*",10*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0xFE,0x0F,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"+",11*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1C,0x00,0x10,0x00,0x10,0x00,0x08,0x00,0x04,0x00},/*",",12*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"-",13*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/ +{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x06,0x00,0x02,0x00,0x03,0x00,0x01,0x00,0x01,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x60,0x00,0x20,0x00,0x20,0x00,0x10,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x06,0x00,0x02,0x00,0x00,0x00},/*"/",15*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x98,0x01,0x0C,0x03,0x0C,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0x03,0x0C,0x03,0x98,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"0",16*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x7C,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"1",17*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x84,0x01,0x02,0x03,0x06,0x03,0x06,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0xC0,0x00,0x60,0x00,0x20,0x00,0x10,0x00,0x08,0x02,0x04,0x02,0x06,0x02,0xFE,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"2",18*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0xC6,0x00,0x86,0x01,0x86,0x01,0x80,0x01,0x80,0x01,0xC0,0x00,0x70,0x00,0x80,0x01,0x00,0x01,0x00,0x03,0x00,0x03,0x06,0x03,0x06,0x03,0x86,0x01,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"3",19*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x80,0x01,0xC0,0x01,0xA0,0x01,0xA0,0x01,0x90,0x01,0x88,0x01,0x88,0x01,0x84,0x01,0x82,0x01,0xFE,0x0F,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*"4",20*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x03,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xF4,0x00,0x8C,0x01,0x04,0x03,0x00,0x03,0x00,0x03,0x06,0x03,0x06,0x03,0x82,0x01,0x84,0x01,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"5",21*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x01,0x18,0x03,0x0C,0x03,0x0C,0x00,0x04,0x00,0x06,0x00,0xE6,0x01,0x16,0x03,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x04,0x06,0x0C,0x02,0x18,0x03,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"6",22*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x07,0x0C,0x06,0x04,0x02,0x04,0x01,0x00,0x01,0x00,0x01,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"7",23*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x01,0x0C,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0x02,0x1C,0x03,0xF0,0x00,0xC8,0x01,0x0C,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0x03,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"8",24*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x0C,0x01,0x0C,0x03,0x06,0x02,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x8C,0x06,0x78,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x0C,0x01,0x8C,0x01,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"9",25*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x40,0x00,0x20,0x00,0x20,0x00},/*";",27*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x00,0x40,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x80,0x00,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00},/*"<",28*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"=",29*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x80,0x00,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x00,0x40,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*">",30*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x03,0x18,0x06,0x04,0x0C,0x04,0x0C,0x0C,0x0C,0x0C,0x0C,0x00,0x07,0x80,0x01,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"?",31*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x18,0x03,0x0C,0x02,0xCC,0x05,0x64,0x05,0x66,0x05,0xA6,0x05,0xB6,0x04,0xB6,0x04,0xB6,0x04,0xB6,0x04,0xB6,0x02,0xE4,0x01,0x0C,0x04,0x0C,0x02,0x18,0x03,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"@",32*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x50,0x00,0xD0,0x00,0x90,0x00,0x90,0x00,0x88,0x00,0x88,0x01,0x08,0x01,0xF8,0x01,0x04,0x03,0x04,0x03,0x04,0x02,0x02,0x02,0x02,0x06,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00},/*"A",33*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x8C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x8C,0x01,0xFC,0x00,0x0C,0x03,0x0C,0x02,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x03,0xFE,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"B",34*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x03,0x18,0x03,0x0C,0x06,0x0C,0x04,0x04,0x04,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x04,0x0C,0x04,0x0C,0x02,0x18,0x03,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"C",35*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x8C,0x01,0x0C,0x03,0x0C,0x03,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x03,0x0C,0x03,0x8C,0x01,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"D",36*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x03,0x06,0x03,0x06,0x04,0x06,0x04,0x06,0x00,0x86,0x00,0x86,0x00,0xFE,0x00,0x86,0x00,0x86,0x00,0x86,0x00,0x06,0x00,0x06,0x04,0x06,0x04,0x06,0x02,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"E",37*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x03,0x06,0x03,0x06,0x04,0x06,0x04,0x06,0x00,0x86,0x00,0x86,0x00,0xFE,0x00,0x86,0x00,0x86,0x00,0x86,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"F",38*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x18,0x01,0x0C,0x02,0x0C,0x02,0x04,0x02,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0xC6,0x0F,0x06,0x03,0x06,0x03,0x0C,0x03,0x0C,0x03,0x18,0x03,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"G",39*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0xFE,0x07,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00},/*"H",40*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x03,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"I",41*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x07,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC6,0x00,0x66,0x00,0x3C,0x00},/*"J",42*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCF,0x03,0x86,0x01,0xC6,0x00,0x46,0x00,0x26,0x00,0x16,0x00,0x36,0x00,0x2E,0x00,0x6E,0x00,0x46,0x00,0xC6,0x00,0x86,0x00,0x86,0x01,0x06,0x01,0x06,0x03,0x8F,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*"K",43*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x04,0x06,0x04,0x06,0x02,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"L",44*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x86,0x03,0x86,0x03,0x8E,0x03,0x8E,0x03,0x4E,0x03,0x4E,0x03,0x4A,0x03,0x5A,0x03,0x5A,0x03,0x3A,0x03,0x32,0x03,0x32,0x03,0x32,0x03,0x12,0x03,0x87,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*"M",45*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8E,0x0F,0x0C,0x02,0x1C,0x02,0x1C,0x02,0x34,0x02,0x34,0x02,0x64,0x02,0x64,0x02,0x44,0x02,0xC4,0x02,0x84,0x02,0x84,0x03,0x84,0x03,0x04,0x03,0x04,0x03,0x1F,0x02,0x00,0x00,0x00,0x00,0x00,0x00},/*"N",46*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x98,0x01,0x0C,0x03,0x0C,0x02,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0x02,0x0C,0x03,0x98,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"O",47*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x06,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x86,0x03,0xFE,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"P",48*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x98,0x01,0x0C,0x03,0x0C,0x02,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x76,0x06,0x4C,0x02,0xCC,0x03,0x98,0x01,0xF0,0x00,0x80,0x07,0x00,0x03,0x00,0x00},/*"Q",49*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x01,0x06,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x03,0xFE,0x00,0x46,0x00,0xC6,0x00,0x86,0x00,0x86,0x01,0x06,0x03,0x06,0x03,0x06,0x06,0x0F,0x0E,0x00,0x00,0x00,0x00,0x00,0x00},/*"R",50*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x02,0x0C,0x03,0x06,0x02,0x06,0x02,0x06,0x00,0x0E,0x00,0x3C,0x00,0xF8,0x00,0xE0,0x03,0x80,0x03,0x00,0x07,0x02,0x06,0x02,0x06,0x06,0x06,0x0C,0x03,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"S",51*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x07,0x62,0x04,0x61,0x08,0x61,0x08,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xF8,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"T",52*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x07,0x0C,0x02,0x0C,0x02,0x0C,0x02,0x0C,0x02,0x0C,0x02,0x0C,0x02,0x0C,0x02,0x0C,0x02,0x0C,0x02,0x0C,0x02,0x0C,0x02,0x0C,0x02,0x0C,0x02,0x18,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"U",53*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x07,0x06,0x02,0x04,0x01,0x04,0x01,0x0C,0x01,0x0C,0x01,0x88,0x00,0x88,0x00,0x98,0x00,0x98,0x00,0x50,0x00,0x50,0x00,0x70,0x00,0x30,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"V",54*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF7,0x0E,0x62,0x04,0x42,0x04,0x46,0x04,0x46,0x04,0x64,0x02,0x64,0x02,0xE4,0x02,0xE4,0x02,0x9C,0x02,0x9C,0x01,0x98,0x01,0x98,0x01,0x88,0x01,0x88,0x00,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"W",55*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x07,0x0C,0x01,0x08,0x01,0x18,0x01,0x90,0x00,0xB0,0x00,0x60,0x00,0x20,0x00,0x60,0x00,0x60,0x00,0xD0,0x00,0x90,0x00,0x88,0x01,0x08,0x01,0x04,0x03,0x8E,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*"X",56*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x06,0x04,0x04,0x02,0x0C,0x02,0x08,0x01,0x18,0x01,0xB8,0x00,0xB0,0x00,0x70,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xF8,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"Y",57*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x07,0x0C,0x02,0x06,0x03,0x02,0x01,0x80,0x01,0x80,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x10,0x00,0x18,0x00,0x08,0x04,0x0C,0x04,0x04,0x02,0xFE,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"Z",58*/ +{0x00,0x00,0x00,0x00,0xE0,0x03,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0xE0,0x03,0x00,0x00},/*"[",59*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x20,0x00,0x20,0x00,0x40,0x00,0x40,0x00,0xC0,0x00,0x80,0x00,0x80,0x00,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x04},/*"\",60*/ +{0x00,0x00,0x00,0x00,0x7C,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7C,0x00,0x00,0x00},/*"]",61*/ +{0x00,0x00,0x60,0x00,0x90,0x00,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x0F},/*"_",63*/ +{0x00,0x00,0x00,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x01,0x0C,0x03,0x0C,0x03,0x00,0x03,0xE0,0x03,0x1C,0x03,0x0E,0x03,0x06,0x03,0x06,0x03,0x8E,0x0B,0x7C,0x0E,0x00,0x00,0x00,0x00,0x00,0x00},/*"a",65*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0xCC,0x01,0x3C,0x03,0x1C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x02,0x1C,0x03,0xE4,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"b",66*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x8C,0x01,0x8C,0x01,0x86,0x01,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x02,0x0C,0x02,0x0C,0x01,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"c",67*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xC0,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x78,0x03,0x8C,0x03,0x0C,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x04,0x03,0x8C,0x07,0x78,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"d",68*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x01,0x18,0x03,0x08,0x02,0x0C,0x06,0x0C,0x06,0xFC,0x07,0x0C,0x00,0x0C,0x00,0x18,0x04,0x18,0x02,0xE0,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"e",69*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x03,0x60,0x06,0x30,0x06,0x30,0x00,0x30,0x00,0xFE,0x01,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"f",70*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0xD8,0x06,0x8C,0x01,0x8C,0x01,0x8C,0x01,0x98,0x01,0xF8,0x00,0x0C,0x00,0xFC,0x00,0xCC,0x03,0x06,0x03,0x06,0x03,0x8E,0x03,0xF8,0x00},/*"g",71*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0xEC,0x01,0x1C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x9E,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*"h",72*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x7C,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"i",73*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x01,0xC0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0xF0,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xCC,0x00,0x7C,0x00},/*"j",74*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x0E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x8C,0x03,0x8C,0x00,0x8C,0x00,0x4C,0x00,0x6C,0x00,0x5C,0x00,0x8C,0x00,0x8C,0x01,0x0C,0x01,0x0C,0x03,0x9E,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*"k",75*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x7C,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"l",76*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x07,0xEE,0x06,0x66,0x06,0x66,0x06,0x66,0x06,0x66,0x06,0x66,0x06,0x66,0x06,0x66,0x06,0x66,0x06,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00},/*"m",77*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x1C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x9E,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*"n",78*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x98,0x01,0x0C,0x03,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0x03,0x0C,0x03,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"o",79*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x01,0x1C,0x03,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x0C,0x03,0x1C,0x03,0xEC,0x01,0x0C,0x00,0x0C,0x00,0x3E,0x00},/*"p",80*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x02,0x8C,0x03,0x0C,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x06,0x03,0x04,0x03,0x8C,0x03,0x78,0x03,0x00,0x03,0x00,0x03,0xC0,0x07},/*"q",81*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9F,0x03,0x58,0x06,0x38,0x06,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"r",82*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x03,0x1C,0x03,0x0C,0x02,0x0C,0x02,0x38,0x00,0xF0,0x00,0xC0,0x03,0x04,0x03,0x04,0x03,0x8C,0x03,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"s",83*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x20,0x00,0x30,0x00,0x30,0x00,0xFE,0x01,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x02,0x30,0x02,0xE0,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"t",84*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x02,0x8E,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x0C,0x03,0x9C,0x07,0x78,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"u",85*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x07,0x0C,0x02,0x08,0x01,0x08,0x01,0x18,0x01,0x90,0x00,0xB0,0x00,0xB0,0x00,0x60,0x00,0x60,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"v",86*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF7,0x0E,0x62,0x04,0x46,0x04,0x64,0x02,0x64,0x02,0xEC,0x02,0x9C,0x01,0x98,0x01,0x98,0x01,0x98,0x01,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"w",87*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBC,0x07,0x18,0x01,0x10,0x01,0xB0,0x00,0x60,0x00,0x60,0x00,0xE0,0x00,0x90,0x00,0x08,0x01,0x08,0x03,0x9E,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*"x",88*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9E,0x07,0x08,0x01,0x08,0x01,0x08,0x01,0x90,0x00,0x90,0x00,0xB0,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x20,0x00,0x20,0x00,0x24,0x00,0x1C,0x00},/*"y",89*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x84,0x01,0xC4,0x00,0x44,0x00,0x60,0x00,0x20,0x00,0x30,0x00,0x18,0x02,0x08,0x02,0x0C,0x03,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"z",90*/ +{0x00,0x00,0x00,0x00,0x00,0x03,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x40,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x03,0x00,0x00},/*"{",91*/ +{0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00},/*"|",92*/ +{0x00,0x00,0x00,0x00,0x0C,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x20,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x0C,0x00,0x00,0x00},/*"}",93*/ +{0x00,0x00,0x1C,0x00,0x22,0x04,0xC2,0x04,0x80,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",94*/ +}; +#endif + +#ifdef ASCII_3216 +const unsigned char ascii_3216[][64]={ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0xC0,0x03,0xC0,0x03,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x1C,0xE0,0x1C,0xF0,0x1E,0x70,0x0E,0x38,0x07,0x18,0x03,0x08,0x01,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0xFE,0x7F,0xFE,0x7F,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0xFE,0x7F,0xFE,0x7F,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"#",3*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0xC0,0x07,0x60,0x19,0x10,0x31,0x18,0x31,0x18,0x39,0x18,0x39,0x38,0x01,0x70,0x01,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0F,0x00,0x1D,0x00,0x39,0x00,0x31,0x1C,0x31,0x1C,0x31,0x0C,0x31,0x0C,0x11,0x18,0x0D,0xE0,0x07,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00},/*"$",4*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x10,0x36,0x18,0x63,0x08,0x63,0x0C,0x63,0x04,0x63,0x04,0x63,0x02,0x63,0x02,0x63,0x01,0x36,0x1D,0x9C,0x37,0x80,0x22,0x80,0x63,0x40,0x63,0x40,0x63,0x20,0x63,0x20,0x63,0x30,0x63,0x10,0x22,0x18,0x36,0x08,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"%",5*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x98,0x01,0x8C,0x01,0x8C,0x01,0x8C,0x01,0x8C,0x01,0x8C,0x00,0xCC,0x00,0x78,0x00,0x18,0x3E,0x1C,0x08,0x36,0x08,0x32,0x08,0x63,0x04,0x63,0x04,0xC3,0x04,0xC3,0x03,0x83,0x43,0x06,0x43,0x8E,0x26,0x78,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"&",6*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x3C,0x00,0x3C,0x00,0x30,0x00,0x30,0x00,0x10,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x03,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x00},/*"(",8*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x30,0x00,0x20,0x00,0x60,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x60,0x00,0x60,0x00,0x30,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x00,0x00},/*")",9*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x80,0x03,0x00,0x01,0x1C,0x71,0x3C,0x79,0x78,0x3D,0xC0,0x07,0x00,0x01,0xC0,0x07,0x78,0x3D,0x3C,0x79,0x1C,0x71,0x00,0x01,0x80,0x03,0x80,0x03,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"*",10*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xFC,0x7F,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"+",11*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x3C,0x00,0x3C,0x00,0x30,0x00,0x30,0x00,0x10,0x00,0x0C,0x00,0x06,0x00},/*",",12*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"-",13*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x3C,0x00,0x3C,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x60,0x00,0x20,0x00,0x30,0x00,0x10,0x00,0x18,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x06,0x00,0x02,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x00,0xC0,0x00,0x40,0x00,0x60,0x00,0x20,0x00,0x30,0x00,0x10,0x00,0x18,0x00,0x08,0x00,0x0C,0x00,0x04,0x00,0x06,0x00,0x02,0x00,0x00,0x00,0x00,0x00},/*"/",15*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x07,0x60,0x0C,0x30,0x18,0x18,0x30,0x18,0x30,0x18,0x20,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x18,0x20,0x18,0x30,0x18,0x30,0x30,0x18,0x60,0x0C,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"0",16*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0xF8,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xC0,0x03,0xF8,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"1",17*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x10,0x1C,0x08,0x18,0x04,0x30,0x04,0x30,0x0C,0x30,0x0C,0x30,0x00,0x30,0x00,0x18,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x00,0x40,0x00,0x20,0x20,0x10,0x20,0x08,0x20,0x04,0x30,0xFC,0x1F,0xFC,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"2",18*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x03,0x18,0x0E,0x0C,0x0C,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x00,0x18,0x00,0x0C,0x00,0x06,0xC0,0x03,0x00,0x0E,0x00,0x18,0x00,0x10,0x00,0x30,0x00,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x10,0x0C,0x18,0x18,0x0C,0xE0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"3",19*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0E,0x00,0x0E,0x00,0x0F,0x80,0x0E,0x80,0x0E,0x40,0x0E,0x60,0x0E,0x20,0x0E,0x10,0x0E,0x10,0x0E,0x08,0x0E,0x04,0x0E,0x04,0x0E,0xFE,0x7F,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0xC0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"4",20*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x3F,0xF0,0x3F,0x10,0x00,0x10,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0xC8,0x07,0x28,0x0C,0x18,0x18,0x08,0x10,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x0C,0x30,0x0C,0x30,0x04,0x18,0x04,0x18,0x08,0x0C,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"5",21*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x10,0x20,0x30,0x10,0x30,0x18,0x00,0x18,0x00,0x08,0x00,0x0C,0x00,0x8C,0x0F,0x6C,0x18,0x3C,0x30,0x1C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x18,0x60,0x18,0x20,0x30,0x30,0x60,0x18,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"6",22*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x3F,0xF8,0x3F,0x1C,0x10,0x0C,0x08,0x04,0x08,0x04,0x04,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x01,0x80,0x00,0x80,0x00,0x80,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"7",23*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x30,0x0C,0x18,0x18,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x1C,0x30,0x38,0x18,0x70,0x08,0xE0,0x07,0xB0,0x07,0x18,0x0E,0x0C,0x1C,0x06,0x38,0x06,0x30,0x06,0x30,0x06,0x30,0x06,0x30,0x0C,0x18,0x18,0x0C,0xE0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"8",24*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x03,0x18,0x04,0x0C,0x08,0x0C,0x18,0x06,0x10,0x06,0x30,0x06,0x30,0x06,0x30,0x06,0x30,0x06,0x38,0x0C,0x3C,0x18,0x36,0xF0,0x31,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x18,0x0C,0x0C,0x0C,0x06,0x0C,0x03,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"9",25*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0xC0,0x03,0xC0,0x03,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0xC0,0x03,0xC0,0x03,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x00,0x00},/*";",27*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x03,0x80,0x01,0xC0,0x00,0x60,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0xC0,0x00,0x80,0x01,0x00,0x03,0x00,0x06,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"<",28*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"=",29*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x60,0x00,0xC0,0x00,0x80,0x01,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x80,0x01,0xC0,0x00,0x60,0x00,0x20,0x00,0x10,0x00,0x08,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*">",30*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x07,0x30,0x18,0x08,0x30,0x08,0x60,0x0C,0x60,0x1C,0x60,0x1C,0x60,0x1C,0x60,0x00,0x30,0x00,0x1C,0x00,0x06,0x00,0x01,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0xC0,0x03,0xC0,0x03,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"?",31*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x07,0x60,0x18,0x10,0x30,0x18,0x20,0x0C,0x2F,0x8C,0x4D,0x86,0x4C,0xC6,0x4C,0xC6,0x4C,0x66,0x4C,0x66,0x44,0x66,0x44,0x66,0x26,0x66,0x26,0x66,0x15,0xCC,0x1C,0x0C,0x40,0x08,0x20,0x18,0x30,0x30,0x18,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"@",32*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x01,0x40,0x01,0x60,0x03,0x20,0x03,0x20,0x03,0x20,0x03,0x30,0x06,0x10,0x06,0x10,0x06,0x10,0x06,0xF8,0x0F,0x08,0x0C,0x08,0x0C,0x08,0x0C,0x0C,0x0C,0x04,0x18,0x04,0x18,0x06,0x18,0x1F,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"A",33*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x07,0x18,0x1C,0x18,0x38,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x18,0x18,0x0C,0xF8,0x07,0x18,0x18,0x18,0x30,0x18,0x20,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x30,0x18,0x18,0xFE,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"B",34*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x27,0x60,0x38,0x10,0x30,0x18,0x20,0x0C,0x40,0x0C,0x40,0x04,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x0C,0x40,0x0C,0x40,0x0C,0x20,0x18,0x30,0x30,0x18,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"C",35*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x03,0x18,0x0E,0x18,0x18,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x30,0x18,0x30,0x18,0x10,0x18,0x18,0x18,0x0E,0xFE,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"D",36*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,0x18,0x30,0x18,0x20,0x18,0x60,0x18,0x40,0x18,0x00,0x18,0x08,0x18,0x08,0x18,0x0C,0xF8,0x0F,0x18,0x0C,0x18,0x08,0x18,0x08,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x40,0x18,0x40,0x18,0x20,0x18,0x30,0xFE,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"E",37*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x18,0x70,0x18,0x40,0x18,0xC0,0x18,0x80,0x18,0x00,0x18,0x10,0x18,0x10,0x18,0x18,0xF8,0x1F,0x18,0x18,0x18,0x10,0x18,0x10,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"F",38*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x13,0x70,0x1C,0x10,0x10,0x18,0x10,0x0C,0x20,0x0C,0x20,0x04,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0xFC,0x06,0x30,0x06,0x30,0x0C,0x30,0x0C,0x30,0x18,0x30,0x18,0x30,0x30,0x08,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"G",39*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x7E,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0xFC,0x1F,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x3F,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"H",40*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x1F,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xF8,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"I",41*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x7F,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x0E,0x06,0x0E,0x03,0x8E,0x01,0xFC,0x00},/*"J",42*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x7C,0x18,0x18,0x18,0x08,0x18,0x04,0x18,0x06,0x18,0x02,0x18,0x01,0x98,0x01,0x98,0x01,0xD8,0x01,0xB8,0x03,0x38,0x03,0x18,0x07,0x18,0x06,0x18,0x0E,0x18,0x0C,0x18,0x1C,0x18,0x18,0x18,0x30,0x18,0x30,0x7E,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"K",43*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x40,0x18,0x40,0x18,0x20,0x18,0x30,0xFE,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"L",44*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF8,0x1C,0x38,0x1C,0x38,0x1C,0x38,0x1C,0x3C,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x36,0x74,0x32,0x64,0x32,0x64,0x32,0x64,0x32,0x64,0x31,0xC4,0x31,0xC4,0x31,0xC4,0x31,0xC4,0x30,0xC4,0x30,0x84,0x30,0x9F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"M",45*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x7C,0x1C,0x10,0x3C,0x10,0x34,0x10,0x34,0x10,0x74,0x10,0x64,0x10,0xE4,0x10,0xC4,0x10,0xC4,0x11,0x84,0x11,0x84,0x13,0x04,0x13,0x04,0x17,0x04,0x16,0x04,0x1E,0x04,0x1C,0x04,0x1C,0x04,0x1C,0x04,0x18,0x1F,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"N",46*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x03,0x30,0x0C,0x18,0x18,0x08,0x10,0x0C,0x30,0x0C,0x30,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x0C,0x20,0x0C,0x30,0x08,0x10,0x18,0x18,0x30,0x0C,0xC0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"O",47*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x0F,0x18,0x18,0x18,0x30,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x30,0x18,0x18,0xF8,0x0F,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"P",48*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x03,0x30,0x0C,0x18,0x18,0x0C,0x10,0x0C,0x30,0x0C,0x20,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0x06,0x60,0xE4,0x61,0x2C,0x33,0x1C,0x32,0x18,0x16,0x30,0x0E,0xC0,0x07,0x00,0x4C,0x00,0x7C,0x00,0x38,0x00,0x00,0x00,0x00},/*"Q",49*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x07,0x18,0x1C,0x18,0x38,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x18,0x18,0x0C,0xF8,0x07,0x98,0x03,0x18,0x03,0x18,0x07,0x18,0x06,0x18,0x06,0x18,0x0E,0x18,0x0C,0x18,0x0C,0x18,0x1C,0x18,0x18,0x7E,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"R",50*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x27,0x30,0x38,0x18,0x30,0x0C,0x20,0x0C,0x20,0x0C,0x00,0x0C,0x00,0x18,0x00,0x78,0x00,0xE0,0x03,0x80,0x0F,0x00,0x1E,0x00,0x38,0x00,0x70,0x00,0x60,0x04,0x60,0x04,0x60,0x08,0x60,0x18,0x30,0x38,0x18,0xC8,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"S",51*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x3F,0x8C,0x21,0x84,0x61,0x82,0x41,0x82,0x41,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"T",52*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x7C,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x0C,0x10,0x08,0x08,0x38,0x04,0xE0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"U",53*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0xF8,0x18,0x20,0x18,0x20,0x18,0x20,0x30,0x10,0x30,0x10,0x30,0x10,0x30,0x10,0x60,0x08,0x60,0x08,0x60,0x08,0xE0,0x0C,0xC0,0x04,0xC0,0x04,0xC0,0x04,0x80,0x03,0x80,0x03,0x80,0x03,0x80,0x03,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"V",54*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDF,0xF3,0x86,0x61,0x86,0x21,0x86,0x21,0x8C,0x21,0x0C,0x21,0x8C,0x23,0x8C,0x13,0x8C,0x13,0x8C,0x13,0x4C,0x13,0x58,0x12,0x58,0x16,0x58,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x30,0x0C,0x10,0x04,0x10,0x04,0x10,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"W",55*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x3E,0x18,0x08,0x38,0x08,0x30,0x04,0x30,0x04,0x70,0x02,0x60,0x02,0xE0,0x01,0xC0,0x01,0xC0,0x01,0x80,0x01,0x80,0x03,0x40,0x03,0x40,0x07,0x20,0x06,0x20,0x06,0x10,0x0C,0x10,0x0C,0x08,0x18,0x08,0x18,0x3E,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"X",56*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x7C,0x1C,0x10,0x18,0x10,0x18,0x08,0x30,0x08,0x30,0x0C,0x70,0x04,0x60,0x04,0x60,0x02,0xC0,0x02,0xC0,0x02,0xC0,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"Y",57*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x3F,0x18,0x18,0x08,0x18,0x04,0x0C,0x04,0x0E,0x00,0x06,0x00,0x07,0x00,0x03,0x80,0x03,0x80,0x01,0xC0,0x01,0xC0,0x00,0xE0,0x00,0x60,0x00,0x70,0x00,0x30,0x00,0x38,0x20,0x18,0x20,0x1C,0x10,0x0C,0x18,0xFE,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"Z",58*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x3F,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0xC0,0x3F,0x00,0x00,0x00,0x00},/*"[",59*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x18,0x00,0x18,0x00,0x10,0x00,0x30,0x00,0x20,0x00,0x60,0x00,0x60,0x00,0x40,0x00,0xC0,0x00,0x80,0x00,0x80,0x01,0x80,0x01,0x00,0x01,0x00,0x03,0x00,0x02,0x00,0x06,0x00,0x06,0x00,0x04,0x00,0x0C,0x00,0x08,0x00,0x18,0x00,0x18,0x00,0x10,0x00,0x30,0x00,0x20,0x00,0x00},/*"\",60*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x03,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0xFC,0x03,0x00,0x00,0x00,0x00},/*"]",61*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x07,0xC0,0x06,0x20,0x08,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF},/*"_",63*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0xC0,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x03,0x18,0x06,0x0C,0x0C,0x0C,0x0C,0x00,0x0C,0x80,0x0F,0x70,0x0C,0x1C,0x0C,0x0C,0x0C,0x06,0x0C,0x06,0x0C,0x06,0x4C,0x0C,0x4F,0xF8,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"a",65*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x1E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x0F,0xD8,0x18,0x38,0x30,0x38,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x20,0x38,0x30,0x78,0x18,0xC8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"b",66*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x07,0x70,0x0C,0x18,0x18,0x18,0x18,0x0C,0x18,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x20,0x18,0x20,0x18,0x10,0x30,0x08,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"c",67*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x1E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0xE0,0x1B,0x30,0x1C,0x18,0x18,0x18,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x0C,0x18,0x08,0x18,0x18,0x1C,0x30,0x7A,0xE0,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"d",68*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x07,0x30,0x0C,0x18,0x18,0x08,0x10,0x0C,0x30,0x0C,0x30,0xFC,0x3F,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x20,0x18,0x10,0x70,0x18,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"e",69*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x80,0xC3,0x80,0xC0,0xC0,0xC0,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xFC,0x1F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xF8,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"f",70*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x77,0x30,0x6C,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x10,0x18,0x30,0x0C,0xF0,0x07,0x18,0x00,0x18,0x00,0xF0,0x0F,0xF0,0x3F,0x08,0x70,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x38,0x38,0xE0,0x0F},/*"g",71*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x1E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x98,0x0F,0xD8,0x18,0x38,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x7E,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"h",72*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x80,0x03,0x80,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF8,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xF8,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"i",73*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x80,0x1F,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x18,0x0C,0x18,0x06,0xF0,0x03},/*"j",74*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x1E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x3E,0x18,0x0C,0x18,0x06,0x18,0x03,0x18,0x01,0x98,0x01,0xD8,0x01,0x38,0x03,0x18,0x07,0x18,0x06,0x18,0x0C,0x18,0x1C,0x18,0x18,0x7E,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"k",75*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xF8,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0xF8,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"l",76*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0xEE,0x1C,0x9C,0x33,0x8C,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x31,0x8C,0x31,0xDE,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"m",77*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x1E,0x0F,0xD8,0x18,0x38,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x7E,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"n",78*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x07,0x70,0x1C,0x10,0x30,0x18,0x30,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x0C,0x60,0x18,0x30,0x18,0x30,0x30,0x18,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"o",79*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x9E,0x0F,0x58,0x18,0x38,0x30,0x18,0x20,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x18,0x30,0x38,0x30,0x78,0x18,0x98,0x07,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x7E,0x00},/*"p",80*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x23,0x30,0x3C,0x18,0x38,0x18,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x08,0x30,0x18,0x38,0x30,0x3C,0xE0,0x33,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0xFC},/*"q",81*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x7E,0x3C,0x60,0x66,0x60,0x61,0xE0,0x00,0xE0,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xFE,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"r",82*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x27,0x30,0x38,0x18,0x30,0x18,0x20,0x18,0x00,0x70,0x00,0xE0,0x03,0x80,0x0F,0x00,0x1C,0x04,0x30,0x04,0x30,0x0C,0x30,0x1C,0x18,0xEC,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"s",83*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xC0,0x00,0xE0,0x00,0xFC,0x1F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x20,0xC0,0x20,0x80,0x11,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"t",84*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x20,0x1E,0x3C,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x30,0x18,0x38,0x30,0xF4,0xE0,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"u",85*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x3C,0x18,0x18,0x18,0x08,0x38,0x08,0x30,0x04,0x30,0x04,0x70,0x02,0x60,0x02,0x60,0x02,0xE0,0x01,0xC0,0x01,0xC0,0x01,0xC0,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"v",86*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDF,0xF7,0x8E,0x63,0x0C,0x23,0x8C,0x23,0x8C,0x23,0x98,0x13,0x98,0x13,0x58,0x16,0x58,0x16,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x20,0x04,0x20,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"w",87*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x3E,0x70,0x08,0x70,0x04,0xE0,0x04,0xC0,0x02,0xC0,0x01,0x80,0x03,0x80,0x03,0x40,0x07,0x60,0x06,0x20,0x0C,0x10,0x0C,0x18,0x18,0x3E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"x",88*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x7C,0x18,0x18,0x18,0x08,0x30,0x08,0x30,0x08,0x30,0x04,0x60,0x04,0x60,0x04,0xC0,0x02,0xC0,0x02,0xC0,0x02,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x80,0x00,0x80,0x00,0x4C,0x00,0x3C,0x00},/*"y",89*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x1F,0x0C,0x0C,0x04,0x0E,0x04,0x06,0x00,0x03,0x80,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x20,0x30,0x20,0x38,0x30,0x1C,0x18,0xFC,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"z",90*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x80,0x01,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x30,0x00,0x00},/*"{",91*/ +{0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01},/*"|",92*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x10,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x40,0x00,0x80,0x01,0x40,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x10,0x00,0x0C,0x00,0x00,0x00},/*"}",93*/ +{0x00,0x00,0x38,0x00,0xC4,0x00,0x86,0x40,0x02,0x61,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",94*/ +}; +#endif + +#ifdef LOGO_M +const unsigned char logo_M[] = { + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xf8, 0x00, 0x00, 0xff, 0xc0, 0x00, + 0x00, 0x07, 0xfc, 0x00, 0x01, 0xff, 0xe0, 0x00, + 0x00, 0x0f, 0xff, 0x00, 0x07, 0xff, 0xf0, 0x00, + 0x00, 0x1f, 0xff, 0x80, 0x0f, 0xff, 0xf0, 0x00, + 0x00, 0x3f, 0xff, 0xc0, 0x1f, 0xff, 0xf8, 0x00, + 0x00, 0x3f, 0xff, 0xe0, 0x7f, 0xff, 0xf8, 0x00, + 0x00, 0x3f, 0xff, 0xf0, 0xff, 0xff, 0xf8, 0x00, + 0x00, 0x3f, 0xff, 0xfb, 0xff, 0xff, 0xf8, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0x9f, 0xf8, 0x00, + 0x00, 0x3f, 0xff, 0xff, 0xff, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xf3, 0xff, 0xfc, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xf1, 0xff, 0xf8, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xf0, 0xff, 0xe0, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xf0, 0x7f, 0x80, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xf0, 0x1e, 0x00, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xf0, 0x08, 0x00, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xf0, 0x00, 0x0e, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xf0, 0x00, 0x1e, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xe0, 0x00, 0x7e, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xe0, 0x00, 0xfe, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xe0, 0x01, 0xfe, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xe0, 0x03, 0xfe, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xe0, 0x07, 0xfe, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xe0, 0x07, 0xfe, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xe0, 0x03, 0xfe, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xe0, 0x01, 0xfe, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xe0, 0x00, 0xfe, 0x0f, 0xf8, 0x00, + 0x00, 0x3f, 0xe0, 0x00, 0x7e, 0x0f, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +}; +#endif + +#ifdef LOGO_R +const unsigned char logo_R[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xc0, + 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xe0, + 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xe0, + 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf8, + 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf8, + 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfc, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfc, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfc, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfc, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfc, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, + 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf0, + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x03, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, + 0x03, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x03, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, + 0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, + 0x07, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x07, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x07, 0xff, 0xf8, 0xff, 0xff, 0x80, 0x00, + 0x07, 0xff, 0xf0, 0xff, 0xff, 0x80, 0x00, + 0x07, 0xff, 0xf0, 0x7f, 0xff, 0x80, 0x00, + 0x0f, 0xff, 0xf0, 0x7f, 0xff, 0xc0, 0x00, + 0x0f, 0xff, 0xf0, 0x7f, 0xff, 0xc0, 0x00, + 0x0f, 0xff, 0xf0, 0x3f, 0xff, 0xe0, 0x00, + 0x0f, 0xff, 0xf0, 0x3f, 0xff, 0xe0, 0x00, + 0x0f, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x00, + 0x1f, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x00, + 0x1f, 0xff, 0xe0, 0x0f, 0xff, 0xf8, 0x00, + 0x1f, 0xff, 0xe0, 0x0f, 0xff, 0xf8, 0x00, + 0x1f, 0xff, 0xe0, 0x0f, 0xff, 0xf8, 0x00, + 0x1f, 0xff, 0xc0, 0x07, 0xff, 0xfc, 0x00, + 0x1f, 0xff, 0xc0, 0x07, 0xff, 0xfc, 0x00, + 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfe, 0x00, + 0x3f, 0xff, 0xc0, 0x03, 0xff, 0xfe, 0x00, + 0x3f, 0xff, 0xc0, 0x01, 0xff, 0xff, 0x00, + 0x3f, 0xff, 0x80, 0x01, 0xff, 0xff, 0x00, + 0x3f, 0xff, 0x80, 0x01, 0xff, 0xff, 0x80, + 0x7f, 0xff, 0x80, 0x00, 0xff, 0xff, 0x80, + 0x7f, 0xff, 0x80, 0x00, 0xff, 0xff, 0xc0, + 0x3f, 0xff, 0x00, 0x00, 0x7f, 0xff, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif + +#ifdef HUAJI +const unsigned char huaji[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xe0, 0x00, 0x1f, 0xc0, 0x00, + 0x00, 0x0f, 0xf0, 0x00, 0x1f, 0xe0, 0x00, + 0x00, 0x0c, 0x70, 0x00, 0x38, 0x70, 0x00, + 0x00, 0x18, 0x18, 0x00, 0x30, 0x70, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x20, 0x30, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xc0, 0x00, 0x01, 0xfe, 0x00, + 0x00, 0xff, 0xfc, 0x00, 0x0f, 0xff, 0x00, + 0x01, 0xe0, 0x0f, 0x00, 0x38, 0x01, 0xc0, + 0x03, 0x00, 0x03, 0x80, 0xe0, 0x00, 0x60, + 0x06, 0x00, 0x00, 0xc1, 0xc0, 0x00, 0x30, + 0x0c, 0xc0, 0x00, 0xc1, 0xb0, 0x00, 0x18, + 0x0d, 0xc0, 0x00, 0x63, 0x78, 0x00, 0x18, + 0x0d, 0xff, 0xf8, 0x43, 0x7f, 0xfe, 0x18, + 0x0f, 0xff, 0x7f, 0xc1, 0xff, 0xcf, 0xf0, + 0x07, 0xe0, 0x07, 0x81, 0xf8, 0x01, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x0c, 0x00, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x0e, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x00, 0x70, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x00, 0xe0, 0x00, + 0x00, 0x01, 0xc0, 0x00, 0x01, 0xc0, 0x00, + 0x00, 0x00, 0xe0, 0x00, 0x07, 0x80, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x00, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif \ No newline at end of file diff --git a/assets/User_code/device/oid.c b/assets/User_code/device/oid.c new file mode 100644 index 0000000..6570526 --- /dev/null +++ b/assets/User_code/device/oid.c @@ -0,0 +1,467 @@ +/* + oid编码器驱动 +*/ + +/*编码器can通信的默认波特率为500kHZ*/ +/* Includes ----------------------------------------------------------------- */ +#include "device/oid.h" +#include "bsp/time.h" +#include "mm.h" +/* Private function prototypes ---------------------------------------------- */ + +static OID_CANManager_t* OID_GetCANManager(BSP_CAN_t can); + +/* Private functions -------------------------------------------------------- */ + +static OID_CANManager_t *can_managers[BSP_CAN_NUM] = {NULL}; + +/** + * @brief 接收数据处理 + * @param[in] none + * @retval none + */ +static void OID_ParseFeedbackFrame( OID_t *encoder , uint8_t *rx_data ) +{ + if(encoder->param.id == rx_data[1])//判断编码器id + { + switch(rx_data[2])//判断指令 + { + case 0x01: + encoder->feedback.angle_fbk = rx_data[3]|rx_data[4]<<8|rx_data[5]<<16|rx_data[6]<<24; + encoder->feedback.angle_360 = encoder->feedback.angle_fbk*360.0f/OID_RESOLUTION; + encoder->feedback.angle_2PI = encoder->feedback.angle_fbk*M_2PI/OID_RESOLUTION; + break; + + case 0x0A: + encoder->feedback.speed_fbk=rx_data[3]|rx_data[4]<<8|rx_data[5]<<16|rx_data[6]<<24; + encoder->feedback.speed_rpm=encoder->feedback.speed_fbk/OID_RESOLUTION/(0.1f/60.0f); + break; + + default: + break; + } + } +} + +int8_t OID_Update(OID_Param_t *param) +{ + + if (param == NULL) return DEVICE_ERR_NULL; + + OID_CANManager_t *manager = OID_GetCANManager(param->can); + if (manager == NULL) return DEVICE_ERR_NULL; + + OID_t *encoder = NULL; + + for (int i = 0; i < manager->encoder_count; i++) { + if (manager->encoders[i] && manager->encoders[i]->param.id == param->id) { + encoder = manager->encoders[i]; + break; + } + } + + if (encoder == NULL) return DEVICE_ERR_NO_DEV; + + // 从CAN队列获取数据 + BSP_CAN_Message_t rx_msg; + if (BSP_CAN_GetMessage( param->can , param->id , &rx_msg, BSP_CAN_TIMEOUT_IMMEDIATE) != BSP_OK) + { + uint64_t now_time = BSP_TIME_Get(); + if (now_time - encoder->header.last_online_time > 100000) // 100ms超时,单位微秒 + { + encoder->header.online = false; + } + return DEVICE_ERR; + } + + encoder->header.online = true; + encoder->header.last_online_time = BSP_TIME_Get(); + // 处理接收到的数据 + OID_ParseFeedbackFrame( encoder , rx_msg.data ); + return DEVICE_OK; // 没有新数据 +} + +/** + * @brief 更新所有编码器数据 + * @return 更新结果 + */ +int8_t OID_UpdateAll(void) { + int8_t ret = DEVICE_OK; + for (int can = 0; can < BSP_CAN_NUM; can++) { + OID_CANManager_t *manager = OID_GetCANManager((BSP_CAN_t)can); + if (manager == NULL) continue; + + for (int i = 0; i < manager->encoder_count; i++) { + OID_t *encoder = manager->encoders[i]; + if (encoder != NULL) { + if (OID_Update(&encoder->param) != DEVICE_OK) { + ret = DEVICE_ERR; + } + } + } + } + return ret; +} + +/** + * @brief 获取指定CAN总线的管理器 + * @param can CAN总线 + * @return CAN管理器指针 + */ +static OID_CANManager_t* OID_GetCANManager(BSP_CAN_t can) { + if (can >= BSP_CAN_NUM) { + return NULL; + } + + return can_managers[can]; +} + +/** + * @brief 创建CAN管理器 + * @param can CAN总线 + * @return 创建结果 + */ +static int8_t OID_CreateCANManager(BSP_CAN_t can) { + if (can >= BSP_CAN_NUM) return DEVICE_ERR; + if (can_managers[can] != NULL) return DEVICE_OK; + + can_managers[can] = (OID_CANManager_t*)BSP_Malloc(sizeof(OID_CANManager_t)); + if (can_managers[can] == NULL) return DEVICE_ERR; + + memset(can_managers[can], 0, sizeof(OID_CANManager_t)); + can_managers[can]->can = can; + return DEVICE_OK; +} + +/** + * @brief 注册一个欧艾迪编码器 + * @param param 编码器参数 + * @return 注册结果 + */ +int8_t OID_Register(OID_Param_t *param) +{ + if (param == NULL) { + return DEVICE_ERR_NULL; + } + + /* 创建CAN管理器 */ + if (OID_CreateCANManager(param->can) != DEVICE_OK) { + return DEVICE_ERR; + } + + /* 获取CAN管理器 */ + OID_CANManager_t *manager = OID_GetCANManager(param->can); + if (manager == NULL) { + return DEVICE_ERR; + } + + /* 检查是否已注册 */ + for (int i = 0; i < manager->encoder_count; i++) { + if (manager->encoders[i] && manager->encoders[i]->param.id == param->id) { + return DEVICE_ERR_INITED; + } + } + + /* 检查是否已达到最大数量 */ + if (manager->encoder_count >= OID_MAX_NUM) { + return DEVICE_ERR; + } + + /* 分配内存 */ + OID_t *encoder = (OID_t *)BSP_Malloc(sizeof(OID_t)); + if (encoder == NULL) { + return DEVICE_ERR; + } + + /* 初始化电机 */ + memset(encoder, 0, sizeof(OID_t)); + memcpy(&encoder->param, param, sizeof(OID_Param_t)); + encoder->header.online = false; +// encoder->encoder.reverse = param->reverse; + + /* 注册CAN接收ID - DM电机使用Master ID接收反馈 */ + uint16_t feedback_id = param->id; + if (BSP_CAN_RegisterId(param->can, feedback_id, 3) != BSP_OK) { + BSP_Free(encoder); + return DEVICE_ERR; + } + + /* 添加到管理器 */ + manager->encoders[manager->encoder_count] = encoder; + manager->encoder_count++; + + return DEVICE_OK; +} + +/** + * @brief 使编码器离线(设置在线状态为false) + * @param param 编码器参数 + * @return 操作结果 + */ +int8_t OID_Offline(OID_Param_t *param) { + if (param == NULL) { + return DEVICE_ERR_NULL; + } + + OID_t *encoder = OID_GetEncoder(param); + if (encoder == NULL) { + return DEVICE_ERR_NO_DEV; + } + + encoder->header.online = false; + return DEVICE_OK; +} + +/** + * @brief 获取指定编码器的实例指针 + * @param param 编码器参数 + * @return 编码器实例指针 + */ +OID_t* OID_GetEncoder(OID_Param_t *param) { + if (param == NULL) { + return NULL; + } + + OID_CANManager_t *manager = OID_GetCANManager(param->can); + if (manager == NULL) { + return NULL; + } + + /* 查找对应的编码器 */ + for (int i = 0; i < manager->encoder_count; i++) { + OID_t *encoder = manager->encoders[i]; + if (encoder && encoder->param.can == param->can && + encoder->param.id == param->id) { + return encoder; + } + } + + return NULL; +} +/** + * @brief 读取编码器值 + * @param[in] 编码器id + * @retval none + */ +int8_t OID_Read_Value(OID_Param_t *param) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x01; + frame.data[3] = 0x00; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} +/** + * @brief 设置编码器id + * @param[in] 编码器当前id,编码器设置id + * @retval none + */ +int8_t OID_Set_ID(OID_Param_t *param,OID_Param_t *param_new) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x02; + frame.data[3] = param_new->id; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} +/** + * @brief 设置can通讯波特率 0x00:500K(默认);0x01:1M;0x02:250K;0x03:125K;0x04:100K; + * @param[in] 编码器id,编码器设置波特率 + * @retval none + */ +int8_t OID_Set_Baudrate(OID_Param_t *param,OID_Baudrate_t encoder_vaud_rate) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x03; + frame.data[3] = encoder_vaud_rate; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} +/** + * @brief 设置编码器模式 0x00:查询,0x02:自动返回编码器角速度值,0xAA:自动返回编码器值 + * @param[in] 编码器id,编码器设置模式 + * @retval none + */ +int8_t OID_Set_Mode(OID_Param_t *param,OID_Mode_t encoder_mode) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x04; + frame.data[3] = encoder_mode; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} +/** + * @brief 设置编码器自动回传时间(掉电记忆,单位:微秒),数值范围:50~65535(16 位无符号整数) + 注意:设置太短的返回时间后,通过编码器上位机再设置其他参数很容易失败,谨慎使用! + * @param[in] 编码器id,编码器自动回传时间 + * @retval none + */ +int8_t OID_Set_AutoFeedbackTime(OID_Param_t *param,uint8_t encoder_time) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x05; + frame.data[3] = encoder_time; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} +/** + * @brief 设置当前位置值为零点 + * @param[in] 编码器id + * @retval none + */ +int8_t OID_Set_ZeroPoint(OID_Param_t *param) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x06; + frame.data[3] = 0x00; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} +/** + * @brief 设置编码器值递增方向 0x00:顺时针,0x01:逆时针 + * @param[in] 编码器id + * @retval none + */ +int8_t OID_Set_Polarity(OID_Param_t *param,OID_Direction_t encoder_direction) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x07; + frame.data[3] = encoder_direction; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} +/** + * @brief 读取编码器角度值 + * @param[in] 编码器id + * @retval none + 编码器旋转速度=编码器角速度值/单圈 + 精度/转速计算时间(单位:转/分钟) + 例如:编码器角速度值回传为1000,单圈 + 精度为32768,转速采样时间为 + 100ms(0.1/60min) + 编码器旋转速度=1000/32768/(0.1/60) + =1000*0.0183=18.31转/分钟 + */ +int8_t OID_Read_AngularVelocity(OID_Param_t *param) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x0A; + frame.data[3] = 0x00; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} +/** + * @brief 设置编码器角速度采样时间(掉电记忆,单位:毫秒) + * @param[in] 编码器id,采样时间 + * @retval none + */ +int8_t OID_Set_AngularVelocitySamplingTime(OID_Param_t *param,uint8_t encoder_time) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x0B; + frame.data[3] = encoder_time; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} +/** + * @brief 设置编码器中点 设定当前编码器值为 M(M 为单圈分辨率*圈数/2) + * @param[in] 编码器id + * @retval none + */ +int8_t OID_Set_Midpoint(OID_Param_t *param) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x0C; + frame.data[3] = 0x01; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} +/** + * @brief 设置编码器当前位置值 数值范围:0~X(X 为单圈分辨率*圈数- 1) + * @param[in] 编码器id + * @retval none + */ +int8_t OID_Set_CurrentPosition(OID_Param_t *param,uint8_t encoder_direction) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x0D; + frame.data[3] = encoder_direction; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} +/** + * @brief 编码器设置当前值为 5 圈值 即当前编码器值为 Z(Z 为单圈分辨率*5) + * @param[in] 编码器id + * @retval none + */ +int8_t OID_Set_CurrentValue5Turns(OID_Param_t *param) +{ + BSP_CAN_StdDataFrame_t frame; + frame.id = param->id; + frame.dlc = 4; + frame.data[0] = 0x04; + frame.data[1] = param->id; + frame.data[2] = 0x0F; + frame.data[3] = 0x01; + + + return BSP_CAN_TransmitStdDataFrame(param->can, &frame) == BSP_OK ? DEVICE_OK : DEVICE_ERR; +} + + + diff --git a/assets/User_code/device/oid.h b/assets/User_code/device/oid.h new file mode 100644 index 0000000..9b74764 --- /dev/null +++ b/assets/User_code/device/oid.h @@ -0,0 +1,269 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ----------------------------------------------------------------- */ +#include "device/device.h" +#include "bsp/can.h" +#include "component/user_math.h" + +/* Exported constants ------------------------------------------------------- */ +#define OID_MAX_NUM 32 +#define OID_RESOLUTION 1024 //编码器分辨率 +/* Exported macro ----------------------------------------------------------- */ +/* Exported types ----------------------------------------------------------- */ + +/** + * @brief 编码器工作模式枚举 + */ +typedef enum { + OID_MODE_QUERY = 0x00, // 查询模式 + OID_MODE_AUTO_SPEED = 0x02, // 自动返回编码器角速度值 + OID_MODE_AUTO_POSITION = 0xAA // 自动返回编码器值 +} OID_Mode_t; + +/** + * @brief 编码器方向枚举 + */ +typedef enum { + OID_DIR_CW = 0x00, // 顺时针 + OID_DIR_CCW = 0x01 // 逆时针 +} OID_Direction_t; + +/** + * @brief 编码器波特率枚举 + * 当编码器的ID和波特率更改后,闪灯的颜色会相应变化,状态灯颜色参照表及代表的意义如下: + * + * 颜色及其数值定义关系: + * - 蓝色(0) : 500K(默认) + * - 青色(1) : 1M + * - 橙色(2) : 250K + * - 紫色(3) : 125K + * - 绿色(4) : 100K + * - 红色(5) : 保留 + */ +typedef enum { + OID_BAUD_500K = 0x00, // 蓝色 - 500K(默认) + OID_BAUD_1M = 0x01, // 青色 - 1M + OID_BAUD_250K = 0x02, // 橙色 - 250K + OID_BAUD_125K = 0x03, // 紫色 - 125K + OID_BAUD_100K = 0x04 // 绿色 - 100K +} OID_Baudrate_t; + +typedef struct { + BSP_CAN_t can; + uint16_t id; + +} OID_Param_t; + +typedef struct { + //0x01 编码器值反馈 + float angle_fbk; + float angle_360; + float angle_2PI; + //0x0A 速度反馈 + float speed_fbk; + float speed_rpm; + +} OID_Feedback_t; + +typedef struct { + DEVICE_Header_t header; + OID_Param_t param; + OID_Feedback_t feedback; +} OID_t; + +/*CAN管理器,管理一个CAN总线上所有的编码器*/ +typedef struct { + BSP_CAN_t can; + OID_t *encoders[OID_MAX_NUM]; + uint8_t encoder_count; +} OID_CANManager_t; + + +/** + * @brief 更新指定编码器数据 + * @param param 编码器参数指针 + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR_NULL: 参数为空 + * - DEVICE_ERR_NO_DEV: 编码器未找到 + * - DEVICE_ERR: 其他错误 + */ +int8_t OID_Update(OID_Param_t *param); + +/** + * @brief 更新所有已注册编码器数据 + * @return 操作结果 + * - DEVICE_OK: 全部成功 + * - DEVICE_ERR: 部分或全部失败 + */ +int8_t OID_UpdateAll(void); + +/** + * @brief 注册一个欧艾迪编码器 + * @param param 编码器参数指针 + * @return 注册结果 + * - DEVICE_OK: 注册成功 + * - DEVICE_ERR_NULL: 参数为空 + * - DEVICE_ERR_INITED: 已注册 + * - DEVICE_ERR: 其他错误 + */ +int8_t OID_Register(OID_Param_t *param); + +/** + * @brief 设置编码器离线状态 + * @param param 编码器参数指针 + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR_NULL: 参数为空 + * - DEVICE_ERR_NO_DEV: 编码器未找到 + */ +int8_t OID_Offline(OID_Param_t *param); + +/** + * @brief 获取指定编码器实例指针 + * @param param 编码器参数指针 + * @return 编码器实例指针,失败返回NULL + */ +OID_t* OID_GetEncoder(OID_Param_t *param); + +/** + * @brief 设置编码器ID + * @param param 当前编码器参数 + * @param param_new 新编码器参数(包含新ID) + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Set_ID(OID_Param_t *param, OID_Param_t *param_new); + +/** + * @brief 设置编码器CAN通信波特率 + * @param param 编码器参数 + * @param encoder_vaud_rate 波特率设置 + * - 0x00: 500K(默认) + * - 0x01: 1M + * - 0x02: 250K + * - 0x03: 125K + * - 0x04: 100K + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Set_Baudrate(OID_Param_t *param, OID_Baudrate_t encoder_vaud_rate); + +/** + * @brief 设置编码器工作模式 + * @param param 编码器参数 + * @param encoder_mode 工作模式 + * - 0x00: 查询模式 + * - 0x02: 自动返回编码器角速度值 + * - 0xAA: 自动返回编码器值 + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Set_Mode(OID_Param_t *param, OID_Mode_t encoder_mode); + +/** + * @brief 设置编码器自动回传时间 + * @param param 编码器参数 + * @param encoder_time 自动回传时间(单位:微秒) + * 数值范围:50~65535(16位无符号整数) + * @note 注意:设置太短的返回时间后,通过编码器上位机再设置其他参数很容易失败,谨慎使用! + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Set_AutoFeedbackTime(OID_Param_t *param, uint8_t encoder_time); + +/** + * @brief 设置当前位置为零点 + * @param param 编码器参数 + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Set_ZeroPoint(OID_Param_t *param); + +/** + * @brief 设置编码器值递增方向 + * @param param 编码器参数 + * @param encoder_direction 方向设置 + * - 0x00: 顺时针 + * - 0x01: 逆时针 + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Set_Polarity(OID_Param_t *param, OID_Direction_t encoder_direction); + +/** + * @brief 设置编码器角速度采样时间 + * @param param 编码器参数 + * @param encoder_time 采样时间(单位:毫秒) + * @note 掉电记忆功能 + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Set_AngularVelocitySamplingTime(OID_Param_t *param, uint8_t encoder_time); + +/** + * @brief 设置编码器中点位置 + * @param param 编码器参数 + * @note 设定当前编码器值为 M(M 为单圈分辨率 × 圈数 / 2) + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Set_Midpoint(OID_Param_t *param); + +/** + * @brief 设置编码器当前位置值 + * @param param 编码器参数 + * @param encoder_direction 位置值 + * 数值范围:0~X(X 为单圈分辨率 × 圈数 - 1) + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Set_CurrentPosition(OID_Param_t *param, uint8_t encoder_direction); + +/** + * @brief 设置编码器当前值为5圈值 + * @param param 编码器参数 + * @note 即当前编码器值为 Z(Z 为单圈分辨率 × 5) + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Set_CurrentValue5Turns(OID_Param_t *param); + +/** + * @brief 读取编码器角速度值 + * @param param 编码器参数 + * @note 编码器旋转速度 = 编码器角速度值 / 单圈精度 / 转速计算时间(单位:转/分钟) + * 例如:编码器角速度值回传为1000,单圈精度为32768,转速采样时间为100ms(0.1/60min) + * 编码器旋转速度 = 1000 / 32768 / (0.1/60) = 1000 × 0.0183 = 18.31转/分钟 + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Read_AngularVelocity(OID_Param_t *param); + +/** + * @brief 读取编码器值 + * @param param 编码器参数 + * @return 操作结果 + * - DEVICE_OK: 成功 + * - DEVICE_ERR: 失败 + */ +int8_t OID_Read_Value(OID_Param_t *param); + +#ifdef __cplusplus +} +#endif diff --git a/assets/User_code/module/cmd/cmd.c b/assets/User_code/module/cmd/cmd.c new file mode 100644 index 0000000..6dcca41 --- /dev/null +++ b/assets/User_code/module/cmd/cmd.c @@ -0,0 +1,265 @@ +/* + * CMD 模块 V2 - 主控制模块实现 + */ +#include "cmd.h" +#include "bsp/time.h" +#include +#include + +/* ========================================================================== */ +/* 命令构建函数 */ +/* ========================================================================== */ + +/* 从RC输入生成底盘命令 */ +static void CMD_RC_BuildChassisCmd(CMD_t *ctx) { + CMD_RCModeMap_t *map = &ctx->config->rc_mode_map; + + /* 根据左拨杆位置选择模式 */ + switch (ctx->input.rc.sw[0]) { + case CMD_SW_UP: + ctx->output.chassis.cmd.mode = map->sw_left_up; + break; + case CMD_SW_MID: + ctx->output.chassis.cmd.mode = map->sw_left_mid; + break; + case CMD_SW_DOWN: + ctx->output.chassis.cmd.mode = map->sw_left_down; + break; + default: + ctx->output.chassis.cmd.mode = CHASSIS_MODE_RELAX; + break; + } + + /* 摇杆控制移动 */ + ctx->output.chassis.cmd.ctrl_vec.vx = ctx->input.rc.joy_right.x; + ctx->output.chassis.cmd.ctrl_vec.vy = ctx->input.rc.joy_right.y; +} + +/* 从RC输入生成云台命令 */ +static void CMD_RC_BuildGimbalCmd(CMD_t *ctx) { + CMD_RCModeMap_t *map = &ctx->config->rc_mode_map; + + /* 根据拨杆选择云台模式 */ + switch (ctx->input.rc.sw[0]) { + case CMD_SW_UP: + ctx->output.gimbal.cmd.mode = map->gimbal_sw_up; + break; + case CMD_SW_MID: + ctx->output.gimbal.cmd.mode = map->gimbal_sw_mid; + break; + case CMD_SW_DOWN: + ctx->output.gimbal.cmd.mode = map->gimbal_sw_down; + break; + default: + ctx->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX; + break; + } + + /* 左摇杆控制云台 */ + ctx->output.gimbal.cmd.delta_yaw = -ctx->input.rc.joy_left.x * 2.0f; + ctx->output.gimbal.cmd.delta_pit = -ctx->input.rc.joy_left.y * 1.5f; +} + +/* 从RC输入生成射击命令 */ +static void CMD_RC_BuildShootCmd(CMD_t *ctx) { + if (ctx->input.online[CMD_SRC_RC]) { + ctx->output.shoot.cmd.mode = SHOOT_MODE_SINGLE; + } else { + ctx->output.shoot.cmd.mode = SHOOT_MODE_SAFE; + } + + /* 根据右拨杆控制射击 */ + switch (ctx->input.rc.sw[1]) { + case CMD_SW_DOWN: + ctx->output.shoot.cmd.ready = true; + ctx->output.shoot.cmd.firecmd = true; + break; + case CMD_SW_MID: + ctx->output.shoot.cmd.ready = true; + ctx->output.shoot.cmd.firecmd = false; + break; + case CMD_SW_UP: + default: + ctx->output.shoot.cmd.ready = false; + ctx->output.shoot.cmd.firecmd = false; + break; + } +} + +/* 从PC输入生成底盘命令 */ +static void CMD_PC_BuildChassisCmd(CMD_t *ctx) { + + if (!ctx->input.online[CMD_SRC_PC]) { + ctx->output.chassis.cmd.mode = CHASSIS_MODE_RELAX; + return; + } + + ctx->output.chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL; + + /* WASD控制移动 */ + ctx->output.chassis.cmd.ctrl_vec.vx = 0.0f; + ctx->output.chassis.cmd.ctrl_vec.vy = 0.0f; + CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_CHASSIS); +} + +/* 从PC输入生成云台命令 */ +static void CMD_PC_BuildGimbalCmd(CMD_t *ctx) { + CMD_Sensitivity_t *sens = &ctx->config->sensitivity; + + if (!ctx->input.online[CMD_SRC_PC]) { + ctx->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX; + return; + } + + ctx->output.gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE; + + /* 鼠标控制云台 */ + ctx->output.gimbal.cmd.delta_yaw = (float)-ctx->input.pc.mouse.x * ctx->timer.dt * sens->mouse_sens; + ctx->output.gimbal.cmd.delta_pit = (float)ctx->input.pc.mouse.y * ctx->timer.dt * sens->mouse_sens * 1.5f; + CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_GIMBAL); +} + +/* 从PC输入生成射击命令 */ +static void CMD_PC_BuildShootCmd(CMD_t *ctx) { + if (!ctx->input.online[CMD_SRC_PC]) { + ctx->output.shoot.cmd.mode = SHOOT_MODE_SAFE; + return; + } + + ctx->output.shoot.cmd.ready = true; + ctx->output.shoot.cmd.firecmd = ctx->input.pc.mouse.l_click; + + CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_SHOOT); + +} + +/* 离线安全模式 */ +static void CMD_SetOfflineMode(CMD_t *ctx) { + ctx->output.chassis.cmd.mode = CHASSIS_MODE_RELAX; + ctx->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX; + ctx->output.shoot.cmd.mode = SHOOT_MODE_SAFE; +} + +/* ========================================================================== */ +/* 公开API实现 */ +/* ========================================================================== */ + +int8_t CMD_Init(CMD_t *ctx, CMD_Config_t *config) { + if (ctx == NULL || config == NULL) { + return CMD_ERR_NULL; + } + + memset(ctx, 0, sizeof(CMD_t)); + ctx->config = config; + + /* 初始化适配器 */ + CMD_Adapter_InitAll(); + + /* 初始化行为处理器 */ + CMD_Behavior_Init(); + + return CMD_OK; +} + +int8_t CMD_UpdateInput(CMD_t *ctx) { + if (ctx == NULL) { + return CMD_ERR_NULL; + } + + /* 保存上一帧输入 */ + memcpy(&ctx->last_input, &ctx->input, sizeof(ctx->input)); + + /* 更新所有输入源 */ + for (int i = 0; i < CMD_SRC_NUM; i++) { + CMD_Adapter_GetInput((CMD_InputSource_t)i, &ctx->input); + } + + return CMD_OK; +} +typedef void (*CMD_BuildCommandFunc)(CMD_t *cmd); +typedef struct { + CMD_InputSource_t source; + CMD_BuildCommandFunc chassisFunc; + CMD_BuildCommandFunc gimbalFunc; + CMD_BuildCommandFunc shootFunc; +} CMD_SourceHandler_t; + +CMD_SourceHandler_t sourceHandlers[CMD_SRC_NUM] = { + {CMD_SRC_RC, CMD_RC_BuildChassisCmd, CMD_RC_BuildGimbalCmd, CMD_RC_BuildShootCmd}, + {CMD_SRC_PC, CMD_PC_BuildChassisCmd, CMD_PC_BuildGimbalCmd, CMD_PC_BuildShootCmd}, + {CMD_SRC_NUC, NULL, NULL, NULL}, + {CMD_SRC_REF, NULL, NULL, NULL}, +}; + +int8_t CMD_Arbitrate(CMD_t *ctx) { + if (ctx == NULL) { + return CMD_ERR_NULL; + } + + /* 自动仲裁:优先级 PC > RC > NUC */ + CMD_InputSource_t candidates[] = {CMD_SRC_PC, CMD_SRC_RC, CMD_SRC_NUC}; + const int num_candidates = sizeof(candidates) / sizeof(candidates[0]); + + /* 如果当前输入源仍然在线且有效,保持使用 */ + if (ctx->active_source < CMD_SRC_NUM && + ctx->active_source != CMD_SRC_REF && + ctx->input.online[ctx->active_source]) { + goto seize; + } + + /* 否则选择第一个可用的控制输入源 */ + for (int i = 0; i < num_candidates; i++) { + CMD_InputSource_t src = candidates[i]; + if (ctx->input.online[src]) { + ctx->active_source = src; + break; + }else { + ctx->active_source = CMD_SRC_NUM; + continue; + } + } + ctx->output.chassis.source = ctx->active_source; + ctx->output.gimbal.source = ctx->active_source; + ctx->output.shoot.source = ctx->active_source; + + /* 优先级抢占逻辑 */ + seize: + CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_NONE); + + return CMD_OK; +} + +int8_t CMD_GenerateCommands(CMD_t *ctx) { + if (ctx == NULL) { + return CMD_ERR_NULL; + } + + /* 更新时间 */ + uint64_t now_us = BSP_TIME_Get_us(); + ctx->timer.now = now_us / 1000000.0f; + ctx->timer.dt = (now_us - ctx->timer.last_us) / 1000000.0f; + ctx->timer.last_us = now_us; + + /* 没有有效输入源 */ + if (ctx->active_source >= CMD_SRC_NUM) { + CMD_SetOfflineMode(ctx); + return CMD_ERR_NO_INPUT; + } + + sourceHandlers[ctx->output.gimbal.source].gimbalFunc(ctx); + sourceHandlers[ctx->output.chassis.source].chassisFunc(ctx); + sourceHandlers[ctx->output.shoot.source].shootFunc(ctx); + return CMD_OK; +} + +int8_t CMD_Update(CMD_t *ctx) { + int8_t ret; + + ret = CMD_UpdateInput(ctx); + if (ret != CMD_OK) return ret; + + CMD_Arbitrate(ctx); + + ret = CMD_GenerateCommands(ctx); + return ret; +} diff --git a/assets/User_code/module/cmd/cmd.h b/assets/User_code/module/cmd/cmd.h new file mode 100644 index 0000000..c70c46f --- /dev/null +++ b/assets/User_code/module/cmd/cmd.h @@ -0,0 +1,172 @@ +/* + * CMD 模块 V2 - 主控制模块 + * 统一的命令控制接口 + */ +#pragma once + +#include "cmd_types.h" +#include "cmd_adapter.h" +#include "cmd_behavior.h" + +/* 引入输出模块的命令类型 */ +#include "module/chassis.h" +#include "module/gimbal.h" +#include "module/shoot.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* 输出命令结构 */ +/* ========================================================================== */ + +/* 每个模块的输出包含源信息和命令 */ +typedef struct { + CMD_InputSource_t source; + Chassis_CMD_t cmd; +} CMD_ChassisOutput_t; + +typedef struct { + CMD_InputSource_t source; + Gimbal_CMD_t cmd; +} CMD_GimbalOutput_t; + +typedef struct { + CMD_InputSource_t source; + Shoot_CMD_t cmd; +} CMD_ShootOutput_t; + +/* ========================================================================== */ +/* 配置结构 */ +/* ========================================================================== */ + +/* 灵敏度配置 */ +typedef struct { + float mouse_sens; /* 鼠标灵敏度 */ + float move_sens; /* 移动灵敏度 */ + float move_fast_mult; /* 快速移动倍率 */ + float move_slow_mult; /* 慢速移动倍率 */ +} CMD_Sensitivity_t; + +/* RC模式映射配置 - 定义开关位置到模式的映射 */ +typedef struct { + /* 左拨杆映射 - 底盘模式 */ + Chassis_Mode_t sw_left_up; + Chassis_Mode_t sw_left_mid; + Chassis_Mode_t sw_left_down; + + /* 右拨杆映射 - 云台/射击模式 */ + Gimbal_Mode_t gimbal_sw_up; + Gimbal_Mode_t gimbal_sw_mid; + Gimbal_Mode_t gimbal_sw_down; +} CMD_RCModeMap_t; + +/* 整体配置 */ +typedef struct { + /* 输入源优先级,索引越小优先级越高 */ + CMD_InputSource_t source_priority[CMD_SRC_NUM]; + + /* 灵敏度设置 */ + CMD_Sensitivity_t sensitivity; + + /* RC模式映射 */ + CMD_RCModeMap_t rc_mode_map; + +} CMD_Config_t; + +/* ========================================================================== */ +/* 主控制上下文 */ +/* ========================================================================== */ + +typedef struct { + float now; + float dt; + uint32_t last_us; +} CMD_Timer_t; + +typedef struct CMD_Context { + /* 配置 */ + CMD_Config_t *config; + + /* 时间 */ + CMD_Timer_t timer; + + /* 当前帧和上一帧的原始输入 */ + CMD_RawInput_t input; + CMD_RawInput_t last_input; + + /* 仲裁后的活跃输入源 */ + CMD_InputSource_t active_source; + + /* 输出 */ + struct { + CMD_ChassisOutput_t chassis; + CMD_GimbalOutput_t gimbal; + CMD_ShootOutput_t shoot; + } output; +} CMD_t; + +/* ========================================================================== */ +/* 主API接口 */ +/* ========================================================================== */ + +/** + * @brief 初始化CMD模块 + * @param ctx CMD上下文 + * @param config 配置指针 + * @return CMD_OK成功,其他失败 + */ +int8_t CMD_Init(CMD_t *ctx, CMD_Config_t *config); + +/** + * @brief 更新所有输入源的数据 + * @param ctx CMD上下文 + * @return CMD_OK成功 + */ +int8_t CMD_UpdateInput(CMD_t *ctx); + +/** + * @brief 执行仲裁,决定使用哪个输入源 + * @param ctx CMD上下文 + * @return 选中的输入源 + */ +int8_t CMD_Arbitrate(CMD_t *ctx); + +/** + * @brief 生成所有模块的控制命令 + * @param ctx CMD上下文 + * @return CMD_OK成功 + */ +int8_t CMD_GenerateCommands(CMD_t *ctx); + +/** + * @brief 一键更新(包含UpdateInput + Arbitrate + GenerateCommands) + * @param ctx CMD上下文 + * @return CMD_OK成功 + */ +int8_t CMD_Update(CMD_t *ctx); + +/* ========================================================================== */ +/* 输出获取接口 */ +/* ========================================================================== */ + +/* 获取底盘命令 */ +static inline Chassis_CMD_t* CMD_GetChassisCmd(CMD_t *ctx) { + return &ctx->output.chassis.cmd; + } + +/* 获取云台命令 */ +static inline Gimbal_CMD_t* CMD_GetGimbalCmd(CMD_t *ctx) { + return &ctx->output.gimbal.cmd; +} + +/* 获取射击命令 */ +static inline Shoot_CMD_t* CMD_GetShootCmd(CMD_t *ctx) { + return &ctx->output.shoot.cmd; +} + +#ifdef __cplusplus +} +#endif diff --git a/assets/User_code/module/cmd/cmd_adapter.c b/assets/User_code/module/cmd/cmd_adapter.c new file mode 100644 index 0000000..d8023f6 --- /dev/null +++ b/assets/User_code/module/cmd/cmd_adapter.c @@ -0,0 +1,184 @@ +/* + * CMD 模块 V2 - 输入适配器实现 + */ +#include "cmd_adapter.h" +#include + +/* ========================================================================== */ +/* 适配器存储 */ +/* ========================================================================== */ +// static CMD_InputAdapter_t *g_adapters[CMD_SRC_NUM] = {0}; +CMD_InputAdapter_t *g_adapters[CMD_SRC_NUM] = {0}; +/* ========================================================================== */ +/* DR16 抽象实现 */ +/* ========================================================================== */ +#if CMD_RC_DEVICE_TYPE == 0 + +int8_t CMD_DR16_Init(void *data) { + DR16_t *dr16 = (DR16_t *)data; + return DR16_Init(dr16); +} + +int8_t CMD_DR16_RC_GetInput(void *data, CMD_RawInput_t *output) { + DR16_t *dr16 = (DR16_t *)data; + + memset(&output->rc, 0, sizeof(CMD_RawInput_RC_t)); + + output->online[CMD_SRC_RC] = dr16->header.online; + + /* 遥控器摇杆映射 */ + output->rc.joy_left.x = dr16->data.rc.ch_l_x; + output->rc.joy_left.y = dr16->data.rc.ch_l_y; + output->rc.joy_right.x = dr16->data.rc.ch_r_x; + output->rc.joy_right.y = dr16->data.rc.ch_r_y; + + /* 拨杆映射 */ + switch (dr16->data.rc.sw_l) { + case DR16_SW_UP: output->rc.sw[0] = CMD_SW_UP; break; + case DR16_SW_MID: output->rc.sw[0] = CMD_SW_MID; break; + case DR16_SW_DOWN: output->rc.sw[0] = CMD_SW_DOWN; break; + default: output->rc.sw[0] = CMD_SW_ERR; break; + } + switch (dr16->data.rc.sw_r) { + case DR16_SW_UP: output->rc.sw[1] = CMD_SW_UP; break; + case DR16_SW_MID: output->rc.sw[1] = CMD_SW_MID; break; + case DR16_SW_DOWN: output->rc.sw[1] = CMD_SW_DOWN; break; + default: output->rc.sw[1] = CMD_SW_ERR; break; + } + + /* 拨轮映射 */ + output->rc.dial = dr16->data.rc.ch_res; + + return CMD_OK; +} + +int8_t CMD_DR16_PC_GetInput(void *data, CMD_RawInput_t *output) { + DR16_t *dr16 = (DR16_t *)data; + + memset(&output->pc, 0, sizeof(CMD_RawInput_PC_t)); + + output->online[CMD_SRC_PC] = dr16->header.online; + + /* PC端鼠标映射 */ + output->pc.mouse.x = dr16->data.pc.mouse.x; + output->pc.mouse.y = dr16->data.pc.mouse.y; + output->pc.mouse.l_click = dr16->data.pc.mouse.l_click; + output->pc.mouse.r_click = dr16->data.pc.mouse.r_click; + + /* 键盘映射 */ + output->pc.keyboard.bitmap = dr16->raw_data.key; + + return CMD_OK; +} + +bool CMD_DR16_IsOnline(void *data) { + DR16_t *dr16 = (DR16_t *)data; + return dr16->header.online; +} +extern DR16_t cmd_dr16; +/* 定义适配器实例 */ +CMD_DEFINE_ADAPTER(DR16_RC, cmd_dr16, CMD_SRC_RC, CMD_DR16_Init, CMD_DR16_RC_GetInput, CMD_DR16_IsOnline) +CMD_DEFINE_ADAPTER(DR16_PC, cmd_dr16, CMD_SRC_PC, CMD_DR16_Init, CMD_DR16_PC_GetInput, CMD_DR16_IsOnline) + +#endif /* CMD_RC_DEVICE_TYPE == 0 */ + +/* ========================================================================== */ +/* AT9S 抽象实现 (示例框架) */ +/* ========================================================================== */ +#if CMD_RC_DEVICE_TYPE == 1 + +int8_t CMD_AT9S_Init(void *data) { + AT9S_t *at9s = (AT9S_t *)data; + return AT9S_Init(at9s); +} + +int8_t CMD_AT9S_GetInput(void *data, CMD_RawInput_t *output) { + AT9S_t *at9s = (AT9S_t *)data; + + memset(output, 0, sizeof(CMD_RawInput_RC_t)); + + output->online[CMD_SRC_RC] = at9s->header.online; + + /* TODO: 按照AT9S的数据格式进行映射 */ + output->joy_left.x = at9s->data.rc.ch_l_x; + output->joy_left.y = at9s->data.rc.ch_l_y; + output->joy_right.x = at9s->data.rc.ch_r_x; + output->joy_right.y = at9s->data.rc.ch_r_y; + + /* 拨杆映射需要根据AT9S的实际定义 */ + + return CMD_OK; +} + +bool CMD_AT9S_IsOnline(void *data) { + AT9S_t *at9s = (AT9S_t *)data; + return at9s->header.online; +} + +CMD_DEFINE_ADAPTER(AT9S, at9s, CMD_SRC_RC, CMD_AT9S_Init, CMD_AT9S_GetInput, CMD_AT9S_IsOnline) + +#endif /* CMD_RC_DEVICE_TYPE == 1 */ + +/* ========================================================================== */ +/* 适配器管理实现 */ +/* ========================================================================== */ + +int8_t CMD_Adapter_Register(CMD_InputAdapter_t *adapter) { + if (adapter == NULL || adapter->source >= CMD_SRC_NUM) { + return CMD_ERR_NULL; + } + g_adapters[adapter->source] = adapter; + return CMD_OK; +} + +int8_t CMD_Adapter_InitAll(void) { + /* 注册编译时选择的RC设备适配器 */ +#if CMD_RC_DEVICE_TYPE == 0 + /* DR16 支持 RC 和 PC 输入 */ + CMD_Adapter_Register(&g_adapter_DR16_RC); + CMD_Adapter_Register(&g_adapter_DR16_PC); +#elif CMD_RC_DEVICE_TYPE == 1 + /* AT9S 目前只支持 RC 输入 */ + CMD_Adapter_Register(&g_adapter_AT9S); +#endif + + /* 注册NUC适配器 */ + + /* 注册REF适配器 */ + + /* 初始化所有已注册的适配器 */ + for (int i = 0; i < CMD_SRC_NUM; i++) { + if (g_adapters[i] != NULL && g_adapters[i]->init != NULL) { + g_adapters[i]->init(g_adapters[i]->device_data); + } + } + + return CMD_OK; +} + +int8_t CMD_Adapter_GetInput(CMD_InputSource_t source, CMD_RawInput_t *output) { + if (source >= CMD_SRC_NUM || output == NULL) { + return CMD_ERR_NULL; + } + + CMD_InputAdapter_t *adapter = g_adapters[source]; + if (adapter == NULL || adapter->get_input == NULL) { + output->online[adapter->source] = false; + return CMD_ERR_NO_INPUT; + } + + return adapter->get_input(adapter->device_data, output); +} + +bool CMD_Adapter_IsOnline(CMD_InputSource_t source) { + if (source >= CMD_SRC_NUM) { + return false; + } + + CMD_InputAdapter_t *adapter = g_adapters[source]; + if (adapter == NULL || adapter->is_online == NULL) { + return false; + } + + return adapter->is_online(adapter->device_data); +} diff --git a/assets/User_code/module/cmd/cmd_adapter.h b/assets/User_code/module/cmd/cmd_adapter.h new file mode 100644 index 0000000..4fbbc47 --- /dev/null +++ b/assets/User_code/module/cmd/cmd_adapter.h @@ -0,0 +1,111 @@ +/* + * CMD 模块 V2 - 输入适配器接口 + * 定义设备到统一输入结构的转换接口 + */ +#pragma once + +#include "cmd_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* 适配器接口定义 */ +/* ========================================================================== */ + +/* 适配器操作函数指针类型 */ +typedef int8_t (*CMD_AdapterInitFunc)(void *device_data); +typedef int8_t (*CMD_AdapterGetInputFunc)(void *device_data, CMD_RawInput_t *output); +typedef bool (*CMD_AdapterIsOnlineFunc)(void *device_data); + +/* 适配器描述结构 */ +typedef struct { + const char *name; /* 适配器名称 */ + CMD_InputSource_t source; /* 对应的输入源 */ + void *device_data; /* 设备数据指针 */ + CMD_AdapterInitFunc init; /* 初始化函数 */ + CMD_AdapterGetInputFunc get_input; /* 获取输入函数 */ + CMD_AdapterIsOnlineFunc is_online; /* 在线检测函数 */ +} CMD_InputAdapter_t; + +/* ========================================================================== */ +/* 适配器注册宏 */ +/* ========================================================================== */ + +/* + * 声明适配器 + * 使用示例: + * CMD_DECLARE_ADAPTER(DR16, dr16, DR16_t) + * + * 会生成: + * - extern DR16_t dr16; // 设备实例声明 + * - int8_t CMD_DR16_Init(void *data); + * - int8_t CMD_DR16_GetInput(void *data, CMD_RawInput_t *output); + * - bool CMD_DR16_IsOnline(void *data); + */ +#define CMD_DECLARE_ADAPTER(NAME, var, TYPE) \ + extern TYPE var; \ + int8_t CMD_##NAME##_Init(void *data); \ + int8_t CMD_##NAME##_GetInput(void *data, CMD_RawInput_t *output); \ + bool CMD_##NAME##_IsOnline(void *data); + +/* + * 定义适配器实例 + * 使用示例: + * CMD_DEFINE_ADAPTER(DR16_RC, dr16, CMD_SRC_RC, CMD_DR16_Init, CMD_DR16_RC_GetInput, CMD_DR16_RC_IsOnline) + */ +#define CMD_DEFINE_ADAPTER(NAME, var, source_enum, init_func, get_func, online_func) \ + static CMD_InputAdapter_t g_adapter_##NAME = { \ + .name = #NAME, \ + .source = source_enum, \ + .device_data = (void*)&var, \ + .init = init_func, \ + .get_input = get_func, \ + .is_online = online_func, \ + }; + +/* ========================================================================== */ +/* RC设备适配器配置 */ +/* ========================================================================== */ + +/* 选择使用的RC设备 - 只需修改这里 */ +#define CMD_RC_DEVICE_TYPE 0 /* 0:DR16, 1:AT9S, 2:VT13 */ + +#if CMD_RC_DEVICE_TYPE == 0 + #include "device/dr16.h" + CMD_DECLARE_ADAPTER(DR16_RC, dr16, DR16_t) + CMD_DECLARE_ADAPTER(DR16_PC, dr16, DR16_t) + #define CMD_RC_ADAPTER_NAME DR16 + #define CMD_RC_ADAPTER_VAR dr16 +#elif CMD_RC_DEVICE_TYPE == 1 + #include "device/at9s_pro.h" + CMD_DECLARE_ADAPTER(AT9S, at9s, AT9S_t) + #define CMD_RC_ADAPTER_NAME AT9S + #define CMD_RC_ADAPTER_VAR at9s +#elif CMD_RC_DEVICE_TYPE == 2 + #include "device/vt13.h" + CMD_DECLARE_ADAPTER(VT13, vt13, VT13_t) + #define CMD_RC_ADAPTER_NAME VT13 + #define CMD_RC_ADAPTER_VAR vt13 +#endif + +/* ========================================================================== */ +/* 适配器管理接口 */ +/* ========================================================================== */ + +/* 初始化所有适配器 */ +int8_t CMD_Adapter_InitAll(void); + +/* 获取指定输入源的原始输入 */ +int8_t CMD_Adapter_GetInput(CMD_InputSource_t source, CMD_RawInput_t *output); + +/* 检查输入源是否在线 */ +bool CMD_Adapter_IsOnline(CMD_InputSource_t source); + +/* 注册适配器 (运行时注册,可选) */ +int8_t CMD_Adapter_Register(CMD_InputAdapter_t *adapter); + +#ifdef __cplusplus +} +#endif diff --git a/assets/User_code/module/cmd/cmd_behavior.c b/assets/User_code/module/cmd/cmd_behavior.c new file mode 100644 index 0000000..92b24bd --- /dev/null +++ b/assets/User_code/module/cmd/cmd_behavior.c @@ -0,0 +1,172 @@ +/* + * CMD 模块 V2 - 行为处理器实现 + */ +#include "cmd_behavior.h" +#include "cmd.h" +#include "module/gimbal.h" +#include + +/* ========================================================================== */ +/* 行为回调函数 */ +/* ========================================================================== */ + +/* 行为处理函数实现 */ +int8_t CMD_Behavior_Handle_FORE(CMD_t *ctx) { + ctx->output.chassis.cmd.ctrl_vec.vy += ctx->config->sensitivity.move_sens; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_BACK(CMD_t *ctx) { + ctx->output.chassis.cmd.ctrl_vec.vy -= ctx->config->sensitivity.move_sens; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_LEFT(CMD_t *ctx) { + ctx->output.chassis.cmd.ctrl_vec.vx -= ctx->config->sensitivity.move_sens; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_RIGHT(CMD_t *ctx) { + ctx->output.chassis.cmd.ctrl_vec.vx += ctx->config->sensitivity.move_sens; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_ACCELERATE(CMD_t *ctx) { + ctx->output.chassis.cmd.ctrl_vec.vx *= ctx->config->sensitivity.move_fast_mult; + ctx->output.chassis.cmd.ctrl_vec.vy *= ctx->config->sensitivity.move_fast_mult; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_DECELERATE(CMD_t *ctx) { + ctx->output.chassis.cmd.ctrl_vec.vx *= ctx->config->sensitivity.move_slow_mult; + ctx->output.chassis.cmd.ctrl_vec.vy *= ctx->config->sensitivity.move_slow_mult; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_FIRE(CMD_t *ctx) { + ctx->output.shoot.cmd.firecmd = true; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_FIRE_MODE(CMD_t *ctx) { + ctx->output.shoot.cmd.mode = (ctx->output.shoot.cmd.mode + 1) % SHOOT_MODE_NUM; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_ROTOR(CMD_t *ctx) { + ctx->output.chassis.cmd.mode = CHASSIS_MODE_ROTOR; + ctx->output.chassis.cmd.mode_rotor = ROTOR_MODE_RAND; + ctx->output.gimbal.cmd.mode = GIMBAL_MODE_RELATIVE; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_AUTOAIM(CMD_t *ctx) { + /* TODO: 自瞄模式切换 */ + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_CHECKSOURCERCPC(CMD_t *ctx) { + /* TODO: 切换RC和PC输入源 */ + if (ctx->active_source == CMD_SRC_PC) { + ctx->active_source = CMD_SRC_RC; + ctx->output.chassis.source = CMD_SRC_RC; + ctx->output.gimbal.source = CMD_SRC_RC; + ctx->output.shoot.source = CMD_SRC_RC; + } else if(ctx->active_source == CMD_SRC_RC) { + ctx->active_source = CMD_SRC_PC; + ctx->output.chassis.source = CMD_SRC_PC; + ctx->output.gimbal.source = CMD_SRC_PC; + ctx->output.shoot.source = CMD_SRC_PC; + } + return CMD_OK; +} + +/* 行为配置表 - 由宏生成 */ +static const CMD_BehaviorConfig_t g_behavior_configs[] = { + CMD_BEHAVIOR_TABLE(BUILD_BEHAVIOR_CONFIG) +}; + +/* ========================================================================== */ +/* API实现 */ +/* ========================================================================== */ + +int8_t CMD_Behavior_Init(void) { + /* 当前静态配置,无需初始化 */ + return CMD_OK; +} + +bool CMD_Behavior_IsTriggered(const CMD_RawInput_t *current, + const CMD_RawInput_t *last, + const CMD_BehaviorConfig_t *config) { + if (config == NULL || current == NULL) { + return false; + } + + bool now_pressed = false; + bool last_pressed = false; + + // 鼠标特殊按键处理 + if (config->key == (CMD_KEY_L_CLICK)) { + now_pressed = current->pc.mouse.l_click; + last_pressed = last ? last->pc.mouse.l_click : false; + } else if (config->key == (CMD_KEY_R_CLICK)) { + now_pressed = current->pc.mouse.r_click; + last_pressed = last ? last->pc.mouse.r_click : false; + } else if (config->key == (CMD_KEY_M_CLICK)) { + now_pressed = current->pc.mouse.m_click; + last_pressed = last ? last->pc.mouse.m_click : false; + } else if (config->key == 0) { + return false; + } else { + // 多按键组合检测 + now_pressed = ((current->pc.keyboard.bitmap & config->key) == config->key); + last_pressed = last ? ((last->pc.keyboard.bitmap & config->key) == config->key) : false; + } + + switch (config->trigger) { + case CMD_ACTIVE_PRESSED: + return now_pressed; + case CMD_ACTIVE_RISING_EDGE: + return now_pressed && !last_pressed; + case CMD_ACTIVE_FALLING_EDGE: + return !now_pressed && last_pressed; + default: + return false; + } +} + +int8_t CMD_Behavior_ProcessAll(CMD_t *ctx, + const CMD_RawInput_t *current, + const CMD_RawInput_t *last, + CMD_ModuleMask_t active_modules) { + if (ctx == NULL || current == NULL) { + return CMD_ERR_NULL; + } + + for (size_t i = 0; i < BEHAVIOR_CONFIG_COUNT; i++) { + const CMD_BehaviorConfig_t *config = &g_behavior_configs[i]; + + /* 过滤模块掩码 */ + if ((config->module_mask & active_modules) == 0) { + continue; + } + + /* 检查是否触发 */ + if (CMD_Behavior_IsTriggered(current, last, config)) { + if (config->handler != NULL) { + config->handler(ctx); + } + } + } + + return CMD_OK; +} + +const CMD_BehaviorConfig_t* CMD_Behavior_GetConfig(CMD_Behavior_t behavior) { + for (size_t i = 0; i < BEHAVIOR_CONFIG_COUNT; i++) { + if (g_behavior_configs[i].behavior == behavior) { + return &g_behavior_configs[i]; + } + } + return NULL; +} diff --git a/assets/User_code/module/cmd/cmd_behavior.h b/assets/User_code/module/cmd/cmd_behavior.h new file mode 100644 index 0000000..fda9074 --- /dev/null +++ b/assets/User_code/module/cmd/cmd_behavior.h @@ -0,0 +1,69 @@ +/* + * CMD 模块 V2 - 行为处理器 + * 实现PC端按键到行为的映射和处理 + */ +#pragma once + +#include "cmd_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* 行为处理器接口 */ +/* ========================================================================== */ + +/* 行为处理函数类型 */ +struct CMD_Context; /* 前向声明 */ +typedef int8_t (*CMD_BehaviorHandler)(struct CMD_Context *ctx); + +/* 行为配置项 */ +typedef struct { + CMD_Behavior_t behavior; /* 行为枚举 */ + uint32_t key; /* 绑定的按键 */ + CMD_TriggerType_t trigger; /* 触发类型 */ + CMD_ModuleMask_t module_mask; /* 影响的模块 */ + CMD_BehaviorHandler handler; /* 处理函数 */ +} CMD_BehaviorConfig_t; + +/* ========================================================================== */ +/* 行为表生成宏 */ +/* ========================================================================== */ + +/* 从宏表生成配置数组 */ +#define BUILD_BEHAVIOR_CONFIG(name, key, trigger, mask) \ + { CMD_BEHAVIOR_##name, key, trigger, mask, CMD_Behavior_Handle_##name }, + +/* 声明所有行为处理函数 */ +#define DECLARE_BEHAVIOR_HANDLER(name, key, trigger, mask) \ + int8_t CMD_Behavior_Handle_##name(struct CMD_Context *ctx); + +/* 展开声明 */ +CMD_BEHAVIOR_TABLE(DECLARE_BEHAVIOR_HANDLER) +#undef DECLARE_BEHAVIOR_HANDLER + +/* ========================================================================== */ +/* 行为处理器API */ +/* ========================================================================== */ + +/* 初始化行为处理器 */ +int8_t CMD_Behavior_Init(void); + +/* 检查行为是否被触发 */ +bool CMD_Behavior_IsTriggered(const CMD_RawInput_t *current, + const CMD_RawInput_t *last, + const CMD_BehaviorConfig_t *config); + +/* 处理所有触发的行为 */ +int8_t CMD_Behavior_ProcessAll(struct CMD_Context *ctx, + const CMD_RawInput_t *current, + const CMD_RawInput_t *last, + CMD_ModuleMask_t active_modules); + +/* 获取行为配置 */ +const CMD_BehaviorConfig_t* CMD_Behavior_GetConfig(CMD_Behavior_t behavior); + +#ifdef __cplusplus +} +#endif diff --git a/assets/User_code/module/cmd/cmd_example.c b/assets/User_code/module/cmd/cmd_example.c new file mode 100644 index 0000000..dbea4b0 --- /dev/null +++ b/assets/User_code/module/cmd/cmd_example.c @@ -0,0 +1,144 @@ +/* + * CMD 模块 V2 - 使用示例和配置模板 + * + * 本文件展示如何配置和使用新的CMD模块 + */ +#include "cmd.h" + +/* ========================================================================== */ +/* 配置示例 */ +/* ========================================================================== */ + +/* 默认配置 */ +// static CMD_Config_t g_cmd_config = { +// /* 灵敏度设置 */ +// .sensitivity = { +// .mouse_sens = 0.8f, +// .move_sens = 1.0f, +// .move_fast_mult = 1.5f, +// .move_slow_mult = 0.5f, +// }, + +// /* RC拨杆模式映射 */ +// .rc_mode_map = { +// /* 左拨杆控制底盘模式 */ +// .sw_left_up = CHASSIS_MODE_BREAK, +// .sw_left_mid = CHASSIS_MODE_FOLLOW_GIMBAL, +// .sw_left_down = CHASSIS_MODE_ROTOR, + +// /* 用于云台模式 */ +// .gimbal_sw_up = GIMBAL_MODE_ABSOLUTE, +// .gimbal_sw_mid = GIMBAL_MODE_ABSOLUTE, +// .gimbal_sw_down = GIMBAL_MODE_RELATIVE, +// }, + +// }; + +// /* CMD上下文 */ +// static CMD_t g_cmd_ctx; + +/* ========================================================================== */ +/* 任务示例 */ +/* ========================================================================== */ + +/* + * 初始化示例 + */ +// void Example_CMD_Init(void) { +// CMD_Init(&g_cmd_ctx, &g_cmd_config); +// } + +// /* +// * 任务循环示例 +// */ +// void Example_CMD_Task(void) { +// /* 一键更新 */ +// CMD_Update(&g_cmd_ctx); + +// /* 获取命令发送到各模块 */ +// Chassis_CMD_t *chassis_cmd = CMD_GetChassisCmd(&g_cmd_ctx); +// Gimbal_CMD_t *gimbal_cmd = CMD_GetGimbalCmd(&g_cmd_ctx); +// Shoot_CMD_t *shoot_cmd = CMD_GetShootCmd(&g_cmd_ctx); + +// /* 使用命令... */ +// (void)chassis_cmd; +// (void)gimbal_cmd; +// (void)shoot_cmd; +// } + +/* ========================================================================== */ +/* 架构说明 */ +/* ========================================================================== */ + +/* + * ## 新架构优势 + * + * ### 1. 统一的输入抽象层 (CMD_RawInput_t) + * - 所有设备(DR16/AT9S/VT13等)都转换成相同格式 + * - 上层代码无需关心具体设备类型 + * - 添加新设备只需实现适配器,不改动主逻辑 + * + * ### 2. 适配器模式 + * - 每个设备一个适配器文件 + * - 实现 Init, GetInput, IsOnline 三个函数 + * - 通过宏选择编译哪个适配器 + * + * ### 3. X-Macro配置表 + * - CMD_INPUT_SOURCE_TABLE: 配置输入源 + * - CMD_OUTPUT_MODULE_TABLE: 配置输出模块 + * - CMD_BEHAVIOR_TABLE: 配置按键行为映射 + * - 编译时生成枚举、配置数组、处理函数 + * + * ### 4. 行为驱动设计 + * - 行为与按键解耦 + * - 运行时可修改映射 + * - 支持边沿触发和持续触发 + * + * ### 5. 清晰的分层 + * + * ┌──────────────────────────────────────┐ + * │ 应用层 (cmd.c) │ + * │ - CMD_Update() │ + * │ - 仲裁、命令生成 │ + * └──────────────┬───────────────────────┘ + * │ + * ┌──────────────▼───────────────────────┐ + * │ 行为处理层 (cmd_behavior.c) │ + * │ - 按键触发检测 │ + * │ - 行为函数调用 │ + * └──────────────┬───────────────────────┘ + * │ + * ┌──────────────▼──────────────────────────┐ + * │ 抽象输入层 (cmd_types.h) │ + * │ - 多输入源操作同一CMD_RawInput_t不同分区 │ + * │ - 统一的摇杆、开关、键鼠结构 │ + * └──────────────┬──────────────────────────┘ + * │ + * ┌──────────────▼───────────────────────┐ + * │ 适配器层 (cmd_adapter.c) │ + * │ - DR16_Adapter │ + * │ - AT9S_Adapter │ + * │ - 设备数据 → CMD_RawInput_t │ + * └──────────────────────────────────────┘ + * + * ## 扩展指南 + * + * ### 添加新遥控器设备 + * 1. 在 cmd_adapter.h 中添加宏定义选项 + * 2. 在 cmd_adapter.c 中实现三个适配器函数 + * 3. 修改 CMD_RC_DEVICE_TYPE 宏选择新设备 + * + * ### 添加新输入源(如自定义协议) + * 1. 在 CMD_INPUT_SOURCE_TABLE 添加条目 + * 2. 实现对应的适配器 + * 3. 在 CMD_GenerateCommands 添加处理分支 + * + * ### 添加新行为 + * 1. 在 CMD_BEHAVIOR_TABLE 添加条目,并修正BEHAVIOR_CONFIG_COUNT + * 2. 实现 CMD_Behavior_Handle_XXX 函数 + * + * ### 添加新输出模块 + * 1. 在 CMD_OUTPUT_MODULE_TABLE 添加条目 + * 2. 在 CMD_t 中添加输出成员 + * 3. 实现对应的 BuildXXXCmd 函数 + */ diff --git a/assets/User_code/module/cmd/cmd_types.h b/assets/User_code/module/cmd/cmd_types.h new file mode 100644 index 0000000..961ea29 --- /dev/null +++ b/assets/User_code/module/cmd/cmd_types.h @@ -0,0 +1,196 @@ +/* + * CMD 模块 V2 - 类型定义 + * 统一的输入/输出抽象层 + */ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* 错误码定义 */ +/* ========================================================================== */ +#define CMD_OK (0) +#define CMD_ERR_NULL (-1) +#define CMD_ERR_MODE (-2) +#define CMD_ERR_SOURCE (-3) +#define CMD_ERR_NO_INPUT (-4) + +/* ========================================================================== */ +/* 输入源配置宏表 */ +/* ========================================================================== */ +/* + * 使用方法:在config中定义需要启用的输入源 + * 格式: X(枚举名, 优先级, 适配器初始化函数, 获取数据函数) + */ +#define CMD_INPUT_SOURCE_TABLE(X) \ + X(RC, CMD_RC_AdapterInit, CMD_RC_GetInput) \ + X(PC, CMD_PC_AdapterInit, CMD_PC_GetInput) \ + X(NUC, CMD_NUC_AdapterInit, CMD_NUC_GetInput) \ + X(REF, CMD_REF_AdapterInit, CMD_REF_GetInput) + +/* 输出模块配置宏表 */ +#define CMD_OUTPUT_MODULE_TABLE(X) \ + X(CHASSIS, Chassis_CMD_t, chassis) \ + X(GIMBAL, Gimbal_CMD_t, gimbal) \ + X(SHOOT, Shoot_CMD_t, shoot) + + +/* ========================================================================== */ +/* 输入源枚举 */ +/* ========================================================================== */ +#define ENUM_INPUT_SOURCE(name, ...) CMD_SRC_##name, +typedef enum { + CMD_INPUT_SOURCE_TABLE(ENUM_INPUT_SOURCE) + CMD_SRC_NUM +} CMD_InputSource_t; +#undef ENUM_INPUT_SOURCE + +/* ========================================================================== */ +/* 统一输入数据结构 */ +/* ========================================================================== */ + +/* 摇杆数据 - 统一为-1.0 ~ 1.0 */ +typedef struct { + float x; + float y; +} CMD_Joystick_t; + +/* 开关位置 */ +typedef enum { + CMD_SW_ERR = 0, + CMD_SW_UP, + CMD_SW_MID, + CMD_SW_DOWN, +} CMD_SwitchPos_t; + +/* 鼠标数据 */ +typedef struct { + int16_t x; /* 鼠标X轴移动速度 */ + int16_t y; /* 鼠标Y轴移动速度 */ + int16_t z; /* 鼠标滚轮 */ + bool l_click; /* 左键 */ + bool r_click; /* 右键 */ + bool m_click; /* 中键 */ +} CMD_Mouse_t; + +/* 键盘数据 - 最多支持32个按键 */ +typedef struct { + uint32_t bitmap; /* 按键位图 */ +} CMD_Keyboard_t; + +/* 键盘按键索引 */ +typedef enum { + CMD_KEY_W = (1 << 0), CMD_KEY_S = (1 << 1), CMD_KEY_A = (1 << 2), CMD_KEY_D = (1 << 3), + CMD_KEY_SHIFT = (1 << 4), CMD_KEY_CTRL = (1 << 5), CMD_KEY_Q = (1 << 6), CMD_KEY_E = (1 << 7), + CMD_KEY_R = (1 << 8), CMD_KEY_F = (1 << 9), CMD_KEY_G = (1 << 10), CMD_KEY_Z = (1 << 11), + CMD_KEY_X = (1 << 12), CMD_KEY_C = (1 << 13), CMD_KEY_V = (1 << 14), CMD_KEY_B = (1 << 15), + CMD_KEY_NUM +} CMD_KeyIndex_t; + +/* 裁判系统数据 */ +typedef struct { + uint8_t game_status; /* 比赛状态 */ +} CMD_Referee_t; + +typedef struct { + CMD_Joystick_t joy_left; /* 左摇杆 */ + CMD_Joystick_t joy_right; /* 右摇杆 */ + CMD_SwitchPos_t sw[4]; /* 4个拨杆 */ + float dial; /* 拨轮 */ +} CMD_RawInput_RC_t; + +typedef struct { + CMD_Mouse_t mouse; + CMD_Keyboard_t keyboard; +} CMD_RawInput_PC_t; + +typedef struct { + int a; +} CMD_RawInput_NUC_t; + +typedef struct { + CMD_Referee_t referee; +} CMD_RawInput_REF_t; + +/* 统一的原始输入结构 - 所有设备适配后都转换成这个格式 */ +typedef struct { + bool online[CMD_SRC_NUM]; + + /* 遥控器部分 */ + CMD_RawInput_RC_t rc; + + /* PC部分 */ + CMD_RawInput_PC_t pc; + + /* NUC部分 */ + /* 暂无定义,预留扩展 */ + CMD_RawInput_NUC_t nuc; + + /* REF部分 - 裁判系统数据 */ + CMD_RawInput_REF_t ref; +} CMD_RawInput_t; + +/* ========================================================================== */ +/* 模块掩码 */ +/* ========================================================================== */ +typedef enum { + CMD_MODULE_NONE = (1 << 0), + CMD_MODULE_CHASSIS = (1 << 1), + CMD_MODULE_GIMBAL = (1 << 2), + CMD_MODULE_SHOOT = (1 << 3), + CMD_MODULE_ALL = 0x0E +} CMD_ModuleMask_t; + +/* ========================================================================== */ +/* 行为定义 */ +/* ========================================================================== */ +/* 行为-按键映射宏表 */ +#define BEHAVIOR_CONFIG_COUNT (11) +#define CMD_BEHAVIOR_TABLE(X) \ + X(FORE, CMD_KEY_W, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(BACK, CMD_KEY_S, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(LEFT, CMD_KEY_A, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(RIGHT, CMD_KEY_D, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(ACCELERATE, CMD_KEY_SHIFT, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(DECELERATE, CMD_KEY_CTRL, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(FIRE, CMD_KEY_L_CLICK, CMD_ACTIVE_PRESSED, CMD_MODULE_SHOOT) \ + X(FIRE_MODE, CMD_KEY_B, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_SHOOT) \ + X(ROTOR, CMD_KEY_E, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(AUTOAIM, CMD_KEY_R, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_GIMBAL | CMD_MODULE_SHOOT) \ + X(CHECKSOURCERCPC, CMD_KEY_CTRL|CMD_KEY_SHIFT|CMD_KEY_V, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_NONE) +/* 触发类型 */ +typedef enum { + CMD_ACTIVE_PRESSED, /* 按住时触发 */ + CMD_ACTIVE_RISING_EDGE, /* 按下瞬间触发 */ + CMD_ACTIVE_FALLING_EDGE, /* 松开瞬间触发 */ +} CMD_TriggerType_t; + +/* 特殊按键值 */ +#define CMD_KEY_NONE 0xFF +#define CMD_KEY_L_CLICK (1 << 31) +#define CMD_KEY_R_CLICK (1 << 30) +#define CMD_KEY_M_CLICK (1 << 29) + +/* 行为枚举 - 由宏表自动生成 */ +#define ENUM_BEHAVIOR(name, key, trigger, mask) CMD_BEHAVIOR_##name, +typedef enum { + CMD_BEHAVIOR_TABLE(ENUM_BEHAVIOR) + CMD_BEHAVIOR_NUM +} CMD_Behavior_t; +#undef ENUM_BEHAVIOR + +/* ========================================================================== */ +/* 键盘辅助宏 */ +/* ========================================================================== */ +#define CMD_KEY_PRESSED(kb, key) (((kb)->bitmap >> (key)) & 1) +#define CMD_KEY_SET(kb, key) ((kb)->bitmap |= (1 << (key))) +#define CMD_KEY_CLEAR(kb, key) ((kb)->bitmap &= ~(1 << (key))) + +#ifdef __cplusplus +} +#endif diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..06d987c --- /dev/null +++ b/build.bat @@ -0,0 +1,51 @@ +@echo off +chcp 65001 > nul +echo ========================================== +echo MRobot 打包脚本 +echo ========================================== +echo. + +REM 清理旧的构建文件 +echo 1. 清理旧的构建文件... +if exist build rmdir /s /q build +if exist dist rmdir /s /q dist +if exist MRobot.spec del /f /q MRobot.spec + +REM 使用 PyInstaller 打包(onedir 模式) +echo. +echo 2. 使用 PyInstaller 打包... +pyinstaller MRobot.py --onedir --windowed --icon=assets\logo\M.ico --name=MRobot --clean + +if %errorlevel% neq 0 ( + echo. + echo ❌ PyInstaller 打包失败! + pause + exit /b 1 +) + +echo. +echo 3. 检查打包结果... +if not exist "dist\MRobot" ( + echo ❌ 未找到 dist\MRobot 目录! + pause + exit /b 1 +) + +if not exist "dist\MRobot\MRobot.exe" ( + echo ❌ 未找到 MRobot.exe! + pause + exit /b 1 +) + +echo. +echo ✅ PyInstaller 打包完成! +echo. +echo 4. 下一步: +echo - 如果要创建安装程序,请运行 Inno Setup 编译 MRobot.iss +echo - 或者直接使用 dist\MRobot 文件夹中的程序 +echo. +echo ========================================== +echo 打包完成 +echo ========================================== +echo. +pause diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..3b59ed0 --- /dev/null +++ b/build.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# MRobot 打包脚本 +# 使用方法: chmod +x build.sh && ./build.sh + +echo "==========================================" +echo " MRobot 打包脚本" +echo "==========================================" +echo "" + +# 清理旧的构建文件 +echo "1. 清理旧的构建文件..." +rm -rf build dist *.spec + +# 使用 PyInstaller 打包(onedir 模式) +echo "" +echo "2. 使用 PyInstaller 打包..." +pyinstaller MRobot.py \ + --onedir \ + --windowed \ + --icon=assets/logo/M.ico \ + --name=MRobot \ + --clean + +if [ $? -ne 0 ]; then + echo "" + echo "❌ PyInstaller 打包失败!" + exit 1 +fi + +echo "" +echo "3. 检查打包结果..." +if [ ! -d "dist/MRobot" ]; then + echo "❌ 未找到 dist/MRobot 目录!" + exit 1 +fi + +if [ ! -f "dist/MRobot/MRobot.exe" ]; then + echo "❌ 未找到 MRobot.exe!" + exit 1 +fi + +echo "" +echo "✅ PyInstaller 打包完成!" +echo "" +echo "4. 下一步:" +echo " - 如果要创建安装程序,请运行 Inno Setup 编译 MRobot.iss" +echo " - 或者直接使用 dist/MRobot 文件夹中的程序" +echo "" +echo "==========================================" +echo " 打包完成" +echo "=========================================="