NanoVNA icon indicating copy to clipboard operation
NanoVNA copied to clipboard

Screen artifacts

Open EB4FBZ opened this issue 4 years ago • 9 comments

I have seen some screen artifacts from traces since the first firmware version i have tested. Has anyone paid attention to this?

photo5796658605267727050 photo6044092117866884827

EB4FBZ avatar Oct 01 '19 17:10 EB4FBZ

I noticed it too and reported it a while ago but I don't think it has been fixed.

https://github.com/ttrftech/NanoVNA/issues/35#issue-494313700

mrobertsn avatar Oct 08 '19 04:10 mrobertsn

It would be nice if there was a way to trigger a screen blank and redraw.

ssd2 avatar Oct 17 '19 01:10 ssd2

This is a workaround to clear the artifacts tapping the screen to get the menu and tapping again for remove it.

In file ui.c the function leave_ui_mode must be rewritten as follows

static void leave_ui_mode(void)
{
  if (ui_mode == UI_MENU) {
	request_to_redraw_grid();
	erase_menu_buttons();
	draw_frequencies();
	draw_cal_status();
//    request_to_draw_cells_behind_menu();
//    erase_menu_buttons();
  } else if (ui_mode == UI_NUMERIC) {
    request_to_draw_cells_behind_numeric_input();
    erase_numeric_input();
    draw_frequencies();
  }
}

Not a solution but clears those unwanted signs.

Have a great day.

Massimo IK1IZA

Pmax65 avatar Feb 03 '20 18:02 Pmax65

Screen artifacts

Screen update goes by cells size 32x32 pixels (processor can,t fast draw all screen) Fore faster screen update used function mark_cells_from_index() for detect cell for update, and detect cells not need update. Some long lines made cell dirty, but cell marked as disabled for update (becose need do it faster, and made mistake in calc).

Fore fix it possible every n draws in mark_cells_from_index set redraw all cells

DiSlord avatar Feb 22 '20 19:02 DiSlord

Hi DiSlord, an alternative for a pseudo-real-time update to clear the screen from artifacts could be done defining a cell counter that every screen update adds to the cells already to update some unmarked-to-update cells. This way, considering the display resolution of a total of 80 cells (for a 320 by 240 pixels display), the worst case (no cells already to update at all) adding 8 cells a time the whole display will be fully cleared in 10 screen updates.

More in detail, considering that the top-left cell has index 0 (I don't investigate this in the current software, it's just an hypothesis) and the bottom-right cell has index 79, calling CleanupCounter the variable which holds the last cell forced to be updated and CellToMark the counter of the cells to add to the current update, the procedure to execute before every update should be as follows:

  1. CellToMark = 8 1a) CellCount = 80
  2. CleanupCounter ++ 2a) CellCount -- 2b) if CellCount = 0 goto step 8
  3. if CleanupCounter = 80 then CleanupCounter = 0
  4. if Cell(CleanupCounter) is already marked to be updated return to step 2 else continue to step 5
  5. mark Cell(CleanupCounter) to be updated
  6. CellToMark --
  7. if CellToMark > 0 return to step 2
  8. exit the procedure

If adding 8 cells leads to a too slow screen refresh, the number of added cells could be reduced until the screen refresh time is acceptable.

I thought a little more and concluded that the algorithm proposed could fall into an infinite loop in case the number of cells not marked to update are less than the maximum value of CellToMark (for example after a call to request_to_redraw_grid() ). So I edited the message adding CellCount (see bold steps above). Note also that CleanupCounter must be a global or static variable.

Have a great day.

Massimo

Pmax65 avatar Feb 23 '20 09:02 Pmax65

I know that the solution should be investigating where the drawing function fails, this is just a workaround, anyways it seems to work fine on nanoVNA-H code This must be added somewhere into plot.c:

int CleanupCounter=0;
static inline void Clean_markmap(void)
{
  int CellCount=80;
  int CellToMark=24;
  int x,y;
  while(1){
	  CleanupCounter++;
	  if (CleanupCounter==80) {
		  CleanupCounter=0;
	  }
	  CellCount--;
	  if (CellCount==0) {
		  return;
	  }
	  x=CleanupCounter>>3;
	  y=CleanupCounter&0x07;
	  if (!is_mapmarked(x,y)){
		  mark_map(x,y);
		  if(--CellToMark==0){
			  return;
		  }
	  }
  }
}

The above function Clean_markmap() should be placed at the first line of draw_all_cells() as follows:

static void draw_all_cells(bool flush_markmap)
{
  int m, n;
  Clean_markmap();
  for (m = 0; m < (area_width+CELLWIDTH-1) / CELLWIDTH; m++)
    for (n = 0; n < (area_height+CELLHEIGHT-1) / CELLHEIGHT; n++) {
      if (is_mapmarked(m, n))
        draw_cell(m, n);
    }

  if (flush_markmap) {
    // keep current map for update
    swap_markmap();
    // clear map for next plotting
    clear_markmap();
  }
}

With 4 traces on, I can't see any appreciable delay, while even with one trace on only, the artifacts are cleared in maximum 4 redraws (I initialized CellToMark to 24 cells per redraw).

Have a great day.

Massimo IK1IZA

Pmax65 avatar Feb 23 '20 23:02 Pmax65

in file plot.c 2 bit buffers for detect cell for clear and update uint16_t markmap[2][MAX_MARKMAP_Y];

Then before screen render need cache line list for render in for all traces static uint32_t trace_index[TRACES_MAX][POINTS_COUNT];

All work do in plot_into_index(float measured[2][POINTS_COUNT][2])

Cache trace index data in screen coordinates for (i = 0; i < sweep_points; i++) trace_index[t][i] = trace_into_index(t, i, measured[ch]); And call static void mark_cells_from_index(void) This function must mark cell for update on screen, but do it not fully correct (aproximate resultfor speed) in some cases cell in 1 run marked as need update, on second run cell marked as remove from update and run draw_cell from

static void draw_all_cells(bool flush_markmap){
  int m, n;

  for (m = 0; m < (area_width+CELLWIDTH-1) / CELLWIDTH; m++)
    for (n = 0; n < (area_height+CELLHEIGHT-1) / CELLHEIGHT; n++) {
      uint16_t bit = 1<<m;
      if ((markmap[0][n] & bit) || (markmap[1][n] & bit)){
        draw_cell(m, n);
      }
  if (flush_markmap) {
    // keep current map for update
    swap_markmap();
    // clear map for next plotting
    clear_markmap();
  }
}

if ((markmap[0][n] & bit) || (markmap[1][n] & bit)) one buffer mark as need erase, second as need update in some cases on long lines static void mark_cells_from_index(void) made error in not mark cell as need update (long line), but cell marked as need erase, and draw_cell draw this line

And not update this cell

1 Solution - write more correct variant static void mark_cells_from_index(void)

2 Solution in static void draw_all_cells(bool flush_markmap) Update some cells partially, for example every 2 run update one cell column anyway add static counter mark= 0-n and add if (mark == n || (markmap[0][n] & bit) || (markmap[1][n] & bit))

mark++; if (mark == bottom) mark = 0; Ore somthing.. this a little slowdown render speed.

DiSlord avatar Feb 25 '20 11:02 DiSlord

Hi DiSlord, My patch does more or less what you suggest in your solution 2 and seems to work. Have a great day Massimo

Pmax65 avatar Feb 25 '20 13:02 Pmax65

I fix this in https://github.com/ttrftech/NanoVNA/pull/126 Use solution 1

DiSlord avatar Mar 09 '20 10:03 DiSlord