memcpy

Status
Not open for further replies.

pd0lew

Well-known member
Slow memcpy or memmove, see the video here and look at the last part of the video.

https://www.youtube.com/watch?v=hIfnh6LuMp4&feature=youtu.be


void printandscroll_layer_1() {

static char line1[43];
static char line2[43];
static char line3[43];
static char line4[43];
static char line5[43];
static char line6[43];
static char line7[43];
static char line8[43];
static char line9[43];
static char line10[43];
static char line11[43];
static uint16_t curs; // Cursor position at bottom line
static int8_t x; // current X co-ordinate
static uint8_t last_space; // location of latest space character


if (ch == ' ') last_space = x; // Keep track of word spaces in order to avoid breaking up words
if (x == 43) // End of line. Scroll everything up one line
{

tft.setTextColor(RA8875_BLACK); // Clear all lines by reprinting in BLACK
tft.setCursor(10, 25);
tft.print(line9);
tft.setCursor(10, 75);
tft.print(line8);
tft.setCursor(10, 125);
tft.print(line7);
tft.setCursor(10, 175);
tft.print(line6);
tft.setCursor(10, 225);
tft.print(line5);
tft.setCursor(10, 275);
tft.print(line4);
tft.setCursor(10, 325);
tft.print(line3);
tft.setCursor(10, 375);
tft.print(line2);
tft.setCursor(10, 430);
tft.print(line1);
memcpy(line11, line10, 42);
memcpy(line10, line9, 42);
memcpy(line9, line8, 42);
memcpy(line8, line7, 42);
memcpy(line7, line6, 42);
memcpy(line6, line5, 42);
memcpy(line5, line4, 42); // Shift all lines up
memcpy(line4, line3, 42);
memcpy(line3, line2, 42);
if (last_space == 0) last_space = 42; // Special case, no space in line1
memcpy(line2, line1, last_space);
line2[last_space] = '\0'; // Terminate string
tft.setTextColor(RA8875_WHITE);
tft.setCursor(10, 25);
tft.print(line9);
tft.setCursor(10, 75);
tft.print(line8);
tft.setCursor(10, 125);
tft.print(line7);
tft.setCursor(10, 175);
tft.print(line6);
tft.setCursor(10, 225); // and print data
tft.print(line5);
tft.setCursor(10, 275);
tft.print(line4);
tft.setCursor(10, 325);
tft.print(line3);
tft.setCursor(10, 375);
tft.print(line2);
tft.setTextColor(RA8875_GREEN);
tft.setCursor(0, 430); // Set cursor at beginning of first (lowest) line
if (last_space == 42) // Special case, no space in line1, therefore nothing to print
{
tft.fillRect(0, 430, 800, 33, RA8875_BLACK);
line1[0] = '\0';
x = 0;
curs = 0;
}
else // Move beginning of unfinished word to front of line
{
x = 42 - (last_space + 1); // Get length of text we want to move to front
memmove(line1, &line1[last_space], x);
line1[x] = '\0'; // Terminate end of string
tft.fillRect(0, 430, 800, 32, RA8875_BLACK); // Clear line
tft.setCursor(0, 430);
tft.print(line1); // Print the moved word-fragment
curs = x * 18 + 18; // + 18 // And move cursor accordingly
line1[x++] = ch; // Print to string
tft.print(ch);
}
last_space = 0;
}
else // Print new character to string and TFT, one char at a time
{
tft.setTextColor(RA8875_GREEN); // Set GREEN as text Colour
tft.setCursor(curs, 430);
line1[x++] = ch;
tft.println(ch);
curs = curs + 16; //space between characters
}
}
 
I think the text scrolls and prints the extra character just fine and your delay happens in some other code after this function has finished.
 
memmove() should be very fast for only 42 bytes.

I recommend calling micros() before and after sections of code you believe may have a performance problem. Subtract and print the numbers, like this:

Code:
  uint32_t begin_micros = micros();

  // slow code here

  uint32_t end_micros = micros();
  Serial.print("slow code took ");
  Serial.print(end_micros - begin_micros);
  Serial.println(" microseconds");
 
