Warning: Custom Fork
This is a custom fork specifically modified for the RX-888 Mk II. Changes include VHF tuner fixes, performance optimizations, and API enhancements that have not been tested against other SDR hardware (HF103, BBRF103, RX888 Mk I, RX999, etc.). If you are using a different SDR, please use the upstream repository instead.
Based on the original work by Oscar Steila (IK1XPV).
If you are looking for RX-888 documents or support, please navigate to: https://www.rx-888.com/rx/
This fork must be built from source. See the build instructions below.
For pre-built binaries from the upstream project, visit: https://github.com/ik1xpv/ExtIO_sddc/releases (note: these will not include the fixes in this fork).
- Install Visual Studio 2019 with Visual C++ support. You can use the free community version, which can be downloaded from: https://visualstudio.microsoft.com/downloads/
- Install CMake 3.19+, https://cmake.org/download/
- Running the following commands in the root folder of the cloned repro:
> mkdir build
> cd build
> cmake ..
> cmake --build .
or
> cmake --build . --config Release
> cmake --build . --config RelWithDebInfo-
You need to download 32bit version of fftw library from fftw website http://www.fftw.org/install/windows.html. Copy libfftw3f-3.dll from the downloaded zip package to the same folder of extio DLL.
-
If you are running 64bit OS, you need to run the following different commands instead of "cmake .." based on your Visual Studio Version:
VS2022: >cmake .. -G "Visual Studio 17 2022" -A Win32
VS2019: >cmake .. -G "Visual Studio 16 2019" -A Win32
VS2017: >cmake .. -G "Visual Studio 15 2017 Win32"
VS2015: >cmake .. -G "Visual Studio 14 2015 Win32"
- download latest Cypress EZ-USB FX3 SDK from here: https://www.cypress.com/documentation/software-and-drivers/ez-usb-fx3-software-development-kit
- follow the installation instructions in the PDF document 'Getting Started with FX3 SDK'; on Windows the default installation path will be 'C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3' (see pages 17-18) - on Linux the installation path could be something like '/opt/Cypress/cyfx3sdk'
- add the following environment variables:
export FX3FWROOT=<installation path>
export ARMGCC_INSTALL_PATH=<ARM GCC installation path>
export ARMGCC_VERSION=4.8.1
(on Linux you may want to add those variables to your '.bash_profile' or '.profile')
- all the previous steps need to be done only once (or when you want to upgrade the version of the Cypress EZ-USB FX3 SDK)
- to compile the firmware run:
cd SDDC_FX3
make
- Install development packages:
> sudo apt install libfftw3-dev libusb-1.0-0-dev pkg-config- Build with CMake:
> mkdir build && cd build
> cmake -DCMAKE_BUILD_TYPE=Release ..
> make -j$(nproc)FFT Backend Selection:
The project supports multiple FFT backends. Choose one at build time:
# FFTW (default, best compatibility)
> cmake -DFFT_BACKEND=FFTW ..
# Intel MKL (best performance on x86_64 with MKL installed)
> cmake -DFFT_BACKEND=MKL ..
# Apple Accelerate (best performance on macOS/Apple Silicon)
> cmake -DFFT_BACKEND=Accelerate ..Apple Silicon / M4 Build:
> mkdir build && cd build
> cmake -DFFT_BACKEND=Accelerate \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_OSX_DEPLOYMENT_TARGET=15.0 ..
> make -j8The Apple Silicon build includes ARM NEON intrinsics for maximum performance.
-
SDDC_ALLOW_USB2— by default, opening the device fails if it enumerates at USB 2.0 High Speed, because the raw ADC stream (≥100 MB/s) exceeds USB 2.0 bandwidth (~40 MB/s) and samples would be silently dropped. SetSDDC_ALLOW_USB2=1to proceed anyway (e.g. for bench testing); leaving it unset, empty, or set to0keeps the strict check. -
SDDC_USB_RESET_CMD— optional recovery command run once if the device does not re-enumerate within ~5 seconds after firmware load (useful on macOS, where FX3 SuperSpeed re-enumeration can get stuck until the port is power-cycled). The command should power-cycle the specific hub port the device is on, e.g.:export SDDC_USB_RESET_CMD="/opt/homebrew/bin/uhubctl -l 2-2 -p 1 -a 2 -d 3"
Unset by default; nothing external is executed unless you set it.
\Core\ > Core logic of the component
r2iq.cpp > The logic to demodulize IQ from ADC real samples
FX3handler.cpp > Interface with firmware
RadioHandler.cpp > The abstraction of different radios
Radio\*.cpp > Hardware specific logic
\ExtIO_sddc\ > ExtIO_sddc sources,
extio_sddc.cpp > The implementation of EXTIO contract
tdialog.cpp > The Configuration GUI Dialog
\libsddc\ > libsddc lib
\SDDC_FX3\ > Firmware sources
This fork has been specifically optimized for the RX-888 Mk II and contains changes that have not been tested on other hardware models.
| Hardware Model | Compatibility | Notes |
|---|---|---|
| RX-888 Mk II | ✅ Full Support | Primary target platform, all features tested |
| RX-888 (original) | Should work but VHF fixes are Mk II-specific | |
| RX-888R2 | R828D tuner support present but not verified | |
| RX-888R3 | May work but optimizations not validated | |
| HF103 | HF-only mode, no VHF tuner changes apply | |
| BBRF103 | Similar to HF103, VHF changes not applicable | |
| RX999 | No tuner, may work for direct sampling |
If you are using hardware other than RX-888 Mk II, we recommend using the upstream repository for better compatibility.
The following changes are specific to the RX-888 Mk II and may not apply to other hardware:
- VHF Spectrum Mirroring Fix - Corrects R828D low-side injection behavior (Mk II specific)
- Performance Optimizations - Tested only on Mk II hardware
- API Enhancements - VGA gain control may behave differently on other models
- R828D IMR Calibration - Image rejection calibration via the tuner's internal power detector
- USB Open/Re-enumeration Hardening - Linux/macOS device-open reliability changes (see July 2026 change log)
VHF Tuner Fixes:
- Fix VHF mode spectrum mirroring caused by incorrect sideband inversion
- R828D tuner uses low-side injection, spectrum should not be inverted at IF
Performance Optimizations:
- Replace byte-by-byte ring buffer copy with memcpy (10-100x sync read improvement)
- Increase FFT processing threads from 1 to 4 for multi-core utilization
- AVX2 vectorization for int16→float conversion, complex multiply, and complex copy (x86_64)
- ARM NEON intrinsics for maximum performance on Apple Silicon M4 (~4.5x speedup)
- Apple Accelerate framework integration for optimized FFT on macOS
- FFT backend abstraction supporting FFTW, Intel MKL, and Apple Accelerate
- Lock-free ring buffer using std::atomic indices
- Reduced mutex contention in fine-tune mixer path
- Fixed FFT thread race conditions for reliable 128 Msps streaming
libsddc API Enhancements:
- Add VGA (AD8370) gain control functions
- Add GPIO control functions for direct hardware access
- Add tuner IF frequency configuration
- Add error handling with sddc_get_last_error()
- Improved sample rate documentation
Performance Benchmarks (Apple M4):
FFT Backend Performance (Accelerate framework):
Size | R2C (µs) | C2C Fwd (µs) | C2C Bwd (µs)
-------------------------------------------------------
4096 | 8.66 | 10.67 | 7.44
2048 | 1.97 | 2.86 | 3.35
1024 | 0.86 | 1.29 | 1.55
NEON Optimization Speedups:
- int16→float conversion: 7.7x faster
- Complex multiplication: 3.4x faster
- Complex copy/conjugate: 3.2x faster
- Overall pipeline: ~4.5x faster (enables 128 Msps real-time streaming)
Tuner:
- R828D IMR (image rejection) calibration using the tuner's internal power detector
USB / device-open reliability (Linux and macOS):
- Firmware-load re-enumeration rewritten: 500 ms polling with a 10 s budget (fast hosts open in under a second; previously a fixed multi-second wait), with automatic firmware re-load if the device comes back in boot loader state (e.g. after a port power cycle)
- Optional
SDDC_USB_RESET_CMDrecovery hook for stuck re-enumeration on macOS (see Runtime environment variables above) - USB 2.0 High Speed links are rejected by default with a clear error instead
of silently streaming corrupted samples;
SDDC_ALLOW_USB2=1overrides - Fixed libusb context lifecycle: repeated open/close no longer leaks a context and its file descriptors per cycle
- Device listing survives unreadable string descriptors (the FX3 boot loader on macOS fails string reads) and no longer truncates the serial number
libsddc:
- Fixed the async callback under-reporting the data size by half, which halved the effective sample rate seen by consumers
- Sync read ring buffer grown from 1 MB to 16 MB to survive full-rate bursts
Testing:
- Unit test suite repaired (mocks updated for the I2C interface) and passing 69/69 on both Linux x86_64 and Apple Silicon
- End-to-end hardware validation on RX-888 Mk II under macOS 26: cold open from boot loader in 0.7 s, ~32 Msps streaming, clean teardown
For references, acknowledgments, and full project history, see the upstream repository.