Pinscape fork (KL25Z)
Dependents: Pinscape_Controller_V2_arnoz Pinscape_Controller_V2
Fork of FastPWM by
Revision 35:25e9500598ae, committed 2017-03-24
- Comitter:
- mjr
- Date:
- Fri Mar 24 05:39:58 2017 +0000
- Parent:
- 34:8b826bfff900
- Parent:
- 33:e880dcb178f4
- Commit message:
- Merge branch
Changed in this revision
diff -r 8b826bfff900 -r 25e9500598ae Device/FastPWM_KSDK.cpp --- a/Device/FastPWM_KSDK.cpp Fri Mar 24 05:32:57 2017 +0000 +++ b/Device/FastPWM_KSDK.cpp Fri Mar 24 05:39:58 2017 +0000 @@ -1,7 +1,7 @@ #if defined(TARGET_KPSDK_MCUS) #include "FastPWM.h" -#include "fsl_clock_manager.h" +#include "fsl_ftm.h" #define PWM_CNV (*(((fastpwm_struct*)fast_obj)->CnV)) @@ -15,18 +15,16 @@ } fastpwm_struct; static uint32_t pwm_prescaler; +static FTM_Type *const ftm_addrs[] = FTM_BASE_PTRS; void FastPWM::initFastPWM( void ) { fast_obj = new fastpwm_struct; bits = 16; - - uint32_t pwm_base_clock; - CLOCK_SYS_GetFreq(kBusClock, &pwm_base_clock); - pwm_prescaler = SystemCoreClock / pwm_base_clock; + + pwm_prescaler = SystemCoreClock / CLOCK_GetFreq(kCLOCK_BusClk);; - uint32_t ftms[] = FTM_BASE_ADDRS; - unsigned int ch_n = (_pwm.pwm_name & 0xFF); - FTM_Type *ftm = (FTM_Type *)ftms[_pwm.pwm_name >> TPM_SHIFT]; + unsigned int ch_n = (_pwm.pwm_name & 0xF); + FTM_Type *ftm = ftm_addrs[_pwm.pwm_name >> TPM_SHIFT]; ((fastpwm_struct*)fast_obj)->CnV = &ftm->CONTROLS[ch_n].CnV; ((fastpwm_struct*)fast_obj)->MOD = &ftm->MOD; @@ -35,6 +33,10 @@ void FastPWM::pulsewidth_ticks( uint32_t ticks ) { PWM_CNV = ticks; + + //Temporary work around until I figure out which settings mbed screwed up in this update + FTM_Type *ftm = ftm_addrs[_pwm.pwm_name >> TPM_SHIFT]; + FTM_SetSoftwareTrigger(ftm, true); } void FastPWM::period_ticks( uint32_t ticks ) {
diff -r 8b826bfff900 -r 25e9500598ae Device/FastPWM_LPC1768.cpp --- a/Device/FastPWM_LPC1768.cpp Fri Mar 24 05:32:57 2017 +0000 +++ b/Device/FastPWM_LPC1768.cpp Fri Mar 24 05:39:58 2017 +0000 @@ -1,4 +1,4 @@ -#ifdef TARGET_LPC1768 +#ifdef TARGET_LPC176X #include "FastPWM.h"
diff -r 8b826bfff900 -r 25e9500598ae Device/FastPWM_LPC_SCT.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Device/FastPWM_LPC_SCT.cpp Fri Mar 24 05:39:58 2017 +0000 @@ -0,0 +1,63 @@ +//For targets which use the SCT +#if defined(TARGET_LPC81X) || defined(TARGET_LPC82X) + +#ifdef TARGET_LPC82X +#define CTRL_U CTRL +#endif + +#include "FastPWM.h" + +void FastPWM::initFastPWM( void ) { + //Mbed uses the timer as a single unified 32-bit timer, who are we to argue with this, and it is easier + bits = 32; + + #ifdef TARGET_LPC82X + //The mbed lib uses the PWM peripheral slightly different, which is irritating. This sets it bck to the LPC81X + _pwm.pwm->EVENT[_pwm.pwm_ch + 1].CTRL = (1 << 12) | (_pwm.pwm_ch + 1); // Event_n on Match_n + _pwm.pwm->EVENT[_pwm.pwm_ch + 1].STATE = 0xFFFFFFFF; // All states + _pwm.pwm->OUT[_pwm.pwm_ch].SET = (1 << 0); // All PWM channels are SET on Event_0 + _pwm.pwm->OUT[_pwm.pwm_ch].CLR = (1 << (_pwm.pwm_ch + 1)); // PWM ch is CLRed on Event_(ch+1) + #endif + + //With 32-bit we fix prescaler to 1 + _pwm.pwm->CTRL_U |= (1 << 2) | (1 << 3); + _pwm.pwm->CTRL_U &= ~(0x7F << 5); + _pwm.pwm->CTRL_U &= ~(1 << 2); + +} + +void FastPWM::pulsewidth_ticks( uint32_t ticks ) { + #ifdef TARGET_LPC81X + _pwm.pwm->MATCHREL[_pwm.pwm_ch + 1].U = ticks; + #else + _pwm.pwm->MATCHREL[_pwm.pwm_ch + 1] = ticks; + #endif +} + +void FastPWM::period_ticks( uint32_t ticks ) { + #ifdef TARGET_LPC81X + _pwm.pwm->MATCHREL[0].U = ticks; + #else + _pwm.pwm->MATCHREL[0] = ticks; + #endif +} + +uint32_t FastPWM::getPeriod( void ) { + #ifdef TARGET_LPC81X + return _pwm.pwm->MATCHREL[0].U; + #else + return _pwm.pwm->MATCHREL[0]; + #endif +} + +//Maybe implemented later, but needing to change the prescaler for a 32-bit +//timer used in PWM mode is kinda unlikely. +//If you really need to do it, rejoice, you can make it run so slow a period is over 40,000 year +uint32_t FastPWM::setPrescaler(uint32_t reqScale) { + //Disable dynamic prescaling + dynamicPrescaler = false; + + return 1; +} + +#endif \ No newline at end of file
diff -r 8b826bfff900 -r 25e9500598ae Device/FastPWM_STM_TIM.cpp --- a/Device/FastPWM_STM_TIM.cpp Fri Mar 24 05:32:57 2017 +0000 +++ b/Device/FastPWM_STM_TIM.cpp Fri Mar 24 05:39:58 2017 +0000 @@ -6,14 +6,38 @@ typedef __IO uint32_t* CHANNEL_P_T; -#define PWM_CHANNEL (**(CHANNEL_P_T*)fast_obj) -#define PWM_TIMER ((TIM_TypeDef*)_pwm.pwm) +typedef struct { + CHANNEL_P_T channel; + uint32_t clk_prescaler; +} fastpwm_struct; -extern CHANNEL_P_T getChannel(TIM_TypeDef* pwm, PinName pin); +#define PWM_CHANNEL ((((fastpwm_struct*)fast_obj)->channel)) +#define PWM_CLK_PRESCALER ((((fastpwm_struct*)fast_obj)->clk_prescaler)) +#define PWM_TIMER ((TIM_TypeDef*)_pwm.pwm) + +#if defined(TARGET_STM32F0) || defined (TARGET_STM32F1) || defined (TARGET_STM32L1) +extern __IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin); +#endif void FastPWM::initFastPWM( void ) { - fast_obj = new (CHANNEL_P_T); - *(CHANNEL_P_T*)fast_obj = getChannel(PWM_TIMER, _pwm.pin); + fast_obj = new fastpwm_struct; + #if defined(TARGET_STM32F0) || defined (TARGET_STM32F1) || defined (TARGET_STM32L1) + PWM_CHANNEL = getChannel(PWM_TIMER, _pwm.pin); + #else + PWM_CHANNEL = (&PWM_TIMER->CCR1 + _pwm.channel - 1); + #endif + + // Depending on the timer and the internal bus it is connected to, each STM timer + // can have a fixed prescaler from the clock, especially the faster devices. + // In order not to have to hardcode this in, we use knowledge that mbed lib sets + // default period to 20ms to reverse engineer the prescaler from this. + uint32_t current_hz = SystemCoreClock / (PWM_TIMER->PSC + 1) / (PWM_TIMER->ARR+1); + PWM_CLK_PRESCALER = (current_hz + 1) / 50; //50Hz is magic number it should be, +1 is to handle possible rounding errors in mbed setup + + //Sanity check in case a target does something different + if ( (PWM_CLK_PRESCALER == 0 ) || (PWM_CLK_PRESCALER > 16)) { + PWM_CLK_PRESCALER = 1; + } //Enable PWM period syncing for glitch free result PWM_TIMER->CR1 |= TIM_CR1_ARPE; @@ -22,7 +46,7 @@ } void FastPWM::pulsewidth_ticks( uint32_t ticks ) { - PWM_CHANNEL = ticks; + *PWM_CHANNEL = ticks; } void FastPWM::period_ticks( uint32_t ticks ) { @@ -34,15 +58,18 @@ } uint32_t FastPWM::setPrescaler(uint32_t reqScale) { - if (reqScale == 0) + if (reqScale == 0) { //Return prescaler - return PWM_TIMER->PSC + 1; - if (reqScale > (uint32_t)(1<<16)) - reqScale = 1<<16; + return (PWM_TIMER->PSC + 1) * PWM_CLK_PRESCALER; + } + if (reqScale > (uint32_t)(PWM_CLK_PRESCALER<<16)) { + reqScale = PWM_CLK_PRESCALER<<16; + } //Else set prescaler, we have to substract one from reqScale since a 0 in PCVAL is prescaler of 1 - PWM_TIMER->PSC = reqScale - 1; + //Take into account PWM_CLK_PRESCALER, we need to make sure reqScale is always rounded up + PWM_TIMER->PSC = (reqScale + PWM_CLK_PRESCALER - 1)/PWM_CLK_PRESCALER - 1; - return reqScale; + return setPrescaler(0); } #endif \ No newline at end of file
diff -r 8b826bfff900 -r 25e9500598ae Device/FastPWM_STM_TIM_PinOut.cpp --- a/Device/FastPWM_STM_TIM_PinOut.cpp Fri Mar 24 05:32:57 2017 +0000 +++ b/Device/FastPWM_STM_TIM_PinOut.cpp Fri Mar 24 05:39:58 2017 +0000 @@ -1,6 +1,6 @@ #include "mbed.h" -#ifdef TARGET_NUCLEO_F030R8 +#if defined (TARGET_NUCLEO_F030R8) || (TARGET_DISCO_F051R8) __IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin) { switch (pin) { // Channels 1 @@ -23,30 +23,7 @@ } #endif -#if defined TARGET_NUCLEO_F401RE || defined TARGET_NUCLEO_F411RE -__IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin) { - switch (pin) { - // Channels 1 : PWMx/1 - case PA_0: case PA_5: case PA_6: case PA_8: case PA_15: case PB_4: case PB_6: case PC_6: case PA_7: case PB_13: - return &pwm->CCR1; - - // Channels 2 : PWMx/2 - case PA_1: case PA_9: case PB_3: case PB_5: case PB_7: case PC_7: case PB_0: case PB_14: - return &pwm->CCR2; - - // Channels 3 : PWMx/3 - case PA_2: case PA_10: case PB_8: case PB_10: case PC_8: case PB_1: case PB_15: - return &pwm->CCR3; - - // Channels 4 : PWMx/4 - case PA_3: case PA_11: case PB_9: case PC_9: - return &pwm->CCR4; - } - return NULL; -} -#endif - -#if defined TARGET_NUCLEO_F103RB +#if defined (TARGET_NUCLEO_F103RB) || (TARGET_DISCO_F100RB) __IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin) { switch (pin) { // Channels 1 : PWMx/1 @@ -69,31 +46,6 @@ } #endif -#ifdef TARGET_NUCLEO_F334R8 -__IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin) { - switch (pin) { - // Channels 1 - case PA_2: case PA_6: case PA_7: case PA_8: case PA_12: case PB_4: case PB_5: case PB_8: case PB_9: case PB_14: case PC_0: case PC_6: - case PA_1: case PA_13: case PB_6: case PB_13: case PC_13: - return &pwm->CCR1; - - // Channels 2 - case PA_3: case PA_4: case PA_9: case PB_15: case PC_1: case PC_7: - return &pwm->CCR2; - - // Channels 3 - case PA_10: case PB_0: case PC_2: case PC_8: - case PF_0: - return &pwm->CCR3; - - // Channels 4 - case PA_11: case PB_1: case PB_7: case PC_3: case PC_9: - return &pwm->CCR4; - } - return NULL; -} -#endif - #if defined TARGET_NUCLEO_F072RB __IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin) { switch (pin) { @@ -117,4 +69,34 @@ } return NULL; } -#endif \ No newline at end of file +#endif + + + +#if defined (TARGET_NUCLEO_L152RE) +__IO uint32_t* getChannel(TIM_TypeDef* pwm, PinName pin) { + switch (pin) { + // Channels 1 : PWMx/1 + case PA_6: case PB_4: case PB_12: case PB_13: case PC_6: + return &pwm->CCR1; + + // Channels 2 : PWMx/2 + case PA_1: case PA_7: case PB_3: case PB_5: case PB_14: case PB_7: case PC_7: + return &pwm->CCR2; + + // Channels 3 : PWMx/3 + case PA_2: case PB_0: case PB_8: case PB_10: case PC_8: + return &pwm->CCR3; + + // Channels 4 : PWMx/4 + case PA_3: case PB_1:case PB_9: case PB_11: case PC_9: + return &pwm->CCR4; + default: + /* NOP */ + break; + } + return NULL; +} +#endif + + \ No newline at end of file