Graphics processing using LTDC and DMA2D example
Dependencies: mbed BSP_DISCO_F746NG
Revision 0:0e534ad140f5, committed 2021-12-09
- Comitter:
- codebreaker7
- Date:
- Thu Dec 09 13:36:25 2021 +0000
- Commit message:
- Initial commit for graphics processing project example
Changed in this revision
diff -r 000000000000 -r 0e534ad140f5 BSP_DISCO_F746NG.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BSP_DISCO_F746NG.lib Thu Dec 09 13:36:25 2021 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/teams/ST/code/BSP_DISCO_F746NG/#fe313c53cdb5
diff -r 000000000000 -r 0e534ad140f5 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Dec 09 13:36:25 2021 +0000 @@ -0,0 +1,277 @@ +/** + ****************************************************************************** + * @file main.c + * @author Ac6 + * @version V1.0 + * @date 01-December-2013 + * @brief Default main function. + ****************************************************************************** +*/ + + +#include "stm32f7xx.h" +#include "stm32746g_discovery.h" +#include "stm32746g_discovery_lcd.h" +#include "stm32746g_discovery_ts.h" +#include "stm32f7xx_hal_dma2d.h" + +#define LCD_INMEM_BUF_ADDR (LCD_FB_START_ADDRESS + (480 * 272) * 4) // address to draw off-screen +#define BUFFER_WIDTH 272 +#define BUFFER_HEIGHT 240 +#define INMEM_BUF_SIZE (BUFFER_WIDTH * BUFFER_HEIGHT * 4) +#define CUBE_SIDE_SIZE 15 +#define CUBES_WIDTH 17 +#define CUBES_HEIGHT 15 + +struct game_state { + int cur_car_pos; + int obstacle_posx; + int obstacle_posy; + int scores; + int prev_car_pos; + int prev_obstacle_posy; +}; + +struct game_state gs = {7, 1, 1, 0, 7 ,1}; + +DMA2D_HandleTypeDef dma2d; + +void EXTI15_10_IRQHandler(void) { + HAL_GPIO_EXTI_IRQHandler(TS_INT_PIN); +} + +void SystemClock_Config(void) +{ + RCC_ClkInitTypeDef RCC_ClkInitStruct; + RCC_OscInitTypeDef RCC_OscInitStruct; + HAL_StatusTypeDef ret = HAL_OK; + + /* Enable HSE Oscillator and activate PLL with HSE as source */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 25; + RCC_OscInitStruct.PLL.PLLN = 400; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 8; + + ret = HAL_RCC_OscConfig(&RCC_OscInitStruct); + if(ret != HAL_OK) + { + while(1) { ; } + } + + /* Activate the OverDrive to reach the 200 MHz Frequency */ + ret = HAL_PWREx_EnableOverDrive(); + if(ret != HAL_OK) + { + while(1) { ; } + } + + /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */ + RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; + + ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6); + if(ret != HAL_OK) + { + while(1) { ; } + } + HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); +} + +void DMA2D_Config(void) { + dma2d.Init.ColorMode = DMA2D_ARGB8888; + dma2d.Init.Mode = DMA2D_R2M; + dma2d.Init.OutputOffset = 0; + + dma2d.Instance = DMA2D; + + dma2d.LayerCfg[1].InputAlpha = 0xff; + dma2d.LayerCfg[1].InputOffset = 0; + dma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA; + dma2d.LayerCfg[1].InputColorMode = CM_ARGB8888; + HAL_DMA2D_Init(&dma2d); + HAL_DMA2D_ConfigLayer(&dma2d, 1); +} + +void Init_Field(void) { + int i, j; + // draw first square in R2M mode + HAL_DMA2D_Start(&dma2d, 0xff000000, LCD_INMEM_BUF_ADDR, BUFFER_WIDTH, BUFFER_HEIGHT); + while(HAL_DMA2D_PollForTransfer(&dma2d, 1000) != HAL_OK); + dma2d.Init.OutputOffset = 272 - CUBE_SIDE_SIZE; + HAL_DMA2D_Init(&dma2d); + HAL_DMA2D_Start(&dma2d, 0xffffffff, LCD_INMEM_BUF_ADDR, 15, 15); + while(HAL_DMA2D_PollForTransfer(&dma2d, 1000) != HAL_OK); + // and then just copy this one into necessary position + dma2d.Init.Mode = DMA2D_M2M; + dma2d.Init.OutputOffset = BUFFER_WIDTH - CUBE_SIDE_SIZE; + dma2d.LayerCfg[1].InputOffset = BUFFER_WIDTH - CUBE_SIDE_SIZE; + HAL_DMA2D_Init(&dma2d); + HAL_DMA2D_ConfigLayer(&dma2d, 1); + for (i = 0; i < 15; i++) { + for (j = 0; j < 17; j++) { + if (i == 0 && j == 0) + continue; + HAL_DMA2D_Start(&dma2d, LCD_INMEM_BUF_ADDR, LCD_INMEM_BUF_ADDR + + (4 * (CUBE_SIDE_SIZE + 1) * j) + + (4 * i * (CUBE_SIDE_SIZE + 1) * BUFFER_WIDTH) + , 15, 15); + while(HAL_DMA2D_PollForTransfer(&dma2d, 1000) != HAL_OK); + } + } +} + +//void Draw_Car(void) { +void Draw_Car(uint32_t color, int posx) { + int i, j; + dma2d.Init.Mode = DMA2D_R2M; + dma2d.Init.OutputOffset = BUFFER_WIDTH - CUBE_SIDE_SIZE; + HAL_DMA2D_Init(&dma2d); + // draw in the 11-15 rows according to current position + for (i = 0; i < 4; i++) { + for (j = 0; j < 3; j++) { + if (i == 0 || i == 2) + if (j == 0 || j == 2) + continue; + HAL_DMA2D_Start(&dma2d, color, LCD_INMEM_BUF_ADDR + + //(4 * (gs.cur_car_pos + j) * (CUBE_SIDE_SIZE + 1)) + + (4 * (posx + j) * (CUBE_SIDE_SIZE + 1)) + + (4 * (i + 11) * (CUBE_SIDE_SIZE + 1) * BUFFER_WIDTH), 15, 15); + while (HAL_DMA2D_PollForTransfer(&dma2d, 1000) != HAL_OK); + } + } +} + +//void Draw_Obstacle(void) { +void Draw_Obstacle(uint32_t color, int posy) { + int i, j; + dma2d.Init.Mode = DMA2D_R2M; + dma2d.Init.OutputOffset = BUFFER_WIDTH - CUBE_SIDE_SIZE; + HAL_DMA2D_Init(&dma2d); + // draw obstacle according to game state + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + //if (gs.obstacle_posy + i < 0 || gs.obstacle_posy > 15) + if (posy + i < 0 || posy > 15) + continue; + HAL_DMA2D_Start(&dma2d, color, LCD_INMEM_BUF_ADDR + + (4 * (gs.obstacle_posx + j) * (CUBE_SIDE_SIZE + 1)) + + (4 * (posy + i) * (CUBE_SIDE_SIZE + 1) * BUFFER_WIDTH), 15, 15); + //(4 * (gs.obstacle_posy + i) * (CUBE_SIDE_SIZE + 1) * BUFFER_WIDTH), 15, 15); + while(HAL_DMA2D_PollForTransfer(&dma2d, 1000) != HAL_OK); + } + } +} + +int main(void) +{ + int game_counter = 0; + uint8_t score_str[4]; + + HAL_Init(); + SystemClock_Config(); + + BSP_LCD_Init(); + BSP_LCD_LayerDefaultInit(1, LCD_FB_START_ADDRESS); + BSP_LCD_SelectLayer(1); + BSP_LCD_Clear(0xff000000); + + BSP_TS_Init(480, 272); + BSP_TS_ITConfig(); + + DMA2D_Config(); + // form the in-buffer game field start state + Init_Field(); + Draw_Car(LCD_COLOR_GREEN, gs.cur_car_pos); + Draw_Obstacle(LCD_COLOR_BLUE, gs.obstacle_posy); + dma2d.Init.Mode = DMA2D_M2M; + dma2d.Init.OutputOffset = 480 - 272; + dma2d.LayerCfg[1].InputOffset = 0; + HAL_DMA2D_Init(&dma2d); + HAL_DMA2D_ConfigLayer(&dma2d, 1); + HAL_DMA2D_Start(&dma2d, LCD_INMEM_BUF_ADDR, LCD_FB_START_ADDRESS, BUFFER_WIDTH, BUFFER_HEIGHT); + while(HAL_DMA2D_PollForTransfer(&dma2d, 1000) != HAL_OK); + BSP_LCD_SetBackColor(LCD_COLOR_RED); + BSP_LCD_SetTextColor(LCD_COLOR_RED); + BSP_LCD_FillRect(0, BUFFER_HEIGHT + 1, 90, 30); + BSP_LCD_FillRect(182, BUFFER_HEIGHT + 1, 90, 30); + BSP_LCD_SetBackColor(LCD_COLOR_YELLOW); + BSP_LCD_SetTextColor(LCD_COLOR_YELLOW); + BSP_LCD_DrawHLine(10, 256, 70); + BSP_LCD_DrawLine(10, 256, 20, 266); + BSP_LCD_DrawLine(10, 256, 20, 246); + BSP_LCD_DrawHLine(192, 256, 70); + BSP_LCD_DrawLine(262, 256, 252, 266); + BSP_LCD_DrawLine(262, 256, 252, 246); + BSP_LCD_SetFont(&Font24); + sprintf((char*)score_str, "%d\0", gs.scores); + BSP_LCD_SetTextColor(LCD_COLOR_DARKGREEN); + BSP_LCD_DisplayStringAt(95, 244, (uint8_t*)score_str, LEFT_MODE); + while(1) { + // draw car + if (gs.cur_car_pos != gs.prev_car_pos) { + Draw_Car(LCD_COLOR_WHITE, gs.prev_car_pos); + Draw_Car(LCD_COLOR_GREEN, gs.cur_car_pos); + gs.prev_car_pos = gs.cur_car_pos; + } + // draw obstacle + if (gs.obstacle_posy != gs.prev_obstacle_posy) { + Draw_Obstacle(LCD_COLOR_WHITE, gs.prev_obstacle_posy); + Draw_Obstacle(LCD_COLOR_BLUE, gs.obstacle_posy); + gs.prev_obstacle_posy = gs.obstacle_posy; + } + // update game state + if (game_counter == 10) { + gs.obstacle_posy += 1; + if (gs.obstacle_posy == 17) { + gs.obstacle_posy = -2; + gs.obstacle_posx = (gs.obstacle_posx + 3) % 14; + gs.scores += 1; + sprintf((char*)score_str, "%d\0", gs.scores); + BSP_LCD_DisplayStringAt(95, 244, (uint8_t*)score_str, LEFT_MODE); + } + game_counter = 0; + } + // delay + HAL_Delay(50); + game_counter++; + // draw on screen + dma2d.Init.Mode = DMA2D_M2M; + dma2d.Init.OutputOffset = 480 - 272; + dma2d.LayerCfg[1].InputOffset = 0; + HAL_DMA2D_Init(&dma2d); + HAL_DMA2D_ConfigLayer(&dma2d, 1); + HAL_DMA2D_Start(&dma2d, LCD_INMEM_BUF_ADDR, LCD_FB_START_ADDRESS, BUFFER_WIDTH, BUFFER_HEIGHT); + while(HAL_DMA2D_PollForTransfer(&dma2d, 1000) != HAL_OK); + } +} + +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { + TS_StateTypeDef ts_data; + if (GPIO_Pin == TS_INT_PIN) { + BSP_TS_ITClear(); + HAL_NVIC_DisableIRQ((IRQn_Type)(TS_INT_EXTI_IRQn)); + HAL_Delay(20); + BSP_TS_GetState(&ts_data); + if (ts_data.touchDetected > 0) { + if (ts_data.touchX[0] > 1 && ts_data.touchX[0] < 90 + && ts_data.touchY[0] > 240 && ts_data.touchY[0] < 272) { + if (gs.cur_car_pos > 0) + gs.cur_car_pos -= 1; + } + if (ts_data.touchX[0] > 181 && ts_data.touchX[0] < 272 + && ts_data.touchY[0] > 240 && ts_data.touchY[0] < 272) { + if (gs.cur_car_pos < 14) + gs.cur_car_pos += 1; + } + } + HAL_NVIC_EnableIRQ((IRQn_Type)(TS_INT_EXTI_IRQn)); + BSP_TS_ResetTouchData(&ts_data); + } +}
diff -r 000000000000 -r 0e534ad140f5 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Dec 09 13:36:25 2021 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/ad3be0349dc5 \ No newline at end of file