Teensy 4 - analog vu meter on ILI9341 tft display to slow

Status
Not open for further replies.

DIYLAB

Well-known member
Hello, everyone,

for a project i am developing a VU-meter which imitates the original analog displays on a 2.8" display with ILI9341 controller.
The SPI clock is 40MHz and the Teensy 4.0 with 600MHz is used.

A frame buffer is used and as data I take automatically generated values between 0 and 100 and back.
The main loop should be run through as fast as possible for testing.

Unfortunately the needles don't move nearly as fast as hoped ;o(
And the lower part of the Peak-LED is cut off and I don't know why yet.

What am I doing wrong?
And how do I get more speed of the needles?

The project is pinned up here.

Best regards
Bruno

revox_vu.jpg


Code:
#include "SPI.h"
#include <ILI9341_t3n.h>
#include "analog_leftside.c"
#include "analog_leftside_led.c"
#include "analog_rightside.c"
#include "analog_rightside_led.c"

#define TFT_RST 8
#define TFT_DC  9
#define TFT_CS  10

ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST);

int16_t leftNeedleRectMinX, rightNeedleRectMinX;
int16_t leftNeedleRectMinY, rightNeedleRectMinY;
int16_t leftNeedleRectMaxX, rightNeedleRectMaxX;
int16_t leftNeedleRectMaxY, rightNeedleRectMaxY;

int16_t workCounter;
uint8_t pastLeft, pastRight;
boolean direction;

void setup() {
	tft.begin(40000000);
	tft.useFrameBuffer(true);
	tft.setRotation(2);
	tft.fillScreen(ILI9341_WHITE);
	tft.writeRect(0, 0, 120, 320, (uint16_t*)analog_leftside);
	tft.writeRect(120, 0, 120, 320, (uint16_t*)analog_rightside);
	tft.updateScreen();
}

void loop(void) {
	(!direction) ? workCounter++ : workCounter--;
	if (workCounter > 100) {
		workCounter = 100;
		direction = true;
	}
	if (workCounter < 0) {
		workCounter = 0;
		direction = false;
	}

	drawNeedleLeft(workCounter);
	drawNeedleRight(workCounter);
}

void drawNeedleLeft(uint8_t percent) {
	if (percent != pastLeft) {
		pastLeft = percent;

		double scale = map(percent, 0, 100, 57, 123);
		int16_t x0 = -115; // Start-X
		int16_t y0 = 160;  // Start-Y
		int16_t x1 = -115 + 193 * sin(scale * 0.0174532925); // End-X
		int16_t y1 = 160 + 193 * cos(scale * 0.0174532925);  // End-Y

		int16_t left_min_x = leftNeedleRectMinX;
		int16_t left_min_y = leftNeedleRectMinY;
		int16_t left_max_x = leftNeedleRectMaxX;
		int16_t left_max_y = leftNeedleRectMaxY;

		leftNeedleRectMinX = min(x0, x1);
		leftNeedleRectMinY = min(y0, y1);
		leftNeedleRectMaxX = max(x0, x1);
		leftNeedleRectMaxY = max(y0, y1);

		left_min_x = min(left_min_x, leftNeedleRectMinX);
		left_min_y = min(left_min_y, leftNeedleRectMinY);
		left_max_x = max(left_max_x, leftNeedleRectMaxX);
		left_max_y = max(left_max_y, leftNeedleRectMaxY);

		tft.setClipRect(0, 0, 120, 320);
		tft.writeRect(0, 0, 120, 320, (percent >= 79) ? (uint16_t*)analog_leftside_led : (uint16_t*)analog_leftside);
		tft.setClipRect(left_min_x, left_min_y, left_max_x - left_min_x + 1, left_max_y - left_min_y + 1);
		tft.drawLine(x0, y0, x1, y1, ILI9341_BLACK);
		tft.updateScreen();
	}
}

void drawNeedleRight(uint8_t percent) {
	if (percent != pastRight) {
		pastRight = percent;

		double scale = map(100 - percent, 0, 100, 57, 123);
		int16_t x0 = 355; // Start-X
		int16_t y0 = 160; // Start-Y
		int16_t x1 = 355 - 193 * sin(scale * 0.0174532925); // End-X
		int16_t y1 = 160 - 193 * cos(scale * 0.0174532925); // End-Y

		int16_t right_min_x = rightNeedleRectMinX;
		int16_t right_min_y = rightNeedleRectMinY;
		int16_t right_max_x = rightNeedleRectMaxX;
		int16_t right_max_y = rightNeedleRectMaxY;

		rightNeedleRectMinX = min(x0, x1);
		rightNeedleRectMinY = min(y0, y1);
		rightNeedleRectMaxX = max(x0, x1);
		rightNeedleRectMaxY = max(y0, y1);

		right_min_x = min(right_min_x, rightNeedleRectMinX);
		right_min_y = min(right_min_y, rightNeedleRectMinY);
		right_max_x = max(right_max_x, rightNeedleRectMaxX);
		right_max_y = max(right_max_y, rightNeedleRectMaxY);

		tft.setClipRect(120, 0, 120, 320);
		tft.writeRect(120, 0, 120, 320, (percent >= 79) ? (uint16_t*)analog_rightside_led : (uint16_t*)analog_rightside);
		tft.setClipRect(right_min_x, right_min_y, right_max_x - right_min_x + 1, right_max_y - right_min_y + 1);
		tft.drawLine(x0, y0, x1, y1, ILI9341_BLACK);
		tft.updateScreen();
	}
}
 

Attachments

  • RevoxA700.zip
    80.9 KB · Views: 290
Last edited:
I think some of the speed issue is due to the math on setting up your bounding rectangles...

That is I added Serial.printf to your output of one meter and only when percent is multiple of 16...
This is right after the updateScreen:
Code:
    if (!(percent & 0xf)) Serial.printf("%d (%d %d)-(%d %d)\n",
        percent, left_min_x, left_min_y, left_max_x, left_max_y);
The output looks like:
Code:
0 (-115 160)-(46 265)
16 (-115 160)-(62 238)
32 (-115 160)-(73 203)
48 (-115 160)-(77 166)
64 (-115 129)-(76 160)
80 (-115 93)-(67 160)
96 (-115 63)-(52 160)
96 (-115 60)-(52 160)
80 (-115 93)-(66 160)
64 (-115 126)-(75 160)
48 (-115 160)-(77 166)
32 (-115 160)-(73 200)
16 (-115 160)-(63 235)
0 (-115 160)-(46 265)

That is you start drawing the needle starting at position:
Code:
		int16_t x0 = -115; // Start-X
		int16_t y0 = 160;  // Start-Y
So your bounding rectangle will start somewhere out in large area. Maybe what you should do is to compute a bound rectangle for where the needles y is when X=0 if that makes sense...

And then the only reason any of your LED shows up at all is because due to the negative position, some of it will be in that rectangle... But if you correct like I mention, probably none will be, so you may need to draw that area separately.
 
Dear Kurt, hello everyone,

Thank you very much for the valuable suggestions!
I am in the process of greatly simplifying the code, but I still have a problem with the calculation of the intersection point where the pointer enters the display.
Unfortunately I am a bit overtaxed with trigonometry.

How could I calculate the point of intersection or the height 'h'?

intersection.jpg

Best regards
Bruno
 
@KurtE shouldn't the clipping rectangle be cleared after updateScreen() (added in red)?
Code:
void setup() {
	tft.begin(40000000);
	tft.useFrameBuffer(true);
	tft.setRotation(2);
	tft.fillScreen(ILI9341_WHITE);
	tft.writeRect(0, 0, 120, 320, (uint16_t*)analog_leftside);
	tft.writeRect(120, 0, 120, 320, (uint16_t*)analog_rightside);
	tft.updateScreen();
        [COLOR="#FF0000"]tft.setClipRect();[/COLOR]
}

void loop(void) {
	(!direction) ? workCounter++ : workCounter--;
	if (workCounter > 100) {
		workCounter = 100;
		direction = true;
	}
	if (workCounter < 0) {
		workCounter = 0;
		direction = false;
	}

	drawNeedleLeft(workCounter);
	drawNeedleRight(workCounter);
}

void drawNeedleLeft(uint8_t percent) {
	if (percent != pastLeft) {
		pastLeft = percent;

		double scale = map(percent, 0, 100, 57, 123);
		int16_t x0 = -115; // Start-X
		int16_t y0 = 160;  // Start-Y
		int16_t x1 = -115 + 193 * sin(scale * 0.0174532925); // End-X
		int16_t y1 = 160 + 193 * cos(scale * 0.0174532925);  // End-Y

		int16_t left_min_x = leftNeedleRectMinX;
		int16_t left_min_y = leftNeedleRectMinY;
		int16_t left_max_x = leftNeedleRectMaxX;
		int16_t left_max_y = leftNeedleRectMaxY;

		leftNeedleRectMinX = min(x0, x1);
		leftNeedleRectMinY = min(y0, y1);
		leftNeedleRectMaxX = max(x0, x1);
		leftNeedleRectMaxY = max(y0, y1);

		left_min_x = min(left_min_x, leftNeedleRectMinX);
		left_min_y = min(left_min_y, leftNeedleRectMinY);
		left_max_x = max(left_max_x, leftNeedleRectMaxX);
		left_max_y = max(left_max_y, leftNeedleRectMaxY);

		tft.setClipRect(0, 0, 120, 320);
		tft.writeRect(0, 0, 120, 320, (percent >= 79) ? (uint16_t*)analog_leftside_led : (uint16_t*)analog_leftside);
		tft.setClipRect(left_min_x, left_min_y, left_max_x - left_min_x + 1, left_max_y - left_min_y + 1);
		tft.drawLine(x0, y0, x1, y1, ILI9341_BLACK);
		tft.updateScreen();
                [COLOR="#FF0000"]tft.setClipRect();[/COLOR]
	}
}

void drawNeedleRight(uint8_t percent) {
	if (percent != pastRight) {
		pastRight = percent;

		double scale = map(100 - percent, 0, 100, 57, 123);
		int16_t x0 = 355; // Start-X
		int16_t y0 = 160; // Start-Y
		int16_t x1 = 355 - 193 * sin(scale * 0.0174532925); // End-X
		int16_t y1 = 160 - 193 * cos(scale * 0.0174532925); // End-Y

		int16_t right_min_x = rightNeedleRectMinX;
		int16_t right_min_y = rightNeedleRectMinY;
		int16_t right_max_x = rightNeedleRectMaxX;
		int16_t right_max_y = rightNeedleRectMaxY;

		rightNeedleRectMinX = min(x0, x1);
		rightNeedleRectMinY = min(y0, y1);
		rightNeedleRectMaxX = max(x0, x1);
		rightNeedleRectMaxY = max(y0, y1);

		right_min_x = min(right_min_x, rightNeedleRectMinX);
		right_min_y = min(right_min_y, rightNeedleRectMinY);
		right_max_x = max(right_max_x, rightNeedleRectMaxX);
		right_max_y = max(right_max_y, rightNeedleRectMaxY);

		tft.setClipRect(120, 0, 120, 320);
		tft.writeRect(120, 0, 120, 320, (percent >= 79) ? (uint16_t*)analog_rightside_led : (uint16_t*)analog_rightside);
		tft.setClipRect(right_min_x, right_min_y, right_max_x - right_min_x + 1, right_max_y - right_min_y + 1);
		tft.drawLine(x0, y0, x1, y1, ILI9341_BLACK);
		tft.updateScreen();
                [COLOR="#FF0000"]tft.setClipRect();[/COLOR]
	}
}
 
@Rezo - clearing the clip rectangle is optional... That is if you ALWAYS set the new clip rectangle before your next output to frame buffer than it does not really matter...

@DIYLAB - I totally understand, I had a minor in math when I got my BS several decades ago and I am now totally math challenged...

But this can be thought of as simply a linear conversion so you can do the math directly or you can just use the map function...
So for left needle you can compute something like:
Code:
    int xEdge = 0;
    int yEdge = map(0, x0, x1, y0, y1);

Below is my quick test of your code with out without minimizing the rectangle... Notice the #define at top, if you comment it out, it will run with your currently computed clip rectangle...
I also added simple elapsedMillis variable which I then print out how many milliseconds it take for your code to do a complete cycle...

Your code was taking about 1130ms to do a complete cycle up and down...
Then using the simple mapping code, it now takes something like 770
So a bit faster, but your LED does not show up at all... There are ways to fix that as well, you could expand the update rectangle if the LED state changes to include it to bounds, or do simple update of that area if LED changes... Could be through different Bitmaps if you like could be by fillCircle call...

Hope this helps

Code:
#define USE_EDGES
#include "SPI.h"
#include <ILI9341_t3n.h>
#include "analog_leftside.c"
#include "analog_leftside_led.c"
#include "analog_rightside.c"
#include "analog_rightside_led.c"

#define TFT_RST 8
#define TFT_DC  9
#define TFT_CS  10

ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST);

int16_t leftNeedleRectMinX, rightNeedleRectMinX;
int16_t leftNeedleRectMinY, rightNeedleRectMinY;
int16_t leftNeedleRectMaxX, rightNeedleRectMaxX;
int16_t leftNeedleRectMaxY, rightNeedleRectMaxY;

int16_t workCounter;
uint8_t pastLeft, pastRight;
boolean direction;
elapsedMillis emCycle;

void setup() {
  while (!Serial && millis() < 4000) ;
  Serial.begin(115200);
  tft.begin(40000000);
  tft.useFrameBuffer(true);
  tft.setRotation(2);
  tft.fillScreen(ILI9341_WHITE);
  tft.writeRect(0, 0, 120, 320, (uint16_t*)analog_leftside);
  tft.writeRect(120, 0, 120, 320, (uint16_t*)analog_rightside);
  tft.updateScreen();
  emCycle = 0;
}

void loop(void) {
  (!direction) ? workCounter++ : workCounter--;
  if (workCounter > 100) {
    workCounter = 100;
    direction = true;
  }
  if (workCounter < 0) {
    workCounter = 0;
    direction = false;
    Serial.println(emCycle, DEC);
    emCycle = 0;
  }

  drawNeedleLeft(workCounter);
  drawNeedleRight(workCounter);
}

void drawNeedleLeft(uint8_t percent) {
  if (percent != pastLeft) {
    pastLeft = percent;

    double scale = map(percent, 0, 100, 57, 123);
    int16_t x0 = -115; // Start-X
    int16_t y0 = 160;  // Start-Y
    int16_t x1 = -115 + 193 * sin(scale * 0.0174532925); // End-X
    int16_t y1 = 160 + 193 * cos(scale * 0.0174532925);  // End-Y

    int xEdge = 0;
    int yEdge = map(0, x0, x1, y0, y1);

    int16_t left_min_x = leftNeedleRectMinX;
    int16_t left_min_y = leftNeedleRectMinY;
    int16_t left_max_x = leftNeedleRectMaxX;
    int16_t left_max_y = leftNeedleRectMaxY;

#ifdef USE_EDGES
    leftNeedleRectMinX = min(xEdge, x1);
    leftNeedleRectMinY = min(yEdge, y1);
    leftNeedleRectMaxX = max(xEdge, x1);
    leftNeedleRectMaxY = max(yEdge, y1);
#else
    leftNeedleRectMinX = min(x0, x1);
    leftNeedleRectMinY = min(y0, y1);
    leftNeedleRectMaxX = max(x0, x1);
    leftNeedleRectMaxY = max(y0, y1);
#endif

    left_min_x = min(left_min_x, leftNeedleRectMinX);
    left_min_y = min(left_min_y, leftNeedleRectMinY);
    left_max_x = max(left_max_x, leftNeedleRectMaxX);
    left_max_y = max(left_max_y, leftNeedleRectMaxY);

    tft.setClipRect(0, 0, 120, 320);
    tft.writeRect(0, 0, 120, 320, (percent >= 79) ? (uint16_t*)analog_leftside_led : (uint16_t*)analog_leftside);
    tft.setClipRect(left_min_x, left_min_y, left_max_x - left_min_x + 1, left_max_y - left_min_y + 1);
    tft.drawLine(x0, y0, x1, y1, ILI9341_BLACK);
    tft.updateScreen();
    //if (!(percent & 0xf)) Serial.printf("%d (%d %d)-(%d %d)\n",
    //    percent, left_min_x, left_min_y, left_max_x, left_max_y);   
  }
}

void drawNeedleRight(uint8_t percent) {
  if (percent != pastRight) {
    pastRight = percent;

    double scale = map(100 - percent, 0, 100, 57, 123);
    int16_t x0 = 355; // Start-X
    int16_t y0 = 160; // Start-Y
    int16_t x1 = 355 - 193 * sin(scale * 0.0174532925); // End-X
    int16_t y1 = 160 - 193 * cos(scale * 0.0174532925); // End-Y
    int xEdge = 240;
    int yEdge = map(240, x0, x1, y0, y1);

    int16_t right_min_x = rightNeedleRectMinX;
    int16_t right_min_y = rightNeedleRectMinY;
    int16_t right_max_x = rightNeedleRectMaxX;
    int16_t right_max_y = rightNeedleRectMaxY;

#ifdef USE_EDGES
    rightNeedleRectMinX = min(xEdge, x1);
    rightNeedleRectMinY = min(yEdge, y1);
    rightNeedleRectMaxX = max(xEdge, x1);
    rightNeedleRectMaxY = max(yEdge, y1);
#else
    rightNeedleRectMinX = min(x0, x1);
    rightNeedleRectMinY = min(y0, y1);
    rightNeedleRectMaxX = max(x0, x1);
    rightNeedleRectMaxY = max(y0, y1);
#endif
    right_min_x = min(right_min_x, rightNeedleRectMinX);
    right_min_y = min(right_min_y, rightNeedleRectMinY);
    right_max_x = max(right_max_x, rightNeedleRectMaxX);
    right_max_y = max(right_max_y, rightNeedleRectMaxY);

    tft.setClipRect(120, 0, 120, 320);
    tft.writeRect(120, 0, 120, 320, (percent >= 79) ? (uint16_t*)analog_rightside_led : (uint16_t*)analog_rightside);
    tft.setClipRect(right_min_x, right_min_y, right_max_x - right_min_x + 1, right_max_y - right_min_y + 1);
    tft.drawLine(x0, y0, x1, y1, ILI9341_BLACK);
    tft.updateScreen();
  }
}
 
for the needle drawing, since you always start at the same location, I think you can create an equation for the needles line (i've not studied the code but it will be something like y=mx + b. So for the first point x1 = 0, then y1 is what ever the computed value is based on the equation. For x2 = NeedleRadius * cos(needleAngle), y2 = NeedleRadius * sin(NeedleAngle).

I would do more of what CurtE did and put timers around certain areas to look for where calcs are slow. I'm 99.9999999% sure in the end you display should be super fast.

I have a bar-chart type meter for an equalizer to control mic input--and is ripping fast--and all bands go through FFT to compute heights. Start watching around the 10 sec mark
https://www.youtube.com/watch?v=tCUUaf6nYE8&list=PLPHBVy6vaT418gVRVzMcq00Ip49w0zeW_&index=15&t=0s
 
Hope this helps

Hello,

Thank you very much for the map solution!
The clipping is now placed correctly around the needle, the peak LED is working and the drawing is only done in the visible area.

All fine, but unfortunately not faster than Kurt's because of these measures.

Something brakes there - only what?

Best regards
Bruno

clipping.jpg


Code:
#include "SPI.h"
#include <ILI9341_t3n.h>
#include "analog_leftside.c"
#include "analog_rightside.c"

#define DEG2RAD 0.0174532925

#define TFT_RST 8
#define TFT_DC  9
#define TFT_CS  10

ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST);

int16_t leftNeedleRectMinX, rightNeedleRectMinX;
int16_t leftNeedleRectMinY, rightNeedleRectMinY;
int16_t leftNeedleRectMaxX, rightNeedleRectMaxX;
int16_t leftNeedleRectMaxY, rightNeedleRectMaxY;
uint8_t pastLeft, pastRight;
elapsedMillis emCycle;

void setup() {
	Serial.begin(115200);
	tft.begin(40000000);
	tft.useFrameBuffer(true);
	tft.setRotation(2);
	tft.fillScreen(ILI9341_WHITE);
	tft.writeRect(0, 0, 120, 320, (uint16_t*)analog_leftside);
	tft.writeRect(120, 0, 120, 320, (uint16_t*)analog_rightside);
	tft.updateScreen();
	emCycle = 0;
}

void loop(void) {
	for (uint8_t i = 0; i <= 100; i++) {
		drawNeedleLeft(i);
		drawNeedleRight(i);
	}
	for (uint8_t i = 99; i > 0; i--) {
		drawNeedleLeft(i);
		drawNeedleRight(i);
	}

	//Serial.println(emCycle, DEC);
	emCycle = 0;
}

void drawNeedleLeft(uint8_t percent) {
	if (percent != pastLeft) {
		pastLeft = percent;

		double scale = map(percent, 0, 100, 57, 123);
		double arc = scale * DEG2RAD;
		int16_t x1 = -115 + 193 * sin(arc);
		int16_t y1 = 160 + 193 * cos(arc);
		int yEdge = map(0, -115, x1, 160, y1);

		int16_t left_min_x = leftNeedleRectMinX;
		int16_t left_min_y = leftNeedleRectMinY;
		int16_t left_max_x = leftNeedleRectMaxX;
		int16_t left_max_y = leftNeedleRectMaxY;

		leftNeedleRectMinX = min(0, x1);
		leftNeedleRectMinY = min(yEdge, y1);
		leftNeedleRectMaxX = max(0, x1);
		leftNeedleRectMaxY = max(yEdge, y1);

		left_min_x = min(left_min_x, leftNeedleRectMinX);
		left_min_y = min(left_min_y, leftNeedleRectMinY);
		left_max_x = max(left_max_x, leftNeedleRectMaxX);
		left_max_y = max(left_max_y, leftNeedleRectMaxY);

		// Background
		tft.setClipRect(0, 0, 120, 320);
		tft.writeRect(0, 0, 120, 320, (uint16_t*)analog_leftside);

		// Peak LED
		if (percent > 78) {
			tft.setClipRect(12, 145, 17, 17);
			tft.fillCircle(20, 153, 7, ILI9341_RED);
			tft.updateScreen();
		}

		// Needle
		// DEBUG: tft.drawRect(left_min_x, left_min_y, left_max_x - left_min_x + 1, left_max_y - left_min_y + 1, ILI9341_MAGENTA);
		tft.setClipRect(left_min_x, left_min_y, left_max_x - left_min_x + 1, left_max_y - left_min_y + 1);
		tft.drawLine(0, yEdge, x1, y1, ILI9341_BLUE);
		tft.updateScreen();
	}
}

void drawNeedleRight(uint8_t percent) {
	if (percent != pastRight) {
		pastRight = percent;

		double scale = map(100 - percent, 0, 100, 57, 123);
		double arc = scale * DEG2RAD;
		int16_t x1 = 355 - 193 * sin(arc);
		int16_t y1 = 160 - 193 * cos(arc);
		int16_t yEdge = map(240, 355, x1, 160, y1);

		int16_t right_min_x = rightNeedleRectMinX;
		int16_t right_min_y = rightNeedleRectMinY;
		int16_t right_max_x = rightNeedleRectMaxX;
		int16_t right_max_y = rightNeedleRectMaxY;

		rightNeedleRectMinX = min(240, x1);
		rightNeedleRectMinY = min(yEdge, y1);
		rightNeedleRectMaxX = max(240, x1);
		rightNeedleRectMaxY = max(yEdge, y1);

		right_min_x = min(right_min_x, rightNeedleRectMinX);
		right_min_y = min(right_min_y, rightNeedleRectMinY);
		right_max_x = max(right_max_x, rightNeedleRectMaxX);
		right_max_y = max(right_max_y, rightNeedleRectMaxY);

		// Background
		tft.setClipRect(120, 0, 120, 320);
		tft.writeRect(120, 0, 120, 320, (uint16_t*)analog_rightside);

		// Peak LED
		if (percent > 78) {
			tft.setClipRect(212, 145, 17, 17);
			tft.fillCircle(220, 153, 7, ILI9341_RED);
			tft.updateScreen();
		}

		// Needle
		// DEBUG: tft.drawRect(right_min_x, right_min_y, right_max_x - right_min_x, right_max_y - right_min_y + 1, ILI9341_MAGENTA);
		tft.setClipRect(right_min_x, right_min_y, right_max_x - right_min_x, right_max_y - right_min_y + 1);
		tft.drawLine(240, yEdge, x1, y1, ILI9341_BLUE);
		tft.updateScreen();
	}
}
 

Attachments

  • RevoxA700.zip
    40.9 KB · Views: 152
Hello everyone,

now the complete loop runs in 247ms :)
Improvements:
- PROGMEM removed from image files;
- both images are no longer 120x320px but 96x224px
- For testing, set the SPI bus to 50MHz, previously 40MHz (stable overnight)

I noticed a strange effect:
When I compile the code with the Arduino IDE, the loop runs in 247ms. If I use VisualStudio2019 with VisualMicro, the loop runs in 418ms. But VisualMicro is set to release and full speed.

One more question:
I would like to try 16 colors instead of real colors for the background images.
There is the method writeRect4BPP - how exactly does it work?
Is there a small example how to convert a 24Bit .PNG into the required format and then use it?

I wish you a nice weekend
Bruno
 

Attachments

  • RevoxA700.zip
    28.5 KB · Views: 184
Visual Studio/Visual Micro - I have not done much with them. In theory if your settings are setup the same as Arduino IDE, you should get the same speed (I think)... But.

writeRect4BPP - How to convert? Not sure. You could probably write some program that runs through your array and converts it to another array where the data is packed 2 pixels per byte, plus an array of the 16 colors to use. But how you choose the 16 colors could be the interesting part.

How it works, is each nibble (4 bits) is used as an index into the passed in color palette which is 16 bits per color. So if a nibble is a 0, it uses the first color. There is no speed up to the display as you have to send the same amount of data. The benefit is the ability for your program to pack more data, especially on boards who have more limited space.
 
Visual Studio/Visual Micro - I have not done much with them. In theory if your settings are setup the same as Arduino IDE, you should get the same speed (I think)... But.

Hi,
I have found the setting in VisualStudio/VisualMicro!
Switch off 'Gdb', then everything is as fast as with the Arduino IDE.
Maybe the info is interesting?

visualmicro01.png

visualmicro02.png

Best regards
Bruno
 
Dear Bruno,
the line
int yEdge = map(0, -115, x1, 160, y1); could be written as:
int yEdge = 160 + 115 *tan(1.57078 -x1);
It derives from the formula:
a = b * tan(arc); with given arc, b.
The hard coded values are:
1.5708 = PI/2,
and from your setup: 160 -> y_0 and 115 -> length of x until display
 
Status
Not open for further replies.
Back
Top