mirror of
https://github.com/ttrftech/NanoVNA.git
synced 2025-12-06 03:31:59 +01:00
add gain/offset/power command, clean up si5351a control
This commit is contained in:
parent
a2e09a7923
commit
7b3b28f8af
16
main.c
16
main.c
|
|
@ -72,6 +72,7 @@ static void cmd_reset(BaseSequentialStream *chp, int argc, char *argv[])
|
||||||
|
|
||||||
int32_t frequency_offset = 5000;
|
int32_t frequency_offset = 5000;
|
||||||
int32_t frequency = 10000000;
|
int32_t frequency = 10000000;
|
||||||
|
uint8_t drive_strength = SI5351_CLK_DRIVE_STRENGTH_2MA;
|
||||||
|
|
||||||
void set_frequency(int freq)
|
void set_frequency(int freq)
|
||||||
{
|
{
|
||||||
|
|
@ -80,7 +81,7 @@ void set_frequency(int freq)
|
||||||
si5351_set_frequency(0, freq + frequency_offset);
|
si5351_set_frequency(0, freq + frequency_offset);
|
||||||
si5351_set_frequency(1, freq);
|
si5351_set_frequency(1, freq);
|
||||||
#else
|
#else
|
||||||
si5351_set_frequency_with_offset(freq, frequency_offset);
|
si5351_set_frequency_with_offset(freq, frequency_offset, drive_strength);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,6 +107,18 @@ static void cmd_freq(BaseSequentialStream *chp, int argc, char *argv[])
|
||||||
set_frequency(freq);
|
set_frequency(freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cmd_power(BaseSequentialStream *chp, int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (argc != 1) {
|
||||||
|
chprintf(chp, "usage: power {0-3}\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
drive_strength = atoi(argv[0]);
|
||||||
|
set_frequency(frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void cmd_time(BaseSequentialStream *chp, int argc, char *argv[])
|
static void cmd_time(BaseSequentialStream *chp, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
(void)argc;
|
(void)argc;
|
||||||
|
|
@ -304,6 +317,7 @@ static const ShellCommand commands[] =
|
||||||
{ "port", cmd_port },
|
{ "port", cmd_port },
|
||||||
{ "stat", cmd_stat },
|
{ "stat", cmd_stat },
|
||||||
{ "gain", cmd_gain },
|
{ "gain", cmd_gain },
|
||||||
|
{ "power", cmd_power },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,4 +33,4 @@ extern int16_t buffer_q[];
|
||||||
void dsp_process(int16_t *src, int16_t *dst, size_t len);
|
void dsp_process(int16_t *src, int16_t *dst, size_t len);
|
||||||
void set_agc_mode(int agcmode);
|
void set_agc_mode(int agcmode);
|
||||||
|
|
||||||
void si5351_set_frequency_with_offset(int freq, int offset);
|
void si5351_set_frequency_with_offset(int freq, int offset, uint8_t drive_strength);
|
||||||
|
|
|
||||||
139
si5351.c
139
si5351.c
|
|
@ -130,7 +130,8 @@ si5351_setupMultisynth(uint8_t output,
|
||||||
uint8_t pllSource,
|
uint8_t pllSource,
|
||||||
uint32_t div, // 4,6,8, 8+ ~ 900
|
uint32_t div, // 4,6,8, 8+ ~ 900
|
||||||
uint32_t num,
|
uint32_t num,
|
||||||
uint32_t denom)
|
uint32_t denom,
|
||||||
|
uint8_t drive_strength)
|
||||||
{
|
{
|
||||||
/* Get the appropriate starting point for the PLL registers */
|
/* Get the appropriate starting point for the PLL registers */
|
||||||
const uint8_t msreg_base[] = {
|
const uint8_t msreg_base[] = {
|
||||||
|
|
@ -149,6 +150,7 @@ si5351_setupMultisynth(uint8_t output,
|
||||||
uint32_t P1;
|
uint32_t P1;
|
||||||
uint32_t P2;
|
uint32_t P2;
|
||||||
uint32_t P3;
|
uint32_t P3;
|
||||||
|
uint32_t div4 = 0;
|
||||||
|
|
||||||
/* Output Multisynth Divider Equations
|
/* Output Multisynth Divider Equations
|
||||||
* where: a = div, b = num and c = denom
|
* where: a = div, b = num and c = denom
|
||||||
|
|
@ -160,19 +162,18 @@ si5351_setupMultisynth(uint8_t output,
|
||||||
* P3[19:0] = c
|
* P3[19:0] = c
|
||||||
*/
|
*/
|
||||||
/* Set the main PLL config registers */
|
/* Set the main PLL config registers */
|
||||||
if (num == 0)
|
if (div == 4) {
|
||||||
{
|
div4 = SI5351_DIVBY4;
|
||||||
|
P1 = P2 = 0;
|
||||||
|
P3 = 1;
|
||||||
|
} else if (num == 0) {
|
||||||
/* Integer mode */
|
/* Integer mode */
|
||||||
P1 = 128 * div - 512;
|
P1 = 128 * div - 512;
|
||||||
P2 = 0;
|
P2 = 0;
|
||||||
P3 = 1;
|
P3 = 1;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Fractional mode */
|
/* Fractional mode */
|
||||||
//P1 = (uint32_t)(128 * div + floor(128 * ((float)num/(float)denom)) - 512);
|
|
||||||
P1 = 128 * div + ((128 * num) / denom) - 512;
|
P1 = 128 * div + ((128 * num) / denom) - 512;
|
||||||
//P2 = (uint32_t)(128 * num - denom * floor(128 * ((float)num/(float)denom)));
|
|
||||||
P2 = 128 * num - denom * ((128 * num) / denom);
|
P2 = 128 * num - denom * ((128 * num) / denom);
|
||||||
P3 = denom;
|
P3 = denom;
|
||||||
}
|
}
|
||||||
|
|
@ -180,7 +181,7 @@ si5351_setupMultisynth(uint8_t output,
|
||||||
/* Set the MSx config registers */
|
/* Set the MSx config registers */
|
||||||
si5351_write(baseaddr, (P3 & 0x0000FF00) >> 8);
|
si5351_write(baseaddr, (P3 & 0x0000FF00) >> 8);
|
||||||
si5351_write(baseaddr+1, (P3 & 0x000000FF));
|
si5351_write(baseaddr+1, (P3 & 0x000000FF));
|
||||||
si5351_write(baseaddr+2, (P1 & 0x00030000) >> 16); /* ToDo: Add DIVBY4 (>150MHz) and R0 support (<500kHz) later */
|
si5351_write(baseaddr+2, ((P1 & 0x00030000) >> 16) | div4);
|
||||||
si5351_write(baseaddr+3, (P1 & 0x0000FF00) >> 8);
|
si5351_write(baseaddr+3, (P1 & 0x0000FF00) >> 8);
|
||||||
si5351_write(baseaddr+4, (P1 & 0x000000FF));
|
si5351_write(baseaddr+4, (P1 & 0x000000FF));
|
||||||
si5351_write(baseaddr+5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
|
si5351_write(baseaddr+5, ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16));
|
||||||
|
|
@ -188,7 +189,7 @@ si5351_setupMultisynth(uint8_t output,
|
||||||
si5351_write(baseaddr+7, (P2 & 0x000000FF));
|
si5351_write(baseaddr+7, (P2 & 0x000000FF));
|
||||||
|
|
||||||
/* Configure the clk control and enable the output */
|
/* Configure the clk control and enable the output */
|
||||||
dat = SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_INPUT_MULTISYNTH_N;
|
dat = drive_strength | SI5351_CLK_INPUT_MULTISYNTH_N;
|
||||||
if (pllSource == SI5351_PLL_B)
|
if (pllSource == SI5351_PLL_B)
|
||||||
dat |= SI5351_CLK_PLL_SELECT_B;
|
dat |= SI5351_CLK_PLL_SELECT_B;
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
|
|
@ -196,86 +197,64 @@ si5351_setupMultisynth(uint8_t output,
|
||||||
si5351_write(clkctrl[output], dat);
|
si5351_write(clkctrl[output], dat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static uint32_t
|
||||||
si5351_setupMultisynthDivBy4(uint8_t output,
|
gcd(uint32_t x, uint32_t y)
|
||||||
uint8_t pllSource)
|
|
||||||
{
|
{
|
||||||
/* Get the appropriate starting point for the PLL registers */
|
uint32_t z;
|
||||||
const uint8_t msreg_base[] = {
|
while (y != 0) {
|
||||||
SI5351_REG_42_MULTISYNTH0,
|
z = x % y;
|
||||||
SI5351_REG_50_MULTISYNTH1,
|
x = y;
|
||||||
SI5351_REG_58_MULTISYNTH2,
|
y = z;
|
||||||
};
|
}
|
||||||
uint8_t baseaddr = msreg_base[output];
|
return x;
|
||||||
const uint8_t clkctrl[] = {
|
|
||||||
SI5351_REG_16_CLK0_CONTROL,
|
|
||||||
SI5351_REG_17_CLK1_CONTROL,
|
|
||||||
SI5351_REG_18_CLK2_CONTROL
|
|
||||||
};
|
|
||||||
uint8_t dat;
|
|
||||||
|
|
||||||
/* Set the MSx config registers */
|
|
||||||
si5351_write(baseaddr, 0);
|
|
||||||
si5351_write(baseaddr+1, 1);
|
|
||||||
si5351_write(baseaddr+2, SI5351_DIVBY4);
|
|
||||||
si5351_write(baseaddr+3, 0);
|
|
||||||
si5351_write(baseaddr+4, 0);
|
|
||||||
si5351_write(baseaddr+5, 0);
|
|
||||||
si5351_write(baseaddr+6, 0);
|
|
||||||
si5351_write(baseaddr+7, 0);
|
|
||||||
|
|
||||||
/* Configure the clk control and enable the output */
|
|
||||||
dat = SI5351_CLK_DRIVE_STRENGTH_2MA
|
|
||||||
| SI5351_CLK_INPUT_MULTISYNTH_N
|
|
||||||
| SI5351_CLK_INTEGER_MODE;
|
|
||||||
if (pllSource == SI5351_PLL_B)
|
|
||||||
dat |= SI5351_CLK_PLL_SELECT_B;
|
|
||||||
si5351_write(clkctrl[output], dat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define XTALFREQ 26000000L
|
#define XTALFREQ 26000000L
|
||||||
#define PLL_N 32
|
#define PLL_N 32
|
||||||
#define PLLFREQ (XTALFREQ * PLL_N)
|
#define PLLFREQ (XTALFREQ * PLL_N)
|
||||||
|
|
||||||
void
|
void
|
||||||
si5351_set_frequency_fixedpll(int channel, int pll, int pllfreq, int freq)
|
si5351_set_frequency_fixedpll(int channel, int pll, int pllfreq, int freq,
|
||||||
|
uint8_t drive_strength)
|
||||||
{
|
{
|
||||||
int32_t div = pllfreq / freq; // range: 8 ~ 1800
|
int32_t div = pllfreq / freq; // range: 8 ~ 1800
|
||||||
int32_t num = pllfreq - freq * div;
|
int32_t num = pllfreq - freq * div;
|
||||||
int32_t denom = freq;
|
int32_t denom = freq;
|
||||||
int32_t k = freq / (1<<20) + 1;
|
//int32_t k = freq / (1<<20) + 1;
|
||||||
|
int32_t k = gcd(num, denom);
|
||||||
num /= k;
|
num /= k;
|
||||||
denom /= k;
|
denom /= k;
|
||||||
si5351_setupMultisynth(channel, pll, div, num, denom);
|
while (denom >= (1<<20)) {
|
||||||
|
num >>= 1;
|
||||||
|
denom >>= 1;
|
||||||
|
}
|
||||||
|
si5351_setupMultisynth(channel, pll, div, num, denom, drive_strength);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
si5351_set_frequency_fixeddiv(int channel, int pll, int freq, int div)
|
si5351_set_frequency_fixeddiv(int channel, int pll, int freq, int div,
|
||||||
|
uint8_t drive_strength)
|
||||||
{
|
{
|
||||||
int32_t pllfreq = freq * div;
|
int32_t pllfreq = freq * div;
|
||||||
int32_t multi = pllfreq / XTALFREQ;
|
int32_t multi = pllfreq / XTALFREQ;
|
||||||
int32_t num = pllfreq - multi * XTALFREQ;
|
int32_t num = pllfreq - multi * XTALFREQ;
|
||||||
|
#if 0
|
||||||
//int32_t denom = 1000000;
|
//int32_t denom = 1000000;
|
||||||
int32_t denom = 520000;
|
int32_t denom = 520000;
|
||||||
int32_t k = XTALFREQ / denom;
|
int32_t k = XTALFREQ / denom;
|
||||||
num /= k;
|
num /= k;
|
||||||
si5351_setupPLL(pll, multi, num, denom);
|
#else
|
||||||
si5351_setupMultisynth(channel, pll, div, 0, 1);
|
int32_t denom = XTALFREQ;
|
||||||
|
int32_t k = gcd(num, denom);
|
||||||
|
num /= k;
|
||||||
|
denom /= k;
|
||||||
|
while (denom >= (1<<20)) {
|
||||||
|
num >>= 1;
|
||||||
|
denom >>= 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
void
|
|
||||||
si5351_set_frequency_fixeddiv4(int channel, int pll, int freq)
|
|
||||||
{
|
|
||||||
int32_t pllfreq = freq * 4;
|
|
||||||
int32_t multi = pllfreq / XTALFREQ;
|
|
||||||
int32_t num = pllfreq - multi * XTALFREQ;
|
|
||||||
//int32_t denom = 1000000;
|
|
||||||
int32_t denom = 520000;
|
|
||||||
int32_t k = XTALFREQ / denom;
|
|
||||||
num /= k;
|
|
||||||
si5351_setupPLL(pll, multi, num, denom);
|
si5351_setupPLL(pll, multi, num, denom);
|
||||||
si5351_setupMultisynthDivBy4(channel, pll);
|
si5351_setupMultisynth(channel, pll, div, 0, 1, drive_strength);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -284,14 +263,14 @@ si5351_set_frequency_fixeddiv4(int channel, int pll, int freq)
|
||||||
* 150~200MHz fractional PLL 600-900MHz, fixed divider 4
|
* 150~200MHz fractional PLL 600-900MHz, fixed divider 4
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
si5351_set_frequency(int channel, int freq)
|
si5351_set_frequency(int channel, int freq, uint8_t drive_strength)
|
||||||
{
|
{
|
||||||
if (freq <= 100000000) {
|
if (freq <= 100000000) {
|
||||||
si5351_set_frequency_fixedpll(channel, SI5351_PLL_B, PLLFREQ, freq);
|
si5351_set_frequency_fixedpll(channel, SI5351_PLL_B, PLLFREQ, freq, drive_strength);
|
||||||
} else if (freq < 150000000) {
|
} else if (freq < 150000000) {
|
||||||
si5351_set_frequency_fixeddiv(channel, SI5351_PLL_B, freq, 6);
|
si5351_set_frequency_fixeddiv(channel, SI5351_PLL_B, freq, 6, drive_strength);
|
||||||
} else {
|
} else {
|
||||||
si5351_set_frequency_fixeddiv4(channel, SI5351_PLL_B, freq);
|
si5351_set_frequency_fixeddiv(channel, SI5351_PLL_B, freq, 4, drive_strength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,25 +282,31 @@ si5351_set_frequency(int channel, int freq)
|
||||||
*/
|
*/
|
||||||
#define CLK2_FREQUENCY 8000000L
|
#define CLK2_FREQUENCY 8000000L
|
||||||
void
|
void
|
||||||
si5351_set_frequency_with_offset(int freq, int offset)
|
si5351_set_frequency_with_offset(int freq, int offset, uint8_t drive_strength)
|
||||||
{
|
{
|
||||||
si5351_disable_output();
|
si5351_disable_output();
|
||||||
if (freq <= 100000000) {
|
if (freq <= 100000000) {
|
||||||
// fractional divider mode. only PLL A is used.
|
// fractional divider mode. only PLL A is used.
|
||||||
si5351_setupPLL(SI5351_PLL_A, 32, 0, 1);
|
si5351_setupPLL(SI5351_PLL_A, 32, 0, 1);
|
||||||
si5351_set_frequency_fixedpll(0, SI5351_PLL_A, PLLFREQ, freq + offset);
|
si5351_set_frequency_fixedpll(0, SI5351_PLL_A, PLLFREQ, freq + offset,
|
||||||
si5351_set_frequency_fixedpll(1, SI5351_PLL_A, PLLFREQ, freq);
|
SI5351_CLK_DRIVE_STRENGTH_2MA);
|
||||||
si5351_set_frequency_fixedpll(2, SI5351_PLL_A, PLLFREQ, CLK2_FREQUENCY);
|
si5351_set_frequency_fixedpll(1, SI5351_PLL_A, PLLFREQ, freq, drive_strength);
|
||||||
|
si5351_set_frequency_fixedpll(2, SI5351_PLL_A, PLLFREQ, CLK2_FREQUENCY,
|
||||||
|
SI5351_CLK_DRIVE_STRENGTH_2MA);
|
||||||
} else if (freq < 150000000) {
|
} else if (freq < 150000000) {
|
||||||
// div by 6 mode. both PLL A and B are dedicated for CLK0, CLK1
|
// div by 6 mode. both PLL A and B are dedicated for CLK0, CLK1
|
||||||
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, freq + offset, 6);
|
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, freq + offset, 6,
|
||||||
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6);
|
SI5351_CLK_DRIVE_STRENGTH_2MA);
|
||||||
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq * 6, CLK2_FREQUENCY);
|
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength);
|
||||||
|
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq * 6, CLK2_FREQUENCY,
|
||||||
|
SI5351_CLK_DRIVE_STRENGTH_2MA);
|
||||||
} else {
|
} else {
|
||||||
// div by 4 mode. both PLL A and B are dedicated for CLK0, CLK1
|
// div by 4 mode. both PLL A and B are dedicated for CLK0, CLK1
|
||||||
si5351_set_frequency_fixeddiv4(0, SI5351_PLL_A, freq + offset);
|
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, freq + offset, 4,
|
||||||
si5351_set_frequency_fixeddiv4(1, SI5351_PLL_B, freq);
|
SI5351_CLK_DRIVE_STRENGTH_2MA);
|
||||||
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq * 4, CLK2_FREQUENCY);
|
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 4, drive_strength);
|
||||||
|
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq * 4, CLK2_FREQUENCY,
|
||||||
|
SI5351_CLK_DRIVE_STRENGTH_2MA);
|
||||||
}
|
}
|
||||||
si5351_reset_pll();
|
si5351_reset_pll();
|
||||||
si5351_enable_output();
|
si5351_enable_output();
|
||||||
|
|
|
||||||
5
si5351.h
5
si5351.h
|
|
@ -63,6 +63,7 @@ void si5351_setupMultisynth(uint8_t output,
|
||||||
uint8_t pllSource,
|
uint8_t pllSource,
|
||||||
uint32_t div,
|
uint32_t div,
|
||||||
uint32_t num,
|
uint32_t num,
|
||||||
uint32_t denom);
|
uint32_t denom,
|
||||||
|
uint8_t drive_strength);
|
||||||
|
|
||||||
void si5351_set_frequency(int channel, int freq);
|
void si5351_set_frequency(int channel, int freq, uint8_t drive_strength);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue