基于 Milkv Duo 控制的 MMDVM 热点盒子

2024-03-16

在本地没有联网的数字中继或本地数字中继较远的情况下, MMDVM 盒子是数字电台全球通联的常用设备。MMDVM 盒子通常使用树莓派作为上位机,控制 MMDVM 单/双工热点板。相对 MMDVM 热点板来说,树莓派更为昂贵,故尝试使用便宜得多的 Milkv Duo 替代树莓派。

准备工作

  1. 有效的业余无线电台执照和呼号( DMR 制式还需要有效的 DMR ID)
  2. 一块刷好镜像、能动、能使用 RNDIS 的 Milkv Duo(这里以刷好 v1.0.9 镜像的 64M 版本 Milkv Duo 为例)
  3. 一台正常运行着 Archlinux (其他发行版也行)的计算机
  4. MMDVM 单工或双工热点板

MMDVM 选型

上位机软件选择 MMDVMHost;而 MMDVM 热点板选择某宝最便宜的 99 元人民币单工热点板,该热点板支持 DMR、 D-STAR、 C4FM、 P25、 NXDN 等常用制式。

线路连接

由于 Milkv Duo 具有 5V 和 3V3 电源引出,故可以直接由 Milkv Duo 给 MMDVM 热点板供电。板间通信使用 Milkv Duo 的 UART4 串口。

Milkv Duo 的引脚复用配置可以使用 duo-pinmux 命令查看,通常 GP2 和 GP3 已经被默认配置为 UART4 串口。热点板的引脚则通常使用树莓派引脚顺序。

详细的连接对应关系如下,热点板上多个 5V 和多个 GND 引脚接一个即可。

Milkv Duo 热点板
VBUS 5V
3V3(OUT) 3.3V
GND GND
UART4_TX TXD
UART4_RX RXD

注意热点板上 TXD 和 RXD 引脚连接的分别是 stm32c8t6 上 USART 的 RXD 和 TXD,故热点板和 Milkv Duo 连接时应当为 UART4_TX 对 TXD、 UART4_RX 对 RXD。

构建 MMDVMHost

这里使用 RUYI 包管理安装 Milkv Duo 交叉编译工具链,在 Archlinux 上构建 Milkv Duo 所需的二进制。

首先建立并进入编译环境。

$ ruyi install gnu-plct
$ ruyi venv -t gnu-plct milkv-duo venv-duo
$ . venv-duo/bin/ruyi-activate

当前目录被认为是 <ruyi_venv_dir>,这个变量后面会用到。基于此,建立的编译环境目录为 <ruyi_venv_dir>/venv-duo

构建 MMDVMHost 之前需要解决前置依赖,这里依次构建。

首先解决 fftw3。

$ wget http://fftw.org/fftw-3.3.10.tar.gz
$ tar xf fftw-3.3.10.tar.gz
$ cd fftw-3.3.10/
$ ./configure CC="riscv64-plct-linux-gnu-gcc" --host=riscv64-linux
$ make -j4
$ make install DESTDIR=<ruyi_venv_dir>/venv-duo/fftw3/

再构建 libsamplerate。

$ git clone https://github.com/libsndfile/libsamplerate
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DLIBSAMPLERATE_EXAMPLES=OFF -DCMAKE_C_COMPILER=riscv64-plct-linux-gnu-gcc -DCMAKE_C_FLAGS=-I<ruyi_venv_dir>/venv-duo/fftw3/usr/local/include
$ make -j4
$ make install DESTDIR=<ruyi_venv_dir>/venv-duo/libsamplerate

前置依赖已经满足,此时可以构建 MMDVMHost。

$ git clone https://github.com/g4klx/MMDVMHost

修改 Makefile,这里给出一个 patch。

diff --git a/Makefile b/Makefile
index aa7dec7..3bd1c34 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,10 @@
 # This makefile is for all platforms, but doesn't include support for the HD44780, OLED, or PCF8574 displays on the Raspberry Pi.
 
