@@ -142,14 +142,14 @@ STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args
142
142
self -> invert = 0 ;
143
143
self -> duty_type = DUTY_NOT_SET ;
144
144
145
- // Select PWM function for given GPIO.
146
- gpio_set_function (gpio , GPIO_FUNC_PWM );
147
-
148
145
// Process the remaining parameters.
149
146
mp_map_t kw_args ;
150
147
mp_map_init_fixed_table (& kw_args , n_kw , all_args + n_args );
151
148
mp_machine_pwm_init_helper (self , n_args - 1 , all_args + 1 , & kw_args );
152
149
150
+ // Select PWM function for given GPIO.
151
+ gpio_set_function (gpio , GPIO_FUNC_PWM );
152
+
153
153
return MP_OBJ_FROM_PTR (self );
154
154
}
155
155
@@ -158,7 +158,15 @@ void machine_pwm_deinit_all(void) {
158
158
for (int i = 0 ; i < 8 ; i ++ ) {
159
159
slice_freq_set [i ] = false;
160
160
pwm_set_enabled (machine_pwm_obj [i ].slice , false);
161
+ // pwm_set_chan_level(i, 0, 0);
162
+ // pwm_set_chan_level(i, 1, 0);
161
163
}
164
+ // Clean out the table
165
+ // for (int i = 0; i < 16; i++) {
166
+ // machine_pwm_obj[i].invert = 0;
167
+ // machine_pwm_obj[i].duty = 0;
168
+ // machine_pwm_obj[i].duty_type = DUTY_NOT_SET;
169
+ // }
162
170
}
163
171
164
172
STATIC void mp_machine_pwm_deinit (machine_pwm_obj_t * self ) {
@@ -189,10 +197,14 @@ uint32_t get_slice_hz_ceil(uint32_t div16) {
189
197
}
190
198
191
199
STATIC mp_obj_t mp_machine_pwm_freq_get (machine_pwm_obj_t * self ) {
192
- uint32_t div16 = pwm_hw -> slice [self -> slice ].div ;
193
- uint32_t top = pwm_hw -> slice [self -> slice ].top ;
194
- uint32_t pwm_freq = get_slice_hz_round (div16 * (top + 1 ));
195
- return MP_OBJ_NEW_SMALL_INT (pwm_freq );
200
+ if (slice_freq_set [self -> slice ] == true) {
201
+ uint32_t div16 = pwm_hw -> slice [self -> slice ].div ;
202
+ uint32_t top = pwm_hw -> slice [self -> slice ].top ;
203
+ uint32_t pwm_freq = get_slice_hz_round (div16 * (top + 1 ));
204
+ return MP_OBJ_NEW_SMALL_INT (pwm_freq );
205
+ } else {
206
+ return MP_OBJ_NEW_SMALL_INT (0 );
207
+ }
196
208
}
197
209
198
210
STATIC void mp_machine_pwm_freq_set (machine_pwm_obj_t * self , mp_int_t freq ) {
@@ -245,19 +257,27 @@ STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
245
257
}
246
258
247
259
STATIC mp_obj_t mp_machine_pwm_duty_get_u16 (machine_pwm_obj_t * self ) {
248
- uint32_t top = pwm_hw -> slice [self -> slice ].top ;
249
- uint32_t cc = pwm_hw -> slice [self -> slice ].cc ;
250
- cc = (cc >> (self -> channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB )) & 0xffff ;
251
-
252
- // Use rounding (instead of flooring) here to give as accurate an
253
- // estimate as possible.
254
- return MP_OBJ_NEW_SMALL_INT ((cc * 65535 + (top + 1 ) / 2 ) / (top + 1 ));
260
+ if (self -> duty_type != DUTY_NOT_SET && slice_freq_set [self -> slice ] == true) {
261
+ uint32_t top = pwm_hw -> slice [self -> slice ].top ;
262
+ uint32_t cc = pwm_hw -> slice [self -> slice ].cc ;
263
+ cc = (cc >> (self -> channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB )) & 0xffff ;
264
+
265
+ // Use rounding (instead of flooring) here to give as accurate an
266
+ // estimate as possible.
267
+ return MP_OBJ_NEW_SMALL_INT ((cc * 65535 + (top + 1 ) / 2 ) / (top + 1 ));
268
+ } else {
269
+ return MP_OBJ_NEW_SMALL_INT (0 );
270
+ }
255
271
}
256
272
257
273
STATIC void mp_machine_pwm_duty_set_u16 (machine_pwm_obj_t * self , mp_int_t duty_u16 ) {
258
274
uint32_t top = pwm_hw -> slice [self -> slice ].top ;
259
275
276
+ // Limit duty_u16 to 65535
260
277
// Use rounding here to set it as accurately as possible.
278
+ if (duty_u16 > 65535 ) {
279
+ duty_u16 = 65535 ;
280
+ }
261
281
uint32_t cc = (duty_u16 * (top + 1 ) + 65535 / 2 ) / 65535 ;
262
282
pwm_set_chan_level (self -> slice , self -> channel , cc );
263
283
self -> duty = duty_u16 ;
@@ -266,17 +286,22 @@ STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u
266
286
}
267
287
268
288
STATIC mp_obj_t mp_machine_pwm_duty_get_ns (machine_pwm_obj_t * self ) {
269
- uint32_t slice_hz = get_slice_hz_round (pwm_hw -> slice [self -> slice ].div );
270
- uint32_t cc = pwm_hw -> slice [self -> slice ].cc ;
271
- cc = (cc >> (self -> channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB )) & 0xffff ;
272
- return MP_OBJ_NEW_SMALL_INT (((uint64_t )cc * 1000000000ULL + slice_hz / 2 ) / slice_hz );
289
+ if (self -> duty_type != DUTY_NOT_SET && slice_freq_set [self -> slice ] == true) {
290
+ uint32_t slice_hz = get_slice_hz_round (pwm_hw -> slice [self -> slice ].div );
291
+ uint32_t cc = pwm_hw -> slice [self -> slice ].cc ;
292
+ cc = (cc >> (self -> channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB )) & 0xffff ;
293
+ return MP_OBJ_NEW_SMALL_INT (((uint64_t )cc * 1000000000ULL + slice_hz / 2 ) / slice_hz );
294
+ } else {
295
+ return MP_OBJ_NEW_SMALL_INT (0 );
296
+ }
273
297
}
274
298
275
299
STATIC void mp_machine_pwm_duty_set_ns (machine_pwm_obj_t * self , mp_int_t duty_ns ) {
276
300
uint32_t slice_hz = get_slice_hz_round (pwm_hw -> slice [self -> slice ].div );
277
301
uint32_t cc = ((uint64_t )duty_ns * slice_hz + 500000000ULL ) / 1000000000ULL ;
278
- if (cc > 65535 ) {
279
- mp_raise_ValueError (MP_ERROR_TEXT ("duty larger than period" ));
302
+ uint32_t top = pwm_hw -> slice [self -> slice ].top ;
303
+ if (cc > (top + 1 )) {
304
+ cc = top + 1 ;
280
305
}
281
306
pwm_set_chan_level (self -> slice , self -> channel , cc );
282
307
self -> duty = duty_ns ;
0 commit comments