Untitled

mail@pastecode.io avatar
unknown
plain_text
3 years ago
20 kB
53
Indexable
Never
#include <SPI.h>             
#define USE_SDFAT
#include <SdFat.h>           // Use the SdFat library
SdFatSoftSpi<12, 11, 13> SD; //Bit-Bang on the Shield pins


#include <Adafruit_GFX.h>    // Hardware-specific library
#include <MCUFRIEND_kbv.h>
#include <TouchScreen.h>
//#include <UTFTGLUE.h>
#include "digi60.h"

MCUFRIEND_kbv tft;





#define SD_CS     10 // PIN DELLA SD DEL NOSTRO TFT

// TOUCH PIN DEL NOSTRO SCHERMO
#define YP A1  
#define XM A2  
#define YM 7   
#define XP 6   
const int TS_LEFT=958,TS_RT=172,TS_TOP=173,TS_BOT=933; //calibrazione LANDSCAPE
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
int pixel_x, pixel_y;


//SENSIBILITA' DEL TOUCHSCREEN
#define MINPRESSURE 200
#define MAXPRESSURE 1000
//BLOCCO COLORI
#define WHITE 0xFFFF
#define BLUE 0x116F



//VARIABILI
int potenza = 0;
long tempo_utente = 0; //il tempo del timer che setta l'utente
bool ATTIVO = false; 
bool PAUSED = false;
unsigned long Scadenza;
long Tempo_Rimanente;
unsigned long t0; // variabile appoggio per il tempo di partenza
long temp; // variabile di appoggio per snellire la memoria
long temp1 = 0;
//funzione Schermo standard
void schermoDefault(){
  showBMP("SFONDO.bmp", 0, 0); //METTIAMO LO SFONDO
  tft.fillTriangle(396,243,396,270,420,256,WHITE); // TRIANGOLI DELLA POTENZA
  tft.fillTriangle(83,243,83,270,59,256,WHITE);
  
  tft.fillRoundRect(105,243,65,28,3,BLUE); // RETTANGOLI OUTPUT POTENZA solo outlines
  tft.fillRoundRect(174,243,64,28,3,BLUE);
  tft.fillRoundRect(242,243,64,28,3,BLUE);
  tft.fillRoundRect(310,243,65,28,3,BLUE);
  tft.drawRoundRect(105,243,65,28,3,WHITE); 
  tft.drawRoundRect(174,243,64,28,3,WHITE);
  tft.drawRoundRect(242,243,64,28,3,WHITE);
  tft.drawRoundRect(310,243,65,28,3,WHITE);

  
  tft.setTextColor(WHITE);          //TESTO TIMER
  tft.setFont(&digital_760pt7b);
  tft.setCursor(185,197);
  // DISEGNIAMO IL TIMER
  tft.fillRoundRect(168,100,144,120,3,BLUE);
  tft.drawRoundRect(168,100,144,120,3,WHITE);
  //tft.setCursor(200,197); //quando c'è un 1 dobbiamo aggiustare la centratura orizzontale
  //tft.setCursor(220,197); //se è 11 dobbiamo centrare ancora di più
  tft.setTextSize(1);
  tft.print("00");

  tft.fillRoundRect(48,120,96,80,3,WHITE); //TASTI TIMER - tasto + SX
  tft.fillRoundRect(91,140,10,40,3,BLUE); // SIMBOLO +
  tft.fillRoundRect(72,155,48,10,3,BLUE);
  tft.fillRoundRect(336,120,96,80,3,WHITE); // tasto - DX
  tft.fillRoundRect(360,155,48,10,3,BLUE); 

  tft.fillRoundRect(48,40,96,40,3,WHITE); // TASTI PLAY PAUSE STOP
  tft.fillTriangle(84,50,84,69,107,60,BLUE); // PLAY
  tft.fillRoundRect(192,40,96,40,3,WHITE); // PAUSE
  tft.fillRoundRect(231,50,6,20,3,BLUE);
  tft.fillRoundRect(243,50,6,20,3,BLUE);
  tft.fillRoundRect(336,40,96,40,3,WHITE); // STOP
  tft.fillRoundRect(372,50,24,20,3,BLUE);
  
  
}





void regolaPotenza(int potenza){
  switch (potenza) {
  case 0:
    Serial.println(potenza);
    tft.fillRoundRect(105,243,65,28,3,BLUE); // RETTANGOLI OUTPUT POTENZA solo outlines
    tft.fillRoundRect(174,243,64,28,3,BLUE);
    tft.fillRoundRect(242,243,64,28,3,BLUE);
    tft.fillRoundRect(310,243,65,28,3,BLUE);
    
    tft.drawRoundRect(105,243,65,28,3,WHITE); 
    tft.drawRoundRect(174,243,64,28,3,WHITE);
    tft.drawRoundRect(242,243,64,28,3,WHITE);
    tft.drawRoundRect(310,243,65,28,3,WHITE);
    break;
    
  case 1:
    Serial.println(potenza);
    tft.fillRoundRect(105,243,65,28,3,WHITE); // OUTPUT POTENZA A 1 PIENO

    tft.fillRoundRect(174,243,64,28,3,BLUE); // OUTPUT POTENZA A 1 OUTLINES
    tft.fillRoundRect(242,243,64,28,3,BLUE);
    tft.fillRoundRect(310,243,65,28,3,BLUE);
    tft.drawRoundRect(174,243,64,28,3,WHITE);
    tft.drawRoundRect(242,243,64,28,3,WHITE);
    tft.drawRoundRect(310,243,65,28,3,WHITE);
    
    //setto potenza al livello 1 col digital write
    break;
  case 2:
    Serial.println(potenza);
    tft.fillRoundRect(105,243,65,28,3,WHITE); // OUTPUT POTENZA A 2
    tft.fillRoundRect(174,243,64,28,3,WHITE);

    tft.fillRoundRect(242,243,64,28,3,BLUE); //OUTPUT 2 OUTLINES
    tft.fillRoundRect(310,243,65,28,3,BLUE);
    tft.drawRoundRect(242,243,64,28,3,WHITE);
    tft.drawRoundRect(310,243,65,28,3,WHITE);
    //setto potenza al livello 2 col digital write
    break;
  case 3:
    Serial.println(potenza);
    tft.fillRoundRect(105,243,65,28,3,WHITE); // OUTPUT POTENZA A 3
    tft.fillRoundRect(174,243,64,28,3,WHITE);
    tft.fillRoundRect(242,243,64,28,3,WHITE);
    
    tft.fillRoundRect(310,243,65,28,3,BLUE); // OUTPUT 3 OUTLINES
    tft.drawRoundRect(310,243,65,28,3,WHITE);
    //setto potenza al livello 3 col digital write
    break;
  case 4:
    Serial.println(potenza);
    tft.fillRoundRect(105,243,65,28,3,WHITE); // OUTPUT POTENZA A 4
    tft.fillRoundRect(174,243,64,28,3,WHITE);
    tft.fillRoundRect(242,243,64,28,3,WHITE);
    tft.fillRoundRect(310,243,65,28,3,WHITE);
    //setto potenza al livello 3 col digital write
    break;
  }  
}



void drawTimer(int tempo_utente)
{
  // PULIAMO LO SCHERMO
  tft.fillRoundRect(168,100,144,120,3,BLUE);
  tft.drawRoundRect(168,100,144,120,3,WHITE);
  tft.setTextColor(WHITE);          //TESTO TIMER
  tft.setFont(&digital_760pt7b);

  tft.setCursor(185,197); // SE NON CI SONO UNO LASCIAMO LA CENTRATURA DEFAULT
  if (String(tempo_utente).indexOf("1") != -1){
    tft.setCursor(200,197); //se c'è un 1 in una delle due posizioni aggiustiamo la centrature (è una cosa puramente estetica)
  }
  if (tempo_utente > 9 && tempo_utente < 20){
    tft.setCursor(205,197);
  }
  if (tempo_utente == 11){
    tft.setCursor(220,197); //se è 11 dobbiamo centrare ancora di più
  }
  tft.setTextSize(1);
  if (tempo_utente < 10){ //SE E' MINORE DI DIECI VISUALIZZIAMO IL 0X
    tft.print("0");tft.print(String(tempo_utente));
  }
  else {
    tft.print(String(tempo_utente)); 
  }
}




void setup()
{
 
  Serial.begin(9600);
  uint16_t identifier = tft.readID();
  tft.begin(identifier);
  tft.setRotation(1);
  if (!SD.begin(SD_CS)) {
  progmemPrintln(PSTR("failed!"));
  return;
  }
  schermoDefault(); //inizializziamo il nostro schermo con la schermata di default
  
  
 
  
  
}
void(* Riavvia)(void) = 0; // punto di riavvio una volta finito il timer

void loop()
{  
  
  //if (ATTIVO == true && temp != Tempo_Rimanente){ //come prima cosa aggiorniamo il TIMER
    //drawTimer(Tempo_Rimanente);
  //}
  
  
  TSPoint p = ts.getPoint(); //Prendiamo le coordinate del nostro tocco
  pixel_x = map(p.y, TS_LEFT, TS_RT, 0, 480); //CALIBRAZIONE TOUCH SCREEN
  pixel_y = map(p.x, TS_TOP, TS_BOT, 0, 320);
  if (p.z > MINPRESSURE && p.z < MAXPRESSURE) { //Se ha la pressione giusta lo prendiamo in considerazione
     Serial.print("X = "); Serial.print(pixel_x);
     Serial.print("\tY = "); Serial.print(pixel_y);
     Serial.print("\tPressure = "); Serial.println(p.z);
     pinMode(XM, OUTPUT); //IMPORTANTE -> LE LIBRERIE CONDIVIDONO DEI PIN!
     pinMode(YP, OUTPUT);
     
     
     //BLOCCO CONTROLLO TASTI POTENZA
     if (pixel_x > 59 && pixel_x < 84){
      if (pixel_y < 270 && pixel_y > 243){
        if (potenza > 0){ //Controllo che non sia già al minimo
         Serial.print("diminuisco la potenza ");
         potenza--; 
         Serial.println(potenza);
         tft.fillTriangle(83,243,83,270,59,256,BLUE);
         tft.drawTriangle(83,243,83,270,59,256,WHITE);
         regolaPotenza(potenza); 
         delay(250); 
         tft.fillTriangle(83,243,83,270,59,256,WHITE);
        }
       
        
      }     
     }
     if (pixel_x > 410 && pixel_x < 435){  // ho dovuto ricalibrare l'area del touch del triangolo a mano per una scarsa fedeltà dello schermo
      if (pixel_y < 270 && pixel_y > 243){
       if (potenza < 4){ //Controllo che non sia già al massimo
        Serial.print("aumento la potenza "); 
        potenza++; 
        Serial.println(potenza);
        tft.fillTriangle(396,243,396,270,420,256,BLUE);
        tft.drawTriangle(396,243,396,270,420,256,WHITE);
        regolaPotenza(potenza);
        delay(250);  
        tft.fillTriangle(396,243,396,270,420,256,WHITE);
       }  
      }     
     }

     //CONTROLLO REGOLAZIONE TIMER
     if (pixel_x > 48 && pixel_x < 144){
      if (pixel_y > 120 && pixel_y < 200){
        //BLOCCO AUMENTO TIMER
        if (tempo_utente < 99){ // CONTROLLO CHE NON SIA STATO RAGGIUNTO IL LIMITE MASSIMO DEL TIMER 
          tft.fillRoundRect(48,120,96,80,3,BLUE); 
          tft.drawRoundRect(48,120,96,80,3,WHITE);
          tft.fillRoundRect(91,140,10,40,3,WHITE); // SIMBOLO +
          tft.fillRoundRect(72,155,48,10,3,WHITE);
          tempo_utente++;
          drawTimer(tempo_utente);
          delay(100);
          tft.fillRoundRect(48,120,96,80,3,WHITE); //TASTI TIMER - tasto + SX
          tft.fillRoundRect(91,140,10,40,3,BLUE); // SIMBOLO +
          tft.fillRoundRect(72,155,48,10,3,BLUE); 
        }  
      }
     }
     //tft.fillRoundRect(48,120,96,80,3,WHITE); //TASTI TIMER - tasto + SX
     if (pixel_x > 350 && pixel_x < 450){ // HO DOVUTO AGGUSTARE LA CALIBRAZIONE
      if (pixel_y > 120 && pixel_y < 200){
        //BLOCCO DIMINUISCO TIMER
        if (tempo_utente > 0){
          tft.fillRoundRect(336,120,96,80,3,BLUE);
          tft.drawRoundRect(336,120,96,80,3,WHITE);
          tft.fillRoundRect(360,155,48,10,3,WHITE);
          tempo_utente--;
          drawTimer(tempo_utente);
          delay(100);
          tft.fillRoundRect(336,120,96,80,3,WHITE); // tasto - DX
          tft.fillRoundRect(360,155,48,10,3,BLUE); //SIMBOLO -
        }
        
      }     
     }
     //CONTROLLO ATTIVAZIONE TIMER
     if (pixel_x > 48 && pixel_x < 144){ // TASTO PLAY
      if (pixel_y > 40 && pixel_y < 79){
        if (ATTIVO == false){
          tft.fillRoundRect(48,40,96,40,3,BLUE); // TASTI PLAY PAUSE STOP
          tft.fillTriangle(84,50,84,69,107,60,WHITE);
          t0 = millis();
          Scadenza = t0 + ((tempo_utente*1000)*60); //scadenza settata in minuti
          Serial.print("la scadenza è settata a ");
          Serial.println(Scadenza);
          Serial.print("il tempo utente inserito è ");
          Serial.println((tempo_utente*1000)*60);
          if (PAUSED == true){ //SE ERA ATTIVA LA PAUSE RESETTO LA GRAFICA DEL PAUSE
            tft.fillRoundRect(192,40,96,40,3,WHITE); // PAUSE
            tft.fillRoundRect(231,50,6,20,3,BLUE);
            tft.fillRoundRect(243,50,6,20,3,BLUE);
            PAUSED = false; // TOLGO LA PAUSA
          }
          ATTIVO = true; // ATTIVO IL TIMER
          
        } 
      }
     }
     if (pixel_x > 192 && pixel_x < 287){ // TASTO PAUSE
      if (pixel_y > 40 && pixel_y < 79){
        if ( ATTIVO == true && PAUSED == false){
          tft.fillRoundRect(192,40,96,40,3,BLUE); // PAUSE
          tft.fillRoundRect(231,50,6,20,3,WHITE);
          tft.fillRoundRect(243,50,6,20,3,WHITE);
          
          tft.fillRoundRect(48,40,96,40,3,WHITE); // RESETTO LA GRAFICA DEL TASTO PLAY
          tft.fillTriangle(84,50,84,69,107,60,BLUE);
          PAUSED = true; // ATTIVO LA PAUSA
          ATTIVO = false; // SPENGO IL PLAY
        }       
      }
     }
     if (pixel_x > 350 && pixel_x < 450){ // TASTO STOP/RESET
      if (pixel_y > 40 && pixel_y < 79){
        tft.fillRoundRect(336,40,96,40,3,BLUE); // STOP
        tft.fillRoundRect(372,50,24,20,3,WHITE);
        
        // RESETTO TUTTO
        tempo_utente = 0;
        potenza = 0;
        drawTimer(tempo_utente);
        regolaPotenza(potenza);
         
        //RESETTO GRAFICHE
        tft.fillRoundRect(48,40,96,40,3,WHITE); // RESETTO LA GRAFICA DEL TASTO PLAY
        tft.fillTriangle(84,50,84,69,107,60,BLUE);
        
        tft.fillRoundRect(192,40,96,40,3,WHITE); // PAUSE
        tft.fillRoundRect(231,50,6,20,3,BLUE);
        tft.fillRoundRect(243,50,6,20,3,BLUE);
      
        tft.fillRoundRect(336,40,96,40,3,WHITE); // STOP
        tft.fillRoundRect(372,50,24,20,3,BLUE);
        ATTIVO = false;
        PAUSED = false;  
      }
     }    
  }
  temp = Tempo_Rimanente; //variabile di appoggio per snellire il carico di lavoro dello schermo
  
  
  if (ATTIVO == true){ // CONTROLLO AD OGNI LOOP SE E' STATO ATTIVATO IL TIMER ED EVENTUALE TEMPO RIMANENTE
    if ( temp1 != round((millis()/60)/1000)){
      Tempo_Rimanente = round((Scadenza/60)/1000) - round((millis()/60)/1000); //visualizziamo quanto manca al nostro timer
      temp1 = round((millis()/60)/1000);
      if (temp != Tempo_Rimanente){ //stampiamo solo se il valore è cambiato
        
        Serial.println(Tempo_Rimanente);
        
        
          
      }
    }
    
    
    
    
    
    
    if(round((Scadenza/60)/1000) == round((millis()/60)/1000)){// IL TEMPO E' SCADUTO
      Serial.println("TEMPO SCADUTOOOOOOOOO");
      tft.fillRoundRect(48,40,96,40,3,WHITE); // TASTI PLAY PAUSE STOP
      tft.fillTriangle(84,50,84,69,107,60,BLUE);
        
    }   
  }
  
}



// BLOCCO MOSTRA .BMP
#define BMPIMAGEOFFSET 54
#define BUFFPIXEL      20
#define PALETTEDEPTH   8     // support 256-colour Palette

uint16_t read16(File& f) {
    uint16_t result;         // read little-endian
    f.read(&result, sizeof(result));
    return result;
}

uint32_t read32(File& f) {
    uint32_t result;
    f.read(&result, sizeof(result));
    return result;
}

uint8_t showBMP(char *nm, int x, int y)
{
    File bmpFile;
    int bmpWidth, bmpHeight;    // W+H in pixels
    uint8_t bmpDepth;           // Bit depth (currently must be 24, 16, 8, 4, 1)
    uint32_t bmpImageoffset;    // Start of image data in file
    uint32_t rowSize;           // Not always = bmpWidth; may have padding
    uint8_t sdbuffer[3 * BUFFPIXEL];    // pixel in buffer (R+G+B per pixel)
    uint16_t lcdbuffer[(1 << PALETTEDEPTH) + BUFFPIXEL], *palette = NULL;
    uint8_t bitmask, bitshift;
    boolean flip = true;        // BMP is stored bottom-to-top
    int w, h, row, col, lcdbufsiz = (1 << PALETTEDEPTH) + BUFFPIXEL, buffidx;
    uint32_t pos;               // seek position
    boolean is565 = false;      //

    uint16_t bmpID;
    uint16_t n;                 // blocks read
    uint8_t ret;

    if ((x >= tft.width()) || (y >= tft.height()))
        return 1;               // off screen

    bmpFile = SD.open(nm);      // Parse BMP header
    bmpID = read16(bmpFile);    // BMP signature
    (void) read32(bmpFile);     // Read & ignore file size
    (void) read32(bmpFile);     // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile);       // Start of image data
    (void) read32(bmpFile);     // Read & ignore DIB header size
    bmpWidth = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    n = read16(bmpFile);        // # planes -- must be '1'
    bmpDepth = read16(bmpFile); // bits per pixel
    pos = read32(bmpFile);      // format
    if (bmpID != 0x4D42) ret = 2; // bad ID
    else if (n != 1) ret = 3;   // too many planes
    else if (pos != 0 && pos != 3) ret = 4; // format: 0 = uncompressed, 3 = 565
    else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5; // palette 
    else {
        bool first = true;
        is565 = (pos == 3);               // ?already in 16-bit format
        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
        if (bmpHeight < 0) {              // If negative, image is in top-down order.
            bmpHeight = -bmpHeight;
            flip = false;
        }

        w = bmpWidth;
        h = bmpHeight;
        if ((x + w) >= tft.width())       // Crop area to be loaded
            w = tft.width() - x;
        if ((y + h) >= tft.height())      //
            h = tft.height() - y;

        if (bmpDepth <= PALETTEDEPTH) {   // these modes have separate palette
            //bmpFile.seek(BMPIMAGEOFFSET); //palette is always @ 54
            bmpFile.seek(bmpImageoffset - (4<<bmpDepth)); //54 for regular, diff for colorsimportant
            bitmask = 0xFF;
            if (bmpDepth < 8)
                bitmask >>= bmpDepth;
            bitshift = 8 - bmpDepth;
            n = 1 << bmpDepth;
            lcdbufsiz -= n;
            palette = lcdbuffer + lcdbufsiz;
            for (col = 0; col < n; col++) {
                pos = read32(bmpFile);    //map palette to 5-6-5
                palette[col] = ((pos & 0x0000F8) >> 3) | ((pos & 0x00FC00) >> 5) | ((pos & 0xF80000) >> 8);
            }
        }

        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
        for (row = 0; row < h; row++) { // For each scanline...
            // Seek to start of scan line.  It might seem labor-
            // intensive to be doing this on every line, but this
            // method covers a lot of gritty details like cropping
            // and scanline padding.  Also, the seek only takes
            // place if the file position actually needs to change
            // (avoids a lot of cluster math in SD library).
            uint8_t r, g, b, *sdptr;
            int lcdidx, lcdleft;
            if (flip)   // Bitmap is stored bottom-to-top order (normal BMP)
                pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
            else        // Bitmap is stored top-to-bottom
                pos = bmpImageoffset + row * rowSize;
            if (bmpFile.position() != pos) { // Need seek?
                bmpFile.seek(pos);
                buffidx = sizeof(sdbuffer); // Force buffer reload
            }

            for (col = 0; col < w; ) {  //pixels in row
                lcdleft = w - col;
                if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
                for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { // buffer at a time
                    uint16_t color;
                    // Time to read more pixel data?
                    if (buffidx >= sizeof(sdbuffer)) { // Indeed
                        bmpFile.read(sdbuffer, sizeof(sdbuffer));
                        buffidx = 0; // Set index to beginning
                        r = 0;
                    }
                    switch (bmpDepth) {          // Convert pixel from BMP to TFT format
                        case 24:
                            b = sdbuffer[buffidx++];
                            g = sdbuffer[buffidx++];
                            r = sdbuffer[buffidx++];
                            color = tft.color565(r, g, b);
                            break;
                        case 16:
                            b = sdbuffer[buffidx++];
                            r = sdbuffer[buffidx++];
                            if (is565)
                                color = (r << 8) | (b);
                            else
                                color = (r << 9) | ((b & 0xE0) << 1) | (b & 0x1F);
                            break;
                        case 1:
                        case 4:
                        case 8:
                            if (r == 0)
                                b = sdbuffer[buffidx++], r = 8;
                            color = palette[(b >> bitshift) & bitmask];
                            r -= bmpDepth;
                            b <<= bmpDepth;
                            break;
                    }
                    lcdbuffer[lcdidx] = color;

                }
                tft.pushColors(lcdbuffer, lcdidx, first);
                first = false;
                col += lcdidx;
            }           // end cols
        }               // end rows
        tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1); //restore full screen
        ret = 0;        // good render
    }
    bmpFile.close();
    return (ret);
}
// Copy string from flash to serial port
// Source string MUST be inside a PSTR() declaration!
void progmemPrint(const char *str) {
  char c;
  while(c = pgm_read_byte(str++)) Serial.print(c);
}
 
// Same as above, with trailing newline
void progmemPrintln(const char *str) {
  progmemPrint(str);
  Serial.println();
}