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

без SDRAM или SRAM нужного размера под видео буфер не имеет практического смысла запускать

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


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

без SDRAM или SRAM нужного размера под видео буфер не имеет практического смысла запускать

Необходимо выводить только примитивы в виде кнопок и текст. Хотя убийственная мысль, что на каждый пиксель экрана необходимо минимум два байта постоянно перезаписываемой памяти, всё больше проникает в мозг. Может есть какие-то уловки с FLASH или SD картой, или ещё какие-то заклинания?!

 

Ищите где производится инициализация LTDC и смотрите где находится видеобуфер

 

Единственное указание на видеобуфер находится в инициализации слоя 1, пока что-то делать с ним боюсь, только расширил массив до 45000,но это - мёртвому припарки.

   displayLayer1.WindowX0 = 10;
   displayLayer1.WindowX1 = 790;
   displayLayer1.WindowY0 = 10;
   displayLayer1.WindowY1 = 470;
   displayLayer1.PixelFormat = LTDC_PIXEL_FORMAT_ARGB4444;
   displayLayer1.Alpha = 255;
   displayLayer1.Alpha0 = 250;
   displayLayer1.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
   displayLayer1.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
   displayLayer1.FBStartAdress = (uint32_t)&aBufferResult;
   displayLayer1.ImageWidth = 0;
   displayLayer1.ImageHeight = 0;
   displayLayer1.Backcolor.Blue = 250;
   displayLayer1.Backcolor.Green = 0;
   displayLayer1.Backcolor.Red = 200;

   HAL_LTDC_ConfigLayer(&displayTypeDef, &displayLayer1, 0);

 

 

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


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

под ваш LCD нужен видео буфер 800*480*2 иначе просто нет смысла возится (ИМХО). Или переходите на маленький экран, что бы разместить видео буфер во внутреннем ОЗУ. Самый менее затратный вариант взять 429Disco, отпаять родной LCD и сделать переходную плату под нужный LCD, а потом уже разводить свою, при рабочем программе (или готовый DevKit).

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


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

Необходимо выводить только примитивы в виде кнопок и текст. Хотя убийственная мысль, что на каждый пиксель экрана необходимо минимум два байта постоянно перезаписываемой памяти, всё больше проникает в мозг. Может есть какие-то уловки с FLASH или SD картой, или ещё какие-то заклинания?!

Вы бы почитали мой пост предварительно. Тогда бы поняли что DMA2D целесообразен только в режиме 16 или 24-битного цвета.

...

Давайте поясню на пальцах. В МК есть 2 совершенно независимых узла: LTDC (контроллер дисплея) и DMA2D (ускоритель, но фактически контроллер прямого доступа к памяти позволяющий работать с прямоугольными областями памяти).

LTDC фактически отображает область памяти (видеобуфер) на экран. А с помощью DMA2D вы можете модифицировать ваш видеобуфер. То есть сам DMA2D к дисплею никакого отношения не имеет. Поскольку в экране у вас ничего не хранится, то видеобуфер должен быть обязательно. Там находится то, что отображается на дисплее.

Самый экономный режим для вашего МК - 8 бит (L8 - 256 цветов из палитры 16 бит или аналогичный AL44 - палитра 16 цветов с 16 градациями яркости). Для реализации потребуется 800*480 = 384 кб. У Вашего контроллера лишь 256.

Выхода 3.

1) Добавить память внешнюю. Но на проводах не запаяешь. Работать не будет. Придётся переразводить плату.

2) Применить дисплей с меньшим разрешением. Например 4.3" 480*272 = 130кб. Качество картинки будет описанное выше. DMA2D будет использоваться ограниченно (только копирование и заливка).

3) Применить дисплей с собственным контроллером типа 1963 или другим. Там память находится на самом дисплее. DMA2D в этом случае теряет смысл.

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


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

Всем спасибо большое за ответ!!!

Понял всю фатальность ситуации, что запуск моей платы снова отодвинут на этап создания паттернов в PCAD.

