-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathblog.html
More file actions
2851 lines (2313 loc) · 258 KB
/
Copy pathblog.html
File metadata and controls
2851 lines (2313 loc) · 258 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Blog — AetherSDR</title>
<meta name="description" content="Release notes, engineering deep-dives, and station notes from the AetherSDR project — the native amateur-radio workstation for FlexRadio transceivers." />
<link rel="canonical" href="https://www.aethersdr.com/blog" />
<meta name="theme-color" content="#060b13" />
<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:site_name" content="AetherSDR" />
<meta property="og:url" content="https://www.aethersdr.com/blog" />
<meta property="og:title" content="AetherSDR Blog" />
<meta property="og:description" content="Release notes, engineering deep-dives, and station notes from the AetherSDR project." />
<meta property="og:image" content="https://www.aethersdr.com/assets/img/og-image.jpg" />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="AetherSDR's 3D stacked-trace panadapter and waterfall over the 40m band, with the full control surface." />
<!-- Twitter / X -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="AetherSDR Blog" />
<meta name="twitter:description" content="Release notes, engineering deep-dives, and station notes from the AetherSDR project." />
<meta name="twitter:image" content="https://www.aethersdr.com/assets/img/og-image.jpg" />
<link rel="icon" type="image/png" href="assets/img/logo-96.png" />
<link rel="apple-touch-icon" href="assets/img/apple-touch-icon.png" />
<link rel="stylesheet" href="styles.css?v=15" />
<!-- Without JS there's nothing to route, so show every post stacked under
the index rather than a grid of cards that go nowhere. -->
<noscript>
<style>
.blog-post[hidden] { display: block; }
.blog-back { display: none; }
</style>
</noscript>
</head>
<body>
<!-- ===================== NAV ===================== -->
<header class="nav">
<div class="wrap nav-inner">
<a class="brand" href="index.html">
<img src="assets/img/logo-96.png" alt="AetherSDR logo" />
<span>Aether<b>SDR</b></span>
</a>
<nav class="nav-links">
<a href="index.html#features">Features</a>
<a href="index.html#built">How it's built</a>
<a href="lineage.html">Lineage</a>
<a href="index.html#partners">Partners</a>
<a href="index.html#contribute">Contribute</a>
<a href="index.html#sponsor">Sponsor</a>
<div class="nav-item">
<button class="nav-dd-toggle" type="button" aria-haspopup="true">
Support
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>
</button>
<div class="nav-dd" role="menu">
<a role="menuitem" href="https://lu5dx.github.io/AetherSDRDocsEnglish/latest/" target="_blank" rel="noopener">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"><path d="M4 5a2 2 0 0 1 2-2h9l5 5v11a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2z"/><path d="M8 10h8M8 14h8"/></svg>
User Manual
</a>
<a role="menuitem" href="https://www.youtube.com/@AetherSDR" target="_blank" rel="noopener">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M10 9l5 3-5 3z"/></svg>
Video tutorials
</a>
<a role="menuitem" href="https://discord.gg/gscnyDqHWc" target="_blank" rel="noopener">
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" style="fill:var(--cyan)" aria-hidden="true"><path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.198.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/></svg>
Discord community
</a>
<a role="menuitem" href="https://github.com/aethersdr/AetherSDR/issues/new/choose" target="_blank" rel="noopener">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v3M12 19v3M2 12h3M19 12h3M5 5l2 2M17 17l2 2M19 5l-2 2M7 17l-2 2"/></svg>
File an issue on GitHub
</a>
</div>
</div>
<a href="blog.html" class="nav-keep is-active" aria-current="page">Blog</a>
</nav>
<div class="nav-cta">
<a class="btn btn-primary btn-sm" href="index.html#download">Download</a>
</div>
</div>
</header>
<a id="top"></a>
<main id="blog-main">
<!-- ===================== BLOG INDEX ===================== -->
<!-- Card grid. Each card links to #<slug>, matched to an <article data-post="<slug>">
below by assets/js/blog.js. Add a post = add one card here + one article there. -->
<section class="block blog-index" id="blog-index">
<div class="wrap">
<div class="section-head">
<span class="eyebrow"><span class="dot"></span> From the project</span>
<h2>The AetherSDR blog</h2>
<p>Release notes, engineering deep-dives, and notes from the bench — how the
workstation gets built, and what's landing next.</p>
</div>
<div class="blog-grid">
<!-- PINNED: stays at the top regardless of date. New posts go BELOW
this card, above the newest release post. -->
<a class="blog-card is-pinned" href="#first-contribution">
<div class="blog-card-media">
<!-- Topmost card is above the fold: eager, so it isn't the LCP holdup. -->
<img width="640" height="560" src="assets/img/first-contribution-card.svg" alt="A contribution pipeline drawn as a signal chain — issue, fix, merged — over a spectrum trace" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<span class="blog-pin">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 17v5"/><path d="M9 10.8V4h6v6.8l2.5 3.2h-11z"/></svg>
Pinned
</span>
<span class="sep" aria-hidden="true">·</span>
<time datetime="2026-07-26">July 26, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>8 min read</span>
</span>
<h3>Your first contribution to AetherSDR</h3>
<p>You no longer need to be a C++ programmer to fix something in this
project. You need judgement, a radio, and the patience to check work —
the same things that make a good Elmer. Here's what an AI coding agent
changes about contributing, and what it very deliberately doesn't.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#adaptive-throttle-cq-wpx-cw">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/adaptive-throttle-cq-wpx-cw-card.svg" alt="A cross-needle meter over an AetherSDR spectrum trace, for the CQ WPX CW station-notes post" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-09-17">September 17, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>4 min read</span>
</span>
<h3>Adaptive Throttle held the line at CQ WPX CW — and two more bugs died live, mid-contest</h3>
<p>1,048 QSOs, 4 bands, 73 DXCC entities, over 47 hours 40 minutes, run remote to KB8O on a link that was never fully reliable. Adaptive Throttle kept it from ever tearing down — and two more bugs, in the amp/tuner reconnect path and the PWR/SWR meters, got found and fixed live, mid-contest.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-9-4">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-9-4-card.svg" alt="v26.9.4 release art — the chain, in one window, drawn as an AetherSDR spectrum panel" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-09-20">September 20, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>8 min read</span>
</span>
<h3>v26.9.4: one window per chain, and the meters that passed every test</h3>
<p>AetherRX and AetherTX rebuild the receive and transmit chains into one window each, where the stage list <em>is</em> the chain and you drag it into order. WDSP 2.10 brings Neural Noise Reduction, precipitation goes worldwide — and two meters that agreed perfectly with a test tone turn out to have been badly wrong on speech.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-9-3">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-9-3-card.svg" alt="v26.9.3 release art — the tools, first, drawn as an AetherSDR spectrum panel" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-09-13">September 13, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>6 min read</span>
</span>
<h3>v26.9.3: a Tools menu, and a digipeater that only arms when you say so</h3>
<p>The menu bar is rebuilt around what operators actually reach for, PSK Reporter gains weather radar and night lights, and AetherModem becomes a WIDE1-1 fill-in digipeater — one that will never come back armed on its own.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-9-2">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-9-2-card.svg" alt="v26.9.2 release art — four skimmers, one stream, drawn as an AetherSDR spectrum panel" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-09-06">September 6, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>6 min read</span>
</span>
<h3>v26.9.2: four skimmers on one stream, and two more ways to receive</h3>
<p>One Flex can now feed four CW skimmers through a single TCI server, experimental ANAN-G2 and RTL-SDR reception arrive, the SPE front panel and an LP-100A wattmeter come inside — and the KiwiSDR directory gets a mirror, so browsing receivers stops billing someone else’s volunteers.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-9-1">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-9-1-card.svg" alt="v26.9.1 release art — the map goes round, drawn as an AetherSDR spectrum panel" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-08-29">August 29, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>4 min read</span>
</span>
<h3>v26.9.1: a globe, a rotator, and buttons that tell the truth</h3>
<p>PSK Reporter gains an optional globe projection, Green Heron antenna and rotator control arrives as a native applet, and — quieter but more consequential — the interface stops offering you controls your radio doesn’t actually have.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-8-4">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-8-4-card.svg" alt="v26.8.4 release art — evidence, not assumption, drawn as an AetherSDR spectrum panel" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-08-22">August 22, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>4 min read</span>
</span>
<h3>v26.8.4: capabilities the radio has to prove</h3>
<p>Icom support stops assuming and starts checking. Each model is described by independently attested facets, and a radio nobody has profiled hides unsupported controls rather than borrowing another model’s commands. Plus client-timed CW on the Hermes-Lite 2.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-8-3">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-8-3-card.svg" alt="v26.8.3 release art — the workspace canvas, drawn as an AetherSDR spectrum panel" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-08-16">August 16, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>5 min read</span>
</span>
<h3>v26.8.3: a new shell, and the reason it’s off by default</h3>
<p>Workspace Canvas turns pans and applets into freely placed, layered items that can span several windows, with named workspaces bound to radio profiles. An install that never enables it never even gains a settings key. Plus an ordered command plane for the Icom.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-8-2">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-8-2-card.svg" alt="v26.8.2 release art — two more radios, drawn as an AetherSDR spectrum panel" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-08-09">August 9, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>14 min read</span>
</span>
<h3>v26.8.2: two more radios, and what “experimental” has to mean</h3>
<p>The Hermes-Lite 2 and the Icom IC-705 arrive on the vendor-neutral backend seam, labelled experimental — which here is a request for reports rather than a disclaimer. Plus SPE Expert amplifiers, a noise reducer found to be delivering a fifth of the attenuation it advertised, and a CW keyer measured at 26 WPM with 30 on the dial.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#one-main-branch">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/one-main-branch-card.svg" alt="A play drawn on a chalkboard: a formation runs routes at one line of scrimmage while the dashed flight of the ball arrives at a point marked main" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-08-06">August 6, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>24 min read</span>
</span>
<h3>An army of agents vs one main branch</h3>
<p>An essay on how a project with no human-authored code actually gets built. There's no ceiling on the number of AI agents proposing changes to it — at least one per contributor, and a single run can spawn ninety. What stops that becoming an unreviewable mess isn't better prompting: it's written-down authority, and a gate that doesn't care how confident anyone sounds.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-8-1">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-8-1-card.svg" alt="v26.8.1 release art — settings that survive, drawn as an AetherSDR spectrum panel" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-08-02">August 2, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>10 min read</span>
</span>
<h3>v26.8.1: settings that survive, and a way in when they don’t</h3>
<p>Your settings stop being an XML file and become a database — transactional saves, verified backups, and credentials moved out to your OS keychain. Then the part that matters when it goes wrong: a config editor that runs without the GUI, because the escape hatch can’t depend on the thing it’s rescuing.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-7-4">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-7-4-card.svg" alt="v26.7.4 release art — speech to text, drawn as an AetherSDR spectrum panel" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-07-26">July 26, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>10 min read</span>
</span>
<h3>v26.7.4: Copy Assist, and the eight milliseconds that ate half the audio</h3>
<p>AetherSDR now transcribes received voice on your own machine — whisper.cpp under the waterfall, confidence colour-coding, no audio leaving the computer unless you send it. Then the deep end: why it sounded broken with NR2 engaged, and how a repaint optimisation was quietly discarding half the speech.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-7-3">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-7-3-card.svg" alt="v26.7.3 release art — meters you can trust, drawn as an AetherSDR spectrum panel" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-07-19">July 19, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>5 min read</span>
</span>
<h3>v26.7.3: the cross-needle returns</h3>
<p>A cross-needle PWR/SWR applet brings the classic forward-power, reflected-power, and SWR view into AetherSDR — the meter where the reading is the crossing point. The analog S-meter gains configurable face themes, and the SWR response and scale maths got more accurate underneath.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-7-2">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-7-2-card.svg" alt="v26.7.2 release art — digital voice, drawn as an AetherSDR spectrum panel" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-07-12">July 12, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>7 min read</span>
</span>
<h3>v26.7.2: D-STAR, locally, with a dongle</h3>
<p>Complete local D-STAR through a connected ThumbDV hardware vocoder — receive and transmit digital voice, headers, callsigns, repeater routing, and 20-character messages. Software AMBE is deliberately not included, and the reason is worth explaining. Plus an MCP server and Blackwell GPU support for BNR.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-7-1">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-7-1-card.svg" alt="v26.7.1 release art — the band, over time, drawn as an AetherSDR spectrum panel" loading="lazy" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-07-02">July 2, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>7 min read</span>
</span>
<h3>v26.7.1: the spectrum stands up</h3>
<p>A 2D/3D toggle turns the panadapter into a perspective stacked-trace surface — a rolling history of FFT traces receding into the distance, so you can watch a band's activity build rather than only seeing the live sweep. Ridge height is anchored to the measured noise floor, and the whole path runs at 60 fps.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-6-5">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-6-5-card.svg" alt="v26.6.5 release art — diversity across geography, drawn as an AetherSDR spectrum panel" loading="lazy" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-06-28">June 28, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>6 min read</span>
</span>
<h3>v26.6.5: aligning a Flex with a receiver a thousand miles away</h3>
<p>KiwiSDR receive sync uses GCC-PHAT correlation to time-align your Flex with a public Kiwi in both audio and the waterfall, so a diversity pair separated by a continent stays phase-coherent. Plus SmartMTR transmit meters and a profile-switcher applet.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-6-4">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-6-4-card.svg" alt="v26.6.4 release art — receivers worldwide, drawn as an AetherSDR spectrum panel" loading="lazy" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-06-23">June 23, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>6 min read</span>
</span>
<h3>v26.6.4: listening from somewhere else</h3>
<p>A KiwiSDR public-receiver browser lands — find and connect to public receivers worldwide, entirely independent of the FlexRadio path. It's deliberately policy-aware rather than pretending the world's volunteer-run receivers are a free API, and it physically cannot transmit.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-6-3">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-6-3-card.svg" alt="v26.6.3 release art — satellite data, drawn as an AetherSDR spectrum panel" loading="lazy" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-06-14">June 14, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>6 min read</span>
</span>
<h3>v26.6.3: WFM, and 9600-baud satellite work</h3>
<p>A per-slice WFM demodulator built specifically for G3RUH 9600-baud satellite telemetry — DAX IQ through Doppler correction, exact resampling, and a flat discriminator into a virtual audio cable. Plus an APRS client and a PSK Reporter map on a new reusable mapping engine.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-6-2">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-6-2-card.svg" alt="v26.6.2 release art — a complete packet station, drawn as an AetherSDR spectrum panel" loading="lazy" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-06-08">June 8, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>7 min read</span>
</span>
<h3>v26.6.2: your radio is now the TNC</h3>
<p>AetherModem grows from a decoder into a full packet station — a KISS-over-TCP TNC server for any host app, a connected-mode AX.25 terminal that calls a real BBS, and a personal mailbox that answers. All over the built-in 1200-baud AFSK modem, with no external TNC hardware anywhere in the chain.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-6-1">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-6-1-card.svg" alt="v26.6.1 release art — hands on the radio, drawn as an AetherSDR spectrum panel" loading="lazy" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-06-01">June 1, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>6 min read</span>
</span>
<h3>v26.6.1: knobs, dials, and physical controls</h3>
<p>Three new classes of physical controller land — the Elgato Stream Deck+, the Ulanzi Dial, and native Icom RC-28 support — all opt-in by design so macOS never prompts for Input Monitoring unless you actually enable one. Plus a seven-year-old noise-reduction crackle finally traced to a Bessel function.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-5-3">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-5-3-card.svg" alt="v26.5.3 release art — aetherial tx complete, drawn as an AetherSDR spectrum panel" loading="lazy" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-05-24">May 24, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>7 min read</span>
</span>
<h3>v26.5.3: the de-esser that was costing you 30 watts</h3>
<p>The Aetherial transmit path reaches feature-complete with a PAPR processor and a split-band de-esser. The de-esser rewrite is the interesting one: the old broadband implementation was quietly pulling roughly 30 W of forward power out of voice content, and the fix is a single change in how the gain is applied.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-5-2-1">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-5-2-1-card.svg" alt="v26.5.2.1 release art — aethermodem, phase 0, drawn as an AetherSDR spectrum panel" loading="lazy" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-05-17">May 17, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>6 min read</span>
</span>
<h3>v26.5.2.1: a packet decoder of our own</h3>
<p>AetherModem lands as a native HDLC/AX.25 receiver — a 21-lane phase bank, FCS validation, and a dedicated Packet Decode dialog, with RX live on 300-baud HF and 1200-baud VHF. Also the story of why this release has a fourth version digit, which turns out to be about one string in a device-identity handshake.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
<a class="blog-card" href="#release-26-5-1">
<div class="blog-card-media">
<img width="640" height="560" src="assets/img/release-26-5-1-card.svg" alt="v26.5.1 release art — the 1.0 release, drawn as an AetherSDR spectrum panel" loading="lazy" />
</div>
<div class="blog-card-body">
<span class="blog-meta">
<time datetime="2026-05-10">May 10, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>6 min read</span>
</span>
<h3>v26.5.1: dropping the pre-1.0 framing</h3>
<p>After eight 0.9.x cycles the version number had stopped telling the truth. v26.5.1 is the 1.0-equivalent release — full SmartSDR feature coverage, the Aetherial strip complete on both paths, and native builds on three platforms. It also switches the project to CalVer, for a reason worth explaining.</p>
<span class="blog-more">Read post
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14m0 0-5-5m5 5-5 5"/></svg>
</span>
</div>
</a>
</div>
</div>
</section>
<!-- ===================== POSTS ===================== -->
<!-- Each article is hidden until its slug is routed to. Keep data-post in sync
with the card href above. Body copy uses .blog-body for prose styling. -->
<article class="blog-post" data-post="first-contribution" tabindex="-1" aria-labelledby="h-first-contribution" hidden>
<div class="wrap blog-post-wrap">
<a class="blog-back" href="#" data-blog-back>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5m0 0 5-5m-5 5 5 5"/></svg>
Back to blog
</a>
<figure class="blog-hero">
<img width="1200" height="630" src="assets/img/first-contribution-hero.svg" alt="The contribution pipeline drawn as an AetherSDR signal chain: issue, claim, fix, evidence, merged — over a spectrum trace and waterfall" />
</figure>
<span class="blog-meta">
<time datetime="2026-07-26">July 26, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>8 min read</span>
</span>
<h1 id="h-first-contribution">Your first contribution to AetherSDR</h1>
<div class="blog-body">
<p class="lede">You no longer need to be a C++ programmer to fix something
in this project. You need judgement, a radio, and the patience to check
work — the same things that make a good Elmer.</p>
<p>Every open-source project says it welcomes newcomers. Most then hand you
a wall of build instructions, a toolchain that fights you for a weekend,
and a code review that assumes you already know what a rebase is. The
welcome is sincere; the on-ramp is still a cliff.</p>
<p>That cliff is what actually changed. Not the code — the on-ramp. We've
published a <a href="https://github.com/aethersdr/AetherSDR/blob/main/docs/first-contribution-cheatsheet.md" target="_blank" rel="noopener">first-contribution cheat sheet</a>
that takes you from "I've never used GitHub" to a merged pull request, and
the striking thing about it is that you never type a command. Every step is
a sentence you say, in English, to an AI coding agent working inside your
editor.</p>
<h2>You're the control operator</h2>
<p>Here's the part worth being clear about, because it's where the whole
thing succeeds or fails: the agent does the typing, not the deciding.</p>
<p>It will install dependencies, find the bug, write the fix, and draft the
pull request. It will also sound completely confident while being wrong.
That is not a flaw you can prompt your way out of — it's the nature of the
tool, and it's exactly why the human in the chair still matters. Your job
is to read what it proposes before you say yes.</p>
<p>If you've ever supervised a Technician on your license, the arrangement
will feel familiar. Someone else is on the mic. You're still responsible
for what goes out. The cheat sheet states it as four rules, and the third
one — <em>it sounds confident even when wrong</em> — is the one to
internalize.</p>
<p>So the skill that makes you useful here isn't C++. It's knowing what
AetherSDR is supposed to do when you key up, and noticing when it doesn't.
That's operator knowledge, and no amount of model capability substitutes
for it.</p>
<h2>What it costs to start</h2>
<p>Three things: a free editor, a GitHub account, and one AI coding agent.
The cheat sheet walks through Copilot, Codex, and Claude Code side by side,
including which tiers can actually drive your editor and which are chat
only — a distinction worth checking before you pay for anything. There is
a genuinely free path. Limits shift often enough that the cheat sheet links
to the live pricing pages rather than quoting numbers that go stale.</p>
<p>The GitHub account is the one step nothing can do for you. Pick your
callsign as the username — it's public, and it's the handle the rest of us
will know you by.</p>
<h2>Finding a first job</h2>
<p>Issues tagged <a href="https://github.com/aethersdr/AetherSDR/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22" target="_blank" rel="noopener">good first issue</a>
are the front door. Ask your agent to read the open ones and explain the
top few in plain English, then to recommend one — it's surprisingly good at
judging which bugs are self-contained.</p>
<p>Then claim it before you start. Claiming means adding yourself to the
issue's assignees, not leaving a comment saying you'll take it. Our triage
bot is auto-assigned to everything, so an issue showing only the bot is
free. This is the one piece of etiquette that matters on day one: it's what
stops two people quietly fixing the same bug on a Saturday afternoon.</p>
<h2>Bring evidence, not vibes</h2>
<p>"Works on my machine" is not evidence, and this is where a first PR
usually either lands or stalls.</p>
<p>AetherSDR ships an agent automation bridge — a switch you flip at launch
that lets your agent drive the running application directly: read the state
of any control, move sliders, click buttons, capture the panadapter. So
instead of asserting the bug is fixed, your agent can walk the issue's
exact reproduction steps through the app and show the control values before
and after.</p>
<p>It's the difference between eyeballing the S-meter and putting the radio
on a service monitor. Reviewers here look for that trace, and a first pull
request that arrives with one moves noticeably faster than one that says
"works for me."</p>
<p>Two ground rules the cheat sheet is firm about, both of which protect your
station rather than the codebase: check the radio isn't already in use
before launching a test run, because two clients fighting over one radio
produce evidence that is simply wrong. And ask for receive-only testing.
The bridge refuses to transmit unless you explicitly enable it — leave it
that way for your first run.</p>
<h2>When it goes wrong</h2>
<p>It will. A build will fail, a check will go red, GitHub will call your
commit "Unverified" for reasons that make sense to roughly nobody the first
time.</p>
<p>The entire troubleshooting procedure is: copy whatever you see, paste it
to your agent, and add <em>"This happened. What does it mean and what
should we do?"</em> That sentence resolves the overwhelming majority of
first-timer problems, because the errors are well-known ones and the agent
has seen them all.</p>
<h2>Why we bother</h2>
<p>Ham radio has always run on people explaining things to each other —
someone signed your license test, someone talked you through your first
HF contact, someone told you your audio was too wide. That tradition is
the reason this project is worth contributing to at all.</p>
<p>The tooling now handles the part that used to gate people out: the syntax,
the build system, the git incantations. What it can't supply is someone who
knows what a properly-behaving panadapter looks like at 3 AM during a
contest. That's you.</p>
<p><a href="https://github.com/aethersdr/AetherSDR/blob/main/docs/first-contribution-cheatsheet.md" target="_blank" rel="noopener">Read the cheat sheet</a>,
pick an issue, and open the pull request. If you get stuck at any point,
<a href="https://github.com/aethersdr/AetherSDR/discussions" target="_blank" rel="noopener">start a discussion</a> —
asking early is not an imposition here, it's the tradition. 73.</p>
</div>
<a class="blog-back blog-back-end" href="#" data-blog-back>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5m0 0 5-5m-5 5 5 5"/></svg>
Back to blog
</a>
</div>
</article>
<article class="blog-post" data-post="adaptive-throttle-cq-wpx-cw" tabindex="-1" aria-labelledby="h-adaptive-throttle-cq-wpx-cw" hidden>
<div class="wrap blog-post-wrap">
<a class="blog-back" href="#" data-blog-back>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5m0 0 5-5m-5 5 5 5"/></svg>
Back to blog
</a>
<figure class="blog-hero">
<img width="1200" height="630" src="assets/img/adaptive-throttle-cq-wpx-cw-hero.svg" alt="A cross-needle meter reading steady under load, over an AetherSDR spectrum trace — CQ WPX CW, 1,048 QSOs" />
</figure>
<span class="blog-meta">
<time datetime="2026-09-17">September 17, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>4 min read</span>
<span class="sep" aria-hidden="true">·</span>
<span>@chibondking (CJ, WT2P) operating the NW8S (KB8O) FlexRadio station remotely</span>
</span>
<h1 id="h-adaptive-throttle-cq-wpx-cw">Adaptive Throttle held the line at CQ WPX CW — and two more bugs died live, mid-contest</h1>
<div class="blog-body">
<p class="lede">CQ WPX CW this year was 1,048 QSOs, 4 bands, 73 DXCC entities, over 47 hours 40 minutes — run entirely on a FlexRadio in KB8O's shack in Ohio, from my desk in Illinois, over a link that was variable in its reliability (VPN, etc.). This is the post about why it held anyway, and about two bugs that only showed themselves under real contest load and got fixed while the clock was still running.</p>
<h2>At a glance</h2>
<ul>
<li><strong>QSOs:</strong> 1,048 (435 on 40m, 494 on 20m, 109 on 15m, 10 on 10m)</li>
<li><strong>Avg rate:</strong> 22/h</li>
<li><strong>Best hour:</strong> 95 Q</li>
<li><strong>Best 10 min:</strong> 25 Q (~150/h)</li>
<li><strong>DXCC / zones:</strong> 73 / 24</li>
<li><strong>Longest gap:</strong> 10h 43m</li>
</ul>
<h2>The link isn't the problem. Panic over the link is.</h2>
<p>Adaptive Throttle (#2829) didn't come out of this contest — it came out of getting fed up with AetherSDR bailing on a merely-congested link like it was a dead one. Before the fix, 5 missed pings (about 5 seconds) was enough to declare the connection gone, tear down every panadapter, and force a full state rebuild. SmartSDR doesn't do this; it leans on the link by dropping frame rate first. So that's what AT does: as the measured network-quality score steps down through Good → Fair → Poor, every owned panadapter (not just the active one) gets told to cut its FFT/waterfall rate — 15fps/150ms → 8fps/250ms → 4fps/500ms — before pings ever start failing. Once you're actually in Poor, the disconnect threshold itself extends from 5 missed pings to 15, on the theory that the throttle has already bought the link some room to recover. Lift the throttle and each panadapter's own configured fps/waterfall setting gets pushed back to the radio — nothing generic, no guessing at what it "should" be.</p>
<p>I proved this on a 0300 CWT sprint before WPX, running remote to KB8O over a genuinely marginal link — an hour of Good/15fps with one clean dip to Poor/4fps and a clean recovery, no disconnects. WPX was the real test. I don't have a screenshot with a timestamp on it — I was a little busy — but I watched the link step down to 8fps multiple times over the weekend, and at no point did I lose a panadapter or get kicked back to a rebuild. That's the whole point of the feature: it should be boring.</p>
<h2>Two bugs that only exist when you actually contest</h2>
<p>Adaptive Throttle covers the radio link. It has nothing to do with the amp, the tuner, or the antenna switch — and WPX is exactly the kind of run that finds the gaps between those systems.</p>
<p><strong>PGXL/TGXL/Antenna Genius would drop and just stay dropped.</strong> SmartSDR's own utilities for these devices reconnect on their own when a TCP hiccup happens over a remote link. AetherSDR's direct connections to them didn't — a drop meant a blank applet and a manual reconnect, every time, in the middle of a run. #3321 gives each of those connections a 5-second retry loop with a guard so it doesn't fight you if you disconnect on purpose, plus a fix for the case where the retry itself fails before the device comes back (Qt reports that as a different signal than a clean disconnect, and the first version of this patch didn't re-arm the timer for it — so it would try once and give up).</p>
<p><strong>The PWR/SWR meters were technically live and practically useless.</strong> During a run they updated so fast the numbers were just noise — you couldn't actually read what the amp was doing between calls. #3277 gives the forward-power gauge slow-release ballistics (30ms attack, 800ms release) so a brief TX burst stays visible instead of flickering past, and throttles the numeric labels to update at 10Hz while the gauge fill still animates at full rate. Small fix, but it's the difference between a meter you glance at and one you have to stare at.</p>
<p>Both of these got found and fixed inside the contest window, not after it. Pattern was the same each time: notice it live, describe the bug to Claude, have it build a local Windows executable, run that build in place at the operating position, confirm the fix actually holds — then push the PR once the contest itself wasn't the thing depending on it.</p>
<h2>Where that leaves it</h2>
<p>Adaptive Throttle got tested twice — once on purpose, once for real — and then just became part of the app. I've run it daily on every remote session from May through now, September, with no reason to touch it. The peripheral reconnect and metering fixes have been running solid for months too — not patches that happened to hold over one weekend, but mature parts of the app at this point. All three came out of the same loop: notice a real failure under real load, fix it, prove it, ship it.</p>
</div>
<a class="blog-back blog-back-end" href="#" data-blog-back>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5m0 0 5-5m-5 5 5 5"/></svg>
Back to blog
</a>
</div>
</article>
<article class="blog-post" data-post="release-26-9-4" tabindex="-1" aria-labelledby="h-release-26-9-4" hidden>
<div class="wrap blog-post-wrap">
<a class="blog-back" href="#" data-blog-back>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5m0 0 5-5m-5 5 5 5"/></svg>
Back to blog
</a>
<figure class="blog-hero">
<img width="1200" height="630" src="assets/img/release-26-9-4-hero.svg" alt="v26.9.4 release art — the chain, in one window, drawn as an AetherSDR spectrum panel" />
</figure>
<span class="blog-meta">
<time datetime="2026-09-20">September 20, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>8 min read</span>
</span>
<h1 id="h-release-26-9-4">v26.9.4: one window per chain, and the meters that passed every test</h1>
<div class="blog-body">
<p class="lede">Ninety-seven merged changes. The receive and transmit chains are rebuilt into one window each, WDSP 2.10 arrives with Neural Noise Reduction behind it, and precipitation goes worldwide. Running underneath is a quieter theme: several meters in this release were reading confidently wrong, and the reason none of them was caught earlier is that they all agree with a steady test tone.</p>
<h2>One window per chain</h2>
<p><strong>AetherRX</strong> puts the whole receive chain in a single window, and every page in it reads the same way: switches along the top, the display beneath them, every knob in one row at the foot. Once you have learned one stage you have learned the shape of all of them.</p>
<p>The tab column down the left side is not a navigation aid — it <em>is</em> the chain. Each row carries an enable checkbox and a grip, and dragging a row rewrites the order the audio actually passes through. Stages are renamed to Gate, Compressor, Exciter and Final Output, and the old spellings still resolve, so nothing you saved stops opening.</p>
<p>Settings gains a profile library — save, load, import, export — that captures every stage’s parameters, its enablement, the chain order and the active NR method as one nested document. And the EQ page now draws the receive filter edges against the mode’s own width ladder; drag an edge and the slice retunes.</p>
<p><strong>AetherTX</strong> is the same shape for the transmit side — Gate, EQ, De-esser, Compressor, Tube, Exciter, Reverb, Final Output — with the stage column, the page frame and the profile machinery <em>shared</em> with AetherRX rather than copied into it. That is the part that decides whether these two windows still behave identically in a year.</p>
<p>A few things moved while the walls were down. BYPASS, Record and Play went into the Settings dialog’s Chain section. RN2 moved to the gate toolbar, which is where it actually acts. The compressor makeup became a focusable, keyboard-driven control that announces itself through accessibility. Channel-strip presets are retired — each saved one is split, once, into its transmit and receive halves the first time you open it. Panels stopped polling the engine while invisible, a tube attack knob that changed nothing at all is gone, and a stored chain that names a retired stage now keeps the rest of your order instead of resetting it.</p>
<h2>The meters that passed every test</h2>
<p>Two measurement bugs in this release share a root cause, and it is worth sitting with, because it is the kind of thing that survives a careful test plan.</p>
<p>The first: on both raw-IQ backends, the S-meter was reading WDSP’s decaying peak-hold rather than its average. On a steady carrier those two numbers agree <em>exactly</em> — which is why every test-tone check passed, for as long as anyone has been running them, while the band noise floor was reading 11 to 14 dB high.</p>
<p>The second: the TGXL was metered from <code>fwd</code>, which sampled the gaps between syllables. Voice at 60 W was reading about 10 W. It now meters from the device’s own <code>peak</code>, and both peripherals are polled at about 60 Hz while transmitting and 4 Hz while receiving.</p>
<p>A steady tone is the one signal that hides both faults. It has no gaps between syllables and no difference between its peak and its average, so it confirms a meter that cannot measure speech. Every test involved was passing and the instrument was still lying to the operator — which is the argument for testing with the thing you actually transmit.</p>
<p>In the same family: the HL2 S-meter no longer publishes the silence clocked in while transmit-muted, so the needle neither dives on key-down nor on unkey, and ADC RMS is measured about the mean, so converter DC can’t deflate the crest factor that distinguishes broadband noise from a carrier.</p>
<h2>WDSP 2.10, and a seventh way to fight noise</h2>
<p><strong>Neural Noise Reduction</strong> joins as the seventh client-side NR method, with its full ten-control surface and pinned default markers. It builds without DeepFilterNet, managed Kiwi sources are no longer silent under it, the selection survives a restart, and the stereo adapter is now told the real 192 ms end-to-end latency on the 24 kHz path with the default strength corrected to match WDSP.</p>
<p>It comes in with <strong>WDSP 2.10</strong>, which fixes an upstream use-after-free on the channel-open path. The refresh costs about 8.8 MB of resident memory per RX channel, because 2.10 instantiates NNR whether or not you use it. That number is in the release notes because it was measured and then judged acceptable, which is the only honest way to spend someone else’s memory.</p>
<p>NR2 also gains WDSP’s psychoacoustic post-processing — the residual-and-noise blend that fills the dead gaps between syllables, and which our port of <code>emnr.c</code> turned out never to have had. It ships off, exactly as upstream does. Alongside it, the minimum-phase FIR workspace — four <code>FFTW_PATIENT</code> plans per instance, 72 of them built and thrown away on a single channel open — is now built only when minimum phase is actually on.</p>
<h2>Modes the radio cannot transmit, declared</h2>
<p>The Hermes-Lite 2 took the largest share of this release, and one item in it is a genuine on-air fix rather than a convenience.</p>
<p>AM, SAM, DSB, FM, NFM, WBFM and DRM were all taking the upper-sideband branch of a phasing SSB modulator. Selecting AM and keying up did not produce AM — it put suppressed-carrier SSB on the air. Keying and TUNE now refuse in those modes, and the backend also publishes the modes it genuinely demodulates, so RTTY, DFM and DSTR stop silently falling back to USB.</p>
<p>The transmit level stack got the same treatment. The ALC now only ever reduces, and the Mic Level slider becomes the operator’s transmit level; the loop it replaces was applying up to 40 dB of upward makeup gain, lifting the room noise between your words along with your voice. Engine-generated audio keeps the level its generator chose, and the host-modulated WSPR beacon defaults to −3 dBFS instead of going out 18.6 dB down.</p>
<p>A <strong>WDSP TXA modulator</strong> is now the default, and the way it got there is worth recording: <code>CMakeLists.txt</code> carried the condition for flipping the flag, and the condition was an on-air test. ON8ST keyed it into a dummy load and then onto an antenna on 17 September, and that is what moved it. The in-tree phasing modulator remains one flag away, and its opposite-sideband suppression is now measured across the passband rather than asserted — 22 dB at 150 Hz on the DIGU/DIGL band, exactly the derived figure.</p>
<p>Also on the HL2: the dBm reference is derived rather than guessed — full scale is +3 dBm at the antenna at 0 dB LNA gain, from the AD9866 datasheet plus the input transformer and filter-board loss. The wideband bandscope is decoded and accounted for behind a duty-cycle gate that is off by default. Automatic RF gain drives on measured wideband headroom instead of the clip counter, and ships off until the +20 dB LNA default can be reconciled with the arming baseline — with a declined arm now explaining itself in the checkbox, on a card and through the accessible channel, because on a fresh install that refusal was the first thing a new operator met. And a zoom no longer silences the radio: pan-bandwidth chains are built on their own thread and installed in one turn, instead of rebuilding inline where EP2 pacing starves and the gateware watchdog halts the stream.</p>
<h2>Weather, worldwide</h2>
<p>The precipitation overlay that arrived for North America last release goes global. An opt-in <strong>LibreWXR</strong> layer carries worldwide precipitation, with independently selectable NOAA, ECCC and EUMETNET OPERA regional feeds behind it, an optional per-provider intensity legend, and default-off coverage shading drawn from 389 bundled sites. If you already had the weather overlay on, LibreWXR becomes your primary and NOAA stays selectable on its own.</p>
<h2>Also in this release</h2>
<p><strong>Copy Assist stops taking the app down.</strong> A GPU without room for the model now fails the load and retries on CPU instead of dereferencing null inside vendored whisper.cpp, the default tier reads free GPU memory before reaching for <code>large-v3-turbo</code>, a fault in device discovery or model load leaves flushed stage records in the log, and a model running slower than real time drops audio at a bounded backlog and tells you how many seconds it dropped rather than queueing forever.</p>
<p><strong>CW.</strong> An optional <strong>DeepFist</strong> receive backend lands behind a build flag that is off by default, with no model weights shipped; ggmorse remains the default and the sidetone decoder, and DeepFist invents no confidence, pitch or speed and does not feed callsign spotting. Separately, decoder parameter changes no longer race the decoding worker.</p>
<p><strong>Panadapter and GPU.</strong> Extended TNF mirrors a tracking notch through the waterfall, the FFT average slider reaches the model on raw-spectrum backends so it survives a pan rebuild, ANAN crops its true panadapter edge instead of fading it and regains its noise-floor auto-adjust, and selecting the discrete GPU on a hybrid-graphics laptop under Wayland works now that a GLX-only environment variable stops vetoing the saved choice.</p>
<p><strong>Amplifiers and tuners.</strong> The TGXL and PGXL gain front-panel presentations that lay out like the devices’ own panels — TUNE becomes STOP while a tune runs, the tuner’s alert channel shows as a banner, and the PGXL gains a drive meter from a <code>DRV</code> reading the radio had been relaying all along. The SPE LCD mirror stops blinking.</p>
<p><strong>Writes that stop lying.</strong> QSO recordings claim their filename with exclusive creation and never truncate an existing WAV; an incomplete write is reported and the recorder stops safely rather than advertising a broken file; recording is rate-aware. DVK uploads don’t queue duplicate bytes on partial socket drains, and a failed export preserves the existing file. The PMS mailbox writes atomically and says <code>SAVED</code> only when it did. And a healthy settings database is never quarantined over a permissions error — recovery now demands actual corruption evidence, and an unwritable store is detected at open rather than at your first save.</p>
<p><strong>Controls that explain themselves.</strong> A three-state doctrine — unavailable, inactive, active — and an availability registry mean an unsupported control stays visible, disabled, and carries the reason it is disabled. Nine Radio Setup surfaces now dim with reasons. It is the same thread as the greyed-out buttons two releases ago, with the missing half added: not just that a control can’t work, but why.</p>
<p><strong>Elsewhere.</strong> A Flex TCP disconnect mid-status-line no longer leaves a parser buffer for the next session to fabricate a response from; concurrent Icom Keychain reads coalesce, so a saved startup route raises one authorization prompt instead of three; ANAN-G2 ships DDC0 droop-correction defaults derived from the Saturn gateware, so an unswept radio gets a corrected FFT on first connect. The Windows CW sidetone defaults back to <code>QAudioSink</code>, and the PortAudio heap corruption behind the Windows connect crash — an upstream bug that frees a stack address while enumerating DAX endpoints — is patched at build time. And the headless engine gains credential-bound transmit grants behind an explicit <code>--allow-local-tx</code> and a vault authority that fails closed, with software PTT handoff hardware-tested on a FLEX-6700; startup stays disarmed.</p>
<p>97 merged changes from 13 contributors, AetherClaude and two Dependabot updates. Full release notes and the complete commit list: <a href="https://github.com/aethersdr/AetherSDR/releases/tag/v26.9.4">v26.9.4 on GitHub</a>.</p>
</div>
<a class="blog-back blog-back-end" href="#" data-blog-back>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5m0 0 5-5m-5 5 5 5"/></svg>
Back to blog
</a>
</div>
</article>
<article class="blog-post" data-post="release-26-9-3" tabindex="-1" aria-labelledby="h-release-26-9-3" hidden>
<div class="wrap blog-post-wrap">
<a class="blog-back" href="#" data-blog-back>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5m0 0 5-5m-5 5 5 5"/></svg>
Back to blog
</a>
<figure class="blog-hero">
<img width="1200" height="630" src="assets/img/release-26-9-3-hero.svg" alt="v26.9.3 release art — the tools, first, drawn as an AetherSDR spectrum panel" />
</figure>
<span class="blog-meta">
<time datetime="2026-09-13">September 13, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>6 min read</span>
</span>
<h1 id="h-release-26-9-3">v26.9.3: a Tools menu, and a digipeater that only arms when you say so</h1>
<div class="blog-body">
<p class="lede">Eighty-six merged changes, and the operator-facing half of them starts at the very top of the window: the menu bar is now organised around what you reach for while operating, rather than around where things happened to get built.</p>
<h2>Where things are</h2>
<p>The top level is now <strong>File · Settings · Profiles · Tools · View · Help</strong>. The operating tools that had scattered themselves across File, Settings, View and Help — PSK Reporter, Memory, Waveforms, Radio Health, the modem and KiwiSDR setup, the guarded tuner operations — collect under <strong>Tools</strong>, which sits ahead of <strong>View</strong> because you reach for them more often than you reach for display settings.</p>
<p>Nothing underneath changed: the same actions, the same handlers, the same shortcuts and lifecycle behaviour. What changed is where things are found, and that is worth a section of its own, because a menu bar is the map of an application and it is the one you read under time pressure — mid-contest, mid-QSO, with the band open and closing.</p>
<p>Radio-sensitive entries now start disabled and track connection and capability changes, which is the same thread that ran through the last release: the interface describes <em>your</em> radio, not the one we developed against. Entries that will key the transmitter — <code>Start SWR Scan…</code> and <code>Pre-tune ATU Bands…</code> — are marked as TX-keying, so you know that before you click rather than after. And Radio Setup keeps its Qt Preferences role, so macOS still files it where a Mac user expects to find it.</p>
<p>One removal is worth naming. Settings carried a placeholder loop that reported “not yet implemented” for actions that in fact worked perfectly well. That is the mirror image of the failure we wrote about last release — not a control that lies about succeeding, but one that lies about failing. It is the cheaper of the two mistakes, and it still sends an operator off looking for a workaround to a problem they didn’t have.</p>
<p>While the menu was open: <strong>View</strong> gains <strong>VFO Marker Size</strong> (Off, 1 px, 3 px) and <strong>VFO Filter Edge</strong> (Show, Hide) as global defaults, stored atomically as a single document. Changing either updates live VFOs without trampling per-slice overrides, and a missing or malformed value falls back to the historical 3 px marker with visible filter edges.</p>
<h2>Weather on the map, and the night side of the earth</h2>
<p>PSK Reporter maps gain two overlays that answer questions the spot data alone can’t. <strong>NOAA weather radar</strong>, with playback over recent frames, puts the storms that are making your noise where you can see them. <strong>NASA city lights</strong> adds a night-lights basemap — the darkness on that layer is the part of the world your signal is most likely to be getting through to.</p>
<p>Alongside them: a dark map style with brightness controls, map controls moved into a left sidebar instead of competing with the map itself, and NASA and NWS tile requests that retry on transient failure rather than leaving you with a blank layer and no explanation. On macOS, the GPU spectrum path no longer takes the map down with it — the map stays on a raster viewport.</p>
<h2>A digipeater you have to arm</h2>
<p>AetherModem gains an <strong>APRS WIDE1-1 fill-in digipeater</strong>. It substitutes MYCALL with the H bit set on the first matching unused hop, and it requires three things before it will do anything at all: the shared 1200-baud profile, a valid callsign, and explicit arming for this session.</p>
<p>That last requirement is the design decision, and it is deliberate that arming is <em>never</em> restored from settings. A fill-in digi is a courtesy to a shared channel when someone is sitting there, and a liability when nobody is. A station that comes back up armed after a reboot — after a power cut, after an update, at three in the morning — is transmitting on behalf of an operator who isn’t present. Making you arm it every session costs one click and removes that entire category of problem.</p>
<p>Wide-area WIDEn-N hop decrementing is not included, and that is also on purpose. Fill-in is the role a home station can fill responsibly; being a wide-area digi is a different commitment.</p>
<h2>Time on the waterfall</h2>
<p>The waterfall can now draw <strong>clock-aligned time markers</strong> — thin UTC-labelled lines at Off, 15 s, 30 s, 1, 5, 10 or 15 minute intervals, aligned to real clock boundaries rather than to whenever you happened to start the application. Off stays the default and the choice persists per panadapter slot.</p>
<p>The detail that makes them usable is that each marker is pinned to the rows it was captured against, and stays pinned through scrolling, pause and resize. A time label that drifts relative to the history it is labelling is worse than no label, because you will believe it.</p>
<p>In the same area, the <strong>Runtime Monitor Overview</strong> adds CPU Total, Max Thread, resident memory and GUI Tick Lag cards over 1 min, 5 min, 15 min and 1 h ranges, with charts for CPU, memory, the top five threads and tick lag — and one timeframe selector now shared across the Runtime Monitor tabs.</p>
<h2>Also in this release</h2>
<p><strong>Receivers.</strong> The <strong>Web-888</strong> joins the KiwiSDR receive path as its own receiver family: saved receivers keep their family across restarts, legacy entries default to KiwiSDR, and CSV import accepts an optional <code>RECEIVER_TYPE</code> field. The ANAN-G2 gains live DDC rate changes — a zoom notch no longer rebuilds the entire Protocol 2 session — plus multi-DDC encoding on the wire and DDC0 edge-droop compensation from an in-app calibration. RTL-SDR gains a bounded receiver lifecycle foundation.</p>
<p><strong>Digital modes.</strong> HF 300 decoding is corrected — the correlator lowpass was narrower than the tone shift — and back-to-back HDLC frames are handled. WSJT-X UDP spots land on the reporting instance’s band rather than another instance’s, a FreeDV Reporter double-click tunes and forces RADE, and the D-STAR tab hides itself on radios without waveform support.</p>
<p><strong>Receive DSP.</strong> NR2 keeps its noise estimate across the TX→RX edge instead of re-converging after every transmission, and the GPU FFT trace reports an honest width rather than a flattering one.</p>
<p><strong>Hermes-Lite 2.</strong> Stream-free telemetry reads the radio’s own telemetry when the IQ stream can’t supply it, TX:ALCGAIN publishes the gain the ALC is actually applying, and an RQST/ACK state machine keeps one request outstanding, echo-matched and quarantined. The SWR detector is linearized and its noise gate re-derived, the AGC ceiling is referred to the dB reference, and two stale documentation claims were corrected rather than left standing.</p>
<p><strong>CW, ATU and transmit.</strong> Break-in delay holds against the radio’s QSK-floor walk when the speed changes, CW keying and TUNE interlock in both directions, ATU tune failures appear in the status bar, a disabled Pre-tune explains why it is disabled, and the PortAudio CW sidetone sink compiles on Windows.</p>
<p><strong>Flex and Icom.</strong> Panadapter and slice capacity come from the radio rather than from a compiled-in assumption, manual squelch reconciles correctly after a band recall, Icom retains squelch intent and waterfall speed across restarts, and a refused tune no longer reads as a successful one.</p>
<p><strong>Under the surface.</strong> The <code>IRadioBackend</code> threading and lifetime contract is now pinned by tests, ordinary RX slice lifecycle routes through the backend seam, and backends announce capability revisions with the capability surface frozen in CI. The headless engine gains capability-qualified local receive controls — mode, filter, audio gain and mute, panadapter centre and bandwidth — and stays observe-only unless you pass <code>--allow-local-control</code>; no transmit methods were added. Audio gains a typed producer PCM contract and a rate-aware engine. Several shutdown crashes in the spectrum and VFO menus are fixed, and firmware upload byte accounting now reports an unconfirmed outcome as unconfirmed.</p>
<p>86 merged changes from 16 contributors, plus AetherClaude and one Dependabot update — including four first-time contributors this cycle. Full release notes and the complete commit list: <a href="https://github.com/aethersdr/AetherSDR/releases/tag/v26.9.3">v26.9.3 on GitHub</a>.</p>
</div>
<a class="blog-back blog-back-end" href="#" data-blog-back>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5m0 0 5-5m-5 5 5 5"/></svg>
Back to blog
</a>
</div>
</article>
<article class="blog-post" data-post="release-26-9-2" tabindex="-1" aria-labelledby="h-release-26-9-2" hidden>
<div class="wrap blog-post-wrap">
<a class="blog-back" href="#" data-blog-back>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5m0 0 5-5m-5 5 5 5"/></svg>
Back to blog
</a>
<figure class="blog-hero">
<img width="1200" height="630" src="assets/img/release-26-9-2-hero.svg" alt="v26.9.2 release art — four skimmers, one stream, drawn as an AetherSDR spectrum panel" />
</figure>
<span class="blog-meta">
<time datetime="2026-09-06">September 6, 2026</time>
<span class="sep" aria-hidden="true">·</span>
<span>6 min read</span>
</span>
<h1 id="h-release-26-9-2">v26.9.2: four skimmers on one stream, and two more ways to receive</h1>
<div class="blog-body">
<p class="lede">Sixty-seven merged changes, and most of them widen what you can listen with: four skimmers through one TCI server, two new experimental receive backends, two more pieces of station hardware brought inside the application — and a mirror for a directory that was never ours to lean on.</p>
<h2>Four skimmers, one stream</h2>
<p>AetherSDR now supports <strong>four concurrent TCI DAX IQ subscriptions</strong>, so a compatible Flex setup can feed several CW skimmers through a single TCI server instead of one.</p>
<p>The arithmetic is worth being precise about, because it decides how you set the station up. Receivers pointed at the same panadapter share that panadapter’s IQ stream — so four skimmers on one band cost you one stream. Four <em>independent</em> band spectra are a different thing: those need four panadapters. If what you want is a skimmer on 40, 20, 15 and 10 at once, that is the configuration to build.</p>
<p>This is the kind of capability that only shows its value at 0400 in a contest, when the thing you most want is to know which band is open without going to look.</p>
<h2>Two more ways to receive</h2>
<p>Two new backends arrive, both labelled <strong>experimental</strong> — which, as in the release that first used the word here, is a request for reports rather than a disclaimer.</p>
<p><strong>ANAN-G2 reception</strong> brings openHPSDR Protocol 2 discovery, a single receive path, spectrum and audio, with live tuning and zoom. This phase is receive-only; transmit is a later one, and the release does not pretend otherwise.</p>
<p><strong>RTL-SDR USB reception</strong> adds a single slice and panadapter with basic AM, FM, SSB and CW demodulation, on builds that carry the required RTL libraries. Availability varies by package, and selectable sharp passband filtering is not implemented yet. A twenty-dollar dongle is not going to behave like a Flex, and the point of supporting it is not to pretend it does — it is that the workstation you already know can drive it.</p>
<h2>The station, not just the radio</h2>
<p>Two more boxes on the desk come inside the application. The <strong>SPE floating front panel</strong> mirrors the amplifier’s LCD live and gives you guarded front-panel keys, so the amp’s own display no longer has to be within arm’s reach. <strong>TelePost LP-100A</strong> support displays the wattmeter’s readings over local serial or a serial-to-network proxy; this first version is read-only, which is the right place for a measurement instrument to start.</p>
<p>Around them: PGXL and TGXL startup synchronisation gives an honest initial status instead of a blank one, PA current appears when PTT originates at the radio rather than only from the client, the connection panel stays visible at startup, CTCSS choices are easier to read, and radio-specific settings and Flex-only zoom controls are gated to the backends that can actually implement them.</p>
<h2>A mirror for the Kiwi directory</h2>
<p>The public-receiver browser now reads its directory from an AetherSDR CDN mirror, and the Worker that maintains that mirror lives in the repository rather than in somebody’s account.</p>
<p>This is a small change with a principle under it. The world’s KiwiSDRs are run by volunteers, and so is the directory that lists them. An application that points every one of its users straight at that directory is quietly spending someone else’s bandwidth, and the more successful it gets, the more it spends. Mirroring is the polite version of popularity. Our thanks to the KiwiSDR team, who partnered with us to set it up.</p>
<p>The second half of it: stale directory data is now advisory rather than fatal. If the mirror falls behind, you get a note saying so and a list you can still browse — a degraded answer instead of an empty page.</p>
<h2>A radio’s own numbers</h2>
<p>The Icom work this cycle is a broad IC-7300MK2 control cleanup, and the shape of it is the same argument the last few releases have been making: the interface should follow the radio’s supported settings, ranges and native readback, not a plausible-looking approximation of them.</p>
<p>So CW speed uses the MK2’s actual 6–48 WPM range, and when capabilities change the slider and the numeric editor reconcile together without firing off an unintended command. CW pitch follows the radio’s 5 Hz steps, so button presses and readback agree instead of displaying intermediate values the radio cannot hold. TX bandwidth cutoff encoding is corrected, including the 300 Hz and 500 Hz low-cut selections. Squelch stays usable in CW and data modes and keeps its value across mode changes, rather than being treated as a voice-only control.</p>
<p>And where the backend cannot implement something — AGC threshold, AGC Off, AM carrier, VOX delay, unsupported repeater offset controls — it is disabled rather than decorative. Selecting an unavailable AGC mode is refused outright instead of silently substituting a different one, which is the failure mode worth removing: a control that quietly does something other than what it says.</p>
<p>Two details in the same section are worth pulling out. Tune in CW and CW-R is refused <em>before</em> changing power, generating a tone or requesting PTT — the refusal happens where it is still free. And meter readings preserve fractional watts at the radio’s own reporting resolution, with a note in the release that resolution is not accuracy. Reporting a number more precisely than you measured it is its own kind of lie.</p>
<p>All of these mappings stay model-specific on purpose, so correcting the MK2 does not impose MK2 behaviour on every other Icom. Alongside them, wire-based model identification replaces reliance on an editable network nickname, and an optional wake-on-connect — off by default, with profiles for the IC-705, IC-7300MK2 and IC-9700 — needs the radio’s network interface to stay reachable to work at all.</p>
<h2>Also in this release</h2>
<p><strong>CW.</strong> Client-side recordings capture the CW you sent rather than the microphone, CWX sidetone follows the keyer’s scheduled edges, the P/CW pane gains APF toggle and level controls, APF wheel input is ignored while APF is disabled, and CW settings stay stable on backends that don’t echo them back.</p>
<p><strong>Audio and Flex controls.</strong> Controller AGC-T input reaches the correct level control with AGC off, active-slice ALC and TX waveform meter routing are corrected, and Ulanzi TCI volume handling converts the wire’s dB values properly.</p>
<p><strong>Hermes-Lite 2.</strong> Power gauges use the appropriate 5 W scale, per-band gain survives startup and temporary overrides, and the HL2 IO Board gains band-following amplifier control. DSP setup is bounded and logged, with diagnostics that expose the actual DSP configuration and connection progress; TX FIFO status decoding follows the gateware, repeated ADC-overload warnings are rate-limited, and spectrum FFTW operations are serialised.</p>
<p><strong>The headless engine.</strong> aetherd Stage 3 groundwork adds the versioned protocol boundary, typed observations, per-session authorisation and an observe-only discovery catalogue. Authenticated radio control, transmit grants and a replacement desktop client are explicitly not part of this release.</p>
<p><strong>Packaging and project quality.</strong> Linux gains CPack DEB/RPM configuration and an optional system SQLite build; Homebrew header precedence and MinGW compatibility are corrected; Windows Store packaging gains fuller symbols, corrected upload handling and an explicit developer-flight submission workflow. The full test suite now runs on pushes to main, sanitizer configuration and suppressions are repaired, two previously unregistered tests join execution — and eight intermittent tests were removed rather than retried, because a test that fails at random teaches you nothing except to stop reading the results.</p>
<p>67 merged changes from 15 contributors and AetherClaude, plus two Dependabot updates, with four first-time contributors this cycle — including a first commit from <strong>Microsoft</strong> on the Windows Store publishing automation, and the KiwiSDR team’s help with the directory mirror. Full release notes and the complete commit list: <a href="https://github.com/aethersdr/AetherSDR/releases/tag/v26.9.2">v26.9.2 on GitHub</a>.</p>
</div>