-CC      = cc
-CXX     = c++
-CFLAGS  = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -I/usr/local/include
-LIBS    = -lpthread -lutil -lsamplerate
-LDFLAGS = -g -L/usr/local/lib
+CC      = riscv64-plct-linux-gnu-gcc
+CXX     = riscv64-plct-linux-gnu-g++
+CFLAGS  = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -I/home/hachi/Documents/Working/ruyi-venv/venv-duo/libsamplerate/usr/local/include/
+LIBS    = -lpthread -lutil -lsamplerate -L/home/hachi/Documents/Working/ruyi-venv/venv-duo/libsamplerate/usr/local/lib/
+LDFLAGS = -g -static
 
 OBJECTS = \
                AMBEFEC.o BCH.o AX25Control.o AX25Network.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \

注意 LDFLAGS 给出了 -static 指定构建静态链接的二进制。

开始构建。

$ make -j4

上传二进制到 Milkv Duo。

$ scp -O MMDVMHost root@192.168.42.1:~
$ scp -O RemoteCommand root@192.168.42.1:~
$ scp -O MMDVM.ini root@192.168.42.1:~

安装和配置 MMDVMHost

登陆 Milkv Duo,这个 IP 地址可能需要根据实际情况修改。

$ ssh root@192.168.42.1

添加 mmdvm 用户和组。

addgroup mmdvm
adduser -H -D -S -G mmdvm -s /bin/false mmdvm

MMDVMHostRemoteCommand 安装在 /opt/MMDVMHost 目录下, MMDVM.ini 则放置在 /etc/MMDVM.ini

本文不涉及 MMDVMHost 的详细配置,但还是提醒更改 /etc/MMDVM.ini 中的配置 Daemon=1

建立 /opt/MMDVMHost/start_mmdvm 启动脚本。

#/bin/sh

echo Check Internet Connection
while ! ping -c 1 bing.com 2>&1 > /dev/null; do
        sleep 5s
done

echo Check NTP time update
wt=1
while [ `date '+%Y'` = 1970 ]; do
        wt=`expr $wt + 1`
        if [ $wt -ge 30 ]; then
                echo Wait NTP timeout 30s
                break
        fi
        try $wt
        sleep 1s
done

echo Start MMDVMHost
[ -d /var/log/mmdvm ] || mkdir /var/log/mmdvm
chown mmdvm:mmdvm /var/log/mmdvm /dev/ttyS4
/opt/MMDVMHost/MMDVMHost

注意 /var/log/mmdvm 是 MMDVM.ini 中配置的日志目录; /dev/ttyS4 是 Milkv Duo 和 MMDVM 热点板通信的串口,这里使用的 UART4 即为 Pin4(GP2) 和 Pin5(GP3)。

使其可执行。

chmod +x /opt/MMDVMHost/start_mmdvm

最后配置网络。

首先编辑 /etc/dnsmasq.conf 固定上位机的 IP。

dhcp-range=192.168.42.46,192.168.42.46,1h

编写 /etc/init.d/S99zuser 脚本,上电自动添加 Gateway 和启动 MMDVMHost。

#!/bin/sh
${CVI_SHOPTS}
#
# Add Default Gateway
#

case "$1" in
  start)
        if /sbin/ip link | grep usb0; then
          echo Add default gateway 192.168.42.46 > /var/log/mylog
        else
          echo RNDIS not on > /var/log/mylog
        fi
        for i in $(seq 1 30); do
          /sbin/ip route add default via 192.168.42.46 && break
          sleep 1s
          echo Try $i >> /var/log/mylog
        done
        /opt/MMDVMHost/start_mmdvm >> /var/log/mylog &
        ;;
  stop)
        ;;
  restart|reload)
        ;;
  *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
esac

exit $?

/etc/resolv.conf.tail 添加 nameserver,这也需要根据实际情况修改。

nameserver 192.168.0.1
nameserver 192.168.1.1
nameserver 223.5.5.5
nameserver 8.8.8.8

重启 Milkv Duo,目的是查看这些配置是否生效。

reboot

查看 ip route 的输出是否有默认网关。

# ip route
default via 192.168.42.46 dev usb0 
192.168.42.0/24 dev usb0 scope link  src 192.168.42.1

此时应当能够共享上位机的网络,如果不能访问则可能需要检查上位机的配置。

