8000 rp2/PWM: Support inverting a channel output. · micropython/micropython@1059265 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1059265

Browse files
committed
rp2/PWM: Support inverting a channel output.
Using the invert=True|False keyword option with the constructor or init().
1 parent 9e1b996 commit 1059265

File tree

3 files changed

+55
-37
lines changed

3 files changed

+55
-37
lines changed

docs/library/machine.PWM.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Example usage::
2424
Constructors
2525
------------
2626

27-
.. class:: PWM(dest, *, freq, duty_u16, duty_ns)
27+
.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert)
2828

2929
Construct and return a new PWM object using the following parameters:
3030

@@ -35,10 +35,12 @@ Constructors
3535
PWM cycle.
3636
- *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65535``.
3737
- *duty_ns* sets the pulse width in nanoseconds.
38+
- *invert* inverts the respective output if the value is True
3839

3940
Setting *freq* may affect other PWM objects if the objects share the same
4041
underlying PWM generator (this is hardware specific).
4142
Only one of *duty_u16* and *duty_ns* should be specified at a time.
43+
*invert* is not available at all ports.
4244

4345
Methods
4446
-------

docs/samd/quickref.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff li 10000 ne numberDiff line change
@@ -192,7 +192,7 @@ It supports all basic methods listed for that class. ::
192192
PWM Constructor
193193
```````````````
194194

195-
.. class:: PWM(dest, freq, duty_u16, duty_ns, *, invert, device)
195+
.. class:: PWM(dest, *, freq, duty_u16, duty_ns, invert, device)
196196
:noindex:
197197

198198
Construct and return a new PWM object using the following parameters:

ports/rp2/machine_pwm.c

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ typedef struct _machine_pwm_obj_t {
3838
mp_obj_base_t base;
3939
uint8_t slice;
4040
uint8_t channel;
41+
uint8_t invert;
4142
uint8_t duty_type;
42-
bool freq_set;
4343
mp_int_t duty;
4444
} machine_pwm_obj_t;
4545

@@ -51,67 +51,80 @@ enum {
5151
};
5252

5353
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 },
7070
};
7171

72+
STATIC bool defer_start;
73+
STATIC bool slice_freq_set[8];
74+
7275
STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq);
7376
STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16);
7477
STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns);
7578

7679
STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
7780
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);
7983
}
8084

8185
void machine_pwm_start(machine_pwm_obj_t *self) {
8286
// 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+
}
8493
pwm_set_enabled(self->slice, true);
8594
}
8695
}
8796

8897
STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
8998
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 };
91100
static const mp_arg_t allowed_args[] = {
92101
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = VALUE_NOT_SET} },
93102
{ MP_QSTR_duty_u16, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = VALUE_NOT_SET} },
94103
{ 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} },
95105
};
96106

97107
// Parse the arguments.
98108
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
99109
mp_arg_parse_all(n_args, pos_args, kw_args,
100110
MP_ARRAY_SIZE(allowed_args), allowed_args, args);
101111

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);
114122
}
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);
115128
}
116129

117130
// 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
126139
uint slice = pwm_gpio_to_slice_num(gpio);
127140
uint8_t channel = pwm_gpio_to_channel(gpio);
128141
machine_pwm_obj_t *self = &machine_pwm_obj[slice * 2 + channel];
129-
self->freq_set = false;
142+
self->invert = 0;
130143
self->duty_type = DUTY_NOT_SET;
131144

132145
// 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
143156
// Stop all active slices.
144157
void machine_pwm_deinit_all(void) {
145158
for (int i = 0; i < 8; i++) {
159+
slice_freq_set[i] = false;
146160
pwm_set_enabled(machine_pwm_obj[i].slice, false);
147161
}
148162
}
@@ -216,14 +230,16 @@ STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
216230
}
217231
pwm_hw->slice[self->slice].div = div16;
218232
pwm_hw->slice[self->slice].top = top;
219-
self->freq_set = true;
233+
slice_freq_set[self->slice] = true;
220234
if (self->duty_type == DUTY_U16) {
221235
mp_machine_pwm_duty_set_u16(self, self->duty);
222236
} else if (self->duty_type == DUTY_NS) {
223237
mp_machine_pwm_duty_set_ns(self, self->duty);
224238
}
225239
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) {
227243
mp_machine_pwm_duty_set_ns(other, other->duty);
228244
}
229245
}

0 commit comments

Comments
 (0)
0