mirror of
https://github.com/ttrftech/NanoVNA.git
synced 2025-12-06 03:31:59 +01:00
Merge pull request #125 from DiSlord/master
Speedup and fix Si5351 clock generator
This commit is contained in:
commit
7c2e4364e6
121
adc.c
121
adc.c
|
|
@ -28,80 +28,79 @@
|
|||
#define ADC_SMPR_SMP_239P5 7U /**< @brief 252 cycles conversion time. */
|
||||
#define ADC_CFGR1_RES_12BIT (0U << 3U)
|
||||
|
||||
#define VNA_ADC ADC1
|
||||
|
||||
void adc_init(void)
|
||||
{
|
||||
rccEnableADC1(FALSE);
|
||||
|
||||
/* Ensure flag states */
|
||||
ADC1->IER = 0;
|
||||
VNA_ADC->IER = 0;
|
||||
|
||||
/* Calibration procedure.*/
|
||||
ADC->CCR = 0;
|
||||
if (ADC1->CR & ADC_CR_ADEN) {
|
||||
ADC1->CR |= ~ADC_CR_ADDIS; /* Disable ADC */
|
||||
if (VNA_ADC->CR & ADC_CR_ADEN) {
|
||||
VNA_ADC->CR |= ~ADC_CR_ADDIS; /* Disable ADC */
|
||||
}
|
||||
while (ADC1->CR & ADC_CR_ADEN)
|
||||
while (VNA_ADC->CR & ADC_CR_ADEN)
|
||||
;
|
||||
ADC1->CFGR1 &= ~ADC_CFGR1_DMAEN;
|
||||
ADC1->CR |= ADC_CR_ADCAL;
|
||||
while (ADC1->CR & ADC_CR_ADCAL)
|
||||
VNA_ADC->CFGR1 &= ~ADC_CFGR1_DMAEN;
|
||||
VNA_ADC->CR |= ADC_CR_ADCAL;
|
||||
while (VNA_ADC->CR & ADC_CR_ADCAL)
|
||||
;
|
||||
|
||||
if (ADC1->ISR & ADC_ISR_ADRDY) {
|
||||
ADC1->ISR |= ADC_ISR_ADRDY; /* clear ADRDY */
|
||||
if (VNA_ADC->ISR & ADC_ISR_ADRDY) {
|
||||
VNA_ADC->ISR |= ADC_ISR_ADRDY; /* clear ADRDY */
|
||||
}
|
||||
/* Enable ADC */
|
||||
ADC1->CR |= ADC_CR_ADEN;
|
||||
while (!(ADC1->ISR & ADC_ISR_ADRDY))
|
||||
VNA_ADC->CR |= ADC_CR_ADEN;
|
||||
while (!(VNA_ADC->ISR & ADC_ISR_ADRDY))
|
||||
;
|
||||
}
|
||||
|
||||
uint16_t adc_single_read(ADC_TypeDef *adc, uint32_t chsel)
|
||||
uint16_t adc_single_read(uint32_t chsel)
|
||||
{
|
||||
/* ADC setup */
|
||||
adc->ISR = adc->ISR;
|
||||
adc->IER = 0;
|
||||
adc->TR = ADC_TR(0, 0);
|
||||
adc->SMPR = ADC_SMPR_SMP_239P5;
|
||||
adc->CFGR1 = ADC_CFGR1_RES_12BIT;
|
||||
adc->CHSELR = chsel;
|
||||
VNA_ADC->ISR = VNA_ADC->ISR;
|
||||
VNA_ADC->IER = 0;
|
||||
VNA_ADC->TR = ADC_TR(0, 0);
|
||||
VNA_ADC->SMPR = ADC_SMPR_SMP_239P5;
|
||||
VNA_ADC->CFGR1 = ADC_CFGR1_RES_12BIT;
|
||||
VNA_ADC->CHSELR = chsel;
|
||||
|
||||
/* ADC conversion start.*/
|
||||
adc->CR |= ADC_CR_ADSTART;
|
||||
VNA_ADC->CR |= ADC_CR_ADSTART;
|
||||
|
||||
while (adc->CR & ADC_CR_ADSTART)
|
||||
while (VNA_ADC->CR & ADC_CR_ADSTART)
|
||||
;
|
||||
|
||||
return adc->DR;
|
||||
return VNA_ADC->DR;
|
||||
}
|
||||
|
||||
int16_t adc_vbat_read(ADC_TypeDef *adc)
|
||||
int16_t adc_vbat_read(void)
|
||||
{
|
||||
#define ADC_FULL_SCALE 3300
|
||||
#define VBAT_DIODE_VF 500
|
||||
#define VREFINT_CAL (*((uint16_t*)0x1FFFF7BA))
|
||||
float vbat = 0;
|
||||
float vrefint = 0;
|
||||
|
||||
ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_VBATEN;
|
||||
// VREFINT == ADC_IN17
|
||||
vrefint = adc_single_read(adc, ADC_CHSELR_CHSEL17);
|
||||
// VBAT == ADC_IN18
|
||||
// VBATEN enables resiter devider circuit. It consume vbat power.
|
||||
vbat = adc_single_read(adc, ADC_CHSELR_CHSEL18);
|
||||
ADC->CCR &= ~(ADC_CCR_VREFEN | ADC_CCR_VBATEN);
|
||||
|
||||
uint16_t vbat_raw = (ADC_FULL_SCALE * VREFINT_CAL * vbat * 2 / (vrefint * ((1<<12)-1)));
|
||||
if (vbat_raw < 100) {
|
||||
// maybe D2 is not installed
|
||||
return -1;
|
||||
}
|
||||
|
||||
return vbat_raw + VBAT_DIODE_VF;
|
||||
|
||||
adc_stop();
|
||||
float vbat = 0;
|
||||
float vrefint = 0;
|
||||
ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_VBATEN;
|
||||
// VREFINT == ADC_IN17
|
||||
vrefint = adc_single_read(ADC_CHSELR_CHSEL17);
|
||||
// VBAT == ADC_IN18
|
||||
// VBATEN enables resiter devider circuit. It consume vbat power.
|
||||
vbat = adc_single_read(ADC_CHSELR_CHSEL18);
|
||||
ADC->CCR &= ~(ADC_CCR_VREFEN | ADC_CCR_VBATEN);
|
||||
touch_start_watchdog();
|
||||
uint16_t vbat_raw = (ADC_FULL_SCALE * VREFINT_CAL * vbat * 2 / (vrefint * ((1<<12)-1)));
|
||||
if (vbat_raw < 100) {
|
||||
// maybe D2 is not installed
|
||||
return -1;
|
||||
}
|
||||
return vbat_raw + config.vbat_offset;
|
||||
}
|
||||
|
||||
void adc_start_analog_watchdogd(ADC_TypeDef *adc, uint32_t chsel)
|
||||
void adc_start_analog_watchdogd(uint32_t chsel)
|
||||
{
|
||||
uint32_t cfgr1;
|
||||
|
||||
|
|
@ -111,38 +110,38 @@ void adc_start_analog_watchdogd(ADC_TypeDef *adc, uint32_t chsel)
|
|||
|
||||
/* ADC setup, if it is defined a callback for the analog watch dog then it
|
||||
is enabled.*/
|
||||
adc->ISR = adc->ISR;
|
||||
adc->IER = ADC_IER_AWDIE;
|
||||
adc->TR = ADC_TR(0, TOUCH_THRESHOLD);
|
||||
adc->SMPR = ADC_SMPR_SMP_1P5;
|
||||
adc->CHSELR = chsel;
|
||||
VNA_ADC->ISR = VNA_ADC->ISR;
|
||||
VNA_ADC->IER = ADC_IER_AWDIE;
|
||||
VNA_ADC->TR = ADC_TR(0, TOUCH_THRESHOLD);
|
||||
VNA_ADC->SMPR = ADC_SMPR_SMP_1P5;
|
||||
VNA_ADC->CHSELR = chsel;
|
||||
|
||||
/* ADC configuration and start.*/
|
||||
adc->CFGR1 = cfgr1;
|
||||
VNA_ADC->CFGR1 = cfgr1;
|
||||
|
||||
/* ADC conversion start.*/
|
||||
adc->CR |= ADC_CR_ADSTART;
|
||||
VNA_ADC->CR |= ADC_CR_ADSTART;
|
||||
}
|
||||
|
||||
void adc_stop(ADC_TypeDef *adc)
|
||||
void adc_stop(void)
|
||||
{
|
||||
if (adc->CR & ADC_CR_ADEN) {
|
||||
if (adc->CR & ADC_CR_ADSTART) {
|
||||
adc->CR |= ADC_CR_ADSTP;
|
||||
while (adc->CR & ADC_CR_ADSTP)
|
||||
if (VNA_ADC->CR & ADC_CR_ADEN) {
|
||||
if (VNA_ADC->CR & ADC_CR_ADSTART) {
|
||||
VNA_ADC->CR |= ADC_CR_ADSTP;
|
||||
while (VNA_ADC->CR & ADC_CR_ADSTP)
|
||||
;
|
||||
}
|
||||
|
||||
/* adc->CR |= ADC_CR_ADDIS;
|
||||
while (adc->CR & ADC_CR_ADDIS)
|
||||
/* VNA_ADC->CR |= ADC_CR_ADDIS;
|
||||
while (VNA_ADC->CR & ADC_CR_ADDIS)
|
||||
;*/
|
||||
}
|
||||
}
|
||||
|
||||
void adc_interrupt(ADC_TypeDef *adc)
|
||||
void adc_interrupt(void)
|
||||
{
|
||||
uint32_t isr = adc->ISR;
|
||||
adc->ISR = isr;
|
||||
uint32_t isr = VNA_ADC->ISR;
|
||||
VNA_ADC->ISR = isr;
|
||||
|
||||
if (isr & ADC_ISR_OVR) {
|
||||
/* ADC overflow condition, this could happen only if the DMA is unable
|
||||
|
|
@ -159,7 +158,7 @@ OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER)
|
|||
{
|
||||
OSAL_IRQ_PROLOGUE();
|
||||
|
||||
adc_interrupt(ADC1);
|
||||
adc_interrupt();
|
||||
|
||||
OSAL_IRQ_EPILOGUE();
|
||||
}
|
||||
|
|
|
|||
206
main.c
206
main.c
|
|
@ -57,6 +57,8 @@ static char shell_line[VNA_SHELL_MAX_LENGTH];
|
|||
//#define ENABLED_DUMP
|
||||
//#define ENABLE_THREADS_COMMAND
|
||||
//#define ENABLE_TIME_COMMAND
|
||||
#define ENABLE_VBAT_OFFSET_COMMAND
|
||||
#define ENABLE_INFO_COMMAND
|
||||
|
||||
static void apply_error_term_at(int i);
|
||||
static void apply_edelay_at(int i);
|
||||
|
|
@ -72,20 +74,30 @@ static MUTEX_DECL(mutex);
|
|||
#define DRIVE_STRENGTH_AUTO (-1)
|
||||
#define FREQ_HARMONICS (config.harmonic_freq_threshold)
|
||||
#define IS_HARMONIC_MODE(f) ((f) > FREQ_HARMONICS)
|
||||
// Obsolete, always use interpolate
|
||||
#define cal_auto_interpolate TRUE
|
||||
|
||||
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
|
||||
int16_t vbat = 0;
|
||||
static int32_t frequency_offset = 5000;
|
||||
static uint32_t frequency = 10000000;
|
||||
static int8_t drive_strength = DRIVE_STRENGTH_AUTO;
|
||||
int8_t sweep_mode = SWEEP_ENABLE;
|
||||
volatile uint8_t redraw_request = 0; // contains REDRAW_XXX flags
|
||||
|
||||
// Version text, displayed in Config->Version menu, also send by info command
|
||||
const char *info_about[]={
|
||||
BOARD_NAME,
|
||||
"2016-2020 Copyright @edy555",
|
||||
"Licensed under GPL. See: https://github.com/ttrftech/NanoVNA",
|
||||
"Version: " VERSION,
|
||||
"Build Time: " __DATE__ " - " __TIME__,
|
||||
"Kernel: " CH_KERNEL_VERSION,
|
||||
"Compiler: " PORT_COMPILER_NAME,
|
||||
"Architecture: " PORT_ARCHITECTURE_NAME " Core Variant: " PORT_CORE_VARIANT_NAME,
|
||||
"Port Info: " PORT_INFO,
|
||||
"Platform: " PLATFORM_NAME,
|
||||
0 // sentinel
|
||||
};
|
||||
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
|
|
@ -94,36 +106,27 @@ static THD_FUNCTION(Thread1, arg)
|
|||
|
||||
while (1) {
|
||||
bool completed = false;
|
||||
if (sweep_enabled || sweep_once) {
|
||||
if (sweep_mode&(SWEEP_ENABLE|SWEEP_ONCE)) {
|
||||
chMtxLock(&mutex);
|
||||
// Sweep require 8367 system tick
|
||||
completed = sweep(true);
|
||||
sweep_once = FALSE;
|
||||
sweep_mode&=~SWEEP_ONCE;
|
||||
chMtxUnlock(&mutex);
|
||||
} else {
|
||||
__WFI();
|
||||
}
|
||||
|
||||
chMtxLock(&mutex);
|
||||
// Ui and render require 800 system tick
|
||||
ui_process();
|
||||
|
||||
if (sweep_enabled) {
|
||||
if (vbat != -1) {
|
||||
adc_stop(ADC1);
|
||||
vbat = adc_vbat_read(ADC1);
|
||||
touch_start_watchdog();
|
||||
draw_battery_status();
|
||||
}
|
||||
|
||||
if (sweep_mode&SWEEP_ENABLE) {
|
||||
// calculate trace coordinates and plot only if scan completed
|
||||
if (completed) {
|
||||
if ((domain_mode & DOMAIN_MODE) == DOMAIN_TIME)
|
||||
transform_domain();
|
||||
plot_into_index(measured);
|
||||
redraw_request |= REDRAW_CELLS;
|
||||
redraw_request |= REDRAW_CELLS|REDRAW_BATTERY;
|
||||
|
||||
if (marker_tracking) {
|
||||
if (uistat.marker_tracking) {
|
||||
int i = marker_search();
|
||||
if (i != -1 && active_marker != -1) {
|
||||
markers[active_marker].index = i;
|
||||
|
|
@ -141,19 +144,19 @@ static THD_FUNCTION(Thread1, arg)
|
|||
static inline void
|
||||
pause_sweep(void)
|
||||
{
|
||||
sweep_enabled = FALSE;
|
||||
sweep_mode&=~SWEEP_ENABLE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
resume_sweep(void)
|
||||
{
|
||||
sweep_enabled = TRUE;
|
||||
sweep_mode|=SWEEP_ENABLE;
|
||||
}
|
||||
|
||||
void
|
||||
toggle_sweep(void)
|
||||
{
|
||||
sweep_enabled = !sweep_enabled;
|
||||
sweep_mode^=SWEEP_ENABLE;
|
||||
}
|
||||
|
||||
static float
|
||||
|
|
@ -316,19 +319,18 @@ const int8_t gain_table[] = {
|
|||
95 // 2400MHz ~
|
||||
};
|
||||
|
||||
#define DELAY_GAIN_CHANGE 10
|
||||
#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)
|
||||
|
|
@ -429,9 +431,9 @@ static int getStringIndex(char *v, const char *list){
|
|||
}
|
||||
// Set new substring ptr
|
||||
while (1){
|
||||
// End of string, not found
|
||||
if (*list == 0 ) return -1;
|
||||
if (*list++ == '|') break;
|
||||
// End of string, not found
|
||||
if (*list == 0 ) return -1;
|
||||
if (*list++ == '|') break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
|
@ -474,7 +476,7 @@ VNA_SHELL_FUNCTION(cmd_power)
|
|||
|
||||
#ifdef ENABLE_TIME_COMMAND
|
||||
#if HAL_USE_RTC == FALSE
|
||||
#error "Error cmd_time require ENABLE_TIME_COMMAND = TRUE in halconf.h"
|
||||
#error "Error cmd_time require define HAL_USE_RTC = TRUE in halconf.h"
|
||||
#endif
|
||||
VNA_SHELL_FUNCTION(cmd_time)
|
||||
{
|
||||
|
|
@ -559,15 +561,6 @@ volatile int16_t wait_count = 0;
|
|||
|
||||
float measured[2][POINTS_COUNT][2];
|
||||
|
||||
static void
|
||||
wait_dsp(int count)
|
||||
{
|
||||
wait_count = count;
|
||||
//reset_dsp_accumerator();
|
||||
while (wait_count)
|
||||
__WFI();
|
||||
}
|
||||
|
||||
#ifdef ENABLED_DUMP
|
||||
static void
|
||||
duplicate_buffer_to_dump(int16_t *p)
|
||||
|
|
@ -725,7 +718,8 @@ config_t config = {
|
|||
.trace_color = { DEFAULT_TRACE_1_COLOR, DEFAULT_TRACE_2_COLOR, DEFAULT_TRACE_3_COLOR, DEFAULT_TRACE_4_COLOR },
|
||||
// .touch_cal = { 693, 605, 124, 171 }, // 2.4 inch LCD panel
|
||||
.touch_cal = { 338, 522, 153, 192 }, // 2.8 inch LCD panel
|
||||
.harmonic_freq_threshold = 300000000
|
||||
.harmonic_freq_threshold = 300000000,
|
||||
.vbat_offset = 500
|
||||
};
|
||||
|
||||
properties_t current_props;
|
||||
|
|
@ -745,7 +739,8 @@ static const marker_t def_markers[MARKERS_MAX] = {
|
|||
|
||||
// Load propeties default settings
|
||||
void loadDefaultProps(void){
|
||||
current_props.magic = CONFIG_MAGIC;
|
||||
//Magic add on caldata_save
|
||||
//current_props.magic = CONFIG_MAGIC;
|
||||
current_props._frequency0 = 50000; // start = 50kHz
|
||||
current_props._frequency1 = 900000000; // end = 900MHz
|
||||
current_props._sweep_points = POINTS_COUNT;
|
||||
|
|
@ -761,6 +756,8 @@ void loadDefaultProps(void){
|
|||
current_props._active_marker = 0;
|
||||
current_props._domain_mode = 0;
|
||||
current_props._marker_smith_format = MS_RLC;
|
||||
//Checksum add on caldata_save
|
||||
//current_props.checksum = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -775,24 +772,37 @@ ensure_edit_config(void)
|
|||
cal_status = 0;
|
||||
}
|
||||
|
||||
#define DELAY_CHANNEL_CHANGE 3
|
||||
#define DSP_START(delay) wait_count = delay;
|
||||
#define DSP_WAIT_READY while (wait_count) __WFI();
|
||||
|
||||
#define DELAY_CHANNEL_CHANGE 2
|
||||
|
||||
// main loop for measurement
|
||||
bool sweep(bool break_on_operation)
|
||||
{
|
||||
int i;
|
||||
int i, delay;
|
||||
// blink LED while scanning
|
||||
palClearPad(GPIOC, GPIOC_LED);
|
||||
for (i = 0; i < sweep_points; i++) { // 8365
|
||||
int delay = set_frequency(frequencies[i]); // 1560
|
||||
// Power stabilization after LED off, also align timings
|
||||
// Also touch made some
|
||||
DSP_START(1); DSP_WAIT_READY;
|
||||
for (i = 0; i < sweep_points; i++) { // 5300
|
||||
delay = set_frequency(frequencies[i]); // 700
|
||||
tlv320aic3204_select(0); // 60 CH0:REFLECT
|
||||
|
||||
wait_dsp(delay); // 3270
|
||||
DSP_START(delay); // 1900
|
||||
//================================================
|
||||
// Place some code thats need execute while delay
|
||||
//================================================
|
||||
DSP_WAIT_READY;
|
||||
// calculate reflection coefficient
|
||||
(*sample_func)(measured[0][i]); // 60
|
||||
|
||||
tlv320aic3204_select(1); // 60 CH1:TRANSMISSION
|
||||
wait_dsp(DELAY_CHANNEL_CHANGE); // 2700
|
||||
DSP_START(DELAY_CHANNEL_CHANGE); // 1700
|
||||
//================================================
|
||||
// Place some code thats need execute while delay
|
||||
//================================================
|
||||
DSP_WAIT_READY;
|
||||
// calculate transmission coefficient
|
||||
(*sample_func)(measured[1][i]); // 60
|
||||
// ======== 170 ===========
|
||||
|
|
@ -841,11 +851,11 @@ VNA_SHELL_FUNCTION(cmd_scan)
|
|||
if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY))
|
||||
cal_interpolate(lastsaveid);
|
||||
|
||||
sweep_once = TRUE;
|
||||
sweep_mode|= SWEEP_ONCE;
|
||||
chMtxUnlock(&mutex);
|
||||
|
||||
// wait finishing sweep
|
||||
while (sweep_once)
|
||||
while (sweep_mode&SWEEP_ONCE)
|
||||
chThdSleepMilliseconds(10);
|
||||
}
|
||||
|
||||
|
|
@ -912,7 +922,7 @@ update_frequencies(void)
|
|||
}
|
||||
|
||||
set_frequencies(start, stop, sweep_points);
|
||||
operation_requested = OP_FREQCHANGE;
|
||||
// operation_requested|= OP_FREQCHANGE;
|
||||
|
||||
update_marker_index();
|
||||
|
||||
|
|
@ -1430,6 +1440,7 @@ VNA_SHELL_FUNCTION(cmd_cal)
|
|||
shell_printf("\r\n");
|
||||
return;
|
||||
}
|
||||
redraw_request|=REDRAW_CAL_STATUS;
|
||||
// 0 1 2 3 4 5 6 7 8 9 10
|
||||
static const char cmd_cal_list[] = "load|open|short|thru|isoln|done|on|off|reset|data|in";
|
||||
switch (getStringIndex(argv[0], cmd_cal_list)){
|
||||
|
|
@ -1439,9 +1450,9 @@ VNA_SHELL_FUNCTION(cmd_cal)
|
|||
case 3:cal_collect(CAL_THRU ); return;
|
||||
case 4:cal_collect(CAL_ISOLN); return;
|
||||
case 5:cal_done(); return;
|
||||
case 6:cal_status|= CALSTAT_APPLY;redraw_request|=REDRAW_CAL_STATUS; return;
|
||||
case 7:cal_status&=~CALSTAT_APPLY;redraw_request|=REDRAW_CAL_STATUS; return;
|
||||
case 8:cal_status = 0; redraw_request|=REDRAW_CAL_STATUS; return;
|
||||
case 6:cal_status|= CALSTAT_APPLY;return;
|
||||
case 7:cal_status&=~CALSTAT_APPLY;return;
|
||||
case 8:cal_status = 0; return;
|
||||
case 9:
|
||||
shell_printf("%f %f\r\n", cal_data[CAL_LOAD ][0][0], cal_data[CAL_LOAD ][0][1]);
|
||||
shell_printf("%f %f\r\n", cal_data[CAL_OPEN ][0][0], cal_data[CAL_OPEN ][0][1]);
|
||||
|
|
@ -1451,11 +1462,9 @@ VNA_SHELL_FUNCTION(cmd_cal)
|
|||
return;
|
||||
case 10:
|
||||
cal_interpolate((argc > 1) ? my_atoi(argv[1]) : 0);
|
||||
redraw_request|=REDRAW_CAL_STATUS;
|
||||
return;
|
||||
default:break;
|
||||
}
|
||||
|
||||
shell_printf("usage: cal [%s]\r\n", cmd_cal_list);
|
||||
}
|
||||
|
||||
|
|
@ -1687,14 +1696,13 @@ VNA_SHELL_FUNCTION(cmd_marker)
|
|||
}
|
||||
return;
|
||||
}
|
||||
redraw_request |= REDRAW_MARKER;
|
||||
if (strcmp(argv[0], "off") == 0) {
|
||||
active_marker = -1;
|
||||
for (t = 0; t < MARKERS_MAX; t++)
|
||||
markers[t].enabled = FALSE;
|
||||
redraw_request |= REDRAW_MARKER;
|
||||
return;
|
||||
}
|
||||
|
||||
t = my_atoi(argv[0])-1;
|
||||
if (t < 0 || t >= MARKERS_MAX)
|
||||
goto usage;
|
||||
|
|
@ -1703,13 +1711,12 @@ VNA_SHELL_FUNCTION(cmd_marker)
|
|||
active_marker = t;
|
||||
// select active marker
|
||||
markers[t].enabled = TRUE;
|
||||
redraw_request |= REDRAW_MARKER;
|
||||
return;
|
||||
}
|
||||
static const char cmd_marker_list[] = "on|off";
|
||||
switch (getStringIndex(argv[1], cmd_marker_list)){
|
||||
case 0: markers[t].enabled = TRUE; active_marker = t; redraw_request |= REDRAW_MARKER; return;
|
||||
case 1: markers[t].enabled =FALSE; if (active_marker == t) active_marker = -1; redraw_request|=REDRAW_MARKER; return;
|
||||
case 0: markers[t].enabled = TRUE; active_marker = t; return;
|
||||
case 1: markers[t].enabled =FALSE; if (active_marker == t) active_marker = -1; return;
|
||||
default:
|
||||
// select active marker and move to index
|
||||
markers[t].enabled = TRUE;
|
||||
|
|
@ -1717,7 +1724,6 @@ VNA_SHELL_FUNCTION(cmd_marker)
|
|||
markers[t].index = index;
|
||||
markers[t].frequency = frequencies[index];
|
||||
active_marker = t;
|
||||
redraw_request |= REDRAW_MARKER;
|
||||
return;
|
||||
}
|
||||
usage:
|
||||
|
|
@ -1923,8 +1929,8 @@ VNA_SHELL_FUNCTION(cmd_stat)
|
|||
//shell_printf("interval cycle: %d\r\n", stat.interval_cycles);
|
||||
//shell_printf("busy cycle: %d\r\n", stat.busy_cycles);
|
||||
//shell_printf("load: %d\r\n", stat.busy_cycles * 100 / stat.interval_cycles);
|
||||
extern int awd_count;
|
||||
shell_printf("awd: %d\r\n", awd_count);
|
||||
// extern int awd_count;
|
||||
// shell_printf("awd: %d\r\n", awd_count);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1945,9 +1951,31 @@ VNA_SHELL_FUNCTION(cmd_vbat)
|
|||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
shell_printf("%d mV\r\n", vbat);
|
||||
shell_printf("%d mV\r\n", adc_vbat_read());
|
||||
}
|
||||
|
||||
#ifdef ENABLE_VBAT_OFFSET_COMMAND
|
||||
VNA_SHELL_FUNCTION(cmd_vbat_offset)
|
||||
{
|
||||
if (argc != 1) {
|
||||
shell_printf("%d\r\n", config.vbat_offset);
|
||||
return;
|
||||
}
|
||||
config.vbat_offset = (int16_t)my_atoi(argv[0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_INFO_COMMAND
|
||||
VNA_SHELL_FUNCTION(cmd_info)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
int i=0;
|
||||
while (info_about[i])
|
||||
shell_printf("%s\r\n", info_about[i++]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_THREADS_COMMAND
|
||||
#if CH_CFG_USE_REGISTRY == FALSE
|
||||
#error "Threads Requite enabled CH_CFG_USE_REGISTRY in chconf.h"
|
||||
|
|
@ -1969,8 +1997,6 @@ VNA_SHELL_FUNCTION(cmd_threads) {
|
|||
#else
|
||||
uint32_t stklimit = 0U;
|
||||
#endif
|
||||
|
||||
|
||||
shell_printf("%08x|%08x|%08x|%08x|%4u|%4u|%9s|%12s"VNA_SHELL_NEWLINE_STR,
|
||||
stklimit, (uint32_t)tp->ctx.sp, max_stack_use, (uint32_t)tp,
|
||||
(uint32_t)tp->refs - 1, (uint32_t)tp->prio, states[tp->state],
|
||||
|
|
@ -2031,9 +2057,15 @@ static const VNAShellCommand commands[] =
|
|||
{"edelay" , cmd_edelay , 0},
|
||||
{"capture" , cmd_capture , CMD_WAIT_MUTEX},
|
||||
{"vbat" , cmd_vbat , 0},
|
||||
#ifdef ENABLE_VBAT_OFFSET_COMMAND
|
||||
{"vbat_offset" , cmd_vbat_offset , 0},
|
||||
#endif
|
||||
{"transform" , cmd_transform , 0},
|
||||
{"threshold" , cmd_threshold , 0},
|
||||
{"help" , cmd_help , 0},
|
||||
#ifdef ENABLE_INFO_COMMAND
|
||||
{"info" , cmd_info , 0},
|
||||
#endif
|
||||
#ifdef ENABLE_THREADS_COMMAND
|
||||
{"threads" , cmd_threads , 0},
|
||||
#endif
|
||||
|
|
@ -2160,10 +2192,28 @@ THD_FUNCTION(myshellThread, p) {
|
|||
}
|
||||
#endif
|
||||
|
||||
// I2C clock bus setting: depend from STM32_I2C1SW in mcuconf.h
|
||||
static const I2CConfig i2ccfg = {
|
||||
0x00300506, //voodoo magic 400kHz @ HSI 8MHz
|
||||
0,
|
||||
0
|
||||
.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
|
||||
//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
|
||||
|
||||
|
|
|
|||
79
nanovna.h
79
nanovna.h
|
|
@ -86,31 +86,10 @@ double my_atof(const char *p);
|
|||
void toggle_sweep(void);
|
||||
void loadDefaultProps(void);
|
||||
|
||||
extern int8_t sweep_enabled;
|
||||
|
||||
/*
|
||||
* flash.c
|
||||
*/
|
||||
#define SAVEAREA_MAX 5
|
||||
// Begin addr 0x08018000
|
||||
#define SAVE_CONFIG_AREA_SIZE 0x00008000
|
||||
// config save area
|
||||
#define SAVE_CONFIG_ADDR 0x08018000
|
||||
// properties_t save area
|
||||
#define SAVE_PROP_CONFIG_0_ADDR 0x08018800
|
||||
#define SAVE_PROP_CONFIG_1_ADDR 0x0801a000
|
||||
#define SAVE_PROP_CONFIG_2_ADDR 0x0801b800
|
||||
#define SAVE_PROP_CONFIG_3_ADDR 0x0801d000
|
||||
#define SAVE_PROP_CONFIG_4_ADDR 0x0801e800
|
||||
|
||||
/*
|
||||
* ui.c
|
||||
*/
|
||||
extern void ui_init(void);
|
||||
extern void ui_process(void);
|
||||
|
||||
enum opreq { OP_NONE = 0, OP_LEVER, OP_TOUCH, OP_FREQCHANGE };
|
||||
extern uint8_t operation_requested;
|
||||
#define SWEEP_ENABLE 0x01
|
||||
#define SWEEP_ONCE 0x02
|
||||
extern int8_t sweep_mode;
|
||||
extern const char *info_about[];
|
||||
|
||||
/*
|
||||
* dsp.c
|
||||
|
|
@ -134,9 +113,6 @@ void calculate_gamma(float *gamma);
|
|||
void fetch_amplitude(float *gamma);
|
||||
void fetch_amplitude_ref(float *gamma);
|
||||
|
||||
int si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength);
|
||||
|
||||
|
||||
/*
|
||||
* tlv320aic3204.c
|
||||
*/
|
||||
|
|
@ -243,8 +219,8 @@ typedef struct config {
|
|||
int16_t touch_cal[4];
|
||||
int8_t reserved_1;
|
||||
uint32_t harmonic_freq_threshold;
|
||||
|
||||
uint8_t _reserved[24];
|
||||
uint16_t vbat_offset;
|
||||
uint8_t _reserved[22];
|
||||
uint32_t checksum;
|
||||
} config_t;
|
||||
|
||||
|
|
@ -259,7 +235,6 @@ void set_trace_refpos(int t, float refpos);
|
|||
float get_trace_scale(int t);
|
||||
float get_trace_refpos(int t);
|
||||
const char *get_trace_typename(int t);
|
||||
void draw_battery_status(void);
|
||||
|
||||
void set_electrical_delay(float picoseconds);
|
||||
float get_electrical_delay(void);
|
||||
|
|
@ -302,14 +277,13 @@ 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 int16_t vbat;
|
||||
#define REDRAW_BATTERY (1<<4)
|
||||
extern volatile uint8_t redraw_request;
|
||||
|
||||
/*
|
||||
* ili9341.c
|
||||
|
|
@ -366,6 +340,16 @@ void show_logo(void);
|
|||
* flash.c
|
||||
*/
|
||||
#define SAVEAREA_MAX 5
|
||||
// Begin addr 0x08018000
|
||||
#define SAVE_CONFIG_AREA_SIZE 0x00008000
|
||||
// config save area
|
||||
#define SAVE_CONFIG_ADDR 0x08018000
|
||||
// properties_t save area
|
||||
#define SAVE_PROP_CONFIG_0_ADDR 0x08018800
|
||||
#define SAVE_PROP_CONFIG_1_ADDR 0x0801a000
|
||||
#define SAVE_PROP_CONFIG_2_ADDR 0x0801b800
|
||||
#define SAVE_PROP_CONFIG_3_ADDR 0x0801d000
|
||||
#define SAVE_PROP_CONFIG_4_ADDR 0x0801e800
|
||||
|
||||
typedef struct properties {
|
||||
uint32_t magic;
|
||||
|
|
@ -432,6 +416,15 @@ void clear_all_config_prop_data(void);
|
|||
/*
|
||||
* ui.c
|
||||
*/
|
||||
extern void ui_init(void);
|
||||
extern void ui_process(void);
|
||||
|
||||
// Irq operation process set
|
||||
#define OP_NONE 0x00
|
||||
#define OP_LEVER 0x01
|
||||
#define OP_TOUCH 0x02
|
||||
//#define OP_FREQCHANGE 0x04
|
||||
extern volatile uint8_t operation_requested;
|
||||
|
||||
// lever_mode
|
||||
enum lever_mode {
|
||||
|
|
@ -448,13 +441,13 @@ typedef struct uistat {
|
|||
int8_t digit_mode;
|
||||
int8_t current_trace; /* 0..3 */
|
||||
uint32_t value; // for editing at numeric input area
|
||||
uint32_t previous_value;
|
||||
// uint32_t previous_value;
|
||||
uint8_t lever_mode;
|
||||
bool marker_delta;
|
||||
uint8_t marker_delta;
|
||||
uint8_t marker_tracking;
|
||||
} uistat_t;
|
||||
|
||||
extern uistat_t uistat;
|
||||
|
||||
void ui_init(void);
|
||||
void ui_show(void);
|
||||
void ui_hide(void);
|
||||
|
|
@ -474,11 +467,11 @@ void enter_dfu(void);
|
|||
*/
|
||||
|
||||
void adc_init(void);
|
||||
uint16_t adc_single_read(ADC_TypeDef *adc, uint32_t chsel);
|
||||
void adc_start_analog_watchdogd(ADC_TypeDef *adc, uint32_t chsel);
|
||||
void adc_stop(ADC_TypeDef *adc);
|
||||
void adc_interrupt(ADC_TypeDef *adc);
|
||||
int16_t adc_vbat_read(ADC_TypeDef *adc);
|
||||
uint16_t adc_single_read(uint32_t chsel);
|
||||
void adc_start_analog_watchdogd(uint32_t chsel);
|
||||
void adc_stop(void);
|
||||
void adc_interrupt(void);
|
||||
int16_t adc_vbat_read(void);
|
||||
|
||||
/*
|
||||
* misclinous
|
||||
|
|
|
|||
10
plot.c
10
plot.c
|
|
@ -6,6 +6,7 @@
|
|||
#include "nanovna.h"
|
||||
|
||||
static void cell_draw_marker_info(int x0, int y0);
|
||||
static void draw_battery_status(void);
|
||||
|
||||
int16_t grid_offset;
|
||||
int16_t grid_width;
|
||||
|
|
@ -1056,7 +1057,6 @@ static int greater(int x, int y) { return x > y; }
|
|||
static int lesser(int x, int y) { return x < y; }
|
||||
|
||||
static int (*compare)(int x, int y) = lesser;
|
||||
int8_t marker_tracking = false;
|
||||
|
||||
int
|
||||
marker_search(void)
|
||||
|
|
@ -1389,6 +1389,8 @@ draw_all(bool flush)
|
|||
draw_frequencies();
|
||||
if (redraw_request & REDRAW_CAL_STATUS)
|
||||
draw_cal_status();
|
||||
if (redraw_request & REDRAW_BATTERY)
|
||||
draw_battery_status();
|
||||
redraw_request = 0;
|
||||
}
|
||||
|
||||
|
|
@ -1662,10 +1664,10 @@ draw_cal_status(void)
|
|||
#define BATTERY_BOTTOM_LEVEL 3100
|
||||
#define BATTERY_WARNING_LEVEL 3300
|
||||
|
||||
void
|
||||
draw_battery_status(void)
|
||||
static void draw_battery_status(void)
|
||||
{
|
||||
if (vbat<=0)
|
||||
int16_t vbat = adc_vbat_read();
|
||||
if (vbat <= 0)
|
||||
return;
|
||||
uint8_t string_buf[16];
|
||||
// Set battery color
|
||||
|
|
|
|||
523
si5351.c
523
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,40 +22,64 @@
|
|||
#include "nanovna.h"
|
||||
#include "si5351.h"
|
||||
|
||||
#define SI5351_I2C_ADDR (0x60<<1)
|
||||
// Enable cache for SI5351 CLKX_CONTROL register, little speedup exchange
|
||||
#define USE_CLK_CONTROL_CACHE TRUE
|
||||
|
||||
static void
|
||||
si5351_write(uint8_t reg, uint8_t dat)
|
||||
{
|
||||
int addr = SI5351_I2C_ADDR>>1;
|
||||
uint8_t buf[] = { reg, dat };
|
||||
i2cAcquireBus(&I2CD1);
|
||||
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, 2, NULL, 0, 1000);
|
||||
i2cReleaseBus(&I2CD1);
|
||||
}
|
||||
// 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
|
||||
|
||||
// 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;
|
||||
|
||||
static void
|
||||
si5351_bulk_write(const uint8_t *buf, int len)
|
||||
{
|
||||
i2cAcquireBus(&I2CD1);
|
||||
(void)i2cMasterTransmitTimeout(&I2CD1, SI5351_I2C_ADDR, buf, len, NULL, 0, 1000);
|
||||
i2cReleaseBus(&I2CD1);
|
||||
}
|
||||
#if 0
|
||||
static void si5351_bulk_read(uint8_t reg, uint8_t* buf, int len)
|
||||
{
|
||||
int addr = SI5351_I2C_ADDR>>1;
|
||||
i2cAcquireBus(&I2CD1);
|
||||
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000);
|
||||
msg_t mr = i2cMasterTransmitTimeout(&I2CD1, addr, ®, 1, buf, len, 1000);
|
||||
i2cReleaseBus(&I2CD1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
si5351_write(uint8_t reg, uint8_t dat)
|
||||
{
|
||||
uint8_t buf[] = { reg, dat };
|
||||
si5351_bulk_write(buf, 2);
|
||||
}
|
||||
|
||||
// register addr, length, data, ...
|
||||
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_26_PLL_A, /*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,
|
||||
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,
|
||||
#endif
|
||||
2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, ~(SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN),
|
||||
0 // sentinel
|
||||
};
|
||||
|
||||
|
|
@ -71,232 +96,207 @@ si5351_init(void)
|
|||
|
||||
static const uint8_t disable_output[] = {
|
||||
SI5351_REG_16_CLK0_CONTROL,
|
||||
SI5351_CLK_POWERDOWN,
|
||||
SI5351_CLK_POWERDOWN,
|
||||
SI5351_CLK_POWERDOWN
|
||||
SI5351_CLK_POWERDOWN, // CLK 0
|
||||
SI5351_CLK_POWERDOWN, // CLK 1
|
||||
SI5351_CLK_POWERDOWN // CLK 2
|
||||
};
|
||||
|
||||
/* Get the appropriate starting point for the PLL registers */
|
||||
static const uint8_t msreg_base[] = {
|
||||
SI5351_REG_42_MULTISYNTH0,
|
||||
SI5351_REG_50_MULTISYNTH1,
|
||||
SI5351_REG_58_MULTISYNTH2,
|
||||
};
|
||||
static const uint8_t clkctrl[] = {
|
||||
SI5351_REG_16_CLK0_CONTROL,
|
||||
SI5351_REG_17_CLK1_CONTROL,
|
||||
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(400);
|
||||
si5351_write(SI5351_REG_177_PLL_RESET, mask | 0x0C);
|
||||
}
|
||||
|
||||
void si5351_disable_output(void)
|
||||
{
|
||||
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));
|
||||
current_band = 0;
|
||||
}
|
||||
|
||||
void si5351_enable_output(void)
|
||||
{
|
||||
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_reset_pll(void)
|
||||
// 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)
|
||||
{
|
||||
//si5351_write(SI5351_REG_177_PLL_RESET, SI5351_PLL_RESET_A | SI5351_PLL_RESET_B);
|
||||
si5351_write(SI5351_REG_177_PLL_RESET, 0xAC);
|
||||
}
|
||||
|
||||
static void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */
|
||||
uint8_t mult,
|
||||
uint32_t num,
|
||||
uint32_t denom)
|
||||
{
|
||||
/* Get the appropriate starting point for the PLL registers */
|
||||
static const uint8_t pllreg_base[] = {
|
||||
SI5351_REG_26_PLL_A,
|
||||
SI5351_REG_34_PLL_B
|
||||
};
|
||||
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;
|
||||
}
|
||||
|
||||
/* The datasheet is a nightmare of typos and inconsistencies here! */
|
||||
// Pll MSN(A|B) registers Datasheet
|
||||
uint8_t reg[9];
|
||||
reg[0] = pllreg_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 output,
|
||||
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)
|
||||
si5351_setupMultisynth(uint8_t channel,
|
||||
uint32_t div, // 4,6,8, 8+ ~ 900
|
||||
uint32_t num,
|
||||
uint32_t denom,
|
||||
uint32_t rdiv, // SI5351_R_DIV_1~128
|
||||
uint8_t chctrl) // SI5351_REG_16_CLKX_CONTROL settings
|
||||
{
|
||||
/* Get the appropriate starting point for the PLL registers */
|
||||
static const uint8_t msreg_base[] = {
|
||||
SI5351_REG_42_MULTISYNTH0,
|
||||
SI5351_REG_50_MULTISYNTH1,
|
||||
SI5351_REG_58_MULTISYNTH2,
|
||||
};
|
||||
static const uint8_t clkctrl[] = {
|
||||
SI5351_REG_16_CLK0_CONTROL,
|
||||
SI5351_REG_17_CLK1_CONTROL,
|
||||
SI5351_REG_18_CLK2_CONTROL
|
||||
};
|
||||
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
|
||||
* 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);
|
||||
P3 = 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[output];
|
||||
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_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;
|
||||
si5351_write(clkctrl[output], dat);
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
#define XTALFREQ 26000000L
|
||||
#define PLL_N 32
|
||||
#define PLLFREQ (XTALFREQ * PLL_N)
|
||||
|
||||
static void
|
||||
si5351_set_frequency_fixedpll(int channel, int pll, uint32_t pllfreq, uint32_t freq,
|
||||
int rdiv, uint8_t drive_strength, int mul)
|
||||
{
|
||||
int denom = freq;
|
||||
int div = (pllfreq * mul) / denom; // range: 8 ~ 1800
|
||||
int num = (pllfreq * mul) - denom * div;
|
||||
|
||||
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
|
||||
int max_denominator = (1 << 20) - 1;
|
||||
if (denom > max_denominator) {
|
||||
int p0 = 0, q0 = 1, p1 = 1, q1 = 0;
|
||||
while (denom != 0) {
|
||||
int a = num / denom;
|
||||
int q2 = q0 + a*q1;
|
||||
if (q2 > max_denominator)
|
||||
break;
|
||||
int p2 = p0 + a*p1;
|
||||
p0 = p1; q0 = q1; p1 = p2; q1 = q2;
|
||||
int new_denom = num - a * denom;
|
||||
num = denom; denom = new_denom;
|
||||
}
|
||||
num = p1;
|
||||
denom = q1;
|
||||
// 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 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;
|
||||
}
|
||||
|
||||
si5351_setupMultisynth(channel, pll, div, num, denom, rdiv, drive_strength);
|
||||
*n = p1;
|
||||
*d = q1;
|
||||
}
|
||||
}
|
||||
|
||||
// Setup Multisynth divider for get correct output freq if fixed PLL = pllfreq
|
||||
static void
|
||||
si5351_set_frequency_fixeddiv(int channel, int pll, uint32_t freq, int div,
|
||||
uint8_t drive_strength, int mul)
|
||||
si5351_set_frequency_fixedpll(uint8_t channel, uint64_t pllfreq, uint32_t freq, uint32_t rdiv, uint8_t chctrl)
|
||||
{
|
||||
int denom = XTALFREQ * mul;
|
||||
int64_t pllfreq = (int64_t)freq * div;
|
||||
int multi = pllfreq / denom;
|
||||
int num = pllfreq - denom * multi;
|
||||
|
||||
// cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
|
||||
int max_denominator = (1 << 20) - 1;
|
||||
if (denom > max_denominator) {
|
||||
int p0 = 0, q0 = 1, p1 = 1, q1 = 0;
|
||||
while (denom != 0) {
|
||||
int a = num / denom;
|
||||
int q2 = q0 + a*q1;
|
||||
if (q2 > max_denominator)
|
||||
break;
|
||||
int p2 = p0 + a*p1;
|
||||
p0 = p1; q0 = q1; p1 = p2; q1 = q2;
|
||||
int new_denom = num - a * denom;
|
||||
num = denom; denom = new_denom;
|
||||
}
|
||||
num = p1;
|
||||
denom = q1;
|
||||
}
|
||||
|
||||
si5351_setupPLL(pll, multi, num, denom);
|
||||
si5351_setupMultisynth(channel, pll, div, 0, 1, SI5351_R_DIV_1, drive_strength);
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 1~100MHz fixed PLL 900MHz, fractional divider
|
||||
* 100~150MHz fractional PLL 600-900MHz, fixed divider 6
|
||||
* 150~200MHz fractional PLL 600-900MHz, fixed divider 4
|
||||
*/
|
||||
#if 0
|
||||
void
|
||||
si5351_set_frequency(int channel, int freq, uint8_t drive_strength)
|
||||
static void
|
||||
si5351_set_frequency_fixeddiv(uint8_t channel, uint32_t pll, uint32_t freq, uint32_t div,
|
||||
uint8_t chctrl, uint32_t mul)
|
||||
{
|
||||
si5351_setupPLL_freq(pll, freq, div, mul);
|
||||
si5351_setupMultisynth(channel, div, 0, 1, SI5351_R_DIV_1, chctrl);
|
||||
}
|
||||
|
||||
void
|
||||
si5351_set_frequency(int channel, uint32_t freq, uint8_t drive_strength){
|
||||
if (freq <= 100000000) {
|
||||
si5351_setupPLL(SI5351_PLL_B, 32, 0, 1);
|
||||
si5351_set_frequency_fixedpll(channel, SI5351_PLL_B, PLLFREQ, freq, SI5351_R_DIV_1, drive_strength, 1);
|
||||
|
|
@ -308,117 +308,116 @@ si5351_set_frequency(int channel, int freq, uint8_t drive_strength)
|
|||
}
|
||||
#endif
|
||||
|
||||
int current_band = -1;
|
||||
/*
|
||||
* 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 |
|
||||
* +-----------------------------------------------------------------------------------------------------------------------+
|
||||
* | Direct mode x1 : x1 | 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-300MHz | f=100-150 | f=150-300 | f=150-300 | f=214-300 | f=233-300 |
|
||||
* | of = 50kHz-300MHz |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;
|
||||
}
|
||||
|
||||
#define DELAY_NORMAL 3
|
||||
#define DELAY_BANDCHANGE 1
|
||||
#define DELAY_LOWBAND 1
|
||||
// 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_1 2
|
||||
#define DELAY_BANDCHANGE_2 2
|
||||
|
||||
/*
|
||||
* Maximum supported frequency = FREQ_HARMONICS * 9U
|
||||
* configure output as follows:
|
||||
* CLK0: frequency + offset
|
||||
* CLK1: frequency
|
||||
* CLK2: fixed 8MHz
|
||||
*/
|
||||
#define CLK2_FREQUENCY 8000000L
|
||||
int
|
||||
si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_strength)
|
||||
{
|
||||
int band;
|
||||
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)
|
||||
return delay;
|
||||
uint32_t ofreq = freq + offset;
|
||||
uint32_t mul = 1, omul = 1;
|
||||
uint32_t rdiv = SI5351_R_DIV_1;
|
||||
uint32_t fdiv;
|
||||
current_freq = freq;
|
||||
if (freq >= config.harmonic_freq_threshold * 7U) {
|
||||
mul = 9;
|
||||
mul = 9;
|
||||
omul = 11;
|
||||
} else if (freq >= config.harmonic_freq_threshold * 5U) {
|
||||
mul = 7;
|
||||
mul = 7;
|
||||
omul = 9;
|
||||
} else if (freq >= config.harmonic_freq_threshold * 3U) {
|
||||
mul = 5;
|
||||
mul = 5;
|
||||
omul = 7;
|
||||
} else if (freq >= config.harmonic_freq_threshold) {
|
||||
mul = 3;
|
||||
mul = 3;
|
||||
omul = 5;
|
||||
}
|
||||
if ((freq / mul) < 100000000U) {
|
||||
band = 0;
|
||||
} else if ((freq / mul) < 150000000U) {
|
||||
band = 1;
|
||||
} else {
|
||||
band = 2;
|
||||
}
|
||||
if (freq <= 500000U) {
|
||||
else if (freq <= 500000U) {
|
||||
rdiv = SI5351_R_DIV_64;
|
||||
freq<<= 6;
|
||||
ofreq<<= 6;
|
||||
} else if (freq <= 4000000U) {
|
||||
rdiv = SI5351_R_DIV_8;
|
||||
freq<<= 3;
|
||||
ofreq<<= 3;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (current_band != band)
|
||||
si5351_disable_output();
|
||||
#endif
|
||||
|
||||
band = si5351_getBand(freq/mul);
|
||||
switch (band) {
|
||||
case 0:
|
||||
// fractional divider mode. only PLL A is used.
|
||||
if (current_band == 1 || current_band == 2)
|
||||
si5351_setupPLL(SI5351_PLL_A, 32, 0, 1);
|
||||
// Set PLL twice on changing from band 2
|
||||
if (current_band == 2)
|
||||
si5351_setupPLL(SI5351_PLL_A, 32, 0, 1);
|
||||
|
||||
if (rdiv == SI5351_R_DIV_8) {
|
||||
freq *= 8;
|
||||
ofreq *= 8;
|
||||
} else if (rdiv == SI5351_R_DIV_64) {
|
||||
freq *= 64;
|
||||
ofreq *= 64;
|
||||
}
|
||||
|
||||
si5351_set_frequency_fixedpll(0, SI5351_PLL_A, PLLFREQ, ofreq,
|
||||
rdiv, drive_strength, omul);
|
||||
si5351_set_frequency_fixedpll(1, SI5351_PLL_A, PLLFREQ, freq,
|
||||
rdiv, drive_strength, mul);
|
||||
//if (current_band != 0)
|
||||
si5351_set_frequency_fixedpll(2, SI5351_PLL_A, PLLFREQ, CLK2_FREQUENCY,
|
||||
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Set PLL twice on changing from band 2
|
||||
if (current_band == 2) {
|
||||
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul);
|
||||
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul);
|
||||
// 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_set_frequency_fixedpll(2, XTALFREQ * PLL_N, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA|SI5351_CLK_PLL_SELECT_A);
|
||||
delay+=DELAY_BANDCHANGE_1;
|
||||
}
|
||||
|
||||
// div by 6 mode. both PLL A and B are dedicated for CLK0, CLK1
|
||||
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul);
|
||||
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul);
|
||||
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq / mul * 6, CLK2_FREQUENCY,
|
||||
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1);
|
||||
// Calculate and set CH0 and CH1 divider
|
||||
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:
|
||||
// div by 4 mode. both PLL A and B are dedicated for CLK0, CLK1
|
||||
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 4, drive_strength, omul);
|
||||
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 4, drive_strength, mul);
|
||||
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq / mul * 4, CLK2_FREQUENCY,
|
||||
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1);
|
||||
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, 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);
|
||||
delay+=DELAY_BANDCHANGE_2;
|
||||
}
|
||||
// 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, (uint64_t)freq*fdiv, CLK2_FREQUENCY*mul, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA|SI5351_CLK_PLL_SELECT_B);
|
||||
break;
|
||||
}
|
||||
|
||||
if (current_band != band) {
|
||||
si5351_reset_pll();
|
||||
#if 1
|
||||
si5351_enable_output();
|
||||
#endif
|
||||
delay += DELAY_BANDCHANGE;
|
||||
si5351_reset_pll(SI5351_PLL_RESET_A|SI5351_PLL_RESET_B);
|
||||
current_band = band;
|
||||
}
|
||||
if (band == 0)
|
||||
delay += DELAY_LOWBAND;
|
||||
|
||||
current_band = band;
|
||||
return delay;
|
||||
}
|
||||
|
|
|
|||
74
si5351.h
74
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,35 +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_REG_16_CLK0_CONTROL 16
|
||||
#define SI5351_REG_17_CLK1_CONTROL 17
|
||||
#define SI5351_REG_18_CLK2_CONTROL 18
|
||||
#define SI5351_REG_26_PLL_A 26
|
||||
#define SI5351_REG_34_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)
|
||||
|
|
@ -70,8 +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_set_frequency(int channel, int freq, uint8_t drive_strength);
|
||||
void si5351_disable_output(void);
|
||||
void si5351_enable_output(void);
|
||||
//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);
|
||||
|
|
|
|||
159
tlv320aic3204.c
159
tlv320aic3204.c
|
|
@ -25,74 +25,78 @@
|
|||
|
||||
#define wait_ms(ms) chThdSleepMilliseconds(ms)
|
||||
|
||||
static const uint8_t conf_data_pll[] = {
|
||||
// len, ( reg, data ),
|
||||
2, 0x00, 0x00, /* Initialize to Page 0 */
|
||||
2, 0x01, 0x01, /* Initialize the device through software reset */
|
||||
2, 0x04, 0x43, /* PLL Clock High, MCLK, PLL */
|
||||
static const uint8_t conf_data[] = {
|
||||
// reg, data,
|
||||
// PLL clock config
|
||||
0x00, 0x00, /* Initialize to Page 0 */
|
||||
0x01, 0x01, /* Initialize the device through software reset */
|
||||
0x04, 0x43, /* PLL Clock High, MCLK, PLL */
|
||||
#ifdef REFCLK_8000KHZ
|
||||
/* 8.000MHz*10.7520 = 86.016MHz, 86.016MHz/(2*7*128) = 48kHz */
|
||||
2, 0x05, 0x91, /* Power up PLL, P=1,R=1 */
|
||||
2, 0x06, 0x0a, /* J=10 */
|
||||
2, 0x07, 29, /* D=7520 = (29<<8) + 96 */
|
||||
2, 0x08, 96,
|
||||
0x05, 0x91, /* Power up PLL, P=1,R=1 */
|
||||
0x06, 0x0a, /* J=10 */
|
||||
0x07, 29, /* D=7520 = (29<<8) + 96 */
|
||||
0x08, 96,
|
||||
#endif
|
||||
0 // sentinel
|
||||
// Clock config, default fs=48kHz
|
||||
0x0b, 0x82, /* Power up the NDAC divider with value 2 */
|
||||
0x0c, 0x87, /* Power up the MDAC divider with value 7 */
|
||||
0x0d, 0x00, /* Program the OSR of DAC to 128 */
|
||||
0x0e, 0x80,
|
||||
0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */
|
||||
//0x3c, 25, /* Set the DAC Mode to PRB_P25 */
|
||||
0x1b, 0x0c, /* Set the BCLK,WCLK as output */
|
||||
0x1e, 0x80 + 28, /* Enable the BCLKN divider with value 28 */
|
||||
0x25, 0xee, /* DAC power up */
|
||||
|
||||
0x12, 0x82, /* Power up the NADC divider with value 2 */
|
||||
0x13, 0x87, /* Power up the MADC divider with value 7 */
|
||||
0x14, 0x80, /* Program the OSR of ADC to 128 */
|
||||
0x3d, 0x01, /* Select ADC PRB_R1 */
|
||||
// Data routing
|
||||
0x00, 0x01, /* Select Page 1 */
|
||||
0x01, 0x08, /* Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO*/
|
||||
0x02, 0x01, /* Enable Master Analog Power Control */
|
||||
0x7b, 0x01, /* Set the REF charging time to 40ms */
|
||||
0x14, 0x25, /* HP soft stepping settings for optimal pop performance at power up Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling capacitor. Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound. */
|
||||
0x0a, 0x33, /* Set the Input Common Mode to 0.9V and Output Common Mode for Headphone to 1.65V */
|
||||
|
||||
0x3d, 0x00, /* Select ADC PTM_R4 */
|
||||
0x47, 0x32, /* Set MicPGA startup delay to 3.1ms */
|
||||
0x7b, 0x01, /* Set the REF charging time to 40ms */
|
||||
0x34, 0x10, /* Route IN2L to LEFT_P with 10K */
|
||||
0x36, 0x10, /* Route IN2R to LEFT_N with 10K */
|
||||
//0x37, 0x04, /* Route IN3R to RIGHT_P with 10K */
|
||||
//0x39, 0x04, /* Route IN3L to RIGHT_N with 10K */
|
||||
//0x3b, 0x00, /* Unmute Left MICPGA, Gain selection of 32dB to make channel gain 0dB */
|
||||
//0x3c, 0x00, /* Unmute Right MICPGA, Gain selection of 32dB to make channel gain 0dB */
|
||||
};
|
||||
|
||||
// default fs=48kHz
|
||||
static const uint8_t conf_data_clk[] = {
|
||||
2, 0x0b, 0x82, /* Power up the NDAC divider with value 2 */
|
||||
2, 0x0c, 0x87, /* Power up the MDAC divider with value 7 */
|
||||
2, 0x0d, 0x00, /* Program the OSR of DAC to 128 */
|
||||
2, 0x0e, 0x80,
|
||||
2, 0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */
|
||||
//2, 0x3c, 25, /* Set the DAC Mode to PRB_P25 */
|
||||
2, 0x1b, 0x0c, /* Set the BCLK,WCLK as output */
|
||||
2, 0x1e, 0x80 + 28, /* Enable the BCLKN divider with value 28 */
|
||||
2, 0x25, 0xee, /* DAC power up */
|
||||
|
||||
2, 0x12, 0x82, /* Power up the NADC divider with value 2 */
|
||||
2, 0x13, 0x87, /* Power up the MADC divider with value 7 */
|
||||
2, 0x14, 0x80, /* Program the OSR of ADC to 128 */
|
||||
2, 0x3d, 0x01, /* Select ADC PRB_R1 */
|
||||
0 // sentinel
|
||||
static const uint8_t conf_data_unmute[] = {
|
||||
// reg, data,
|
||||
0x00, 0x00, /* Select Page 0 */
|
||||
0x51, 0xc0, /* Power up Left and Right ADC Channels */
|
||||
0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */
|
||||
};
|
||||
|
||||
static const uint8_t conf_data_routing[] = {
|
||||
2, 0x00, 0x01, /* Select Page 1 */
|
||||
2, 0x01, 0x08, /* Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO*/
|
||||
2, 0x02, 0x01, /* Enable Master Analog Power Control */
|
||||
2, 0x7b, 0x01, /* Set the REF charging time to 40ms */
|
||||
2, 0x14, 0x25, /* HP soft stepping settings for optimal pop performance at power up Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling capacitor. Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound. */
|
||||
2, 0x0a, 0x33, /* Set the Input Common Mode to 0.9V and Output Common Mode for Headphone to 1.65V */
|
||||
|
||||
2, 0x3d, 0x00, /* Select ADC PTM_R4 */
|
||||
2, 0x47, 0x32, /* Set MicPGA startup delay to 3.1ms */
|
||||
2, 0x7b, 0x01, /* Set the REF charging time to 40ms */
|
||||
2, 0x34, 0x10, /* Route IN2L to LEFT_P with 10K */
|
||||
2, 0x36, 0x10, /* Route IN2R to LEFT_N with 10K */
|
||||
2, 0x37, 0x04, /* Route IN3R to RIGHT_P with 10K */
|
||||
2, 0x39, 0x04, /* Route IN3L to RIGHT_N with 10K */
|
||||
2, 0x3b, 0, /* Unmute Left MICPGA, Gain selection of 32dB to make channel gain 0dB */
|
||||
2, 0x3c, 0, /* Unmute Right MICPGA, Gain selection of 32dB to make channel gain 0dB */
|
||||
0 // sentinel
|
||||
static const uint8_t conf_data_ch3_select[] = {
|
||||
// reg, data,
|
||||
0x00, 0x01, /* Select Page 1 */
|
||||
0x37, 0x04, /* Route IN3R to RIGHT_P with input impedance of 10K */
|
||||
0x39, 0x04, /* Route IN3L to RIGHT_N with input impedance of 10K */
|
||||
};
|
||||
|
||||
const uint8_t conf_data_unmute[] = {
|
||||
2, 0x00, 0x00, /* Select Page 0 */
|
||||
2, 0x51, 0xc0, /* Power up Left and Right ADC Channels */
|
||||
2, 0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */
|
||||
0 // sentinel
|
||||
static const uint8_t conf_data_ch1_select[] = {
|
||||
// reg, data,
|
||||
0x00, 0x01, /* Select Page 1 */
|
||||
0x37, 0x40, /* Route IN1R to RIGHT_P with input impedance of 10K */
|
||||
0x39, 0x10, /* Route IN1L to RIGHT_N with input impedance of 10K */
|
||||
};
|
||||
|
||||
static void
|
||||
static inline void
|
||||
tlv320aic3204_bulk_write(const uint8_t *buf, int len)
|
||||
{
|
||||
int addr = AIC3204_ADDR;
|
||||
i2cAcquireBus(&I2CD1);
|
||||
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000);
|
||||
i2cReleaseBus(&I2CD1);
|
||||
(void)i2cMasterTransmitTimeout(&I2CD1, AIC3204_ADDR, buf, len, NULL, 0, 1000);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
@ -109,49 +113,32 @@ tlv320aic3204_read(uint8_t d0)
|
|||
#endif
|
||||
|
||||
static void
|
||||
tlv320aic3204_config(const uint8_t *data)
|
||||
tlv320aic3204_config(const uint8_t *data, int len)
|
||||
{
|
||||
const uint8_t *p = data;
|
||||
while (*p) {
|
||||
uint8_t len = *p++;
|
||||
tlv320aic3204_bulk_write(p, len);
|
||||
p += len;
|
||||
}
|
||||
i2cAcquireBus(&I2CD1);
|
||||
for (;len--;data+=2)
|
||||
tlv320aic3204_bulk_write(data, 2);
|
||||
i2cReleaseBus(&I2CD1);
|
||||
}
|
||||
|
||||
void tlv320aic3204_init(void)
|
||||
{
|
||||
tlv320aic3204_config(conf_data_pll);
|
||||
tlv320aic3204_config(conf_data_clk);
|
||||
tlv320aic3204_config(conf_data_routing);
|
||||
tlv320aic3204_config(conf_data, sizeof(conf_data)/2);
|
||||
wait_ms(40);
|
||||
tlv320aic3204_config(conf_data_unmute);
|
||||
tlv320aic3204_config(conf_data_unmute, sizeof(conf_data_unmute)/2);
|
||||
}
|
||||
|
||||
void tlv320aic3204_select(int channel)
|
||||
{
|
||||
const uint8_t ch3[] = {
|
||||
2, 0x00, 0x01, /* Select Page 1 */
|
||||
2, 0x37, 0x04, /* Route IN3R to RIGHT_P with input impedance of 10K */
|
||||
2, 0x39, 0x04, /* Route IN3L to RIGHT_N with input impedance of 10K */
|
||||
0 // sentinel
|
||||
};
|
||||
const uint8_t ch1[] = {
|
||||
2, 0x00, 0x01, /* Select Page 1 */
|
||||
2, 0x37, 0x40, /* Route IN1R to RIGHT_P with input impedance of 10K */
|
||||
2, 0x39, 0x10, /* Route IN1L to RIGHT_N with input impedance of 10K */
|
||||
0 // sentinel
|
||||
};
|
||||
tlv320aic3204_config(channel ? ch1 : ch3);
|
||||
tlv320aic3204_config(channel ? conf_data_ch1_select : conf_data_ch3_select, sizeof(conf_data_ch3_select)/2);
|
||||
}
|
||||
|
||||
void tlv320aic3204_set_gain(int lgain, int rgain)
|
||||
{
|
||||
uint8_t data[] = {
|
||||
2, 0x00, 0x01, /* Select Page 1 */
|
||||
2, 0x3b, lgain, /* Unmute Left MICPGA, set gain */
|
||||
2, 0x3c, rgain, /* Unmute Right MICPGA, set gain */
|
||||
0 // sentinel
|
||||
};
|
||||
tlv320aic3204_config(data);
|
||||
uint8_t data[] = {
|
||||
0x00, 0x01, /* Select Page 1 */
|
||||
0x3b, lgain, /* Unmute Left MICPGA, set gain */
|
||||
0x3c, rgain, /* Unmute Right MICPGA, set gain */
|
||||
};
|
||||
tlv320aic3204_config(data, sizeof(data)/2);
|
||||
}
|
||||
|
|
|
|||
127
ui.c
127
ui.c
|
|
@ -25,12 +25,12 @@
|
|||
//#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
uistat_t uistat = {
|
||||
digit: 6,
|
||||
current_trace: 0,
|
||||
lever_mode: LM_MARKER,
|
||||
marker_delta: FALSE,
|
||||
marker_tracking : FALSE,
|
||||
};
|
||||
|
||||
#define NO_EVENT 0
|
||||
|
|
@ -41,9 +41,9 @@ uistat_t uistat = {
|
|||
#define EVT_DOWN 0x20
|
||||
#define EVT_REPEAT 0x40
|
||||
|
||||
#define BUTTON_DOWN_LONG_TICKS 5000 /* 1sec */
|
||||
#define BUTTON_DOUBLE_TICKS 5000 /* 500ms */
|
||||
#define BUTTON_REPEAT_TICKS 1000 /* 100ms */
|
||||
#define BUTTON_DOWN_LONG_TICKS 5000 /* 1sec */
|
||||
#define BUTTON_DOUBLE_TICKS 2500 /* 500ms */
|
||||
#define BUTTON_REPEAT_TICKS 625 /* 125ms */
|
||||
#define BUTTON_DEBOUNCE_TICKS 200
|
||||
|
||||
/* lever switch assignment */
|
||||
|
|
@ -59,7 +59,7 @@ static uint32_t last_button_down_ticks;
|
|||
static uint32_t last_button_repeat_ticks;
|
||||
static int8_t inhibit_until_release = FALSE;
|
||||
|
||||
uint8_t operation_requested = OP_NONE;
|
||||
volatile uint8_t operation_requested = OP_NONE;
|
||||
|
||||
int8_t previous_marker = -1;
|
||||
|
||||
|
|
@ -71,8 +71,14 @@ enum {
|
|||
KM_START, KM_STOP, KM_CENTER, KM_SPAN, KM_CW, KM_SCALE, KM_REFPOS, KM_EDELAY, KM_VELOCITY_FACTOR, KM_SCALEDELAY
|
||||
};
|
||||
|
||||
#define NUMINPUT_LEN 10
|
||||
|
||||
static uint8_t ui_mode = UI_NORMAL;
|
||||
static uint8_t keypad_mode;
|
||||
static uint8_t keypads_last_index;
|
||||
static char kp_buf[NUMINPUT_LEN+1];
|
||||
static int8_t kp_index = 0;
|
||||
static uint8_t menu_current_level = 0;
|
||||
static int8_t selection = 0;
|
||||
|
||||
// Set structure align as WORD (save flash memory)
|
||||
|
|
@ -98,18 +104,13 @@ static int16_t last_touch_y;
|
|||
//int16_t touch_cal[4] = { 1000, 1000, 10*16, 12*16 };
|
||||
//int16_t touch_cal[4] = { 620, 600, 130, 180 };
|
||||
|
||||
int awd_count;
|
||||
//int awd_count;
|
||||
//int touch_x, touch_y;
|
||||
|
||||
#define NUMINPUT_LEN 10
|
||||
|
||||
#define KP_CONTINUE 0
|
||||
#define KP_DONE 1
|
||||
#define KP_CANCEL 2
|
||||
|
||||
static char kp_buf[NUMINPUT_LEN+1];
|
||||
static int8_t kp_index = 0;
|
||||
|
||||
static void ui_mode_normal(void);
|
||||
static void ui_mode_menu(void);
|
||||
static void ui_mode_numeric(int _keypad_mode);
|
||||
|
|
@ -130,33 +131,29 @@ static int btn_check(void)
|
|||
int status = 0;
|
||||
uint32_t ticks = chVTGetSystemTime();
|
||||
if (changed & (1<<BIT_PUSH)) {
|
||||
if (ticks - last_button_down_ticks >= BUTTON_DEBOUNCE_TICKS) {
|
||||
if (cur_button & (1<<BIT_PUSH)) {
|
||||
// button released
|
||||
status |= EVT_BUTTON_SINGLE_CLICK;
|
||||
if (inhibit_until_release) {
|
||||
status = 0;
|
||||
inhibit_until_release = FALSE;
|
||||
}
|
||||
if ((cur_button & (1<<BIT_PUSH))
|
||||
&& ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS) {
|
||||
// button released
|
||||
status |= EVT_BUTTON_SINGLE_CLICK;
|
||||
if (inhibit_until_release) {
|
||||
status = 0;
|
||||
inhibit_until_release = FALSE;
|
||||
}
|
||||
last_button_down_ticks = ticks;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & (1<<BIT_UP1)) {
|
||||
if ((cur_button & (1<<BIT_UP1))
|
||||
&& (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) {
|
||||
status |= EVT_UP;
|
||||
}
|
||||
last_button_down_ticks = ticks;
|
||||
}
|
||||
if (changed & (1<<BIT_DOWN1)) {
|
||||
if ((cur_button & (1<<BIT_DOWN1))
|
||||
&& (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) {
|
||||
status |= EVT_DOWN;
|
||||
}
|
||||
last_button_down_ticks = ticks;
|
||||
}
|
||||
last_button_down_ticks = ticks;
|
||||
last_button = cur_button;
|
||||
|
||||
return status;
|
||||
|
|
@ -169,15 +166,14 @@ static int btn_wait_release(void)
|
|||
int changed = last_button ^ cur_button;
|
||||
uint32_t ticks = chVTGetSystemTime();
|
||||
int status = 0;
|
||||
|
||||
if (!inhibit_until_release) {
|
||||
if ((cur_button & (1<<BIT_PUSH))
|
||||
&& ticks - last_button_down_ticks >= BUTTON_DOWN_LONG_TICKS) {
|
||||
&& ticks >= last_button_down_ticks + BUTTON_DOWN_LONG_TICKS) {
|
||||
inhibit_until_release = TRUE;
|
||||
return EVT_BUTTON_DOWN_LONG;
|
||||
}
|
||||
if ((changed & (1<<BIT_PUSH))
|
||||
&& ticks - last_button_down_ticks < BUTTON_DOWN_LONG_TICKS) {
|
||||
&& ticks < last_button_down_ticks + BUTTON_DOWN_LONG_TICKS) {
|
||||
return EVT_BUTTON_SINGLE_CLICK;
|
||||
}
|
||||
}
|
||||
|
|
@ -190,14 +186,12 @@ static int btn_wait_release(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (ticks - last_button_down_ticks >= BUTTON_DOWN_LONG_TICKS
|
||||
&& ticks - last_button_repeat_ticks >= BUTTON_REPEAT_TICKS) {
|
||||
if (cur_button & (1<<BIT_DOWN1)) {
|
||||
if (ticks >= last_button_down_ticks + BUTTON_DOWN_LONG_TICKS
|
||||
&& ticks >= last_button_repeat_ticks + BUTTON_REPEAT_TICKS) {
|
||||
if (cur_button & (1<<BIT_DOWN1))
|
||||
status |= EVT_DOWN | EVT_REPEAT;
|
||||
}
|
||||
if (cur_button & (1<<BIT_UP1)) {
|
||||
if (cur_button & (1<<BIT_UP1))
|
||||
status |= EVT_UP | EVT_REPEAT;
|
||||
}
|
||||
last_button_repeat_ticks = ticks;
|
||||
return status;
|
||||
}
|
||||
|
|
@ -218,7 +212,7 @@ touch_measure_y(void)
|
|||
palSetPad(GPIOA, 6);
|
||||
|
||||
chThdSleepMilliseconds(2);
|
||||
v = adc_single_read(ADC1, ADC_CHSELR_CHSEL7);
|
||||
v = adc_single_read(ADC_CHSELR_CHSEL7);
|
||||
//chThdSleepMilliseconds(2);
|
||||
//v += adc_single_read(ADC1, ADC_CHSELR_CHSEL7);
|
||||
return v;
|
||||
|
|
@ -238,7 +232,7 @@ touch_measure_x(void)
|
|||
palClearPad(GPIOA, 7);
|
||||
|
||||
chThdSleepMilliseconds(2);
|
||||
v = adc_single_read(ADC1, ADC_CHSELR_CHSEL6);
|
||||
v = adc_single_read(ADC_CHSELR_CHSEL6);
|
||||
//chThdSleepMilliseconds(2);
|
||||
//v += adc_single_read(ADC1, ADC_CHSELR_CHSEL6);
|
||||
return v;
|
||||
|
|
@ -261,14 +255,14 @@ void
|
|||
touch_start_watchdog(void)
|
||||
{
|
||||
touch_prepare_sense();
|
||||
adc_start_analog_watchdogd(ADC1, ADC_CHSELR_CHSEL7);
|
||||
adc_start_analog_watchdogd(ADC_CHSELR_CHSEL7);
|
||||
}
|
||||
|
||||
static int
|
||||
touch_status(void)
|
||||
{
|
||||
touch_prepare_sense();
|
||||
return adc_single_read(ADC1, ADC_CHSELR_CHSEL7) > TOUCH_THRESHOLD;
|
||||
return adc_single_read(ADC_CHSELR_CHSEL7) > TOUCH_THRESHOLD;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -308,7 +302,7 @@ touch_cal_exec(void)
|
|||
{
|
||||
int x1, x2, y1, y2;
|
||||
|
||||
adc_stop(ADC1);
|
||||
adc_stop();
|
||||
setForegroundColor(DEFAULT_FG_COLOR);
|
||||
setBackgroundColor(DEFAULT_BG_COLOR);
|
||||
clearScreen();
|
||||
|
|
@ -344,7 +338,7 @@ touch_draw_test(void)
|
|||
int x0, y0;
|
||||
int x1, y1;
|
||||
|
||||
adc_stop(ADC1);
|
||||
adc_stop();
|
||||
|
||||
setForegroundColor(DEFAULT_FG_COLOR);
|
||||
setBackgroundColor(DEFAULT_BG_COLOR);
|
||||
|
|
@ -373,30 +367,21 @@ touch_position(int *x, int *y)
|
|||
*y = (last_touch_y - config.touch_cal[1]) * 16 / config.touch_cal[3];
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
show_version(void)
|
||||
{
|
||||
int x = 5, y = 5;
|
||||
adc_stop(ADC1);
|
||||
int x = 5, y = 5, i = 0;
|
||||
adc_stop();
|
||||
setForegroundColor(DEFAULT_FG_COLOR);
|
||||
setBackgroundColor(DEFAULT_BG_COLOR);
|
||||
|
||||
clearScreen();
|
||||
ili9341_drawstring_size(BOARD_NAME, x, y, 4);
|
||||
y += 25;
|
||||
|
||||
ili9341_drawstring("2016-2020 Copyright @edy555", x, y += 10);
|
||||
ili9341_drawstring("Licensed under GPL. See: https://github.com/ttrftech/NanoVNA", x, y += 10);
|
||||
ili9341_drawstring("Version: " VERSION, x, y += 10);
|
||||
ili9341_drawstring("Build Time: " __DATE__ " - " __TIME__, x, y += 10);
|
||||
y += 5;
|
||||
ili9341_drawstring("Kernel: " CH_KERNEL_VERSION, x, y += 10);
|
||||
ili9341_drawstring("Compiler: " PORT_COMPILER_NAME, x, y += 10);
|
||||
ili9341_drawstring("Architecture: " PORT_ARCHITECTURE_NAME " Core Variant: " PORT_CORE_VARIANT_NAME, x, y += 10);
|
||||
ili9341_drawstring("Port Info: " PORT_INFO, x, y += 10);
|
||||
ili9341_drawstring("Platform: " PLATFORM_NAME, x, y += 10);
|
||||
|
||||
uint16_t shift = 0b0000010000111110;
|
||||
ili9341_drawstring_size(info_about[i++], x , y, 4);
|
||||
while (info_about[i]){
|
||||
do {shift>>=1; y+=5;} while (shift&1);
|
||||
ili9341_drawstring(info_about[i++], x, y+=5);
|
||||
}
|
||||
while (true) {
|
||||
if (touch_check() == EVT_TOUCH_PRESSED)
|
||||
break;
|
||||
|
|
@ -410,7 +395,7 @@ show_version(void)
|
|||
void
|
||||
enter_dfu(void)
|
||||
{
|
||||
adc_stop(ADC1);
|
||||
adc_stop();
|
||||
|
||||
int x = 5, y = 5;
|
||||
setForegroundColor(DEFAULT_FG_COLOR);
|
||||
|
|
@ -776,7 +761,7 @@ menu_marker_search_cb(int item, uint8_t data)
|
|||
i = marker_search_right(markers[active_marker].index);
|
||||
break;
|
||||
case 4: /* tracking */
|
||||
marker_tracking = !marker_tracking;
|
||||
uistat.marker_tracking = !uistat.marker_tracking;
|
||||
break;
|
||||
}
|
||||
if (i != -1)
|
||||
|
|
@ -1047,7 +1032,6 @@ const menuitem_t menu_top[] = {
|
|||
};
|
||||
|
||||
#define MENU_STACK_DEPTH_MAX 4
|
||||
uint8_t menu_current_level = 0;
|
||||
const menuitem_t *menu_stack[MENU_STACK_DEPTH_MAX] = {
|
||||
menu_top, NULL, NULL, NULL
|
||||
};
|
||||
|
|
@ -1171,7 +1155,6 @@ typedef struct {
|
|||
} keypads_t;
|
||||
|
||||
static const keypads_t *keypads;
|
||||
static uint8_t keypads_last_index;
|
||||
|
||||
static const keypads_t keypads_freq[] = {
|
||||
{ 1, 3, KP_PERIOD },
|
||||
|
|
@ -1345,7 +1328,7 @@ menu_item_modify_attribute(const menuitem_t *menu, int item,
|
|||
}
|
||||
}
|
||||
} else if (menu == menu_marker_search) {
|
||||
if (item == 4 && marker_tracking) {
|
||||
if (item == 4 && uistat.marker_tracking) {
|
||||
*bg = DEFAULT_MENU_TEXT_COLOR;
|
||||
*fg = config.menu_normal_color;
|
||||
}
|
||||
|
|
@ -1366,7 +1349,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_ENABLE)) {
|
||||
*bg = DEFAULT_MENU_TEXT_COLOR;
|
||||
*fg = config.menu_normal_color;
|
||||
}
|
||||
|
|
@ -1535,7 +1518,7 @@ fetch_numeric_target(void)
|
|||
x /= 10;
|
||||
uistat.digit = n;
|
||||
}
|
||||
uistat.previous_value = uistat.value;
|
||||
// uistat.previous_value = uistat.value;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2011,7 +1994,7 @@ static void
|
|||
ui_process_keypad(void)
|
||||
{
|
||||
int status;
|
||||
adc_stop(ADC1);
|
||||
adc_stop();
|
||||
|
||||
kp_index = 0;
|
||||
while (TRUE) {
|
||||
|
|
@ -2139,7 +2122,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
|
||||
|
|
@ -2152,8 +2135,8 @@ touch_lever_mode_select(void)
|
|||
static
|
||||
void ui_process_touch(void)
|
||||
{
|
||||
awd_count++;
|
||||
adc_stop(ADC1);
|
||||
// awd_count++;
|
||||
adc_stop();
|
||||
|
||||
int status = touch_check();
|
||||
if (status == EVT_TOUCH_PRESSED || status == EVT_TOUCH_DOWN) {
|
||||
|
|
@ -2189,14 +2172,10 @@ void ui_process_touch(void)
|
|||
void
|
||||
ui_process(void)
|
||||
{
|
||||
switch (operation_requested) {
|
||||
case OP_LEVER:
|
||||
if (operation_requested&OP_LEVER)
|
||||
ui_process_lever();
|
||||
break;
|
||||
case OP_TOUCH:
|
||||
if (operation_requested&OP_TOUCH)
|
||||
ui_process_touch();
|
||||
break;
|
||||
}
|
||||
operation_requested = OP_NONE;
|
||||
}
|
||||
|
||||
|
|
@ -2204,7 +2183,7 @@ ui_process(void)
|
|||
static void extcb1(EXTDriver *extp, expchannel_t channel) {
|
||||
(void)extp;
|
||||
(void)channel;
|
||||
operation_requested = OP_LEVER;
|
||||
operation_requested|=OP_LEVER;
|
||||
//cur_button = READ_PORT() & BUTTON_MASK;
|
||||
}
|
||||
|
||||
|
|
@ -2259,7 +2238,7 @@ test_touch(int *x, int *y)
|
|||
void
|
||||
handle_touch_interrupt(void)
|
||||
{
|
||||
operation_requested = OP_TOUCH;
|
||||
operation_requested|= OP_TOUCH;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
Loading…
Reference in a new issue