mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-12-17 10:22:01 +03:00
3de856f8d5
* FuriHal: add bus abstraction and port some subsystem to it * Make PVS happy, cleanup code * Update API symbols for f18 * F18: backport bus changes from f7 * Revert to STOP2 sleep mode * Fix downgrading the firmware via updater * Port iButton TIM1 to furi_hal_bus * Port Infrared TIM1 and TIM2 to furi_hal_bus * Just enable the timer bus * Port furi_hal_pwm to bus API * Fix include statement * Port furi_hal_rfid to bus API * Port furi_hal_subghz and others to bus API * Remove unneeded include * Improve furi_hal_infrared defines * Reset LPTIM1 via furi_hal_bus API * Crash when trying to enable an already enabled peripheral * Better defines * Improved checks * Lots of macro wrappers * Copy spi changes for f18 * Fix crashes in LFRFID system * Fix crashes in NFC system * Improve comments * Create FuriHalBus.md * Update FuriHalBus.md * Fix crash when launching updater * Documentation: couple small fixes in FuriHalBus * FuriHal: fix copypaste in furi_hal_rfid_tim_reset * FuriHal: reset radio core related peripherals on restart * FuriHalBus: is enabled routine and bug fix for uart * RFID HAL: accomodate furi hal bus Co-authored-by: Georgii Surkov <georgii.surkov@outlook.com> Co-authored-by: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Co-authored-by: SG <who.just.the.doctor@gmail.com>
130 lines
4.2 KiB
C
130 lines
4.2 KiB
C
#include <furi_hal_pwm.h>
|
|
#include <furi_hal_resources.h>
|
|
#include <furi_hal_bus.h>
|
|
|
|
#include <stm32wbxx_ll_tim.h>
|
|
#include <stm32wbxx_ll_lptim.h>
|
|
#include <stm32wbxx_ll_rcc.h>
|
|
|
|
#include <furi.h>
|
|
|
|
const uint32_t lptim_psc_table[] = {
|
|
LL_LPTIM_PRESCALER_DIV1,
|
|
LL_LPTIM_PRESCALER_DIV2,
|
|
LL_LPTIM_PRESCALER_DIV4,
|
|
LL_LPTIM_PRESCALER_DIV8,
|
|
LL_LPTIM_PRESCALER_DIV16,
|
|
LL_LPTIM_PRESCALER_DIV32,
|
|
LL_LPTIM_PRESCALER_DIV64,
|
|
LL_LPTIM_PRESCALER_DIV128,
|
|
};
|
|
|
|
void furi_hal_pwm_start(FuriHalPwmOutputId channel, uint32_t freq, uint8_t duty) {
|
|
if(channel == FuriHalPwmOutputIdTim1PA7) {
|
|
furi_hal_gpio_init_ex(
|
|
&gpio_ext_pa7,
|
|
GpioModeAltFunctionPushPull,
|
|
GpioPullNo,
|
|
GpioSpeedVeryHigh,
|
|
GpioAltFn1TIM1);
|
|
|
|
furi_hal_bus_enable(FuriHalBusTIM1);
|
|
|
|
LL_TIM_SetCounterMode(TIM1, LL_TIM_COUNTERMODE_UP);
|
|
LL_TIM_SetRepetitionCounter(TIM1, 0);
|
|
LL_TIM_SetClockDivision(TIM1, LL_TIM_CLOCKDIVISION_DIV1);
|
|
LL_TIM_SetClockSource(TIM1, LL_TIM_CLOCKSOURCE_INTERNAL);
|
|
LL_TIM_EnableARRPreload(TIM1);
|
|
|
|
LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH1);
|
|
LL_TIM_OC_SetMode(TIM1, LL_TIM_CHANNEL_CH1, LL_TIM_OCMODE_PWM1);
|
|
LL_TIM_OC_SetPolarity(TIM1, LL_TIM_CHANNEL_CH1N, LL_TIM_OCPOLARITY_HIGH);
|
|
LL_TIM_OC_DisableFast(TIM1, LL_TIM_CHANNEL_CH1);
|
|
LL_TIM_CC_EnableChannel(TIM1, LL_TIM_CHANNEL_CH1N);
|
|
|
|
LL_TIM_EnableAllOutputs(TIM1);
|
|
|
|
furi_hal_pwm_set_params(channel, freq, duty);
|
|
|
|
LL_TIM_EnableCounter(TIM1);
|
|
} else if(channel == FuriHalPwmOutputIdLptim2PA4) {
|
|
furi_hal_gpio_init_ex(
|
|
&gpio_ext_pa4,
|
|
GpioModeAltFunctionPushPull,
|
|
GpioPullNo,
|
|
GpioSpeedVeryHigh,
|
|
GpioAltFn14LPTIM2);
|
|
|
|
furi_hal_bus_enable(FuriHalBusLPTIM2);
|
|
|
|
LL_LPTIM_SetUpdateMode(LPTIM2, LL_LPTIM_UPDATE_MODE_ENDOFPERIOD);
|
|
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_PCLK1);
|
|
LL_LPTIM_SetClockSource(LPTIM2, LL_LPTIM_CLK_SOURCE_INTERNAL);
|
|
LL_LPTIM_ConfigOutput(
|
|
LPTIM2, LL_LPTIM_OUTPUT_WAVEFORM_PWM, LL_LPTIM_OUTPUT_POLARITY_INVERSE);
|
|
LL_LPTIM_SetCounterMode(LPTIM2, LL_LPTIM_COUNTER_MODE_INTERNAL);
|
|
|
|
LL_LPTIM_Enable(LPTIM2);
|
|
|
|
furi_hal_pwm_set_params(channel, freq, duty);
|
|
|
|
LL_LPTIM_StartCounter(LPTIM2, LL_LPTIM_OPERATING_MODE_CONTINUOUS);
|
|
}
|
|
}
|
|
|
|
void furi_hal_pwm_stop(FuriHalPwmOutputId channel) {
|
|
if(channel == FuriHalPwmOutputIdTim1PA7) {
|
|
furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog);
|
|
furi_hal_bus_disable(FuriHalBusTIM1);
|
|
} else if(channel == FuriHalPwmOutputIdLptim2PA4) {
|
|
furi_hal_gpio_init_simple(&gpio_ext_pa4, GpioModeAnalog);
|
|
furi_hal_bus_disable(FuriHalBusLPTIM2);
|
|
}
|
|
}
|
|
|
|
void furi_hal_pwm_set_params(FuriHalPwmOutputId channel, uint32_t freq, uint8_t duty) {
|
|
furi_assert(freq > 0);
|
|
uint32_t freq_div = 64000000LU / freq;
|
|
|
|
if(channel == FuriHalPwmOutputIdTim1PA7) {
|
|
uint32_t prescaler = freq_div / 0x10000LU;
|
|
uint32_t period = freq_div / (prescaler + 1);
|
|
uint32_t compare = period * duty / 100;
|
|
|
|
LL_TIM_SetPrescaler(TIM1, prescaler);
|
|
LL_TIM_SetAutoReload(TIM1, period - 1);
|
|
LL_TIM_OC_SetCompareCH1(TIM1, compare);
|
|
} else if(channel == FuriHalPwmOutputIdLptim2PA4) {
|
|
uint32_t prescaler = 0;
|
|
uint32_t period = 0;
|
|
|
|
bool clock_lse = false;
|
|
|
|
do {
|
|
period = freq_div / (1UL << prescaler);
|
|
if(period <= 0xFFFF) {
|
|
break;
|
|
}
|
|
prescaler++;
|
|
if(prescaler > 7) {
|
|
prescaler = 0;
|
|
clock_lse = true;
|
|
period = 32768LU / freq;
|
|
break;
|
|
}
|
|
} while(1);
|
|
|
|
uint32_t compare = period * duty / 100;
|
|
|
|
LL_LPTIM_SetPrescaler(LPTIM2, lptim_psc_table[prescaler]);
|
|
LL_LPTIM_SetAutoReload(LPTIM2, period);
|
|
LL_LPTIM_SetCompare(LPTIM2, compare);
|
|
|
|
if(clock_lse) {
|
|
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_LSE);
|
|
} else {
|
|
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_PCLK1);
|
|
}
|
|
}
|
|
}
|