BSides San Diego 2026 RF Village Demonstrations

This is what development looks like!

Open Research Institute organized and executed the RF Village at BSides San Diego on 4 April 2026. This highly anticipated sold-out annual event has a focus on cybersecurity and DIY problem solving. Held at Montezuma Hall at San Diego State University, the one-day event had multiple speaking tracks, at least three Capture the Flag contests (CTFs), an electronic hackable badge, a variety of food and drink available throughout the day, extensive volunteer support, relevant and timely workshops, an After Hours party with more food and drink at Aztec Lanes bowling alley, and a vibrant Village Square that combined Villages and Vendors. 

BSides San Diego 2026 RF Village Opulent Voice Development station staffed by Paul Williamson KB5MU. The post it note on the wall says "This is what development looks like!"
BSides San Diego 2026 RF Village Opulent Voice Development station staffed by Paul Williamson KB5MU. The post it note on the wall says “This is what development looks like!”

ORI served as the organizer for RF Village, bringing four staff members and multiple exhibits. We debuted our Lunar Lander CTF, announced the W6ORI amateur radio club, and gave away a large box of Amateur Satellite handbooks. We had RFBitBanger kits available for donation (5 were sold), hosted a live Meshcore node, and exhibited a real live FPGA development station with lab equipment for Opulent Voice. Our poster session included Authentication and Authorization and the technical side of RFBitBanger. Thank you to BSides San Diego for the excellent support, with rotating village volunteer staffers, volunteer green room, excellent communications before during and after the event, and genuine care for positive participant experience. Organizations like this make demonstrating open source digital radio work a real joy instead of a daunting chore.

Demonstrations give you deadlines, documentations, and get things “done”. The BSides Opulent Voice demonstration revealed some immediate problems with the 24 dB transmitter fix. The signal was clearly being transmitted at sufficient power, but the symbol and frame lock were not happening. We were seeing “garbage” frames where we were expecting to see actual live data.

Since the over-the-air voice call had worked so well just a few days prior, what was going on? The demonstration was still very successful, as plenty could be shown to the steady stream of people at the RF Village. As the day progressed, more information was gathered. It was very clear we’d have to go back to the lab to figure out how a badly needed transmitter fix had broken the receiver. Why was it working over the air, and not in RF loopback on the bench? First, we went back to the VHDL-only test bench. This sends 10 frames into the transmitter, routes the transmit I and Q streams right back to the receiver, and then demodulates, decodes, and displays the frames. The data in should match the data out. And, frames were coming out, but they were completely scrambled! Something had gone wrong in the RF loopback. 

The difference between simulations and real life is usually a lot, and Opulent Voice is no different. A real hardware RF loopback has the radio chip in the loop. The VHDL test bench has only the FPGA contents. We don’t have analog to digital converters (ADCs), digital to analog converters (DACs), or anything else that is in the radio chip. Since the transmitter fix had a lot to do with how the transmitter DAC dealt with the data, it seemed reasonable to assume that the transmitter fix had upset the receiver. 

The missing gain was in the transmitter, but the fix applied some math changes to both the transmiter and the receiver, and investigating this took up part of the next day back in the lab. WIth two minor changes, the test bench started working flawlessly again. A new version of the firmware was created, and… it didn’t work in hardware at all! Symbol lock and frame lock were totally non-functional. The plot had certainly thickened.

This is one of the many reasons why demonstrations are so valuable. We find things that we might not go looking for, and it forces us to regularly show things working end-to-end. Work continues this week in the lab to separate the transmitter fix from inadvetently affecting the receiver, and bring us back to working perfectly over the air as well as in simulation. 

Lunar Descent, the BSides San Diego 2026 RF Village Capture the Flag (CTF) from ORI

A capture-the-flag challenge based on a real signal processing problem in a radar altimeter!

https://github.com/OpenResearchInstitute/lunar-descent-ctf

Indian Space Research Organization (ISRO) designed a Ka band radar altimeter (KaRA) that guided Chandrayaan-3 to a soft lunar landing on 23 August 2023. The Radar Altimeter Processor (RAP) computes altitude and velocity from FMCW chirp signals, running on a single Xilinx Virtex-5 FPGA. This CTF uses a Python model of that system, faithful to the published paper in the Aeronautics and Electronic Systems Journal, where the altimeter feeds a landing autopilot. In our CTF, the altimeter works perfectly. The autopilot keeps crashing. Why? (solution in next newsletter!)

What did the participants see? A python script that could be installed on their computer and then run.

pip install numpy matplotlib
python lunar_descent_ctf.py --help        # See all options
python lunar_descent_ctf.py               # Run the mission, watch it crash
python lunar_descent_ctf.py --modes       # See the sweep mode table
python lunar_descent_ctf.py --test -p all # Test all three profiles
python lunar_descent_ctf.py --score       # Score your fix and earn flags

Rules

Edit ONLY the `MeasurementQualifier` class (clearly marked in the source)

Don’t change the RAP, signal generation, autopilot, or scoring

The qualifier decides what the autopilot sees — fix it there

Submit flags at the RF Village table

Three Flags

None of the flags are “free”. The buggy code scores 0 / 1000 points out of the box.

FlagPointsChallenge
RECON100Explain the bug to RF Village staff. No hash on screen.
FIRST LIGHT500Land all three profiles without crashing.
NO GAPS400Zero qualifier rejections on all three profiles.

Total: 1000 points

The Scenario

The radar altimeter was tested on helicopters and aircraft at altitudes above 50 meters. It worked flawlessly. Field test performance met all mission specifications.

The altimeter is now integrated with a landing autopilot that uses both altitude and velocity measurements for thrust control during final approach. In simulation, the autopilot crashes the lander every time below 15 meters altitude. The altitude readings are fine. Sub-meter accuracy all the way to touchdown. Something else is killing the lander.

You need to find out what’s going wrong and fix the measurement qualification logic so the autopilot can land safely.

Difficulty Curve

0 points: Running the code unmodified. The default run shows OK status all the way down until the final approach, then CRASH. 

100 points: Explaining the problem to staff. 

600 points: Fixing the `MeasurementQualifier` so it can land. 

1000 points: Eliminating all qualifier rejections.

Validating Flag 1 (RECON)

No hash is printed on screen for Flag 1. Staff issue the flag manually.

Timing

The CTF ran all day alongside the workshop modules and talks. It’s self-paced and doesn’t require staff attention except for Flag 1 validation and prize distribution.

Test Profiles

ProfileCharacterWhat It Tests
standardChandrayaan-3-like smooth descent, 10 km → 3 m, with altitude excursion at 20 m (thruster anomaly or drifting over crater)Landing
aggressiveFast exponential braking, 10 km → 3 m in 400 sRapid mode transitions at hight altitude + Landing
stepwiseHover at guard band boundaries (9851/4795/2334/553/131/31/5 m), drop between themMode transitions + Low Hover

The Physics

The RAP uses FMCW radar. Up-chirp and down-chirp signals produce beat frequencies:

f_up = fb − fd (up-chirp)
f_dn = fb + fd (down-chirp)

Altitude comes from the sum: R = M × (f_up_index + f_dn_index). 
Velocity comes from the difference: fd = (f_dn_index − f_up_index) × freq_res / 2. 

The FFT is always 8192 points, but the number of real signal samples depends on the sweep time:

Mode 12 (high altitude): 8192 samples, full FFT
Mode 0 (3 m altitude): 14 samples, 99.8% zero-padding

Connection to Real Engineering

The problem is pedagogically framed but the pattern is real. Sensor qualification, knowing when to trust a measurement and when to reject it, is important.

Radar and sonar tracking systems (Doppler reliability vs integration time)
GPS/INS integration (knowing when satellite geometry is too poor to trust)
Medical imaging (SNR-dependent confidence in measurements)
Autonomous vehicle sensor fusion (camera vs lidar vs radar confidence)

The paper mentions “three sample qualification logics to generate the final altitude” without detailing them. What are those logics? Will some of those qualification logics help solve this CTF?

Source

Based on: Sharma et al., “FPGA Implementation of a Hardware-Optimized Autonomous Real-Time Radar Altimeter Processor for Interplanetary Landing Missions,” IEEE A&E Systems Magazine, Vol. 41, No. 1, January 2026. DOI: 10.1109/MAES.2025.3595090