Initial success with cost-effective 6m WSPR + 2m FT8 beacons

Our 6m WSPR beacon design works fine now. The key is to use a 25 MHz high-quality TCXO, like the 25 MHz HCI 0.5ppm TCXO! 2m WSPR is still out of reach for this VFO design - see the following drifty screenshots: While WSPR is no good, 2m FT8 works pretty fine! ...

August 16, 2025 · 1 min · 72 words · Dhiru Kholia

Checking Zoom latency externally

Here is a handy script that I often use to check the quality of the Zoom connection. It measures TCP latency instead of the usual ICMP stuff (which is often blocked). #!/usr/bin/env python3 """ TCP Ping Test (defaults to port 80, 10000 packets) Usage: ./tcpping.py host [port] [maxCount] - Ctrl-C Exits with Results """ """ pip3 install matplotlib numpy python3 ./tcp_ping_grapher.py 115.114.56.202 443 100 python3 ./tcp_ping_grapher.py teams.microsoft.com 443 100 """ import sys import socket import time import signal from timeit import default_timer as timer # https://matplotlib.org/examples/animation/animate_decay.html import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation host = None port = 80 # Default to 10000 connections max maxCount = 10000 ## Inputs # Required Host try: host = sys.argv[1] # host = "115.114.56.202" except IndexError: print("Usage: tcpping.py host [port] [maxCount]") sys.exit(1) # Optional Port try: port = int(sys.argv[2]) # port = 443 except ValueError: print("Error: Port Must be Integer:", sys.argv[2]) sys.exit(1) except IndexError: pass # Optional maxCount try: maxCount = int(sys.argv[3]) except ValueError: print("Error: Max Count Value Must be Integer", sys.argv[3]) sys.exit(1) except IndexError: pass # Pass/Fail counters passed = 0 failed = 0 def getResults(): """ Summarize Results """ lRate = 0 if failed != 0: lRate = failed / (count) * 100 lRate = "%.2f" % lRate print("\nTCP Ping Results: Connections (Total/Pass/Fail): [{:}/{:}/{:}] (Failed: {:}%)".format((count), passed, failed, str(lRate))) def signal_handler(signal, frame): """ Catch Ctrl-C and Exit """ getResults() sys.exit(0) # Register SIGINT Handler signal.signal(signal.SIGINT, signal_handler) def work(t=0): passed = 0 failed = 0 count = 0 maxCount = 3200 # Loop while less than max count or until Ctrl-C caught while count < maxCount: # Increment Counter count += 1 success = False # New Socket s = socket.socket( socket.AF_INET, socket.SOCK_STREAM) # 1sec Timeout s.settimeout(1) # Start a timer s_start = timer() # Try to Connect try: s.connect((host, int(port))) s.shutdown(socket.SHUT_RD) success = True # Connection Timed Out except socket.timeout: print("Connection timed out!") failed += 1 except OSError as e: print("OS Error:", e) failed += 1 # Stop Timer s_stop = timer() s_runtime = "%.2f" % (1000 * (s_stop - s_start)) if success: print("Connected to %s[%s]: tcp_seq=%s time=%s ms" % (host, port, (count-1), s_runtime)) passed += 1 # Sleep for 1sec if count < maxCount: # time.sleep(0.5) # time.sleep(1) time.sleep(2) t += 2 yield t, float(s_runtime) # Output Results if maxCount reached # getResults() def data_gen(t=0): cnt = 0 while cnt < 1000: cnt += 1 t += 0.1 yield t, np.sin(2*np.pi*t) * np.exp(-t/10.) def init(): ax.set_ylim(0, 128 * 3) ax.set_xlim(0, 300) del xdata[:] del ydata[:] line.set_data(xdata, ydata) return line, fig, ax = plt.subplots() line, = ax.plot([], [], lw=2) ax.grid() xdata, ydata = [], [] def run(data): # update the data t, y = data xdata.append(t) ydata.append(y) xmin, xmax = ax.get_xlim() if t >= xmax: ax.set_xlim(xmin, 2*xmax) ax.figure.canvas.draw() line.set_data(xdata, ydata) return line, ani = animation.FuncAnimation(fig, run, work, blit=False, interval=10, repeat=False, init_func=init) plt.show() Usage: ...

August 8, 2025 · 3 min · 516 words · Dhiru Kholia

WiFi VFO, beacon and signal generator

We make heavy use of Easy-Digital-Beacons-v1 for testing RF amplifiers. This single board is a versatile WiFi VFO and FT8 / FT4 / WSPR beacon. You can also use our CW-SigGen project to generate a suitable test signal.

July 5, 2025 · 1 min · 38 words · Dhiru Kholia

New RF parts and new promises - part 2

Tokmas CID9N65E3 rocks! Performance It is CRAZY how efficient this GaN FET is in TO-252 (DPAK) package. It generates 5W @ 28 MHz with 13.8V at drain without even warming up! Close to 4W @ 50 MHz with 12.0V at drain. 5W+ @ 50 MHz with 13.8V at drain. 11W+ @ 50 MHz with 20V at drain. It even produces ~3W at 70 MHz with 13V at drain - w00t! ...

June 15, 2025 · 1 min · 207 words · Dhiru Kholia

The poor quality, reliability and longevity of MOONDROP products

I had bought two pairs of MOONDROP Aria 2 IEMs after auditioning them at a Headphone Connect event. After a few months of usage, one of the Aria 2 earphones lost audio in the left earpiece. We got it 'serviced' under warranty from Headphone Zone. After a year of almost no usage, the other pair of Aria 2 IEMs lost audio in one of the earpieces too! I have never seen this poor quality, reliability and longevity before! ...

June 15, 2025 · 1 min · 127 words · Dhiru Kholia

Fast(est) gate drivers in the West

I recently found some FET gate drivers which are quite fast! The Drivers Wuxi Maxinmicro MX1025D - Favorite! BD2311NVX-LBE2 from ROHM Semiconductor TI LMG1020 Tokmas LMG1020YFFR Usage They are perfect for driving the fast Tokmas GaN FETs that we recently discussed on this site. Our 'workhorse' gate driver for the recent experiments has been the Onsemi's NCP81074ADR2G in a friendly SOIC-8 package. We have also used UCC27614DR and UCC27517 (SOT-23-5) with excellent results. ...

June 3, 2025 · 1 min · 90 words · Dhiru Kholia

Debugging/Reversing Firebase gRPC Traffic with mitmproxy

Recently, I was stuck trying to understand how Firebase gRPC calls worked and how I could generate, modify, and replay them. Trapping and modifying existing gRPC traffic was not working well. Finally, I took a step back and spent some time learning how to build and debug simple Firebase applications. This approach helped me tremendously, and I was able to make further progress with my original task quickly. Solution You may find the following code sample useful when reversing/debugging Firebase applications. ...

April 16, 2025 · 2 min · 426 words · Dhiru Kholia

Ideas for a 2m (144 MHz) WSPR / FT8 beacon

This is an early design sketch of a 2m WSPR beacon. Key Points 25 MHz HCI 0.5ppm TCXO powering the Si5351 module instead of the 26 MHz TCXO. If this fails, we can use a 10 MHz OCXO instead (a bit out of spec but works fine). Tokmas CID10N65F GaN FET might work @ 144 MHz as the 'final'. If not, use Mitsubishi RD15HVF1-501 MOSFET as backup. 2SK3475 as the driver with variable DC bias at the gate The whole VCC to this amplifier will be PTT switched Ideally, we would want to keep the driver stage linear but the final stage as switched (Class C/D) Alternate: Perhaps by DC coupling the Si5351 input to 2SK3475, we can avoid the need for DC gate bias The "RFC" (bifilar coil still needed?) part will need to be figured out for VHF! Status Results: To be built and tested soon! ...

April 15, 2025 · 1 min · 172 words · Dhiru Kholia

Easily verifying certificate chains

Here is a quick script to verify that the certificate chain is valid and will work. % cat verify-cert-key.sh #!/usr/bin/env bash certFile="${1}" keyFile="${2}" caFile="${3}" certPubKey="$(openssl x509 -noout -pubkey -in "${certFile}")" keyPubKey="$(openssl pkey -pubout -in "${keyFile}")" if [[ "${certPubKey}" == "${keyPubKey}" ]] then echo "PASS: key and cert match" else echo "FAIL: key and cert DO NOT match" fi openssl verify -CAfile "${3}" "${1}"

April 14, 2025 · 1 min · 63 words · Dhiru Kholia

Reimagining the 'Tangara' Music Player - Part 2

Tangara is an excellent project! It recently inspired us to build a similar FOSS DAP product but at a much lower cost of <= 40 USD. Our initial tech stack: RP2350-Zero, PCM5102A 32-bit 384kHz DAC, Burr-Brown OPA1662 (specified for 3.3v) as the unity gain buffer and headphone driver, no explicit DC-DC converters anywhere, microSD card, everything will be a module if possible We quickly got this prototype working on a breadboard and discovered some limitations: ...

April 11, 2025 · 5 min · 966 words · Dhiru Kholia