# Avaota F1 开发与集成

> 面向仓库根目录的总览文档，整合 Day1–Day9 日志、任务清单与完成总结。

---

## 1. 项目简介

本项目面向 **Avaota F1 AI 机器人**，基于 **全志 V821 / 32-bit RISC‑V** SoC，目标是在 Tina Linux 固件上实现一套「可量产」的机器人终端固件，集成：

- 音频采集（板载模拟麦克风）与播放（I2S + MAX98357A）
- IMU 六轴姿态传感（ICM‑42688‑P）
- GC2083 MIPI 摄像头 JPEG 图像采集
- UDP / HTTP / WebSocket 网络通讯
- 多线程主程序与静态链接交叉编译流程

文档与代码组织按「Day1–Day9 开发日志 + 任务清单 + 完成总结」推进，可作为以后移植到其他 Tina Linux / 全志平台的模板工程。

目前对话的位置是本地Windows 11系统的主机，用于开发的环境是局域网中的Ubuntu服务器。

---

## 2. 硬件与开发环境

### 2.1 目标硬件（板端）

- **SoC**：全志 V821，32‑bit RISC‑V 架构  
- **板载外设**
  - 模拟麦克风 → 内置 Audio Codec（audiocodec）
  - I2S 数字功放：MAX98357A（BCLK/LRCK/DOUT：PD12/PD13/PD15）
  - 摄像头：GC2083，MIPI‑CSI2，典型输出 1280×720 @ 20fps
  - IMU：ICM‑42688‑P（GPIO 模拟 SPI）
- **操作系统**：Tina Linux（基于 OpenWrt 的 Allwinner SDK）

### 2.2 主机开发环境（PC）

- **系统**：Ubuntu 24.04 LTS（同时也有 Windows + WSL 的混合开发）
- **工具链 & SDK**
  - Tina SDK：`tina-v821-release`
  - `/home/rongye/ProgramFiles/AvaotaF1/avaota_sdk/tina-v821-release` 这是SDK位置
  - 交叉编译工具链：
    - **当前使用**：`prebuilt/rootfsbuilt/riscv/nds32le-linux-musl-v5d` ⭐ **musl 工具链（与开发板兼容）**
    - 编译器前缀：`riscv32-linux-musl-`
    - ~~已废弃~~：`out/toolchain/nds32le-linux-glibc-v5d` (glibc 工具链，与板端 musl libc 1.2.4 不兼容)
  - `/home/rongye/ProgramFiles/AvaotaF1/avaota_app_demo` 这是交叉编译的位置
  - Python：通过 `python-is-python3` 或为遗留脚本装 python2 并软链到 `python`

### 2.3 开发主机准备要点（Ubuntu 24.04）

- 开启 i386 架构以兼容旧版 32 位库
- 手动安装被移除的 `libncurses5` / `libtinfo5`
- 安装 bison / flex / 交叉编译依赖，修复 `lunch` / `make` 时报错
- 注意 `make -j` 一定要限制并行度（如 `-j8`），避免 OOM

---

## 3. 仓库结构建议

实际仓库结构可按以下思路组织（示例）：

```text
.
├── ../Docs/DevLogs/   # (位于上级目录) 每日开发日志
│   ├── Day1.md … Day18.md
├── docs/              # 本地硬件/SDK文档
│   ├── 1.png … 2.png
│   ├── AvaotaF1.md
│   ├── 引脚.md
│   ├── TinaSDK-Docs/
│   ├── tina_files_clean.csv
├── ESP32S3/                       # 可参考的ESP32S3固件
├── src/
│   ├── audio/                     # AudioCapture / AudioPlayer
│   ├── camera/                    # Camera 类 / MPP 封装
│   ├── imu/                       # ICM‑42688 SPI 驱动与测试
│   ├── network/                   # UDP / HTTP / WebSocket 客户端
│   ├── utils/                     
│   ├── main.cpp                   # 主程序入口（多线程集成）
│   ├── main_test.cpp              # 本地硬件自检程序
│   ├── Makefile                   # 交叉编译配置
│   └── build_*.sh                 # 构建脚本（main/test/phaseX）
├── build_main.sh
├── logs.md                        # 编译时的日志（实时填写）
└── README.md                      # 本文档
```

你可以直接把 Day1–Day7、任务清单与完成总结放到 `../docs/DevLogs/` 目录，并用当前 README 作为入口索引。

---

## 4. 功能模块概览

### 4.1 音频系统

**输入：板载模拟麦克风**

- 通过 SoC 内部 **Audio Codec (audiocodec)** 采集  
- ALSA 设备：`hw:audiocodec` 或 `hw:0,0`（录音推荐 `plughw:0,0`）  
- 运行时配置：
  - `MIC Switch` 开启
  - `MIC Gain` 建议值 25（在音量与底噪之间平衡）
  - `adc-vol` 与 `lineout-gain` 使用 DTS 默认值或适度调整
- 采样参数：
  - 16 kHz, S16_LE, Mono  
