393 views
in GUI Development by
I have an issue with screen burn-ins on the LPC54628 development board. As a solution I want to lower the screen brightness after one minute of inactivity (last user touch). Once the user again touches the screen the brightness should go back to normal. Is there any way to adjust the brightness in embedded wizard ? Do you have other solutions to this issue ?

1 Answer

0 votes
by

Hello,

the screen brightness is typically controlled by some PWM that can controlled by setting the corresponding register value.

You can either control that brightness setting from your GUI application (e.g. within your application class - see question about screensaver activation) or you can detect the activity / inactivity state directly within the main loop. As soon as there is an update necessary you set full brightness and if there are no updates detected for a longer time, you can reduce the brightness.

Does this answer your question?

Concerning the PWM settings, please have a look to the schematics of the board and the examples provided from NXP concerning PWM usage.

Best regards,

Manfred.

by

Dear Manfred,

Thanks for your quick reply and your suggestions. I tried lowering the backlight intensity by changing the duty cycle of the PWM in the display initialization function "EwBspDisplayInit"  which can be found in ew_bsp_display.c. I changed the duty cycle form 5 (default) to 1 percent but I do no see a noticeable difference in display brightness. 


pwmParam.dutyCyclePercent = 1;

SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 1000U, CLOCK_GetSctClkFreq(), &event);

Is this the PWM setting that you mean or is the display brightness not directly coupled to the backlight intensity.

Best,

Jim
 

by
Hi Jim,

according to the schematics, the backlight is connected to a PWM pin. Please check the examples within the NXP SDK or the NXP forum for more details about the register initialization and necessary PWM settings.

Best regards,

Manfred.
by

Dear Manfred,

On the LPC54628 development board the blacklight is controlled by pin P3_31-SCT0-OUT5 (see attached image).

I soldered a cable to pin 4 (EN) of the AP5724WG-7 and monitored the output on the scope. I found out that the PWM output is not working (possibly due to some faulty clock setup).

I find it strange that in the function "EwBspDisplayInit" which can be found in ew_bsp_display.c (this file was written by embedded wizard) the PWM configuration starts at a duty cycle of 5 percent. Why is this the case ?

I will post a thread on the NXP forum for help regarding the SCT - PWM setup.

Thanks,

Jim

/*******************************************************************************
* FUNCTION:
*   EwBspDisplayInit
*
* DESCRIPTION:
*   The function EwBspDisplayInit initializes the display hardware and returns
*   the display parameter.
*
* ARGUMENTS:
*   aGuiWidth,
*   aGuiHeight   - Size of the GUI in pixel.
*   aDisplayInfo - Display info data structure.
*
* RETURN VALUE:
*   Returns 1 if successful, 0 otherwise.
*
*******************************************************************************/
int EwBspDisplayInit( int aGuiWidth, int aGuiHeight, XDisplayInfo* aDisplayInfo )
{
  sctimer_config_t config;
  sctimer_pwm_signal_param_t pwmParam;
  uint32_t event;
  lcdc_config_t lcdConfig;

  EW_UNUSED_ARG( aGuiWidth );
  EW_UNUSED_ARG( aGuiHeight );

  /* check and clean display info structure */
  if ( !aDisplayInfo )
    return 0;
  memset( aDisplayInfo, 0, sizeof( XDisplayInfo ));

  /* Route Main clock to LCD. */
  CLOCK_AttachClk(kMAIN_CLK_to_LCD_CLK);
  CLOCK_SetClkDiv(kCLOCK_DivLcdClk, 1, true);

  /* Init back light pwm */
  CLOCK_AttachClk(kMAIN_CLK_to_SCT_CLK);
  CLOCK_SetClkDiv(kCLOCK_DivSctClk, 2, true);
  SCTIMER_GetDefaultConfig(&config);
  SCTIMER_Init(SCT0, &config);

  pwmParam.output = kSCTIMER_Out_5;
  pwmParam.level = kSCTIMER_HighTrue;
  pwmParam.dutyCyclePercent = 5;

  SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 1000U, CLOCK_GetSctClkFreq(), &event);

  #if EW_USE_FREE_RTOS == 1

    /* create semaphore for handling double-buffering on V-sync */
    LcdUpdateSemaphore = xSemaphoreCreateBinary();
    xSemaphoreGive( LcdUpdateSemaphore );

  #endif

  LCDC_GetDefaultConfig(&lcdConfig);

  lcdConfig.panelClock_Hz = LCD_PANEL_CLK;
  lcdConfig.ppl = EW_FRAME_BUFFER_WIDTH;
  lcdConfig.hsw = LCD_HSW;
  lcdConfig.hfp = LCD_HFP;
  lcdConfig.hbp = LCD_HBP;
  lcdConfig.lpp = EW_FRAME_BUFFER_HEIGHT;
  lcdConfig.vsw = LCD_VSW;
  lcdConfig.vfp = LCD_VFP;
  lcdConfig.vbp = LCD_VBP;
  lcdConfig.polarityFlags = kLCDC_InvertVsyncPolarity | kLCDC_InvertHsyncPolarity;
  lcdConfig.upperPanelAddr = (uint32_t)EW_FRAME_BUFFER_ADDR;
  lcdConfig.display = kLCDC_DisplayTFT;
  lcdConfig.swapRedBlue = true;

  #if ( EW_FRAME_BUFFER_COLOR_FORMAT == EW_FRAME_BUFFER_COLOR_FORMAT_RGBA8888 )
    lcdConfig.bpp = kLCDC_24BPP;
  #elif ( EW_FRAME_BUFFER_COLOR_FORMAT == EW_FRAME_BUFFER_COLOR_FORMAT_RGB888 )
    lcdConfig.bpp = kLCDC_24BPP;
  #elif ( EW_FRAME_BUFFER_COLOR_FORMAT == EW_FRAME_BUFFER_COLOR_FORMAT_RGB565 )
    lcdConfig.bpp = kLCDC_16BPP565;
  #elif ( EW_FRAME_BUFFER_COLOR_FORMAT == EW_FRAME_BUFFER_COLOR_FORMAT_Index8 )
    lcdConfig.bpp = kLCDC_8BPP;
  #elif ( EW_FRAME_BUFFER_COLOR_FORMAT == EW_FRAME_BUFFER_COLOR_FORMAT_LumA44 )
    lcdConfig.bpp = kLCDC_8BPP;
  #endif

  LCDC_Init(LCD, &lcdConfig, CLOCK_GetLcdClkFreq());

#if EW_USE_DOUBLE_BUFFER == 1

  /* Trigger interrupt at start of every vertical back porch. */
  LCDC_SetVerticalInterruptMode(LCD, kLCDC_StartOfFrontPorch);

#else

  /* Trigger interrupt at start of active video. */
  LCDC_SetVerticalInterruptMode(LCD, kLCDC_StartOfActiveVideo);

#endif

  LCDC_EnableInterrupts(LCD, kLCDC_VerticalCompareInterrupt);

  /* lower interrupt priority needed with FreeRTOS */
  NVIC_SetPriority(APP_LCD_IRQn, 10);
  NVIC_EnableIRQ(APP_LCD_IRQn);

  LCDC_Start(LCD);
  LCDC_PowerUp(LCD);

  /* return the current display configuration */
  aDisplayInfo->FrameBuffer    = (void*)EW_FRAME_BUFFER_ADDR;
  aDisplayInfo->DoubleBuffer   = (void*)EW_DOUBLE_BUFFER_ADDR;
  aDisplayInfo->BufferWidth    = EW_FRAME_BUFFER_WIDTH;
  aDisplayInfo->BufferHeight   = EW_FRAME_BUFFER_HEIGHT;
  aDisplayInfo->DisplayWidth   = EW_DISPLAY_WIDTH;
  aDisplayInfo->DisplayHeight  = EW_DISPLAY_HEIGHT;

  #if EW_USE_DOUBLE_BUFFER == 1
    aDisplayInfo->UpdateMode   = EW_BSP_DISPLAY_UPDATE_NORMAL;
  #else
    aDisplayInfo->UpdateMode   = EW_BSP_DISPLAY_UPDATE_PARTIAL;
  #endif

  return 1;
}

 

 

 

by
Hello Jim,

the different ew_bsp_xxx modules are the interface between the Embedded Wizard GUI application and the underlying board support package (BSP).

The initialization code of the different board components are taken from examples that were provided within the NXP SDK. So we took the initialization code of the display (and the backlight control) as it was shown in some examples.

Maybe you can download our latest version of the Build Environment for LPC54628 (Version 11.00.01) - it contains now the hardware configuration file (LPCXpresso54628.mex). Maybe this is helpful in case that the clock settings are not matching. We also detected some conflicts when we created the mex file.

I hope this helps.

Best regards,

Manfred.
by

For LPC54628 you need to link J14 pin (P3_31) to SCT0,OUT5. See Code below from pin_mux.c

  - {pin_num: J14, peripheral: SCT0, signal: 'OUT, 5', pin_signal: PIO3_31/FC9_RTS_SCL_SSEL1/SCT0_OUT5/CTIMER4_MAT2/SCT0_GPI0/EMC_A(20)}

IOCON->PIO[3][31] = ((IOCON->PIO[3][31] &
                          /* Mask bits to zero which are setting */
                          (~(IOCON_PIO_FUNC_MASK | IOCON_PIO_DIGIMODE_MASK)))

                         /* Selects pin function.
                          * : PORT331 (pin J14) is configured as SCT0_OUT5. */
                         | IOCON_PIO_FUNC(PIO331_FUNC_ALT2)

                         /* Select Analog/Digital mode.
                          * : Digital mode. */
                         | IOCON_PIO_DIGIMODE(PIO331_DIGIMODE_DIGITAL));

SCT0 and PWM initialization in peripherals.c 

/***********************************************************************************************************************
 * SCT0 initialization code
 **********************************************************************************************************************/
/* clang-format off */
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
instance:
- name: 'SCT0'
- type: 'sctimer'
- mode: 'basic'
- custom_name_enabled: 'false'
- type_id: 'sctimer_7973000102117ff9c4fa4742aaf3ccb0'
- functional_group: 'BOARD_InitPeripherals'
- peripheral: 'SCT0'
- config_sets:
  - main:
    - config:
      - clockMode: 'kSCTIMER_System_ClockMode'
      - clockSource: 'SynchronousFunctionClock'
      - clockSourceFreq: 'BOARD_BootClockPLL180M'
      - SCTInputClockSourceFreq: 'custom:0'
      - clockSelect: 'kSCTIMER_Clock_On_Rise_Input_0'
      - enableCounterUnify: 'true'
      - enableBidirection_l: 'false'
      - enableBidirection_h: 'false'
      - prescale_l: '1'
      - prescale_h: '1'
      - outInitState: 'SCTIMER_OUTPUT_5_MASK'
      - inputsync: ''
    - enableIRQ: 'false'
    - interrupt:
      - IRQn: 'SCT0_IRQn'
      - enable_interrrupt: 'enabled'
      - enable_priority: 'false'
      - priority: '0'
      - enable_custom_name: 'false'
    - enableLTimer: 'false'
    - enableHTimer: 'false'
    - pwms:
      - 0:
        - output: 'kSCTIMER_Out_5'
        - level: 'kSCTIMER_HighTrue'
        - dutyCyclePercent: '10'
    - pwmMode: 'kSCTIMER_EdgeAlignedPwm'
    - pwmFrequency: '1000'
    - events: []
    - states:
      - 0:
        - pwms: 'pwm0'
 * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
/* clang-format on */
const sctimer_config_t SCT0_initConfig = {
  .enableCounterUnify = true,
  .clockMode = kSCTIMER_System_ClockMode,
  .clockSelect = kSCTIMER_Clock_On_Rise_Input_0,
  .enableBidirection_l = false,
  .enableBidirection_h = false,
  .prescale_l = 0U,
  .prescale_h = 0U,
  .outInitState = (uint8_t)(SCT0_OUTPUT_5),
  .inputsync = 0U
};
const sctimer_pwm_signal_param_t SCT0_pwmSignalsConfig[1] = {
  {
    .output = kSCTIMER_Out_5,
    .level = kSCTIMER_LowTrue,
    .dutyCyclePercent = 100U // 100% means backlight off
  }
};
uint32_t SCT0_pwmEvent[1];

static void SCT0_init(void) {

  SCTIMER_Init(SCT0_PERIPHERAL, &SCT0_initConfig);
  /* Initialization of state 0 */
  SCTIMER_SetupPwm(SCT0_PERIPHERAL, &SCT0_pwmSignalsConfig[0], kSCTIMER_EdgeAlignedPwm, 1000U, SCT0_CLOCK_FREQ, &SCT0_pwmEvent[0]);

  /* Start the timer */
  SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_U);

  SCTIMER_UpdatePwmDutycycle(SCT0_PERIPHERAL, kSCTIMER_Out_5, 1U, SCT0_pwmEvent[0]); // backlight full brightness

  //SCTIMER_UpdatePwmDutycycle(SCT0_PERIPHERAL, kSCTIMER_Out_5, 50U, SCT0_pwmEvent[0]); // backlight half brightness

  //SCTIMER_UpdatePwmDutycycle(SCT0_PERIPHERAL, kSCTIMER_Out_5, 100U, SCT0_pwmEvent[0]); // backlight off

}

BacklightPWM.c which has function for changing duty cycle of PWM signal

void Blacklight_Brightness(uint8_t level)
{

	if (level <= 0) {level = 1;}
	if (level >100) {level = 100; }


	uint8_t dutyCyclePercent = 101-level;

    SCTIMER_UpdatePwmDutycycle(SCT0_PERIPHERAL, kSCTIMER_Out_5, dutyCyclePercent, SCT0_pwmEvent[0]);

}

 

I added the following code to ewmain.c

// Add timer for backlight dimming
#include "BacklightPWM.h"
#include "FreeRTOS.h"
#include "timers.h"
TimerHandle_t xTimerBacklight;
bool Backlight_dimmed = false;

void vTimerCallback( TimerHandle_t xTimer )
{
	// Lower backlight intensity
    Blacklight_Brightness(25);
    Backlight_dimmed = true;
}



int EwInit( void )
{
.
.
EMWI code
.
.

  // create backlight timer
  xTimerBacklight = xTimerCreate( /* Just a text name, not used by the RTOS
                      kernel. */
                      "TimerBacklight",
                      /* The timer period in ticks, must be
                      greater than 10*60*1000 = 10 min */
					  600000 / portTICK_PERIOD_MS,
                      /* The timers will auto-reload themselves
                      when they expire. */
                      pdTRUE,
                      /* The ID is used to store a count of the
                      number of times the timer has expired, which
                      is initialised to 0. */
                      ( void * ) 0,
                      /* Each timer calls the same callback when
                      it expires. */
                      vTimerCallback);

  // Start the timer
  xTimerStart( xTimerBacklight, 0);

 return 1;
}

int EwProcess( void )
{
  int          timers  = 0;
  int          signals = 0;
  int          events  = 0;
  int          devices = 0;
  XEnum        cmd     = CoreKeyCodeNoKey;
  int          noOfTouch;
  XTouchEvent* touchEvent;
  int          touch;
  int          finger;
  XPoint       touchPos;

.
.
.
EMWI code
.
.


 if ( noOfTouch > 0 )
  {
    for ( touch = 0; touch < noOfTouch; touch++ )
    {
      .
      .
      EMWI code
      .
      .
    }

    xTimerReset( xTimerBacklight , 0);
    if(Backlight_dimmed)
    {
    	// increase backlight intensity
    	Blacklight_Brightness(100);
    }

  }

.
.
.
EMWI code
.
.

  return 1;
}


 

by
Hello Jim,

thanks for sharing your results!

Best regards,

Manfred.

Embedded Wizard Website | Privacy Policy | Imprint

...