cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G431CBU: section `.bss' will not fit in region `RAM'

ValterMatos
Associate II

 

Good morning.
Could anyone tell me about this error and how to resolve it.
C:/ST/STM32CubeIDE_1.19.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.13.3 .rel1.win32_1.0.0.202411081344/tools/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld.exe: Oscillo_STM32G431CBU.elf section `.bss' will not fit in region `RAM'
C:/ST/STM32CubeIDE_1.19.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.13.3 .rel1.win32_1.0.0.202411081344/tools/bin/../lib/gcc/arm-none-eabi/13.3.1/../../../../arm-none-eabi/bin/ld.exe: region `RAM' overflowed by 54928 bytes
I'm using IDE 1.19 to compile the code for a G431CBU
Grateful

Valter Matos

58 REPLIES 58

I checked the .map 

 .bss.image_buffer
                0x200000b4    0x12c00 ./Core/Src/ILI9488.o

is 76.800 decimal, no way.

hth

KnarfB


@Andrew Neil wrote:

@ValterMatos wrote:

/* Memories definition */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
}

You've defined the 'RAM' region to be only 32K ?


 

That part only has 32K of ram. 

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.
CAN Jammer an open source CAN bus hacking tool
CANableV3 Open Source


@ValterMatos wrote:
/*
 * sprites.c
 *
 *  Created on: 3 maj 2024
 *      Author: Dominik
 */

#include "sprites.h"
#include "ILI9488.h"



const uint8_t trigRisingIcon[15][9] = {
    {0     , 0     , 0     , 0     , WHITE , WHITE , WHITE , WHITE , WHITE},
    {0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     },
    {0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     },
    {0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     },
    {0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     },
    {0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     },
    {0     , 0     , 0     , WHITE , WHITE , WHITE , 0     , 0     , 0     },
    {0     , 0     , WHITE , WHITE , WHITE , WHITE , WHITE , 0     , 0     },
    {0     , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , 0     },
    {0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     },
    {0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     },
    {0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     },
    {0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     },
    {0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     },
    {WHITE , WHITE , WHITE , WHITE , WHITE , 0     , 0     , 0     , 0     }
};

const uint8_t arrowUpDown[15][8] = {
    {0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0},
    {0     , 0     , WHITE , WHITE , WHITE , 0     , 0     , 0},
    {0     , WHITE , WHITE , WHITE , WHITE , WHITE , 0     , 0},
    {WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , 0},
	{0     , 0     , WHITE , WHITE , WHITE , 0     , 0     , 0},
    {0     , 0     , WHITE , WHITE , WHITE , 0     , 0     , 0},
    {0     , 0     , WHITE , WHITE , WHITE , 0     , 0     , 0},
    {0     , 0     , WHITE , WHITE , WHITE , 0     , 0     , 0},
    {0     , 0     , WHITE , WHITE , WHITE , 0     , 0     , 0},
    {0     , 0     , WHITE , WHITE , WHITE , 0     , 0     , 0},
    {0     , 0     , WHITE , WHITE , WHITE , 0     , 0     , 0},
    {WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , 0},
    {0     , WHITE , WHITE , WHITE , WHITE , WHITE , 0     , 0},
    {0     , 0     , WHITE , WHITE , WHITE , 0     , 0     , 0},
    {0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0}
};

const uint8_t arrowLeftRight[7][15] = {
    {0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0},
    {0     , 0     , WHITE , WHITE , 0     , 0     , 0     , 0     , 0     , 0     , 0     , WHITE , WHITE , 0     , 0},
    {0     , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , 0},
    {WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE},
    {0     , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , WHITE , 0},
    {0     , 0     , WHITE , WHITE , 0     , 0     , 0     , 0     , 0     , 0     , 0     , WHITE , WHITE , 0     , 0},
    {0     , 0     , 0     , WHITE , 0     , 0     , 0     , 0     , 0     , 0     , 0     , WHITE , 0     , 0     , 0}
};

You've defined the tables as const, so no RAM is used for your tables. Check the .map file to see what is eating up your ram.

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.
CAN Jammer an open source CAN bus hacking tool
CANableV3 Open Source


@KnarfB wrote:

is 76.800 decimal, 


So that's nearly the 50K overflow reported!

Presumably, this is allocating a full frame buffer in RAM?

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

The G431C has 128K flash and 32K RAM, and the CUBE MX is set in the configuration.

I still don't understand a 50K overflow.

I've already tried optimizing by reducing it by only 1K.
Maybe it's in the ILI9488 display buffer? I think it's unlikely.

I'll attach the codes for the ILI9488 display.

/*
 * ILI9488.c
 *
 *  Created on: Apr 29, 2021
 *      Author: hydra
 *
 * 	Modified by:
 * 		Dominik Workshop, Eryk Możdżeń
 * 		8.04.2024
 *
 * 		Added image buffer
 */

#include "ILI9488.h"
#include "stdlib.h"
#include <stdbool.h>
#include <string.h>

extern SPI_HandleTypeDef hspi1;
extern DMA_HandleTypeDef hdma_spi1_tx;
extern uint8_t SPI1_TX_completed_flag;


/**
 * @brief Buffer storing 4-bit color values for each LCD pixel.
 * Each byte represents color information for two adjacent pixels, utilizing 4 bits per pixel
 */
static uint8_t image_buffer[ILI9488_TFTWIDTH*ILI9488_TFTHEIGHT/2 ] = {0};

/**
 * @brief Macro to retrieve the color value of a pixel from the image buffer.
 *
 * @PAram x The x-coordinate of the pixel.
 * @PAram y The y-coordinate of the pixel.
 * @return The 4-bit color value of the specified pixel.
 */
#define IMG_BUFF_GET(x, y) 		(((x)%2)==0)?(image_buffer[((y)*240)+((x)/2)]>>4):(image_buffer[((y)*240)+((x)/2)]&0x0F)

/**
 * @brief Macro to set the color value of a pixel in the image buffer.
 *
 * @PAram x The x-coordinate of the pixel.
 * @PAram y The y-coordinate of the pixel.
 * @PAram c The 4-bit color value to set for the pixel.
 */
#define IMG_BUF_SET(x, y, c) 	if(((x)%2)==0){image_buffer[((y)*(_width/2))+((x)/2)]&=0x0F;image_buffer[((y)*(_width/2))+((x)/2)]|=((c)<<4);} \
								else{image_buffer[((y)*(_width/2))+((x)/2)]&=0xF0;image_buffer[((y)*(_width/2))+((x)/2)]|=(c);}


static uint8_t colors[16][3] = {
  // r, g, b //
	{0, 0, 0},			// black
	{0x55, 0x55, 0x55},	// grey
	{0xFF, 0xFF, 0xFF}, // white

	{0, 0x55, 0},		// dark green
	{0, 0xAA, 0},		// green
	{0, 0xFF, 0},		// light green

	{0, 0, 0xFF},		// dark blue
	{0, 0x55, 0xFF},	// blue
	{0, 0xAA, 0xFF},	// light blue
	{0, 0xFF, 0xFF},	// cyan

	{0xFF, 0, 0},		// red
	{0xFF, 0x55, 0},	// light red
	{0xFF, 0xAA, 0},	// orange
	{0xFF, 0xFF, 0},	// yellow

	{0xFF, 0, 0xFF},	// dark pink
	{0xFF, 0x55, 0xFF}	// pink
};


uint8_t tabcolor;
uint8_t mySPCR;

int16_t WIDTH;
int16_t HEIGHT;
int16_t _width;
int16_t  _height;
int16_t cursor_x;
int16_t cursor_y;
uint16_t textcolor;
uint16_t textbgcolor;
uint8_t textsize_x;
uint8_t textsize_y;
uint8_t rotation;


void ILI9488_Init(void){
	HAL_GPIO_WritePin(TFT_RST_GPIO_Port,TFT_RST_Pin, GPIO_PIN_RESET);
	HAL_Delay(10);
	HAL_GPIO_WritePin(TFT_RST_GPIO_Port,TFT_RST_Pin, GPIO_PIN_SET);
	_width=ILI9488_TFTWIDTH;
	_height=ILI9488_TFTHEIGHT;

	writecommand(0xE0);
	writedata(0x00);
	writedata(0x03);
	writedata(0x09);
	writedata(0x08);
	writedata(0x16);
	writedata(0x0A);
	writedata(0x3F);
	writedata(0x78);
	writedata(0x4C);
	writedata(0x09);
	writedata(0x0A);
	writedata(0x08);
	writedata(0x16);
	writedata(0x1A);
	writedata(0x0F);

	writecommand(0XE1);
	writedata(0x00);
	writedata(0x16);
	writedata(0x19);
	writedata(0x03);
	writedata(0x0F);
	writedata(0x05);
	writedata(0x32);
	writedata(0x45);
	writedata(0x46);
	writedata(0x04);
	writedata(0x0E);
	writedata(0x0D);
	writedata(0x35);
	writedata(0x37);
	writedata(0x0F);

	writecommand(0XC0);     //Power Control 1
	writedata(0x17);    	//Vreg1out
	writedata(0x15);    	//Verg2out

	writecommand(0xC1);     //Power Control 2
	writedata(0x41);    	//VGH,VGL

	writecommand(0xC5);     //Power Control 3
	writedata(0x00);
	writedata(0x12);    	//Vcom
	writedata(0x80);

	writecommand(0x36);     //Memory Access
	writedata(0x48);

	writecommand(0x36);     // Interface Pixel Format
	writedata(0x66); 	  	//18 bit

	writecommand(0XB0);     // Interface Mode Control
	writedata(0x80);     	//SDO NOT USE

	writecommand(0xB1);     //Frame rate
	writedata(0xA0);    	//60Hz

	writecommand(0xB4);     //Display Inversion Control
	writedata(0x02);    	//2-dot

	writecommand(0XB6); 	//Display Function Control  RGB/MCU Interface Control

	writedata(0x02);    	//MCU
	writedata(0x02);    	//Source,Gate scan dieection

	writecommand(0XE9);     // Set Image Functio
	writedata(0x00);    	// Disable 24 bit data

	writecommand(0xF7);     // Adjust Control
	writedata(0xA9);
	writedata(0x51);
	writedata(0x2C);
	writedata(0x82);    	// D7 stream, loose

	writecommand(ILI9488_SLPOUT); 	//Exit Sleep

	HAL_Delay(120);

	writecommand(ILI9488_DISPON); 	//Display on
}

void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1){
	writecommand(ILI9488_CASET); // Column addr set
	writedata(x0 >> 8);
	writedata(x0 & 0xFF);     	 // XSTART
	writedata(x1 >> 8);
	writedata(x1 & 0xFF);     	 // XEND
	writecommand(ILI9488_PASET); // Row addr set
	writedata(y0 >> 8);
	writedata(y0 & 0xff);        // YSTART
	writedata(y1 >> 8);
	writedata(y1 & 0xff);        // YEND
	writecommand(ILI9488_RAMWR); // write to RAM
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(TFT_DC_GPIO_Port,TFT_DC_Pin, GPIO_PIN_SET);
}


void setScrollArea(uint16_t topFixedArea, uint16_t bottomFixedArea){
	writecommand(0x33); // Vertical scroll definition
	writedata(topFixedArea >> 8);
	writedata(topFixedArea);
	writedata((_height - topFixedArea - bottomFixedArea) >> 8);
	writedata(_height - topFixedArea - bottomFixedArea);
	writedata(bottomFixedArea >> 8);
	writedata(bottomFixedArea);
}

void scroll(uint16_t pixels){
	writecommand(0x37); // Vertical scrolling start address
	writedata(pixels >> 8);
	writedata(pixels);
}

/*
void pushColor(uint16_t color){
	HAL_GPIO_WritePin(TFT_DC_GPIO_Port,TFT_DC_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_RESET);
	write16BitColor(color);
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_SET);
}

void pushColors(uint16_t *data, uint8_t len, uint8_t first){
	uint16_t color;
	uint8_t buff[len * 3 + 1];
	uint16_t count = 0;
	uint8_t lencount = len;

	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_RESET);
	if (first == 1){
		HAL_GPIO_WritePin(TFT_DC_GPIO_Port,TFT_DC_Pin,GPIO_PIN_SET);
	}
	while (lencount--){
		color = *data++;
		buff[count] = (((color & 0xF800) >> 11) * 255) / 31;
		count++;
		buff[count] = (((color & 0x07E0) >> 5) * 255) / 63;
		count++;
		buff[count] = ((color & 0x001F) * 255) / 31;
		count++;
	}
	HAL_SPI_Transmit(&hspi1, buff, len * 3, 100);
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_SET);
}
*/

/**
 * @brief Draws image (img[h][w]) to a buffer
 *
 */
void drawImageTransparent(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint8_t* img){

	if ((x >= _width) || (y >= _height))
		return;
	if ((x + w - 1) >= _width)
		w = _width - x;
	if ((y + h - 1) >= _height)
		h = _height - y;

	for (uint16_t i = 0; i < h; i++) {
	    for (uint16_t o = 0; o < w; o++) {
	        if (img[i * w + o] != BLACK) {
	            drawPixel(x + o, y + i, img[i * w + o]);
	        }
	    }
	}
}

/**
 * @brief Draws image (img[h][w]) to a buffer with every non black pixel colored to given color
 *
 */
void drawImageTransparentColored(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint8_t* img, uint8_t color){

	if ((x >= _width) || (y >= _height))
		return;
	if ((x + w - 1) >= _width)
		w = _width - x;
	if ((y + h - 1) >= _height)
		h = _height - y;

	for (uint16_t i = 0; i < h; i++) {
	    for (uint16_t o = 0; o < w; o++) {
	        if (img[i * w + o] != BLACK) {
	            drawPixel(x + o, y + i, color);
	        }
	    }
	}
}

/**
 * @brief Draws image (img[h][w]) to a buffer
 *
 */
void drawImage(const uint8_t* img, uint16_t x, uint16_t y, uint16_t w, uint16_t h){

	if ((x >= _width) || (y >= _height))
		return;
	if ((x + w - 1) >= _width)
		w = _width - x;
	if ((y + h - 1) >= _height)
		h = _height - y;

	for (uint16_t i = 0; i < h; i++) {
	    for (uint16_t o = 0; o < w; o++) {
	        drawPixel(x + o, y + i, img[i * w + o]);
	    }
	}
}

/**
 * @brief Fills the entire screen with the specified color.
 *
 * @PAram color The 4-bit color value to fill the screen with.
 */
void fillScreen(uint8_t color){
	fillRect(0, 0,  _width, _height, color);
}

/**
 * @brief Sets all pixels to black
 */
void clearScreen(){
	memset(image_buffer, BLACK, sizeof(image_buffer));
}

/**
 * @brief Sets the pixel at the specified location to the specified color.
 *
 *
 * @PAram x The x-coordinate of the pixel.
 * @PAram y The y-coordinate of the pixel.
 * @PAram color The color value to set for the pixel.
 */
void drawPixel(int16_t x, int16_t y, uint8_t color){
	if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height))
		return;
	IMG_BUF_SET(x, y, color);
}

void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color){
	if ((x >= _width) || (y >= _height))
		return;
	if ((y + h - 1) >= _height)
		h = _height - y;

	for(uint16_t i = 0; i < h; ++i){
		IMG_BUF_SET(x, y+i, color);
	}
}

void drawFastVDottedLine(int16_t x, int16_t y, int16_t h, uint16_t color){
	if ((x >= _width) || (y >= _height))
		return;
	if ((y + h - 1) >= _height)
		h = _height - y;

	for(uint16_t i = 0; i < h; i+=2){
		IMG_BUF_SET(x, y+i, color);
	}
}

void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color){
	if ((x >= _width) || (y >= _height))
		return;
	if ((x + w - 1) >= _width)
		w = _width - x;

	for(uint16_t i = 0; i < w; ++i){
			IMG_BUF_SET(x+i, y, color);
		}
}

void drawFastHDottedLine(int16_t x, int16_t y, int16_t w, uint16_t color){
	if ((x >= _width) || (y >= _height))
		return;
	if ((x + w - 1) >= _width)
		w = _width - x;

	for(uint16_t i = 0; i < w; i+=2){
			IMG_BUF_SET(x+i, y, color);
		}
}

void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,uint16_t color){
	 if (x0 == x1) {
	    if (y0 > y1)
	      _swap_int16_t(y0, y1);
	    drawFastVLine(x0, y0, y1 - y0 + 1, color);
	  } else if (y0 == y1) {
	    if (x0 > x1)
	      _swap_int16_t(x0, x1);
	    drawFastHLine(x0, y0, x1 - x0 + 1, color);
	  } else {

	    writeLine(x0, y0, x1, y1, color);
	  }
}

void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,uint16_t color){
  int16_t steep = abs(y1 - y0) > abs(x1 - x0);
  if (steep) {
    _swap_int16_t(x0, y0);
    _swap_int16_t(x1, y1);
  }

  if (x0 > x1) {
    _swap_int16_t(x0, x1);
    _swap_int16_t(y0, y1);
  }

  int16_t dx, dy;
  dx = x1 - x0;
  dy = abs(y1 - y0);

  int16_t err = dx / 2;
  int16_t ystep;

  if (y0 < y1) {
    ystep = 1;
  } else {
    ystep = -1;
  }

  for (; x0 <= x1; x0++) {
    if (steep) {
    	IMG_BUF_SET(y0, x0, color)
    } else {
    	IMG_BUF_SET(x0, y0, color)
    }
    err -= dy;
    if (err < 0) {
      y0 += ystep;
      err += dx;
    }
  }
}

void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint8_t color){
	if ((x >= _width) || (y >= _height))
		return;
	if ((x + w - 1) >= _width)
		w = _width - x;
	if ((y + h - 1) >= _height)
		h = _height - y;

	for(int16_t i = 0; i < w; ++i){
		for(int16_t j = 0; j < h; ++j){
			IMG_BUF_SET(x+i, y+j, color);
		}
	}
}

void setRotation(uint8_t r){
	writecommand(ILI9488_MADCTL);
	rotation = r % 4; // can't be higher than 3
	switch (rotation) {
	case 0:
		writedata(MADCTL_MX | MADCTL_BGR);
		_width = ILI9488_TFTWIDTH;
		_height = ILI9488_TFTHEIGHT;
		break;
	case 1:
		writedata(MADCTL_MV | MADCTL_BGR);
		_width = ILI9488_TFTHEIGHT;
		_height = ILI9488_TFTWIDTH;
		break;
	case 2:
		writedata(MADCTL_MY | MADCTL_BGR);
		_width = ILI9488_TFTWIDTH;
		_height = ILI9488_TFTHEIGHT;
		break;
	case 3:
		writedata(MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
		_width = ILI9488_TFTHEIGHT;
		_height = ILI9488_TFTWIDTH;
		break;
	}
}

void invertDisplay(uint8_t i){
	  writecommand(i ? ILI9488_INVON : ILI9488_INVOFF);
}

uint16_t color565(uint8_t r, uint8_t g, uint8_t b){
	return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}

void spiwrite(uint8_t data){
	HAL_SPI_Transmit(&hspi1, &data, 1, 1);
}

void writecommand(uint8_t c){
	HAL_GPIO_WritePin(TFT_DC_GPIO_Port,TFT_DC_Pin,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_RESET);
	HAL_SPI_Transmit(&hspi1, &c, 1, 1);
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_SET);
}

void write16BitColor(uint16_t color){
	  uint8_t r = (color & 0xF800) >> 11;
	  uint8_t g = (color & 0x07E0) >> 5;
	  uint8_t b = color & 0x001F;

	  r = (r * 255) / 31;
	  g = (g * 255) / 63;
	  b = (b * 255) / 31;

	  HAL_SPI_Transmit(&hspi1, &r, 1, 1);
	  HAL_SPI_Transmit(&hspi1, &g, 1, 1);
	  HAL_SPI_Transmit(&hspi1, &b, 1, 1);
}

void writedata(uint8_t d){
	HAL_GPIO_WritePin(TFT_DC_GPIO_Port,TFT_DC_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_RESET);

	HAL_SPI_Transmit(&hspi1, &d, 1, 1);
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_SET);
}

void testLines(uint8_t color){
	//unsigned long start, t;
	int x1, y1, x2, y2, w = _width, h = _height;
	fillScreen(BLACK);

	x1 = y1 = 0;
	y2 = h - 1;

	for (x2 = 0; x2 < w; x2 += 6)
		drawLine(x1, y1, x2, y2, color);
	x2 = w - 1;
	for (y2 = 0; y2 < h; y2 += 6)
		drawLine(x1, y1, x2, y2, color);
	fillScreen(BLACK);

	x1 = w - 1;
	y1 = 0;
	y2 = h - 1;

	for (x2 = 0; x2 < w; x2 += 6)
		drawLine(x1, y1, x2, y2, color);
	x2 = 0;
	for (y2 = 0; y2 < h; y2 += 6)
		drawLine(x1, y1, x2, y2, color);

	fillScreen(BLACK);

	x1 = 0;
	y1 = h - 1;
	y2 = 0;

	for (x2 = 0; x2 < w; x2 += 6)
		drawLine(x1, y1, x2, y2, color);
	x2 = w - 1;
	for (y2 = 0; y2 < h; y2 += 6)
		drawLine(x1, y1, x2, y2, color);

	fillScreen(ILI9488_BLACK);

	x1 = w - 1;
	y1 = h - 1;
	y2 = 0;

	for (x2 = 0; x2 < w; x2 += 6)
		drawLine(x1, y1, x2, y2, color);
	x2 = 0;
	for (y2 = 0; y2 < h; y2 += 6)
		drawLine(x1, y1, x2, y2, color);
}

void sendasIO(uint8_t d){
	for (uint8_t bit = 0x80; bit; bit >>= 1) {

		if (d & bit) {
			//_mosi->setHigh();
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);
		} else {
			//_mosi->setLow();
			HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET);
		}
		//_sck->setHigh();
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
		//HAL_Delay(4);
		//__ASM volatile ("NOP");

		//_sck->setLow();
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
	}
}

/*void ILI9488::commandList(uint8_t *addr)
 {
	uint8_t numCommands, numArgs;
	uint16_t ms;

	numCommands = pgm_read_byte(addr++);
	while (numCommands--) {
		writecommand(pgm_read_byte(addr++));
		numArgs = pgm_read_byte(addr++);
		ms = numArgs & 0x80;
		numArgs &= ~0x80;
		while (numArgs--) {
			writedata(pgm_read_byte(addr++));
		}

		if (ms) {
			ms = pgm_read_byte(addr++); // Read post-command delay time (ms)
			if (ms == 255)
				ms = 500;     // If 255, delay for 500 ms
			delay(ms);
		}
	}

}*/


void ILI9341_Draw_Colour(uint16_t Colour){
	//SENDS COLOUR

	uint8_t r = (Colour & 0xF800) >> 11;
	uint8_t g = (Colour & 0x07E0) >> 5;
	uint8_t b = Colour & 0x001F;

	r = (r * 255) / 31;
	g = (g * 255) / 63;
	b = (b * 255) / 31;

	unsigned char TempBuffer[3] = { r, g ,b };

	for (uint32_t j = 0; j < 480*320; j++){
		HAL_GPIO_WritePin(TFT_DC_GPIO_Port, TFT_DC_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(TFT_CS_GPIO_Port, TFT_CS_Pin, GPIO_PIN_RESET);

		SPI1_TX_completed_flag = 0;
		HAL_SPI_Transmit_DMA(&hspi1, TempBuffer, 3);
		while (SPI1_TX_completed_flag == 0)
			HAL_GPIO_WritePin(TFT_CS_GPIO_Port, TFT_CS_Pin, GPIO_PIN_SET);
	}
}

//INTERNAL FUNCTION OF LIBRARY
/*Sends block colour information to LCD*/
void ILI9341_Draw_Colour_Burst(uint16_t Colour, uint32_t Size){
//SENDS COLOUR
	uint32_t Buffer_Size = 0;
	if ((Size * 2) < BURST_MAX_SIZE){
		Buffer_Size = Size;
	}
	else{
		Buffer_Size = BURST_MAX_SIZE;
	}

	HAL_GPIO_WritePin(TFT_DC_GPIO_Port, TFT_DC_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port, TFT_CS_Pin, GPIO_PIN_RESET);

//	unsigned char MSB_color = Colour >> 8;

	  uint8_t r = (Colour & 0xF800) >> 11;
	  uint8_t g = (Colour & 0x07E0) >> 5;
	  uint8_t b = Colour & 0x001F;

	  r = (r * 255) / 31;
	  g = (g * 255) / 63;
	  b = (b * 255) / 31;

	unsigned char burst_buffer[Buffer_Size];
	for (uint32_t j = 0; j < Buffer_Size; j += 3){
		burst_buffer[j] = r;
		burst_buffer[j + 1] = g;
		burst_buffer[j + 2] = b;
	}

	uint32_t Sending_Size = Size * 3;
	uint32_t Sending_in_Block = Sending_Size / Buffer_Size;
	uint32_t Remainder_from_block = Sending_Size % Buffer_Size;

	if (Sending_in_Block != 0){
		for (uint32_t j = 0; j < (Sending_in_Block); j++){
			SPI1_TX_completed_flag = 0;
			HAL_SPI_Transmit_DMA(&hspi1, (unsigned char*) burst_buffer, Buffer_Size);
			while (SPI1_TX_completed_flag == 0);
		}
	}

//REMAINDER!

	if (Remainder_from_block > 0)
	{
		SPI1_TX_completed_flag = 0;
		HAL_SPI_Transmit_DMA(&hspi1, (unsigned char*) burst_buffer, Remainder_from_block);
		while (SPI1_TX_completed_flag == 0);
	}
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port, TFT_CS_Pin, GPIO_PIN_SET);
}

//FILL THE ENTIRE SCREEN WITH SELECTED COLOUR (either #define-d ones or custom 16bit)
/*Sets address (entire screen) and Sends Height*Width ammount of colour information to LCD*/
void ILI9341_Fill_Screen(uint16_t Colour){
//	LCD_Address_Set(xsta,ysta+OFFSET_Y,xend-1,yend-1+OFFSET_Y);/
	setAddrWindow(0, 0, ILI9488_TFTHEIGHT-1, ILI9488_TFTWIDTH-1);
	ILI9341_Draw_Colour_Burst(Colour, ILI9488_TFTWIDTH * ILI9488_TFTHEIGHT);
}

void ILI9341_Fill_Screen1(uint16_t x, uint16_t y, uint16_t w, uint16_t h,uint16_t Colour){
//	LCD_Address_Set(xsta,ysta+OFFSET_Y,xend-1,yend-1+OFFSET_Y);/
	setAddrWindow(x, y, h-1, w-1);
	ILI9341_Draw_Colour_Burst(Colour, w * h);
}

//static void WriteDataDMA(const void *data, uint16_t length)
//{
//	txComplete = false;
//	HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)data, length);
//}
//
//static void WaitForDMAWriteComplete(void)
//{
//	while (txComplete == false)
//	{
//	}
//}
//
//void ILI9341FilledRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, colour_t colour)
//{
//	colour_t dmaBuffer[DMA_BUFFER_SIZE];
//	uint8_t i;
//	uint32_t totalBytesToWrite;
//	uint32_t bytesToWriteThisTime;
//
//	for (i = 0U; i < DMA_BUFFER_SIZE; i++)
//	{
//		dmaBuffer[i] = __builtin_bswap16(colour);
//	}
//
//	setAddrWindow(x, y, x + ILI9488_TFTWIDTH - 1U, y + ILI9488_TFTHEIGHT - 1U);
//	totalBytesToWrite = (uint32_t)width * (uint32_t)height * (uint32_t)sizeof(colour_t);
//	bytesToWriteThisTime = DMA_BUFFER_SIZE * (uint16_t)sizeof(colour_t);
//
//	while (totalBytesToWrite > 0UL)
//	{
//		if (totalBytesToWrite < bytesToWriteThisTime)
//		{
//			bytesToWriteThisTime = totalBytesToWrite;
//		}
//		totalBytesToWrite -= bytesToWriteThisTime;
//
//		WriteDataDMA(&dmaBuffer, bytesToWriteThisTime);
//		WaitForDMAWriteComplete();
//	}
//}
//
//static void filledRectangleClip(int16_t x, int16_t y, uint16_t width, uint16_t height, colour_t colour)
//{
//	int16_t x_end;
//	int16_t y_end;
//
//	if (x > (int16_t)ILI9488_TFTWIDTH - 1 || y > (int16_t)ILI9488_TFTHEIGHT - 1)
//	{
//		return;
//	}
//
//	if (x + (int16_t)width < 0 || y + (int16_t)height < 0)
//	{
//		return;
//	}
//
//	if (x < 0)
//	{
//		width -= (uint16_t)-x;
//		x = 0;
//	}
//
//	if (y < 0)
//	{
//		height -= (uint16_t)-y;
//		y = 0;
//	}
//
//	x_end = x + (int16_t)width - 1;
//	if (x_end >(int16_t)ILI9488_TFTWIDTH - 1)
//	{
//		x_end = (int16_t)ILI9488_TFTWIDTH - 1;
//	}
//
//	y_end = y + (int16_t)height - 1;
//	if (y_end > (int16_t)ILI9488_TFTHEIGHT - 1)
//	{
//		y_end = (int16_t)ILI9488_TFTHEIGHT - 1;
//	}
//
//	// clipped sizes
//	width = (uint16_t)(x_end - x + 1);
//	height = (uint16_t)(y_end - y + 1);
//
//	ILI9341FilledRectangle((uint16_t)x, (uint16_t)y, width, height, colour);
//}
//
//
//void GraphicsClear(colour_t colour)
//{
//	filledRectangleClip(0U, 0U, (uint16_t)ILI9488_TFTWIDTH, (uint16_t)ILI9488_TFTHEIGHT, colour);
//}
//

void LCD_Char(int16_t x, int16_t y, const GFXglyph *glyph, const GFXfont *font, uint8_t size, uint32_t color24){
	uint8_t  *bitmap = font -> bitmap;
	uint16_t bo = glyph -> bitmapOffset;
	uint8_t bits = 0, bit = 0;
	uint16_t set_pixels = 0;
	uint8_t  cur_x, cur_y;
	for (cur_y = 0; cur_y < glyph -> height; cur_y++){
		for (cur_x = 0; cur_x < glyph -> width; cur_x++){
			if (bit == 0){
				bits = (*(const unsigned char *)(&bitmap[bo++]));
				bit  = 0x80;
			}
			if (bits & bit) set_pixels++;
			else if (set_pixels > 0){
				fillRect(x + (glyph -> xOffset + cur_x - set_pixels) * size, y + (glyph -> yOffset + cur_y) * size, size * set_pixels, size, color24);
				set_pixels = 0;
			}
			bit >>= 1;
		}
		if (set_pixels > 0){
			fillRect(x + (glyph -> xOffset + cur_x-set_pixels) * size, y + (glyph -> yOffset + cur_y) * size, size * set_pixels, size, color24);
			set_pixels = 0;
		}
	}
}

void LCD_Font(uint16_t x, uint16_t y, const char *text, const GFXfont *p_font, uint8_t size, uint32_t color24){
	int16_t cursor_x = x;
	int16_t cursor_y = y;
	GFXfont font;
	memcpy(&font, p_font, sizeof(GFXfont));
	for (uint16_t text_pos = 0; text_pos < strlen(text); text_pos++){
		char c = text[text_pos];
		if (c == '\n'){
			cursor_x = x;
			cursor_y += font.yAdvance * size;
		}
		else if (c >= font.first && c <= font.last && c != '\r'){
			GFXglyph glyph;
			memcpy(&glyph, &font.glyph[c - font.first], sizeof(GFXglyph));
			LCD_Char(cursor_x, cursor_y, &glyph, &font, size, color24);
			cursor_x += glyph.xAdvance * size;
		}
	}
}

void drawImage2(){

}

void drawCanva(){
	int x =0;
	int y=20;
	int w = _width;
	int h = _height;
	if ((x >= _width) || (y >= _height))
		return;
	if ((x + w - 1) >= _width)
		w = _width - x;
	if ((y + h - 1) >= _height)
		h = _height - y;
	setAddrWindow(x, y, x + w - 1, y + h - 1);
	HAL_GPIO_WritePin(TFT_DC_GPIO_Port,TFT_DC_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_RESET);

	uint8_t linebuff[w * 3 + 1];
	uint16_t color;
	for (uint16_t i = 0; i < h; i++) {
		uint16_t pixcount = 0;
		for (uint16_t o = 0; o < w; o++) {

			// Check if it's a horizontal grid line
			if ((i % 60 == 0) || (i == 319- y)) {
				color = ILI9488_DARKGREY; // White
			} else {
				// Check if it's a vertical grid line
				if ((o % 60 == 0) || (o == 479)) {
					color = ILI9488_DARKGREY; // White
				} else {
					color = 0x0000; // Black
				}
			}


			linebuff[pixcount] = (((color & 0xF800) >> 11) * 255)
				/ 31;
			pixcount++;
			linebuff[pixcount] = (((color & 0x07E0) >> 5) * 255)
					/ 63;
			pixcount++;
			linebuff[pixcount] = ((color & 0x001F) * 255) / 31;
			pixcount++;
		}
		HAL_SPI_Transmit(&hspi1, linebuff, w * 3, 100);

	}
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_SET);
}

/**
 * @brief Renders an image stored in an image buffer to the LCD screen
 *
 */
void imageRender(){
	setAddrWindow(0, 0, _width - 1, _height - 1);
	HAL_GPIO_WritePin(TFT_DC_GPIO_Port,TFT_DC_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_RESET);

	// Buffer to hold pixel color data for a single line of the screen
	uint8_t linebuff[_width * 3 + 1];

	// Iterate through each row (height) of the screen
	for (uint16_t h = 0; h < _height; h++){
		// Iterate through each column (width) of the screen
		for (uint16_t w = 0; w < _width; w++){
			// Retrieve the pixel color index from the image buffer
			uint8_t pixel_color = IMG_BUFF_GET(w, h);
			// Retrieve the RGB color values corresponding to the pixel color index
			linebuff[3*w + 0] = colors[pixel_color][0];	// r
			linebuff[3*w + 1] = colors[pixel_color][1];	// g
			linebuff[3*w + 2] = colors[pixel_color][2];	// b
		}
		HAL_SPI_Transmit(&hspi1, linebuff, _width * 3, 100);
	}
	HAL_GPIO_WritePin(TFT_CS_GPIO_Port,TFT_CS_Pin,GPIO_PIN_SET);
}

void drawRectangleRoundedFrame(int16_t x, int16_t y, int16_t w, int16_t h, uint8_t color) {
    drawFastHLine(x + 5, y, w - 9, color); // Top line
    drawFastHLine(x + 5, y + h, w - 9, color); // Bottom line

    drawFastVLine(x, y + 5, h - 9, color); // Left line
    drawFastVLine(x + w, y + 5, h - 9, color); // Right line

    // right top corner
    drawFastHLine(x + 3, y + 1, 2, color); // Top line
    drawFastVLine(x + 1, y + 3, 2, color); // Left line
    drawPixel(x + 2, y + 2, color);

    // left top corner
	drawFastHLine(x - 4 + w, y + 1, 2, color); // Top line
	drawFastVLine(x - 1 + w, y + 3, 2, color); // Right line
	drawPixel(x - 2 + w, y + 2, color);

	// right bottom corner
	drawFastHLine(x + 3, y - 1 + h, 2, color); // Bottom line
	drawFastVLine(x + 1, y - 4 + h, 2, color); // Left line
	drawPixel(x + 2, y - 2 + h, color);

	// left bottom corner
	drawFastHLine(x - 4 + w, y - 1 + h, 2, color); // Bottom line
	drawFastVLine(x - 1 + w, y - 4 + h, 2, color); // Left line
	drawPixel(x - 2 + w, y - 2 + h, color);
}
/*
 * ILI9488.h
 *
 *  Created on: Apr 29, 2021
 *      Author: hydra
 *
 * 	Modified by:
 * 		Dominik Workshop, Eryk Możdżeń
 * 		8.04.2024
 *
 * 		Added image buffer
 */

#ifndef ILI9488_H_
#define ILI9488_H_
#include <math.h>
#include "main.h"

enum colors{
    BLACK,
    GREY,
    WHITE,
    DARK_GREEN,
    GREEN,
    LIGHT_GREEN,
    DARK_BLUE,
    BLUE,
    LIGHT_BLUE,
    CYAN,
    RED,
    LIGHT_RED,
    ORANGE,
    YELLOW,
    DARK_PINK,
    PINK
};

#define DMA_BUFFER_SIZE 	64U
#define BURST_MAX_SIZE 		750

#define ILI9488_TFTWIDTH  	320
#define ILI9488_TFTHEIGHT 	480

#define ILI9488_NOP     	0x00
#define ILI9488_SWRESET 	0x01
#define ILI9488_RDDID   	0x04
#define ILI9488_RDDST   	0x09

#define ILI9488_SLPIN   	0x10
#define ILI9488_SLPOUT  	0x11
#define ILI9488_PTLON   	0x12
#define ILI9488_NORON   	0x13

#define ILI9488_RDMODE  	0x0A
#define ILI9488_RDMADCTL	0x0B
#define ILI9488_RDPIXFMT  	0x0C
#define ILI9488_RDIMGFMT  	0x0D
#define ILI9488_RDSELFDIAG  0x0F

#define ILI9488_INVOFF  	0x20
#define ILI9488_INVON   	0x21
#define ILI9488_GAMMASET 	0x26
#define ILI9488_DISPOFF 	0x28
#define ILI9488_DISPON  	0x29

#define ILI9488_CASET  		0x2A
#define ILI9488_PASET   	0x2B
#define ILI9488_RAMWR   	0x2C
#define ILI9488_RAMRD   	0x2E

#define ILI9488_PTLAR   	0x30
#define ILI9488_MADCTL  	0x36
#define ILI9488_PIXFMT  	0x3A

#define ILI9488_FRMCTR1 	0xB1
#define ILI9488_FRMCTR2 	0xB2
#define ILI9488_FRMCTR3 	0xB3
#define ILI9488_INVCTR  	0xB4
#define ILI9488_DFUNCTR 	0xB6

#define ILI9488_PWCTR1  	0xC0
#define ILI9488_PWCTR2  	0xC1
#define ILI9488_PWCTR3  	0xC2
#define ILI9488_PWCTR4  	0xC3
#define ILI9488_PWCTR5  	0xC4
#define ILI9488_VMCTR1  	0xC5
#define ILI9488_VMCTR2  	0xC7

#define ILI9488_RDID1   	0xDA
#define ILI9488_RDID2   	0xDB
#define ILI9488_RDID3   	0xDC
#define ILI9488_RDID4   	0xDD

#define ILI9488_GMCTRP1 	0xE0
#define ILI9488_GMCTRN1 	0xE1

//#define ILI9488_PWCTR6  0xFC


// Color definitions
#define ILI9488_BLACK      			0x0000      /*   0,   0,   0 */
#define ILI9488_NAVY				0x000F      /*   0,   0, 128 */
#define ILI9488_DARKGREEN   		0x03E0      /*   0, 128,   0 */
#define ILI9488_DARKCYAN    		0x03EF      /*   0, 128, 128 */
#define ILI9488_MAROON      		0x7800      /* 128,   0,   0 */
#define ILI9488_PURPLE      		0x780F      /* 128,   0, 128 */
#define ILI9488_OLIVE       			0x7BE0      /* 128, 128,   0 */
#define ILI9488_LIGHTGREY   		0xC618      /* 192, 192, 192 */
#define ILI9488_DARKGREY    		0x7BEF      /* 128, 128, 128 */
#define ILI9488_BLUE        			0x001F      /*   0,   0, 255 */
#define ILI9488_GREEN       		0x07E0      /*   0, 255,   0 */
#define ILI9488_CYAN        			0x07FF      /*   0, 255, 255 */
#define ILI9488_RED         			0xF800      /* 255,   0,   0 */
#define ILI9488_MAGENTA     		0xF81F      /* 255,   0, 255 */
#define ILI9488_YELLOW      		0xFFE0      /* 255, 255,   0 */
#define ILI9488_WHITE       			0xFFFF      /* 255, 255, 255 */
#define ILI9488_ORANGE      		0xFD20      /* 255, 165,   0 */
#define ILI9488_GREENYELLOW 	0xAFE5      /* 173, 255,  47 */
#define ILI9488_PINK        			0xF81F

typedef uint16_t colour_t;


#define MADCTL_MY  0x80
#define MADCTL_MX  0x40
#define MADCTL_MV  0x20
#define MADCTL_ML  0x10
#define MADCTL_RGB 0x00
#define MADCTL_BGR 0x08
#define MADCTL_MH  0x04

#define _swap_int16_t(a, b) \
	{int16_t t = a; \
	a = b;   \
	b = t; \
  }

typedef struct { // Data stored PER GLYPH
	uint16_t bitmapOffset;     // Pointer into GFXfont->bitmap
	uint8_t  width, height;    // Bitmap dimensions in pixels
	uint8_t  xAdvance;         // Distance to advance cursor (x axis)
	int8_t   xOffset, yOffset; // Dist from cursor position to UL corner
} GFXglyph;

typedef struct { // Data stored for FONT AS A WHOLE:
	uint8_t  *bitmap;      // Glyph bitmaps, concatenated
	GFXglyph *glyph;       // Glyph array
	uint8_t   first, last; // ASCII extents
	uint8_t   yAdvance;    // Newline distance (y axis)
} GFXfont;

/* GENERAL CONFIGURATIONS */

#define _DEGUG_MODE 1
#define SINGLE_IO_MODE 1

void ILI9488_Init(void);
void begin(void);
void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
void setScrollArea(uint16_t topFixedArea, uint16_t bottomFixedArea);
void scroll(uint16_t pixels);
void pushColor(uint16_t color);
void pushColors(uint16_t *data, uint8_t len, uint8_t first);
void drawImageTransparent(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint8_t* img);
void drawImageTransparentColored(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint8_t* img, uint8_t color);
void drawImage(const uint8_t* img, uint16_t x, uint16_t y, uint16_t w, uint16_t h);
void fillScreen(uint8_t color);
void drawPixel(int16_t x, int16_t y, uint8_t color);
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
void drawFastVDottedLine(int16_t x, int16_t y, int16_t h, uint16_t color);
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
void drawFastHDottedLine(int16_t x, int16_t y, int16_t w, uint16_t color);
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,uint16_t color);
void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,uint16_t color);
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint8_t color);
void setRotation(uint8_t r);
void invertDisplay(uint8_t  i);
uint16_t color565(uint8_t r, uint8_t g, uint8_t b);
void spiwrite(uint8_t data);
void writecommand(uint8_t c);
void write16BitColor(uint16_t color);
void writedata(uint8_t d);
void testLines(uint8_t color);
void sendasIO(uint8_t d);
void ILI9341FilledRectangle(uint16_t x, uint16_t y, uint16_t width, uint16_t height, colour_t colour);
void GraphicsClear(colour_t colour);
void ILI9341_Fill_Screen(uint16_t Colour);
void ILI9341_Draw_Colour(uint16_t Colour);
void ILI9341_Fill_Screen1(uint16_t x, uint16_t y, uint16_t w, uint16_t h,uint16_t Colour);
void LCD_Font(uint16_t x, uint16_t y, const char *text, const GFXfont *p_font, uint8_t size, uint32_t color24);
void drawCanva();
void imageRender();
void clearScreen();
void drawRectangleRoundedFrame(int16_t x, int16_t y, int16_t w, int16_t h, uint8_t color);

#endif /* ILI9488_H_ */

I've also attached the .map file, which I didn't quite understand.

The ".map" file is too large to attach.

So you have:

#define ILI9488_TFTWIDTH  	320
#define ILI9488_TFTHEIGHT 	480

and

/**
 * @brief Buffer storing 4-bit color values for each LCD pixel.
 * Each byte represents color information for two adjacent pixels, utilizing 4 bits per pixel
 */
static uint8_t image_buffer[ ILI9488_TFTWIDTH*ILI9488_TFTHEIGHT/2 ] = {0};

which becomes

static uint8_t image_buffer[ 320*480/2 ] = {0};

320*480/2 = 76800 bytes !

ie, 75K bytes

 

Which is exactly what @KnarfB said earlier - from the map file.

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.