28
28
*/
29
29
static const PinMap PinMap_PWM [] = {
30
30
/* CT16B0 */
31
- {P0_8 , PWM_1 , 0x02 }, /* MR0 */
32
- {P0_9 , PWM_2 , 0x02 }, /* MR1 */
31
+ {P0_8 , PWM_1 , 0x02 }, /* MR0 */
32
+ {P0_9 , PWM_2 , 0x02 }, /* MR1 */
33
33
34
34
/* CT16B1 */
35
- {P1_9 , PWM_3 , 0x01 }, /* MR0 */
35
+ {P1_9 , PWM_3 , 0x01 }, /* MR0 */
36
36
{P1_10 , PWM_4 , 0x02 }, /* MR1 */
37
37
38
38
/* CT32B0 */
39
- {P0_1 , PWM_5 , 0x02 }, /* MR2 */
39
+ {P0_1 , PWM_5 , 0x02 }, /* MR2 */
40
40
41
- {NC , NC , 0x00 }
41
+ {NC , NC , 0x00 }
42
42
};
43
43
44
44
typedef struct {
@@ -61,49 +61,52 @@ static LPC_TMR_TypeDef *Timers[3] = {
61
61
LPC_TMR32B0
62
62
};
63
63
64
- void pwmout_init (pwmout_t * obj , PinName pin ) {
64
+ void pwmout_init (pwmout_t * obj , PinName pin )
65
+ {
65
66
// determine the channel
66
67
PWMName pwm = (PWMName )pinmap_peripheral (pin , PinMap_PWM );
67
68
MBED_ASSERT (pwm != (PWMName )NC );
68
69
69
70
obj -> pwm = pwm ;
70
-
71
+
71
72
// Timer registers
72
73
timer_mr tid = pwm_timer_map [pwm ];
73
74
LPC_TMR_TypeDef * timer = Timers [tid .timer ];
74
-
75
+
75
76
// Disable timer
76
77
timer -> TCR = 0 ;
77
-
78
+
78
79
// Power the correspondent timer
79
80
LPC_SYSCON -> SYSAHBCLKCTRL |= 1 << (tid .timer + 7 );
80
-
81
+
81
82
/* Enable PWM function */
82
- timer -> PWMC = (1 << 3 )| (1 << 2 )| (1 << 1 )| (1 << 0 );
83
-
83
+ timer -> PWMC = (1 << 3 ) | (1 << 2 ) | (1 << 1 ) | (1 << 0 );
84
+
84
85
/* Reset Functionality on MR3 controlling the PWM period */
85
86
timer -> MCR = 1 << 10 ;
86
-
87
+
87
88
if (timer == LPC_TMR16B0 || timer == LPC_TMR16B1 ) {
88
- /* Set 16-bit timer prescaler to avoid timer expire for default 20ms */
89
- /* This can be also modified by user application, but the prescaler value */
90
- /* might be trade-off to timer accuracy */
89
+ /* Set 16-bit timer prescaler to avoid timer expire for default 20ms */
90
+ /* This can be also modified by user application, but the prescaler value */
91
+ /* might be trade-off to timer accuracy */
91
92
timer -> PR = 30 ;
92
93
}
93
94
94
95
// default to 20ms: standard for servos, and fine for e.g. brightness control
95
96
pwmout_period_ms (obj , 20 );
96
- pwmout_write (obj , 0 );
97
-
97
+ pwmout_write (obj , 0 );
98
+
98
99
// Wire pinout
99
100
pinmap_pinout (pin , PinMap_PWM );
100
101
}
101
102
102
- void pwmout_free (pwmout_t * obj ) {
103
+ void pwmout_free (pwmout_t * obj )
104
+ {
103
105
// [TODO]
104
106
}
105
107
106
- void pwmout_write (pwmout_t * obj , float value ) {
108
+ void pwmout_write (pwmout_t * obj , float value )
109
+ {
107
110
if (value < 0.0f ) {
108
111
value = 0.0 ;
109
112
} else if (value > 1.0f ) {
@@ -123,61 +126,73 @@ void pwmout_write(pwmout_t* obj, float value) {
123
126
timer -> TCR = TCR_CNT_EN ;
124
127
}
125
128
126
- float pwmout_read (pwmout_t * obj ) {
129
+ float pwmout_read (pwmout_t * obj )
130
+ {
127
131
timer_mr tid = pwm_timer_map [obj -> pwm ];
128
132
LPC_TMR_TypeDef * timer = Timers [tid .timer ];
129
-
133
+
130
134
float v = (float )(timer -> MR3 - timer -> MR [tid .mr ]) / (float )(timer -> MR3 );
131
135
if (timer -> MR [tid .mr ] > timer -> MR3 ) {
132
136
v = 0.0f ;
133
137
}
134
138
return (v > 1.0f ) ? (1.0f ) : (v );
135
139
}
136
140
137
- void pwmout_period (pwmout_t * obj , float seconds ) {
141
+ void pwmout_period (pwmout_t * obj , float seconds )
142
+ {
138
143
pwmout_period_us (obj , seconds * 1000000.0f );
139
144
}
140
145
141
- void pwmout_period_ms (pwmout_t * obj , int ms ) {
146
+ void pwmout_period_ms (pwmout_t * obj , int ms )
147
+ {
142
148
pwmout_period_us (obj , ms * 1000 );
143
149
}
144
150
145
151
// Set the PWM period, keeping the duty cycle the same.
146
- void pwmout_period_us (pwmout_t * obj , int us ) {
152
+ void pwmout_period_us (pwmout_t * obj , int us )
153
+ {
147
154
int i = 0 ;
148
155
uint32_t period_ticks ;
149
-
156
+
150
157
timer_mr tid = pwm_timer_map [obj -> pwm ];
151
158
LPC_TMR_TypeDef * timer = Timers [tid .timer ];
152
159
uint32_t old_period_ticks = timer -> MR3 ;
153
160
period_ticks = (SystemCoreClock / 1000000 * us ) / (timer -> PR + 1 );
154
161
155
162
timer -> TCR = TCR_RESET ;
156
163
timer -> MR3 = period_ticks ;
157
-
164
+
158
165
// Scale the pulse width to preserve the duty ratio
159
166
if (old_period_ticks > 0 ) {
160
- for (i = 0 ; i < 3 ; i ++ ) {
167
+ for (i = 0 ; i < 3 ; i ++ ) {
161
168
uint32_t t_off = period_ticks - (uint32_t )(((uint64_t )timer -> MR [i ] * (uint64_t )period_ticks ) / (uint64_t )old_period_ticks );
162
169
timer -> MR [i ] = t_off ;
163
170
}
164
171
}
165
172
timer -> TCR = TCR_CNT_EN ;
166
173
}
167
174
168
- void pwmout_pulsewidth (pwmout_t * obj , float seconds ) {
175
+ int pwmout_read_period_us (pwmout_t * obj )
176
+ {
177
+ return (timer -> MR3 );
178
+ }
179
+
180
+ void pwmout_pulsewidth (pwmout_t * obj , float seconds )
181
+ {
169
182
pwmout_pulsewidth_us (obj , seconds * 1000000.0f );
170
183
}
171
184
172
- void pwmout_pulsewidth_ms (pwmout_t * obj , int ms ) {
185
+ void pwmout_pulsewidth_ms (pwmout_t * obj , int ms )
186
+ {
173
187
pwmout_pulsewidth_us (obj , ms * 1000 );
174
188
}
175
189
176
- void pwmout_pulsewidth_us (pwmout_t * obj , int us ) {
190
+ void pwmout_pulsewidth_us (pwmout_t * obj , int us )
191
+ {
177
192
timer_mr tid = pwm_timer_map [obj -> pwm ];
178
193
LPC_TMR_TypeDef * timer = Timers [tid .timer ];
179
194
uint32_t t_on = (uint32_t )((((uint64_t )SystemCoreClock * (uint64_t )us ) / (uint64_t )1000000 ) / (timer -> PR + 1 ));
180
-
195
+
181
196
timer -> TCR = TCR_RESET ;
182
197
if (t_on > timer -> MR3 ) {
183
198
pwmout_period_us (obj , us );
@@ -187,6 +202,10 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
187
202
timer -> TCR = TCR_CNT_EN ;
188
203
}
189
204
205
+ int pwmout_read_pulsewidth_us (pwmout_t * obj {
206
+ return (timer -> MR3 - timer -> MR [tid .mr ]);
207
+ }
208
+
190
209
const PinMap * pwmout_pinmap ()
191
210
{
192
211
return PinMap_PWM ;
0 commit comments