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}
0 commit comments