Display often draws nonsense data

Hello,

I'm currently facing issue with drawing data on display. Mostly it works perfectly, but often is drawing nonsense / wrong text data.
I would be happy, if someone could take a look and advise.

I'm using this controller

and this display

Display library used: GxEPD2_750_T7
GxEPD2_BW<GxEPD2_750_T7, GxEPD2_750_T7::HEIGHT> display(GxEPD2_750_T7(/CS=5/ SS, /DC=/17, /RST=/16, /BUSY=/4));

I've written following method to draw meeting data on display. Please bear in mind it is not fully completed yet.

void displayMeetings()
{  
  String currentDateTime = getCurrentDateTime(); //format: "2024-07-11T11:30:00"
  String startUtc = getCurrentDateTimeUTC();
  String startTime = getStartTimeUTC(); //startUtc.substring(0,13) + ":00:01Z";
  String end = currentDateTime.substring(0, 10) + "T23:59:59Z";  

  String token = getAccessToken();
  MeetingsData meetingData = getMeetings(token, startTime, end); 

  Meeting *meetings = meetingData.meetings;
  int numMeetings = meetingData.numMeetings;  

  display.setRotation(0);
  display.setTextColor(GxEPD_BLACK);
  
  // Display if the room is occupied or available
  display.setPartialWindow(150, 130, 400, 60);
  display.firstPage();
  do {
    display.fillRect(150, 130, 400, 60, GxEPD_WHITE);  // Clear the area
    display.setFont(&FreeSansBold18pt8b);        
    
    bool isMeetingInProgress = false;
    String endTimeOfCurrentMeeting = "";
    int t = 0;

    for (int i = 0; i < numMeetings; i++) {
      if (currentDateTime >= meetings[i].startTime && currentDateTime <= meetings[i].endTime) {
        isMeetingInProgress = true;        
        endTimeOfCurrentMeeting = format_time_cet(meetings[i].endTime);
        t = i;
        break;
      }
    }   
    
    if (isMeetingInProgress) {
      display.setCursor(160, 180);  
      display.print(occupiedTill + endTimeOfCurrentMeeting);
    }     
    else if(numMeetings > 0) { 
      if(currentDateTime < meetings[t].startTime){
        display.setCursor(160, 180);  
        String result = format_time_cet(meetings[t].startTime);
        display.print(availableTill + result);
      }   
      else if(currentDateTime > meetings[t].endTime){
        display.setCursor(160, 180);  
        String result = format_time_cet(meetings[t].endTime);
        display.print(availableFrom + result);
      }
    }
    else if (numMeetings == 0) {
      display.setCursor(250, 180);
      display.print(available);
    }
  } while (display.nextPage());

  if(numMeetings > 0){  
    // Display the next meeting details
    display.setPartialWindow(10, 230, 780, 165);
    display.firstPage();
    do{
      int maxEvents = (numMeetings > 2) ? 2 : numMeetings;
      display.setTextWrap(true);
      display.setFont(&FreeSansBold15pt8b);
      int yPos = 260;
      display.setCursor(10, yPos);
          
      String start = format_time_cet(meetings[0].startTime); 
      String end = format_time_cet(meetings[0].endTime);
      display.print(start + " - " + end);
          
      display.setCursor(10, 300);        
      String name = ConvertToISO(meetings[0].name);
      display.print(name);

      display.setCursor(10, 340); 
      String organizer = ConvertToISO(meetings[0].organizer);              
      display.print(organizer);
    } while (display.nextPage());

    // Display time slots
    int squareSize = 60;
    int totalSquares = 12;
    int partialWindowWidth = 780;
    int spacing = (partialWindowWidth - (totalSquares * squareSize)) / (totalSquares - 1);

    display.setPartialWindow(10, 400, 780, squareSize + 15);
    display.firstPage();
    do {
      for (int i = 0; i < totalSquares; i++) {
        int slotX = 10 + i * (squareSize + spacing);  
        int slotY = 410;  
        display.drawRect(slotX, slotY, squareSize, squareSize, GxEPD_BLACK); 

        String timeSlot = String(7 + i) + ":00 ";
        int16_t x1, y1;
        uint16_t w, h;
        display.setFont(&FreeSans9pt8b);
        display.getTextBounds(timeSlot, 0, 0, &x1, &y1, &w, &h);
        
        int centeredX = slotX + (squareSize - w) / 2;
        int centeredY = slotY + (squareSize + h) / 2;

        display.setCursor(centeredX, centeredY);
        display.print(timeSlot);

        for (int j = 0; j < numMeetings; j++) {
          int startHour = String(format_time_cet(meetings[j].startTime)).substring(0, 2).toInt();
          int startMinute = String(format_time_cet(meetings[j].startTime)).substring(3, 5).toInt();
          int endHour = String(format_time_cet(meetings[j].endTime)).substring(0, 2).toInt();
          int endMinute = String(format_time_cet(meetings[j].endTime)).substring(3, 5).toInt();
          int currentHour = 7 + i;

          int duration = (endHour * 60 + endMinute) - (startHour * 60 + startMinute);
          Serial.println(duration);
          
        if (duration % 30 == 0) {
          if ((startHour < currentHour || (startHour == currentHour && startMinute == 0)) &&
              (endHour > currentHour || (endHour == currentHour && endMinute > 0))) {
            display.fillRect(slotX + 1, slotY + 1, squareSize - 2, squareSize - 2, GxEPD_BLACK);
            display.setTextColor(GxEPD_WHITE);
            display.setCursor(centeredX, centeredY);
            display.print(timeSlot);
            display.setTextColor(GxEPD_BLACK);
            }
          }
        }
      }
    } while (display.nextPage());
  }
}

Data which I'm drawing is being converted to 8bit GFX fonts (ISO-8859-2, used for Czech diacritics)

More details here:

https://www.sigmdel.ca/michel/program/misc/gfxfont_8bit_en.html

Here is the function which converts the font data.

String ConvertToISO(const char *input)
{
  char text[255];
  strcpy(text, input);
  utf8tocp(text);
  return text;
}

I'm also attaching image of faulty data showed on display. Please note some sections with company sensitive data are intentionally erased (section after Meeting room text and QR code for reservations in the top right corner).

EDIT:
After performing some Serial prints, I've found out the problem is probably not in the font converter as it prints wrong data even before conversion.

Attaching also the method to fetch data from Graph API. I believe the problem is somewhere here

MeetingsData getMeetings(String token, String startTime, String endTime)
{
  String payload = "";
  String url = "https://graph.microsoft.com/v1.0/users/" + userId + "/calendarView?startDateTime=" + startTime + "&endDateTime=" + endTime;
  http.begin(url);
  http.addHeader("Authorization", "Bearer " + token);
  http.addHeader("Prefer", "outlook.timezone=\"Central European Standard Time\"");

  int httpResponseCode = http.GET();
  if (httpResponseCode > 0)
  {
    if (httpResponseCode == HTTP_CODE_OK)
    {
      payload = http.getString();
      //Serial.println(payload);   
      JsonDocument doc;
      deserializeJson(doc, payload);
      
      JsonArray events = doc["value"];
      Serial.print("Meeting count:");
      Serial.println(events.size());
      
      if (events.size() == 0)
      {        
        http.end();
        return { nullptr, 0 };
      }
     
      int meetingCount = events.size();    
      Meeting *meetings = new Meeting[meetingCount]; 

      for (int i = 0; i < events.size(); ++i)
      {
        JsonObject event = events[i];
        const char* subject = event["subject"];
        const char* organizer = event["organizer"]["emailAddress"]["name"];
        const char* startTime = event["start"]["dateTime"];
        const char* endTime = event["end"]["dateTime"];      

        meetings[i].name = subject;
        meetings[i].organizer = organizer;
        meetings[i].startTime = startTime;
        meetings[i].endTime = endTime;
      }      
      http.end();
      return { meetings, meetingCount };
    }
    else
    {
      Serial.printf("[HTTP] GET... code: %d\n", httpResponseCode);
    }
  }
  else
  {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpResponseCode).c_str());
  }
  
  http.end();
  return { nullptr, 0 };
} 

Here is definition for MeetingsData:

#ifndef MEETING_H
#define MEETING_H
#include <string.h>

class Meeting {
public:
    const char* name;
    const char* organizer;
    const char* startTime;
    const char* endTime;
};

#endif

and

#ifndef MEETINGDATA_H
#define MEETINGDATA_H
#include <string.h>
#include "meeting.h"

class MeetingsData {
public:
    Meeting* meetings;
    int numMeetings;  
};

#endif

Therefore we can't know what is correct and what is wrong. Some explanation needed.

If anyone would like to reproduce it, he would need the complete code.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.