Phase jumps are still a problem. Added some monitor commands to support analysis.
pull/13/head
ArjanteMarvelde 2022-08-03 22:08:54 +02:00
rodzic b43b223dba
commit 2ad6d2b9ba
3 zmienionych plików z 71 dodań i 41 usunięć

Wyświetl plik

@ -69,14 +69,40 @@ void mon_init()
uint8_t si5351_reg[200];
void mon_si(void)
{
int base=0, nreg=200, i;
int base=0, nreg=0, i;
for (i=0; i<nreg; i++) si5351_reg[i] = 0xaa;
if (nargs>2)
{
base = atoi(argv[1]);
nreg = atoi(argv[2]);
}
if ((base<0)||(base+nreg>200)) return;
for (i=0; i<200; i++) si5351_reg[i] = 0xaa;
si_getreg(si5351_reg, (uint8_t)base, (uint8_t)nreg);
for (i=0; i<nreg; i++) printf("%02x ",(int)(si5351_reg[i]));
for (i=0; i<nreg; i++) printf("%03d : %02x \n", base+i, (int)(si5351_reg[i]));
printf("\n");
}
/*
* Dumps the VFO registers
*/
extern vfo_t vfo[2];
void mon_vfo(void)
{
int i;
if (nargs>1)
i = atoi(argv[1]);
if ((i<0)||(i>1)) return;
printf("Frequency: %lu\n", vfo[i].freq);
printf("Phase : %u\n", (int)(vfo[i].phase));
printf("Ri : %lu\n", (int)(vfo[i].ri));
printf("MSi : %lu\n", (int)(vfo[i].msi));
printf("MSN : %g\n\n", vfo[i].msn);
}
/*
* Dumps the entire built-in and programmed characterset on the LCD
@ -192,10 +218,11 @@ void mon_adc(void)
/*
* Command shell table, organize the command functions above
*/
#define NCMD 7
#define NCMD 8
shell_t shell[NCMD]=
{
{"si", 2, &mon_si, "si <start> <nr of reg>", "Dumps Si5351 registers"},
{"vfo", 3, &mon_vfo, "vfo <id>", "Dumps vfo[id] registers"},
{"lt", 2, &mon_lt, "lt (no parameters)", "LCD test, dumps characterset on LCD"},
{"or", 2, &mon_or, "or (no parameters)", "Returns overrun information"},
{"pt", 2, &mon_pt, "pt (no parameters)", "Toggles PTT status"},

Wyświetl plik

@ -37,7 +37,7 @@ Details:
P3 = c (P3 = c = 1000000 for MSN tuning, P3 = 1 for MSi integer mode)
This VFO implementation assumes PLLA is used for VFO 0 (clk0 and clk1), and PLLB is used for VFO 1 (clk2)
This VFO implementation assigns PLLA to VFO 0 (clk0 and clk1), and PLLB to VFO 1 (clk2)
The algorithm to get from required Fout to synthesizer settings:
| calculate new <MSN> from the desired <Fout>, based on the current <Ri> and <MSi>
@ -171,20 +171,22 @@ Control Si5351 (see AN619):
#define SI_XTAL_LOAD 183
// CLK_OE register 3 masks
#define SI_CLK0_ENABLE 0b00000001 // Enable clock 0 output
#define SI_CLK1_ENABLE 0b00000010 // Enable clock 1 output
#define SI_CLK2_ENABLE 0b00000100 // Enable clock 2 output
#define SI_CLK0_DISABLE 0b00000001 // Disable clock 0 output
#define SI_CLK1_DISABLE 0b00000010 // Disable clock 1 output
#define SI_CLK2_DISABLE 0b00000100 // Disable clock 2 output
#define SI_VFO0_DISABLE 0b00000011 // Set bits to disable
#define SI_VFO1_DISABLE 0b00000100 // Set bits to disable
// CLKi_CTL register 16, 17, 18 values
// Normally 0x4f for clk 0 and 1, 0x6f for clk 2
#define SI_CLK_INT 0b01000000 // Set integer mode
#define SI_CLK_PLL 0b00100000 // Select PLL B as MS source (default 0 = PLL A)
#define SI_CLK_PLLB 0b00100000 // Select PLL B as MS source (default 0 = PLL A)
#define SI_CLK_INV 0b00010000 // Invert output (i.e. phase + 180deg)
#define SI_CLK_SRC 0b00001100 // Select output source: 11=MS, 00=XTAL direct
#define SI_CLK_DRV 0b00000011 // Select output drive, increasingly: 2-4-6-8 mA
// Play with these to get a nice block output
// Play with DRV to get a nice block output
#define SI_VFO0CTL 0b00001101 // nonINT, PLLA, nonINV, SRC=MS, 4mA
#define SI_VFO1CTL 0b00101101 // nonINT, PLLB, nonINV, SRC=MS, 4mA
// PLL_RESET register 177 values
#define SI_PLLB_RST 0b10000000 // Reset PLL B
@ -198,15 +200,6 @@ Control Si5351 (see AN619):
#define SI_PLL_C 1000000UL // Parameter c for PLL-A and -B setting
typedef struct
{
uint32_t freq; // type can hold up to 4GHz
uint8_t flag; // flag != 0 when update needed
uint8_t phase; // in quarter waves (0, 1, 2, 3)
uint8_t ri; // Ri (1 .. 128), but should be 1 for VFO 0
uint8_t msi; // MSi parameter a (4, 6, 8 .. 126)
double msn; // MSN (24.0 .. 35.9999)
} vfo_t;
vfo_t vfo[2]; // 0: clk0 / clk1 1: clk2
@ -217,7 +210,7 @@ void si_setfreq(int i, uint32_t f)
if (vfo[i].freq == f) return; // Anything to set at all?
vfo[i].freq = f; // Entry checks pass, so do the actual setting
vfo[i].flag = 1;
vfo[i].flag |= 0x01;
}
void si_setphase(int i, uint8_t p)
@ -227,7 +220,7 @@ void si_setphase(int i, uint8_t p)
if (vfo[i].phase == p) return; // Anything to set at all?
vfo[i].phase = p; // Entry checks pass, so do the actual setting
vfo[i].flag = 1;
vfo[i].flag |= 0x02;
}
void si_enable(int i, bool en)
@ -240,15 +233,10 @@ void si_enable(int i, bool en)
i2c_write_blocking(i2c0, I2C_VFO, &data[0], 1, true);
i2c_read_blocking(i2c0, I2C_VFO, &data[1], 1, false);
data[0] = SI_CLK_OE;
if (i==0)
{
data[1] = en ? data[1]&~SI_VFO0_DISABLE : data[1]|SI_VFO0_DISABLE; // clk0 and clk1
}
else
{
data[1] = en ? data[1]&~SI_VFO1_DISABLE : data[1]|SI_VFO1_DISABLE; // clk2
}
i2c_write_blocking(i2c0, I2C_VFO, &data[0], 2, false);
}
@ -347,13 +335,13 @@ void si_setmsi(uint8_t i)
data[8] = 0x00;
i2c_write_blocking(i2c0, I2C_VFO, data, 9, false);
// If vfo[0] also set clk 1 and phase offset, (integer mode and high drive current for low phase noise).
// If vfo[0] also set clk 1 and phase offset, (integer mode(?) and high drive current for low phase noise).
if (i==0)
{
data[0] = SI_SYNTH_MS1; // Same data in synthesizer
i2c_write_blocking(i2c0, I2C_VFO, data, 9, false);
if (vfo[0].phase&(PH090|PH270)) // Phase is 90 or 270 deg?
if ((vfo[0].phase==PH090)||(vfo[0].phase==PH270)) // Phase is 90 or 270 deg?
{
data[0] = SI_CLK1_PHOFF;
data[1] = vfo[0].msi; // offset == MSi for 90deg
@ -365,29 +353,31 @@ void si_setmsi(uint8_t i)
data[1] = 0; // offset == 0 for 0deg
i2c_write_blocking(i2c0, I2C_VFO, data, 2, false);
}
if (vfo[0].phase&(PH180|PH270)) // Phase is 180 or 270 deg?
if ((vfo[0].phase==PH180)||(vfo[0].phase==PH270)) // Phase is 180 or 270 deg?
{
data[0] = SI_CLK1_CTL; // set the invert flag
data[1] = 0x1d; // CLK1: nonINT, PLLA, INV, MS, 4mA
i2c_write_blocking(i2c0, I2C_VFO, data, 2, false);
data[0] = SI_CLK0_CTL; // set the invert flag
data[1] = SI_VFO0CTL; // CLK0: nonINV
data[2] = SI_VFO0CTL | SI_CLK_INV; // CLK1: INV
i2c_write_blocking(i2c0, I2C_VFO, data, 3, false);
}
else
{
data[0] = SI_CLK1_CTL; // clear the invert flag
data[1] = 0x0d; // CLK1: nonINT, PLLA, nonINV, MS, 4mA
i2c_write_blocking(i2c0, I2C_VFO, data, 2, false);
data[0] = SI_CLK0_CTL; // set the invert flag
data[1] = SI_VFO0CTL; // CLK0: nonINV
data[2] = SI_VFO0CTL; // CLK1: nonINV
i2c_write_blocking(i2c0, I2C_VFO, data, 3, false);
}
}
else
{
data[0] = SI_CLK2_CTL; // set the invert flag
data[1] = 0x2d; // CLK2: nonINT, PLLB, nonINV, MS, 4mA
data[1] = SI_VFO1CTL; // CLK2: nonINV
i2c_write_blocking(i2c0, I2C_VFO, data, 2, false);
}
// Reset associated PLL
data[0] = SI_PLL_RESET;
data[1] = (i==1)?0x80:0x20;
data[1] = (i==1)?SI_PLLB_RST:SI_PLLA_RST;
i2c_write_blocking(i2c0, I2C_VFO, data, 2, false);
}
@ -431,13 +421,15 @@ void si_evaluate(void)
if ((vfo[0].freq >= 3000000)&&(vfo[0].freq < 6000000)) // Handle Low end of Ri=1 range
vfo[0].msi = (uint8_t)126; // Maximum MSi on Fvco=(4x126)MHz
else // Or calculate MSi on Fvco=750MHz
vfo[0].msi = (uint8_t)(750000000UL / (vfo[0].freq * vfo[0].ri)) & 0x000000fe;
vfo[0].msi = (uint8_t)((750000000UL / (vfo[0].freq * vfo[0].ri)) & 0x000000fe);
msn = (double)(vfo[0].msi); // Re-calculate MSN
msn = msn * (double)(vfo[0].ri);
msn = msn * (double)(vfo[0].freq) / SI_XTAL_FREQ;
vfo[0].msn = msn;
vfo[0].phase = PH090;
si_setmsn(0);
si_setmsi(0);
}
@ -498,9 +490,9 @@ void si_init(void)
// First time init of clock control registers
data[0] = SI_CLK0_CTL;
data[1] = 0x0d; // CLK0: nonINT, PLLA, nonINV, MS, 4mA
data[2] = 0x0d; // CLK1: nonINT, PLLA, nonINV, MS, 4mA
data[3] = 0x2d; // CLK2: nonINT, PLLB, nonINV, MS, 4mA
data[1] = SI_VFO0CTL;
data[2] = SI_VFO0CTL;
data[3] = SI_VFO1CTL;
i2c_write_blocking(i2c0, I2C_VFO, data, 4, false);
// Initialize VFO values

Wyświetl plik

@ -27,6 +27,17 @@
#define PH180 2
#define PH270 3
typedef struct
{
uint32_t freq; // type can hold up to 4GHz
uint8_t flag; // flag != 0 when update needed
uint8_t phase; // in quarter waves (0, 1, 2, 3)
uint8_t ri; // Ri (1 .. 128), but should be 1 for VFO 0
uint8_t msi; // MSi parameter a (4, 6, 8 .. 126)
double msn; // MSN (24.0 .. 35.9999)
} vfo_t;
int si_getreg(uint8_t *data, uint8_t reg, uint8_t len);
void si_init(void);
void si_evaluate(void);