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"
20 #include "RZ_A1_Init.h"
21 #include "cpg_iodefine.h"
22 #include "pwm_iodefine.h"
24 // PORT ID, PWM ID, Pin function
25 static const PinMap PinMap_PWM[] = {
26 {P4_4 , PWM0_PIN , 4},
27 {P3_2 , PWM1_PIN , 7},
28 {P4_6 , PWM2_PIN , 4},
29 {P4_7 , PWM3_PIN , 4},
30 {P8_14 , PWM4_PIN , 6},
31 {P8_15 , PWM5_PIN , 6},
32 {P8_13 , PWM6_PIN , 6},
33 {P8_11 , PWM7_PIN , 6},
34 {P8_8 , PWM8_PIN , 6},
35 {P10_0 , PWM9_PIN , 3},
36 {P8_12 , PWM10_PIN, 6},
37 {P8_9 , PWM11_PIN, 6},
38 {P8_10 , PWM12_PIN, 6},
39 {P4_5 , PWM13_PIN, 4},
43 static PWMType PORT[] = {
60 static __IO uint16_t *PWM_MATCH[] = {
61 &PWMPWBFR_2E, // PWM0_PIN
62 &PWMPWBFR_2C, // PWM1_PIN
63 &PWMPWBFR_2G, // PWM2_PIN
64 &PWMPWBFR_2G, // PWM3_PIN
65 &PWMPWBFR_1G, // PWM4_PIN
66 &PWMPWBFR_1G, // PWM5_PIN
67 &PWMPWBFR_1E, // PWM6_PIN
68 &PWMPWBFR_1C, // PWM7_PIN
69 &PWMPWBFR_1A, // PWM8_PIN
70 &PWMPWBFR_2A, // PWM9_PIN
71 &PWMPWBFR_1E, // PWM10_PIN
72 &PWMPWBFR_1A, // PWM11_PIN
73 &PWMPWBFR_1C, // PWM12_PIN
74 &PWMPWBFR_2E, // PWM13_PIN
77 static uint16_t init_period_ch1 = 0;
78 static uint16_t init_period_ch2 = 0;
79 static int32_t period_ch1 = 1;
80 static int32_t period_ch2 = 1;
82 void pwmout_init(pwmout_t* obj, PinName pin) {
83 // determine the channel
84 PWMName pwm = (PWMName)pinmap_peripheral(pin, PinMap_PWM);
85 MBED_ASSERT(pwm != (PWMName)NC);
91 if (((uint32_t)PORT[obj->pwm] & 0x00000010) != 0) {
93 PWMPWPR_2_BYTE_L = 0x00;
96 PWMPWPR_1_BYTE_L = 0x00;
100 pinmap_pinout(pin, PinMap_PWM);
102 // default to 491us: standard for servos, and fine for e.g. brightness control
103 pwmout_write(obj, 0);
104 if ((obj->ch == 2) && (init_period_ch2 == 0)) {
105 pwmout_period_us(obj, 491);
108 if ((obj->ch == 1) && (init_period_ch1 == 0)) {
109 pwmout_period_us(obj, 491);
114 void pwmout_free(pwmout_t* obj) {
115 pwmout_write(obj, 0);
118 void pwmout_write(pwmout_t* obj, float value) {
124 } else if (value > 1.0f) {
131 wk_cycle = PWMPWCYR_2 & 0x03ff;
133 wk_cycle = PWMPWCYR_1 & 0x03ff;
136 // set channel match to percentage
137 v = (uint16_t)((float)wk_cycle * value);
138 *PWM_MATCH[obj->pwm] = (v | ((PORT[obj->pwm] & 1) << 12));
141 float pwmout_read(pwmout_t* obj) {
146 wk_cycle = PWMPWCYR_2 & 0x03ff;
148 wk_cycle = PWMPWCYR_1 & 0x03ff;
150 value = ((float)(*PWM_MATCH[obj->pwm] & 0x03ff) / (float)wk_cycle);
152 return (value > 1.0f) ? (1.0f) : (value);
155 void pwmout_period(pwmout_t* obj, float seconds) {
156 pwmout_period_us(obj, seconds * 1000000.0f);
159 void pwmout_period_ms(pwmout_t* obj, int ms) {
160 pwmout_period_us(obj, ms * 1000);
163 static void set_duty_again(__IO uint16_t *p_pwmpbfr, uint16_t last_cycle, uint16_t new_cycle){
168 wk_pwmpbfr = *p_pwmpbfr;
169 value = ((float)(wk_pwmpbfr & 0x03ff) / (float)last_cycle);
170 v = (uint16_t)((float)new_cycle * value);
171 *p_pwmpbfr = (v | (wk_pwmpbfr & 0x1000));
174 // Set the PWM period, keeping the duty cycle the same.
175 void pwmout_period_us(pwmout_t* obj, int us) {
178 uint16_t wk_last_cycle;
189 if (RZ_A1_IsClockMode0() == false) {
190 pclk_base = (uint32_t)CM1_RENESAS_RZ_A1_P0_CLK / 10000;
192 pclk_base = (uint32_t)CM0_RENESAS_RZ_A1_P0_CLK / 10000;
195 wk_cycle = pclk_base * us;
196 while (wk_cycle >= 102350) {
200 wk_cycle = (wk_cycle + 50) / 100;
203 wk_last_cycle = PWMPWCYR_2 & 0x03ff;
204 PWMPWCR_2_BYTE_L = 0xc0 | wk_cks;
205 PWMPWCYR_2 = (uint16_t)wk_cycle;
208 set_duty_again(&PWMPWBFR_2A, wk_last_cycle, wk_cycle);
209 set_duty_again(&PWMPWBFR_2C, wk_last_cycle, wk_cycle);
210 set_duty_again(&PWMPWBFR_2E, wk_last_cycle, wk_cycle);
211 set_duty_again(&PWMPWBFR_2G, wk_last_cycle, wk_cycle);
214 PWMPWCR_2_BYTE_L |= 0x08;
216 // Save for future use
219 wk_last_cycle = PWMPWCYR_1 & 0x03ff;
220 PWMPWCR_1_BYTE_L = 0xc0 | wk_cks;
221 PWMPWCYR_1 = (uint16_t)wk_cycle;
224 set_duty_again(&PWMPWBFR_1A, wk_last_cycle, wk_cycle);
225 set_duty_again(&PWMPWBFR_1C, wk_last_cycle, wk_cycle);
226 set_duty_again(&PWMPWBFR_1E, wk_last_cycle, wk_cycle);
227 set_duty_again(&PWMPWBFR_1G, wk_last_cycle, wk_cycle);
230 PWMPWCR_1_BYTE_L |= 0x08;
232 // Save for future use
237 void pwmout_pulsewidth(pwmout_t* obj, float seconds) {
238 pwmout_pulsewidth_us(obj, seconds * 1000000.0f);
241 void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
242 pwmout_pulsewidth_us(obj, ms * 1000);
245 void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
249 if (period_ch2 != 0) {
250 value = (float)us / (float)period_ch2;
253 if (period_ch1 != 0) {
254 value = (float)us / (float)period_ch1;
258 pwmout_write(obj, value);