@@ -29,12 +29,12 @@ static const PinMap PinMap_PWM[] = {
29
29
{P1_23 , PWM_4 , 2 },
30
30
{P1_24 , PWM_5 , 2 },
31
31
{P1_26 , PWM_6 , 2 },
32
- {P2_0 , PWM_1 , 1 },
33
- {P2_1 , PWM_2 , 1 },
34
- {P2_2 , PWM_3 , 1 },
35
- {P2_3 , PWM_4 , 1 },
36
- {P2_4 , PWM_5 , 1 },
37
- {P2_5 , PWM_6 , 1 },
32
+ {P2_0 , PWM_1 , 1 },
33
+ {P2_1 , PWM_2 , 1 },
34
+ {P2_2 , PWM_3 , 1 },
35
+ {P2_3 , PWM_4 , 1 },
36
+ {P2_4 , PWM_5 , 1 },
37
+ {P2_5 , PWM_6 , 1 },
38
38
{P3_25 , PWM_2 , 3 },
39
39
{P3_26 , PWM_3 , 3 },
40
40
{NC , NC , 0 }
@@ -54,77 +54,84 @@ __IO uint32_t *PWM_MATCH[] = {
54
54
55
55
static unsigned int pwm_clock_mhz ;
56
56
57
- void pwmout_init (pwmout_t * obj , PinName pin ) {
57
+ void pwmout_init (pwmout_t * obj , PinName pin )
58
+ {
58
59
// determine the channel
59
60
PWMName pwm = (PWMName )pinmap_peripheral (pin , PinMap_PWM );
60
61
MBED_ASSERT (pwm != (PWMName )NC );
61
62
62
63
obj -> pwm = pwm ;
63
64
obj -> MR = PWM_MATCH [pwm ];
64
-
65
+
65
66
// ensure the power is on
66
67
LPC_SC -> PCONP |= 1 << 6 ;
67
-
68
+
68
69
// ensure clock to /4
69
70
LPC_SC -> PCLKSEL0 &= ~(0x3 << 12 ); // pclk = /4
70
71
LPC_PWM1 -> PR = 0 ; // no pre-scale
71
-
72
+
72
73
// ensure single PWM mode
73
74
LPC_PWM1 -> MCR = 1 << 1 ; // reset TC on match 0
74
-
75
+
75
76
// enable the specific PWM output
76
77
LPC_PWM1 -> PCR |= 1 << (8 + pwm );
77
-
78
+
78
79
pwm_clock_mhz = SystemCoreClock / 4000000 ;
79
-
80
+
80
81
// default to 20ms: standard for servos, and fine for e.g. brightness control
81
82
pwmout_period_ms (obj , 20 );
82
- pwmout_write (obj , 0 );
83
-
83
+ pwmout_write (obj , 0 );
84
+
84
85
// Wire pinout
85
86
pinmap_pinout (pin , PinMap_PWM );
86
87
}
87
88
88
- void pwmout_free (pwmout_t * obj ) {
89
+ void pwmout_free (pwmout_t * obj )
90
+ {
89
91
// [TODO]
90
92
}
91
93
92
- void pwmout_write (pwmout_t * obj , float value ) {
94
+ void pwmout_write (pwmout_t * obj , float value )
95
+ {
93
96
if (value < 0.0f ) {
94
97
value = 0.0 ;
95
98
} else if (value > 1.0f ) {
96
99
value = 1.0 ;
97
100
}
98
-
101
+
99
102
// set channel match to percentage
100
103
uint32_t v = (uint32_t )((float )(LPC_PWM1 -> MR0 ) * value );
101
-
104
+
102
105
// workaround for PWM1[1] - Never make it equal MR0, else we get 1 cycle dropout
103
106
if (v == LPC_PWM1 -> MR0 ) {
104
107
v ++ ;
105
108
}
106
-
109
+
107
110
* obj -> MR = v ;
108
-
111
+
109
112
// accept on next period start
110
113
LPC_PWM1 -> LER |= 1 << obj -> pwm ;
111
114
}
112
115
113
- float pwmout_read (pwmout_t * obj ) {
116
+ float pwmout_read (pwmout_t * obj )
117
+ {
114
118
float v = (float )(* obj -> MR ) / (float )(LPC_PWM1 -> MR0 );
115
119
return (v > 1.0f ) ? (1.0f ) : (v );
116
120
}
117
121
118
- void pwmout_period (pwmout_t * obj , float seconds ) {
122
+ void pwmout_period (pwmout_t * obj , float seconds )
123
+ {
119
124
pwmout_period_us (obj , seconds * 1000000.0f );
120
125
}
121
126
122
- void pwmout_period_ms (pwmout_t * obj , int ms ) {
127
+ void pwmout_period_ms (pwmout_t * obj , int ms )
128
+ {
123
129
pwmout_period_us (obj , ms * 1000 );
124
130
}
125
131
126
132
// Set the PWM period, keeping the duty cycle the same.
127
- void pwmout_period_us (pwmout_t * obj , int us ) {
133
+ void pwmout_period_us (pwmout_t * obj , int us )
134
+ {
128
135
// calculate number of ticks
129
136
uint32_t ticks = pwm_clock_mhz * us ;
130
137
@@ -146,30 +153,42 @@ void pwmout_period_us(pwmout_t* obj, int us) {
146
153
LPC_PWM1 -> TCR = TCR_CNT_EN | TCR_PWM_EN ;
147
154
}
148
155
149
- void pwmout_pulsewidth (pwmout_t * obj , float seconds ) {
156
+ int pwmout_read_period_us (pwmout_t * obj )
157
+ {
158
+ return (float )(LPC_PWM1 -> MR0 );
159
+ }
160
+
161
+ void pwmout_pulsewidth (pwmout_t * obj , float seconds )
162
+ {
150
163
pwmout_pulsewidth_us (obj , seconds * 1000000.0f );
151
164
}
152
165
153
- void pwmout_pulsewidth_ms (pwmout_t * obj , int ms ) {
166
+ void pwmout_pulsewidth_ms (pwmout_t * obj , int ms )
167
+ {
154
168
pwmout_pulsewidth_us (obj , ms * 1000 );
155
169
}
156
170
157
- void pwmout_pulsewidth_us (pwmout_t * obj , int us ) {
171
+ void pwmout_pulsewidth_us (pwmout_t * obj , int us )
172
+ {
158
173
// calculate number of ticks
159
174
uint32_t v = pwm_clock_mhz * us ;
160
-
175
+
161
176
// workaround for PWM1[1] - Never make it equal MR0, else we get 1 cycle dropout
162
177
if (v == LPC_PWM1 -> MR0 ) {
163
178
v ++ ;
164
179
}
165
-
180
+
166
181
// set the match register value
167
182
* obj -> MR = v ;
168
-
183
+
169
184
// set the channel latch to update value at next period start
170
185
LPC_PWM1 -> LER |= 1 << obj -> pwm ;
171
186
}
172
187
188
+ int pwmout_read_pulsewidth_us (pwmout_t * obj {
189
+ return (timer -> MR3 - timer -> MR [tid .mr ]);
190
+ }
191
+
173
192
const PinMap * pwmout_pinmap ()
174
193
{
175
194
return PinMap_PWM ;
0 commit comments