223 lines
7.0 KiB
Markdown
223 lines
7.0 KiB
Markdown
# mini_desktop — GEC6818 桌面系统
|
||
|
||
粤嵌 GEC6818(ARM Cortex-A53 armv7l, Linux 3.4.39-gec)
|
||
嵌入式桌面系统。800×480 LCD 触摸屏,集成电子相册、红外遥控和游戏启动器。
|
||
|
||
## 功能
|
||
|
||
```
|
||
桌面 ── 图库 (触摸滑动 / 遥控翻页浏览照片)
|
||
├─ 游戏 (3D 光线投射游戏)
|
||
└─ 红外 (学习 / 发送 / 接收红外遥控码)
|
||
└─ 后台接收 → 遥控桌面导航
|
||
```
|
||
|
||
- **桌面**:3 个圆角图标(图库、游戏、红外),支持触摸点击和遥控框选
|
||
- **图库**:BMP 照片浏览,触摸左右滑动或遥控翻页,上键/点顶栏退出
|
||
- **游戏**:通过 `system()` 启动外部 `raycast_game_static`,退出后 fb_reset 恢复
|
||
- **红外**:5 键学习(上下左右中),发送/接收页面,后台常驻识别遥控码
|
||
- **遥控导航**:左右键移动白色选框,中键进入应用
|
||
|
||
## 硬件
|
||
|
||
| 项目 | 详情 |
|
||
|------|------|
|
||
| 开发板 | 粤嵌 GEC6818 |
|
||
| 主控 | Samsung S5P6818, ARM Cortex-A53, armv7l |
|
||
| 系统 | Linux 3.4.39-gec, BusyBox |
|
||
| 屏幕 | 800×480 LCD, 32bpp framebuffer (/dev/fb0) |
|
||
| 触摸 | gslX680, 1024×600 raw → 800×480 校准 (/dev/input/event0) |
|
||
| 红外 | YS-IRTM 红外模块,串口 /dev/ttySAC1, 9600 8N1, 模块自动去 A1F1 头,输出 3 字节用户码 |
|
||
| 蜂鸣器 | /sys/kernel/gec_ctrl/beep(4 字节小端 int 写入;shell echo 会写入 `0\n` 误解析为非零值)|
|
||
| LED | /sys/class/leds/ledN/brightness(1 字节 ASCII '0'/'1' 写入)|
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
mini_desktop/
|
||
├── main.c # 入口
|
||
├── Makefile
|
||
├── common/ # 硬件抽象层
|
||
│ ├── device.c/.h # framebuffer / 触摸 / BMP / 字体 / 蜂鸣器 / LED
|
||
│ ├── param.h # 屏幕参数、触摸校准
|
||
│ └── tools.c/.h
|
||
├── button/ # 按钮系统
|
||
│ └── button.c/.h # 圆角矩形、文字标签、BMP 背景、绿色已学标记
|
||
├── album/ # 电子相册
|
||
│ └── album.c/.h
|
||
├── ir_app/ # 红外功能
|
||
│ └── ir_app.c/.h # 学习 / 发送 / 接收 / 后台遥控
|
||
├── desktop/ # 桌面
|
||
│ └── desktop.c/.h # 图标布局、触摸分发、遥控导航
|
||
├── fonts/
|
||
│ └── font_16x16.h # 16×16 等宽字模(A-Z + 0-9, Monaco 14pt 生成)
|
||
├── images/ # 相册照片(800×480 BMP)
|
||
├── icon/ # 桌面图标 + 背景(BMP)
|
||
└── test/ # 分步测试
|
||
```
|
||
|
||
## 板子初始化
|
||
|
||
首次拿到板子或烧录系统后,需要配置网络和 SSH。
|
||
|
||
### 固定 IP
|
||
|
||
编辑 `/etc/profile`,在末尾添加:
|
||
|
||
```bash
|
||
ifconfig eth0 up
|
||
ifconfig eth0 192.168.1.88 netmask 255.255.255.0
|
||
route add default gw 192.168.1.1
|
||
```
|
||
|
||
重启或执行 `source /etc/profile` 生效。注意板子 IP 需要和电脑在同一网段。
|
||
|
||
### 启用 eth0
|
||
|
||
如果 `ifconfig` 看不到 eth0,检查网线是否插好、交换机/路由器是否通电:
|
||
|
||
```bash
|
||
# 查看所有网口
|
||
ifconfig -a
|
||
|
||
# 手动启用
|
||
ifconfig eth0 up
|
||
```
|
||
|
||
某些镜像的 eth0 默认是 down 状态,加到 `/etc/profile` 里开机自动启用即可。
|
||
|
||
### 安装 SSH(dropbear)
|
||
|
||
板子默认可能没有 SSH 服务。检查:
|
||
|
||
```bash
|
||
ls /usr/sbin/dropbear # dropbear 服务端
|
||
ls /usr/bin/dbclient # dropbear 客户端(SSH 登录用)
|
||
```
|
||
|
||
如果缺失,从交叉编译工具链或同型号板子拷贝:
|
||
|
||
```bash
|
||
# 在能 SSH 的板子上导出
|
||
scp /usr/sbin/dropbear /usr/bin/dbclient root@<目标IP>:/tmp/
|
||
|
||
# 在目标板子上
|
||
cp /tmp/dropbear /usr/sbin/dropbear
|
||
cp /tmp/dbclient /usr/bin/dbclient
|
||
chmod +x /usr/sbin/dropbear /usr/bin/dbclient
|
||
```
|
||
|
||
创建 host key 并启动:
|
||
|
||
```bash
|
||
mkdir -p /etc/dropbear
|
||
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
|
||
dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key
|
||
dropbear -p 22
|
||
```
|
||
|
||
确认启动:
|
||
|
||
```bash
|
||
ps | grep dropbear
|
||
```
|
||
|
||
设置开机自启(加到 `/etc/profile` 末尾):
|
||
|
||
```bash
|
||
dropbear -p 22 &
|
||
```
|
||
|
||
之后即可从电脑 SSH 登录:`ssh root@192.168.1.88`。
|
||
|
||
## 编译
|
||
|
||
```bash
|
||
docker run --platform linux/amd64 --rm \
|
||
-v /path/to/toolchain:/opt/gec6818-toolchain:ro \
|
||
-v /path/to/mini_desktop:/work -w /work \
|
||
gec6818-dev:ubuntu18 bash -c 'make static'
|
||
```
|
||
|
||
工具链路径:[`gec6818_env_toolchain/toolchain/`](../gec6818_env_toolchain/toolchain/),ARM 32-bit soft-float,GCC 5.4.0。
|
||
|
||
## 部署
|
||
|
||
板子 IP `192.168.1.88`,目标目录 `/home/cyy/`。
|
||
|
||
```bash
|
||
# 停止旧进程
|
||
ssh root@192.168.1.88 'killall mini_desktop 2>/dev/null; sleep 1'
|
||
|
||
# 主程序
|
||
scp -O mini_desktop root@192.168.1.88:/home/cyy/
|
||
|
||
# 资源文件
|
||
ssh root@192.168.1.88 'mkdir -p /home/cyy/icon /home/cyy/images'
|
||
scp -O icon/*.bmp root@192.168.1.88:/home/cyy/icon/
|
||
scp -O images/*.bmp root@192.168.1.88:/home/cyy/images/
|
||
|
||
# 游戏(单独部署)
|
||
scp -O raycast_game_static root@192.168.1.88:/home/cyy/
|
||
```
|
||
|
||
### 需要部署的 BMP 清单
|
||
|
||
```
|
||
icon/
|
||
├── background.bmp # 桌面背景(800×480)
|
||
├── photo_icon.bmp # 图库图标(~80×80,圆角)
|
||
├── game_icon.bmp # 游戏图标
|
||
├── ir_icon.bmp # 红外图标
|
||
├── bg_page.bmp # 红外子页面背景(800×480)
|
||
└── bar_top.bmp # 红外顶栏(800×44)
|
||
|
||
images/
|
||
├── photo_1.bmp # 相册照片(800×480)
|
||
├── photo_2.bmp
|
||
└── photo_3.bmp
|
||
```
|
||
|
||
IR 学习数据 `ir_send_*.txt` / `ir_recv_*.txt` 由程序自动生成,无需预部署。
|
||
|
||
## 运行
|
||
|
||
在板子上:
|
||
|
||
```bash
|
||
cd /home/cyy
|
||
./mini_desktop
|
||
```
|
||
|
||
触摸顶栏返回上级菜单,触摸图标进入应用。遥控器需先在「红外 → Learn → RECV 模式」学习 5 个键(上下左右中),之后桌面和图库中可用遥控操作。
|
||
|
||
## 设计约定
|
||
|
||
### 非阻塞 I/O
|
||
|
||
所有 I/O 使用 `O_NONBLOCK` + 事件排空模式。每帧先 `while(ts_read > 0)` 排空触摸,
|
||
循环退出后执行其他逻辑(串口轮询等),最后回到外层循环。UI 对触摸和串口同时响应。
|
||
|
||
### `ts_read()` 的 `has_new` 陷阱
|
||
|
||
`ts_read()` 内有 `static int has_new`,**每次调用必须重置为 0**。
|
||
忘记重置会导致首次触摸后 `ts_read()` 永远返回 1,
|
||
`while(ts_read > 0)` 死循环,后续代码永不执行。
|
||
此前曾导致红外学习页面无法读到串口数据。
|
||
|
||
### 触摸排空
|
||
|
||
子应用返回时务必排空触摸 + 红外缓冲,防止上一个触摸/遥控事件泄漏到下个页面。
|
||
使用 `drain_both()`(排空触摸 + `ir_flush()`)。
|
||
|
||
### 游戏退出后的 framebuffer
|
||
|
||
游戏使用双缓冲 `FBIOPAN_DISPLAY` 翻页,退出后 yoffset 可能非零。
|
||
必须在游戏返回后调 `fb_reset()` 复位 yoffset 并重读参数。
|
||
|
||
### BMP 渲染性能
|
||
|
||
- `bmp_display`(全屏背景):stride 匹配时一次 `memcpy`,否则逐行 `memcpy`
|
||
- `show_bmp`(图标/局部):无裁剪时一次 `memcpy`,有裁剪时逐行 `memcpy`
|
||
- 不再逐像素处理透明(alpha 字节由 LCD 控制器忽略)
|