- 典型链路：
  - `setup_mic.sh` → `arecord` → `/tmp/test_mic.wav` → `aplay` / 上行网络

**输出：I2S + MAX98357A**

- I2S0 接 MAX98357A，扬声器输出  
- Device Tree 为每个引脚创建独立 pinctrl 节点：
  - `i2s0_bclk_pin`：PD12
  - `i2s0_lrck_pin`：PD13
  - `i2s0_dout0_pin`：PD15
- I2S 平台设备 `&i2s0_plat` 绑定这些引脚，`status = "okay"`
- 通过 ALSA `aplay` / 自己的 `AudioPlayer` 类进行播放

### 4.2 IMU 传感器（ICM‑42688‑P）

- 最终采用 **GPIO 模拟 SPI**：
  - SCLK: PD3
  - MOSI: PD2
  - MISO: PD4
  - CS  : PD5
- SPI Mode0，软件 bit‑bang，速率约 500 kHz（可按需提升）
- 主要特性：
  - WHO_AM_I = 0x47 识别验证
  - 加速度计：±16g，1 kHz ODR
  - 陀螺仪：±2000 °/s，1 kHz ODR
  - 温度通道：用于环境监控与漂移补偿
- 静止状态验证：
  - 合加速度 ≈ 9.8 m/s²
  - 陀螺仪接近 0 °/s
- 上层封装：
  - `ICM42688` 类提供采样与单位转换
  - 独立 `test_imu` 自检程序
  - 在主程序中通过 UDP 周期性上报 JSON/结构体数据

### 4.3 摄像头系统（GC2083 + MPP）

- 使用 Allwinner Eyesee‑MPP 框架：SYS → VI → ISP → VENC
- 流水线：
  - VI（接 MIPI 摄像头）
  - ISP（自动曝光、白平衡、降噪）
  - VENC（JPEG 编码）
- 关键配置：
  - 分辨率：1280×720 @ 20fps（可调）
  - JPEG 质量：80（在质量与码率之间折中）
  - VI Buffer：5 帧
  - VBV Buffer：4 MB，避免 `VBV FULL` 错误
- `Camera` 类职责：
  - 完成 MPP 初始化 / 绑定 / 销毁
  - 按需抓拍单帧 JPEG（用于 WebSocket 发送或本地保存）
  - 提供阻塞式 `capture_frame()` 接口与重试机制
- 测试程序：
  - `test_camera` 抓拍多张 JPEG 保存到 SD 卡
  - 实测成功率 100%，文件大小 20–80 KB 之间，画面曝光正常

### 4.4 网络通讯

**UDP**

- 轻量 IMU 数据上报通道
- 使用 POSIX socket，静态链接，无额外依赖
- 典型用法：
  - `UDPSender` 初始化目标 IP/Port
  - 周期性发送 IMU/状态数据

**HTTP（libcurl 或轻量封装）**

- 主要用途：
  - 从服务器拉取 TTS 音频流（如 `stream.wav`）
  - 拉取配置文件或诊断信息
- 流式下载接口已预留，可边下边写入 `AudioPlayer` 播放

**WebSocket**

- 早期方案：SDK 内置 `libuwsc`（后期为规避依赖，可用自实现轻量 WS 客户端）
- 主要用途：
  - 上行：摄像头 JPEG 帧、音频 PCM 片段
  - 下行：控制指令 / 状态同步
- 接口设计：
  - `WSClient` 负责 TCP 连接、握手、帧收发、心跳与重连
  - 主线程中，每个子模块持有各自的 WSClient 实例或共享连接

---

## 5. 编译与构建流程

### 5.1 Tina SDK 环境准备（概要）

1. 解压 SDK：
   ```bash
   mkdir -p ~/ProgramFiles/avaota_sdk
   tar -xvf tina-v821-*.tar.xz -C ~/ProgramFiles/avaota_sdk
   ```
2. 初始化环境：
   ```bash
   cd ~/ProgramFiles/avaota_sdk/tina-v821-release
   source build/envsetup.sh
   lunch  # 选择 avaota_f1 / v821 相关配置
   ```
3. 全量编译：
   ```bash
   make -j8
   pack  # 需要时打包固件
   ```

### 5.2 应用程序交叉编译

在 `src/` 目录中提供一个或多个构建脚本，例如：

```bash
#!/bin/bash
set -e

SDK_ROOT=~/ProgramFiles/AvaotaF1/avaota_sdk/tina-v821-release
# ⚠️ 使用 musl 工具链（与开发板兼容）
TOOLCHAIN=${SDK_ROOT}/prebuilt/rootfsbuilt/riscv/nds32le-linux-musl-v5d/bin

export PATH=${TOOLCHAIN}:$PATH

make clean
make all -j4   # 或按目标拆分：make main / make test_audio / make test_imu
```

Makefile 要点：

- 使用 `riscv32-linux-musl-g++` 编译器（musl 工具链）
- 动态链接器：`/lib32/ld.so.1`（板端需创建符号链接：`ln -s /lib32/ilp32d/libc.so /lib32/ld.so.1`）
- 链接静态或最小依赖的动态库
- 注意链接顺序：业务库 → MPP/ISP/cedarx → `-lpthread -lrt -lm -ldl -lstdc++`

