This code is forked from KiwiSDR project.
- Use Linux Kernel Driver to interactive with hardware. No strict timing requirement on code.
- Use Linux Pthread scheduler to replace userland task scheduler. Add lock protection in many code paths, which was assumed running in single core.
- Use native thread instead of process for most blocking opertaions.
- Use hardware GPS instead of Software Defined GPS receiver
- Use PPS signal to tune ADC clock.
- Disable ToDA extention for now
- Use CMake as build system instead of Makefile, gcc as compiler instead of clang.
The instruction is only tested on Debian. It may work on Ubuntu as well but not testsed.
- Install necessary packages
# sudo apt install qemu-user-static binfmt-support wget
- Create a virtual ARM enviroment (!!not a VM!!)
# mkdir ~/alpine
# cd ~/alpine
# wget http://dl-cdn.alpinelinux.org/alpine/v3.20/main/armv7/apk-tools-static-2.14.4-r1.apk
# mkdir alpine-apk
# tar -zxf apk-tools-static-2.14.4-r1.apk --directory=alpine-apk --warning=no-unknown-keyword
# mkdir -p alpine-root/usr/bin
# cp /usr/bin/qemu-arm-static alpine-root/usr/bin/
# mkdir -p alpine-root/etc
# cp /etc/resolv.conf alpine-root/etc/
# cp -r alpine-apk/sbin alpine-root/
# sudo chroot alpine-root /sbin/apk.static --repository http://dl-cdn.alpinelinux.org/alpine/v3.20/main --update-cache --allow-untrusted --initdb add alpine-base
Configure apk repo, add main and community channels.
# echo http://dl-cdn.alpinelinux.org/alpine/v3.20/main | sudo tee alpine-root/etc/apk/repositories
# echo http://dl-cdn.alpinelinux.org/alpine/v3.20/community | sudo tee -a alpine-root/etc/apk/repositories
- Get into the virtual enviroment, This command will be used next time after you exist from the virtual enviroment
sudo chroot alpine-root /bin/sh --login
run the following commands to install the build tools
# apk update
# apk add openssh-server wpa_supplicant git dhcpcd dnsmasq u-boot-tools hostapd iptables avahi dbus chrony gpsd curl-dev htop frp jq libunwind zlib noip2 noip2-openrc netpbm musl-dev linux-headers g++ gcc cmake make minify fftw-dev fdk-aac-dev pkgconf perl gpsd-dev libunwind-dev zlib-dev sqlite-dev sqlite-static libconfig-static libconfig-dev patch automake autoconf
- Inside the virtual enviroment, it is like a normal linux. You can use git to enlist the code, update submodules and use cmake to build the binary.
# cd /root
# git clone https://github.com/raspsdr/server
# cd server
# git submodule update --init
# mkdir build
# cd build
# cmake ..
# cmake --build .
-
Use the compiled binary websdr.bin to replace the one in the root of your TF card. When
ENABLE_ACARS=ON, also installbuild/acarsdecas/media/mmcblk0p1/acarsdecand make it executable. The server feeds this audio-only decoder raw 12 kHz mono PCM. The bundled frontend links directly to the acarsdec decoder core and does not require SDR or audio-file libraries. The AIS decoder is built intowebsdr.bin; no separate AIS executable is installed. The extension receives one selected NFM channel: AIS 1 at 161.975 MHz or AIS 2 at 162.025 MHz. -
Happy hack
The native harness builds the server for the current Linux host, replaces the Zynq hardware interface with deterministic fake receiver and waterfall data, and opens the UI in headless Chromium.
Install the browser test dependency and Chromium once:
npm install
npx playwright install chromiumRun the complete build and browser smoke test:
npm run test:native-browserThe native build runs its CTest regressions before opening Chromium. These include a dependency-free JavaScript MQTT broker that verifies the server's credentials, client ID, topics, QoS, and JSON payloads for startup and status publications. Run all JavaScript and native browser regressions with:
npm run test:regressionGitHub Actions runs two verification jobs on every push and pull request. One runs the native host regressions, while a separate job performs a non-harness Release build that compiles and links the production Zynq source path. The latter is still an x86 compile check and does not replace validation on Zynq hardware.
Set WEBSDR_HARNESS_PORT to use a port other than 8073. The native harness
does not start GPS, update, registration, LED, or other target-only services.
DRM is excluded because its decoder processes depend on the target FDK-AAC
runtime.
The browser UI uses a compatibility-first design system layered over the
existing w3_* helpers. The implementation is intentionally framework-free so
the receiver, admin interface, and extensions keep their existing callback,
WebSocket, canvas, and embedded-asset behavior.
web/kiwi/modern_ui.cssdefines semantic design tokens and the shared receiver, admin, extension, control, focus, and responsive styles.web/kiwi/modern_ui.jsapplies and persists the selected color theme.web/kiwi/w3_util.jsemits stableui-*component hooks while retaining the legacy W3.CSS classes used by existing callers and external extensions.web/web.cppandCMakeLists.txtmust both include any new UI asset so development loading and release embedding stay consistent.
The built-in modern themes are Midnight (default), Ember, and
Cloud. Classic retains the legacy layout and palette.
They override semantic tokens through data-ui-theme on the document root.
Each uses neutral surfaces, one primary accent, and semantic status colors
instead of the legacy per-control rainbow palette. New themes should change
tokens instead of adding theme-specific component markup. Spectrum and
waterfall colormaps remain independent from the application theme.
When changing the UI:
- Preserve existing element IDs, callback signatures, panel metadata, and canvas sizing behavior.
- Prefer shared
ui-*hooks or semantic tokens over page-specific color overrides. - Keep keyboard focus visible and respect
prefers-reduced-motion. - Run
npm run test:native-browser. The smoke test checks all themes plus desktop, tablet, phone portrait, and phone landscape receiver layouts, and desktop/tablet/phone admin layouts.