nopnop2002 / esp-idf-ili9340

SPI TFT and XPT2046 touch screen controller driver for esp-idf
MIT License
163 stars 34 forks source link

not able to show icons on the display. #46

Closed newone-hub closed 5 months ago

newone-hub commented 5 months ago

Hello, i am using esp32-s2 and interface ili9341. If i run the whole main file, then there is not output on the display. But if i run some commands from the function like from fill rectangle it will show output. Now i want to display icon on the display. Can you tell which arguments i have to pass the function so that it will shoe icon image on display.

nopnop2002 commented 5 months ago

Files with the ico extension cannot be drawn.

You need to convert the image file to PNG or JPEG format using something like ImageMagick.

JPEG display and PNG display are included in the sample project I provide. https://github.com/nopnop2002/esp-idf-ili9340/blob/master/main/main.c#L848 https://github.com/nopnop2002/esp-idf-ili9340/blob/master/main/main.c#L922

However, it is not possible to display the image at any arbitrary position. Always display the image in the center of the screen. Since ESP32S2 has small RAM, there is a possibility that JPEG cannot be displayed due to insufficient memory.

To display an image in any position, you need to convert the image to BMP format using something like ImageMagick, and then resize the converted image to a smaller size. It is necessary to develop a new function to display the resized image file in any position. Based on the BMP display sample that I provide, you can develop a new function that displays BMP images in any position. https://github.com/nopnop2002/esp-idf-ili9340/blob/master/main/main.c#L695

Displaying images is difficult, so you need to have a thorough understanding of image files. Additionally, you need to understand the relationship between the number of pixels in the image file and the number of pixels on the screen.

newone-hub commented 5 months ago

WhatsApp Image 2024-03-21 at 11 57 12_ca4d39b6 1

See i have just run the function of BMP test, the function is calling again and again but there is no output on the display.

nopnop2002 commented 5 months ago

I would like to know the version of IDF you are using.

You can check it with the command below.

$ idf.py --version
ESP-IDF v5.1.2-695-gd922d4178f-dirty

I would like to know all your logging print.

nopnop2002 commented 5 months ago

Added png icon display example. You can display the PNG icon wherever you like.

https://github.com/nopnop2002/esp-idf-ili9340/blob/master/main/main.c#L2233

IMG_5124 IMG_5123

newone-hub commented 5 months ago

image

nopnop2002 commented 5 months ago

No such version exists.

The current stable version is below. https://github.com/espressif/esp-idf/releases

newone-hub commented 5 months ago

now i have to do to solve my problem?

nopnop2002 commented 5 months ago

Installation of the stable version of ESP-IDF.

https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/

newone-hub commented 5 months ago

Thank you @nopnop2002 , now the icon is displaying on the LCD. I am also facing another issue that if i write something on the LCD and then write an other line on the same postion. It will not remove the previous data, and rewrite on the previous data. Can you tell me how can i update the LCD and write the new line on same postion. WhatsApp Image 2024-03-26 at 15 06 12_f3de9920

nopnop2002 commented 5 months ago
    lcdFillScreen(dev, WHITE);
    strcpy((char *)ascii, "ABCD");
    lcdDrawString(dev, fx, 0, 0, ascii, BLACK);
    sleep(10);
    lcdDrawString(dev, fx, 0, 0, ascii, WHITE);
    strcpy((char *)ascii, "abcd");
    lcdDrawString(dev, fx, 0, 0, ascii, BLACK);
newone-hub commented 5 months ago

Thank you @nopnop2002 . I really appreciate your effort and soory for asking to much queries. I am the new one in the embedded system field. So i am facing lot of issues.

newone-hub commented 5 months ago

Now the issue i am facing is that i have to display the fingerprint icon and time at the same time. But when i run the code it just show the time and then wait and again refresh the screen. 12 WhatsApp Image 2024-03-27 at 13 08 50_20f0b7ad

newone-hub commented 5 months ago

if i comment the code portion of time from the app main function then just fingerprint icon is displayed on the LCD image

nopnop2002 commented 5 months ago

I can't figure out what the problem is just by looking at some of the code.

You can share your project using your github account.

newone-hub commented 5 months ago

I have uploaded the code on my github account.

nopnop2002 commented 5 months ago

The date and time obtained with Get_current_date_time() is 24 characters. Therefore, an buffer of at least 25 bytes is required. strcpy adds NULL to the end of buffer.

I (58073) wifi station: The current date/time is: [Thu Mar 28 16:18:47 2024]
I (58073) wifi station: strlen(strftime_buf)=24
        //uint8_t ascii[24];
        uint8_t ascii[25];
        Get_current_date_time(Current_Date_Time);

IMG_5126


I have found that there is no problem with this library, so I will close it.

newone-hub commented 5 months ago

Sir just tell me what changes you have made to get the output. I have increased the size of buffer but i am still facing the issue.

nopnop2002 commented 5 months ago

You need to change this.

define EXAMPLE_ESP_WIFI_SSID "xxxxxxxxxxxxxxx"

define EXAMPLE_ESP_WIFI_PASS "xxxxxxxxxxxxxxx"

#include <stdio.h>
#include <inttypes.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include "esp_attr.h"
#include "esp_sleep.h"
#include "esp_sntp.h"
#include <string.h>
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "lwip/err.h"
#include "lwip/sys.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "esp_vfs.h"
#include "esp_spiffs.h"

#include "ili9340.h"
#include "fontx.h"
#include "bmpfile.h"
#include "decode_jpeg.h"
#include "decode_png.h"
#include "pngle.h"

#include "driver/gpio.h"

#define INTERVAL 400
#define WAIT vTaskDelay(INTERVAL)

static const char *TAG = "MAIN";

// You have to set these CONFIG value using menuconfig.
#define CONFIG_WIDTH    240
#define CONFIG_HEIGHT 320

#define EXAMPLE_ESP_WIFI_SSID      "xxxxxxxxxxxxxxx"
#define EXAMPLE_ESP_WIFI_PASS      "xxxxxxxxxxxxxxx"

static EventGroupHandle_t s_wifi_event_group;

/* The event group allows multiple bits for each event, but we only care about two events:
 * - we are connected to the AP with an IP
 * - we failed to connect after the maximum amount of retries */
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT      BIT1
static const char *TAG1 = "wifi station";

char Current_Date_Time[100];

void time_sync_notification_cb(struct timeval *tv)
{
    ESP_LOGI(TAG1, "Notification of a time synchronization event");
}
static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
    {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
    {
       // if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY)
        //{
            esp_wifi_connect();
           // s_retry_num++;
            ESP_LOGI(TAG1, "retry to connect to the AP");
        //} else {
        //    xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
        ESP_LOGI(TAG1,"connect to the AP fail");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
        ESP_LOGI(TAG1, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
        //s_retry_num = 0;
        xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
    }
}

void wifi_init_sta(void)
{
    s_wifi_event_group = xEventGroupCreate();

    ESP_ERROR_CHECK(esp_netif_init());

    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_create_default_wifi_sta();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                                                        ESP_EVENT_ANY_ID,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_any_id));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT,
                                                        IP_EVENT_STA_GOT_IP,
                                                        &event_handler,
                                                        NULL,
                                                        &instance_got_ip));

    ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
                    WIFI_EVENT_STA_DISCONNECTED,
                    &event_handler,
                    NULL,
                    NULL));

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_ESP_WIFI_SSID,
            .password = EXAMPLE_ESP_WIFI_PASS,
            /* Setting a password implies station will connect to all security modes including WEP/WPA.
             * However these modes are deprecated and not advisable to be used. Incase your Access point
             * doesn't support WPA2, these mode can be enabled by commenting below line */
         .threshold.authmode = WIFI_AUTH_WPA2_PSK,

            .pmf_cfg = {
                .capable = true,
                .required = false
            },
        },
    };
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
    ESP_ERROR_CHECK(esp_wifi_start() );

    ESP_LOGI(TAG1, "wifi_init_sta finished.");

    /* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
     * number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
    EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
            WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
            pdFALSE,
            pdFALSE,
            portMAX_DELAY);

    /* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
     * happened. */
    if (bits & WIFI_CONNECTED_BIT) {
        ESP_LOGI(TAG1, "connected to ap SSID:%s password:%s",
                 EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
    } else if (bits & WIFI_FAIL_BIT) {
        ESP_LOGI(TAG1, "Failed to connect to SSID:%s, password:%s",
                 EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS);
    } else {
        ESP_LOGE(TAG1, "UNEXPECTED EVENT");
    }

    /* The event will not be processed after unregister */
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, instance_got_ip));
    ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, instance_any_id));
    vEventGroupDelete(s_wifi_event_group);
}

void Get_current_date_time(char *date_time){
    char strftime_buf[64];
    time_t now;
        struct tm timeinfo;
        time(&now);
        localtime_r(&now, &timeinfo);

                setenv("TZ", "UTC-05:00", 1);
                tzset();
                localtime_r(&now, &timeinfo);

                strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
                ESP_LOGI(TAG1, "The current date/time is: [%s]", strftime_buf);
                ESP_LOGI(TAG1, "strlen(strftime_buf)=%d", strlen(strftime_buf));
                strcpy(date_time,strftime_buf);
}

static void initialize_sntp(void)
{
    ESP_LOGI(TAG1, "Initializing SNTP");
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, "pool.ntp.org");
    sntp_set_time_sync_notification_cb(time_sync_notification_cb);
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH
    sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH);
#endif
    sntp_init();
}
static void obtain_time(void)
{

    initialize_sntp();
    // wait for time to be set
    time_t now = 0;
    struct tm timeinfo = { 0 };
    int retry = 0;
    const int retry_count = 10;
    while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) {
        ESP_LOGI(TAG1, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
        vTaskDelay(2000 / portTICK_PERIOD_MS);
    }
    time(&now);
    localtime_r(&now, &timeinfo);
}
 void Set_SystemTime_SNTP()  {

     time_t now;
        struct tm timeinfo;
        time(&now);
        localtime_r(&now, &timeinfo);
        // Is time set? If not, tm_year will be (1970 - 1900).
        if (timeinfo.tm_year < (2016 - 1900)) {
            ESP_LOGI(TAG1, "Time is not set yet. Connecting to WiFi and getting time over NTP.");
            obtain_time();
            // update 'now' variable with current time
            time(&now);
        }
}
/********************************************************************************************************************************/
void ShowPngImage(TFT_t * dev, char * file, int width, int height, int xpos, int ypos) {
    // open PNG file
    FILE* fp = fopen(file, "rb");
    if (fp == NULL) {
        ESP_LOGW(__FUNCTION__, "File not found [%s]", file);
        return;
    }

    char buf[1024];
    size_t remain = 0;
    int len;

    int _width = width;
    if (width > 240) _width = 240;
    int _height = height;
    if (height > 320) _height = 320;
    pngle_t *pngle = pngle_new(_width, _height);

    pngle_set_init_callback(pngle, png_init);
    pngle_set_draw_callback(pngle, png_draw);
    pngle_set_done_callback(pngle, png_finish);

    double display_gamma = 2.2;
    pngle_set_display_gamma(pngle, display_gamma);

    while (!feof(fp)) {
        if (remain >= sizeof(buf)) {
            ESP_LOGE(__FUNCTION__, "Buffer exceeded");
            while(1) vTaskDelay(1);
        }

        len = fread(buf + remain, 1, sizeof(buf) - remain, fp);
        if (len <= 0) {
            //printf("EOF\n");
            break;
        }

        int fed = pngle_feed(pngle, buf, remain + len);
        if (fed < 0) {
            ESP_LOGE(__FUNCTION__, "ERROR; %s", pngle_error(pngle));
            while(1) vTaskDelay(1);
        }

        remain = remain + len - fed;
        if (remain > 0) memmove(buf, buf + fed, remain);
    }

    fclose(fp);

    uint16_t pngWidth = pngle_get_width(pngle);
    uint16_t pngHeight = pngle_get_height(pngle);
    ESP_LOGD(__FUNCTION__, "pngWidth=%d pngHeight=%d", pngWidth, pngHeight);
    int _xpos = xpos - (pngHeight/2);
    int _ypos = ypos - (pngWidth/2);
    ESP_LOGD(__FUNCTION__, "xpos=%d ypos=%d _xpos=%d _ypos=%d", xpos, ypos, _xpos, _ypos);
    uint16_t *colors = (uint16_t*)malloc(sizeof(uint16_t) * pngWidth);
    if (colors == NULL) {
        ESP_LOGE(__FUNCTION__, "malloc fail");
        pngle_destroy(pngle, _width, _height);
        return;
    }

    for(int y = 0; y < pngHeight; y++){
        for(int x = 0;x < pngWidth; x++){
            //pixel_png pixel = pngle->pixels[y][x];
            //colors[x] = rgb565(pixel.red, pixel.green, pixel.blue);
            colors[x] = pngle->pixels[y][x];
        }
        lcdDrawMultiPixels(dev, _xpos, y+_ypos, pngWidth, colors);
        vTaskDelay(1);
    }
    free(colors);
    pngle_destroy(pngle, _width, _height);
    return;
}

void ILI9341(void *pvParameters)
{
    // set font file
    FontxFile fx16G[2];
    FontxFile fx24G[2];
    FontxFile fx32G[2];
    FontxFile fx32L[2];
    InitFontx(fx16G,"/spiffs/ILGH16XB.FNT",""); // 8x16Dot Gothic
    InitFontx(fx24G,"/spiffs/ILGH24XB.FNT",""); // 12x24Dot Gothic
    InitFontx(fx32G,"/spiffs/ILGH32XB.FNT",""); // 16x32Dot Gothic
    InitFontx(fx32L,"/spiffs/LATIN32B.FNT",""); // 16x32Dot Latinc

    FontxFile fx16M[2];
    FontxFile fx24M[2];
    FontxFile fx32M[2];
    InitFontx(fx16M,"/spiffs/ILMH16XB.FNT",""); // 8x16Dot Mincyo
    InitFontx(fx24M,"/spiffs/ILMH24XB.FNT",""); // 12x24Dot Mincyo
    InitFontx(fx32M,"/spiffs/ILMH32XB.FNT",""); // 16x32Dot Mincyo

    TFT_t dev;
    #if CONFIG_XPT2046_ENABLE_SAME_BUS
    ESP_LOGI(TAG, "Enable Touch Contoller using the same SPI bus as TFT");
    int XPT_MISO_GPIO = CONFIG_XPT_MISO_GPIO;
    int XPT_CS_GPIO = CONFIG_XPT_CS_GPIO;
    int XPT_IRQ_GPIO = CONFIG_XPT_IRQ_GPIO;
    int XPT_SCLK_GPIO = -1;
    int XPT_MOSI_GPIO = -1;
#elif CONFIG_XPT2046_ENABLE_DIFF_BUS
    ESP_LOGI(TAG, "Enable Touch Contoller using the different SPI bus from TFT");
    int XPT_MISO_GPIO = CONFIG_XPT_MISO_GPIO;
    int XPT_CS_GPIO = CONFIG_XPT_CS_GPIO;
    int XPT_IRQ_GPIO = CONFIG_XPT_IRQ_GPIO;
    int XPT_SCLK_GPIO = CONFIG_XPT_SCLK_GPIO;
    int XPT_MOSI_GPIO = CONFIG_XPT_MOSI_GPIO;
#else
    ESP_LOGI(TAG, "Disable Touch Contoller");
    int XPT_MISO_GPIO = -1;
    int XPT_CS_GPIO = -1;
    int XPT_IRQ_GPIO = -1;
    int XPT_SCLK_GPIO = -1;
    int XPT_MOSI_GPIO = -1;
#endif
    spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_TFT_CS_GPIO, CONFIG_DC_GPIO, 
    CONFIG_RESET_GPIO, CONFIG_BL_GPIO, XPT_MISO_GPIO, XPT_CS_GPIO, XPT_IRQ_GPIO, XPT_SCLK_GPIO, XPT_MOSI_GPIO);
    #if CONFIG_ILI9225
    uint16_t model = 0x9225;
#endif
#if CONFIG_ILI9225G
    uint16_t model = 0x9226;
#endif
#if CONFIG_ILI9340
    uint16_t model = 0x9340;
#endif
#if CONFIG_ILI9341
    uint16_t model = 0x9341;
#endif
#if CONFIG_ST7735
    uint16_t model = 0x7735;
#endif
#if CONFIG_ST7796
    uint16_t model = 0x7796;
