Rash 0 22 августа, 2016 Опубликовано 22 августа, 2016 · Жалоба без SDRAM или SRAM нужного размера под видео буфер не имеет практического смысла запускать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adrvyho 0 22 августа, 2016 Опубликовано 22 августа, 2016 · Жалоба без 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); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Rash 0 23 августа, 2016 Опубликовано 23 августа, 2016 · Жалоба под ваш LCD нужен видео буфер 800*480*2 иначе просто нет смысла возится (ИМХО). Или переходите на маленький экран, что бы разместить видео буфер во внутреннем ОЗУ. Самый менее затратный вариант взять 429Disco, отпаять родной LCD и сделать переходную плату под нужный LCD, а потом уже разводить свою, при рабочем программе (или готовый DevKit). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 23 августа, 2016 Опубликовано 23 августа, 2016 · Жалоба Необходимо выводить только примитивы в виде кнопок и текст. Хотя убийственная мысль, что на каждый пиксель экрана необходимо минимум два байта постоянно перезаписываемой памяти, всё больше проникает в мозг. Может есть какие-то уловки с 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 в этом случае теряет смысл. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adrvyho 0 24 августа, 2016 Опубликовано 24 августа, 2016 · Жалоба Всем спасибо большое за ответ!!! Понял всю фатальность ситуации, что запуск моей платы снова отодвинут на этап создания паттернов в PCAD. Для себя на пальцах представил ОЗУ, как участок земли определённой площади, которым я обладаю (в моём случае - 256 кв. м). Видеобуфер - это полотно, которое я могу расстелить в пределах моего участка. Полотно, зараза, большое. Пиксели - это кубики с площадью основания >= 2 кв.м. И чтобы мне расстелить полотно, нужно купить участок побольше, можно и в другом районе, дабы курьерская служба DMA2D может доставить кубики-пиксели куда угодно) Уважаемый SasaVitebsk, я ведь в случае варианта 2 могу не брать другой экран, а на своём задать область размером, допустим 400х300 на слое 1? Или нужно вначале инициализировать экран конкретно под это разрешение? Пока не выходит, хотя создал uint16_t aBufferResult[95000] (больше не создаётся). Может нужно как-то по-другому задавать видеобуфер? Тут мои знания уже конкретно плывут( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 25 августа, 2016 Опубликовано 25 августа, 2016 · Жалоба В доке на МК имеется достаточно детальное описание как программируется дисплей. Вы сможете слегка уменьшить отображаемое поле. Но в целом, TFT дисплей это всё же не телевизор и поля с краёв будут небольшими. То есть я думаю вас это не спасёт. Хотя я не пробовал, честно скажу. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 25 августа, 2016 Опубликовано 25 августа, 2016 · Жалоба а на своём задать область размером, допустим 400х300 на слое 1? Или нужно вначале инициализировать экран конкретно под это разрешение? Нужно проинициализировать экран со всеми таймингами под полное разрешение, но при инициализации слоев (а именно они используют видеопамять) можно указать буфера меньшего размера. Границы будут залиты цветом фона, который можно выбрать. Можно один из слоев натравить на ПЗУ, тогда будет выводится статический логотип к примеру. Можно попробовать анимировать этот логотип, перезависывая адрес начала видеобуфера синхронно с ходом луча :) PS. Я так делал - работает, но при определенных соотношениях размеров. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adrvyho 0 25 августа, 2016 Опубликовано 25 августа, 2016 · Жалоба Нужно проинициализировать экран со всеми таймингами под полное разрешение, но при инициализации слоев (а именно они используют видеопамять) можно указать буфера меньшего размера. Границы будут залиты цветом фона, который можно выбрать. Именно так и сделал - задал массив aBufferResult при инициализации слоя 1, сделал заполнение 2х областей. Дык, всё равно заливаются линии, а не области! Видимо, прокладка между рулём и сиденьем износилась) Подскажите, пожалуйста, как корректно задать видеобуфер - видимо я это совсем через пень-колоду делаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 25 августа, 2016 Опубликовано 25 августа, 2016 · Жалоба Именно так и сделал Кусок кода покажете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adrvyho 0 25 августа, 2016 Опубликовано 25 августа, 2016 (изменено) · Жалоба Кусок кода покажете? #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); Изменено 25 августа, 2016 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 25 августа, 2016 Опубликовано 25 августа, 2016 · Жалоба Я не спец по HAL, но displayLayer1.ImageWidth = 0; displayLayer1.ImageHeight = 0; по-моему, не должны быть нулевыми. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adrvyho 0 25 августа, 2016 Опубликовано 25 августа, 2016 · Жалоба Я не спец по HAL, но displayLayer1.ImageWidth = 0; displayLayer1.ImageHeight = 0; по-моему, не должны быть нулевыми. почему-то, когда они не нулевые, картинка вообще безобразная Пытался выставлять 380х280 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 25 августа, 2016 Опубликовано 25 августа, 2016 · Жалоба Попробуйте 400x240. Попробуйте записать в видеопамять напрямую, без DMA2D. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AVI-crak 0 25 августа, 2016 Опубликовано 25 августа, 2016 · Жалоба Когда требуется сложить два слоя с разным форматом и разной площадью - то смещение считается не в пикселах, а в байтах!!! Точно так-же как и в простом dma. Сам модуль DMA2D достаточно тупой для таких подсчётов, он просто гонит поток данных через свою матрицу, заниматься расчётами приходится пользователю. Перед смешиванием оба потока преобразуются в ARGB 32бита, и выхлоп уже считается в пикселах. Для того чтобы юзать DMA2D в полном масштабе - придётся написать собственную функцию, с прямым обращением в регистры. При этом глубина изменений (количество меняемых регистров) - напрямую зависит от разнообразности режимов. Универсальный модуль есно меняет всё, но и запускается медленнее всех, хал - это универсальный способ!!! Посему выбирается некий компромисс, с отбрасыванием неиспользуемых режимов - вот тогда будет всё летать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
pvo125 0 1 сентября, 2016 Опубликовано 1 сентября, 2016 · Жалоба Такая запись конечно же ошибка. 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; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться