Compare commits

...

12 commits

Author SHA1 Message Date
TT d02db797a7
Merge pull request #144 from czietz/window_loss
Compensate IFFT window / zero-padding loss in TD
2020-11-12 06:02:21 +09:00
Christian Zietz 4d64ef6e48 Compensate IFFT window / zero-padding loss in TD
Depending on the chosen window and mode, the magnitude of the
impulse response in time-domain previously was to low. This can
be explained by looking at the signal processing. For example,
in bandpass mode with normal window, it applies a 101 point Kaiser
window (shape factor 6) and zero-pads to do a 256 point IFFT.
Therefore, the loss is 20*log10(256/sum(kaiser(101,6))) ≈ 14.2 dB.

This change compensates the signal processing losses in bandpass
and lowpass impulse mode depending on the window type, which makes
the time-domain results similar to other VNAs.
2020-10-25 13:34:19 +01:00
TT bc1b57c3f0 feat: add format quality factor 2020-06-20 08:08:21 +09:00
TT 64de4d5d87 fix: add wait in dump command 2020-06-16 08:22:18 +09:00
TT e57292ea01 doc: add ssci to README.md 2020-06-12 05:50:55 +09:00
TT fb57511f9a view: change R+Xj to R+jX in menu label of smith value format 2020-05-16 10:48:50 +09:00
TT 56b0d3ad8a env: insert wait after switching to dfu 2020-05-14 07:20:29 +09:00
TT ba7d358d35 fix: force disable tracking on marker search left/right op 2020-05-14 07:18:59 +09:00
TT d7c7d8faeb feat: add bandwidth command 2020-05-14 07:05:43 +09:00
TT fe7a1ac4de fix: keep freq mode in each save slot 2020-05-14 06:53:52 +09:00
TT 5a10105b1a Merge branch 'bandwidth' 2020-03-21 21:19:53 +09:00
TT 1656342eeb feat: add bandwidth setting of detector 2020-03-21 21:03:08 +09:00
7 changed files with 176 additions and 65 deletions

View file

@ -81,6 +81,10 @@ endif
# Project, sources and paths
#
# Dvice node to flash
DEVICE = /dev/cu.usbmodem401
#DEVICE = /dev/ttyACM0
# Define project name here
PROJECT = ch
@ -225,6 +229,4 @@ flash: build/ch.bin
dfu-util -d 0483:df11 -a 0 -s 0x08000000:leave -D build/ch.bin
dfu:
-@printf "reset dfu\r" >/dev/cu.usbmodem401
-printf "reset dfu\r" >$(DEVICE) && sleep 1

View file

