Compare commits
No commits in common. "main" and "portapack-detection" have entirely different histories.
main
...
portapack-
21 changed files with 212 additions and 465 deletions
149
.github/workflows/build.yml
vendored
149
.github/workflows/build.yml
vendored
|
|
@ -17,127 +17,70 @@ jobs:
|
|||
host:
|
||||
strategy:
|
||||
matrix:
|
||||
os: ['macos', 'ubuntu', 'windows']
|
||||
cmake: ['3.10.0', '3.21.7', '4.2.6', 'latest']
|
||||
compiler: ['gcc', 'msvc']
|
||||
sys:
|
||||
- {os: 'macos', shell: 'bash'}
|
||||
- {os: 'ubuntu', shell: 'bash'}
|
||||
- {os: 'windows', shell: 'pwsh'}
|
||||
- {os: 'windows', shell: 'msys2'}
|
||||
cmake: ['3.10.0', '3.16.0', '3.21.0', '4.0.0', 'latest']
|
||||
exclude:
|
||||
# MSVC only runs on Windows.
|
||||
- os: 'macos'
|
||||
compiler: 'msvc'
|
||||
- os: 'ubuntu'
|
||||
compiler: 'msvc'
|
||||
# We can't use the oldest CMake versions on Windows.
|
||||
- os: 'windows'
|
||||
# GitHub runners use Visual Studio 2022. Support added in CMake 3.21.
|
||||
- sys: {os: 'windows', shell: 'pwsh'}
|
||||
cmake: '3.10.0'
|
||||
# The in-between CMake versions aren't so intersting with GCC.
|
||||
- compiler: 'gcc'
|
||||
cmake: '3.21.7'
|
||||
- compiler: 'gcc'
|
||||
cmake: '4.2.6'
|
||||
- sys: {os: 'windows', shell: 'pwsh'}
|
||||
cmake: '3.16.0'
|
||||
# MSYS2 always supplies the latest cmake.
|
||||
- sys: {os: 'windows', shell: 'msys2'}
|
||||
cmake: '3.10.0'
|
||||
- sys: {os: 'windows', shell: 'msys2'}
|
||||
cmake: '3.16.0'
|
||||
- sys: {os: 'windows', shell: 'msys2'}
|
||||
cmake: '3.21.0'
|
||||
- sys: {os: 'windows', shell: 'msys2'}
|
||||
cmake: '4.0.0'
|
||||
include:
|
||||
# Shell selection
|
||||
- os: 'macos'
|
||||
shell: 'bash'
|
||||
- os: 'ubuntu'
|
||||
shell: 'bash'
|
||||
- os: 'windows'
|
||||
compiler: 'msvc'
|
||||
shell: 'pwsh'
|
||||
- os: 'windows'
|
||||
compiler: 'gcc'
|
||||
shell: 'msys2'
|
||||
# MSVC version selection
|
||||
- cmake: '3.21.7'
|
||||
msvc: '17.14'
|
||||
- cmake: '4.2.6'
|
||||
msvc: 'latest'
|
||||
- cmake: 'latest'
|
||||
msvc: 'latest'
|
||||
# CMake generator selection
|
||||
- os: 'macos'
|
||||
generator: 'Unix Makefiles'
|
||||
- os: 'ubuntu'
|
||||
generator: 'Unix Makefiles'
|
||||
- compiler: 'msvc'
|
||||
cmake: '3.21.7'
|
||||
generator: 'Visual Studio 17 2022'
|
||||
- compiler: 'msvc'
|
||||
cmake: '4.2.6'
|
||||
generator: 'Visual Studio 18 2026'
|
||||
- compiler: 'msvc'
|
||||
cmake: 'latest'
|
||||
generator: 'Visual Studio 18 2026'
|
||||
- os: 'windows'
|
||||
compiler: 'gcc'
|
||||
generator: 'MSYS Makefiles'
|
||||
# Additional CMake arguments
|
||||
- os: 'windows'
|
||||
compiler: 'msvc'
|
||||
- sys: {os: 'windows', shell: 'pwsh'}
|
||||
cmake_args: >-
|
||||
-DPKG_CONFIG_EXECUTABLE=C:/vcpkg/installed/x64-windows/tools/pkgconf/pkgconf.exe
|
||||
-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||
--install-prefix=$env:GITHUB_WORKSPACE/install
|
||||
- os: 'windows'
|
||||
compiler: 'gcc'
|
||||
- sys: {os: 'windows', shell: 'msys2'}
|
||||
cmake_args: >-
|
||||
--install-prefix=/usr/local
|
||||
# CMake 3.10 uses --build with --target install
|
||||
- cmake: '3.10.0'
|
||||
install_cmd: --build
|
||||
install_args: --target install
|
||||
# Later versions just use --install
|
||||
- cmake: '3.21.7'
|
||||
install_cmd: --install
|
||||
- cmake: '4.2.6'
|
||||
install_cmd: --install
|
||||
- cmake: 'latest'
|
||||
install_cmd: --install
|
||||
# We need sudo on MacOS and Ubuntu only
|
||||
- os: macos
|
||||
sudo: sudo
|
||||
- os: ubuntu
|
||||
sudo: sudo
|
||||
|
||||
|
||||
# Don't cancel all builds when one fails
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}-latest
|
||||
runs-on: ${{ matrix.sys.os }}-latest
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: '${{ matrix.shell }} {0}'
|
||||
shell: '${{ matrix.sys.shell }} {0}'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup cmake
|
||||
uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: ${{ matrix.cmake }}
|
||||
if: matrix.shell != 'msys2'
|
||||
|
||||
- name: Install MSVC (Windows)
|
||||
uses: k3DW/setup-msvc@v1
|
||||
with:
|
||||
vs-version: ${{ matrix.msvc }}
|
||||
if: matrix.compiler == 'msvc' && matrix.msvc != 'latest'
|
||||
if: matrix.sys.shell != 'msys2'
|
||||
|
||||
- name: Install dependencies (macOS)
|
||||
run: brew install fftw
|
||||
if: matrix.os == 'macos'
|
||||
if: matrix.sys.os == 'macos'
|
||||
|
||||
- name: Install dependencies (Ubuntu)
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install libfftw3-dev libusb-1.0-0-dev
|
||||
if: matrix.os == 'ubuntu'
|
||||
if: matrix.sys.os == 'ubuntu'
|
||||
|
||||
- name: Install dependencies (Windows)
|
||||
run: vcpkg install --triplet=x64-windows libusb fftw3 pthreads pkgconf
|
||||
if: matrix.os == 'windows' && matrix.shell != 'msys2'
|
||||
if: matrix.sys.os == 'windows' && matrix.sys.shell != 'msys2'
|
||||
|
||||
- name: Setup MSYS (Windows)
|
||||
if: matrix.os == 'windows' && matrix.shell == 'msys2'
|
||||
if: matrix.sys.os == 'windows' && matrix.sys.shell == 'msys2'
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: UCRT64
|
||||
|
|
@ -155,7 +98,7 @@ jobs:
|
|||
run: |
|
||||
cmake -E make_directory host/build
|
||||
cd host/build
|
||||
cmake .. -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE=Release ${{matrix.cmake_args}}
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release ${{matrix.cmake_args}}
|
||||
cmake --build . --config Release
|
||||
|
||||
# Build libhackrf ONLY
|
||||
|
|
@ -164,12 +107,22 @@ jobs:
|
|||
run: |
|
||||
cmake -E make_directory host/libhackrf/build
|
||||
cd host/libhackrf/build
|
||||
cmake .. -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }}
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }}
|
||||
cmake --build . --config Release
|
||||
|
||||
- name: Install (libhackrf)
|
||||
run: |
|
||||
${{ matrix.sudo }} cmake ${{ matrix.install_cmd }} host/libhackrf/build ${{ matrix.install_args }} --config Release
|
||||
sudo cmake --install host/libhackrf/build --config Release
|
||||
if: matrix.sys.os != 'windows' && matrix.cmake != '3.10.0'
|
||||
|
||||
- name: Install (libhackrf, CMake 3.10)
|
||||
run: |
|
||||
sudo cmake --build host/libhackrf/build --target install --config Release
|
||||
if: matrix.sys.os != 'windows' && matrix.cmake == '3.10.0'
|
||||
|
||||
- name: Install (libhackrf, Windows)
|
||||
run: cmake --install host/libhackrf/build --config Release
|
||||
if: matrix.sys.os == 'windows'
|
||||
|
||||
# Build hackrf-tools ONLY
|
||||
|
||||
|
|
@ -177,12 +130,22 @@ jobs:
|
|||
run: |
|
||||
cmake -E make_directory host/hackrf-tools/build
|
||||
cd host/hackrf-tools/build
|
||||
cmake .. -G "${{ matrix.generator }}" -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }}
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_args }}
|
||||
cmake --build . --config Release
|
||||
|
||||
- name: Install (hackrf-tools)
|
||||
run: |
|
||||
${{ matrix.sudo }} cmake ${{ matrix.install_cmd }} host/hackrf-tools/build ${{ matrix.install_args }}
|
||||
sudo cmake --install host/hackrf-tools/build --config Release
|
||||
if: matrix.sys.os != 'windows' && matrix.cmake != '3.10.0'
|
||||
|
||||
- name: Install (hackrf-tools, CMake 3.10)
|
||||
run: |
|
||||
sudo cmake --build host/hackrf-tools/build --target install --config Release
|
||||
if: matrix.sys.os != 'windows' && matrix.cmake == '3.10.0'
|
||||
|
||||
- name: Install (hackrf-tools, Windows)
|
||||
run: cmake --install host/hackrf-tools/build --config Release
|
||||
if: matrix.sys.os == 'windows'
|
||||
|
||||
# Publish the contents of install/bin (which should be the combination libhackrf and host-tools) for Windows
|
||||
- name: Publish Artifacts (Windows)
|
||||
|
|
@ -190,7 +153,7 @@ jobs:
|
|||
with:
|
||||
name: hackrf-tools-windows
|
||||
path: ${{github.workspace}}/install/bin
|
||||
if: matrix.os == 'windows' && matrix.cmake == 'latest' && matrix.shell == 'pwsh'
|
||||
if: matrix.sys.os == 'windows' && matrix.cmake == 'latest' && matrix.sys.shell == 'pwsh'
|
||||
|
||||
firmware:
|
||||
strategy:
|
||||
|
|
@ -216,7 +179,7 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
|
|
|
|||
2
.github/workflows/clang-format-check.yml
vendored
2
.github/workflows/clang-format-check.yml
vendored
|
|
@ -16,7 +16,7 @@ jobs:
|
|||
- check: 'firmware/hackrf_usb'
|
||||
exclude: ''
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run clang-format-action
|
||||
uses: jidicula/clang-format-action@v4.6.2
|
||||
with:
|
||||
|
|
|
|||
135
Jenkinsfile
vendored
135
Jenkinsfile
vendored
|
|
@ -39,15 +39,31 @@ pipeline {
|
|||
timeout(time: 20, unit: 'MINUTES')
|
||||
}
|
||||
steps {
|
||||
runCommand("Install Host Tools", './ci-scripts/install_host.sh', 3, 1, 'MINUTES')
|
||||
runCommand("Build HackRF One Firmware", './ci-scripts/build_firmware.sh HACKRF_ONE', 3, 1, 'MINUTES')
|
||||
lock('HIL_hubs') {
|
||||
script {
|
||||
allOff()
|
||||
runTest("Check Host", 'h1_eut', './ci-scripts/test_host.sh')
|
||||
runTest("HackRF One HIL Test", 'h1_tester h1_eut', h1_test)
|
||||
runTest("SGPIO Debug Test", 'h1_eut', 'python3 ci-scripts/test_sgpio_debug.py')
|
||||
}
|
||||
sh './ci-scripts/install_host.sh'
|
||||
sh './ci-scripts/build_firmware.sh HACKRF_ONE'
|
||||
script {
|
||||
allOff()
|
||||
reset('h1_eut')
|
||||
}
|
||||
sh 'sleep 1s'
|
||||
retry(3) {
|
||||
sh './ci-scripts/test_host.sh'
|
||||
}
|
||||
script {
|
||||
reset('h1_tester h1_eut')
|
||||
}
|
||||
sh 'sleep 1s'
|
||||
script {
|
||||
// Allow up to 3 retries 5 minutes each for the HIL test
|
||||
runCommand(3, 5, 'MINUTES', "HackRF One Test", h1_test)
|
||||
}
|
||||
script {
|
||||
allOff()
|
||||
reset('h1_eut')
|
||||
}
|
||||
sh 'sleep 1s'
|
||||
retry(3) {
|
||||
sh 'python3 ci-scripts/test_sgpio_debug.py'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -63,17 +79,32 @@ pipeline {
|
|||
timeout(time: 20, unit: 'MINUTES')
|
||||
}
|
||||
steps {
|
||||
runCommand("Install Host Tools", './ci-scripts/install_host.sh', 3, 1, 'MINUTES')
|
||||
runCommand("Build Universal Firmware", './ci-scripts/build_firmware.sh UNIVERSAL', 3, 1, 'MINUTES')
|
||||
lock('HIL_hubs') {
|
||||
script {
|
||||
allOff()
|
||||
runTest("Check Host", 'h1_eut', './ci-scripts/test_host.sh')
|
||||
runTest("HackRF One HIL Test", 'h1_tester h1_eut', h1_test)
|
||||
runTest("SGPIO Debug Test", 'h1_eut', 'python3 ci-scripts/test_sgpio_debug.py')
|
||||
}
|
||||
sh './ci-scripts/install_host.sh'
|
||||
sh './ci-scripts/build_firmware.sh UNIVERSAL'
|
||||
script {
|
||||
allOff()
|
||||
reset('h1_eut')
|
||||
}
|
||||
sh 'sleep 1s'
|
||||
retry(3) {
|
||||
sh './ci-scripts/test_host.sh'
|
||||
}
|
||||
script {
|
||||
reset('h1_tester h1_eut')
|
||||
}
|
||||
sh 'sleep 1s'
|
||||
script {
|
||||
// Allow up to 3 retries 5 minutes each for the HIL test
|
||||
runCommand(3, 5, 'MINUTES', "HackRF One Test", h1_test)
|
||||
}
|
||||
script {
|
||||
allOff()
|
||||
reset('h1_eut')
|
||||
}
|
||||
sh 'sleep 1s'
|
||||
retry(3) {
|
||||
sh 'python3 ci-scripts/test_sgpio_debug.py'
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
stage('Test HackRF Pro with BOARD=PRALINE') {
|
||||
|
|
@ -88,14 +119,23 @@ pipeline {
|
|||
timeout(time: 20, unit: 'MINUTES')
|
||||
}
|
||||
steps {
|
||||
runCommand("Install Host Tools", './ci-scripts/install_host.sh', 3, 1, 'MINUTES')
|
||||
runCommand("Build Praline Firmware", './ci-scripts/build_firmware.sh PRALINE', 3, 1, 'MINUTES')
|
||||
lock('HIL_hubs') {
|
||||
script {
|
||||
allOff()
|
||||
runTest("Check Host", 'hpro_eut', './ci-scripts/test_host.sh')
|
||||
runTest("HackRF Pro HIL Test", 'hpro_tester hpro_eut', hpro_test)
|
||||
}
|
||||
sh './ci-scripts/install_host.sh'
|
||||
sh './ci-scripts/build_firmware.sh PRALINE'
|
||||
script {
|
||||
allOff()
|
||||
reset('hpro_eut')
|
||||
}
|
||||
sh 'sleep 1s'
|
||||
retry(3) {
|
||||
sh './ci-scripts/test_host.sh'
|
||||
}
|
||||
script {
|
||||
reset('hpro_tester hpro_eut')
|
||||
}
|
||||
sh 'sleep 1s'
|
||||
script {
|
||||
// Allow up to 3 retries 5 minutes each for the HIL test
|
||||
runCommand(3, 5, 'MINUTES', "HackRF Pro Test", hpro_test)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -111,14 +151,23 @@ pipeline {
|
|||
timeout(time: 20, unit: 'MINUTES')
|
||||
}
|
||||
steps {
|
||||
runCommand("Install Host Tools", './ci-scripts/install_host.sh', 3, 1, 'MINUTES')
|
||||
runCommand("Build Universal Firmware", './ci-scripts/build_firmware.sh UNIVERSAL', 3, 1, 'MINUTES')
|
||||
lock('HIL_hubs') {
|
||||
script {
|
||||
allOff()
|
||||
runTest("Check Host", 'hpro_eut', './ci-scripts/test_host.sh')
|
||||
runTest("HackRF Pro HIL Test", 'hpro_tester hpro_eut', hpro_test)
|
||||
}
|
||||
sh './ci-scripts/install_host.sh'
|
||||
sh './ci-scripts/build_firmware.sh UNIVERSAL'
|
||||
script {
|
||||
allOff()
|
||||
reset('hpro_eut')
|
||||
}
|
||||
sh 'sleep 1s'
|
||||
retry(3) {
|
||||
sh './ci-scripts/test_host.sh'
|
||||
}
|
||||
script {
|
||||
reset('hpro_tester hpro_eut')
|
||||
}
|
||||
sh 'sleep 1s'
|
||||
script {
|
||||
// Allow up to 3 retries 5 minutes each for the HIL test
|
||||
runCommand(3, 5, 'MINUTES', "HackRF Pro Test", hpro_test)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -135,15 +184,15 @@ pipeline {
|
|||
|
||||
def allOff() {
|
||||
// Allow up to 3 retries, 20 seconds each, for the USB hub port power server to respond appropriately
|
||||
runCommand('USB hub port power server command', "hubs all off", 3, 20, 'SECONDS')
|
||||
runCommand(3, 20, 'SECONDS', 'USB hub port power server command', "hubs all off")
|
||||
}
|
||||
|
||||
def reset(devices) {
|
||||
// Allow up to 3 retries, 20 seconds each, for the USB hub port power server to respond appropriately
|
||||
runCommand('USB hub port power server command', "hubs ${devices} reset", 3, 20, 'SECONDS')
|
||||
runCommand(3, 20, 'SECONDS', 'USB hub port power server command', "hubs ${devices} reset")
|
||||
}
|
||||
|
||||
def runCommand(title, cmd, retries, time, unit) {
|
||||
def runCommand(retries, time, unit, title, cmd) {
|
||||
retry(retries) {
|
||||
try {
|
||||
timeout(time: time, unit: unit) {
|
||||
|
|
@ -165,13 +214,3 @@ def runCommand(title, cmd, retries, time, unit) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
def runTest(title, devices, cmd) {
|
||||
retry(3) {
|
||||
// reset() retains it's own internal retries
|
||||
reset(devices)
|
||||
sh 'sleep 1s'
|
||||
// run the test with 0 internal retries and 3 external retries to ensure resets between runs
|
||||
runCommand(title, cmd, 0, 5, 'MINUTES')
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include "hackrf_ui.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "i2c_lpc.h"
|
||||
#include "platform_detect.h"
|
||||
#include "sgpio.h"
|
||||
#include "si5351c.h"
|
||||
|
|
@ -34,6 +36,8 @@
|
|||
|
||||
void clock_gen_init(void)
|
||||
{
|
||||
i2c_bus_start(si5351c.bus, &i2c_config_fast_clock);
|
||||
|
||||
si5351c_init(&si5351c);
|
||||
si5351c_disable_all_outputs(&si5351c);
|
||||
si5351c_disable_oeb_pin_control(&si5351c);
|
||||
|
|
@ -116,6 +120,7 @@ void clock_gen_init(void)
|
|||
|
||||
void clock_gen_shutdown(void)
|
||||
{
|
||||
i2c_bus_start(si5351c.bus, &i2c_config_fast_clock);
|
||||
si5351c_disable_all_outputs(&si5351c);
|
||||
si5351c_disable_oeb_pin_control(&si5351c);
|
||||
si5351c_power_down_all_clocks(&si5351c);
|
||||
|
|
|
|||
|
|
@ -54,20 +54,3 @@ typedef uint64_t fp_28_36_t;
|
|||
#define SR_FP_MHZ(mhz) (mhz##ULL * SR_FP_ONE_MHZ)
|
||||
#define SR_FP_KHZ(khz) (khz##ULL * SR_FP_ONE_KHZ)
|
||||
#define SR_FP_HZ(hz) (hz##ULL * SR_FP_ONE_HZ)
|
||||
|
||||
/* 1.63 fixed point */
|
||||
typedef uint64_t fp_1_63_t;
|
||||
|
||||
#define FRAC_ONE (1ULL << 63)
|
||||
|
||||
/* one hundredth in 1.63 fixed point */
|
||||
#define FRAC_ONE_PERCENT (FRAC_ONE / (100ULL))
|
||||
|
||||
/* one thousandth in 1.63 fixed point */
|
||||
#define FRAC_ONE_PERMILLE (FRAC_ONE / (1000ULL))
|
||||
|
||||
/* one millionth in 1.63 fixed point */
|
||||
#define FRAC_ONE_PPM (FRAC_ONE / (1000000ULL))
|
||||
|
||||
/* one billionth in 1.63 fixed point */
|
||||
#define FRAC_ONE_PPB (FRAC_ONE / (1000000000ULL))
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@
|
|||
#include <libopencm3/lpc43xx/i2c.h>
|
||||
#include <libopencm3/lpc43xx/memorymap.h>
|
||||
|
||||
#include "cpu_clock.h"
|
||||
|
||||
/* Driver instances. */
|
||||
i2c_bus_t i2c0 = {
|
||||
.obj = (void*) I2C0_BASE,
|
||||
|
|
@ -43,7 +41,7 @@ i2c_bus_t i2c1 = {
|
|||
};
|
||||
|
||||
const i2c_lpc_config_t i2c_config_fast_clock = {
|
||||
.clock_khz = 400,
|
||||
.duty_cycle_count = 255,
|
||||
};
|
||||
|
||||
/* FIXME return i2c0 status from each function */
|
||||
|
|
@ -53,9 +51,7 @@ void i2c_lpc_start(i2c_bus_t* const bus, const void* const _config)
|
|||
const i2c_lpc_config_t* const config = _config;
|
||||
|
||||
const uint32_t port = (uint32_t) bus->obj;
|
||||
const uint16_t duty_cycle_count =
|
||||
(cpu_clock_mhz * (2000 / config->clock_khz)) / 4;
|
||||
i2c_init(port, duty_cycle_count);
|
||||
i2c_init(port, config->duty_cycle_count);
|
||||
}
|
||||
|
||||
void i2c_lpc_stop(i2c_bus_t* const bus)
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "i2c_bus.h"
|
||||
|
||||
typedef struct {
|
||||
const uint16_t clock_khz;
|
||||
const uint16_t duty_cycle_count;
|
||||
} i2c_lpc_config_t;
|
||||
|
||||
void i2c_lpc_start(i2c_bus_t* const bus, const void* const config);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include "rf_path.h"
|
||||
#include "transceiver_mode.h"
|
||||
#include "tuning.h"
|
||||
#include "u128.h"
|
||||
#ifdef IS_PRALINE
|
||||
#include "fpga.h"
|
||||
#include "tune_config.h"
|
||||
|
|
@ -54,7 +53,7 @@ void radio_init(radio_t* const radio)
|
|||
}
|
||||
}
|
||||
radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF;
|
||||
radio->config[RADIO_BANK_REQUESTED][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF;
|
||||
radio->config[RADIO_BANK_ACTIVE][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF;
|
||||
radio->config[RADIO_BANK_IDLE][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF;
|
||||
radio->config[RADIO_BANK_RX][RADIO_OPMODE] = TRANSCEIVER_MODE_RX;
|
||||
radio->config[RADIO_BANK_TX][RADIO_OPMODE] = TRANSCEIVER_MODE_TX;
|
||||
|
|
@ -78,7 +77,7 @@ radio_error_t radio_reg_write(
|
|||
}
|
||||
|
||||
switch (bank) {
|
||||
case RADIO_BANK_REQUESTED:
|
||||
case RADIO_BANK_ACTIVE:
|
||||
mark_dirty(radio, reg);
|
||||
/* fall through */
|
||||
case RADIO_BANK_IDLE:
|
||||
|
|
@ -133,75 +132,6 @@ static uint32_t radio_update_direction(radio_t* const radio, uint64_t* bank)
|
|||
return (1 << RADIO_OPMODE);
|
||||
}
|
||||
|
||||
/* Apply correction to a true frequency to get an adjusted frequency. */
|
||||
static uint64_t adjust(uint64_t freq, uint64_t correction)
|
||||
{
|
||||
/* skip if we can */
|
||||
if (correction == FRAC_ONE) {
|
||||
return freq;
|
||||
}
|
||||
|
||||
u128 product = u128_multiply(freq, correction);
|
||||
|
||||
/* product >> 63 */
|
||||
return (product.hi << 1) | (product.lo >> 63);
|
||||
}
|
||||
|
||||
/* Given an adjusted frequency and correction, return the true frequency. */
|
||||
static uint64_t unadjust(uint64_t freq, uint64_t correction)
|
||||
{
|
||||
/* skip if we can */
|
||||
if (correction == FRAC_ONE) {
|
||||
return freq;
|
||||
}
|
||||
|
||||
/* (1 << (63 + 63)) */
|
||||
u128 numerator = (u128){
|
||||
.hi = 1ULL << 62,
|
||||
.lo = 0,
|
||||
};
|
||||
u128 denominator = (u128){
|
||||
.hi = 0,
|
||||
.lo = correction,
|
||||
};
|
||||
u128 reciprocal = u128_divide(numerator, denominator);
|
||||
return adjust(freq, reciprocal.lo);
|
||||
}
|
||||
|
||||
static uint64_t restrict_correction(uint64_t requested_correction)
|
||||
{
|
||||
/* Correction should be in the range 0.99 to 1.01 */
|
||||
const uint64_t min_correction = FRAC_ONE - FRAC_ONE_PERCENT;
|
||||
const uint64_t max_correction = FRAC_ONE + FRAC_ONE_PERCENT;
|
||||
if (requested_correction >= min_correction &&
|
||||
requested_correction <= max_correction) {
|
||||
return requested_correction;
|
||||
} else {
|
||||
return FRAC_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t set_lo(uint64_t freq_lo, uint64_t correction, bool apply)
|
||||
{
|
||||
fp_40_24_t corrected_lo = adjust(freq_lo, correction);
|
||||
fp_40_24_t achieved_lo = mixer_set_frequency(&mixer, corrected_lo, apply);
|
||||
return unadjust(achieved_lo, correction);
|
||||
}
|
||||
|
||||
static uint64_t set_if(uint64_t freq_if, uint64_t correction, bool apply)
|
||||
{
|
||||
fp_40_24_t corrected_if = adjust(freq_if, correction);
|
||||
fp_40_24_t achieved_if = max283x_set_frequency(&max283x, corrected_if, apply);
|
||||
return unadjust(achieved_if, correction);
|
||||
}
|
||||
|
||||
static uint64_t set_afe_rate(uint64_t afe_rate, uint64_t correction, bool apply)
|
||||
{
|
||||
fp_28_36_t corrected_rate = adjust(afe_rate, correction);
|
||||
fp_28_36_t achieved_rate = sample_rate_set(corrected_rate, apply);
|
||||
return unadjust(achieved_rate, correction);
|
||||
}
|
||||
|
||||
#define ABSOLUTE_MIN_AFE_RATE SR_FP_KHZ(200)
|
||||
#define ABSOLUTE_MAX_AFE_RATE SR_FP_KHZ(43600)
|
||||
#define MAX_SUPPORTED_AFE_RATE SR_FP_KHZ(40000)
|
||||
|
|
@ -253,9 +183,6 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank)
|
|||
bool new_n = false;
|
||||
|
||||
const uint64_t requested_rate = bank[RADIO_SAMPLE_RATE];
|
||||
const uint64_t requested_correction = bank[RADIO_CLOCK_CORRECTION];
|
||||
|
||||
uint64_t correction = restrict_correction(requested_correction);
|
||||
|
||||
if (requested_rate != RADIO_UNSET) {
|
||||
rate = MIN(requested_rate, MAX_MCU_RATE);
|
||||
|
|
@ -309,7 +236,7 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank)
|
|||
new_n = (n != previous_n);
|
||||
|
||||
afe_rate = rate << n;
|
||||
afe_rate = set_afe_rate(afe_rate, correction, false);
|
||||
afe_rate = sample_rate_set(afe_rate, false);
|
||||
previous_rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE];
|
||||
if ((previous_n == RADIO_UNSET) || previous_rate == RADIO_UNSET) {
|
||||
previous_afe_rate = RADIO_UNSET;
|
||||
|
|
@ -318,7 +245,7 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank)
|
|||
}
|
||||
new_afe_rate = (afe_rate != previous_afe_rate);
|
||||
if (new_afe_rate) {
|
||||
afe_rate = set_afe_rate(afe_rate, correction, true);
|
||||
afe_rate = sample_rate_set(afe_rate, true);
|
||||
}
|
||||
|
||||
rate = afe_rate >> n;
|
||||
|
|
@ -446,7 +373,6 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
|
|||
#ifdef IS_PRALINE
|
||||
const uint64_t requested_rotation = bank[RADIO_ROTATION];
|
||||
#endif
|
||||
const uint64_t requested_correction = bank[RADIO_CLOCK_CORRECTION];
|
||||
|
||||
const uint64_t applied_rf = radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF];
|
||||
const uint64_t applied_if = radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF];
|
||||
|
|
@ -455,8 +381,6 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
|
|||
radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT];
|
||||
const uint64_t applied_rotation =
|
||||
radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION];
|
||||
const uint64_t applied_correction =
|
||||
radio->config[RADIO_BANK_APPLIED][RADIO_CLOCK_CORRECTION];
|
||||
|
||||
uint64_t freq_rf = applied_rf;
|
||||
uint64_t analog_rf = applied_rf;
|
||||
|
|
@ -464,7 +388,6 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
|
|||
uint64_t freq_lo = applied_lo;
|
||||
uint64_t img_reject = applied_img_reject;
|
||||
uint64_t rotation = applied_rotation;
|
||||
uint64_t correction = applied_correction;
|
||||
|
||||
uint64_t opmode = bank[RADIO_OPMODE];
|
||||
if (opmode == RADIO_UNSET) {
|
||||
|
|
@ -482,12 +405,11 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
|
|||
img_reject = RF_PATH_FILTER_BYPASS;
|
||||
}
|
||||
}
|
||||
correction = restrict_correction(requested_correction);
|
||||
if (requested_if != RADIO_UNSET) {
|
||||
freq_if = set_if(requested_if, correction, false);
|
||||
freq_if = max283x_set_frequency(&max283x, requested_if, false);
|
||||
}
|
||||
if (requested_lo != RADIO_UNSET) {
|
||||
freq_lo = set_lo(requested_lo, correction, false);
|
||||
freq_lo = mixer_set_frequency(&mixer, freq_lo, false);
|
||||
}
|
||||
#ifdef IS_PRALINE
|
||||
if (IS_PRALINE) {
|
||||
|
|
@ -569,7 +491,7 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
|
|||
freq_lo = RADIO_UNSET;
|
||||
}
|
||||
if (freq_lo != RADIO_UNSET) {
|
||||
freq_lo = set_lo(freq_lo, correction, false);
|
||||
freq_lo = mixer_set_frequency(&mixer, freq_lo, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -591,12 +513,12 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
|
|||
|
||||
/* Apply settings. */
|
||||
if ((freq_if != applied_if) && (freq_if != RADIO_UNSET)) {
|
||||
freq_if = set_if(freq_if, correction, true);
|
||||
freq_if = max283x_set_frequency(&max283x, freq_if, true);
|
||||
radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF] = freq_if;
|
||||
changed |= (1 << RADIO_FREQUENCY_IF);
|
||||
}
|
||||
if ((freq_lo != applied_lo) && (freq_lo != RADIO_UNSET)) {
|
||||
freq_lo = set_lo(freq_lo, correction, true);
|
||||
freq_lo = mixer_set_frequency(&mixer, freq_lo, true);
|
||||
radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO] = freq_lo;
|
||||
changed |= (1 << RADIO_FREQUENCY_LO);
|
||||
}
|
||||
|
|
@ -639,10 +561,6 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
|
|||
radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] = freq_rf;
|
||||
changed |= (1 << RADIO_FREQUENCY_RF);
|
||||
}
|
||||
if ((correction != applied_correction) && (correction != RADIO_UNSET)) {
|
||||
radio->config[RADIO_BANK_APPLIED][RADIO_CLOCK_CORRECTION] = correction;
|
||||
changed |= (1 << RADIO_CLOCK_CORRECTION);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
|
@ -937,7 +855,7 @@ bool radio_update(radio_t* const radio)
|
|||
return false;
|
||||
}
|
||||
radio->regs_dirty = 0;
|
||||
memcpy(&tmp_bank[0], &(radio->config[RADIO_BANK_REQUESTED][0]), sizeof(tmp_bank));
|
||||
memcpy(&tmp_bank[0], &(radio->config[RADIO_BANK_ACTIVE][0]), sizeof(tmp_bank));
|
||||
nvic_enable_irq(NVIC_USB0_IRQ);
|
||||
|
||||
if ((dirty & RADIO_REG_GROUP_RATE) ||
|
||||
|
|
@ -998,14 +916,14 @@ void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode)
|
|||
nvic_disable_irq(NVIC_USB0_IRQ);
|
||||
for (uint8_t reg = 0; reg < RADIO_NUM_REGS; reg++) {
|
||||
value = radio->config[source_bank][reg];
|
||||
previous = radio->config[RADIO_BANK_REQUESTED][reg];
|
||||
previous = radio->config[RADIO_BANK_ACTIVE][reg];
|
||||
if ((value != RADIO_UNSET) && (value != previous)) {
|
||||
radio->config[RADIO_BANK_REQUESTED][reg] = value;
|
||||
radio->config[RADIO_BANK_ACTIVE][reg] = value;
|
||||
mark_dirty(radio, reg);
|
||||
}
|
||||
}
|
||||
|
||||
radio->config[RADIO_BANK_REQUESTED][RADIO_OPMODE] = mode;
|
||||
radio->config[RADIO_BANK_ACTIVE][RADIO_OPMODE] = mode;
|
||||
mark_dirty(radio, RADIO_OPMODE);
|
||||
nvic_enable_irq(NVIC_USB0_IRQ);
|
||||
radio_update(radio);
|
||||
|
|
|
|||
|
|
@ -165,23 +165,17 @@ typedef enum {
|
|||
* DC block enable of type bool.
|
||||
*/
|
||||
RADIO_DC_BLOCK = 22,
|
||||
/**
|
||||
* Correction factor for radio reference clock, of type fp_1_63_t.
|
||||
*/
|
||||
RADIO_CLOCK_CORRECTION = 23,
|
||||
} radio_register_t;
|
||||
|
||||
#define RADIO_NUM_REGS (24)
|
||||
#define RADIO_NUM_REGS (23)
|
||||
#define RADIO_UNSET (0xffffffffffffffff)
|
||||
|
||||
/* register groups for bitfield convenience */
|
||||
#define RADIO_REG_GROUP_RATE \
|
||||
((1 << RADIO_SAMPLE_RATE) | (1 << RADIO_RESAMPLE_TX) | \
|
||||
(1 << RADIO_RESAMPLE_RX) | (1 << RADIO_CLOCK_CORRECTION))
|
||||
#define RADIO_REG_GROUP_FREQ \
|
||||
((1 << RADIO_FREQUENCY_RF) | (1 << RADIO_FREQUENCY_IF) | \
|
||||
(1 << RADIO_FREQUENCY_LO) | (1 << RADIO_IMAGE_REJECT) | (1 << RADIO_ROTATION) | \
|
||||
(1 << RADIO_CLOCK_CORRECTION))
|
||||
#define RADIO_REG_GROUP_RATE \
|
||||
((1 << RADIO_SAMPLE_RATE) | (1 << RADIO_RESAMPLE_TX) | (1 << RADIO_RESAMPLE_RX))
|
||||
#define RADIO_REG_GROUP_FREQ \
|
||||
((1 << RADIO_FREQUENCY_RF) | (1 << RADIO_FREQUENCY_IF) | \
|
||||
(1 << RADIO_FREQUENCY_LO) | (1 << RADIO_IMAGE_REJECT) | (1 << RADIO_ROTATION))
|
||||
#define RADIO_REG_GROUP_BW \
|
||||
((1 << RADIO_BB_BANDWIDTH_TX) | (1 << RADIO_BB_BANDWIDTH_RX) | \
|
||||
(1 << RADIO_XCVR_TX_LPF) | (1 << RADIO_XCVR_RX_LPF) | \
|
||||
|
|
@ -191,7 +185,7 @@ typedef enum {
|
|||
(1 << RADIO_GAIN_RX_IF) | (1 << RADIO_GAIN_RX_BB))
|
||||
|
||||
/**
|
||||
* Register bank RADIO_BANK_REQUESTED stores the active configuration. Active
|
||||
* Register bank RADIO_BANK_ACTIVE stores the active configuration. Active
|
||||
* register settings are copied to the applied register when applied.
|
||||
*
|
||||
* The other three banks store settings that will be applied when switching to
|
||||
|
|
@ -202,7 +196,7 @@ typedef enum {
|
|||
*/
|
||||
typedef enum {
|
||||
RADIO_BANK_APPLIED = 0,
|
||||
RADIO_BANK_REQUESTED = 1,
|
||||
RADIO_BANK_ACTIVE = 1,
|
||||
RADIO_BANK_IDLE = 2,
|
||||
RADIO_BANK_RX = 3,
|
||||
RADIO_BANK_TX = 4,
|
||||
|
|
@ -237,7 +231,7 @@ typedef struct {
|
|||
void radio_init(radio_t* const radio);
|
||||
|
||||
/**
|
||||
* Write to one or more registers. Writes to RADIO_BANK_REQUESTED are applied at
|
||||
* Write to one or more registers. Writes to RADIO_BANK_ACTIVE are applied at
|
||||
* the next radio_update(). Writes to RADIO_BANK_APPLIED are not supported.
|
||||
*/
|
||||
radio_error_t radio_reg_write(
|
||||
|
|
@ -255,7 +249,7 @@ uint64_t radio_reg_read(
|
|||
const radio_register_t reg);
|
||||
|
||||
/**
|
||||
* Apply changes requested in RADIO_BANK_REQUESTED.
|
||||
* Apply changes requested in RADIO_BANK_ACTIVE.
|
||||
* Return true if any changes were applied.
|
||||
*/
|
||||
bool radio_update(radio_t* const radio);
|
||||
|
|
|
|||
|
|
@ -274,6 +274,17 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
|
|||
SI5351C_OUTPUT_DISABLE);
|
||||
}
|
||||
si5351c_regs_commit(drv);
|
||||
|
||||
#ifdef IS_H1_R9
|
||||
if (IS_H1_R9) {
|
||||
const platform_gpio_t* gpio = platform_gpio();
|
||||
if (drv->clk[drv->clkout_id].output_enable) {
|
||||
gpio_set(gpio->h1r9_clkout_en);
|
||||
} else {
|
||||
gpio_clear(gpio->h1r9_clkout_en);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void si5351c_set_int_mode(
|
||||
|
|
@ -328,7 +339,7 @@ bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv)
|
|||
}
|
||||
}
|
||||
|
||||
static void si5351c_clkout_ms_enable(si5351c_driver_t* const drv, bool enable)
|
||||
void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable)
|
||||
{
|
||||
drv->clk[drv->clkout_id].output_enable = enable;
|
||||
drv->clk[drv->clkout_id].power_down = !enable;
|
||||
|
|
@ -340,42 +351,12 @@ static void si5351c_clkout_ms_enable(si5351c_driver_t* const drv, bool enable)
|
|||
si5351c_enable_clock_outputs(drv);
|
||||
}
|
||||
|
||||
void si5351c_clkout_enable(si5351c_driver_t* const drv, bool enable)
|
||||
{
|
||||
#ifdef IS_H1_R9
|
||||
if (IS_H1_R9) {
|
||||
const platform_gpio_t* gpio = platform_gpio();
|
||||
|
||||
/* CLKOUT is shared with MCU_CLK, enable MS when either on. */
|
||||
bool mcu_clkin_enabled = gpio_read(gpio->h1r9_mcu_clk_en);
|
||||
bool ms_needed = enable | mcu_clkin_enabled;
|
||||
si5351c_clkout_ms_enable(drv, ms_needed);
|
||||
|
||||
/* Set GPIO to gate CLKOUT output downstream of MS. */
|
||||
gpio_write(gpio->h1r9_clkout_en, enable);
|
||||
}
|
||||
#endif
|
||||
#ifdef IS_NOT_H1_R9
|
||||
if (IS_NOT_H1_R9) {
|
||||
/* We have a dedicated CLKOUT multisynth. */
|
||||
si5351c_clkout_ms_enable(drv, enable);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void si5351c_mcu_clkin_enable(si5351c_driver_t* const drv, bool enable)
|
||||
{
|
||||
#ifdef IS_H1_R9
|
||||
if (IS_H1_R9) {
|
||||
const platform_gpio_t* gpio = platform_gpio();
|
||||
|
||||
/* MCU_CLK is shared with CLKOUT, enable MS when either on. */
|
||||
bool clkout_enabled = gpio_read(gpio->h1r9_clkout_en);
|
||||
bool ms_needed = enable | clkout_enabled;
|
||||
si5351c_clkout_ms_enable(drv, ms_needed);
|
||||
|
||||
/* Set GPIO to gate MCU_CLK output downstream of MS. */
|
||||
gpio_write(gpio->h1r9_mcu_clk_en, enable);
|
||||
/* MCU clock is shared with CLKOUT. */
|
||||
si5351c_clkout_enable(drv, enable);
|
||||
}
|
||||
#endif
|
||||
#ifdef IS_NOT_H1_R9
|
||||
|
|
|
|||
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright 2026 Great Scott Gadgets <info@greatscottgadgets.com>
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "u128.h"
|
||||
|
||||
/* From https://stackoverflow.com/a/58381061 */
|
||||
|
||||
u128 u128_multiply(uint64_t lhs, uint64_t rhs)
|
||||
{
|
||||
uint64_t lo_lo = (lhs & 0xFFFFFFFF) * (rhs & 0xFFFFFFFF);
|
||||
uint64_t hi_lo = (lhs >> 32) * (rhs & 0xFFFFFFFF);
|
||||
uint64_t lo_hi = (lhs & 0xFFFFFFFF) * (rhs >> 32);
|
||||
uint64_t hi_hi = (lhs >> 32) * (rhs >> 32);
|
||||
uint64_t cross = ((lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi);
|
||||
return (u128){
|
||||
.hi = ((hi_lo >> 32) + (cross >> 32) + hi_hi),
|
||||
.lo = ((cross << 32) | (lo_lo & 0xFFFFFFFF)),
|
||||
};
|
||||
}
|
||||
|
||||
/* From https://stackoverflow.com/a/70052545 */
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
#define SUBCcc(a,b,cy,t0,t1,t2) \
|
||||
(t0=(b)+cy, t1=(a), cy=t0<cy, t2=t1<t0, cy=cy+t2, t1-t0)
|
||||
|
||||
#define SUBcc(a,b,cy,t0,t1) \
|
||||
(t0=(b), t1=(a), cy=t1<t0, t1-t0)
|
||||
|
||||
#define SUBC(a,b,cy,t0,t1) \
|
||||
(t0=(b)+cy, t1=(a), t1-t0)
|
||||
|
||||
#define ADDCcc(a,b,cy,t0,t1) \
|
||||
(t0=(b)+cy, t1=(a), cy=t0<cy, t0=t0+t1, t1=t0<t1, cy=cy+t1, t0=t0)
|
||||
|
||||
#define ADDcc(a,b,cy,t0,t1) \
|
||||
(t0=(b), t1=(a), t0=t0+t1, cy=t0<t1, t0=t0)
|
||||
|
||||
#define ADDC(a,b,cy,t0,t1) \
|
||||
(t0=(b)+cy, t1=(a), t0+t1)
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
u128 u128_divide(u128 dvnd, u128 dvsr)
|
||||
{
|
||||
u128 quot, rem, tmp;
|
||||
uint64_t cy, t0, t1, t2;
|
||||
|
||||
quot.hi = dvnd.hi;
|
||||
quot.lo = dvnd.lo;
|
||||
rem.hi = 0;
|
||||
rem.lo = 0;
|
||||
|
||||
for (int i = 0; i < 128; i++) {
|
||||
quot.lo = ADDcc(quot.lo, quot.lo, cy, t0, t1);
|
||||
quot.hi = ADDCcc(quot.hi, quot.hi, cy, t0, t1);
|
||||
rem.lo = ADDCcc(rem.lo, rem.lo, cy, t0, t1);
|
||||
rem.hi = ADDC(rem.hi, rem.hi, cy, t0, t1);
|
||||
tmp.lo = SUBcc(rem.lo, dvsr.lo, cy, t0, t1);
|
||||
tmp.hi = SUBCcc(rem.hi, dvsr.hi, cy, t0, t1, t2);
|
||||
if (!cy) { // remainder >= divisor
|
||||
rem.lo = tmp.lo;
|
||||
rem.hi = tmp.hi;
|
||||
quot.lo |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return quot;
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright 2026 Great Scott Gadgets <info@greatscottgadgets.com>
|
||||
*
|
||||
* This file is part of HackRF.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint64_t hi;
|
||||
uint64_t lo;
|
||||
} u128;
|
||||
|
||||
u128 u128_multiply(uint64_t a, uint64_t b);
|
||||
u128 u128_divide(u128 dvnd, u128 dvsr);
|
||||
Binary file not shown.
|
|
@ -240,7 +240,6 @@ class ProgrammableShift(wiring.Component):
|
|||
|
||||
# Implement the map itself (should it be done outside?)
|
||||
max_shift = max(self.shift_map.values())
|
||||
min_shift = min(self.shift_map.values())
|
||||
|
||||
value_scaled = [ Signal(signed(self.width_in + max_shift)) for _ in range(self.num_channels) ]
|
||||
scaled_valid = Signal()
|
||||
|
|
@ -256,9 +255,7 @@ class ProgrammableShift(wiring.Component):
|
|||
for k, v in self.shift_map.items():
|
||||
with m.Case(k):
|
||||
m.d.sync += value_scaled[c].eq(self.input.payload[c] << (max_shift - v))
|
||||
with m.Default():
|
||||
m.d.sync += value_scaled[c].eq(self.input.payload[c] << (max_shift - min_shift))
|
||||
|
||||
|
||||
with m.If(~self.output.valid | self.output.ready):
|
||||
m.d.comb += scaled_ready.eq(1)
|
||||
m.d.sync += self.output.valid.eq(scaled_valid)
|
||||
|
|
|
|||
|
|
@ -203,7 +203,6 @@ macro(DeclareTargets)
|
|||
${PATH_HACKRF_FIRMWARE_COMMON}/adc.c
|
||||
${PATH_HACKRF_FIRMWARE_COMMON}/da7219.c
|
||||
${PATH_HACKRF_FIRMWARE_COMMON}/max283x.c
|
||||
${PATH_HACKRF_FIRMWARE_COMMON}/u128.c
|
||||
)
|
||||
|
||||
if(BOARD STREQUAL "RAD1O")
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@
|
|||
#include <delay.h>
|
||||
#include <fixed_point.h>
|
||||
#include <hackrf_ui.h>
|
||||
#include <i2c_bus.h>
|
||||
#include <i2c_lpc.h>
|
||||
#include <leds.h>
|
||||
#include <operacake.h>
|
||||
#include <mixer.h>
|
||||
|
|
@ -428,8 +426,6 @@ int main(void)
|
|||
detect_hardware_platform();
|
||||
board_id_t board_id = detected_platform();
|
||||
|
||||
i2c_bus_start(&i2c0, &i2c_config_fast_clock);
|
||||
|
||||
pins_shutdown();
|
||||
sgpio_pin_shutdown(&sgpio_config);
|
||||
rf_path_pin_shutdown();
|
||||
|
|
@ -491,9 +487,6 @@ int main(void)
|
|||
#endif
|
||||
cpu_clock_init();
|
||||
|
||||
/* Clock speed has changed, adjust I2C clock */
|
||||
i2c_bus_start(&i2c0, &i2c_config_fast_clock);
|
||||
|
||||
/* Wake the M0 */
|
||||
ipc_halt_m0();
|
||||
ipc_start_m0((uint32_t) &__ram_m0_start__);
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ usb_request_status_t usb_vendor_request_init_sweep(
|
|||
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_FREQUENCY_RF,
|
||||
(sweep_freq + offset) * FP_ONE_HZ);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
|
|
@ -263,7 +263,7 @@ void sweep_mode(uint32_t seq)
|
|||
nvic_disable_irq(NVIC_USB0_IRQ);
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_FREQUENCY_RF,
|
||||
(sweep_freq + offset) * FP_ONE_HZ);
|
||||
nvic_enable_irq(NVIC_USB0_IRQ);
|
||||
|
|
|
|||
|
|
@ -94,12 +94,12 @@ usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth(
|
|||
(endpoint->setup.index << 16) | endpoint->setup.value;
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_BB_BANDWIDTH_TX,
|
||||
bandwidth);
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_BB_BANDWIDTH_RX,
|
||||
bandwidth);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
|
|
@ -123,22 +123,22 @@ usb_request_status_t usb_vendor_request_set_freq(
|
|||
set_freq_params.freq_mhz * 1000000ULL + set_freq_params.freq_hz;
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_FREQUENCY_RF,
|
||||
freq * FP_ONE_HZ);
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_FREQUENCY_IF,
|
||||
RADIO_UNSET);
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_FREQUENCY_LO,
|
||||
RADIO_UNSET);
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_IMAGE_REJECT,
|
||||
RADIO_UNSET);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
|
|
@ -160,17 +160,17 @@ usb_request_status_t usb_vendor_request_set_freq_explicit(
|
|||
} else if (stage == USB_TRANSFER_STAGE_DATA) {
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_FREQUENCY_IF,
|
||||
explicit_params.if_freq_hz * FP_ONE_HZ);
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_FREQUENCY_LO,
|
||||
explicit_params.lo_freq_hz * FP_ONE_HZ);
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_IMAGE_REJECT,
|
||||
explicit_params.path);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
|
|
@ -215,7 +215,7 @@ usb_request_status_t usb_vendor_request_set_sample_rate_frac(
|
|||
uint32_t numerator = set_sample_r_params.freq_hz;
|
||||
uint32_t denominator = set_sample_r_params.divider;
|
||||
uint64_t value = round_sample_rate(numerator, denominator);
|
||||
radio_reg_write(&radio, RADIO_BANK_REQUESTED, RADIO_SAMPLE_RATE, value);
|
||||
radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_SAMPLE_RATE, value);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
}
|
||||
return USB_REQUEST_STATUS_OK;
|
||||
|
|
@ -228,12 +228,12 @@ usb_request_status_t usb_vendor_request_set_amp_enable(
|
|||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_GAIN_TX_RF,
|
||||
endpoint->setup.value);
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_GAIN_RX_RF,
|
||||
endpoint->setup.value);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
|
|
@ -247,7 +247,7 @@ usb_request_status_t usb_vendor_request_set_lna_gain(
|
|||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
uint8_t gain = endpoint->setup.index;
|
||||
radio_reg_write(&radio, RADIO_BANK_REQUESTED, RADIO_GAIN_RX_IF, gain);
|
||||
radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_RX_IF, gain);
|
||||
endpoint->buffer[0] = RADIO_OK;
|
||||
usb_transfer_schedule_block(
|
||||
endpoint->in,
|
||||
|
|
@ -266,7 +266,7 @@ usb_request_status_t usb_vendor_request_set_vga_gain(
|
|||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
uint8_t gain = endpoint->setup.index;
|
||||
radio_reg_write(&radio, RADIO_BANK_REQUESTED, RADIO_GAIN_RX_BB, gain);
|
||||
radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_RX_BB, gain);
|
||||
endpoint->buffer[0] = RADIO_OK;
|
||||
usb_transfer_schedule_block(
|
||||
endpoint->in,
|
||||
|
|
@ -285,7 +285,7 @@ usb_request_status_t usb_vendor_request_set_txvga_gain(
|
|||
{
|
||||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
uint8_t gain = endpoint->setup.index;
|
||||
radio_reg_write(&radio, RADIO_BANK_REQUESTED, RADIO_GAIN_TX_IF, gain);
|
||||
radio_reg_write(&radio, RADIO_BANK_ACTIVE, RADIO_GAIN_TX_IF, gain);
|
||||
endpoint->buffer[0] = RADIO_OK;
|
||||
usb_transfer_schedule_block(
|
||||
endpoint->in,
|
||||
|
|
@ -315,7 +315,7 @@ usb_request_status_t usb_vendor_request_set_antenna_enable(
|
|||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_BIAS_TEE,
|
||||
endpoint->setup.value);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
|
|
@ -427,7 +427,7 @@ usb_request_status_t usb_vendor_request_set_hw_sync_mode(
|
|||
if (stage == USB_TRANSFER_STAGE_SETUP) {
|
||||
radio_reg_write(
|
||||
&radio,
|
||||
RADIO_BANK_REQUESTED,
|
||||
RADIO_BANK_ACTIVE,
|
||||
RADIO_TRIGGER,
|
||||
endpoint->setup.value);
|
||||
usb_transfer_schedule_ack(endpoint->in);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
#define USB_VENDOR_ID (0x1D50)
|
||||
|
||||
#define USB_API_VERSION (0x0113)
|
||||
#define USB_API_VERSION (0x0112)
|
||||
|
||||
#define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF)
|
||||
|
||||
|
|
|
|||
|
|
@ -501,7 +501,7 @@ int radio_read_register(
|
|||
return result;
|
||||
}
|
||||
|
||||
#define RADIO_NUM_REGS (24)
|
||||
#define RADIO_NUM_REGS (23)
|
||||
|
||||
int radio_read_registers(hackrf_device* device, const uint8_t bank)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI
|
|||
#define DEFAULT_REQUEST_TIMEOUT 100
|
||||
#define CPLD_WRITE_TIMEOUT 10000
|
||||
#define SPIFLASH_WRITE_TIMEOUT 50000 // W25Q32JV max chip erase time
|
||||
#define FPGA_BITSTREAM_TIMEOUT 500
|
||||
|
||||
// TODO: Factor this into a shared #include so that firmware can use
|
||||
// the same values.
|
||||
|
|
@ -3497,7 +3496,7 @@ int ADDCALL hackrf_set_fpga_bitstream(hackrf_device* device, const uint8_t index
|
|||
0,
|
||||
NULL,
|
||||
0,
|
||||
FPGA_BITSTREAM_TIMEOUT);
|
||||
DEFAULT_REQUEST_TIMEOUT);
|
||||
|
||||
if (result != 0) {
|
||||
last_libusb_error = result;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue