Forum Rule: Always post complete source code & details to reproduce any issue!
Page 11 of 12 FirstFirst ... 9 10 11 12 LastLast
Results 251 to 275 of 276

Thread: RA8875 from Buydisplay

  1. #251
    Thank you for your help.I'm getting this error, when I'm trying to compile

    T4_RA8875_pictureEmbed:58: error: 'enable_layers' was not declared in this scope
    if (enable_layers) tft.writeTo(layer);
    ^
    T4_RA8875_pictureEmbed:113: error: 'enable_layers' was not declared in this scope
    if (enable_layers)tft.layerEffect((layer == L1) ? LAYER1 : LAYER2);

    Any idea why?
    Thank you

  2. #252
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,625
    I probably need to look at the layers stuff again at some point, but for example it can only work on 800x.. at 8 bits per pixel...
    But did not appear to actually do it...

    So in the test it was trying to use the two layers, update the display and then tell the display to switch to the other layer...

    But I included the zip again.

    Edit: Wonder if I should clean up slightly and add as example?
    Attached Files Attached Files

  3. #253
    You Are a Genius !!!!!!
    It Works !!!
    Thank you !

    One more think,
    In old library (drawArray)), we had a option to change image location(x, y),
    In this example, to move the image, I'm changing
    uint16_t start_x
    uint16_t start_y
    but what If there is multiple images?
    Please tell me, how I can have different coordinates, for multiple images?
    Thank you

  4. #254
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,625
    @momosh13 - Not sure if Genius, but simply someone who has been around the block a time or two. Again don't know what you mean by old library...

    @mjs513 and ... Again at times I am not sure what to do with these semi-orphaned libraries.
    As you know that a few of us are spending some time making this library work, plus actually getting several of our display drivers have reasonably compatible functionality.

    But I have been thinking about maybe extracting some of the code in this sketch and maybe potentially maybe add it to RA8875 library
    Probably with the same name and functionality as the method: void writeRect(int16_t x, int16_t y, int16_t w, int16_t h, const uint16_t *pcolors);

    which is in ILI9341_t3/n ST7735_t3/ST7789_t3, ILI9488_t3...

    What the sketch currently does, that I don't believe these member functions do, is if you pass an an image that does not fit in the current orientation, but will in the other orientation, the sketch will rotate the image to fit...

    I need to see what the other methods, do. They may simply clip...

    With this API, it is up to the caller to figure out the proper X, Y to start drawing at. So if you want it centered you need to pass in:
    (tft.width()-image_width)/2 ...

    Does this make sense?

  5. #255
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,625
    @mjs513 - I added writeRect
    PR: https://github.com/mjs513/RA8875/pull/11

    Branch: https://github.com/KurtE/RA8875/tree/write_rect

    Updated sketch that uses it and cycles through rotations as well.


    One difference so for from other versions of this api...
    I currently call it like:
    Code:
      tft.writeRect(start_x, start_y, image_width, image_height, image);
    But in this case I could also have done it by:
    Code:
     tft.writeRect(CENTER, CENTER, image_width, image_height, image);
    I may next check to see if 8 bit color mode works and enables using layer...

    EDIT: the new branch was screwed up... was based off of .070...
    So closed PR, opened new one: https://github.com/mjs513/RA8875/pull/12

    https://github.com/KurtE/RA8875/tree...t_write_branch
    Attached Files Attached Files
    Last edited by KurtE; 01-28-2020 at 11:49 PM.

  6. #256

    Compiling error

    Quote Originally Posted by mjs513 View Post
    Recently @KurtE and I have been working on a modification of the RA8875 library to use the ILI9xxx fonts and Adafruit GFX fonts. We have finished our initial implementation of modifications to the RA8875 library and the ILI9341_font library. Here are some screen shots for the ILI style fonts on the RA8875:
    Attachment 18762Attachment 18763Attachment 18764

    The updated RA8875 library is on the T4 branch: https://github.com/mjs513/RA8875/tree/RA8875_t4
    The fonts are a slightly modified version of the PJRC's ILI9341_fonts library: https://github.com/mjs513/ILI9341_fonts

    Feel free to give it a try.
    Hello KurtE
    I'm having compile error and here is what I'm doing.
    1. downloaded and installed library from https://github.com/mjs513/RA8875/tree/RA8875_t4
    2. trying compile example from ..\_Teensy3\ILI_Ada_FontTest\ILI_Ada_FontTest.ino
    3. getting compile error "C:\Users\HPVIDEO\AppData\Local\Temp\arduino_modif ied_sketch_334801\ILI_Ada_FontTest.ino:6:41: fatal error: ili9488_t3_font_ComicSansMS.h: No such file or directory"

    That is not right because there is ili9488_t3_font_ComicSansMS.h in fonts folder.

    Any suggestion?
    Thanks in advance.

  7. #257
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,101
    Just looked at the current library at https://github.com/mjs513/RA8875/tree/RA8875_t4 and there is no ili9488_t3_font_ComicSansMS.h in the fonts folder. Unfortunately that particular example was not updated to work with the RA8875 display. That's on us, forgot to update it. It was an early development sketch that we used for initial testing.

    However the ILI_Ada_FontTest's will work based on the quick review I just did as a double check. You will need to download the fonts library https://github.com/mjs513/ILI9341_fonts to use the additional fonts then you would just have to include as in the examples.

  8. #258
    Thank you,
    Works as expected.

  9. #259
    Quote Originally Posted by KurtE View Post
    Actually got it to work:

    If you use: tft.begin(RA8875_480x272)
    You end up with the problem I have.

    However if you use: tft.begin(Adafruit_480x272)

    It works...
    Genius. Thanks Kurt

  10. #260
    Senior Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    115
    Hi mjs, Kurt, I like to use the Awesome fonts for my RA8875 from buydisplay, I noticed that there are fonts for the ILI9341 display ... Font_Awesome_F000 and how I can use them?
    Thanks for helping,
    Best,
    Johan

  11. #261
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,625
    You might take a look at the current example sketches that were added like: ILI_Aa_FontTest4 that is in the teensy... example sketches.


    To use a bunch of the different fonts: @mjs513 has a version of the ILI9341 fonts library which is setup with several of the fonts and these are setup such that they can be included in several of our different display libraries.
    https://github.com/mjs513/ILI9341_fonts


    You simply need to include the font into your sketch: Something like:
    #include "font_OpenSans.h"


    You then need to say you wish to use that font: tft.setFont(OpenSans24);

    Then you can do things like: tft.print("This is Open Sand 24");

  12. #262
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,101
    First download the updated ILI9341_fonts library: https://github.com/mjs513/ILI9341_fonts. Put it in your libraries folder and then just:
    #include "font_Crystal.h" <--- ref in header

    then just:
    tft.setFont(Crystal_24_Italic);

    Look familiar

  13. #263
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,101
    Ok - Kurt and I just cross posted

  14. #264
    Senior Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    115
    @Mike,
    It looks like something is wrong at my site ... when running my application the Awesome fonts type font_AwesomeF100.h are scrolling over my RA8875 display.
    #include <font_AwesomeF100.h> No errors
    tft.setFont(AwesomeF100_48);

    In my buttons application : /* Button 0*/{60, 378, 110, 100, 20, 0x100, char(0xf011 ), WHITE, DKGREY, char(0xf011), WHITE, GREY, 0}, // Start stopClick image for larger version. 

Name:	DeepinScreenshot_select-area_20200301162945.jpg 
Views:	4 
Size:	79.3 KB 
ID:	19233

  15. #265
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,101
    Try downloading the latest updates to the RA8875 library: https://github.com/mjs513/RA8875/tree/RA8875_t4. The one include with Teensyduino is outdated and does not have the new font code. Did you try running the example sketch that Kurt referenced?

  16. #266
    Senior Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    115
    This works fine in a fresh sketch. I think I must look at my application.
    Thanks Mike!
    /*
    Explain the minimal setup and how to use instances...
    */

    #include <SPI.h>
    #include <RA8875.h>

    /*
    Teensy3.x
    You are using 4 wire SPI here, so:
    MOSI: 11
    MISO: 12
    SCK: 13
    */
    #define RA8875_CS 20 //any digital pin
    #define RA8875_RESET 255//any pin, if you wnat to disable just set at 255 or not use at all

    /*
    Teensy3.x has small difference since it can use alternative SPI pins,
    essential if you want to use this library with Audio Shield.
    You can set alternative SPI pins:
    RA8875(CSpin,RSTpin=255,MOSI=11,SCLK=13,MISO=12);//the default configuration
    To use with Audio shield:-------------------------------
    CS: 2,20,21 because are not used by audio shield
    MOSI:7
    SCLK:14
    RA8875(2,255,7,14);//will not interfere with Audio Shield
    Teensy LC
    This cpu can use slight different configuration, it can be instanced
    with the CS pin only so it will use SPI0 but you can use this:
    //RA8875(CSp,RSTp,mosi_pin,sclk_pin,miso_pin);
    RA8875 tft = RA8875(RA8875_CS,RA8875_RESET,0,20,1);
    This will use the SPI1 (24Mhz)
    --------------------------------------------------------
    To omit Reset pin, set as 255
    For CS you CANNOT use arbitrary pin!
    Teensy 3.x can use: 2,6,9,10,15,20,21,22,23
    The shorter instance can be: RA8875(CSpin);
    */
    RA8875 tft = RA8875(RA8875_CS,RA8875_RESET);//Teensy
    //or
    //RA8875 tft = RA8875(RA8875_CS);//Teensy (not using rst pin)
    //or (for audio board)
    //RA8875 tft = RA8875(RA8875_CS,RA8875_RESET,RA8875_MOSI,RA8875_S CLK);//Teensy using alternative SPI pin
    //or
    //RA8875 tft = RA8875(RA8875_CS,RA8875_RESET,RA8875_MOSI,RA8875_S CLK,RA8875_MISO);//Teensy using alternative SPI pin + alt miso
    #include "font_AwesomeF100.h"
    #include "font_AwesomeF000.h"

    void setup()
    {
    Serial.begin(38400);
    //long unsigned debug_start = millis ();
    //while (!Serial && ((millis () - debug_start) <= 5000)) ;
    Serial.println("RA8875 start");
    /*
    If you have an Adafruit RA8875 board + display choose:
    Adafruit_480x272 , Adafruit_800x480
    If you have any other display you have to choose:
    RA8875_480x272 , RA8875_800x480
    */
    tft.begin(RA8875_800x480);

    /*
    By default the library init display at 16bit color depth but
    you can optionally force the display to work at 8 bit:

    tft.begin(RA8875_480x272,8);//force 8bit color depth
    */

    //Now that board it's inited you can use any draw or text command:
    tft.setFont(AwesomeF000_48);
    tft.setCursor(100,100);
    tft.print(char(17 )); // power on icon
    }
    void loop()
    {

    }

  17. #267
    Senior Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    115
    @Kurt, Mike,
    All perfect with the new Awesome fonts,
    Thanks again.

    Best,
    Johan
    Click image for larger version. 

