-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
670 lines (640 loc) · 68.6 KB
/
Copy pathindex.html
File metadata and controls
670 lines (640 loc) · 68.6 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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VU2CPL – Manoj Ramawarrier</title>
<meta name="description" content="Amateur radio station VU2CPL – Manoj Ramawarrier, Bengaluru, India. Grid MK83TE. Licensed 1993. FLEX-6600, 10 BDXCC, DXpeditioner.">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Mono:wght@400;500&family=DM+Sans:wght@300;400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/assets/site.css">
<!-- Cloudflare Web Analytics --><script type='module' src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "bb5c13644c834a9fb621de380f7e5597"}'></script><!-- End Cloudflare Web Analytics -->
</head>
<body>
<nav>
<a class="nav-logo" href="#"><span>VU2CPL</span> · Manoj</a>
<div class="nav-links">
<a href="#about">About</a>
<a href="#station">Station</a>
<a href="#log">Log</a>
<a href="#projects">Projects</a>
<a href="#writings">Writings</a>
<a href="/dxcc/">VU DXCC</a>
<details class="nav-dd">
<summary title="Listen live on VU2CPL's WebSDR — HF and VHF">WebSDR</summary>
<div class="nav-dd-menu">
<a href="https://vu2cpl.tunnel.ubersdr.org/?freq=7150000&mode=lsb&bwl=-2700&bwh=-50&zoom_freq=7150000&zoom_bw=500.0" target="_blank" rel="noopener" title="HF WebSDR — RX-888 + LZ1AQ active loop, 0–30 MHz">HF — 0–30 MHz</a>
<a href="https://vu2cpl.ddns.net:8873/" target="_blank" rel="noopener" title="VHF WebSDR — 2 m / 70 cm / airband / FM, SDRplay RSP2 + MSi2500 (OpenWebRX+)">VHF — 2 m / 70 cm / air / FM</a>
</div>
</details>
<a href="#contact">Contact</a>
</div>
</nav>
<div class="hero">
<div class="hero-inner">
<div class="hero-left">
<div class="hero-tag">QRV · Bengaluru</div>
<h1>VU2CPL<br><em>Manoj Ramawarrier</em></h1>
<p class="hero-sub">MK83TE · Bengaluru, Karnataka · Licenced 1993</p>
<div class="hero-badges">
<span class="badge badge-blue">FLEX-6600 · RGO One · IC-705</span>
<span class="badge badge-green">10 BDXCC</span>
<span class="badge badge-amber">DXpeditioner</span>
<span class="badge badge-pink">Remote Ops</span>
</div>
</div>
<div class="hero-stats">
<div class="stat-card"><div class="stat-val">1.5 KFA</div><div class="stat-lbl">SPE Expert Amp</div></div>
<div class="stat-card"><div class="stat-val">10 BDXCC</div><div class="stat-lbl">Awards</div></div>
<div class="stat-card"><div class="stat-val">VU7T · AT5P</div><div class="stat-lbl">DXpeditions</div></div>
</div>
</div>
</div>
<hr class="divider">
<section id="about">
<div class="section-label">01 · About</div>
<h2>The Operator</h2>
<div class="qsl-banner">
<a class="shack-zoom" href="qslcard.jpg" data-caption="QSL card · VU2CPL">
<img src="qslcard.jpg" alt="VU2CPL QSL card — Taj Mahal, India" loading="lazy">
</a>
</div>
<div class="about-grid">
<div class="about-text">
<p>Located in the garden city of India, Bangalore. Licensed since 1993, I started operations in Thrissur, Kerala with a simple homebrew QRP rig following VU2VWN OM Vasanth (SK)'s circuit — the most popular design of those days.</p>
<p>Later graduated to SSB with the help of an old exciter originally made by VU2UCY Om Bhasi (SK). Went through different iterations of 807 tube QRO and some military surplus gear (Redifone GR 345) during the 1990s. Shifted to Bangalore in early 2003.</p>
<p>I travel extensively for work and mostly operate remote during free time. The shack runs a fully automated setup including remote antenna switching and lightning protection.</p>
<div class="dxped-list">
<div style="font-family:var(--mono);font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:0.08em;margin-bottom:4px;">DXpeditions</div>
<div class="dxped-item"><span class="dxped-call">VU7T / VU7MS</span><span class="dxped-desc">Kavaratti Is, Lakshadweep</span><span class="dxped-year">Oct 2017</span></div>
<div class="dxped-item"><span class="dxped-call">AT5P</span><span class="dxped-desc">Rameshwaram Is, IOTA AS-173</span><span class="dxped-year">May 2015</span></div>
<div class="dxped-item"><span class="dxped-call">AT3N · ARSI Hilltop</span><span class="dxped-desc">Nelliyampathy, Kerala — 4,417 QSOs, 261 DXCC</span><span class="dxped-year">Jan 2024</span></div>
<div class="dxped-item"><span class="dxped-call">ARSI Hilltop 2025</span><span class="dxped-desc">Vayalada Hills, Kozhikode MK71WM</span><span class="dxped-year">Jan 2025</span></div>
<div class="dxped-item"><span class="dxped-call">ARSI Hilltop 2023</span><span class="dxped-desc">Kulamavu, Idukki MJ89KT — HF/VHF/UHF</span><span class="dxped-year">Feb 2023</span></div>
</div>
</div>
<div>
<div class="about-details">
<div class="detail-row"><span class="detail-key">Callsign</span><span class="detail-val">VU2CPL</span></div>
<div class="detail-row"><span class="detail-key">Grid</span><span class="detail-val">MK83TE</span></div>
<div class="detail-row"><span class="detail-key">Location</span><span class="detail-val">Bengaluru, KA 562157</span></div>
<div class="detail-row"><span class="detail-key">Licenced</span><span class="detail-val">1993</span></div>
<div class="detail-row"><span class="detail-key">Modes</span><span class="detail-val">SSB · FT8 · CW</span></div>
<div class="detail-row"><span class="detail-key">Bands</span><span class="detail-val">160m – 6m incl. 60m</span></div>
<div class="detail-row"><span class="detail-key">QSL</span><span class="detail-val">LOTW · Clublog OQRS</span></div>
</div>
<div style="margin-top:1.25rem;">
<div style="font-family:var(--mono);font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:0.08em;margin-bottom:8px;">Awards</div>
<div class="awards-row">
<span class="award-badge">5BDXCC</span><span class="award-badge">160m DXCC</span><span class="award-badge">30m DXCC</span><span class="award-badge">17m DXCC</span><span class="award-badge">12m DXCC</span><span class="award-badge">6m DXCC</span>
</div>
</div>
<div class="shack-gallery">
<figure>
<a class="shack-zoom" href="shack-desk.jpg"
data-caption="Operating position — FLEX-6600, audio chain, mic boom">
<img src="shack-desk.jpg" alt="VU2CPL operating position — curved monitor, FlexRadio, audio chain, mic boom">
</a>
<figcaption>Operating position — FLEX-6600, audio chain, mic boom</figcaption>
</figure>
<figure>
<a class="shack-zoom" href="shack-workbench.jpg"
data-caption="Workbench — Maestro, Li-ion pack, microscope, tools">
<img src="shack-workbench.jpg" alt="VU2CPL workbench — FlexRadio Maestro, BatteryInc Li-ion pack, microscope, pegboard tools">
</a>
<figcaption>Workbench — Maestro, Li-ion pack, microscope, tools</figcaption>
</figure>
</div>
<div class="shack-credit">
Photos by Girish, VU2KGB · <a href="https://www.hamphotos.com" target="_blank" rel="noopener">hamphotos.com</a>
</div>
</div>
</div>
</section>
<hr class="divider">
<section id="station">
<div class="section-label">02 · Station</div>
<h2>Equipment</h2>
<div class="station-cols">
<div>
<div class="equip-group">
<div class="equip-group-title">Radios</div>
<div class="equip-item"><span class="equip-dot"></span>FlexRadio FLEX-6600 (SDR)</div>
<div class="equip-item"><span class="equip-dot"></span>RGO One</div>
<div class="equip-item"><span class="equip-dot"></span>Icom IC-705</div>
</div>
<div class="equip-group">
<div class="equip-group-title">Amplifier</div>
<div class="equip-item"><span class="equip-dot"></span>SPE Expert 1.5 KFA</div>
</div>
<div class="equip-group">
<div class="equip-group-title">RX Antennas (Low Band)</div>
<div class="equip-item"><span class="equip-dot"></span>350 ft 2-wire reversible Beverage (N/S) — winters only</div>
<div class="equip-item"><span class="equip-dot"></span>N6RK Loop</div>
<div class="equip-item"><span class="equip-dot"></span>K9AY Loop</div>
</div>
</div>
<div>
<div class="equip-group">
<div class="equip-group-title">Antennas</div>
<div class="equip-item"><span class="equip-dot"></span>Hex beam — 20m to 6m</div>
<div class="equip-item"><span class="equip-dot"></span>Vertical — 30m</div>
<div class="equip-item"><span class="equip-dot"></span>Inverted Vee — 80m & 40m</div>
<div class="equip-item"><span class="equip-dot"></span>Inverted L — 160m (hairpin matched, 2 elevated radials)</div>
<div class="equip-item"><span class="equip-dot"></span>4 ele LFA Yagi — 6m</div>
</div>
<div class="equip-group">
<div class="equip-group-title">Band Allocation Notes</div>
<div class="equip-item"><span class="equip-dot"></span>80m: 3500–3700 kHz</div>
<div class="equip-item"><span class="equip-dot"></span>160m: 1800–1825 kHz</div>
<div class="equip-item"><span class="equip-dot"></span>60m: QRV from Dec 2018</div>
<div class="equip-item"><span class="equip-dot"></span>FT8: split needed within VU allocation</div>
</div>
</div>
</div>
</section>
<hr class="divider">
<section id="log" style="max-width:1200px;">
<div class="section-label">03 · Logbook</div>
<h2>Operating Dashboard</h2>
<div class="clublog-wrap">
<div class="clublog-header">
<span class="clublog-title">DX Dashboard · Clublog</span>
<span class="clublog-live">Live</span>
</div>
<iframe src="https://clublog.org/dx-dash/vu2cpl" height="1075" scrolling="no" title="VU2CPL DX Dashboard from Clublog" style="margin-top:-8px;display:block;"></iframe>
</div>
<div style="display:flex;justify-content:space-between;align-items:center;margin-top:10px;gap:1rem;flex-wrap:wrap;">
<div class="qsl-note" style="margin-top:0;flex:1;">
<strong>QSL Policy:</strong> Preferred route is LOTW or direct via Clublog OQRS. No bureau (stopped March 2019). For VU7MS and VU7T QSLs, use Clublog OQRS only. No IRC accepted.
</div>
<a href="https://clublog.org/logsearch/VU2CPL" target="_blank" rel="noopener" style="font-family:var(--mono);font-size:11px;color:var(--accent);text-decoration:none;white-space:nowrap;">Full log search →</a>
</div>
</section>
<hr class="divider">
<section id="projects">
<div class="section-label">04 · Projects</div>
<h2>Shack Automation & Utilities</h2>
<div style="font-family:var(--mono);font-size:11px;font-weight:500;color:var(--muted);text-transform:uppercase;letter-spacing:0.1em;margin-bottom:12px;">Node-RED Flows</div>
<div class="project-list" style="margin-bottom:2.5rem;">
<div class="project-card">
<div>
<div class="project-name">Shack Dashboard — Vue 3 SPA</div>
<div class="project-desc">Unified single-page dashboard for the whole shack, built in Vue 3 and served from Node-RED via uibuilder — replacing the legacy AngularJS <code>/ui</code> board. Thirteen collapsible cards (FlexRadio, LP-700, SPE amplifier, rotator, lightning protection, power control, solar conditions, DXCC tracker, RBN skimmer, Raspberry Pi fleet, internet health, GPS NTP, UberSDR receiver) lay out in a responsive masonry grid that adapts from phone to desktop with no build step. Each card polls flow context every 1–5 s, shows a colour-coded collapsed summary and expands for full telemetry. Top bar carries the callsign, a live/offline connectivity pill and four clocks (UTC / IST / sunrise / sunset). PWA-installable on iPad and iPhone via "Add to Home Screen".</div>
<div class="project-tags"><span class="proj-tag">Node-RED</span><span class="proj-tag">Vue 3</span><span class="proj-tag">uibuilder</span><span class="proj-tag">PWA</span><span class="proj-tag">MQTT</span><span class="proj-tag">Responsive</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/vu2cpl-shack" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">FLEX-6600 State Monitor Dashboard</div>
<div class="project-desc">Real-time Node-RED flow tracking all four slice receivers via the FlexRadio TCP API, with dual SmartSDR client support (AetherSDR + iPad). Colour-coded active-slice indication — amber for RX, red for TX — now surfaced as the FlexRadio card in the Vue 3 shack dashboard above, and still on the legacy AngularJS <code>/ui</code> board.</div>
<div class="project-tags"><span class="proj-tag">Node-RED</span><span class="proj-tag">FlexRadio API</span><span class="proj-tag">SmartSDR</span><span class="proj-tag">MQTT</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/vu2cpl-shack" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">DXCC Tracker & DX Alert System</div>
<div class="project-desc">Subscribes to four DX cluster telnet sources (VU2CPL, VU2OY, VE7CC, N2WQ) and pulls worked/confirmed DXCC data from Club Log via a nightly API call. Each incoming spot is prefix-resolved against cty.xml and classified against the confirmed grid — new DXCC entity (red), new band (blue), new mode fill (amber). Alerts fan out to the shack dashboard panel, MQTT, the FlexRadio slice, and a Telegram bot, with per-band / per-mode filtering.</div>
<div class="project-tags"><span class="proj-tag">Node-RED</span><span class="proj-tag">Club Log API</span><span class="proj-tag">DX Cluster</span><span class="proj-tag">Telnet</span><span class="proj-tag">cty.xml</span><span class="proj-tag">MQTT</span><span class="proj-tag">Telegram</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/vu2cpl-shack" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">Lightning Antenna Protector</div>
<div class="project-desc">Automatically disconnects antenna and radio when lightning is detected within 25 km, from Open-Meteo CAPE and weather-code polling plus a local AS3935 sensor over MQTT, and inhibits TX on the FLEX-6600 so the rig cannot key up into a disconnected antenna. <a href="/projects/lightning-antenna-protector/" style="color:var(--accent);white-space:nowrap;">Read more →</a></div>
<div class="project-tags"><span class="proj-tag">Node-RED</span><span class="proj-tag">Open-Meteo</span><span class="proj-tag">Tasmota</span><span class="proj-tag">AS3935</span><span class="proj-tag">SmartSDR API</span><span class="proj-tag">TX inhibit</span><span class="proj-tag">Telegram</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/vu2cpl-shack" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
<a class="yt-link" href="https://youtu.be/vq5DuG9_yD8" target="_blank" rel="noopener">▶ YouTube demo</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">Remote Shack Control</div>
<div class="project-desc">Full remote operation capability including antenna switching via Tasmota MQTT relays. Operates the FLEX-6600 via SmartSDR from anywhere. Integrated with the lightning protection system for safe unattended operation.</div>
<div class="project-tags"><span class="proj-tag">Tasmota</span><span class="proj-tag">MQTT</span><span class="proj-tag">SmartSDR</span><span class="proj-tag">Node-RED</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/vu2cpl-shack" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
</div>
<div style="font-family:var(--mono);font-size:11px;font-weight:500;color:var(--muted);text-transform:uppercase;letter-spacing:0.1em;margin-bottom:12px;">Shack Firmware & Field Devices</div>
<div class="project-list" style="margin-bottom:2.5rem;">
<div class="project-card">
<div>
<div class="project-name">Pi GPS NTP Server — shack stratum-1 timeserver</div>
<div class="project-desc">Stratum-1 GPS-disciplined NTP server on a Raspberry Pi 3B with a u-blox NEO-M8N. Kernel <code>pps-gpio</code> + chrony pulls PPS error down to ±171 ns — well below anything a userland NTP implementation can match. Publishes chrony status, satellite count and fix quality over MQTT to the shack dashboard, with an LWT offline marker. Production timeserver for the LAN.</div>
<div class="project-tags"><span class="proj-tag">Raspberry Pi</span><span class="proj-tag">GPS</span><span class="proj-tag">NTP</span><span class="proj-tag">chrony</span><span class="proj-tag">kernel PPS</span><span class="proj-tag">u-blox NEO-M8N</span><span class="proj-tag">MQTT</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/pi-gps-ntp-server" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">ESP8266 GPS-disciplined NTP server</div>
<div class="project-desc">PPS-disciplined NTP server on a NodeMCU ESP8266 with a Quectel L89 GPS. Captures the PPS edge on a GPIO interrupt for sub-microsecond second alignment, holds stratum 1 across short PPS dropouts via holdover logic, and once the PPS+RMC pair goes stale for more than 5 s advertises stratum 16 / refid <code>INIT</code> (RFC 5905 §3.5) so clients cleanly fall back to other NTP sources rather than trusting a drifting local clock. Publishes status over MQTT with the same schema as the Pi NTP server and an LWT offline marker. WiFiManager captive-portal config — no compile-time secrets.</div>
<div class="project-tags"><span class="proj-tag">ESP8266</span><span class="proj-tag">PlatformIO</span><span class="proj-tag">GPS</span><span class="proj-tag">NTP</span><span class="proj-tag">PPS</span><span class="proj-tag">Quectel L89</span><span class="proj-tag">MQTT</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/esp8266-gps-ntp" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">vu2cpl-as3935-bridge — outdoor lightning sensor</div>
<div class="project-desc">ESP32 firmware bridging an outdoor AS3935 lightning sensor to the shack MQTT broker. Moving the sensor outdoors — 18650 + TP4056 + solar, IP65 enclosure, shade-mounted — recovers the chip's rated ~40 km range that an indoor I²C bus eats. The full AS3935 register surface plus battery-voltage telemetry (<code>vbat_mv</code> on <code>/hb</code> + <code>/status</code>, on-demand <code>query_vbat</code>) is exposed over MQTT, so noise floor, watchdog threshold, TUN_CAP calibration and %SOC are all tunable live from the dashboard without opening the enclosure. WiFiManager captive portal carries WiFi and the shack broker's ACL-scoped <code>iot</code> MQTT credentials — no compiled-in secrets.</div>
<div class="project-tags"><span class="proj-tag">ESP32</span><span class="proj-tag">PlatformIO</span><span class="proj-tag">AS3935</span><span class="proj-tag">MQTT</span><span class="proj-tag">Lightning</span><span class="proj-tag">18650 + solar</span><span class="proj-tag">Vbat telemetry</span><span class="proj-tag">I²C</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/vu2cpl-as3935-bridge" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">VUKEYER — WiFi CW keyer with FlexRadio network keying</div>
<div class="project-desc">WinKeyer-protocol compatible CW keyer on an ESP32. Loggers drive it with the standard K1EL WinKeyer protocol over USB serial or WiFi TCP, with the host protocol audited against a genuine K1EL WK3.1; elements are timed on the device, so the network adds no jitter to the CW. The paddle keys a FlexRadio over the network with no KEY or PTT wire (verified on a FLEX-6600), and the sidetone of memories is paced to the radio's measured CW timing so it stays in step with the air. Opto-isolated KEY/PTT/FSK outputs for any other rig. An OLED or LCD shows speed, backend and link state, and scrolls the CW being sent in large letters; settings live on a web page at <code>vukeyer.local</code> and survive power cycles. WinKeyer protocol by Steve K1EL; the K3NG keyer by Anthony Good K3NG was the behavioural reference — the implementation is original.</div>
<div class="project-tags"><span class="proj-tag">ESP32</span><span class="proj-tag">PlatformIO</span><span class="proj-tag">CW</span><span class="proj-tag">WinKeyer protocol</span><span class="proj-tag">FlexRadio</span><span class="proj-tag">WiFi</span><span class="proj-tag">OLED</span><span class="proj-tag">MQTT</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/vukeyer" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
</div>
<div style="font-family:var(--mono);font-size:11px;font-weight:500;color:var(--muted);text-transform:uppercase;letter-spacing:0.1em;margin-bottom:12px;">Utilities & Tools</div>
<div class="project-list">
<div class="project-card">
<div>
<div class="project-name">spe-remote — SPE Expert remote control server</div>
<div class="project-desc">Python 3 remote-control server for SPE Expert HF amplifiers, running on a Raspberry Pi over USB serial and serving both a built-in web dashboard and a WebSocket API — the full Application Programmer’s Guide Rev 1.1 plus the undocumented RCU command set. Based on original work by OH2GEK, rewritten and extended. <a href="/projects/spe-remote/" style="color:var(--accent);white-space:nowrap;">Read more →</a></div>
<div class="project-tags"><span class="proj-tag">Python 3</span><span class="proj-tag">WebSocket</span><span class="proj-tag">Raspberry Pi</span><span class="proj-tag">USB serial</span><span class="proj-tag">SPE Expert</span><span class="proj-tag">RCU protocol</span><span class="proj-tag">SmartSDR</span><span class="proj-tag">TUNE sweep</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/spe-remote" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">MacExpert — native SPE Expert control app for macOS</div>
<div class="project-desc">Swift / SwiftUI macOS app that mirrors and controls SPE Expert HF amplifiers over either local USB serial or remote WebSocket, with a two-way live mirror of the amplifier’s LCD. Named after and inspired by the original MacExpert by Georg Isenbürger DJ6GI/NZ1C; RCU protocol reverse-engineered from scratch by VU2CPL. <a href="/projects/macexpert/" style="color:var(--accent);white-space:nowrap;">Read more →</a></div>
<div class="project-tags"><span class="proj-tag">macOS</span><span class="proj-tag">Swift</span><span class="proj-tag">SwiftUI</span><span class="proj-tag">SPE Expert</span><span class="proj-tag">RCU</span><span class="proj-tag">USB serial</span><span class="proj-tag">WebSocket</span><span class="proj-tag">SWEEP panel</span><span class="proj-tag">Apple-notarised</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/macexpert-spe" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">LP-700-Server — Telepost LP-700 WebSocket bridge</div>
<div class="project-desc">Go WebSocket bridge for the Telepost LP-500 / LP-700 USB-HID power and SWR meter. Owns the meter's HID handle and fans live telemetry out to many concurrent clients — browsers, phones, logging PCs — while routing control verbs back. Cross-compiles to Linux (amd64 / arm64 / armv7), macOS (Apple Silicon + Intel) and Windows (amd64) via a tag-driven GitHub Actions release workflow; ships a systemd unit and udev rules for headless Raspberry Pi deployment. LAN-only, zero auth. Forked from and tracking the original <a href="https://github.com/VU3ESV/LP-700-Server" target="_blank" rel="noopener" style="color:var(--accent);">LP-700-Server</a> by Vinod VU3ESV.</div>
<div class="project-tags"><span class="proj-tag">Go</span><span class="proj-tag">WebSocket</span><span class="proj-tag">USB HID</span><span class="proj-tag">Raspberry Pi</span><span class="proj-tag">LP-700</span><span class="proj-tag">Telepost</span><span class="proj-tag">systemd</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/LP-700-Server" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">LP-700-App — native macOS client for the LP-700</div>
<div class="project-desc">Native SwiftUI macOS client that talks to LP-700-Server over WebSocket. Live power / SWR / channel / alarm display, full control-verb support, settings persistence, a menu-bar glance-view, and macOS notifications for alarm states. Pairs with LP-700-Server so a single HID-attached meter drives operating positions, logging PCs and phones simultaneously. Forked from and tracking the original <a href="https://github.com/VU3ESV/LP-700-App" target="_blank" rel="noopener" style="color:var(--accent);">LP-700-App</a> by Vinod VU3ESV.</div>
<div class="project-tags"><span class="proj-tag">macOS</span><span class="proj-tag">Swift</span><span class="proj-tag">SwiftUI</span><span class="proj-tag">WebSocket</span><span class="proj-tag">LP-700</span><span class="proj-tag">Telepost</span><span class="proj-tag">menu-bar</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/LP-700-App" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">Amateur Radio Suite — macOS plugin host</div>
<div class="project-desc">Single macOS container app that hosts independent amateur-radio control apps as <em>plugins</em> in one window — switchable between a vertical sidebar and horizontal tabs. Each plugin stays in its own repo and ships as a standalone <code>.app</code>; the suite loads it through the <a href="https://github.com/VU3ESV/RadioPluginKit" target="_blank" rel="noopener" style="color:var(--accent);">RadioPluginKit</a> contract — the host links only the contract, never compiles a plugin in. Plugins are discovered at runtime (browse a catalog or sideload a <code>.radioplugin</code>) and run out-of-process as sandboxed ExtensionKit extensions, so crash isolation is real and adding one never requires rebuilding the suite. Ships with an empty catalog: published plugins today are LP-700, LP-100A, Band Pass Filter and Antenna Switch; SPE amplifier (MacExpert) and SO2R Box are next. Notarized release pipeline, macOS 14+. Original concept and reference implementation by Vinod VU3ESV — upstream at <a href="https://github.com/VU3ESV/AmateurRadioSuite" target="_blank" rel="noopener" style="color:var(--accent);">VU3ESV/AmateurRadioSuite</a>.</div>
<div class="project-tags"><span class="proj-tag">macOS</span><span class="proj-tag">Swift</span><span class="proj-tag">SwiftUI</span><span class="proj-tag">ExtensionKit</span><span class="proj-tag">Plugin host</span><span class="proj-tag">RadioPluginKit</span><span class="proj-tag">Notarized</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/AmateurRadioSuite" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">rotator-remote — Rotor-EZ WebSocket gateway</div>
<div class="project-desc">Python WebSocket gateway that owns the Idiom Press Rotor-EZ (Hy-Gain DCU-1 compatible) FTDI serial port on the shack Raspberry Pi and fans azimuth out to any number of clients — Node-RED, a built-in web UI, future Mac apps. The third shack USB device lifted into a gateway service alongside spe-remote and LP-700-Server: same threaded-reader + asyncio-writer pattern, so the serial port has a single owner and clients no longer have to restart Node-RED to free it. Self-contained web UI on port 8090 — large heading readout, click-to-slew compass dial, preset bearings (N/NE/E/SE/S/SW/W/NW), prominent STOP, and LP/+180° long-path. JSON <code>state</code> + <code>heartbeat</code> events over <code>/ws</code>, <code>/healthz</code> endpoint, all writes serialised through one lock so poll queries and client commands never interleave on the wire.</div>
<div class="project-tags"><span class="proj-tag">Python</span><span class="proj-tag">Tornado</span><span class="proj-tag">WebSocket</span><span class="proj-tag">Raspberry Pi</span><span class="proj-tag">USB serial</span><span class="proj-tag">FTDI</span><span class="proj-tag">Rotor-EZ</span><span class="proj-tag">Hy-Gain DCU-1</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/rotator-remote" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">SO2R Box — macOS controller for the YCCC SO2R Box Plus</div>
<div class="project-desc">Native macOS controller for the YCCC SO2R Box Plus contesting switch. USB-HID to the box; live front-panel mirror in the SwiftUI UI (TX/RX, footswitch, speed pot) using the YCCC HID protocol. Hosts OTRSP and Winkeyer TCP servers, so N1MM+, Win-Test, WriteLog and TR4W see it as a standard SO2R interface. Supports the default 2-radio SO2R mode and the 4-radio SO2R+ mode. Co-developed with Vinod VU3ESV (LB9KJ); the YCCC HID protocol was reverse-engineered from YCCC's own <code>SO2RBox.exe</code> and cross-checked against N4AF's TR4W <code>uYCCCSO2R.pas</code>.</div>
<div class="project-tags"><span class="proj-tag">macOS</span><span class="proj-tag">Swift</span><span class="proj-tag">USB HID</span><span class="proj-tag">OTRSP</span><span class="proj-tag">Winkeyer</span><span class="proj-tag">YCCC</span><span class="proj-tag">SO2R</span><span class="proj-tag">Contesting</span></div>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">DXCA — DX Cluster Aggregator 2.0</div>
<div class="project-desc">Rust rewrite of the DX Cluster Aggregator, running the whole aggregation stack headless on a Raspberry Pi behind a multi-user web GUI — WSJT-X / JTDX / MSHV decoder feeds and cluster telnet merged into one stream, per-account ClubLog matrices driving seventeen alert levels, Telegram alerts, and match marking on FlexRadio and ExpertSDR3 panadapters. Original concept and reference implementation by Vinod VU3ESV. <a href="/projects/dxca/" style="color:var(--accent);white-space:nowrap;">Read more →</a></div>
<div class="project-tags"><span class="proj-tag">Rust</span><span class="proj-tag">Svelte</span><span class="proj-tag">Raspberry Pi</span><span class="proj-tag">Windows</span><span class="proj-tag">DX Cluster</span><span class="proj-tag">WSJT-X / JTDX</span><span class="proj-tag">Club Log</span><span class="proj-tag">Multi-user</span><span class="proj-tag">Telegram</span><span class="proj-tag">MQTT</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/dxca" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">MSHV-Mac — native macOS port of LZ2HV/MSHV</div>
<div class="project-desc">Native macOS port of LZ2HV’s MSHV multi-mode weak-signal program (FT8 / FT4 / Q65 / MSK144 / JT9 / JT65). Apple Silicon and Intel, Developer-ID signed and Apple-notarised, with patches on a macos-port branch so new LZ2HV releases merge cleanly. <a href="/projects/mshv-mac/" style="color:var(--accent);white-space:nowrap;">Read more →</a></div>
<div class="project-tags"><span class="proj-tag">macOS</span><span class="proj-tag">Qt5</span><span class="proj-tag">PortAudio</span><span class="proj-tag">FT8 / FT4</span><span class="proj-tag">MSK144</span><span class="proj-tag">FlexRadio</span><span class="proj-tag">TCI</span><span class="proj-tag">WSJT-X UDP</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/mshv-macos-port" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">Ulanzi D100H — hardware front panel for AetherSDR over TCI</div>
<div class="project-desc">A seven-key Bluetooth LE macro dial turned into a physical front panel for AetherSDR over its TCI WebSocket — tuning with grid snapping, split, PTT, ATU tune, mode cycle, mute and band stacking. Doubles as the plugin’s first-light hardware test: five defects found on the air, all now merged upstream. Plugin by Nigel Fenton G0JKN. <a href="/projects/ulanzi-d100h/" style="color:var(--accent);white-space:nowrap;">Read more →</a></div>
<div class="project-tags"><span class="proj-tag">macOS</span><span class="proj-tag">JavaScript</span><span class="proj-tag">Node.js</span><span class="proj-tag">Ulanzi Studio</span><span class="proj-tag">TCI</span><span class="proj-tag">AetherSDR</span><span class="proj-tag">Bluetooth LE</span><span class="proj-tag">WebSocket</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/ulanzi-d100h-aethersdr" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">Meridian — headless multi-platform SDR skimmer server</div>
<div class="project-desc">Headless SDR skimmer server in Rust with in-process FT8 / FT4 / CW / RTTY / WSPR decoders behind one registry, running on Linux, Raspberry Pi, macOS and Windows. Deployed as the station daemon on a Pi 5 driving the Red Pitaya as VU2CPL-9. A joint project, built together with Basil Thomas W6BT, Vinod VU3ESV and Ram VU3RDD. <a href="/projects/meridian/" style="color:var(--accent);white-space:nowrap;">Read more →</a></div>
<div class="project-tags"><span class="proj-tag">Rust</span><span class="proj-tag">C (FFI)</span><span class="proj-tag">Multi-platform</span><span class="proj-tag">Linux</span><span class="proj-tag">Raspberry Pi</span><span class="proj-tag">macOS</span><span class="proj-tag">Windows</span><span class="proj-tag">HPSDR</span><span class="proj-tag">Red Pitaya</span><span class="proj-tag">HermesLite</span><span class="proj-tag">RX-888</span><span class="proj-tag">FlexRadio DAX</span><span class="proj-tag">CW skimmer</span><span class="proj-tag">FT8 / FT4</span><span class="proj-tag">WSPR</span><span class="proj-tag">NCDXF beacon</span><span class="proj-tag">PSKR</span><span class="proj-tag">WSPRnet</span><span class="proj-tag">Svelte 5</span></div>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">TimeSync — clock-drift watcher for macOS</div>
<div class="project-desc">Menu-bar macOS app showing system-clock drift against NTP servers and an attached USB GPS, with a one-click "step the clock now" via chrony. Built for digital-mode operators where ~1 s alignment matters and the LAN may not always reach an upstream NTP source. An optional bundled <code>gpsd</code> + chrony stack turns the Mac itself into a stratum-2 NTP server for the rest of the shack; a small privileged helper daemon lets the app talk to chrony without sudo each time.</div>
<div class="project-tags"><span class="proj-tag">macOS</span><span class="proj-tag">Swift</span><span class="proj-tag">SwiftUI</span><span class="proj-tag">NTP</span><span class="proj-tag">GPS</span><span class="proj-tag">chrony</span><span class="proj-tag">gpsd</span><span class="proj-tag">menu-bar</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/timesync-mac" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">KST2Mac — native ON4KST chat client for macOS</div>
<div class="project-desc">Native macOS client for the ON4KST chats VHF, UHF and microwave operators keep open beside the radio — any number of rooms at once, each pane holding its own login, room picker and station list, and each able to be torn out into its own window. Named after and modelled on KST2Me by Bo OZ2M; the protocol work here is original. <a href="/projects/kst2mac/" style="color:var(--accent);white-space:nowrap;">Read more →</a></div>
<div class="project-tags"><span class="proj-tag">macOS</span><span class="proj-tag">Swift</span><span class="proj-tag">SwiftUI</span><span class="proj-tag">ON4KST</span><span class="proj-tag">VHF / UHF</span><span class="proj-tag">DX cluster</span><span class="proj-tag">telnet</span><span class="proj-tag">Notarised</span></div>
<a class="yt-link" href="https://github.com/vu2cpl/kst2mac/releases/latest" target="_blank" rel="noopener" style="color:var(--accent);">Download v1.0.0 for macOS →</a>
<a class="repo-btn" href="https://github.com/vu2cpl/kst2mac" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">NanoVNASaver — packaged macOS .app</div>
<div class="project-desc">Self-contained NanoVNASaver v0.7.3 .app bundle for Apple Silicon. Upstream NanoVNASaver only ships Windows and Raspberry Pi binaries, so this build wraps a Python 3.12 virtual-environment with PySide6 / Qt and the NanoVNASaver package, behind a small bash launcher in <code>Contents/MacOS/</code>. Slimmed from ~1.3 GB to 253 MB by stripping unused Qt frameworks, qml, translations, metatypes, and lipo-thinning every Mach-O binary to arm64. A macOS UI sizing patch relaxes upstream's hard-coded <code>setFixedHeight/Width</code> calls so Qt stops clipping label text on native macOS control chrome (<code>50kHz</code>→<code>50kH</code>, <code>Sweep</code>→<code>Sweer</code>, <code>Rescan</code>→<code>Rescar</code>). Ships with a hand-drawn 1024 px macOS-style <code>.icns</code> (rounded square + Smith-chart logo) in place of the upstream 128 px fallback. Logs to <code>~/Library/Logs/NanoVNASaver/nanovnasaver.log</code> for easy support.</div>
<div class="project-tags"><span class="proj-tag">macOS</span><span class="proj-tag">.app bundle</span><span class="proj-tag">PySide6 / Qt</span><span class="proj-tag">Apple Silicon</span><span class="proj-tag">NanoVNA</span><span class="proj-tag">VNA</span></div>
<a class="repo-btn" href="https://github.com/vu2cpl/nanovnasaver-mac" target="_blank" rel="noopener">
<svg width="14" height="14" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>
View repo on GitHub
</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">WebSDR — live RX-888 receiver on an LZ1AQ active loop</div>
<div class="project-desc">Public web-based SDR receiver running on a self-hosted <a href="https://github.com/madpsy/ka9q_ubersdr" target="_blank" rel="noopener" style="color:var(--accent);">UberSDR</a> instance — drag-tune the HF spectrum waterfall in the browser, switch between LSB / USB / CW / AM / FM / digital modes, adjust the filter, zoom the waterfall, and listen to the off-air audio with no install. The default deep-link below opens at 7.150 MHz LSB so you land mid-40m phone band ready to listen. Hardware is an RX-888 MkII front-end fed by an LZ1AQ wideband active loop (0–30 MHz HF coverage); reachable via UberSDR's zero-config tunnel at <code>vu2cpl.tunnel.ubersdr.org</code>. UberSDR by M9PSY (madpsy), built on Phil Karn KA9Q's <a href="https://github.com/ka9q/ka9q-radio" target="_blank" rel="noopener" style="color:var(--accent);">ka9q-radio</a> engine; the receive antenna is Chavdar Levkov LZ1AQ's active loop design.</div>
<div class="project-tags"><span class="proj-tag">WebSDR</span><span class="proj-tag">RX-888 MkII</span><span class="proj-tag">LZ1AQ active loop</span><span class="proj-tag">UberSDR</span><span class="proj-tag">ka9q-radio</span><span class="proj-tag">HF 0–30 MHz</span><span class="proj-tag">Live receiver</span><span class="proj-tag">Self-hosted</span></div>
<a class="yt-link" href="https://vu2cpl.tunnel.ubersdr.org/?freq=7150000&mode=lsb&bwl=-2700&bwh=-50&zoom_freq=7150000&zoom_bw=500.0" target="_blank" rel="noopener" style="color:var(--accent);">Open live WebSDR →</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">VHF WebSDR — 2 m / 70 cm / airband / FM</div>
<div class="project-desc">A companion VHF receiver to the HF WebSDR above — the same drag-tune waterfall in the browser, switch modes, zoom, and listen off-air with no install. <strong>Two receivers share the one instance:</strong> an <a href="https://www.sdrplay.com/products/rsp2/" target="_blank" rel="noopener" style="color:var(--accent);">SDRplay RSP2</a> covers the 2 m and 70 cm amateur bands and the VHF airband (118–134 MHz AM), while a second MSi2500 dongle on its own antenna covers the FM broadcast band — so someone listening to FM no longer pulls the amateur bands off the air. Bookmarks cover the local repeaters, Bengaluru airport and approach frequencies, and the Bengaluru FM stations. Served over HTTPS with a Let's Encrypt certificate, on a self-hosted <a href="https://github.com/luarvique/openwebrx" target="_blank" rel="noopener" style="color:var(--accent);">OpenWebRX+</a> instance. OpenWebRX+ by Marat Fayzullin, an extended fork of Jakob Ketterl DD5JFK's <a href="https://github.com/jketterl/openwebrx" target="_blank" rel="noopener" style="color:var(--accent);">OpenWebRX</a>.</div>
<div class="project-tags"><span class="proj-tag">VHF WebSDR</span><span class="proj-tag">SDRplay RSP2</span><span class="proj-tag">MSi2500</span><span class="proj-tag">OpenWebRX+</span><span class="proj-tag">2 m / 70 cm</span><span class="proj-tag">Airband</span><span class="proj-tag">FM broadcast</span><span class="proj-tag">Live receiver</span><span class="proj-tag">Self-hosted</span></div>
<a class="yt-link" href="https://vu2cpl.ddns.net:8873/" target="_blank" rel="noopener" style="color:var(--accent);">Open live VHF WebSDR →</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
<div class="project-card">
<div>
<div class="project-name">VU DXCC Credits Tracker</div>
<div class="project-desc">Live, sortable tables of DXCC standings for every Indian (VU / AT / AU) callsign, from two data sources on one page. The <strong>LoTW</strong> tab parses all 17 ARRL DXCC Standings PDFs each month — Mixed / Phone / CW / Digital / Satellite / bands 160 m to 6 m / Challenge / Honor Roll. The <strong>Clublog</strong> tab scrapes the Asia Top-2000 Confirmed league every day and pulls out Indian prefixes. Both tabs share the same layout: green highlight for column leaders, red for changes since the last snapshot, click-through to QRZ.com on every callsign. Table layout adapted from the original VU DXCC list template by VU2DCC.</div>
<div class="project-tags"><span class="proj-tag">Python</span><span class="proj-tag">pdfplumber</span><span class="proj-tag">reportlab</span><span class="proj-tag">GitHub Actions</span><span class="proj-tag">ARRL DXCC</span><span class="proj-tag">Clublog</span></div>
<a class="yt-link" href="/dxcc/" style="color:var(--accent);">View live page →</a>
</div>
<span class="status-badge status-active">Active</span>
</div>
</div>
</section>
<hr class="divider">
<!-- WRITINGS -->
<section id="writings">
<div class="section-label">05 · Writings & Field Reports</div>
<h2>Articles & Contest Reports</h2>
<div class="writings-grid">
<div class="writing-card">
<span class="writing-cat cat-topband">Top Band</span>
<div class="writing-title">0–100 on 160m</div>
<div class="writing-desc">My journey exploring the Gentleman's band from scratch — inverted L antenna, hairpin matching, beverage antennas, and chasing 100 DXCC on 160m from Zone 22.</div>
<div class="writing-stats">
<span class="wstat"><strong>102</strong> countries worked</span>
<span class="wstat"><strong>29</strong> CQ zones</span>
<span class="wstat"><strong>1,622</strong> QSOs</span>
</div>
<div class="writing-meta">
<span class="writing-date">Jan 2019</span>
<a class="writing-pdf" href="0-100_on_160m.pdf" target="_blank">↓ PDF</a>
</div>
</div>
<div class="writing-card">
<span class="writing-cat cat-dxped">DXpedition</span>
<div class="writing-title">VU7MS — Lakshadweep DXpedition</div>
<div class="writing-desc">Writeup of the VU7MS DXpedition to Kavaratti Island, Lakshadweep. Operations on HF with cubical quad and wire antennas from one of India's rarest DXCC entities.</div>
<div class="writing-meta">
<span class="writing-date">2016</span>
<a class="writing-pdf" href="vu7ms_writeup.pdf" target="_blank">↓ PDF</a>
</div>
</div>
<div class="writing-card">
<span class="writing-cat cat-dxped">DXpedition</span>
<div class="writing-title">VU7T — A Sequel to VU7MS</div>
<div class="writing-desc">The follow-up DXpedition to Kavaratti Island, Lakshadweep in October 2017. Expanded operations including first steps towards 160m activation from this rare entity.</div>
<div class="writing-meta">
<span class="writing-date">Oct 2017</span>
<a class="writing-pdf" href="vu7t_writeup.pdf" target="_blank">↓ PDF</a>
</div>
</div>
<div class="writing-card">
<span class="writing-cat cat-contest">Contest Report</span>
<div class="writing-title">AT3N — ARSI Hilltop Contest 2024</div>
<div class="writing-desc">Field report from team AT3N operating from Nelliyampathy, Kerala at 1,380m ASL. Multi-band HF/VHF/UHF operation — 4,417 QSOs, 261 DXCC entities, Category C winners.</div>
<div class="writing-stats">
<span class="wstat"><strong>4,417</strong> QSOs</span>
<span class="wstat"><strong>261</strong> DXCC</span>
</div>
<div class="writing-meta">
<span class="writing-date">Jan 2024</span>
<a class="writing-pdf" href="AT3N_REPORT_FOR_ARSI_CPL.pdf" target="_blank">↓ PDF</a>
</div>
</div>
<div class="writing-card">
<span class="writing-cat cat-contest">Contest Report</span>
<div class="writing-title">ARSI Hilltop Contest 2025</div>
<div class="writing-desc">Report from Vayalada Hills, Kozhikode (MK71WM). Smaller team, new location. 160m Inverted L and 90m reversible Beverage installed. Experimenting with 10m delta loop and CQ160 contest entries.</div>
<div class="writing-stats">
<span class="wstat"><strong>763</strong> QSOs</span>
<span class="wstat"><strong>148</strong> DXCC</span>
</div>
<div class="writing-meta">
<span class="writing-date">Jan 2025</span>
<a class="writing-pdf" href="ARSI_Hilltop_2025.pdf" target="_blank">↓ PDF</a>
</div>
</div>
<div class="writing-card">
<span class="writing-cat cat-tech">Technical</span>
<div class="writing-title">Interfacing the PA2500 with Modern Radios</div>
<div class="writing-desc">How to interface the Furuno PA2500 linear amplifier with modern transceivers — Arduino band decoder customisation, direct LPF switching, ALC polarity conversion using LT7660, and automated 4:1 antenna switching.</div>
<div class="writing-meta">
<span class="writing-date">2015</span>
<a class="writing-pdf" href="Interfacing_PA2500_with_modern_radios.pdf" target="_blank">↓ PDF</a>
</div>
</div>
</div>
</section>
<hr class="divider">
<section id="contact">
<div class="section-label">06 · Contact</div>
<h2>Get in Touch</h2>
<div class="contact-grid">
<div class="contact-info">
<div class="contact-item">
<div class="contact-icon"><svg viewBox="0 0 16 16" fill="none" stroke="#1a6bdb" stroke-width="1.5" width="16" height="16"><path d="M2 4l6 5 6-5M2 4h12v9H2V4z" stroke-linecap="round" stroke-linejoin="round"/></svg></div>
<div><div class="contact-label">QRZ</div><div class="contact-val"><a href="https://www.qrz.com/db/VU2CPL" target="_blank" rel="noopener">qrz.com/db/VU2CPL</a></div></div>
</div>
<div class="contact-item">
<div class="contact-icon"><svg viewBox="0 0 16 16" fill="none" stroke="#1a6bdb" stroke-width="1.5" width="16" height="16"><circle cx="8" cy="7" r="3"/><path d="M8 1C4.7 1 2 3.7 2 7c0 4.5 6 9 6 9s6-4.5 6-9c0-3.3-2.7-6-6-6z" stroke-linecap="round" stroke-linejoin="round"/></svg></div>
<div><div class="contact-label">Location</div><div class="contact-val">Tarabanahalli, Chikkajala PO<br>Bengaluru, KA 562157</div></div>
</div>
<div class="contact-item">
<div class="contact-icon"><svg viewBox="0 0 16 16" fill="none" stroke="#1a6bdb" stroke-width="1.5" width="16" height="16"><rect x="2" y="3" width="12" height="10" rx="1"/><path d="M5 7h6M5 10h4" stroke-linecap="round"/></svg></div>
<div><div class="contact-label">Logbook</div><div class="contact-val"><a href="https://clublog.org/logsearch/VU2CPL" target="_blank" rel="noopener">Clublog · VU2CPL</a></div></div>
</div>
<div class="contact-item">
<div class="contact-icon"><svg viewBox="0 0 16 16" fill="none" stroke="#1a6bdb" stroke-width="1.5" width="16" height="16"><circle cx="8" cy="8" r="6"/><path d="M8 4v4l3 2" stroke-linecap="round" stroke-linejoin="round"/></svg></div>
<div><div class="contact-label">Photos</div><div class="contact-val"><a href="https://hamphotos.com" target="_blank" rel="noopener">hamphotos.com</a></div></div>
</div>
<p style="font-size:13px;color:var(--muted);line-height:1.7;margin-top:0.5rem;">For sked requests, email via QRZ or WhatsApp. For QSL, use LOTW or Clublog OQRS — no bureau. 73 de VU2CPL.</p>
</div>
<div>
<form id="contact-form" action="https://formspree.io/f/mzdkogba" method="POST">
<div class="form-row">
<div class="form-group"><label>Name</label><input type="text" name="name" placeholder="Your name" required></div>
<div class="form-group"><label>Callsign</label><input type="text" name="callsign" placeholder="e.g. W1AW"></div>
</div>
<div class="form-group"><label>Email</label><input type="email" name="email" placeholder="your@email.com" required></div>
<div class="form-group">
<label>Subject</label>
<select name="subject">
<option>QSL / Sked request</option>
<option>DXpedition QSL (VU7T / AT5P)</option>
<option>Technical / Node-RED discussion</option>
<option>Remote shack / automation</option>
<option>160m / Low band discussion</option>
<option>General</option>
</select>
</div>
<div class="form-group"><label>Message</label><textarea name="message" placeholder="73, QSL via LOTW or..." required></textarea></div>
<button type="submit" class="btn-submit" id="submit-btn">Send Message</button>
<div class="form-success" id="form-success">Message sent! I'll get back to you soon. 73</div>
</form>
</div>
</div>
</section>
<footer>
<span>VU2CPL · Manoj Ramawarrier</span> · Bengaluru, India · MK83TE<br>
Licenced 1993 ·
<a href="https://www.qrz.com/db/VU2CPL">QRZ</a> ·
<a href="https://clublog.org/logsearch/VU2CPL">Clublog</a> ·
<a href="https://hamphotos.com">HamPhotos</a>
<br><br>73
</footer>
<script>
const form = document.getElementById('contact-form');
const btn = document.getElementById('submit-btn');
const success = document.getElementById('form-success');
form.addEventListener('submit', async function(e) {
e.preventDefault();
btn.disabled = true; btn.textContent = 'Sending...';
try {
const res = await fetch(form.action, { method:'POST', body: new FormData(form), headers:{'Accept':'application/json'} });
if (res.ok) { form.reset(); success.style.display='block'; btn.style.display='none'; }
else { btn.disabled=false; btn.textContent='Send Message'; alert('Problem sending. Please try again or contact via QRZ.'); }
} catch(err) { btn.disabled=false; btn.textContent='Send Message'; alert('Problem sending. Please try again or contact via QRZ.'); }
});
</script>
<!-- Lightbox: click any .shack-zoom anchor to open at full resolution -->
<div id="lightbox" class="lightbox" role="dialog" aria-hidden="true" aria-label="Photo viewer">
<button type="button" class="lightbox-close" aria-label="Close">×</button>
<img alt="">
<div class="lightbox-caption"></div>
</div>
<script src="/assets/lightbox.js"></script>
</body>
</html>