diff --git a/ili9341.c b/ili9341.c index b91a55d..a39ba1c 100644 --- a/ili9341.c +++ b/ili9341.c @@ -26,8 +26,6 @@ #include "spi.h" - - // Allow enable DMA for read display data #ifdef TINYSA4 #define __USE_DISPLAY_DMA_RX__ @@ -58,10 +56,10 @@ #define LCD_SPI_RX_SPEED SPI_BR_DIV4 #endif -uint16_t spi_buffer[SPI_BUFFER_SIZE]; +pixel_t spi_buffer[SPI_BUFFER_SIZE]; // Default foreground & background colors -uint16_t foreground_color = 0; -uint16_t background_color = 0; +pixel_t foreground_color = 0; +pixel_t background_color = 0; // Display width and height definition #define ILI9341_WIDTH LCD_WIDTH @@ -357,11 +355,8 @@ void set_SPI_mode(uint16_t mode){ static void send_command(uint8_t cmd, uint8_t len, const uint8_t *data) { // Uncomment on low speed SPI (possible get here before previous tx complete) -#ifndef TINYSA4 - while (SPI_IN_TX_RX(LCD_SPI)); -#endif +// while (SPI_IN_TX_RX(LCD_SPI)); #ifdef TINYSA4 -// while (SPI_IN_TX_RX); set_SPI_mode(SPI_MODE_LCD); #endif LCD_CS_LOW; @@ -517,7 +512,9 @@ static void ili9341_setWindow(int x, int y, int w, int h){ send_command(ILI9341_PAGE_ADDRESS_SET, 4, (uint8_t *)&yy); } -void ili9341_bulk_8bit(int x, int y, int w, int h, uint16_t *palette) +#if 0 +// Test code for palette mode +void ili9341_bulk_8bit(int x, int y, int w, int h, pixel_t *palette) { ili9341_setWindow(x, y ,w, h); send_command(ILI9341_MEMORY_WRITE, 0, NULL); @@ -528,27 +525,62 @@ void ili9341_bulk_8bit(int x, int y, int w, int h, uint16_t *palette) spi_TxWord(palette[*buf++]); // LCD_CS_HIGH; } +#endif + +#if DISPLAY_CELL_BUFFER_COUNT != 1 +#define LCD_BUFFER_1 0x01 +#define LCD_DMA_RUN 0x02 +static uint8_t LCD_dma_status = 0; +#endif + +pixel_t *ili9341_get_cell_buffer(void){ +#if DISPLAY_CELL_BUFFER_COUNT == 1 + return spi_buffer; +#else + return &spi_buffer[(LCD_dma_status&LCD_BUFFER_1) ? SPI_BUFFER_SIZE/2 : 0]; +#endif +} #ifndef __USE_DISPLAY_DMA__ -void ili9341_fill(int x, int y, int w, int h, uint16_t color) +void ili9341_fill(int x, int y, int w, int h, pixel_t color) { ili9341_setWindow(x, y ,w, h); send_command(ILI9341_MEMORY_WRITE, 0, NULL); - int32_t len = w * h; - while (len-- > 0) - spi_TxWord(color); -// LCD_CS_HIGH; + uint32_t len = w * h; + do { + while (SPI_TX_IS_NOT_EMPTY(LCD_SPI)) + ; + SPI_WRITE_16BIT(LCD_SPI, color); + }while(--len); +#ifdef __REMOTE_DESKTOP__ + if (auto_capture) { + send_region("fill", x,y,w,h); + send_buffer((uint8_t *)&background_color, 2); + } +#endif } void ili9341_bulk(int x, int y, int w, int h) { ili9341_setWindow(x, y ,w, h); send_command(ILI9341_MEMORY_WRITE, 0, NULL); - int32_t len = w * h; - while (len-- > 0) - spi_TxWord(*buf++); -// LCD_CS_HIGH; + spi_TxBuffer((uint8_t *)spi_buffer, w * h * sizeof(pixel_t)); +#ifdef __REMOTE_DESKTOP__ + if (auto_capture) { + send_region("bulk", x,y,w,h); + send_buffer((uint8_t *)buffer, w *h * sizeof(pixel_t)); + } +#endif +} + +void ili9341_bulk_continue(int x, int y, int w, int h){ + ili9341_bulk(x, y, w, h); } + +void ili9341_bulk_finish(void){ + while (SPI_IS_BUSY(LCD_SPI)); // Wait tx +} + #else // // Use DMA for send data @@ -563,36 +595,57 @@ void ili9341_fill(int x, int y, int w, int h) dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD); #ifdef __REMOTE_DESKTOP__ if (auto_capture) { - send_region("fill", x,y,w,h); - send_buffer((uint8_t *)&background_color, 2); + send_region("fill", x, y, w, h); + send_buffer((uint8_t *)&background_color, sizeof(pixel_t)); } #endif dmaStreamFlush(w * h); } -// Copy spi_buffer to region -void ili9341_bulk(int x, int y, int w, int h) -{ +void ili9341_bulk_finish(void){ + dmaWaitCompletion(dmatx); // Wait DMA + while (SPI_IN_TX_RX(LCD_SPI)); // Wait tx +} + +static void ili9341_DMA_bulk(int x, int y, int w, int h, pixel_t *buffer){ ili9341_setWindow(x, y ,w, h); send_command(ILI9341_MEMORY_WRITE, 0, NULL); - // Init Tx DMA mem->spi, set size, mode (spi and mem data size is 16 bit) - dmaStreamSetMemory0(dmatx, spi_buffer); - dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | - STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_MINC); + dmaStreamSetMemory0(dmatx, buffer); + dmaStreamSetMode(dmatx, txdmamode | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_MINC); + dmaStreamSetTransactionSize(dmatx, w * h); + dmaStreamEnable(dmatx); #ifdef __REMOTE_DESKTOP__ if (auto_capture) { - send_region("bulk", x,y,w,h); - send_buffer((uint8_t *)spi_buffer, w*h*2); + send_region("bulk", x, y, w, h); + send_buffer((uint8_t *)buffer, w *h * sizeof(pixel_t)); } #endif - dmaStreamFlush(w * h); +} + +// Copy spi_buffer to region +void ili9341_bulk(int x, int y, int w, int h) +{ + ili9341_DMA_bulk(x, y ,w, h, spi_buffer); // Send data + ili9341_bulk_finish(); // Wait } #endif +// Copy part of spi_buffer to region, no wait completion after if buffer count !=1 +void ili9341_bulk_continue(int x, int y, int w, int h) +{ +#if DISPLAY_CELL_BUFFER_COUNT == 1 + ili9341_bulk(x, y, w, h); +#else + ili9341_bulk_finish(); // Wait DMA + ili9341_DMA_bulk(x, y , w, h, ili9341_get_cell_buffer()); // Send new cell data + LCD_dma_status^=LCD_BUFFER_1; // Switch buffer +#endif +} + #ifndef __USE_DISPLAY_DMA_RX__ -void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out) +void ili9341_read_memory(int x, int y, int w, int h, int len, pixel_t *out) { ili9341_setWindow(x, y ,w, h); send_command(ILI9341_MEMORY_READ, 0, NULL); @@ -627,7 +680,7 @@ void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out) #else // Copy screen data to buffer // Warning!!! buffer size must be greater then 3*len + 1 bytes -void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out) +void ili9341_read_memory(int x, int y, int w, int h, int len, pixel_t *out) { uint16_t dummy_tx = 0; uint8_t *rgbbuf = (uint8_t *)out; @@ -719,7 +772,7 @@ void ili9341_set_rotation(uint8_t r) } static uint8_t bit_align = 0; -void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, +void ili9341_blitBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *b) { uint16_t *buf = spi_buffer; @@ -735,25 +788,9 @@ void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height ili9341_bulk(x, y, width, height); } -#if 0 -void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, - const uint16_t *bitmap) -{ - uint16_t *buf = spi_buffer; - for (uint16_t c = 0; c < height; c++) { - uint16_t bits = *bitmap++; - for (uint16_t r = 0; r < width; r++) { - *buf++ = (0x8000 & bits) ? foreground_color : background_color; - bits <<= 1; - } - } - ili9341_bulk(x, y, width, height); -} -#endif - void ili9341_drawchar(uint8_t ch, int x, int y) { - blit8BitWidthBitmap(x, y, FONT_GET_WIDTH(ch), FONT_GET_HEIGHT, FONT_GET_DATA(ch)); + ili9341_blitBitmap(x, y, FONT_GET_WIDTH(ch), FONT_GET_HEIGHT, FONT_GET_DATA(ch)); } void ili9341_drawstring(const char *str, int x, int y) @@ -764,7 +801,7 @@ void ili9341_drawstring(const char *str, int x, int y) if (ch == '\n') {x = x_pos; y+=FONT_STR_HEIGHT; continue;} const uint8_t *char_buf = FONT_GET_DATA(ch); uint16_t w = FONT_GET_WIDTH(ch); - blit8BitWidthBitmap(x, y, w, FONT_GET_HEIGHT, char_buf); + ili9341_blitBitmap(x, y, w, FONT_GET_HEIGHT, char_buf); x += w; } } @@ -777,7 +814,7 @@ void ili9341_drawstring_7x13(const char *str, int x, int y) if (ch == '\n') {x = x_pos; y+=bFONT_STR_HEIGHT; continue;} const uint8_t *char_buf = bFONT_GET_DATA(ch); uint16_t w = bFONT_GET_WIDTH(ch); - blit8BitWidthBitmap(x, y, w, bFONT_GET_HEIGHT, char_buf); + ili9341_blitBitmap(x, y, w, bFONT_GET_HEIGHT, char_buf); x += w; } } @@ -792,7 +829,7 @@ void ili9341_drawstring_10x14(const char *str, int x, int y) const uint8_t *char_buf = wFONT_GET_DATA(ch); uint16_t w = wFONT_GET_WIDTH(ch); bit_align = (w<=8) ? 1 : 0; - blit8BitWidthBitmap(x, y, w, wFONT_GET_HEIGHT, char_buf); + ili9341_blitBitmap(x, y, w, wFONT_GET_HEIGHT, char_buf); x += w; } bit_align = 0; @@ -834,7 +871,7 @@ void ili9341_drawstring_size(const char *str, int x, int y, uint8_t size) void ili9341_drawfont(uint8_t ch, int x, int y) { - blit8BitWidthBitmap(x, y, NUM_FONT_GET_WIDTH, NUM_FONT_GET_HEIGHT, + ili9341_blitBitmap(x, y, NUM_FONT_GET_WIDTH, NUM_FONT_GET_HEIGHT, NUM_FONT_GET_DATA(ch)); } diff --git a/main.c b/main.c index ccf3628..90e9dfa 100644 --- a/main.c +++ b/main.c @@ -1019,9 +1019,9 @@ config_t config = { // NanoVNA Default settings static const trace_t def_trace[TRACES_MAX] = {//enable, type, channel, reserved, scale, refpos - { 0, TRC_LOGMAG, 0, 0, 10.0, (float) NGRIDY+1 }, //Temp - { 0, TRC_LOGMAG, 1, 0, 10.0, (float) NGRIDY+1 }, //Stored - { 1, TRC_LOGMAG, 2, 0, 10.0, (float) NGRIDY+1 } //Actual + [TRACE_TEMP] = { 0}, //Temp + [TRACE_STORED] = { 0}, //Stored + [TRACE_ACTUAL] = { 1} //Actual }; static const marker_t def_markers[MARKERS_MAX] = { @@ -1049,6 +1049,8 @@ void load_LCD_properties(void) //============================================= setting._electrical_delay = 0.0; #endif + setting.trace_scale = 10.0; + setting.trace_refpos = 0; memcpy(setting._trace, def_trace, sizeof(def_trace)); memcpy(setting._markers, def_markers, sizeof(def_markers)); #ifdef __VNA__ @@ -1064,10 +1066,10 @@ void load_LCD_properties(void) //setting.checksum = 0; } +#ifdef __VNA__ void ensure_edit_config(void) { -#ifdef __VNA__ if (active_props == ¤t_props) return; @@ -1075,8 +1077,8 @@ ensure_edit_config(void) active_props = ¤t_props; // move to uncal state cal_status = 0; -#endif } +#endif #include "sa_core.c" #ifdef __AUDIO__ @@ -1273,81 +1275,57 @@ update_frequencies(void) void set_sweep_frequency(int type, freq_t freq) { -#ifdef __VNA__ - int cal_applied = cal_status & CALSTAT_APPLY; -#endif - // Check frequency for out of bounds (minimum SPAN can be any value) if (type != ST_SPAN && freq < START_MIN) freq = START_MIN; if (freq > STOP_MAX) freq = STOP_MAX; - // CW mode if span freq = 0 - if (type == ST_SPAN && freq == 0){ - type = ST_CW; - freq = setting.frequency0 / 2 + setting.frequency1 / 2; - } - ensure_edit_config(); + bool cw_mode = FREQ_IS_CW(); // remember old mode + freq_t center, span; switch (type) { case ST_START: setting.freq_mode &= ~FREQ_MODE_CENTER_SPAN; - if (setting.frequency0 != freq) { - setting.frequency0 = freq; - // if start > stop then make start = stop - if (setting.frequency1 < freq) setting.frequency1 = freq; - } + setting.frequency0 = freq; + // if start > stop then make start = stop + if (setting.frequency1 < freq) setting.frequency1 = freq; break; case ST_STOP: setting.freq_mode &= ~FREQ_MODE_CENTER_SPAN; - if (setting.frequency1 != freq) { - setting.frequency1 = freq; - // if start > stop then make start = stop - if (setting.frequency0 > freq) setting.frequency0 = freq; - } + setting.frequency1 = freq; + // if start > stop then make start = stop + if (setting.frequency0 > freq) setting.frequency0 = freq; break; case ST_CENTER: setting.freq_mode |= FREQ_MODE_CENTER_SPAN; - freq_t center = setting.frequency0 / 2 + setting.frequency1 / 2; - if (center != freq) { - freq_t span = setting.frequency1 - setting.frequency0; - if (freq < START_MIN + span / 2) { - span = (freq - START_MIN) * 2; - } - if (freq > STOP_MAX - span / 2) { - span = (STOP_MAX - freq) * 2; - } - setting.frequency0 = freq - span / 2; - setting.frequency1 = freq + span / 2; - } + center = setting.frequency0/2 + setting.frequency1/2; + span = (setting.frequency1 - setting.frequency0)/2; + if (freq < START_MIN + span) + span = (freq - START_MIN); + if (freq > STOP_MAX - span) + span = (STOP_MAX - freq); + setting.frequency0 = freq - span; + setting.frequency1 = freq + span; break; case ST_SPAN: setting.freq_mode |= FREQ_MODE_CENTER_SPAN; - if (setting.frequency1 - setting.frequency0 != freq) { - freq_t center = setting.frequency0 / 2 + setting.frequency1 / 2; - if (center < START_MIN + freq / 2) { - center = START_MIN + freq / 2; - } - if (center > STOP_MAX - freq / 2) { - center = STOP_MAX - freq / 2; - } - setting.frequency0 = center - freq / 2; - setting.frequency1 = center + freq / 2; - } + center = setting.frequency0/2 + setting.frequency1/2; + span = freq/2; + if (center < START_MIN + span) + center = START_MIN + span; + if (center > STOP_MAX - span) + center = STOP_MAX - span; + setting.frequency0 = center - span; + setting.frequency1 = center + span; break; case ST_CW: setting.freq_mode |= FREQ_MODE_CENTER_SPAN; - if (setting.frequency0 != freq || setting.frequency1 != freq) { - setting.frequency0 = freq; - setting.frequency1 = freq; - setting.sweep_time_us = 0; // use minimum as start - } + setting.frequency0 = freq; + setting.frequency1 = freq; break; } + if (!cw_mode && FREQ_IS_CW()) // switch to CW mode + setting.sweep_time_us = 0; // use minimum as start update_frequencies(); -#ifdef __VNA__ - if (cal_auto_interpolate && cal_applied) - cal_interpolate(lastsaveid); -#endif } freq_t @@ -1825,91 +1803,24 @@ VNA_SHELL_FUNCTION(cmd_recall) shell_printf("recall {id}\r\n"); } -static const struct { - const char *name; - uint16_t refpos; - float scale_unit; -} trace_info[] = { - { "LOGMAG", NGRIDY, 10.0 }, -#ifdef __VNA__ - { "PHASE", NGRIDY/2, 90.0 }, - { "DELAY", NGRIDY/2, 1e-9 }, - { "SMITH", 0, 1.00 }, - { "POLAR", 0, 1.00 }, - { "LINEAR", 0, 0.125}, - { "SWR", 0, 0.25 }, - { "REAL", NGRIDY/2, 0.25 }, - { "IMAG", NGRIDY/2, 0.25 }, - { "R", NGRIDY/2, 100.0 }, - { "X", NGRIDY/2, 100.0 } -#endif -}; - -#ifdef __VNA__ -static const char * const trc_channel_name[] = { - "CH0", "CH1" -}; -#endif const char * const trc_channel_name[] = { - "ACTUAL", "STORED", "COMPUTED" + [TRACE_ACTUAL] = "ACTUAL", + [TRACE_STORED] = "STORED", + [TRACE_TEMP] = "COMPUTED", }; -const char *get_trace_typename(int t) -{ - return trace_info[trace[t].type].name; -} - -void set_trace_type(int t, int type) -{ - int enabled = type != TRC_OFF; - int force = FALSE; - - if (trace[t].enabled != enabled) { - trace[t].enabled = enabled; - force = TRUE; - } - if (trace[t].type != type) { - trace[t].type = type; - // Set default trace refpos - trace[t].refpos = trace_info[type].refpos; - // Set default trace scale - trace[t].scale = trace_info[type].scale_unit; - force = TRUE; - } - if (force) { - plot_into_index(measured); - redraw_request |= REDRAW_AREA; - } -} - void set_trace_scale(float scale) { - if (trace[TRACE_ACTUAL].scale != scale){ - trace[TRACE_ACTUAL].scale = scale; - trace[TRACE_STORED].scale = scale; - trace[TRACE_TEMP].scale = scale; - redraw_request |= REDRAW_AREA | REDRAW_CAL_STATUS; - } -} - -float get_trace_scale(int t) -{ - return trace[t].scale; + if (setting.trace_scale == scale) return; + setting.trace_scale = scale; + redraw_request |= REDRAW_AREA | REDRAW_CAL_STATUS; } void set_trace_refpos(float refpos) { - if (trace[TRACE_ACTUAL].refpos != refpos){ - trace[TRACE_ACTUAL].refpos = refpos; - trace[TRACE_STORED].refpos = refpos; - trace[TRACE_TEMP].refpos = refpos; - redraw_request |= REDRAW_AREA | REDRAW_CAL_STATUS; - } -} - -float get_trace_refpos(int t) -{ - return trace[t].refpos; + if (setting.trace_refpos == refpos) return; + setting.trace_refpos = refpos; + redraw_request |= REDRAW_AREA | REDRAW_CAL_STATUS; } VNA_SHELL_FUNCTION(cmd_trace) @@ -1919,9 +1830,9 @@ VNA_SHELL_FUNCTION(cmd_trace) for (t = 0; t < TRACES_MAX; t++) { if (trace[t].enabled) { const char *type = unit_string[setting.unit]; // get_trace_typename(t); - const char *channel = trc_channel_name[trace[t].channel]; - float scale = get_trace_scale(t); - float refpos = get_trace_refpos(t); + const char *channel = trc_channel_name[t]; + float scale = get_trace_scale(); + float refpos = get_trace_refpos(); shell_printf("%d %s %s %f %f\r\n", t, type, channel, scale, refpos); } } @@ -1932,8 +1843,8 @@ VNA_SHELL_FUNCTION(cmd_trace) t = my_atoi(argv[0]); if (argc != 1 || t < 0 || t >= TRACES_MAX) goto usage; - const char *type = get_trace_typename(t); - const char *channel = trc_channel_name[trace[t].channel]; + const char *type = "LOGMAG";//unit_string[setting.unit]; + const char *channel = trc_channel_name[t]; shell_printf("%d %s %s\r\n", t, type, channel); return; } diff --git a/nanovna.h b/nanovna.h index 6dfad0b..f74dcec 100644 --- a/nanovna.h +++ b/nanovna.h @@ -103,16 +103,16 @@ #define MARKER_COUNT 4 #define TRACES_MAX 3 -//#define TRACE_AGE 3 -#define TRACE_ACTUAL 2 +#define TRACE_ACTUAL 0 #define TRACE_STORED 1 -#define TRACE_TEMP 0 +#define TRACE_TEMP 2 +//#define TRACE_AGE 3 #define TRACE_INVALID -1 -// #define age_t measured[TRACE_AGE] -#define stored_t measured[TRACE_STORED] #define actual_t measured[TRACE_ACTUAL] +#define stored_t measured[TRACE_STORED] #define temp_t measured[TRACE_TEMP] +// #define age_t measured[TRACE_AGE] #ifdef TINYSA3 typedef uint32_t freq_t; @@ -423,9 +423,6 @@ extern uint16_t graph_bottom; #define WIDTH (LCD_WIDTH - 1 - OFFSETX) #define HEIGHT (GRIDY*NGRIDY) -#define CELLWIDTH (32) -#define CELLHEIGHT (32) - #define FREQUENCIES_XPOS1 OFFSETX #define FREQUENCIES_XPOS2 (LCD_WIDTH-120) #define FREQUENCIES_YPOS (LCD_HEIGHT-8) @@ -568,11 +565,6 @@ float value(float); typedef struct trace { uint8_t enabled; - uint8_t type; - uint8_t channel; - uint8_t reserved; - float scale; - float refpos; } trace_t; #define FREQ_MODE_START_STOP 0x0 @@ -633,13 +625,6 @@ extern config_t config; //#define settingLevelOffset config.level_offset float get_level_offset(void); -void set_trace_type(int t, int type); -void set_trace_channel(int t, int channel); -void set_trace_scale(float scale); -void set_trace_refpos(float refpos); -float get_trace_scale(int t); -float get_trace_refpos(int t); -const char *get_trace_typename(int t); extern int in_selftest; extern int display_test(void); @@ -723,14 +708,35 @@ extern volatile uint8_t redraw_request; /* * ili9341.c */ +// Set display buffers count for cell render (if use 2 and DMA, possible send data and prepare new in some time) + +#ifdef __USE_DISPLAY_DMA__ +// Cell size = sizeof(spi_buffer), but need wait while cell cata send to LCD +//#define DISPLAY_CELL_BUFFER_COUNT 1 +// Cell size = sizeof(spi_buffer)/2, while one cell send to LCD by DMA, CPU render to next cell +#define DISPLAY_CELL_BUFFER_COUNT 2 +#else +// Always one if no DMA mode +#define DISPLAY_CELL_BUFFER_COUNT 1 +#endif + +// One pixel size +typedef uint16_t pixel_t; + +//#define CELLWIDTH (64/DISPLAY_CELL_BUFFER_COUNT) +//#define CELLHEIGHT (32) +#define CELLWIDTH (16) +#define CELLHEIGHT (16) + +// Define size of screen buffer in pixels (one pixel 16bit size) +#define SPI_BUFFER_SIZE (CELLWIDTH*CELLHEIGHT*DISPLAY_CELL_BUFFER_COUNT*2) + // SPI bus revert byte order // 16-bit gggBBBbb RRRrrGGG #define RGB565(r,g,b) ( (((g)&0x1c)<<11) | (((b)&0xf8)<<5) | ((r)&0xf8) | (((g)&0xe0)>>5) ) #define RGBHEX(hex) ( (((hex)&0x001c00)<<3) | (((hex)&0x0000f8)<<5) | (((hex)&0xf80000)>>16) | (((hex)&0x00e000)>>13) ) #define HEXRGB(hex) ( (((hex)>>3)&0x001c00) | (((hex)>>5)&0x0000f8) | (((hex)<<16)&0xf80000) | (((hex)<<13)&0x00e000) ) -// Define size of screen buffer in pixels (one pixel 16bit size) -#define SPI_BUFFER_SIZE (CELLWIDTH*CELLHEIGHT) #ifdef TINYSA4 #define LCD_WIDTH 480 @@ -778,9 +784,9 @@ extern volatile uint8_t redraw_request; [LCD_MENU_COLOR ] = RGB565(230,230,230), \ [LCD_MENU_TEXT_COLOR ] = RGB565( 0, 0, 0), \ [LCD_MENU_ACTIVE_COLOR] = RGB565(210,210,210), \ -[LCD_TRACE_1_COLOR ] = RGB565(255, 0, 0), \ +[LCD_TRACE_1_COLOR ] = RGB565(255,255, 0), \ [LCD_TRACE_2_COLOR ] = RGB565( 0,255, 0), \ -[LCD_TRACE_3_COLOR ] = RGB565(255,255, 0), \ +[LCD_TRACE_3_COLOR ] = RGB565(255, 0, 0), \ [LCD_TRACE_4_COLOR ] = RGB565(255, 0,255), \ [LCD_NORMAL_BAT_COLOR ] = RGB565( 31,227, 0), \ [LCD_LOW_BAT_COLOR ] = RGB565(255, 0, 0), \ @@ -819,15 +825,17 @@ extern uint16_t spi_buffer[SPI_BUFFER_SIZE]; void ili9341_init(void); void ili9341_test(int mode); -void ili9341_bulk(int x, int y, int w, int h); +void ili9341_bulk(int x, int y, int w, int h); // send data to display, in DMA mode use it, but wait DMA complete +void ili9341_bulk_continue(int x, int y, int w, int h); // send data to display, in DMA mode use it, no wait DMA complete +void ili9341_bulk_finish(void); // wait DMA complete (need call at end) void ili9341_fill(int x, int y, int w, int h); +pixel_t *ili9341_get_cell_buffer(void); // get buffer for cell render void ili9341_set_foreground(uint16_t fg_idx); void ili9341_set_background(uint16_t bg_idx); void ili9341_clear_screen(void); -void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *bitmap); -void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint16_t *bitmap); +void ili9341_blitBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, const uint8_t *bitmap); void ili9341_drawchar(uint8_t ch, int x, int y); void ili9341_drawstring(const char *str, int x, int y); void ili9341_drawstring_7x13(const char *str, int x, int y); @@ -836,7 +844,7 @@ void ili9341_drawstringV(const char *str, int x, int y); int ili9341_drawchar_size(uint8_t ch, int x, int y, uint8_t size); void ili9341_drawstring_size(const char *str, int x, int y, uint8_t size); void ili9341_drawfont(uint8_t ch, int x, int y); -void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t* out); +void ili9341_read_memory(int x, int y, int w, int h, int len, pixel_t* out); void ili9341_line(int x0, int y0, int x1, int y1); void show_version(void); @@ -896,9 +904,13 @@ typedef struct setting int decay; // KM_DECAY < 1000000 int attack; // KM_ATTACK < 20000 +#ifdef TINYSA4 + int32_t slider_position; freq_t slider_span; - long_t slider_position; - +#else + int32_t slider_position; + int32_t slider_span; +#endif uint32_t rbw_x10; uint32_t vbw_x10; @@ -918,6 +930,8 @@ typedef struct setting freq_t frequency1; freq_t frequency_IF; + float trace_scale; + float trace_refpos; trace_t _trace[TRACES_MAX]; marker_t _markers[MARKERS_MAX]; @@ -942,6 +956,11 @@ extern setting_t setting; void reset_settings(int m); +void set_trace_scale(float scale); +void set_trace_refpos(float refpos); +#define get_trace_scale() setting.trace_scale +#define get_trace_refpos() setting.trace_refpos + #define S_IS_AUTO(x) ((x)&2) #define S_STATE(X) ((X)&1) enum { S_OFF=0, S_ON=1, S_AUTO_OFF=2, S_AUTO_ON=3 }; diff --git a/plot.c b/plot.c index 2ac592f..9d6fb4c 100644 --- a/plot.c +++ b/plot.c @@ -23,10 +23,8 @@ #include "chprintf.h" #include "nanovna.h" - #pragma GCC push_options -#pragma GCC optimize ("Os") // Makes the code just a bit faster, disable during debugging. - +#pragma GCC optimize ("O2") // Makes the code just a bit faster, disable during debugging. #ifdef __SCROLL__ uint16_t _grid_y = (CHART_BOTTOM / NGRIDY); @@ -49,12 +47,8 @@ uint16_t area_width = AREA_WIDTH_NORMAL; uint16_t area_height; // initialized in main() = AREA_HEIGHT_NORMAL; // Cell render use spi buffer -typedef uint16_t pixel_t; pixel_t *cell_buffer = (pixel_t *)spi_buffer; -// Cell size -// Depends from spi_buffer size, CELLWIDTH*CELLHEIGHT*sizeof(pixel) <= sizeof(spi_buffer) -//#define CELLWIDTH (64) // moved to nanovna.h -//#define CELLHEIGHT (32) + // Check buffer size #if CELLWIDTH*CELLHEIGHT > SPI_BUFFER_SIZE #error "Too small spi_buffer size SPI_BUFFER_SIZE < CELLWIDTH*CELLHEIGH" @@ -72,6 +66,27 @@ typedef uint16_t map_t; typedef uint32_t map_t; #endif +static map_t markmap[2][MAX_MARKMAP_Y+1]; +static uint8_t current_mappage = 0; + +// Trace data cache, for faster redraw cells +// Set data size types depend from screen resolution +// Set type for x resolution +#if LCD_WIDTH < 256 +typedef uint8_t index_x_t; +#else +typedef uint16_t index_x_t; +#endif +// Set type for y resolution +#if LCD_HEIGHT < 256 +typedef uint8_t index_y_t; +#else +typedef uint16_t index_y_t; +#endif + +static index_x_t trace_index_x[POINTS_COUNT]; +static index_y_t trace_index_y[TRACES_MAX][POINTS_COUNT]; + uint16_t marker_color(int mtype) { if (mtype & M_REFERENCE) @@ -96,19 +111,6 @@ char marker_letter[5] = 'T' }; -map_t markmap[2][MAX_MARKMAP_Y+1]; -uint8_t current_mappage = 0; - -// Trace data cache, for faster redraw cells -// CELL_X[16:31] x position -// CELL_Y[ 0:15] y position -typedef uint32_t index_t; -static index_t trace_index[TRACES_MAX][POINTS_COUNT]; - -#define INDEX(x, y) ((((index_t)x)<<16)|(((index_t)y))) -#define CELL_X(i) (int)(((i)>>16)) -#define CELL_Y(i) (int)(((i)&0xFFFF)) - //#define float2int(v) ((int)(v)) static int float2int(float v) @@ -156,240 +158,6 @@ void update_grid(void) redraw_request |= REDRAW_FREQUENCY | REDRAW_AREA; } -#ifdef __VNA__ -static inline int -circle_inout(int x, int y, int r) -{ - int d = x*x + y*y - r*r; - if (d < -r) - return 1; - if (d > r) - return -1; - return 0; -} - -static int -polar_grid(int x, int y) -{ - int d; - - // offset to center - x -= P_CENTER_X; - y -= P_CENTER_Y; - - // outer circle - d = circle_inout(x, y, P_RADIUS); - if (d < 0) return 0; - if (d == 0) return 1; - - // vertical and horizontal axis - if (x == 0 || y == 0) return 1; - - d = circle_inout(x, y, P_RADIUS / 5); - if (d == 0) return 1; - if (d > 0) return 0; - - d = circle_inout(x, y, P_RADIUS * 2 / 5); - if (d == 0) return 1; - if (d > 0) return 0; - - // cross sloping lines - if (x == y || x == -y) return 1; - - d = circle_inout(x, y, P_RADIUS * 3 / 5); - if (d == 0) return 1; - if (d > 0) return 0; - - d = circle_inout(x, y, P_RADIUS * 4 / 5); - if (d == 0) return 1; - return 0; -} - -/* - * 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 - */ -static int -smith_grid(int x, int y) -{ - int d; - - // offset to center - x -= P_CENTER_X; - y -= P_CENTER_Y; - - // outer circle - d = circle_inout(x, y, P_RADIUS); - if (d < 0) return 0; - if (d == 0) return 1; - - // horizontal axis - if (y == 0) return 1; - - // shift circle center to right origin - x -= P_RADIUS; - - // Constant Reactance Circle: 2j : R/2 = P_RADIUS/2 - if (circle_inout(x, y + P_RADIUS / 2, P_RADIUS / 2) == 0) return 1; - if (circle_inout(x, y - P_RADIUS / 2, P_RADIUS / 2) == 0) return 1; - - // Constant Resistance Circle: 3 : R/4 = P_RADIUS/4 - d = circle_inout(x + P_RADIUS / 4, y, P_RADIUS / 4); - if (d > 0) return 0; - if (d == 0) return 1; - - // Constant Reactance Circle: 1j : R = P_RADIUS - if (circle_inout(x, y + P_RADIUS, P_RADIUS) == 0) return 1; - if (circle_inout(x, y - P_RADIUS, P_RADIUS) == 0) return 1; - - // Constant Resistance Circle: 1 : R/2 - d = circle_inout(x + P_RADIUS / 2, y, P_RADIUS / 2); - if (d > 0) return 0; - if (d == 0) return 1; - - // Constant Reactance Circle: 1/2j : R*2 - if (circle_inout(x, y + P_RADIUS * 2, P_RADIUS * 2) == 0) return 1; - if (circle_inout(x, y - P_RADIUS * 2, P_RADIUS * 2) == 0) return 1; - - // Constant Resistance Circle: 1/3 : R*3/4 - if (circle_inout(x + P_RADIUS * 3 / 4, y, P_RADIUS * 3 / 4) == 0) return 1; - return 0; -} - -#if 0 -static int -smith_grid2(int x, int y, float scale) -{ - int d; - - // offset to center - x -= P_CENTER_X; - y -= P_CENTER_Y; - - // outer circle - d = circle_inout(x, y, P_RADIUS); - if (d < 0) - return 0; - if (d == 0) - return 1; - - // shift circle center to right origin - x -= P_RADIUS * scale; - - // Constant Reactance Circle: 2j : R/2 = 58 - if (circle_inout(x, y+58*scale, 58*scale) == 0) - return 1; - if (circle_inout(x, y-58*scale, 58*scale) == 0) - return 1; -#if 0 - // Constant Resistance Circle: 3 : R/4 = 29 - d = circle_inout(x+29*scale, y, 29*scale); - if (d > 0) return 0; - if (d == 0) return 1; - d = circle_inout(x-29*scale, y, 29*scale); - if (d > 0) return 0; - if (d == 0) return 1; -#endif - - // Constant Reactance Circle: 1j : R = 116 - if (circle_inout(x, y+116*scale, 116*scale) == 0) - return 1; - if (circle_inout(x, y-116*scale, 116*scale) == 0) - return 1; - - // Constant Resistance Circle: 1 : R/2 = 58 - d = circle_inout(x+58*scale, y, 58*scale); - if (d > 0) return 0; - if (d == 0) return 1; - d = circle_inout(x-58*scale, y, 58*scale); - if (d > 0) return 0; - if (d == 0) return 1; - - // Constant Reactance Circle: 1/2j : R*2 = 232 - if (circle_inout(x, y+232*scale, 232*scale) == 0) - return 1; - if (circle_inout(x, y-232*scale, 232*scale) == 0) - return 1; - -#if 0 - // Constant Resistance Circle: 1/3 : R*3/4 = 87 - d = circle_inout(x+87*scale, y, 87*scale); - if (d > 0) return 0; - if (d == 0) return 1; - d = circle_inout(x+87*scale, y, 87*scale); - if (d > 0) return 0; - if (d == 0) return 1; -#endif - - // Constant Resistance Circle: 0 : R - d = circle_inout(x+P_RADIUS*scale, y, P_RADIUS*scale); - if (d > 0) return 0; - if (d == 0) return 1; - d = circle_inout(x-P_RADIUS*scale, y, P_RADIUS*scale); - if (d > 0) return 0; - if (d == 0) return 1; - - // Constant Resistance Circle: -1/3 : R*3/2 = 174 - d = circle_inout(x+174*scale, y, 174*scale); - if (d > 0) return 0; - if (d == 0) return 1; - d = circle_inout(x-174*scale, y, 174*scale); - //if (d > 0) return 0; - if (d == 0) return 1; - return 0; -} -#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 - { 0, 115/2, 115/2, 0 }, // Constant Reactance Circle: 1j : R = 115 - { 58/2, 0, 58/2, 1 }, // Constant Resistance Circle: 1 : R/2 = 58 - { 0, 230/2, 230/2, 0 }, // Constant Reactance Circle: 1/2j : R*2 = 230 - { 86/2, 0, 86/2, 1 }, // Constant Resistance Circle: 1/3 : R*3/4 = 86 - { 0, 460/2, 460/2, 0 }, // Constant Reactance Circle: 1/4j : R*4 = 460 - { 115/2, 0, 115/2, 1 }, // Constant Resistance Circle: 0 : R - { 173/2, 0, 173/2, 1 }, // Constant Resistance Circle: -1/3 : R*3/2 = 173 - { 0, 0, 0, 0 } // sentinel -}; - -static int -smith_grid3(int x, int y) -{ - int d; - - // offset to center - x -= P_CENTER_X; - y -= P_CENTER_Y; - - // outer circle - d = circle_inout(x, y, P_RADIUS); - if (d < 0) - return 0; - if (d == 0) - return 1; - - // shift circle center to right origin - x -= P_RADIUS /2; - - int i; - for (i = 0; cirs[i][2]; i++) { - d = circle_inout(x+cirs[i][0], y+cirs[i][1], cirs[i][2]); - if (d == 0) - return 1; - if (d > 0 && cirs[i][3]) - return 0; - d = circle_inout(x-cirs[i][0], y-cirs[i][1], cirs[i][2]); - if (d == 0) - return 1; - if (d > 0 && cirs[i][3]) - return 0; - } - return 0; -} -#endif -#endif #if 0 static int rectangular_grid(int x, int y) @@ -523,8 +291,6 @@ draw_on_strut(int v0, int d, int color) /* * calculate log10f(abs(gamma)) */ - - float index_to_value(const int i) { @@ -555,7 +321,6 @@ value(const float v) } // case U_DBM: return v; // raw data is in logmag*10 format - } float @@ -581,329 +346,24 @@ to_dBm(const float v) } // case U_DBM: return v; // raw data is in logmag*10 format - -} - - -#ifdef __VNA_ -/* - * calculate phase[-2:2] of coefficient - */ -static float -phase(const float *v) -{ - return 2 * atan2f(v[1], v[0]) / VNA_PI * 90; -} - -/* - * calculate groupdelay - */ -static float -groupdelay(const float *v, const float *w, float deltaf) -{ -#if 1 - // atan(w)-atan(v) = atan((w-v)/(1+wv)) - float r = w[0]*v[1] - w[1]*v[0]; - float i = w[0]*v[0] + w[1]*v[1]; - return atan2f(r, i) / (2 * VNA_PI * deltaf); -#else - return (atan2f(w[0], w[1]) - atan2f(v[0], v[1])) / (2 * VNA_PI * deltaf); -#endif -} - -/* - * calculate abs(gamma) - */ -static float -linear(const float *v) -{ - return - sqrtf(v[0]*v[0] + v[1]*v[1]); -} - -/* - * calculate vswr; (1+gamma)/(1-gamma) - */ -static float -swr(const float *v) -{ - float x = sqrtf(v[0]*v[0] + v[1]*v[1]); - if (x >= 1) - return INFINITY; - return (1 + x)/(1 - x); } -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; -} - -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; +static inline index_x_t +trace_into_index_x(int i){ + return (i * (WIDTH) + (sweep_points-1)/2) / (sweep_points-1) + CELLOFFSETX; } -static void -cartesian_scale(float re, float im, int *xp, int *yp, float scale) +static index_y_t +trace_into_index_y(float coeff) { - //float scale = 4e-3; - int x = float2int(re * P_RADIUS * scale); - int y = float2int(im * P_RADIUS * scale); - 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; -} - -float -groupdelay_from_array(int i, float array[POINTS_COUNT][2]) -{ - int bottom = (i == 0) ? 0 : i - 1; - int top = (i == sweep_points-1) ? sweep_points-1 : i + 1; - float deltaf = frequencies[top] - frequencies[bottom]; - return groupdelay(array[bottom], array[top], deltaf); -} - -static float -gamma2resistance(const float v[2]) -{ - float z0 = 50; - float d = z0 / ((1-v[0])*(1-v[0])+v[1]*v[1]); - return ((1+v[0])*(1-v[0]) - v[1]*v[1]) * d; -} - -static float -gamma2reactance(const float v[2]) -{ - float z0 = 50; - float d = z0 / ((1-v[0])*(1-v[0])+v[1]*v[1]); - return 2*v[1] * d; -} -#endif - -static index_t -trace_into_index(int t, int i, float array[POINTS_COUNT]) -{ - int y, x; - float coeff = array[i]; - float refpos = get_trace_refpos(t); - float v=0; - float scale = get_trace_scale(t); - - switch (trace[t].type) { - case TRC_LOGMAG: - v = ( refpos - value(coeff) ) / scale; - break; -#ifdef __VNA__ - case TRC_PHASE: - v-= phase(coeff) * scale; - break; - case TRC_DELAY: - v-= groupdelay_from_array(i, array) * scale; - break; - case TRC_LINEAR: - v+= linear(coeff) * scale; - break; - case TRC_SWR: - v+= (1 - swr(coeff)) * scale; - break; - case TRC_REAL: - v-= coeff[0] * scale; - break; - case TRC_IMAG: - v-= coeff[1] * scale; - break; - case TRC_R: - v-= resitance(coeff) * scale; - break; - case TRC_X: - v-= reactance(coeff) * scale; - break; - case TRC_SMITH: - //case TRC_ADMIT: - case TRC_POLAR: - cartesian_scale(coeff[0], coeff[1], &x, &y, scale); - goto set_index; -#endif - } + float refpos = get_trace_refpos(); + float scale = get_trace_scale(); + float v = (refpos - value(coeff)) / scale; if (v < 0) v = 0; if (v > NGRIDY) v = NGRIDY; - x = (i * (WIDTH) + (sweep_points-1)/2) / (sweep_points-1) + CELLOFFSETX; - y = float2int(v * GRIDY); -// set_index: - return INDEX(x, y); -} - -#ifdef __VNA__ -static void -format_smith_value(char *buf, int len, const float coeff[2], uint32_t frequency) -{ - // z = (gamma+1)/(gamma-1) * z0 - float z0 = 50; - float d = z0 / ((1-coeff[0])*(1-coeff[0])+coeff[1]*coeff[1]); - float zr = ((1+coeff[0])*(1-coeff[0]) - coeff[1]*coeff[1]) * d; - float zi = 2*coeff[1] * d; - char prefix; - float value; - switch (marker_smith_format) { - case MS_LIN: - plot_printf(buf, len, "%.2f %.1f" S_DEGREE, linear(coeff), phase(coeff)); - break; - - case MS_LOG: { - float v = logmag(coeff); - if (v == -INFINITY) - plot_printf(buf, len, "-"S_INFINITY" dB"); - else - plot_printf(buf, len, "%.1fdB %.1f" S_DEGREE, v, phase(coeff)); - } - break; - case MS_REIM: - plot_printf(buf, len, "%F%+Fj", coeff[0], coeff[1]); - break; - - case MS_RX: - plot_printf(buf, len, "%F"S_OHM"%+Fj", zr, zi); - break; - - case MS_RLC: - if (zi < 0) {// Capacity - prefix = 'F'; - value = -1 / (2 * VNA_PI * frequency * zi); - } else { - prefix = 'H'; - value = zi / (2 * VNA_PI * frequency); - } - plot_printf(buf, len, "%F"S_OHM" %F%c", zr, value, prefix); - break; - } -} -#endif - -#ifdef __VNA__ -static void -trace_get_value_string(int t, char *buf, int len, float array[POINTS_COUNT][2], int i) -{ - float *coeff = array[i]; - float v; - char *format; - switch (trace[t].type) { - case TRC_LOGMAG: - format = "%.2fdB"; - v = logmag(coeff); - break; - case TRC_PHASE: - format = "%.1f"S_DEGREE; - v = phase(coeff); - break; - case TRC_DELAY: - format = "%.2Fs"; - v = groupdelay_from_array(i, array); - break; - case TRC_LINEAR: - format = "%.4f"; - v = linear(coeff); - break; - case TRC_SWR: - format = "%.4f"; - v = swr(coeff); - break; - case TRC_REAL: - format = "%.4f"; - v = coeff[0]; - break; - case TRC_IMAG: - format = "%.4fj"; - v = coeff[1]; - break; - case TRC_R: - format = "%.2F"S_OHM; - v = gamma2resistance(coeff); - break; - case TRC_X: - format = "%.2F"S_OHM; - v = gamma2reactance(coeff); - break; - case TRC_SMITH: - format_smith_value(buf, len, coeff, frequencies[i]); - return; - //case TRC_ADMIT: - case TRC_POLAR: - plot_printf(buf, len, "%.2f%+.2fj", coeff[0], coeff[1]); - default: - return; - } - plot_printf(buf, len, format, v); -} - -static void -trace_get_value_string_delta(int t, char *buf, int len, float array[POINTS_COUNT][2], int index, int index_ref) -{ - float *coeff = array[index]; - float *coeff_ref = array[index_ref]; - float v; - char *format; - switch (trace[t].type) { - case TRC_LOGMAG: - format = S_DELTA"%.2fdB"; - v = logmag(coeff) - logmag(coeff_ref); - break; - case TRC_PHASE: - format = S_DELTA"%.2f"S_DEGREE; - v = phase(coeff) - phase(coeff_ref); - break; - case TRC_DELAY: - format = "%.2Fs"; - v = groupdelay_from_array(index, array) - groupdelay_from_array(index_ref, array); - break; - case TRC_LINEAR: - format = S_DELTA"%.3f"; - v = linear(coeff) - linear(coeff_ref); - break; - case TRC_SWR: - format = S_DELTA"%.3f"; - v = swr(coeff); - if (v != INFINITY) v -= swr(coeff_ref); - break; - case TRC_SMITH: - format_smith_value(buf, len, coeff, frequencies[index]); - return; - case TRC_REAL: - format = S_DELTA"%.3f"; - v = coeff[0] - coeff_ref[0]; - break; - case TRC_IMAG: - format = S_DELTA"%.3fj"; - v = coeff[1] - coeff_ref[1]; - break; - case TRC_R: - format = "%.2F"S_OHM; - v = gamma2resistance(coeff); - break; - case TRC_X: - format = "%.2F"S_OHM; - v = gamma2reactance(coeff); - break; - //case TRC_ADMIT: - case TRC_POLAR: - plot_printf(buf, len, "%.2f%+.2fj", coeff[0], coeff[1]); - return; - default: - return; - } - plot_printf(buf, len, format, v); + return float2int(v * GRIDY); } -#endif void trace_get_value_string( // Only used at one place int t, char *buf, int len, @@ -989,43 +449,6 @@ void trace_get_value_string( // Only used at one place } } -#ifdef __VNA__ -static int -trace_get_info(int t, char *buf, int len) -{ - const char *name = get_trace_typename(t); - float scale = get_trace_scale(t); - switch (trace[t].type) { - case TRC_LOGMAG: - return plot_printf(buf, len, "%s %ddB/", name, (int)scale); - case TRC_PHASE: - return plot_printf(buf, len, "%s %d" S_DEGREE "/", name, (int)scale); - case TRC_SMITH: - //case TRC_ADMIT: - case TRC_POLAR: - if (scale != 1.0) - return plot_printf(buf, len, "%s %.1fFS", name, scale); - else - return plot_printf(buf, len, "%s ", name); - default: - return plot_printf(buf, len, "%s %F/", name, scale); - } - return 0; -} - -static float time_of_index(int idx) -{ - return 1.0 / (float)(frequencies[1] - frequencies[0]) / (float)FFT_SIZE * idx; -} - -static float distance_of_index(int idx) -{ - float distance = ((float)idx * (float)SPEED_OF_LIGHT) / - ((float)(frequencies[1] - frequencies[0]) * (float)FFT_SIZE * 2.0); - return distance * velocity_factor; -} -#endif - static inline void swap_markmap(void) { @@ -1059,25 +482,24 @@ invalidate_rect_func(int x0, int y0, int x1, int y1) } #define invalidate_rect(x0, y0, x1, y1) invalidate_rect_func((x0)/CELLWIDTH, (y0)/CELLHEIGHT, (x1)/CELLWIDTH, (y1)/CELLHEIGHT) - #define SWAP(x,y) {int t=x;x=y;y=t;} - static void mark_cells_from_index(void) { int t, i, j; /* mark cells between each neighber points */ map_t *map = &markmap[current_mappage][0]; + index_x_t *index_x = trace_index_x; for (t = 0; t < TRACES_MAX; t++) { if (!trace[t].enabled) continue; - index_t *index = trace_index[t]; - int m0 = CELL_X(index[0]) / CELLWIDTH; - int n0 = CELL_Y(index[0]) / CELLHEIGHT; + index_y_t *index_y = trace_index_y[t]; + int m0 = index_x[0] / CELLWIDTH; + int n0 = index_y[0] / CELLHEIGHT; map[n0] |= 1 << m0; for (i = 1; i < sweep_points; i++) { - int m1 = CELL_X(index[i]) / CELLWIDTH; - int n1 = CELL_Y(index[i]) / CELLHEIGHT; + int m1 = index_x[i] / CELLWIDTH; + int n1 = index_y[i] / CELLHEIGHT; if (m0 == m1 && n0 == n1) continue; int x0 = m0; int x1 = m1; if (x0>x1) SWAP(x0, x1); m0 = m1; @@ -1097,14 +519,13 @@ markmap_upperarea(void) } static uint16_t get_trigger_level(void){ - index_t idx = trace_into_index(TRACE_ACTUAL, 0, &setting.trigger_level); - return CELL_Y(idx); + return trace_into_index_y(setting.trigger_level); } static inline void markmap_trigger_area(void){ uint16_t tp = get_trigger_level(); - markmap[current_mappage][tp/CELLWIDTH] = 0xFFFF; + markmap[current_mappage][tp/CELLWIDTH] = (map_t)0xFFFFFFFF; } // @@ -1119,36 +540,47 @@ cell_drawline(int x0, int y0, int x1, int y1, int c) if (y0 >= CELLHEIGHT && y1 >= CELLHEIGHT) return; // modifed Bresenham's line algorithm, see https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm - if (x1 < x0) { SWAP(x0, x1); SWAP(y0, y1); } - int dx = x1 - x0; - int dy = y1 - y0, sy = 1; if (dy < 0) { dy = -dy; sy = -1; } - int err = (dx > dy ? dx : -dy) / 2; - + // Draw from top to bottom (most graph contain vertical lines) + if (y1 < y0) { SWAP(x0, x1); SWAP(y0, y1); } + int dx =-(x1 - x0), sx = 1; if (dx > 0) { dx = -dx; sx = -sx; } + int dy = (y1 - y0); + int err = ((dy + dx) < 0 ? -dx : -dy) / 2; + // Fast skip points while y0 < 0 + if (y0 < 0){ + while(1){ + int e2 = err; + if (e2 > dx) { err-= dy; x0+=sx;} + if (e2 < dy) { err-= dx; y0++; if (y0 == 0) break;} + } + } + // align y by CELLWIDTH for faster calculations + y0*=CELLWIDTH; + y1*=CELLWIDTH; while (1) { - if (y0 >= 0 && y0 < CELLHEIGHT && x0 >= 0 && x0 < CELLWIDTH) - cell_buffer[y0 * CELLWIDTH + x0] |= c; + if ((uint32_t)x0 < CELLWIDTH) + cell_buffer[y0 + x0]|= c; if (x0 == x1 && y0 == y1) return; int e2 = err; - if (e2 > -dx) { err -= dy; x0++; } - if (e2 < dy) { err += dx; y0+=sy;} + if (e2 > dx) { err-= dy; x0+=sx;} + if (e2 < dy) { err-= dx; y0+=CELLWIDTH; if (y0>=CELLHEIGHT*CELLWIDTH) return;} // stop after cell bottom } } // Give a little speedup then draw rectangular plot (50 systick on all calls, all render req 700 systick) // Write more difficult algoritm for seach indexes not give speedup static int -search_index_range_x(int x1, int x2, index_t index[POINTS_COUNT], int *i0, int *i1) +search_index_range_x(int x1, int x2, int *i0, int *i1) { int i, j; int head = 0; int tail = sweep_points; int idx_x; - + index_x_t *index_x = trace_index_x; // Search index point in cell while (1) { i = (head + tail) / 2; - idx_x = CELL_X(index[i]); + idx_x = index_x[i]; if (idx_x >= x2) { // index after cell if (tail == i) return false; @@ -1166,12 +598,12 @@ search_index_range_x(int x1, int x2, index_t index[POINTS_COUNT], int *i0, int * // Search index left from point do { j--; - } while (j > 0 && x1 <= CELL_X(index[j])); + } while (j > 0 && x1 <= index_x[j]); *i0 = j; // Search index right from point do { i++; - } while (i < sweep_points-1 && CELL_X(index[i]) < x2); + } while (i < sweep_points-1 && index_x[i] < x2); *i1 = i; return TRUE; @@ -1338,17 +770,14 @@ static const uint8_t marker_bitmap[]={ static void markmap_marker(int marker) { - int t; if (!markers[marker].enabled) return; - for (t = TRACE_ACTUAL; t <= TRACE_ACTUAL; t++) { - if (!trace[t].enabled) - continue; - index_t index = trace_index[t][markers[marker].index]; - int x = CELL_X(index) - X_MARKER_OFFSET; - int y = CELL_Y(index) - Y_MARKER_OFFSET; - invalidate_rect(x, y, x+MARKER_WIDTH-1, y+MARKER_HEIGHT-1); - } + if (!trace[TRACE_ACTUAL].enabled) + return; + int idx = markers[marker].index; + int x = trace_index_x[idx] - X_MARKER_OFFSET; + int y = trace_index_y[TRACE_ACTUAL][idx] - Y_MARKER_OFFSET; + invalidate_rect(x, y, x+MARKER_WIDTH-1, y+MARKER_HEIGHT-1); } void @@ -1366,9 +795,8 @@ markmap_all_markers(void) int distance_to_index(int8_t t, uint16_t idx, int16_t x, int16_t y) { - index_t *index = trace_index[t]; - x-= CELL_X(index[idx]); - y-= CELL_Y(index[idx]); + x-= trace_index_x[idx]; + y-= trace_index_y[t][idx]; return x*x + y*y; } @@ -1393,21 +821,18 @@ plot_into_index(measurement_t measured) { int t, i; // START_PROFILE + index_x_t *index_x = trace_index_x; + for (i = 0; i < sweep_points; i++) + index_x[i] = trace_into_index_x(i); + for (t = 0; t < TRACES_MAX; t++) { if (!trace[t].enabled) continue; - int ch = trace[t].channel; - index_t *index = trace_index[t]; + index_y_t *index_y = trace_index_y[t]; for (i = 0; i < sweep_points; i++) - index[i] = trace_into_index(t, i, measured[ch]); + index_y[i] = trace_into_index_y(measured[t][i]); } // STOP_PROFILE -#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(); } @@ -1420,7 +845,7 @@ draw_cell(int m, int n) int w = CELLWIDTH; int h = CELLHEIGHT; int x, y; - int i0, i1, i; + int i; int t; uint16_t c; // Clip cell by area @@ -1431,7 +856,7 @@ draw_cell(int m, int n) if (w <= 0 || h <= 0) return; // PULSE; - + cell_buffer = ili9341_get_cell_buffer(); // Clear buffer ("0 : height" lines) #if 0 // use memset 350 system ticks for all screen calls @@ -1462,7 +887,7 @@ draw_cell(int m, int n) uint32_t trace_type = 0; for (t = 0; t < TRACES_MAX; t++) { if (trace[t].enabled) { - trace_type |= (1 << trace[t].type); + trace_type |= RECTANGULAR_GRID_MASK; } } // Draw rectangular plot (40 system ticks for all screen calls) @@ -1485,29 +910,7 @@ draw_cell(int m, int n) } } } -#ifdef __VNA__ - // Smith greed line (1000 system ticks for all screen calls) - if (trace_type & (1 << TRC_SMITH)) { - for (y = 0; y < h; y++) - for (x = 0; x < w; x++) - if (smith_grid(x + x0, y + y0)) cell_buffer[y * CELLWIDTH + x] = c; - } - // Polar greed line (800 system ticks for all screen calls) - else if (trace_type & (1 << TRC_POLAR)) { - for (y = 0; y < h; y++) - for (x = 0; x < w; x++) - if (polar_grid(x + x0, y + y0)) cell_buffer[y * CELLWIDTH + x] = c; - } -#if 0 - else if (trace_type & (1 << TRC_ADMIT)) { - for (y = 0; y < h; y++) - for (x = 0; x < w; x++) - if (smith_grid3(x+x0, y+y0) - // smith_grid2(x+x0, y+y0, 0.5)) - cell_buffer[y * CELLWIDTH + x] = c; - } -#endif -#endif + // PULSE; #endif // Draw trigger line @@ -1515,7 +918,7 @@ draw_cell(int m, int n) int tp = get_trigger_level() - y0; if (tp>=0 && tp < h) for (x = 0; x < w; x++) - if (x + x0 >= CELLOFFSETX && x + x0 <= WIDTH + CELLOFFSETX) + if ((uint32_t)(x + x0 - CELLOFFSETX) <= WIDTH + CELLOFFSETX) cell_buffer[tp * CELLWIDTH + x] = LCD_TRIGGER_COLOR; } @@ -1528,25 +931,20 @@ draw_cell(int m, int n) // Draw traces (50-600 system ticks for all screen calls, depend from lines // count and size) #if 1 + int i0 = 0; + int i1 = 0; + index_x_t *index_x = trace_index_x; + search_index_range_x(x0, x0 + w, &i0, &i1); for (t = 0; t < TRACES_MAX; t++) { if (!trace[t].enabled) continue; c = GET_PALTETTE_COLOR(LCD_TRACE_1_COLOR + t); - // draw polar plot (check all points) - i0 = 0; - i1 = 0; - uint32_t trace_type = (1 << trace[t].type); - if (trace_type & ((1 << TRC_SMITH) | (1 << TRC_POLAR))) - i1 = sweep_points - 1; - else // draw rectangular plot (search index range in cell, save 50-70 - // system ticks for all screen calls) - search_index_range_x(x0, x0 + w, trace_index[t], &i0, &i1); - index_t *index = trace_index[t]; + index_y_t *index_y = trace_index_y[t]; for (i = i0; i < i1; i++) { - int x1 = CELL_X(index[i]) - x0; - int y1 = CELL_Y(index[i]) - y0; - int x2 = CELL_X(index[i + 1]) - x0; - int y2 = CELL_Y(index[i + 1]) - y0; + int x1 = index_x[i ] - x0; + int x2 = index_x[i+1] - x0; + int y1 = index_y[i ] - y0; + int y2 = index_y[i+1] - y0; cell_drawline(x1, y1, x2, y2, c); } } @@ -1558,27 +956,24 @@ draw_cell(int m, int n) // PULSE; // draw marker symbols on each trace (<10 system ticks for all screen calls) #if 1 - for (i = 0; i < MARKERS_MAX; i++) { - if (!markers[i].enabled) - continue; -// for (t = 0; t < TRACES_MAX; t++) { -// if (!trace[t].enabled) -// continue; - t = TRACE_ACTUAL; - index_t index = trace_index[t][markers[i].index]; - int x = CELL_X(index) - x0 - X_MARKER_OFFSET; - int y = CELL_Y(index) - y0 - Y_MARKER_OFFSET; + if (trace[TRACE_ACTUAL].enabled) { + for (i = 0; i < MARKERS_MAX; i++) { + if (!markers[i].enabled) + continue; + int idx = markers[i].index; + int x = trace_index_x[idx] - x0 - X_MARKER_OFFSET; + int y = trace_index_y[TRACE_ACTUAL][idx] - y0 - Y_MARKER_OFFSET; // Check marker icon on cell if ((uint32_t)(x+MARKER_WIDTH ) < (CELLWIDTH + MARKER_WIDTH ) && (uint32_t)(y+MARKER_HEIGHT) < (CELLHEIGHT + MARKER_HEIGHT)){ // Draw marker plate - ili9341_set_foreground(LCD_TRACE_1_COLOR + t); + ili9341_set_foreground(LCD_TRACE_1_COLOR + TRACE_ACTUAL); cell_blit_bitmap(x, y, MARKER_WIDTH, MARKER_HEIGHT, MARKER_BITMAP(0)); // Draw marker number ili9341_set_foreground(LCD_BG_COLOR); cell_blit_bitmap(x, y, MARKER_WIDTH, MARKER_HEIGHT, MARKER_BITMAP(i+1)); } -// } + } } #endif // Draw trace and marker info on the top (50 system ticks for all screen calls) @@ -1619,47 +1014,49 @@ draw_cell(int m, int n) } #endif // Draw cell (500 system ticks for all screen calls) - ili9341_bulk(OFFSETX + x0, OFFSETY + y0, w, h); + ili9341_bulk_continue(OFFSETX + x0, OFFSETY + y0, w, h); } -extern float peakLevel; -extern float min_level; -int w_max = -130; -int w_min = 0; - - static void draw_all_cells(bool flush_markmap) { int m, n; // START_PROFILE for (m = 0; m < (area_width+CELLWIDTH-1) / CELLWIDTH; m++) - for (n = 0; n < (area_height+CELLHEIGHT-1) / CELLHEIGHT; n++) { - if ((markmap[0][n] | markmap[1][n]) & (1 << m)) { + for (n = 0; n < (area_height+CELLHEIGHT-1) / CELLHEIGHT; n++) + if ((markmap[0][n] | markmap[1][n]) & (1 << m)) draw_cell(m, n); -// ili9341_fill(m*CELLWIDTH+10, n*CELLHEIGHT, 2, 2, RGB565(255,0,0)); - } -// else -// ili9341_fill(m*CELLWIDTH+10, n*CELLHEIGHT, 2, 2, RGB565(0,255,0)); +#if 0 + // Used for debug control cell update + ili9341_bulk_finish(); + for (m = 0; m < (area_width+CELLWIDTH-1) / CELLWIDTH; m++) + for (n = 0; n < (area_height+CELLHEIGHT-1) / CELLHEIGHT; n++) { + ili9341_set_background(((markmap[0][n] | markmap[1][n]) & (1 << m)) ? LCD_LOW_BAT_COLOR : LCD_NORMAL_BAT_COLOR); + ili9341_fill(m*CELLWIDTH+OFFSETX, n*CELLHEIGHT, 2, 2); } -// STOP_PROFILE +#endif if (flush_markmap) { // keep current map for update swap_markmap(); // clear map for next plotting clear_markmap(); } + // Flush LCD buffer, wait completion (need call after end use ili9341_bulk_continue mode) + ili9341_bulk_finish(); +// STOP_PROFILE } void draw_all(bool flush) { - if (redraw_request & REDRAW_AREA) + if (redraw_request & REDRAW_AREA) // this set all area for update force_set_markmap(); - if (redraw_request & REDRAW_MARKER) - markmap_upperarea(); - if (redraw_request & REDRAW_TRIGGER) - markmap_trigger_area(); + else { + if (redraw_request & REDRAW_MARKER) // update marker area + markmap_upperarea(); + if (redraw_request & REDRAW_TRIGGER) // update trigger area + markmap_trigger_area(); + } if (redraw_request & (REDRAW_CELLS | REDRAW_MARKER | REDRAW_AREA | REDRAW_TRIGGER)){ draw_all_cells(flush); #ifdef __SCROLL__ @@ -1828,134 +1225,6 @@ cell_drawstring_size(char *str, int x, int y, int size) } #endif -#ifdef __VNA__ -static void -cell_draw_marker_info(int x0, int y0) -{ - char buf[24]; - int t; - if (active_marker < 0) - return; - int idx = markers[active_marker].index; - int j = 0; - if (previous_marker != -1 && uistat.current_trace != -1) { - int t = uistat.current_trace; - int mk; - for (mk = 0; mk < MARKERS_MAX; mk++) { - if (!markers[mk].enabled) - continue; - int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0; - int ypos = 1 + (j/2)*(FONT_GET_HEIGHT+1) - y0; - - ili9341_set_foreground(GET_PALTETTE_COLOR(LCD_TRACE_1_COLOR + t)); - if (mk == active_marker) - cell_drawstring(S_SARROW, xpos, ypos); - xpos += 5; - plot_printf(buf, sizeof buf, "M%d", mk+1); - cell_drawstring(buf, xpos, ypos); - xpos += 13; - //trace_get_info(t, buf, sizeof buf); - freq_t freq = frequencies[markers[mk].index]; - if (uistat.marker_delta && mk != active_marker) { - freq_t freq1 = frequencies[markers[active_marker].index]; - freq_t delta = freq > freq1 ? freq - freq1 : freq1 - freq; - plot_printf(buf, sizeof buf, S_DELTA"%.9qHz", delta); - } else { - plot_printf(buf, sizeof buf, "%.10qHz", freq); - } - cell_drawstring(buf, xpos, ypos); - xpos += 67; - if (uistat.marker_delta && mk != active_marker) - trace_get_value_string_delta(t, buf, sizeof buf, measured[trace[t].channel], markers[mk].index, markers[active_marker].index); - else - trace_get_value_string(t, buf, sizeof buf, measured[trace[t].channel], markers[mk].index); - ili9341_set_foreground(LCD_FG_COLOR); - cell_drawstring(buf, xpos, ypos); - j++; - } - - // draw marker delta - if (!uistat.marker_delta && previous_marker >= 0 && active_marker != previous_marker && markers[previous_marker].enabled) { - int idx0 = markers[previous_marker].index; - int xpos = (WIDTH/2+30) + CELLOFFSETX - x0; - int ypos = 1 + (j/2)*(FONT_GET_HEIGHT+1) - y0; - - plot_printf(buf, sizeof buf, S_DELTA"%d-%d:", active_marker+1, previous_marker+1); - ili9341_set_foreground(LCD_FG_COLOR); - cell_drawstring(buf, xpos, ypos); - xpos += 27; - if ((domain_mode & DOMAIN_MODE) == DOMAIN_FREQ) { - freq_t freq = frequencies[idx]; - freq_t freq1 = frequencies[idx0]; - freq_t delta = freq > freq1 ? freq - freq1 : freq1 - freq; - plot_printf(buf, sizeof buf, "%c%.13qHz", freq >= freq1 ? '+' : '-', delta); - } else { - plot_printf(buf, sizeof buf, "%Fs (%Fm)", time_of_index(idx) - time_of_index(idx0), distance_of_index(idx) - distance_of_index(idx0)); - } - cell_drawstring(buf, xpos, ypos); - } - } else { - for (t = 0; t < TRACES_MAX; t++) { - if (!trace[t].enabled) - continue; - int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0; - int ypos = 1 + (j/2)*(FONT_GET_HEIGHT+1) - y0; - - ili9341_set_foreground(GET_PALTETTE_COLOR(LCD_TRACE_1_COLOR + t)); - if (t == uistat.current_trace) - cell_drawstring(S_SARROW, xpos, ypos); - xpos += 5; - plot_printf(buf, sizeof buf, "CH%d", trace[t].channel); - cell_drawstring(buf, xpos, ypos); - xpos += 19; - - int n = trace_get_info(t, buf, sizeof buf); - cell_drawstring(buf, xpos, ypos); - xpos += n * 5 + 2; - //xpos += 60; - trace_get_value_string(t, buf, sizeof buf, measured[trace[t].channel], idx); - ili9341_set_foreground(LCD_FG_COLOR); - cell_drawstring(buf, xpos, ypos); - j++; - } - - // draw marker frequency - int xpos = (WIDTH/2+40) + CELLOFFSETX - x0; - int ypos = 1 + (j/2)*(FONT_GET_HEIGHT+1) - y0; - - ili9341_set_foreground(LCD_FG_COLOR); - if (uistat.lever_mode == LM_MARKER) - cell_drawstring(S_SARROW, xpos, ypos); - xpos += 5; - plot_printf(buf, sizeof buf, "M%d:", active_marker+1); - cell_drawstring(buf, xpos, ypos); - xpos += 19; - - if ((domain_mode & DOMAIN_MODE) == DOMAIN_FREQ) { - plot_printf(buf, sizeof buf, "%qHz", frequencies[idx]); - } else { - plot_printf(buf, sizeof buf, "%Fs (%Fm)", time_of_index(idx), distance_of_index(idx)); - } - cell_drawstring(buf, xpos, ypos); - } - ili9341_set_foreground(LCD_FG_COLOR); - if (electrical_delay != 0) { - // draw electrical delay - int xpos = 21 + CELLOFFSETX - x0; - int ypos = 1 + ((j+1)/2)*(FONT_GET_HEIGHT+1) - y0; - - if (uistat.lever_mode == LM_EDELAY) - cell_drawstring(S_SARROW, xpos, ypos); - xpos += 5; - - float light_speed_ps = SPEED_OF_LIGHT*1e-12; //(m/ps) - plot_printf(buf, sizeof buf, "Edelay %Fs %Fm", electrical_delay * 1e-12, - electrical_delay * light_speed_ps * velocity_factor); - cell_drawstring(buf, xpos, ypos); - } -} -#endif - extern float temppeakLevel; static void cell_grid_line_info(int x0, int y0) @@ -1964,8 +1233,8 @@ static void cell_grid_line_info(int x0, int y0) int xpos = GRID_X_TEXT - x0; int ypos = 0 - y0 + 2; ili9341_set_foreground(LCD_GRID_VALUE_COLOR); - float ref = get_trace_refpos(TRACE_ACTUAL); - float scale = get_trace_scale(TRACE_ACTUAL);; + float ref = get_trace_refpos(); + float scale = get_trace_scale(); for (int i = 0; i < NGRIDY; i++){ if (ypos >= CELLHEIGHT) break; if (ypos >= -FONT_GET_HEIGHT){ @@ -2137,7 +1406,7 @@ static void cell_draw_marker_info(int x0, int y0) // cell_drawstring_7x13(buf, xpos, ypos); trace_get_value_string( t, &buf[k], (sizeof buf) - k, - idx, measured[trace[t].channel], ridx, markers[i].mtype,markers[i].frequency, markers[ref_marker].frequency); + idx, measured[t], ridx, markers[i].mtype,markers[i].frequency, markers[ref_marker].frequency); #if 1 int xpos = 1 + (j%2)*(WIDTH/2) + CELLOFFSETX - x0; // int ypos = 1 + (j/2)*(13) - y0; @@ -2159,37 +1428,28 @@ void draw_frequencies(void) { char buf1[32]; - char buf2[32]; buf2[0] = 0; + char buf2[32]; if (MODE_OUTPUT(setting.mode)) // No frequencies during output return; if (current_menu_is_form() && !in_selftest) return; -#ifdef __VNA__ - if ((domain_mode & DOMAIN_MODE) == DOMAIN_FREQ) { -#endif - if (FREQ_IS_CW()) { - plot_printf(buf1, sizeof(buf1), " CW %QHz", get_sweep_frequency(ST_CW)); - // Show user actual select sweep time? - uint32_t t = setting.actual_sweep_time_us; - plot_printf(buf2, sizeof(buf2), " TIME %.3Fs", (float)t/ONE_SECOND_TIME); - - } else if (FREQ_IS_STARTSTOP()) { - plot_printf(buf1, sizeof(buf1), " START %.3QHz %5.1QHz/", get_sweep_frequency(ST_START), grid_span); - plot_printf(buf2, sizeof(buf2), " STOP %.3QHz", get_sweep_frequency(ST_STOP)); - } else if (FREQ_IS_CENTERSPAN()) { - plot_printf(buf1, sizeof(buf1), " CENTER %.3QHz %5.1QHz/", get_sweep_frequency(ST_CENTER), grid_span); - plot_printf(buf2, sizeof(buf2), " SPAN %.3QHz", get_sweep_frequency(ST_SPAN)); - } -#ifdef __VNA__ - } else { - plot_printf(buf1, sizeof(buf1), " START 0s"); - plot_printf(buf2, sizeof(buf2), "STOP %Fs (%Fm)", time_of_index(sweep_points-1), distance_of_index(sweep_points-1)); + if (FREQ_IS_CW()) { + plot_printf(buf1, sizeof(buf1), " CW %QHz", get_sweep_frequency(ST_CW)); + // Show user actual select sweep time? + uint32_t t = setting.actual_sweep_time_us; + plot_printf(buf2, sizeof(buf2), " TIME %.3Fs", (float)t/ONE_SECOND_TIME); + + } else if (FREQ_IS_STARTSTOP()) { + plot_printf(buf1, sizeof(buf1), " START %.3QHz %5.1QHz/", get_sweep_frequency(ST_START), grid_span); + plot_printf(buf2, sizeof(buf2), " STOP %.3QHz", get_sweep_frequency(ST_STOP)); + } else if (FREQ_IS_CENTERSPAN()) { + plot_printf(buf1, sizeof(buf1), " CENTER %.3QHz %5.1QHz/", get_sweep_frequency(ST_CENTER), grid_span); + plot_printf(buf2, sizeof(buf2), " SPAN %.3QHz", get_sweep_frequency(ST_SPAN)); } -#endif ili9341_set_foreground(LCD_FG_COLOR); ili9341_set_background(LCD_BG_COLOR); - ili9341_fill(FREQUENCIES_XPOS1, FREQUENCIES_YPOS, LCD_WIDTH- FREQUENCIES_XPOS1, FONT_GET_HEIGHT); + ili9341_fill(FREQUENCIES_XPOS1, FREQUENCIES_YPOS, LCD_WIDTH - FREQUENCIES_XPOS1, LCD_HEIGHT - FREQUENCIES_YPOS); if (uistat.lever_mode == LM_CENTER) buf1[0] = S_SARROW[0]; if (uistat.lever_mode == LM_SPAN) @@ -2201,36 +1461,6 @@ draw_frequencies(void) ili9341_drawstring(buf2, p2, FREQUENCIES_YPOS); ili9341_drawstring(buf1, FREQUENCIES_XPOS1, FREQUENCIES_YPOS); } -#ifdef __VNA__ -void -draw_cal_status(void) -{ - int x = 0; - int y = 100; - char c[3]; - ili9341_set_foreground(LCD_FG_COLOR); - ili9341_set_background(LCD_BG_COLOR); - ili9341_fill(0, y, OFFSETX, 6*(FONT_GET_HEIGHT+1), LCD_BG_COLOR); - if (cal_status & CALSTAT_APPLY) { - c[0] = cal_status & CALSTAT_INTERPOLATED ? 'c' : 'C'; - c[1] = active_props == ¤t_props ? '*' : '0' + lastsaveid; - c[2] = 0; - ili9341_drawstring(c, x, y); - y +=FONT_GET_HEIGHT+1; - } - int i; - static const struct {char text, zero, mask;} calibration_text[]={ - {'D', 0, CALSTAT_ED}, - {'R', 0, CALSTAT_ER}, - {'S', 0, CALSTAT_ES}, - {'T', 0, CALSTAT_ET}, - {'X', 0, CALSTAT_EX} - }; - for (i = 0; i < 5; i++, y+=FONT_GET_HEIGHT+1) - if (cal_status & calibration_text[i].mask) - ili9341_drawstring(&calibration_text[i].text, x, y); -} -#endif // Draw battery level #define BATTERY_TOP_LEVEL 4100 @@ -2265,7 +1495,7 @@ static void draw_battery_status(void) string_buf[x++] = 0b10000001; string_buf[x++] = 0b11111111; // Draw battery - blit8BitWidthBitmap(7, BATTERY_START, 8, x, string_buf); + ili9341_blitBitmap(7, BATTERY_START, 8, x, string_buf); plot_printf((char*)string_buf, sizeof string_buf, "%.2fv", vbat/1000.0); ili9341_drawstring((char*)string_buf, 1, BATTERY_START+x+3); } @@ -2321,11 +1551,11 @@ static void update_waterfall(void){ ili9341_read_memory(OFFSETX, i , w_width, 1, w_width*1, spi_buffer); ili9341_bulk(OFFSETX, i+1, w_width, 1); } - index_t *index; + index_y_t *index; if (setting.average == AV_OFF) - index = trace_index[TRACE_ACTUAL]; + index = trace_index_y[TRACE_ACTUAL]; else - index = trace_index[TRACE_TEMP]; + index = trace_index_y[TRACE_TEMP]; int j = 0; for (i=0; i< sweep_points; i++) { // Add new topline uint16_t color; @@ -2334,7 +1564,7 @@ static void update_waterfall(void){ // y = (uint8_t)i; // for test color = waterfall_palette[y]; #elif 0 - uint16_t y = CELL_Y(index[i]); // should be always in range 0 - graph_bottom + uint16_t y = index[i]; // should be always in range 0 - graph_bottom uint16_t ratio = (graph_bottom - y)*2; // ratio = (i*2); // Uncomment for testing the waterfall colors int16_t b = 255 - ratio; @@ -2350,7 +1580,7 @@ static void update_waterfall(void){ gamma_correct(b); color = RGB565(r, g, b); #else - uint16_t y = SMALL_WATERFALL - CELL_Y(index[i])* (graph_bottom == BIG_WATERFALL ? 2 : 1); // should be always in range 0 - graph_bottom *2 depends on height of scroll + uint16_t y = SMALL_WATERFALL - index[i]* (graph_bottom == BIG_WATERFALL ? 2 : 1); // should be always in range 0 - graph_bottom *2 depends on height of scroll // Calculate gradient palette for range 0 .. 192 // idx r g b // 0 - 127 0 0 @@ -2382,14 +1612,18 @@ int get_waterfall(void) return(setting.waterfall); } +//extern float peakLevel; +//extern float min_level; +//int w_max = -130; +//int w_min = 0; void toggle_waterfall(void) { if (setting.waterfall == W_OFF) { - w_min = (int)min_level; - w_max = (int)peakLevel; - if (w_max < w_min + 20) - w_max = w_min + 20; +// w_min = (int)min_level; +// w_max = (int)peakLevel; +// if (w_max < w_min + 20) +// w_max = w_min + 20; graph_bottom = SMALL_WATERFALL; setting.waterfall = W_SMALL; } else if (setting.waterfall == W_SMALL) { @@ -2416,12 +1650,10 @@ disable_waterfall(void) request_to_redraw_grid(); } - void plot_init(void) { force_set_markmap(); } - #pragma GCC pop_options diff --git a/ui.c b/ui.c index 7de4d90..dadd036 100644 --- a/ui.c +++ b/ui.c @@ -105,6 +105,10 @@ static const uint8_t slider_bitmap[]= #define BUTTON_ICON_GROUP 4 #define BUTTON_ICON_GROUP_CHECKED 5 +#define CHECK_ICON(S) ((S) ? BUTTON_ICON_CHECK : BUTTON_ICON_NOCHECK) +#define GROUP_ICON(S) ((S) ? BUTTON_ICON_GROUP_CHECKED : BUTTON_ICON_GROUP) +#define AUTO_ICON(S) (S>=2?BUTTON_ICON_CHECK_AUTO:S) // Depends on order of ICONs!!!!! + #define BUTTON_BORDER_NONE 0x00 #define BUTTON_BORDER_WIDTH_MASK 0x0F @@ -794,7 +798,6 @@ menu_velocity_cb(int item, uint8_t data) ui_process_numeric(); } else { ui_mode_keypad(KM_VELOCITY_FACTOR); - ui_process_keypad(); } } @@ -839,7 +842,6 @@ menu_scale_cb(int item, uint8_t data) ui_process_numeric(); } else { ui_mode_keypad(data); - ui_process_keypad(); } } @@ -858,7 +860,6 @@ menu_stimulus_cb(int item, uint8_t data) ui_process_numeric(); } else { ui_mode_keypad(item); - ui_process_keypad(); } break; case 5: /* PAUSE */ @@ -1294,7 +1295,8 @@ static void ensure_selection(void) { const menuitem_t *menu = menu_stack[menu_current_level]; - int i=0; + if (selection < 0) {selection = -1; return;} + int i; if (MT_MASK(menu[0].type) == MT_TITLE && selection == 0) { selection = 1; return; @@ -1311,10 +1313,11 @@ menu_move_back(bool leave_ui) if (menu_current_level == 0) return; erase_menu_buttons(); + if ( menu_is_form(menu_stack[menu_current_level ]) && + !menu_is_form(menu_stack[menu_current_level-1])) + redraw_request|=REDRAW_AREA|REDRAW_BATTERY|REDRAW_FREQUENCY|REDRAW_CAL_STATUS; // redraw all if switch from form to normal menu mode menu_current_level--; - if (selection >= 0) - selection = 0; - ensure_selection(); + selection = -1; if (leave_ui){ ui_mode_normal(); @@ -1412,7 +1415,6 @@ menu_invoke(int item) kp_help_text = "240..960Mhz"; } ui_mode_keypad(menu->data); - ui_process_keypad(); redraw_request |= REDRAW_CAL_STATUS; break; } @@ -1866,13 +1868,13 @@ draw_menu_buttons(const menuitem_t *menu) ili9341_set_background(button.bg); uint16_t text_offs = button_start + 6; if (button.icon >=0){ - blit8BitWidthBitmap(button_start+3, y+(MENU_BUTTON_HEIGHT-ICON_HEIGHT)/2, ICON_WIDTH, ICON_HEIGHT, &check_box[button.icon*2*ICON_HEIGHT]); + ili9341_blitBitmap(button_start+3, y+(MENU_BUTTON_HEIGHT-ICON_HEIGHT)/2, ICON_WIDTH, ICON_HEIGHT, &check_box[button.icon*2*ICON_HEIGHT]); text_offs = button_start+6+ICON_WIDTH+1; } #ifdef __ICONS__ if (menu[i].type & MT_ICON) { - blit8BitWidthBitmap(button_start+MENU_FORM_WIDTH-2*FORM_ICON_WIDTH-8,y+(button_height-FORM_ICON_HEIGHT)/2,FORM_ICON_WIDTH,FORM_ICON_HEIGHT,& left_icons[((menu[i].data >>4)&0xf)*2*FORM_ICON_HEIGHT]); - blit8BitWidthBitmap(button_start+MENU_FORM_WIDTH- FORM_ICON_WIDTH-8,y+(button_height-FORM_ICON_HEIGHT)/2,FORM_ICON_WIDTH,FORM_ICON_HEIGHT,&right_icons[((menu[i].data >>0)&0xf)*2*FORM_ICON_HEIGHT]); + ili9341_blitBitmap(button_start+MENU_FORM_WIDTH-2*FORM_ICON_WIDTH-8,y+(button_height-FORM_ICON_HEIGHT)/2,FORM_ICON_WIDTH,FORM_ICON_HEIGHT,& left_icons[((menu[i].data >>4)&0xf)*2*FORM_ICON_HEIGHT]); + ili9341_blitBitmap(button_start+MENU_FORM_WIDTH- FORM_ICON_WIDTH-8,y+(button_height-FORM_ICON_HEIGHT)/2,FORM_ICON_WIDTH,FORM_ICON_HEIGHT,&right_icons[((menu[i].data >>0)&0xf)*2*FORM_ICON_HEIGHT]); } #endif int local_slider_positions = 0; @@ -1901,7 +1903,7 @@ draw_menu_buttons(const menuitem_t *menu) draw_slider: if (local_slider_positions < button_start) local_slider_positions = button_start; - blit8BitWidthBitmap(local_slider_positions - 4, y, 7, 5, slider_bitmap); + ili9341_blitBitmap(local_slider_positions - 4, y, 7, 5, slider_bitmap); } else if (menu[i].data == KM_HIGHOUTLEVEL) { local_slider_positions = ((get_level() - level_min() ) * (MENU_FORM_WIDTH-8)) / level_range() + OFFSETX+4; goto draw_slider; @@ -1918,7 +1920,7 @@ draw_menu_buttons(const menuitem_t *menu) ili9341_set_background(button.bg); uint16_t text_offs = button_start + 7; if (button.icon >=0){ - blit8BitWidthBitmap(button_start+2, y+(MENU_BUTTON_HEIGHT-ICON_HEIGHT)/2, ICON_WIDTH, ICON_HEIGHT, &check_box[button.icon*2*ICON_HEIGHT]); + ili9341_blitBitmap(button_start+2, y+(MENU_BUTTON_HEIGHT-ICON_HEIGHT)/2, ICON_WIDTH, ICON_HEIGHT, &check_box[button.icon*2*ICON_HEIGHT]); text_offs = button_start+2+ICON_WIDTH; } int lines = menu_is_multiline(button.text); @@ -2349,6 +2351,7 @@ ui_mode_keypad(int _keypad_mode) draw_menu(); draw_keypad(); draw_numeric_area_frame(); + ui_process_keypad(); } void @@ -2724,11 +2727,8 @@ ui_process_keypad(void) if (current_menu_is_form()) { ui_mode_menu(); //Reactivate menu after keypad selection = -1; - ensure_selection(); -// redraw_request|= REDRAW_BATTERY; // Only redraw battery } else { ui_mode_normal(); -// request_to_redraw_grid(); } //redraw_all(); } @@ -2826,38 +2826,28 @@ static int touch_lever_mode_select(int touch_x, int touch_y) { if (touch_y > HEIGHT) { - if (touch_x < FREQUENCIES_XPOS2 -50 && uistat.lever_mode == LM_CENTER) { - touch_wait_release(); - if (setting.freq_mode & FREQ_MODE_CENTER_SPAN) - ui_mode_keypad(KM_CENTER); - else - ui_mode_keypad(KM_START); - ui_process_keypad(); - return TRUE; + touch_wait_release(); + // Touch on left frequency field side + if (touch_x < FREQUENCIES_XPOS2 - 50) { + if (uistat.lever_mode == LM_CENTER){ + ui_mode_keypad(FREQ_IS_CENTERSPAN() ? KM_CENTER : KM_START); + return TRUE; + } } - if (touch_x > FREQUENCIES_XPOS2 - 50 && touch_x < FREQUENCIES_XPOS2 +50) { - touch_wait_release(); - if (FREQ_IS_STARTSTOP()) - setting.freq_mode |= FREQ_MODE_CENTER_SPAN; - else if (FREQ_IS_CENTERSPAN()) - setting.freq_mode &= ~FREQ_MODE_CENTER_SPAN; + else if (touch_x < FREQUENCIES_XPOS2 + 50) { + // toggle frequency mode start/stop <=> center/span + setting.freq_mode^= FREQ_MODE_CENTER_SPAN; redraw_request |= REDRAW_FREQUENCY; return true; } - if (touch_x >= FREQUENCIES_XPOS2 +50 && uistat.lever_mode == LM_SPAN) { - touch_wait_release(); - if (setting.freq_mode & FREQ_MODE_CENTER_SPAN) - ui_mode_keypad(KM_SPAN); - else - ui_mode_keypad(KM_STOP); - ui_process_keypad(); + else if (uistat.lever_mode == LM_SPAN) { + ui_mode_keypad(FREQ_IS_CW() ? KM_SWEEP_TIME : (FREQ_IS_CENTERSPAN() ? KM_SPAN : KM_STOP)); return TRUE; } select_lever_mode(touch_x < FREQUENCIES_XPOS2 ? LM_CENTER : LM_SPAN); - touch_wait_release(); return TRUE; } - if (touch_x =2?BUTTON_ICON_CHECK_AUTO:S) // Depends on order of ICONs!!!!! - static UI_FUNCTION_ADV_CALLBACK(menu_sweep_acb) { (void)data; @@ -883,7 +881,6 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) markers[0].mtype = M_REFERENCE | M_TRACKING; kp_help_text = "Frequency of fundamental"; ui_mode_keypad(KM_CENTER); - ui_process_keypad(); set_sweep_frequency(ST_START, 0); set_sweep_frequency(ST_STOP, uistat.value*5); set_measurement(M_IMD); @@ -898,11 +895,9 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) markers[1].mtype = M_TRACKING; kp_help_text = "Frequency of left signal"; ui_mode_keypad(KM_CENTER); - ui_process_keypad(); int left = uistat.value; kp_help_text = "Right signal"; ui_mode_keypad(KM_CENTER); - ui_process_keypad(); int right = uistat.value; set_sweep_frequency(ST_CENTER, (left+right)/2); set_sweep_frequency(ST_SPAN, (right - left)*5); @@ -920,10 +915,8 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) markers[1].mtype = M_DELTA | M_NOISE; kp_help_text = "Frequency of signal"; ui_mode_keypad(KM_CENTER); - ui_process_keypad(); kp_help_text = "Frequency offset"; ui_mode_keypad(KM_SPAN); - ui_process_keypad(); set_sweep_frequency(ST_SPAN, uistat.value*4); set_measurement(M_PHASE_NOISE); set_average(4); @@ -937,10 +930,8 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) markers[2].mtype = M_DELTA; kp_help_text = "Frequency of signal"; ui_mode_keypad(KM_CENTER); - ui_process_keypad(); kp_help_text = "Width of signal"; ui_mode_keypad(KM_SPAN); - ui_process_keypad(); set_sweep_frequency(ST_SPAN, uistat.value*4); set_measurement(M_STOP_BAND); // SetAverage(4); @@ -956,10 +947,8 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) markers[2].mtype = M_DELTA; // kp_help_text = "Frequency of signal"; // ui_mode_keypad(KM_CENTER); -// ui_process_keypad(); // kp_help_text = "Width of signal"; // ui_mode_keypad(KM_SPAN); -// ui_process_keypad(); // set_sweep_frequency(ST_SPAN, uistat.value*2); set_measurement(M_PASS_BAND); // SetAverage(4); @@ -980,11 +969,9 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) markers[0].mtype = M_REFERENCE;// | M_TRACKING; kp_help_text = "Frequency of signal"; ui_mode_keypad(KM_CENTER); - ui_process_keypad(); center = uistat.value; - kp_help_text = "Modulation frequency, 3 .. 10 kHz"; + kp_help_text = "Modulation frequency: 3 .. 10kHz"; ui_mode_keypad(KM_SPAN); - ui_process_keypad(); // if (uistat.value < 3000) // break; span = uistat.value; @@ -1005,18 +992,15 @@ static UI_FUNCTION_ADV_CALLBACK(menu_measure_acb) markers[0].mtype = M_REFERENCE; kp_help_text = "Frequency of signal"; ui_mode_keypad(KM_CENTER); - ui_process_keypad(); set_marker_frequency(0, uistat.value); kp_help_text = "Modulation frequency: 1 .. 2.5kHz"; ui_mode_keypad(KM_SPAN); - ui_process_keypad(); if (uistat.value < 1000 || uistat.value > 2500) break; set_RBW(uistat.value/100); // actual_rbw_x10 kp_help_text = "Frequency deviation: 3 .. 500kHz"; ui_mode_keypad(KM_SPAN); - ui_process_keypad(); if (uistat.value < 12000) uistat.value = 12000; // minimum span set_sweep_frequency(ST_SPAN, uistat.value*4); @@ -1097,7 +1081,6 @@ static UI_FUNCTION_ADV_CALLBACK(menu_storage_acb) if (setting.subtract_stored) { kp_help_text = "Ref level"; ui_mode_keypad(KM_REFLEVEL); - ui_process_keypad(); // setting.normalize_level = uistat.value; } else set_auto_reflevel(true); @@ -2133,13 +2116,18 @@ static const menuitem_t menu_top[] = { #define ACTIVE_COLOR RGBHEX(0x007FFF) -int menu_is_form(const menuitem_t *menu) +static bool menu_is_form(const menuitem_t *menu) { +#if 1 + // Not good set only one item as form and others as normal + return menu[0].type & MT_FORM; +#else int i; for (i = 0; MT_MASK(menu[i].type) != MT_NONE; i++) if (menu[i].type & MT_FORM) return (true); return(false); +#endif } static void menu_item_modify_attribute( @@ -2530,7 +2518,6 @@ int invoke_quick_menu(int y) if (y < quick_menu_y[i]) { if ((uint32_t)quick_menu[i] < KM_NONE) { ui_mode_keypad((int)quick_menu[i]); - ui_process_keypad(); } else { selection = -1; menu_current_level = 0; @@ -2562,9 +2549,7 @@ void draw_cal_status(void) int x = 0; int y = OFFSETY; unsigned int color; - int rounding = false; - if (!UNIT_IS_LINEAR(setting.unit)) - rounding = true; + const bool rounding = !UNIT_IS_LINEAR(setting.unit); const char * const unit = unit_string[setting.unit]; redraw_cal_status: buf[6]=0;