### 5.3 部署与运行

1. 将交叉编译好的可执行文件拷贝到 SD 卡：
   ```bash
   cp avaota_client /media/$USER/SDCARD/
   ```
2. 板端挂载 SD 卡并复制到 `/tmp`：
   ```bash
   mount /dev/mmcblk0p1 /mnt/extsd
   cp /mnt/extsd/avaota_client /tmp/
   chmod +x /tmp/avaota_client
   ```
3. 运行：
   ```bash
   /tmp/avaota_client
   ```

> 推荐所有测试程序（`test_audio` / `test_imu` / `test_camera` / `avaota_test`）都统一走上述流程，避免执行权限与只读分区问题。

---

## 6. 主程序（集成）架构示意

主程序建议使用多线程模型，将各个模块解耦：

```cpp
// 伪代码示例
int main() {
    init_logging();
    init_network_config();   // 服务器 IP / 端口 / 路径等
    init_signal_handler();   // Ctrl+C 安全退出

    std::thread cam_thread(run_camera_loop);
    std::thread mic_thread(run_audio_capture_loop);
    std::thread spk_thread(run_audio_play_loop);
    std::thread imu_thread(run_imu_udp_loop);

    // 可选：主线程处理下行指令 / 状态机
    run_main_control_loop();

    // 等待退出
    cam_thread.join();
    mic_thread.join();
    spk_thread.join();
    imu_thread.join();
    return 0;
}
```

每个线程内部：

- 初始化各自的硬件和网络客户端
- 进入循环：
  - 采集 → 编码（可选） → 通过 UDP/WS 发送
  - 或从 HTTP/WS 接收 → 解码（可选） → 播放/控制硬件
- 捕获异常并尝试重连 / 恢复，必要时上报主线程

---

## 7. 日志与文档索引

可以在 README 中给出所有开发日志与计划文档的入口，方便回溯：

- `../Docs/DevLogs/Day1.md`：SDK 编译与 32 位环境踩坑
- `../Docs/DevLogs/Day2.md`：UDP 通信、网络库编译、libuwsc / libcurl 准备
- `../Docs/DevLogs/Day3.md`：音频采集 & 播放模块（ALSA + I2S）
- `../Docs/DevLogs/Day4.md`：模拟麦克风配置 + IMU SPI 驱动与验证
- `../Docs/DevLogs/Day5.md`：GC2083 摄像头 MPP 集成与 JPEG 捕获
- `../Docs/DevLogs/Day6.md`：硬件全功能验证、本地测试程序、网络库诊断
- `../Docs/DevLogs/Day7.md`：交叉编译 Makefile 收敛、工具链配置
- `../Docs/DevLogs/Day8.md`：整体编译成功、Cedar 库链接完成
- `../Docs/DevLogs/Day9.md`：⭐ **musl 工具链修复 + 板上测试通过**
- `../Docs/task_complete.md`：完整任务清单与进度条（97% 完成）
- `../Docs/implementation_plan_complete.md`：实现计划 & 各阶段目标拆解

---

## 8. 任务完成度与后续工作

### 8.1 当前完成度（参考任务清单与总结）

- SDK/工具链/固件：✅
- musl 工具链修复：✅ **（Day 9 关键突破）**
- 音频采集 & 播放：✅
- IMU 采集：✅ **（板上测试通过）**
- 摄像头采集：✅ **（板上测试通过）**
- UDP / HTTP / WebSocket 基础：✅（库与客户端实现已完成）
- WiFi 网络配置：✅ **（192.168.110.132）**
- 板端硬件测试：✅ **（所有模块通过）**
- 网络服务器通信测试：⏳（服务器已部署，待测试）
- 性能评估与稳定性验证：⏳（待完成）

整体项目 **97%** 完成，核心功能全部验证通过！🎉

### 8.2 建议的后续 TODO

- 将服务器 IP / 端口、音频参数、帧率等抽象为配置文件（JSON / INI）
- 丰富错误日志并加上日志轮转
- 对 WebSocket / HTTP 加入重连与指数退避策略
- 若后续量产，考虑：
  - 用硬件 SPI 替换 GPIO bit‑bang
  - 对功耗与休眠策略进行优化
  - 引入简单看门狗机制，防止长期运行卡死

---

## 9. 如何使用本 README

- **新成员上手**：从本 README 入手，结合 `../Docs/DevLogs/DayX.md` 逐步了解每个子系统的设计与坑点。
- **以后复用到新项目**：可以直接复制「编译流程」「外设接线 + DTS 配置」「主程序多线程架构」这几部分，稍作修改即可移植到其他全志 / RISC‑V 设备。
- **代码导航入口**：按模块查找 `src/audio`, `src/imu`, `src/camera`, `src/network` 目录，结合对应的 DayX 日志阅读。

祝使用愉快 🎉，也欢迎在后续开发阶段继续补充和更新本 README。
