diff --git a/overlay/etc/udev/rules.d/89-et-xiegu-x6100.rules b/overlay/etc/udev/rules.d/89-et-xiegu-x6100.rules new file mode 100644 index 0000000..319f137 --- /dev/null +++ b/overlay/etc/udev/rules.d/89-et-xiegu-x6100.rules @@ -0,0 +1,26 @@ +# Author : Gaston Gonzalez +# Date : 5 October 2025 +# Purpose : udev rules for the Xiegu X6100 +# +# Preconditions: +# 1. Xiegu X6100 connected via USB cable +# +# Postconditions: +# 1. /dev/et-cat created +# 2. rigctld is started +# 3. /dev/et-audio created + +SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="55d2", ENV{ET_DEVICE}=="", \ + PROGRAM="/opt/emcomm-tools/sbin/udev-tester.sh xiegu-x6100", \ + ACTION=="add", \ + ENV{ET_DEVICE}="X6100", ENV{ET_SUBDEVICE}="CAT", GROUP="dialout", MODE="0660", SYMLINK+="et-cat", \ + RUN+="/usr/bin/systemctl start rigctld" + +# This soundcard will collide with the DigiRig, so we need to ensure that this +# rule is ordered before it and that we guard the match with the PROGRAM check. +SUBSYSTEM=="sound", ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="0012", \ + PROGRAM="/opt/emcomm-tools/sbin/udev-tester.sh xiegu-x6100", \ + ACTION=="add", \ + ENV{ET_DEVICE}="X6100", \ + ATTR{id}="ET_AUDIO", \ + ENV{ET_SUBDEVICE}="AUDIO", GROUP="audio", MODE="0660", SYMLINK+="et-audio" diff --git a/overlay/opt/emcomm-tools/bin/et-audio b/overlay/opt/emcomm-tools/bin/et-audio index b7a4e05..4aa9062 100755 --- a/overlay/opt/emcomm-tools/bin/et-audio +++ b/overlay/opt/emcomm-tools/bin/et-audio @@ -2,7 +2,7 @@ # # Author : Gaston Gonzalez # Date : 31 October 2024 -# Updated : 26 September 2025 +# Updated : 5 October 2025 # Purpose : Configures ET audio device with sane defaults # # Preconditions @@ -112,6 +112,18 @@ update-config () { et-log "Applied amixer settings for ${ET_DEVICE_NAME}" ;; + "X6100") + # Unmute Speaker a set volume. Adjust if remote station can't decode you. + amixer -q -c ${AUDIO_CARD} sset Speaker Playback Switch 42% unmute + # Unmute Mic + amixer -q -c ${AUDIO_CARD} sset Mic Playback Switch 52% unmute + # Set "L/R Capture" to 19. Adjust if you can't decode received audio. + amixer -q -c ${AUDIO_CARD} sset Mic Capture Switch 31% unmute + # Disable Auto Gain Control + amixer -q -c ${AUDIO_CARD} sset 'Auto Gain Control' mute + + et-log "Applied amixer settings for ${ET_DEVICE_NAME}" + ;; *) et-log "No ALSA configuration specified for this ET_DEVICE." ;; diff --git a/overlay/opt/emcomm-tools/bin/et-common b/overlay/opt/emcomm-tools/bin/et-common index bc781dd..b3e94aa 100755 --- a/overlay/opt/emcomm-tools/bin/et-common +++ b/overlay/opt/emcomm-tools/bin/et-common @@ -1,7 +1,7 @@ #!/bin/bash # Author : Gaston Gonzalez # Date : 1 February 2025 -# Updated : 20 August 2025 +# Updated : 7 October 2025 # Purpose : Common environment variables and functions # Standardized device paths for supported hardware @@ -10,6 +10,10 @@ export ET_DEVICE_CAT="/dev/et-cat" export ET_DEVICE_GPS="/dev/et-gps" export ET_DEVICE_SDR="/dev/et-sdr" +# Standardized configuration locations and files +export ET_HOME="/opt/emcomm-tools" +export ET_ACTIVE_RADIO_CONF="${ET_HOME}/conf/radios.d/active-radio.json" + export ESC="\x1B" export RED="${ESC}[1;31m" export BLUE="${ESC}[1;34m" @@ -141,3 +145,24 @@ download_with_retries() { echo "Download failed after $max_retries attempts." return 1 } + +# prime_rigctld_conn makes a connection to the rig control daemon (rigctld) +# and requests the radio's frequency in an effort to initialize CAT control. +# +# For example, it takes almost 6 seconds for rig control clients (including +# the rigctl client) to connect the first time with the Xiegu X6100 to rigctld. +# JS8Call will fail to handle this properly if this "priming" task is not +# executed before it starts up.. +prime_rigctld_conn() { + + ACTIVE_RADIO=$(jq -r -e '.rigctrl.primeRig' ${ET_ACTIVE_RADIO_CONF}) + if [[ $? -eq 0 ]]; then + if [[ "${ACTIVE_RADIO}" = "true" ]]; then + et-log "Priming rig control client connection" + notify_user "Please be patient. Priming connection to radio." + rigctl -m 2 f > /dev/null + else + et-log "No rigctld priming needed" + fi + fi +} diff --git a/overlay/opt/emcomm-tools/bin/et-js8call b/overlay/opt/emcomm-tools/bin/et-js8call index 76315d2..401a577 100755 --- a/overlay/opt/emcomm-tools/bin/et-js8call +++ b/overlay/opt/emcomm-tools/bin/et-js8call @@ -2,7 +2,7 @@ # # Author : Gaston Gonzalez # Date : 24 October 2024 -# Updated : 5 October 2025 +# Updated : 7 October 2025 # Purpose : Wrapper script for starting JS8Call with PnP support # # Preconditions @@ -12,6 +12,7 @@ # 1. Stop all running EmComm Tools modes # 2. JS8Call audio settings updated # 3. JS8Call started +. /opt/emcomm-tools/bin/et-common usage() { echo "usage: $(basename $0) " @@ -32,6 +33,10 @@ notify_user() { } start() { + + # Ensure that we have a pre-initialized CAT control connection for select radios + prime_rigctld_conn + /opt/emcomm-tools/bin/et-kill-all && update-config && /usr/bin/js8call & if [ ! -e /dev/et-gps ]; then @@ -42,7 +47,7 @@ start() { } -update-config () { +update-config() { JS8CALL_CONF_FILE="${HOME}/.config/JS8Call.ini" diff --git a/overlay/opt/emcomm-tools/conf/radios.d/xiegu-x6100.json b/overlay/opt/emcomm-tools/conf/radios.d/xiegu-x6100.json new file mode 100644 index 0000000..2550b68 --- /dev/null +++ b/overlay/opt/emcomm-tools/conf/radios.d/xiegu-x6100.json @@ -0,0 +1,22 @@ +{ + "id": "xiegu-x6100", + "vendor": "Xiegu", + "model": "X6100", + "rigctrl": { + "id": "3087", + "baud": "19200", + "ptt": "RIG", + "conf": "timeout=1000,retry=1,timeout_retry=1", + "primeRig": true + }, + "notes": [ + "Turn on radio", + "Plug USB-C cable into the DEV port", + "Set mode to U-DIG", + "Set filter to FILTER1", + "Set AGC to AGC--" + ], + "fieldNotes": [ + "Tested with firmware version: 1.1.9 APP / 1.1.8 BASE" + ] +} diff --git a/overlay/opt/emcomm-tools/sbin/udev-tester.sh b/overlay/opt/emcomm-tools/sbin/udev-tester.sh index 02fb7f9..5959aab 100755 --- a/overlay/opt/emcomm-tools/sbin/udev-tester.sh +++ b/overlay/opt/emcomm-tools/sbin/udev-tester.sh @@ -1,7 +1,7 @@ #!/bin/bash # Author : Gaston Gonzalez # Date : 11 October 2024 -# Updated : 13 September 2025 +# Updated : 5 October 2025 # Purpose : Perform tests that can be used by the udev subsystem to aid # in rule development. This is intended to by used with the PROGRAM # directive inside of a udev rule. @@ -13,6 +13,20 @@ ET_HOME=/opt/emcomm-tools ACTIVE_RADIO="${ET_HOME}/conf/radios.d/active-radio.json" +# Exit with a 0 exit status if, and only if, the currently selected radio is +# a Xiegu X6100 +test_xiegu_x6100() { + if [[ -L "${ET_HOME}/conf/radios.d/active-radio.json" ]]; then + ID=$(cat "${ET_HOME}/conf/radios.d/active-radio.json" | jq -r .id) + + if [[ "$ID" == "xiegu-x6100" ]]; then + exit 0 + fi + fi + + exit 1 +} + # Exit with a 0 exit status if, and only if, the currently selected radio is # a Yaesu FTX-1. test_yaesu_ftx1() { @@ -101,6 +115,9 @@ if [ $# -ne 1 ]; then fi case $1 in + xiegu-x6100) + test_xiegu_x6100 + ;; yaesu-ftx1) test_yaesu_ftx1 ;; @@ -112,6 +129,7 @@ case $1 in ;; digirig-mobile) test_digirig_mobile + ;; esac exit 1 diff --git a/scripts/install-hamlib.sh b/scripts/install-hamlib.sh index 423ba7d..174745f 100755 --- a/scripts/install-hamlib.sh +++ b/scripts/install-hamlib.sh @@ -2,46 +2,48 @@ # # Author : Gaston Gonzalez # Date : 25 November 2022 -# Updated : 19 May 2024 -# Purpose : Install hamlib for rig control +# Updated : 6 October 2025 +# Purpose : Install hamlib for rig control (rigctld) set -e +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR -ET_DIST_DIR=/opt/dist -ET_SRC_DIR=/opt/src +. ./env.sh +. ../overlay/opt/emcomm-tools/bin/et-common -VERSION=4.5 -APP_AND_VERSION=hamlib-$VERSION -TARBALL=$APP_AND_VERSION.tar.gz -URL=https://github.com/Hamlib/Hamlib/releases/download/$VERSION/$TARBALL -INSTALL_DIR=/opt/$APP_AND_VERSION -LINK_PATH=/opt/hamlib +APP="hamlib" +VERSION=4.6.5 +APP_AND_VERSION="${APP}-${VERSION}" +INSTALL_DIR="/opt/${APP_AND_VERSION}" +LINK_PATH="/opt/${APP}" +TARBALL=${APP_AND_VERSION}.tar.gz +URL=https://github.com/Hamlib/Hamlib/releases/download/${VERSION}/${TARBALL} -if [ ! -e $ET_DIST_DIR/$TARBALL ]; then +if [[ ! -e $ET_DIST_DIR/$TARBALL ]]; then et-log "Downloading hamlib: $URL " - curl -s -L -O --fail $URL + download_with_retries ${URL} ${TARBALL} - [ ! -e $ET_DIST_DIR ] && mkdir -v $ET_DIST_DIR - [ ! -e $ET_SRC_DIR ] && mkdir -v $ET_SRC_DIR + [ ! -e ${ET_DIST_DIR} ] && mkdir -v ${ET_DIST_DIR} + [ ! -e ${ET_SRC_DIR} ] && mkdir -v ${ET_SRC_DIR} - mv $TARBALL $ET_DIST_DIR + mv ${TARBALL} ${ET_DIST_DIR} fi CWD_DIR=`pwd` -cd $ET_SRC_DIR -et-log "Unpacking $ET_DIST_DIR/$TARBALL" -tar -xzf $ET_DIST_DIR/$TARBALL && cd $APP_AND_VERSION +cd ${ET_SRC_DIR} +et-log "Unpacking ${ET_DIST_DIR}/${TARBALL}" +tar -xzf ${ET_DIST_DIR}/${TARBALL} && cd ${APP_AND_VERSION} -[ ! -e $INSTALL_DIR ] && mkdir -v $INSTALL_DIR +[ ! -e ${INSTALL_DIR} ] && mkdir -v ${INSTALL_DIR} -et-log "Building Hamlib $VERSION" -./configure --prefix=$INSTALL_DIR +et-log "Building Hamlib ${VERSION}" +./configure --prefix=${INSTALL_DIR} make && make check && make install -[ -e $LINK_PATH ] && rm $LINK_PATH -ln -v -s $INSTALL_DIR $LINK_PATH +[ -e ${LINK_PATH} ] && rm ${LINK_PATH} +ln -v -s ${INSTALL_DIR} ${LINK_PATH} -stow -v -d /opt hamlib -t /usr/local +stow -v -d /opt ${APP} -t /usr/local cd $CWD_DIR - diff --git a/tests/test-hamlib.sh b/tests/test-hamlib.sh new file mode 100755 index 0000000..acff967 --- /dev/null +++ b/tests/test-hamlib.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 8 November 2024 +# Updated : 6 October 2025 +# Purpose : Test hamlib installation + +OUT=$(which rigctld) +exit $?