Для себя на пальцах представил ОЗУ, как участок земли определённой площади, которым я обладаю (в моём случае - 256 кв. м).

Видеобуфер - это полотно, которое я могу расстелить в пределах моего участка. Полотно, зараза, большое.

Пиксели - это кубики с площадью основания >= 2 кв.м.

И чтобы мне расстелить полотно, нужно купить участок побольше, можно и в другом районе, дабы курьерская служба DMA2D может доставить кубики-пиксели куда угодно)

Уважаемый SasaVitebsk, я ведь в случае варианта 2 могу не брать другой экран, а на своём задать область размером, допустим 400х300 на слое 1? Или нужно вначале инициализировать экран конкретно под это разрешение?

Пока не выходит, хотя создал uint16_t aBufferResult[95000] (больше не создаётся). Может нужно как-то по-другому задавать видеобуфер? Тут мои знания уже конкретно плывут(

 

 

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


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

В доке на МК имеется достаточно детальное описание как программируется дисплей.

Вы сможете слегка уменьшить отображаемое поле. Но в целом, TFT дисплей это всё же не телевизор и поля с краёв будут небольшими.

То есть я думаю вас это не спасёт. Хотя я не пробовал, честно скажу.

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


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

а на своём задать область размером, допустим 400х300 на слое 1? Или нужно вначале инициализировать экран конкретно под это разрешение?

Нужно проинициализировать экран со всеми таймингами под полное разрешение,

но при инициализации слоев (а именно они используют видеопамять) можно указать буфера меньшего размера.

Границы будут залиты цветом фона, который можно выбрать.

Можно один из слоев натравить на ПЗУ, тогда будет выводится статический логотип к примеру.

Можно попробовать анимировать этот логотип, перезависывая адрес начала видеобуфера синхронно с ходом луча :)

 

PS. Я так делал - работает, но при определенных соотношениях размеров.

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


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

Нужно проинициализировать экран со всеми таймингами под полное разрешение,

но при инициализации слоев (а именно они используют видеопамять) можно указать буфера меньшего размера.

Границы будут залиты цветом фона, который можно выбрать.

 

Именно так и сделал - задал массив aBufferResult при инициализации слоя 1, сделал заполнение 2х областей. Дык, всё равно заливаются линии, а не области!

DSC_0077.jpg

 

Видимо, прокладка между рулём и сиденьем износилась)

Подскажите, пожалуйста, как корректно задать видеобуфер - видимо я это совсем через пень-колоду делаю.

 

 

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


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

Кусок кода покажете?

#define PIXELWIDHT			  2

#define LCD_WIDTH		800
#define LCD_HEIGHT		480

#define HFP 	40
#define HSYNC   48
#define HBP 	40

#define VFP 	13
#define VSYNC 	3
#define VBP 	29



#define ACTIVE_W (HSYNC + LCD_WIDTH + HBP - 1)
#define ACTIVE_H (VSYNC + LCD_HEIGHT + VBP - 1)
#define DISP_ACCUM_HORIZ_BACKPORCH  (HSYNC + HBP - 1)
#define DISP_ACCUM_VERT_BACKPORCH  (VSYNC + VBP - 1)
#define TOTAL_WIDTH  (HSYNC + HBP + LCD_WIDTH + HFP - 1)
#define TOTAL_HEIGHT (VSYNC + VBP + LCD_HEIGHT + VFP - 1)

uint16_t aBufferResult[95000];

void Screen_Init(void)
{
  LTDC_HandleTypeDef displayTypeDef;
  LTDC_LayerCfgTypeDef displayLayer1;
  LTDC_LayerCfgTypeDef displayLayer2;

GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5| GPIO_PIN_6|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;  
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = 14;

HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);  

GPIO_InitStruct.Pin = GPIO_PIN_10| GPIO_PIN_11;

HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); 

GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1| GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_9|GPIO_PIN_10;

HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);  

GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3| GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_1
4|GPIO_PIN_15;

HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

GPIO_InitStruct.Pin =  GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;  
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); 

HAL_GPIO_WritePin(GPIOE, GPIO_PIN_12, 1);   

 __LTDC_CLK_ENABLE(); 

// PLL 

/* LCD clock configuration */
 /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 MHz */
 /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 MHz */
 /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 MHz */
 /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_4 = 38.4/4 = 9.6MHz */
 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
 PeriphClkInitStruct.PLLSAI.PLLSAIN = 192;
 PeriphClkInitStruct.PLLSAI.PLLSAIR = 5;
 PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_4;
 HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);  

 // enable clock for LTDC 
 RCC->APB2ENR |= RCC_APB2ENR_LTDCEN;

  // LTDC
  HAL_LTDC_Init(&displayTypeDef);
  displayTypeDef.Instance = LTDC;
  displayTypeDef.Init.HSPolarity = LTDC_HSPOLARITY_AL;
  displayTypeDef.Init.VSPolarity = LTDC_VSPOLARITY_AL;
  displayTypeDef.Init.DEPolarity = LTDC_DEPOLARITY_AL;
  displayTypeDef.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
  displayTypeDef.Init.HorizontalSync = HSYNC-1;
  displayTypeDef.Init.VerticalSync = VSYNC-1;
  displayTypeDef.Init.AccumulatedHBP = DISP_ACCUM_HORIZ_BACKPORCH;
  displayTypeDef.Init.AccumulatedVBP = DISP_ACCUM_VERT_BACKPORCH;
  displayTypeDef.Init.AccumulatedActiveW = ACTIVE_W;
  displayTypeDef.Init.AccumulatedActiveH = ACTIVE_H;
  displayTypeDef.Init.TotalWidth = TOTAL_WIDTH;
  displayTypeDef.Init.TotalHeigh = TOTAL_HEIGHT;
  displayTypeDef.Init.Backcolor.Blue = 200;
  displayTypeDef.Init.Backcolor.Green = 0;
  displayTypeDef.Init.Backcolor.Red = 200;

  HAL_LTDC_Init(&displayTypeDef);

  // Layer 1
  displayLayer1.WindowX0 = 210;
  displayLayer1.WindowX1 = 590;
  displayLayer1.WindowY0 = 100;
  displayLayer1.WindowY1 = 380;
  displayLayer1.PixelFormat = LTDC_PIXEL_FORMAT_ARGB4444;
  displayLayer1.Alpha = 255;
  displayLayer1.Alpha0 = 250;
  displayLayer1.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
  displayLayer1.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
  displayLayer1.FBStartAdress = (uint32_t)&aBufferResult;
  displayLayer1.ImageWidth = 0;
  displayLayer1.ImageHeight = 0;
  displayLayer1.Backcolor.Blue = 250;
  displayLayer1.Backcolor.Green = 0;
  displayLayer1.Backcolor.Red = 200;

  HAL_LTDC_ConfigLayer(&displayTypeDef, &displayLayer1, 0);

}

static void DMA2D_Config(void)
{  
  __HAL_RCC_DMA2D_CLK_ENABLE();
 /* Register to memory mode with ARGB4444 as colorMode */  
 Dma2dHandle.Init.Mode		 = DMA2D_R2M;
 Dma2dHandle.Init.ColorMode	= DMA2D_ARGB4444;
 Dma2dHandle.Init.OutputOffset = 0x0;	 

 Dma2dHandle.XferCpltCallback  = TransferComplete;
 Dma2dHandle.XferErrorCallback = TransferError;
 Dma2dHandle.Instance		  = DMA2D;	

 /* DMA2D Initialization */
 if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK) 
 {

 }  
}

static void _DMA_Fill(void * pDst, int xSize, int ySize, int OffLine, uint32_t ColorIndex) {

 DMA2D->CR	  = 0x00030000UL | (1 << 9);		 // Register to memory and TCIE
 DMA2D->OCOLR   = ColorIndex;					  // Color to be used
 DMA2D->OMAR	= (uint32_t)pDst;					   // Destination address
 DMA2D->OOR	 = OffLine;						 // Destination line offset
 DMA2D->OPFCCR  = 4;					 // Defines the number of pixels to be transfered
 DMA2D->NLR	 = ((uint32_t)xSize << 16) | ySize; // Size configuration of area to be transfered
 DMA2D->CR	 |= 1;							   // Start operation
 //
 // Wait until transfer is done
 //
 while (DMA2D->CR & DMA2D_CR_START) {
//__WFI();										// Sleep until next interrupt
 }

 

_DMA_Fill(aBufferResult+10, 10, 10, 0, 0x1F0A);
_DMA_Fill(aBufferResult+200, 20, 2, 0, 0x1C01); 
_DMA_Fill(aBufferResult+300, 50, 20, 0, 0xF0F0);

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!

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


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

Я не спец по HAL, но

  displayLayer1.ImageWidth = 0;
   displayLayer1.ImageHeight = 0;

по-моему, не должны быть нулевыми.

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


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

Я не спец по HAL, но

  displayLayer1.ImageWidth = 0;
   displayLayer1.ImageHeight = 0;

по-моему, не должны быть нулевыми.

почему-то, когда они не нулевые, картинка вообще безобразная

Пытался выставлять 380х280

 

DSC_0084.jpg

 

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


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

Попробуйте 400x240.

Попробуйте записать в видеопамять напрямую, без DMA2D.

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


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

Когда требуется сложить два слоя с разным форматом и разной площадью - то смещение считается не в пикселах, а в байтах!!! Точно так-же как и в простом dma.

Сам модуль DMA2D достаточно тупой для таких подсчётов, он просто гонит поток данных через свою матрицу, заниматься расчётами приходится пользователю. Перед смешиванием оба потока преобразуются в ARGB 32бита, и выхлоп уже считается в пикселах.

 

Для того чтобы юзать DMA2D в полном масштабе - придётся написать собственную функцию, с прямым обращением в регистры. При этом глубина изменений (количество меняемых регистров) - напрямую зависит от разнообразности режимов. Универсальный модуль есно меняет всё, но и запускается медленнее всех, хал - это универсальный способ!!! Посему выбирается некий компромисс, с отбрасыванием неиспользуемых режимов - вот тогда будет всё летать.

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


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

Такая запись конечно же ошибка.

displayLayer1.ImageWidth = 0;

displayLayer1.ImageHeight = 0;

Если смотреть функцию LTDC_SetConfig() то она записывает в регистр LTDC_LxCFBLR

 

CFBP[17:0]=displayLayer1.ImageWidth*2 (для ARGB4444 ) Сolor frame buffer pitch (по смыслу длина строки в байтах смысл pitch не смог перевести )

CFBLL[12:0]= (displayLayer1.WindowX1- displayLayer1.WindowX0)*2 (для ARGB4444) Color Frame Buffer Line Length которые задают длину строки в байтах плюс 3.

Короче одно другое повторяет но на 3 больше если по крестьянски сказать.

 

А в регистр LTDC_LxCFBLNR = displayLayer1.ImageHeight который определяет количество линий в color frame buffer.

Так что .ImageWidth ImageHeight не могут быть 0 и даже больше они должны четко соответствовать и тому что задано в

displayLayer1.WindowX1

displayLayer1.WindowX0

displayLayer1.WindowY1

displayLayer1.WindowY0

 

Делал для 480*272 экрана и эти параметры задавал такие

pLayerCfg.WindowX0 = 0;

pLayerCfg.WindowX1 = 480;

pLayerCfg.WindowY0 = 0;

pLayerCfg.WindowY1 = 272;

pLayerCfg.ImageWidth = 480;

pLayerCfg.ImageHeight = 272;

 

 

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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