Jump to content

    

Подскажите по буферу LCD. Закипел.

Для LCD размером 160х128 при глубине цвета требуется 40КБ RAM. При этом буфер делаю unsigned short int размером 128х160.

Можно взять глубину цвета 8 бит. Т.е. буфер будет unsigned char и потребуется 20кб. Это тоже работает.

Но на малых контроллерах (L151) есть необходимость тоже запускать подобные LCD (других нет). При этом хотелось бы сделать буфер размером 4 бита и самому выбирать одно из 16 значений цветов. И 1 бит. И вот тут я на трансляции адресов закипел. Может кто подскажет литературу или пример где можно посмотреть как это делается? В SSD1309 делается так:

	if (color == WHITE) 
	buffer[x+ (y/8)*SSD1306_LCDWIDTH] |= (1 << (y&7));  
	else
	buffer[x+ (y/8)*SSD1306_LCDWIDTH] &= ~(1 << (y&7)); 

Но здесь сложнее. Здесь приходится еще и разгребать буфер перед записью в LCD.

Заранее спасибо.

Edited by Димон Безпарольный

Share this post


Link to post
Share on other sites

В подобных ситуациях делаю иначе - при записи в видео-буфер данные преобразую на ходу (тексты, картинки), а уже другая задача периодически гонит эти готовые данные в LCD, это позволяет использовать DMA при нужде.

Share this post


Link to post
Share on other sites
void write_buffer(x,y,color){
  buffer[(x+y*WIDTH)/2] = buffer[(x+y*WIDTH)/2] & (0xF0 >> (4*(x&1))) | ((color & 0x0F) << (4*(x&1)));
}

int read_buffer(x,y){
  return (buffer[(x+y*WIDTH)/2] >> (4*(x&1))) & 0x0F;
}

const uint16_t PALLETE[16] = {0xAABB, ...};

LCD_Write(x, y, PALLETE[read_buffer(x,y)]);

 

Share this post


Link to post
Share on other sites
3 hours ago, _pv said:

void write_buffer(x,y,color){
  buffer[(x+y*WIDTH)/2] = buffer[(x+y*WIDTH)/2] & (0xF0 >> (4*(x&1))) | ((color & 0x0F) << (4*(x&1)));
}

int read_buffer(x,y){
  return (buffer[(x+y*WIDTH)/2] >> (4*(x&1))) & 0x0F;
}

const uint16_t PALLETE[16] = {0xAABB, ...};

LCD_Write(x, y, PALLETE[read_buffer(x,y)]);

 

Круто. Спасибо. Вот что получилось:

 

void drawPixel(unsigned char x, unsigned char y, unsigned char color) 
{                                    //
    LCDBUF[(x+y*160)/2] = (LCDBUF[(x+y*160)/2] & (0xF0 >> (4*(x&1)))) | ((color & 0x0F) << (4*(x&1)));
}                                    //
 

 

И отправляем в дисплей:

void Display(void)					//Функция передает содержимое буферов цветов в дисплей LCD
{									//
	setAddrWindow(0, 0, width, height);//Диаппазон, в котором действует автоинкремент
	Set_Pin_DC;						//
	int h = width * height/2;		//Число точек
	int ADR = 0;					//Индекс массива
	while (h--)						//Цикл передачи массивов цветов в дисплей
	{								//
		unsigned char LCDByte;
		LCDByte = LCDBUF[ADR];
		if(LCDByte & 0x0F)		//Foreground
			{						//
				unsigned int short color = Colors[LCDByte & 0x0F];
				ST7735_write(color >> 8);	//Старший байт цвета
				ST7735_write(color);//Младший байт цвет
			}						//
		else						//BackGround
			{						//
				ST7735_write(0);	//Старший байт цвета
				ST7735_write(0);	//Младший байт цвета
			}						//
		LCDByte = LCDByte >> 4;		//
		if(LCDByte)					//Foreground
			{						//
				unsigned int short color = Colors[LCDByte];
				ST7735_write(color >> 8);	//Старший байт цвета
				ST7735_write(color);//Младший байт цвет
			}						//
		else						//BackGround
			{						//
				ST7735_write(0);	//Старший байт цвета
				ST7735_write(0);	//Младший байт цвета
			}						//	
		ADR++;						//
	}								//
	for(int i=0; i < width * height/2; i++)
		{							//Очистка видеобуфера
			LCDBUF[i] = 0;			//
		}							//
}									//

Теперь проще. Попробую еще монохром сделать.

Edited by Димон Безпарольный

Share this post


Link to post
Share on other sites

Монохром получился.

 

void drawPixel(unsigned char x, unsigned char y, unsigned char color) 
{                                    //
    if (color) 
        LCDBUF[(x+y*160)/8] |=  (1 << (x & 7));
    else
        LCDBUF[(x+y*160)/8] &= ~(1 << (x & 7));    
}                                    //

Вывод в дисплей:

void Display(void)					//Функция передает содержимое буферов цветов в дисплей LCD
{									//
	setAddrWindow(0, 0, width, height);//Диаппазон, в котором действует автоинкремент
	Set_Pin_DC;						//
	int h = width * height / 8;		//Число точек
	int ADR = 0, i;					//Индекс массива
	while (h--)						//Цикл передачи массивов цветов в дисплей
	{								//
		unsigned char LCDByte;		//
		LCDByte = LCDBUF[ADR];		//
		for(i = 0; i < 8; i++)		//
			{						//
				if(LCDByte & (1 << i))//Foreground
					{				//
						ST7735_write(Colors[PixelColor] >> 8);	//Старший байт цвета
						ST7735_write(Colors[PixelColor]);		//Младший байт цвет
					}				//
				else				//BackGround
					{				//
						ST7735_write(0);//Старший байт цвета
						ST7735_write(0);//Младший байт цвета
					}				//			
			}						//
		ADR++;						//
	}								//
	for(int i=0; i < width * height / 8; i++)
		{							//Очистка видеобуфера
			LCDBUF[i] = 0;			//
		}							//
}									//

 

Share this post


Link to post
Share on other sites

Два бита цвета тоже получилось, но коряво.

 

void drawPixel(unsigned char x, unsigned char y, unsigned char color) 
{									//
	if((x&3) == 0)
	{
		LCDBUF[(x+y*160)/4] = ((LCDBUF[(x+y*160)/4] & 0xfc) | (color & 0x03));
	}
	if((x&3) == 1)
	{
		LCDBUF[(x+y*160)/4] = ((LCDBUF[(x+y*160)/4] & 0xf3) | ((color & 0x03) << 2));
	}	
	if((x&3) == 2)
	{
		LCDBUF[(x+y*160)/4] = ((LCDBUF[(x+y*160)/4] & 0xcf) | ((color & 0x03) << 4));
	}		
	if((x&3) == 3)
	{
		LCDBUF[(x+y*160)/4] = ((LCDBUF[(x+y*160)/4] & 0x3f) | ((color & 0x03) << 6));
	}		
}									//

Передача в буфер еще хуже

 

void Display(void)					//Функция передает содержимое буферов цветов в дисплей LCD
{									//
	setAddrWindow(0, 0, width, height);//Диаппазон, в котором действует автоинкремент
	Set_Pin_DC;						//
	int h = width * height/4;		//Число точек
	int ADR = 0, i;					//Индекс массива
	while (h--)						//Цикл передачи массивов цветов в дисплей
	{								//
		unsigned char LCDByte;
		LCDByte = LCDBUF[ADR];
		
		if(LCDByte & 0x03)			//Foreground
			{						//
				unsigned int short color = Colors[LCDByte & 0x03];
				ST7735_write(color >> 8);	//Старший байт цвета
				ST7735_write(color);//Младший байт цвет
			}						//
		else						//BackGround
			{						//
				ST7735_write(0);	//Старший байт цвета
				ST7735_write(0);	//Младший байт цвета
			}						//


		LCDByte = LCDByte >> 2;		//
		if(LCDByte & 0x03)			//Foreground
			{						//
				unsigned int short color = Colors[LCDByte & 0x03];
				ST7735_write(color >> 8);	//Старший байт цвета
				ST7735_write(color);//Младший байт цвет
			}						//
		else						//BackGround
			{						//
				ST7735_write(0);	//Старший байт цвета
				ST7735_write(0);	//Младший байт цвета
			}						//


		LCDByte = LCDByte >> 2;		//
		if(LCDByte & 0x03)			//Foreground
			{						//
				unsigned int short color = Colors[LCDByte & 0x03];
				ST7735_write(color >> 8);	//Старший байт цвета
				ST7735_write(color);//Младший байт цвет
			}						//
		else						//BackGround
			{						//
				ST7735_write(0);	//Старший байт цвета
				ST7735_write(0);	//Младший байт цвета
			}						//
	
			LCDByte = LCDByte >> 2;	//
			if(LCDByte)				//Foreground
			{						//
				unsigned int short color = Colors[LCDByte & 0x03];
				ST7735_write(color >> 8);	//Старший байт цвета
				ST7735_write(color);//Младший байт цвет
			}						//
		else						//BackGround
			{						//
				ST7735_write(0);	//Старший байт цвета
				ST7735_write(0);	//Младший байт цвета
			}						//	
			
		ADR++;						//
	}								//
	for(int i=0; i < width * height/2; i++)
		{							//Очистка видеобуфера
			LCDBUF[i] = 0;			//
		}							//
}									//

Почему - то не получилось запихнуть в цикл. Так не работает:

		for(i = 0; i > 4; i++)
			{
				if(LCDByte & 0x03)	//Foreground
					{				//
						unsigned int short color = Colors[LCDByte & 0x03];
						ST7735_write(color >> 8);	//Старший байт цвета
						ST7735_write(color);//Младший байт цвет
					}				//
				else				//BackGround
					{				//
						ST7735_write(0);//Старший байт цвета
						ST7735_write(0);//Младший байт цвета
					}				//
			LCDByte = LCDByte >> 2;			//	
			}

 

Share this post


Link to post
Share on other sites
2 hours ago, scifi said:

Отступы - огонь! :good2:

Тут куда ни плюнь - все огонь :biggrin:

Share this post


Link to post
Share on other sites

а вот эти вот ручные разворачивания всевозможных вариантов они зачем? особенно отдельная проверка на 0.

 

write_buffer(x, y, color, const N){  //N=0,1,2,3  =>  1,2,4,8 bpp
  idx = (x + y * WIDTH);
  mask = (1 << (1 << N)) - 1;
  shift = (idx & ((1 << (3-N))-1));
  buff[idx >> (3-N)] = buff[idx >> (3-N)] & (mask << shift) | ((color & mask) << shift);
}

read_buffer(x, y, const N){
  idx = (x + y * WIDTH);
  mask = (1 << (1 << N)) - 1;
  shift = (idx & ((1 << (3-N))-1));
  return (buff[idx >> (3-N)] >> shift) & mask;
}


 

Share this post


Link to post
Share on other sites
4 hours ago, _pv said:

а вот эти вот ручные разворачивания всевозможных вариантов они зачем? особенно отдельная проверка на 0.

Еще круче. Но этот вариант не работает - часть пикселей другого цвета и сдвинуто по оси Х.

void drawPixel(unsigned char x, unsigned char y, unsigned char color) 
{									//
#define N 2 						//N = 0, 1, 2, 3  =>  1, 2, 4, 8 bpp
  unsigned int idx = (x + y * width);
  unsigned char mask = (1 << (1 << N)) - 1;
  unsigned int shift = (idx & ((1 << (3-N))-1));
  LCDBUF[idx >> (3-N)] = (LCDBUF[idx >> (3-N)] & (mask << shift)) | ((color & mask) << shift);
}	

Для 4-х битового режима. Чтение буфера не менял. Только запись. Строка 

 

LCDBUF[(x+y*160)/2] = (LCDBUF[(x+y*160)/2] & (0xF0 >> (4*(x&1)))) | ((color & 0x0F) << (4*(x&1)));

исправно работает. Понять в чем причина не смог пока.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now