diff --git a/main.c b/main.c index bb5580b..4f35b24 100644 --- a/main.c +++ b/main.c @@ -69,10 +69,6 @@ static void transform_domain(void); static MUTEX_DECL(mutex); -#define DRIVE_STRENGTH_AUTO (-1) -#define FREQ_HARMONICS (config.harmonic_freq_threshold) -#define IS_HARMONIC_MODE(f) ((f) > FREQ_HARMONICS) - int32_t frequency_offset = 5000; uint32_t frequency = 10000000; int8_t drive_strength = DRIVE_STRENGTH_AUTO; @@ -101,6 +97,7 @@ static THD_FUNCTION(Thread1, arg) sweep_once = FALSE; chMtxUnlock(&mutex); } else { + si5351_disable_output(); __WFI(); } @@ -123,7 +120,7 @@ static THD_FUNCTION(Thread1, arg) plot_into_index(measured); redraw_request |= REDRAW_CELLS; - if (marker_tracking) { + if (uistat.marker_tracking) { int i = marker_search(); if (i != -1 && active_marker != -1) { markers[active_marker].index = i; @@ -316,7 +313,7 @@ const int8_t gain_table[] = { 95 // 2400MHz ~ }; -#define DELAY_GAIN_CHANGE 10 +#define DELAY_GAIN_CHANGE 2 static int adjust_gain(int newfreq) @@ -474,7 +471,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) { @@ -745,7 +742,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 +759,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,7 +775,7 @@ ensure_edit_config(void) cal_status = 0; } -#define DELAY_CHANNEL_CHANGE 3 +#define DELAY_CHANNEL_CHANGE 2 // main loop for measurement bool sweep(bool break_on_operation) @@ -783,11 +783,17 @@ bool sweep(bool break_on_operation) int i; // blink LED while scanning palClearPad(GPIOC, GPIOC_LED); + systime_t time = chVTGetSystemTimeX(); + systime_t sweep_t = 0; + si5351_enable_output(); + // On CW set freq once, and run for (i = 0; i < sweep_points; i++) { // 8365 + sweep_t-= chVTGetSystemTimeX(); int delay = set_frequency(frequencies[i]); // 1560 + sweep_t+= chVTGetSystemTimeX(); tlv320aic3204_select(0); // 60 CH0:REFLECT - wait_dsp(delay); // 3270 + wait_dsp(delay+(i==0 ? 1 :0)); // 3270 // calculate reflection coefficient (*sample_func)(measured[0][i]); // 60 @@ -803,9 +809,11 @@ bool sweep(bool break_on_operation) apply_edelay_at(i); // back to toplevel to handle ui operation - if (operation_requested && break_on_operation) + if (operation_requested && break_on_operation){ return false; + } } + {char string_buf[18];plot_printf(string_buf, sizeof string_buf, "T:%06d:%06d", chVTGetSystemTimeX() - time, sweep_t);ili9341_drawstringV(string_buf, 1, 90);} // blink LED while scanning palSetPad(GPIOC, GPIOC_LED); return true; @@ -912,7 +920,7 @@ update_frequencies(void) } set_frequencies(start, stop, sweep_points); - operation_requested = OP_FREQCHANGE; +// operation_requested|= OP_FREQCHANGE; update_marker_index(); @@ -1430,6 +1438,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 +1448,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 +1460,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 +1694,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 +1709,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 +1722,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 +1927,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); } @@ -2160,10 +2164,25 @@ THD_FUNCTION(myshellThread, p) { } #endif +// I2C clock bus setting: depend from STM32_I2C1SW in mcuconf.h +// STM32_I2C1SW = STM32_I2C1SW_HSI (HSI=8MHz) +// STM32_I2C1SW = STM32_I2C1SW_SYSCLK (SYSCLK = 48MHz) static const I2CConfig i2ccfg = { - 0x00300506, //voodoo magic 400kHz @ HSI 8MHz - 0, - 0 + // TIMINGR register initialization. (use I2C timing configuration tool for STM32F3xx and STM32F0xx microcontrollers (AN4235)) + // 400kHz @ SYSCLK 48MHz (Use 26.4.10 I2C_TIMINGR register configuration examples from STM32 RM0091 Reference manual) +// STM32_TIMINGR_PRESC(5U) | +// STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(3U) | +// STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U), +// 400kHz @ HSI 8MHz (Use 26.4.10 I2C_TIMINGR register configuration examples from STM32 RM0091 Reference manual) + STM32_TIMINGR_PRESC(0U) | + STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(1U) | + STM32_TIMINGR_SCLH(3U) | STM32_TIMINGR_SCLL(9U), +// Old values voodoo magic 400kHz @ HSI 8MHz +// STM32_TIMINGR_PRESC(0U) | +// STM32_TIMINGR_SCLDEL(3U) | STM32_TIMINGR_SDADEL(0U) | +// STM32_TIMINGR_SCLH(5U) | STM32_TIMINGR_SCLL(6U), + 0, // CR1 register initialization. + 0 // CR2 register initialization. }; static DACConfig dac1cfg1 = { diff --git a/nanovna.h b/nanovna.h index 524b2aa..ba87162 100644 --- a/nanovna.h +++ b/nanovna.h @@ -88,30 +88,6 @@ 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; - /* * dsp.c */ @@ -134,9 +110,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 */ @@ -250,6 +223,10 @@ typedef struct config { extern config_t config; +#define DRIVE_STRENGTH_AUTO (-1) +#define FREQ_HARMONICS (config.harmonic_freq_threshold) +#define IS_HARMONIC_MODE(f) ((f) > FREQ_HARMONICS) + //extern trace_t trace[TRACES_MAX]; void set_trace_type(int t, int type); @@ -366,6 +343,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 +419,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 +444,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); diff --git a/plot.c b/plot.c index 70f5e31..d1762f0 100644 --- a/plot.c +++ b/plot.c @@ -1056,7 +1056,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) diff --git a/si5351.c b/si5351.c index 56ba597..ace6af4 100644 --- a/si5351.c +++ b/si5351.c @@ -21,17 +21,18 @@ #include "nanovna.h" #include "si5351.h" +#define XTALFREQ 26000000L +// MCLK (processor clock, audio codec) frequency clock +#define CLK2_FREQUENCY 8000000L + +// Fixed PLL mode multiplier +#define PLL_N 32 + +// #define SI5351_I2C_ADDR (0x60<<1) -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); -} +static uint8_t current_band = 0; +static uint32_t current_freq = 0; static void si5351_bulk_write(const uint8_t *buf, int len) @@ -41,6 +42,22 @@ si5351_bulk_write(const uint8_t *buf, int len) (void)i2cMasterTransmitTimeout(&I2CD1, 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); + 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[] = { @@ -48,13 +65,14 @@ const uint8_t si5351_configs[] = { 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, // 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, +// 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, 0 // sentinel }; @@ -71,26 +89,46 @@ 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 }; +static void si5351_reset_pll(uint8_t mask) +{ + // Writing a 1<<5 will reset PLLA, 1<<7 reset PLLB, this is a self clearing bits. + // !!! Need delay before reset PLL for apply PLL freq changes before + chThdSleepMicroseconds(200); + si5351_write(SI5351_REG_177_PLL_RESET, mask | 0x0C); +// chThdSleepMicroseconds(250); +} + void si5351_disable_output(void) { +// si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, (SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN)); si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0xff); si5351_bulk_write(disable_output, sizeof(disable_output)); } void si5351_enable_output(void) { + si5351_reset_pll( SI5351_PLL_RESET_A | SI5351_PLL_RESET_B ); +// si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, ~(SI5351_CLK0_EN|SI5351_CLK1_EN|SI5351_CLK2_EN)); si5351_write(SI5351_REG_3_OUTPUT_ENABLE_CONTROL, 0x00); -} - -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); + current_freq = 0; + current_band = 0; } static void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */ @@ -98,11 +136,6 @@ static void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */ 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; @@ -134,10 +167,17 @@ static void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */ P2 = 128 * num - denom * ((128 * num) / denom); P3 = denom; } - - /* The datasheet is a nightmare of typos and inconsistencies here! */ +// Pll MSN(A|B) registers Datasheet +// MSN_P3[15:8] +// MSN_P3[ 7:0] +// Reserved | MSN_P1[17:16] +// MSN_P1[15:8] +// MSN_P1[ 7:0] +// MSN_P3[19:16] | MSN_P2[19:16] +// MSN_P2[15:8] +// MSN_P2[ 7:0] uint8_t reg[9]; - reg[0] = pllreg_base[pll]; + reg[0] = pll;//reg_base[pll]; reg[1] = (P3 & 0x0000FF00) >> 8; reg[2] = (P3 & 0x000000FF); reg[3] = (P1 & 0x00030000) >> 16; @@ -149,8 +189,9 @@ static void si5351_setupPLL(uint8_t pll, /* SI5351_PLL_A or SI5351_PLL_B */ si5351_bulk_write(reg, 9); } + static void -si5351_setupMultisynth(uint8_t output, +si5351_setupMultisynth(uint8_t channel, uint8_t pllSource, uint32_t div, // 4,6,8, 8+ ~ 900 uint32_t num, @@ -158,17 +199,6 @@ si5351_setupMultisynth(uint8_t output, uint32_t rdiv, // SI5351_R_DIV_1~128 uint8_t drive_strength) { - /* 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; @@ -204,7 +234,7 @@ si5351_setupMultisynth(uint8_t output, /* Set the MSx config registers */ uint8_t reg[9]; - reg[0] = msreg_base[output]; + reg[0] = msreg_base[channel]; reg[1] = (P3 & 0x0000FF00) >> 8; reg[2] = (P3 & 0x000000FF); reg[3] = ((P1 & 0x00030000) >> 16) | div4 | rdiv; @@ -217,86 +247,80 @@ si5351_setupMultisynth(uint8_t output, /* Configure the clk control and enable the output */ dat = drive_strength | SI5351_CLK_INPUT_MULTISYNTH_N; - if (pllSource == SI5351_PLL_B) + if (pllSource == SI5351_REG_PLL_B) dat |= SI5351_CLK_PLL_SELECT_B; if (num == 0) dat |= SI5351_CLK_INTEGER_MODE; - si5351_write(clkctrl[output], dat); + si5351_write(clkctrl[channel], dat); } -#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) +si5351_set_frequency_fixedpll(uint8_t channel, uint32_t pllSource, uint64_t pllfreq, uint32_t freq, uint32_t rdiv, uint8_t drive_strength) { - int denom = freq; - int div = (pllfreq * mul) / denom; // range: 8 ~ 1800 - int num = (pllfreq * mul) - denom * div; + uint32_t denom = freq; + uint32_t div = pllfreq / denom; // range: 8 ~ 1800 + uint32_t num = pllfreq % denom; // cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227 - int max_denominator = (1 << 20) - 1; + uint32_t max_denominator = (1 << 20) - 1; if (denom > max_denominator) { - int p0 = 0, q0 = 1, p1 = 1, q1 = 0; + uint32_t p0 = 0, q0 = 1, p1 = 1, q1 = 0; while (denom != 0) { - int a = num / denom; - int q2 = q0 + a*q1; + uint32_t a = num / denom; + uint32_t b = num % denom; + uint32_t 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; + uint32_t p2 = p0 + a*p1; + p0 = p1; + q0 = q1; + p1 = p2; + q1 = q2; + num = denom; denom = b; } num = p1; denom = q1; } + si5351_setupMultisynth(channel, pllSource, div, num, denom, rdiv, drive_strength); +} - si5351_setupMultisynth(channel, pll, div, num, denom, rdiv, drive_strength); +void si5351_setupPLL_freq(uint32_t pll, uint32_t freq, uint32_t div, uint32_t mul){ + uint32_t denom = XTALFREQ * mul; + uint64_t pllfreq = (uint64_t)freq * div; + uint32_t multi = pllfreq / denom; + uint32_t num = pllfreq % denom; + + // cf. https://github.com/python/cpython/blob/master/Lib/fractions.py#L227 + uint32_t max_denominator = (1 << 20) - 1; + if (denom > max_denominator) { + uint32_t p0 = 0, q0 = 1, p1 = 1, q1 = 0; + while (denom != 0) { + uint32_t a = num / denom; + uint32_t b = num % denom; + uint32_t q2 = q0 + a*q1; + if (q2 > max_denominator) + break; + uint32_t p2 = p0 + a*p1; + p0 = p1; q0 = q1; p1 = p2; q1 = q2; + num = denom; denom = b; + } + num = p1; + denom = q1; + } + si5351_setupPLL(pll, multi, num, denom); } +#if 0 static void -si5351_set_frequency_fixeddiv(int channel, int pll, uint32_t freq, int div, - uint8_t drive_strength, int mul) +si5351_set_frequency_fixeddiv(uint8_t channel, uint32_t pll, uint32_t freq, uint32_t div, + uint8_t drive_strength, uint32_t mul) { - 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); + si5351_setupPLL_freq(pll, freq, div, mul); + si5351_setupMultisynth(channel, pll, div, 0, 1, SI5351_R_DIV_1, drive_strength); } -/* - * 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) -{ +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,11 +332,8 @@ si5351_set_frequency(int channel, int freq, uint8_t drive_strength) } #endif -int current_band = -1; - -#define DELAY_NORMAL 3 -#define DELAY_BANDCHANGE 1 -#define DELAY_LOWBAND 1 +#define DELAY_NORMAL 2 +#define DELAY_BANDCHANGE 2 /* * configure output as follows: @@ -320,105 +341,89 @@ int current_band = -1; * 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; + 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; - if (freq >= config.harmonic_freq_threshold * 7U) { + uint32_t fdiv; + current_freq = freq; + if (freq >= FREQ_HARMONICS * 7U) { mul = 9; omul = 11; - } else if (freq >= config.harmonic_freq_threshold * 5U) { + } else if (freq >= FREQ_HARMONICS * 5U) { mul = 7; omul = 9; - } else if (freq >= config.harmonic_freq_threshold * 3U) { + } else if (freq >= FREQ_HARMONICS * 3U) { mul = 5; omul = 7; - } else if (freq >= config.harmonic_freq_threshold) { + } else if (freq >= FREQ_HARMONICS) { 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 *= 64; + ofreq *= 64; } else if (freq <= 4000000U) { rdiv = SI5351_R_DIV_8; + freq *= 8; + ofreq *= 8; + } + /* + * Band 0 + * 1~100MHz fixed PLL = XTALFREQ * PLL_N, fractional divider + * Band 1 + * 100~150MHz fractional PLL = 600- 900MHz, fixed divider 6 + * Band 2 + * 150~300MHz fractional PLL = 600-1200MHz, fixed divider 4 + */ + if ((freq / mul) < 100000000U) { + band = 1; + } else if ((freq / mul) < 150000000U) { + band = 2; + fdiv = 6; + } else { + band = 3; + fdiv = 4; } - -#if 1 - if (current_band != band) - si5351_disable_output(); -#endif - 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 PLL freq at band change, and set CH2 freq = CLK2_FREQUENCY + if (current_band != 1){ + si5351_setupPLL(SI5351_REG_PLL_A, PLL_N, 0, 1); + si5351_setupPLL(SI5351_REG_PLL_B, PLL_N, 0, 1); + si5351_set_frequency_fixedpll(2, SI5351_REG_PLL_B, XTALFREQ * PLL_N, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA); } - - // 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, SI5351_REG_PLL_A, XTALFREQ * PLL_N * omul, ofreq, rdiv, drive_strength); + si5351_set_frequency_fixedpll(1, SI5351_REG_PLL_A, XTALFREQ * PLL_N * mul, freq, rdiv, drive_strength); 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 3: + // Setup CH0 and CH1 constant fdiv divider at change + if (current_band != band){ + si5351_setupMultisynth(0, SI5351_REG_PLL_A, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength); + si5351_setupMultisynth(1, SI5351_REG_PLL_B, fdiv, 0, 1, SI5351_R_DIV_1, drive_strength); + } + // Calculate and set CH0 and CH1 PLL freq + si5351_setupPLL_freq(SI5351_REG_PLL_A, ofreq, fdiv, omul);// set PLLA freq = (ofreq/omul)*fdiv + si5351_setupPLL_freq(SI5351_REG_PLL_B, freq, fdiv, mul);// set PLLB freq = ( freq/ mul)*fdiv + // Calculate CH2 freq = CLK2_FREQUENCY, depend from calculated before CH1 PLLB = (freq/mul)*fdiv + si5351_set_frequency_fixedpll(2, SI5351_REG_PLL_B, (freq/mul)*fdiv, CLK2_FREQUENCY, SI5351_R_DIV_1, SI5351_CLK_DRIVE_STRENGTH_2MA); 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; + delay+=DELAY_BANDCHANGE; } - if (band == 0) - delay += DELAY_LOWBAND; - - current_band = band; return delay; } diff --git a/si5351.h b/si5351.h index 0a10c96..4572dc8 100644 --- a/si5351.h +++ b/si5351.h @@ -17,8 +17,8 @@ * 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_PLL_A 0 +//#define SI5351_PLL_B 1 #define SI5351_MULTISYNTH_DIV_4 4 #define SI5351_MULTISYNTH_DIV_6 6 @@ -33,12 +33,16 @@ #define SI5351_R_DIV_128 (7<<4) #define SI5351_DIVBY4 (3<<2) -#define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3 +#define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3 +#define SI5351_CLK0_EN (1<<0) +#define SI5351_CLK1_EN (1<<2) +#define SI5351_CLK2_EN (1<<3) + #define SI5351_REG_16_CLK0_CONTROL 16 #define SI5351_REG_17_CLK1_CONTROL 17 #define SI5351_REG_18_CLK2_CONTROL 18 -#define SI5351_REG_26_PLL_A 26 -#define SI5351_REG_34_PLL_B 34 +#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 @@ -74,4 +78,7 @@ 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); diff --git a/tlv320aic3204.c b/tlv320aic3204.c index cb86ad5..c1b57b5 100644 --- a/tlv320aic3204.c +++ b/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 */ -// 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 */ + 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 */ - 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 + 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 */ }; -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 */ +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 */ +}; - 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); } diff --git a/ui.c b/ui.c index 681c8bb..562d0dd 100644 --- a/ui.c +++ b/ui.c @@ -25,12 +25,12 @@ //#include #include - 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<= BUTTON_DEBOUNCE_TICKS) { - if (cur_button & (1<= 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<= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) { status |= EVT_UP; } - last_button_down_ticks = ticks; } if (changed & (1<= 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<= 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<= BUTTON_DOWN_LONG_TICKS - && ticks - last_button_repeat_ticks >= BUTTON_REPEAT_TICKS) { - if (cur_button & (1<= last_button_down_ticks + BUTTON_DOWN_LONG_TICKS + && ticks >= last_button_repeat_ticks + BUTTON_REPEAT_TICKS) { + if (cur_button & (1<