PaulStoffregen / ST7735_t3

Teensy 3.x Optimized Version of Adafruit_ST7735 (1.8 inch TFT Display)
33 stars 16 forks source link

ST7735 framebuffer `Pixel` func does not account for rotation setting #21

Open grahamwhaley opened 3 years ago

grahamwhaley commented 3 years ago

Description

Using an ST7735 1.8" display, Teensy 4.0, and latest head of this codebase (12d3e1d117578ff38ad3f557c4ddebc45aa0096b), it looks like sloping lines do not render with using roation(1) along with the framebuffer. The potential issue looks to be in the Pixel() routine, that does not account for the rotation into the RAM array. Proposed patch below.

Steps To Reproduce Problem

Initialise a screen, and setRotation(1) to spin it around (to landscape in my case). Draw a sloping line, or a triangle suffices as well, and you get 'strided splatter' rather than nice lines. Removing either the useFrameBuffer or setRotation makes the issue go away. Snippet of my example code:

  display.initR(INITR_GREENTAB);
  display.setRotation(1);
  display.useFrameBuffer(true);
  width = display.width()-1;
  height = display.height()-1;
  display.waitUpdateAsyncComplete();
  display.fillScreen(ST7735_BLACK);
  display.drawLine(0, 0, width, height, ST7735_WHITE);
  display.drawTriangle(50, 50, 70, 70, 40, 60, ST7735_GREEN);

Hardware & Software

Teensy 4.0 with audio board.

ST7735 based 128x160 TFT 'generic' SPI board, wired to SPI0 interface.

This library on https://github.com/PaulStoffregen/ST7735_t3/commit/12d3e1d117578ff38ad3f557c4ddebc45aa0096b

Arduino Sketch

NOTE - I've not actually built and run this - if really necessary then let me know and I can/will fix up ;-) It is heavily extracted from my real local example though.

// Change the code below by your sketch (please try to give the smallest code which demonstrates the problem)
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <ST7735_t3.h>

#define TFT_SCL 13  //LED pin??
#define TFT_SCA 11
#define TFT_CS 10 //hardware CS
#define TFT_DC 1
#define TFT_RST 2

static int width=0, height=0;

void setup() {
  display.initR(INITR_GREENTAB);
  display.setRotation(1);
  display.useFrameBuffer(true);
  width = display.width()-1;
  height = display.height()-1;

  display.waitUpdateAsyncComplete();
  display.fillScreen(ST7735_BLACK);
  display.drawLine(0, 0, width, height, ST7735_WHITE);
  display.drawTriangle(50, 50, 70, 70, 40, 60, ST7735_GREEN);

  display.drawLine(0, 0, width, 0, ST7735_WHITE); //across top
  display.drawLine(width, 0, width, height, ST7735_WHITE); //rhs
  display.drawLine(0, 0, 0, height, ST7735_WHITE); //lhs
  display.drawLine(0, height, width, height, ST7735_WHITE); //bottom
}

void loop() {
  static int y = 100;
  static bool up = true;

  //Animate a line going up and down on the bottom part of the screen.
  display.waitUpdateAsyncComplete();
  display.fillRect(0, 100, width, height, ST7735_BLACK);
  display.drawLine(0, y, width, y, ST7735_WHITE); //bottom

  if (up) y++;
  else y--;

  if ( y > height ) up = false;
  if ( y < 100 ) up = true;

  display.updateScreenAsync();
}

Errors or Incorrect Output

The error is on the screen display - you can see the horizontal/vertical lines are drawn fine, but the sloping lines (the one from corner to corner, and the green triangle) are broken up and scattered across the screen.

Proposed fix

I believe the core issue is that the Pixel() routine does not take into account screen rotation when writing to the frame buffer array. I had a play, and I think if we go from:

        #ifdef ENABLE_ST77XX_FRAMEBUFFER
        if (_use_fbtft) {
            _pfbtft[y*_screenWidth + x] = color;
            return;
        }
        #endif

to

                #ifdef ENABLE_ST77XX_FRAMEBUFFER
                if (_use_fbtft) {
                        switch(rotation) {
                                case 0:
                                case 2:
                                        _pfbtft[y*_screenWidth + x] = color;
                                        break;
                                case 1:
                                case 3:
                                        _pfbtft[y*_screenHeight + x] = color;
                                        break;
                        }
                        return;
                }
                #endif

that at least fixes it. I've tested with all four rotations and my simple 'triangle test' looks to work OK. I've not thought terribly hard about it though, and don't know if there are other places this might need fixing.

Let me know if you'd like a PR pushing. I can also supply screenshots if necessary etc.

georgegohl888 commented 3 years ago

The fix worked perectly for me, thanks.