#endif
    lcdInit(&dev, model, CONFIG_WIDTH, CONFIG_HEIGHT, CONFIG_OFFSETX, CONFIG_OFFSETY);
    lcdSetFontDirection(&dev, DIRECTION90);
    lcdFillScreen(&dev, WHITE);
    while(1) {

        //uint8_t ascii[24];
        uint8_t ascii[25];
        Get_current_date_time(Current_Date_Time);
        strcpy((char *)ascii, Current_Date_Time);
        lcdSetFontFill(&dev,WHITE);
        lcdDrawString(&dev, fx24G, 210,20, ascii, BLACK);
        vTaskDelay(110);
        char file[32];
        strcpy(file, "/icons/fingerprint.png");
        ShowPngImage(&dev, file, CONFIG_WIDTH, CONFIG_HEIGHT, CONFIG_WIDTH/2, CONFIG_HEIGHT/2);

    } // end while

    // never reach here
    vTaskDelete(NULL);
}

static void listSPIFFS(char * path) {
    DIR* dir = opendir(path);
    assert(dir != NULL);
    while (true) {
        struct dirent*pe = readdir(dir);
        if (!pe) break;
        ESP_LOGI(__FUNCTION__,"d_name=%s d_ino=%d d_type=%x", pe->d_name,pe->d_ino, pe->d_type);
    }
    closedir(dir);
}

esp_err_t mountSPIFFS(char * path, char * label, int max_files) {
    esp_vfs_spiffs_conf_t conf = {
        .base_path = path,
        .partition_label = label,
        .max_files = max_files,
        .format_if_mount_failed =true
    };

    // Use settings defined above toinitialize and mount SPIFFS filesystem.
    // Note: esp_vfs_spiffs_register is anall-in-one convenience function.
    esp_err_t ret = esp_vfs_spiffs_register(&conf);

    if (ret != ESP_OK) {
        if (ret ==ESP_FAIL) {
            ESP_LOGE(TAG, "Failed to mount or format filesystem");
        } else if (ret== ESP_ERR_NOT_FOUND) {
            ESP_LOGE(TAG, "Failed to find SPIFFS partition");
        } else {
            ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)",esp_err_to_name(ret));
        }
        return ret;
    }

#if 0
    ESP_LOGI(TAG, "Performing SPIFFS_check().");
    ret = esp_spiffs_check(conf.partition_label);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "SPIFFS_check() failed (%s)", esp_err_to_name(ret));
        return ret;
    } else {
            ESP_LOGI(TAG, "SPIFFS_check() successful");
    }
#endif

    size_t total = 0, used = 0;
    ret = esp_spiffs_info(conf.partition_label, &total, &used);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG,"Failed to get SPIFFS partition information (%s)",esp_err_to_name(ret));
    } else {
        ESP_LOGI(TAG,"Mount %s to %s success", path, label);
        ESP_LOGI(TAG,"Partition size: total: %d, used: %d", total, used);
    }

    return ret;
}

void app_main(void)
{
    esp_err_t ret1 = nvs_flash_init();
    if (ret1 == ESP_ERR_NVS_NO_FREE_PAGES || ret1 == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret1 = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret1);

    ESP_LOGI(TAG1, "ESP_WIFI_MODE_STA");
    wifi_init_sta();

    Set_SystemTime_SNTP();
/**************************************************************************************************************/
    // Initialize NVS
    ESP_LOGI(TAG, "Initialize NVS");
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        // NVS partition was truncated and needs to be erased
        // Retry nvs_flash_init
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    ESP_ERROR_CHECK( err );

    ESP_LOGI(TAG, "Initializing SPIFFS");
    esp_err_t ret;
    ret = mountSPIFFS("/spiffs", "storage0", 10);
    if (ret != ESP_OK) return;
    listSPIFFS("/spiffs/");

    // Image file borrowed from here
    // https://www.flaticon.com/packs/social-media-343
    ret = mountSPIFFS("/icons", "storage1", 10);
    if (ret != ESP_OK) return;
    listSPIFFS("/icons/");

    ret = mountSPIFFS("/images", "storage2", 14);
    if (ret != ESP_OK) return;
    listSPIFFS("/images/");

    xTaskCreate(ILI9341, "ILI9341", 1024*6, NULL, 2, NULL);
}
newone-hub commented 5 months ago

I run that code but i am not getting the output

nopnop2002 commented 5 months ago

Narrow down the bad code by commenting out parts of the code.