Dual AIOC Full-Duplex Pi Zero 2w node

Introduction

I recently undertook a journey to setup a full duplex node/repeater using 2 AIOC devices and a pi zero 2w. I struggled to find documentation that covered how to use 2 different sound devices for a node, as opposed to 1 device with input and output split, and even more specifically on a pi zero 2w with AIOCs, so I wanted to put together a quick guide in hopes that I might help others on this same path.

This is not meant as a comprehensive guide, but rather pulling together a few other guides and what extra information may be helpful. Though I am sure there are others, I am only aware of one person with a similar setup. Unfortunately his videos are in French and I don’t see any actual configuration examples in them.

If you find this guide useful, please do leave a comment. If you feel anything needs clarification, addition, or is factually inaccurate, please also leave a comment and I will make every effort to update the guide for accuracy/completeness.

Prerequisites

Hardware

  1. RPi Zero 2w (this should work with any current Pi, but I only tested with a Zero 2w and some of the issues encountered were likely specific to the zero 2w).
  2. USB Hat. I used this one, however this should work with any similar “pogo pin” style hat and possibly the USB/POE hats.
  3. 2x AOIC, hardware revision 1.2, flashed to firmware 1.4
  4. 2x node radios verified working with your AIOC, programmed to your desired frequencies. I have tested with Baofeng BF-888s and Retevis RT85 radios.

Software

  1. A working baseline install asl3 and some familiarity with asl3.
  2. aioc-util setup and working on your node, including the udev rule.
  3. Ideally you will have created a basic simplex node using one of the radios and one of the AIOCs via the asl3 setup menu and verified that it functions.
  4. All PI work will be using SSH, assuming a regular user with access to run sudo commands.

General Notes

If COS is not triggering consistently, check the volume level on the radio receiving node communications. The AIOC uses voltage from the carrier on the incoming audio to trigger COS. This scales with volume. This is also the easiest way to set node volume.

The AIOC is a composite USB device, meaning that it presents itself to the OS as several devices. Relevant to our uses, these are

  • A USB sound card emulating a CM108.
  • A Human Interface Device (hereafter HID) used to program the AIOC.
  • A serial port used to program the radio.

On your asl3 installation you will see something like this:

❯ lsusb -t
/:  Bus 001.Port 001: Dev 001, Class=root_hub, Driver=dwc2/1p, 480M
    |__ Port 001: Dev 002, If 0, Class=Hub, Driver=hub/4p, 480M
        |__ Port 001: Dev 003, If 0, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 001: Dev 003, If 1, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 001: Dev 003, If 2, Class=Audio, Driver=snd-usb-audio, 12M
        |__ Port 001: Dev 003, If 3, Class=Human Interface Device, Driver=usbfs, 12M
        |__ Port 001: Dev 003, If 4, Class=Communications, Driver=cdc_acm, 12M
        |__ Port 001: Dev 003, If 5, Class=CDC Data, Driver=cdc_acm, 12M
        |__ Port 001: Dev 003, If 6, Class=Application Specific Interface, Driver=[none], 12M

In this example we see that the HID is using driver=usbfs - when the device is in this state, you cannot use aioc-util.py to program it. For some reason starting asterisk causes the device to switch to that driver. When running aioc-util.py it may be necessary to stop asterisk, unbind the usbfs driver, and re-bind the HID driver. Note the paths below may be different depending on what USB devices you have plugged in where.

sudo systemctl stop asterisk
echo -n '1-1.1:1.3' | sudo tee /sys/bus/usb/drivers/usbfs/unbind >/dev/null
echo -n '1-1.1:1.3' | sudo tee /sys/bus/usb/drivers/usbhid/bind >/dev/null
echo -n '1-1.2:1.3' | sudo tee /sys/bus/usb/drivers/usbfs/unbind >/dev/null
echo -n '1-1.2:1.3' | sudo tee /sys/bus/usb/drivers/usbhid/bind >/dev/null

Configuration

On the pi, sudo nano /boot/firmware/config.txt. At the end of the file, add the line dtoverlay=dwc2,dr_mode=host. This changes the USB driver from the default dwc_otg to dwc2. In my experience, using the older dwc_otg driver resulted in completely unusable audio quality issues (stuttering, garbled, robotic audio). This was ONLY an issue when using 2 AIOC devices, and could be reproduced outside of asterisk by trying to record both devices at the same time.

