Untitled
unknown
plain_text
4 years ago
20 kB
76
Indexable
#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(); }
Editor is loading...