1 /* mbed Microcontroller Library
2 * Copyright (c) 2006-2013 ARM Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #include "mbed_assert.h"
17 #include "pwmout_api.h"
23 #include "fsl_ftm_hal.h"
24 #include "fsl_mcg_hal.h"
25 #include "fsl_clock_manager.h"
26 #include "PeripheralPins.h"
28 static float pwm_clock_mhz
;
30 void pwmout_init(pwmout_t
* obj
, PinName pin
) {
31 PWMName pwm
= (PWMName
)pinmap_peripheral(pin
, PinMap_PWM
);
32 MBED_ASSERT(pwm
!= (PWMName
)NC
);
36 uint32_t pwm_base_clock
;
37 CLOCK_SYS_GetFreq(kBusClock
, &pwm_base_clock
);
38 float clkval
= (float)pwm_base_clock
/ 1000000.0f
;
48 pwm_clock_mhz
= clkval
;
49 uint32_t channel
= pwm
& 0xF;
50 uint32_t instance
= pwm
>> TPM_SHIFT
;
51 uint32_t ftm_addrs
[] = FTM_BASE_ADDRS
;
52 CLOCK_SYS_EnableFtmClock(instance
);
54 FTM_HAL_SetTofFreq(ftm_addrs
[instance
], 3);
55 FTM_HAL_SetClockSource(ftm_addrs
[instance
], kClock_source_FTM_SystemClk
);
56 FTM_HAL_SetClockPs(ftm_addrs
[instance
], (ftm_clock_ps_t
)clkdiv
);
57 FTM_HAL_SetCounter(ftm_addrs
[instance
], 0);
58 // default to 20ms: standard for servos, and fine for e.g. brightness control
59 pwmout_period_ms(obj
, 20);
60 pwmout_write (obj
, 0);
61 ftm_pwm_param_t config
= {
62 .mode
= kFtmEdgeAlignedPWM
,
63 .edgeMode
= kFtmHighTrue
65 FTM_HAL_EnablePwmMode(ftm_addrs
[instance
], &config
, channel
);
68 pinmap_pinout(pin
, PinMap_PWM
);
71 void pwmout_free(pwmout_t
* obj
) {
74 void pwmout_write(pwmout_t
* obj
, float value
) {
75 uint32_t instance
= obj
->pwm_name
>> TPM_SHIFT
;
78 } else if (value
> 1.0f
) {
81 uint32_t ftm_addrs
[] = FTM_BASE_ADDRS
;
82 uint16_t mod
= FTM_HAL_GetMod(ftm_addrs
[instance
]);
83 uint32_t new_count
= (uint32_t)((float)(mod
) * value
);
84 // Stop FTM clock to ensure instant update of MOD register
85 FTM_HAL_SetClockSource(ftm_addrs
[instance
], kClock_source_FTM_None
);
86 FTM_HAL_SetChnCountVal(ftm_addrs
[instance
], obj
->pwm_name
& 0xF, new_count
);
87 FTM_HAL_SetCounter(ftm_addrs
[instance
], 0);
88 FTM_HAL_SetClockSource(ftm_addrs
[instance
], kClock_source_FTM_SystemClk
);
91 float pwmout_read(pwmout_t
* obj
) {
92 uint32_t ftm_addrs
[] = FTM_BASE_ADDRS
;
93 uint16_t count
= FTM_HAL_GetChnCountVal(ftm_addrs
[obj
->pwm_name
>> TPM_SHIFT
], obj
->pwm_name
& 0xF, 0);
94 uint16_t mod
= FTM_HAL_GetMod(ftm_addrs
[obj
->pwm_name
>> TPM_SHIFT
]);
97 float v
= (float)(count
) / (float)(mod
);
98 return (v
> 1.0f
) ? (1.0f
) : (v
);
101 void pwmout_period(pwmout_t
* obj
, float seconds
) {
102 pwmout_period_us(obj
, seconds
* 1000000.0f
);
105 void pwmout_period_ms(pwmout_t
* obj
, int ms
) {
106 pwmout_period_us(obj
, ms
* 1000);
109 // Set the PWM period, keeping the duty cycle the same.
110 void pwmout_period_us(pwmout_t
* obj
, int us
) {
111 uint32_t instance
= obj
->pwm_name
>> TPM_SHIFT
;
112 uint32_t ftm_addrs
[] = FTM_BASE_ADDRS
;
113 float dc
= pwmout_read(obj
);
114 // Stop FTM clock to ensure instant update of MOD register
115 FTM_HAL_SetClockSource(ftm_addrs
[instance
], kClock_source_FTM_None
);
116 FTM_HAL_SetMod(ftm_addrs
[instance
], (uint32_t)(pwm_clock_mhz
* (float)us
) - 1);
117 pwmout_write(obj
, dc
);
118 FTM_HAL_SetClockSource(ftm_addrs
[instance
], kClock_source_FTM_SystemClk
);
121 void pwmout_pulsewidth(pwmout_t
* obj
, float seconds
) {
122 pwmout_pulsewidth_us(obj
, seconds
* 1000000.0f
);
125 void pwmout_pulsewidth_ms(pwmout_t
* obj
, int ms
) {
126 pwmout_pulsewidth_us(obj
, ms
* 1000);
129 void pwmout_pulsewidth_us(pwmout_t
* obj
, int us
) {
130 uint32_t ftm_addrs
[] = FTM_BASE_ADDRS
;
131 uint32_t value
= (uint32_t)(pwm_clock_mhz
* (float)us
);
132 FTM_HAL_SetChnCountVal(ftm_addrs
[obj
->pwm_name
>> TPM_SHIFT
], obj
->pwm_name
& 0xF, value
);