mirror of
https://github.com/armel/uv-k1-k5v3-firmware-custom.git
synced 2026-10-02 03:15:37 +00:00
277 lines
7.1 KiB
C
277 lines
7.1 KiB
C
/* Copyright 2025 muzkr https://github.com/muzkr
|
|
* Copyright 2023 Dual Tachyon
|
|
* https://github.com/DualTachyon
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "driver/backlight.h"
|
|
#include "py32f071_ll_system.h"
|
|
#include "py32f071_ll_dma.h"
|
|
#include "py32f071_ll_bus.h"
|
|
#include "py32f071_ll_tim.h"
|
|
#include "driver/gpio.h"
|
|
#include "driver/systick.h"
|
|
#include "settings.h"
|
|
#include "external/printf/printf.h"
|
|
|
|
#ifdef ENABLE_FEAT_F4HWN
|
|
#include "driver/system.h"
|
|
#include "audio.h"
|
|
#include "misc.h"
|
|
#endif
|
|
|
|
#define PWM_FREQ 4000
|
|
#define DUTY_CYCLE_LEVELS 64
|
|
|
|
#define DUTY_CYCLE_ON_VALUE GPIO_PIN_MASK(GPIO_PIN_BACKLIGHT)
|
|
#define DUTY_CYCLE_OFF_VALUE (DUTY_CYCLE_ON_VALUE << 16)
|
|
|
|
#define TIMx TIM7
|
|
#define DMA_CHANNEL LL_DMA_CHANNEL_7
|
|
|
|
static uint32_t dutyCycle[DUTY_CYCLE_LEVELS];
|
|
|
|
// this is decremented once every 500ms
|
|
uint16_t gBacklightCountdown_500ms = 0;
|
|
bool gUpdateBacklight = false;
|
|
bool backlightOn;
|
|
|
|
static uint8_t currentIndex = 0;
|
|
static int16_t currentBrightness = 0;
|
|
static int16_t targetBrightness = 0;
|
|
static int16_t fadeStep = 0;
|
|
|
|
#ifdef ENABLE_FEAT_F4HWN
|
|
const uint8_t value[] = {
|
|
0, // 0 off
|
|
8, // 1 visible in the dark
|
|
14, // 2
|
|
22, // 3
|
|
32, // 4
|
|
48, // 5
|
|
72, // 6
|
|
104, // 7
|
|
150, // 8
|
|
200, // 9
|
|
255 // 10 max
|
|
};
|
|
#endif
|
|
|
|
#ifdef ENABLE_FEAT_F4HWN_SLEEP
|
|
uint16_t gSleepModeCountdown_500ms = 0;
|
|
#endif
|
|
|
|
void BACKLIGHT_InitHardware()
|
|
{
|
|
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM7);
|
|
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
|
|
|
|
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM7);
|
|
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM7);
|
|
|
|
// 48 MHz / ((1 + PSC) * (1 + ARR)) == PWM_freq * levels
|
|
LL_TIM_SetPrescaler(TIMx, 0);
|
|
LL_TIM_SetAutoReload(TIMx, SystemCoreClock / PWM_FREQ / DUTY_CYCLE_LEVELS - 1);
|
|
LL_TIM_EnableARRPreload(TIMx);
|
|
LL_TIM_EnableDMAReq_UPDATE(TIMx);
|
|
LL_TIM_EnableUpdateEvent(TIMx);
|
|
|
|
LL_DMA_DisableChannel(DMA1, DMA_CHANNEL) ;
|
|
LL_SYSCFG_SetDMARemap(DMA1, DMA_CHANNEL, LL_SYSCFG_DMA_MAP_TIM7_UP);
|
|
|
|
LL_DMA_ConfigTransfer(DMA1, DMA_CHANNEL, //
|
|
LL_DMA_DIRECTION_MEMORY_TO_PERIPH //
|
|
| LL_DMA_MODE_CIRCULAR //
|
|
| LL_DMA_PERIPH_NOINCREMENT //
|
|
| LL_DMA_MEMORY_INCREMENT //
|
|
| LL_DMA_PDATAALIGN_WORD //
|
|
| LL_DMA_MDATAALIGN_WORD //
|
|
| LL_DMA_PRIORITY_HIGH //
|
|
);
|
|
|
|
LL_DMA_SetMemoryAddress(DMA1, DMA_CHANNEL, (uint32_t)dutyCycle);
|
|
LL_DMA_SetPeriphAddress(DMA1, DMA_CHANNEL, (uint32_t)(&GPIO_PORT(GPIO_PIN_BACKLIGHT)->BSRR));
|
|
LL_DMA_SetDataLength(DMA1, DMA_CHANNEL, sizeof(dutyCycle) / sizeof(uint32_t));
|
|
}
|
|
|
|
static void BACKLIGHT_Sound(void)
|
|
{
|
|
if (gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_SOUND || gEeprom.POWER_ON_DISPLAY_MODE == POWER_ON_DISPLAY_MODE_ALL)
|
|
{
|
|
AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP);
|
|
AUDIO_PlayBeep(BEEP_880HZ_60MS_DOUBLE_BEEP);
|
|
}
|
|
|
|
gK5startup = false;
|
|
}
|
|
|
|
void BACKLIGHT_UpdateTickless(void) {
|
|
while(gUpdateBacklight) {
|
|
BACKLIGHT_Update();
|
|
SYSTEM_DelayMs(10);
|
|
}
|
|
}
|
|
|
|
void BACKLIGHT_TurnOn(void)
|
|
{
|
|
#ifdef ENABLE_FEAT_F4HWN_SLEEP
|
|
gSleepModeCountdown_500ms = gSetting_set_off * 120;
|
|
#endif
|
|
|
|
#ifdef ENABLE_FEAT_F4HWN
|
|
gBacklightBrightnessOld = BACKLIGHT_GetBrightness();
|
|
#endif
|
|
|
|
if (gEeprom.BACKLIGHT_TIME == 0) {
|
|
BACKLIGHT_TurnOff();
|
|
#ifdef ENABLE_FEAT_F4HWN
|
|
if(gK5startup == true)
|
|
{
|
|
BACKLIGHT_Sound();
|
|
}
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
backlightOn = true;
|
|
|
|
BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MAX);
|
|
|
|
#ifdef ENABLE_FEAT_F4HWN
|
|
if(gK5startup == true)
|
|
#else
|
|
static bool startup = true;
|
|
|
|
if(startup)
|
|
#endif
|
|
{
|
|
BACKLIGHT_UpdateTickless();
|
|
#ifdef ENABLE_FEAT_F4HWN
|
|
BACKLIGHT_Sound();
|
|
#else
|
|
startup = false;
|
|
#endif
|
|
}
|
|
|
|
switch (gEeprom.BACKLIGHT_TIME) {
|
|
default:
|
|
case 1 ... 60: // 5 sec * value
|
|
gBacklightCountdown_500ms = 1 + (gEeprom.BACKLIGHT_TIME * 5) * 2;
|
|
break;
|
|
case 61: // always on
|
|
gBacklightCountdown_500ms = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void BACKLIGHT_TurnOff()
|
|
{
|
|
#ifdef ENABLE_BLMIN_TMP_OFF
|
|
register uint8_t tmp;
|
|
|
|
if (gEeprom.BACKLIGHT_MIN_STAT == BLMIN_STAT_ON)
|
|
tmp = gEeprom.BACKLIGHT_MIN;
|
|
else
|
|
tmp = 0;
|
|
|
|
BACKLIGHT_SetBrightness(tmp);
|
|
#else
|
|
BACKLIGHT_SetBrightness(gEeprom.BACKLIGHT_MIN);
|
|
#endif
|
|
gBacklightCountdown_500ms = 0;
|
|
backlightOn = false;
|
|
}
|
|
|
|
bool BACKLIGHT_IsOn()
|
|
{
|
|
return backlightOn;
|
|
}
|
|
|
|
static void BACKLIGHT_SetHardwareBrightness(uint8_t brightness)
|
|
{
|
|
// printf("BL: %d\n", brigtness);
|
|
|
|
if (0 == brightness)
|
|
{
|
|
LL_TIM_DisableCounter(TIMx);
|
|
LL_DMA_DisableChannel(DMA1, DMA_CHANNEL);
|
|
SYSTICK_DelayUs(1);
|
|
GPIO_TurnOffBacklight();
|
|
}
|
|
else
|
|
{
|
|
const uint32_t level = (uint32_t)(brightness) * DUTY_CYCLE_LEVELS / 255;
|
|
if (level >= DUTY_CYCLE_LEVELS)
|
|
{
|
|
LL_TIM_DisableCounter(TIMx);
|
|
LL_DMA_DisableChannel(DMA1, DMA_CHANNEL);
|
|
GPIO_TurnOnBacklight();
|
|
}
|
|
else
|
|
{
|
|
for (uint32_t i = 0; i < DUTY_CYCLE_LEVELS; i++)
|
|
{
|
|
dutyCycle[i] = i < level ? DUTY_CYCLE_ON_VALUE : DUTY_CYCLE_OFF_VALUE;
|
|
}
|
|
|
|
if (!LL_TIM_IsEnabledCounter(TIMx))
|
|
{
|
|
LL_DMA_EnableChannel(DMA1, DMA_CHANNEL);
|
|
LL_TIM_EnableCounter(TIMx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BACKLIGHT_Update(void)
|
|
{
|
|
if (gUpdateBacklight) {
|
|
currentBrightness += fadeStep;
|
|
|
|
if ((fadeStep > 0 && currentBrightness >= targetBrightness) ||
|
|
(fadeStep < 0 && currentBrightness <= targetBrightness)) {
|
|
currentBrightness = targetBrightness;
|
|
gUpdateBacklight = false;
|
|
}
|
|
|
|
BACKLIGHT_SetHardwareBrightness((uint8_t)currentBrightness);
|
|
}
|
|
}
|
|
|
|
void BACKLIGHT_SetBrightness(uint8_t targetIndex)
|
|
{
|
|
if (currentIndex == targetIndex) {
|
|
return;
|
|
}
|
|
|
|
currentIndex = targetIndex;
|
|
targetBrightness = value[targetIndex];
|
|
|
|
int16_t diff = targetBrightness - currentBrightness;
|
|
|
|
if (diff == 0) {
|
|
gUpdateBacklight = false;
|
|
return;
|
|
}
|
|
|
|
fadeStep = diff > 0 ? -(-diff >> 4) : diff >> 4;
|
|
|
|
gUpdateBacklight = true;
|
|
}
|
|
|
|
uint8_t BACKLIGHT_GetBrightness(void)
|
|
{
|
|
return currentIndex;
|
|
}
|