Big work around si5351 generator

Improve sweep speed about 60%
Stop generation on pause sweep
Remove all hack for si5351
Reduce code size
Fix integer overflow on big freq values

Additional
Change I2C

Others:
 move marker_tracking variable to ui config
 move some definition to correct place
 reduce tlv320aic3204 code size
 Speedup marker move from lever (BUTTON_REPEAT_TICKS = 625)

Need test stability
This commit is contained in:
DiSlord 2020-03-05 22:36:44 +03:00
parent f1cc60e99e
commit b77e1d6680
7 changed files with 372 additions and 371 deletions

75
main.c
View file

@ -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 = {

View file

@ -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);

1
plot.c
View file

@ -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)

333
si5351.c
View file

@ -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, &reg, 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, pll, div, num, denom, rdiv, drive_strength);
si5351_setupMultisynth(channel, pllSource, div, num, denom, rdiv, drive_strength);
}
static void
si5351_set_frequency_fixeddiv(int channel, int pll, uint32_t freq, int div,
uint8_t drive_strength, int mul)
{
int denom = XTALFREQ * mul;
int64_t pllfreq = (int64_t)freq * div;
int multi = pllfreq / denom;
int num = pllfreq - denom * multi;
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
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;
uint32_t p2 = p0 + a*p1;
p0 = p1; q0 = q1; p1 = p2; q1 = q2;
int new_denom = num - a * denom;
num = denom; denom = new_denom;
num = denom; denom = b;
}
num = p1;
denom = q1;
}
si5351_setupPLL(pll, multi, num, denom);
}
#if 0
static void
si5351_set_frequency_fixeddiv(uint8_t channel, uint32_t pll, uint32_t freq, uint32_t div,
uint8_t drive_strength, uint32_t mul)
{
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;
} else if (freq <= 4000000U) {
rdiv = SI5351_R_DIV_8;
}
#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;
} else if (freq <= 4000000U) {
rdiv = SI5351_R_DIV_8;
freq *= 8;
ofreq *= 8;
}
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;
/*
* 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;
}
switch (band) {
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
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;
}

View file

@ -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
@ -34,11 +34,15 @@
#define SI5351_DIVBY4 (3<<2)
#define SI5351_REG_3_OUTPUT_ENABLE_CONTROL 3
#define SI5351_CLK0_EN (1<<0)
#define SI5351_CLK1_EN (1<<2)
#define SI5351_CLK2_EN (1<<3)
#define SI5351_REG_16_CLK0_CONTROL 16
#define SI5351_REG_17_CLK1_CONTROL 17
#define SI5351_REG_18_CLK2_CONTROL 18
#define SI5351_REG_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);

View file

@ -25,74 +25,78 @@
#define wait_ms(ms) chThdSleepMilliseconds(ms)
static const uint8_t conf_data_pll[] = {
// len, ( reg, data ),
2, 0x00, 0x00, /* Initialize to Page 0 */
2, 0x01, 0x01, /* Initialize the device through software reset */
2, 0x04, 0x43, /* PLL Clock High, MCLK, PLL */
static const uint8_t conf_data[] = {
// reg, data,
// PLL clock config
0x00, 0x00, /* Initialize to Page 0 */
0x01, 0x01, /* Initialize the device through software reset */
0x04, 0x43, /* PLL Clock High, MCLK, PLL */
#ifdef REFCLK_8000KHZ
/* 8.000MHz*10.7520 = 86.016MHz, 86.016MHz/(2*7*128) = 48kHz */
2, 0x05, 0x91, /* Power up PLL, P=1,R=1 */
2, 0x06, 0x0a, /* J=10 */
2, 0x07, 29, /* D=7520 = (29<<8) + 96 */
2, 0x08, 96,
0x05, 0x91, /* Power up PLL, P=1,R=1 */
0x06, 0x0a, /* J=10 */
0x07, 29, /* D=7520 = (29<<8) + 96 */
0x08, 96,
#endif
0 // sentinel
// Clock config, default fs=48kHz
0x0b, 0x82, /* Power up the NDAC divider with value 2 */
0x0c, 0x87, /* Power up the MDAC divider with value 7 */
0x0d, 0x00, /* Program the OSR of DAC to 128 */
0x0e, 0x80,
0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */
//0x3c, 25, /* Set the DAC Mode to PRB_P25 */
0x1b, 0x0c, /* Set the BCLK,WCLK as output */
0x1e, 0x80 + 28, /* Enable the BCLKN divider with value 28 */
0x25, 0xee, /* DAC power up */
0x12, 0x82, /* Power up the NADC divider with value 2 */
0x13, 0x87, /* Power up the MADC divider with value 7 */
0x14, 0x80, /* Program the OSR of ADC to 128 */
0x3d, 0x01, /* Select ADC PRB_R1 */
// Data routing
0x00, 0x01, /* Select Page 1 */
0x01, 0x08, /* Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO*/
0x02, 0x01, /* Enable Master Analog Power Control */
0x7b, 0x01, /* Set the REF charging time to 40ms */
0x14, 0x25, /* HP soft stepping settings for optimal pop performance at power up Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling capacitor. Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound. */
0x0a, 0x33, /* Set the Input Common Mode to 0.9V and Output Common Mode for Headphone to 1.65V */
0x3d, 0x00, /* Select ADC PTM_R4 */
0x47, 0x32, /* Set MicPGA startup delay to 3.1ms */
0x7b, 0x01, /* Set the REF charging time to 40ms */
0x34, 0x10, /* Route IN2L to LEFT_P with 10K */
0x36, 0x10, /* Route IN2R to LEFT_N with 10K */
//0x37, 0x04, /* Route IN3R to RIGHT_P with 10K */
//0x39, 0x04, /* Route IN3L to RIGHT_N with 10K */
//0x3b, 0x00, /* Unmute Left MICPGA, Gain selection of 32dB to make channel gain 0dB */
//0x3c, 0x00, /* Unmute Right MICPGA, Gain selection of 32dB to make channel gain 0dB */
};
// default fs=48kHz
static const uint8_t conf_data_clk[] = {
2, 0x0b, 0x82, /* Power up the NDAC divider with value 2 */
2, 0x0c, 0x87, /* Power up the MDAC divider with value 7 */
2, 0x0d, 0x00, /* Program the OSR of DAC to 128 */
2, 0x0e, 0x80,
2, 0x3c, 0x08, /* Set the DAC Mode to PRB_P8 */
//2, 0x3c, 25, /* Set the DAC Mode to PRB_P25 */
2, 0x1b, 0x0c, /* Set the BCLK,WCLK as output */
2, 0x1e, 0x80 + 28, /* Enable the BCLKN divider with value 28 */
2, 0x25, 0xee, /* DAC power up */
2, 0x12, 0x82, /* Power up the NADC divider with value 2 */
2, 0x13, 0x87, /* Power up the MADC divider with value 7 */
2, 0x14, 0x80, /* Program the OSR of ADC to 128 */
2, 0x3d, 0x01, /* Select ADC PRB_R1 */
0 // sentinel
static const uint8_t conf_data_unmute[] = {
// reg, data,
0x00, 0x00, /* Select Page 0 */
0x51, 0xc0, /* Power up Left and Right ADC Channels */
0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */
};
static const uint8_t conf_data_routing[] = {
2, 0x00, 0x01, /* Select Page 1 */
2, 0x01, 0x08, /* Disable Internal Crude AVdd in presence of external AVdd supply or before powering up internal AVdd LDO*/
2, 0x02, 0x01, /* Enable Master Analog Power Control */
2, 0x7b, 0x01, /* Set the REF charging time to 40ms */
2, 0x14, 0x25, /* HP soft stepping settings for optimal pop performance at power up Rpop used is 6k with N = 6 and soft step = 20usec. This should work with 47uF coupling capacitor. Can try N=5,6 or 7 time constants as well. Trade-off delay vs “pop” sound. */
2, 0x0a, 0x33, /* Set the Input Common Mode to 0.9V and Output Common Mode for Headphone to 1.65V */
2, 0x3d, 0x00, /* Select ADC PTM_R4 */
2, 0x47, 0x32, /* Set MicPGA startup delay to 3.1ms */
2, 0x7b, 0x01, /* Set the REF charging time to 40ms */
2, 0x34, 0x10, /* Route IN2L to LEFT_P with 10K */
2, 0x36, 0x10, /* Route IN2R to LEFT_N with 10K */
2, 0x37, 0x04, /* Route IN3R to RIGHT_P with 10K */
2, 0x39, 0x04, /* Route IN3L to RIGHT_N with 10K */
2, 0x3b, 0, /* Unmute Left MICPGA, Gain selection of 32dB to make channel gain 0dB */
2, 0x3c, 0, /* Unmute Right MICPGA, Gain selection of 32dB to make channel gain 0dB */
0 // sentinel
static const uint8_t conf_data_ch3_select[] = {
// reg, data,
0x00, 0x01, /* Select Page 1 */
0x37, 0x04, /* Route IN3R to RIGHT_P with input impedance of 10K */
0x39, 0x04, /* Route IN3L to RIGHT_N with input impedance of 10K */
};
const uint8_t conf_data_unmute[] = {
2, 0x00, 0x00, /* Select Page 0 */
2, 0x51, 0xc0, /* Power up Left and Right ADC Channels */
2, 0x52, 0x00, /* Unmute Left and Right ADC Digital Volume Control */
0 // sentinel
static const uint8_t conf_data_ch1_select[] = {
// reg, data,
0x00, 0x01, /* Select Page 1 */
0x37, 0x40, /* Route IN1R to RIGHT_P with input impedance of 10K */
0x39, 0x10, /* Route IN1L to RIGHT_N with input impedance of 10K */
};
static void
static inline void
tlv320aic3204_bulk_write(const uint8_t *buf, int len)
{
int addr = AIC3204_ADDR;
i2cAcquireBus(&I2CD1);
(void)i2cMasterTransmitTimeout(&I2CD1, addr, buf, len, NULL, 0, 1000);
i2cReleaseBus(&I2CD1);
(void)i2cMasterTransmitTimeout(&I2CD1, AIC3204_ADDR, buf, len, NULL, 0, 1000);
}
#if 0
@ -109,49 +113,32 @@ tlv320aic3204_read(uint8_t d0)
#endif
static void
tlv320aic3204_config(const uint8_t *data)
tlv320aic3204_config(const uint8_t *data, int len)
{
const uint8_t *p = data;
while (*p) {
uint8_t len = *p++;
tlv320aic3204_bulk_write(p, len);
p += len;
}
i2cAcquireBus(&I2CD1);
for (;len--;data+=2)
tlv320aic3204_bulk_write(data, 2);
i2cReleaseBus(&I2CD1);
}
void tlv320aic3204_init(void)
{
tlv320aic3204_config(conf_data_pll);
tlv320aic3204_config(conf_data_clk);
tlv320aic3204_config(conf_data_routing);
tlv320aic3204_config(conf_data, sizeof(conf_data)/2);
wait_ms(40);
tlv320aic3204_config(conf_data_unmute);
tlv320aic3204_config(conf_data_unmute, sizeof(conf_data_unmute)/2);
}
void tlv320aic3204_select(int channel)
{
const uint8_t ch3[] = {
2, 0x00, 0x01, /* Select Page 1 */
2, 0x37, 0x04, /* Route IN3R to RIGHT_P with input impedance of 10K */
2, 0x39, 0x04, /* Route IN3L to RIGHT_N with input impedance of 10K */
0 // sentinel
};
const uint8_t ch1[] = {
2, 0x00, 0x01, /* Select Page 1 */
2, 0x37, 0x40, /* Route IN1R to RIGHT_P with input impedance of 10K */
2, 0x39, 0x10, /* Route IN1L to RIGHT_N with input impedance of 10K */
0 // sentinel
};
tlv320aic3204_config(channel ? ch1 : ch3);
tlv320aic3204_config(channel ? conf_data_ch1_select : conf_data_ch3_select, sizeof(conf_data_ch3_select)/2);
}
void tlv320aic3204_set_gain(int lgain, int rgain)
{
uint8_t data[] = {
2, 0x00, 0x01, /* Select Page 1 */
2, 0x3b, lgain, /* Unmute Left MICPGA, set gain */
2, 0x3c, rgain, /* Unmute Right MICPGA, set gain */
0 // sentinel
0x00, 0x01, /* Select Page 1 */
0x3b, lgain, /* Unmute Left MICPGA, set gain */
0x3c, rgain, /* Unmute Right MICPGA, set gain */
};
tlv320aic3204_config(data);
tlv320aic3204_config(data, sizeof(data)/2);
}

68
ui.c
View file

@ -25,12 +25,12 @@
//#include <stdlib.h>
#include <string.h>
uistat_t uistat = {
digit: 6,
current_trace: 0,
lever_mode: LM_MARKER,
marker_delta: FALSE,
marker_tracking : FALSE,
};
#define NO_EVENT 0
@ -42,8 +42,8 @@ uistat_t uistat = {
#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_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,8 +131,8 @@ static int btn_check(void)
int status = 0;
uint32_t ticks = chVTGetSystemTime();
if (changed & (1<<BIT_PUSH)) {
if (ticks - last_button_down_ticks >= BUTTON_DEBOUNCE_TICKS) {
if (cur_button & (1<<BIT_PUSH)) {
if ((cur_button & (1<<BIT_PUSH))
&& ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS) {
// button released
status |= EVT_BUTTON_SINGLE_CLICK;
if (inhibit_until_release) {
@ -139,24 +140,20 @@ static int btn_check(void)
inhibit_until_release = FALSE;
}
}
last_button_down_ticks = ticks;
}
}
if (changed & (1<<BIT_UP1)) {
if ((cur_button & (1<<BIT_UP1))
&& (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) {
status |= EVT_UP;
}
last_button_down_ticks = ticks;
}
if (changed & (1<<BIT_DOWN1)) {
if ((cur_button & (1<<BIT_DOWN1))
&& (ticks >= last_button_down_ticks + BUTTON_DEBOUNCE_TICKS)) {
status |= EVT_DOWN;
}
last_button_down_ticks = ticks;
}
last_button_down_ticks = ticks;
last_button = cur_button;
return status;
@ -169,15 +166,14 @@ static int btn_wait_release(void)
int changed = last_button ^ cur_button;
uint32_t ticks = chVTGetSystemTime();
int status = 0;
if (!inhibit_until_release) {
if ((cur_button & (1<<BIT_PUSH))
&& ticks - last_button_down_ticks >= BUTTON_DOWN_LONG_TICKS) {
&& ticks >= last_button_down_ticks + BUTTON_DOWN_LONG_TICKS) {
inhibit_until_release = TRUE;
return EVT_BUTTON_DOWN_LONG;
}
if ((changed & (1<<BIT_PUSH))
&& ticks - last_button_down_ticks < BUTTON_DOWN_LONG_TICKS) {
&& ticks < last_button_down_ticks + BUTTON_DOWN_LONG_TICKS) {
return EVT_BUTTON_SINGLE_CLICK;
}
}
@ -190,14 +186,12 @@ static int btn_wait_release(void)
return 0;
}
if (ticks - last_button_down_ticks >= BUTTON_DOWN_LONG_TICKS
&& ticks - last_button_repeat_ticks >= BUTTON_REPEAT_TICKS) {
if (cur_button & (1<<BIT_DOWN1)) {
if (ticks >= last_button_down_ticks + BUTTON_DOWN_LONG_TICKS
&& ticks >= last_button_repeat_ticks + BUTTON_REPEAT_TICKS) {
if (cur_button & (1<<BIT_DOWN1))
status |= EVT_DOWN | EVT_REPEAT;
}
if (cur_button & (1<<BIT_UP1)) {
if (cur_button & (1<<BIT_UP1))
status |= EVT_UP | EVT_REPEAT;
}
last_button_repeat_ticks = ticks;
return status;
}
@ -776,7 +770,7 @@ menu_marker_search_cb(int item, uint8_t data)
i = marker_search_right(markers[active_marker].index);
break;
case 4: /* tracking */
marker_tracking = !marker_tracking;
uistat.marker_tracking = !uistat.marker_tracking;
break;
}
if (i != -1)
@ -1047,7 +1041,6 @@ const menuitem_t menu_top[] = {
};
#define MENU_STACK_DEPTH_MAX 4
uint8_t menu_current_level = 0;
const menuitem_t *menu_stack[MENU_STACK_DEPTH_MAX] = {
menu_top, NULL, NULL, NULL
};
@ -1171,7 +1164,6 @@ typedef struct {
} keypads_t;
static const keypads_t *keypads;
static uint8_t keypads_last_index;
static const keypads_t keypads_freq[] = {
{ 1, 3, KP_PERIOD },
@ -1345,7 +1337,7 @@ menu_item_modify_attribute(const menuitem_t *menu, int item,
}
}
} else if (menu == menu_marker_search) {
if (item == 4 && marker_tracking) {
if (item == 4 && uistat.marker_tracking) {
*bg = DEFAULT_MENU_TEXT_COLOR;
*fg = config.menu_normal_color;
}
@ -1535,7 +1527,7 @@ fetch_numeric_target(void)
x /= 10;
uistat.digit = n;
}
uistat.previous_value = uistat.value;
// uistat.previous_value = uistat.value;
}
static void
@ -2152,7 +2144,7 @@ touch_lever_mode_select(void)
static
void ui_process_touch(void)
{
awd_count++;
// awd_count++;
adc_stop(ADC1);
int status = touch_check();
@ -2189,14 +2181,10 @@ void ui_process_touch(void)
void
ui_process(void)
{
switch (operation_requested) {
case OP_LEVER:
if (operation_requested&OP_LEVER)
ui_process_lever();
break;
case OP_TOUCH:
if (operation_requested&OP_TOUCH)
ui_process_touch();
break;
}
operation_requested = OP_NONE;
}
@ -2204,7 +2192,7 @@ ui_process(void)
static void extcb1(EXTDriver *extp, expchannel_t channel) {
(void)extp;
(void)channel;
operation_requested = OP_LEVER;
operation_requested|=OP_LEVER;
//cur_button = READ_PORT() & BUTTON_MASK;
}
@ -2259,7 +2247,7 @@ test_touch(int *x, int *y)
void
handle_touch_interrupt(void)
{
operation_requested = OP_TOUCH;
operation_requested|= OP_TOUCH;
}
void