nikthefix / Lilygo_Support_T_Display_S3_Long_TFT_eSPI_Volos-nikthefix

16 stars 2 forks source link

PushRotate? #3

Open d3mac123 opened 4 months ago

d3mac123 commented 4 months ago

Is the pushRotate function already implemented? I am trying to run this piece of code but it is crashing when pushRotate is called.

#include "AXS15231B.h"
#include <Arduino.h>
#include <TFT_eSPI.h> 

TFT_eSPI tft = TFT_eSPI();
TFT_eSprite back = TFT_eSprite(&tft);
TFT_eSprite sky = TFT_eSprite(&tft);

const uint16_t SCREEN_X = 320;  // Screen sizes are set here.
const uint16_t SCREEN_Y = 170;
#define cBlue 0x665B //blue background
#define cRed 0xC0E3 //red background

int angle=0;
int pline;

void setup() {
  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, LOW);        // turn off backlight asap to minimise power on artifacts
  Serial.begin(115200); 
  axs15231_init();

  tft.setPivot(SCREEN_X/2,SCREEN_Y/2);
  sky.createSprite(SCREEN_X*2,SCREEN_Y*2);
  sky.setSwapBytes(1);
  back.createSprite(SCREEN_X,SCREEN_Y);
  lcd_fill(0,0,180,640,0x00);       // clear screen
  digitalWrite(TFT_BL, HIGH);       // turn on backlight

}

void loop() {
  back.fillSprite(TFT_BLACK);
  pline = 0;

  sky.fillRect((SCREEN_X/2) - SCREEN_X, ((SCREEN_Y/2) - SCREEN_Y)+ pline, SCREEN_X*2, ((SCREEN_Y/2) + SCREEN_Y) + pline,cBlue); //SKY
  sky.fillRect((SCREEN_X/2) - SCREEN_X, SCREEN_Y + pline + 1, SCREEN_X * 2, SCREEN_Y + (SCREEN_Y/2) + pline + 1,cRed); //GROUND
  sky.drawLine((SCREEN_X/2) - SCREEN_X, SCREEN_Y + pline, SCREEN_X * 2, SCREEN_Y + pline,TFT_WHITE);

  sky.pushRotated(&back,angle,TFT_BLACK);

  back.drawNumber(angle,160,100,2);
  back.pushSprite(0,0);
  lcd_PushColors_rotated_90(0, 0, 640, 180, (uint16_t*)back.getPointer());

  angle++;
  if(angle==360) { 
    angle=0;
  } 
}
nikthefix commented 4 months ago

Yes as long as you're using the AXS15231B files from my repo.

Your main full screen sprite needs to be the full size of the Long display so change the main sprite to 640x180. Then when updating the display you always push this sprite using lcd_PushColors_rotated_90() in this case. All other writes to the display are actually writes to the main sprite so instead of

tft.setPivot(SCREEN_X/2,SCREEN_Y/2);

you need to use

sky.setPivot(SCREEN_X/2,SCREEN_Y/2);

or which ever sprite you want to set a pivot for.

Using this display buffer approach you'd only refer to the tft object here and nowhere else:

TFT_eSPI tft = TFT_eSPI(); TFT_eSprite back = TFT_eSprite(&tft); TFT_eSprite sky = TFT_eSprite(&tft);

I think I see what your making. Forgive me if I'm wrong. Try this:

include "AXS15231B.h"

include

include

TFT_eSPI tft = TFT_eSPI(); TFT_eSprite back = TFT_eSprite(&tft); TFT_eSprite sky = TFT_eSprite(&tft);

const uint16_t SCREEN_X = 320; // Screen sizes are set here. const uint16_t SCREEN_Y = 170;

define cBlue 0x665B //blue background

define cRed 0xC0E3 //red background

int angle=0; int pline;

void setup() { pinMode(TFT_BL, OUTPUT); digitalWrite(TFT_BL, LOW); // turn off backlight asap to minimise power on artifacts Serial.begin(115200); axs15231_init();

back.createSprite(640,180); back.setSwapBytes(1); //only needed for the main top level sprite

sky.createSprite(SCREEN_X2,SCREEN_Y2); sky.setPivot(SCREEN_X/2,SCREEN_Y/2);

lcd_fill(0,0,180,640,0x00); // clear screen digitalWrite(TFT_BL, HIGH); // turn on backlight

}

void loop() { back.fillSprite(TFT_BLACK); pline = 0;

sky.fillRect((SCREEN_X/2) - SCREEN_X, ((SCREEN_Y/2) - SCREEN_Y)+ pline, SCREEN_X2, ((SCREEN_Y/2) + SCREEN_Y) + pline,cBlue); //SKY sky.fillRect((SCREEN_X/2) - SCREEN_X, SCREEN_Y + pline + 1, SCREEN_X 2, SCREEN_Y + (SCREEN_Y/2) + pline + 1,cRed); //GROUND sky.drawLine((SCREEN_X/2) - SCREEN_X, SCREEN_Y + pline, SCREEN_X * 2, SCREEN_Y + pline,TFT_WHITE);

sky.pushRotated(&back,angle,TFT_BLACK);

back.drawNumber(angle,160,100,2); //back.pushSprite(0,0); //not needed lcd_PushColors_rotated_90(0, 0, 640, 180, (uint16_t*)back.getPointer());

angle++; if(angle==360) { angle=0; } }

I recommend that you call your main display buffer sprite 'full_screen' or 'screen_buffer' or something like that. Then you can re-use the code in other projects without possibly confusing references to project specific gui elements.

To place a rotated sprite to an arbitrary location you can use the new TFT_eSPI Viewport function. It's very useful as saves doing a lot of arithmetic.

d3mac123 commented 4 months ago

The reason I need to have a larger than the screen size sprite (it works on the regular T-Display, btw) is for the full rotation - see here Screenshot 2023-12-22 at 10 41 58 AM

Having it set only to the full screen size gets me the wrong drawing - see below IMG_5316 Large

nikthefix commented 4 months ago

Yes I understand. I was only guessing the dimensions. But it does work with the sky.pushRotated(&back,angle,TFT_BLACK); ? You're not getting the crash now?

nikthefix commented 4 months ago

Your project looks great. Is it a flight sim avionix?

d3mac123 commented 4 months ago

I am not getting the crash anymore (although refreshing the full-screen is painful as you can see by the movie).

Regarding the project, this is for a real airplane :) - My main avionics display is a Dynon Skyview, which transmits all the data wireless via UDP. I use the ESP32 to capture the data and serve as a backup system. Also, I am adding more functionality, like the checklist part.

https://github.com/nikthefix/Lilygo_Support_T_Display_S3_Long_TFT_eSPI_Volos-nikthefix/assets/229148/2256926c-de27-49ca-a400-1454d7246f15

nikthefix commented 4 months ago

Yes the full screen update is slow due to the low max spi rate of the display plus the fact that we have to do software rotate for landscape mode. But I'm working on partial update for TFT_eSPI. You can see in my LVGL demo that things are very fast as I already implemented partial update (it was much easier to do for LVGL). Partial update is only beneficial if animations are restricted to regions less than full screen.

But for an artificial horizon which requires a full screen sprite rotate there's only so much you can do. At the moment my lib is not using DMA as it was problematic with alpha3. I will add that after successful tests. Then things should be faster all round.

I think the Long will be fine for you to develop your product but at some point you'll probably want to migrate your code to a hardware configuration with a similar display form factor but which allows not only faster MCU->Display comms but a native landscape mode. There are loads of parallel RGB displays out there with similar dimensions. They come with a different set of problems for the current ESP32_Arduino Core implementation but speed is definitely not one of those problems.

A good entry point for using RGB 40-pin displays is Adafruit Qualia: https://www.adafruit.com/product/5800

They have a hopefully growing list of officially supported displays.

BTW, your video IMG_5317.MOV wouldn't play.

d3mac123 commented 4 months ago

Video is working fine for me... Weird...

The artificial horizon is not the main feature (probably neither the second, as I have already a second display in the aircraft as a backup). I just added that because, why not? 😃

The reason I like the Long format is for the checklist part and because panel space is very limited in my case.

nikthefix commented 4 months ago

It's probably my browser (Brave). If you upload a zip of your video I can download.

There is a 10MB limit on videos you can add directly to comments and 25MB limit on a zipped file upload.

nikthefix commented 4 months ago

Just out of interest, you say UDP for the data transfer. Is that a wifi peer-to-peer config? Sounds interesting. Does the Dynon Skyview offer other ways to transmit its data? Or is it acting as a wifi hotspot?

I always wondered how 'In-Cockpit' telemetry was done if not hard wired.

You're a pilot? I'm jealous! Love planes. I took a 2 week hang gliding course and a basic helicopter lesson once. I nearly got into auto-gyros but was put off by some overly negative microlight enthusiasts! :) I plan to do sailplanes tho.

d3mac123 commented 4 months ago

IMG_5317.MOV.zip

Dynon transmits via Wifi/UDP (if you have their Wifi module - a USB dongle that creates a hotspot) or via serial ports. All avionics use serial but I had to opt for the WiFi mode because all my serial ports are already in use by other stuff.

I got my pilot license a few years ago (just as a hobby). Before planes, I flew powered paragliders for a decade. I like gyros and helicopters but, I don't think they are my thing :)

d3mac123 commented 3 months ago

Any updates on the library (refresh rates, rotation, etc)? BTW, do you recommend any good tutorials on the LVGL? Maybe it is the time to move on from TFT_eSPI?

nikthefix commented 3 months ago

I'm going to be adding some demos for the T4-S3 AMOLED soon so some of that stuff will filter back to the Long. I started using LVGL when I tried Square Line Studio for the first time. It's really a very good way to learn about LVGL. I'm not familiar with any tutorials but the on-line documentation for LVGL is fantastic! There are also great tutorials on YT for getting started with Square Line Studio.