Merge pull request #13492 from talorion/fix-PwmOut-resets-after-suspend

Fix pwm out resets after suspend
pull/13587/head
Martin Kojtal 2020-09-10 12:40:18 +01:00 committed by GitHub
commit 468372e759
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 1263 additions and 573 deletions

View File

@ -51,6 +51,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
{
}
int pwmout_read_period_us(pwmout_t *obj)
{
return 0;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
}
@ -63,4 +68,9 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return 0;
}
#endif // DEVICE_PWMOUT

View File

@ -110,6 +110,12 @@ public:
*/
void period_us(int us);
/** Read the PWM period
* @returns
* The PWM period, specified in microseconds (int)
*/
int read_period_us();
/** Set the PWM pulsewidth, specified in seconds (float), keeping the period the same.
* @param seconds Change the pulse width of a PWM signal specified in seconds (float)
*/
@ -125,6 +131,12 @@ public:
*/
void pulsewidth_us(int us);
/** Read the PWM pulsewidth
* @returns
* The PWM pulsewith, specified in microseconds (int)
*/
int read_pulsewitdth_us();
/** Suspend PWM operation
*
* Control the PWM state. This is primarily intended
@ -191,6 +203,7 @@ protected:
bool _deep_sleep_locked;
bool _initialized;
float _duty_cycle;
int _period_us;
#endif
};

View File

@ -30,7 +30,8 @@ PwmOut::PwmOut(PinName pin) :
_pin(pin),
_deep_sleep_locked(false),
_initialized(false),
_duty_cycle(0)
_duty_cycle(0),
_period_us(0)
{
PwmOut::init();
}
@ -83,6 +84,14 @@ void PwmOut::period_us(int us)
core_util_critical_section_exit();
}
int PwmOut::read_period_us()
{
core_util_critical_section_enter();
auto val = pwmout_read_period_us(&_pwm);
core_util_critical_section_exit();
return val;
}
void PwmOut::pulsewidth(float seconds)
{
core_util_critical_section_enter();
@ -104,11 +113,20 @@ void PwmOut::pulsewidth_us(int us)
core_util_critical_section_exit();
}
int PwmOut::read_pulsewitdth_us()
{
core_util_critical_section_enter();
auto val = pwmout_read_pulsewidth_us(&_pwm);
core_util_critical_section_exit();
return val;
}
void PwmOut::suspend()
{
core_util_critical_section_enter();
if (_initialized) {
_duty_cycle = PwmOut::read();
_period_us = PwmOut::read_period_us();
PwmOut::deinit();
}
core_util_critical_section_exit();
@ -120,6 +138,7 @@ void PwmOut::resume()
if (!_initialized) {
PwmOut::init();
PwmOut::write(_duty_cycle);
PwmOut::period_us(_period_us);
}
core_util_critical_section_exit();
}

View File

@ -44,9 +44,11 @@ typedef struct pwmout_s pwmout_t;
* * ::pwmout_period sets the PWM period specified in seconds, keeping the duty cycle the same
* * ::pwmout_period_ms sets the PWM period specified in miliseconds, keeping the duty cycle the same
* * ::pwmout_period_us sets the PWM period specified in microseconds, keeping the duty cycle the same
* * ::pwmout_read_period_us reads the PWM period specified in microseconds
* * ::pwmout_pulsewidth sets the PWM pulsewidth specified in seconds, keeping the period the same
* * ::pwmout_pulsewidth_ms sets the PWM pulsewidth specified in miliseconds, keeping the period the same
* * ::pwmout_pulsewidth_us sets the PWM pulsewidth specified in microseconds, keeping the period the same
* * ::pwmout_read_pulsewidth_us read the PWM pulsewidth specified in microseconds
* * The accuracy of the PWM is +/- 10%
* * The PWM operations ::pwmout_write, ::pwmout_read, ::pwmout_read, ::pwmout_period_ms, ::pwmout_period_us
* ::pwmout_pulsewidth, ::pwmout_pulsewidth_ms, ::pwmout_pulsewidth_us take less than 20us to complete
@ -125,6 +127,13 @@ void pwmout_period_ms(pwmout_t *obj, int ms);
*/
void pwmout_period_us(pwmout_t *obj, int us);
/** Read the PWM period specified in microseconds
*
* @param obj The pwmout object
* @return A int output period
*/
int pwmout_read_period_us(pwmout_t *obj);
/** Set the PWM pulsewidth specified in seconds, keeping the period the same.
*
* @param obj The pwmout object
@ -146,6 +155,13 @@ void pwmout_pulsewidth_ms(pwmout_t *obj, int ms);
*/
void pwmout_pulsewidth_us(pwmout_t *obj, int us);
/** Read the PWM pulsewidth specified in microseconds
*
* @param obj The pwmout object
* @return A int output pulsewitdth
*/
int pwmout_read_pulsewidth_us(pwmout_t *obj);
/** Get the pins that support PWM
*
* Return a PinMap array of pins that support PWM.

View File

@ -74,6 +74,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
}
}
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period_us;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, (int)(seconds * CY_US_PER_SECOND));
@ -92,6 +97,11 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
}
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->width_us;
}
const PinMap *pwmout_pinmap(void)
{
return PinMap_PWM_OUT;

View File

@ -22,7 +22,8 @@
static float pwm_clock = 0;
void pwmout_init(pwmout_t* obj, PinName pin) {
void pwmout_init(pwmout_t *obj, PinName pin)
{
// determine the channel
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
@ -36,8 +37,9 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
while (clkval > 1) {
clkdiv++;
clkval /= 2.0;
if (clkdiv == 7)
if (clkdiv == 7) {
break;
}
}
pwm_clock = clkval;
@ -53,7 +55,7 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
ftm->MODE = FTM_MODE_FTMEN_MASK;
ftm->SYNC = FTM_SYNC_CNTMIN_MASK;
ftm->SYNCONF = FTM_SYNCONF_SYNCMODE_MASK | FTM_SYNCONF_SWSOC_MASK | FTM_SYNCONF_SWWRBUF_MASK;
//Without SYNCEN set CnV does not seem to update
ftm->COMBINE = FTM_COMBINE_SYNCEN0_MASK | FTM_COMBINE_SYNCEN1_MASK | FTM_COMBINE_SYNCEN2_MASK | FTM_COMBINE_SYNCEN3_MASK;
@ -64,60 +66,86 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_ms(obj, 20);
pwmout_write(obj, 0.0);
// Wire pinout
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj) {}
void pwmout_free(pwmout_t *obj) {}
void pwmout_write(pwmout_t* obj, float value) {
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0) {
value = 0.0;
} else if (value > 1.0) {
value = 1.0;
}
while(*obj->SYNC & FTM_SYNC_SWSYNC_MASK);
while (*obj->SYNC & FTM_SYNC_SWSYNC_MASK);
*obj->CnV = (uint32_t)((float)(*obj->MOD + 1) * value);
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
}
float pwmout_read(pwmout_t* obj) {
while(*obj->SYNC & FTM_SYNC_SWSYNC_MASK);
float pwmout_read(pwmout_t *obj)
{
while (*obj->SYNC & FTM_SYNC_SWSYNC_MASK);
float v = (float)(*obj->CnV) / (float)(*obj->MOD + 1);
return (v > 1.0) ? (1.0) : (v);
}
void pwmout_period(pwmout_t* obj, float seconds) {
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms) {
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) {
void pwmout_period_us(pwmout_t *obj, int us)
{
float dc = pwmout_read(obj);
*obj->MOD = (uint32_t)(pwm_clock * (float)us) - 1;
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
pwmout_write(obj, dc);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
int pwmout_read_period_us(pwmout_t *obj)
{
uint32_t pwm_period = 0;
if (pwm_clock > 0) {
pwm_period = ((*obj->MOD) + 1) / pwm_clock;
}
return pwm_period;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
*obj->CnV = (uint32_t)(pwm_clock * (float)us);
*obj->SYNC |= FTM_SYNC_SWSYNC_MASK;
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint32_t pwm_pulsewidth = 0;
if (pwm_clock > 0) {
pwm_pulsewidth = (*obj->CnV) / pwm_clock;
}
return pwm_pulsewidth;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -23,7 +23,8 @@
static float pwm_clock;
void pwmout_init(pwmout_t* obj, PinName pin) {
void pwmout_init(pwmout_t *obj, PinName pin)
{
// determine the channel
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
@ -51,10 +52,11 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
while (clkval > 1) {
clkdiv++;
clkval /= 2.0;
if (clkdiv == 7)
if (clkdiv == 7) {
break;
}
}
pwm_clock = clkval;
unsigned int port = (unsigned int)pin >> PORT_SHIFT;
unsigned int tpm_n = (pwm >> TPM_SHIFT);
@ -73,15 +75,16 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_ms(obj, 20);
pwmout_write (obj, 0);
pwmout_write(obj, 0);
// Wire pinout
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj) {}
void pwmout_free(pwmout_t *obj) {}
void pwmout_write(pwmout_t* obj, float value) {
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0) {
value = 0.0;
} else if (value > 1.0) {
@ -92,38 +95,63 @@ void pwmout_write(pwmout_t* obj, float value) {
*obj->CNT = 0;
}
float pwmout_read(pwmout_t* obj) {
float pwmout_read(pwmout_t *obj)
{
float v = (float)(*obj->CnV) / (float)(*obj->MOD + 1);
return (v > 1.0) ? (1.0) : (v);
}
void pwmout_period(pwmout_t* obj, float seconds) {
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms) {
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) {
void pwmout_period_us(pwmout_t *obj, int us)
{
float dc = pwmout_read(obj);
*obj->MOD = (uint32_t)(pwm_clock * (float)us) - 1;
pwmout_write(obj, dc);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
int pwmout_read_period_us(pwmout_t *obj)
{
uint32_t pwm_period = 0;
if (pwm_clock > 0) {
pwm_period = ((*obj->MOD) + 1) / pwm_clock;
}
return pwm_period;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
*obj->CnV = (uint32_t)(pwm_clock * (float)us);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint32_t pwm_pulsewidth = 0;
if (pwm_clock > 0) {
pwm_pulsewidth = (*obj->CnV) / pwm_clock;
}
return pwm_pulsewidth;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -27,7 +27,7 @@ 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)
void pwmout_init(pwmout_t *obj, PinName pin)
{
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
@ -73,12 +73,12 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
FTM_Deinit(ftm_addrs[obj->pwm_name >> TPM_SHIFT]);
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0f) {
value = 0.0f;
@ -96,30 +96,31 @@ void pwmout_write(pwmout_t* obj, float value)
FTM_SetSoftwareTrigger(base, true);
}
float pwmout_read(pwmout_t* obj)
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)
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)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
float dc = pwmout_read(obj);
@ -129,17 +130,27 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_write(obj, dc);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
uint32_t pwm_period = 0;
if (pwm_clock_mhz > 0) {
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_period = ((base->MOD) + 1) / pwm_clock_mhz;
}
return pwm_period;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
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);
@ -150,6 +161,16 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
FTM_SetSoftwareTrigger(base, true);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint32_t pwm_pulsewidth = 0;
if (pwm_clock_mhz > 0) {
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_pulsewidth = (base->CONTROLS[obj->pwm_name & 0xF].CnV) / pwm_clock_mhz;
}
return pwm_pulsewidth;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -27,7 +27,7 @@ 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)
void pwmout_init(pwmout_t *obj, PinName pin)
{
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
@ -73,12 +73,12 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
FTM_Deinit(ftm_addrs[obj->pwm_name >> TPM_SHIFT]);
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0f) {
value = 0.0f;
@ -96,30 +96,31 @@ void pwmout_write(pwmout_t* obj, float value)
FTM_SetSoftwareTrigger(base, true);
}
float pwmout_read(pwmout_t* obj)
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)
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)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
float dc = pwmout_read(obj);
@ -129,17 +130,27 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_write(obj, dc);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
uint32_t pwm_period = 0;
if (pwm_clock_mhz > 0) {
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_period = ((base->MOD) + 1) / pwm_clock_mhz;
}
return pwm_period;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
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);
@ -150,6 +161,16 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
FTM_SetSoftwareTrigger(base, true);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint32_t pwm_pulsewidth = 0;
if (pwm_clock_mhz > 0) {
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_pulsewidth = (base->CONTROLS[obj->pwm_name & 0xF].CnV) / pwm_clock_mhz;
}
return pwm_pulsewidth;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -27,7 +27,7 @@ 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)
void pwmout_init(pwmout_t *obj, PinName pin)
{
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
@ -72,12 +72,12 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
TPM_Deinit(tpm_addrs[obj->pwm_name >> TPM_SHIFT]);
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0f) {
value = 0.0f;
@ -93,30 +93,31 @@ void pwmout_write(pwmout_t* obj, float value)
base->CNT = 0;
}
float pwmout_read(pwmout_t* obj)
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)
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)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
float dc = pwmout_read(obj);
@ -126,17 +127,27 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_write(obj, dc);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
uint32_t pwm_period = 0;
if (pwm_clock_mhz > 0) {
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_period = ((base->MOD) + 1) / pwm_clock_mhz;
}
return pwm_period;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
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);
@ -145,6 +156,16 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
base->CONTROLS[obj->pwm_name & 0xF].CnV = value;
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint32_t pwm_pulsewidth = 0;
if (pwm_clock_mhz > 0) {
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_pulsewidth = (base->CONTROLS[obj->pwm_name & 0xF].CnV) / pwm_clock_mhz;
}
return pwm_pulsewidth;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -27,7 +27,7 @@ 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)
void pwmout_init(pwmout_t *obj, PinName pin)
{
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
@ -72,12 +72,12 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
TPM_Deinit(tpm_addrs[obj->pwm_name >> TPM_SHIFT]);
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0f) {
value = 0.0f;
@ -93,30 +93,31 @@ void pwmout_write(pwmout_t* obj, float value)
base->CNT = 0;
}
float pwmout_read(pwmout_t* obj)
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)
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)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
float dc = pwmout_read(obj);
@ -126,17 +127,27 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_write(obj, dc);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
uint32_t pwm_period = 0;
if (pwm_clock_mhz > 0) {
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_period = ((base->MOD) + 1) / pwm_clock_mhz;
}
return pwm_period;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
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);
@ -145,6 +156,16 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
base->CONTROLS[obj->pwm_name & 0xF].CnV = value;
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint32_t pwm_pulsewidth = 0;
if (pwm_clock_mhz > 0) {
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_pulsewidth = (base->CONTROLS[obj->pwm_name & 0xF].CnV) / pwm_clock_mhz;
}
return pwm_pulsewidth;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -27,7 +27,7 @@ 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)
void pwmout_init(pwmout_t *obj, PinName pin)
{
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
@ -72,12 +72,12 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
TPM_Deinit(tpm_addrs[obj->pwm_name >> TPM_SHIFT]);
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0f) {
value = 0.0f;
@ -93,30 +93,31 @@ void pwmout_write(pwmout_t* obj, float value)
base->CNT = 0;
}
float pwmout_read(pwmout_t* obj)
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)
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)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
float dc = pwmout_read(obj);
@ -126,17 +127,27 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_write(obj, dc);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
uint32_t pwm_period = 0;
if (pwm_clock_mhz > 0) {
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_period = ((base->MOD) + 1) / pwm_clock_mhz;
}
return pwm_period;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
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);
@ -145,6 +156,16 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
base->CONTROLS[obj->pwm_name & 0xF].CnV = value;
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint32_t pwm_pulsewidth = 0;
if (pwm_clock_mhz > 0) {
TPM_Type *base = tpm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_pulsewidth = (base->CONTROLS[obj->pwm_name & 0xF].CnV) / pwm_clock_mhz;
}
return pwm_pulsewidth;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -27,7 +27,7 @@ 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)
void pwmout_init(pwmout_t *obj, PinName pin)
{
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
@ -73,12 +73,12 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
FTM_Deinit(ftm_addrs[obj->pwm_name >> TPM_SHIFT]);
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0f) {
value = 0.0f;
@ -96,30 +96,31 @@ void pwmout_write(pwmout_t* obj, float value)
FTM_SetSoftwareTrigger(base, true);
}
float pwmout_read(pwmout_t* obj)
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)
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)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
float dc = pwmout_read(obj);
@ -129,17 +130,27 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_write(obj, dc);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
uint32_t pwm_period = 0;
if (pwm_clock_mhz > 0) {
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];;
pwm_period = ((base->MOD) + 1) / pwm_clock_mhz;
}
return pwm_period;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
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);
@ -150,6 +161,16 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
FTM_SetSoftwareTrigger(base, true);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint32_t pwm_pulsewidth = 0;
if (pwm_clock_mhz > 0) {
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_pulsewidth = (base->CONTROLS[obj->pwm_name & 0xF].CnV) / pwm_clock_mhz;
}
return pwm_pulsewidth;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -158,6 +158,17 @@ void pwmout_period_us(pwmout_t *obj, int us)
pwmout_write(obj, dc);
}
int pwmout_read_period_us(pwmout_t *obj)
{
uint32_t pwm_period = 0;
if (pwm_clock_mhz > 0) {
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
uint16_t mod = base->MOD & FTM_MOD_MOD_MASK;
pwm_period = ((mod) + 1) / pwm_clock_mhz;
}
return pwm_period;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
@ -179,6 +190,16 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
FTM_SetSoftwareTrigger(base, true);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint32_t pwm_pulsewidth = 0;
if (pwm_clock_mhz > 0) {
FTM_Type *base = ftm_addrs[obj->pwm_name >> TPM_SHIFT];
pwm_pulsewidth = (base->CONTROLS[obj->pwm_name & 0xF].CnV) / pwm_clock_mhz;
}
return pwm_pulsewidth;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -249,6 +249,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
timer_enable(obj->pwm);
}
int pwmout_read_period_us(pwmout_t *obj)
{
return TIMER_CAR(obj->pwm);
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
@ -298,6 +303,34 @@ static uint32_t timer_get_clock(uint32_t timer_periph)
return timerclk;
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint16_t pulse = 0;
switch (obj->ch) {
case TIMER_CH_0:
pulse = TIMER_CH0CV(obj->pwm);
break;
case TIMER_CH_1:
pulse = TIMER_CH1CV(obj->pwm);
break;
case TIMER_CH_2:
pulse = TIMER_CH2CV(obj->pwm);
break;
case TIMER_CH_3:
pulse = TIMER_CH3CV(obj->pwm);
break;
default:
error("Error: pwm channel error! \r\n");
}
return pulse;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -194,6 +194,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
timer_enable(obj->pwm);
}
int pwmout_read_period_us(pwmout_t *obj)
{
return TIMER_CAR(obj->pwm);
}
/** Set the PWM pulsewidth specified in seconds, keeping the period the same.
*
* @param obj The pwmout object
@ -234,6 +239,34 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
timer_channel_output_pulse_value_config(obj->pwm, obj->ch, pulse);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint16_t pulse = 0;
switch (obj->ch) {
case TIMER_CH_0:
pulse = TIMER_CH0CV(obj->pwm);
break;
case TIMER_CH_1:
pulse = TIMER_CH1CV(obj->pwm);
break;
case TIMER_CH_2:
pulse = TIMER_CH2CV(obj->pwm);
break;
case TIMER_CH_3:
pulse = TIMER_CH3CV(obj->pwm);
break;
default:
error("Error: pwm channel error! \r\n");
}
return pulse;
}
static uint32_t timer_get_clock(uint32_t timer_periph)
{
uint32_t timerclk;

View File

@ -40,7 +40,7 @@
#include "PeripheralPins.h"
//******************************************************************************
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
// Make sure the pin is free for GPIO use
unsigned int port = (unsigned int)pin >> PORT_SHIFT;
@ -51,20 +51,20 @@ void pwmout_init(pwmout_t* obj, PinName pin)
PinMap pwm = PinMap_PWM[0];
// Check if there is a pulse train already active on this port
int pin_func = (MXC_GPIO->func_sel[port] & (0xF << (port_pin*4))) >> (port_pin*4);
int pin_func = (MXC_GPIO->func_sel[port] & (0xF << (port_pin * 4))) >> (port_pin * 4);
MBED_ASSERT((pin_func < 1) || (pin_func > 3));
// Search through PinMap_PWM to find the pin
while(pwm.pin != pin) {
while (pwm.pin != pin) {
pwm = PinMap_PWM[++i];
}
// Find a free PT instance on this pin
while(pwm.pin == pin) {
while (pwm.pin == pin) {
// Check to see if this PT instance is free
if((((mxc_pt_regs_t*)pwm.peripheral)->rate_length &
MXC_F_PT_RATE_LENGTH_MODE)) {
if ((((mxc_pt_regs_t *)pwm.peripheral)->rate_length &
MXC_F_PT_RATE_LENGTH_MODE)) {
break;
}
@ -78,10 +78,10 @@ void pwmout_init(pwmout_t* obj, PinName pin)
MXC_CLKMAN->clk_ctrl_2_pt = MXC_E_CLKMAN_CLK_SCALE_ENABLED;
// Set the obj pointer to the propper PWM instance
obj->pwm = (mxc_pt_regs_t*)pwm.peripheral;
obj->pwm = (mxc_pt_regs_t *)pwm.peripheral;
// Initialize object period and pulse width
obj->period = -1;
obj->period = -1;
obj->pulse_width = -1;
// Disable the output
@ -94,17 +94,17 @@ void pwmout_init(pwmout_t* obj, PinName pin)
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_us(obj, 20000);
pwmout_write (obj, 0);
pwmout_write(obj, 0);
// Set the drive mode to normal
MXC_SET_FIELD(&MXC_GPIO->out_mode[port], (0x7 << (port_pin*4)), (MXC_V_GPIO_OUT_MODE_NORMAL_DRIVE << (port_pin*4)));
MXC_SET_FIELD(&MXC_GPIO->out_mode[port], (0x7 << (port_pin * 4)), (MXC_V_GPIO_OUT_MODE_NORMAL_DRIVE << (port_pin * 4)));
// Enable the global pwm
MXC_PTG->ctrl = MXC_F_PT_CTRL_ENABLE_ALL;
}
//******************************************************************************
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
// Set the registers to the reset value
obj->pwm->train = 0;
@ -112,39 +112,39 @@ void pwmout_free(pwmout_t* obj)
}
//******************************************************************************
static void pwmout_update(pwmout_t* obj)
static void pwmout_update(pwmout_t *obj)
{
// Calculate and set the divider ratio
int div = (obj->period * (SystemCoreClock/1000000))/32;
if (div < 2){
int div = (obj->period * (SystemCoreClock / 1000000)) / 32;
if (div < 2) {
div = 2;
}
MXC_SET_FIELD(&obj->pwm->rate_length, MXC_F_PT_RATE_LENGTH_RATE_CONTROL, div);
// Change the duty cycle to adjust the pulse width
obj->pwm->train = (0xFFFFFFFF << (32-((32*obj->pulse_width)/obj->period)));
obj->pwm->train = (0xFFFFFFFF << (32 - ((32 * obj->pulse_width) / obj->period)));
}
//******************************************************************************
void pwmout_write(pwmout_t* obj, float percent)
void pwmout_write(pwmout_t *obj, float percent)
{
// Saturate percent if outside of range
if(percent < 0.0) {
if (percent < 0.0) {
percent = 0.0;
} else if(percent > 1.0) {
} else if (percent > 1.0) {
percent = 1.0;
}
// Resize the pulse width to set the duty cycle
pwmout_pulsewidth_us(obj, (int)(percent*obj->period));
pwmout_pulsewidth_us(obj, (int)(percent * obj->period));
}
//******************************************************************************
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
// Check for when pulsewidth or period equals 0
if((obj->pulse_width == 0) || (obj->period == 0)){
if ((obj->pulse_width == 0) || (obj->period == 0)) {
return 0;
}
@ -153,26 +153,26 @@ float pwmout_read(pwmout_t* obj)
}
//******************************************************************************
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, (int)(seconds * 1000000.0));
}
//******************************************************************************
void pwmout_period_ms(pwmout_t* obj, int ms)
void pwmout_period_ms(pwmout_t *obj, int ms)
{
pwmout_period_us(obj, ms*1000);
pwmout_period_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_period_us(pwmout_t* obj, int us)
void pwmout_period_us(pwmout_t *obj, int us)
{
// Check the range of the period
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock/32)));
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
// Set pulse width to half the period if uninitialized
if(obj->pulse_width == -1){
obj->pulse_width = us/2;
if (obj->pulse_width == -1) {
obj->pulse_width = us / 2;
}
// Save the period
@ -183,26 +183,32 @@ void pwmout_period_us(pwmout_t* obj, int us)
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period;
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, (int)(seconds * 1000000.0));
}
//******************************************************************************
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms*1000);
pwmout_pulsewidth_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
// Check the range of the pulsewidth
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock/32)));
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
// Initialize period to double the pulsewidth if uninitialized
if(obj->period == -1){
obj->period = 2*us;
if (obj->period == -1) {
obj->period = 2 * us;
}
// Save the pulsewidth
@ -212,6 +218,12 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
pwmout_update(obj);
}
//******************************************************************************
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulse_width;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -40,7 +40,7 @@
#include "PeripheralPins.h"
//******************************************************************************
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
// Make sure the pin is free for GPIO use
unsigned int port = (unsigned int)pin >> PORT_SHIFT;
@ -51,20 +51,20 @@ void pwmout_init(pwmout_t* obj, PinName pin)
PinMap pwm = PinMap_PWM[0];
// Check if there is a pulse train already active on this port
int pin_func = (MXC_GPIO->func_sel[port] & (0xF << (port_pin*4))) >> (port_pin*4);
int pin_func = (MXC_GPIO->func_sel[port] & (0xF << (port_pin * 4))) >> (port_pin * 4);
MBED_ASSERT((pin_func < 1) || (pin_func > 3));
// Search through PinMap_PWM to find the pin
while(pwm.pin != pin) {
while (pwm.pin != pin) {
pwm = PinMap_PWM[++i];
}
// Find a free PT instance on this pin
while(pwm.pin == pin) {
while (pwm.pin == pin) {
// Check to see if this PT instance is free
if((((mxc_pt_regs_t*)pwm.peripheral)->rate_length &
MXC_F_PT_RATE_LENGTH_MODE)) {
if ((((mxc_pt_regs_t *)pwm.peripheral)->rate_length &
MXC_F_PT_RATE_LENGTH_MODE)) {
break;
}
@ -78,10 +78,10 @@ void pwmout_init(pwmout_t* obj, PinName pin)
MXC_CLKMAN->clk_ctrl_2_pt = MXC_E_CLKMAN_CLK_SCALE_ENABLED;
// Set the obj pointer to the propper PWM instance
obj->pwm = (mxc_pt_regs_t*)pwm.peripheral;
obj->pwm = (mxc_pt_regs_t *)pwm.peripheral;
// Initialize object period and pulse width
obj->period = -1;
obj->period = -1;
obj->pulse_width = -1;
// Disable the output
@ -94,17 +94,17 @@ void pwmout_init(pwmout_t* obj, PinName pin)
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_us(obj, 20000);
pwmout_write (obj, 0);
pwmout_write(obj, 0);
// Set the drive mode to normal
MXC_SET_FIELD(&MXC_GPIO->out_mode[port], (0x7 << (port_pin*4)), (MXC_V_GPIO_OUT_MODE_NORMAL_DRIVE << (port_pin*4)));
MXC_SET_FIELD(&MXC_GPIO->out_mode[port], (0x7 << (port_pin * 4)), (MXC_V_GPIO_OUT_MODE_NORMAL_DRIVE << (port_pin * 4)));
// Enable the global pwm
MXC_PTG->ctrl = MXC_F_PT_CTRL_ENABLE_ALL;
}
//******************************************************************************
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
// Set the registers to the reset value
obj->pwm->train = 0;
@ -112,39 +112,39 @@ void pwmout_free(pwmout_t* obj)
}
//******************************************************************************
static void pwmout_update(pwmout_t* obj)
static void pwmout_update(pwmout_t *obj)
{
// Calculate and set the divider ratio
int div = (obj->period * (SystemCoreClock/1000000))/32;
if (div < 2){
int div = (obj->period * (SystemCoreClock / 1000000)) / 32;
if (div < 2) {
div = 2;
}
MXC_SET_FIELD(&obj->pwm->rate_length, MXC_F_PT_RATE_LENGTH_RATE_CONTROL, div);
// Change the duty cycle to adjust the pulse width
obj->pwm->train = (0xFFFFFFFF << (32-((32*obj->pulse_width)/obj->period)));
obj->pwm->train = (0xFFFFFFFF << (32 - ((32 * obj->pulse_width) / obj->period)));
}
//******************************************************************************
void pwmout_write(pwmout_t* obj, float percent)
void pwmout_write(pwmout_t *obj, float percent)
{
// Saturate percent if outside of range
if(percent < 0.0) {
if (percent < 0.0) {
percent = 0.0;
} else if(percent > 1.0) {
} else if (percent > 1.0) {
percent = 1.0;
}
// Resize the pulse width to set the duty cycle
pwmout_pulsewidth_us(obj, (int)(percent*obj->period));
pwmout_pulsewidth_us(obj, (int)(percent * obj->period));
}
//******************************************************************************
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
// Check for when pulsewidth or period equals 0
if((obj->pulse_width == 0) || (obj->period == 0)){
if ((obj->pulse_width == 0) || (obj->period == 0)) {
return 0;
}
@ -153,26 +153,26 @@ float pwmout_read(pwmout_t* obj)
}
//******************************************************************************
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, (int)(seconds * 1000000.0));
}
//******************************************************************************
void pwmout_period_ms(pwmout_t* obj, int ms)
void pwmout_period_ms(pwmout_t *obj, int ms)
{
pwmout_period_us(obj, ms*1000);
pwmout_period_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_period_us(pwmout_t* obj, int us)
void pwmout_period_us(pwmout_t *obj, int us)
{
// Check the range of the period
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock/32)));
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
// Set pulse width to half the period if uninitialized
if(obj->pulse_width == -1){
obj->pulse_width = us/2;
if (obj->pulse_width == -1) {
obj->pulse_width = us / 2;
}
// Save the period
@ -183,26 +183,32 @@ void pwmout_period_us(pwmout_t* obj, int us)
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period;
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, (int)(seconds * 1000000.0));
}
//******************************************************************************
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms*1000);
pwmout_pulsewidth_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
// Check the range of the pulsewidth
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock/32)));
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
// Initialize period to double the pulsewidth if uninitialized
if(obj->period == -1){
obj->period = 2*us;
if (obj->period == -1) {
obj->period = 2 * us;
}
// Save the pulsewidth
@ -212,6 +218,12 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
pwmout_update(obj);
}
//******************************************************************************
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulse_width;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -39,7 +39,7 @@
#include "PeripheralPins.h"
//******************************************************************************
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
// Make sure the pin is free for GPIO use
unsigned int port = (unsigned int)pin >> PORT_SHIFT;
@ -50,7 +50,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
PinMap pwm = PinMap_PWM[0];
// Check if there is a pulse train already active on this port
int pin_func = (MXC_GPIO->func_sel[port] & (0xF << (port_pin*4))) >> (port_pin*4);
int pin_func = (MXC_GPIO->func_sel[port] & (0xF << (port_pin * 4))) >> (port_pin * 4);
MBED_ASSERT((pin_func < 1) || (pin_func > 3));
// Search through PinMap_PWM to find the pin
@ -62,7 +62,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
while (pwm.pin == pin) {
// Check to see if this PT instance is free
if (((mxc_pt_regs_t*)pwm.peripheral)->rate_length & MXC_F_PT_RATE_LENGTH_MODE) {
if (((mxc_pt_regs_t *)pwm.peripheral)->rate_length & MXC_F_PT_RATE_LENGTH_MODE) {
break;
}
@ -76,7 +76,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
MXC_CLKMAN->sys_clk_ctrl_7_pt = MXC_S_CLKMAN_CLK_SCALE_DIV_1;
// Set the obj pointer to the propper PWM instance
obj->pwm = (mxc_pt_regs_t*)pwm.peripheral;
obj->pwm = (mxc_pt_regs_t *)pwm.peripheral;
// Initialize object period and pulse width
obj->period = -1;
@ -92,17 +92,17 @@ void pwmout_init(pwmout_t* obj, PinName pin)
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_us(obj, 20000);
pwmout_write (obj, 0);
pwmout_write(obj, 0);
// Set the drive mode to normal
MXC_SET_FIELD(&MXC_GPIO->out_mode[port], (0x7 << (port_pin*4)), (MXC_V_GPIO_OUT_MODE_NORMAL << (port_pin*4)));
MXC_SET_FIELD(&MXC_GPIO->out_mode[port], (0x7 << (port_pin * 4)), (MXC_V_GPIO_OUT_MODE_NORMAL << (port_pin * 4)));
// Enable this PWM channel
MXC_PTG->enable |= (1 << MXC_PT_GET_IDX(obj->pwm));
}
//******************************************************************************
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
// Set the registers to the reset value
obj->pwm->train = 0;
@ -110,36 +110,36 @@ void pwmout_free(pwmout_t* obj)
}
//******************************************************************************
static void pwmout_update(pwmout_t* obj)
static void pwmout_update(pwmout_t *obj)
{
// Calculate and set the divider ratio
int div = (obj->period * (SystemCoreClock/1000000))/32;
int div = (obj->period * (SystemCoreClock / 1000000)) / 32;
if (div < 2) {
div = 2;
}
MXC_SET_FIELD(&obj->pwm->rate_length, MXC_F_PT_RATE_LENGTH_RATE_CONTROL, div);
// Change the duty cycle to adjust the pulse width
obj->pwm->train = (0xFFFFFFFF << (32-((32*obj->pulse_width)/obj->period)));
obj->pwm->train = (0xFFFFFFFF << (32 - ((32 * obj->pulse_width) / obj->period)));
}
//******************************************************************************
void pwmout_write(pwmout_t* obj, float percent)
void pwmout_write(pwmout_t *obj, float percent)
{
// Saturate percent if outside of range
if (percent < 0.0f) {
percent = 0.0f;
} else if(percent > 1.0f) {
} else if (percent > 1.0f) {
percent = 1.0f;
}
// Resize the pulse width to set the duty cycle
pwmout_pulsewidth_us(obj, (int)(percent*obj->period));
pwmout_pulsewidth_us(obj, (int)(percent * obj->period));
}
//******************************************************************************
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
// Check for when pulsewidth or period equals 0
if ((obj->pulse_width == 0) || (obj->period == 0)) {
@ -151,26 +151,26 @@ float pwmout_read(pwmout_t* obj)
}
//******************************************************************************
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, (int)(seconds * 1000000.0f));
}
//******************************************************************************
void pwmout_period_ms(pwmout_t* obj, int ms)
void pwmout_period_ms(pwmout_t *obj, int ms)
{
pwmout_period_us(obj, ms*1000);
pwmout_period_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_period_us(pwmout_t* obj, int us)
void pwmout_period_us(pwmout_t *obj, int us)
{
// Check the range of the period
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock/32)));
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
// Set pulse width to half the period if uninitialized
if (obj->pulse_width == -1) {
obj->pulse_width = us/2;
obj->pulse_width = us / 2;
}
// Save the period
@ -181,26 +181,32 @@ void pwmout_period_us(pwmout_t* obj, int us)
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period;
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, (int)(seconds * 1000000.0f));
}
//******************************************************************************
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms*1000);
pwmout_pulsewidth_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
// Check the range of the pulsewidth
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock/32)));
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
// Initialize period to double the pulsewidth if uninitialized
if (obj->period == -1) {
obj->period = 2*us;
obj->period = 2 * us;
}
// Save the pulsewidth
@ -210,6 +216,12 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
pwmout_update(obj);
}
//******************************************************************************
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulse_width;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -45,7 +45,7 @@
//******************************************************************************
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
// Make sure the pin is free for GPIO use
unsigned int port = (unsigned int)pin >> PORT_SHIFT;
@ -69,7 +69,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
while (pwm.pin == pin) {
// Check to see if this PT instance is free
if (((mxc_pt_regs_t*)pwm.peripheral)->rate_length & MXC_F_PT_RATE_LENGTH_MODE) {
if (((mxc_pt_regs_t *)pwm.peripheral)->rate_length & MXC_F_PT_RATE_LENGTH_MODE) {
break;
}
@ -83,7 +83,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
MXC_CLKMAN->sys_clk_ctrl_7_pt = MXC_S_CLKMAN_CLK_SCALE_DIV_1;
// Set the obj pointer to the propper PWM instance
obj->pwm = (mxc_pt_regs_t*)pwm.peripheral;
obj->pwm = (mxc_pt_regs_t *)pwm.peripheral;
// Initialize object period and pulse width
obj->period = -1;
@ -99,7 +99,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_us(obj, 20000);
pwmout_write (obj, 0);
pwmout_write(obj, 0);
// Set the drive mode to normal
MXC_SET_FIELD(&MXC_GPIO->out_mode[port],
@ -111,7 +111,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
}
//******************************************************************************
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
// Set the registers to the reset value
obj->pwm->train = 0;
@ -119,10 +119,10 @@ void pwmout_free(pwmout_t* obj)
}
//******************************************************************************
static void pwmout_update(pwmout_t* obj)
static void pwmout_update(pwmout_t *obj)
{
// Calculate and set the divider ratio
int div = (obj->period * (SystemCoreClock / 1000000))/32;
int div = (obj->period * (SystemCoreClock / 1000000)) / 32;
if (div < 2) {
div = 2;
}
@ -134,24 +134,24 @@ static void pwmout_update(pwmout_t* obj)
//******************************************************************************
void pwmout_write(pwmout_t* obj, float percent)
void pwmout_write(pwmout_t *obj, float percent)
{
// Saturate percent if outside of range
if(percent < 0.0f) {
if (percent < 0.0f) {
percent = 0.0f;
} else if(percent > 1.0f) {
} else if (percent > 1.0f) {
percent = 1.0f;
}
// Resize the pulse width to set the duty cycle
pwmout_pulsewidth_us(obj, (int)(percent*obj->period));
pwmout_pulsewidth_us(obj, (int)(percent * obj->period));
}
//******************************************************************************
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
// Check for when pulsewidth or period equals 0
if((obj->pulse_width == 0) || (obj->period == 0)) {
if ((obj->pulse_width == 0) || (obj->period == 0)) {
return 0;
}
@ -160,19 +160,19 @@ float pwmout_read(pwmout_t* obj)
}
//******************************************************************************
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, (int)(seconds * 1000000.0f));
}
//******************************************************************************
void pwmout_period_ms(pwmout_t* obj, int ms)
void pwmout_period_ms(pwmout_t *obj, int ms)
{
pwmout_period_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_period_us(pwmout_t* obj, int us)
void pwmout_period_us(pwmout_t *obj, int us)
{
// Check the range of the period
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
@ -190,19 +190,25 @@ void pwmout_period_us(pwmout_t* obj, int us)
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period;
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, (int)(seconds * 1000000.0f));
}
//******************************************************************************
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
// Check the range of the pulsewidth
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
@ -219,6 +225,12 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
pwmout_update(obj);
}
//******************************************************************************
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulse_width;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -45,7 +45,7 @@
//******************************************************************************
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
// Make sure the pin is free for GPIO use
unsigned int port = (unsigned int)pin >> PORT_SHIFT;
@ -69,7 +69,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
while (pwm.pin == pin) {
// Check to see if this PT instance is free
if (((mxc_pt_regs_t*)pwm.peripheral)->rate_length & MXC_F_PT_RATE_LENGTH_MODE) {
if (((mxc_pt_regs_t *)pwm.peripheral)->rate_length & MXC_F_PT_RATE_LENGTH_MODE) {
break;
}
@ -83,7 +83,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
MXC_CLKMAN->sys_clk_ctrl_7_pt = MXC_S_CLKMAN_CLK_SCALE_DIV_1;
// Set the obj pointer to the propper PWM instance
obj->pwm = (mxc_pt_regs_t*)pwm.peripheral;
obj->pwm = (mxc_pt_regs_t *)pwm.peripheral;
// Initialize object period and pulse width
obj->period = -1;
@ -99,7 +99,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_us(obj, 20000);
pwmout_write (obj, 0);
pwmout_write(obj, 0);
// Set the drive mode to normal
MXC_SET_FIELD(&MXC_GPIO->out_mode[port],
@ -111,7 +111,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
}
//******************************************************************************
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
// Set the registers to the reset value
obj->pwm->train = 0;
@ -119,10 +119,10 @@ void pwmout_free(pwmout_t* obj)
}
//******************************************************************************
static void pwmout_update(pwmout_t* obj)
static void pwmout_update(pwmout_t *obj)
{
// Calculate and set the divider ratio
int div = (obj->period * (SystemCoreClock / 1000000))/32;
int div = (obj->period * (SystemCoreClock / 1000000)) / 32;
if (div < 2) {
div = 2;
}
@ -134,24 +134,24 @@ static void pwmout_update(pwmout_t* obj)
//******************************************************************************
void pwmout_write(pwmout_t* obj, float percent)
void pwmout_write(pwmout_t *obj, float percent)
{
// Saturate percent if outside of range
if(percent < 0.0f) {
if (percent < 0.0f) {
percent = 0.0f;
} else if(percent > 1.0f) {
} else if (percent > 1.0f) {
percent = 1.0f;
}
// Resize the pulse width to set the duty cycle
pwmout_pulsewidth_us(obj, (int)(percent*obj->period));
pwmout_pulsewidth_us(obj, (int)(percent * obj->period));
}
//******************************************************************************
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
// Check for when pulsewidth or period equals 0
if((obj->pulse_width == 0) || (obj->period == 0)) {
if ((obj->pulse_width == 0) || (obj->period == 0)) {
return 0;
}
@ -160,19 +160,19 @@ float pwmout_read(pwmout_t* obj)
}
//******************************************************************************
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, (int)(seconds * 1000000.0f));
}
//******************************************************************************
void pwmout_period_ms(pwmout_t* obj, int ms)
void pwmout_period_ms(pwmout_t *obj, int ms)
{
pwmout_period_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_period_us(pwmout_t* obj, int us)
void pwmout_period_us(pwmout_t *obj, int us)
{
// Check the range of the period
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
@ -190,19 +190,25 @@ void pwmout_period_us(pwmout_t* obj, int us)
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period;
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, (int)(seconds * 1000000.0f));
}
//******************************************************************************
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
// Check the range of the pulsewidth
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
@ -219,6 +225,12 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
pwmout_update(obj);
}
//******************************************************************************
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulse_width;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -45,7 +45,7 @@
//******************************************************************************
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
// Make sure the pin is free for GPIO use
unsigned int port = (unsigned int)pin >> PORT_SHIFT;
@ -69,7 +69,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
while (pwm.pin == pin) {
// Check to see if this PT instance is free
if (((mxc_pt_regs_t*)pwm.peripheral)->rate_length & MXC_F_PT_RATE_LENGTH_MODE) {
if (((mxc_pt_regs_t *)pwm.peripheral)->rate_length & MXC_F_PT_RATE_LENGTH_MODE) {
break;
}
@ -83,7 +83,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
MXC_CLKMAN->sys_clk_ctrl_7_pt = MXC_S_CLKMAN_CLK_SCALE_DIV_1;
// Set the obj pointer to the propper PWM instance
obj->pwm = (mxc_pt_regs_t*)pwm.peripheral;
obj->pwm = (mxc_pt_regs_t *)pwm.peripheral;
// Initialize object period and pulse width
obj->period = -1;
@ -99,7 +99,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_us(obj, 20000);
pwmout_write (obj, 0);
pwmout_write(obj, 0);
// Set the drive mode to normal
MXC_SET_FIELD(&MXC_GPIO->out_mode[port],
@ -111,7 +111,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
}
//******************************************************************************
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
// Set the registers to the reset value
obj->pwm->train = 0;
@ -119,10 +119,10 @@ void pwmout_free(pwmout_t* obj)
}
//******************************************************************************
static void pwmout_update(pwmout_t* obj)
static void pwmout_update(pwmout_t *obj)
{
// Calculate and set the divider ratio
int div = (obj->period * (SystemCoreClock / 1000000))/32;
int div = (obj->period * (SystemCoreClock / 1000000)) / 32;
if (div < 2) {
div = 2;
}
@ -134,24 +134,24 @@ static void pwmout_update(pwmout_t* obj)
//******************************************************************************
void pwmout_write(pwmout_t* obj, float percent)
void pwmout_write(pwmout_t *obj, float percent)
{
// Saturate percent if outside of range
if(percent < 0.0f) {
if (percent < 0.0f) {
percent = 0.0f;
} else if(percent > 1.0f) {
} else if (percent > 1.0f) {
percent = 1.0f;
}
// Resize the pulse width to set the duty cycle
pwmout_pulsewidth_us(obj, (int)(percent*obj->period));
pwmout_pulsewidth_us(obj, (int)(percent * obj->period));
}
//******************************************************************************
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
// Check for when pulsewidth or period equals 0
if((obj->pulse_width == 0) || (obj->period == 0)) {
if ((obj->pulse_width == 0) || (obj->period == 0)) {
return 0;
}
@ -160,19 +160,19 @@ float pwmout_read(pwmout_t* obj)
}
//******************************************************************************
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, (int)(seconds * 1000000.0f));
}
//******************************************************************************
void pwmout_period_ms(pwmout_t* obj, int ms)
void pwmout_period_ms(pwmout_t *obj, int ms)
{
pwmout_period_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_period_us(pwmout_t* obj, int us)
void pwmout_period_us(pwmout_t *obj, int us)
{
// Check the range of the period
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
@ -190,19 +190,25 @@ void pwmout_period_us(pwmout_t* obj, int us)
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period;
}
//******************************************************************************
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, (int)(seconds * 1000000.0f));
}
//******************************************************************************
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
//******************************************************************************
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
// Check the range of the pulsewidth
MBED_ASSERT((us >= 0) && (us <= (int)(SystemCoreClock / 32)));
@ -219,6 +225,12 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
pwmout_update(obj);
}
//******************************************************************************
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulse_width;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -143,7 +143,7 @@ void pwmout_init(pwmout_t *obj, PinName pin)
/* Get hardware instance from pinmap. */
int instance = pin_instance_pwm(pin);
MBED_ASSERT(instance < (int) (sizeof(nordic_nrf5_pwm_instance) / sizeof(nrfx_pwm_t)));
MBED_ASSERT(instance < (int)(sizeof(nordic_nrf5_pwm_instance) / sizeof(nrfx_pwm_t)));
/* Populate PWM object with default values. */
obj->instance = instance;
@ -287,6 +287,11 @@ void pwmout_period_us(pwmout_t *obj, int period)
nordic_pwm_restart(obj);
}
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period;
}
/** Set the PWM pulsewidth specified in seconds, keeping the period the same.
*
* Parameter obj The pwmout object
@ -348,6 +353,10 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int pulse)
nordic_pwm_restart(obj);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj) {
return (obj->period) * (obj->percent);
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM_testing;

View File

@ -59,9 +59,9 @@ static const struct nu_modinit_s pwm_modinit_tab[] = {
{NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
};
static void pwmout_config(pwmout_t* obj, int start);
static void pwmout_config(pwmout_t *obj, int start);
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
obj->pwm = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT((int) obj->pwm != NC);
@ -91,7 +91,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
}
// NOTE: All channels (identified by PWMName) share a PWM module. This reset will also affect other channels of the same PWM module.
if (! ((struct nu_pwm_var *) modinit->var)->en_msk) {
if (!((struct nu_pwm_var *) modinit->var)->en_msk) {
/* Reset module
*
* NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
@ -113,7 +113,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pwm_modinit_mask |= 1 << i;
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
EPWM_T *pwm_base = (EPWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);
@ -142,29 +142,29 @@ void pwmout_free(pwmout_t* obj)
obj->pin = NC;
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
obj->pulsewidth_us = NU_CLAMP((uint32_t) (value * obj->period_us), 0, obj->period_us);
obj->pulsewidth_us = NU_CLAMP((uint32_t)(value * obj->period_us), 0, obj->period_us);
pwmout_config(obj, 1);
}
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
return NU_CLAMP((((float) obj->pulsewidth_us) / obj->period_us), 0.0f, 1.0f);
}
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
uint32_t period_us_old = obj->period_us;
uint32_t pulsewidth_us_old = obj->pulsewidth_us;
@ -173,23 +173,33 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_config(obj, 1);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period_us;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
obj->pulsewidth_us = NU_CLAMP(us, 0, obj->period_us);
pwmout_config(obj, 1);
}
static void pwmout_config(pwmout_t* obj, int start)
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulsewidth_us;
}
static void pwmout_config(pwmout_t *obj, int start)
{
EPWM_T *pwm_base = (EPWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);

View File

@ -59,9 +59,9 @@ static const struct nu_modinit_s pwm_modinit_tab[] = {
{NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
};
static void pwmout_config(pwmout_t* obj, int start);
static void pwmout_config(pwmout_t *obj, int start);
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
obj->pwm = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT((int) obj->pwm != NC);
@ -86,7 +86,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
}
// NOTE: All channels (identified by PWMName) share a PWM module. This reset will also affect other channels of the same PWM module.
if (! ((struct nu_pwm_var *) modinit->var)->en_msk) {
if (!((struct nu_pwm_var *) modinit->var)->en_msk) {
// Reset this module if no channel enabled
SYS_ResetModule(modinit->rsetidx);
}
@ -103,7 +103,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pwm_modinit_mask |= 1 << i;
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
PWM_T *pwm_base = (PWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);
@ -128,29 +128,29 @@ void pwmout_free(pwmout_t* obj)
obj->pin = NC;
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
obj->pulsewidth_us = NU_CLAMP((uint32_t) (value * obj->period_us), 0, obj->period_us);
obj->pulsewidth_us = NU_CLAMP((uint32_t)(value * obj->period_us), 0, obj->period_us);
pwmout_config(obj, 1);
}
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
return NU_CLAMP((((float) obj->pulsewidth_us) / obj->period_us), 0.0f, 1.0f);
}
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
uint32_t period_us_old = obj->period_us;
uint32_t pulsewidth_us_old = obj->pulsewidth_us;
@ -159,23 +159,32 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_config(obj, 1);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period_us;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
obj->pulsewidth_us = NU_CLAMP(us, 0, obj->period_us);
pwmout_config(obj, 1);
}
static void pwmout_config(pwmout_t* obj, int start)
int pwmout_read_pulsewidth_us(pwmout_t *obj) {
return obj->pulsewidth_us;
}
static void pwmout_config(pwmout_t *obj, int start)
{
PWM_T *pwm_base = (PWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);

View File

@ -1,4 +1,4 @@
/*
/*
* Copyright (c) 2019-2020 Nuvoton Technology Corporation
* SPDX-License-Identifier: Apache-2.0
*
@ -58,9 +58,9 @@ static const struct nu_modinit_s pwm_modinit_tab[] = {
{NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
};
static void pwmout_config(pwmout_t* obj, int start);
static void pwmout_config(pwmout_t *obj, int start);
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
obj->pwm = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT((int) obj->pwm != NC);
@ -85,7 +85,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
}
// NOTE: All channels (identified by PWMName) share a PWM module. This reset will also affect other channels of the same PWM module.
if (! ((struct nu_pwm_var *) modinit->var)->en_msk) {
if (!((struct nu_pwm_var *) modinit->var)->en_msk) {
// Reset this module if no channel enabled
SYS_ResetModule(modinit->rsetidx);
}
@ -102,7 +102,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pwm_modinit_mask |= 1 << i;
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
EPWM_T *pwm_base = (EPWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);
@ -127,29 +127,29 @@ void pwmout_free(pwmout_t* obj)
obj->pin = NC;
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
obj->pulsewidth_us = NU_CLAMP((uint32_t) (value * obj->period_us), 0, obj->period_us);
obj->pulsewidth_us = NU_CLAMP((uint32_t)(value * obj->period_us), 0, obj->period_us);
pwmout_config(obj, 1);
}
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
return NU_CLAMP((((float) obj->pulsewidth_us) / obj->period_us), 0.0f, 1.0f);
}
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
uint32_t period_us_old = obj->period_us;
uint32_t pulsewidth_us_old = obj->pulsewidth_us;
@ -158,23 +158,33 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_config(obj, 1);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period_us;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
obj->pulsewidth_us = NU_CLAMP(us, 0, obj->period_us);
pwmout_config(obj, 1);
}
static void pwmout_config(pwmout_t* obj, int start)
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulsewidth_us;
}
static void pwmout_config(pwmout_t *obj, int start)
{
EPWM_T *pwm_base = (EPWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pwmout_api.h"
#if DEVICE_PWMOUT
@ -46,20 +46,20 @@ static const struct nu_modinit_s pwm_modinit_tab[] = {
{PWM_0_3, PWM0_MODULE, CLK_CLKSEL2_PWM0SEL_PCLK0, 0, PWM0_RST, PWM0P1_IRQn, &pwm0_var},
{PWM_0_4, PWM0_MODULE, CLK_CLKSEL2_PWM0SEL_PCLK0, 0, PWM0_RST, PWM0P2_IRQn, &pwm0_var},
{PWM_0_5, PWM0_MODULE, CLK_CLKSEL2_PWM0SEL_PCLK0, 0, PWM0_RST, PWM0P2_IRQn, &pwm0_var},
{PWM_1_0, PWM1_MODULE, CLK_CLKSEL2_PWM1SEL_PCLK1, 0, PWM1_RST, PWM1P0_IRQn, &pwm1_var},
{PWM_1_1, PWM1_MODULE, CLK_CLKSEL2_PWM1SEL_PCLK1, 0, PWM1_RST, PWM1P0_IRQn, &pwm1_var},
{PWM_1_2, PWM1_MODULE, CLK_CLKSEL2_PWM1SEL_PCLK1, 0, PWM1_RST, PWM1P1_IRQn, &pwm1_var},
{PWM_1_3, PWM1_MODULE, CLK_CLKSEL2_PWM1SEL_PCLK1, 0, PWM1_RST, PWM1P1_IRQn, &pwm1_var},
{PWM_1_4, PWM1_MODULE, CLK_CLKSEL2_PWM1SEL_PCLK1, 0, PWM1_RST, PWM1P2_IRQn, &pwm1_var},
{PWM_1_5, PWM1_MODULE, CLK_CLKSEL2_PWM1SEL_PCLK1, 0, PWM1_RST, PWM1P2_IRQn, &pwm1_var},
{NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
};
static void pwmout_config(pwmout_t* obj);
static void pwmout_config(pwmout_t *obj);
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
obj->pwm = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT((int) obj->pwm != NC);
@ -83,7 +83,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
}
// NOTE: All channels (identified by PWMName) share a PWM module. This reset will also affect other channels of the same PWM module.
if (! ((struct nu_pwm_var *) modinit->var)->en_msk) {
if (!((struct nu_pwm_var *) modinit->var)->en_msk) {
// Reset this module if no channel enabled
SYS_ResetModule(modinit->rsetidx);
}
@ -107,22 +107,22 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pwm_modinit_mask |= 1 << i;
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
PWM_T *pwm_base = (PWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);
PWM_ForceStop(pwm_base, 1 << chn);
const struct nu_modinit_s *modinit = get_modinit(obj->pwm, pwm_modinit_tab);
MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == obj->pwm);
((struct nu_pwm_var *) modinit->var)->en_msk &= ~(1 << chn);
if ((((struct nu_pwm_var *) modinit->var)->en_msk & 0x3F) == 0) {
CLK_DisableModuleClock(modinit->clkidx);
}
// Mark this module to be deinited.
int i = modinit - pwm_modinit_tab;
pwm_modinit_mask &= ~(1 << i);
@ -132,29 +132,29 @@ void pwmout_free(pwmout_t* obj)
obj->pin = NC;
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
obj->pulsewidth_us = NU_CLAMP((uint32_t) (value * obj->period_us), 0, obj->period_us);
obj->pulsewidth_us = NU_CLAMP((uint32_t)(value * obj->period_us), 0, obj->period_us);
pwmout_config(obj);
}
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
return NU_CLAMP((((float) obj->pulsewidth_us) / obj->period_us), 0.0f, 1.0f);
}
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
uint32_t period_us_old = obj->period_us;
uint32_t pulsewidth_us_old = obj->pulsewidth_us;
@ -163,23 +163,33 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_config(obj);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period_us;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
obj->pulsewidth_us = NU_CLAMP(us, 0, obj->period_us);
pwmout_config(obj);
}
static void pwmout_config(pwmout_t* obj)
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulsewidth_us;
}
static void pwmout_config(pwmout_t *obj)
{
PWM_T *pwm_base = (PWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);

View File

@ -60,9 +60,9 @@ static const struct nu_modinit_s pwm_modinit_tab[] = {
{NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
};
static void pwmout_config(pwmout_t* obj, int start);
static void pwmout_config(pwmout_t *obj, int start);
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
obj->pwm = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT((int) obj->pwm != NC);
@ -86,7 +86,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
}
// NOTE: All channels (identified by PWMName) share a PWM module. This reset will also affect other channels of the same PWM module.
if (! ((struct nu_pwm_var *) modinit->var)->en_msk) {
if (!((struct nu_pwm_var *) modinit->var)->en_msk) {
// Reset this module if no channel enabled
SYS_ResetModule(modinit->rsetidx);
}
@ -105,7 +105,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pwm_modinit_mask |= 1 << i;
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
EPWM_T *pwm_base = (EPWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);
@ -130,29 +130,29 @@ void pwmout_free(pwmout_t* obj)
obj->pin = NC;
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
obj->pulsewidth_us = NU_CLAMP((uint32_t) (value * obj->period_us), 0, obj->period_us);
obj->pulsewidth_us = NU_CLAMP((uint32_t)(value * obj->period_us), 0, obj->period_us);
pwmout_config(obj, 1);
}
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
return NU_CLAMP((((float) obj->pulsewidth_us) / obj->period_us), 0.0f, 1.0f);
}
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
uint32_t period_us_old = obj->period_us;
uint32_t pulsewidth_us_old = obj->pulsewidth_us;
@ -161,23 +161,33 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_config(obj, 1);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period_us;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
obj->pulsewidth_us = NU_CLAMP(us, 0, obj->period_us);
pwmout_config(obj, 1);
}
static void pwmout_config(pwmout_t* obj, int start)
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulsewidth_us;
}
static void pwmout_config(pwmout_t *obj, int start)
{
EPWM_T *pwm_base = (EPWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pwmout_api.h"
#if DEVICE_PWMOUT
@ -52,18 +52,18 @@ static const struct nu_modinit_s pwm_modinit_tab[] = {
{PWM_0_1, PWM0_CH01_MODULE, CLK_CLKSEL1_PWM0_CH01_S_HCLK, 0, PWM0_RST, PWM0_IRQn, &pwm0_01_var},
{PWM_0_2, PWM0_CH23_MODULE, CLK_CLKSEL1_PWM0_CH23_S_HCLK, 0, PWM0_RST, PWM0_IRQn, &pwm0_23_var},
{PWM_0_3, PWM0_CH23_MODULE, CLK_CLKSEL1_PWM0_CH23_S_HCLK, 0, PWM0_RST, PWM0_IRQn, &pwm0_23_var},
{PWM_1_0, PWM1_CH01_MODULE, CLK_CLKSEL2_PWM1_CH01_S_HCLK, 0, PWM1_RST, PWM1_IRQn, &pwm1_01_var},
{PWM_1_1, PWM1_CH01_MODULE, CLK_CLKSEL2_PWM1_CH01_S_HCLK, 0, PWM1_RST, PWM1_IRQn, &pwm1_01_var},
{PWM_1_2, PWM1_CH23_MODULE, CLK_CLKSEL2_PWM1_CH23_S_HCLK, 0, PWM1_RST, PWM1_IRQn, &pwm1_23_var},
{PWM_1_3, PWM1_CH23_MODULE, CLK_CLKSEL2_PWM1_CH23_S_HCLK, 0, PWM1_RST, PWM1_IRQn, &pwm1_23_var},
{NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
};
static void pwmout_config(pwmout_t* obj);
static void pwmout_config(pwmout_t *obj);
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
obj->pwm = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT((int) obj->pwm != NC);
@ -108,22 +108,22 @@ void pwmout_init(pwmout_t* obj, PinName pin)
}
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
PWM_T *pwm_base = (PWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);
PWM_ForceStop(pwm_base, 1 << chn);
const struct nu_modinit_s *modinit = get_modinit(obj->pwm, pwm_modinit_tab);
MBED_ASSERT(modinit != NULL);
MBED_ASSERT((PWMName) modinit->modname == obj->pwm);
((struct nu_pwm_var *) modinit->var)->en_msk &= ~(1 << chn);
if ((((struct nu_pwm_var *) modinit->var)->en_msk & 0xF) == 0) {
CLK_DisableModuleClock(modinit->clkidx);
}
if (((struct nu_pwm_var *) modinit->var)->en_msk == 0) {
// Mark this module to be deinited.
int i = modinit - pwm_modinit_tab;
@ -135,29 +135,29 @@ void pwmout_free(pwmout_t* obj)
obj->pin = NC;
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
obj->pulsewidth_us = NU_CLAMP((uint32_t) (value * obj->period_us), 0, obj->period_us);
obj->pulsewidth_us = NU_CLAMP((uint32_t)(value * obj->period_us), 0, obj->period_us);
pwmout_config(obj);
}
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
return NU_CLAMP((((float) obj->pulsewidth_us) / obj->period_us), 0.0f, 1.0f);
}
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
uint32_t period_us_old = obj->period_us;
uint32_t pulsewidth_us_old = obj->pulsewidth_us;
@ -166,23 +166,33 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_config(obj);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period_us;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
obj->pulsewidth_us = NU_CLAMP(us, 0, obj->period_us);
pwmout_config(obj);
}
static void pwmout_config(pwmout_t* obj)
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulsewidth_us;
}
static void pwmout_config(pwmout_t *obj)
{
PWM_T *pwm_base = (PWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pwmout_api.h"
#if DEVICE_PWMOUT
@ -47,20 +47,20 @@ static const struct nu_modinit_s pwm_modinit_tab[] = {
{PWM_0_3, PWM0CH23_MODULE, CLK_CLKSEL2_PWM0CH23SEL_HIRC, 0, PWM0_RST, PWM0CH3_IRQn, &pwm0_var},
{PWM_0_4, PWM0CH45_MODULE, CLK_CLKSEL2_PWM0CH45SEL_HIRC, 0, PWM0_RST, PWM0CH4_IRQn, &pwm0_var},
{PWM_0_5, PWM0CH45_MODULE, CLK_CLKSEL2_PWM0CH45SEL_HIRC, 0, PWM0_RST, PWM0CH5_IRQn, &pwm0_var},
{PWM_1_0, PWM1CH01_MODULE, CLK_CLKSEL2_PWM1CH01SEL_HIRC, 0, PWM1_RST, PWM1CH0_IRQn, &pwm1_var},
{PWM_1_1, PWM1CH01_MODULE, CLK_CLKSEL2_PWM1CH01SEL_HIRC, 0, PWM1_RST, PWM1CH1_IRQn, &pwm1_var},
{PWM_1_2, PWM1CH23_MODULE, CLK_CLKSEL2_PWM1CH23SEL_HIRC, 0, PWM1_RST, PWM1CH2_IRQn, &pwm1_var},
{PWM_1_3, PWM1CH23_MODULE, CLK_CLKSEL2_PWM1CH23SEL_HIRC, 0, PWM1_RST, PWM1CH3_IRQn, &pwm1_var},
{PWM_1_4, PWM1CH45_MODULE, CLK_CLKSEL2_PWM1CH45SEL_HIRC, 0, PWM1_RST, PWM1CH4_IRQn, &pwm1_var},
{PWM_1_5, PWM1CH45_MODULE, CLK_CLKSEL2_PWM1CH45SEL_HIRC, 0, PWM1_RST, PWM1CH5_IRQn, &pwm1_var},
{NC, 0, 0, 0, 0, (IRQn_Type) 0, NULL}
};
static void pwmout_config(pwmout_t* obj);
static void pwmout_config(pwmout_t *obj);
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
obj->pwm = (PWMName) pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT((int) obj->pwm != NC);
@ -83,7 +83,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
// Enable clock of paired channels
CLK_EnableModuleClock(modinit->clkidx);
// FIXME: PWM_1_2/3 design bug. PWM_1_2/3 also require PWM_1_0/1 clock enabled.
if (obj->pwm == PWM_1_2 || obj->pwm == PWM_1_3) {
CLK_EnableModuleClock(PWM1CH01_MODULE);
@ -91,7 +91,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
}
// NOTE: All channels (identified by PWMName) share a PWM module. This reset will also affect other channels of the same PWM module.
if (! ((struct nu_pwm_var *) modinit->var)->en_msk) {
if (!((struct nu_pwm_var *) modinit->var)->en_msk) {
// Reset this module if no channel enabled
SYS_ResetModule(modinit->rsetidx);
}
@ -102,30 +102,30 @@ void pwmout_init(pwmout_t* obj, PinName pin)
obj->period_us = 1000 * 10;
obj->pulsewidth_us = 0;
pwmout_config(obj);
// Enable output of the specified PWM channel
PWM_EnableOutput(pwm_base, 1 << chn);
PWM_Start(pwm_base, 1 << chn);
((struct nu_pwm_var *) modinit->var)->en_msk |= 1 << chn;
// Mark this module to be inited.
int i = modinit - pwm_modinit_tab;
pwm_modinit_mask |= 1 << i;
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
PWM_T *pwm_base = (PWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);
PWM_ForceStop(pwm_base, 1 << chn);
const struct nu_modinit_s *modinit = get_modinit(obj->pwm, pwm_modinit_tab);
MBED_ASSERT(modinit != NULL);
MBED_ASSERT(modinit->modname == obj->pwm);
((struct nu_pwm_var *) modinit->var)->en_msk &= ~(1 << chn);
if ((((struct nu_pwm_var *) modinit->var)->en_msk & (0x3 << (chn / 2 * 2))) == 0) {
// FIXME: PWM_1_2/3 design bug. PWM_1_2/3 also require PWM_1_0/1 clock enabled.
switch (obj->pwm) {
@ -134,51 +134,51 @@ void pwmout_free(pwmout_t* obj)
if (pwm1_var.en_msk & 0xC) {
break;
}
case PWM_1_2:
case PWM_1_3:
if (! (pwm1_var.en_msk & 0x3)) {
if (!(pwm1_var.en_msk & 0x3)) {
CLK_DisableModuleClock(PWM1CH01_MODULE);
}
default:
// Disable clock of paired channels
CLK_DisableModuleClock(modinit->clkidx);
}
}
// Mark this module to be deinited.
int i = modinit - pwm_modinit_tab;
pwm_modinit_mask &= ~(1 << i);
// Free up pins
gpio_set(obj->pin);
obj->pin = NC;
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
obj->pulsewidth_us = NU_CLAMP((uint32_t) (value * obj->period_us), 0, obj->period_us);
obj->pulsewidth_us = NU_CLAMP((uint32_t)(value * obj->period_us), 0, obj->period_us);
pwmout_config(obj);
}
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
return NU_CLAMP((((float) obj->pulsewidth_us) / obj->period_us), 0.0f, 1.0f);
}
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
uint32_t period_us_old = obj->period_us;
uint32_t pulsewidth_us_old = obj->pulsewidth_us;
@ -187,23 +187,33 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_config(obj);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period_us;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
obj->pulsewidth_us = NU_CLAMP(us, 0, obj->period_us);
pwmout_config(obj);
}
static void pwmout_config(pwmout_t* obj)
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->pulsewidth_us;
}
static void pwmout_config(pwmout_t *obj)
{
PWM_T *pwm_base = (PWM_T *) NU_MODBASE(obj->pwm);
uint32_t chn = NU_MODSUBINDEX(obj->pwm);

View File

@ -25,36 +25,39 @@
static const PinMap PinMap_PWM[] = {
{P1_19, SCT0_0, 2},
{P2_2 , SCT0_1, 3},
{P2_7 , SCT0_2, 2},
{P2_2, SCT0_1, 3},
{P2_7, SCT0_2, 2},
{P1_13, SCT0_3, 2},
{P2_16, SCT1_0, 1},
{P2_17, SCT1_1, 1},
{P2_18, SCT1_2, 1},
{P2_19, SCT1_3, 1},
{NC , NC ,0}
{NC, NC, 0}
};
static LPC_SCT0_Type *SCTs[SCT_CHANNELS] = {
(LPC_SCT0_Type*)LPC_SCT0,
(LPC_SCT0_Type*)LPC_SCT1,
(LPC_SCT0_Type *)LPC_SCT0,
(LPC_SCT0_Type *)LPC_SCT1,
};
// bit flags for used SCTs
static unsigned char sct_used = 0;
static int get_available_sct(void) {
static int get_available_sct(void)
{
int i;
for (i=0; i<SCT_CHANNELS; i++) {
if ((sct_used & (1 << i)) == 0)
for (i = 0; i < SCT_CHANNELS; i++) {
if ((sct_used & (1 << i)) == 0) {
return i;
}
}
return -1;
}
void pwmout_init(pwmout_t* obj, PinName pin) {
void pwmout_init(pwmout_t *obj, PinName pin)
{
// determine the SPI to use
PWMName pwm_mapped = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
if (pwm_mapped == (PWMName)NC) {
@ -73,17 +76,17 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 31);
// Clear peripheral reset the SCT:
LPC_SYSCON->PRESETCTRL |= (1 << (obj->pwm_ch + 9));
LPC_SYSCON->PRESETCTRL |= (1 << (obj->pwm_ch + 9));
pinmap_pinout(pin, PinMap_PWM);
LPC_SCT0_Type* pwm = obj->pwm;
LPC_SCT0_Type *pwm = obj->pwm;
// Unified 32-bit counter, autolimit
pwm->CONFIG |= ((0x3 << 17) | 0x01);
// halt and clear the counter
pwm->CTRL |= (1 << 2) | (1 << 3);
switch(pwm_mapped) {
switch (pwm_mapped) {
case SCT0_0:
case SCT1_0:
pwm->OUT0_SET = (1 << 0); // event 0
@ -116,10 +119,11 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_ms(obj, 20);
pwmout_write (obj, 0);
pwmout_write(obj, 0);
}
void pwmout_free(pwmout_t* obj) {
void pwmout_free(pwmout_t *obj)
{
sct_used &= ~(1 << obj->pwm_ch);
if (sct_used == 0) {
// Disable the SCT clock
@ -127,8 +131,9 @@ void pwmout_free(pwmout_t* obj) {
}
}
void pwmout_write(pwmout_t* obj, float value) {
LPC_SCT0_Type* pwm = obj->pwm;
void pwmout_write(pwmout_t *obj, float value)
{
LPC_SCT0_Type *pwm = obj->pwm;
if (value < 0.0f) {
value = 0.0;
} else if (value > 1.0f) {
@ -137,7 +142,7 @@ void pwmout_write(pwmout_t* obj, float value) {
uint32_t t_on = (uint32_t)((float)(pwm->MATCHREL0 + 1) * value);
if (t_on > 0) {
pwm->MATCHREL1 = t_on - 1;
// Un-halt the timer and ensure the new pulse-width takes immediate effect if necessary
if (pwm->CTRL & (1 << 2)) {
pwm->MATCH1 = pwm->MATCHREL1;
@ -150,34 +155,38 @@ void pwmout_write(pwmout_t* obj, float value) {
}
}
float pwmout_read(pwmout_t* obj) {
LPC_SCT0_Type* pwm = obj->pwm;
float pwmout_read(pwmout_t *obj)
{
LPC_SCT0_Type *pwm = obj->pwm;
uint32_t t_off = pwm->MATCHREL0 + 1;
uint32_t t_on = (!(pwm->CTRL & (1 << 2))) ? pwm->MATCHREL1 + 1 : 0;
float v = (float)t_on/(float)t_off;
float v = (float)t_on / (float)t_off;
return (v > 1.0f) ? (1.0f) : (v);
}
void pwmout_period(pwmout_t* obj, float seconds) {
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms) {
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) {
LPC_SCT0_Type* pwm = obj->pwm;
void pwmout_period_us(pwmout_t *obj, int us)
{
LPC_SCT0_Type *pwm = obj->pwm;
uint32_t t_off = pwm->MATCHREL0 + 1;
uint32_t t_on = (!(pwm->CTRL & (1 << 2))) ? pwm->MATCHREL1 + 1 : 0;
float v = (float)t_on/(float)t_off;
float v = (float)t_on / (float)t_off;
uint32_t period_ticks = (uint32_t)(((uint64_t)SystemCoreClock * (uint64_t)us) / (uint64_t)1000000);
uint32_t pulsewidth_ticks = period_ticks * v;
pwm->MATCHREL0 = period_ticks - 1;
if (pulsewidth_ticks > 0) {
pwm->MATCHREL1 = pulsewidth_ticks - 1;
// Un-halt the timer and ensure the new period & pulse-width take immediate effect if necessary
if (pwm->CTRL & (1 << 2)) {
pwm->MATCH0 = pwm->MATCHREL0;
@ -188,25 +197,33 @@ void pwmout_period_us(pwmout_t* obj, int us) {
// Halt the timer and force the output low
pwm->CTRL |= (1 << 2) | (1 << 3);
pwm->OUTPUT = 0x00000000;
// Ensure the new period will take immediate effect when the timer is un-halted
pwm->MATCH0 = pwm->MATCHREL0;
}
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
int pwmout_read_period_us(pwmout_t *obj)
{
return pwm->MATCHREL0 + 1;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
LPC_SCT0_Type* pwm = obj->pwm;
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
LPC_SCT0_Type *pwm = obj->pwm;
if (us > 0) {
pwm->MATCHREL1 = (uint32_t)(((uint64_t)SystemCoreClock * (uint64_t)us) / (uint64_t)1000000) - 1;
// Un-halt the timer and ensure the new pulse-width takes immediate effect if necessary
if (pwm->CTRL & (1 << 2)) {
pwm->MATCH1 = pwm->MATCHREL1;
@ -219,6 +236,11 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
}
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return (!(pwm->CTRL & (1 << 2))) ? pwm->MATCHREL1 + 1 : 0;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -28,17 +28,17 @@
*/
static const PinMap PinMap_PWM[] = {
/* CT16B0 */
{P0_8 , PWM_1, 0x02}, /* MR0 */
{P0_9 , PWM_2, 0x02}, /* MR1 */
{P0_8, PWM_1, 0x02}, /* MR0 */
{P0_9, PWM_2, 0x02}, /* MR1 */
/* CT16B1 */
{P1_9 , PWM_3, 0x01}, /* MR0 */
{P1_9, PWM_3, 0x01}, /* MR0 */
{P1_10, PWM_4, 0x02}, /* MR1 */
/* CT32B0 */
{P0_1 , PWM_5, 0x02}, /* MR2 */
{P0_1, PWM_5, 0x02}, /* MR2 */
{NC , NC ,0x00}
{NC, NC, 0x00}
};
typedef struct {
@ -61,49 +61,52 @@ static LPC_TMR_TypeDef *Timers[3] = {
LPC_TMR32B0
};
void pwmout_init(pwmout_t* obj, PinName pin) {
void pwmout_init(pwmout_t *obj, PinName pin)
{
// determine the channel
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
obj->pwm = pwm;
// Timer registers
timer_mr tid = pwm_timer_map[pwm];
LPC_TMR_TypeDef *timer = Timers[tid.timer];
// Disable timer
timer->TCR = 0;
// Power the correspondent timer
LPC_SYSCON->SYSAHBCLKCTRL |= 1 << (tid.timer + 7);
/* Enable PWM function */
timer->PWMC = (1 << 3)|(1 << 2)|(1 << 1)|(1 << 0);
timer->PWMC = (1 << 3) | (1 << 2) | (1 << 1) | (1 << 0);
/* Reset Functionality on MR3 controlling the PWM period */
timer->MCR = 1 << 10;
if (timer == LPC_TMR16B0 || timer == LPC_TMR16B1) {
/* Set 16-bit timer prescaler to avoid timer expire for default 20ms */
/* This can be also modified by user application, but the prescaler value */
/* might be trade-off to timer accuracy */
/* Set 16-bit timer prescaler to avoid timer expire for default 20ms */
/* This can be also modified by user application, but the prescaler value */
/* might be trade-off to timer accuracy */
timer->PR = 30;
}
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_ms(obj, 20);
pwmout_write (obj, 0);
pwmout_write(obj, 0);
// Wire pinout
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj) {
void pwmout_free(pwmout_t *obj)
{
// [TODO]
}
void pwmout_write(pwmout_t* obj, float value) {
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0f) {
value = 0.0;
} else if (value > 1.0f) {
@ -123,10 +126,11 @@ void pwmout_write(pwmout_t* obj, float value) {
timer->TCR = TCR_CNT_EN;
}
float pwmout_read(pwmout_t* obj) {
float pwmout_read(pwmout_t *obj)
{
timer_mr tid = pwm_timer_map[obj->pwm];
LPC_TMR_TypeDef *timer = Timers[tid.timer];
float v = (float)(timer->MR3 - timer->MR[tid.mr]) / (float)(timer->MR3);
if (timer->MR[tid.mr] > timer->MR3) {
v = 0.0f;
@ -134,19 +138,22 @@ float pwmout_read(pwmout_t* obj) {
return (v > 1.0f) ? (1.0f) : (v);
}
void pwmout_period(pwmout_t* obj, float seconds) {
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms) {
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) {
void pwmout_period_us(pwmout_t *obj, int us)
{
int i = 0;
uint32_t period_ticks;
timer_mr tid = pwm_timer_map[obj->pwm];
LPC_TMR_TypeDef *timer = Timers[tid.timer];
uint32_t old_period_ticks = timer->MR3;
@ -154,10 +161,10 @@ void pwmout_period_us(pwmout_t* obj, int us) {
timer->TCR = TCR_RESET;
timer->MR3 = period_ticks;
// Scale the pulse width to preserve the duty ratio
if (old_period_ticks > 0) {
for (i=0; i<3; i++) {
for (i = 0; i < 3; i++) {
uint32_t t_off = period_ticks - (uint32_t)(((uint64_t)timer->MR[i] * (uint64_t)period_ticks) / (uint64_t)old_period_ticks);
timer->MR[i] = t_off;
}
@ -165,19 +172,29 @@ void pwmout_period_us(pwmout_t* obj, int us) {
timer->TCR = TCR_CNT_EN;
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
int pwmout_read_period_us(pwmout_t *obj)
{
timer_mr tid = pwm_timer_map[obj->pwm];
LPC_TMR_TypeDef *timer = Timers[tid.timer];
return (timer->MR3);
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
timer_mr tid = pwm_timer_map[obj->pwm];
LPC_TMR_TypeDef *timer = Timers[tid.timer];
uint32_t t_on = (uint32_t)((((uint64_t)SystemCoreClock * (uint64_t)us) / (uint64_t)1000000) / (timer->PR + 1));
timer->TCR = TCR_RESET;
if (t_on > timer->MR3) {
pwmout_period_us(obj, us);
@ -187,6 +204,13 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
timer->TCR = TCR_CNT_EN;
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
timer_mr tid = pwm_timer_map[obj->pwm];
LPC_TMR_TypeDef *timer = Timers[tid.timer];
return (timer->MR3 - timer->MR[tid.mr]);
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -29,12 +29,12 @@ static const PinMap PinMap_PWM[] = {
{P1_23, PWM_4, 2},
{P1_24, PWM_5, 2},
{P1_26, PWM_6, 2},
{P2_0 , PWM_1, 1},
{P2_1 , PWM_2, 1},
{P2_2 , PWM_3, 1},
{P2_3 , PWM_4, 1},
{P2_4 , PWM_5, 1},
{P2_5 , PWM_6, 1},
{P2_0, PWM_1, 1},
{P2_1, PWM_2, 1},
{P2_2, PWM_3, 1},
{P2_3, PWM_4, 1},
{P2_4, PWM_5, 1},
{P2_5, PWM_6, 1},
{P3_25, PWM_2, 3},
{P3_26, PWM_3, 3},
{NC, NC, 0}
@ -54,77 +54,84 @@ __IO uint32_t *PWM_MATCH[] = {
static unsigned int pwm_clock_mhz;
void pwmout_init(pwmout_t* obj, PinName pin) {
void pwmout_init(pwmout_t *obj, PinName pin)
{
// determine the channel
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
obj->pwm = pwm;
obj->MR = PWM_MATCH[pwm];
// ensure the power is on
LPC_SC->PCONP |= 1 << 6;
// ensure clock to /4
LPC_SC->PCLKSEL0 &= ~(0x3 << 12); // pclk = /4
LPC_PWM1->PR = 0; // no pre-scale
// ensure single PWM mode
LPC_PWM1->MCR = 1 << 1; // reset TC on match 0
// enable the specific PWM output
LPC_PWM1->PCR |= 1 << (8 + pwm);
pwm_clock_mhz = SystemCoreClock / 4000000;
// default to 20ms: standard for servos, and fine for e.g. brightness control
pwmout_period_ms(obj, 20);
pwmout_write (obj, 0);
pwmout_write(obj, 0);
// Wire pinout
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj) {
void pwmout_free(pwmout_t *obj)
{
// [TODO]
}
void pwmout_write(pwmout_t* obj, float value) {
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0f) {
value = 0.0;
} else if (value > 1.0f) {
value = 1.0;
}
// set channel match to percentage
uint32_t v = (uint32_t)((float)(LPC_PWM1->MR0) * value);
// workaround for PWM1[1] - Never make it equal MR0, else we get 1 cycle dropout
if (v == LPC_PWM1->MR0) {
v++;
}
*obj->MR = v;
// accept on next period start
LPC_PWM1->LER |= 1 << obj->pwm;
}
float pwmout_read(pwmout_t* obj) {
float pwmout_read(pwmout_t *obj)
{
float v = (float)(*obj->MR) / (float)(LPC_PWM1->MR0);
return (v > 1.0f) ? (1.0f) : (v);
}
void pwmout_period(pwmout_t* obj, float seconds) {
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms) {
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) {
void pwmout_period_us(pwmout_t *obj, int us)
{
// calculate number of ticks
uint32_t ticks = pwm_clock_mhz * us;
@ -146,30 +153,43 @@ void pwmout_period_us(pwmout_t* obj, int us) {
LPC_PWM1->TCR = TCR_CNT_EN | TCR_PWM_EN;
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
int pwmout_read_period_us(pwmout_t *obj)
{
return (LPC_PWM1->MR0);
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
// calculate number of ticks
uint32_t v = pwm_clock_mhz * us;
// workaround for PWM1[1] - Never make it equal MR0, else we get 1 cycle dropout
if (v == LPC_PWM1->MR0) {
v++;
}
// set the match register value
*obj->MR = v;
// set the channel latch to update value at next period start
LPC_PWM1->LER |= 1 << obj->pwm;
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return (*obj->MR);
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -32,7 +32,7 @@ static PWM_Type *const pwm_addrs[] = PWM_BASE_PTRS;
extern void pwm_setup();
extern uint32_t pwm_get_clock();
void pwmout_init(pwmout_t* obj, PinName pin)
void pwmout_init(pwmout_t *obj, PinName pin)
{
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
@ -93,7 +93,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
pinmap_pinout(pin, PinMap_PWM);
}
void pwmout_free(pwmout_t* obj)
void pwmout_free(pwmout_t *obj)
{
uint32_t instance = (obj->pwm_name >> PWM_SHIFT) & 0x7;
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
@ -101,7 +101,7 @@ void pwmout_free(pwmout_t* obj)
PWM_StopTimer(pwm_addrs[instance], (1 << module));
}
void pwmout_write(pwmout_t* obj, float value)
void pwmout_write(pwmout_t *obj, float value)
{
if (value < 0.0f) {
value = 0.0f;
@ -130,7 +130,7 @@ void pwmout_write(pwmout_t* obj, float value)
PWM_SetPwmLdok(base, (1 << module), true);
}
float pwmout_read(pwmout_t* obj)
float pwmout_read(pwmout_t *obj)
{
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
@ -153,18 +153,18 @@ float pwmout_read(pwmout_t* obj)
return (v > 1.0f) ? (1.0f) : (v);
}
void pwmout_period(pwmout_t* obj, float seconds)
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms)
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)
void pwmout_period_us(pwmout_t *obj, int us)
{
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
@ -194,17 +194,24 @@ void pwmout_period_us(pwmout_t* obj, int us)
pwmout_write(obj, dc);
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds)
int pwmout_read_period_us(pwmout_t *obj)
{
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
return (base->SM[module].VAL1) & PWM_VAL1_VAL1_MASK;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us)
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
@ -223,6 +230,20 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us)
PWM_SetPwmLdok(base, (1 << module), true);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj) {
uint16_t count;
PWM_Type *base = pwm_addrs[(obj->pwm_name >> PWM_SHIFT) & 0x7];
uint32_t module = (obj->pwm_name >> PWM_MODULE_SHIFT) & 0x3;
uint32_t pwmchannel = obj->pwm_name & 0x1;
if (pwmchannel == 0)
{
count = (base->SM[module].VAL3) & PWM_VAL3_VAL3_MASK;
} else
{
count = (base->SM[module].VAL5) & PWM_VAL5_VAL5_MASK;
}
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -46,22 +46,22 @@ typedef enum {
} PWMType;
static const PWMType PORT[] = {
PWM1A, // PWM_PWM1A
PWM1B, // PWM_PWM1B
PWM1C, // PWM_PWM1C
PWM1D, // PWM_PWM1D
PWM1E, // PWM_PWM1E
PWM1F, // PWM_PWM1F
PWM1G, // PWM_PWM1G
PWM1H, // PWM_PWM1H
PWM2A, // PWM_PWM2A
PWM2B, // PWM_PWM2B
PWM2C, // PWM_PWM2C
PWM2D, // PWM_PWM2D
PWM2E, // PWM_PWM2E
PWM2F, // PWM_PWM2F
PWM2G, // PWM_PWM2G
PWM2H, // PWM_PWM2H
PWM1A, // PWM_PWM1A
PWM1B, // PWM_PWM1B
PWM1C, // PWM_PWM1C
PWM1D, // PWM_PWM1D
PWM1E, // PWM_PWM1E
PWM1F, // PWM_PWM1F
PWM1G, // PWM_PWM1G
PWM1H, // PWM_PWM1H
PWM2A, // PWM_PWM2A
PWM2B, // PWM_PWM2B
PWM2C, // PWM_PWM2C
PWM2D, // PWM_PWM2D
PWM2E, // PWM_PWM2E
PWM2F, // PWM_PWM2F
PWM2G, // PWM_PWM2G
PWM2H, // PWM_PWM2H
};
static __IO uint16_t *PWM_MATCH[] = {
@ -111,23 +111,23 @@ typedef enum {
typedef struct {
MTU2_PWMType port;
__IO uint16_t * pulse1;
__IO uint16_t * pulse2;
__IO uint16_t * period1;
__IO uint16_t * period2;
__IO uint8_t * tior;
__IO uint8_t * tcr;
__IO uint8_t * tmdr;
__IO uint16_t *pulse1;
__IO uint16_t *pulse2;
__IO uint16_t *period1;
__IO uint16_t *period2;
__IO uint8_t *tior;
__IO uint8_t *tcr;
__IO uint8_t *tmdr;
int max_period;
} st_mtu2_ctrl_t;
static st_mtu2_ctrl_t mtu2_ctl[] = {
{ TIOC0A, &MTU2TGRA_0, &MTU2TGRC_0, &MTU2TGRB_0, &MTU2TGRD_0, &MTU2TIORH_0, &MTU2TCR_0, &MTU2TMDR_0, 125000 }, // PWM_TIOC0A
{ TIOC0C, &MTU2TGRC_0, &MTU2TGRA_0, &MTU2TGRB_0, &MTU2TGRD_0, &MTU2TIORL_0, &MTU2TCR_0, &MTU2TMDR_0, 125000 }, // PWM_TIOC0C
{ TIOC1A, &MTU2TGRA_1, NULL , &MTU2TGRB_1, NULL , &MTU2TIOR_1 , &MTU2TCR_1, &MTU2TMDR_1, 503000 }, // PWM_TIOC1A
{ TIOC1B, &MTU2TGRB_1, NULL , &MTU2TGRA_1, NULL , &MTU2TIOR_1 , &MTU2TCR_1, &MTU2TMDR_1, 503000 }, // PWM_TIOC1B
{ TIOC2A, &MTU2TGRA_2, NULL , &MTU2TGRB_2, NULL , &MTU2TIOR_2 , &MTU2TCR_2, &MTU2TMDR_2, 2000000 }, // PWM_TIOC2A
{ TIOC2B, &MTU2TGRB_2, NULL , &MTU2TGRA_2, NULL , &MTU2TIOR_2 , &MTU2TCR_2, &MTU2TMDR_2, 2000000 }, // PWM_TIOC2B
{ TIOC1A, &MTU2TGRA_1, NULL, &MTU2TGRB_1, NULL, &MTU2TIOR_1, &MTU2TCR_1, &MTU2TMDR_1, 503000 }, // PWM_TIOC1A
{ TIOC1B, &MTU2TGRB_1, NULL, &MTU2TGRA_1, NULL, &MTU2TIOR_1, &MTU2TCR_1, &MTU2TMDR_1, 503000 }, // PWM_TIOC1B
{ TIOC2A, &MTU2TGRA_2, NULL, &MTU2TGRB_2, NULL, &MTU2TIOR_2, &MTU2TCR_2, &MTU2TMDR_2, 2000000 }, // PWM_TIOC2A
{ TIOC2B, &MTU2TGRB_2, NULL, &MTU2TGRA_2, NULL, &MTU2TIOR_2, &MTU2TCR_2, &MTU2TMDR_2, 2000000 }, // PWM_TIOC2B
{ TIOC3A, &MTU2TGRA_3, &MTU2TGRC_3, &MTU2TGRB_3, &MTU2TGRD_3, &MTU2TIORH_3, &MTU2TCR_3, &MTU2TMDR_3, 2000000 }, // PWM_TIOC3A
{ TIOC3C, &MTU2TGRC_3, &MTU2TGRA_3, &MTU2TGRB_3, &MTU2TGRD_3, &MTU2TIORL_3, &MTU2TCR_3, &MTU2TMDR_3, 2000000 }, // PWM_TIOC3C
{ TIOC4A, &MTU2TGRA_4, &MTU2TGRC_4, &MTU2TGRB_4, &MTU2TGRD_4, &MTU2TIORH_4, &MTU2TCR_4, &MTU2TMDR_4, 2000000 }, // PWM_TIOC4A
@ -138,7 +138,8 @@ static uint16_t init_mtu2_period_ch[5] = {0};
static int32_t mtu2_period_ch[5] = {1, 1, 1, 1, 1};
#endif
void pwmout_init(pwmout_t* obj, PinName pin) {
void pwmout_init(pwmout_t *obj, PinName pin)
{
// determine the channel
PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
MBED_ASSERT(pwm != (PWMName)NC);
@ -150,7 +151,7 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
mtu2_init();
obj->pwm = pwm;
st_mtu2_ctrl_t * p_mtu2_ctl = &mtu2_ctl[(int)(obj->pwm - MTU2_PWM_OFFSET)];
st_mtu2_ctrl_t *p_mtu2_ctl = &mtu2_ctl[(int)(obj->pwm - MTU2_PWM_OFFSET)];
obj->ch = (uint8_t)(((uint32_t)p_mtu2_ctl->port & 0x000000F0) >> 4);
if (obj->ch == 4) {
@ -208,18 +209,20 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
}
}
void pwmout_free(pwmout_t* obj) {
void pwmout_free(pwmout_t *obj)
{
pwmout_write(obj, 0);
mtu2_free();
}
void pwmout_write(pwmout_t* obj, float value) {
void pwmout_write(pwmout_t *obj, float value)
{
uint32_t wk_cycle;
if (obj->pwm >= MTU2_PWM_OFFSET) {
#ifdef FUMC_MTU2_PWM
/* PWM by MTU2 */
st_mtu2_ctrl_t * p_mtu2_ctl = &mtu2_ctl[(int)(obj->pwm - MTU2_PWM_OFFSET)];
st_mtu2_ctrl_t *p_mtu2_ctl = &mtu2_ctl[(int)(obj->pwm - MTU2_PWM_OFFSET)];
uint8_t tmp_tstr_st;
if (value < 0.0f) {
@ -229,7 +232,7 @@ void pwmout_write(pwmout_t* obj, float value) {
} else {
// Do Nothing
}
wk_cycle = (uint32_t)*p_mtu2_ctl->period1;
wk_cycle = (uint32_t) * p_mtu2_ctl->period1;
if ((obj->ch == 4) || (obj->ch == 3)) {
tmp_tstr_st = (1 << (obj->ch + 3));
} else {
@ -291,7 +294,8 @@ void pwmout_write(pwmout_t* obj, float value) {
}
}
float pwmout_read(pwmout_t* obj) {
float pwmout_read(pwmout_t *obj)
{
uint32_t wk_cycle;
float value;
@ -299,10 +303,10 @@ float pwmout_read(pwmout_t* obj) {
#ifdef FUMC_MTU2_PWM
/* PWM by MTU2 */
uint32_t wk_pulse;
st_mtu2_ctrl_t * p_mtu2_ctl = &mtu2_ctl[(int)(obj->pwm - MTU2_PWM_OFFSET)];
st_mtu2_ctrl_t *p_mtu2_ctl = &mtu2_ctl[(int)(obj->pwm - MTU2_PWM_OFFSET)];
wk_cycle = (uint32_t)*p_mtu2_ctl->period1;
wk_pulse = (uint32_t)*p_mtu2_ctl->pulse1;
wk_cycle = (uint32_t) * p_mtu2_ctl->period1;
wk_pulse = (uint32_t) * p_mtu2_ctl->pulse1;
value = ((float)wk_pulse / (float)wk_cycle);
#endif
} else {
@ -320,16 +324,19 @@ float pwmout_read(pwmout_t* obj) {
return (value > 1.0f) ? (1.0f) : (value);
}
void pwmout_period(pwmout_t* obj, float seconds) {
void pwmout_period(pwmout_t *obj, float seconds)
{
pwmout_period_us(obj, seconds * 1000000.0f);
}
void pwmout_period_ms(pwmout_t* obj, int ms) {
void pwmout_period_ms(pwmout_t *obj, int ms)
{
pwmout_period_us(obj, ms * 1000);
}
#ifdef FUNC_MOTOR_CTL_PWM
static void set_duty_again(__IO uint16_t *p_pwmpbfr, uint16_t last_cycle, uint16_t new_cycle){
static void set_duty_again(__IO uint16_t *p_pwmpbfr, uint16_t last_cycle, uint16_t new_cycle)
{
uint16_t wk_pwmpbfr;
float value;
uint16_t v;
@ -342,7 +349,8 @@ static void set_duty_again(__IO uint16_t *p_pwmpbfr, uint16_t last_cycle, uint16
#endif
#ifdef FUMC_MTU2_PWM
static void set_mtu2_duty_again(__IO uint16_t *p_pwmpbfr, uint16_t last_cycle, uint16_t new_cycle){
static void set_mtu2_duty_again(__IO uint16_t *p_pwmpbfr, uint16_t last_cycle, uint16_t new_cycle)
{
uint16_t wk_pwmpbfr;
float value;
@ -353,7 +361,8 @@ static void set_mtu2_duty_again(__IO uint16_t *p_pwmpbfr, uint16_t last_cycle, u
#endif
// Set the PWM period, keeping the duty cycle the same.
void pwmout_period_us(pwmout_t* obj, int us) {
void pwmout_period_us(pwmout_t *obj, int us)
{
uint32_t pclk_base;
uint32_t wk_cycle;
uint32_t wk_cks = 0;
@ -365,7 +374,7 @@ void pwmout_period_us(pwmout_t* obj, int us) {
int max_us = 0;
/* PWM by MTU2 */
st_mtu2_ctrl_t * p_mtu2_ctl = &mtu2_ctl[(int)(obj->pwm - MTU2_PWM_OFFSET)];
st_mtu2_ctrl_t *p_mtu2_ctl = &mtu2_ctl[(int)(obj->pwm - MTU2_PWM_OFFSET)];
uint8_t tmp_tcr_up;
uint8_t tmp_tstr_st;
@ -387,10 +396,10 @@ void pwmout_period_us(pwmout_t* obj, int us) {
wk_cycle_mtu2 = (uint64_t)pclk_base * us;
while (wk_cycle_mtu2 >= 65535000000) {
if ((obj->ch == 1) && (wk_cks == 3)) {
wk_cks+=2;
wk_cks += 2;
} else if ((obj->ch == 2) && (wk_cks == 3)) {
wk_cycle_mtu2 >>= 2;
wk_cks+=3;
wk_cks += 3;
}
wk_cycle_mtu2 >>= 2;
wk_cks++;
@ -494,15 +503,44 @@ void pwmout_period_us(pwmout_t* obj, int us) {
}
}
void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
int pwmout_read_period_us(pwmout_t *obj)
{
uint32_t wk_cycle;
float value;
if (obj->pwm >= MTU2_PWM_OFFSET) {
#ifdef FUMC_MTU2_PWM
/* PWM by MTU2 */
st_mtu2_ctrl_t *p_mtu2_ctl = &mtu2_ctl[(int)(obj->pwm - MTU2_PWM_OFFSET)];
wk_cycle = (uint32_t) * p_mtu2_ctl->period1;
#endif
} else {
#ifdef FUNC_MOTOR_CTL_PWM
/* PWM */
if (obj->ch == 2) {
wk_cycle = PWMPWCYR_2 & 0x03ff;
} else {
wk_cycle = PWMPWCYR_1 & 0x03ff;
}
#endif
}
return wk_cycle;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
}
void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
pwmout_pulsewidth_us(obj, ms * 1000);
}
void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
float value = 0;
if (obj->pwm >= MTU2_PWM_OFFSET) {
@ -529,6 +567,23 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
pwmout_write(obj, value);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
uint32_t wk_pulse = 0;
if (obj->pwm >= MTU2_PWM_OFFSET) {
#ifdef FUMC_MTU2_PWM
/* PWM by MTU2 */
st_mtu2_ctrl_t *p_mtu2_ctl = &mtu2_ctl[(int)(obj->pwm - MTU2_PWM_OFFSET)];
wk_pulse = (uint32_t) * p_mtu2_ctl->pulse1;
#endif
}
return wk_pulse;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -166,6 +166,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
pwmout_write(obj, obj->duty);
}
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->pwm->GTPR.LONG;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
@ -188,6 +193,14 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
pwmout_write(obj, value);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
if (obj->type == 0) {
return (float)obj->pwm->GTCCRC.LONG;
}
return (float)obj->pwm->GTCCRE.LONG ;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -386,6 +386,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
__HAL_TIM_ENABLE(&TimHandle);
}
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->period;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
@ -402,6 +407,12 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
pwmout_write(obj, value);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
float pwm_duty_cycle = pwmout_read(obj);
return (int)(pwm_duty_cycle * (float)obj->period);
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -78,15 +78,16 @@ uint32_t pwmout_get_channel_route(uint32_t channel)
/*
* Disables the route location given. Returns true if it was enabled, false if it wasn't.
*/
bool pwmout_disable_channel_route(uint32_t routeloc) {
bool pwmout_disable_channel_route(uint32_t routeloc)
{
#ifdef TIMER_ROUTEPEN_CC0PEN
if(PWM_TIMER->ROUTEPEN & routeloc) {
if (PWM_TIMER->ROUTEPEN & routeloc) {
//This channel was in use, so disable
PWM_TIMER->ROUTEPEN &= ~routeloc;
return true;
}
#else
if(PWM_TIMER->ROUTE & routeloc) {
if (PWM_TIMER->ROUTE & routeloc) {
//This channel was in use, so disable
PWM_TIMER->ROUTE &= ~routeloc;
return true;
@ -98,13 +99,14 @@ bool pwmout_disable_channel_route(uint32_t routeloc) {
/*
* Check if a channel is active
*/
bool pwmout_channel_route_active(uint32_t routeloc) {
bool pwmout_channel_route_active(uint32_t routeloc)
{
#ifdef TIMER_ROUTEPEN_CC0PEN
if(PWM_TIMER->ROUTEPEN & routeloc) {
if (PWM_TIMER->ROUTEPEN & routeloc) {
return true;
}
#else
if(PWM_TIMER->ROUTE & routeloc) {
if (PWM_TIMER->ROUTE & routeloc) {
return true;
}
#endif
@ -114,7 +116,8 @@ bool pwmout_channel_route_active(uint32_t routeloc) {
/*
* Set the given route PEN flag
*/
void pwmout_set_channel_route(uint32_t routeloc) {
void pwmout_set_channel_route(uint32_t routeloc)
{
#ifdef TIMER_ROUTEPEN_CC0PEN
PWM_TIMER->ROUTEPEN |= routeloc;
#else
@ -125,9 +128,10 @@ void pwmout_set_channel_route(uint32_t routeloc) {
/*
* Check if all routes are disabled
*/
bool pwmout_all_inactive(void) {
bool pwmout_all_inactive(void)
{
#ifdef TIMER_ROUTEPEN_CC0PEN
if(PWM_TIMER->ROUTEPEN == _TIMER_ROUTEPEN_RESETVALUE) {
if (PWM_TIMER->ROUTEPEN == _TIMER_ROUTEPEN_RESETVALUE) {
return true;
}
#else
@ -148,7 +152,8 @@ void pwmout_enable_pins(pwmout_t *obj, uint8_t enable)
}
}
void pwmout_enable(pwmout_t *obj, uint8_t enable){
void pwmout_enable(pwmout_t *obj, uint8_t enable)
{
if (enable) {
// Set mode to PWM
PWM_TIMER->CC[obj->channel].CTRL = TIMER_CC_CTRL_MODE_PWM;
@ -168,13 +173,13 @@ void pwmout_init(pwmout_t *obj, PinName pin)
CMU_ClockEnable(PWM_TIMER_CLOCK, true);
/* Turn on timer */
if(!(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING)) {
if (!(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING)) {
TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
TIMER_Init(PWM_TIMER, &timerInit);
}
// Set route enable
if(pwmout_channel_route_active(pwmout_get_channel_route(obj->channel))) {
if (pwmout_channel_route_active(pwmout_get_channel_route(obj->channel))) {
//This channel was already in use
//TODO: gracefully handle this case. mbed_error?
return;
@ -190,19 +195,19 @@ void pwmout_init(pwmout_t *obj, PinName pin)
switch (obj->channel) {
case PWM_CH0:
PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC0LOC_MASK;
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTELOC0_CC0LOC_SHIFT;
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTELOC0_CC0LOC_SHIFT;
break;
case PWM_CH1:
PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC1LOC_MASK;
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM)<< _TIMER_ROUTELOC0_CC1LOC_SHIFT;
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTELOC0_CC1LOC_SHIFT;
break;
case PWM_CH2:
PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC2LOC_MASK;
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTELOC0_CC2LOC_SHIFT;
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTELOC0_CC2LOC_SHIFT;
break;
case PWM_CH3:
PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC3LOC_MASK;
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTELOC0_CC3LOC_SHIFT;
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTELOC0_CC3LOC_SHIFT;
break;
default:
MBED_ASSERT(false);
@ -211,10 +216,10 @@ void pwmout_init(pwmout_t *obj, PinName pin)
// On P1, the route location is statically defined for the entire timer.
PWM_TIMER->ROUTE &= ~_TIMER_ROUTE_LOCATION_MASK;
// Make sure the route location is not overwritten
if(pwmout_all_inactive()) {
PWM_TIMER->ROUTE |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT;
if (pwmout_all_inactive()) {
PWM_TIMER->ROUTE |= pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT;
} else {
MBED_ASSERT((PWM_TIMER->ROUTE & _TIMER_ROUTE_LOCATION_MASK) == pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT);
MBED_ASSERT((PWM_TIMER->ROUTE & _TIMER_ROUTE_LOCATION_MASK) == pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT);
}
#endif
@ -224,7 +229,7 @@ void pwmout_init(pwmout_t *obj, PinName pin)
void pwmout_free(pwmout_t *obj)
{
if(pwmout_disable_channel_route(pwmout_get_channel_route(obj->channel))) {
if (pwmout_disable_channel_route(pwmout_get_channel_route(obj->channel))) {
//Channel was previously enabled, so do housekeeping
sleep_manager_unlock_deep_sleep();
} else {
@ -233,10 +238,10 @@ void pwmout_free(pwmout_t *obj)
pwmout_enable_pins(obj, false);
if(pwmout_all_inactive()) {
if (pwmout_all_inactive()) {
//Stop timer
PWM_TIMER->CMD = TIMER_CMD_STOP;
while(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING);
while (PWM_TIMER->STATUS & TIMER_STATUS_RUNNING);
//Disable clock
CMU_ClockEnable(PWM_TIMER_CLOCK, false);
@ -248,14 +253,15 @@ void pwmout_write(pwmout_t *obj, float value)
pwmout_write_channel(obj->channel, value);
}
void pwmout_write_channel(uint32_t channel, float value) {
void pwmout_write_channel(uint32_t channel, float value)
{
uint32_t width_cycles = 0;
if (value < 0.0f) {
width_cycles = 0;
} else if (value >= 1.0f) {
width_cycles = PWM_TIMER->TOPB + 1;
} else {
width_cycles = (uint16_t)((float)PWM_TIMER->TOPB * value);
width_cycles = (uint16_t)((float)PWM_TIMER->TOPB * value);
}
TIMER_CompareBufSet(PWM_TIMER, channel, width_cycles);
@ -266,14 +272,13 @@ float pwmout_read(pwmout_t *obj)
return pwmout_calculate_duty(TIMER_CaptureGet(PWM_TIMER, obj->channel), TIMER_TopGet(PWM_TIMER));
}
float pwmout_calculate_duty(uint32_t width_cycles, uint32_t period_cycles) {
if(width_cycles > period_cycles) {
float pwmout_calculate_duty(uint32_t width_cycles, uint32_t period_cycles)
{
if (width_cycles > period_cycles) {
return 1.0f;
}
else if (width_cycles == 0) {
} else if (width_cycles == 0) {
return 0.0f;
}
else {
} else {
return (float) width_cycles / (float) period_cycles;
}
}
@ -302,7 +307,9 @@ void pwmout_period(pwmout_t *obj, float seconds)
}
//Check if anything changed
if(((PWM_TIMER->CTRL & _TIMER_CTRL_PRESC_MASK) == (pwm_prescaler_div << _TIMER_CTRL_PRESC_SHIFT)) && (TIMER_TopGet(PWM_TIMER) == cycles)) return;
if (((PWM_TIMER->CTRL & _TIMER_CTRL_PRESC_MASK) == (pwm_prescaler_div << _TIMER_CTRL_PRESC_SHIFT)) && (TIMER_TopGet(PWM_TIMER) == cycles)) {
return;
}
//Save previous period for recalculation of duty cycles
uint32_t previous_period_cycles = PWM_TIMER->TOPB;
@ -315,8 +322,8 @@ void pwmout_period(pwmout_t *obj, float seconds)
//For each active channel, re-calculate the compare value
uint32_t channel = 0;
while(pwmout_get_channel_route(channel) != 0) {
if(pwmout_channel_route_active(channel)) {
while (pwmout_get_channel_route(channel) != 0) {
if (pwmout_channel_route_active(channel)) {
//recalc and reset compare value
pwmout_write_channel(channel, pwmout_calculate_duty(PWM_TIMER->CC[channel].CCVB, previous_period_cycles));
}
@ -334,24 +341,34 @@ void pwmout_period_us(pwmout_t *obj, int us)
pwmout_period(obj, us / 1000000.0f);
}
int pwmout_read_period_us(pwmout_t *obj)
{
return (TIMER_TopGet(PWM_TIMER) * 1000000) / REFERENCE_FREQUENCY;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
uint16_t width_cycles = (uint16_t) (((float) (REFERENCE_FREQUENCY >> pwm_prescaler_div)) * seconds);
uint16_t width_cycles = (uint16_t)(((float)(REFERENCE_FREQUENCY >> pwm_prescaler_div)) * seconds);
TIMER_CompareBufSet(PWM_TIMER, obj->channel, width_cycles);
}
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
uint16_t width_cycles = (uint16_t) (((REFERENCE_FREQUENCY >> pwm_prescaler_div) * ms) / 1000);
uint16_t width_cycles = (uint16_t)(((REFERENCE_FREQUENCY >> pwm_prescaler_div) * ms) / 1000);
TIMER_CompareBufSet(PWM_TIMER, obj->channel, width_cycles);
}
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
uint16_t width_cycles = (uint16_t) (((uint64_t)(REFERENCE_FREQUENCY >> pwm_prescaler_div) * (uint64_t)us) / 1000000UL);
uint16_t width_cycles = (uint16_t)(((uint64_t)(REFERENCE_FREQUENCY >> pwm_prescaler_div) * (uint64_t)us) / 1000000UL);
TIMER_CompareBufSet(PWM_TIMER, obj->channel, width_cycles);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return (TIMER_CaptureGet(PWM_TIMER, obj->channel) * 1000000) / REFERENCE_FREQUENCY ;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -80,7 +80,7 @@ void pwmout_free(pwmout_t *obj)
{
// Stops and clear count operation
TMRB_SetRunState(obj->channel, TMRB_STOP);
pwmout_write(obj,0);
pwmout_write(obj, 0);
obj->channel = NULL;
obj->trailing_timing = 0;
obj->leading_timing = 0;
@ -169,7 +169,7 @@ void pwmout_period_us(pwmout_t *obj, int us)
// Restore the duty-cycle
duty_cycle = (float)((obj->trailing_timing - obj->leading_timing) / obj->trailing_timing);
obj->trailing_timing = cycles;
obj->leading_timing = ((cycles)- (uint16_t)(cycles * duty_cycle));
obj->leading_timing = ((cycles) - (uint16_t)(cycles * duty_cycle));
// Change the source clock division and period
m_tmrb.Mode = TMRB_INTERVAL_TIMER;
@ -192,6 +192,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
TMRB_SetRunState(obj->channel, TMRB_RUN);
}
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->trailing_timing;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, (seconds * 1000000.0f));
@ -212,6 +217,11 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
pwmout_write(obj, value);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->trailing_timing - obj->leading_timing;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;

View File

@ -193,7 +193,7 @@ void pwmout_period_us(pwmout_t *obj, int us)
prscl = T32A_PRSCLx_32;
obj->trailing_timing = (us * CALCULATE_RGC1_VAL);
obj->leading_timing = ((obj->trailing_timing)- (obj->trailing_timing * duty_cycle));
obj->leading_timing = ((obj->trailing_timing) - (obj->trailing_timing * duty_cycle));
obj->p_t32a.p_instance->MOD = T32A_MODE_32;
obj->p_t32a.p_instance->RUNC = (T32A_RUN_DISABLE | T32A_COUNT_STOP);
@ -207,6 +207,11 @@ void pwmout_period_us(pwmout_t *obj, int us)
obj->p_t32a.p_instance->RUNC = (T32A_RUN_ENABLE | T32A_COUNT_START);
}
int pwmout_read_period_us(pwmout_t *obj)
{
return obj->trailing_timing;
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
pwmout_pulsewidth_us(obj, (seconds * 1000000.0f));
@ -227,6 +232,11 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
pwmout_write(obj, value);
}
int pwmout_read_pulsewidth_us(pwmout_t *obj)
{
return obj->trailing_timing - obj->leading_timing;
}
const PinMap *pwmout_pinmap()
{
return PinMap_PWM;