329 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			329 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
| 
 | |
|   This program provides cartesian type graph function
 | |
| 
 | |
|   Revisions
 | |
|   rev     date        author      description
 | |
|   1       12-24-2015  kasprzak    initial creation
 | |
| 
 | |
|   Updated by Bodmer to be an example for the library here:
 | |
|   https://github.com/Bodmer/TFT_eSPI
 | |
|   
 | |
| */
 | |
| 
 | |
| #include <TFT_eSPI.h> // Hardware-specific library
 | |
| #include <SPI.h>
 | |
| 
 | |
| TFT_eSPI tft = TFT_eSPI();                   // Invoke custom library with default width and height
 | |
| 
 | |
| 
 | |
| #define LTBLUE    0xB6DF
 | |
| #define LTTEAL    0xBF5F
 | |
| #define LTGREEN   0xBFF7
 | |
| #define LTCYAN    0xC7FF
 | |
| #define LTRED     0xFD34
 | |
| #define LTMAGENTA 0xFD5F
 | |
| #define LTYELLOW  0xFFF8
 | |
| #define LTORANGE  0xFE73
 | |
| #define LTPINK    0xFDDF
 | |
| #define LTPURPLE  0xCCFF
 | |
| #define LTGREY    0xE71C
 | |
| 
 | |
| #define BLUE      0x001F
 | |
| #define TEAL      0x0438
 | |
| #define GREEN     0x07E0
 | |
| #define CYAN      0x07FF
 | |
| #define RED       0xF800
 | |
| #define MAGENTA   0xF81F
 | |
| #define YELLOW    0xFFE0
 | |
| #define ORANGE    0xFC00
 | |
| #define PINK      0xF81F
 | |
| #define PURPLE    0x8010
 | |
| #define GREY      0xC618
 | |
| #define WHITE     0xFFFF
 | |
| #define BLACK     0x0000
 | |
| 
 | |
| #define DKBLUE    0x000D
 | |
| #define DKTEAL    0x020C
 | |
| #define DKGREEN   0x03E0
 | |
| #define DKCYAN    0x03EF
 | |
| #define DKRED     0x6000
 | |
| #define DKMAGENTA 0x8008
 | |
| #define DKYELLOW  0x8400
 | |
| #define DKORANGE  0x8200
 | |
| #define DKPINK    0x9009
 | |
| #define DKPURPLE  0x4010
 | |
| #define DKGREY    0x4A49
 | |
| 
 | |
| // these are the only external variables used by the graph function
 | |
| // it's a flag to draw the coordinate system only on the first call to the Graph() function
 | |
| // and will mimize flicker
 | |
| // also create some variables to store the old x and y, if you draw 2 graphs on the same display
 | |
| // you will need to store ox and oy per each display
 | |
| bool display1 = true;
 | |
| bool update1 = true;
 | |
| 
 | |
| double ox = -999, oy = -999; // Force them to be off screen
 | |
| 
 | |
| /*
 | |
| 
 | |
|   function to draw a cartesian coordinate system and plot whatever data you want
 | |
|   just pass x and y and the graph will be drawn
 | |
| 
 | |
|   huge arguement list
 | |
|   &d name of your display object
 | |
|   x = x data point
 | |
|   y = y datapont
 | |
|   gx = x graph location (lower left)
 | |
|   gy = y graph location (lower left)
 | |
|   w = width of graph
 | |
|   h = height of graph
 | |
|   xlo = lower bound of x axis
 | |
|   xhi = upper bound of x asis
 | |
|   xinc = division of x axis (distance not count)
 | |
|   ylo = lower bound of y axis
 | |
|   yhi = upper bound of y asis
 | |
|   yinc = division of y axis (distance not count)
 | |
|   title = title of graph
 | |
|   xlabel = x asis label
 | |
|   ylabel = y asis label
 | |
|   &redraw = flag to redraw graph on first call only
 | |
|   color = plotted trace colour
 | |
| */
 | |
| 
 | |
| 
 | |
| void Graph(TFT_eSPI &tft, double x, double y, byte dp,
 | |
|                            double gx, double gy, double w, double h,
 | |
|                            double xlo, double xhi, double xinc,
 | |
|                            double ylo, double yhi, double yinc,
 | |
|                            char *title, char *xlabel, char *ylabel,
 | |
|                            bool &redraw, unsigned int color) {
 | |
| 
 | |
|   double ydiv, xdiv;
 | |
|   double i;
 | |
|   double temp;
 | |
|   int rot, newrot;
 | |
| 
 | |
|   // gcolor = graph grid colors
 | |
|   // acolor = axes line colors
 | |
|   // pcolor = color of your plotted data
 | |
|   // tcolor = text color
 | |
|   // bcolor = background color
 | |
|   unsigned int gcolor = DKBLUE;
 | |
|   unsigned int acolor = RED;
 | |
|   unsigned int pcolor = color;
 | |
|   unsigned int tcolor = WHITE;
 | |
|   unsigned int bcolor = BLACK;
 | |
| 
 | |
|   if (redraw == true) {
 | |
| 
 | |
|     redraw = false;
 | |
|     // initialize old x and old y in order to draw the first point of the graph
 | |
|     // but save the transformed value
 | |
|     // note my transform funcition is the same as the map function, except the map uses long and we need doubles
 | |
|     //ox = (x - xlo) * ( w) / (xhi - xlo) + gx;
 | |
|     //oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
 | |
| 
 | |
|     tft.setTextDatum(MR_DATUM);
 | |
| 
 | |
|     // draw y scale
 | |
|     for ( i = ylo; i <= yhi; i += yinc) {
 | |
|       // compute the transform
 | |
|       temp =  (i - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
 | |
| 
 | |
|       if (i == 0) {
 | |
|         tft.drawLine(gx, temp, gx + w, temp, acolor);
 | |
|         tft.setTextColor(acolor, bcolor);
 | |
|         tft.drawString(xlabel, (int)(gx + w) , (int)temp, 2);
 | |
|       }
 | |
|       else {
 | |
|         tft.drawLine(gx, temp, gx + w, temp, gcolor);
 | |
|       }
 | |
|       // draw the axis labels
 | |
|       tft.setTextColor(tcolor, bcolor);
 | |
|       // precision is default Arduino--this could really use some format control
 | |
|       tft.drawFloat(i, dp, gx - 4, temp, 1);
 | |
|     }
 | |
| 
 | |
|     // draw x scale
 | |
|     for (i = xlo; i <= xhi; i += xinc) {
 | |
| 
 | |
|       // compute the transform
 | |
|       temp =  (i - xlo) * ( w) / (xhi - xlo) + gx;
 | |
|       if (i == 0) {
 | |
|         tft.drawLine(temp, gy, temp, gy - h, acolor);
 | |
|         tft.setTextColor(acolor, bcolor);
 | |
|         tft.setTextDatum(BC_DATUM);
 | |
|         tft.drawString(ylabel, (int)temp, (int)(gy - h - 8) , 2);
 | |
|       }
 | |
|       else {
 | |
|         tft.drawLine(temp, gy, temp, gy - h, gcolor);
 | |
|       }
 | |
|       // draw the axis labels
 | |
|       tft.setTextColor(tcolor, bcolor);
 | |
|       tft.setTextDatum(TC_DATUM);
 | |
|       // precision is default Arduino--this could really use some format control
 | |
|       tft.drawFloat(i, dp, temp, gy + 7, 1);
 | |
|     }
 | |
| 
 | |
|     //now draw the graph labels
 | |
|     tft.setTextColor(tcolor, bcolor);
 | |
|     tft.drawString(title, (int)(gx + w / 2) , (int)(gy - h - 30), 4);
 | |
|   }
 | |
| 
 | |
|   // the coordinates are now drawn, plot the data
 | |
|   // the entire plotting code are these few lines...
 | |
|   // recall that ox and oy are initialized above
 | |
|   //x =  (x - xlo) * ( w) / (xhi - xlo) + gx;
 | |
|   //y =  (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
 | |
|   //tft.drawLine(ox, oy, x, y, pcolor);
 | |
|   // it's up to you but drawing 2 more lines to give the graph some thickness
 | |
|   //tft.drawLine(ox, oy + 1, x, y + 1, pcolor);
 | |
|   //tft.drawLine(ox, oy - 1, x, y - 1, pcolor);
 | |
|   //ox = x;
 | |
|   //oy = y;
 | |
| 
 | |
| }
 | |
| 
 | |
| void Trace(TFT_eSPI &tft, double x,  double y,  byte dp,
 | |
|            double gx, double gy,
 | |
|            double w, double h,
 | |
|            double xlo, double xhi, double xinc,
 | |
|            double ylo, double yhi, double yinc,
 | |
|            char *title, char *xlabel, char *ylabel,
 | |
|            bool &update1, unsigned int color)
 | |
| {
 | |
|   double ydiv, xdiv;
 | |
|   double i;
 | |
|   double temp;
 | |
|   int rot, newrot;
 | |
| 
 | |
|   //unsigned int gcolor = DKBLUE;   // gcolor = graph grid color
 | |
|   unsigned int acolor = RED;        // acolor = main axes and label color
 | |
|   unsigned int pcolor = color;      // pcolor = color of your plotted data
 | |
|   unsigned int tcolor = WHITE;      // tcolor = text color
 | |
|   unsigned int bcolor = BLACK;      // bcolor = background color
 | |
| 
 | |
|   // initialize old x and old y in order to draw the first point of the graph
 | |
|   // but save the transformed value
 | |
|   // note my transform funcition is the same as the map function, except the map uses long and we need doubles
 | |
|   if (update1) {
 | |
|     update1 = false;
 | |
|     
 | |
|     ox = (x - xlo) * ( w) / (xhi - xlo) + gx;
 | |
|     oy = (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
 | |
| 
 | |
|     if ((ox < gx) || (ox > gx+w)) {update1 = true; return;}
 | |
|     if ((oy < gy-h) || (oy > gy)) {update1 = true; return;}
 | |
|     
 | |
| 
 | |
|     tft.setTextDatum(MR_DATUM);
 | |
| 
 | |
|     // draw y scale
 | |
|     for ( i = ylo; i <= yhi; i += yinc) {
 | |
|       // compute the transform
 | |
|       temp =  (i - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
 | |
| 
 | |
|       if (i == 0) {
 | |
|         tft.setTextColor(acolor, bcolor);
 | |
|         tft.drawString(xlabel, (int)(gx + w) , (int)temp, 2);
 | |
|       }
 | |
|       // draw the axis labels
 | |
|       tft.setTextColor(tcolor, bcolor);
 | |
|       // precision is default Arduino--this could really use some format control
 | |
|       tft.drawFloat(i, dp, gx - 4, temp, 1);
 | |
|     }
 | |
| 
 | |
|     // draw x scale
 | |
|     for (i = xlo; i <= xhi; i += xinc) {
 | |
| 
 | |
|       // compute the transform
 | |
|       temp =  (i - xlo) * ( w) / (xhi - xlo) + gx;
 | |
|       if (i == 0) {
 | |
|         tft.setTextColor(acolor, bcolor);
 | |
|         tft.setTextDatum(BC_DATUM);
 | |
|         tft.drawString(ylabel, (int)temp, (int)(gy - h - 8) , 2);
 | |
|       }
 | |
| 
 | |
|       // draw the axis labels
 | |
|       tft.setTextColor(tcolor, bcolor);
 | |
|       tft.setTextDatum(TC_DATUM);
 | |
|       // precision is default Arduino--this could really use some format control
 | |
|       tft.drawFloat(i, dp, temp, gy + 7, 1);
 | |
|     }
 | |
| 
 | |
|     //now draw the graph labels
 | |
|     tft.setTextColor(tcolor, bcolor);
 | |
|     tft.drawString(title, (int)(gx + w / 2) , (int)(gy - h - 30), 4);
 | |
|   }
 | |
| 
 | |
|   // the coordinates are now drawn, plot the data
 | |
|   // the entire plotting code are these few lines...
 | |
|   // recall that ox and oy are initialized above
 | |
|   x =  (x - xlo) * ( w) / (xhi - xlo) + gx;
 | |
|   y =  (y - ylo) * (gy - h - gy) / (yhi - ylo) + gy;
 | |
| 
 | |
|   if ((x < gx) || (x > gx+w)) {update1 = true; return;}
 | |
|   if ((y < gy-h) || (y > gy)) {update1 = true; return;}
 | |
|     
 | |
|     
 | |
|   tft.drawLine(ox, oy, x, y, pcolor);
 | |
|   // it's up to you but drawing 2 more lines to give the graph some thickness
 | |
|   //tft.drawLine(ox, oy + 1, x, y + 1, pcolor);
 | |
|   //tft.drawLine(ox, oy - 1, x, y - 1, pcolor);
 | |
|   ox = x;
 | |
|   oy = y;
 | |
| 
 | |
| }
 | |
| 
 | |
| /*
 | |
| 
 | |
|   End of graphing function
 | |
| 
 | |
| */
 | |
| 
 | |
| 
 | |
| 
 | |
| void setup() {
 | |
|   double x, y;
 | |
| 
 | |
|   tft.begin();
 | |
|   tft.fillScreen(BLACK);
 | |
|   tft.setRotation(1);
 | |
| 
 | |
|   Graph(tft, x, y, 1, 60, 290, 390, 260, 0, 6.5, 1, -1, 1, .25, "", "", "", display1, YELLOW);
 | |
| 
 | |
|   //delay(1000);
 | |
|   
 | |
|   update1 = true;
 | |
|   for (x = 0; x <= 6.3; x += .1) {
 | |
|     y = sin(x);
 | |
|     Trace(tft, x, y, 1, 60, 290, 390, 260, 0, 6.5, 1, -1, 1, .25, "Sin(x)", "x", "fn(x)", update1, YELLOW);
 | |
|   }
 | |
| 
 | |
|   delay(2000);
 | |
| 
 | |
|   update1 = true;
 | |
|   for (x = 0; x <= 6.3; x += .1) {
 | |
|     y = cos(x);
 | |
|     Trace(tft, x, y, 1, 60, 290, 390, 260, 0, 6.5, 1, -1, 1, .25, "Sin(x) + Cos(x)", " x", "fn(x)", update1, TFT_PINK);
 | |
|   }
 | |
| 
 | |
|   delay(2000);
 | |
|   
 | |
|   update1 = true;
 | |
|   for (x = 0; x <= 6.3; x += .02) {
 | |
|     y = tan(x);
 | |
|     Trace(tft, x, y, 1, 60, 290, 390, 260, 0, 6.5, 1, -1, 1, .25, "Sin(x) + Cos(x) + Tan(x)", " x", "fn(x)", update1, CYAN);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void loop(void) {
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |