Skip to content

Commit 8bfbd71

Browse files
committed
Add RADIO_CLOCK_CORRECTION register, bump USB API to 1.13.
1 parent dda161c commit 8bfbd71

4 files changed

Lines changed: 103 additions & 15 deletions

File tree

firmware/common/radio.c

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "rf_path.h"
3535
#include "transceiver_mode.h"
3636
#include "tuning.h"
37+
#include "u128.h"
3738
#ifdef IS_PRALINE
3839
#include "fpga.h"
3940
#include "tune_config.h"
@@ -132,6 +133,75 @@ static uint32_t radio_update_direction(radio_t* const radio, uint64_t* bank)
132133
return (1 << RADIO_OPMODE);
133134
}
134135

136+
/* Apply correction to a true frequency to get an adjusted frequency. */
137+
static uint64_t adjust(uint64_t freq, uint64_t correction)
138+
{
139+
/* skip if we can */
140+
if (correction == FRAC_ONE) {
141+
return freq;
142+
}
143+
144+
u128 product = u128_multiply(freq, correction);
145+
146+
/* product >> 63 */
147+
return (product.hi << 1) | (product.lo >> 63);
148+
}
149+
150+
/* Given an adjusted frequency and correction, return the true frequency. */
151+
static uint64_t unadjust(uint64_t freq, uint64_t correction)
152+
{
153+
/* skip if we can */
154+
if (correction == FRAC_ONE) {
155+
return freq;
156+
}
157+
158+
/* (1 << (63 + 63)) */
159+
u128 numerator = (u128){
160+
.hi = 1ULL << 62,
161+
.lo = 0,
162+
};
163+
u128 denominator = (u128){
164+
.hi = 0,
165+
.lo = correction,
166+
};
167+
u128 reciprocal = u128_divide(numerator, denominator);
168+
return adjust(freq, reciprocal.lo);
169+
}
170+
171+
static uint64_t restrict_correction(uint64_t requested_correction)
172+
{
173+
/* Correction should be in the range 0.99 to 1.01 */
174+
const uint64_t min_correction = FRAC_ONE - FRAC_ONE_PERCENT;
175+
const uint64_t max_correction = FRAC_ONE + FRAC_ONE_PERCENT;
176+
if (requested_correction >= min_correction &&
177+
requested_correction <= max_correction) {
178+
return requested_correction;
179+
} else {
180+
return FRAC_ONE;
181+
}
182+
}
183+
184+
static uint64_t set_lo(uint64_t freq_lo, uint64_t correction, bool apply)
185+
{
186+
fp_40_24_t corrected_lo = adjust(freq_lo, correction);
187+
fp_40_24_t achieved_lo = mixer_set_frequency(&mixer, corrected_lo, apply);
188+
return unadjust(achieved_lo, correction);
189+
}
190+
191+
static uint64_t set_if(uint64_t freq_if, uint64_t correction, bool apply)
192+
{
193+
fp_40_24_t corrected_if = adjust(freq_if, correction);
194+
fp_40_24_t achieved_if = max283x_set_frequency(&max283x, corrected_if, apply);
195+
return unadjust(achieved_if, correction);
196+
}
197+
198+
static uint64_t set_afe_rate(uint64_t afe_rate, uint64_t correction, bool apply)
199+
{
200+
fp_28_36_t corrected_rate = adjust(afe_rate, correction);
201+
fp_28_36_t achieved_rate = sample_rate_set(corrected_rate, apply);
202+
return unadjust(achieved_rate, correction);
203+
}
204+
135205
#define ABSOLUTE_MIN_AFE_RATE SR_FP_KHZ(200)
136206
#define ABSOLUTE_MAX_AFE_RATE SR_FP_KHZ(43600)
137207
#define MAX_SUPPORTED_AFE_RATE SR_FP_KHZ(40000)
@@ -183,6 +253,9 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank)
183253
bool new_n = false;
184254

