#define SCREEN_Y  240   // Screen sizes are set here.
    #define SCREEN_X  320

    #define ARROW_OUT 1
    #define ARROW_IN 2

    #define BAR_LONG 3
    #define BAR_SHORT 4
    
#include "STM32Link.h"
#include "Free_Fonts.h"
#include "GaugeWidgetsStm32.h"
TFT_eSprite gdraw = TFT_eSprite(&VV.Lcd);

Gauges myGauges;
/*
   Function prototype
*/
void AiGraph  (int16_t px0, int16_t py0, int16_t arcSize, int16_t arcWidth, int16_t maxDisplay, int16_t minDisplay,
              int16_t startAngle, int16_t arcAngle, bool clockWise, uint8_t gradMarks,
              int16_t pitch, int16_t roll, int16_t yaw);

void pitchGraph(int16_t pitch, int16_t roll, int16_t px0, int16_t py0, uint8_t scale);               
       
// uint16_t displayBrightness = 100;       
/*
  Example data values. Usually these are derived from a data input function.
*/  
// int16_t px0 = 240;// center of the screen Х
int16_t px0 = SCREEN_X / 2;
// int16_t py0 = 160;// center of the screen Y
int16_t py0 = SCREEN_Y / 2;
int16_t pitch = 0;
int16_t roll = 20;
int16_t yaw = 0;
// int16_t arcSize = 160; // size of the ar
int16_t arcSize = SCREEN_X / 2;
int16_t arcWidth = 15;
int16_t maxDisplay = 360;
int16_t minDisplay = 0;
int16_t startAngle = -roll;
int16_t arcAngle = 360;
int16_t clockWise = true;
uint8_t gradMarks = 0;

uint16_t pitchdirection = 4;
uint16_t rolldirection = 2;

void setup() {

  // printf("Flash size: %d bytes\n", spi_flash_get_chip_size());// displayed on starting
  // printf("Psram size: %d bytes\n", ESP.getPsramSize()); // not displayed on starting

  VV.begin();
  // VV.Lcd.setSwapBytes(true);
  // M5.Lcd.setRotation(1);
  //VV.Lcd.fillScreen(TFT_CYAN);
  //delay (100);

  gdraw.setColorDepth(6);
  gdraw.createSprite(SCREEN_X, SCREEN_Y);
  // gdraw.setFreeFont(FSSB9);
  // gdraw.setTextWrap(false); // Very important for scaling
}

void loop() {

  // gdraw.fillSprite (TFT_CYAN);
  gdraw.fillSprite (TFT_BLUE);
  // VV.update();
  
  /*
   Change display brightness using panel buttons.
  */
  // if (M5.BtnC.wasReleased() && !M5.BtnA.wasPressed() && (displayBrightness > 0)) {
    // displayBrightness *= 2; // brightness up
  // }

  // if (M5.BtnA.wasPressed() && !M5.BtnC.wasReleased() && (displayBrightness <= 255)) {
    // displayBrightness /= 2; // brightness down
  // }

  // if (displayBrightness < 1) displayBrightness = 1;
  // if (displayBrightness > 255) displayBrightness = 255;
	// Init the back-light LED PWM
	// ledcSetup(BLK_PWM_CHANNEL, 44100, 8);
	// ledcAttachPin(TFT_BL, BLK_PWM_CHANNEL);
	// ledcWrite(BLK_PWM_CHANNEL, displayBrightness);  
	// M5.Lcd.setBrightness (displayBrightness);
	// M5.setBrightness (displayBrightness);
  
  /*
  */
  AiGraph (px0, py0, arcSize, arcWidth, maxDisplay, minDisplay, startAngle, arcAngle, clockWise,
           gradMarks, pitch, roll, yaw);

  gdraw.pushSprite (0, 0);
  
  pitch += pitchdirection;
  roll += rolldirection;

  if (pitch >= 90) pitchdirection = -2;
  if (roll >= 180) rolldirection = -2;
  if (pitch <= -90) pitchdirection = +2;
  if (roll <= -180) rolldirection = +2;
  
}

void AiGraph (int16_t px0, int16_t py0, int16_t arcSize, int16_t arcWidth, int16_t maxDisplay, int16_t minDisplay,
              int16_t startAngle, int16_t arcAngle, bool clockWise, uint8_t gradMarks,
              int16_t pitch, int16_t roll, int16_t yaw) {        
  
/*
    Draw Horizon first

<----------------------p0----------------------> about +/- 2x screen width
       |
       |
       | Pitch
      \ /
      p1---------------pc---------------p2   
      |                                 |
      |                                 |
      |                                 |
      p3--------------------------------p4 
      
  */
 {
    arcSize = 160;
   
  /*
  Establish a wide horizontal baseline segment
  */ 
    float xRotate = (2.0f * (float)SCREEN_X) * cos (roll * DEG_TO_RAD); 
    float yRotate = (2.0f * (float)SCREEN_X) * sin (roll * DEG_TO_RAD); 

  /*
  Adjust it for roll and pitch
  */
    float pxc = px0 + pitch * SCREEN_Y/80 * sin (roll * DEG_TO_RAD ); 
    float pyc = py0 + pitch * SCREEN_Y/80 * cos (roll * DEG_TO_RAD ); 

    float px1 = pxc - xRotate;
    float py1 = pyc + yRotate;
    
    float px2 = pxc + xRotate;
    float py2 = pyc - yRotate;

  /*  
   Compute offset parallel line segment to establish a wide bar
  */
    float px3 = px1 + 3 * SCREEN_Y * cos(roll * DEG_TO_RAD - HALF_PI);
    float py3 = py1 - 3 * SCREEN_Y * sin(-roll * DEG_TO_RAD - HALF_PI);
                      
    float px4 = px2 - 3 * SCREEN_Y * cos(roll * DEG_TO_RAD + HALF_PI);
    float py4 = py2 + 3 * SCREEN_Y * sin(roll * DEG_TO_RAD + HALF_PI);
 
/*
 Fill the bar.  Will be automatically clipped outside of screen bounds
*/ 
    
    // gdraw.fillTriangle (px1, py1, px2, py2, px3, py3, TFT_OLIVE);
    gdraw.fillTriangle (px1, py1, px2, py2, px3, py3, TFT_BROWN);
    // gdraw.fillTriangle (px3, py3, px4, py4, px2, py2, TFT_OLIVE);
    gdraw.fillTriangle (px3, py3, px4, py4, px2, py2, TFT_BROWN);
    gdraw.drawLine (px1, py1, px2, py2, TFT_BLACK);
    gdraw.drawLine (px3, py3, px4, py4, TFT_BLUE);
    gdraw.fillCircle (pxc, pyc, 3, TFT_BLACK);
       
//  gdraw.drawString("1", px1, py1);
//  gdraw.drawString("2", px2, py2);
//  gdraw.drawString("3", px3, py3);
//  gdraw.drawString("4", px4, py4);

}
  /*
    Draw pitch graphic in background
  */
  pitchGraph(pitch, roll, px0, py0, 10);

  /*
    Draw Horizon Indicator
  */  
  arcSize = 115;
  arcWidth = 15;
  
  myGauges.clearRanges();

  myGauges.clearPointers();
  myGauges.setPointer (1, 0,   BAR_LONG, TFT_WHITE, '\0');
  myGauges.setPointer (2, 180, BAR_LONG, TFT_WHITE, '\0'); 
  myGauges.setPointer (3, 210, BAR_LONG, TFT_WHITE, '\0'); 
  myGauges.setPointer (4, 240, BAR_LONG, TFT_WHITE, '\0'); 
  myGauges.setPointer (5, 270, ARROW_OUT, TFT_YELLOW, '\0'); 
  myGauges.setPointer (6, 300, BAR_LONG, TFT_WHITE, '\0'); 
  myGauges.setPointer (7, 330, BAR_LONG, TFT_WHITE, '\0'); 
  myGauges.setPointer (8, 0, 0,  0, '\0');

  myGauges.arcGraph (px0, py0, arcSize, arcWidth , maxDisplay, minDisplay,
                     -roll, arcAngle, clockWise, gradMarks);
				 
  /*
    Draw additional small markers
  */	
  arcSize = 115;
  arcWidth = 15;
  
  myGauges.clearRanges();
 
  myGauges.clearPointers();
  myGauges.setPointer (1, 250, BAR_SHORT, TFT_WHITE, '\0');
  myGauges.setPointer (2, 260, BAR_SHORT, TFT_WHITE, '\0'); 
  myGauges.setPointer (3, 280, BAR_SHORT, TFT_WHITE, '\0');
  myGauges.setPointer (4, 290, BAR_SHORT, TFT_WHITE, '\0');
  myGauges.setPointer (5, 225, ROUND_DOT, TFT_WHITE, '\0');
  myGauges.setPointer (6, 315, ROUND_DOT, TFT_WHITE, '\0');
  myGauges.setPointer (7, 0, 0,  0, '\0');
  myGauges.setPointer (8, 0, 0,  0, '\0');
 
  
  myGauges.arcGraph (px0, py0, arcSize, arcWidth , maxDisplay, minDisplay,
                     -roll, arcAngle, clockWise, gradMarks);					 
  

  /*
    Draw Airplane
	
                   p0
	p1----------p2 o  p3---------p4
			     \   /
			      \ /
				   p5
  */
 
  arcSize = 100;
  arcWidth = 15;
  
  uint16_t px1 = px0 - arcSize; 
  uint16_t py1 = py0;
  uint16_t px2 = px0 - arcSize / 4 ; 
  uint16_t py2 = py0;
  uint16_t px3 = px0 + arcSize / 4 ; 
  uint16_t py3 = py0;
  uint16_t px4 = px0 + arcSize; 
  uint16_t py4 = py0;
  uint16_t px5 = px0; 
  uint16_t py5 = py0 + arcSize / 4;
  
  gdraw.fillCircle (px0, py0, 2 * SCREEN_Y/80, TFT_YELLOW);   // 2 degree radius circle
  gdraw.drawCircle (px0, py0, 2 * SCREEN_Y/80, TFT_BLACK);  
  
  gdraw.drawFastHLine (px1, py1, 3*arcSize/4, TFT_YELLOW);
  gdraw.drawLine (px2, py2, px5, py5, TFT_YELLOW);
  gdraw.drawLine (px5, py5, px3, py3, TFT_YELLOW);
  gdraw.drawFastHLine (px3, py3, 3*arcSize/4, TFT_YELLOW);

  gdraw.drawFastHLine (px1, py1-1, 3*arcSize/4, TFT_YELLOW);
  gdraw.drawLine (px2, py2-1, px5, py5-1, TFT_YELLOW);
  gdraw.drawLine (px5, py5-1, px3, py3-1, TFT_YELLOW);
  gdraw.drawFastHLine (px3, py3-1, 3*arcSize/4, TFT_YELLOW);
  
  gdraw.drawFastHLine (px1, py1-2, 3*arcSize/4, TFT_YELLOW);
  gdraw.drawLine (px2, py2-2, px5, py5-2, TFT_YELLOW);
  gdraw.drawLine (px5, py5-2, px3, py3-2, TFT_YELLOW);
  gdraw.drawFastHLine (px3, py3-2, 3*arcSize/4, TFT_YELLOW);
 
  gdraw.drawFastHLine (px1, py1-3, 3*arcSize/4, TFT_BLACK);
  gdraw.drawLine (px2, py2-3, px5, py5-3, TFT_BLACK);
  gdraw.drawLine (px5, py5-3, px3, py3-3, TFT_BLACK);
  gdraw.drawFastHLine (px3, py3-3, 3*arcSize/4, TFT_BLACK);
  
  gdraw.drawFastHLine (px1, py1+1, 3*arcSize/4, TFT_YELLOW);
  gdraw.drawLine (px2, py2+1, px5, py5+1, TFT_YELLOW);
  gdraw.drawLine (px5, py5+1, px3, py3+1, TFT_YELLOW);
  gdraw.drawFastHLine (px3, py3+1, 3*arcSize/4, TFT_YELLOW);
									   
  gdraw.drawFastHLine (px1, py1+2, 3*arcSize/4, TFT_YELLOW);
  gdraw.drawLine (px2, py2+2, px5, py5+2, TFT_YELLOW);
  gdraw.drawLine (px5, py5+2, px3, py3+2, TFT_YELLOW);
  gdraw.drawFastHLine (px3, py3+2, 3*arcSize/4, TFT_YELLOW);
									   
  gdraw.drawFastHLine (px1, py1+3, 3*arcSize/4, TFT_BLACK);
  gdraw.drawLine (px2, py2+3, px5, py5+3, TFT_BLACK);
  gdraw.drawLine (px5, py5+3, px3, py3+3, TFT_BLACK);
  gdraw.drawFastHLine (px3, py3+3, 3*arcSize/4, TFT_BLACK);

  gdraw.drawFastVLine (px1, py1-3, 6, TFT_BLACK);
  gdraw.drawFastVLine (px4, py4-3, 6, TFT_BLACK);

  /*
	Draw top pointer
  */
  px1 = px0;
  py1 = py0 - arcSize + arcWidth / 2;
  px2 = px0 - arcWidth / 2;
  py2 = py0 - arcSize + 2 * arcWidth;
  px3 = px0 + arcWidth / 2;
  py3 = py0 - arcSize + 2 * arcWidth;
  
  gdraw.fillTriangle (px1, py1, px2, py2, px3, py3, TFT_YELLOW);
					 
  gdraw.drawLine (px1, py1, px2, py2, TFT_BLACK);
  gdraw.drawLine (px2, py2, px3, py3, TFT_BLACK);
  gdraw.drawLine (px3, py3, px1, py1, TFT_BLACK);
}

void pitchGraph(int16_t pitch, int16_t roll, int16_t px0, int16_t py0, uint8_t scale) {  

  /* Draw Pitch scale
    
    --------- 40
      -----
    --------- 30
      -----
    --------- 20
      -----
  p3---------p4 10
    p1-----p2 
      p0+
      
  */

   
 /*
  Establish a horizontal baseline segment
  */ 

  float px1, px2, px3, px4, px5;
  float py1, py2, py3, py4, py5;
  float xRotate;
  float yRotate;   
  
  float pxc = px0 + pitch * SCREEN_Y/80  * sin (roll * DEG_TO_RAD ); 
  float pyc = py0 + pitch * SCREEN_Y/80 * cos (roll * DEG_TO_RAD ); 

  /*
    Compute pitch scale
  */
    
    gdraw.setTextDatum(MC_DATUM);
    
    xRotate = (0.10f * arcSize) * cos (roll * DEG_TO_RAD); // establish the width.
    yRotate = (0.10f * arcSize) * sin (roll * DEG_TO_RAD); 
    
    px1 = pxc - xRotate*1.0f; 
    py1 = pyc + yRotate*1.0f;  
                           
    px2 = pxc + xRotate*1.0f;
    py2 = pyc - yRotate*1.0f;
    
  for (int16_t i = -85; i <= 85; i+= scale){

// Marks every 5 degrees
     
    px3 = px1 - (i * SCREEN_Y/80) * cos(roll * DEG_TO_RAD - HALF_PI);
    py3 = py1 + (i * SCREEN_Y/80) * sin(-roll * DEG_TO_RAD - HALF_PI);
                         
    px4 = px2 + (i * SCREEN_Y/80) * cos(roll * DEG_TO_RAD + HALF_PI);
    py4 = py2 - (i * SCREEN_Y/80) * sin(roll * DEG_TO_RAD + HALF_PI);

    gdraw.drawLine (px3, py3, px4, py4, TFT_BLACK); 
}

    px1 = pxc - xRotate*2.0f; 
    py1 = pyc + yRotate*2.0f;  
                         
    px2 = pxc + xRotate*2.0f;
    py2 = pyc - yRotate*2.0f; 

  for (int16_t i = -90; i <= 90; i+= scale){

// Marks every 5 degrees
     
    px3 = px1 - (i * SCREEN_Y/80) * cos(roll * DEG_TO_RAD - HALF_PI);
    py3 = py1 + (i * SCREEN_Y/80) * sin(-roll * DEG_TO_RAD - HALF_PI);
                         
    px4 = px2 + (i * SCREEN_Y/80) * cos(roll * DEG_TO_RAD + HALF_PI);
    py4 = py2 - (i * SCREEN_Y/80) * sin(roll * DEG_TO_RAD + HALF_PI);

    gdraw.setCursor(px4, py4);
    gdraw.drawLine (px3, py3, px4, py4, TFT_BLACK); 
    
    px4 += xRotate*0.75f; 
    py4 -= yRotate*0.75f; 
    //myGauges.printNum ("123456789", 160, 120, 8, 12, roll, TFT_BLACK, MR_DATUM);
    myGauges.printNum (String (i)+"o", px4, py4, 8, 12, roll, TFT_BLACK, ML_DATUM);
  }    
} // end pitchGraph