m5stack / M5Core2

M5Core2 Arduino Library
MIT License
265 stars 116 forks source link

BUG: PointAndZone.cpp -> Zone::rotate() #47

Open FerNadal opened 3 years ago

FerNadal commented 3 years ago

In the calculation of inv_x and inv_y, TFT_WIDTH and TFT_HEIGHT must be interchanged according to the rotation of the screen. Otherwise, the resulting coordinates of the Zone :: rotate () function are wrong and do not correspond to the physical locations of buttons A, B, and C.

Demonstration:

M5.Lcd.setRotation(2);
...
BtnA(10,240,110,40..);

Inside Zone :: rotate ():

inv_x = TFT_WIDTH - 1 - x - w (= 240 - 1 - 10 - 110 = 119 -> Wrong!!)
...
switch (m) {
...
  case 2:
    x = normal_y;
    y = inv_x;
    break;
...

The zone corresponding to button A would have the coordinates (240,119,280,229), overlapping with the real button B (240,130,280,200).

Correct value:

When the rotation is 2, the screen has a resolution of 240(280)x320 in the rotated x and y directions, so:

inv_x = TFT_WIDTH - 1 - x - w (= 320 - 1 - 10 - 110 = 199 - > Correct !!)

Fixed function:

void Zone::rotate(uint8_t m) {
  if (m == 1) return;

  int16_t tftW = TFT_WIDTH;
  int16_t tftH = TFT_HEIGHT;

  switch (m) {
    case 0:
      tftW = TFT_HEIGHT;
      tftH = TFT_WIDTH;
      break;
    case 2:
      tftW = TFT_HEIGHT;
      tftH = TFT_WIDTH;
      break;
    case 3:
      tftW = TFT_WIDTH;
      tftH = TFT_HEIGHT;
      break;
    // rotations 4-7 are mirrored
    case 4:
      tftW = TFT_HEIGHT;
      tftH = TFT_WIDTH;
      break;
    case 5:
      tftW = TFT_WIDTH;
      tftH = TFT_HEIGHT;
      break;
    case 6:
      tftW = TFT_HEIGHT;
      tftH = TFT_WIDTH;
      break;
    case 7:
      tftW = TFT_WIDTH;
      tftH = TFT_HEIGHT;
      break;
  }

  int16_t normal_x = x;
  int16_t normal_y = y;
  int16_t inv_x = tftW - 1 - x - w;
  int16_t inv_y = tftH - 1 - y - h;
...

There are no changes from this line to the end of the function.

digi-thomas2003 commented 1 year ago

Thx a lot for this issue. It helped me to find out, why my M5Stack Core2 didn't work properly with rotation. But in the section "case 3" is still a mistake.

The right variables are the following:

case 3:
      tftW = TFT_HEIGHT;
      tftH = TFT_WIDTH;
      break;

Then it works as expected: The buttons (aka the small red circles) are on the top and they react now.