cancel
Showing results for 
Search instead for 
Did you mean: 

TouchGFX DSI display, not coming out of standby mode.

KDubo
Associate II

Hello @Romain DIELEMAN​ , @Martin KJELDSEN​, I see that you have a lot of replies on the TouchGFX so I hope it's ok that I address you directly. I am running a low-power application with a DSI display and TouchGFX 13 (will update to latest eventually). The problem that I have is that I cannot bring the display out of power off mode without deleting and re-creating the TouchGFX task. My ideal approach would be to simply stop the tick (seem like the suggestion for this is to stop LTDC interrupt via __HAL_LTDC_DISABLE(&hltdc); / __HAL_LTDC_ENABLE(&hltdc). I've also tried touchgfx::HAL::getInstance()->disableInterrupts(); / touchgfx::HAL::getInstance()->enableInterrupts();. But it seems like whenever the interrupts are stopped, I am unable to get the tick running again - DSI_IRQHandler stoppes triggering.

My display power-off consists simply of issuing required DSI commands, then pulling power to the supply. Upon power-on I can tell that the display is active, but is not being refreshed by the application. If I delete and recreate the TouchGFX task in RTOS, this is resolved, but I believe there should be a way to kick start the application without needing to re-init the task. I suppose the main question is, how to restart Vsync / DSI interrupts after they've been disabled. Any thoughts on this would be very much appreciated.

1 ACCEPTED SOLUTION

Accepted Solutions
KDubo
Associate II

Solved - I had to add the following after display re-initialization:

  LCD_force_refresh();

  LCD_ReqTear();

View solution in original post

4 REPLIES 4
KDubo
Associate II

Code that is currently used to suspend / resume display operation:

void GRAPHICS_Suspend(void)
{
   if(gui_state & GUI_STATE_INITALIZED)
   {
      if(gui_state & (GUI_STATE_ACTIVE | GUI_STATE_IDLE))
      {
         gui_state = (GUI_STATE_INITALIZED | GUI_STATE_SUSPENDED);
         
         //issue CTP and display sleep commands and power off:
         display_suspend();
 
         /* Stop and then deInitialize the Touch Screen Controller */
         BSP_TS_ITClear();
         BSP_TS_DeInit();
 
         // Disable DSI interrupts to stop screen refreshing
         touchgfx::HAL::getInstance()->disableInterrupts();
         __HAL_LTDC_DISABLE(&hltdc);
 
         //disable touch interrupt
         gpio_disable_interrupt(DISPLAY_INT_N_Pin);
 
         //display_suspend();
 
		// Delete GUI task
//		vTaskDelete(m_gui_task);
//		m_gui_task = NULL;
         
         Log(DISPLAY, "Graphics suspended");
         RESET_LOW_POWER_INHIBIT(LPIF_DISP_ACTIVE);
      }
      else
      {
         Log(DISPLAY, "Graphics already suspended");
      }
   }
   else
   {
      Log(DISPLAY, "Graphics not initialized");
   }
}
 
void GRAPHICS_Resume(void)
{
	if(gui_state & GUI_STATE_INITALIZED)
	{
		// Make sure GFX are not suspended and OSPI is in memory mapped mode
		if(!(gui_state & GUI_STATE_ACTIVE) && ospi_mem_mapped_enable(true))
		{
			if(gui_state & GUI_STATE_IDLE)
			{
				display_exit_idle();
			}
			else if(gui_state & GUI_STATE_SUSPENDED)
			{
				//set sleep inhibit flag
				SET_LOW_POWER_INHIBIT(LPIF_DISP_ACTIVE);
 
				// Set touch screen interrupt callback
				gpio_enable_interrupt(DISPLAY_INT_N_Pin);
 
				// Re-enable DSI interrupts to resume screen refresh
				touchgfx::HAL::getInstance()->enableInterrupts();
				__HAL_LTDC_ENABLE(&hltdc);
				display_resume();
 
				// Create GUI task
//				if (pdPASS != xTaskCreate(gui_task,
//										"GUI",
//										GUI_STACK_SIZE,
//										NULL,
//										GUI_PRIORITY,
//										&m_gui_task))
//				{
//					Error_Handler(GUI_ERROR);
//				}
 
				// Force display refresh in case where display is uninitialized and then reinitialized
//				STM32HAL_DSI::forceRefresh();
 
				Log(DISPLAY, "Graphics resumed");
			}
 
			gui_state = (GUI_STATE_ACTIVE | GUI_STATE_INITALIZED);
			reset_gui_timer();
		}
		else
		{
			Log(DISPLAY, "Graphics already active");
		}
	}
	else
	{
		Log(DISPLAY, "Graphics not initialized");
	}
}
 
void display_resume(void)
{
	uint8_t ScanLineParams[2];
	uint16_t scanline = (GFXMMU_LCD_SIZE - 10);
 
	LCD_PowerOn();
 
    //switch to command bank 07h, set mfg config
    HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xFE, 0x07);
    HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0x15, 0x04);
 
    //switch to command bank 00h (user)
    HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xFE, 0x00);
 
//    HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, DSI_SET_TEAR_ON, 0x00);
 
    //Default settings changed for TouchGFX
    // Set tear off
    HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, DSI_SET_TEAR_OFF, 0x00); // 0x34 -> 0x00
    /* Set DSI mode to internal timing added vs ORIGINAL for Command mode */
    HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P1, 0xC2, 0x00);
    //End Default settings changed for TouchGFX
 
    //Set column address
    uint8_t InitParam1[4] = { 0x00, 0x0C, 0x01, 0xD1 };
    HAL_DSI_LongWrite(&hdsi, 0, DSI_DCS_LONG_PKT_WRITE, 4, DSI_SET_COLUMN_ADDRESS, InitParam1);
 
    //Set row address
    uint8_t InitParam2[4] = { 0x00, 0x00, 0x01, 0xC5 };
    HAL_DSI_LongWrite(&hdsi, 0, DSI_DCS_LONG_PKT_WRITE, 4, DSI_SET_PAGE_ADDRESS, InitParam2);
 
    //Set display brightness to max - 0xFF
    HAL_DSI_ShortWrite(&hdsi, 0, DSI_GEN_SHORT_PKT_WRITE_P2, 0x51, 0xFF);
 
    //Exit sleep mode
    HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, DSI_EXIT_SLEEP_MODE, 0x00);
 
    HAL_Delay(50);
 
    //Turn Display On
    if (HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, DSI_SET_DISPLAY_ON, 0x00) != HAL_OK)
    {
        Error_Handler(GUI_ERROR);
    }
 
    ScanLineParams[0] = scanline >> 8;
    ScanLineParams[1] = scanline & 0x00FF;
 
    HAL_DSI_LongWrite(&hdsi, 0, DSI_DCS_LONG_PKT_WRITE, 2, DSI_SET_TEAR_SCANLINE, ScanLineParams);
 
 
	//re-init the CTP
	int nb_tries = 5;
 
	/* Initialize the Touch Screen Controller */
	while (nb_tries > 0)
	{
		if (BSP_TS_Init(GUI_DISPLAY_WIDTH, GUI_DISPLAY_HEIGHT) == TS_OK)
		{
			/* Enable TS interrupt */
			if (BSP_TS_ITConfig() != TS_OK)
			{
				Error_Handler(GUI_ERROR);
			}
			break;
		}
		nb_tries--;
	}
 
	if (nb_tries <= 0)
	{
		Error_Handler(GUI_ERROR);
	}
 
}
 
void display_suspend()
{
	//turn off all pixels
	HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, 0x22, 0x00);
	//turn off display
	HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, DSI_SET_DISPLAY_OFF, 0x00);
	//enter sleep mode
	HAL_DSI_ShortWrite(&hdsi, 0, DSI_DCS_SHORT_PKT_WRITE_P0, DSI_ENTER_SLEEP_MODE, 0x00);
	//turn off display power
	LCD_PowerOff();
}

KDubo
Associate II

Solved - I had to add the following after display re-initialization:

  LCD_force_refresh();

  LCD_ReqTear();

Good to hear you made it work and thanks for sharing your code + fix :thumbs_up:

/Romain

ladislas
Associate II

Dear @KDubo​ 

It seems that I'm facing a very similar issue! See https://community.st.com/s/feed/0D53W00001yzBQ8SAM

We are using the STM32F79 -- which MCU are you using?

We are not using TouchGFX, so I don't know what LCD_force_refresh(); and LCD_ReqTear(); does, could you share the code please?

Also what's the difference in your code between display suspend/resume and graphics suspend/resume?

In our case we are only displaying images or playing video, which works great. Our issue is really focused on going into STOP MODE and waking up with a working system.

Any help would be greatly appreciated :)