You might also want to verify that there is not some bound condition bug in your code that may end up either calling memmove or memcopy with some large number, like if your calculation ends up passing in a size of -1 or the like.

If you end up believing that the overhead of memcopy is too much (highly doubt it), you could reduce how many times you call it....

That is instead of having each line declared, like:
Code:
static char line1[43];
static char line2[43];
static char line3[43];
static char line4[43];
static char line5[43];
static char line6[43];
static char line7[43];
static char line8[43];
static char line9[43];
static char line10[43];
static char line11[43];

You could define one line like:
static char lines[11*43];

And then you would need to know that each line started at some offset in the array... And then you should be able to do one memcopy to move all of the lines up one...
 
The CW moinitor program in total

Thank you all for helping !
I included the whole CW monitor program ... I use Layer 1 and Layer 2 this is needed for speed up when copy the lines. This is really needed because I use Liberation mono fonts otherwise the scrolling is to slow.

The CW signal (serial format) comes from an other Teensy and when monitoring the Serial signal there is not any delay.

Can someone edit my code so that it will be faster or is there perhaps a mistake with the layers....
Code:
#include <RA8875.h>
//MISO 8
//SCLK 14
//MOSI 7
#define RA8875_RESET 2
#define RA8875_CS 20
RA8875 tft = RA8875(RA8875_CS, RA8875_RESET, 7, 14, 8);


#include <SPI.h>
#include <fonts/Liberation_Mono_24.c>
char ch;

void setup() {
  tft.begin(RA8875_800x480);
  tft.fillWindow(RA8875_BLACK);
  tft.setTextColor(RA8875_YELLOW);
  tft.setFont(&Liberation_Mono_24);
  tft.setCursor(310, 240);
  tft.print("PD0LEW");
  delay(1000);
  tft.fillWindow(RA8875_BLACK);
  Serial1.begin(115200);


}

void loop() {

  if (Serial1.available() )
  {
    ch = Serial1.read();
    printandscroll_layer_2(); tft.writeTo(L2); tft.layerEffect(LAYER1);
    printandscroll_layer_1(); tft.writeTo(L1); tft.layerEffect(LAYER2);
  }

}

void printandscroll_layer_1() {

  static char line1[43];
  static char line2[43];
  static char line3[43];
  static char line4[43];
  static char line5[43];
  static char line6[43];
  static char line7[43];
  static char line8[43];
  static char line9[43];
  static char line10[43];
  static char line11[43];
  static uint16_t curs; // Cursor position at bottom line
  static int8_t x; // current X co-ordinate
  static uint8_t last_space; // location of latest space character


  if (ch == ' ') last_space = x; // Keep track of word spaces in order to avoid breaking up words
  if (x == 42) // End of line. Scroll everything up one line
  {

    tft.setTextColor(RA8875_BLACK); // Clear all lines by reprinting in BLACK
    tft.setCursor(10, 25);
    tft.print(line9);
    tft.setCursor(10, 75);
    tft.print(line8);
    tft.setCursor(10, 125);
    tft.print(line7);
    tft.setCursor(10, 175);
    tft.print(line6);
    tft.setCursor(10, 225);
    tft.print(line5);
    tft.setCursor(10, 275);
    tft.print(line4);
    tft.setCursor(10, 325);
    tft.print(line3);
    tft.setCursor(10, 375);
    tft.print(line2);
    tft.setCursor(10, 430);
    tft.print(line1);
    memcpy(line11, line10, 42);
    memcpy(line10, line9, 42);
    memcpy(line9, line8, 42);
    memcpy(line8, line7, 42);
    memcpy(line7, line6, 42);
    memcpy(line6, line5, 42);
    memcpy(line5, line4, 42); // Shift all lines up
    memcpy(line4, line3, 42);
    memcpy(line3, line2, 42);
    if (last_space == 0) last_space = 42; // Special case, no space in line1
    memcpy(line2, line1, last_space);
    line2[last_space] = '\0'; // Terminate string
    tft.setTextColor(RA8875_WHITE);
    tft.setCursor(10, 25);
    tft.print(line9);
    tft.setCursor(10, 75);
    tft.print(line8);
    tft.setCursor(10, 125);
    tft.print(line7);
    tft.setCursor(10, 175);
    tft.print(line6);
    tft.setCursor(10, 225); // and print data
    tft.print(line5);
    tft.setCursor(10, 275);
    tft.print(line4);
    tft.setCursor(10, 325);
    tft.print(line3);
    tft.setCursor(10, 375);
    tft.print(line2);
    tft.setTextColor(RA8875_GREEN);
    tft.setCursor(0, 430); // Set cursor at beginning of first (lowest) line
    if (last_space == 42) // Special case, no space in line1, therefore nothing to print
    {
      tft.fillRect(0, 430, 800, 33, RA8875_BLACK);
      line1[0] = '\0';
      x = 0;
      curs = 0;
    }
    else // Move beginning of unfinished word to front of line
    {
      x = 42 - (last_space + 1); // Get length of text we want to move to front
      memmove(line1, &line1[last_space], x);
      line1[x] = '\0'; // Terminate end of string
      tft.fillRect(0, 430, 800, 32, RA8875_BLACK); // Clear line
      tft.setCursor(0, 430);
      tft.print(line1); // Print the moved word-fragment
      curs = x * 18 + 18; // And move cursor accordingly
      line1[x++] = ch; // Print to string
      tft.print(ch);
    }
    last_space = 0;
  }
  else // Print new character to string and TFT, one char at a time
  {
    tft.setTextColor(RA8875_GREEN); // Set GREEN as text Colour
    tft.setCursor(curs, 430);
    line1[x++] = ch;
    tft.println(ch);
    curs = curs + 18; //space between characters
  }
}
void printandscroll_layer_2() {

  static char line1[43];
  static char line2[43];
  static char line3[43];
  static char line4[43];
  static char line5[43];
  static char line6[43];
  static char line7[43];
  static char line8[43];
  static char line9[43];
  static char line10[43];
  static char line11[43];
  static uint16_t curs; // Cursor position at bottom line
  static int8_t x; // current X co-ordinate
  static uint8_t last_space; // location of latest space character

  if (ch == ' ') last_space = x; // Keep track of word spaces in order to avoid breaking up words
  if (x == 42) // End of line. Scroll everything up one line
  {
    tft.setTextColor(RA8875_BLACK); // Clear all lines by reprinting in BLACK
    tft.setCursor(10, 25);
    tft.print(line9);
    tft.setCursor(10, 75);
    tft.print(line8);
    tft.setCursor(10, 125);
    tft.print(line7);
    tft.setCursor(10, 175);
    tft.print(line6);
    tft.setCursor(10, 225);
    tft.print(line5);
    tft.setCursor(10, 275);
    tft.print(line4);
    tft.setCursor(10, 325);
    tft.print(line3);
    tft.setCursor(10, 375);
    tft.print(line2);
    tft.setCursor(10, 430);
    tft.print(line1);
    memcpy(line11, line10, 42);
    memcpy(line10, line9, 42);
    memcpy(line9, line8, 42);
    memcpy(line8, line7, 42);
    memcpy(line7, line6, 42);
    memcpy(line6, line5, 42);
    memcpy(line5, line4, 42); // Shift all lines up
    memcpy(line4, line3, 42);
    memcpy(line3, line2, 42);
    if (last_space == 0) last_space = 42; // Special case, no space in line1
    memcpy(line2, line1, last_space);
    line2[last_space] = '\0'; // Terminate string
    tft.setTextColor(RA8875_WHITE);
    tft.setCursor(10, 25);
    tft.print(line9);
    tft.setCursor(10, 75);
    tft.print(line8);
    tft.setCursor(10, 125);
    tft.print(line7);
    tft.setCursor(10, 175);
    tft.print(line6);
    tft.setCursor(10, 225);
    tft.print(line5);
    tft.setCursor(10, 275);
    tft.print(line4);
    tft.setCursor(10, 325);
    tft.print(line3);
    tft.setCursor(10, 375);
    tft.print(line2);
    tft.setTextColor(RA8875_GREEN);
    tft.setCursor(0, 430); // Set cursor at beginning of first (lowest) line
    if (last_space == 42) // Special case, no space in line1, therefore nothing to print
    {
      tft.fillRect(0, 430, 800, 33, RA8875_BLACK);
      line1[0] = '\0';
      x = 0;
      curs = 0;
    }
    else // Move beginning of unfinished word to front of line
    {
      x = 42 - (last_space + 1); // Get length of text we want to move to front
      memmove(line1, &line1[last_space], x);
      line1[x] = '\0'; // Terminate end of string
      tft.fillRect(0, 430, 800, 32, RA8875_BLACK); // Clear line
      tft.setCursor(0, 430);
      tft.print(line1); // Print the moved word-fragment
      curs = x * 18 + 18; // + 18 // And move cursor accordingly
      line1[x++] = ch; // Print to string
      tft.print(ch);
    }
    last_space = 0;
  }
  else // Print new character to string and TFT, one char at a time
  {
    tft.setTextColor(RA8875_GREEN); // Set GREEN as text Colour
    tft.setCursor(curs, 430);
    line1[x++] = ch;
    tft.println(ch);
    curs = curs + 18; //space between characters
  }
}
void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}





