mirror of
https://github.com/skot/ESP-Miner.git
synced 2025-10-09 18:52:41 +02:00
* Accept and store float frequency values * Unify PLL resolver for 1366/1368/1370 Pick the closest frequency to the requested target. If there are multiple PLL settings, pick the one with first the lowest VDO frequency, and finally the lowest posdividers. Merged frequency ramp start and loop. This solves overshooting when requesting a target frequency within the current step size. It also eliminates the duplicate setting of the target frequency is that's on a step boundary. Cleaned up several unused defines. * Restore postdiv2 < postdiv1 condition for BM1368 and BM1370 * Whitespace * Clean up intermediate functions Simplify frequency_transition further, finally fix overshoot * Code cleanup * Add debug logging for BM1397 * Fix log * Flip postdiv condition for readability * Add test * Fix BM1370 fb_range * EOF line in test_pll.c
62 lines
2.5 KiB
C
62 lines
2.5 KiB
C
#include <stdbool.h>
|
|
#include <float.h>
|
|
#include <math.h>
|
|
|
|
#include "pll.h"
|
|
|
|
#include "esp_log.h"
|
|
|
|
#define EPSILON 0.0001f
|
|
|
|
static const char * TAG = "pll";
|
|
|
|
void pll_get_parameters(float target_freq, uint16_t fb_divider_min, uint16_t fb_divider_max,
|
|
uint8_t *fb_divider, uint8_t *refdiv, uint8_t *postdiv1, uint8_t *postdiv2,
|
|
float *actual_freq)
|
|
{
|
|
float best_freq = 0;
|
|
uint8_t best_refdiv = 0, best_fb_divider = 0, best_postdiv1 = 0, best_postdiv2 = 0;
|
|
float min_diff = FLT_MAX;
|
|
float min_vco_freq = FLT_MAX;
|
|
uint16_t min_postdiv = UINT16_MAX;
|
|
|
|
for (uint8_t refdiv = 2; refdiv > 0; refdiv--) {
|
|
for (uint8_t postdiv1 = 7; postdiv1 > 0; postdiv1--) {
|
|
for (uint8_t postdiv2 = 7; postdiv2 > 0; postdiv2--) {
|
|
uint16_t divider = refdiv * postdiv1 * postdiv2;
|
|
uint16_t fb_divider = round(target_freq / FREQ_MULT * divider);
|
|
if (postdiv1 > postdiv2 &&
|
|
fb_divider >= fb_divider_min && fb_divider <= fb_divider_max) {
|
|
float new_freq = FREQ_MULT * fb_divider / divider;
|
|
float curr_diff = fabs(target_freq - new_freq);
|
|
float vco_freq = FREQ_MULT * fb_divider / refdiv;
|
|
// Prioritize:
|
|
// 1. Closest frequency to target
|
|
// 2. Lowest VCO frequency
|
|
// 3. Lowest postdiv1 * postdiv2
|
|
if (curr_diff < min_diff ||
|
|
(fabs(curr_diff - min_diff) < EPSILON && vco_freq < min_vco_freq) ||
|
|
(fabs(curr_diff - min_diff) < EPSILON && fabs(vco_freq - min_vco_freq) < EPSILON && postdiv1 * postdiv2 < min_postdiv)) {
|
|
min_diff = curr_diff;
|
|
min_vco_freq = vco_freq;
|
|
min_postdiv = postdiv1 * postdiv2;
|
|
best_freq = new_freq;
|
|
best_refdiv = refdiv;
|
|
best_fb_divider = fb_divider;
|
|
best_postdiv1 = postdiv1;
|
|
best_postdiv2 = postdiv2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ESP_LOGI(TAG, "Frequency: %g MHz (fb_divider: %d, refdiv: %d, postdiv1: %d, postdiv2: %d)", best_freq, best_fb_divider, best_refdiv, best_postdiv1, best_postdiv2);
|
|
|
|
*actual_freq = best_freq;
|
|
*fb_divider = best_fb_divider;
|
|
*refdiv = best_refdiv;
|
|
*postdiv1 = best_postdiv1;
|
|
*postdiv2 = best_postdiv2;
|
|
}
|