185255
const uint64_t requested_rate = bank[RADIO_SAMPLE_RATE];
256+
const uint64_t requested_correction = bank[RADIO_CLOCK_CORRECTION];
257+
258+
uint64_t correction = restrict_correction(requested_correction);
186259

187260
if (requested_rate != RADIO_UNSET) {
188261
rate = MIN(requested_rate, MAX_MCU_RATE);
@@ -236,7 +309,7 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank)
236309
new_n = (n != previous_n);
237310

238311
afe_rate = rate << n;
239-
afe_rate = sample_rate_set(afe_rate, false);
312+
afe_rate = set_afe_rate(afe_rate, correction, false);
240313
previous_rate = radio->config[RADIO_BANK_APPLIED][RADIO_SAMPLE_RATE];
241314
if ((previous_n == RADIO_UNSET) || previous_rate == RADIO_UNSET) {
242315
previous_afe_rate = RADIO_UNSET;
@@ -245,7 +318,7 @@ static uint32_t radio_update_sample_rate(radio_t* const radio, uint64_t* bank)
245318
}
246319
new_afe_rate = (afe_rate != previous_afe_rate);
247320
if (new_afe_rate) {
248-
afe_rate = sample_rate_set(afe_rate, true);
321+
afe_rate = set_afe_rate(afe_rate, correction, true);
249322
}
250323

251324
rate = afe_rate >> n;
@@ -373,6 +446,7 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
373446
#ifdef IS_PRALINE
374447
const uint64_t requested_rotation = bank[RADIO_ROTATION];
375448
#endif
449+
const uint64_t requested_correction = bank[RADIO_CLOCK_CORRECTION];
376450

377451
const uint64_t applied_rf = radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF];
378452
const uint64_t applied_if = radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF];
@@ -381,13 +455,16 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
381455
radio->config[RADIO_BANK_APPLIED][RADIO_IMAGE_REJECT];
382456
const uint64_t applied_rotation =
383457
radio->config[RADIO_BANK_APPLIED][RADIO_ROTATION];
458+
const uint64_t applied_correction =
459+
radio->config[RADIO_BANK_APPLIED][RADIO_CLOCK_CORRECTION];
384460

385461
uint64_t freq_rf = applied_rf;
386462
uint64_t analog_rf = applied_rf;
387463
uint64_t freq_if = applied_if;
388464
uint64_t freq_lo = applied_lo;
389465
uint64_t img_reject = applied_img_reject;
390466
uint64_t rotation = applied_rotation;
467+
uint64_t correction = applied_correction;
391468

392469
uint64_t opmode = bank[RADIO_OPMODE];
393470
if (opmode == RADIO_UNSET) {
@@ -405,11 +482,12 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
405482
img_reject = RF_PATH_FILTER_BYPASS;
406483
}
407484
}
485+
correction = restrict_correction(requested_correction);
408486
if (requested_if != RADIO_UNSET) {
409-
freq_if = max283x_set_frequency(&max283x, requested_if, false);
487+
freq_if = set_if(requested_if, correction, false);
410488
}
411489
if (requested_lo != RADIO_UNSET) {
412-
freq_lo = mixer_set_frequency(&mixer, freq_lo, false);
490+
freq_lo = set_lo(requested_lo, correction, false);
413491
}
414492
#ifdef IS_PRALINE
415493
if (IS_PRALINE) {
@@ -491,7 +569,7 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
491569
freq_lo = RADIO_UNSET;
492570
}
493571
if (freq_lo != RADIO_UNSET) {
494-
freq_lo = mixer_set_frequency(&mixer, freq_lo, false);
572+
freq_lo = set_lo(freq_lo, correction, false);
495573
}
496574
}
497575

@@ -513,12 +591,12 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
513591