You might also want to verify that there is not some bound condition bug in your code that may end up either calling memmove or memcopy with some large number, like if your calculation ends up passing in a size of -1 or the like.

If you end up believing that the overhead of memcopy is too much (highly doubt it), you could reduce how many times you call it....

That is instead of having each line declared, like:
Code:
static char line1[43];
static char line2[43];
static char line3[43];
static char line4[43];
static char line5[43];
static char line6[43];
static char line7[43];
static char line8[43];
static char line9[43];
static char line10[43];
static char line11[43];

You could define one line like:
static char lines[11*43];

And then you would need to know that each line started at some offset in the array... And then you should be able to do one memcopy to move all of the lines up one...
 
Last edited by a moderator:
Sorry, I don't have your hardware... I did edit the code to put in code tags as to make it easier to read (The # button on the posting pages)

Did you try instrumenting the code the way that Paul suggested?
 
If you add the Serial.print() stuff to show you the actual elapsed time in the Arduino Serial Monitor, I'm pretty sure you'll discover memmove() is very fast, and much more time is taken by functions like tft.fillRect().
 
yes, memmove is very fast and more safer than memcpy
although it has "move" in it's name, it actually does a copy
 
With the new information, I would say the difference in time is due to the printing of the strings 4 times, twice to erase the strings and twice to print them to the layers. When the strings are empty at the beginning, they will print very fast as there is nothing to do. As the strings fill up with characters, they take longer to print.
 
What can we do rcarr?

Again, you need to learn exactly which parts of the program are running so slow. Add those Serial.print() and watch with the serial monitor. Move them around, until you learn which parts of the code are taking too much time.

Nobody else has this hardware set up for testing your code. Only you can do this. Do it, then you can tell us the info you learned about which lines are taking how much time.
 
you can also calculate the time of each function by calculating millis()/micros() time consumed from beginning to end of the given calls
 
Again I do not have nor know this hardware... So I don't understand the details of for example Layers? For example why each time you get a character do you do two full calls through drawing things first in Layer 1 and then in Layer 2?

If it is a set of double buffering.....

My guess is things slow down as I believe you redraw the text for each text character that is on the screen.

That is if you only have one row of text, your earlier draws of text will end as each line is filled with NULL character. As you scroll, you are having to draw more and more characters...
 
Hi everyone,

I measured the time in the printandscroll_layer_1 shifting lines up.
43 x 9 = 387 bytes and 4 rectangles black over the SPI bus is this to much?