Reboot the pi for this setting to take effect sudo reboot.

For the AIOC setup, you do not need change VID/PID of the USB device to pretend it is a CM108. Instead I recommend you follow the docs from aioc-util and uncomment the relevant VID/PID in /etc/asterisk/res_usbradio.conf. You do need to run ./aioc-util.py --enable-vcos --vcos-timctrl 1500 --store on the receiving AIOC (you may need to re-bind the driver, as mentioned above).

Note: the released version of aioc-util currently only runs on a single device. You may need to unplug the TX AIOC to ensure the RX AIOC is the one being programmed. Alternatively, you can use the version from my pull request which supports listing devices and attaching by serial number.

As for ASL3 configuration - You will create 2 SimpleUSB stanzas, one for RX and 1 for TX, then configure the node to use these 2 stanzas. This should also work with USBRadio.

Run asl-find-sound. You will see something like the following. You can figure out which AIOC is connected to which radio by unplugging them one at a time. The device path e.g. 1-1.1:1.0 is what we need to know, as that will go into your simpleusb.conf.

1-1.1:1.0       -->     1209:7388 AIOC (S/N: 4959ddd4)
1-1.2:1.0       -->     1209:7388 AIOC (S/N: 546918c6)

Next run sudo nano /etc/asterisk/simpleusb.conf.

Note: You can change global settings to AIOC-safe defaults (recommended) or set everything the stanza. In particular I would set carrierfrom = usbinvert, ctcssfrom=no, and invertptt=no at the global settings.

Add the following stanzas, changing the node numbers and USB paths to match your system.

[tx12345](node-main)
devstr = 1-1.1:1.0
carrierfrom = no
ctcssfrom = no
txmixaset = 750
txmixbset = 0

[rx12345](node-main)
devstr = 1-1.2:1.0
carrierfrom = usbinvert
ctcssfrom = no
plfilter = yes
deemphasis = no
rxboost = no
rxmixerset = 500
rxvoiceadj = 0.5
rxctcssadj = 0.5
rxsquelchadj = 500

Then you can add them to sudo nano /etc/asterisk/rpt.conf.

Note: You can use duplex=2 if you want the node to act like a repeater, or will have multiple users, however that means that while you are transmitting the node will be transmitting, and that increases the likelihood of RFI issues. If you are the only user of this node, running duplex=3 achieves the desired result with less RFI concern.

[12345](node-main)
rxchannel = SimpleUSB/rx12345
txchannel = SimpleUSB/tx12345
duplex = 3

Restart asterisk sudo systemctl restart asterisk.service and everything should work. From here you should be able to tune levels using simpleusb-tune-menu, however it you will need to tell it which device to operate on (either sudo simpleusb-tune-menu -n rx12345 or menu 1) since TX and RX are split. I would recommend setting the RX audio level with the volume dial on the radio.

AllStarLink Newbies:
it took some sleuthing to find out what this legendary AIOC is and a place to get one

Always nice to see DiY approaches to building cross-band full-duplex nodes. I started doing this myself in 2022, and over time documented what I learned in the process, at How To - Build a High-Quality Cross-Band Full-Duplex AllStar Node for Under $200. I then started building URI’s in 2024, and over many months of R&D and testing developed the ANF101-M URI & mounting plate, which in my experience has better RFI-rejection and higher audio quality than any other URI or node at anywhere near the same price. An ANF101-M is only $89, which while a bit more than 2 AIOCs, has 55+dB audio SNR, directly powers the HTs (RT85s) such that no batteries or separate power adapters are needed, and provides an integrated mounting plate solution that enables a node to be assembled in well under an hour with no soldering required.

Hello! I am quite aware of your product, and honestly it is what I would steer most people towards vs the approach I took. :joy: The time it took to get everything working together more than offset the cost, and I still have to do a bit more work to do to get it where I want it from a power delivery, mounting, and RFI perspective.

That said, I am a chronic tinkerer and had a confluence of circumstances (lost my old AIOC and wanted to try ordering from JLCPCB, had an old CM108/BF888 node that had been physically broken for some time so I had the pi available, wanted to try ASL3 with the hopes of moving my other repeater and my simplex node away from a certain obsolete, closed source distro, etc).

I will say that your work is what convinced me to go with the RT85s though, and no regrets there. I had been using spare BF888s leftover from an old CM108 node but out of the box the RT85s sound better and have much better RFI output and rejection.