Name:	DeepinScreenshot_select-area_20200301175719.jpg 
Views:	11 
Size:	69.3 KB 
ID:	19234

  18. #268
    Senior Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    115
    Hi all,

    For my hotplate controller and is made with a cheap RPI 9488 type display and a STM32 and works fine, I like to convert this to my fantastic RA8875 display but I use tft.drawBitmap but this is not available in the RA8875 is there a solution?

    Thanks for help as always.

    Best,
    Johan

  19. #269
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,101
    As you said there is no direct function call for tft.drawBitmap however, if you look at the SDfatTest example in the Teensy3 folder it will show you how to read a bmp from a SDCard and display it.

    If you want to use bmp files encoded as arrays with PROGMEM you might check out the load2424bitimages example.

    In both cases you are going to be reading in the pixels from a file or an array and then drawing the pixels to the screen. My guess is that the STM32 function drawBitmap is following that same basic flow.

    Hope this helps

  20. #270
    Senior Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    115
    Hi Mile,

    This not that easy I suppose please read below, is it not possible to use AdafruitGFX for the drawBitmap ?


    // draw a button on the screen
    Code:
    void button(but bx){
      if (bx.draw == 1){// draw a button
        uint8_t byte0 = pgm_read_byte(&bx.bm[0]); // get the button symbol width
        uint8_t byte1 = pgm_read_byte(&bx.bm[1]); // get the button symbol height
        if (bx.in == 0){ //pushbutton
          tft.fillRect(bx.x, bx.y, bx.w, bx.h, bx.bacolor);                                              // draw the button background (background color)
          tft.drawRect(bx.x, bx.y, bx.w, bx.h, bx.bocolor);                                              // draw the button border
          //tft.drawBitmap(bx.x+(bx.w-byte0)/2, bx.y+(bx.h-byte1)/2, bx.bm+2, byte0, byte1, bx.color);     // draw the button symbol (symbol color)
        } else {
          if (bx.latch == 1){  //pushbutton colors inverted
            tft.fillRect(bx.x, bx.y, bx.w, bx.h, bx.color);                                              // draw the button background (symbol color)
            tft.drawRect(bx.x, bx.y, bx.w, bx.h, bx.bocolor);                                            // draw the button border
            //tft.drawBitmap(bx.x+(bx.w-byte0)/2, bx.y+(bx.h-byte1)/2, bx.bm+2, byte0, byte1, bx.bacolor); // draw the button symbol (background color)
          }
          if (bx.latch == 2){ //switch
            tft.fillRect(bx.x, bx.y, bx.w, bx.h, bx.bacolor);                                             // draw the button background (background color)
            tft.drawRect(bx.x, bx.y, bx.w, bx.h, bx.bocolor);                                             // draw the button border
            //tft.drawBitmap(bx.x+(bx.w-byte0)/2, bx.y+(bx.h-byte1)/2, bx.bm+2, byte0, byte1, bx.swcolor);  // draw the button symbol (switch color)
          }
        }
      }
    }
    Last edited by KurtE; 03-19-2020 at 04:30 PM. Reason: Add code tags

  21. #271
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,101
    Morning
    This not that easy I suppose please read below, is it not possible to use AdafruitGFX for the drawBitmap ?
    Unless I have an old version of the adafruit RA8875 library I didn't see a drawBitmap function in their library. I did find a similar function to what I referenced. If you look at the ILI9488 drawBitmap function in the library
    Code:
    void ILI9488_t3::drawBitmap(int16_t x, int16_t y,
    			      const uint8_t *bitmap, int16_t w, int16_t h,
    			      uint16_t color) {
    
      int16_t i, j, byteWidth = (w + 7) / 8;
    
      for(j=0; j<h; j++) {
        for(i=0; i<w; i++ ) {
          if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
    	drawPixel(x+i, y+j, color);
          }
        }
      }
    }
    its basically doing what was done in the load2424bitimages example as does the Adafruit GFX function:
    Code:
    void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[],
                                  int16_t w, int16_t h, uint16_t color) {
      int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
      uint8_t byte = 0;
      startWrite();
    
      for (int16_t j = 0; j < h; j++, y++) {
        for (int16_t i = 0; i < w; i++) {
          if (i & 7)
            byte <<= 1;
          else
            byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
          if (byte & 0x80)
            writePixel(x + i, y, color);
        }
      }
      endWrite();
    }
    I would suppose we could add a similar function for drawBitmap. Haven't tried your example yet have to go dig out my RA8875 first.

  22. #272
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,625
    The simple answer is probably no, to using drawBitmap.

    Again it would not be that hard roll your own or add it to library.
    That is it already has writeRect...

    Several of our libraries have some other functions like:
    Code:
    void writeRect8BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *pixels, const uint16_t * palette );
    
    	// writeRect4BPP - 	write 4 bit per pixel paletted bitmap
    	//					bitmap data in array at pixels, 4 bits per pixel
    	//					color palette data in array at palette
    	//					width must be at least 2 pixels
    	void writeRect4BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *pixels, const uint16_t * palette );
    	
    	// writeRect2BPP - 	write 2 bit per pixel paletted bitmap
    	//					bitmap data in array at pixels, 4 bits per pixel
    	//					color palette data in array at palette
    	//					width must be at least 4 pixels
    	void writeRect2BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *pixels, const uint16_t * palette );
    	
    	// writeRect1BPP - 	write 1 bit per pixel paletted bitmap
    	//					bitmap data in array at pixels, 4 bits per pixel
    	//					color palette data in array at palette
    	//					width must be at least 8 pixels
    	void writeRect1BPP(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t *pixels, const uint16_t * palette );
    
    	// writeRectNBPP - 	write N(1, 2, 4, 8) bit per pixel paletted bitmap
    	//					bitmap data in array at pixels
    	//  Currently writeRect1BPP, writeRect2BPP, writeRect4BPP use this to do all of the work. 
    	// 
    	void writeRectNBPP(int16_t x, int16_t y, int16_t w, int16_t h,  uint8_t bits_per_pixel, 
    		const uint8_t *pixels, const uint16_t * palette );
    All of these could be written to work similar to the writeRect... Note: drawBitmap is more or less the 1BPP one above.

    But again you could write your own quick and dirty (note it may not be quick )

    Code:
    void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[],
                                  int16_t w, int16_t h, uint16_t color) {
    
      int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
      uint8_t byte = 0;
    
      startWrite();
      for (int16_t j = 0; j < h; j++, y++) {
        for (int16_t i = 0; i < w; i++) {
          if (i & 7)
            byte <<= 1;
          else
            byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
          if (byte & 0x80)
            writePixel(x + i, y, color);
        }
      }
      endWrite();
    }
    Could convert to something as simple as:
    Code:
    void myDrawBitmap(int16_t x, int16_t y, const uint8_t bitmap[],
                                  int16_t w, int16_t h, uint16_t color) {
    
      int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
      uint8_t byte = 0;
    
      for (int16_t j = 0; j < h; j++, y++) {
        for (int16_t i = 0; i < w; i++) {
          if (i & 7)
            byte <<= 1;
          else
            byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
          if (byte & 0x80)
            tft.drawPixel(x + i, y, color);
        }
      }
    }
    Last edited by KurtE; 03-19-2020 at 06:42 PM. Reason: added void

  23. #273
    Senior Member
    Join Date
    May 2017
    Location
    Netherlands
    Posts
    115
    Hi Mike, Kurt,

    For me a bit difficult can you look at the code and is it possible to adjust my code with your function see below.
    Compile works but not the drawBitmap.
    Thanks.


    Code:
    //#include <Adafruit_GFX.h>
    //#include <Adafruit_SPITFT_Macros.h>
    //#include <Adafruit_SPITFT.h>
    //#include <gfxfont.h>
    
    #include <Adafruit_MAX31856.h>   //Type K thermocouple module
    //#include <ILI9486_SPI.h>         //RPI 3.5 inch tft
    #include <SPI.h>
    #include <RA8875.h>
    #include <XPT2046_Touchscreen.h> //Touchscreen 12 bits
    #include <PID_v1.h>              //PID controller
    #include "symbols.h"             //Keyboard symbols
    #include "Monospaced_plain_22.h" //Monospaced font
    #include <EEPROM.h>
    
    #define ms22_spacing 14
    
    #define MAX_CS  36   // MAX31856 CS
    #define MAX_DI  37  // MAX31856 DI
    #define MAX_DO  38  // MAX31856 DO
    #define MAX_CLK 39  // MAX31856 CLK
    
    Adafruit_MAX31856 maxtemp = Adafruit_MAX31856(MAX_CS, MAX_DI, MAX_DO, MAX_CLK); 
    
    
    #define TFT_CS 20 // RPI display CS
    #define TFT_DC 18 // RPI display DC
    // SCK = PA5, MISO = PA6, MOSI = PA7, RST = +3V3
    
    //ILI9486_SPI tft(/*CS=4*/ TFT_CS, /*DC=*/ TFT_DC, /*RST=*/ 0);
    
    
    #define RA8875_RESET 255    //Not used
    #define RA8875_CS 20
    RA8875 tft = RA8875(RA8875_CS, RA8875_RESET, 11, 13, 12);   // 11=MOSI   13=SCLK   12=MISO  10=CS
    #define CS_PIN  2 // Touchscreen CS
    // SCK = PA5, MISO = PA6, MOSI = PA7
    
    XPT2046_Touchscreen ts(CS_PIN);
    
    // These are the default min and maximum values, set between 0 and 4095 (12 bit)
    #define HMIN 230
    #define HMAX 3930
    #define VMIN 230
    #define VMAX 3830
    
    #define WIDTH 800  // Default screen resulution for X axis
    #define HEIGHT 480 // Default screen resulution for Y axis
    #define BUTTONW 80 // Default button resulution for X axis
    #define BUTTONH 80 // Default button resulution for X axis
    
    #define HEATER_PIN  3 //Heater output pin
    #define FAN_PIN  4    //Fan output pin
    #define BUZZER_PIN 5  //Buzzer output pin (option)
    
    
    #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 MDBLUE    0x0016
    #define TEAL      0x0438
    #define GREEN     0x07E0
    #define MDGREEN   0x05E0
    #define CYAN      0x07FF
    #define RED       0xF800
    #define MDRED     0xC800
    #define MAGENTA   0xF81F
    #define YELLOW    0xFFE0
    #define ORANGE    0xFC00
    #define PINK      0xF81F
    #define PURPLE    0x8010
    #define GREY      0xC618
    #define MDGREY    0x94B2
    #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
    
    uint16_t backcolor = BLUE;      // color of display background
    uint16_t txtcolor = WHITE;      // color of text on display
    uint16_t bordercolor = BLACK;   // color of borders and lines
    uint16_t trendcolor = CYAN;     // color of trenline
    uint16_t rastcolor = MDGREY;     // color of the raster lines
    
    
    
    int screen = 0;                         // screen = 0 is main screen     screen = 1 is setup screen
    int butnr =999;                         // number of touched button
    int recipenr = 1;                       // start with recipe number one
    int oldrecipenr = 1;                    // start with recipe number one
    char rcptxt[6][11]={"          ", "    SAC305", " LEAD_FREE", "    LEADED", "    CURVE1", "    CURVE2"};
    //String rcptxt[6];                       // The name of the reflow curve
    uint8_t rptxt[6][7];                    // The reflow zone the oven can be in (Stopped, Preheat, Soak, etc)
    String rptext = "Stopped";              // The actual reflow zone the oven is in
    String oldrptext = "Stopped";           // The actual reflow zone the oven is in
    uint8_t xv[480];                        // temperature values
    uint16_t T[6][7];                       // recipes temperature --- 5 recipes ---- 6 points per recipe
    uint16_t m[6][7];                       // recipes time --- 5 recipes ---- 6 points per recipe
    int mt;                                 // calculated total time trend x-axes
    int Tt;                                 // highest temoperatuur y-axes
    int startcurve = 0;                     // 0 if the curve is not running -- 1 if the curve is running.
    int pointcounter = 0;                   // The current point in a recipe
    int cur = 2;                            // The current parameter
    int valinit = 0;                        // valinit = 0 --- reprint the complete editor window on the setup screen (screen 1)    valinit = 1 --- print only the changes
    int redrtop = 1;                        // TRUE if the drawstring text should be completely redrawn
    String valuestrm[6];                    // temporarily variable to hold the new recipe values of the current recipe
    String valueoldstrm[6];                 // temporarily variable to hold the previous recipe values of the current recipe
    String valuestrT[6];                    // temporarily variable to hold the new recipe values of the current recipe
    String valueoldstrT[6];                 // temporarily variable to hold the previous recipe values of the current recipe
    String valuestrtxt[6];                  // temporarily variable to hold the new recipe values of the current recipe
    String valueoldstrtxt[6];               // temporarily variable to hold the previous recipe values of the current recipe
    int btnr = 999;                         // Holds the pressed butten number  999 no button is pressed
    int blocked = 0;                        // 0 = one puls button         1 = repeat puls button
    int starttimer = 0;                     // start the timer for the repeat puls button. If you hold the button longer, the repeatfrequence goes up.
    double rate = 1;                        // temperature rise per second
    int tchd = 0;                           // 1 if the touchscreen is touched
    int elapsedtime = 0;                    // elapsed time between steps in the temperature curve
    int stepcounter = 0;                    // next step in the recipecurve
    int curtemp, curtemp2;
    int rtxtcur = 0;                        // recipe text cursor
    int scrltxt = 0;
    
    String zonetxt[6] = {"Stopped", "Preheat", "Soak", "Prereflow", "Reflow", "Cool"};
    int maxvaluem[6] = {350, 350, 350, 350, 350, 350}; // maximum adjustable time value
    int maxvalueT[6] = {350, 350, 350, 350, 350, 350}; // maximum adjustable temperature value
    int xcursor[18] = {0, 0, 241, 20, 123, 216, 20, 123, 216, 20, 123, 216, 20, 123, 216, 20, 123, 216, };        // place of the cursor in the editor window
    int ycursor[18] = {0, 0, 20, 110, 110, 110, 135, 135, 135, 160, 160, 160, 185, 185, 185, 210, 210, 210};    // place of the cursor in the editor window
    int alphabet[38] = {32, 45, 48, 49, 50, 51, 52, 53, 54, 55 ,56 ,57, 65, 66 ,67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77 ,78, 79 ,80, 81, 82, 83, 84, 85 ,86 ,87 ,88 ,89 ,90};
    int alphabetconv[59] = {0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37};
    
    //trend variables
    int ybegin = 35;
    int yend = 215;
    int xbegin = 30;
    int xend = 450;
    int tempdiv = 50;
    int timediv = 60;
    
    double temperature, oldtemperature; // heater temperature
    double sp = 0;                      // PID running setpoint
    double Setpoint;                    // PID end setpiont
    double Input;                       // PID input(heater temperature)
    double Output;                      // PID output(heater power)
    
    struct but {                // button parameters
      uint8_t draw;             // 1 draw the button    0 draw an empty space
      uint16_t x;               // button x coordinate
      uint16_t y;               // button y coordinate
      const uint8_t *bm;        // button image name
      uint16_t w;               // button width
      uint16_t h;               // button height
      uint16_t color;           // button symbol color
      uint16_t swcolor;         // button active symbol color
      uint16_t bacolor;         // button background color
      uint16_t bocolor;         // button border color
      uint8_t latch;            // 0 push button    1 color inverted pushbutton    2 switch
      uint8_t in;               // 0 button is released   1 button is in
      uint8_t repeat;           // 0 repeat puls button   1 single puls button
    };
    
    //int buttons=10; // number of buttons 
    but scr[11]={ // button array to draw the buttons
      {1, 0, 240, homesymbol, BUTTONW, BUTTONH, txtcolor, WHITE, backcolor, bordercolor, 0,0,1},
      {1, 80, 240, fansymbol, BUTTONW, BUTTONH, MDGREY, GREEN, backcolor, bordercolor, 2,0,1},
      {1, 160, 240, backwardsymbol, BUTTONW, BUTTONH, txtcolor, WHITE, backcolor, bordercolor, 0,0,0},
      {1, 240, 240, forwardsymbol, BUTTONW, BUTTONH, txtcolor, WHITE, backcolor, bordercolor, 0,0,0},
      {1, 320, 240, heatersymbol, BUTTONW, BUTTONH, MDGREY, GREEN, backcolor, bordercolor, 2,0,1},
      {1, 400, 240, onoffsymbol, BUTTONW, BUTTONH, txtcolor, GREEN, backcolor, bordercolor, 2,0,1},
      {1, 400, 0, rightsymbol, BUTTONW, BUTTONH, txtcolor, WHITE, backcolor, bordercolor, 0,0,0},
      {1, 400, 80, upsymbol, BUTTONW, BUTTONH, txtcolor, WHITE, backcolor, bordercolor, 0,0,0},
      {1, 400, 160, downsymbol, BUTTONW, BUTTONH, txtcolor, WHITE, backcolor, bordercolor, 0,0,0},
      {1, 0, 240, gearsymbol, BUTTONW, BUTTONH, txtcolor, WHITE, backcolor, bordercolor, 0,0,1},
      {1, 400, 240, rightrightsymbol, BUTTONW, BUTTONH, txtcolor, WHITE, backcolor, bordercolor, 0,0,0},
    };
    
    int scr0but[7] = {0, 1, 2, 3, 4, 5};
    int scr1but[10] = {1, 2, 3, 4, 6, 7, 8, 9, 10};
    
    // define text instead of numbers for the buttons
    #define gear 0
    #define fan 1
    #define backward 2
    #define forward 3
    #define heater 4
    #define onoff 5
    #define right 6
    #define up 7
    #define down 8
    #define home 9
    #define tab 10
    
    unsigned long windowStartTime;
    int WindowSize = 2000; // output limit for the PID controller
    
    unsigned long meastime = 0;
    int measwindow = 1000; //time in ms temperature measurement
    
    unsigned long touchtime = 0;
    int touchwindow = 0; //time in ms button touch delay
    
    unsigned long drawtime = 0;
    int drawwindow = 1000;
    
    
    
    
    //Specify the links and initial tuning parameters
    //double Kp=2, Ki=5, Kd=1;
    double Kp=100, Ki=5, Kd=1;
    PID myPID(&Input, &Output, &sp, Kp, Ki, Kd, DIRECT);
    
    
    
    void setup()
    {
      //disableDebugPorts(); //Release PB4 (FAN_PIN) so we can used it as an output
    
      tft.begin(RA8875_800x480);
      tft.setRotation(0);
      pinMode(HEATER_PIN, OUTPUT); 
      pinMode(FAN_PIN, OUTPUT);
      pinMode(BUZZER_PIN, OUTPUT);
    
      windowStartTime = millis();
      myPID.SetOutputLimits(0, WindowSize);
      
      //turn the PID on
      myPID.SetMode(AUTOMATIC);
      
      Serial.begin(115200);
       
     
      //ts.begin();         // initialize the touchscreen
      //ts.setRotation(1);  // touchscreen the same as the tft
    
       uint16_t DataWrite = 11111;
      uint16_t AddressWrite = 0x10;
      uint16_t StatusInit;  
      uint16_t StatusRead;
      uint16_t StatusWrite;
      uint16_t Data;
      //delay(3000);
      //StatusInit = EEPROM.init();
      //delay(3000);
      //EEPROM.PageBase0 = 0x801F000;
      //EEPROM.PageBase1 = 0x801F800;
      //EEPROM.PageSize  = 0x800;
      //StatusRead = EEPROM.read(AddressWrite, &Data);
      if (Data != 11111){
        //StatusWrite = EEPROM.write(AddressWrite, DataWrite);
        
        // pre set recipes
        // SAC305
        T[1][0]  = 0;   m[1][0]  =  0; rptxt[1][0] = 0;
        T[1][1]  = 150; m[1][1]  = 90; rptxt[1][1] = 1;
        T[1][2]  = 175; m[1][2]  = 90; rptxt[1][2] = 2;
        T[1][3]  = 217; m[1][3]  = 30; rptxt[1][3] = 3;
        T[1][4]  = 249; m[1][4]  = 30; rptxt[1][4] = 4;
        T[1][5]  = 217; m[1][5]  = 30; rptxt[1][5] = 4;
        T[1][6]  = 20;  m[1][6]  = 90; rptxt[1][6] = 5;
    
        // Lead-Free
        T[2][0]  =   0; m[2][0]  =  0; rptxt[2][0] = 0;
        T[2][1]  = 150; m[2][1]  = 90; rptxt[2][1] = 1;
        T[2][2]  = 200; m[2][2]  = 90; rptxt[2][2] = 2;
        T[2][3]  = 245; m[2][3]  = 45; rptxt[2][3] = 4;
        T[2][4]  = 200; m[2][4]  = 45; rptxt[2][4] = 4;
        T[2][5]  =  20; m[2][5]  = 90; rptxt[2][5] = 5;
        T[2][6]  =  20; m[2][6]  =  0; rptxt[2][5] = 5;
      
        // Leaded
        T[3][0]  =   0; m[3][0]  =  0; rptxt[3][0] = 0;
        T[3][1]  = 150; m[3][1]  = 90; rptxt[3][1] = 1;
        T[3][2]  = 180; m[3][2]  = 90; rptxt[3][2] = 2;
        T[3][3]  = 219; m[3][3]  = 30; rptxt[3][3] = 4;
        T[3][4]  = 180; m[3][4]  = 30; rptxt[3][4] = 4;
        T[3][5]  =  20; m[3][5]  = 90; rptxt[3][5] = 5;
        T[3][6]  =  20; m[3][6]  =  0; rptxt[3][5] = 5;
      
        // reflow curve
        T[4][0]  =   0; m[4][0]  =  0; rptxt[4][0] = 0;
        T[4][1]  = 150; m[4][1]  = 90; rptxt[4][1] = 1;
        T[4][2]  = 180; m[4][2]  = 90; rptxt[4][2] = 2;
        T[4][3]  = 219; m[4][3]  = 30; rptxt[4][3] = 4;
        T[4][4]  = 180; m[4][4]  = 30; rptxt[4][4] = 4;
        T[4][5]  =  20; m[4][5]  = 90; rptxt[4][5] = 5;
        T[4][6]  =  20; m[4][6]  =  0; rptxt[4][5] = 5;
      
        // reflow curve
        T[5][0]  =   0; m[5][0]  =  0; rptxt[5][0] = 0;
        T[5][1]  = 150; m[5][1]  = 90; rptxt[5][1] = 1;
        T[5][2]  = 180; m[5][2]  = 90; rptxt[5][2] = 2;
        T[5][3]  = 219; m[5][3]  = 30; rptxt[5][3] = 4;
        T[5][4]  = 180; m[5][4]  = 30; rptxt[5][4] = 4;
        T[5][5]  =  20; m[5][5]  = 90; rptxt[5][5] = 5;
        T[5][6]  =  20; m[5][6] =  0;  rptxt[5][5] = 5;
    
        store();
      } else {
        T[1][0]  = 0;   m[1][0]  =  0; rptxt[1][0] = 0;
    
        // Lead-Free
        T[2][0]  =   0; m[2][0]  =  0; rptxt[2][0] = 0;
      
        // Leaded
        T[3][0]  =   0; m[3][0]  =  0; rptxt[3][0] = 0;
      
        // reflow curve
        T[4][0]  =   0; m[4][0]  =  0; rptxt[4][0] = 0;
      
        // reflow curve
        T[5][0]  =   0; m[5][0]  =  0; rptxt[5][0] = 0;
        
        for (int ir = 1; ir <= 5; ir++){
          for (int iz = 1; iz <= 6; iz++){
            AddressWrite = AddressWrite + 16;
            //StatusRead = EEPROM.read(AddressWrite, &Data);
            T[ir][iz] = Data;
          }
        }
        for (int ir = 1; ir <= 5; ir++){
          for (int iz = 1; iz <= 6; iz++){
            AddressWrite = AddressWrite + 16;
            //StatusRead = EEPROM.read(AddressWrite, &Data);
            m[ir][iz] = Data;
          }
        }
        for (int ir = 1; ir <= 5; ir++){
          for (int iz = 1; iz <= 6; iz++){
            AddressWrite = AddressWrite + 16;
            //StatusRead = EEPROM.read(AddressWrite, &Data);
            rptxt[ir][iz] = Data;
          }
        }
        for (int ir = 1; ir < 5; ir++){
          for (int iz = 0; iz < 9; iz=iz+2){
            AddressWrite = AddressWrite + 16;        
            //StatusRead = EEPROM.read(AddressWrite, &Data);
            rcptxt[ir][iz+1] = Data/256;
            rcptxt[ir][iz] = Data - rcptxt[ir][iz+1]*256;
    
          }     
        }
         
      }
      //StatusRead = EEPROM.read(AddressWrite, &Data);
    
    
      recalc();
    
       tft.fillWindow(BLACK);
      tft.setTextColor(txtcolor, backcolor);
      tft.setFont(&Monospaced_plain_22);
        
      maxtemp.begin();    // initialize the temperature measure unit
    
      drawbuttons(0);                                         // Place the buttons on the bottom of the screen (parameter = 0)
      tft.drawRect(0, 0, WIDTH, HEIGHT-BUTTONH, bordercolor); // Place a rectangle above the buttons on screen 0
      drawaxes();                                             // Draw the vertical and horizontal axes and the raster on screen 0
      drawtraceline();                                        // Draw the recipe 0 trace line on screen 0
      reflowtext(1);                                          // Draw the current reflow zone text on the left top of the screen
      recipetext(1, 335);                                     // draw the recipe name on the right top of the screen
    
    }
    
    void loop() {
    
      // measure temperature and chang setpoint
      unsigned long measnow = millis();
      if (measnow - meastime > measwindow) {
        meastime = measnow;
        
        oldtemperature = temperature;                          // save the previous temperature
        temperature = maxtemp.readThermocoupleTemperature();   // read the new temperature
        Setpoint = T[recipenr][stepcounter + 1];               // read the first step end setpoint
        
        drawString(redrtop, 110, 20, ms22_spacing, 8, String(oldtemperature) + "C", String(temperature) + "C", 1, txtcolor, backcolor, Monospaced_plain_22); // print the new temperature at the top of the screen
        if (redrtop == 1){redrtop = 0;} // next time only redraw the changes
    
        if (rate >= 0 && temperature > Setpoint){// if the temperature goes from a lower to a higher setpoint and the setpoint is reached
          if (stepcounter < 5){
            oldrptext = zonetxt[rptxt[recipenr][stepcounter]]; // save the old reflow zone text
            stepcounter++;                                     // go to the next step
            elapsedtime = 0;                                   // reset the elapsed step time
            rptext = zonetxt[rptxt[recipenr][stepcounter]];    // get the new reflow zone text
            reflowtext(1);                                     // print the new reflow zone text at th left top of the screen
          }
        }
        if (rate < 0  && temperature < Setpoint){// if the temperature goes from a higher to a lower setpoint and the setpoint is reached
          if (stepcounter < 5){
            oldrptext = zonetxt[rptxt[recipenr][stepcounter]]; // save the old reflow zone text
            stepcounter++;                                     // go to the next step
            elapsedtime = 0;                                   // reset the elapsed step time
            rptext = zonetxt[rptxt[recipenr][stepcounter]];    // get the new reflow zone text
            reflowtext(1);                                     // print the new reflow zone text at th left top of the screen
          }
        }
        if(startcurve == 1){
          rate = (T[recipenr][stepcounter + 1] - temperature) / (m[recipenr][stepcounter + 1] - elapsedtime); // recalculate the rate (pos or neg rise in degrees per second) 
          if (elapsedtime < m[recipenr][stepcounter + 1] - 1){elapsedtime++;}                  // if the total time between steps is not reached, increase the elapsed time
          if (rate >= 0 && sp < Setpoint) {sp = sp + rate; if (sp > Setpoint){sp = Setpoint;}} // increase the sp with the positive rate until the setpoint is reached
          if (rate < 0  && sp > Setpoint) {sp = sp + rate; if (sp < Setpoint){sp = Setpoint;}} // increase the sp with the negative rate until the setpoint is reached
        }
      }
    
      // draw reflowcurve
      unsigned long drawnow = millis();
      if (drawnow - drawtime > drawwindow) {
        drawtime = drawnow;
        drawreflowcurve(); // redraw the temperature curve
      }
    
      // button touch delay
      unsigned long touchnow = millis();
      if (touchnow - touchtime > touchwindow) {
        touchtime = touchnow;
        readbutton();         // check if, and which button is pressed
        if(screen == 1) {editrecipe(recipenr);} //print the edit recipe window on screen 1
        if (starttimer == 1){touchwindow = touchwindow - 40; if(touchwindow < 0){touchwindow = 0;}}  // if a repeat puls button is still pressed, lower the repeat time
      }
      Input = temperature; // connect the current temperature to the PID controller
      myPID.Compute();     // recompute the PID output
    
      if (millis() - windowStartTime > WindowSize)
      { //time to shift the Relay Window
        windowStartTime += WindowSize;
      }
      if (Output < millis() - windowStartTime) {digitalWrite(HEATER_PIN, LOW);} else { digitalWrite(HEATER_PIN, HIGH);} // send the PID output(0 or 1) to the heater
    
    }
    
    void recalc(){ // function to recalculate the trend time and temperature scale
      mt = m[recipenr][0]+m[recipenr][1]+m[recipenr][2]+m[recipenr][3]+m[recipenr][4]+m[recipenr][5]+m[recipenr][6];
      Tt = 0; for (int i = 1; i <= 6; i++) {if (Tt < T[recipenr][i]){Tt = T[recipenr][i];}}
      mt = (mt+timediv-1)/timediv; // calculate the next rounded time value on the scale
      Tt = (Tt+tempdiv-1)/tempdiv; // calculate the next rounded temperature value on the scale
      drawwindow = (mt*timediv*1000)/(xend-xbegin);// calculate the redraw time interval per pixel
      
    }
    
    void fan_onoff(int pos){ // switch the fan on or off
      if (pos == 0){//fan off
        switchbutton(fan, 0); // switch the fan button symbol off
        digitalWrite(FAN_PIN, LOW); // switch the fan output off
      }
      if (pos == 1){//fan on
        switchbutton(fan, 1); // switch the fan button symbol on
        digitalWrite(FAN_PIN, HIGH); // switch the fan output on
      }
    }
    
    void buzzer_onoff(int pos){ // switch the buzzer on or off
      if (pos == 0){//buzzer off
        digitalWrite(BUZZER_PIN, LOW); // switch the buzzer output off
      }
      if (pos == 1){//buzzer on
        digitalWrite(BUZZER_PIN, HIGH); // switch the buzzer output on
      }
    }
    
    void on_off(int pos){ // start or stop the reflow
      if (pos == 0){//off
        oldrptext = zonetxt[rptxt[recipenr][stepcounter+1]];    // save the old reflow zone text
        rptext = zonetxt[rptxt[recipenr][stepcounter]];         // get the new reflow zone text
        reflowtext(1);                                          // print the reflow zone text at the left top of the screen
        T[recipenr][0] = 0;                                     // make the first temperature of the recipe 0
        elapsedtime = 0;                                        // reset the elapsed time between zone steps
        stepcounter = 0;                                        // reset the zone step counter
        sp = 0;                                                 // set the sp (PID setpoint) to zero
        if(screen == 0){switchbutton(onoff, 0);}                // switch the onoff button symbol off
        scr[onoff].in = 0;                                      // Set the onoff button.in parameter to zero
        startcurve = 0;                                         // stop the reflow curve
        fan_onoff(1);                                           // Start the cooling fan
      }
      if (pos == 1){//on
        resettemperaturecurve();                                // reset the themperature curve array (make all the elements zero)
        
        oldrptext = zonetxt[rptxt[recipenr][stepcounter]];      // save the old reflow zone text
        rptext = zonetxt[rptxt[recipenr][stepcounter+1]];       // get the new reflow zone text
        rate = (T[recipenr][1] - temperature) / m[recipenr][1]; // calculate the first rate (rise in celcius per second)
        elapsedtime = 0;                                        // reset the elapsed time between zone steps
        stepcounter = 0;                                        // reset the zone step counter
        sp = temperature;                                       // set the sp (PID setpoint) to the current temperature
        T[recipenr][0] = sp;                                    // make the first temperature of the recipe the current temperature
        switchbutton(onoff, 1);                                 // switch the onoff button symbol on
        scr[onoff].in = 1;                                      // Set the onoff button.in parameter to one
        startcurve = 1;                                         // start the reflow curve
        fan_onoff(0);                                           // Stop the cooling fan
    /*      screen = 0;
          fillScreen(backcolor);
          tft.setTextColor(txtcolor);
          drawbuttons(1);
          tft.drawRect(0, 0, WIDTH, HEIGHT-BUTTONH, bordercolor);
          recalc();
          drawaxes(); drawtraceline();
          reflowtext(1);
          recipetext(1, 350);
          redrtop = 1;*/
      }
    }
    
    
    void drawreflowcurve(){                                                        // draw the temperature trend
      if (startcurve == 1){                                                        // only draw if the reflow has started
        float pixelsgrd = (float(yend-ybegin) / (Tt*tempdiv)) * temperature;       // calculate te pixels corresponding with the temperature
        if (pixelsgrd > (yend-ybegin)){pixelsgrd = yend-ybegin;}                   // prefent the temperature from going off scale
        xv[pointcounter] = pixelsgrd;                                              // place the pixel value in the temperature array
        if (screen == 0){                                                          // only print the trend if the screen is the main screen
          for (int i = 0; i < (xend-xbegin); i++) {                                // redraw the whole trend every new point
            if (pixelsgrd > 0){tft.drawPixel(i+xbegin, yend - xv[i], trendcolor);} // only print a value if the temperature is larger then zero
          }
        }
        pointcounter++; if (pointcounter > xend-xbegin){pointcounter = 0;}         // set the pointer for the next value
      }
    }
    
    void drawaxes(){
      tft.setFont();
      int Ttpix = (yend - ybegin) / Tt;
      int mtpix = (xend - xbegin) / mt;
      tft.fillRect(0, ybegin-5, 480, yend-ybegin+28, backcolor);
      tft.drawLine(xbegin-1, ybegin, xbegin-1, yend+1, txtcolor);                                        // draw the vertical axes
      for (int i = 0; i <= Tt; i++) {
        if (i == Tt){tft.setCursor(xbegin-25, yend - i*Ttpix + Ttpix/2 - 4); tft.print("(C)");}          // print the temperature symbol in the trend
        drawString(1, xbegin-25, yend-i*Ttpix - 4, 6, 3, "", String(i*tempdiv), 1, txtcolor, backcolor, 1); // print the numbers next to the vertical axis
        tft.drawLine(xbegin - 6, yend-i*Ttpix , xbegin-1, yend-i*Ttpix, txtcolor);                       // print the division lines
      }
      tft.drawLine(xbegin-1, yend+1, xend, yend+1, txtcolor);                                            // draw the horizontal axes
      for (int i = 0; i <= mt; i++) {
        if (i == mt){tft.setCursor(xbegin + i*mtpix - mtpix/2 - 9, yend+10); tft.print("(sec)");}        // print the time symbol in the trend
        drawString(1, xbegin+i*mtpix - 9, yend+10, 6, 3, "", String(i*timediv), 1, txtcolor, backcolor, 1); // print the numbers below the horizontal axis
        tft.drawLine(xbegin+i*mtpix, yend+6 , xbegin+i*mtpix, yend+1, txtcolor);                         // print the division lines
      }
      drawraster(); // draw the raster lines
      tft.setFont(&Monospaced_plain_22);
    }
    
    void drawraster(){                                                          // draw the trend background and the rasterlines
      int Ttpix = (yend - ybegin) / Tt;                                         // pixels between two horizontal rasterlines
      int mtpix = (xend - xbegin) / mt;                                         // pixels between two vertical rasterlines
      tft.fillRect(xbegin, ybegin, xend-xbegin, yend-ybegin, BLACK);            // make a black trend background
      for (int i = 0; i <= Tt; i++) {
        tft.drawLine(xbegin, yend-i*Ttpix , xend, yend-i*Ttpix, rastcolor);     // draw the horizontal rasterlines
      }
      for (int i = 0; i <= mt; i++) {
        tft.drawLine(xbegin+i*mtpix, ybegin , xbegin+i*mtpix, yend, rastcolor); // draw the vertical rasterlines
      }
    }
    
    void drawtraceline(){                                                       // draw the recipe traceline in the trend
      int Ttot0 = 0; int Ttot1 = 0;
      int yrange = Tt*tempdiv; float pixpergrd = float(yend-ybegin)/yrange;
      int xrange = mt*timediv; float pixpersec = float(xend-xbegin)/xrange;
      for (int i = 1; i <= 6; i++) {
        Ttot0 = Ttot0 + m[recipenr][i-1]*pixpersec;
        Ttot1 = Ttot1 + m[recipenr][i]*pixpersec;
        tft.drawLine(xbegin + Ttot0, yend - T[recipenr][i-1]*pixpergrd, xbegin + Ttot1, yend - T[recipenr][i]*pixpergrd, GREY);
      }
    }
    
    void reflowtext(int tinit){
      drawString(tinit, 10, 20, ms22_spacing, 8, oldrptext, rptext, 0, txtcolor, backcolor, Monospaced_plain_22); // draw reflow zone text at the left top of the screen
    }
    
    void recipetext(int tinit, int pos){
      drawString(tinit, pos, 20, ms22_spacing, 10, rcptxt[oldrecipenr], rcptxt[recipenr], 1, txtcolor, backcolor, Monospaced_plain_22); // draw the recipe text at the right top of the screen
    }
    
    void fillScreen(int scolor){// fill the screen above the buttons at the bottom of the screen
      tft.fillRect(0, 0, WIDTH, HEIGHT-BUTTONH, scolor);
    }
    
    void drawString(int pinit, int px, int py, int pspacing, int plength, String oldpvalue, String pvalue, int pjust, uint16_t txtcol, uint16_t bckcol, const GFXfont &font){// draw a string or only the changes in a string on the screen
      //&font is the gfx font + fontsize 1
      tft.setFont(&font); tft.setTextSize(1);
      drawStringHelper(pinit, px, py, pspacing, plength, oldpvalue, pvalue, pjust, txtcol, bckcol);
    }
    
    void drawString(int pinit, int px, int py, int pspacing, int plength, String oldpvalue, String pvalue, int pjust, uint16_t txtcol, uint16_t bckcol, int fontsize){// draw a string or only the changes in a string on the screen
      //Is the standard font fontsize
      tft.setFont(); tft.setTextSize(fontsize);
      drawStringHelper(pinit, px, py, pspacing, plength, oldpvalue, pvalue, pjust, txtcol, bckcol);
    }
    
    void drawStringHelper(int pinit, int px, int py, int pspacing, int plength, String oldpvalue, String pvalue, int pjust, uint16_t txtcol, uint16_t bckcol){// draw a string or only the changes in a string on the screen
    
      // pinit = 0 prints only changed characters, pinit = 1 prints all the characters
      // px and py are the coordinates on the screen
      // pspacing is the character spacing
      // plength is de total length to print
      // oldpvalue, pvalue is the string to print
      // pjust = 0 is left justify, pjust = 1 is right justify
      // txtcol is the text color
      // bckcol is the text background color
    
      String spaces = "                    ";                                                  // used for adding spaces in right and left justify
      
      if (pjust == 0){// left justify
        pvalue = pvalue + String(spaces.substring(0, plength - pvalue.length()));              // add spaces to the right of the text until the string length = plength
        oldpvalue = oldpvalue + String(spaces.substring(0, plength - oldpvalue.length()));     // add spaces to the right of the text until the string length = plength
      }
      
      if (pjust == 1){// right justify
        pvalue = String(spaces.substring(0, plength - pvalue.length())) + pvalue;              // add spaces to the left of the text until the string length = plength
        oldpvalue = String(spaces.substring(0, plength - oldpvalue.length())) + oldpvalue;     // add spaces to the left of the text until the string length = plength
      }
      
      for (int i = 0; i < plength; i++) {
        if (pvalue.substring(i, i+1) != oldpvalue.substring(i, i+1) or pinit == 1){// Only print, if de characters in de string are different than in the old string or if pinit =1
          tft.setTextColor(bckcol);            // set the font color the same as the background to erase the old character
          tft.setCursor(px+i*pspacing, py);
          tft.print(oldpvalue.substring(i, i+1)); // erase the old character
          tft.setTextColor(txtcol);             // set the font color the same as the foreground to print the new character
          tft.setCursor(px+i*pspacing, py);
          tft.print(pvalue.substring(i, i+1));    // print the new character
        }
      }
    }
    
    void editrecipe(int rnr){
      // valinit = 0 --- reprint the complete editor window on the setup screen (screen 1)
      // valinit = 1 --- print only the changes since the last time it was printed 
        tft.setFont(&Monospaced_plain_22);
        tft.setTextColor(txtcolor);
        if (valinit == 0){ //Print the fixed texts at the top of the values
                tft.setCursor(10, 60); tft.print("Time(s)");
                tft.setCursor(123, 60); tft.print("Temp(C)");
                tft.setCursor(241, 60); tft.print("Zone");
        }
        for (int i = 1; i < 6; i++) {
            curtemp = cur/3; curtemp2 = cur-curtemp*3;
            if (curtemp2 == 0 || valinit == 0 || valinit == 2) {
              if (valinit == 1 || valinit == 2){valueoldstrm[i] = valuestrm[i];}                                       // save the time value from the parameter at the current position
              if (valinit == 0){valueoldstrm[i] = "";}                                                   // clear the old time value to make it different from the new time value
              valuestrm[i] = String(m[recipenr][i]);                                               // get the new time value from the recipe parameter
              drawString(0, 35, 85+i*25, ms22_spacing, 3, valueoldstrm[i], valuestrm[i], 1, txtcolor, backcolor, Monospaced_plain_22); // draw the new time value on the screen
            }
            
            if (curtemp2 == 1 || valinit == 0 || valinit == 2) {
              if (valinit == 1 || valinit == 2){valueoldstrT[i] = valuestrT[i];}                                         // save the temperature value from the parameter at the current position
              if (valinit == 0){valueoldstrT[i] = "";}                                                     // clear the old temperature value to make it different from the new temperature value
              valuestrT[i] = String(T[recipenr][i]);                                                 // get the new temperature value from the recipe parameter
             drawString(0, 148, 85+i*25, ms22_spacing, 3, valueoldstrT[i], valuestrT[i], 1, txtcolor, backcolor, Monospaced_plain_22);  // draw the new temperature value on the screen
            }
    
            if (curtemp2 == 2 || valinit == 0 || valinit == 2) {
              if (valinit == 1 || valinit == 2){valueoldstrtxt[i] = valuestrtxt[i];}                                         // save the temperature value from the parameter at the current position
              if (valinit == 0){valueoldstrtxt[i] = "";}                                                     // clear the old temperature value to make it different from the new temperature value
              valuestrtxt[i] = zonetxt[rptxt[recipenr][i]];                                                 // get the new temperature value from the recipe parameter
              drawString(0, 241, 85+i*25, ms22_spacing, 10, valueoldstrtxt[i], valuestrtxt[i], 0, txtcolor, backcolor, Monospaced_plain_22);  // draw the new temperature value on the screen
            }
    
    }
    valinit = 1;
    }
    
    // find the button number that is touched and change the looks of the touched button on the screen
    int touchtft(){
      tchd = ts.touched();                       // 0 = not touched, 1 = touched
      if (tchd && btnr == 999){blocked = 0;}     // btnr == 999 is no button pressed, blocked = 0 is one puls button
      TS_Point p = ts.getPoint();                // get values from the touchscreen 
      uint16_t xxn, yyn; 
      btnr = 999;                                // reset the button nr.
        if (tchd) {                              // if touched
        uint16_t X_Raw = p.x;                    // get the raw x coordinate from the touchscreen (0-4095)
        uint16_t Y_Raw = p.y;                    // get the raw y coordinate from the touchscreen (0-4095)
        xxn = map(X_Raw, HMAX, HMIN, 0, WIDTH);  // convert the raw x coordinate to the screen width (0-480)
        yyn = map(Y_Raw, VMIN, VMAX, 0, HEIGHT); // convert the raw y coordinate to the screen height (0-320)
    
        if (screen == 0){ // the main screen
          for (int i = 0; i <= 6; i++) {
            int ii = scr0but[i];
            if (xxn >= scr[ii].x & xxn <= scr[ii].x+scr[ii].w & yyn >= scr[ii].y & yyn <= scr[ii].y+scr[ii].h){ // compare the touchscreen coordinates with the button coordinates
              btnr = ii; // if the coordinates match, save the button number
            }
          }
        }
        if (screen == 1){// the setup screen
          for (int i = 1; i <= 9; i++) {
            int ii = scr1but[i];
            if (xxn >= scr[ii].x & xxn <= scr[ii].x+scr[ii].w & yyn >= scr[ii].y & yyn <= scr[ii].y+scr[ii].h){ // compare the touchscreen coordinates with the button coordinates
              btnr = ii; // if the coordinates match, save the button number
            }
          }
        }
      }
      return btnr;
    }
    
    void resettemperaturecurve(){// make every element of the temperature array zero
      for (int i = 0; i < 480; i++) {
        xv[i]=0;
      }
      pointcounter = 1; // reset the pointcounter
      sp = 0;           // reset the PID setpoint to zero
    }
    
    void readbutton(){
      
      butnr = touchtft(); // get the button number from the touchscreen
      
      if (blocked == 0 && btnr != 999 ){
        switchbutton(btnr, 2);
    
        if (scr[butnr].repeat == 1){blocked = 1;}
        if (blocked == 0){if (starttimer == 0){touchwindow = 500;} starttimer = 1;}
        tft.setFont(&Monospaced_plain_22);
    
        if (butnr == gear){ // setup
          valinit = 0;
          screen = 1;
          fillScreen(backcolor);
          tft.setTextColor(txtcolor);
          drawbuttons(1);
          tft.drawRect(0, 0, WIDTH-BUTTONW, HEIGHT-BUTTONH, bordercolor);
          tft.setCursor(xcursor[cur], ycursor[cur]); tft.print(">");
          reflowtext(1);
    //      if (screen == 0){recipetext(1, 350);}
    //      if (screen == 1){recipetext(1, 270);}
          recipetext(1, 255);
          redrtop = 1;
          butnr = 999;
          rtxtcur = 0;
          scrltxt = alphabetconv[int(rcptxt[recipenr][rtxtcur])-32];
          drawString(1, 241+rtxtcur*ms22_spacing, 30, ms22_spacing, 2, "- ", " -", 1, txtcolor, backcolor, Monospaced_plain_22);
        }
        if (butnr == backward){ // backward
          store();
          if (recipenr > 1){
            oldrecipenr = recipenr;
            recipenr--;
            valinit = 2;
            recalc();
            resettemperaturecurve();
            on_off(0);
            if (screen == 0){drawaxes(); drawtraceline();}
            if (screen == 0){recipetext(1, 335);}
            if (screen == 1){recipetext(1, 255);}
          }
        }
        if (butnr == forward){ // forward
          store();
          if (recipenr < 5){
            oldrecipenr = recipenr;
            recipenr++;
            valinit = 2;
            recalc();
            resettemperaturecurve();
            on_off(0);
            if (screen == 0){drawaxes(); drawtraceline();}
            if (screen == 0){recipetext(1, 335);}
            if (screen == 1){recipetext(1, 255);}
          }
        }
        if(butnr == fan){ // down
          fan_onoff(scr[butnr].in);
        }
        if (butnr == onoff){ // onoff
          startcurve = scr[butnr].in;
          on_off(startcurve);
        }
    
        if(butnr == home){ // home
          store();
          screen = 0;
          fillScreen(backcolor);
          tft.setTextColor(txtcolor);
          tft.drawRect(0, 0, WIDTH, HEIGHT-BUTTONH, bordercolor);
          recalc();
          drawbuttons(0);
          drawaxes(); drawtraceline();
          reflowtext(1);
    //      if (screen == 0){recipetext(1, 350);}
    //      if (screen == 1){recipetext(1, 270);}
          recipetext(1, 335);
          redrtop = 1;
        }
        if(butnr == tab){ // tab
          tft.setTextColor(backcolor, backcolor); tft.setCursor(xcursor[cur], ycursor[cur]); tft.print(">");
          cur=cur+1; if (cur > 17){cur = 2;}
          tft.setTextColor(txtcolor, backcolor); tft.setCursor(xcursor[cur], ycursor[cur]); tft.print(">");
          if (cur == 2){
            rtxtcur = 0;
            scrltxt = alphabetconv[int(rcptxt[recipenr][rtxtcur])-32];
            drawString(1, 241+rtxtcur*ms22_spacing, 30, ms22_spacing, 2, "- ", " -", 1, txtcolor, backcolor, Monospaced_plain_22);
          }
          if (cur == 3){
            drawString(1, 241+rtxtcur*ms22_spacing, 30, ms22_spacing, 2, " -", "", 1, txtcolor, backcolor, Monospaced_plain_22);
          }
        }
        if(butnr == right){ // right
          rtxtcur++; if (rtxtcur > 9){rtxtcur = 0; drawString(1, 241+rtxtcur*ms22_spacing, 30, ms22_spacing, 11, "-", " ", 1, txtcolor, backcolor, Monospaced_plain_22);}
          scrltxt = alphabetconv[int(rcptxt[recipenr][rtxtcur])-32];
          drawString(1, 241+rtxtcur*ms22_spacing, 30, ms22_spacing, 2, "- ", " -", 1, txtcolor, backcolor, Monospaced_plain_22);
         }
        if(butnr == up){ // up
          if (scr[onoff].in == 1){scr[onoff].in = 0; startcurve = scr[onoff].in; on_off(startcurve);}
          
          if (ycursor[cur]>25){
            curtemp = cur/3; curtemp2 = cur-curtemp*3;
            if(curtemp2 == 0){ // time
              if(m[recipenr][curtemp] < maxvaluem[curtemp]){
                m[recipenr][curtemp]++;
              }
            }
            if(curtemp2 == 1){ // temperature
              if(T[recipenr][curtemp] < maxvalueT[curtemp]){
                T[recipenr][curtemp]++;
              }
            }
            if(curtemp2 == 2){ // temperature
              if(rptxt[recipenr][curtemp] < 5){
                rptxt[recipenr][curtemp]++;
              }
            }
          }else{
            String rcptxtemp = String(rcptxt[recipenr]);
            scrltxt++; if(scrltxt>37){scrltxt=0;}
            rcptxt[recipenr][rtxtcur] = alphabet[scrltxt];
            drawString(0, 255, 20, ms22_spacing, 10, rcptxtemp, String(rcptxt[recipenr]), 1, txtcolor, backcolor, Monospaced_plain_22);
          }
        }
        if(butnr == down){ // down
          if (scr[onoff].in == 1){scr[onoff].in = 0; startcurve = scr[onoff].in; on_off(startcurve);}
          
          if (ycursor[cur]>25){
            curtemp = cur/3; curtemp2 = cur-curtemp*3;
            if(curtemp2 == 0){ // time
              if(m[recipenr][curtemp] > 0){
                m[recipenr][curtemp]--;
              }
            }
            if(curtemp2 == 1){ // temperature
              if(T[recipenr][curtemp] > 0){
                T[recipenr][curtemp]--;
              }
            }
            if(curtemp2 == 2){ // temperature
              if(rptxt[recipenr][curtemp] >0){
                rptxt[recipenr][curtemp]--;
              }
            }
          }else{
            String rcptxtemp = String(rcptxt[recipenr]);
            scrltxt--; if(scrltxt<0){scrltxt=37;}
            rcptxt[recipenr][rtxtcur] = alphabet[scrltxt];
            drawString(0, 255, 20, ms22_spacing, 10, rcptxtemp, String(rcptxt[recipenr]), 1, txtcolor, backcolor, Monospaced_plain_22);
          }
        }
     
    
      }else{starttimer = 0; touchwindow = 0;}
    }
    
    void switchbutton(int btnr, int mod){
      if (btnr<999 & scr[btnr].latch==0){button(scr[btnr]); button(scr[btnr]);}// switch button form positive to negative and back to positive (pushbutton)
      if (btnr<999 & scr[btnr].latch>0){
        if (mod == 0) {scr[btnr].in = 0; button(scr[btnr]);}  // button = off
        if (mod == 1) {scr[btnr].in = 1; button(scr[btnr]);}  // button = on
        if (mod == 2) {
          scr[btnr].in = 1 - scr[btnr].in; button(scr[btnr]); // toggle button
        }
      }
    }
    
    void drawbuttons(int part){
        if (part == 0 & screen == 0){button(scr[9]); for (int i = 1; i <= 5; i++) {button(scr[i]);}}  // draw only the bottom row buttons
        if (part == 0 & screen == 1){for (int i = 0; i <= 5; i++) {button(scr[i]);};}                   // draw only the left bottom row button (Home)
        if (part == 1 & screen == 1){for (int i = 6; i <= 8; i++) {button(scr[i]);} button(scr[10]);} // draw the three right side butons
    }
    
    // draw a button on the screen
    void button(but bx){
      if (bx.draw == 1){// draw a button
        uint8_t byte0 = pgm_read_byte(&bx.bm[0]); // get the button symbol width
        uint8_t byte1 = pgm_read_byte(&bx.bm[1]); // get the button symbol height
        if (bx.in == 0){ //pushbutton
          tft.fillRect(bx.x, bx.y, bx.w, bx.h, bx.bacolor);                                              // draw the button background (background color)
          tft.drawRect(bx.x, bx.y, bx.w, bx.h, bx.bocolor);                                              // draw the button border
          //tft.drawBitmap(bx.x+(bx.w-byte0)/2, bx.y+(bx.h-byte1)/2, bx.bm+2, byte0, byte1, bx.color);     // draw the button symbol (symbol color)
        } else {
          if (bx.latch == 1){  //pushbutton colors inverted
            tft.fillRect(bx.x, bx.y, bx.w, bx.h, bx.color);                                              // draw the button background (symbol color)
            tft.drawRect(bx.x, bx.y, bx.w, bx.h, bx.bocolor);                                            // draw the button border
            //tft.drawBitmap(bx.x+(bx.w-byte0)/2, bx.y+(bx.h-byte1)/2, bx.bm+2, byte0, byte1, bx.bacolor); // draw the button symbol (background color)
          }
          if (bx.latch == 2){ //switch
            tft.fillRect(bx.x, bx.y, bx.w, bx.h, bx.bacolor);                                             // draw the button background (background color)
            tft.drawRect(bx.x, bx.y, bx.w, bx.h, bx.bocolor);                                             // draw the button border
            //tft.drawBitmap(bx.x+(bx.w-byte0)/2, bx.y+(bx.h-byte1)/2, bx.bm+2, byte0, byte1, bx.swcolor);  // draw the button symbol (switch color)
          }
        }
      }
    }
    
    void store(){
      //drawBitmap DataWrite;
      uint16_t AddressWrite = 0x10;
      uint16_t StatusWrite;
     
      for (int ir = 1; ir <= 5; ir++){
        for (int iz = 1; iz <= 6; iz++){
          AddressWrite = AddressWrite + 16;
          //DataWrite = T[ir][iz];
          //StatusWrite = EEPROM.write(AddressWrite, DataWrite);        
        }
      }
      for (int ir = 1; ir <= 5; ir++){
        for (int iz = 1; iz <= 6; iz++){
          AddressWrite = AddressWrite + 16;
          //DataWrite = m[ir][iz];
          //StatusWrite = EEPROM.write(AddressWrite, DataWrite);        
        }
      }
      for (int ir = 1; ir <= 5; ir++){
        for (int iz = 1; iz <= 6; iz++){
          AddressWrite = AddressWrite + 16;
          //DataWrite = rptxt[ir][iz];
          //StatusWrite = EEPROM.write(AddressWrite, DataWrite);   
        }     
      }
      for (int ir = 1; ir < 5; ir++){
        for (int iz = 0; iz < 9; iz=iz+2){
          AddressWrite = AddressWrite + 16;        
          //DataWrite = rcptxt[ir][iz]+rcptxt[ir][iz+1]*256;
         // StatusWrite = EEPROM.write(AddressWrite, DataWrite);   
        }     
      }
    }
    Last edited by KurtE; 03-19-2020 at 06:35 PM. Reason: code tags

  24. #274
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,625
    Note: I put code tags around your code to make it easier to read.... It is the # button in the toolbar...

    Did you try simply pasting in the function I mentioned?

    And change your commented out calls like:
    Code:
           //tft.drawBitmap(bx.x+(bx.w-byte0)/2, bx.y+(bx.h-byte1)/2, bx.bm+2, byte0, byte1, bx.swcolor);  // draw the button symbol (
    to simply be:
    Code:
           mydrawBitmap(bx.x+(bx.w-byte0)/2, bx.y+(bx.h-byte1)/2, bx.bm+2, byte0, byte1, bx.swcolor);  // draw the button symbol (
    Note: sometimes Arduino does not always generate the proper forward reference so you might need a definition for it some where earlier up in sketch before first call.

    Also note sometimes when typing stuff in on the fly there could be minor typos, like the my function should have the void return value at start...

    Code:
    extern void Adafruit_GFX::drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);

  25. #275
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,101
    This is going to sound funny but where are you defining the bitmaps for the buttons? Looks like the bitmap names are in your scr array but don't see how it gets there?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •