Gavin
Published

FIFA World Cup 2022 Schedule Monitor

Use Raspberry Pi RP2040 & WizFi360 to display FIFA 2022 Schedule through football-data API on the screen(GC9A01)

IntermediateFull instructions provided1,238
FIFA World Cup 2022 Schedule Monitor

Things used in this project

Hardware components

WizFi360-EVB-Pico
WIZnet WizFi360-EVB-Pico
×1
RP2040
Raspberry Pi RP2040
×1
GC9A01 1.28 Inch Round LCD
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

FIFA World Cup Qatar 2022 Schedule Moniter Schmatic

Code

FIFA_World_Cup_Schedule_Moniter_Code

Arduino
/*
 WizFi360 example: FIFA_World_Cup_Schedule_Moniter
*/

#include "WizFi360.h"
#include "icon.h"

#include <Arduino_GFX_Library.h>
Arduino_GFX *tft = create_default_Arduino_GFX();

#include <PNGdec.h>

PNG png;
uint8_t image_x;
uint8_t image_y;

typedef enum 
{   
  link_football_server = 0,
  get_football_data,
  display_wait_timeout, 
}STATE_;
STATE_ currentState;

/* Wi-Fi info */
char ssid[] = "wiznet";       // your network SSID (name)
char pass[] = "password";   // your network password

IPAddress ip;
char football_server[] = "api.football-data.org"; 
char football_token[] = "bddbcf892a34414fbb8da6********";
uint16_t football_api_len;
String football_match[4];
uint16_t football_match_len[4];
String football_match_homeTeam[4];
String football_match_awayTeam[4];
String football_match_time[4];
String football_match_day[4];

String match_time_hour;
String match_time_minute;

uint8_t team_num = 0;
uint8_t data_now; 
String json_String; 
uint16_t dataStart = 0;
uint16_t dataEnd = 0;
String dataStr;

int status = WL_IDLE_STATUS;  // the Wifi radio's status
// Initialize the Ethernet client object
WiFiClient client;
    
void setup() {
  // initialize serial for debugging  
  Serial.begin(115200);

  tft->begin();
  tft->fillScreen(WHITE);
  pinMode(22, OUTPUT); 
  digitalWrite(22, HIGH);     

  display_wifi_status();
  // initialize serial for WizFi360 module
  Serial2.setFIFOSize(4096);
  Serial2.begin(2000000);
  WiFi.init(&Serial2);  
  // check for the presence of the shield
  if (WiFi.status() == WL_NO_SHIELD) {
    while (true);// don't continue
  }  
  // attempt to connect to WiFi network
  while ( status != WL_CONNECTED) {
    status = WiFi.begin(ssid, pass);// Connect to WPA/WPA2 network
  }
  display_wifi_status();
  
  // print your WiFi shield's IP address
  ip = WiFi.localIP();
  
  display_dashboard();
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  currentState = link_football_server;
}

void loop(){
  switch(currentState){
    case link_football_server:
       {
        // if you get a connection, report back via serial
        if (client.connectSSL(football_server,443)) {
          Serial.println("Connected to server");
          // Make a HTTP request
          client.println(String("GET /v4/matches?date=TODAY HTTP/1.1"));
          client.println(String("Host:") + String(football_server));
          client.println(String("X-Auth-Token:") + String(football_token));
          client.println("Connection: close");
          client.println();
          data_now = 0;
        }
        currentState = get_football_data;
       }
      break;
      
    case get_football_data:
       {
          while (client.available()) {
            json_String += (char)client.read();
            data_now =1;            
          }
          if(data_now)
          {
            //Serial.println(json_String);            
            dataStart = json_String.indexOf("en-US") + strlen("en-US")+4;
            dataEnd = json_String.indexOf("\r\n", dataStart); 
            dataStr = json_String.substring(dataStart, dataEnd);
            football_api_len = HexStr2Int(dataStr);
            
            json_String = json_String.substring(dataEnd+2, json_String.length());

            uint16_t football_api_cnt;
            football_api_cnt = football_api_len - json_String.length();
            
            while(football_api_cnt>0)
            {
              while(client.available()){
                json_String += (char)client.read();
                football_api_cnt--;
              }
                if(football_api_cnt != 0)
                {
                  dataEnd = json_String.lastIndexOf("\r\n")- strlen("\r\n"); 
                  dataStart = json_String.indexOf("\r\n", dataEnd-10)+ strlen("\r\n"); 
                  dataStr = json_String.substring(dataStart, dataEnd);
                  if(HexStr2Int(dataStr) == 0)
                  {
                    football_api_cnt = 0;
                  }
                }
            }            
            //Serial.println(json_String);
            dataEnd = json_String.indexOf("utcDate");

            for(int i =0; i<4;i++)
            {
              dataStart = json_String.indexOf("utcDate",dataEnd) + strlen("utcDate")+3;
              dataEnd = json_String.indexOf("\",", dataStart);
              football_match_day[i] = json_String.substring(dataStart+8, dataStart+10);
              match_time_hour = json_String.substring(dataStart+11, dataStart+13);
              match_time_minute = json_String.substring(dataStart+14, dataStart+16);
              if((match_time_hour>="16"))
              {
                if(football_match_day[i].toInt()+1 < 10)
                {
                  football_match_day[i] = (String("2022-12-0") + (String)(football_match_day[i].toInt()+1));
                }
                else
                {
                  football_match_day[i] = (String("2022-12-") + (String)(football_match_day[i].toInt()+1));
                }
                
                football_match_time[i] = ("0"+String(match_time_hour.toInt()-16) + ":"  + (String)match_time_minute);
              }
              else
              {
                if(football_match_day[i].toInt() < 10)
                {
                  football_match_day[i] = (String("2022-12-0") + (String)(football_match_day[i].toInt()));
                }
                else
                {
                  football_match_day[i] = (String("2022-12-") + (String)(football_match_day[i].toInt()));
                }
                if(match_time_hour.toInt()+8 > 10 )
                {
                  football_match_time[i] = (String(match_time_hour.toInt()+8) + ":" + (String)match_time_minute);  
                }
                else
                {
                  football_match_time[i] = ("0"+String(match_time_hour.toInt()+8) + ":" + (String)match_time_minute);  
                }
              }
              Serial.print("football_match_time");
              Serial.println(i);
              Serial.println(football_match_day[i]);
              Serial.println(football_match_time[i]);
              dataStart = json_String.indexOf("name", dataEnd)+ strlen("name")+3;
              dataEnd = json_String.indexOf("\",", dataStart);
              football_match_homeTeam[i]= json_String.substring(dataStart, dataEnd);
              Serial.print("football_match_homeTeam");
              Serial.println(i);
              Serial.println(football_match_homeTeam[i]);
              dataStart = json_String.indexOf("name", dataEnd)+ strlen("name")+3;
              dataEnd = json_String.indexOf("\",", dataStart);
              football_match_awayTeam[i]= json_String.substring(dataStart, dataEnd);
              Serial.print("football_match_awayTeam");
              Serial.println(i);
              Serial.println(football_match_awayTeam[i]);   
            } 
            currentState = display_wait_timeout;
            tft->fillRect(0,65,240,100,WHITE);
            client.stop();
        }
      }
      break;
         
    case display_wait_timeout:
       {
          Serial.print("team_num");
          Serial.println(team_num);
          display_match_info(team_num);
          team_num++;
          if(team_num == 4)
          {
            team_num = 0;
          }
          delay(6000);
       }
      break;
  }
}

uint16_t HexStr2Int(String HexStr)
{
  uint16_t ASCIIValue;
  for (int i = 0; i < HexStr.length(); i++) {
    int val = HexStr[i] > 0x39 ? (HexStr[i] - 'a' + 10) : (HexStr[i] - '0');
    ASCIIValue = ASCIIValue << 4;
    ASCIIValue += val; 
  }
  return ASCIIValue;
}
  
void display_wifi_status()
{
  if( status != WL_CONNECTED)
  {
    tft->fillCircle(120,230,3,DARKGREY);
    tft->fillArc(120,230, 5, 7, 225, 315, DARKGREY); 
    tft->fillArc(120,230, 9, 11, 225, 315, DARKGREY); 
    tft->fillArc(120,230, 13, 15, 225, 315, DARKGREY); 
  }
  else
  {
    tft->fillCircle(120,230,3,GREEN);
    tft->fillArc(120,230, 5, 7, 225, 315, GREEN); 
    tft->fillArc(120,230, 9, 11, 225, 315, GREEN); 
    tft->fillArc(120,230, 13, 15, 225, 315, GREEN); 
  }
}

// Function to draw pixels to the display
void PNGDraw(PNGDRAW *pDraw)
{
  uint16_t usPixels[240];
  uint8_t usMask[240];
  png.getLineAsRGB565(pDraw, usPixels, PNG_RGB565_LITTLE_ENDIAN, 0x00000000);
  png.getAlphaMask(pDraw, usMask, 1);
  tft->draw16bitRGBBitmap(image_x, image_y + pDraw->y, usPixels, usMask, pDraw->iWidth, 1);
}

void display_dashboard()
{
    image_x = 93;
    image_y = 10;    
    int rc = png.openFLASH((uint8_t *)WorldCupIcon, sizeof(WorldCupIcon), PNGDraw);
    if (rc == PNG_SUCCESS) {
      char szTemp[256];
      sprintf(szTemp, "image specs: (%d x %d), %d bpp, pixel type: %d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType());
      Serial.print(szTemp);
      rc = png.decode(NULL, 0); // no private structure and skip CRC checking
      png.close();
    } // png opened successfully
    else
    {
      Serial.println("ERROR");
    }
    tft->setTextColor(LIGHTGREY);
    tft->setTextSize(4);
    tft->setCursor(76, 72);
    tft->print("FIFA");
    tft->setTextSize(2);
    tft->setCursor(69, 111);
    tft->print("World Cup");
    tft->setCursor(65, 136);
    tft->print("Qatar 2022");
    tft->setTextSize(3);
    tft->setCursor(52, 162);
    tft->print("Schedule");
    
    tft->setTextColor(DARKGREY);
    tft->setTextSize(4);
    tft->setCursor(74, 70);
    tft->print("FIFA");
    tft->setTextSize(2);
    tft->setCursor(68, 110);
    tft->print("World Cup");
    tft->setCursor(64, 135);
    tft->print("Qatar 2022");
    tft->setTextSize(3);
    tft->setCursor(50, 160);
    tft->print("Schedule");
    tft->drawRoundRect(40,157,160,30,20,DARKGREY);
}

void display_match_info(uint8_t num)
{    
    image_x = 21;
    image_y = 55;
    display_country_icon(football_match_homeTeam[num]);
    tft->fillArc(60,95, 40, 45, 0, 360, LIGHTGREY); 
    tft->fillArc(60,95, 42, 43, 0, 360, DARKGREY); 
    image_x = 141;
    image_y = 55;
    display_country_icon(football_match_awayTeam[num]);  
    tft->fillArc(180,95, 40, 45, 0, 360, LIGHTGREY);
    tft->fillArc(180,95, 42, 43, 0, 360, DARKGREY); 

    tft->setTextColor(LIGHTGREY);
    tft->setTextSize(2);
    tft->setCursor(111, 111);
    tft->print("VS");
    tft->setTextColor(DARKGREY);
    tft->setCursor(109, 109);
    tft->print("VS");
    
    tft->fillRect(0,139,240,70,WHITE);
    tft->setTextColor(DARKGREY);
    tft->setTextSize(2);
    tft->setCursor(55-(football_match_homeTeam[num].length())*5, 145);
    tft->print(football_match_homeTeam[num]);
    tft->setTextColor(DARKGREY);
    tft->setCursor(175-(football_match_awayTeam[num].length())*5, 145);  
    tft->print(football_match_awayTeam[num]);
   
    tft->setTextColor(DARKGREY);
    tft->setTextSize(2);
    tft->setCursor(62, 175);  
    tft->print(football_match_day[num]); 
    tft->setTextSize(2);
    tft->setCursor(91, 195);
    tft->print(football_match_time[num]); 
}

void display_country_icon(String Country)
{
  char szTemp[256];
  int rc;
  if(Country =="Argentina")
  {
    rc = png.openFLASH((uint8_t *)Argentina, sizeof(Argentina), PNGDraw);
  }
  else if(Country =="Australia")
  {
    rc = png.openFLASH((uint8_t *)Australia, sizeof(Australia), PNGDraw);
  }
  else if(Country =="Belgium")
  {
    rc = png.openFLASH((uint8_t *)Belgium, sizeof(Belgium), PNGDraw);
  }
  else if(Country =="Brazil")
  {
    rc = png.openFLASH((uint8_t *)Brazil, sizeof(Brazil), PNGDraw);
  }
  else if(Country =="Cameroon")
  {
    rc = png.openFLASH((uint8_t *)Cameroon, sizeof(Cameroon), PNGDraw);
  }
  else if(Country =="Canada")
  {
    rc = png.openFLASH((uint8_t *)Canada, sizeof(Canada), PNGDraw);
  }
  else if(Country =="Costa Rica")
  {
    rc = png.openFLASH((uint8_t *)Costa_rica, sizeof(Costa_rica), PNGDraw);
  }
  else if(Country =="Croatia")
  {
    rc = png.openFLASH((uint8_t *)Croatia, sizeof(Croatia), PNGDraw);
  }
  else if(Country =="Denmark")
  {
    rc = png.openFLASH((uint8_t *)Denmark, sizeof(Denmark), PNGDraw);
  }
  else if(Country =="Ecuador")
  {
    rc = png.openFLASH((uint8_t *)Ecuador, sizeof(Ecuador), PNGDraw);
  }
  else if(Country =="England")
  {
    rc = png.openFLASH((uint8_t *)England, sizeof(England), PNGDraw);
  }
  else if(Country =="France")
  {
    rc = png.openFLASH((uint8_t *)France, sizeof(France), PNGDraw);
  }
  else if(Country =="Germany")
  {
    rc = png.openFLASH((uint8_t *)Germany, sizeof(Germany), PNGDraw);
  }
  else if(Country =="Ghana")
  {
    rc = png.openFLASH((uint8_t *)Ghana, sizeof(Ghana), PNGDraw);
  }
  else if(Country =="Iran")
  {
    rc = png.openFLASH((uint8_t *)Iran, sizeof(Iran), PNGDraw);
  }
  else if(Country =="Japan")
  {
    rc = png.openFLASH((uint8_t *)Japan, sizeof(Japan), PNGDraw);
  }
  else if(Country =="Mexico")
  {
    rc = png.openFLASH((uint8_t *)Mexico, sizeof(Mexico), PNGDraw);
  }
  else if(Country =="Morocco")
  {
    rc = png.openFLASH((uint8_t *)Morocco, sizeof(Morocco), PNGDraw);
  }
  else if(Country =="Netherlands")
  {
    rc = png.openFLASH((uint8_t *)Netherlands, sizeof(Netherlands), PNGDraw);
  }
  else if(Country =="Poland")
  {
    rc = png.openFLASH((uint8_t *)Poland, sizeof(Poland), PNGDraw);
  }
  else if(Country =="Portugal")
  {
    rc = png.openFLASH((uint8_t *)Portugal, sizeof(Portugal), PNGDraw);
  }
  else if(Country =="Qatar")
  {
    rc = png.openFLASH((uint8_t *)Qatar, sizeof(Qatar), PNGDraw);
  }
  else if(Country =="Saudi Arabia")
  {
    rc = png.openFLASH((uint8_t *)Saudi_arabia, sizeof(Saudi_arabia), PNGDraw);
  }
  else if(Country =="Senegal")
  {
    rc = png.openFLASH((uint8_t *)Senegal, sizeof(Senegal), PNGDraw);
  }
  else if(Country =="Serbia")
  {
    rc = png.openFLASH((uint8_t *)Serbia, sizeof(Serbia), PNGDraw);
  }
  else if(Country =="South Korea")
  {
    rc = png.openFLASH((uint8_t *)South_korea, sizeof(South_korea), PNGDraw);
  }
  else if(Country =="Spain")
  {
    rc = png.openFLASH((uint8_t *)Spain, sizeof(Spain), PNGDraw);
  }
  else if(Country =="Switzerland")
  {
    rc = png.openFLASH((uint8_t *)Switzerland, sizeof(Switzerland), PNGDraw);
  }
  else if(Country =="Tunisia")
  {
    rc = png.openFLASH((uint8_t *)Tunisia, sizeof(Tunisia), PNGDraw);
  }
  else if(Country =="United States")
  {
    rc = png.openFLASH((uint8_t *)United_states, sizeof(United_states), PNGDraw);
  }
  else if(Country =="Uruguay")
  {
    rc = png.openFLASH((uint8_t *)Uruguay, sizeof(Uruguay), PNGDraw);
  }
  else if(Country =="Wales")
  {
    rc = png.openFLASH((uint8_t *)Wales, sizeof(Wales), PNGDraw);
  }
    if (rc == PNG_SUCCESS) {      
    sprintf(szTemp, "image specs: (%d x %d), %d bpp, pixel type: %d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType());
    Serial.print(szTemp);
    rc = png.decode(NULL, 0); // no private structure and skip CRC checking
    png.close();
    } // png opened successfully
    else
    {
      Serial.println("ERROR");
    }
}

Credits

Gavin

Gavin

22 projects • 17 followers
Make it Funny.

Comments