mirror of
https://github.com/ttrftech/NanoVNA.git
synced 2025-12-06 03:31:59 +01:00
si5351.c and si5351.h
Cleanup and optimize code Add comments, fix definitions Fix rounding errors Fix band 1 stability mcuconf.h Set I2C bus clock to SYSCLK (more fast) Apply 400kHz bus I2C clock timings for 8MHz and 48Mhz clock main.c Remove and reset some variables Add separate sweep for calibration (allow calibrate if sweep paused) Increase main thread stack (need for run calibrate, possibly need execute some commands in sweep threads for reduce stack usage)
This commit is contained in:
parent
b77e1d6680
commit
a43b6e3acc
4
Makefile
4
Makefile
|
|
@ -64,13 +64,13 @@ endif
|
|||
# Stack size to be allocated to the Cortex-M process stack. This stack is
|
||||
# the stack used by the main() thread.
|
||||
ifeq ($(USE_PROCESS_STACKSIZE),)
|
||||
USE_PROCESS_STACKSIZE = 0x200
|
||||
USE_PROCESS_STACKSIZE = 0x300
|
||||
endif
|
||||
|
||||
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
|
||||
# stack is used for processing interrupts and exceptions.
|
||||
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
|
||||
USE_EXCEPTIONS_STACKSIZE = 0x200
|
||||
USE_EXCEPTIONS_STACKSIZE = 0x100
|
||||
endif
|
||||
|
||||
#
|
||||
|
|
|
|||
146
main.c
146
main.c
|
|
@ -69,19 +69,17 @@ static void transform_domain(void);
|
|||
|
||||
static MUTEX_DECL(mutex);
|
||||
|
||||
int32_t frequency_offset = 5000;
|
||||
uint32_t frequency = 10000000;
|
||||
int8_t drive_strength = DRIVE_STRENGTH_AUTO;
|
||||
int8_t sweep_enabled = TRUE;
|
||||
volatile int8_t sweep_once = FALSE;
|
||||
int8_t cal_auto_interpolate = TRUE;
|
||||
uint16_t redraw_request = 0; // contains REDRAW_XXX flags
|
||||
// Obsolete enable/disable calibration interpolation (always on)
|
||||
#define cal_auto_interpolate TRUE
|
||||
|
||||
static int32_t frequency_offset = 5000;
|
||||
static uint32_t frequency = 10000000;
|
||||
static int8_t drive_strength = DRIVE_STRENGTH_AUTO;
|
||||
volatile int8_t sweep_mode = SWEEP_MODE_ENABLED;
|
||||
|
||||
volatile uint8_t redraw_request = 0; // contains REDRAW_XXX flags
|
||||
int16_t vbat = 0;
|
||||
|
||||
//
|
||||
// Profile stack usage (enable threads command by def ENABLE_THREADS_COMMAND) show:
|
||||
// Stack maximum usage = 576 bytes, free stack = 64 bytes
|
||||
//
|
||||
static THD_WORKING_AREA(waThread1, 640);
|
||||
static THD_FUNCTION(Thread1, arg)
|
||||
{
|
||||
|
|
@ -90,11 +88,10 @@ static THD_FUNCTION(Thread1, arg)
|
|||
|
||||
while (1) {
|
||||
bool completed = false;
|
||||
if (sweep_enabled || sweep_once) {
|
||||
if (sweep_mode&(SWEEP_MODE_ENABLED|SWEEP_MODE_RUN_ONCE)) {
|
||||
chMtxLock(&mutex);
|
||||
// Sweep require 8367 system tick
|
||||
completed = sweep(true);
|
||||
sweep_once = FALSE;
|
||||
sweep_mode&=~SWEEP_MODE_RUN_ONCE;
|
||||
chMtxUnlock(&mutex);
|
||||
} else {
|
||||
si5351_disable_output();
|
||||
|
|
@ -102,10 +99,8 @@ static THD_FUNCTION(Thread1, arg)
|
|||
}
|
||||
|
||||
chMtxLock(&mutex);
|
||||
// Ui and render require 800 system tick
|
||||
ui_process();
|
||||
|
||||
if (sweep_enabled) {
|
||||
if (sweep_mode&SWEEP_MODE_ENABLED) {
|
||||
if (vbat != -1) {
|
||||
adc_stop(ADC1);
|
||||
vbat = adc_vbat_read(ADC1);
|
||||
|
|
@ -135,23 +130,10 @@ static THD_FUNCTION(Thread1, arg)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
pause_sweep(void)
|
||||
{
|
||||
sweep_enabled = FALSE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
resume_sweep(void)
|
||||
{
|
||||
sweep_enabled = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
toggle_sweep(void)
|
||||
{
|
||||
sweep_enabled = !sweep_enabled;
|
||||
}
|
||||
static inline void run_once_sweep(void) {sweep_mode|=SWEEP_MODE_RUN_ONCE;}
|
||||
static inline void pause_sweep(void) {sweep_mode&=~SWEEP_MODE_ENABLED;}
|
||||
static inline void resume_sweep(void){sweep_mode|= SWEEP_MODE_ENABLED;}
|
||||
void toggle_sweep(void){sweep_mode^= SWEEP_MODE_ENABLED;}
|
||||
|
||||
static float
|
||||
bessel0(float x) {
|
||||
|
|
@ -316,16 +298,15 @@ const int8_t gain_table[] = {
|
|||
#define DELAY_GAIN_CHANGE 2
|
||||
|
||||
static int
|
||||
adjust_gain(int newfreq)
|
||||
adjust_gain(uint32_t newfreq)
|
||||
{
|
||||
int delay = 0;
|
||||
int new_order = newfreq / FREQ_HARMONICS;
|
||||
int old_order = frequency / FREQ_HARMONICS;
|
||||
if (new_order != old_order) {
|
||||
tlv320aic3204_set_gain(gain_table[new_order], gain_table[new_order]);
|
||||
delay += DELAY_GAIN_CHANGE;
|
||||
return DELAY_GAIN_CHANGE;
|
||||
}
|
||||
return delay;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_frequency(uint32_t freq)
|
||||
|
|
@ -778,27 +759,23 @@ ensure_edit_config(void)
|
|||
#define DELAY_CHANNEL_CHANGE 2
|
||||
|
||||
// main loop for measurement
|
||||
bool sweep(bool break_on_operation)
|
||||
static bool sweep(bool break_on_operation)
|
||||
{
|
||||
int i;
|
||||
int i, delay;
|
||||
// blink LED while scanning
|
||||
palClearPad(GPIOC, GPIOC_LED);
|
||||
systime_t time = chVTGetSystemTimeX();
|
||||
systime_t sweep_t = 0;
|
||||
si5351_enable_output();
|
||||
// On CW set freq once, and run
|
||||
for (i = 0; i < sweep_points; i++) { // 8365
|
||||
sweep_t-= chVTGetSystemTimeX();
|
||||
int delay = set_frequency(frequencies[i]); // 1560
|
||||
sweep_t+= chVTGetSystemTimeX();
|
||||
wait_dsp(1); // Wait for get optimal timings
|
||||
for (i = 0; i < sweep_points; i++) { // 5300
|
||||
delay = set_frequency(frequencies[i]); // 700
|
||||
tlv320aic3204_select(0); // 60 CH0:REFLECT
|
||||
|
||||
wait_dsp(delay+(i==0 ? 1 :0)); // 3270
|
||||
wait_dsp(delay); // 1900
|
||||
// calculate reflection coefficient
|
||||
(*sample_func)(measured[0][i]); // 60
|
||||
|
||||
tlv320aic3204_select(1); // 60 CH1:TRANSMISSION
|
||||
wait_dsp(DELAY_CHANNEL_CHANGE); // 2700
|
||||
wait_dsp(DELAY_CHANNEL_CHANGE); // 1800
|
||||
// calculate transmission coefficient
|
||||
(*sample_func)(measured[1][i]); // 60
|
||||
// ======== 170 ===========
|
||||
|
|
@ -813,7 +790,6 @@ bool sweep(bool break_on_operation)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
{char string_buf[18];plot_printf(string_buf, sizeof string_buf, "T:%06d:%06d", chVTGetSystemTimeX() - time, sweep_t);ili9341_drawstringV(string_buf, 1, 90);}
|
||||
// blink LED while scanning
|
||||
palSetPad(GPIOC, GPIOC_LED);
|
||||
return true;
|
||||
|
|
@ -849,11 +825,11 @@ VNA_SHELL_FUNCTION(cmd_scan)
|
|||
if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY))
|
||||
cal_interpolate(lastsaveid);
|
||||
|
||||
sweep_once = TRUE;
|
||||
run_once_sweep();
|
||||
chMtxUnlock(&mutex);
|
||||
|
||||
// wait finishing sweep
|
||||
while (sweep_once)
|
||||
while (sweep_mode&SWEEP_MODE_RUN_ONCE)
|
||||
chThdSleepMilliseconds(10);
|
||||
}
|
||||
|
||||
|
|
@ -1294,35 +1270,20 @@ void
|
|||
cal_collect(int type)
|
||||
{
|
||||
ensure_edit_config();
|
||||
|
||||
int dst, src;
|
||||
switch (type) {
|
||||
case CAL_LOAD:
|
||||
cal_status |= CALSTAT_LOAD;
|
||||
memcpy(cal_data[CAL_LOAD], measured[0], sizeof measured[0]);
|
||||
break;
|
||||
|
||||
case CAL_OPEN:
|
||||
cal_status |= CALSTAT_OPEN;
|
||||
cal_status &= ~(CALSTAT_ES|CALSTAT_APPLY);
|
||||
memcpy(cal_data[CAL_OPEN], measured[0], sizeof measured[0]);
|
||||
break;
|
||||
|
||||
case CAL_SHORT:
|
||||
cal_status |= CALSTAT_SHORT;
|
||||
cal_status &= ~(CALSTAT_ER|CALSTAT_APPLY);
|
||||
memcpy(cal_data[CAL_SHORT], measured[0], sizeof measured[0]);
|
||||
break;
|
||||
|
||||
case CAL_THRU:
|
||||
cal_status |= CALSTAT_THRU;
|
||||
memcpy(cal_data[CAL_THRU], measured[1], sizeof measured[0]);
|
||||
break;
|
||||
|
||||
case CAL_ISOLN:
|
||||
cal_status |= CALSTAT_ISOLN;
|
||||
memcpy(cal_data[CAL_ISOLN], measured[1], sizeof measured[0]);
|
||||
break;
|
||||
case CAL_LOAD: cal_status|= CALSTAT_LOAD; dst = CAL_LOAD; src = 0; break;
|
||||
case CAL_OPEN: cal_status|= CALSTAT_OPEN; dst = CAL_OPEN; src = 0; cal_status&= ~(CALSTAT_ES|CALSTAT_APPLY); break;
|
||||
case CAL_SHORT: cal_status|= CALSTAT_SHORT; dst = CAL_SHORT; src = 0; cal_status&= ~(CALSTAT_ER|CALSTAT_APPLY); break;
|
||||
case CAL_THRU: cal_status|= CALSTAT_THRU; dst = CAL_THRU; src = 1; break;
|
||||
case CAL_ISOLN: cal_status|= CALSTAT_ISOLN; dst = CAL_ISOLN; src = 1; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
// Made sweep operation for collect calibration data
|
||||
sweep(false);
|
||||
// Copy calibration data
|
||||
memcpy(cal_data[dst], measured[src], sizeof measured[0]);
|
||||
redraw_request|= REDRAW_CAL_STATUS;
|
||||
}
|
||||
|
||||
|
|
@ -2165,24 +2126,27 @@ THD_FUNCTION(myshellThread, p) {
|
|||
#endif
|
||||
|
||||
// I2C clock bus setting: depend from STM32_I2C1SW in mcuconf.h
|
||||
// STM32_I2C1SW = STM32_I2C1SW_HSI (HSI=8MHz)
|
||||
// STM32_I2C1SW = STM32_I2C1SW_SYSCLK (SYSCLK = 48MHz)
|
||||
static const I2CConfig i2ccfg = {
|
||||
// TIMINGR register initialization. (use I2C timing configuration tool for STM32F3xx and STM32F0xx microcontrollers (AN4235))
|
||||
// 400kHz @ SYSCLK 48MHz (Use 26.4.10 I2C_TIMINGR register configuration examples from STM32 RM0091 Reference manual)
|
||||
// STM32_TIMINGR_PRESC(5U) |
|
||||
// STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) |
|
||||
// STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U),
|
||||
.timingr = // TIMINGR register initialization. (use I2C timing configuration tool for STM32F3xx and STM32F0xx microcontrollers (AN4235))
|
||||
#if STM32_I2C1SW == STM32_I2C1SW_HSI
|
||||
// STM32_I2C1SW == STM32_I2C1SW_HSI (HSI=8MHz)
|
||||
// 400kHz @ HSI 8MHz (Use 26.4.10 I2C_TIMINGR register configuration examples from STM32 RM0091 Reference manual)
|
||||
STM32_TIMINGR_PRESC(0U) |
|
||||
STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(1U) |
|
||||
STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U),
|
||||
// Old values voodoo magic 400kHz @ HSI 8MHz
|
||||
// STM32_TIMINGR_PRESC(0U) |
|
||||
// STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(0U) |
|
||||
// STM32_TIMINGR_SCLH(5U) | STM32_TIMINGR_SCLL(6U),
|
||||
0, // CR1 register initialization.
|
||||
0 // CR2 register initialization.
|
||||
//0x00300506,
|
||||
#elif STM32_I2C1SW == STM32_I2C1SW_SYSCLK
|
||||
// STM32_I2C1SW == STM32_I2C1SW_SYSCLK (SYSCLK = 48MHz)
|
||||
// 400kHz @ SYSCLK 48MHz (Use 26.4.10 I2C_TIMINGR register configuration examples from STM32 RM0091 Reference manual)
|
||||
STM32_TIMINGR_PRESC(5U) |
|
||||
STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) |
|
||||
STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U),
|
||||
#else
|
||||
#error "Need Define STM32_I2C1SW and set correct TIMINGR settings"
|
||||
#endif
|
||||
.cr1 = 0, // CR1 register initialization.
|
||||
.cr2 = 0 // CR2 register initialization.
|
||||
};
|
||||
|
||||
static DACConfig dac1cfg1 = {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@
|
|||
#define STM32_ADCSW STM32_ADCSW_HSI14
|
||||
#define STM32_USBSW STM32_USBSW_HSI48
|
||||
#define STM32_CECSW STM32_CECSW_HSI
|
||||
#define STM32_I2C1SW STM32_I2C1SW_HSI
|
||||
//#define STM32_I2C1SW STM32_I2C1SW_HSI
|
||||
#define STM32_I2C1SW STM32_I2C1SW_SYSCLK
|
||||
#define STM32_USART1SW STM32_USART1SW_PCLK
|
||||
#define STM32_RTCSEL STM32_RTCSEL_LSI
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,9 @@ double my_atof(const char *p);
|
|||
void toggle_sweep(void);
|
||||
void loadDefaultProps(void);
|
||||
|
||||
extern int8_t sweep_enabled;
|
||||
#define SWEEP_MODE_ENABLED 0x01
|
||||
#define SWEEP_MODE_RUN_ONCE 0x02
|
||||
extern volatile int8_t sweep_mode;
|
||||
|
||||
/*
|
||||
* dsp.c
|
||||
|
|
@ -279,12 +281,12 @@ int marker_search(void);
|
|||
int marker_search_left(int from);
|
||||
int marker_search_right(int from);
|
||||
|
||||
extern uint16_t redraw_request;
|
||||
|
||||
// _request flag for update screen
|
||||
#define REDRAW_CELLS (1<<0)
|
||||
#define REDRAW_FREQUENCY (1<<1)
|
||||
#define REDRAW_CAL_STATUS (1<<2)
|
||||
#define REDRAW_MARKER (1<<3)
|
||||
extern volatile uint8_t redraw_request;
|
||||
|
||||
extern int16_t vbat;
|
||||
|
||||
|
|
|
|||
340
si5351.c
340
si5351.c
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com
|
||||
* Modified by DiSlord dislordlive@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
|
|
@ -21,15 +22,19 @@
|
|||
#include "nanovna.h"
|
||||
#include "si5351.h"
|
||||
|
||||
#define XTALFREQ 26000000L
|
||||
// MCLK (processor clock, audio codec) frequency clock
|
||||
#define CLK2_FREQUENCY 8000000L
|
||||
// Enable cache for SI5351 CLKX_CONTROL register, little speedup exchange
|
||||
#define USE_CLK_CONTROL_CACHE TRUE
|
||||
|
||||
// Fixed PLL mode multiplier
|
||||
// XTAL frequency on si5351
|
||||
#define XTALFREQ 26000000U
|
||||
// MCLK (processor clock if set, audio codec) frequency clock
|
||||
#define CLK2_FREQUENCY 8000000U
|
||||
|
||||
// Fixed PLL mode multiplier (used in band 1)
|
||||
#define PLL_N 32
|
||||
|
||||
//
|
||||
#define SI5351_I2C_ADDR (0x60<<1)
|
||||
// I2C address on bus (only 0x60 for Si5351A in 10-Pin MSOP)
|
||||
#define SI5351_I2C_ADDR 0x60
|
||||
|
||||
static uint8_t current_band = 0;
|
||||
static uint32_t current_freq = 0;
|
||||
|
|
@ -37,9 +42,8 @@ static uint32_t current_freq = 0;
|
|||
static void
|
||||
si5351_bulk_write(const uint8_t *buf, int len)
|
||||
{
|
||||
int addr = SI5351_I2C_ADDR>>1;
|
||||
i2cAcquireBus(&I2CD1);
|
||||
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000);
|
||||
(void)i2cMasterTransmitTimeout(&I2CD1, SI5351_I2C_ADDR, buf, len, NULL, 0, 1000);
|
||||
i2cReleaseBus(&I2CD1);
|
||||
}
|
||||
#if 0
|
||||
|
|
@ -64,15 +68,18 @@ const uint8_t si5351_configs[] = {
|
|||
2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff,
|
||||
4, SI5351_REG_16_CLK0_CONTROL, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN,
|
||||
2, SI5351_REG_183_CRYSTAL_LOAD, SI5351_CRYSTAL_LOAD_8PF,
|
||||
// All of this init code run late on sweep
|
||||
#if 0
|
||||
// setup PLL (26MHz * 32 = 832MHz, 32/2-2=14)
|
||||
// 9, SI5351_REG_PLL_A, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
|
||||
// 9, SI5351_REG_PLL_B, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
|
||||
9, SI5351_REG_PLL_A, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
|
||||
9, SI5351_REG_PLL_B, /*P3*/0, 1, /*P1*/0, 14, 0, /*P3/P2*/0, 0, 0,
|
||||
// RESET PLL
|
||||
2, SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B | 0x0C, //
|
||||
// setup multisynth (832MHz / 104 = 8MHz, 104/2-2=50)
|
||||
// 9, SI5351_REG_58_MULTISYNTH2, /*P3*/0, 1, /*P1*/0, 50, 0, /*P2|P3*/0, 0, 0,
|
||||
// 2, SI5351_REG_18_CLK2_CONTROL, SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_INPUT_MULTISYNTH_N | SI5351_CLK_INTEGER_MODE,
|
||||
// 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0,
|
||||
9, SI5351_REG_58_MULTISYNTH2, /*P3*/0, 1, /*P1*/0, 50, 0, /*P2|P3*/0, 0, 0,
|
||||
2, SI5351_REG_18_CLK2_CONTROL, SI5351_CLK_DRIVE_STRENGTH_2MA | SI5351_CLK_INPUT_MULTISYNTH_N | SI5351_CLK_INTEGER_MODE,
|
||||
2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0,
|
||||
#endif
|
||||
0 // sentinel
|
||||
};
|
||||
|
||||
|
|
@ -106,217 +113,185 @@ static const uint8_t clkctrl[] = {
|
|||
SI5351_REG_18_CLK2_CONTROL
|
||||
};
|
||||
|
||||
// Reset PLL need then band changes
|
||||
static void si5351_reset_pll(uint8_t mask)
|
||||
{
|
||||
// Writing a 1<<5 will reset PLLA, 1<<7 reset PLLB, this is a self clearing bits.
|
||||
// !!! Need delay before reset PLL for apply PLL freq changes before
|
||||
chThdSleepMicroseconds(200);
|
||||
si5351_write(SI5351_REG_177_PLL_RESET, mask | 0x0C);
|
||||
// chThdSleepMicroseconds(250);
|
||||
}
|
||||
|
||||
void si5351_disable_output(void)
|
||||
{
|
||||
// si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, (SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN));
|
||||
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff);
|
||||
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xFF);
|
||||
si5351_bulk_write(disable_output, sizeof(disable_output));
|
||||
}
|
||||
|
||||
void si5351_enable_output(void)
|
||||
{
|
||||
si5351_reset_pll( SI5351_PLL_RESET_A | SI5351_PLL_RESET_B );
|
||||
// si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, ~(SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN));
|
||||
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0x00);
|
||||
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, ~(SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN));
|
||||
//si5351_reset_pll(SI5351_PLL_RESET_A | SI5351_PLL_RESET_B);
|
||||
current_freq = 0;
|
||||
current_band = 0;
|
||||
}
|
||||
|
||||
static void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */
|
||||
uint8_t mult,
|
||||
// Set PLL freq = XTALFREQ * (mult + num/denom)
|
||||
static void si5351_setupPLL(uint8_t pllSource, /* SI5351_REG_PLL_A or SI5351_REG_PLL_B */
|
||||
uint32_t mult,
|
||||
uint32_t num,
|
||||
uint32_t denom)
|
||||
{
|
||||
uint32_t P1;
|
||||
uint32_t P2;
|
||||
uint32_t P3;
|
||||
|
||||
/* Feedback Multisynth Divider Equation
|
||||
* where: a = mult, b = num and c = denom
|
||||
* P1 register is an 18-bit value using following formula:
|
||||
* P1[17:0] = 128 * mult + floor(128*(num/denom)) - 512
|
||||
* P1[17:0] = 128 * mult + int((128*num)/denom) - 512
|
||||
* P2 register is a 20-bit value using the following formula:
|
||||
* P2[19:0] = 128 * num - denom * floor(128*(num/denom))
|
||||
* P2[19:0] = (128 * num) % denom
|
||||
* P3 register is a 20-bit value using the following formula:
|
||||
* P3[19:0] = denom
|
||||
*/
|
||||
|
||||
/* Set the main PLL config registers */
|
||||
if (num == 0)
|
||||
{
|
||||
/* Integer mode */
|
||||
P1 = 128 * mult - 512;
|
||||
P2 = 0;
|
||||
P3 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fractional mode */
|
||||
//P1 = (uint32_t)(128 * mult + floor(128 * ((float)num/(float)denom)) - 512);
|
||||
P1 = 128 * mult + ((128 * num) / denom) - 512;
|
||||
//P2 = (uint32_t)(128 * num - denom * floor(128 * ((float)num/(float)denom)));
|
||||
P2 = 128 * num - denom * ((128 * num) / denom);
|
||||
mult<<=7;
|
||||
num<<=7;
|
||||
uint32_t P1 = mult - 512; // Integer mode
|
||||
uint32_t P2 = 0;
|
||||
uint32_t P3 = 1;
|
||||
if (num){ // Fractional mode
|
||||
P1+= num / denom;
|
||||
P2 = num % denom;
|
||||
P3 = denom;
|
||||
}
|
||||
// Pll MSN(A|B) registers Datasheet
|
||||
// MSN_P3[15:8]
|
||||
// MSN_P3[ 7:0]
|
||||
// Reserved | MSN_P1[17:16]
|
||||
// MSN_P1[15:8]
|
||||
// MSN_P1[ 7:0]
|
||||
// MSN_P3[19:16] | MSN_P2[19:16]
|
||||
// MSN_P2[15:8]
|
||||
// MSN_P2[ 7:0]
|
||||
uint8_t reg[9];
|
||||
reg[0] = pll;//reg_base[pll];
|
||||
reg[1] = (P3 & 0x0000FF00) >> 8;
|
||||
reg[2] = (P3 & 0x000000FF);
|
||||
reg[3] = (P1 & 0x00030000) >> 16;
|
||||
reg[4] = (P1 & 0x0000FF00) >> 8;
|
||||
reg[5] = (P1 & 0x000000FF);
|
||||
reg[6] = ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16);
|
||||
reg[7] = (P2 & 0x0000FF00) >> 8;
|
||||
reg[8] = (P2 & 0x000000FF);
|
||||
reg[0]= pllSource; // SI5351_REG_PLL_A or SI5351_REG_PLL_B
|
||||
reg[1]=( P3 & 0x0FF00)>> 8; // MSN_P3[15: 8]
|
||||
reg[2]=( P3 & 0x000FF); // MSN_P3[ 7: 0]
|
||||
reg[3]=( P1 & 0x30000)>>16; // MSN_P1[17:16]
|
||||
reg[4]=( P1 & 0x0FF00)>> 8; // MSN_P1[15: 8]
|
||||
reg[5]=( P1 & 0x000FF); // MSN_P1[ 7: 0]
|
||||
reg[6]=((P3 & 0xF0000)>>12)|((P2 & 0xF0000)>>16); // MSN_P3[19:16] | MSN_P2[19:16]
|
||||
reg[7]=( P2 & 0x0FF00)>> 8; // MSN_P2[15: 8]
|
||||
reg[8]=( P2 & 0x000FF); // MSN_P2[ 7: 0]
|
||||
si5351_bulk_write(reg, 9);
|
||||
}
|
||||
|
||||
|
||||
// Set Multisynth divider = (div + num/denom) * rdiv
|
||||
static void
|
||||
si5351_setupMultisynth(uint8_t channel,
|
||||
uint8_t pllSource,
|
||||
uint32_t div, // 4,6,8, 8+ ~ 900
|
||||
uint32_t num,
|
||||
uint32_t denom,
|
||||
uint32_t rdiv, // SI5351_R_DIV_1~128
|
||||
uint8_t drive_strength)
|
||||
uint8_t chctrl) // SI5351_REG_16_CLKX_CONTROL settings
|
||||
{
|
||||
uint8_t dat;
|
||||
|
||||
uint32_t P1;
|
||||
uint32_t P2;
|
||||
uint32_t P3;
|
||||
uint32_t div4 = 0;
|
||||
|
||||
/* Output Multisynth Divider Equations
|
||||
* where: a = div, b = num and c = denom
|
||||
* P1 register is an 18-bit value using following formula:
|
||||
* P1[17:0] = 128 * a + floor(128*(b/c)) - 512
|
||||
* P1[17:0] = 128 * a + int((128*b)/c) - 512
|
||||
* P2 register is a 20-bit value using the following formula:
|
||||
* P2[19:0] = 128 * b - c * floor(128*(b/c))
|
||||
* P2[19:0] = (128 * b) % c
|
||||
* P3 register is a 20-bit value using the following formula:
|
||||
* P3[19:0] = c
|
||||
*/
|
||||
/* Set the main PLL config registers */
|
||||
if (div == 4) {
|
||||
div4 = SI5351_DIVBY4;
|
||||
P1 = P2 = 0;
|
||||
P3 = 1;
|
||||
} else if (num == 0) {
|
||||
/* Integer mode */
|
||||
P1 = 128 * div - 512;
|
||||
P2 = 0;
|
||||
P3 = 1;
|
||||
} else {
|
||||
/* Fractional mode */
|
||||
P1 = 128 * div + ((128 * num) / denom) - 512;
|
||||
P2 = 128 * num - denom * ((128 * num) / denom);
|
||||
uint32_t P1 = 0;
|
||||
uint32_t P2 = 0;
|
||||
uint32_t P3 = 1;
|
||||
if (div == 4)
|
||||
rdiv|= SI5351_DIVBY4;
|
||||
else {
|
||||
num<<=7;
|
||||
div<<=7;
|
||||
P1 = div - 512; // Integer mode
|
||||
if (num){ // Fractional mode
|
||||
P1+= num / denom;
|
||||
P2 = num % denom;
|
||||
P3 = denom;
|
||||
}
|
||||
|
||||
}
|
||||
/* Set the MSx config registers */
|
||||
uint8_t reg[9];
|
||||
reg[0] = msreg_base[channel];
|
||||
reg[1] = (P3 & 0x0000FF00) >> 8;
|
||||
reg[2] = (P3 & 0x000000FF);
|
||||
reg[3] = ((P1 & 0x00030000) >> 16) | div4 | rdiv;
|
||||
reg[4] = (P1 & 0x0000FF00) >> 8;
|
||||
reg[5] = (P1 & 0x000000FF);
|
||||
reg[6] = ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16);
|
||||
reg[7] = (P2 & 0x0000FF00) >> 8;
|
||||
reg[8] = (P2 & 0x000000FF);
|
||||
reg[0]= msreg_base[channel]; // SI5351_REG_42_MULTISYNTH0, SI5351_REG_50_MULTISYNTH1, SI5351_REG_58_MULTISYNTH2
|
||||
reg[1]=( P3 & 0x0FF00)>>8; // MSx_P3[15: 8]
|
||||
reg[2]=( P3 & 0x000FF); // MSx_P3[ 7: 0]
|
||||
reg[3]=((P1 & 0x30000)>>16)| rdiv; // Rx_DIV[2:0] | MSx_DIVBY4[1:0] | MSx_P1[17:16]
|
||||
reg[4]=( P1 & 0x0FF00)>> 8; // MSx_P1[15: 8]
|
||||
reg[5]=( P1 & 0x000FF); // MSx_P1[ 7: 0]
|
||||
reg[6]=((P3 & 0xF0000)>>12)|((P2 & 0xF0000)>>16); // MSx_P3[19:16] | MSx_P2[19:16]
|
||||
reg[7]=( P2 & 0x0FF00)>>8; // MSx_P2[15: 8]
|
||||
reg[8]=( P2 & 0x000FF); // MSx_P2[ 7: 0]
|
||||
si5351_bulk_write(reg, 9);
|
||||
|
||||
/* Configure the clk control and enable the output */
|
||||
dat = drive_strength | SI5351_CLK_INPUT_MULTISYNTH_N;
|
||||
if (pllSource == SI5351_REG_PLL_B)
|
||||
dat |= SI5351_CLK_PLL_SELECT_B;
|
||||
uint8_t dat = chctrl | SI5351_CLK_INPUT_MULTISYNTH_N;
|
||||
if (num == 0)
|
||||
dat |= SI5351_CLK_INTEGER_MODE;
|
||||
|
||||
#if USE_CLK_CONTROL_CACHE == TRUE
|
||||
// Use cache for this reg, not update if not change
|
||||
static uint8_t clk_cache[3];
|
||||
if (clk_cache[channel]!=dat){
|
||||
si5351_write(clkctrl[channel], dat);
|
||||
clk_cache[channel]=dat;
|
||||
}
|
||||
#else
|
||||
si5351_write(clkctrl[channel], dat);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
si5351_set_frequency_fixedpll(uint8_t channel, uint32_t pllSource, uint64_t pllfreq, uint32_t freq, uint32_t rdiv, uint8_t drive_strength)
|
||||
{
|
||||
uint32_t denom = freq;
|
||||
uint32_t div = pllfreq / denom; // range: 8 ~ 1800
|
||||
uint32_t num = pllfreq % denom;
|
||||
|
||||
// Find better approximate values for n/d
|
||||
#define MAX_DENOMINATOR ((1 << 20) - 1)
|
||||
static inline void fractionalSolve(uint32_t *n, uint32_t *d){
|
||||
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
|
||||
uint32_t max_denominator = (1 << 20) - 1;
|
||||
if (denom > max_denominator) {
|
||||
uint32_t denom = *d;
|
||||
if (denom > MAX_DENOMINATOR) {
|
||||
uint32_t num = *n;
|
||||
uint32_t p0 = 0, q0 = 1, p1 = 1, q1 = 0;
|
||||
while (denom != 0) {
|
||||
uint32_t a = num / denom;
|
||||
uint32_t b = num % denom;
|
||||
uint32_t q2 = q0 + a*q1;
|
||||
if (q2 > max_denominator)
|
||||
break;
|
||||
uint32_t p2 = p0 + a*p1;
|
||||
p0 = p1;
|
||||
q0 = q1;
|
||||
p1 = p2;
|
||||
q1 = q2;
|
||||
num = denom; denom = b;
|
||||
}
|
||||
num = p1;
|
||||
denom = q1;
|
||||
}
|
||||
si5351_setupMultisynth(channel, pllSource, div, num, denom, rdiv, drive_strength);
|
||||
}
|
||||
|
||||
void si5351_setupPLL_freq(uint32_t pll, uint32_t freq, uint32_t div, uint32_t mul){
|
||||
uint32_t denom = XTALFREQ * mul;
|
||||
uint64_t pllfreq = (uint64_t)freq * div;
|
||||
uint32_t multi = pllfreq / denom;
|
||||
uint32_t num = pllfreq % denom;
|
||||
|
||||
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
|
||||
uint32_t max_denominator = (1 << 20) - 1;
|
||||
if (denom > max_denominator) {
|
||||
uint32_t p0 = 0, q0 = 1, p1 = 1, q1 = 0;
|
||||
while (denom != 0) {
|
||||
uint32_t a = num / denom;
|
||||
uint32_t b = num % denom;
|
||||
uint32_t q2 = q0 + a*q1;
|
||||
if (q2 > max_denominator)
|
||||
if (q2 > MAX_DENOMINATOR)
|
||||
break;
|
||||
uint32_t p2 = p0 + a*p1;
|
||||
p0 = p1; q0 = q1; p1 = p2; q1 = q2;
|
||||
num = denom; denom = b;
|
||||
}
|
||||
num = p1;
|
||||
denom = q1;
|
||||
*n = p1;
|
||||
*d = q1;
|
||||
}
|
||||
si5351_setupPLL(pll, multi, num, denom);
|
||||
}
|
||||
|
||||
// Setup Multisynth divider for get correct output freq if fixed PLL = pllfreq
|
||||
static void
|
||||
si5351_set_frequency_fixedpll(uint8_t channel, uint64_t pllfreq, uint32_t freq, uint32_t rdiv, uint8_t chctrl)
|
||||
{
|
||||
uint32_t denom = freq;
|
||||
uint32_t div = pllfreq / denom; // range: 8 ~ 1800
|
||||
uint32_t num = pllfreq % denom;
|
||||
fractionalSolve(&num, &denom);
|
||||
si5351_setupMultisynth(channel, div, num, denom, rdiv, chctrl);
|
||||
}
|
||||
|
||||
// Setup PLL freq if Multisynth divider fixed = div (need get output = freq/mul)
|
||||
static void
|
||||
si5351_setupPLL_freq(uint32_t pllSource, uint32_t freq, uint32_t div, uint32_t mul){
|
||||
uint32_t denom = XTALFREQ * mul;
|
||||
uint64_t pllfreq = (uint64_t)freq * div;
|
||||
uint32_t multi = pllfreq / denom;
|
||||
uint32_t num = pllfreq % denom;
|
||||
fractionalSolve(&num, &denom);
|
||||
si5351_setupPLL(pllSource, multi, num, denom);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
si5351_set_frequency_fixeddiv(uint8_t channel, uint32_t pll, uint32_t freq, uint32_t div,
|
||||
uint8_t drive_strength, uint32_t mul)
|
||||
uint8_t chctrl, uint32_t mul)
|
||||
{
|
||||
si5351_setupPLL_freq(pll, freq, div, mul);
|
||||
si5351_setupMultisynth(channel, pll, div, 0, 1, SI5351_R_DIV_1, drive_strength);
|
||||
si5351_setupMultisynth(channel, div, 0, 1, SI5351_R_DIV_1, chctrl);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -332,19 +307,48 @@ si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength){
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Frequency generation divide on 3 band
|
||||
* Band 1
|
||||
* 1~100MHz fixed PLL = XTALFREQ * PLL_N, fractional divider
|
||||
* Band 2
|
||||
* 100~150MHz fractional PLL = 600- 900MHz, fixed divider 'fdiv = 6'
|
||||
* Band 3
|
||||
* 150~300MHz fractional PLL = 600-1200MHz, fixed divider 'fdiv = 4'
|
||||
*
|
||||
* For FREQ_HARMONICS = 300MHz - band range is:
|
||||
* +-----------------------------------------------------------------------------------------------------------------------+
|
||||
* | Band 1 | Band 2 | Band 3 | Band 2 | Band 3 |
|
||||
* +-----------------------------------------------------------------------------------------------------------------------+
|
||||
* | x1 : x1 | x1 : x1 | x1 : x1 | x3 : x5 | x3 : x5 | x5-x7 | x7-x9 | x9-x11 |
|
||||
* | 50kHz - 100MHz | 100 - 150MHz | 150 - 300MHz | 300-450MHz | 450-900MHz | 900-1500MHz | 1500-2100MHz | 2100-2700MHz |
|
||||
* +-----------------------------------------------------------------------------------------------------------------------+
|
||||
* | f = 50kHz-100MHz | f=100-150 | f=150-300 | f=150-300 | f=214-300 | f=233-300 |
|
||||
* | of = 50kHz-100MHz |of= 60- 90 |of= 90-180 |of=128-215 |of=166-234 |of=190-246 |
|
||||
* +-----------------------------------------------------------------------------------------------------------------------+
|
||||
*/
|
||||
static inline uint8_t si5351_getBand(uint32_t freq){
|
||||
if (freq < 100000000U) return 1;
|
||||
if (freq < 150000000U) return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Minimum value is 2, freq change apply at next dsp measure, and need skip it
|
||||
#define DELAY_NORMAL 2
|
||||
// Additional delay for band 1 (remove unstable generation at begin)
|
||||
#define DELAY_BAND_1 1
|
||||
// Band changes need additional delay after reset PLL
|
||||
#define DELAY_BANDCHANGE 2
|
||||
|
||||
/*
|
||||
* Maximum supported frequency = FREQ_HARMONICS * 9U
|
||||
* configure output as follows:
|
||||
* CLK0: frequency + offset
|
||||
* CLK1: frequency
|
||||
* CLK2: fixed 8MHz
|
||||
*/
|
||||
|
||||
int
|
||||
si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength)
|
||||
{
|
||||
si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength){
|
||||
uint8_t band;
|
||||
int delay = DELAY_NORMAL;
|
||||
if (freq == current_freq)
|
||||
|
|
@ -369,54 +373,40 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng
|
|||
}
|
||||
else if (freq <= 500000U) {
|
||||
rdiv = SI5351_R_DIV_64;
|
||||
freq *= 64;
|
||||
ofreq *= 64;
|
||||
freq<<= 6;
|
||||
ofreq<<= 6;
|
||||
} else if (freq <= 4000000U) {
|
||||
rdiv = SI5351_R_DIV_8;
|
||||
freq *= 8;
|
||||
ofreq *= 8;
|
||||
}
|
||||
/*
|
||||
* Band 0
|
||||
* 1~100MHz fixed PLL = XTALFREQ * PLL_N, fractional divider
|
||||
* Band 1
|
||||
* 100~150MHz fractional PLL = 600- 900MHz, fixed divider 6
|
||||
* Band 2
|
||||
* 150~300MHz fractional PLL = 600-1200MHz, fixed divider 4
|
||||
*/
|
||||
if ((freq / mul) < 100000000U) {
|
||||
band = 1;
|
||||
} else if ((freq / mul) < 150000000U) {
|
||||
band = 2;
|
||||
fdiv = 6;
|
||||
} else {
|
||||
band = 3;
|
||||
fdiv = 4;
|
||||
freq<<= 3;
|
||||
ofreq<<= 3;
|
||||
}
|
||||
|
||||
band = si5351_getBand(freq/mul);
|
||||
switch (band) {
|
||||
case 1:
|
||||
// Setup CH0 and CH1 constant PLL freq at band change, and set CH2 freq = CLK2_FREQUENCY
|
||||
// Setup CH0 and CH1 constant PLLA freq at band change, and set CH2 freq = CLK2_FREQUENCY
|
||||
if (current_band != 1){
|
||||
si5351_setupPLL(SI5351_REG_PLL_A, PLL_N, 0, 1);
|
||||
si5351_setupPLL(SI5351_REG_PLL_B, PLL_N, 0, 1);
|
||||
si5351_set_frequency_fixedpll(2, SI5351_REG_PLL_B, XTALFREQ * PLL_N, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA);
|
||||
si5351_set_frequency_fixedpll(2, XTALFREQ * PLL_N, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA|SI5351_CLK_PLL_SELECT_A);
|
||||
}
|
||||
// Calculate and set CH0 and CH1 divider
|
||||
si5351_set_frequency_fixedpll(0, SI5351_REG_PLL_A, XTALFREQ * PLL_N * omul, ofreq, rdiv, drive_strength);
|
||||
si5351_set_frequency_fixedpll(1, SI5351_REG_PLL_A, XTALFREQ * PLL_N * mul, freq, rdiv, drive_strength);
|
||||
si5351_set_frequency_fixedpll(0, (uint64_t)omul * XTALFREQ * PLL_N, ofreq, rdiv, drive_strength|SI5351_CLK_PLL_SELECT_A);
|
||||
si5351_set_frequency_fixedpll(1, (uint64_t) mul * XTALFREQ * PLL_N, freq, rdiv, drive_strength|SI5351_CLK_PLL_SELECT_A);
|
||||
delay+=DELAY_BAND_1;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 2:// fdiv = 6
|
||||
case 3:// fdiv = 4;
|
||||
fdiv = (band == 2) ? 6 : 4;
|
||||
// Setup CH0 and CH1 constant fdiv divider at change
|
||||
if (current_band != band){
|
||||
si5351_setupMultisynth(0, SI5351_REG_PLL_A, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength);
|
||||
si5351_setupMultisynth(1, SI5351_REG_PLL_B, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength);
|
||||
si5351_setupMultisynth(0, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength|SI5351_CLK_PLL_SELECT_A);
|
||||
si5351_setupMultisynth(1, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength|SI5351_CLK_PLL_SELECT_B);
|
||||
}
|
||||
// Calculate and set CH0 and CH1 PLL freq
|
||||
si5351_setupPLL_freq(SI5351_REG_PLL_A, ofreq, fdiv, omul);// set PLLA freq = (ofreq/omul)*fdiv
|
||||
si5351_setupPLL_freq(SI5351_REG_PLL_B, freq, fdiv, mul);// set PLLB freq = ( freq/ mul)*fdiv
|
||||
// Calculate CH2 freq = CLK2_FREQUENCY, depend from calculated before CH1 PLLB = (freq/mul)*fdiv
|
||||
si5351_set_frequency_fixedpll(2, SI5351_REG_PLL_B, (freq/mul)*fdiv, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA);
|
||||
si5351_set_frequency_fixedpll(2, (uint64_t)freq*fdiv, CLK2_FREQUENCY*mul, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA|SI5351_CLK_PLL_SELECT_B);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
75
si5351.h
75
si5351.h
|
|
@ -17,12 +17,39 @@
|
|||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//#define SI5351_PLL_A 0
|
||||
//#define SI5351_PLL_B 1
|
||||
|
||||
#define SI5351_MULTISYNTH_DIV_4 4
|
||||
#define SI5351_MULTISYNTH_DIV_6 6
|
||||
#define SI5351_MULTISYNTH_DIV_8 8
|
||||
#define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3
|
||||
#define SI5351_CLK0_EN (1<<0)
|
||||
#define SI5351_CLK1_EN (1<<1)
|
||||
#define SI5351_CLK2_EN (1<<2)
|
||||
|
||||
// Reg 16-18 CLKX_CONTROL
|
||||
#define SI5351_REG_16_CLK0_CONTROL 16
|
||||
#define SI5351_REG_17_CLK1_CONTROL 17
|
||||
#define SI5351_REG_18_CLK2_CONTROL 18
|
||||
#define SI5351_CLK_POWERDOWN (1<<7)
|
||||
#define SI5351_CLK_INTEGER_MODE (1<<6)
|
||||
#define SI5351_CLK_PLL_SELECT_A (0<<5)
|
||||
#define SI5351_CLK_PLL_SELECT_B (1<<5)
|
||||
#define SI5351_CLK_INVERT (1<<4)
|
||||
#define SI5351_CLK_INPUT_MASK (3<<2)
|
||||
#define SI5351_CLK_INPUT_XTAL (0<<2)
|
||||
#define SI5351_CLK_INPUT_CLKIN (1<<2)
|
||||
#define SI5351_CLK_INPUT_MULTISYNTH_0_4 (2<<2)
|
||||
#define SI5351_CLK_INPUT_MULTISYNTH_N (3<<2)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_MASK (3<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_2MA (0<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_4MA (1<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_6MA (2<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_8MA (3<<0)
|
||||
|
||||
#define SI5351_REG_PLL_A 26
|
||||
#define SI5351_REG_PLL_B 34
|
||||
|
||||
#define SI5351_REG_42_MULTISYNTH0 42
|
||||
#define SI5351_REG_50_MULTISYNTH1 50
|
||||
#define SI5351_REG_58_MULTISYNTH2 58
|
||||
#define SI5351_DIVBY4 (3<<2)
|
||||
#define SI5351_R_DIV_1 (0<<4)
|
||||
#define SI5351_R_DIV_2 (1<<4)
|
||||
#define SI5351_R_DIV_4 (2<<4)
|
||||
|
|
@ -31,39 +58,6 @@
|
|||
#define SI5351_R_DIV_32 (5<<4)
|
||||
#define SI5351_R_DIV_64 (6<<4)
|
||||
#define SI5351_R_DIV_128 (7<<4)
|
||||
#define SI5351_DIVBY4 (3<<2)
|
||||
|
||||
#define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3
|
||||
#define SI5351_CLK0_EN (1<<0)
|
||||
#define SI5351_CLK1_EN (1<<2)
|
||||
#define SI5351_CLK2_EN (1<<3)
|
||||
|
||||
#define SI5351_REG_16_CLK0_CONTROL 16
|
||||
#define SI5351_REG_17_CLK1_CONTROL 17
|
||||
#define SI5351_REG_18_CLK2_CONTROL 18
|
||||
#define SI5351_REG_PLL_A 26
|
||||
#define SI5351_REG_PLL_B 34
|
||||
#define SI5351_REG_42_MULTISYNTH0 42
|
||||
#define SI5351_REG_50_MULTISYNTH1 50
|
||||
#define SI5351_REG_58_MULTISYNTH2 58
|
||||
|
||||
#define SI5351_CLK_POWERDOWN (1<<7)
|
||||
#define SI5351_CLK_INTEGER_MODE (1<<6)
|
||||
#define SI5351_CLK_PLL_SELECT_B (1<<5)
|
||||
#define SI5351_CLK_INVERT (1<<4)
|
||||
|
||||
#define SI5351_CLK_INPUT_MASK (3<<2)
|
||||
#define SI5351_CLK_INPUT_XTAL (0<<2)
|
||||
#define SI5351_CLK_INPUT_CLKIN (1<<2)
|
||||
#define SI5351_CLK_INPUT_MULTISYNTH_0_4 (2<<2)
|
||||
#define SI5351_CLK_INPUT_MULTISYNTH_N (3<<2)
|
||||
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_MASK (3<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_2MA (0<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_4MA (1<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_6MA (2<<0)
|
||||
#define SI5351_CLK_DRIVE_STRENGTH_8MA (3<<0)
|
||||
|
||||
|
||||
#define SI5351_REG_177_PLL_RESET 177
|
||||
#define SI5351_PLL_RESET_B (1<<7)
|
||||
|
|
@ -74,11 +68,8 @@
|
|||
#define SI5351_CRYSTAL_LOAD_8PF (2<<6)
|
||||
#define SI5351_CRYSTAL_LOAD_10PF (3<<6)
|
||||
|
||||
#define SI5351_CRYSTAL_FREQ_25MHZ 25000000
|
||||
|
||||
void si5351_init(void);
|
||||
|
||||
void si5351_disable_output(void);
|
||||
void si5351_enable_output(void);
|
||||
void si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength);
|
||||
//void si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength);
|
||||
int si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength);
|
||||
|
|
|
|||
4
ui.c
4
ui.c
|
|
@ -1358,7 +1358,7 @@ menu_item_modify_attribute(const menuitem_t *menu, int item,
|
|||
*fg = config.menu_normal_color;
|
||||
}
|
||||
} else if (menu == menu_stimulus) {
|
||||
if (item == 5 /* PAUSE */ && !sweep_enabled) {
|
||||
if (item == 5 /* PAUSE */ && !(sweep_mode&SWEEP_MODE_ENABLED)) {
|
||||
*bg = DEFAULT_MENU_TEXT_COLOR;
|
||||
*fg = config.menu_normal_color;
|
||||
}
|
||||
|
|
@ -2131,7 +2131,7 @@ touch_lever_mode_select(void)
|
|||
select_lever_mode(touch_x < FREQUENCIES_XPOS2 ? LM_CENTER : LM_SPAN);
|
||||
return TRUE;
|
||||
}
|
||||
if (touch_y < 15) {
|
||||
if (touch_y < 25) {
|
||||
if (touch_x < FREQUENCIES_XPOS2 && get_electrical_delay() != 0.0) {
|
||||
select_lever_mode(LM_EDELAY);
|
||||
} else
|
||||
|
|
|
|||
Loading…
Reference in a new issue