From 02a5715bb49037319a4eb7ba693e4076c5db0c77 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 22 Feb 2020 10:50:54 +0300 Subject: [PATCH] Big code redisign (increase CELL draw size, more faster screen render), also save about 4-5kB flash size Try remove all hardcoded values from code (use definition if set) Some error fix main.c: Rewrite Shell, now it run on main thread and require less RAM (not need stack) (possible run it as thread if define VNA_SHELL_THREAD Remove not used trace_info[].scale_unit in set_trace_scale/get_trace_scale (it just divede on set and multiple on get, better use it for default scale set) Replace some hardcoded values MARKERS_MAX SAVEAREA_MAX TRACES_MAX plot.c Rewrite CELLWIDTH and CELLHEIGHT use, now possible set any CELL width and height (CELLWIDTH * CELLHEIGHT <= spi_buffer size) Free RAM from shell stack use fore increase spi_buffer size now it have 2048 pixel (64x32) Rewrite cell index and markmap use (now correct use cell size, and more faster), correct use CELLWIDTH and CELLHEIGHT in calculation Fore set update area use invalidateRect (still need use some hardcoded values :( ) Rewrite cell_draw_line Rewrite many hardcoded size definitions Refrence point now draw as bitmap (less size, more costumable) Fix drag marker (now correct search closest index in search_nearest_index) Rewrite plot_into_index, now correct use size definitions, moe ui.c Small rewrite keyboard definitions, for use less flash size Define KP_WIDTH, KP_HEIGHT for set key size Better look some big font symvols All: use static fore some local functions (use less space on calls) replace tabs on spaces (code style) Use M_PI from math.h fore define pi value Fix printf on print HEX values --- chprintf.c | 2 +- ili9341.c | 39 ++- main.c | 604 +++++++++++++++++++++------------ nanovna.h | 39 ++- numfont20x22.c | 70 ++-- plot.c | 879 +++++++++++++++++++++++-------------------------- ui.c | 387 +++++++++++----------- 7 files changed, 1065 insertions(+), 955 deletions(-) diff --git a/chprintf.c b/chprintf.c index 8c75b29..6ba7efd 100644 --- a/chprintf.c +++ b/chprintf.c @@ -64,7 +64,7 @@ static char *long_to_string_with_divisor(char *p, do { uint8_t c = num % radix; num /= radix; - *--q = c + ((c > 9) ? 'A' : '0'); + *--q = c + ((c > 9) ? ('A'-10) : '0'); }while((precision && --precision) || num); // copy string at begin int i = (int)(b - q); diff --git a/ili9341.c b/ili9341.c index 12edc9c..e134025 100644 --- a/ili9341.c +++ b/ili9341.c @@ -21,7 +21,7 @@ #include "hal.h" #include "nanovna.h" -uint16_t spi_buffer[1024]; +uint16_t spi_buffer[2048]; // Default foreground & background colors uint16_t foreground_color=DEFAULT_FG_COLOR; uint16_t background_color=DEFAULT_BG_COLOR; @@ -568,10 +568,34 @@ void ili9341_drawstring_size(const char *str, int x, int y, uint8_t size) while (*str) x += ili9341_drawchar_size(*str++, x, y, size); } +#if 0 +static void ili9341_pixel(int x, int y, uint16_t color) +{ + uint32_t xx = __REV16(x|((x)<<16)); + uint32_t yy = __REV16(y|((y)<<16)); + send_command(ILI9341_COLUMN_ADDRESS_SET, 4, (uint8_t*)&xx); + send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t*)&yy); + send_command(ILI9341_MEMORY_WRITE, 2, &color); +} +#endif #define SWAP(x,y) { int z=x; x = y; y = z; } void ili9341_line(int x0, int y0, int x1, int y1) { +#if 0 + // modifed Bresenham's line algorithm, see https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm + int dx = x1 - x0, sx = 1; if (dx < 0) {dx = -dx; sx = -1;} + int dy = y1 - y0, sy = 1; if (dy < 0) {dy = -dy; sy = -1;} + int err = (dx > dy ? dx : -dy) / 2; + while (1){ + ili9341_pixel(x0, y0, DEFAULT_FG_COLOR); + if (x0 == x1 && y0 == y1) + break; + int e2 = err; + if (e2 > -dx) { err -= dy; x0 += sx; } + if (e2 < dy) { err += dx; y0 += sy; } + } +#endif if (x0 > x1) { SWAP(x0, x1); @@ -611,20 +635,8 @@ static const uint16_t colormap[] = { RGBHEX(0x00ffff), RGBHEX(0xff00ff), RGBHEX(0xffff00) }; -static void ili9341_pixel(int x, int y, int color) -{ - uint8_t xx[4] = { x >> 8, x, (x+1) >> 8, (x+1) }; - uint8_t yy[4] = { y >> 8, y, (y+1) >> 8, (y+1) }; - uint8_t cc[2] = { color >> 8, color }; - send_command(ILI9341_COLUMN_ADDRESS_SET, 4, xx); - send_command(ILI9341_PAGE_ADDRESS_SET, 4, yy); - send_command(ILI9341_MEMORY_WRITE, 2, cc); - //send_command16(ILI9341_MEMORY_WRITE, color); -} - void ili9341_test(int mode) { - chMtxLock(&mutex_ili9341); int x, y; int i; switch (mode) { @@ -666,6 +678,5 @@ void ili9341_test(int mode) ili9341_line(0, 100, 100, 0); break; } - chMtxUnlock(&mutex_ili9341); } #endif diff --git a/main.c b/main.c index 795d187..1a06fa7 100644 --- a/main.c +++ b/main.c @@ -26,13 +26,34 @@ #include "fft.h" #include -#include -#include +//#include #include -#include +//#include #include +/* + * Shell settings + */ +// If need run shell as thread (use more amount of memory fore stack), after enable this need reduce spi_buffer size, by default shell run in main thread +//#define VNA_SHELL_THREAD + +static BaseSequentialStream *shell_stream = (BaseSequentialStream *)&SDU1; + +// Shell new line +#define VNA_SHELL_NEWLINE_STR "\r\n" +// Shell command promt +#define VNA_SHELL_PROMPT_STR "ch> " +// Shell max arguments +#define VNA_SHELL_MAX_ARGUMENTS 4 +// Shell max command line size +#define VNA_SHELL_MAX_LENGTH 64 +// Shell command functions prototypes +typedef void (*vna_shellcmd_t)(BaseSequentialStream *chp, int argc, char *argv[]); +#define VNA_SHELL_FUNCTION(command_name) static void command_name(BaseSequentialStream *chp, int argc, char *argv[]) + //#define ENABLED_DUMP +//#define ENABLE_THREADS_COMMAND + static void apply_error_term_at(int i); static void apply_edelay_at(int i); @@ -124,30 +145,30 @@ toggle_sweep(void) sweep_enabled = !sweep_enabled; } -float bessel0(float x) { - const float eps = 0.0001; +static float +bessel0(float x) { + const float eps = 0.0001; - float ret = 0; - float term = 1; - float m = 0; + float ret = 0; + float term = 1; + float m = 0; - while (term > eps * ret) { - ret += term; - ++m; - term *= (x*x) / (4*m*m); - } - - return ret; + while (term > eps * ret) { + ret += term; + ++m; + term *= (x*x) / (4*m*m); + } + return ret; } -float kaiser_window(float k, float n, float beta) { - if (beta == 0.0) return 1.0; - float r = (2 * k) / (n - 1) - 1; - return bessel0(beta * sqrt(1 - r * r)) / bessel0(beta); +static float +kaiser_window(float k, float n, float beta) { + if (beta == 0.0) return 1.0; + float r = (2 * k) / (n - 1) - 1; + return bessel0(beta * sqrt(1 - r * r)) / bessel0(beta); } -static -void +static void transform_domain(void) { if ((domain_mode & DOMAIN_MODE) != DOMAIN_TIME) return; // nothing to do for freq domain @@ -220,6 +241,16 @@ transform_domain(void) } } +// Shell commands output +static int shell_printf(BaseSequentialStream *chp, const char *fmt, ...) { + va_list ap; + int formatted_bytes; + va_start(ap, fmt); + formatted_bytes = chvprintf(chp, fmt, ap); + va_end(ap); + return formatted_bytes; +} + static void cmd_pause(BaseSequentialStream *chp, int argc, char *argv[]) { (void)chp; @@ -249,13 +280,13 @@ static void cmd_reset(BaseSequentialStream *chp, int argc, char *argv[]) if (argc == 1) { if (strcmp(argv[0], "dfu") == 0) { - chprintf(chp, "Performing reset to DFU mode\r\n"); + shell_printf(chp, "Performing reset to DFU mode\r\n"); enter_dfu(); return; } } - chprintf(chp, "Performing reset\r\n"); + shell_printf(chp, "Performing reset\r\n"); rccEnableWWDG(FALSE); @@ -312,7 +343,7 @@ int set_frequency(uint32_t freq) // Rewrite universal standart str to value functions to more compact // // Convert string to int32 -int32_t my_atoi(const char *p){ +static int32_t my_atoi(const char *p){ int32_t value = 0; uint32_t c; bool neg = false; @@ -374,7 +405,7 @@ my_atof(const char *p) static void cmd_offset(BaseSequentialStream *chp, int argc, char *argv[]) { if (argc != 1) { - chprintf(chp, "usage: offset {frequency offset(Hz)}\r\n"); + shell_printf(chp, "usage: offset {frequency offset(Hz)}\r\n"); return; } frequency_offset = my_atoui(argv[0]); @@ -394,13 +425,13 @@ static void cmd_freq(BaseSequentialStream *chp, int argc, char *argv[]) chMtxUnlock(&mutex); return; usage: - chprintf(chp, "usage: freq {frequency(Hz)}\r\n"); + shell_printf(chp, "usage: freq {frequency(Hz)}\r\n"); } static void cmd_power(BaseSequentialStream *chp, int argc, char *argv[]) { if (argc != 1) { - chprintf(chp, "usage: power {0-3|-1}\r\n"); + shell_printf(chp, "usage: power {0-3|-1}\r\n"); return; } drive_strength = my_atoi(argv[0]); @@ -413,7 +444,7 @@ static void cmd_time(BaseSequentialStream *chp, int argc, char *argv[]) (void)argc; (void)argv; rtcGetTime(&RTCD1, ×pec); - chprintf(chp, "%d/%d/%d %d\r\n", timespec.year+1980, timespec.month, timespec.day, timespec.millisecond); + shell_printf(chp, "%d/%d/%d %d\r\n", timespec.year+1980, timespec.month, timespec.day, timespec.millisecond); } @@ -421,8 +452,8 @@ static void cmd_dac(BaseSequentialStream *chp, int argc, char *argv[]) { int value; if (argc != 1) { - chprintf(chp, "usage: dac {value(0-4095)}\r\n"); - chprintf(chp, "current value: %d\r\n", config.dac_value); + shell_printf(chp, "usage: dac {value(0-4095)}\r\n"\ + "current value: %d\r\n", config.dac_value); return; } value = my_atoi(argv[0]); @@ -434,8 +465,8 @@ static void cmd_threshold(BaseSequentialStream *chp, int argc, char *argv[]) { uint32_t value; if (argc != 1) { - chprintf(chp, "usage: threshold {frequency in harmonic mode}\r\n"); - chprintf(chp, "current: %d\r\n", config.harmonic_freq_threshold); + shell_printf(chp, "usage: threshold {frequency in harmonic mode}\r\n"\ + "current: %d\r\n", config.harmonic_freq_threshold); return; } value = my_atoui(argv[0]); @@ -447,24 +478,24 @@ static void cmd_saveconfig(BaseSequentialStream *chp, int argc, char *argv[]) (void)argc; (void)argv; config_save(); - chprintf(chp, "Config saved.\r\n"); + shell_printf(chp, "Config saved.\r\n"); } static void cmd_clearconfig(BaseSequentialStream *chp, int argc, char *argv[]) { if (argc != 1) { - chprintf(chp, "usage: clearconfig {protection key}\r\n"); + shell_printf(chp, "usage: clearconfig {protection key}\r\n"); return; } if (strcmp(argv[0], "1234") != 0) { - chprintf(chp, "Key unmatched.\r\n"); + shell_printf(chp, "Key unmatched.\r\n"); return; } clear_all_config_prop_data(); - chprintf(chp, "Config and all cal data cleared.\r\n"); - chprintf(chp, "Do reset manually to take effect. Then do touch cal and save.\r\n"); + shell_printf(chp, "Config and all cal data cleared.\r\n"\ + "Do reset manually to take effect. Then do touch cal and save.\r\n"); } static struct { @@ -560,18 +591,18 @@ static void cmd_data(BaseSequentialStream *chp, int argc, char *argv[]) chMtxLock(&mutex); for (i = 0; i < sweep_points; i++) { if (frequencies[i] != 0) - chprintf(chp, "%f %f\r\n", measured[sel][i][0], measured[sel][i][1]); + shell_printf(chp, "%f %f\r\n", measured[sel][i][0], measured[sel][i][1]); } chMtxUnlock(&mutex); } else if (sel >= 2 && sel < 7) { chMtxLock(&mutex); for (i = 0; i < sweep_points; i++) { if (frequencies[i] != 0) - chprintf(chp, "%f %f\r\n", cal_data[sel-2][i][0], cal_data[sel-2][i][1]); + shell_printf(chp, "%f %f\r\n", cal_data[sel-2][i][0], cal_data[sel-2][i][1]); } chMtxUnlock(&mutex); } else { - chprintf(chp, "usage: data [array]\r\n"); + shell_printf(chp, "usage: data [array]\r\n"); } } @@ -591,9 +622,9 @@ static void cmd_dump(BaseSequentialStream *chp, int argc, char *argv[]) len /= 2; for (i = 0; i < len; ) { for (j = 0; j < 16; j++, i++) { - chprintf(chp, "%04x ", 0xffff & (int)dump_buffer[i]); + shell_printf(chp, "%04x ", 0xffff & (int)dump_buffer[i]); } - chprintf(chp, "\r\n"); + shell_printf(chp, "\r\n"); } } #endif @@ -609,12 +640,12 @@ static void cmd_capture(BaseSequentialStream *chp, int argc, char *argv[]) // read 2 row pixel time (read buffer limit by 2/3 + 1 from spi_buffer size) for (int y=0; y < 240; y+=2) { - // use uint16_t spi_buffer[1024] (defined in ili9341) for read buffer - uint8_t *buf = (uint8_t *)spi_buffer; - ili9341_read_memory(0, y, 320, 2, 2*320, spi_buffer); - for (int i = 0; i < 4*320; i++) { - streamPut(chp, *buf++); - } + // use uint16_t spi_buffer[2048] (defined in ili9341) for read buffer + uint8_t *buf = (uint8_t *)spi_buffer; + ili9341_read_memory(0, y, 320, 2, 2*320, spi_buffer); + for (int i = 0; i < 4*320; i++) { + streamPut(chp, *buf++); + } } chMtxUnlock(&mutex); @@ -633,7 +664,7 @@ static void cmd_gamma(BaseSequentialStream *chp, int argc, char *argv[]) calculate_gamma(gamma); chMtxUnlock(&mutex); - chprintf(chp, "%d %d\r\n", gamma[0], gamma[1]); + shell_printf(chp, "%d %d\r\n", gamma[0], gamma[1]); } #endif @@ -653,7 +684,7 @@ static void cmd_sample(BaseSequentialStream *chp, int argc, char *argv[]) return; } } - chprintf(chp, "usage: sample {gamma|ampl|ref}\r\n"); + shell_printf(chp, "usage: sample {gamma|ampl|ref}\r\n"); } config_t config = { @@ -674,10 +705,10 @@ properties_t current_props = { ._frequency0 = 50000, // start = 50kHz ._frequency1 = 900000000, // end = 900MHz ._sweep_points = POINTS_COUNT, - ._trace = {/*enable, type, channel, polar, scale, refpos*/ + ._trace = {/*enable, type, channel, reserved, scale, refpos*/ { 1, TRC_LOGMAG, 0, 0, 1.0, 9.0 }, { 1, TRC_LOGMAG, 1, 0, 1.0, 9.0 }, - { 1, TRC_SMITH, 0, 1, 1.0, 0.0 }, + { 1, TRC_SMITH, 0, 0, 1.0, 0.0 }, { 1, TRC_PHASE, 1, 0, 1.0, 5.0 } }, ._markers = { @@ -748,20 +779,20 @@ static void cmd_scan(BaseSequentialStream *chp, int argc, char *argv[]) int16_t points = sweep_points; if (argc != 2 && argc != 3) { - chprintf(chp, "usage: scan {start(Hz)} {stop(Hz)} [points]\r\n"); + shell_printf(chp, "usage: scan {start(Hz)} {stop(Hz)} [points]\r\n"); return; } start = my_atoui(argv[0]); stop = my_atoui(argv[1]); if (start == 0 || stop == 0 || start > stop) { - chprintf(chp, "frequency range is invalid\r\n"); + shell_printf(chp, "frequency range is invalid\r\n"); return; } if (argc == 3) { points = my_atoi(argv[2]); if (points <= 0 || points > sweep_points) { - chprintf(chp, "sweep points exceeds range\r\n"); + shell_printf(chp, "sweep points exceeds range\r\n"); return; } } @@ -785,7 +816,7 @@ update_marker_index(void) { int m; int i; - for (m = 0; m < 4; m++) { + for (m = 0; m < MARKERS_MAX; m++) { if (!markers[m].enabled) continue; uint32_t f = markers[m].frequency; @@ -854,7 +885,7 @@ update_frequencies(void) update_grid(); } -void +static void freq_mode_startstop(void) { if (frequency0 > frequency1) { @@ -865,7 +896,7 @@ freq_mode_startstop(void) } } -void +static void freq_mode_centerspan(void) { if (frequency0 <= frequency1) { @@ -876,7 +907,6 @@ freq_mode_centerspan(void) } } - #define START_MIN 50000 #define STOP_MAX 2700000000U @@ -983,7 +1013,7 @@ get_sweep_frequency(int type) static void cmd_sweep(BaseSequentialStream *chp, int argc, char *argv[]) { if (argc == 0) { - chprintf(chp, "%d %d %d\r\n", frequency0, frequency1, sweep_points); + shell_printf(chp, "%d %d %d\r\n", frequency0, frequency1, sweep_points); return; } else if (argc > 3) { goto usage; @@ -1018,8 +1048,8 @@ static void cmd_sweep(BaseSequentialStream *chp, int argc, char *argv[]) set_sweep_frequency(ST_STOP, value1); return; usage: - chprintf(chp, "usage: sweep {start(Hz)} [stop(Hz)]\r\n"); - chprintf(chp, "\tsweep {start|stop|center|span|cw} {freq(Hz)}\r\n"); + shell_printf(chp, "usage: sweep {start(Hz)} [stop(Hz)]\r\n"\ + "\tsweep {start|stop|center|span|cw} {freq(Hz)}\r\n"); } @@ -1058,7 +1088,7 @@ adjust_ed(void) // prepare 1/s11ao to avoid dividing complex float c = 1000e-15; float z0 = 50; - //float z = 6.2832 * frequencies[i] * c * z0; + //float z = 2 * M_PI * frequencies[i] * c * z0; float z = 0.02; cal_data[ETERM_ED][i][0] += z; } @@ -1076,7 +1106,7 @@ eterm_calc_es(void) float c = 50e-15; //float c = 1.707e-12; float z0 = 50; - float z = 6.2832 * frequencies[i] * c * z0; + float z = 2 * M_PI * frequencies[i] * c * z0; float sq = 1 + z*z; float s11aor = (1 - z*z) / sq; float s11aoi = 2*z / sq; @@ -1181,7 +1211,7 @@ void apply_error_term(void) } #endif -void apply_error_term_at(int i) +static void apply_error_term_at(int i) { // S11m' = S11m - Ed // S11a = S11m' / (Er + Es S11m') @@ -1298,7 +1328,7 @@ cal_done(void) redraw_request |= REDRAW_CAL_STATUS; } -void +static void cal_interpolate(int s) { const properties_t *src = caldata_ref(s); @@ -1370,9 +1400,9 @@ static void cmd_cal(BaseSequentialStream *chp, int argc, char *argv[]) int i; for (i = 0; i < 9; i++) { if (cal_status & (1< 1 && strcmp(argv[1], "off") == 0) { - set_trace_type(0, TRC_OFF); - set_trace_type(1, TRC_OFF); - set_trace_type(2, TRC_OFF); - set_trace_type(3, TRC_OFF); + for (t = 0; t < TRACES_MAX; t++) + set_trace_type(t, TRC_OFF); goto exit; } t = my_atoi(argv[0]); - if (t < 0 || t >= 4) + if (t < 0 || t >= TRACES_MAX) goto usage; if (argc == 1) { const char *type = get_trace_typename(t); const char *channel = trc_channel_name[trace[t].channel]; - chprintf(chp, "%d %s %s\r\n", t, type, channel); + shell_printf(chp, "%d %s %s\r\n", t, type, channel); return; } - - if (argc > 1) { - static const type_list t_list[] = { - {"logmag", TRC_LOGMAG}, - {"phase", TRC_PHASE}, - {"polar", TRC_POLAR}, - {"smith", TRC_SMITH}, - {"delay", TRC_DELAY}, - {"linear", TRC_LINEAR}, - {"swr", TRC_SWR}, - {"real", TRC_REAL}, - {"imag", TRC_IMAG}, - {"r", TRC_R}, - {"x", TRC_X}, - {"off", TRC_OFF}, - }; - for (uint16_t i=0; i= 3) { - //trace[t].scale = my_atof(argv[2]); - set_trace_scale(t, my_atof(argv[2])); - goto exit; - } else if (strcmp(argv[1], "refpos") == 0 && argc >= 3) { - //trace[t].refpos = my_atof(argv[2]); - set_trace_refpos(t, my_atof(argv[2])); - goto exit; - } else { - goto usage; + static const type_list t_list[] = { + {"logmag", TRC_LOGMAG}, + {"phase", TRC_PHASE}, + {"delay", TRC_DELAY}, + {"smith", TRC_SMITH}, + {"polar", TRC_POLAR}, + {"linear", TRC_LINEAR}, + {"swr", TRC_SWR}, + {"real", TRC_REAL}, + {"imag", TRC_IMAG}, + {"r", TRC_R}, + {"x", TRC_X}, + {"off", TRC_OFF}, + }; + for (uint16_t i=0; i= 3) { + //trace[t].scale = my_atof(argv[2]); + set_trace_scale(t, my_atof(argv[2])); + goto exit; + } else if (strcmp(argv[1], "refpos") == 0 && argc >= 3) { + //trace[t].refpos = my_atof(argv[2]); + set_trace_refpos(t, my_atof(argv[2])); + goto exit; + } else { + goto usage; + } + check_ch_num: if (argc > 2) { int src = my_atoi(argv[2]); @@ -1637,8 +1656,8 @@ static void cmd_trace(BaseSequentialStream *chp, int argc, char *argv[]) exit: return; usage: - chprintf(chp, "trace {0|1|2|3|all} [logmag|phase|polar|smith|linear|delay|swr|real|imag|r|x|off] [src]\r\n"); - chprintf(chp, "trace {0|1|2|3} {scale|refpos} {value}\r\n"); + shell_printf(chp, "trace {0|1|2|3|all} [logmag|phase|polar|smith|linear|delay|swr|real|imag|r|x|off] [src]\r\n"\ + "trace {0|1|2|3} {scale|refpos} {value}\r\n"); } @@ -1658,7 +1677,7 @@ float get_electrical_delay(void) static void cmd_edelay(BaseSequentialStream *chp, int argc, char *argv[]) { if (argc == 0) { - chprintf(chp, "%f\r\n", electrical_delay); + shell_printf(chp, "%f\r\n", electrical_delay); return; } if (argc > 0) { @@ -1671,26 +1690,26 @@ static void cmd_marker(BaseSequentialStream *chp, int argc, char *argv[]) { int t; if (argc == 0) { - for (t = 0; t < 4; t++) { + for (t = 0; t < MARKERS_MAX; t++) { if (markers[t].enabled) { - chprintf(chp, "%d %d %d\r\n", t+1, markers[t].index, markers[t].frequency); + shell_printf(chp, "%d %d %d\r\n", t+1, markers[t].index, markers[t].frequency); } } return; } if (strcmp(argv[0], "off") == 0) { active_marker = -1; - for (t = 0; t < 4; t++) + 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 >= 4) + if (t < 0 || t >= MARKERS_MAX) goto usage; if (argc == 1) { - chprintf(chp, "%d %d %d\r\n", t+1, markers[t].index, frequency); + shell_printf(chp, "%d %d %d\r\n", t+1, markers[t].index, frequency); active_marker = t; // select active marker markers[t].enabled = TRUE; @@ -1719,7 +1738,7 @@ static void cmd_marker(BaseSequentialStream *chp, int argc, char *argv[]) } return; usage: - chprintf(chp, "marker [n] [off|{index}]\r\n"); + shell_printf(chp, "marker [n] [off|{index}]\r\n"); } static void cmd_touchcal(BaseSequentialStream *chp, int argc, char *argv[]) @@ -1730,15 +1749,15 @@ static void cmd_touchcal(BaseSequentialStream *chp, int argc, char *argv[]) int i; chMtxLock(&mutex); - chprintf(chp, "first touch upper left, then lower right..."); + shell_printf(chp, "first touch upper left, then lower right..."); touch_cal_exec(); - chprintf(chp, "done\r\n"); + shell_printf(chp, "done\r\n"); - chprintf(chp, "touch cal params: "); + shell_printf(chp, "touch cal params: "); for (i = 0; i < 4; i++) { - chprintf(chp, "%d ", config.touch_cal[i]); + shell_printf(chp, "%d ", config.touch_cal[i]); } - chprintf(chp, "\r\n"); + shell_printf(chp, "\r\n"); chMtxUnlock(&mutex); } @@ -1763,7 +1782,7 @@ static void cmd_frequencies(BaseSequentialStream *chp, int argc, char *argv[]) (void)argv; for (i = 0; i < sweep_points; i++) { if (frequencies[i] != 0) - chprintf(chp, "%d\r\n", frequencies[i]); + shell_printf(chp, "%d\r\n", frequencies[i]); } } @@ -1821,7 +1840,7 @@ static void cmd_transform(BaseSequentialStream *chp, int argc, char *argv[]) return; usage: - chprintf(chp, "usage: transform {on|off|impulse|step|bandpass|minimum|normal|maximum} [...]\r\n"); + shell_printf(chp, "usage: transform {on|off|impulse|step|bandpass|minimum|normal|maximum} [...]\r\n"); } static void cmd_test(BaseSequentialStream *chp, int argc, char *argv[]) @@ -1861,22 +1880,22 @@ static void cmd_test(BaseSequentialStream *chp, int argc, char *argv[]) #if 0 //extern adcsample_t adc_samples[2]; - //chprintf(chp, "adc: %d %d\r\n", adc_samples[0], adc_samples[1]); + //shell_printf(chp, "adc: %d %d\r\n", adc_samples[0], adc_samples[1]); int i; int x, y; for (i = 0; i < 50; i++) { test_touch(&x, &y); - chprintf(chp, "adc: %d %d\r\n", x, y); + shell_printf(chp, "adc: %d %d\r\n", x, y); chThdSleepMilliseconds(200); } //extern int touch_x, touch_y; - //chprintf(chp, "adc: %d %d\r\n", touch_x, touch_y); + //shell_printf(chp, "adc: %d %d\r\n", touch_x, touch_y); #endif while (argc > 1) { int x, y; touch_position(&x, &y); - chprintf(chp, "touch: %d %d\r\n", x, y); + shell_printf(chp, "touch: %d %d\r\n", x, y); chThdSleepMilliseconds(200); } } @@ -1886,7 +1905,7 @@ static void cmd_gain(BaseSequentialStream *chp, int argc, char *argv[]) int rvalue; int lvalue = 0; if (argc != 1 && argc != 2) { - chprintf(chp, "usage: gain {lgain(0-95)} [rgain(0-95)]\r\n"); + shell_printf(chp, "usage: gain {lgain(0-95)} [rgain(0-95)]\r\n"); return; } rvalue = my_atoi(argv[0]); @@ -1899,7 +1918,7 @@ static void cmd_port(BaseSequentialStream *chp, int argc, char *argv[]) { int port; if (argc != 1) { - chprintf(chp, "usage: port {0:TX 1:RX}\r\n"); + shell_printf(chp, "usage: port {0:TX 1:RX}\r\n"); return; } port = my_atoi(argv[0]); @@ -1932,14 +1951,14 @@ static void cmd_stat(BaseSequentialStream *chp, int argc, char *argv[]) stat.ave[0] = ave0; stat.ave[1] = ave1; - chprintf(chp, "average: %d %d\r\n", stat.ave[0], stat.ave[1]); - chprintf(chp, "rms: %d %d\r\n", stat.rms[0], stat.rms[1]); - chprintf(chp, "callback count: %d\r\n", stat.callback_count); - //chprintf(chp, "interval cycle: %d\r\n", stat.interval_cycles); - //chprintf(chp, "busy cycle: %d\r\n", stat.busy_cycles); - //chprintf(chp, "load: %d\r\n", stat.busy_cycles * 100 / stat.interval_cycles); + shell_printf(chp, "average: %d %d\r\n", stat.ave[0], stat.ave[1]); + shell_printf(chp, "rms: %d %d\r\n", stat.rms[0], stat.rms[1]); + shell_printf(chp, "callback count: %d\r\n", stat.callback_count); + //shell_printf(chp, "interval cycle: %d\r\n", stat.interval_cycles); + //shell_printf(chp, "busy cycle: %d\r\n", stat.busy_cycles); + //shell_printf(chp, "load: %d\r\n", stat.busy_cycles * 100 / stat.interval_cycles); extern int awd_count; - chprintf(chp, "awd: %d\r\n", awd_count); + shell_printf(chp, "awd: %d\r\n", awd_count); } @@ -1953,64 +1972,207 @@ static void cmd_version(BaseSequentialStream *chp, int argc, char *argv[]) { (void)argc; (void)argv; - chprintf(chp, "%s\r\n", NANOVNA_VERSION); + shell_printf(chp, "%s\r\n", NANOVNA_VERSION); } static void cmd_vbat(BaseSequentialStream *chp, int argc, char *argv[]) { (void)argc; (void)argv; - chprintf(chp, "%d mV\r\n", vbat); + shell_printf(chp, "%d mV\r\n", vbat); } -static THD_WORKING_AREA(waThread2, /* cmd_* max stack size + alpha */442); - -static const ShellCommand commands[] = -{ - { "version", cmd_version }, - { "reset", cmd_reset }, - { "freq", cmd_freq }, - { "offset", cmd_offset }, - { "time", cmd_time }, - { "dac", cmd_dac }, - { "saveconfig", cmd_saveconfig }, - { "clearconfig", cmd_clearconfig }, - { "data", cmd_data }, -#ifdef ENABLED_DUMP - { "dump", cmd_dump }, +#ifdef ENABLE_THREADS_COMMAND +#if CH_CFG_USE_REGISTRY == FALSE +#error "Threads Requite enabled CH_CFG_USE_REGISTRY in chconf.h" #endif - { "frequencies", cmd_frequencies }, - { "port", cmd_port }, - { "stat", cmd_stat }, - { "gain", cmd_gain }, - { "power", cmd_power }, - { "sample", cmd_sample }, - //{ "gamma", cmd_gamma }, - { "scan", cmd_scan }, - { "sweep", cmd_sweep }, - { "test", cmd_test }, - { "touchcal", cmd_touchcal }, - { "touchtest", cmd_touchtest }, - { "pause", cmd_pause }, - { "resume", cmd_resume }, - { "cal", cmd_cal }, - { "save", cmd_save }, - { "recall", cmd_recall }, - { "trace", cmd_trace }, - { "marker", cmd_marker }, - { "edelay", cmd_edelay }, - { "capture", cmd_capture }, - { "vbat", cmd_vbat }, - { "transform", cmd_transform }, - { "threshold", cmd_threshold }, - { NULL, NULL } +static void cmd_threads(BaseSequentialStream *chp, int argc, char *argv[]) { + static const char *states[] = {CH_STATE_NAMES}; + thread_t *tp; + + (void)argv; + if (argc > 0) { + shellUsage(chp, "threads"); + return; + } + chprintf(chp, "stklimit stack addr refs prio state name\r\n"SHELL_NEWLINE_STR); + tp = chRegFirstThread(); + do { + uint32_t stklimit = (uint32_t)tp->wabase; + shell_printf(chp, "%08x %08x %08x %4u %4u %9s %12s"SHELL_NEWLINE_STR, + stklimit, (uint32_t)tp->ctx.sp, (uint32_t)tp, + (uint32_t)tp->refs - 1, (uint32_t)tp->prio, states[tp->state], + tp->name == NULL ? "" : tp->name); + tp = chRegNextThread(tp); + } while (tp != NULL); +} +#endif + +//============================================================================= +static void cmd_help(BaseSequentialStream *chp, int argc, char *argv[]); +typedef struct { + const char *sc_name; + vna_shellcmd_t sc_function; +} VNAShellCommand; + +static const VNAShellCommand commands[] = +{ + { "version" , cmd_version }, + { "reset" , cmd_reset }, + { "freq" , cmd_freq }, + { "offset" , cmd_offset }, + { "time" , cmd_time }, + { "dac" , cmd_dac }, + { "saveconfig" , cmd_saveconfig }, + { "clearconfig" , cmd_clearconfig }, + { "data" , cmd_data }, +#ifdef ENABLED_DUMP + { "dump" , cmd_dump }, +#endif + { "frequencies" , cmd_frequencies }, + { "port" , cmd_port }, + { "stat" , cmd_stat }, + { "gain" , cmd_gain }, + { "power" , cmd_power }, + { "sample" , cmd_sample }, +// { "gamma" , cmd_gamma }, + { "scan" , cmd_scan }, + { "sweep" , cmd_sweep }, + { "test" , cmd_test }, + { "touchcal" , cmd_touchcal }, + { "touchtest" , cmd_touchtest }, + { "pause" , cmd_pause }, + { "resume" , cmd_resume }, + { "cal" , cmd_cal }, + { "save" , cmd_save }, + { "recall" , cmd_recall }, + { "trace" , cmd_trace }, + { "marker" , cmd_marker }, + { "edelay" , cmd_edelay }, + { "capture" , cmd_capture }, + { "vbat" , cmd_vbat }, + { "transform" , cmd_transform }, + { "threshold" , cmd_threshold }, + { "help" , cmd_help }, +#ifdef ENABLE_THREADS_COMMAND +// { "threads" , cmd_threads }, +#endif + { NULL , NULL } }; -static const ShellConfig shell_cfg1 = +static void cmd_help(BaseSequentialStream *chp, int argc, char *argv[]) { - (BaseSequentialStream *)&SDU1, - commands -}; + (void)argc; + (void)argv; + const VNAShellCommand *scp = commands; + shell_printf(chp, "Commands:"); + while (scp->sc_name != NULL) { + shell_printf(chp, " %s", scp->sc_name); + scp++; + } + shell_printf(chp, VNA_SHELL_NEWLINE_STR); + return; +} + +/* + * VNA shell functions + */ + +// +// Read command line from shell_stream +// +static int VNAShell_readLine(char *line, int max_size){ + // Read line from input stream + uint8_t c; + char *ptr = line; + while (1){ + // Return 0 only if stream not active + if (streamRead(shell_stream, &c, 1) == 0) + return 0; + // Backspace + if (c == 8) { + if (ptr != line) { + static const char backspace[] = {0x08,0x20,0x08,0x00}; + shell_printf(shell_stream, backspace); + ptr--; + } + continue; + } + // New line (Enter) + if (c == '\r') { + shell_printf(shell_stream, VNA_SHELL_NEWLINE_STR); + *ptr = 0; + return 1; + } + // Others (skip) + if (c < 0x20) + continue; + // Store + if (ptr < line + max_size - 1) { + streamPut(shell_stream, c); // Echo + *ptr++ = (char)c; + } + } + return 0; +} + +// +// Parse and run command line +// +static void VNAShell_executeLine(char *line){ + // Parse and execute line + char *args[VNA_SHELL_MAX_ARGUMENTS + 1]; + int n = 0; + char *lp = line, *ep; + while (*lp!=0){ + // Skipping white space and tabs at string begin. + while (*lp==' ' || *lp=='\t') lp++; + // If an argument starts with a double quote then its delimiter is another quote, else delimiter is white space. + ep = (*lp == '"') ? strpbrk(++lp, "\"") : strpbrk( lp, " \t"); + // Store in args string + args[n++]=lp; + // Stop, end of input string + if ((lp = ep) == NULL) + break; + // Argument limits check + if (n > VNA_SHELL_MAX_ARGUMENTS) { + shell_printf(shell_stream, "too many arguments, max 4"VNA_SHELL_NEWLINE_STR); + return; + } + // Set zero at the end of string and continue check + *lp++ = 0; + } + if (n == 0) + return; + // Execute line + const VNAShellCommand *scp; + for (scp = commands; scp->sc_name!=NULL;scp++) { + if (strcmp(scp->sc_name, args[0]) == 0) { +// chMtxLock(&mutex); + scp->sc_function(shell_stream, n-1, &args[1]); +// chMtxUnlock(&mutex); + return; + } + } + shell_printf(shell_stream, "%s?"VNA_SHELL_NEWLINE_STR, args[0]); +} + +#ifdef VNA_SHELL_THREAD +static THD_WORKING_AREA(waThread2, /* cmd_* max stack size + alpha */442); +THD_FUNCTION(myshellThread, p) { + (void)p; + chRegSetThreadName("shell"); + char line[VNA_SHELL_MAX_LENGTH]; + shell_printf(shell_stream, VNA_SHELL_NEWLINE_STR"NanoVNA Shell"VNA_SHELL_NEWLINE_STR); + while (true) { + shell_printf(shell_stream, VNA_SHELL_PROMPT_STR); + if (VNAShell_readLine(line, VNA_SHELL_MAX_LENGTH)) + VNAShell_executeLine(line); + else // Putting a delay in order to avoid an endless loop trying to read an unavailable stream. + osalThreadSleepMilliseconds(100); + } +} +#endif static const I2CConfig i2ccfg = { 0x00300506, //voodoo magic 400kHz @ HSI 8MHz @@ -2094,23 +2256,29 @@ int main(void) ui_init(); - /* - * Shell manager initialization. - */ - shellInit(); + chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO-1, Thread1, NULL); - chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); - - while (1) { - if (SDU1.config->usbp->state == USB_ACTIVE) { - thread_t *shelltp = chThdCreateStatic(waThread2, sizeof(waThread2), - NORMALPRIO + 1, - shellThread, (void *)&shell_cfg1); - chThdWait(shelltp); /* Waiting termination. */ - } - - chThdSleepMilliseconds(1000); + while (1) { + if (SDU1.config->usbp->state == USB_ACTIVE) { +#ifdef VNA_SHELL_THREAD + thread_t *shelltp = chThdCreateStatic(waThread2, sizeof(waThread2), + NORMALPRIO + 1, + myshellThread, NULL); + chThdWait(shelltp); +#else + char line[VNA_SHELL_MAX_LENGTH]; + shell_printf(shell_stream, VNA_SHELL_NEWLINE_STR"NanoVNA Shell"VNA_SHELL_NEWLINE_STR); + do { + shell_printf(shell_stream, VNA_SHELL_PROMPT_STR); + if (VNAShell_readLine(line, VNA_SHELL_MAX_LENGTH)) + VNAShell_executeLine(line); + else + chThdSleepMilliseconds(200); + } while (SDU1.config->usbp->state == USB_ACTIVE); +#endif } + chThdSleepMilliseconds(1000); + } } /* The prototype shows it is a naked function - in effect this is just an diff --git a/nanovna.h b/nanovna.h index a1b490c..7df26ec 100644 --- a/nanovna.h +++ b/nanovna.h @@ -126,30 +126,35 @@ extern void tlv320aic3204_init(void); extern void tlv320aic3204_set_gain(int lgain, int rgain); extern void tlv320aic3204_select(int channel); - /* * plot.c */ -#define OFFSETX 15 -#define OFFSETY 0 -#define WIDTH 291 +// GRIDX calculated depends from frequency span +#define GRIDY 23 + +// Offset of plot area +#define OFFSETX 10 +#define OFFSETY 0 + +// WIDTH better be n*(POINTS_COUNT-1) +#define WIDTH 300 +// HEIGHT = 10*GRIDY #define HEIGHT 230 -// Smith/polar chart -#define P_CENTER_X 145 -#define P_CENTER_Y 115 -#define P_RADIUS 115 - +// #define CELLOFFSETX 5 -#define AREA_WIDTH_NORMAL (WIDTH + CELLOFFSETX*2) +#define AREA_WIDTH_NORMAL (CELLOFFSETX + WIDTH + 1 + 4) +#define AREA_HEIGHT_NORMAL ( HEIGHT + 1) + +// Smith/polar chart +#define P_CENTER_X (CELLOFFSETX + WIDTH/2) +#define P_CENTER_Y (HEIGHT/2) +#define P_RADIUS (HEIGHT/2) extern int16_t area_width; extern int16_t area_height; -#define GRIDY 23 - // font - extern const uint8_t x5x7_bits []; #define FONT_GET_DATA(ch) (&x5x7_bits[ch*7]) #define FONT_GET_WIDTH(ch) (8-(x5x7_bits[ch*7]&7)) @@ -176,6 +181,8 @@ extern const uint16_t numfont16x22[]; 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 }; +// Mask for define rectangular plot +#define RECTANGULAR_GRID_MASK ((1<>5)&0x1f) | (((i)>>22)&0x03e0)) -#define CELL_Y(i) (int)(((i)&0x1f) | (((i)>>17)&0x03e0)) -#define CELL_N(i) (int)(((i)>>10)&0xfff) - -#define CELL_X0(i) (int)(((i)>>22)&0x03e0) -#define CELL_Y0(i) (int)(((i)>>17)&0x03e0) - -#define CELL_P(i, x, y) (((((x)&0x03e0UL)<<22) | (((y)&0x03e0UL)<<17)) == ((i)&0xffc00000UL)) +#define INDEX(x, y) ((((uint32_t)x)<<16)|(((uint32_t)y))) +#define CELL_X(i) (int)(((i)>>16)) +#define CELL_Y(i) (int)(((i)&0xFFFF)) +//#define CELL_P(i, x, y) (((((x)&0x03e0UL)<<22) | (((y)&0x03e0UL)<<17)) == ((i)&0xffc00000UL)) //#define floatToInt(v) ((int)(v)) -int floatToInt(float v){ - if (v < 0) return v-0.5; - if (v > 0) return v+0.5; - return 0; +static int +floatToInt(float v){ + if (v < 0) return v-0.5; + if (v > 0) return v+0.5; + return 0; } void update_grid(void) { uint32_t gdigit = 100000000; - uint32_t fstart, fspan; + uint32_t fstart = get_sweep_frequency(ST_START); + uint32_t fspan = get_sweep_frequency(ST_SPAN); uint32_t grid; - if (frequency0 <= frequency1) { - fstart = frequency0; - fspan = frequency1 - frequency0; - } else { - fstart = frequency1; - fspan = frequency0 - frequency1; - } while (gdigit > 100) { grid = 5 * gdigit; @@ -84,8 +61,8 @@ void update_grid(void) gdigit /= 10; } - grid_offset = (WIDTH-1) * ((fstart % grid) / 100) / (fspan / 100); - grid_width = (WIDTH-1) * (grid / 100) / (fspan / 1000); + grid_offset = (WIDTH) * ((fstart % grid) / 100) / (fspan / 100); + grid_width = (WIDTH) * (grid / 100) / (fspan / 1000); force_set_markmap(); redraw_request |= REDRAW_FREQUENCY; @@ -95,9 +72,9 @@ static inline int circle_inout(int x, int y, int r) { int d = x*x + y*y - r*r; - if (d <= -r) + if (d < -r) return 1; - if (d > r) + if (d > r) return -1; return 0; } @@ -145,7 +122,7 @@ polar_grid(int x, int y) * Constant Resistance circle: (u - r/(r+1))^2 + v^2 = 1/(r+1)^2 * Constant Reactance circle: (u - 1)^2 + (v-1/x)^2 = 1/x^2 */ -int +static int smith_grid(int x, int y) { int d; @@ -203,7 +180,7 @@ smith_grid(int x, int y) } #if 0 -int +static int smith_grid2(int x, int y, float scale) { int d; @@ -286,6 +263,7 @@ smith_grid2(int x, int y, float scale) } #endif +#if 0 const int cirs[][4] = { { 0, 58/2, 58/2, 0 }, // Constant Reactance Circle: 2j : R/2 = 58 { 29/2, 0, 29/2, 1 }, // Constant Resistance Circle: 3 : R/4 = 29 @@ -299,7 +277,7 @@ const int cirs[][4] = { { 0, 0, 0, 0 } // sentinel }; -int +static int smith_grid3(int x, int y) { int d; @@ -333,9 +311,10 @@ smith_grid3(int x, int y) } return 0; } +#endif #if 0 -int +static int rectangular_grid(int x, int y) { //#define FREQ(x) (((x) * (fspan / 1000) / (WIDTH-1)) * 1000 + fstart) @@ -357,9 +336,10 @@ rectangular_grid(int x, int y) static int rectangular_grid_x(int x) { + x-=CELLOFFSETX; if (x < 0) return 0; - if (x == 0 || x == WIDTH-1) + if (x == 0 || x == WIDTH) return 1; if ((((x + grid_offset) * 10) % grid_width) < 10) return 1; @@ -415,7 +395,8 @@ draw_on_strut(int v0, int d, int color) /* * calculate log10(abs(gamma)) */ -float logmag(const float *v) +static float +logmag(const float *v) { return log10f(v[0]*v[0] + v[1]*v[1]) * 10; } @@ -423,7 +404,8 @@ float logmag(const float *v) /* * calculate phase[-2:2] of coefficient */ -float phase(const float *v) +static float +phase(const float *v) { return 2 * atan2f(v[1], v[0]) / M_PI * 90; } @@ -431,7 +413,8 @@ float phase(const float *v) /* * calculate groupdelay */ -float groupdelay(const float *v, const float *w, float deltaf) +static float +groupdelay(const float *v, const float *w, float deltaf) { #if 1 // atan(w)-atan(v) = atan((w-v)/(1+wv)) @@ -446,7 +429,8 @@ float groupdelay(const float *v, const float *w, float deltaf) /* * calculate abs(gamma) */ -float linear(const float *v) +static float +linear(const float *v) { return - sqrtf(v[0]*v[0] + v[1]*v[1]); } @@ -454,7 +438,8 @@ float linear(const float *v) /* * calculate vswr; (1+gamma)/(1-gamma) */ -float swr(const float *v) +static float +swr(const float *v) { float x = sqrtf(v[0]*v[0] + v[1]*v[1]); if (x >= 1) @@ -462,30 +447,32 @@ float swr(const float *v) return (1 + x)/(1 - x); } -float resitance(const float *v) { +static float +resitance(const float *v) { float z0 = 50; float d = z0 / ((1-v[0])*(1-v[0])+v[1]*v[1]); float zr = ((1+v[0])*(1-v[0]) - v[1]*v[1]) * d; return zr; } -float reactance(const float *v) { +static float +reactance(const float *v) { float z0 = 50; float d = z0 / ((1-v[0])*(1-v[0])+v[1]*v[1]); float zi = 2*v[1] * d; return zi; } -void +static void cartesian_scale(float re, float im, int *xp, int *yp, float scale) { //float scale = 4e-3; int x = floatToInt(re * P_RADIUS * scale); int y = floatToInt(im * P_RADIUS * scale); - if (x < -P_RADIUS) x = -P_RADIUS; - if (y < -P_RADIUS) y = -P_RADIUS; - if (x > P_RADIUS) x = P_RADIUS; - if (y > P_RADIUS) y = P_RADIUS; + if (x < -P_RADIUS) x = -P_RADIUS; + else if (x > P_RADIUS) x = P_RADIUS; + if (y < -P_RADIUS) y = -P_RADIUS; + else if (y > P_RADIUS) y = P_RADIUS; *xp = P_CENTER_X + x; *yp = P_CENTER_Y - y; } @@ -515,57 +502,57 @@ gamma2reactance(const float v[2]) return 2*v[1] * d; } -uint32_t -trace_into_index(int x, int t, int i, float array[POINTS_COUNT][2]) +static uint32_t +trace_into_index(int t, int i, float array[POINTS_COUNT][2]) { - int y = 0; - float v = 0; + int y, x; + float *coeff = array[i]; float refpos = 10 - get_trace_refpos(t); + float v = refpos; float scale = 1 / get_trace_scale(t); switch (trace[t].type) { case TRC_LOGMAG: - v = refpos - logmag(coeff) * scale; + v-= logmag(coeff) * scale; break; case TRC_PHASE: - v = refpos - phase(coeff) * scale; + v-= phase(coeff) * scale; break; case TRC_DELAY: - v = refpos - groupdelay_from_array(i, array) * scale; + v-= groupdelay_from_array(i, array) * scale; break; case TRC_LINEAR: - v = refpos + linear(coeff) * scale; + v+= linear(coeff) * scale; break; case TRC_SWR: - v = refpos+ (1 - swr(coeff)) * scale; + v+= (1 - swr(coeff)) * scale; break; case TRC_REAL: - v = refpos - coeff[0] * scale; + v-= coeff[0] * scale; break; case TRC_IMAG: - v = refpos - coeff[1] * scale; + v-= coeff[1] * scale; break; case TRC_R: - v = refpos - resitance(coeff) * scale; + v-= resitance(coeff) * scale; break; case TRC_X: - v = refpos - reactance(coeff) * scale; + v-= reactance(coeff) * scale; break; case TRC_SMITH: //case TRC_ADMIT: case TRC_POLAR: cartesian_scale(coeff[0], coeff[1], &x, &y, scale); - return INDEX(x +CELLOFFSETX, y, i); - break; + goto set_index; } - if (v < 0) v = 0; + if (v < 0) v = 0; if (v > 10) v = 10; + x = (i * (WIDTH) + (sweep_points-1)/2) / (sweep_points-1) + CELLOFFSETX; y = floatToInt(v * GRIDY); - return INDEX(x +CELLOFFSETX, y, i); +set_index: + return INDEX(x, y); } -#define PI2 6.283184 - static void format_smith_value(char *buf, int len, const float coeff[2], uint32_t frequency) { @@ -600,11 +587,11 @@ format_smith_value(char *buf, int len, const float coeff[2], uint32_t frequency) case MS_RLC: if (zi < 0){// Capacity prefix = 'F'; - value = -1 / (PI2 * frequency * zi); + value = -1 / (2 * M_PI * frequency * zi); } else { prefix = 'H'; - value = zi / (PI2 * frequency); + value = zi / (2 * M_PI * frequency); } chsnprintf(buf, len, "%F"S_OHM" %F%c", zr, value, prefix); break; @@ -758,46 +745,44 @@ static float distance_of_index(int idx) { return distance * velocity_factor; } - static inline void mark_map(int x, int y) { - if (y >= 0 && y < 8 && x >= 0 && x < 16) + if (y >= 0 && y < MAX_MARKMAP_Y && x >= 0 && x < MAX_MARKMAP_X) markmap[current_mappage][y] |= 1<> 5; - int n0 = y0 >> 5; + int m0 = x0 / CELLWIDTH; + int n0 = y0 / CELLHEIGHT; int i; mark_map(m0, n0); for (i = 1; i < sweep_points; i++) { int x1 = CELL_X(trace_index[t][i]); int y1 = CELL_Y(trace_index[t][i]); - int m1 = x1 >> 5; - int n1 = y1 >> 5; + int m1 = x1 / CELLWIDTH; + int n1 = y1 / CELLHEIGHT; while (m0 != m1 || n0 != n1) { if (m0 == m1) { if (n0 < n1) n0++; else n0--; } else if (n0 == n1) { if (m0 < m1) m0++; else m0--; } else { - int x = (m0 < m1) ? (m0 + 1)<<5 : m0<<5; - int y = (n0 < n1) ? (n0 + 1)<<5 : n0<<5; + int x = ((m0 < m1) ? (m0 + 1) : m0) * CELLWIDTH; + int y = ((n0 < n1) ? (n0 + 1) : n0) * CELLHEIGHT; int sgn = (n0 < n1) ? 1 : -1; if (sgn*(y-y0)*(x1-x0) < sgn*(x-x0)*(y1-y0)) { if (m0 < m1) m0++; @@ -843,38 +828,23 @@ mark_cells_from_index(void) } } -void plot_into_index(float measured[2][POINTS_COUNT][2]) +static inline void +markmap_upperarea(void) { - int i, t; - for (i = 0; i < sweep_points; i++) { - int x = (i * (WIDTH-1) + sweep_points/2) / (sweep_points-1); - for (t = 0; t < TRACES_MAX; t++) { - if (!trace[t].enabled) - continue; - int n = trace[t].channel; - trace_index[t][i] = trace_into_index(x, t, i, measured[n]); - } - } -#if 0 - for (t = 0; t < TRACES_MAX; t++) - if (trace[t].enabled && trace[t].polar) - quicksort(trace_index[t], 0, sweep_points); -#endif - - mark_cells_from_index(); - markmap_all_markers(); + // Hardcoded, Text info from upper area + invalidateRect(0, 0, AREA_WIDTH_NORMAL, 31); } -const uint8_t INSIDE = 0b0000; -const uint8_t LEFT = 0b0001; -const uint8_t RIGHT = 0b0010; -const uint8_t BOTTOM = 0b0100; -const uint8_t TOP = 0b1000; +#define INSIDE 0b0000; +#define LEFT 0b0001; +#define RIGHT 0b0010; +#define BOTTOM 0b0100; +#define TOP 0b1000; -inline static uint8_t +static uint32_t _compute_outcode(int w, int h, int x, int y) { - uint8_t code = 0; + uint32_t code = INSIDE; if (x < 0) { code |= LEFT; } else @@ -893,53 +863,32 @@ _compute_outcode(int w, int h, int x, int y) static void cell_drawline(int w, int h, int x0, int y0, int x1, int y1, int c) { - uint8_t outcode0 = _compute_outcode(w, h, x0, y0); - uint8_t outcode1 = _compute_outcode(w, h, x1, y1); - - if (outcode0 & outcode1) { + uint32_t outcode1 = _compute_outcode(w, h, x0, y0); + uint32_t outcode2 = _compute_outcode(w, h, x1, y1); + if (outcode1 & outcode2) { // this line is out of requested area. early return return; } + // If outcode1 == 0 && outcode2 == 0, no clipping, not need check + //outcode1+=outcode2; + // modifed Bresenham's line algorithm, see https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm + int dx = x1 - x0, sx = 1; if (dx < 0) {dx = -dx; sx = -1;} + int dy = y1 - y0, sy = 1; if (dy < 0) {dy = -dy; sy = -1;} + int err = (dx > dy ? dx : -dy) / 2; - if (x0 > x1) { - SWAP(x0, x1); - SWAP(y0, y1); - } - - int dx = x1 - x0; - int dy = y1 - y0; - int sy = dy > 0 ? 1 : -1; - int e = 0; - - dy *= sy; - - if (dx >= dy) { - e = dy * 2 - dx; - while (x0 != x1) { - if (y0 >= 0 && y0 < h && x0 >= 0 && x0 < w) spi_buffer[y0*w+x0] |= c; - x0++; - e += dy * 2; - if (e >= 0) { - e -= dx * 2; - y0 += sy; - } - } - if (y0 >= 0 && y0 < h && x0 >= 0 && x0 < w) spi_buffer[y0*w+x0] |= c; - } else { - e = dx * 2 - dy; - while (y0 != y1) { - if (y0 >= 0 && y0 < h && x0 >= 0 && x0 < w) spi_buffer[y0*w+x0] |= c; - y0 += sy; - e += dx * 2; - if (e >= 0) { - e -= dy * 2; - x0++; - } - } - if (y0 >= 0 && y0 < h && x0 >= 0 && x0 < w) spi_buffer[y0*w+x0] |= c; + while (1){ + if (//outcode1 == 0 || + (y0 >= 0 && y0 < h && x0 >= 0 && x0 < w)) + spi_buffer[y0*w+x0] |= c; + if (x0 == x1 && y0 == y1) + break; + int e2 = err; + if (e2 > -dx) { err -= dy; x0 += sx; } + if (e2 < dy) { err += dx; y0 += sy; } } } +#if 0 int search_index_range(int x, int y, uint32_t index[POINTS_COUNT], int *i0, int *i1) { @@ -976,157 +925,180 @@ search_index_range(int x, int y, uint32_t index[POINTS_COUNT], int *i0, int *i1) *i1 = j; return TRUE; } +#endif static int -search_index_range_x(int x, uint32_t index[POINTS_COUNT], int *i0, int *i1) +search_index_range_x(int x1, int x2, uint32_t index[POINTS_COUNT], int *i0, int *i1) { int i, j; int head = 0; int tail = sweep_points; - x &= 0x03e0; - i = 0; - while (head < tail) { + int idx_x; + + // Search index point in cell + while (1) { i = (head + tail) / 2; - if (x == CELL_X0(index[i])) - break; - else if (x < CELL_X0(index[i])) { - if (tail == i+1) - break; - tail = i+1; - } else { + idx_x = CELL_X(index[i]); + if (idx_x >= x2){ // index after cell + if (tail == i) + return false; + tail = i; + } + else if (idx_x < x1){ // index before cell if (head == i) - break; + return false; head = i; } + else // index in cell (x =< idx_x < cell_end) + break; } - - if (x != CELL_X0(index[i])) - return FALSE; - j = i; - while (j > 0 && x == CELL_X0(index[j-1])) + // Search index left from point + do{ j--; + }while (j > 0 && x1 <= CELL_X(index[j])); *i0 = j; - j = i; - while (j < POINTS_COUNT-1 && x == CELL_X0(index[j+1])) - j++; - *i1 = j; + // Search index right from point + do{ + i++; + }while (i < sweep_points-1 && CELL_X(index[i]) < x2); + *i1 = i; + return TRUE; } -void +#define REFERENCE_WIDTH 5 +#define REFERENCE_HEIGHT 5 +#define REFERENCE_X_OFFSET 5 +#define REFERENCE_Y_OFFSET 2 + +// Reference bitmap +static const uint8_t reference_bitmap[]={ + 0b11000000, + 0b11110000, + 0b11111100, + 0b11110000, + 0b11000000, +}; + +static void draw_refpos(int w, int h, int x, int y, int c) { - // draw triangle - int i, j; - if (y < -3 || y > 32 + 3) - return; - for (j = 0; j < 3; j++) { - int j0 = 6 - j*2; - for (i = 0; i < j0; i++) { - int x0 = x + i-5; - int y0 = y - j; - int y1 = y + j; - if (y0 >= 0 && y0 < h && x0 >= 0 && x0 < w) - spi_buffer[y0*w+x0] = c; - if (j != 0 && y1 >= 0 && y1 < h && x0 >= 0 && x0 < w) - spi_buffer[y1*w+x0] = c; + int y0=y, j; + for (j=0; j= h) + continue; + int x0=x; + uint8_t bits = reference_bitmap[j]; + while (bits){ + if (x0 >= 0 && x0 < w) + spi_buffer[y0*w+x0] = (bits&0x80) ? c : DEFAULT_BG_COLOR; + x0++; + bits<<=1; } } } - -void -cell_draw_refpos(int m, int n, int w, int h) -{ - int x0 = m * CELLWIDTH; - int y0 = n * CELLHEIGHT; - int t; - for (t = 0; t < TRACES_MAX; t++) { - if (!trace[t].enabled) - continue; - if (trace[t].type == TRC_SMITH || trace[t].type == TRC_POLAR) - continue; - int x = 0 - x0 +CELLOFFSETX; - int y = 10*GRIDY - floatToInt((get_trace_refpos(t) * GRIDY)) - y0; - if (x > -5 && x < w && y >= -3 && y < h+3) - draw_refpos(w, h, x, y, config.trace_color[t]); - } -} - #define MARKER_WIDTH 7 #define MARKER_HEIGHT 10 #define X_MARKER_OFFSET 3 #define Y_MARKER_OFFSET 10 static const uint8_t marker_bitmap[]={ - // Marker 1 - 0b11111110, - 0b11101110, - 0b11001110, - 0b11101110, - 0b11101110, - 0b11101110, - 0b11000110, - 0b01111100, - 0b00111000, - 0b00010000, - // Marker 2 - 0b11111110, - 0b11000110, - 0b10111010, - 0b11111010, - 0b11000110, - 0b10111110, - 0b10000010, - 0b01111100, - 0b00111000, - 0b00010000, - // Marker 3 - 0b11111110, - 0b11000110, - 0b10111010, - 0b11100110, - 0b11111010, - 0b10111010, - 0b11000110, - 0b01111100, - 0b00111000, - 0b00010000, - // Marker 4 - 0b11111110, - 0b11110110, - 0b11100110, - 0b11010110, - 0b10110110, - 0b10110110, - 0b10000010, - 0b01110100, - 0b00111000, - 0b00010000, + // Marker 1 + 0b11111110, + 0b11101110, + 0b11001110, + 0b11101110, + 0b11101110, + 0b11101110, + 0b11000110, + 0b01111100, + 0b00111000, + 0b00010000, + // Marker 2 + 0b11111110, + 0b11000110, + 0b10111010, + 0b11111010, + 0b11000110, + 0b10111110, + 0b10000010, + 0b01111100, + 0b00111000, + 0b00010000, + // Marker 3 + 0b11111110, + 0b11000110, + 0b10111010, + 0b11100110, + 0b11111010, + 0b10111010, + 0b11000110, + 0b01111100, + 0b00111000, + 0b00010000, + // Marker 4 + 0b11111110, + 0b11110110, + 0b11100110, + 0b11010110, + 0b10110110, + 0b10110110, + 0b10000010, + 0b01110100, + 0b00111000, + 0b00010000, }; -static void draw_marker(int w, int h, int x, int y, int c, int ch) +static void +draw_marker(int w, int h, int x, int y, int c, int ch) { - int y0=y; - for (int j=0;j= 0 && x0 < w && y0 >= 0 && y0 < h) - { - if (bits&0x80) - spi_buffer[y0*w+x0] = c; - else if (force_color) - spi_buffer[y0*w+x0] = DEFAULT_BG_COLOR; - } - x0++; - bits<<=1; - } - } + int y0=y, j; + for (j=0;j= 0 && x0 < w && y0 >= 0 && y0 < h){ + if (bits&0x80) + spi_buffer[y0*w+x0] = c; + else if (force_color) + spi_buffer[y0*w+x0] = DEFAULT_BG_COLOR; + } + x0++; + bits<<=1; + } + } +} + +static void +markmap_marker(int marker) +{ + int t; + if (!markers[marker].enabled) + return; + for (t = 0; t < TRACES_MAX; t++) { + if (!trace[t].enabled) + continue; + uint32_t index = trace_index[t][markers[marker].index]; + int x = CELL_X(index) - X_MARKER_OFFSET; + int y = CELL_Y(index) - Y_MARKER_OFFSET; + invalidateRect(x, y, x+MARKER_WIDTH-1, y+MARKER_HEIGHT-1); + } +} + +static void +markmap_all_markers(void) +{ + int i; + for (i = 0; i < MARKERS_MAX; i++) { + if (!markers[i].enabled) + continue; + markmap_marker(i); + } + markmap_upperarea(); } void @@ -1167,10 +1139,7 @@ marker_search(void) void set_marker_search(int mode) { - if (mode == 0) - compare = greater; - else - compare = lesser; + compare = (mode == 0) ? greater : lesser; } int @@ -1237,14 +1206,15 @@ search_nearest_index(int x, int y, int t) int min_d = 1000; int i; for (i = 0; i < sweep_points; i++) { - int16_t dx = x - CELL_X(index[i]) - OFFSETX; - int16_t dy = y - CELL_Y(index[i]) - OFFSETY; + int16_t dx = x - CELL_X(index[i]); + int16_t dy = y - CELL_Y(index[i]); if (dx < 0) dx = -dx; if (dy < 0) dy = -dy; if (dx > 20 || dy > 20) continue; int d = dx*dx + dy*dy; if (d < min_d) { + min_d = d; min_i = i; } } @@ -1253,207 +1223,172 @@ search_nearest_index(int x, int y, int t) } void -cell_draw_markers(int m, int n, int w, int h) +plot_into_index(float measured[2][POINTS_COUNT][2]) { - int t, i; - for (i = 0; i < MARKERS_MAX; i++) { - if (!markers[i].enabled) - continue; - for (t = 0; t < TRACES_MAX; t++) { - if (!trace[t].enabled) - continue; - uint32_t index = trace_index[t][markers[i].index]; - int x = CELL_X(index) - m * CELLWIDTH - X_MARKER_OFFSET; - int y = CELL_Y(index) - n * CELLHEIGHT - Y_MARKER_OFFSET; - - if (x >=-MARKER_WIDTH && x < w + MARKER_WIDTH && y >= -MARKER_HEIGHT && y < h + MARKER_HEIGHT) - draw_marker(w, h, x, y, config.trace_color[t], i); - } - } -} - -void -markmap_marker(int marker) -{ - int t; - if (!markers[marker].enabled) - return; + int t, i; for (t = 0; t < TRACES_MAX; t++) { if (!trace[t].enabled) continue; - uint32_t index = trace_index[t][markers[marker].index]; - int x = CELL_X(index); - int y = CELL_Y(index); - int m = x>>5; - int n = y>>5; - mark_map(m, n); - if ((x&31) < 6) - mark_map(m-1, n); - if ((x&31) > 32-6) - mark_map(m+1, n); - if ((y&31) < 12) { - mark_map(m, n-1); - if ((x&31) < 6) - mark_map(m-1, n-1); - if ((x&31) > 32-6) - mark_map(m+1, n-1); - } + int ch = trace[t].channel; + for (i = 0; i < sweep_points; i++) + trace_index[t][i] = trace_into_index(t, i, measured[ch]); } -} +#if 0 + for (t = 0; t < TRACES_MAX; t++) + if (trace[t].enabled && trace[t].polar) + quicksort(trace_index[t], 0, sweep_points); +#endif -void -markmap_all_markers(void) -{ - int i; - for (i = 0; i < MARKERS_MAX; i++) { - if (!markers[i].enabled) - continue; - markmap_marker(i); - } - markmap_upperarea(); + mark_cells_from_index(); + markmap_all_markers(); } - static void draw_cell(int m, int n) { int x0 = m * CELLWIDTH; int y0 = n * CELLHEIGHT; - int x0off = x0 - CELLOFFSETX; int w = CELLWIDTH; int h = CELLHEIGHT; int x, y; - int i0, i1; - int i; + int i0, i1, i; int t; - - if (x0off + w > area_width) - w = area_width - x0off; + // Clip cell by area + if (x0 + w > area_width) + w = area_width - x0; if (y0 + h > area_height) h = area_height - y0; if (w <= 0 || h <= 0) return; - uint16_t grid_mode = 0; - for (t = 0; t < TRACES_MAX; t++) { - if (!trace[t].enabled) - continue; - - if (trace[t].type == TRC_SMITH) - grid_mode |= GRID_SMITH; - //else if (trace[t].type == TRC_ADMIT) - // grid_mode |= GRID_ADMIT; - else if (trace[t].type == TRC_POLAR) - grid_mode |= GRID_POLAR; - else - grid_mode |= GRID_RECTANGULAR; - } - PULSE; + // Clear buffer memset(spi_buffer, DEFAULT_BG_COLOR, sizeof spi_buffer); uint16_t c = config.grid_color; - /* draw grid */ - if (grid_mode & GRID_RECTANGULAR) { - for (x = 0; x < w; x++) { - if (rectangular_grid_x(x+x0off)){ - for (y = 0; y < h; y++) - spi_buffer[y * w + x] = c; - } - } - for (y = 0; y < h; y++) { - if (rectangular_grid_y(y+y0)){ - for (x = 0; x < w; x++) - if (x+x0off >= 0 && x+x0off < WIDTH) - spi_buffer[y * w + x] = c; - } - } - } - if (grid_mode & (GRID_SMITH|GRID_ADMIT|GRID_POLAR)) { - for (y = 0; y < h; y++) { + // Draw grid + for (t = 0; t < TRACES_MAX; t++) { + if (!trace[t].enabled) + continue; + uint32_t trace_type = (1<= CELLOFFSETX && x+x0 <= WIDTH+CELLOFFSETX) + spi_buffer[y * w + x] = c; + } + } + continue; } + if(trace_type&(1< 0) - i0--; - if (i1 < POINTS_COUNT-1) - i1++; - for (i = i0; i < i1; i++) { - int x1 = CELL_X(trace_index[t][i]); - int x2 = CELL_X(trace_index[t][i+1]); - int y1 = CELL_Y(trace_index[t][i]); - int y2 = CELL_Y(trace_index[t][i+1]); - int c = config.trace_color[t]; - cell_drawline(w, h, x1 - x0, y1 - y0, x2 - x0, y2 - y0, c); - } + c = config.trace_color[t]; + // draw polar plot (check all points) + i0 = 0; i1=0; + uint32_t trace_type = (1<=0 && x-MARKER_WIDTH=0 && y-MARKER_HEIGHT=0 && x-REFERENCE_WIDTH=0 && y-REFERENCE_HEIGHT +//#include #include @@ -106,28 +106,29 @@ int awd_count; #define KP_DONE 1 #define KP_CANCEL 2 -char kp_buf[NUMINPUT_LEN+1]; -int8_t kp_index = 0; +static char kp_buf[NUMINPUT_LEN+1]; +static int8_t kp_index = 0; -void ui_mode_normal(void); -void ui_mode_menu(void); -void ui_mode_numeric(int _keypad_mode); -void ui_mode_keypad(int _keypad_mode); -void draw_menu(void); -void leave_ui_mode(void); -void erase_menu_buttons(void); -void ui_process_keypad(void); +static void ui_mode_normal(void); +static void ui_mode_menu(void); +static void ui_mode_numeric(int _keypad_mode); +static void ui_mode_keypad(int _keypad_mode); +static void draw_menu(void); +static void leave_ui_mode(void); +static void erase_menu_buttons(void); +static void ui_process_keypad(void); static void ui_process_numeric(void); +static void menu_move_back(void); static void menu_push_submenu(const menuitem_t *submenu); static int btn_check(void) { int cur_button = READ_PORT() & BUTTON_MASK; - int changed = last_button ^ cur_button; - int status = 0; + int changed = last_button ^ cur_button; + int status = 0; uint32_t ticks = chVTGetSystemTime(); - if (changed & (1<= BUTTON_DEBOUNCE_TICKS) { if (cur_button & (1< TOUCH_THRESHOLD; } -int touch_check(void) +static int +touch_check(void) { int stat = touch_status(); if (stat) { @@ -298,7 +300,8 @@ int touch_check(void) } } -void touch_wait_release(void) +static void +touch_wait_release(void) { int status; /* wait touch release */ @@ -451,10 +454,6 @@ enum { typedef void (*menuaction_cb_t)(int item, uint8_t data); - -static void menu_move_back(void); - - static void menu_calop_cb(int item, uint8_t data) { @@ -563,7 +562,7 @@ choose_active_trace(void) if (trace[uistat.current_trace].enabled) // do nothing return; - for (i = 0; i < 4; i++) + for (i = 0; i < TRACES_MAX; i++) if (trace[i].enabled) { uistat.current_trace = i; return; @@ -669,7 +668,7 @@ menu_scale_cb(int item, uint8_t data) { (void)item; if (data == KM_SCALE && trace[uistat.current_trace].type == TRC_DELAY) { - data = KM_SCALEDELAY; + data = KM_SCALEDELAY; } int status = btn_wait_release(); if (status & EVT_BUTTON_DOWN_LONG) { @@ -815,7 +814,7 @@ menu_marker_smith_cb(int item, uint8_t data) draw_menu(); } -void +static void active_marker_select(int item) { if (item == -1) { @@ -863,7 +862,7 @@ menu_marker_sel_cb(int item, uint8_t data) uistat.lever_mode = LM_MARKER; } -const menuitem_t menu_calop[] = { +static const menuitem_t menu_calop[] = { { MT_CALLBACK, CAL_OPEN, "OPEN", menu_calop_cb }, { MT_CALLBACK, CAL_SHORT, "SHORT", menu_calop_cb }, { MT_CALLBACK, CAL_LOAD, "LOAD", menu_calop_cb }, @@ -1085,7 +1084,8 @@ ensure_selection(void) selection = i-1; } -static void menu_move_back(void) +static void +menu_move_back(void) { if (menu_current_level == 0) return; @@ -1095,7 +1095,8 @@ static void menu_move_back(void) draw_menu(); } -static void menu_push_submenu(const menuitem_t *submenu) +static void +menu_push_submenu(const menuitem_t *submenu) { if (menu_current_level < MENU_STACK_DEPTH_MAX-1) menu_current_level++; @@ -1106,7 +1107,8 @@ static void menu_push_submenu(const menuitem_t *submenu) } /* -static void menu_move_top(void) +static void +menu_move_top(void) { if (menu_current_level == 0) return; @@ -1117,7 +1119,8 @@ static void menu_move_top(void) } */ -void menu_invoke(int item) +static void +menu_invoke(int item) { const menuitem_t *menu = menu_stack[menu_current_level]; menu = &menu[item]; @@ -1147,91 +1150,103 @@ void menu_invoke(int item) } } -#define KP_X(x) (48*(x) + 2 + (320-64-192)) -#define KP_Y(y) (48*(y) + 2) +#define KP_WIDTH 48 +#define KP_HEIGHT 48 +// Key x, y position (0 - 15) on screen +#define KP_GET_X(posx) ((posx)*KP_WIDTH + (320-64-KP_WIDTH*4)) +#define KP_GET_Y(posy) ((posy)*KP_HEIGHT + 12 ) -#define KP_PERIOD 10 -#define KP_MINUS 11 -#define KP_X1 12 -#define KP_K 13 -#define KP_M 14 -#define KP_G 15 -#define KP_BS 16 -#define KP_INF 17 -#define KP_DB 18 +// Key names +#define KP_0 0 +#define KP_1 1 +#define KP_2 2 +#define KP_3 3 +#define KP_4 4 +#define KP_5 5 +#define KP_6 6 +#define KP_7 7 +#define KP_8 8 +#define KP_9 9 +#define KP_PERIOD 10 +#define KP_MINUS 11 +#define KP_X1 12 +#define KP_K 13 +#define KP_M 14 +#define KP_G 15 +#define KP_BS 16 +#define KP_INF 17 +#define KP_DB 18 #define KP_PLUSMINUS 19 -#define KP_KEYPAD 20 -#define KP_N 21 -#define KP_P 22 +#define KP_KEYPAD 20 +#define KP_N 21 +#define KP_P 22 -// Set struct data align as BYTE for save flash memory -#pragma pack(push, 1) typedef struct { - uint16_t x, y; - int8_t c; + uint8_t x:4; + uint8_t y:4; + int8_t c; } keypads_t; -#pragma pack(pop) -const keypads_t *keypads; -uint8_t keypads_last_index; +static const keypads_t *keypads; +static uint8_t keypads_last_index; -const keypads_t keypads_freq[] = { - { KP_X(1), KP_Y(3), KP_PERIOD }, - { KP_X(0), KP_Y(3), 0 }, - { KP_X(0), KP_Y(2), 1 }, - { KP_X(1), KP_Y(2), 2 }, - { KP_X(2), KP_Y(2), 3 }, - { KP_X(0), KP_Y(1), 4 }, - { KP_X(1), KP_Y(1), 5 }, - { KP_X(2), KP_Y(1), 6 }, - { KP_X(0), KP_Y(0), 7 }, - { KP_X(1), KP_Y(0), 8 }, - { KP_X(2), KP_Y(0), 9 }, - { KP_X(3), KP_Y(0), KP_G }, - { KP_X(3), KP_Y(1), KP_M }, - { KP_X(3), KP_Y(2), KP_K }, - { KP_X(3), KP_Y(3), KP_X1 }, - { KP_X(2), KP_Y(3), KP_BS }, +static const keypads_t keypads_freq[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, KP_0 }, + { 0, 2, KP_1 }, + { 1, 2, KP_2 }, + { 2, 2, KP_3 }, + { 0, 1, KP_4 }, + { 1, 1, KP_5 }, + { 2, 1, KP_6 }, + { 0, 0, KP_7 }, + { 1, 0, KP_8 }, + { 2, 0, KP_9 }, + { 3, 0, KP_G }, + { 3, 1, KP_M }, + { 3, 2, KP_K }, + { 3, 3, KP_X1 }, + { 2, 3, KP_BS }, { 0, 0, -1 } }; -const keypads_t keypads_scale[] = { - { KP_X(1), KP_Y(3), KP_PERIOD }, - { KP_X(0), KP_Y(3), 0 }, - { KP_X(0), KP_Y(2), 1 }, - { KP_X(1), KP_Y(2), 2 }, - { KP_X(2), KP_Y(2), 3 }, - { KP_X(0), KP_Y(1), 4 }, - { KP_X(1), KP_Y(1), 5 }, - { KP_X(2), KP_Y(1), 6 }, - { KP_X(0), KP_Y(0), 7 }, - { KP_X(1), KP_Y(0), 8 }, - { KP_X(2), KP_Y(0), 9 }, - { KP_X(3), KP_Y(3), KP_X1 }, - { KP_X(2), KP_Y(3), KP_BS }, +static const keypads_t keypads_scale[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, KP_0 }, + { 0, 2, KP_1 }, + { 1, 2, KP_2 }, + { 2, 2, KP_3 }, + { 0, 1, KP_4 }, + { 1, 1, KP_5 }, + { 2, 1, KP_6 }, + { 0, 0, KP_7 }, + { 1, 0, KP_8 }, + { 2, 0, KP_9 }, + { 3, 3, KP_X1 }, + { 2, 3, KP_BS }, { 0, 0, -1 } }; -const keypads_t keypads_time[] = { - { KP_X(1), KP_Y(3), KP_PERIOD }, - { KP_X(0), KP_Y(3), 0 }, - { KP_X(0), KP_Y(2), 1 }, - { KP_X(1), KP_Y(2), 2 }, - { KP_X(2), KP_Y(2), 3 }, - { KP_X(0), KP_Y(1), 4 }, - { KP_X(1), KP_Y(1), 5 }, - { KP_X(2), KP_Y(1), 6 }, - { KP_X(0), KP_Y(0), 7 }, - { KP_X(1), KP_Y(0), 8 }, - { KP_X(2), KP_Y(0), 9 }, - { KP_X(3), KP_Y(1), KP_N }, - { KP_X(3), KP_Y(2), KP_P }, - { KP_X(3), KP_Y(3), KP_MINUS }, - { KP_X(2), KP_Y(3), KP_BS }, +static const keypads_t keypads_time[] = { + { 1, 3, KP_PERIOD }, + { 0, 3, KP_0 }, + { 0, 2, KP_1 }, + { 1, 2, KP_2 }, + { 2, 2, KP_3 }, + { 0, 1, KP_4 }, + { 1, 1, KP_5 }, + { 2, 1, KP_6 }, + { 0, 0, KP_7 }, + { 1, 0, KP_8 }, + { 2, 0, KP_9 }, + { 3, 1, KP_N }, + { 3, 2, KP_P }, + { 3, 3, KP_MINUS }, + { 2, 3, KP_BS }, { 0, 0, -1 } }; -const keypads_t * const keypads_mode_tbl[] = { +static const keypads_t * const keypads_mode_tbl[] = { keypads_freq, // start keypads_freq, // stop keypads_freq, // center @@ -1244,27 +1259,29 @@ const keypads_t * const keypads_mode_tbl[] = { keypads_time // scale of delay }; -const char * const keypad_mode_label[] = { +static const char * const keypad_mode_label[] = { "START", "STOP", "CENTER", "SPAN", "CW FREQ", "SCALE", "REFPOS", "EDELAY", "VELOCITY%", "DELAY" }; -void +static void draw_keypad(void) { int i = 0; - while (keypads[i].x) { + while (keypads[i].c>=0) { uint16_t bg = config.menu_normal_color; if (i == selection) bg = config.menu_active_color; setForegroundColor(DEFAULT_MENU_TEXT_COLOR); setBackgroundColor(bg); - ili9341_fill(keypads[i].x, keypads[i].y, 44, 44, bg); - ili9341_drawfont(keypads[i].c, keypads[i].x+14, keypads[i].y+10); + int x = KP_GET_X(keypads[i].x); + int y = KP_GET_Y(keypads[i].y); + ili9341_fill(x+2, y+2, KP_WIDTH-4, KP_HEIGHT-4, bg); + ili9341_drawfont(keypads[i].c, x+(KP_WIDTH-NUM_FONT_GET_WIDTH)/2, y+(KP_HEIGHT-NUM_FONT_GET_HEIGHT)/2); i++; } } -void +static void draw_numeric_area_frame(void) { ili9341_fill(0, 208, 320, 32, DEFAULT_MENU_COLOR); @@ -1274,15 +1291,15 @@ draw_numeric_area_frame(void) //ili9341_drawfont(KP_KEYPAD, 300, 216); } -void +static void draw_numeric_input(const char *buf) { - int i = 0; - int x = 64; + int i; + int x; int focused = FALSE; uint16_t xsim = 0b0010010000000000; - for (i = 0; i < 10 && buf[i]; i++, xsim<<=1) { + for (i = 0, x = 64; i < 10 && buf[i]; i++, xsim<<=1) { uint16_t fg = DEFAULT_MENU_TEXT_COLOR; uint16_t bg = DEFAULT_MENU_COLOR; int c = buf[i]; @@ -1290,12 +1307,10 @@ draw_numeric_input(const char *buf) c = KP_PERIOD; else if (c == '-') c = KP_MINUS; - else if (c >= '0' && c <= '9') + else// if (c >= '0' && c <= '9') c = c - '0'; - else - c = -1; - if (uistat.digit == 8-i) { + if (ui_mode == UI_NUMERIC && uistat.digit == 8-i) { fg = DEFAULT_SPEC_INPUT_COLOR; focused = TRUE; if (uistat.digit_mode) @@ -1303,18 +1318,17 @@ draw_numeric_input(const char *buf) } setForegroundColor(fg); setBackgroundColor(bg); - if (c >= 0) + if (c >= 0) // c is number ili9341_drawfont(c, x, 208+4); - else if (focused) + else if (focused) // c not number, but focused ili9341_drawfont(0, x, 208+4); - else + else // erase ili9341_fill(x, 208+4, 20, 24, bg); - x += xsim&0x8000 ? 18+8 : 18; - } - if (i < 10) { - ili9341_fill(x, 208+4, 20*(10-i), 24, DEFAULT_MENU_COLOR); + x += xsim&0x8000 ? NUM_FONT_GET_WIDTH+2+8 : NUM_FONT_GET_WIDTH+2; } + // erase last + ili9341_fill(x, 208+4, NUM_FONT_GET_WIDTH+2+8, 24, DEFAULT_MENU_COLOR); } static int @@ -1398,7 +1412,7 @@ menu_item_modify_attribute(const menuitem_t *menu, int item, } } -void +static void draw_menu_buttons(const menuitem_t *menu) { int i = 0; @@ -1430,7 +1444,7 @@ draw_menu_buttons(const menuitem_t *menu) } } -void +static void menu_select_touch(int i) { selection = i; @@ -1440,7 +1454,7 @@ menu_select_touch(int i) menu_invoke(i); } -void +static void menu_apply_touch(void) { int touch_x, touch_y; @@ -1465,25 +1479,25 @@ menu_apply_touch(void) ui_mode_normal(); } -void +static void draw_menu(void) { draw_menu_buttons(menu_stack[menu_current_level]); } -void +static void erase_menu_buttons(void) { ili9341_fill(320-60, 0, 60, 32*7, DEFAULT_BG_COLOR); } -void +static void erase_numeric_input(void) { ili9341_fill(0, 240-32, 320, 32, DEFAULT_BG_COLOR); } -void +static void leave_ui_mode() { if (ui_mode == UI_MENU) { @@ -1496,7 +1510,7 @@ leave_ui_mode() } } -void +static void fetch_numeric_target(void) { switch (keypad_mode) { @@ -1542,7 +1556,8 @@ fetch_numeric_target(void) uistat.previous_value = uistat.value; } -void set_numeric_value(void) +static void +set_numeric_value(void) { switch (keypad_mode) { case KM_START: @@ -1575,7 +1590,7 @@ void set_numeric_value(void) } } -void +static void draw_numeric_area(void) { char buf[10]; @@ -1583,7 +1598,7 @@ draw_numeric_area(void) draw_numeric_input(buf); } -void +static void ui_mode_menu(void) { if (ui_mode == UI_MENU) @@ -1591,13 +1606,13 @@ ui_mode_menu(void) ui_mode = UI_MENU; /* narrowen plotting area */ - area_width = AREA_WIDTH_NORMAL - (64-8); - area_height = HEIGHT+1; + area_width = AREA_WIDTH_NORMAL - 60; + area_height = AREA_HEIGHT_NORMAL; ensure_selection(); draw_menu(); } -void +static void ui_mode_numeric(int _keypad_mode) { if (ui_mode == UI_NUMERIC) @@ -1609,14 +1624,14 @@ ui_mode_numeric(int _keypad_mode) keypad_mode = _keypad_mode; ui_mode = UI_NUMERIC; area_width = AREA_WIDTH_NORMAL; - area_height = 240-32;//HEIGHT - 32; + area_height = 240-32;//AREA_HEIGHT_NORMAL - 32; draw_numeric_area_frame(); fetch_numeric_target(); draw_numeric_area(); } -void +static void ui_mode_keypad(int _keypad_mode) { if (ui_mode == UI_KEYPAD) @@ -1631,7 +1646,7 @@ ui_mode_keypad(int _keypad_mode) keypads_last_index = i; ui_mode = UI_KEYPAD; - area_width = AREA_WIDTH_NORMAL - (64-8); + area_width = AREA_WIDTH_NORMAL - 60; area_height = HEIGHT - 32; draw_menu(); draw_keypad(); @@ -1639,14 +1654,14 @@ ui_mode_keypad(int _keypad_mode) draw_numeric_input(""); } -void +static void ui_mode_normal(void) { if (ui_mode == UI_NORMAL) return; - area_width = AREA_WIDTH_NORMAL; - area_height = HEIGHT+1; + area_width = AREA_WIDTH_NORMAL; + area_height = AREA_HEIGHT_NORMAL; leave_ui_mode(); ui_mode = UI_NORMAL; } @@ -1676,16 +1691,14 @@ lever_move_marker(int status) static void lever_search_marker(int status) { + int i = -1; if (active_marker >= 0) { - if (status & EVT_DOWN) { - int i = marker_search_left(markers[active_marker].index); - if (i != -1) - markers[active_marker].index = i; - } else if (status & EVT_UP) { - int i = marker_search_right(markers[active_marker].index); - if (i != -1) - markers[active_marker].index = i; - } + if (status & EVT_DOWN) + i = marker_search_left(markers[active_marker].index); + else if (status & EVT_UP) + i = marker_search_right(markers[active_marker].index); + if (i != -1) + markers[active_marker].index = i; redraw_marker(active_marker, TRUE); } } @@ -1748,7 +1761,7 @@ ui_process_normal(void) case LM_MARKER: lever_move_marker(status); break; case LM_SEARCH: lever_search_marker(status); break; case LM_CENTER: lever_move_center(status); break; - case LM_SPAN: lever_zoom_span(status); break; + case LM_SPAN: lever_zoom_span(status); break; } } } @@ -1768,14 +1781,13 @@ ui_process_menu(void) if (menu_stack[menu_current_level][selection+1].type == MT_NONE) goto menuclose; selection++; - draw_menu(); } if (status & EVT_DOWN) { if (selection == 0) goto menuclose; selection--; - draw_menu(); } + draw_menu(); status = btn_wait_release(); } while (status != 0); } @@ -1867,9 +1879,11 @@ keypad_apply_touch(void) touch_position(&touch_x, &touch_y); - while (keypads[i].x) { - if (keypads[i].x-2 < touch_x && touch_x < keypads[i].x+44+2 - && keypads[i].y-2 < touch_y && touch_y < keypads[i].y+44+2) { + while (keypads[i].c>=0) { + int x = KP_GET_X(keypads[i].x); + int y = KP_GET_Y(keypads[i].y); + if (x < touch_x && touch_x < x+KP_WIDTH + && y < touch_y && touch_y < y+KP_HEIGHT) { // draw focus selection = i; draw_keypad(); @@ -1951,35 +1965,28 @@ ui_process_numeric(void) do { if (uistat.digit_mode) { if (status & EVT_DOWN) { - if (uistat.digit < 8) { + if (uistat.digit < 8) uistat.digit++; - draw_numeric_area(); - } else { + else goto exit; - } } if (status & EVT_UP) { - if (uistat.digit > 0) { + if (uistat.digit > 0) uistat.digit--; - draw_numeric_area(); - } else { + else goto exit; - } } } else { int32_t step = 1; int n; for (n = uistat.digit; n > 0; n--) step *= 10; - if (status & EVT_DOWN) { + if (status & EVT_DOWN) uistat.value += step; - draw_numeric_area(); - } - if (status & EVT_UP) { + if (status & EVT_UP) uistat.value -= step; - draw_numeric_area(); - } } + draw_numeric_area(); status = btn_wait_release(); } while (status != 0); } @@ -1992,7 +1999,7 @@ ui_process_numeric(void) ui_mode_normal(); } -void +static void ui_process_keypad(void) { int status; @@ -2004,20 +2011,13 @@ ui_process_keypad(void) if (status & (EVT_UP|EVT_DOWN)) { int s = status; do { - if (s & EVT_UP) { - selection--; - if (selection < 0) + if (s & EVT_UP) + if (--selection < 0) selection = keypads_last_index; - draw_keypad(); - } - if (s & EVT_DOWN) { - selection++; - if (keypads[selection].c < 0) { - // reaches to tail + if (s & EVT_DOWN) + if (++selection > keypads_last_index) selection = 0; - } - draw_keypad(); - } + draw_keypad(); s = btn_wait_release(); } while (s != 0); } @@ -2086,12 +2086,6 @@ drag_marker(int t, int m) } while(status != EVT_TOUCH_RELEASED); } -static int -sq_distance(int x0, int y0) -{ - return x0*x0 + y0*y0; -} - static int touch_pickup_marker(void) { @@ -2101,18 +2095,19 @@ touch_pickup_marker(void) touch_x -= OFFSETX; touch_y -= OFFSETY; - for (m = 0; m < 4; m++) { + for (m = 0; m < MARKERS_MAX; m++) { if (!markers[m].enabled) continue; - for (t = 0; t < 4; t++) { + for (t = 0; t < TRACES_MAX; t++) { int x, y; if (!trace[t].enabled) continue; marker_position(m, t, &x, &y); - - if (sq_distance(x - touch_x, y - touch_y) < 400) { + x-=touch_x; + y-=touch_y; + if ((x*x+y*y) < 20*20) { if (active_marker != m) { previous_marker = active_marker; active_marker = m; @@ -2223,7 +2218,7 @@ static const GPTConfig gpt3cfg = { 0 }; -void +static void test_touch(int *x, int *y) { adc_stop(ADC1);