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