Merge pull request #125 from DiSlord/master

Speedup and fix Si5351 clock generator
This commit is contained in:
TT 2020-03-08 19:33:13 +09:00 committed by GitHub
commit 7c2e4364e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 655 additions and 647 deletions

97
adc.c
View file

@ -28,80 +28,79 @@
#define ADC_SMPR_SMP_239P5 7U /**< @brief 252 cycles conversion time. */ #define ADC_SMPR_SMP_239P5 7U /**< @brief 252 cycles conversion time. */
#define ADC_CFGR1_RES_12BIT (0U << 3U) #define ADC_CFGR1_RES_12BIT (0U << 3U)
#define VNA_ADC ADC1
void adc_init(void) void adc_init(void)
{ {
rccEnableADC1(FALSE); rccEnableADC1(FALSE);
/* Ensure flag states */ /* Ensure flag states */
ADC1->IER = 0; VNA_ADC->IER = 0;
/* Calibration procedure.*/ /* Calibration procedure.*/
ADC->CCR = 0; ADC->CCR = 0;
if (ADC1->CR & ADC_CR_ADEN) { if (VNA_ADC->CR & ADC_CR_ADEN) {
ADC1->CR |= ~ADC_CR_ADDIS; /* Disable ADC */ 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; VNA_ADC->CFGR1 &= ~ADC_CFGR1_DMAEN;
ADC1->CR |= ADC_CR_ADCAL; VNA_ADC->CR |= ADC_CR_ADCAL;
while (ADC1->CR & ADC_CR_ADCAL) while (VNA_ADC->CR & ADC_CR_ADCAL)
; ;
if (ADC1->ISR & ADC_ISR_ADRDY) { if (VNA_ADC->ISR & ADC_ISR_ADRDY) {
ADC1->ISR |= ADC_ISR_ADRDY; /* clear ADRDY */ VNA_ADC->ISR |= ADC_ISR_ADRDY; /* clear ADRDY */
} }
/* Enable ADC */ /* Enable ADC */
ADC1->CR |= ADC_CR_ADEN; VNA_ADC->CR |= ADC_CR_ADEN;
while (!(ADC1->ISR & ADC_ISR_ADRDY)) 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 setup */
adc->ISR = adc->ISR; VNA_ADC->ISR = VNA_ADC->ISR;
adc->IER = 0; VNA_ADC->IER = 0;
adc->TR = ADC_TR(0, 0); VNA_ADC->TR = ADC_TR(0, 0);
adc->SMPR = ADC_SMPR_SMP_239P5; VNA_ADC->SMPR = ADC_SMPR_SMP_239P5;
adc->CFGR1 = ADC_CFGR1_RES_12BIT; VNA_ADC->CFGR1 = ADC_CFGR1_RES_12BIT;
adc->CHSELR = chsel; VNA_ADC->CHSELR = chsel;
/* ADC conversion start.*/ /* 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 ADC_FULL_SCALE 3300
#define VBAT_DIODE_VF 500
#define VREFINT_CAL (*((uint16_t*)0x1FFFF7BA)) #define VREFINT_CAL (*((uint16_t*)0x1FFFF7BA))
adc_stop();
float vbat = 0; float vbat = 0;
float vrefint = 0; float vrefint = 0;
ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_VBATEN; ADC->CCR |= ADC_CCR_VREFEN | ADC_CCR_VBATEN;
// VREFINT == ADC_IN17 // VREFINT == ADC_IN17
vrefint = adc_single_read(adc, ADC_CHSELR_CHSEL17); vrefint = adc_single_read(ADC_CHSELR_CHSEL17);
// VBAT == ADC_IN18 // VBAT == ADC_IN18
// VBATEN enables resiter devider circuit. It consume vbat power. // VBATEN enables resiter devider circuit. It consume vbat power.
vbat = adc_single_read(adc, ADC_CHSELR_CHSEL18); vbat = adc_single_read(ADC_CHSELR_CHSEL18);
ADC->CCR &= ~(ADC_CCR_VREFEN | ADC_CCR_VBATEN); 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))); uint16_t vbat_raw = (ADC_FULL_SCALE * VREFINT_CAL * vbat * 2 / (vrefint * ((1<<12)-1)));
if (vbat_raw < 100) { if (vbat_raw < 100) {
// maybe D2 is not installed // maybe D2 is not installed
return -1; return -1;
} }
return vbat_raw + config.vbat_offset;
return vbat_raw + VBAT_DIODE_VF;
} }
void adc_start_analog_watchdogd(ADC_TypeDef *adc, uint32_t chsel) void adc_start_analog_watchdogd(uint32_t chsel)
{ {
uint32_t cfgr1; 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 /* ADC setup, if it is defined a callback for the analog watch dog then it
is enabled.*/ is enabled.*/
adc->ISR = adc->ISR; VNA_ADC->ISR = VNA_ADC->ISR;
adc->IER = ADC_IER_AWDIE; VNA_ADC->IER = ADC_IER_AWDIE;
adc->TR = ADC_TR(0, TOUCH_THRESHOLD); VNA_ADC->TR = ADC_TR(0, TOUCH_THRESHOLD);
adc->SMPR = ADC_SMPR_SMP_1P5; VNA_ADC->SMPR = ADC_SMPR_SMP_1P5;
adc->CHSELR = chsel; VNA_ADC->CHSELR = chsel;
/* ADC configuration and start.*/ /* ADC configuration and start.*/
adc->CFGR1 = cfgr1; VNA_ADC->CFGR1 = cfgr1;
/* ADC conversion start.*/ /* 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 (VNA_ADC->CR & ADC_CR_ADEN) {
if (adc->CR & ADC_CR_ADSTART) { if (VNA_ADC->CR & ADC_CR_ADSTART) {
adc->CR |= ADC_CR_ADSTP; VNA_ADC->CR |= ADC_CR_ADSTP;
while (adc->CR & ADC_CR_ADSTP) while (VNA_ADC->CR & ADC_CR_ADSTP)
; ;
} }
/* adc->CR |= ADC_CR_ADDIS; /* VNA_ADC->CR |= ADC_CR_ADDIS;
while (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; uint32_t isr = VNA_ADC->ISR;
adc->ISR = isr; VNA_ADC->ISR = isr;
if (isr & ADC_ISR_OVR) { if (isr & ADC_ISR_OVR) {
/* ADC overflow condition, this could happen only if the DMA is unable /* 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(); OSAL_IRQ_PROLOGUE();
adc_interrupt(ADC1); adc_interrupt();
OSAL_IRQ_EPILOGUE(); OSAL_IRQ_EPILOGUE();
} }

200
main.c
View file

@ -57,6 +57,8 @@ static char shell_line[VNA_SHELL_MAX_LENGTH];
//#define ENABLED_DUMP //#define ENABLED_DUMP
//#define ENABLE_THREADS_COMMAND //#define ENABLE_THREADS_COMMAND
//#define ENABLE_TIME_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_error_term_at(int i);
static void apply_edelay_at(int i); static void apply_edelay_at(int i);
@ -72,20 +74,30 @@ static MUTEX_DECL(mutex);
#define DRIVE_STRENGTH_AUTO (-1) #define DRIVE_STRENGTH_AUTO (-1)
#define FREQ_HARMONICS (config.harmonic_freq_threshold) #define FREQ_HARMONICS (config.harmonic_freq_threshold)
#define IS_HARMONIC_MODE(f) ((f) > FREQ_HARMONICS) #define IS_HARMONIC_MODE(f) ((f) > FREQ_HARMONICS)
// Obsolete, always use interpolate
#define cal_auto_interpolate TRUE
int32_t frequency_offset = 5000; static int32_t frequency_offset = 5000;
uint32_t frequency = 10000000; static uint32_t frequency = 10000000;
int8_t drive_strength = DRIVE_STRENGTH_AUTO; static int8_t drive_strength = DRIVE_STRENGTH_AUTO;
int8_t sweep_enabled = TRUE; int8_t sweep_mode = SWEEP_ENABLE;
volatile int8_t sweep_once = FALSE; volatile uint8_t redraw_request = 0; // contains REDRAW_XXX flags
int8_t cal_auto_interpolate = TRUE;
uint16_t redraw_request = 0; // contains REDRAW_XXX flags // Version text, displayed in Config->Version menu, also send by info command
int16_t vbat = 0; 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_WORKING_AREA(waThread1, 640);
static THD_FUNCTION(Thread1, arg) static THD_FUNCTION(Thread1, arg)
{ {
@ -94,36 +106,27 @@ static THD_FUNCTION(Thread1, arg)
while (1) { while (1) {
bool completed = false; bool completed = false;
if (sweep_enabled || sweep_once) { if (sweep_mode&(SWEEP_ENABLE|SWEEP_ONCE)) {
chMtxLock(&mutex); chMtxLock(&mutex);
// Sweep require 8367 system tick
completed = sweep(true); completed = sweep(true);
sweep_once = FALSE; sweep_mode&=~SWEEP_ONCE;
chMtxUnlock(&mutex); chMtxUnlock(&mutex);
} else { } else {
__WFI(); __WFI();
} }
chMtxLock(&mutex); chMtxLock(&mutex);
// Ui and render require 800 system tick
ui_process(); ui_process();
if (sweep_enabled) { if (sweep_mode&SWEEP_ENABLE) {
if (vbat != -1) {
adc_stop(ADC1);
vbat = adc_vbat_read(ADC1);
touch_start_watchdog();
draw_battery_status();
}
// calculate trace coordinates and plot only if scan completed // calculate trace coordinates and plot only if scan completed
if (completed) { if (completed) {
if ((domain_mode & DOMAIN_MODE) == DOMAIN_TIME) if ((domain_mode & DOMAIN_MODE) == DOMAIN_TIME)
transform_domain(); transform_domain();
plot_into_index(measured); 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(); int i = marker_search();
if (i != -1 && active_marker != -1) { if (i != -1 && active_marker != -1) {
markers[active_marker].index = i; markers[active_marker].index = i;
@ -141,19 +144,19 @@ static THD_FUNCTION(Thread1, arg)
static inline void static inline void
pause_sweep(void) pause_sweep(void)
{ {
sweep_enabled = FALSE; sweep_mode&=~SWEEP_ENABLE;
} }
static inline void static inline void
resume_sweep(void) resume_sweep(void)
{ {
sweep_enabled = TRUE; sweep_mode|=SWEEP_ENABLE;
} }
void void
toggle_sweep(void) toggle_sweep(void)
{ {
sweep_enabled = !sweep_enabled; sweep_mode^=SWEEP_ENABLE;
} }
static float static float
@ -316,19 +319,18 @@ const int8_t gain_table[] = {
95 // 2400MHz ~ 95 // 2400MHz ~
}; };
#define DELAY_GAIN_CHANGE 10 #define DELAY_GAIN_CHANGE 2
static int static int
adjust_gain(int newfreq) adjust_gain(uint32_t newfreq)
{ {
int delay = 0;
int new_order = newfreq / FREQ_HARMONICS; int new_order = newfreq / FREQ_HARMONICS;
int old_order = frequency / FREQ_HARMONICS; int old_order = frequency / FREQ_HARMONICS;
if (new_order != old_order) { if (new_order != old_order) {
tlv320aic3204_set_gain(gain_table[new_order], gain_table[new_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) int set_frequency(uint32_t freq)
@ -474,7 +476,7 @@ VNA_SHELL_FUNCTION(cmd_power)
#ifdef ENABLE_TIME_COMMAND #ifdef ENABLE_TIME_COMMAND
#if HAL_USE_RTC == FALSE #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 #endif
VNA_SHELL_FUNCTION(cmd_time) VNA_SHELL_FUNCTION(cmd_time)
{ {
@ -559,15 +561,6 @@ volatile int16_t wait_count = 0;
float measured[2][POINTS_COUNT][2]; 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 #ifdef ENABLED_DUMP
static void static void
duplicate_buffer_to_dump(int16_t *p) 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 }, .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 = { 693, 605, 124, 171 }, // 2.4 inch LCD panel
.touch_cal = { 338, 522, 153, 192 }, // 2.8 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; properties_t current_props;
@ -745,7 +739,8 @@ static const marker_t def_markers[MARKERS_MAX] = {
// Load propeties default settings // Load propeties default settings
void loadDefaultProps(void){ 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._frequency0 = 50000; // start = 50kHz
current_props._frequency1 = 900000000; // end = 900MHz current_props._frequency1 = 900000000; // end = 900MHz
current_props._sweep_points = POINTS_COUNT; current_props._sweep_points = POINTS_COUNT;
@ -761,6 +756,8 @@ void loadDefaultProps(void){
current_props._active_marker = 0; current_props._active_marker = 0;
current_props._domain_mode = 0; current_props._domain_mode = 0;
current_props._marker_smith_format = MS_RLC; current_props._marker_smith_format = MS_RLC;
//Checksum add on caldata_save
//current_props.checksum = 0;
} }
void void
@ -775,24 +772,37 @@ ensure_edit_config(void)
cal_status = 0; 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 // main loop for measurement
bool sweep(bool break_on_operation) bool sweep(bool break_on_operation)
{ {
int i; int i, delay;
// blink LED while scanning // blink LED while scanning
palClearPad(GPIOC, GPIOC_LED); palClearPad(GPIOC, GPIOC_LED);
for (i = 0; i < sweep_points; i++) { // 8365 // Power stabilization after LED off, also align timings
int delay = set_frequency(frequencies[i]); // 1560 // 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 tlv320aic3204_select(0); // 60 CH0:REFLECT
DSP_START(delay); // 1900
wait_dsp(delay); // 3270 //================================================
// Place some code thats need execute while delay
//================================================
DSP_WAIT_READY;
// calculate reflection coefficient // calculate reflection coefficient
(*sample_func)(measured[0][i]); // 60 (*sample_func)(measured[0][i]); // 60
tlv320aic3204_select(1); // 60 CH1:TRANSMISSION 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 // calculate transmission coefficient
(*sample_func)(measured[1][i]); // 60 (*sample_func)(measured[1][i]); // 60
// ======== 170 =========== // ======== 170 ===========
@ -841,11 +851,11 @@ VNA_SHELL_FUNCTION(cmd_scan)
if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY)) if (cal_auto_interpolate && (cal_status & CALSTAT_APPLY))
cal_interpolate(lastsaveid); cal_interpolate(lastsaveid);
sweep_once = TRUE; sweep_mode|= SWEEP_ONCE;
chMtxUnlock(&mutex); chMtxUnlock(&mutex);
// wait finishing sweep // wait finishing sweep
while (sweep_once) while (sweep_mode&SWEEP_ONCE)
chThdSleepMilliseconds(10); chThdSleepMilliseconds(10);
} }
@ -912,7 +922,7 @@ update_frequencies(void)
} }
set_frequencies(start, stop, sweep_points); set_frequencies(start, stop, sweep_points);
operation_requested = OP_FREQCHANGE; // operation_requested|= OP_FREQCHANGE;
update_marker_index(); update_marker_index();
@ -1430,6 +1440,7 @@ VNA_SHELL_FUNCTION(cmd_cal)
shell_printf("\r\n"); shell_printf("\r\n");
return; return;
} }
redraw_request|=REDRAW_CAL_STATUS;
// 0 1 2 3 4 5 6 7 8 9 10 // 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"; static const char cmd_cal_list[] = "load|open|short|thru|isoln|done|on|off|reset|data|in";
switch (getStringIndex(argv[0], cmd_cal_list)){ switch (getStringIndex(argv[0], cmd_cal_list)){
@ -1439,9 +1450,9 @@ VNA_SHELL_FUNCTION(cmd_cal)
case 3:cal_collect(CAL_THRU ); return; case 3:cal_collect(CAL_THRU ); return;
case 4:cal_collect(CAL_ISOLN); return; case 4:cal_collect(CAL_ISOLN); return;
case 5:cal_done(); return; case 5:cal_done(); return;
case 6:cal_status|= CALSTAT_APPLY;redraw_request|=REDRAW_CAL_STATUS; return; case 6:cal_status|= CALSTAT_APPLY;return;
case 7:cal_status&=~CALSTAT_APPLY;redraw_request|=REDRAW_CAL_STATUS; return; case 7:cal_status&=~CALSTAT_APPLY;return;
case 8:cal_status = 0; redraw_request|=REDRAW_CAL_STATUS; return; case 8:cal_status = 0; return;
case 9: 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_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]); 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; return;
case 10: case 10:
cal_interpolate((argc > 1) ? my_atoi(argv[1]) : 0); cal_interpolate((argc > 1) ? my_atoi(argv[1]) : 0);
redraw_request|=REDRAW_CAL_STATUS;
return; return;
default:break; default:break;
} }
shell_printf("usage: cal [%s]\r\n", cmd_cal_list); shell_printf("usage: cal [%s]\r\n", cmd_cal_list);
} }
@ -1687,14 +1696,13 @@ VNA_SHELL_FUNCTION(cmd_marker)
} }
return; return;
} }
redraw_request |= REDRAW_MARKER;
if (strcmp(argv[0], "off") == 0) { if (strcmp(argv[0], "off") == 0) {
active_marker = -1; active_marker = -1;
for (t = 0; t < MARKERS_MAX; t++) for (t = 0; t < MARKERS_MAX; t++)
markers[t].enabled = FALSE; markers[t].enabled = FALSE;
redraw_request |= REDRAW_MARKER;
return; return;
} }
t = my_atoi(argv[0])-1; t = my_atoi(argv[0])-1;
if (t < 0 || t >= MARKERS_MAX) if (t < 0 || t >= MARKERS_MAX)
goto usage; goto usage;
@ -1703,13 +1711,12 @@ VNA_SHELL_FUNCTION(cmd_marker)
active_marker = t; active_marker = t;
// select active marker // select active marker
markers[t].enabled = TRUE; markers[t].enabled = TRUE;
redraw_request |= REDRAW_MARKER;
return; return;
} }
static const char cmd_marker_list[] = "on|off"; static const char cmd_marker_list[] = "on|off";
switch (getStringIndex(argv[1], cmd_marker_list)){ switch (getStringIndex(argv[1], cmd_marker_list)){
case 0: markers[t].enabled = TRUE; active_marker = t; 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; redraw_request|=REDRAW_MARKER; return; case 1: markers[t].enabled =FALSE; if (active_marker == t) active_marker = -1; return;
default: default:
// select active marker and move to index // select active marker and move to index
markers[t].enabled = TRUE; markers[t].enabled = TRUE;
@ -1717,7 +1724,6 @@ VNA_SHELL_FUNCTION(cmd_marker)
markers[t].index = index; markers[t].index = index;
markers[t].frequency = frequencies[index]; markers[t].frequency = frequencies[index];
active_marker = t; active_marker = t;
redraw_request |= REDRAW_MARKER;
return; return;
} }
usage: usage:
@ -1923,8 +1929,8 @@ VNA_SHELL_FUNCTION(cmd_stat)
//shell_printf("interval cycle: %d\r\n", stat.interval_cycles); //shell_printf("interval cycle: %d\r\n", stat.interval_cycles);
//shell_printf("busy cycle: %d\r\n", stat.busy_cycles); //shell_printf("busy cycle: %d\r\n", stat.busy_cycles);
//shell_printf("load: %d\r\n", stat.busy_cycles * 100 / stat.interval_cycles); //shell_printf("load: %d\r\n", stat.busy_cycles * 100 / stat.interval_cycles);
extern int awd_count; // extern int awd_count;
shell_printf("awd: %d\r\n", awd_count); // shell_printf("awd: %d\r\n", awd_count);
} }
@ -1945,9 +1951,31 @@ VNA_SHELL_FUNCTION(cmd_vbat)
{ {
(void)argc; (void)argc;
(void)argv; (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 #ifdef ENABLE_THREADS_COMMAND
#if CH_CFG_USE_REGISTRY == FALSE #if CH_CFG_USE_REGISTRY == FALSE
#error "Threads Requite enabled CH_CFG_USE_REGISTRY in chconf.h" #error "Threads Requite enabled CH_CFG_USE_REGISTRY in chconf.h"
@ -1969,8 +1997,6 @@ VNA_SHELL_FUNCTION(cmd_threads) {
#else #else
uint32_t stklimit = 0U; uint32_t stklimit = 0U;
#endif #endif
shell_printf("%08x|%08x|%08x|%08x|%4u|%4u|%9s|%12s"VNA_SHELL_NEWLINE_STR, 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, stklimit, (uint32_t)tp->ctx.sp, max_stack_use, (uint32_t)tp,
(uint32_t)tp->refs - 1, (uint32_t)tp->prio, states[tp->state], (uint32_t)tp->refs - 1, (uint32_t)tp->prio, states[tp->state],
@ -2031,9 +2057,15 @@ static const VNAShellCommand commands[] =
{"edelay" , cmd_edelay , 0}, {"edelay" , cmd_edelay , 0},
{"capture" , cmd_capture , CMD_WAIT_MUTEX}, {"capture" , cmd_capture , CMD_WAIT_MUTEX},
{"vbat" , cmd_vbat , 0}, {"vbat" , cmd_vbat , 0},
#ifdef ENABLE_VBAT_OFFSET_COMMAND
{"vbat_offset" , cmd_vbat_offset , 0},
#endif
{"transform" , cmd_transform , 0}, {"transform" , cmd_transform , 0},
{"threshold" , cmd_threshold , 0}, {"threshold" , cmd_threshold , 0},
{"help" , cmd_help , 0}, {"help" , cmd_help , 0},
#ifdef ENABLE_INFO_COMMAND
{"info" , cmd_info , 0},
#endif
#ifdef ENABLE_THREADS_COMMAND #ifdef ENABLE_THREADS_COMMAND
{"threads" , cmd_threads , 0}, {"threads" , cmd_threads , 0},
#endif #endif
@ -2160,10 +2192,28 @@ THD_FUNCTION(myshellThread, p) {
} }
#endif #endif
// I2C clock bus setting: depend from STM32_I2C1SW in mcuconf.h
static const I2CConfig i2ccfg = { static const I2CConfig i2ccfg = {
0x00300506, //voodoo magic 400kHz @ HSI 8MHz .timingr = // TIMINGR register initialization. (use I2C timing configuration tool for STM32F3xx and STM32F0xx microcontrollers (AN4235))
0, #if STM32_I2C1SW == STM32_I2C1SW_HSI
0 // 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 = { static DACConfig dac1cfg1 = {

View file

@ -58,7 +58,8 @@
#define STM32_ADCSW STM32_ADCSW_HSI14 #define STM32_ADCSW STM32_ADCSW_HSI14
#define STM32_USBSW STM32_USBSW_HSI48 #define STM32_USBSW STM32_USBSW_HSI48
#define STM32_CECSW STM32_CECSW_HSI #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_USART1SW STM32_USART1SW_PCLK
#define STM32_RTCSEL STM32_RTCSEL_LSI #define STM32_RTCSEL STM32_RTCSEL_LSI

View file

@ -86,31 +86,10 @@ double my_atof(const char *p);
void toggle_sweep(void); void toggle_sweep(void);
void loadDefaultProps(void); void loadDefaultProps(void);
extern int8_t sweep_enabled; #define SWEEP_ENABLE 0x01
#define SWEEP_ONCE 0x02
/* extern int8_t sweep_mode;
* flash.c extern const char *info_about[];
*/
#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;
/* /*
* dsp.c * dsp.c
@ -134,9 +113,6 @@ void calculate_gamma(float *gamma);
void fetch_amplitude(float *gamma); void fetch_amplitude(float *gamma);
void fetch_amplitude_ref(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 * tlv320aic3204.c
*/ */
@ -243,8 +219,8 @@ typedef struct config {
int16_t touch_cal[4]; int16_t touch_cal[4];
int8_t reserved_1; int8_t reserved_1;
uint32_t harmonic_freq_threshold; uint32_t harmonic_freq_threshold;
uint16_t vbat_offset;
uint8_t _reserved[24]; uint8_t _reserved[22];
uint32_t checksum; uint32_t checksum;
} config_t; } config_t;
@ -259,7 +235,6 @@ void set_trace_refpos(int t, float refpos);
float get_trace_scale(int t); float get_trace_scale(int t);
float get_trace_refpos(int t); float get_trace_refpos(int t);
const char *get_trace_typename(int t); const char *get_trace_typename(int t);
void draw_battery_status(void);
void set_electrical_delay(float picoseconds); void set_electrical_delay(float picoseconds);
float get_electrical_delay(void); float get_electrical_delay(void);
@ -302,14 +277,13 @@ int marker_search(void);
int marker_search_left(int from); int marker_search_left(int from);
int marker_search_right(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_CELLS (1<<0)
#define REDRAW_FREQUENCY (1<<1) #define REDRAW_FREQUENCY (1<<1)
#define REDRAW_CAL_STATUS (1<<2) #define REDRAW_CAL_STATUS (1<<2)
#define REDRAW_MARKER (1<<3) #define REDRAW_MARKER (1<<3)
#define REDRAW_BATTERY (1<<4)
extern int16_t vbat; extern volatile uint8_t redraw_request;
/* /*
* ili9341.c * ili9341.c
@ -366,6 +340,16 @@ void show_logo(void);
* flash.c * flash.c
*/ */
#define SAVEAREA_MAX 5 #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 { typedef struct properties {
uint32_t magic; uint32_t magic;
@ -432,6 +416,15 @@ void clear_all_config_prop_data(void);
/* /*
* ui.c * 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 // lever_mode
enum lever_mode { enum lever_mode {
@ -448,13 +441,13 @@ typedef struct uistat {
int8_t digit_mode; int8_t digit_mode;
int8_t current_trace; /* 0..3 */ int8_t current_trace; /* 0..3 */
uint32_t value; // for editing at numeric input area uint32_t value; // for editing at numeric input area
uint32_t previous_value; // uint32_t previous_value;
uint8_t lever_mode; uint8_t lever_mode;
bool marker_delta; uint8_t marker_delta;
uint8_t marker_tracking;
} uistat_t; } uistat_t;
extern uistat_t uistat; extern uistat_t uistat;
void ui_init(void); void ui_init(void);
void ui_show(void); void ui_show(void);
void ui_hide(void); void ui_hide(void);
@ -474,11 +467,11 @@ void enter_dfu(void);
*/ */
void adc_init(void); void adc_init(void);
uint16_t adc_single_read(ADC_TypeDef *adc, uint32_t chsel); uint16_t adc_single_read(uint32_t chsel);
void adc_start_analog_watchdogd(ADC_TypeDef *adc, uint32_t chsel); void adc_start_analog_watchdogd(uint32_t chsel);
void adc_stop(ADC_TypeDef *adc); void adc_stop(void);
void adc_interrupt(ADC_TypeDef *adc); void adc_interrupt(void);
int16_t adc_vbat_read(ADC_TypeDef *adc); int16_t adc_vbat_read(void);
/* /*
* misclinous * misclinous

8
plot.c
View file

@ -6,6 +6,7 @@
#include "nanovna.h" #include "nanovna.h"
static void cell_draw_marker_info(int x0, int y0); static void cell_draw_marker_info(int x0, int y0);
static void draw_battery_status(void);
int16_t grid_offset; int16_t grid_offset;
int16_t grid_width; 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 lesser(int x, int y) { return x < y; }
static int (*compare)(int x, int y) = lesser; static int (*compare)(int x, int y) = lesser;
int8_t marker_tracking = false;
int int
marker_search(void) marker_search(void)
@ -1389,6 +1389,8 @@ draw_all(bool flush)
draw_frequencies(); draw_frequencies();
if (redraw_request & REDRAW_CAL_STATUS) if (redraw_request & REDRAW_CAL_STATUS)
draw_cal_status(); draw_cal_status();
if (redraw_request & REDRAW_BATTERY)
draw_battery_status();
redraw_request = 0; redraw_request = 0;
} }
@ -1662,9 +1664,9 @@ draw_cal_status(void)
#define BATTERY_BOTTOM_LEVEL 3100 #define BATTERY_BOTTOM_LEVEL 3100
#define BATTERY_WARNING_LEVEL 3300 #define BATTERY_WARNING_LEVEL 3300
void static void draw_battery_status(void)
draw_battery_status(void)
{ {
int16_t vbat = adc_vbat_read();
if (vbat <= 0) if (vbat <= 0)
return; return;
uint8_t string_buf[16]; uint8_t string_buf[16];

525
si5351.c
View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com
* Modified by DiSlord dislordlive@gmail.com
* All rights reserved. * All rights reserved.
* *
* This is free software; you can redistribute it and/or modify * This is free software; you can redistribute it and/or modify
@ -21,40 +22,64 @@
#include "nanovna.h" #include "nanovna.h"
#include "si5351.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 // XTAL frequency on si5351
si5351_write(uint8_t reg, uint8_t dat) #define XTALFREQ 26000000U
{ // MCLK (processor clock if set, audio codec) frequency clock
int addr = SI5351_I2C_ADDR>>1; #define CLK2_FREQUENCY 8000000U
uint8_t buf[] = { reg, dat };
i2cAcquireBus(&I2CD1); // Fixed PLL mode multiplier (used in band 1)
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, 2, NULL, 0, 1000); #define PLL_N 32
i2cReleaseBus(&I2CD1);
} // 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 static void
si5351_bulk_write(const uint8_t *buf, int len) 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; int addr = SI5351_I2C_ADDR>>1;
i2cAcquireBus(&I2CD1); i2cAcquireBus(&I2CD1);
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000); msg_t mr = i2cMasterTransmitTimeout(&I2CD1, addr, &reg, 1, buf, len, 1000);
i2cReleaseBus(&I2CD1); 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, ... // register addr, length, data, ...
const uint8_t si5351_configs[] = { const uint8_t si5351_configs[] = {
2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff, 2, SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff,
4, SI5351_REG_16_CLK0_CONTROL, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, 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, 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) // 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 // 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) // 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, 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_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 0 // sentinel
}; };
@ -71,93 +96,11 @@ si5351_init(void)
static const uint8_t disable_output[] = { static const uint8_t disable_output[] = {
SI5351_REG_16_CLK0_CONTROL, SI5351_REG_16_CLK0_CONTROL,
SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, // CLK 0
SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN, // CLK 1
SI5351_CLK_POWERDOWN SI5351_CLK_POWERDOWN // CLK 2
}; };
void si5351_disable_output(void)
{
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff);
si5351_bulk_write(disable_output, sizeof(disable_output));
}
void si5351_enable_output(void)
{
si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0x00);
}
static void si5351_reset_pll(void)
{
//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
* P2 register is a 20-bit value using the following formula:
* P2[19:0] = 128 * num - denom * floor(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);
P3 = denom;
}
/* The datasheet is a nightmare of typos and inconsistencies here! */
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);
si5351_bulk_write(reg, 9);
}
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)
{
/* Get the appropriate starting point for the PLL registers */ /* Get the appropriate starting point for the PLL registers */
static const uint8_t msreg_base[] = { static const uint8_t msreg_base[] = {
SI5351_REG_42_MULTISYNTH0, SI5351_REG_42_MULTISYNTH0,
@ -169,134 +112,191 @@ si5351_setupMultisynth(uint8_t output,
SI5351_REG_17_CLK1_CONTROL, SI5351_REG_17_CLK1_CONTROL,
SI5351_REG_18_CLK2_CONTROL SI5351_REG_18_CLK2_CONTROL
}; };
uint8_t dat;
uint32_t P1; // Reset PLL need then band changes
uint32_t P2; static void si5351_reset_pll(uint8_t mask)
uint32_t P3; {
uint32_t div4 = 0; // 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_bulk_write(disable_output, sizeof(disable_output));
current_band = 0;
}
void si5351_enable_output(void)
{
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;
}
// 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)
{
/* 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 + int((128*num)/denom) - 512
* P2 register is a 20-bit value using the following formula:
* 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 */
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
uint8_t reg[9];
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,
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
{
/* Output Multisynth Divider Equations /* Output Multisynth Divider Equations
* where: a = div, b = num and c = denom * where: a = div, b = num and c = denom
* P1 register is an 18-bit value using following formula: * 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 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 register is a 20-bit value using the following formula:
* P3[19:0] = c * P3[19:0] = c
*/ */
/* Set the main PLL config registers */ /* Set the main PLL config registers */
if (div == 4) { uint32_t P1 = 0;
div4 = SI5351_DIVBY4; uint32_t P2 = 0;
P1 = P2 = 0; uint32_t P3 = 1;
P3 = 1; if (div == 4)
} else if (num == 0) { rdiv|= SI5351_DIVBY4;
/* Integer mode */ else {
P1 = 128 * div - 512; num<<=7;
P2 = 0; div<<=7;
P3 = 1; P1 = div - 512; // Integer mode
} else { if (num){ // Fractional mode
/* Fractional mode */ P1+= num / denom;
P1 = 128 * div + ((128 * num) / denom) - 512; P2 = num % denom;
P2 = 128 * num - denom * ((128 * num) / denom);
P3 = denom; P3 = denom;
} }
}
/* Set the MSx config registers */ /* Set the MSx config registers */
uint8_t reg[9]; uint8_t reg[9];
reg[0] = msreg_base[output]; reg[0]= msreg_base[channel]; // SI5351_REG_42_MULTISYNTH0, SI5351_REG_50_MULTISYNTH1, SI5351_REG_58_MULTISYNTH2
reg[1] = (P3 & 0x0000FF00) >> 8; reg[1]=( P3 & 0x0FF00)>>8; // MSx_P3[15: 8]
reg[2] = (P3 & 0x000000FF); reg[2]=( P3 & 0x000FF); // MSx_P3[ 7: 0]
reg[3] = ((P1 & 0x00030000) >> 16) | div4 | rdiv; reg[3]=((P1 & 0x30000)>>16)| rdiv; // Rx_DIV[2:0] | MSx_DIVBY4[1:0] | MSx_P1[17:16]
reg[4] = (P1 & 0x0000FF00) >> 8; reg[4]=( P1 & 0x0FF00)>> 8; // MSx_P1[15: 8]
reg[5] = (P1 & 0x000000FF); reg[5]=( P1 & 0x000FF); // MSx_P1[ 7: 0]
reg[6] = ((P3 & 0x000F0000) >> 12) | ((P2 & 0x000F0000) >> 16); reg[6]=((P3 & 0xF0000)>>12)|((P2 & 0xF0000)>>16); // MSx_P3[19:16] | MSx_P2[19:16]
reg[7] = (P2 & 0x0000FF00) >> 8; reg[7]=( P2 & 0x0FF00)>>8; // MSx_P2[15: 8]
reg[8] = (P2 & 0x000000FF); reg[8]=( P2 & 0x000FF); // MSx_P2[ 7: 0]
si5351_bulk_write(reg, 9); si5351_bulk_write(reg, 9);
/* Configure the clk control and enable the output */ /* Configure the clk control and enable the output */
dat = drive_strength | SI5351_CLK_INPUT_MULTISYNTH_N; uint8_t dat = chctrl | SI5351_CLK_INPUT_MULTISYNTH_N;
if (pllSource == SI5351_PLL_B)
dat |= SI5351_CLK_PLL_SELECT_B;
if (num == 0) if (num == 0)
dat |= SI5351_CLK_INTEGER_MODE; 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 // Find better approximate values for n/d
#define PLL_N 32 #define MAX_DENOMINATOR ((1 << 20) - 1)
#define PLLFREQ (XTALFREQ * PLL_N) static inline void fractionalSolve(uint32_t *n, uint32_t *d){
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 // cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227
int max_denominator = (1 << 20) - 1; uint32_t denom = *d;
if (denom > max_denominator) { if (denom > MAX_DENOMINATOR) {
int p0 = 0, q0 = 1, p1 = 1, q1 = 0; uint32_t num = *n;
uint32_t p0 = 0, q0 = 1, p1 = 1, q1 = 0;
while (denom != 0) { while (denom != 0) {
int a = num / denom; uint32_t a = num / denom;
int q2 = q0 + a*q1; uint32_t b = num % denom;
if (q2 > max_denominator) uint32_t q2 = q0 + a*q1;
if (q2 > MAX_DENOMINATOR)
break; break;
int p2 = p0 + a*p1; uint32_t p2 = p0 + a*p1;
p0 = p1; q0 = q1; p1 = p2; q1 = q2; p0 = p1; q0 = q1; p1 = p2; q1 = q2;
int new_denom = num - a * denom; num = denom; denom = b;
num = denom; denom = new_denom; }
*n = p1;
*d = q1;
} }
num = p1;
denom = q1;
}
si5351_setupMultisynth(channel, pll, div, num, denom, rdiv, drive_strength);
} }
// Setup Multisynth divider for get correct output freq if fixed PLL = pllfreq
static void static void
si5351_set_frequency_fixeddiv(int channel, int pll, uint32_t freq, int div, si5351_set_frequency_fixedpll(uint8_t channel, uint64_t pllfreq, uint32_t freq, uint32_t rdiv, uint8_t chctrl)
uint8_t drive_strength, int mul)
{ {
int denom = XTALFREQ * mul; uint32_t denom = freq;
int64_t pllfreq = (int64_t)freq * div; uint32_t div = pllfreq / denom; // range: 8 ~ 1800
int multi = pllfreq / denom; uint32_t num = pllfreq % denom;
int num = pllfreq - denom * multi; fractionalSolve(&num, &denom);
si5351_setupMultisynth(channel, div, num, denom, rdiv, chctrl);
// 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); // Setup PLL freq if Multisynth divider fixed = div (need get output = freq/mul)
si5351_setupMultisynth(channel, pll, div, 0, 1, SI5351_R_DIV_1, drive_strength); 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 #if 0
void static void
si5351_set_frequency(int channel, int freq, uint8_t drive_strength) 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) { if (freq <= 100000000) {
si5351_setupPLL(SI5351_PLL_B, 32, 0, 1); 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); si5351_set_frequency_fixedpll(channel, SI5351_PLL_B, PLLFREQ, freq, SI5351_R_DIV_1, drive_strength, 1);
@ -308,27 +308,59 @@ si5351_set_frequency(int channel, int freq, uint8_t drive_strength)
} }
#endif #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 // Minimum value is 2, freq change apply at next dsp measure, and need skip it
#define DELAY_BANDCHANGE 1 #define DELAY_NORMAL 2
#define DELAY_LOWBAND 1 // 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: * configure output as follows:
* CLK0: frequency + offset * CLK0: frequency + offset
* CLK1: frequency * CLK1: frequency
* CLK2: fixed 8MHz * CLK2: fixed 8MHz
*/ */
#define CLK2_FREQUENCY 8000000L
int 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 band;
int delay = DELAY_NORMAL; int delay = DELAY_NORMAL;
if (freq == current_freq)
return delay;
uint32_t ofreq = freq + offset; uint32_t ofreq = freq + offset;
uint32_t mul = 1, omul = 1; uint32_t mul = 1, omul = 1;
uint32_t rdiv = SI5351_R_DIV_1; uint32_t rdiv = SI5351_R_DIV_1;
uint32_t fdiv;
current_freq = freq;
if (freq >= config.harmonic_freq_threshold * 7U) { if (freq >= config.harmonic_freq_threshold * 7U) {
mul = 9; mul = 9;
omul = 11; omul = 11;
@ -342,83 +374,50 @@ si5351_set_frequency_with_offset(uint32_t freq, int offset, uint8_t drive_streng
mul = 3; mul = 3;
omul = 5; omul = 5;
} }
if ((freq / mul) < 100000000U) { else if (freq <= 500000U) {
band = 0;
} else if ((freq / mul) < 150000000U) {
band = 1;
} else {
band = 2;
}
if (freq <= 500000U) {
rdiv = SI5351_R_DIV_64; rdiv = SI5351_R_DIV_64;
freq<<= 6;
ofreq<<= 6;
} else if (freq <= 4000000U) { } else if (freq <= 4000000U) {
rdiv = SI5351_R_DIV_8; rdiv = SI5351_R_DIV_8;
freq<<= 3;
ofreq<<= 3;
} }
#if 1 band = si5351_getBand(freq/mul);
if (current_band != band)
si5351_disable_output();
#endif
switch (band) { 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: case 1:
// Set PLL twice on changing from band 2 // Setup CH0 and CH1 constant PLLA freq at band change, and set CH2 freq = CLK2_FREQUENCY
if (current_band == 2) { if (current_band != 1){
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul); si5351_setupPLL(SI5351_REG_PLL_A, PLL_N, 0, 1);
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul); 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;
} }
// Calculate and set CH0 and CH1 divider
// div by 6 mode. both PLL A and B are dedicated for CLK0, CLK1 si5351_set_frequency_fixedpll(0, (uint64_t)omul * XTALFREQ * PLL_N, ofreq, rdiv, drive_strength|SI5351_CLK_PLL_SELECT_A);
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 6, drive_strength, omul); si5351_set_frequency_fixedpll(1, (uint64_t) mul * XTALFREQ * PLL_N, freq, rdiv, drive_strength|SI5351_CLK_PLL_SELECT_A);
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 6, drive_strength, mul); delay+=DELAY_BAND_1;
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq / mul * 6, CLK2_FREQUENCY,
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1);
break; break;
case 2:// fdiv = 6
case 2: case 3:// fdiv = 4;
// div by 4 mode. both PLL A and B are dedicated for CLK0, CLK1 fdiv = (band == 2) ? 6 : 4;
si5351_set_frequency_fixeddiv(0, SI5351_PLL_A, ofreq, 4, drive_strength, omul); // Setup CH0 and CH1 constant fdiv divider at change
si5351_set_frequency_fixeddiv(1, SI5351_PLL_B, freq, 4, drive_strength, mul); if (current_band != band){
si5351_set_frequency_fixedpll(2, SI5351_PLL_B, freq / mul * 4, CLK2_FREQUENCY, si5351_setupMultisynth(0, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength|SI5351_CLK_PLL_SELECT_A);
SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA, 1); 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; break;
} }
if (current_band != band) { if (current_band != band) {
si5351_reset_pll(); si5351_reset_pll(SI5351_PLL_RESET_A|SI5351_PLL_RESET_B);
#if 1
si5351_enable_output();
#endif
delay += DELAY_BANDCHANGE;
}
if (band == 0)
delay += DELAY_LOWBAND;
current_band = band; current_band = band;
}
return delay; return delay;
} }

View file

@ -17,12 +17,39 @@
* the Free Software Foundation, Inc., 51 Franklin Street, * the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
#define SI5351_PLL_A 0
#define SI5351_PLL_B 1
#define SI5351_MULTISYNTH_DIV_4 4 #define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3
#define SI5351_MULTISYNTH_DIV_6 6 #define SI5351_CLK0_EN (1<<0)
#define SI5351_MULTISYNTH_DIV_8 8 #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_1 (0<<4)
#define SI5351_R_DIV_2 (1<<4) #define SI5351_R_DIV_2 (1<<4)
#define SI5351_R_DIV_4 (2<<4) #define SI5351_R_DIV_4 (2<<4)
@ -31,35 +58,6 @@
#define SI5351_R_DIV_32 (5<<4) #define SI5351_R_DIV_32 (5<<4)
#define SI5351_R_DIV_64 (6<<4) #define SI5351_R_DIV_64 (6<<4)
#define SI5351_R_DIV_128 (7<<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_REG_177_PLL_RESET 177
#define SI5351_PLL_RESET_B (1<<7) #define SI5351_PLL_RESET_B (1<<7)
@ -70,8 +68,8 @@
#define SI5351_CRYSTAL_LOAD_8PF (2<<6) #define SI5351_CRYSTAL_LOAD_8PF (2<<6)
#define SI5351_CRYSTAL_LOAD_10PF (3<<6) #define SI5351_CRYSTAL_LOAD_10PF (3<<6)
#define SI5351_CRYSTAL_FREQ_25MHZ 25000000
void si5351_init(void); void si5351_init(void);
void si5351_disable_output(void);
void si5351_set_frequency(int channel, int freq, uint8_t drive_strength); 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);

View file

@ -25,74 +25,78 @@
#define wait_ms(ms) chThdSleepMilliseconds(ms) #define wait_ms(ms) chThdSleepMilliseconds(ms)
static const uint8_t conf_data_pll[] = { static const uint8_t conf_data[] = {
// len, ( reg, data ), // reg, data,
2, 0x00, 0x00, /* Initialize to Page 0 */ // PLL clock config
2, 0x01, 0x01, /* Initialize the device through software reset */ 0x00, 0x00, /* Initialize to Page 0 */
2, 0x04, 0x43, /* PLL Clock High, MCLK, PLL */ 0x01, 0x01, /* Initialize the device through software reset */
0x04, 0x43, /* PLL Clock High, MCLK, PLL */
#ifdef REFCLK_8000KHZ #ifdef REFCLK_8000KHZ
/* 8.000MHz*10.7520 = 86.016MHz, 86.016MHz/(2*7*128) = 48kHz */ /* 8.000MHz*10.7520 = 86.016MHz, 86.016MHz/(2*7*128) = 48kHz */
2, 0x05, 0x91, /* Power up PLL, P=1,R=1 */ 0x05, 0x91, /* Power up PLL, P=1,R=1 */
2, 0x06, 0x0a, /* J=10 */ 0x06, 0x0a, /* J=10 */
2, 0x07, 29, /* D=7520 = (29<<8) + 96 */ 0x07, 29, /* D=7520 = (29<<8) + 96 */
2, 0x08, 96, 0x08, 96,
#endif #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_unmute[] = {
static const uint8_t conf_data_clk[] = { // reg, data,
2, 0x0b, 0x82, /* Power up the NDAC divider with value 2 */ 0x00, 0x00, /* Select Page 0 */
2, 0x0c, 0x87, /* Power up the MDAC divider with value 7 */ 0x51, 0xc0, /* Power up Left and Right ADC Channels */
2, 0x0d, 0x00, /* Program the OSR of DAC to 128 */ 0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */
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_routing[] = { static const uint8_t conf_data_ch3_select[] = {
2, 0x00, 0x01, /* Select Page 1 */ // reg, data,
2, 0x01, 0x08, /* Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO*/ 0x00, 0x01, /* Select Page 1 */
2, 0x02, 0x01, /* Enable Master Analog Power Control */ 0x37, 0x04, /* Route IN3R to RIGHT_P with input impedance of 10K */
2, 0x7b, 0x01, /* Set the REF charging time to 40ms */ 0x39, 0x04, /* Route IN3L to RIGHT_N with input impedance of 10K */
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
}; };
const uint8_t conf_data_unmute[] = { static const uint8_t conf_data_ch1_select[] = {
2, 0x00, 0x00, /* Select Page 0 */ // reg, data,
2, 0x51, 0xc0, /* Power up Left and Right ADC Channels */ 0x00, 0x01, /* Select Page 1 */
2, 0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */ 0x37, 0x40, /* Route IN1R to RIGHT_P with input impedance of 10K */
0 // sentinel 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) tlv320aic3204_bulk_write(const uint8_t *buf, int len)
{ {
int addr = AIC3204_ADDR; (void)i2cMasterTransmitTimeout(&I2CD1, AIC3204_ADDR, buf, len, NULL, 0, 1000);
i2cAcquireBus(&I2CD1);
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000);
i2cReleaseBus(&I2CD1);
} }
#if 0 #if 0
@ -109,49 +113,32 @@ tlv320aic3204_read(uint8_t d0)
#endif #endif
static void static void
tlv320aic3204_config(const uint8_t *data) tlv320aic3204_config(const uint8_t *data, int len)
{ {
const uint8_t *p = data; i2cAcquireBus(&I2CD1);
while (*p) { for (;len--;data+=2)
uint8_t len = *p++; tlv320aic3204_bulk_write(data, 2);
tlv320aic3204_bulk_write(p, len); i2cReleaseBus(&I2CD1);
p += len;
}
} }
void tlv320aic3204_init(void) void tlv320aic3204_init(void)
{ {
tlv320aic3204_config(conf_data_pll); tlv320aic3204_config(conf_data, sizeof(conf_data)/2);
tlv320aic3204_config(conf_data_clk);
tlv320aic3204_config(conf_data_routing);
wait_ms(40); wait_ms(40);
tlv320aic3204_config(conf_data_unmute); tlv320aic3204_config(conf_data_unmute, sizeof(conf_data_unmute)/2);
} }
void tlv320aic3204_select(int channel) void tlv320aic3204_select(int channel)
{ {
const uint8_t ch3[] = { tlv320aic3204_config(channel ? conf_data_ch1_select : conf_data_ch3_select, sizeof(conf_data_ch3_select)/2);
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);
} }
void tlv320aic3204_set_gain(int lgain, int rgain) void tlv320aic3204_set_gain(int lgain, int rgain)
{ {
uint8_t data[] = { uint8_t data[] = {
2, 0x00, 0x01, /* Select Page 1 */ 0x00, 0x01, /* Select Page 1 */
2, 0x3b, lgain, /* Unmute Left MICPGA, set gain */ 0x3b, lgain, /* Unmute Left MICPGA, set gain */
2, 0x3c, rgain, /* Unmute Right MICPGA, set gain */ 0x3c, rgain, /* Unmute Right MICPGA, set gain */
0 // sentinel
}; };
tlv320aic3204_config(data); tlv320aic3204_config(data, sizeof(data)/2);
} }

115
ui.c
View file

@ -25,12 +25,12 @@
//#include <stdlib.h> //#include <stdlib.h>
#include <string.h> #include <string.h>
uistat_t uistat = { uistat_t uistat = {
digit: 6, digit: 6,
current_trace: 0, current_trace: 0,
lever_mode: LM_MARKER, lever_mode: LM_MARKER,
marker_delta: FALSE, marker_delta: FALSE,
marker_tracking : FALSE,
}; };
#define NO_EVENT 0 #define NO_EVENT 0
@ -42,8 +42,8 @@ uistat_t uistat = {
#define EVT_REPEAT 0x40 #define EVT_REPEAT 0x40
#define BUTTON_DOWN_LONG_TICKS 5000 /* 1sec */ #define BUTTON_DOWN_LONG_TICKS 5000 /* 1sec */
#define BUTTON_DOUBLE_TICKS 5000 /* 500ms */ #define BUTTON_DOUBLE_TICKS 2500 /* 500ms */
#define BUTTON_REPEAT_TICKS 1000 /* 100ms */ #define BUTTON_REPEAT_TICKS 625 /* 125ms */
#define BUTTON_DEBOUNCE_TICKS 200 #define BUTTON_DEBOUNCE_TICKS 200
/* lever switch assignment */ /* lever switch assignment */
@ -59,7 +59,7 @@ static uint32_t last_button_down_ticks;
static uint32_t last_button_repeat_ticks; static uint32_t last_button_repeat_ticks;
static int8_t inhibit_until_release = FALSE; 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; 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 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 ui_mode = UI_NORMAL;
static uint8_t keypad_mode; 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; static int8_t selection = 0;
// Set structure align as WORD (save flash memory) // 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] = { 1000, 1000, 10*16, 12*16 };
//int16_t touch_cal[4] = { 620, 600, 130, 180 }; //int16_t touch_cal[4] = { 620, 600, 130, 180 };
int awd_count; //int awd_count;
//int touch_x, touch_y; //int touch_x, touch_y;
#define NUMINPUT_LEN 10
#define KP_CONTINUE 0 #define KP_CONTINUE 0
#define KP_DONE 1 #define KP_DONE 1
#define KP_CANCEL 2 #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_normal(void);
static void ui_mode_menu(void); static void ui_mode_menu(void);
static void ui_mode_numeric(int _keypad_mode); static void ui_mode_numeric(int _keypad_mode);
@ -130,8 +131,8 @@ static int btn_check(void)
int status = 0; int status = 0;
uint32_t ticks = chVTGetSystemTime(); uint32_t ticks = chVTGetSystemTime();
if (changed & (1<<BIT_PUSH)) { if (changed & (1<<BIT_PUSH)) {
if (ticks - last_button_down_ticks >= BUTTON_DEBOUNCE_TICKS) { if ((cur_button & (1<<BIT_PUSH))
if (cur_button & (1<<BIT_PUSH)) { && ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS) {
// button released // button released
status |= EVT_BUTTON_SINGLE_CLICK; status |= EVT_BUTTON_SINGLE_CLICK;
if (inhibit_until_release) { if (inhibit_until_release) {
@ -139,24 +140,20 @@ static int btn_check(void)
inhibit_until_release = FALSE; inhibit_until_release = FALSE;
} }
} }
last_button_down_ticks = ticks;
} }
}
if (changed & (1<<BIT_UP1)) { if (changed & (1<<BIT_UP1)) {
if ((cur_button & (1<<BIT_UP1)) if ((cur_button & (1<<BIT_UP1))
&& (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) { && (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) {
status |= EVT_UP; status |= EVT_UP;
} }
last_button_down_ticks = ticks;
} }
if (changed & (1<<BIT_DOWN1)) { if (changed & (1<<BIT_DOWN1)) {
if ((cur_button & (1<<BIT_DOWN1)) if ((cur_button & (1<<BIT_DOWN1))
&& (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) { && (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) {
status |= EVT_DOWN; status |= EVT_DOWN;
} }
last_button_down_ticks = ticks;
} }
last_button_down_ticks = ticks;
last_button = cur_button; last_button = cur_button;
return status; return status;
@ -169,15 +166,14 @@ static int btn_wait_release(void)
int changed = last_button ^ cur_button; int changed = last_button ^ cur_button;
uint32_t ticks = chVTGetSystemTime(); uint32_t ticks = chVTGetSystemTime();
int status = 0; int status = 0;
if (!inhibit_until_release) { if (!inhibit_until_release) {
if ((cur_button & (1<<BIT_PUSH)) 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; inhibit_until_release = TRUE;
return EVT_BUTTON_DOWN_LONG; return EVT_BUTTON_DOWN_LONG;
} }
if ((changed & (1<<BIT_PUSH)) 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; return EVT_BUTTON_SINGLE_CLICK;
} }
} }
@ -190,14 +186,12 @@ static int btn_wait_release(void)
return 0; return 0;
} }
if (ticks - last_button_down_ticks >= BUTTON_DOWN_LONG_TICKS if (ticks >= last_button_down_ticks + BUTTON_DOWN_LONG_TICKS
&& ticks - last_button_repeat_ticks >= BUTTON_REPEAT_TICKS) { && ticks >= last_button_repeat_ticks + BUTTON_REPEAT_TICKS) {
if (cur_button & (1<<BIT_DOWN1)) { if (cur_button & (1<<BIT_DOWN1))
status |= EVT_DOWN | EVT_REPEAT; status |= EVT_DOWN | EVT_REPEAT;
} if (cur_button & (1<<BIT_UP1))
if (cur_button & (1<<BIT_UP1)) {
status |= EVT_UP | EVT_REPEAT; status |= EVT_UP | EVT_REPEAT;
}
last_button_repeat_ticks = ticks; last_button_repeat_ticks = ticks;
return status; return status;
} }
@ -218,7 +212,7 @@ touch_measure_y(void)
palSetPad(GPIOA, 6); palSetPad(GPIOA, 6);
chThdSleepMilliseconds(2); chThdSleepMilliseconds(2);
v = adc_single_read(ADC1, ADC_CHSELR_CHSEL7); v = adc_single_read(ADC_CHSELR_CHSEL7);
//chThdSleepMilliseconds(2); //chThdSleepMilliseconds(2);
//v += adc_single_read(ADC1, ADC_CHSELR_CHSEL7); //v += adc_single_read(ADC1, ADC_CHSELR_CHSEL7);
return v; return v;
@ -238,7 +232,7 @@ touch_measure_x(void)
palClearPad(GPIOA, 7); palClearPad(GPIOA, 7);
chThdSleepMilliseconds(2); chThdSleepMilliseconds(2);
v = adc_single_read(ADC1, ADC_CHSELR_CHSEL6); v = adc_single_read(ADC_CHSELR_CHSEL6);
//chThdSleepMilliseconds(2); //chThdSleepMilliseconds(2);
//v += adc_single_read(ADC1, ADC_CHSELR_CHSEL6); //v += adc_single_read(ADC1, ADC_CHSELR_CHSEL6);
return v; return v;
@ -261,14 +255,14 @@ void
touch_start_watchdog(void) touch_start_watchdog(void)
{ {
touch_prepare_sense(); touch_prepare_sense();
adc_start_analog_watchdogd(ADC1, ADC_CHSELR_CHSEL7); adc_start_analog_watchdogd(ADC_CHSELR_CHSEL7);
} }
static int static int
touch_status(void) touch_status(void)
{ {
touch_prepare_sense(); touch_prepare_sense();
return adc_single_read(ADC1, ADC_CHSELR_CHSEL7) > TOUCH_THRESHOLD; return adc_single_read(ADC_CHSELR_CHSEL7) > TOUCH_THRESHOLD;
} }
static int static int
@ -308,7 +302,7 @@ touch_cal_exec(void)
{ {
int x1, x2, y1, y2; int x1, x2, y1, y2;
adc_stop(ADC1); adc_stop();
setForegroundColor(DEFAULT_FG_COLOR); setForegroundColor(DEFAULT_FG_COLOR);
setBackgroundColor(DEFAULT_BG_COLOR); setBackgroundColor(DEFAULT_BG_COLOR);
clearScreen(); clearScreen();
@ -344,7 +338,7 @@ touch_draw_test(void)
int x0, y0; int x0, y0;
int x1, y1; int x1, y1;
adc_stop(ADC1); adc_stop();
setForegroundColor(DEFAULT_FG_COLOR); setForegroundColor(DEFAULT_FG_COLOR);
setBackgroundColor(DEFAULT_BG_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]; *y = (last_touch_y - config.touch_cal[1]) * 16 / config.touch_cal[3];
} }
void void
show_version(void) show_version(void)
{ {
int x = 5, y = 5; int x = 5, y = 5, i = 0;
adc_stop(ADC1); adc_stop();
setForegroundColor(DEFAULT_FG_COLOR); setForegroundColor(DEFAULT_FG_COLOR);
setBackgroundColor(DEFAULT_BG_COLOR); setBackgroundColor(DEFAULT_BG_COLOR);
clearScreen(); clearScreen();
ili9341_drawstring_size(BOARD_NAME, x, y, 4); uint16_t shift = 0b0000010000111110;
y += 25; ili9341_drawstring_size(info_about[i++], x , y, 4);
while (info_about[i]){
ili9341_drawstring("2016-2020 Copyright @edy555", x, y += 10); do {shift>>=1; y+=5;} while (shift&1);
ili9341_drawstring("Licensed under GPL. See: https://github.com/ttrftech/NanoVNA", x, y += 10); ili9341_drawstring(info_about[i++], x, y+=5);
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);
while (true) { while (true) {
if (touch_check() == EVT_TOUCH_PRESSED) if (touch_check() == EVT_TOUCH_PRESSED)
break; break;
@ -410,7 +395,7 @@ show_version(void)
void void
enter_dfu(void) enter_dfu(void)
{ {
adc_stop(ADC1); adc_stop();
int x = 5, y = 5; int x = 5, y = 5;
setForegroundColor(DEFAULT_FG_COLOR); 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); i = marker_search_right(markers[active_marker].index);
break; break;
case 4: /* tracking */ case 4: /* tracking */
marker_tracking = !marker_tracking; uistat.marker_tracking = !uistat.marker_tracking;
break; break;
} }
if (i != -1) if (i != -1)
@ -1047,7 +1032,6 @@ const menuitem_t menu_top[] = {
}; };
#define MENU_STACK_DEPTH_MAX 4 #define MENU_STACK_DEPTH_MAX 4
uint8_t menu_current_level = 0;
const menuitem_t *menu_stack[MENU_STACK_DEPTH_MAX] = { const menuitem_t *menu_stack[MENU_STACK_DEPTH_MAX] = {
menu_top, NULL, NULL, NULL menu_top, NULL, NULL, NULL
}; };
@ -1171,7 +1155,6 @@ typedef struct {
} keypads_t; } keypads_t;
static const keypads_t *keypads; static const keypads_t *keypads;
static uint8_t keypads_last_index;
static const keypads_t keypads_freq[] = { static const keypads_t keypads_freq[] = {
{ 1, 3, KP_PERIOD }, { 1, 3, KP_PERIOD },
@ -1345,7 +1328,7 @@ menu_item_modify_attribute(const menuitem_t *menu, int item,
} }
} }
} else if (menu == menu_marker_search) { } else if (menu == menu_marker_search) {
if (item == 4 && marker_tracking) { if (item == 4 && uistat.marker_tracking) {
*bg = DEFAULT_MENU_TEXT_COLOR; *bg = DEFAULT_MENU_TEXT_COLOR;
*fg = config.menu_normal_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; *fg = config.menu_normal_color;
} }
} else if (menu == menu_stimulus) { } else if (menu == menu_stimulus) {
if (item == 5 /* PAUSE */ && !sweep_enabled) { if (item == 5 /* PAUSE */ && !(sweep_mode&SWEEP_ENABLE)) {
*bg = DEFAULT_MENU_TEXT_COLOR; *bg = DEFAULT_MENU_TEXT_COLOR;
*fg = config.menu_normal_color; *fg = config.menu_normal_color;
} }
@ -1535,7 +1518,7 @@ fetch_numeric_target(void)
x /= 10; x /= 10;
uistat.digit = n; uistat.digit = n;
} }
uistat.previous_value = uistat.value; // uistat.previous_value = uistat.value;
} }
static void static void
@ -2011,7 +1994,7 @@ static void
ui_process_keypad(void) ui_process_keypad(void)
{ {
int status; int status;
adc_stop(ADC1); adc_stop();
kp_index = 0; kp_index = 0;
while (TRUE) { while (TRUE) {
@ -2139,7 +2122,7 @@ touch_lever_mode_select(void)
select_lever_mode(touch_x < FREQUENCIES_XPOS2 ? LM_CENTER : LM_SPAN); select_lever_mode(touch_x < FREQUENCIES_XPOS2 ? LM_CENTER : LM_SPAN);
return TRUE; return TRUE;
} }
if (touch_y < 15) { if (touch_y < 25) {
if (touch_x < FREQUENCIES_XPOS2 && get_electrical_delay() != 0.0) { if (touch_x < FREQUENCIES_XPOS2 && get_electrical_delay() != 0.0) {
select_lever_mode(LM_EDELAY); select_lever_mode(LM_EDELAY);
} else } else
@ -2152,8 +2135,8 @@ touch_lever_mode_select(void)
static static
void ui_process_touch(void) void ui_process_touch(void)
{ {
awd_count++; // awd_count++;
adc_stop(ADC1); adc_stop();
int status = touch_check(); int status = touch_check();
if (status == EVT_TOUCH_PRESSED || status == EVT_TOUCH_DOWN) { if (status == EVT_TOUCH_PRESSED || status == EVT_TOUCH_DOWN) {
@ -2189,14 +2172,10 @@ void ui_process_touch(void)
void void
ui_process(void) ui_process(void)
{ {
switch (operation_requested) { if (operation_requested&OP_LEVER)
case OP_LEVER:
ui_process_lever(); ui_process_lever();
break; if (operation_requested&OP_TOUCH)
case OP_TOUCH:
ui_process_touch(); ui_process_touch();
break;
}
operation_requested = OP_NONE; operation_requested = OP_NONE;
} }
@ -2204,7 +2183,7 @@ ui_process(void)
static void extcb1(EXTDriver *extp, expchannel_t channel) { static void extcb1(EXTDriver *extp, expchannel_t channel) {
(void)extp; (void)extp;
(void)channel; (void)channel;
operation_requested = OP_LEVER; operation_requested|=OP_LEVER;
//cur_button = READ_PORT() & BUTTON_MASK; //cur_button = READ_PORT() & BUTTON_MASK;
} }
@ -2259,7 +2238,7 @@ test_touch(int *x, int *y)
void void
handle_touch_interrupt(void) handle_touch_interrupt(void)
{ {
operation_requested = OP_TOUCH; operation_requested|= OP_TOUCH;
} }
void void