slow code took 65477 microseconds
slow code took 124000 microseconds
slow code took 176630 microseconds
slow code took 238065 microseconds
slow code took 292520 microseconds
slow code took 355183 microseconds
slow code took 418221 microseconds
slow code took 469390 microseconds
slow code took 532916 microseconds //here we at the last line
slow code took 526851 microseconds
slow code took 526606 microseconds
slow code took 533245 microseconds
slow code took 536681 microseconds
slow code took 540261 microseconds
slow code took 533695 microseconds


void printandscroll_layer_1() {

begin_micros = micros();


static char line1[43];
static char line2[43];
static char line3[43];
static char line4[43];
static char line5[43];
static char line6[43];
static char line7[43];
static char line8[43];
static char line9[43];

static uint16_t curs; // Cursor position at bottom line
static int8_t x; // current X co-ordinate
static uint8_t last_space; // location of latest space character


if (ch == ' ') last_space = x; // Keep track of word spaces in order to avoid breaking up words
if (x == 42) // End of line. Scroll everything up one line
{

tft.setTextColor(RA8875_BLACK); // Clear all lines by reprinting in BLACK
tft.setCursor(10, 25);
tft.print(line9);
tft.setCursor(10, 75);
tft.print(line8);
tft.setCursor(10, 125);
tft.print(line7);
tft.setCursor(10, 175);
tft.print(line6);
tft.setCursor(10, 225);
tft.print(line5);
tft.setCursor(10, 275);
tft.print(line4);
tft.setCursor(10, 325);
tft.print(line3);
tft.setCursor(10, 375);
tft.print(line2);
tft.setCursor(10, 430);
tft.print(line1);


memcpy(line9, line8, 42);
memcpy(line8, line7, 42);
memcpy(line7, line6, 42);
memcpy(line6, line5, 42);
memcpy(line5, line4, 42); // Shift all lines up
memcpy(line4, line3, 42);
memcpy(line3, line2, 42);
if (last_space == 0) last_space = 42; // Special case, no space in line1
memcpy(line2, line1, last_space);
line2[last_space] = '\0'; // Terminate string

end_micros = micros();
Serial.print("slow code took ");
Serial.print(end_micros - begin_micros);
Serial.println(" microseconds");


tft.setTextColor(RA8875_WHITE);
tft.setCursor(10, 25);
tft.print(line9);
tft.setCursor(10, 75);
tft.print(line8);
tft.setCursor(10, 125);
tft.print(line7);
tft.setCursor(10, 175);
tft.print(line6);
tft.setCursor(10, 225); // and print data
tft.print(line5);
tft.setCursor(10, 275);
tft.print(line4);
tft.setCursor(10, 325);
tft.print(line3);
tft.setCursor(10, 375);
tft.print(line2);
tft.setTextColor(RA8875_GREEN);
tft.setCursor(0, 430); // Set cursor at beginning of first (lowest) line
if (last_space == 42) // Special case, no space in line1, therefore nothing to print
{
tft.fillRect(0, 430, 800, 33, RA8875_BLACK);
line1[0] = '\0';
x = 0;
curs = 0;
}
else // Move beginning of unfinished word to front of line
{
x = 42 - (last_space + 1); // Get length of text we want to move to front
memmove(line1, &line1[last_space], x);
line1[x] = '\0'; // Terminate end of string
tft.fillRect(0, 430, 800, 32, RA8875_BLACK); // Clear line
tft.setCursor(0, 430);
tft.print(line1); // Print the moved word-fragment
curs = x * 18 + 18; // And move cursor accordingly
line1[x++] = ch; // Print to string
tft.print(ch);
}
last_space = 0;
}
else // Print new character to string and TFT, one char at a time
{
tft.setTextColor(RA8875_GREEN); // Set GREEN as text Colour
tft.setCursor(curs, 430);
line1[x++] = ch;
tft.println(ch);
curs = curs + 18; //space between characters
}


}
 
Time without tft.fillRect(0, 430, 800, 32, RA8875_BLACK); // Clear line


slow code took 62995 microseconds
slow code took 120994 microseconds
slow code took 191341 microseconds
slow code took 245492 microseconds
slow code took 308209 microseconds
slow code took 364438 microseconds
slow code took 418259 microseconds
slow code took 482628 microseconds
slow code took 546116 microseconds
slow code took 547465 microseconds
slow code took 534834 microseconds
slow code took 522711 microseconds
slow code took 518513 microseconds
slow code took 515780 microseconds
slow code took 529889 microseconds
slow code took 520772 microseconds
slow code took 516395 microseconds
 
Looks like you're on the right path. Just to be clear, we can try to help you to troubleshoot this problem, but we can't just see one set of measurements over a wide range of the code and know what's wrong. You have more work to do here.

Your results are measuring the elapsed time for many lines of code, including 9 calls to tft.print(), 9 calls to tft.setCursor(), 8 calls to memcpy(), one to tft.setTextColor(), plus some miscellaneous code. You next step (and I hope this should be obvious) it to make more measurements over progressively smaller portions of the slow code. Your goal is to learn which specific part is so slow, and which parts are very fast.
 
To reiterate what Paul mentioned, your numbers are starting to get you closer to understanding what is going on... Also as I mentioned in previous posting, it helps for us to read the code when you put the code in code tags:
Which you can do with the # button in the edit window: What you need is the
<code>
...
</code>
Tags to be around your code. Note it uses [ and ] instead of < >...

As I mentioned in previous posting, my guess is the text output is what is eating the time...

Code:
void printandscroll_layer_1() {

  begin_micros = micros();
  int count_chars = 0; //*********************


  static char line1[43];
  static char line2[43];
  static char line3[43];
  static char line4[43];
  static char line5[43];
  static char line6[43];
  static char line7[43];
  static char line8[43];
  static char line9[43];

  static uint16_t curs; // Cursor position at bottom line
  static int8_t x; // current X co-ordinate
  static uint8_t last_space; // location of latest space character


  if (ch == ' ') last_space = x; // Keep track of word spaces in order to avoid breaking up words
  if (x == 42) // End of line. Scroll everything up one line
  {

    tft.setTextColor(RA8875_BLACK); // Clear all lines by reprinting in BLACK
    tft.setCursor(10, 25);
    tft.print(line9);
    tft.setCursor(10, 75);
    tft.print(line8);
    tft.setCursor(10, 125);
    tft.print(line7);
    tft.setCursor(10, 175);
    tft.print(line6);
    tft.setCursor(10, 225);
    tft.print(line5);
    tft.setCursor(10, 275);
    tft.print(line4);
    tft.setCursor(10, 325);
    tft.print(line3);
    tft.setCursor(10, 375);
    tft.print(line2);
    tft.setCursor(10, 430);
    tft.print(line1);

    after_print_times = micros(); // ***********
    count_chars = strlen(line9) + strlen(line8) + strlen(line7) + strlen(line6)
    + strlen(line5) + strlen(line4)+ strlen(line3) + strlen(line2) + strlen(line1); //*********

    memcpy(line9, line8, 42);
    memcpy(line8, line7, 42);
    memcpy(line7, line6, 42);
    memcpy(line6, line5, 42);
    memcpy(line5, line4, 42); // Shift all lines up
    memcpy(line4, line3, 42);
    memcpy(line3, line2, 42);
    if (last_space == 0) last_space = 42; // Special case, no space in line1
    memcpy(line2, line1, last_space);
    line2[last_space] = '\0'; // Terminate string

    end_micros = micros();
    Serial.print("slow code took text part: ");
    Serial.print(after_print_times - begin_micros); //***********
    Serial.print(" Chars output: "); //***********
    Serial.print(count_chars);      //***********
    Serial.print(" Total time: ");  //***********
    Serial.print(end_micros - begin_micros);
    Serial.println(" microseconds");


    tft.setTextColor(RA8875_WHITE);
    tft.setCursor(10, 25);
    tft.print(line9);
    tft.setCursor(10, 75);
    tft.print(line8);
    tft.setCursor(10, 125);
    tft.print(line7);
    tft.setCursor(10, 175);
    tft.print(line6);
    tft.setCursor(10, 225); // and print data
    tft.print(line5);
    tft.setCursor(10, 275);
    tft.print(line4);
    tft.setCursor(10, 325);
    tft.print(line3);
    tft.setCursor(10, 375);
    tft.print(line2);
    tft.setTextColor(RA8875_GREEN);
    tft.setCursor(0, 430); // Set cursor at beginning of first (lowest) line
    if (last_space == 42) // Special case, no space in line1, therefore nothing to print
    {
      tft.fillRect(0, 430, 800, 33, RA8875_BLACK);
      line1[0] = '\0';
      x = 0;
      curs = 0;
    }
    else // Move beginning of unfinished word to front of line
    {
      x = 42 - (last_space + 1); // Get length of text we want to move to front
      memmove(line1, &line1[last_space], x);
      line1[x] = '\0'; // Terminate end of string
      tft.fillRect(0, 430, 800, 32, RA8875_BLACK); // Clear line
      tft.setCursor(0, 430);
      tft.print(line1); // Print the moved word-fragment
      curs = x * 18 + 18; // And move cursor accordingly
      line1[x++] = ch; // Print to string
      tft.print(ch);
    }
    last_space = 0;
  }
  else // Print new character to string and TFT, one char at a time
  {
    tft.setTextColor(RA8875_GREEN); // Set GREEN as text Colour
    tft.setCursor(curs, 430);
    line1[x++] = ch;
    tft.println(ch);
    curs = curs + 18; //space between characters
  }


};

So again if it were me, I would add in a time check for the time it took to output the actual text, which I did above, plus I slightly slowed it down to get a total count of characters you are outputting to the screen and printed that as well.. All (most) of the lines I changed, have //********** like comments at the end of the line...

Did not try to compile so maybe issues, like I did not declare the after_time variable, figured you would do that where you did the other time variables as it was not included in the above post
 
Hi Kurt,

Thanks for helping with my CW decoder, a small display is working awesome.
Why so much effort..... because the display is cheap and the colours are very nice for my CW decoder.

If it is not possible then I must forget the RA8875 ... however a 5" SPI displays are hard to find for scrolling text lines..

I did the above with build in fonts (ugly) and LiberationMono_28 mono fonts see the difference.

Thanks,
Johan, PD0LEW


BUILD IN FONTS

slow code took text part: 1104 Chars output: 42 Total time: 1115 microseconds
slow code took text part: 1862 Chars output: 82 Total time: 1874 microseconds
slow code took text part: 2663 Chars output: 124 Total time: 2675 microseconds
slow code took text part: 3466 Chars output: 166 Total time: 3479 microseconds
slow code took text part: 4217 Chars output: 205 Total time: 4231 microseconds
slow code took text part: 4884 Chars output: 240 Total time: 4899 microseconds
slow code took text part: 5568 Chars output: 276 Total time: 5583 microseconds
slow code took text part: 6364 Chars output: 318 Total time: 6379 microseconds
slow code took text part: 7070 Chars output: 355 Total time: 7087 microseconds
slow code took text part: 7098 Chars output: 357 Total time: 7114 microseconds

LIBERATION MONO FONTS

slow code took text part: 80191 Chars output: 42 Total time: 80202 microseconds
slow code took text part: 164622 Chars output: 84 Total time: 164634 microseconds
slow code took text part: 230930 Chars output: 120 Total time: 230942 microseconds
slow code took text part: 306028 Chars output: 161 Total time: 306041 microseconds
slow code took text part: 380542 Chars output: 200 Total time: 380555 microseconds
slow code took text part: 462546 Chars output: 241 Total time: 462562 microseconds
slow code took text part: 536564 Chars output: 283 Total time: 536579 microseconds
slow code took text part: 602992 Chars output: 322 Total time: 603007 microseconds
slow code took text part: 666515 Chars output: 357 Total time: 666531 microseconds
slow code took text part: 662253 Chars output: 357 Total time: 662269 microseconds
 
What can we do rcarr?

Actually your program works fine. There is nothing wrong with it. While it is busy scrolling the screen, the characters on the serial line are buffered.

If the delay bothers you and you wish to remove it, one thing you can do is to distribute in time the processing required. Right now all your processing is done when there is a character available. When a character is not available, it just loops and the cpu cycles are not doing any useful work. You could look to push the slower functions into this idle time. If you wish an idea of how this may be done, I can provide one. But the fun part of programming for me is finding solutions, so I don't want to spoil your fun.
 
More or less I did everything what I can think off.... all the help is very welcome.

Thanks,
Johan
 
Currently you swap the visible layer twice for each character you receive. Have it swap the visible layer only when you need to scroll.

The processing on the visible layer would be fairly simple. As a character comes in, it is saved in a buffer and is printed in green on the bottom line.

Now envision the not visible layer as different from the visible layer. It is already scrolled up a line. You do not write letters to this layer, instead you write words. Only when a space is received do you empty the buffer mentioned above and you write it in the color White on the line above the bottom line.

When you need to scroll, hopefully you can see that the not visible layer is all set to display. So swap visible layers and write the buffer in green on the bottom line and write the new character. ( or put the new character in the buffer and write the buffer ).

Now comes the hard part. Your old visible layer which is now hidden is way out of sync. But it can be fixed during the idle time and you can break up the processing in time. What needs to be done: It needs to be erased, scrolled up two lines and the bottom 2 lines needs to be erased. It needs to be updated on the line above the bottom line in color white with any words in the buffer. And again, you can break up all this work in time and still process new characters arriving between pieces of this work.

Hopefully that explanation is somewhat clear.
 
Again I am not really sure what your swapping of visible layers gets you... If it is some form of double buffering. Can you not simply alternate between the two and only output one buffer per character output?

But I have not worked with this library so I don't know the state of things. Example can you use different fonts with the setTextColor(fg, bg) setup? The ili9341_t3 library did not support this for the non standard font. I added support in ili9341_t3n that did... Don't think that PR ever made it back into main library...

But assuming this works with the RA8875 library ( as it says it also works with rendered fonts).

One way I have handled scrolling in the past was to do something logically like:
Code:
    tft.setTextColor(RA8875_WHITE, RA8875_BLACK);
    for (int i=0; i < COUNT_LINES; i++) {
        tft.setCursor(10, i*50+25);
        tft.print(lines[i]);
        int16_t x, y;
        tft.getCursor(x, y);
        if (x < end_xs[i]) {
            tft.fillRect(x, y, end_xs[i]-x, 50);
        }
        end_xs[i] = x;
    }

In the above I sort of wrapped your stuff to be a set of arrays, such as to not have to repeat everything for each line. But the idea is reasonably simple. Instead of redrawing the old text in black and then redraw the new text in white... You try to use the non transparent text output to write over the old text with new (assuming it works properly) and then if the new text is not as long as the old text, blank out everything beyond the new text in black...

If the above does not work. Instead of redrawing the text in black, what happens if you simply fillRect black the whole line. My guess again is that would be a lot faster...
 
Hi Kurt and others, Thank you.

See the code below..... repaint in black is removed and changed tft.setTextColor(RA8875_WHITE,RA8875_BLACK);
This looks much better ..... now quickly test for 10 mins and see how this works out!


slow code took text part: 1 Chars output: 42 Total time: 12 microseconds
slow code took text part: 1 Chars output: 81 Total time: 12 microseconds
slow code took text part: 1 Chars output: 123 Total time: 13 microseconds
slow code took text part: 1 Chars output: 164 Total time: 14 microseconds
slow code took text part: 0 Chars output: 202 Total time: 14 microseconds
slow code took text part: 0 Chars output: 244 Total time: 15 microseconds
slow code took text part: 1 Chars output: 283 Total time: 15 microseconds
slow code took text part: 0 Chars output: 321 Total time: 16 microseconds
slow code took text part: 0 Chars output: 361 Total time: 16 microseconds
slow code took text part: 1 Chars output: 362 Total time: 17 microseconds
slow code took text part: 1 Chars output: 361 Total time: 17 microseconds
slow code took text part: 0 Chars output: 362 Total time: 16 microseconds
 
Status
Not open for further replies.
Back
Top