# ping bing.com
PING bing.com (204.79.197.200): 56 data bytes
64 bytes from 204.79.197.200: seq=0 ttl=113 time=69.016 ms
^C
--- bing.com ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 69.016/69.016/69.016 ms

在上位机中,首先确认已经允许 IPv4 Forward。

# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1

再允许两个 interface 之间的转发,其中 eth0 是上位机可以访问外网的端口,而 usb0 是 Milkv Duo 的 USB 网络。这两个端口名称需要根据实际情况修改。

sudo iptables -A FORWARD -i usb0 -j ACCEPT
sudo iptables -A FORWARD -o usb0 -j ACCEPT
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

由于 MMDVMHost 的启动脚本在外网不通的情况下会一直等待,在外网访问畅通时 MMDVMHost 才会启动。
查看日志 /var/log/mylog/var/log/mmdvm 确认此时 MMDVMHost 运行正常。

不再使用 RNDIS

若不再希望使用 RNDIS 进行网络连接,那么有线网络是一个最容易实现的选择,在解决了无线网卡驱动的情况下也可以使用 USB 无线网卡。

首先关闭 RNDIS 并启用 USB Host 模式,这主要为了后续能够使用 USB 无线网卡。

rm /mnt/system/usb.sh
ln -sf /mnt/system/usb-host.sh /mnt/system/usb.sh

连接 RJ45,这里连接公头母头均可,它们的线序是一样的。

Milkv Duo RJ45
TX+ 1
TX- 2
RX+ 3
RX- 6

连接网线后会自动配置网络。

ethtool

实验板是用洞洞板飞线飞起来的,连线质量不高导致,网口速率高了就会断联。

# dmesg
[  108.724734] bm-dwmac 4070000.ethernet eth0: Link is Down
[  110.773714] bm-dwmac 4070000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
[  111.796713] bm-dwmac 4070000.ethernet eth0: Link is Down
[  112.821740] bm-dwmac 4070000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
[  113.844730] bm-dwmac 4070000.ethernet eth0: Link is Down
[  115.893750] bm-dwmac 4070000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
[  116.916746] bm-dwmac 4070000.ethernet eth0: Link is Down
[  117.941771] bm-dwmac 4070000.ethernet eth0: Link is Up - 10Mbps/Full - flow control rx/tx
[  118.964725] bm-dwmac 4070000.ethernet eth0: Link is Down
[  119.989769] bm-dwmac 4070000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
[  121.012725] bm-dwmac 4070000.ethernet eth0: Link is Down
[  125.109749] bm-dwmac 4070000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
[  126.132731] bm-dwmac 4070000.ethernet eth0: Link is Down
[  127.157731] bm-dwmac 4070000.ethernet eth0: Link is Up - 10Mbps/Full - flow control rx/tx
[  139.444722] bm-dwmac 4070000.ethernet eth0: Link is Down
[  143.541737] bm-dwmac 4070000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
[  144.564727] bm-dwmac 4070000.ethernet eth0: Link is Down
[  145.589742] bm-dwmac 4070000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
[  146.612728] bm-dwmac 4070000.ethernet eth0: Link is Down
[  148.661731] bm-dwmac 4070000.ethernet eth0: Link is Up - 10Mbps/Full - flow control rx/tx

MMDVM 并不需要多高的网络连接速度,故尝试限制到 10Mbps。

$ git clone https://github.com/Distrotech/ethtool --depth=1
$ cd ethtool
$ LDFLAGS=-static ./configure CC="riscv64-plct-linux-gnu-gcc" --host=riscv64-linux
$ make -j4

得到 ethtool 二进制,传送到 Milkv Duo 上。

限制网络连接速度。

ethtool -s eth0 speed 10

应该也可以用 tc 命令,不过 ethtool 显然更简洁些。

局限性

  1. 在没有显示屏的情况下,只能通过 MMDVM 热点板上的 LED 指示灯观察工作情况

其他工作

  1. 由于官方镜像至多只有 29M 可供使用,建议自行重新构建镜像
  2. 该 MMDVMHost 构建不携带 LCD/OLED 显示屏驱动,这是因为这个驱动依赖于 WiringPi,驱动支持还需要额外的工作

这些工作已经更新在这篇中。

这里是桜風の狐,将美好的 73 送上。

3 Likes