mirror of https://github.com/ARMmbed/mbed-os.git
Move PWM API to the target specific folder
Some use the FTM module and some use the TPM module. Signed-off-by: Mahadevan Mahesh <Mahesh.Mahadevan@nxp.com>pull/1700/head
parent
fffadba309
commit
840cd1ccb5
|
@ -0,0 +1,143 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2006-2013 ARM Limited
|
||||||
|
*
|
||||||
|
* 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 "mbed_assert.h"
|
||||||
|
#include "pwmout_api.h"
|
||||||
|
|
||||||
|
#if DEVICE_PWMOUT
|
||||||
|
|
||||||
|
#include "cmsis.h"
|
||||||
|
#include "pinmap.h"
|
||||||
|
#include "fsl_ftm.h"
|
||||||
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
|
static float pwm_clock_mhz;
|
||||||
|
/* Array of FTM peripheral base address. */
|
||||||
|
static FTM_Type *const ftm_addrs[] = FTM_BASE_PTRS;
|
||||||
|
|
||||||
|
void pwmout_init(pwmout_t* obj, PinName pin) {
|
||||||
|
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
|
||||||
|
MBED_ASSERT(pwm != (PWMName)NC);
|
||||||
|
|
||||||
|
obj->pwm_name = pwm;
|
||||||
|
|
||||||
|
uint32_t pwm_base_clock;
|
||||||
|
pwm_base_clock = CLOCK_GetFreq(kCLOCK_BusClk);
|
||||||
|
float clkval = (float)pwm_base_clock / 1000000.0f;
|
||||||
|
uint32_t clkdiv = 0;
|
||||||
|
while (clkval > 1) {
|
||||||
|
clkdiv++;
|
||||||
|
clkval /= 2.0f;
|
||||||
|
if (clkdiv == 7) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pwm_clock_mhz = clkval;
|
||||||
|
uint32_t channel = pwm & 0xF;
|
||||||
|
uint32_t instance = pwm >> TPM_SHIFT;
|
||||||
|
ftm_config_t ftmInfo;
|
||||||
|
|
||||||
|
FTM_GetDefaultConfig(&ftmInfo);
|
||||||
|
ftmInfo.prescale = (ftm_clock_prescale_t)clkdiv;
|
||||||
|
/* Initialize FTM module */
|
||||||
|
FTM_Init(ftm_addrs[instance], &ftmInfo);
|
||||||
|
|
||||||
|
ftm_addrs[instance]->CONF |= FTM_CONF_NUMTOF(3);
|
||||||
|
|
||||||
|
ftm_chnl_pwm_signal_param_t config = {
|
||||||
|
.chnlNumber = (ftm_chnl_t)channel,
|
||||||
|
.level = kFTM_HighTrue,
|
||||||
|
.dutyCyclePercent = 0,
|
||||||
|
.firstEdgeDelayPercent = 0
|
||||||
|
};
|
||||||
|
// default to 20ms: standard for servos, and fine for e.g. brightness control
|
||||||
|
FTM_SetupPwm(ftm_addrs[instance], &config, 1, kFTM_EdgeAlignedPwm, 50, pwm_base_clock);
|
||||||
|
|
||||||
|
FTM_StartTimer(ftm_addrs[instance], kFTM_SystemClock);
|
||||||
|
|
||||||
|
// Wire pinout
|
||||||
|
pinmap_pinout(pin, PinMap_PWM);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_free(pwmout_t* obj) {
|
||||||
|
FTM_Deinit(ftm_addrs[obj->pwm_name >> TPM_SHIFT]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_write(pwmout_t* obj, float value) {
|
||||||
|
if (value < 0.0f) {
|
||||||
|
value = 0.0f;
|
||||||
|
} else if (value > 1.0f) {
|
||||||
|
value = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
|
||||||
|
uint16_t mod = base->MOD & FTM_MOD_MOD_MASK;
|
||||||
|
uint32_t new_count = (uint32_t)((float)(mod) * value);
|
||||||
|
// Update of CnV register
|
||||||
|
base->CONTROLS[obj->pwm_name & 0xF].CnV = new_count;
|
||||||
|
base->CNT = 0;
|
||||||
|
/* Software trigger to update registers */
|
||||||
|
FTM_SetSoftwareTrigger(base, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
float pwmout_read(pwmout_t* obj) {
|
||||||
|
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
|
||||||
|
uint16_t count = (base->CONTROLS[obj->pwm_name & 0xF].CnV) & FTM_CnV_VAL_MASK;
|
||||||
|
uint16_t mod = base->MOD & FTM_MOD_MOD_MASK;
|
||||||
|
|
||||||
|
if (mod == 0)
|
||||||
|
return 0.0;
|
||||||
|
float v = (float)(count) / (float)(mod);
|
||||||
|
return (v > 1.0f) ? (1.0f) : (v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_period(pwmout_t* obj, float seconds) {
|
||||||
|
pwmout_period_us(obj, seconds * 1000000.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_period_ms(pwmout_t* obj, int ms) {
|
||||||
|
pwmout_period_us(obj, ms * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the PWM period, keeping the duty cycle the same.
|
||||||
|
void pwmout_period_us(pwmout_t* obj, int us) {
|
||||||
|
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
|
||||||
|
float dc = pwmout_read(obj);
|
||||||
|
|
||||||
|
// Stop FTM clock to ensure instant update of MOD register
|
||||||
|
base->MOD = FTM_MOD_MOD((pwm_clock_mhz * (float)us) - 1);
|
||||||
|
pwmout_write(obj, dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
|
||||||
|
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
|
||||||
|
pwmout_pulsewidth_us(obj, ms * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
|
||||||
|
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
|
||||||
|
uint32_t value = (uint32_t)(pwm_clock_mhz * (float)us);
|
||||||
|
|
||||||
|
// Update of CnV register
|
||||||
|
base->CONTROLS[obj->pwm_name & 0xF].CnV = value;
|
||||||
|
/* Software trigger to update registers */
|
||||||
|
FTM_SetSoftwareTrigger(base, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -41,8 +41,18 @@ typedef enum {
|
||||||
I2C_1 = 1,
|
I2C_1 = 1,
|
||||||
} I2CName;
|
} I2CName;
|
||||||
|
|
||||||
|
#define TPM_SHIFT 8
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PWM = 0,
|
PWM_1 = (0 << TPM_SHIFT) | (0), // TPM0 CH0
|
||||||
|
PWM_2 = (0 << TPM_SHIFT) | (1), // TPM0 CH1
|
||||||
|
PWM_3 = (0 << TPM_SHIFT) | (2), // TPM0 CH2
|
||||||
|
PWM_4 = (0 << TPM_SHIFT) | (3), // TPM0 CH3
|
||||||
|
PWM_5 = (0 << TPM_SHIFT) | (4), // TPM0 CH4
|
||||||
|
PWM_6 = (0 << TPM_SHIFT) | (5), // TPM0 CH5
|
||||||
|
PWM_7 = (1 << TPM_SHIFT) | (0), // TPM1 CH0
|
||||||
|
PWM_8 = (1 << TPM_SHIFT) | (1), // TPM1 CH1
|
||||||
|
PWM_9 = (2 << TPM_SHIFT) | (0), // TPM2 CH0
|
||||||
|
PWM_10 = (2 << TPM_SHIFT) | (1), // TPM2 CH1
|
||||||
} PWMName;
|
} PWMName;
|
||||||
|
|
||||||
#define ADC_INSTANCE_SHIFT 8
|
#define ADC_INSTANCE_SHIFT 8
|
||||||
|
|
|
@ -148,3 +148,47 @@ const PinMap PinMap_SPI_SSEL[] = {
|
||||||
{PTD4 , SPI_1, 2},
|
{PTD4 , SPI_1, 2},
|
||||||
{NC , NC , 0}
|
{NC , NC , 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/************PWM***************/
|
||||||
|
const PinMap PinMap_PWM[] = {
|
||||||
|
{PTE29, PWM_3 , 3},
|
||||||
|
{PTE30, PWM_4 , 3},
|
||||||
|
{PTE31, PWM_5 , 3},
|
||||||
|
{PTE24, PWM_1 , 3},
|
||||||
|
{PTE25, PWM_2 , 3},
|
||||||
|
{PTA0 , PWM_6 , 3},
|
||||||
|
{PTA3 , PWM_1 , 3},
|
||||||
|
{PTA4 , PWM_2 , 3},
|
||||||
|
{PTA5 , PWM_3 , 3},
|
||||||
|
{PTC1 , PWM_1 , 4},
|
||||||
|
{PTC2 , PWM_2 , 4},
|
||||||
|
{PTC3 , PWM_3 , 4},
|
||||||
|
{PTC4 , PWM_4 , 4},
|
||||||
|
{PTC8 , PWM_5 , 3},
|
||||||
|
{PTC9 , PWM_6 , 3},
|
||||||
|
{PTD0 , PWM_1 , 4},
|
||||||
|
{PTD1 , PWM_2 , 4},
|
||||||
|
{PTD2 , PWM_3 , 4},
|
||||||
|
{PTD3 , PWM_4 , 4},
|
||||||
|
{PTD4 , PWM_5 , 4},
|
||||||
|
{PTD5 , PWM_6 , 4},
|
||||||
|
|
||||||
|
{PTE20, PWM_7 , 3},
|
||||||
|
{PTE21, PWM_8 , 3},
|
||||||
|
{PTA12, PWM_7 , 3},
|
||||||
|
{PTA13, PWM_8 , 3},
|
||||||
|
{PTB0, PWM_7 , 3},
|
||||||
|
{PTB1, PWM_8 , 3},
|
||||||
|
|
||||||
|
{PTE22, PWM_9 , 3},
|
||||||
|
{PTE23, PWM_10, 3},
|
||||||
|
{PTA1 , PWM_9 , 3},
|
||||||
|
{PTA2 , PWM_10, 3},
|
||||||
|
{PTB2 , PWM_9 , 3},
|
||||||
|
{PTB3 , PWM_10, 3},
|
||||||
|
{PTB18, PWM_9 , 3},
|
||||||
|
{PTB19, PWM_10, 3},
|
||||||
|
|
||||||
|
{NC , NC , 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2006-2013 ARM Limited
|
||||||
|
*
|
||||||
|
* 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 "mbed_assert.h"
|
||||||
|
#include "pwmout_api.h"
|
||||||
|
|
||||||
|
#if DEVICE_PWMOUT
|
||||||
|
|
||||||
|
#include "cmsis.h"
|
||||||
|
#include "pinmap.h"
|
||||||
|
#include "fsl_tpm.h"
|
||||||
|
#include "PeripheralPins.h"
|
||||||
|
|
||||||
|
static float pwm_clock_mhz;
|
||||||
|
/* Array of TPM peripheral base address. */
|
||||||
|
static TPM_Type *const tpm_addrs[] = TPM_BASE_PTRS;
|
||||||
|
|
||||||
|
void pwmout_init(pwmout_t* obj, PinName pin) {
|
||||||
|
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
|
||||||
|
MBED_ASSERT(pwm != (PWMName)NC);
|
||||||
|
|
||||||
|
obj->pwm_name = pwm;
|
||||||
|
|
||||||
|
uint32_t pwm_base_clock;
|
||||||
|
pwm_base_clock = CLOCK_GetFreq(kCLOCK_McgIrc48MClk);
|
||||||
|
float clkval = (float)pwm_base_clock / 1000000.0f;
|
||||||
|
uint32_t clkdiv = 0;
|
||||||
|
while (clkval > 1) {
|
||||||
|
clkdiv++;
|
||||||
|
clkval /= 2.0f;
|
||||||
|
if (clkdiv == 7) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pwm_clock_mhz = clkval;
|
||||||
|
uint32_t channel = pwm & 0xF;
|
||||||
|
uint32_t instance = pwm >> TPM_SHIFT;
|
||||||
|
tpm_config_t tpmInfo;
|
||||||
|
|
||||||
|
TPM_GetDefaultConfig(&tpmInfo);
|
||||||
|
tpmInfo.prescale = (tpm_clock_prescale_t)clkdiv;
|
||||||
|
/* Initialize TPM module */
|
||||||
|
TPM_Init(tpm_addrs[instance], &tpmInfo);
|
||||||
|
|
||||||
|
tpm_chnl_pwm_signal_param_t config = {
|
||||||
|
.chnlNumber = (tpm_chnl_t)channel,
|
||||||
|
.level = kTPM_HighTrue,
|
||||||
|
.dutyCyclePercent = 0,
|
||||||
|
};
|
||||||
|
// default to 20ms: standard for servos, and fine for e.g. brightness control
|
||||||
|
TPM_SetupPwm(tpm_addrs[instance], &config, 1, kTPM_EdgeAlignedPwm, 50, pwm_base_clock);
|
||||||
|
|
||||||
|
TPM_StartTimer(tpm_addrs[instance], kTPM_SystemClock);
|
||||||
|
|
||||||
|
// Wire pinout
|
||||||
|
pinmap_pinout(pin, PinMap_PWM);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_free(pwmout_t* obj) {
|
||||||
|
TPM_Deinit(tpm_addrs[obj->pwm_name >> TPM_SHIFT]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_write(pwmout_t* obj, float value) {
|
||||||
|
if (value < 0.0f) {
|
||||||
|
value = 0.0f;
|
||||||
|
} else if (value > 1.0f) {
|
||||||
|
value = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
|
||||||
|
uint16_t mod = base->MOD & TPM_MOD_MOD_MASK;
|
||||||
|
uint32_t new_count = (uint32_t)((float)(mod) * value);
|
||||||
|
// Update of CnV register
|
||||||
|
base->CONTROLS[obj->pwm_name & 0xF].CnV = new_count;
|
||||||
|
base->CNT = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float pwmout_read(pwmout_t* obj) {
|
||||||
|
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
|
||||||
|
uint16_t count = (base->CONTROLS[obj->pwm_name & 0xF].CnV) & TPM_CnV_VAL_MASK;
|
||||||
|
uint16_t mod = base->MOD & TPM_MOD_MOD_MASK;
|
||||||
|
|
||||||
|
if (mod == 0)
|
||||||
|
return 0.0;
|
||||||
|
float v = (float)(count) / (float)(mod);
|
||||||
|
return (v > 1.0f) ? (1.0f) : (v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_period(pwmout_t* obj, float seconds) {
|
||||||
|
pwmout_period_us(obj, seconds * 1000000.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_period_ms(pwmout_t* obj, int ms) {
|
||||||
|
pwmout_period_us(obj, ms * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the PWM period, keeping the duty cycle the same.
|
||||||
|
void pwmout_period_us(pwmout_t* obj, int us) {
|
||||||
|
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
|
||||||
|
float dc = pwmout_read(obj);
|
||||||
|
|
||||||
|
// Stop TPM clock to ensure instant update of MOD register
|
||||||
|
base->MOD = TPM_MOD_MOD((pwm_clock_mhz * (float)us) - 1);
|
||||||
|
pwmout_write(obj, dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
|
||||||
|
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
|
||||||
|
pwmout_pulsewidth_us(obj, ms * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
|
||||||
|
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
|
||||||
|
uint32_t value = (uint32_t)(pwm_clock_mhz * (float)us);
|
||||||
|
|
||||||
|
// Update of CnV register
|
||||||
|
base->CONTROLS[obj->pwm_name & 0xF].CnV = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -20,6 +20,7 @@
|
||||||
#define TEST_LED D3
|
#define TEST_LED D3
|
||||||
|
|
||||||
#elif defined (TARGET_K22F) || \
|
#elif defined (TARGET_K22F) || \
|
||||||
|
defined(TARGET_KL27Z) || \
|
||||||
defined (TARGET_LPC824)
|
defined (TARGET_LPC824)
|
||||||
#define TEST_LED LED_GREEN
|
#define TEST_LED LED_GREEN
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue