Перейти к содержанию
    

Подскажите по буферу 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.

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

Изменено пользователем Димон Безпарольный

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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)]);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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;			//
		}							//
}									//

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

Изменено пользователем Димон Безпарольный

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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;			//
		}							//
}									//

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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;			//	
			}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а вот эти вот ручные разворачивания всевозможных вариантов они зачем? особенно отдельная проверка на 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;
}


 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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)));

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...