Commit 47b02df1 authored by schneider's avatar schneider
Browse files

change(backlight): Keep PWM stable when changing PCLK

Timer frequency is now held close to a value which can be achieved both
with a 48 MHz PCLK (96 MHz system clock) and a 7.5 MHz PCLK (15 MHz
system clock).

If even lower PCLKs should be supported, the frequency of the timer has
to be changed as well.
parent 01dab506
Pipeline #5239 passed with stages
in 30 seconds
......@@ -311,6 +311,11 @@ int epic_disp_close()
}
}
void disp_update_backlight_clock(void)
{
LCD_UpdateBacklightClock();
}
void disp_forcelock()
{
TaskHandle_t task = xTaskGetCurrentTaskHandle();
......
......@@ -61,6 +61,7 @@ int pmic_read_amux(enum pmic_amux_signal sig, float *result);
/* ---------- Display ------------------------------------------------------ */
/* Forces an unlock of the display. Only to be used in Epicardium */
void disp_forcelock();
void disp_update_backlight_clock(void);
/* ---------- BHI160 ------------------------------------------------------- */
#define BHI160_FIFO_SIZE 128
......
......@@ -70,7 +70,68 @@ void lcd_write(uint8_t *data, int size)
#define PORT_PWM PORT_0 // port
#define PIN_PWM PIN_28 // pin
#define FREQ 1000 // (Hz)
#define TIMER_FREQ 6000000 // _Target_ timer frequncy (Hz)
#define PWM_TIMER MXC_TMR4 // must change PORT_PWM and PIN_PWM if changed
/* Find a prescaler which gives us at least TIMER_FREQ HZ base clock
* at the current PCLK setting.
*
* Maximum prescaler chosen is 128.
*/
static uint8_t timer_prescale_factor(void)
{
uint32_t target_prescaler = PeripheralClock / TIMER_FREQ;
if (target_prescaler == 0) {
printf("TIMER_FREQ to high for PeripheralClock\n");
while (1)
;
}
uint8_t prescaler = 1;
for (int i = 0; i < 7; i++) {
uint8_t next_prescaler = prescaler << 1;
if (next_prescaler > target_prescaler) {
break;
}
prescaler = next_prescaler;
}
return prescaler;
}
/* Return the constant need for the timer prescaler register to
* reach a least TIMER_FREQ HZ base clock frequency at the
* current PCLK setting */
static uint32_t timer_prescaler(void)
{
switch (timer_prescale_factor()) {
case 1:
return MXC_S_TMR_CN_PRES_DIV1;
case 2:
return MXC_S_TMR_CN_PRES_DIV2;
case 4:
return MXC_S_TMR_CN_PRES_DIV4;
case 8:
return MXC_S_TMR_CN_PRES_DIV8;
case 16:
return MXC_S_TMR_CN_PRES_DIV16;
case 32:
return MXC_S_TMR_CN_PRES_DIV32;
case 64:
return MXC_S_TMR_CN_PRES_DIV64;
default:
return MXC_S_TMR_CN_PRES_DIV128;
}
}
/* Update the timer prescaler to what ever PCLK currently requires */
void DEV_Update_BL_Clock(void)
{
PWM_TIMER->cn =
(PWM_TIMER->cn & ~(MXC_F_TMR_CN_PRES)) | timer_prescaler();
}
void DEV_Set_BL(uint16_t _Value)
{
// Declare variables
......@@ -82,8 +143,9 @@ void DEV_Set_BL(uint16_t _Value)
_Value = 100;
}
unsigned int period_ticks = PeripheralClock / FREQ;
unsigned int duty_ticks = period_ticks * _Value / 100;
unsigned int period_ticks =
PeripheralClock / timer_prescale_factor() / FREQ;
unsigned int duty_ticks = period_ticks * _Value / 100;
TMR_Disable(PWM_TIMER);
......@@ -95,7 +157,7 @@ void DEV_Set_BL(uint16_t _Value)
gpio_pwm.pad = GPIO_PAD_PULL_DOWN;
GPIO_Config(&gpio_pwm);
TMR_Init(PWM_TIMER, TMR_PRES_1, 0);
TMR_Init(PWM_TIMER, timer_prescaler(), 0);
tmr.mode = TMR_MODE_PWM;
tmr.cmp_cnt = period_ticks;
......
......@@ -74,6 +74,8 @@ void display_set_reset_pin(uint8_t state);
//#define DEV_Set_BL(_Value) DEV_BL_PIN= _Value
void DEV_Set_BL(uint16_t _Value);
void DEV_Update_BL(void);
void DEV_Update_BL_Clock(void);
/*-----------------------------------------------------------------------------*/
#endif
......@@ -56,6 +56,14 @@ void LCD_SetBacklight(UWORD Value)
{
DEV_Set_BL(Value);
}
/*******************************************************************************
function:
Update backlight clock
*******************************************************************************/
void LCD_UpdateBacklightClock(void)
{
DEV_Update_BL_Clock();
}
/*******************************************************************************
function:
......
......@@ -46,6 +46,7 @@ void LCD_SetUWORD(UWORD x, UWORD y, UWORD Color);
void LCD_Init(void);
void LCD_SetBacklight(UWORD Value);
void LCD_UpdateBacklightClock(void);
void LCD_Clear(UWORD Color);
void LCD_ClearWindow(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD UWORD);
uint8_t *LCD_Framebuffer(void);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment