@@ -38,8 +38,8 @@ typedef struct _machine_pwm_obj_t {
38
38
mp_obj_base_t base ;
39
39
uint8_t slice ;
40
40
uint8_t channel ;
41
+ uint8_t invert ;
41
42
uint8_t duty_type ;
42
- bool freq_set ;
43
43
mp_int_t duty ;
44
44
} machine_pwm_obj_t ;
45
45
@@ -51,67 +51,80 @@ enum {
51
51
};
52
52
53
53
STATIC machine_pwm_obj_t machine_pwm_obj [] = {
54
- {{& machine_pwm_type }, 0 , PWM_CHAN_A , DUTY_NOT_SET , 0 , 0 },
55
- {{& machine_pwm_type }, 0 , PWM_CHAN_B , DUTY_NOT_SET , 0 , 0 },
56
- {{& machine_pwm_type }, 1 , PWM_CHAN_A , DUTY_NOT_SET , 0 , 0 },
57
- {{& machine_pwm_type }, 1 , PWM_CHAN_B , DUTY_NOT_SET , 0 , 0 },
58
- {{& machine_pwm_type }, 2 , PWM_CHAN_A , DUTY_NOT_SET , 0 , 0 },
59
- {{& machine_pwm_type }, 2 , PWM_CHAN_B , DUTY_NOT_SET , 0 , 0 },
60
- {{& machine_pwm_type }, 3 , PWM_CHAN_A , DUTY_NOT_SET , 0 , 0 },
61
- {{& machine_pwm_type }, 3 , PWM_CHAN_B , DUTY_NOT_SET , 0 , 0 },
62
- {{& machine_pwm_type }, 4 , PWM_CHAN_A , DUTY_NOT_SET , 0 , 0 },
63
- {{& machine_pwm_type }, 4 , PWM_CHAN_B , DUTY_NOT_SET , 0 , 0 },
64
- {{& machine_pwm_type }, 5 , PWM_CHAN_A , DUTY_NOT_SET , 0 , 0 },
65
- {{& machine_pwm_type }, 5 , PWM_CHAN_B , DUTY_NOT_SET , 0 , 0 },
66
- {{& machine_pwm_type }, 6 , PWM_CHAN_A , DUTY_NOT_SET , 0 , 0 },
67
- {{& machine_pwm_type }, 6 , PWM_CHAN_B , DUTY_NOT_SET , 0 , 0 },
68
- {{& machine_pwm_type }, 7 , PWM_CHAN_A , DUTY_NOT_SET , 0 , 0 },
69
- {{& machine_pwm_type }, 7 , PWM_CHAN_B , DUTY_NOT_SET , 0 , 0 },
54
+ {{& machine_pwm_type }, 0 , PWM_CHAN_A , 0 , DUTY_NOT_SET , 0 },
55
+ {{& machine_pwm_type }, 0 , PWM_CHAN_B , 0 , DUTY_NOT_SET , 0 },
56
+ {{& machine_pwm_type }, 1 , PWM_CHAN_A , 0 , DUTY_NOT_SET , 0 },
57
+ {{& machine_pwm_type }, 1 , PWM_CHAN_B , 0 , DUTY_NOT_SET , 0 },
58
+ {{& machine_pwm_type }, 2 , PWM_CHAN_A , 0 , DUTY_NOT_SET , 0 },
59
+ {{& machine_pwm_type }, 2 , PWM_CHAN_B , 0 , DUTY_NOT_SET , 0 },
60
+ {{& machine_pwm_type }, 3 , PWM_CHAN_A , 0 , DUTY_NOT_SET , 0 },
61
+ {{& machine_pwm_type }, 3 , PWM_CHAN_B , 0 , DUTY_NOT_SET , 0 },
62
+ {{& machine_pwm_type }, 4 , PWM_CHAN_A , 0 , DUTY_NOT_SET , 0 },
63
+ {{& machine_pwm_type }, 4 , PWM_CHAN_B , 0 , DUTY_NOT_SET , 0 },
64
+ {{& machine_pwm_type }, 5 , PWM_CHAN_A , 0 , DUTY_NOT_SET , 0 },
65
+ {{& machine_pwm_type }, 5 , PWM_CHAN_B , 0 , DUTY_NOT_SET , 0 },
66
+ {{& machine_pwm_type }, 6 , PWM_CHAN_A , 0 , DUTY_NOT_SET , 0 },
67
+ {{& machine_pwm_type }, 6 , PWM_CHAN_B , 0 , DUTY_NOT_SET , 0 },
68
+ {{& machine_pwm_type }, 7 , PWM_CHAN_A , 0 , DUTY_NOT_SET , 0 },
69
+ {{& machine_pwm_type }, 7 , PWM_CHAN_B , 0 , DUTY_NOT_SET , 0 },
70
70
};
71
71
72
+ STATIC bool defer_start ;
73
+ STATIC bool slice_freq_set [8 ];
74
+
72
75
STATIC void mp_machine_pwm_freq_set (machine_pwm_obj_t * self , mp_int_t freq );
73
76
STATIC void mp_machine_pwm_duty_set_u16 (machine_pwm_obj_t * self , mp_int_t duty_u16 );
74
77
STATIC void mp_machine_pwm_duty_set_ns (machine_pwm_obj_t * self , mp_int_t duty_ns );
75
78
76
79
STATIC void mp_machine_pwm_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
77
80
machine_pwm_obj_t * self = MP_OBJ_TO_PTR (self_in );
78
- mp_printf (print , "<PWM slice=%u channel=%u>" , self -> slice , self -> channel );
81
+ mp_printf (print , "<PWM slice=%u channel=%u invert=%u>" ,
82
+ self -> slice , self -> channel , self -> invert );
79
83
}
80
84
81
85
void machine_pwm_start (machine_pwm_obj_t * self ) {
82
86
// Start the PWM if properly set.
83
- if (self -> freq_set && self -> duty_type != DUTY_NOT_SET ) {
87
+ if (defer_start == false && slice_freq_set [self -> slice ] == true && self -> duty_type != DUTY_NOT_SET ) {
88
+ if (self -> channel == PWM_CHAN_A ) {
89
+ pwm_set_output_polarity (self -> slice , self -> invert , (self + 1 )-> invert );
90
+ } else {
91
+ pwm_set_output_polarity (self -> slice , (self - 1 )-> invert , self -> invert );
92
+ }
84
93
pwm_set_enabled (self -> slice , true);
85
94
}
86
95
}
87
96
88
97
STATIC void mp_machine_pwm_init_helper (machine_pwm_obj_t * self ,
89
98
size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
90
- enum { ARG_freq , ARG_duty_u16 , ARG_duty_ns };
99
+ enum { ARG_freq , ARG_duty_u16 , ARG_duty_ns , ARG_invert };
91
100
static const mp_arg_t allowed_args [] = {
92
101
{ MP_QSTR_freq , MP_ARG_INT , {.u_int = VALUE_NOT_SET } },
93
102
{ MP_QSTR_duty_u16 , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = VALUE_NOT_SET } },
94
103
{ MP_QSTR_duty_ns , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = VALUE_NOT_SET } },
104
+ { MP_QSTR_invert , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = VALUE_NOT_SET } },
95
105
};
96
106
97
107
// Parse the arguments.
98
108
mp_arg_val_t args [MP_ARRAY_SIZE (allowed_args )];
99
109
mp_arg_parse_all (n_args , pos_args , kw_args ,
100
110
MP_ARRAY_SIZE (allowed_args ), allowed_args , args );
101
111
102
- if ((n_args + kw_args -> used ) > 0 ) {
103
- if (args [ARG_freq ].u_int != VALUE_NOT_SET ) {
104
- mp_machine_pwm_freq_set (self , args [ARG_freq ].u_int );
105
- }
106
- if (args [ARG_duty_u16 ].u_int != VALUE_NOT_SET ) {
107
- mp_machine_pwm_duty_set_u16 (self , args [ARG_duty_u16 ].u_int );
108
- }
109
- if (args [ARG_duty_ns ].u_int != VALUE_NOT_SET ) {
110
- mp_machine_pwm_duty_set_ns (self , args [ARG_duty_ns ].u_int );
111
- }
112
- } else {
113
- machine_pwm_start (self );
112
+ // defer starting PWM until all provided args are checked.
113
+ defer_start = true;
114
+ if (args [ARG_freq ].u_int != VALUE_NOT_SET ) {
115
+ mp_machine_pwm_freq_set (self , args [ARG_freq ].u_int );
116
+ }
117
+ if (args [ARG_duty_u16 ].u_int != VALUE_NOT_SET ) {
118
+ mp_machine_pwm_duty_set_u16 (self , args [ARG_duty_u16 ].u_int );
119
+ }
120
+ if (args [ARG_duty_ns ].u_int != VALUE_NOT_SET ) {
121
+ mp_machine_pwm_duty_set_ns (self , args [ARG_duty_ns ].u_int );
114
122
}
123
+ if (args [ARG_invert ].u_int != VALUE_NOT_SET ) {
124
+ self -> invert = !!args [ARG_invert ].u_int ;
125
+ }
126
+ defer_start = false;
127
+ machine_pwm_start (self );
115
128
}
116
129
117
130
// PWM(pin [, args])
@@ -126,7 +139,7 @@ STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args
126
139
uint slice = pwm_gpio_to_slice_num (gpio );
127
140
uint8_t channel = pwm_gpio_to_channel (gpio );
128
141
machine_pwm_obj_t * self = & machine_pwm_obj [slice * 2 + channel ];
129
- self -> freq_set = false ;
142
+ self -> invert = 0 ;
130
143
self -> duty_type = DUTY_NOT_SET ;
131
144
132
145
// Select PWM function for given GPIO.
@@ -143,6 +156,7 @@ STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args
143
156
// Stop all active slices.
144
157
void machine_pwm_deinit_all (void ) {
145
158
for (int i = 0 ; i < 8 ; i ++ ) {
159
+ slice_freq_set [i ] = false;
146
160
pwm_set_enabled (machine_pwm_obj [i ].slice , false);
147
161
}
148
162
}
@@ -216,14 +230,16 @@ STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
216
230
}
217
231
pwm_hw -> slice [self -> slice ].div = div16 ;
218
232
pwm_hw -> slice [self -> slice ].top = top ;
219
- self -> freq_set = true;
233
+ slice_freq_set [ self -> slice ] = true;
220
234
if (self -> duty_type == DUTY_U16 ) {
221
235
mp_machine_pwm_duty_set_u16 (self , self -> duty );
222
236
} else if (self -> duty_type == DUTY_NS ) {
223
237
mp_machine_pwm_duty_set_ns (self , self -> duty );
224
238
}
225
239
machine_pwm_obj_t * other = self -> channel == PWM_CHAN_A ? self + 1 : self - 1 ;
226
- if (other -> duty_type == DUTY_NS ) {
240
+ if (other -> duty_type == DUTY_U16 ) {
241
+ mp_machine_pwm_duty_set_u16 (other , other -> duty );
242
+ } else if (other -> duty_type == DUTY_NS ) {
227
243
mp_machine_pwm_duty_set_ns (other , other -> duty );
228
244
}
229
245
}
0 commit comments