514592
/* Apply settings. */
515593
if ((freq_if != applied_if) && (freq_if != RADIO_UNSET)) {
516-
freq_if = max283x_set_frequency(&max283x, freq_if, true);
594+
freq_if = set_if(freq_if, correction, true);
517595
radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_IF] = freq_if;
518596
changed |= (1 << RADIO_FREQUENCY_IF);
519597
}
520598
if ((freq_lo != applied_lo) && (freq_lo != RADIO_UNSET)) {
521-
freq_lo = mixer_set_frequency(&mixer, freq_lo, true);
599+
freq_lo = set_lo(freq_lo, correction, true);
522600
radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_LO] = freq_lo;
523601
changed |= (1 << RADIO_FREQUENCY_LO);
524602
}
@@ -561,6 +639,10 @@ static uint32_t radio_update_frequency(radio_t* const radio, uint64_t* bank)
561639
radio->config[RADIO_BANK_APPLIED][RADIO_FREQUENCY_RF] = freq_rf;
562640
changed |= (1 << RADIO_FREQUENCY_RF);
563641
}
642+
if ((correction != applied_correction) && (correction != RADIO_UNSET)) {
643+
radio->config[RADIO_BANK_APPLIED][RADIO_CLOCK_CORRECTION] = correction;
644+
changed |= (1 << RADIO_CLOCK_CORRECTION);
645+
}
564646

565647
return changed;
566648
}

firmware/common/radio.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,17 +165,23 @@ typedef enum {
165165
* DC block enable of type bool.
166166
*/
167167
RADIO_DC_BLOCK = 22,
168+
/**
169+
* Correction factor for radio reference clock, of type fp_1_63_t.
170+
*/
171+
RADIO_CLOCK_CORRECTION = 23,
168172
} radio_register_t;
169173

170-
#define RADIO_NUM_REGS (23)
174+
#define RADIO_NUM_REGS (24)
171175
#define RADIO_UNSET (0xffffffffffffffff)
172176

173177
/* register groups for bitfield convenience */
174-
#define RADIO_REG_GROUP_RATE \
175-
((1 << RADIO_SAMPLE_RATE) | (1 << RADIO_RESAMPLE_TX) | (1 << RADIO_RESAMPLE_RX))
176-
#define RADIO_REG_GROUP_FREQ \
177-
((1 << RADIO_FREQUENCY_RF) | (1 << RADIO_FREQUENCY_IF) | \
178-
(1 << RADIO_FREQUENCY_LO) | (1 << RADIO_IMAGE_REJECT) | (1 << RADIO_ROTATION))
178+
#define RADIO_REG_GROUP_RATE \
179+
((1 << RADIO_SAMPLE_RATE) | (1 << RADIO_RESAMPLE_TX) | \
180+
(1 << RADIO_RESAMPLE_RX) | (1 << RADIO_CLOCK_CORRECTION))
181+
#define RADIO_REG_GROUP_FREQ \
182+
((1 << RADIO_FREQUENCY_RF) | (1 << RADIO_FREQUENCY_IF) | \
183+
(1 << RADIO_FREQUENCY_LO) | (1 << RADIO_IMAGE_REJECT) | (1 << RADIO_ROTATION) | \
184+
(1 << RADIO_CLOCK_CORRECTION))
179185
#define RADIO_REG_GROUP_BW \
180186
((1 << RADIO_BB_BANDWIDTH_TX) | (1 << RADIO_BB_BANDWIDTH_RX) | \
181187
(1 << RADIO_XCVR_TX_LPF) | (1 << RADIO_XCVR_RX_LPF) | \

firmware/hackrf_usb/usb_descriptor.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
#define USB_VENDOR_ID (0x1D50)
3030

31-
#define USB_API_VERSION (0x0112)
31+
#define USB_API_VERSION (0x0113)
3232

3333
#define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF)
3434

host/hackrf-tools/src/hackrf_debug.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ int radio_read_register(
501501
return result;
502502
}
503503

504-
#define RADIO_NUM_REGS (23)
504+
#define RADIO_NUM_REGS (24)
505505

506506
int radio_read_registers(hackrf_device* device, const uint8_t bank)
507507
{

0 commit comments

Comments
 (0)