feat: added APF for CW in Icom
This commit is contained in:
+300
@@ -0,0 +1,300 @@
|
|||||||
|
# OpsLog
|
||||||
|
|
||||||
|
Un logiciel de log radioamateur moderne et rapide pour Windows — saisie façon
|
||||||
|
Log4OM, CAT en temps réel pour **OmniRig**, **FlexRadio/SmartSDR** natif,
|
||||||
|
**Icom CI-V** natif (USB **et** à distance par internet, en remplacement de
|
||||||
|
RS-BA1) et **TCI** (SunSDR / Expert Electronics), cluster DX avec alertes de
|
||||||
|
spots, suivi des diplômes, cartes, log de concours, gestion des QSL et un
|
||||||
|
concepteur de cartes QSL. Construit avec **Wails v2** (backend Go + frontend
|
||||||
|
React/TypeScript), **100 % Go** (sans CGO) : SQLite pour la configuration,
|
||||||
|
**MySQL partagé** optionnel pour le journal afin que plusieurs opérateurs
|
||||||
|
partagent un même log. Entièrement thémable et bilingue (anglais / français).
|
||||||
|
|
||||||
|
Développé par **F4BPO**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Compilation / développement
|
||||||
|
|
||||||
|
- **Dev :** `wails dev` (rechargement à chaud Vite ; méthodes Go accessibles sur http://localhost:34115).
|
||||||
|
- **Build :** `wails build` (utiliser la version wails v2.11 du projet — `~/go/bin/wails.exe`).
|
||||||
|
- **Régénérer les bindings Go↔TS** après modification des méthodes `App`
|
||||||
|
exportées : `wails generate module`.
|
||||||
|
- **Release :** `.vscode/release.ps1` (Ctrl+Maj+P → *Tasks: Run Task* →
|
||||||
|
*Release OpsLog*) — incrémente la version, pousse le source sur Gitea, compile
|
||||||
|
l'exe et le publie sur les releases Gitea + GitHub.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Journalisation
|
||||||
|
|
||||||
|
- **Bandeau de saisie façon Log4OM :** indicatif, RST émis/reçu, nom/QTH/locator,
|
||||||
|
bande/mode, fréquence TX/RX (split), heure de début/fin, commentaire/note. Le
|
||||||
|
**drapeau** de l'entité contactée est affiché en grand à côté des champs RST.
|
||||||
|
- **Recherche d'indicatif** (QRZ.com / HamQTH) avec photo, pré-remplissage du
|
||||||
|
nom/QTH/locator et onglet QRZ.com.
|
||||||
|
- **Résolution DXCC hors ligne** depuis `cty.dat` (pays, zones CQ/ITU,
|
||||||
|
continent), avec gestion des `/MM` `/AM` `/B` (balise) et des changements de
|
||||||
|
district (`/8`, `/W6`), plus les dérogations DXpédition de ClubLog par dates.
|
||||||
|
- **QSO récents**, matrice **déjà contactés** (par créneau bande/mode),
|
||||||
|
re-résolution en masse depuis cty/QRZ/ClubLog, envoi en masse vers les services
|
||||||
|
QSL.
|
||||||
|
- **Constructeur de filtres QSO avancé** (champ / opérateur / valeur, ET / OU,
|
||||||
|
préréglages enregistrés) avec **export ADIF** des lignes filtrées ou
|
||||||
|
sélectionnées.
|
||||||
|
- **Recherche de doublons** (Outils) — regroupe les QSO par même indicatif +
|
||||||
|
bande + mode (optionnellement même jour / minute) et permet de choisir lesquels
|
||||||
|
supprimer.
|
||||||
|
- **Conforme ADIF 3.1.7** en import/export : dictionnaire complet des champs,
|
||||||
|
30 colonnes promues, éditeur générique de « champs supplémentaires » et modes
|
||||||
|
d'export standard/complet.
|
||||||
|
- **Profils :** chaque réglage est par profil ; chaque profil peut pointer son
|
||||||
|
journal vers le fichier SQLite local ou une base **MySQL partagée**
|
||||||
|
(multi-opérateur).
|
||||||
|
|
||||||
|
## Cartes & antenne
|
||||||
|
|
||||||
|
- **Vue principale = deux volets configurables** (par profil, Réglages → Général
|
||||||
|
→ *Vue principale*) : carte grand-cercle, carte locator (rue), la grille du
|
||||||
|
cluster, la grille des déjà-contactés, les QSO récents, les **commandes
|
||||||
|
FlexRadio**, la **console Icom** ou le panneau **Net control**.
|
||||||
|
- **Carte grand-cercle** avec distance & azimut trajet court/long, fonds de carte
|
||||||
|
sélectionnables (Light / Voyager / Street / Satellite, tous sans clé et
|
||||||
|
légendés) et le(s) **lobe(s) du faisceau d'antenne** tracés depuis l'azimut du
|
||||||
|
rotor.
|
||||||
|
- **Compas de rotor** (azimutal équidistant, clic pour tourner) piloté par
|
||||||
|
PstRotator.
|
||||||
|
- **Support Ultrabeam** (Normal / inversé 180° / bidirectionnel) : la direction
|
||||||
|
rayonnée est en vert et le **boom mécanique** en gris, à la fois sur le compas
|
||||||
|
et sur la carte, pour toujours savoir où pointe l'antenne.
|
||||||
|
|
||||||
|
## Cluster DX
|
||||||
|
|
||||||
|
- Plusieurs serveurs de cluster avec reconnexion auto, un maître pour les
|
||||||
|
commandes.
|
||||||
|
- **Barre latérale de filtres** (recherche d'indicatif, masquer-déjà-contactés,
|
||||||
|
grouper les doublons, bande / mode / statut / source) partagée entre l'onglet
|
||||||
|
Cluster et le volet cluster de la vue principale, avec bascule affichage/masquage.
|
||||||
|
- **Statut** par spot (nouveau / nouvelle bande / nouveau créneau / contacté),
|
||||||
|
clic pour accorder la radio, et une **bandmap** multi-bandes (bandes façon
|
||||||
|
panadapter).
|
||||||
|
- Les spots **POTA** sont étiquetés avec leur référence de parc (via
|
||||||
|
`api.pota.app`).
|
||||||
|
- **Alertes de spots** (façon Log4OM) : règles sur indicatif / pays / bande /
|
||||||
|
mode / spotter, avec notification sonore, visuelle et e-mail (Outils →
|
||||||
|
*Gestion des alertes*).
|
||||||
|
|
||||||
|
## Contrôle CAT
|
||||||
|
|
||||||
|
Quatre backends natifs (Réglages → CAT), chacun avec reconnexion auto et une
|
||||||
|
connexion rapide non bloquante — une radio éteinte ne fige jamais l'application :
|
||||||
|
|
||||||
|
- **OmniRig** (Rig 1/2, changement à chaud) — fonctionne avec toute radio
|
||||||
|
supportée par OmniRig.
|
||||||
|
- **FlexRadio (SmartSDR)** via l'API TCP de la radio — fréquence / mode / split
|
||||||
|
de la slice en temps réel, découverte UDP, et **spots panadapter** (les spots
|
||||||
|
du cluster poussés sur l'écran Flex, clic → remplir l'indicatif).
|
||||||
|
- **Icom CI-V** — natif, via le port **USB** de la radio *ou* par internet via le
|
||||||
|
**serveur LAN intégré** de la radio (voir *Icom à distance* ci-dessous). Ni
|
||||||
|
RS-BA1 ni Remote Utility nécessaires.
|
||||||
|
- **TCI** (WebSocket) — SunSDR / ExpertSDR2 et tout serveur compatible TCI :
|
||||||
|
fréquence / mode / PTT / split, plus spots panorama optionnels.
|
||||||
|
|
||||||
|
Le mode est lu depuis la radio ; le sous-mode numérique (FT4 vs FT8) est déduit
|
||||||
|
de la fréquence. Les **antennes RX/TX Flex par bande** sont configurables et
|
||||||
|
appliquées automatiquement au changement de bande.
|
||||||
|
|
||||||
|
### Onglet de commande FlexRadio (façon SmartSDR)
|
||||||
|
|
||||||
|
Affiché uniquement quand le backend CAT est une FlexRadio :
|
||||||
|
|
||||||
|
- **Émission :** puissance RF, puissance d'accord, TUNE, MOX, processeur de
|
||||||
|
parole (NOR/DX/DX+), VOX (+ niveau + délai), moniteur (+ niveau), gain micro.
|
||||||
|
- **Réception (slice active) :** mode/seuil AGC, niveau audio, NB / NR / ANF.
|
||||||
|
- **Coupleur d'antenne (ATU) :** accord / bypass / mémoires.
|
||||||
|
- **Amplificateur :** PowerGenius XL operate/standby + défaut.
|
||||||
|
- **Mesures en direct** via le flux UDP VITA-49 : S-mètre (unités S), puissance
|
||||||
|
directe (W), ROS, ALC, température PA, tension, plus les mesures de l'ampli.
|
||||||
|
|
||||||
|
### Onglet de commande Icom
|
||||||
|
|
||||||
|
Affiché quand le backend CAT est Icom (USB ou réseau). Une console complète façon
|
||||||
|
RS-BA1 :
|
||||||
|
|
||||||
|
- **Double afficheur VFO** (MAIN / SUB) avec la grande fréquence tabulaire, le
|
||||||
|
badge de mode, la bande et l'offset RIT/ΔTX, et une **rangée de boutons de
|
||||||
|
mode** (SSB / CW / RTTY / PSK / AM / FM).
|
||||||
|
- **Scope de spectre + waterfall** (panadapter) : ON/OFF, CTR/FIX, double-clic
|
||||||
|
pour accorder, et boutons **◀ ⊙ ▶** pour centrer le scope sur la fréquence
|
||||||
|
actuelle (±50 kHz) et le décaler à gauche/droite.
|
||||||
|
- **Mesures en direct** toujours visibles : S-mètre (clic → remplir le RST),
|
||||||
|
puissance en watts, ROS.
|
||||||
|
- **DSP réception :** gain AF / RF, squelch, AGC, préampli, atténuateur, filtre
|
||||||
|
(FIL1/2/3), NB, NR, ANF et — **en CW seulement** — l'**APF** (filtre de pic
|
||||||
|
audio).
|
||||||
|
- **Passe-bande / notch :** Twin PBT (intérieur / extérieur), notch manuel +
|
||||||
|
position.
|
||||||
|
- **Émission :** puissance RF, MOX, TUNE, **split avec offset automatique**
|
||||||
|
(+5 kHz en SSB, +1 kHz en CW), et moniteur. **En phonie seulement** : gain
|
||||||
|
micro, processeur de parole, VOX (+ gain + anti-VOX). Les commandes qui ne
|
||||||
|
s'appliquent pas au mode courant sont masquées automatiquement.
|
||||||
|
- **Bandes & antenne :** boutons de bande en un clic et sélection ANT1/ANT2.
|
||||||
|
- **Clarificateurs :** RIT et ΔTX avec accord molette / ± (Ctrl+←/→ décale le
|
||||||
|
RIT).
|
||||||
|
- Boutons **Marche / Arrêt** (manuels par choix — l'application ne réveille
|
||||||
|
jamais la radio à la connexion).
|
||||||
|
- La **manipulation CW** peut passer par le keyer intégré de la radio (voir
|
||||||
|
*Keyers* ci-dessous).
|
||||||
|
|
||||||
|
### Icom à distance (par internet, sans RS-BA1)
|
||||||
|
|
||||||
|
OpsLog parle directement le protocole réseau intégré de l'IC-7610 — il
|
||||||
|
**remplace à la fois l'Icom Remote Utility et RS-BA1**. Saisissez l'IP de la
|
||||||
|
radio, le nom/mot de passe Network User1 et l'adresse CI-V, et toute la console
|
||||||
|
Icom fonctionne sur le LAN/internet : login + token (renouvelé automatiquement),
|
||||||
|
tunnel CI-V, retransmission côté réception pour une liaison très stable même
|
||||||
|
avec le panadapter en flux, et Marche/Arrêt manuel. (L'audio est hors périmètre
|
||||||
|
— utilisez la radio en USB + une liaison voix comme Mumble.)
|
||||||
|
|
||||||
|
## Keyers & audio
|
||||||
|
|
||||||
|
- **Keyer CW** avec macros et macros sur touches F. Le moteur du keyer est
|
||||||
|
sélectionnable : **WinKeyer** (K1EL WK1/2/3 sur port COM), **Icom** (le keyer
|
||||||
|
intégré de la radio via CI-V — sans matériel supplémentaire, fonctionne aussi à
|
||||||
|
distance) ou **TCI**.
|
||||||
|
- **Keyer vocal numérique** (DVK) : enregistrer les messages vocaux F1–F6 et les
|
||||||
|
émettre.
|
||||||
|
- **Enregistrement audio des QSO :** capture continue en tampon glissant ; au
|
||||||
|
*Log QSO* le contact est sauvegardé dans un WAV par QSO
|
||||||
|
(`INDICATIF_AAAAMMJJ_HHMMSS.wav`) ; mixe RX + micro.
|
||||||
|
|
||||||
|
## Amplis & commutateurs
|
||||||
|
|
||||||
|
- Amplificateur **PowerGenius XL** (4O3A) — TCP direct : operate/standby,
|
||||||
|
sélecteur de mode ventilateur et affichage des défauts.
|
||||||
|
- Commutateur d'antenne **Antenna Genius** (4O3A) via TCP/GSCP — un widget de
|
||||||
|
commutation A/B ancré.
|
||||||
|
|
||||||
|
## QSL & diplômes
|
||||||
|
|
||||||
|
- **Moteur de diplômes :** définitions intégrées + personnalisées (partagées
|
||||||
|
**globalement** entre profils) — DXCC, WAS / WAZ / WAC, WPX,
|
||||||
|
IOTA / POTA / SOTA / WWFF, **DDFM**, contacté/confirmé/validé par bande & mode,
|
||||||
|
règles OU et affectation manuelle de références, détection de référence en
|
||||||
|
direct à la saisie de l'indicatif, **import de listes de références** pour les
|
||||||
|
totaux/noms, et un **Rescan** qui relit le journal (récupère les nouvelles
|
||||||
|
confirmations LoTW/QRZ).
|
||||||
|
- **Services QSL :** ClubLog (upload ADIF par lots), LoTW, QRZ.com, eQSL —
|
||||||
|
upload et **téléchargement des confirmations** (qui rafraîchit automatiquement
|
||||||
|
les stats de diplômes).
|
||||||
|
- **Concepteur de cartes QSL** (voir ci-dessous).
|
||||||
|
- **eQSL par e-mail :** clic droit sur un QSO → *Envoyer l'eQSL par e-mail* via
|
||||||
|
le compte SMTP configuré. (Outlook/Hotmail désactivent le SMTP basic-auth —
|
||||||
|
utilisez Gmail avec un mot de passe d'application, ou un mot de passe
|
||||||
|
d'application Microsoft.)
|
||||||
|
|
||||||
|
## Log de concours
|
||||||
|
|
||||||
|
- **Onglet Contest :** choisissez un concours (liste ADIF `CONTEST_ID` intégrée)
|
||||||
|
et un échange (numéro de série courant ou échange fixe). OpsLog remplit
|
||||||
|
automatiquement `CONTEST_ID` et les numéros émis/reçus (`STX` / `SRX`), impose
|
||||||
|
un début/fin de fenêtre, signale les doublons et tient un tableau de score en
|
||||||
|
direct.
|
||||||
|
|
||||||
|
## Statut opérateur en direct (événements spéciaux)
|
||||||
|
|
||||||
|
Pour un indicatif d'événement spécial multi-op sur un journal MySQL partagé (ex.
|
||||||
|
**TM74TFR**) : Réglages → Général → *Publier le statut opérateur en direct*.
|
||||||
|
Chaque instance OpsLog envoie un battement de cœur de son activité (indicatif de
|
||||||
|
l'opérateur, bande, fréquence, mode) dans une table `live_status` toutes les
|
||||||
|
~15 s. Un petit rendu PHP
|
||||||
|
([`docs/livestatus/tm74-status.php`](docs/livestatus/tm74-status.php)) sur votre
|
||||||
|
propre serveur web lit cette table et produit une page/image en direct que vous
|
||||||
|
pouvez intégrer sur la bio **QRZ.com** de la station
|
||||||
|
(`<img src="…/tm74-status.php?img=1">`). OpsLog écrit seulement dans la base —
|
||||||
|
ce n'est pas un serveur web.
|
||||||
|
|
||||||
|
## Net control
|
||||||
|
|
||||||
|
- **Log de net dirigé** (Outils → Net) : un roster global (`nets.json`) plus une
|
||||||
|
session active en mémoire — pointez les stations présentes, puis loguez tout le
|
||||||
|
net d'un coup en utilisant la fréquence CAT.
|
||||||
|
|
||||||
|
## Apparence & langue
|
||||||
|
|
||||||
|
- **Thèmes :** quatre thèmes complets (Clair chaud, Sombre chaud, Graphite
|
||||||
|
sombre, Contraste élevé) plus **Auto** (suit la préférence clair/sombre du
|
||||||
|
système), sélectionnables dans Réglages → Général. Chaque panneau et chaque
|
||||||
|
table AG-Grid suit le thème.
|
||||||
|
- **Bilingue :** interface complète **anglais / français**, avec un choix de
|
||||||
|
drapeau au premier lancement et un sélecteur dans Réglages → Général.
|
||||||
|
|
||||||
|
## Sécurité
|
||||||
|
|
||||||
|
- **Coffre à secrets :** chiffrement optionnel par phrase de passe des mots de
|
||||||
|
passe stockés (AES-GCM + PBKDF2). Les valeurs chiffrées sont portables ; une
|
||||||
|
seule invite de déverrouillage au lancement les déchiffre pour la session.
|
||||||
|
|
||||||
|
## Intégrations (sortantes)
|
||||||
|
|
||||||
|
- **Émetteurs UDP :** pousser la fréquence actuelle vers **PstRotator**, les
|
||||||
|
infos radio au format **N1MM `RadioInfo`**, ou un **enregistrement ADIF à
|
||||||
|
chaque QSO logué** — pour que les outils externes (contrôle de rotor,
|
||||||
|
applications numériques, autres logiciels de log) restent synchronisés.
|
||||||
|
|
||||||
|
## Divers
|
||||||
|
|
||||||
|
- **Démarrage automatique :** lancer des programmes externes (WSJT-X, JTAlert,
|
||||||
|
contrôle de rotor…) au démarrage d'OpsLog, en sautant ceux déjà lancés.
|
||||||
|
- **Sauvegarde :** sauvegarde optionnelle base + ADIF à la fermeture.
|
||||||
|
- **Vérification de mise à jour** au démarrage avec un toast (désactivable).
|
||||||
|
- **Télémétrie d'usage anonyme** (un battement de cœur quotidien : ID
|
||||||
|
d'installation aléatoire + version + OS — aucune donnée d'indicatif ou de QSO ;
|
||||||
|
désactivable dans les Préférences).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Concepteur de cartes QSL
|
||||||
|
|
||||||
|
Outils → *Concepteur de cartes QSL…* transforme quelques photos en une carte
|
||||||
|
eQSL soignée :
|
||||||
|
|
||||||
|
1. Choisissez 1 à 6 photos (jpeg/png). OpsLog les analyse hors ligne (grille de
|
||||||
|
détail/luminance) et propose **3 designs** — indicatif dans la zone la plus
|
||||||
|
calme de la meilleure photo, nom de l'opérateur, zones CQ/ITU + ligne locator,
|
||||||
|
drapeau du pays, les autres photos en inserts encadrés, et un encart de
|
||||||
|
confirmation par QSO.
|
||||||
|
2. Choisissez une proposition et affinez-la : cliquez un élément pour le
|
||||||
|
sélectionner, glissez pour déplacer, changez la police / le préréglage de
|
||||||
|
style (gel or, gel argent, contour blanc classique, script, plat) et les
|
||||||
|
réglages par préréglage dans le panneau de droite.
|
||||||
|
3. Enregistrez le modèle (les photos sont copiées dans
|
||||||
|
`data/qsl/templates/<id>/`, les originaux peuvent donc être déplacés). Un
|
||||||
|
modèle peut être le défaut par profil.
|
||||||
|
|
||||||
|
Envoi : clic droit sur un QSO → *Envoyer l'eQSL par e-mail*. La carte est rendue
|
||||||
|
avec les données de ce QSO, matricée en JPEG ≤ 800 Ko, archivée dans
|
||||||
|
`data/qsl/outbox/` et envoyée via le compte SMTP configuré à l'adresse trouvée
|
||||||
|
par la recherche QRZ/HamQTH. En cas de succès le QSO est marqué `EQSL_SENT=Y`
|
||||||
|
(ADIF). Les modèles de sujet/corps de l'e-mail sont dans le concepteur (variables
|
||||||
|
`{CALL} {DATE} {BAND} {MODE} {MYCALL}`).
|
||||||
|
|
||||||
|
Polices : Archivo Black, Lilita One, Baloo 2, Oswald, Great Vibes, Allura
|
||||||
|
(toutes OFL, embarquées — licences dans `internal/qslcard/assets/fonts/`) ;
|
||||||
|
Cooper Black est proposée si MS Office l'a installée. Drapeaux : flag-icons
|
||||||
|
(MIT), embarqués pour les entités DXCC couramment contactées.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Données & stockage
|
||||||
|
|
||||||
|
- La **config** (réglages, profils, radios/antennes, nœuds de cluster, cache de
|
||||||
|
recherche, listes de diplômes, modèles QSL) réside toujours dans le fichier
|
||||||
|
SQLite local sous `data/` — instantané même quand le journal est sur un MySQL
|
||||||
|
lointain.
|
||||||
|
- Le **journal** (QSO) réside là où pointe le profil actif : le fichier SQLite
|
||||||
|
local ou une base **MySQL** partagée par profil.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*An English version of this document is available in [README.md](README.md).*
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
# OpsLog
|
# OpsLog
|
||||||
|
|
||||||
A modern, fast ham-radio logger for Windows — Log4OM-style entry, real-time CAT
|
A modern, fast ham-radio logger for Windows — Log4OM-style entry, real-time CAT
|
||||||
(OmniRig **and** native FlexRadio/SmartSDR), DX cluster, awards tracking, maps,
|
for **OmniRig**, native **FlexRadio/SmartSDR**, native **Icom CI-V** (USB **and**
|
||||||
QSL management and a QSL-card designer. Built with **Wails v2** (Go backend +
|
remote-over-internet, replacing RS-BA1) and **TCI** (SunSDR / Expert Electronics),
|
||||||
|
DX cluster with spot alerts, awards tracking, maps, contest logging, QSL
|
||||||
|
management and a QSL-card designer. Built with **Wails v2** (Go backend +
|
||||||
React/TypeScript frontend), **pure Go** (no CGO): SQLite for configuration,
|
React/TypeScript frontend), **pure Go** (no CGO): SQLite for configuration,
|
||||||
optional **shared MySQL** for the logbook so several operators can run one log.
|
optional **shared MySQL** for the logbook so several operators can run one log.
|
||||||
|
Fully themeable and bilingual (English / French).
|
||||||
|
|
||||||
Developed by **F4BPO**.
|
Developed by **F4BPO**.
|
||||||
|
|
||||||
@@ -30,10 +33,16 @@ Developed by **F4BPO**.
|
|||||||
- **Callsign lookup** (QRZ.com / HamQTH) with photo, auto-fill of name/QTH/grid
|
- **Callsign lookup** (QRZ.com / HamQTH) with photo, auto-fill of name/QTH/grid
|
||||||
and the QRZ.com tab.
|
and the QRZ.com tab.
|
||||||
- **Offline DXCC** resolution from `cty.dat` (country, CQ/ITU zones, continent),
|
- **Offline DXCC** resolution from `cty.dat` (country, CQ/ITU zones, continent),
|
||||||
with `/MM` `/AM` and call-area (`/8`, `/W6`) handling, plus ClubLog DXpedition
|
with `/MM` `/AM` `/B` (beacon) and call-area (`/8`, `/W6`) handling, plus
|
||||||
date overrides.
|
ClubLog DXpedition date overrides.
|
||||||
- **Recent QSOs**, **Worked-before** matrix (per band/mode slot), bulk re-resolve
|
- **Recent QSOs**, **Worked-before** matrix (per band/mode slot), bulk re-resolve
|
||||||
from cty/QRZ/ClubLog, bulk send to QSL services.
|
from cty/QRZ/ClubLog, bulk send to QSL services.
|
||||||
|
- **Advanced QSO filter builder** (field / operator / value, AND / OR, saved
|
||||||
|
presets) with filtered- and selected-row **ADIF export**.
|
||||||
|
- **Find duplicates** (Tools) — groups QSOs by same call + band + mode (optionally
|
||||||
|
same day / minute) and lets you pick which to delete.
|
||||||
|
- **ADIF 3.1.7 compliant** import/export: a full field dictionary, 30 promoted
|
||||||
|
columns, a generic "extra fields" editor and standard/all export modes.
|
||||||
- **Profiles:** every setting is per-profile; each profile can point its logbook
|
- **Profiles:** every setting is per-profile; each profile can point its logbook
|
||||||
at the local SQLite file or a **shared MySQL** database (multi-operator).
|
at the local SQLite file or a **shared MySQL** database (multi-operator).
|
||||||
|
|
||||||
@@ -41,7 +50,8 @@ Developed by **F4BPO**.
|
|||||||
|
|
||||||
- **Main view = two configurable panes** (per profile, Settings → General →
|
- **Main view = two configurable panes** (per profile, Settings → General →
|
||||||
*Main view*): great-circle map, locator (street) map, the cluster grid, the
|
*Main view*): great-circle map, locator (street) map, the cluster grid, the
|
||||||
worked-before grid, or the **FlexRadio controls**.
|
worked-before grid, recent QSOs, the **FlexRadio controls**, the **Icom
|
||||||
|
console** or the **Net control** panel.
|
||||||
- **Great-circle map** with short/long-path distance & azimuth, selectable
|
- **Great-circle map** with short/long-path distance & azimuth, selectable
|
||||||
basemaps (Light / Voyager / Street / Satellite, all key-free and labelled) and
|
basemaps (Light / Voyager / Street / Satellite, all key-free and labelled) and
|
||||||
the **antenna beam lobe(s)** drawn from the rotor azimuth.
|
the **antenna beam lobe(s)** drawn from the rotor azimuth.
|
||||||
@@ -58,15 +68,29 @@ Developed by **F4BPO**.
|
|||||||
pane, with a show/hide toggle.
|
pane, with a show/hide toggle.
|
||||||
- Per-spot **status** (new / new-band / new-slot / worked), click-to-tune the
|
- Per-spot **status** (new / new-band / new-slot / worked), click-to-tune the
|
||||||
rig, and a multi-band **Band Map** (panadapter-style strips).
|
rig, and a multi-band **Band Map** (panadapter-style strips).
|
||||||
|
- **POTA** spots are tagged with their park reference (via `api.pota.app`).
|
||||||
|
- **Spot alerts** (Log4OM-style): rules on call / country / band / mode /
|
||||||
|
spotter, with sound, visual and e-mail notification (Tools → *Alert
|
||||||
|
management*).
|
||||||
|
|
||||||
## CAT control
|
## CAT control
|
||||||
|
|
||||||
- **OmniRig** backend (Rig 1/2, hot-swap), and a native **FlexRadio (SmartSDR)**
|
Four native backends (Settings → CAT), each with auto-reconnect and a fast,
|
||||||
backend over the radio's TCP API — real-time slice freq/mode/split, auto
|
non-blocking connect so a powered-off radio never freezes the app:
|
||||||
reconnect, UDP discovery, and **panadapter spots** (cluster spots pushed to the
|
|
||||||
Flex display, click → fill the call).
|
- **OmniRig** (Rig 1/2, hot-swap) — works with any OmniRig-supported rig.
|
||||||
- Mode is taken from the radio; the digital sub-mode (FT4 vs FT8) is inferred
|
- **FlexRadio (SmartSDR)** over the radio's TCP API — real-time slice freq /
|
||||||
from the frequency.
|
mode / split, UDP discovery, and **panadapter spots** (cluster spots pushed to
|
||||||
|
the Flex display, click → fill the call).
|
||||||
|
- **Icom CI-V** — native, over the radio's **USB** port *or* over the internet
|
||||||
|
via the radio's **built-in LAN server** (see *Remote Icom* below). No RS-BA1 or
|
||||||
|
Remote Utility needed.
|
||||||
|
- **TCI** (WebSocket) — SunSDR / ExpertSDR2 and any TCI-compatible server:
|
||||||
|
freq / mode / PTT / split, plus optional panorama spots.
|
||||||
|
|
||||||
|
Mode is taken from the radio; the digital sub-mode (FT4 vs FT8) is inferred from
|
||||||
|
the frequency. **Per-band Flex RX/TX antennas** can be configured and are applied
|
||||||
|
automatically on band change.
|
||||||
|
|
||||||
### FlexRadio control tab (SmartSDR-style)
|
### FlexRadio control tab (SmartSDR-style)
|
||||||
|
|
||||||
@@ -80,19 +104,64 @@ Shown only when the CAT backend is a FlexRadio:
|
|||||||
- **Live meters** over the UDP VITA-49 stream: S-meter (S-units), forward power
|
- **Live meters** over the UDP VITA-49 stream: S-meter (S-units), forward power
|
||||||
(W), SWR, ALC, PA temperature, voltage, plus the amplifier's meters.
|
(W), SWR, ALC, PA temperature, voltage, plus the amplifier's meters.
|
||||||
|
|
||||||
|
### Icom control tab
|
||||||
|
|
||||||
|
Shown when the CAT backend is Icom (USB or network). A full RS-BA1-style console:
|
||||||
|
|
||||||
|
- **Twin VFO readout** (MAIN / SUB) with the big tabular frequency, mode badge,
|
||||||
|
band and RIT/ΔTX offset, and a **mode-button row** (SSB / CW / RTTY / PSK /
|
||||||
|
AM / FM).
|
||||||
|
- **Spectrum scope + waterfall** (panadapter): ON/OFF, CTR/FIX, double-click to
|
||||||
|
tune, and **◀ ⊙ ▶** buttons to centre the scope on the current frequency
|
||||||
|
(±50 kHz) and pan left/right.
|
||||||
|
- **Live meters** always visible: S-meter (click → fill RST), power in watts, SWR.
|
||||||
|
- **Receive DSP:** AF / RF gain, squelch, AGC, preamp, attenuator, filter
|
||||||
|
(FIL1/2/3), NB, NR, ANF and — **on CW only** — the **APF** (audio peak filter).
|
||||||
|
- **Passband / notch:** Twin PBT (inner / outer), manual notch + position.
|
||||||
|
- **Transmit:** RF power, MOX, TUNE, **split with an automatic offset**
|
||||||
|
(+5 kHz on SSB, +1 kHz on CW), and monitor. On **voice modes only**: mic gain,
|
||||||
|
speech compressor, VOX (+ gain + anti-VOX). Controls that don't apply to the
|
||||||
|
current mode are hidden automatically.
|
||||||
|
- **Bands & antenna:** one-touch band buttons and ANT1/ANT2 selection.
|
||||||
|
- **Clarifiers:** RIT and ΔTX with wheel / ± tuning (Ctrl+←/→ nudges RIT).
|
||||||
|
- **Power ON / OFF** buttons (manual by design — the app never wakes the rig on
|
||||||
|
connect).
|
||||||
|
- **CW keying** can run through the radio's own keyer (see *Keyers* below).
|
||||||
|
|
||||||
|
### Remote Icom (over the internet, no RS-BA1)
|
||||||
|
|
||||||
|
OpsLog speaks the IC-7610's built-in network protocol directly — it **replaces
|
||||||
|
both the Icom Remote Utility and RS-BA1**. Enter the radio's IP, the Network
|
||||||
|
User1 name/password and the CI-V address, and the whole Icom console works over
|
||||||
|
the LAN/internet: login + token (auto-renewed), CI-V tunnel, receive-side
|
||||||
|
retransmit for a rock-solid link even with the panadapter streaming, and manual
|
||||||
|
power ON/OFF. (Audio is out of scope — use the radio in USB + a voice link such
|
||||||
|
as Mumble.)
|
||||||
|
|
||||||
## Keyers & audio
|
## Keyers & audio
|
||||||
|
|
||||||
- **WinKeyer** CW keyer (macros, F-key macros, auto-call repeat).
|
- **CW keyer** with macros and F-key macros. The keyer engine is selectable:
|
||||||
- **Digital Voice Keyer** (DVK) message playback.
|
**WinKeyer** (K1EL WK1/2/3 over a COM port), **Icom** (the radio's own keyer
|
||||||
- **QSO audio recording** (SSB/DAX) archived per QSO; disabled for CW (no DAX
|
over CI-V — no extra hardware, works over the remote link too) or **TCI**.
|
||||||
audio in CW).
|
- **Digital Voice Keyer** (DVK): record F1–F6 voice messages and transmit them.
|
||||||
|
- **QSO audio recording:** continuous rolling capture; on *Log QSO* the contact
|
||||||
|
is saved to a per-QSO WAV (`CALL_YYYYMMDD_HHMMSS.wav`); mixes RX + mic.
|
||||||
|
|
||||||
|
## Amplifiers & switches
|
||||||
|
|
||||||
|
- **PowerGenius XL** (4O3A) amplifier — direct TCP: operate/standby, fan-mode
|
||||||
|
selector and fault display.
|
||||||
|
- **Antenna Genius** (4O3A) antenna switch over TCP/GSCP — a docked A/B
|
||||||
|
antenna-switch widget.
|
||||||
|
|
||||||
## QSL & awards
|
## QSL & awards
|
||||||
|
|
||||||
- **Awards engine:** built-in + custom award definitions (shared **globally**
|
- **Awards engine:** built-in + custom award definitions (shared **globally**
|
||||||
across profiles), worked/confirmed/validated by band & mode, OR rules and
|
across profiles) — DXCC, WAS / WAZ / WAC, WPX, IOTA / POTA / SOTA / WWFF,
|
||||||
manual reference assignment, live reference detection on call entry, and a
|
**DDFM**, worked/confirmed/validated by band & mode, OR rules and manual
|
||||||
**Rescan** that re-pulls the logbook (picks up fresh LoTW/QRZ confirmations).
|
reference assignment, live reference detection on call entry, **reference-list
|
||||||
|
import** for totals/names, and a **Rescan** that re-pulls the logbook (picks up
|
||||||
|
fresh LoTW/QRZ confirmations).
|
||||||
- **QSL services:** ClubLog (batched ADIF upload), LoTW, QRZ.com, eQSL — upload
|
- **QSL services:** ClubLog (batched ADIF upload), LoTW, QRZ.com, eQSL — upload
|
||||||
and **confirmation download** (which auto-refreshes the award stats).
|
and **confirmation download** (which auto-refreshes the award stats).
|
||||||
- **QSL Card Designer** (see below).
|
- **QSL Card Designer** (see below).
|
||||||
@@ -100,6 +169,13 @@ Shown only when the CAT backend is a FlexRadio:
|
|||||||
SMTP account. (Outlook/Hotmail disable basic-auth SMTP — use Gmail with an app
|
SMTP account. (Outlook/Hotmail disable basic-auth SMTP — use Gmail with an app
|
||||||
password, or a Microsoft app password.)
|
password, or a Microsoft app password.)
|
||||||
|
|
||||||
|
## Contest logging
|
||||||
|
|
||||||
|
- **Contest tab:** pick a contest (built-in ADIF `CONTEST_ID` list) and an
|
||||||
|
exchange (running serial or a fixed exchange). OpsLog auto-fills `CONTEST_ID`
|
||||||
|
and the sent/received serials (`STX` / `SRX`), enforces a window start/end,
|
||||||
|
flags dupes and keeps a live scoreboard.
|
||||||
|
|
||||||
## Multi-operator live status (special events)
|
## Multi-operator live status (special events)
|
||||||
|
|
||||||
For a multi-op special-event call on a shared MySQL logbook (e.g. **TM74TFR**):
|
For a multi-op special-event call on a shared MySQL logbook (e.g. **TM74TFR**):
|
||||||
@@ -111,10 +187,37 @@ own web server reads that table and produces a live page/image you can embed on
|
|||||||
the station's **QRZ.com** bio (`<img src="…/tm74-status.php?img=1">`). OpsLog
|
the station's **QRZ.com** bio (`<img src="…/tm74-status.php?img=1">`). OpsLog
|
||||||
only writes to the DB — it is not a web server.
|
only writes to the DB — it is not a web server.
|
||||||
|
|
||||||
|
## Net control
|
||||||
|
|
||||||
|
- **Directed-net logging** (Tools → Net): a global roster (`nets.json`) plus an
|
||||||
|
in-memory active session — check stations in, then log the whole net at once
|
||||||
|
using the CAT frequency.
|
||||||
|
|
||||||
|
## Appearance & language
|
||||||
|
|
||||||
|
- **Themes:** four complete themes (Warm light, Warm dark, Graphite dark, High
|
||||||
|
contrast) plus **Auto** (follows the OS light/dark preference), selectable in
|
||||||
|
Settings → General. Every panel and every AG-Grid table follows the theme.
|
||||||
|
- **Bilingual:** full **English / French** UI, with a first-run flag chooser and
|
||||||
|
a switcher in Settings → General.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- **Secret vault:** opt-in passphrase encryption of the stored passwords
|
||||||
|
(AES-GCM + PBKDF2). Encrypted values are portable; a single unlock prompt at
|
||||||
|
launch decrypts them for the session.
|
||||||
|
|
||||||
|
## Integrations (outbound)
|
||||||
|
|
||||||
|
- **UDP emitters:** push the current frequency to **PstRotator**, radio info in
|
||||||
|
**N1MM `RadioInfo`** format, or an **ADIF record on each logged QSO** — so
|
||||||
|
external tools (rotator control, digital apps, other loggers) stay in sync.
|
||||||
|
|
||||||
## Other
|
## Other
|
||||||
|
|
||||||
- **Autostart:** launch external programs (WSJT-X, JTAlert, rotator control…) at
|
- **Autostart:** launch external programs (WSJT-X, JTAlert, rotator control…) at
|
||||||
OpsLog startup, skipping any already running.
|
OpsLog startup, skipping any already running.
|
||||||
|
- **Backup:** optional database + ADIF backup at shutdown.
|
||||||
- **Update check** at startup with a toast (toggleable).
|
- **Update check** at startup with a toast (toggleable).
|
||||||
- **Anonymous usage telemetry** (a once-a-day heartbeat: random install ID +
|
- **Anonymous usage telemetry** (a once-a-day heartbeat: random install ID +
|
||||||
version + OS — no callsign or QSO data; opt-out in Preferences).
|
version + OS — no callsign or QSO data; opt-out in Preferences).
|
||||||
@@ -156,3 +259,7 @@ commonly-worked DXCC entities.
|
|||||||
`data/` — instant even when the logbook is on a far-away MySQL.
|
`data/` — instant even when the logbook is on a far-away MySQL.
|
||||||
- **Logbook** (QSOs) lives where the active profile points it: the local SQLite
|
- **Logbook** (QSOs) lives where the active profile points it: the local SQLite
|
||||||
file or a per-profile shared **MySQL** database.
|
file or a per-profile shared **MySQL** database.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*A French version of this document is available in [README.fr.md](README.fr.md).*
|
||||||
|
|||||||
@@ -7843,6 +7843,13 @@ func (a *App) IcomSetANF(on bool) error {
|
|||||||
return a.cat.IcomDo(func(ic cat.IcomController) error { return ic.SetANF(on) })
|
return a.cat.IcomDo(func(ic cat.IcomController) error { return ic.SetANF(on) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) IcomSetAPF(on bool) error {
|
||||||
|
if a.cat == nil {
|
||||||
|
return fmt.Errorf("cat not initialized")
|
||||||
|
}
|
||||||
|
return a.cat.IcomDo(func(ic cat.IcomController) error { return ic.SetAPF(on) })
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) IcomSetAGC(mode string) error {
|
func (a *App) IcomSetAGC(mode string) error {
|
||||||
if a.cat == nil {
|
if a.cat == nil {
|
||||||
return fmt.Errorf("cat not initialized")
|
return fmt.Errorf("cat not initialized")
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Radio, AudioLines, Mic, Activity, SlidersHorizontal, Antenna, Filter, P
|
|||||||
import {
|
import {
|
||||||
GetIcomState, IcomRefresh,
|
GetIcomState, IcomRefresh,
|
||||||
IcomSetAFGain, IcomSetRFGain, IcomSetNB, IcomSetNBLevel, IcomSetNR, IcomSetNRLevel,
|
IcomSetAFGain, IcomSetRFGain, IcomSetNB, IcomSetNBLevel, IcomSetNR, IcomSetNRLevel,
|
||||||
IcomSetANF, IcomSetAGC, IcomSetPreamp, IcomSetAtt, IcomSetFilter,
|
IcomSetANF, IcomSetAPF, IcomSetAGC, IcomSetPreamp, IcomSetAtt, IcomSetFilter,
|
||||||
IcomSetRFPower, IcomSetMicGain, IcomSetSplit, IcomTune, IcomSetPTT,
|
IcomSetRFPower, IcomSetMicGain, IcomSetSplit, IcomTune, IcomSetPTT,
|
||||||
IcomSetScope, IcomScopeData, IcomSetScopeMode, IcomSetScopeEdges, GetCATState, SetCATFrequency, SetCATMode,
|
IcomSetScope, IcomScopeData, IcomSetScopeMode, IcomSetScopeEdges, GetCATState, SetCATFrequency, SetCATMode,
|
||||||
IcomSetRIT, IcomSetRITOn, IcomSetXITOn,
|
IcomSetRIT, IcomSetRITOn, IcomSetXITOn,
|
||||||
@@ -21,7 +21,7 @@ type IcomState = {
|
|||||||
s_meter: number; power_meter: number; swr_meter: number;
|
s_meter: number; power_meter: number; swr_meter: number;
|
||||||
rf_power: number; mic_gain: number;
|
rf_power: number; mic_gain: number;
|
||||||
af_gain: number; rf_gain: number;
|
af_gain: number; rf_gain: number;
|
||||||
nb: boolean; nb_level: number; nr: boolean; nr_level: number; anf: boolean;
|
nb: boolean; nb_level: number; nr: boolean; nr_level: number; anf: boolean; apf: boolean;
|
||||||
agc?: string; preamp: number; att: number; filter: number;
|
agc?: string; preamp: number; att: number; filter: number;
|
||||||
rit_hz: number; rit_on: boolean; xit_on: boolean;
|
rit_hz: number; rit_on: boolean; xit_on: boolean;
|
||||||
antenna: number;
|
antenna: number;
|
||||||
@@ -35,7 +35,7 @@ const ZERO: IcomState = {
|
|||||||
available: false, transmitting: false, split: false,
|
available: false, transmitting: false, split: false,
|
||||||
s_meter: 0, power_meter: 0, swr_meter: 0, rf_power: 0, mic_gain: 0,
|
s_meter: 0, power_meter: 0, swr_meter: 0, rf_power: 0, mic_gain: 0,
|
||||||
af_gain: 0, rf_gain: 0,
|
af_gain: 0, rf_gain: 0,
|
||||||
nb: false, nb_level: 0, nr: false, nr_level: 0, anf: false,
|
nb: false, nb_level: 0, nr: false, nr_level: 0, anf: false, apf: false,
|
||||||
preamp: 0, att: 0, filter: 1,
|
preamp: 0, att: 0, filter: 1,
|
||||||
rit_hz: 0, rit_on: false, xit_on: false,
|
rit_hz: 0, rit_on: false, xit_on: false,
|
||||||
antenna: 1,
|
antenna: 1,
|
||||||
@@ -615,6 +615,11 @@ export function IcomPanel({ onReportRST }: { onReportRST?: (rst: string) => void
|
|||||||
const mainHz: number = split ? (cat?.freq_rx_hz || 0) : (cat?.freq_hz || 0);
|
const mainHz: number = split ? (cat?.freq_rx_hz || 0) : (cat?.freq_hz || 0);
|
||||||
const subHz: number = split ? (cat?.freq_hz || 0) : 0;
|
const subHz: number = split ? (cat?.freq_hz || 0) : 0;
|
||||||
const curMode: string = cat?.mode || st.mode || '';
|
const curMode: string = cat?.mode || st.mode || '';
|
||||||
|
// Mode-dependent controls: VOX / speech-comp / mic are voice-only (hidden on
|
||||||
|
// CW and data); APF (audio peak filter) is CW-only. Fold USB/LSB into phone.
|
||||||
|
const um = curMode.toUpperCase();
|
||||||
|
const isCW = um === 'CW' || um === 'CWR';
|
||||||
|
const isPhone = um === 'SSB' || um === 'USB' || um === 'LSB' || um === 'AM' || um === 'FM';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full min-h-0 overflow-auto bg-background">
|
<div className="h-full min-h-0 overflow-auto bg-background">
|
||||||
@@ -735,10 +740,12 @@ export function IcomPanel({ onReportRST }: { onReportRST?: (rst: string) => void
|
|||||||
<Slider value={st.rf_power} accent="#ef4444" onChange={(v) => set({ rf_power: v }, () => IcomSetRFPower(v))} />
|
<Slider value={st.rf_power} accent="#ef4444" onChange={(v) => set({ rf_power: v }, () => IcomSetRFPower(v))} />
|
||||||
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.rf_power}</span>
|
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.rf_power}</span>
|
||||||
</Row>
|
</Row>
|
||||||
<Row label={t('icmp.mic')}>
|
{isPhone && (
|
||||||
<Slider value={st.mic_gain} accent="#ef4444" onChange={(v) => set({ mic_gain: v }, () => IcomSetMicGain(v))} />
|
<Row label={t('icmp.mic')}>
|
||||||
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.mic_gain}</span>
|
<Slider value={st.mic_gain} accent="#ef4444" onChange={(v) => set({ mic_gain: v }, () => IcomSetMicGain(v))} />
|
||||||
</Row>
|
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.mic_gain}</span>
|
||||||
|
</Row>
|
||||||
|
)}
|
||||||
<div className="flex items-center gap-2 pt-1">
|
<div className="flex items-center gap-2 pt-1">
|
||||||
<button type="button" onClick={toggleMox}
|
<button type="button" onClick={toggleMox}
|
||||||
className={cn('flex-1 px-3 py-1.5 rounded-md text-xs font-bold border transition-colors',
|
className={cn('flex-1 px-3 py-1.5 rounded-md text-xs font-bold border transition-colors',
|
||||||
@@ -752,21 +759,26 @@ export function IcomPanel({ onReportRST }: { onReportRST?: (rst: string) => void
|
|||||||
TUNE
|
TUNE
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/* Speech processor / monitor / VOX. */}
|
{/* Monitor (all modes) + speech processor / VOX (voice modes only —
|
||||||
|
they don't exist on CW or data). */}
|
||||||
<div className="pt-2 mt-1 border-t border-border/60 space-y-3">
|
<div className="pt-2 mt-1 border-t border-border/60 space-y-3">
|
||||||
<LevelRow label="COMP" on={st.comp} value={st.comp_level}
|
|
||||||
onToggle={() => set({ comp: !st.comp }, () => IcomSetComp(!st.comp))}
|
|
||||||
onLevel={(v) => set({ comp_level: v }, () => IcomSetCompLevel(v))} />
|
|
||||||
<LevelRow label="MON" on={st.monitor} value={st.mon_level}
|
<LevelRow label="MON" on={st.monitor} value={st.mon_level}
|
||||||
onToggle={() => set({ monitor: !st.monitor }, () => IcomSetMonitor(!st.monitor))}
|
onToggle={() => set({ monitor: !st.monitor }, () => IcomSetMonitor(!st.monitor))}
|
||||||
onLevel={(v) => set({ mon_level: v }, () => IcomSetMonLevel(v))} />
|
onLevel={(v) => set({ mon_level: v }, () => IcomSetMonLevel(v))} />
|
||||||
<LevelRow label="VOX" on={st.vox} value={st.vox_gain}
|
{isPhone && (
|
||||||
onToggle={() => set({ vox: !st.vox }, () => IcomSetVOX(!st.vox))}
|
<>
|
||||||
onLevel={(v) => set({ vox_gain: v }, () => IcomSetVOXGain(v))} />
|
<LevelRow label="COMP" on={st.comp} value={st.comp_level}
|
||||||
<Row label="Anti-VOX">
|
onToggle={() => set({ comp: !st.comp }, () => IcomSetComp(!st.comp))}
|
||||||
<Slider value={st.anti_vox} disabled={!st.vox} onChange={(v) => set({ anti_vox: v }, () => IcomSetAntiVOX(v))} />
|
onLevel={(v) => set({ comp_level: v }, () => IcomSetCompLevel(v))} />
|
||||||
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.anti_vox}</span>
|
<LevelRow label="VOX" on={st.vox} value={st.vox_gain}
|
||||||
</Row>
|
onToggle={() => set({ vox: !st.vox }, () => IcomSetVOX(!st.vox))}
|
||||||
|
onLevel={(v) => set({ vox_gain: v }, () => IcomSetVOXGain(v))} />
|
||||||
|
<Row label="Anti-VOX">
|
||||||
|
<Slider value={st.anti_vox} disabled={!st.vox} onChange={(v) => set({ anti_vox: v }, () => IcomSetAntiVOX(v))} />
|
||||||
|
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{st.anti_vox}</span>
|
||||||
|
</Row>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
@@ -837,6 +849,13 @@ export function IcomPanel({ onReportRST }: { onReportRST?: (rst: string) => void
|
|||||||
<Chip label="ANF" on={st.anf} onClick={() => set({ anf: !st.anf }, () => IcomSetANF(!st.anf))} />
|
<Chip label="ANF" on={st.anf} onClick={() => set({ anf: !st.anf }, () => IcomSetANF(!st.anf))} />
|
||||||
<span className="text-xs text-muted-foreground">{t('icmp.autoNotch')}</span>
|
<span className="text-xs text-muted-foreground">{t('icmp.autoNotch')}</span>
|
||||||
</div>
|
</div>
|
||||||
|
{/* APF (audio peak filter) — CW only: peaks the CW tone. */}
|
||||||
|
{isCW && (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Chip label="APF" on={st.apf} onClick={() => set({ apf: !st.apf }, () => IcomSetAPF(!st.apf))} />
|
||||||
|
<span className="text-xs text-muted-foreground">{t('icmp.apf')}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ const en: Dict = {
|
|||||||
'agp.portDeselect': 'Port {letter} — click to deselect', 'agp.portSelect': 'Select on port {letter}', 'agp.online': 'online', 'agp.offline': 'offline', 'agp.close': 'Close', 'agp.connecting': 'Connecting…', 'agp.noAntennas': 'No antennas configured.',
|
'agp.portDeselect': 'Port {letter} — click to deselect', 'agp.portSelect': 'Select on port {letter}', 'agp.online': 'online', 'agp.offline': 'offline', 'agp.close': 'Close', 'agp.connecting': 'Connecting…', 'agp.noAntennas': 'No antennas configured.',
|
||||||
'flxp.smartsdrRemote': 'SmartSDR remote control', 'flxp.offline': 'OFFLINE', 'flxp.waiting': 'Waiting for the FlexRadio… (set CAT to FlexRadio and connect)', 'flxp.transmit': 'Transmit', 'flxp.rfPower': 'RF Power', 'flxp.tunePwr': 'Tune Pwr', 'flxp.splitHint': 'Split: RX/TX on separate slices. ON creates a TX slice +1 kHz (CW) / +5 kHz (SSB) up, like SmartSDR.', 'flxp.voxDly': 'VOX Dly', 'flxp.speed': 'Speed', 'flxp.pitch': 'Pitch', 'flxp.delay': 'Delay',
|
'flxp.smartsdrRemote': 'SmartSDR remote control', 'flxp.offline': 'OFFLINE', 'flxp.waiting': 'Waiting for the FlexRadio… (set CAT to FlexRadio and connect)', 'flxp.transmit': 'Transmit', 'flxp.rfPower': 'RF Power', 'flxp.tunePwr': 'Tune Pwr', 'flxp.splitHint': 'Split: RX/TX on separate slices. ON creates a TX slice +1 kHz (CW) / +5 kHz (SSB) up, like SmartSDR.', 'flxp.voxDly': 'VOX Dly', 'flxp.speed': 'Speed', 'flxp.pitch': 'Pitch', 'flxp.delay': 'Delay',
|
||||||
'flxp.receiveActive': 'Receive (active slice)', 'flxp.muted': 'Muted — click to unmute', 'flxp.mute': 'Mute RX audio', 'flxp.filter': 'Filter', 'flxp.amplifier': 'Amplifier', 'flxp.ampInLine': 'Amplifier is in line (transmitting through PA).', 'flxp.ampBypassed': 'Amplifier bypassed (standby).', 'flxp.pgConnected': 'PowerGenius connected', 'flxp.pgOffline': 'PowerGenius offline', 'flxp.fan': 'Fan', 'flxp.fanStandard': 'Standard', 'flxp.fanContest': 'Contest', 'flxp.fanBroadcast': 'Broadcast', 'flxp.fault': 'FAULT', 'flxp.meters': 'Meters', 'flxp.noMeters': "No meters yet — waiting for the radio's UDP stream…", 'flxp.amplifierHdr': 'AMPLIFIER',
|
'flxp.receiveActive': 'Receive (active slice)', 'flxp.muted': 'Muted — click to unmute', 'flxp.mute': 'Mute RX audio', 'flxp.filter': 'Filter', 'flxp.amplifier': 'Amplifier', 'flxp.ampInLine': 'Amplifier is in line (transmitting through PA).', 'flxp.ampBypassed': 'Amplifier bypassed (standby).', 'flxp.pgConnected': 'PowerGenius connected', 'flxp.pgOffline': 'PowerGenius offline', 'flxp.fan': 'Fan', 'flxp.fanStandard': 'Standard', 'flxp.fanContest': 'Contest', 'flxp.fanBroadcast': 'Broadcast', 'flxp.fault': 'FAULT', 'flxp.meters': 'Meters', 'flxp.noMeters': "No meters yet — waiting for the radio's UDP stream…", 'flxp.amplifierHdr': 'AMPLIFIER',
|
||||||
'icmp.spectrum': 'Spectrum', 'icmp.scopeFixed': 'Fixed — double-click / wheel to tune', 'icmp.scopeCenter': 'Center — follows VFO', 'icmp.scopeOff': 'Scope off', 'icmp.scopePanDown': 'Shift scope −50 kHz', 'icmp.scopePanUp': 'Shift scope +50 kHz', 'icmp.scopeCenterVfo': 'Center scope on the current frequency (±50 kHz)', 'icmp.notConnected': "Icom not connected. Enable the Icom CI-V backend in Settings → CAT and connect the radio's USB port.", 'icmp.refresh': 'Refresh', 'icmp.meters': 'Meters', 'icmp.transmit': 'Transmit', 'icmp.power': 'Power', 'icmp.mic': 'Mic', 'icmp.receive': 'Receive', 'icmp.preamp': 'Preamp', 'icmp.filter': 'Filter', 'icmp.noiseNotch': 'Noise / Notch', 'icmp.autoNotch': 'Auto notch filter', 'icmp.clarifiers': 'RIT / ΔTX', 'icmp.ritHint': 'Wheel or ± to shift · Ctrl+←/→ shifts RIT when active', 'icmp.bandsAntenna': 'Bands & Antenna', 'icmp.antenna': 'Antenna', 'icmp.passband': 'Passband / Notch', 'icmp.pbtCenter': 'Center PBT', 'icmp.manualNotch': 'Manual notch — MN on, then set position', 'icmp.squelch': 'Squelch', 'icmp.powerOnHint': 'Power the radio ON (boots ~15 s)', 'icmp.powerOffHint': 'Power the radio OFF', 'icmp.powerOffConfirm': 'Switch the radio OFF?',
|
'icmp.spectrum': 'Spectrum', 'icmp.scopeFixed': 'Fixed — double-click / wheel to tune', 'icmp.scopeCenter': 'Center — follows VFO', 'icmp.scopeOff': 'Scope off', 'icmp.scopePanDown': 'Shift scope −50 kHz', 'icmp.scopePanUp': 'Shift scope +50 kHz', 'icmp.scopeCenterVfo': 'Center scope on the current frequency (±50 kHz)', 'icmp.notConnected': "Icom not connected. Enable the Icom CI-V backend in Settings → CAT and connect the radio's USB port.", 'icmp.refresh': 'Refresh', 'icmp.meters': 'Meters', 'icmp.transmit': 'Transmit', 'icmp.power': 'Power', 'icmp.mic': 'Mic', 'icmp.receive': 'Receive', 'icmp.preamp': 'Preamp', 'icmp.filter': 'Filter', 'icmp.noiseNotch': 'Noise / Notch', 'icmp.autoNotch': 'Auto notch filter', 'icmp.apf': 'Audio peak filter (CW)', 'icmp.clarifiers': 'RIT / ΔTX', 'icmp.ritHint': 'Wheel or ± to shift · Ctrl+←/→ shifts RIT when active', 'icmp.bandsAntenna': 'Bands & Antenna', 'icmp.antenna': 'Antenna', 'icmp.passband': 'Passband / Notch', 'icmp.pbtCenter': 'Center PBT', 'icmp.manualNotch': 'Manual notch — MN on, then set position', 'icmp.squelch': 'Squelch', 'icmp.powerOnHint': 'Power the radio ON (boots ~15 s)', 'icmp.powerOffHint': 'Power the radio OFF', 'icmp.powerOffConfirm': 'Switch the radio OFF?',
|
||||||
'rst.clickToFill': 'Click to set RST tx from the signal',
|
'rst.clickToFill': 'Click to set RST tx from the signal',
|
||||||
'qrz.openTitle': 'Open {call} on QRZ.com',
|
'qrz.openTitle': 'Open {call} on QRZ.com',
|
||||||
// Misc panels/modals (alerts / send-spot / net / udp / filter / details)
|
// Misc panels/modals (alerts / send-spot / net / udp / filter / details)
|
||||||
@@ -379,7 +379,7 @@ const fr: Dict = {
|
|||||||
'agp.portDeselect': 'Port {letter} — clic pour désélectionner', 'agp.portSelect': 'Sélectionner sur le port {letter}', 'agp.online': 'en ligne', 'agp.offline': 'hors ligne', 'agp.close': 'Fermer', 'agp.connecting': 'Connexion…', 'agp.noAntennas': 'Aucune antenne configurée.',
|
'agp.portDeselect': 'Port {letter} — clic pour désélectionner', 'agp.portSelect': 'Sélectionner sur le port {letter}', 'agp.online': 'en ligne', 'agp.offline': 'hors ligne', 'agp.close': 'Fermer', 'agp.connecting': 'Connexion…', 'agp.noAntennas': 'Aucune antenne configurée.',
|
||||||
'flxp.smartsdrRemote': 'Contrôle à distance SmartSDR', 'flxp.offline': 'HORS LIGNE', 'flxp.waiting': 'En attente du FlexRadio… (règle le CAT sur FlexRadio et connecte)', 'flxp.transmit': 'Émission', 'flxp.rfPower': 'Puissance RF', 'flxp.tunePwr': 'Puiss. TUNE', 'flxp.splitHint': 'Split : RX/TX sur des slices séparées. ON crée une slice TX +1 kHz (CW) / +5 kHz (SSB) au-dessus, comme SmartSDR.', 'flxp.voxDly': 'Délai VOX', 'flxp.speed': 'Vitesse', 'flxp.pitch': 'Tonalité', 'flxp.delay': 'Délai',
|
'flxp.smartsdrRemote': 'Contrôle à distance SmartSDR', 'flxp.offline': 'HORS LIGNE', 'flxp.waiting': 'En attente du FlexRadio… (règle le CAT sur FlexRadio et connecte)', 'flxp.transmit': 'Émission', 'flxp.rfPower': 'Puissance RF', 'flxp.tunePwr': 'Puiss. TUNE', 'flxp.splitHint': 'Split : RX/TX sur des slices séparées. ON crée une slice TX +1 kHz (CW) / +5 kHz (SSB) au-dessus, comme SmartSDR.', 'flxp.voxDly': 'Délai VOX', 'flxp.speed': 'Vitesse', 'flxp.pitch': 'Tonalité', 'flxp.delay': 'Délai',
|
||||||
'flxp.receiveActive': 'Réception (slice active)', 'flxp.muted': 'Coupé — clic pour rétablir', 'flxp.mute': "Couper l'audio RX", 'flxp.filter': 'Filtre', 'flxp.amplifier': 'Amplificateur', 'flxp.ampInLine': 'Amplificateur en ligne (émission via le PA).', 'flxp.ampBypassed': 'Amplificateur en bypass (standby).', 'flxp.pgConnected': 'PowerGenius connecté', 'flxp.pgOffline': 'PowerGenius hors ligne', 'flxp.fan': 'Ventilo', 'flxp.fanStandard': 'Standard', 'flxp.fanContest': 'Contest', 'flxp.fanBroadcast': 'Diffusion', 'flxp.fault': 'DÉFAUT', 'flxp.meters': 'Mesures', 'flxp.noMeters': 'Aucune mesure — en attente du flux UDP de la radio…', 'flxp.amplifierHdr': 'AMPLIFICATEUR',
|
'flxp.receiveActive': 'Réception (slice active)', 'flxp.muted': 'Coupé — clic pour rétablir', 'flxp.mute': "Couper l'audio RX", 'flxp.filter': 'Filtre', 'flxp.amplifier': 'Amplificateur', 'flxp.ampInLine': 'Amplificateur en ligne (émission via le PA).', 'flxp.ampBypassed': 'Amplificateur en bypass (standby).', 'flxp.pgConnected': 'PowerGenius connecté', 'flxp.pgOffline': 'PowerGenius hors ligne', 'flxp.fan': 'Ventilo', 'flxp.fanStandard': 'Standard', 'flxp.fanContest': 'Contest', 'flxp.fanBroadcast': 'Diffusion', 'flxp.fault': 'DÉFAUT', 'flxp.meters': 'Mesures', 'flxp.noMeters': 'Aucune mesure — en attente du flux UDP de la radio…', 'flxp.amplifierHdr': 'AMPLIFICATEUR',
|
||||||
'icmp.spectrum': 'Spectre', 'icmp.scopeFixed': 'Fixe — double-clic / molette pour accorder', 'icmp.scopeCenter': 'Centré — suit le VFO', 'icmp.scopeOff': 'Scope éteint', 'icmp.scopePanDown': 'Décaler le scope −50 kHz', 'icmp.scopePanUp': 'Décaler le scope +50 kHz', 'icmp.scopeCenterVfo': 'Centrer le scope sur la fréquence actuelle (±50 kHz)', 'icmp.notConnected': 'Icom non connecté. Active le backend CI-V Icom dans Réglages → CAT et connecte le port USB de la radio.', 'icmp.refresh': 'Rafraîchir', 'icmp.meters': 'Mesures', 'icmp.transmit': 'Émission', 'icmp.power': 'Puissance', 'icmp.mic': 'Micro', 'icmp.receive': 'Réception', 'icmp.preamp': 'Préampli', 'icmp.filter': 'Filtre', 'icmp.noiseNotch': 'Bruit / Notch', 'icmp.autoNotch': 'Filtre notch auto', 'icmp.clarifiers': 'RIT / ΔTX', 'icmp.ritHint': 'Molette ou ± pour décaler · Ctrl+←/→ décale le RIT si actif', 'icmp.bandsAntenna': 'Bandes & Antenne', 'icmp.antenna': 'Antenne', 'icmp.passband': 'Passe-bande / Notch', 'icmp.pbtCenter': 'Centrer PBT', 'icmp.manualNotch': 'Notch manuel — active MN, puis règle la position', 'icmp.squelch': 'Squelch', 'icmp.powerOnHint': 'Allumer la radio (démarre en ~15 s)', 'icmp.powerOffHint': 'Éteindre la radio', 'icmp.powerOffConfirm': 'Éteindre la radio ?',
|
'icmp.spectrum': 'Spectre', 'icmp.scopeFixed': 'Fixe — double-clic / molette pour accorder', 'icmp.scopeCenter': 'Centré — suit le VFO', 'icmp.scopeOff': 'Scope éteint', 'icmp.scopePanDown': 'Décaler le scope −50 kHz', 'icmp.scopePanUp': 'Décaler le scope +50 kHz', 'icmp.scopeCenterVfo': 'Centrer le scope sur la fréquence actuelle (±50 kHz)', 'icmp.notConnected': 'Icom non connecté. Active le backend CI-V Icom dans Réglages → CAT et connecte le port USB de la radio.', 'icmp.refresh': 'Rafraîchir', 'icmp.meters': 'Mesures', 'icmp.transmit': 'Émission', 'icmp.power': 'Puissance', 'icmp.mic': 'Micro', 'icmp.receive': 'Réception', 'icmp.preamp': 'Préampli', 'icmp.filter': 'Filtre', 'icmp.noiseNotch': 'Bruit / Notch', 'icmp.autoNotch': 'Filtre notch auto', 'icmp.apf': 'Filtre de pic audio (CW)', 'icmp.clarifiers': 'RIT / ΔTX', 'icmp.ritHint': 'Molette ou ± pour décaler · Ctrl+←/→ décale le RIT si actif', 'icmp.bandsAntenna': 'Bandes & Antenne', 'icmp.antenna': 'Antenne', 'icmp.passband': 'Passe-bande / Notch', 'icmp.pbtCenter': 'Centrer PBT', 'icmp.manualNotch': 'Notch manuel — active MN, puis règle la position', 'icmp.squelch': 'Squelch', 'icmp.powerOnHint': 'Allumer la radio (démarre en ~15 s)', 'icmp.powerOffHint': 'Éteindre la radio', 'icmp.powerOffConfirm': 'Éteindre la radio ?',
|
||||||
'rst.clickToFill': 'Clic pour remplir le RST tx depuis le signal',
|
'rst.clickToFill': 'Clic pour remplir le RST tx depuis le signal',
|
||||||
'qrz.openTitle': 'Ouvrir {call} sur QRZ.com',
|
'qrz.openTitle': 'Ouvrir {call} sur QRZ.com',
|
||||||
'altm.filterPh': 'Filtrer…', 'altm.noMatch': 'aucun résultat', 'altm.noneAll': 'aucune sélection = TOUT', 'altm.nSelected': '{n} sélectionné(s)', 'altm.giveName': 'Donne un nom à la règle', 'altm.deleteConfirm': "Supprimer l'alerte « {name} » ?", 'altm.title': 'Gestion des alertes', 'altm.desc': 'Alerte quand un spot correspond à une règle. Filtres vides = TOUT ; les filtres définis sont combinés par ET (ex. France + 20m = stations françaises sur 20m).', 'altm.rules': 'Règles', 'altm.noRules': 'Aucune règle — clique sur +', 'altm.emailTo': "E-mail d'alerte à", 'altm.selectOrCreate': 'Sélectionne ou crée une règle.', 'altm.tabDef': 'Définition', 'altm.tabCall': 'Indicatif / DXCC', 'altm.tabBandMode': 'Bande / Mode', 'altm.tabOrigin': 'Origine', 'altm.ruleName': 'Nom de la règle', 'altm.alertEnabled': 'Alerte activée', 'altm.againAfter': 'Réalerter après (min)', 'altm.againHint': '0 = une fois/session · -1 = toujours', 'altm.actions': 'Actions', 'altm.visual': 'Visuel', 'altm.sound': 'Son', 'altm.email': 'E-mail', 'altm.skipWorked': 'Ignorer les indicatifs déjà contactés (même bande + mode)', 'altm.callsigns': 'Indicatifs (un par ligne, jokers : IW3*, */P)', 'altm.countries': 'Pays (DXCC)', 'altm.continents': 'Continents', 'altm.bands': 'Bandes', 'altm.modes': 'Modes', 'altm.spotterCall': 'Indicatif du spotteur (joker)', 'altm.spotterCallPh': 'ex. F* ou DL1ABC', 'altm.spotterContinents': 'Continents du spotteur', 'altm.spotterCountries': 'Pays du spotteur', 'altm.delete': 'Supprimer', 'altm.saveRule': 'Enregistrer la règle', 'altm.close': 'Fermer',
|
'altm.filterPh': 'Filtrer…', 'altm.noMatch': 'aucun résultat', 'altm.noneAll': 'aucune sélection = TOUT', 'altm.nSelected': '{n} sélectionné(s)', 'altm.giveName': 'Donne un nom à la règle', 'altm.deleteConfirm': "Supprimer l'alerte « {name} » ?", 'altm.title': 'Gestion des alertes', 'altm.desc': 'Alerte quand un spot correspond à une règle. Filtres vides = TOUT ; les filtres définis sont combinés par ET (ex. France + 20m = stations françaises sur 20m).', 'altm.rules': 'Règles', 'altm.noRules': 'Aucune règle — clique sur +', 'altm.emailTo': "E-mail d'alerte à", 'altm.selectOrCreate': 'Sélectionne ou crée une règle.', 'altm.tabDef': 'Définition', 'altm.tabCall': 'Indicatif / DXCC', 'altm.tabBandMode': 'Bande / Mode', 'altm.tabOrigin': 'Origine', 'altm.ruleName': 'Nom de la règle', 'altm.alertEnabled': 'Alerte activée', 'altm.againAfter': 'Réalerter après (min)', 'altm.againHint': '0 = une fois/session · -1 = toujours', 'altm.actions': 'Actions', 'altm.visual': 'Visuel', 'altm.sound': 'Son', 'altm.email': 'E-mail', 'altm.skipWorked': 'Ignorer les indicatifs déjà contactés (même bande + mode)', 'altm.callsigns': 'Indicatifs (un par ligne, jokers : IW3*, */P)', 'altm.countries': 'Pays (DXCC)', 'altm.continents': 'Continents', 'altm.bands': 'Bandes', 'altm.modes': 'Modes', 'altm.spotterCall': 'Indicatif du spotteur (joker)', 'altm.spotterCallPh': 'ex. F* ou DL1ABC', 'altm.spotterContinents': 'Continents du spotteur', 'altm.spotterCountries': 'Pays du spotteur', 'altm.delete': 'Supprimer', 'altm.saveRule': 'Enregistrer la règle', 'altm.close': 'Fermer',
|
||||||
|
|||||||
Vendored
+2
@@ -350,6 +350,8 @@ export function IcomSetAGC(arg1:string):Promise<void>;
|
|||||||
|
|
||||||
export function IcomSetANF(arg1:boolean):Promise<void>;
|
export function IcomSetANF(arg1:boolean):Promise<void>;
|
||||||
|
|
||||||
|
export function IcomSetAPF(arg1:boolean):Promise<void>;
|
||||||
|
|
||||||
export function IcomSetAntenna(arg1:number):Promise<void>;
|
export function IcomSetAntenna(arg1:number):Promise<void>;
|
||||||
|
|
||||||
export function IcomSetAntiVOX(arg1:number):Promise<void>;
|
export function IcomSetAntiVOX(arg1:number):Promise<void>;
|
||||||
|
|||||||
@@ -662,6 +662,10 @@ export function IcomSetANF(arg1) {
|
|||||||
return window['go']['main']['App']['IcomSetANF'](arg1);
|
return window['go']['main']['App']['IcomSetANF'](arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function IcomSetAPF(arg1) {
|
||||||
|
return window['go']['main']['App']['IcomSetAPF'](arg1);
|
||||||
|
}
|
||||||
|
|
||||||
export function IcomSetAntenna(arg1) {
|
export function IcomSetAntenna(arg1) {
|
||||||
return window['go']['main']['App']['IcomSetAntenna'](arg1);
|
return window['go']['main']['App']['IcomSetAntenna'](arg1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -690,6 +690,7 @@ export namespace cat {
|
|||||||
nr: boolean;
|
nr: boolean;
|
||||||
nr_level: number;
|
nr_level: number;
|
||||||
anf: boolean;
|
anf: boolean;
|
||||||
|
apf: boolean;
|
||||||
agc?: string;
|
agc?: string;
|
||||||
preamp: number;
|
preamp: number;
|
||||||
att: number;
|
att: number;
|
||||||
@@ -736,6 +737,7 @@ export namespace cat {
|
|||||||
this.nr = source["nr"];
|
this.nr = source["nr"];
|
||||||
this.nr_level = source["nr_level"];
|
this.nr_level = source["nr_level"];
|
||||||
this.anf = source["anf"];
|
this.anf = source["anf"];
|
||||||
|
this.apf = source["apf"];
|
||||||
this.agc = source["agc"];
|
this.agc = source["agc"];
|
||||||
this.preamp = source["preamp"];
|
this.preamp = source["preamp"];
|
||||||
this.att = source["att"];
|
this.att = source["att"];
|
||||||
|
|||||||
@@ -415,6 +415,7 @@ type IcomTXState struct {
|
|||||||
NR bool `json:"nr"`
|
NR bool `json:"nr"`
|
||||||
NRLevel int `json:"nr_level"`
|
NRLevel int `json:"nr_level"`
|
||||||
ANF bool `json:"anf"`
|
ANF bool `json:"anf"`
|
||||||
|
APF bool `json:"apf"` // audio peak filter (CW only)
|
||||||
AGC string `json:"agc,omitempty"` // FAST | MID | SLOW
|
AGC string `json:"agc,omitempty"` // FAST | MID | SLOW
|
||||||
Preamp int `json:"preamp"` // 0=off, 1=P.AMP1, 2=P.AMP2
|
Preamp int `json:"preamp"` // 0=off, 1=P.AMP1, 2=P.AMP2
|
||||||
Att int `json:"att"` // dB attenuation, 0=off
|
Att int `json:"att"` // dB attenuation, 0=off
|
||||||
@@ -450,6 +451,7 @@ type IcomController interface {
|
|||||||
SetNR(bool) error
|
SetNR(bool) error
|
||||||
SetNRLevel(int) error
|
SetNRLevel(int) error
|
||||||
SetANF(bool) error
|
SetANF(bool) error
|
||||||
|
SetAPF(bool) error
|
||||||
SetAGC(string) error
|
SetAGC(string) error
|
||||||
SetPreamp(int) error
|
SetPreamp(int) error
|
||||||
SetAtt(int) error
|
SetAtt(int) error
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ const (
|
|||||||
SubSwVOX = 0x46 // VOX on/off
|
SubSwVOX = 0x46 // VOX on/off
|
||||||
SubSwBreakIn = 0x47 // CW break-in: 0=OFF, 1=SEMI, 2=FULL (needed so 0x17 CW keys TX)
|
SubSwBreakIn = 0x47 // CW break-in: 0=OFF, 1=SEMI, 2=FULL (needed so 0x17 CW keys TX)
|
||||||
SubSwMN = 0x48 // manual notch on/off
|
SubSwMN = 0x48 // manual notch on/off
|
||||||
|
SubSwAPF = 0x32 // audio peak filter on/off (CW only)
|
||||||
)
|
)
|
||||||
|
|
||||||
// CW break-in modes (CmdSwitch 0x47).
|
// CW break-in modes (CmdSwitch 0x47).
|
||||||
|
|||||||
@@ -1166,6 +1166,9 @@ func (b *IcomSerial) readDSP() {
|
|||||||
if v, ok := b.readSwitch(civ.SubSwANF); ok {
|
if v, ok := b.readSwitch(civ.SubSwANF); ok {
|
||||||
st.ANF = v != 0
|
st.ANF = v != 0
|
||||||
}
|
}
|
||||||
|
if v, ok := b.readSwitch(civ.SubSwAPF); ok {
|
||||||
|
st.APF = v != 0
|
||||||
|
}
|
||||||
if v, ok := b.readSwitch(civ.SubSwAGC); ok {
|
if v, ok := b.readSwitch(civ.SubSwAGC); ok {
|
||||||
st.AGC = agcName(v)
|
st.AGC = agcName(v)
|
||||||
}
|
}
|
||||||
@@ -1357,6 +1360,14 @@ func (b *IcomSerial) SetANF(on bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *IcomSerial) SetAPF(on bool) error {
|
||||||
|
if err := b.exec(civ.CmdSwitch, civ.SubSwAPF, boolByte(on)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.setCache(func(s *IcomTXState) { s.APF = on })
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (b *IcomSerial) SetAGC(name string) error {
|
func (b *IcomSerial) SetAGC(name string) error {
|
||||||
v := agcValue(name)
|
v := agcValue(name)
|
||||||
if v == 0 {
|
if v == 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user