@ -89,7 +89,7 @@ There are seveal numbers of great companion PC tools from third-party.
## Documentation
* [NanoVNA User Guide](https://cho45.github.io/NanoVNA-manual/) [(google translate)](https://translate.google.com/translate?sl=ja&tl=en&u=https%3A%2F%2Fcho45.github.io%2FNanoVNA-manual%2F) by cho45
* [NanoVNA User Guide(ja)](https://cho45.github.io/NanoVNA-manual/) by cho45. [(en:google translate)](https://translate.google.com/translate?sl=ja&tl=en&u=https%3A%2F%2Fcho45.github.io%2FNanoVNA-manual%2F)
## Reference
@ -105,6 +105,7 @@ Hardware design material is disclosed to prevent bad quality clone. Please let m
## Authorized Distributor
* [Nooelec](https://www.nooelec.com/store/nanovna-bundle.html)
* Switch Science(ja) [NanoVNA-H](https://www.switch-science.com/catalog/6405/) [NanoVNA-H4](https://www.switch-science.com/catalog/6406/)
## Credit

16
dsp.c
View file

@ -41,10 +41,10 @@ const int16_t sincos_tbl[48][2] = {
{-24636, -21605 }, {-32698, -2143 }, {-27246, 18205 }, {-10533, 31029 }
};
int32_t acc_samp_s;
int32_t acc_samp_c;
int32_t acc_ref_s;
int32_t acc_ref_c;
float acc_samp_s;
float acc_samp_c;
float acc_ref_s;
float acc_ref_c;
void
dsp_process(int16_t *capture, size_t length)
@ -79,10 +79,10 @@ dsp_process(int16_t *capture, size_t length)
ref_c = __SMLATT(sr, sc, ref_c);
#endif
}
acc_samp_s = samp_s;
acc_samp_c = samp_c;
acc_ref_s = ref_s;
acc_ref_c = ref_c;
acc_samp_s += samp_s;
acc_samp_c += samp_c;
acc_ref_s += ref_s;
acc_ref_c += ref_c;
}
void

139
main.c
View file

@ -198,40 +198,54 @@ transform_domain(void)
// and calculate ifft for time domain
float* tmp = (float*)spi_buffer;
// correct IFFT window and zero-padding loss
// assuming a 2*POINT_COUNT window
float wincorr = 1.0f;
float beta = 0.0;
switch (domain_mode & TD_WINDOW) {
case TD_WINDOW_MINIMUM:
beta = 0.0; // this is rectangular
// loss by zero-padding 202 to 256 points
wincorr = (float)FFT_SIZE / (float)(2*POINTS_COUNT);
break;
case TD_WINDOW_NORMAL:
beta = 6.0;
// additional window loss: 1/mean(kaiser(202,6)) = 2.01
wincorr = (float)FFT_SIZE / (float)(2*POINTS_COUNT) * 2.01f;
break;
case TD_WINDOW_MAXIMUM:
beta = 13;
// additional window loss: 1/mean(kaiser(202,13)) = 2.92
wincorr = (float)FFT_SIZE / (float)(2*POINTS_COUNT) * 2.92f;
break;
}
uint8_t window_size = POINTS_COUNT, offset = 0;
uint8_t is_lowpass = FALSE;
switch (domain_mode & TD_FUNC) {
case TD_FUNC_BANDPASS:
offset = 0;
window_size = POINTS_COUNT;
// window size is half the size as assumed above => twice the IFFT loss
wincorr *= 2.0f;
break;
case TD_FUNC_LOWPASS_IMPULSE:
case TD_FUNC_LOWPASS_STEP:
// no IFFT losses need to be considered to calculate the step response
wincorr = 1.0f;
// fall-through
case TD_FUNC_LOWPASS_IMPULSE:
is_lowpass = TRUE;
offset = POINTS_COUNT;
window_size = POINTS_COUNT * 2;
break;
}
float beta = 0.0;
switch (domain_mode & TD_WINDOW) {
case TD_WINDOW_MINIMUM:
beta = 0.0; // this is rectangular
break;
case TD_WINDOW_NORMAL:
beta = 6.0;
break;
case TD_WINDOW_MAXIMUM:
beta = 13;
break;
}
for (int ch = 0; ch < 2; ch++) {
memcpy(tmp, measured[ch], sizeof(measured[0]));
for (int i = 0; i < POINTS_COUNT; i++) {
float w = kaiser_window(i + offset, window_size, beta);
tmp[i * 2 + 0] *= w;
tmp[i * 2 + 1] *= w;
tmp[i * 2 + 0] *= w * wincorr;
tmp[i * 2 + 1] *= w * wincorr;
}
for (int i = POINTS_COUNT; i < FFT_SIZE; i++) {
tmp[i * 2 + 0] = 0.0;
@ -584,10 +598,34 @@ int16_t dump_buffer[AUDIO_BUFFER_LEN];
int16_t dump_selection = 0;
#endif
volatile int16_t wait_count = 0;
volatile uint8_t wait_count = 0;
volatile uint8_t accumerate_count = 0;
const int8_t bandwidth_accumerate_count[] = {
1, // 1kHz
3, // 300Hz
10, // 100Hz
33, // 30Hz
100 // 10Hz
};
float measured[2][POINTS_COUNT][2];
static inline void
dsp_start(int count)
{
wait_count = count;
accumerate_count = bandwidth_accumerate_count[bandwidth];
reset_dsp_accumerator();
}
static inline void
dsp_wait(void)
{
while (accumerate_count > 0)
__WFI();
}
#ifdef ENABLED_DUMP
static void
duplicate_buffer_to_dump(int16_t *p)
@ -610,13 +648,16 @@ void i2s_end_callback(I2SDriver *i2sp, size_t offset, size_t n)
(void)i2sp;
(void)n;
if (wait_count > 0) {
if (wait_count == 1)
dsp_process(p, n);
#ifdef ENABLED_DUMP
duplicate_buffer_to_dump(p);
#endif
if (wait_count > 1) {
--wait_count;
} else if (wait_count > 0) {
if (accumerate_count > 0) {
dsp_process(p, n);
accumerate_count--;
}
#ifdef ENABLED_DUMP
duplicate_buffer_to_dump(p);
#endif
}
#if PORT_SUPPORTS_RT
@ -668,7 +709,8 @@ VNA_SHELL_FUNCTION(cmd_dump)
if (argc == 1)
dump_selection = my_atoi(argv[0]);
wait_dsp(3);
dsp_start(3);
dsp_wait();
len = AUDIO_BUFFER_LEN;
if (dump_selection == 1 || dump_selection == 2)
@ -752,7 +794,6 @@ config_t config = {
.trace_color = { DEFAULT_TRACE_1_COLOR, DEFAULT_TRACE_2_COLOR, DEFAULT_TRACE_3_COLOR, DEFAULT_TRACE_4_COLOR },
// .touch_cal = { 693, 605, 124, 171 }, // 2.4 inch LCD panel
.touch_cal = { 338, 522, 153, 192 }, // 2.8 inch LCD panel
.freq_mode = FREQ_MODE_START_STOP,
.harmonic_freq_threshold = 300000000,
.vbat_offset = 500
};
@ -792,6 +833,8 @@ void load_default_properties(void)
current_props._active_marker = 0;
current_props._domain_mode = 0;
current_props._marker_smith_format = MS_RLC;
current_props._freq_mode = FREQ_MODE_START_STOP;
//Checksum add on caldata_save
//current_props.checksum = 0;
}
@ -808,9 +851,6 @@ ensure_edit_config(void)
cal_status = 0;
}
#define DSP_START(delay) wait_count = delay;
#define DSP_WAIT_READY while (wait_count) __WFI();
#define DELAY_CHANNEL_CHANGE 2
// main loop for measurement
@ -824,20 +864,20 @@ bool sweep(bool break_on_operation)
if (frequencies[i] == 0) break;
delay = set_frequency(frequencies[i]); // 700
tlv320aic3204_select(0); // 60 CH0:REFLECT, reset and begin measure
DSP_START(delay + ((i == 0) ? 1 : 0)); // 1900
dsp_start(delay + ((i == 0) ? 1 : 0)); // 1900
//================================================
// Place some code thats need execute while delay
//================================================
DSP_WAIT_READY;
dsp_wait();
// calculate reflection coefficient
(*sample_func)(measured[0][i]); // 60
tlv320aic3204_select(1); // 60 CH1:TRANSMISSION, reset and begin measure
DSP_START(DELAY_CHANNEL_CHANGE); // 1700
dsp_start(DELAY_CHANNEL_CHANGE); // 1700
//================================================
// Place some code thats need execute while delay
//================================================
DSP_WAIT_READY;
dsp_wait();
// calculate transmission coefficient
(*sample_func)(measured[1][i]); // 60
// ======== 170 ===========
@ -979,7 +1019,7 @@ set_sweep_frequency(int type, uint32_t freq)
ensure_edit_config();
switch (type) {
case ST_START:
config.freq_mode &= ~FREQ_MODE_CENTER_SPAN;
freq_mode &= ~FREQ_MODE_CENTER_SPAN;
if (frequency0 != freq) {
frequency0 = freq;
// if start > stop then make start = stop
@ -987,7 +1027,7 @@ set_sweep_frequency(int type, uint32_t freq)
}
break;
case ST_STOP:
config.freq_mode &= ~FREQ_MODE_CENTER_SPAN;
freq_mode &= ~FREQ_MODE_CENTER_SPAN;
if (frequency1 != freq) {
frequency1 = freq;
// if start > stop then make start = stop
@ -995,7 +1035,7 @@ set_sweep_frequency(int type, uint32_t freq)
}
break;
case ST_CENTER:
config.freq_mode |= FREQ_MODE_CENTER_SPAN;
freq_mode |= FREQ_MODE_CENTER_SPAN;
uint32_t center = frequency0 / 2 + frequency1 / 2;
if (center != freq) {
uint32_t span = frequency1 - frequency0;
@ -1010,7 +1050,7 @@ set_sweep_frequency(int type, uint32_t freq)
}
break;
case ST_SPAN:
config.freq_mode |= FREQ_MODE_CENTER_SPAN;
freq_mode |= FREQ_MODE_CENTER_SPAN;
if (frequency1 - frequency0 != freq) {
uint32_t center = frequency0 / 2 + frequency1 / 2;
if (center < START_MIN + freq / 2) {
@ -1024,7 +1064,7 @@ set_sweep_frequency(int type, uint32_t freq)
}
break;
case ST_CW:
config.freq_mode |= FREQ_MODE_CENTER_SPAN;
freq_mode |= FREQ_MODE_CENTER_SPAN;
if (frequency0 != freq || frequency1 != freq) {
frequency0 = freq;
frequency1 = freq;
@ -1524,7 +1564,8 @@ static const struct {
{ "REAL", NGRIDY/2, 0.25 },
{ "IMAG", NGRIDY/2, 0.25 },
{ "R", NGRIDY/2, 100.0 },
{ "X", NGRIDY/2, 100.0 }
{ "X", NGRIDY/2, 100.0 },
{ "Q", 0, 10.0 }
};
static const char * const trc_channel_name[] = {
@ -1628,8 +1669,8 @@ VNA_SHELL_FUNCTION(cmd_trace)
#if MAX_TRACE_TYPE != 12
#error "Trace type enum possibly changed, check cmd_trace function"
#endif
// enum TRC_LOGMAG, TRC_PHASE, TRC_DELAY, TRC_SMITH, TRC_POLAR, TRC_LINEAR, TRC_SWR, TRC_REAL, TRC_IMAG, TRC_R, TRC_X, TRC_OFF
static const char cmd_type_list[] = "logmag|phase|delay|smith|polar|linear|swr|real|imag|r|x|off";
// enum TRC_LOGMAG, TRC_PHASE, TRC_DELAY, TRC_SMITH, TRC_POLAR, TRC_LINEAR, TRC_SWR, TRC_REAL, TRC_IMAG, TRC_R, TRC_X, TRC_Q, TRC_OFF
static const char cmd_type_list[] = "logmag|phase|delay|smith|polar|linear|swr|real|imag|r|x|q|off";
int type = get_str_index(argv[1], cmd_type_list);
if (type >= 0) {
set_trace_type(t, type);
@ -1921,6 +1962,23 @@ VNA_SHELL_FUNCTION(cmd_port)
tlv320aic3204_select(port);
}
VNA_SHELL_FUNCTION(cmd_bandwidth)
{
if (argc != 1)
goto usage;
static const char bw_choice[] = "1000|300|100|30|10";
int i = get_str_index(argv[0], bw_choice);
if (i < 0)
goto usage;
bandwidth = i;
return;
usage:
shell_printf("usage: bandwidth {%s}\r\n", bw_choice);
}
VNA_SHELL_FUNCTION(cmd_stat)
{
int16_t *p = &rx_buffer[0];
@ -2109,6 +2167,7 @@ static const VNAShellCommand commands[] =
{"dump" , cmd_dump , 0},
#endif
{"frequencies" , cmd_frequencies , 0},
{"bandwidth" , cmd_bandwidth , 0},
{"port" , cmd_port , 0},
{"stat" , cmd_stat , 0},
{"gain" , cmd_gain , 0},

View file

@ -194,10 +194,10 @@ extern const uint16_t numfont16x22[];
#define MAX_TRACE_TYPE 12
enum trace_type {
TRC_LOGMAG=0, TRC_PHASE, TRC_DELAY, TRC_SMITH, TRC_POLAR, TRC_LINEAR, TRC_SWR, TRC_REAL, TRC_IMAG, TRC_R, TRC_X, TRC_OFF
TRC_LOGMAG=0, TRC_PHASE, TRC_DELAY, TRC_SMITH, TRC_POLAR, TRC_LINEAR, TRC_SWR, TRC_REAL, TRC_IMAG, TRC_R, TRC_X, TRC_Q, TRC_OFF
};
// Mask for define rectangular plot
#define RECTANGULAR_GRID_MASK ((1<<TRC_LOGMAG)|(1<<TRC_PHASE)|(1<<TRC_DELAY)|(1<<TRC_LINEAR)|(1<<TRC_SWR)|(1<<TRC_REAL)|(1<<TRC_IMAG)|(1<<TRC_R)|(1<<TRC_X))
#define RECTANGULAR_GRID_MASK ((1<<TRC_LOGMAG)|(1<<TRC_PHASE)|(1<<TRC_DELAY)|(1<<TRC_LINEAR)|(1<<TRC_SWR)|(1<<TRC_REAL)|(1<<TRC_IMAG)|(1<<TRC_R)|(1<<TRC_X)|(1<<TRC_Q))
// LOGMAG: SCALE, REFPOS, REFVAL
// PHASE: SCALE, REFPOS, REFVAL
@ -230,7 +230,6 @@ typedef struct config {
uint16_t menu_active_color;
uint16_t trace_color[TRACES_MAX];
int16_t touch_cal[4];
int8_t freq_mode;
uint32_t harmonic_freq_threshold;
uint16_t vbat_offset;
uint8_t _reserved[22];
@ -379,7 +378,9 @@ typedef struct properties {
int8_t _active_marker;
uint8_t _domain_mode; /* 0bxxxxxffm : where ff: TD_FUNC m: DOMAIN_MODE */
uint8_t _marker_smith_format;
uint8_t _reserved[50];
uint8_t _bandwidth;
int8_t _freq_mode;
uint8_t _reserved[49];
uint32_t checksum;
} properties_t;
@ -405,9 +406,11 @@ extern properties_t current_props;
#define domain_mode current_props._domain_mode
#define velocity_factor current_props._velocity_factor
#define marker_smith_format current_props._marker_smith_format
#define bandwidth current_props._bandwidth
#define freq_mode current_props._freq_mode
#define FREQ_IS_STARTSTOP() (!(config.freq_mode&FREQ_MODE_CENTER_SPAN))
#define FREQ_IS_CENTERSPAN() (config.freq_mode&FREQ_MODE_CENTER_SPAN)
#define FREQ_IS_STARTSTOP() (!(freq_mode & FREQ_MODE_CENTER_SPAN))
#define FREQ_IS_CENTERSPAN() (freq_mode & FREQ_MODE_CENTER_SPAN)
#define FREQ_IS_CW() (frequency0 == frequency1)
int caldata_save(int id);

21
plot.c
View file

@ -491,6 +491,14 @@ reactance(const float *v)
return zi;
}
static float
qualityfactor(const float *v)
{
float i = 2*v[1];
float r = (1+v[0])*(1-v[0]) - v[1]*v[1];
return fabs(i / r);
}
static void
cartesian_scale(float re, float im, int *xp, int *yp, float scale)
{
@ -567,6 +575,9 @@ trace_into_index(int t, int i, float array[POINTS_COUNT][2])
case TRC_X:
v-= reactance(coeff) * scale;
break;
case TRC_Q:
v-= qualityfactor(coeff) * scale;
break;
case TRC_SMITH:
//case TRC_ADMIT:
case TRC_POLAR:
@ -610,7 +621,7 @@ format_smith_value(char *buf, int len, const float coeff[2], uint32_t frequency)
break;
case MS_RX:
plot_printf(buf, len, "%F"S_OHM"%+Fj", zr, zi);
plot_printf(buf, len, "%F%+Fj"S_OHM, zr, zi);
break;
case MS_RLC:
@ -669,6 +680,10 @@ trace_get_value_string(int t, char *buf, int len, float array[POINTS_COUNT][2],
format = "%.2F"S_OHM;
v = gamma2reactance(coeff);
break;
case TRC_Q:
format = "%.1f";
v = qualityfactor(coeff);
break;
case TRC_SMITH:
format_smith_value(buf, len, coeff, frequencies[i]);
return;
@ -729,6 +744,10 @@ trace_get_value_string_delta(int t, char *buf, int len, float array[POINTS_COUNT
format = "%.2F"S_OHM;
v = gamma2reactance(coeff);
break;
case TRC_Q:
format = "%.1f";
v = qualityfactor(coeff);
break;
//case TRC_ADMIT:
case TRC_POLAR:
plot_printf(buf, len, "%.2f%+.2fj", coeff[0], coeff[1]);

39
ui.c
View file

@ -631,7 +631,14 @@ menu_transform_filter_cb(int item, uint8_t data)
ui_mode_normal();
}
static void
static void
menu_bandwidth_cb(int item)
{
bandwidth = item;
draw_menu();
}
static void
choose_active_marker(void)
{
int i;
@ -761,9 +768,11 @@ menu_marker_search_cb(int item, uint8_t data)
break;
case 2: /* search Left */
i = marker_search_left(markers[active_marker].index);
uistat.marker_tracking = false;
break;
case 3: /* search right */
i = marker_search_right(markers[active_marker].index);
uistat.marker_tracking = false;
break;
case 4: /* tracking */
uistat.marker_tracking = !uistat.marker_tracking;
@ -877,6 +886,7 @@ const menuitem_t menu_format2[] = {
{ MT_CALLBACK, TRC_IMAG, "IMAG", menu_format_cb },
{ MT_CALLBACK, TRC_R, "RESISTANCE", menu_format_cb },
{ MT_CALLBACK, TRC_X, "REACTANCE", menu_format_cb },
{ MT_CALLBACK, TRC_Q, "Q FACTOR", menu_format_cb },
{ MT_CANCEL, 0, S_LARROW" BACK", NULL },
{ MT_NONE, 0, NULL, NULL } // sentinel
};
@ -928,12 +938,23 @@ const menuitem_t menu_transform[] = {
{ MT_NONE, 0, NULL, NULL } // sentinel
};
const menuitem_t menu_bandwidth[] = {
{ MT_CALLBACK, 0, "1 kHz", menu_bandwidth_cb },
{ MT_CALLBACK, 0, "300 Hz", menu_bandwidth_cb },
{ MT_CALLBACK, 0, "100 Hz", menu_bandwidth_cb },
{ MT_CALLBACK, 0, "30 Hz", menu_bandwidth_cb },
{ MT_CALLBACK, 0, "10 Hz", menu_bandwidth_cb },
{ MT_CANCEL, 0, S_LARROW" BACK", NULL },
{ MT_NONE, 0, NULL, NULL } // sentinel
};
const menuitem_t menu_display[] = {
{ MT_SUBMENU, 0, "TRACE", menu_trace },
{ MT_SUBMENU, 0, "FORMAT", menu_format },
{ MT_SUBMENU, 0, "SCALE", menu_scale },
{ MT_SUBMENU, 0, "CHANNEL", menu_channel },
{ MT_SUBMENU, 0, "TRANSFORM", menu_transform },
{ MT_SUBMENU, 0, "BANDWIDTH", menu_bandwidth },
{ MT_CANCEL, 0, S_LARROW" BACK", NULL },
{ MT_NONE, 0, NULL, NULL } // sentinel
};
@ -985,7 +1006,7 @@ const menuitem_t menu_marker_smith[] = {
{ MT_CALLBACK, MS_LIN, "LIN", menu_marker_smith_cb },
{ MT_CALLBACK, MS_LOG, "LOG", menu_marker_smith_cb },
{ MT_CALLBACK, MS_REIM,"Re+Im", menu_marker_smith_cb },
{ MT_CALLBACK, MS_RX, "R+Xj", menu_marker_smith_cb },
{ MT_CALLBACK, MS_RX, "R+jX", menu_marker_smith_cb },
{ MT_CALLBACK, MS_RLC, "R+L/C", menu_marker_smith_cb },
{ MT_CANCEL, 0, S_LARROW" BACK", NULL },
{ MT_NONE, 0, NULL, NULL } // sentinel
@ -1120,6 +1141,7 @@ menu_invoke(int item)
#define MENU_BUTTON_WIDTH 60
#define MENU_BUTTON_HEIGHT 30
#define MENU_BUTTON_MAX 8
#define NUM_INPUT_HEIGHT 30
#define KP_WIDTH 48
@ -1365,6 +1387,11 @@ menu_item_modify_attribute(const menuitem_t *menu, int item,
*bg = DEFAULT_MENU_TEXT_COLOR;
*fg = config.menu_normal_color;
}
} else if (menu == menu_bandwidth) {
if (item == bandwidth) {
*bg = 0x0000;
*fg = 0xffff;
}
} else if (menu == menu_transform) {
if ((item == 0 && (domain_mode & DOMAIN_MODE) == DOMAIN_TIME)
|| (item == 1 && (domain_mode & TD_FUNC) == TD_FUNC_LOWPASS_IMPULSE)
@ -1389,7 +1416,7 @@ static void
draw_menu_buttons(const menuitem_t *menu)
{
int i = 0;
for (i = 0; i < 7; i++) {
for (i = 0; i < MENU_BUTTON_MAX; i++) {
const char *l1, *l2;
if (menu[i].type == MT_NONE)
break;
@ -1435,7 +1462,7 @@ menu_apply_touch(void)
int i;
touch_position(&touch_x, &touch_y);
for (i = 0; i < 7; i++) {
for (i = 0; i < MENU_BUTTON_MAX; i++) {
if (menu[i].type == MT_NONE)
break;
if (menu[i].type == MT_BLANK)
@ -1460,7 +1487,7 @@ draw_menu(void)
static void
erase_menu_buttons(void)
{
ili9341_fill(320-MENU_BUTTON_WIDTH, 0, MENU_BUTTON_WIDTH, MENU_BUTTON_HEIGHT*7, DEFAULT_BG_COLOR);
ili9341_fill(320-MENU_BUTTON_WIDTH, 0, MENU_BUTTON_WIDTH, MENU_BUTTON_HEIGHT * MENU_BUTTON_MAX, DEFAULT_BG_COLOR);
}
static void
@ -1478,8 +1505,8 @@ leave_ui_mode()
} else if (ui_mode == UI_NUMERIC) {
request_to_draw_cells_behind_numeric_input();
erase_numeric_input();
draw_frequencies();
}
draw_frequencies();
}
static void