summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--extmod/extmod.cmake1
-rw-r--r--extmod/machine_pwm.c143
-rw-r--r--extmod/machine_pwm.h55
-rw-r--r--ports/esp32/machine_pwm.c108
-rw-r--r--ports/esp32/main/CMakeLists.txt1
-rw-r--r--ports/esp32/modmachine.c1
-rw-r--r--ports/esp32/modmachine.h1
-rw-r--r--ports/esp32/mpconfigport.h4
-rw-r--r--ports/esp8266/Makefile1
-rw-r--r--ports/esp8266/machine_pwm.c95
-rw-r--r--ports/esp8266/modmachine.c3
-rw-r--r--ports/esp8266/modmachine.h1
-rw-r--r--ports/esp8266/mpconfigport.h4
-rw-r--r--ports/rp2/CMakeLists.txt2
-rw-r--r--ports/rp2/machine_pwm.c161
-rw-r--r--ports/rp2/modmachine.c1
-rw-r--r--ports/rp2/modmachine.h1
-rw-r--r--ports/rp2/mpconfigport.h3
-rw-r--r--py/py.mk1
19 files changed, 336 insertions, 251 deletions
diff --git a/extmod/extmod.cmake b/extmod/extmod.cmake
index c6b45b0d3e..69ec39759b 100644
--- a/extmod/extmod.cmake
+++ b/extmod/extmod.cmake
@@ -10,6 +10,7 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/machine_i2c.c
${MICROPY_EXTMOD_DIR}/machine_mem.c
${MICROPY_EXTMOD_DIR}/machine_pulse.c
+ ${MICROPY_EXTMOD_DIR}/machine_pwm.c
${MICROPY_EXTMOD_DIR}/machine_signal.c
${MICROPY_EXTMOD_DIR}/machine_spi.c
${MICROPY_EXTMOD_DIR}/modbluetooth.c
diff --git a/extmod/machine_pwm.c b/extmod/machine_pwm.c
new file mode 100644
index 0000000000..ddf49c1358
--- /dev/null
+++ b/extmod/machine_pwm.c
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020-2021 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/runtime.h"
+
+#if MICROPY_PY_MACHINE_PWM
+
+#include "extmod/machine_pwm.h"
+
+#ifdef MICROPY_PY_MACHINE_PWM_INCLUDEFILE
+#include MICROPY_PY_MACHINE_PWM_INCLUDEFILE
+#endif
+
+#if MICROPY_PY_MACHINE_PWM_INIT
+STATIC mp_obj_t machine_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ mp_machine_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pwm_init_obj, 1, machine_pwm_init);
+#endif
+
+// PWM.deinit()
+STATIC mp_obj_t machine_pwm_deinit(mp_obj_t self_in) {
+ machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ mp_machine_pwm_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pwm_deinit_obj, machine_pwm_deinit);
+
+// PWM.freq([value])
+STATIC mp_obj_t machine_pwm_freq(size_t n_args, const mp_obj_t *args) {
+ machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ if (n_args == 1) {
+ // Get frequency.
+ return mp_machine_pwm_freq_get(self);
+ } else {
+ // Set the frequency.
+ mp_int_t freq = mp_obj_get_int(args[1]);
+ mp_machine_pwm_freq_set(self, freq);
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_freq_obj, 1, 2, machine_pwm_freq);
+
+#if MICROPY_PY_MACHINE_PWM_DUTY
+// PWM.duty([duty])
+STATIC mp_obj_t machine_pwm_duty(size_t n_args, const mp_obj_t *args) {
+ machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ if (n_args == 1) {
+ // Get duty cycle.
+ return mp_machine_pwm_duty_get(self);
+ } else {
+ // Set duty cycle.
+ mp_int_t duty = mp_obj_get_int(args[1]);
+ mp_machine_pwm_duty_set(self, duty);
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_obj, 1, 2, machine_pwm_duty);
+#endif
+
+#if MICROPY_PY_MACHINE_PWM_DUTY_U16_NS
+
+// PWM.duty_u16([value])
+STATIC mp_obj_t machine_pwm_duty_u16(size_t n_args, const mp_obj_t *args) {
+ machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ if (n_args == 1) {
+ // Get duty cycle.
+ return mp_machine_pwm_duty_get_u16(self);
+ } else {
+ // Set duty cycle.
+ mp_int_t duty_u16 = mp_obj_get_int(args[1]);
+ mp_machine_pwm_duty_set_u16(self, duty_u16);
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_u16_obj, 1, 2, machine_pwm_duty_u16);
+
+// PWM.duty_ns([value])
+STATIC mp_obj_t machine_pwm_duty_ns(size_t n_args, const mp_obj_t *args) {
+ machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+ if (n_args == 1) {
+ // Get duty cycle.
+ return mp_machine_pwm_duty_get_ns(self);
+ } else {
+ // Set duty cycle.
+ mp_int_t duty_ns = mp_obj_get_int(args[1]);
+ mp_machine_pwm_duty_set_ns(self, duty_ns);
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_ns_obj, 1, 2, machine_pwm_duty_ns);
+
+#endif
+
+STATIC const mp_rom_map_elem_t machine_pwm_locals_dict_table[] = {
+ #if MICROPY_PY_MACHINE_PWM_INIT
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pwm_init_obj) },
+ #endif
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_pwm_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_pwm_freq_obj) },
+ #if MICROPY_PY_MACHINE_PWM_DUTY
+ { MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&machine_pwm_duty_obj) },
+ #endif
+ #if MICROPY_PY_MACHINE_PWM_DUTY_U16_NS
+ { MP_ROM_QSTR(MP_QSTR_duty_u16), MP_ROM_PTR(&machine_pwm_duty_u16_obj) },
+ { MP_ROM_QSTR(MP_QSTR_duty_ns), MP_ROM_PTR(&machine_pwm_duty_ns_obj) },
+ #endif
+};
+STATIC MP_DEFINE_CONST_DICT(machine_pwm_locals_dict, machine_pwm_locals_dict_table);
+
+const mp_obj_type_t machine_pwm_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_PWM,
+ .print = mp_machine_pwm_print,
+ .make_new = mp_machine_pwm_make_new,
+ .locals_dict = (mp_obj_dict_t *)&machine_pwm_locals_dict,
+};
+
+#endif // MICROPY_PY_MACHINE_PWM
diff --git a/extmod/machine_pwm.h b/extmod/machine_pwm.h
new file mode 100644
index 0000000000..f0953014ca
--- /dev/null
+++ b/extmod/machine_pwm.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H
+#define MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H
+
+#include "py/obj.h"
+
+// A port must provide this type, but it's otherwise opaque.
+typedef struct _machine_pwm_obj_t machine_pwm_obj_t;
+
+// This PWM class is implemented by machine_pwm.c.
+extern const mp_obj_type_t machine_pwm_type;
+
+// A port must provide implementations of these low-level PWM functions, either as global
+// linker symbols, or included directly if MICROPY_PY_MACHINE_PWM_INCLUDEFILE is defined.
+#ifndef MICROPY_PY_MACHINE_PWM_INCLUDEFILE
+void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
+mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
+void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
+void mp_machine_pwm_deinit(machine_pwm_obj_t *self);
+mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self);
+void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq);
+mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self);
+void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty);
+mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self);
+void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16);
+mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self);
+void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns);
+#endif
+
+#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H
diff --git a/ports/esp32/machine_pwm.c b/ports/esp32/machine_pwm.c
index a7d7d29df8..9fe06aa699 100644
--- a/ports/esp32/machine_pwm.c
+++ b/ports/esp32/machine_pwm.c
@@ -23,24 +23,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include <stdio.h>
-#include "driver/ledc.h"
-#include "esp_err.h"
-#include "py/nlr.h"
#include "py/runtime.h"
-#include "modmachine.h"
-#include "mphalport.h"
+#include "py/mphal.h"
-// Forward dec'l
-extern const mp_obj_type_t machine_pwm_type;
-
-typedef struct _esp32_pwm_obj_t {
- mp_obj_base_t base;
- gpio_num_t pin;
- uint8_t active;
- uint8_t channel;
-} esp32_pwm_obj_t;
+#include "driver/ledc.h"
+#include "esp_err.h"
// Which channel has which GPIO pin assigned?
// (-1 if not assigned)
@@ -110,11 +98,17 @@ STATIC int set_freq(int newval) {
}
/******************************************************************************/
-
// MicroPython bindings for PWM
-STATIC void esp32_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
+typedef struct _machine_pwm_obj_t {
+ mp_obj_base_t base;
+ gpio_num_t pin;
+ uint8_t active;
+ uint8_t channel;
+} machine_pwm_obj_t;
+
+STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "PWM(%u", self->pin);
if (self->active) {
mp_printf(print, ", freq=%u, duty=%u", timer_cfg.freq_hz,
@@ -123,7 +117,7 @@ STATIC void esp32_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
mp_printf(print, ")");
}
-STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self,
+STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self,
size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_freq, ARG_duty };
static const mp_arg_t allowed_args[] = {
@@ -192,13 +186,13 @@ STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self,
}
}
-STATIC mp_obj_t esp32_pwm_make_new(const mp_obj_type_t *type,
+STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type,
size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
gpio_num_t pin_id = machine_pin_get_id(args[0]);
// create PWM object from the given pin
- esp32_pwm_obj_t *self = m_new_obj(esp32_pwm_obj_t);
+ machine_pwm_obj_t *self = m_new_obj(machine_pwm_obj_t);
self->base.type = &machine_pwm_type;
self->pin = pin_id;
self->active = 0;
@@ -213,20 +207,12 @@ STATIC mp_obj_t esp32_pwm_make_new(const mp_obj_type_t *type,
// start the PWM running for this channel
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
- esp32_pwm_init_helper(self, n_args - 1, args + 1, &kw_args);
+ mp_machine_pwm_init_helper(self, n_args - 1, args + 1, &kw_args);
return MP_OBJ_FROM_PTR(self);
}
-STATIC mp_obj_t esp32_pwm_init(size_t n_args,
- const mp_obj_t *args, mp_map_t *kw_args) {
- esp32_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_KW(esp32_pwm_init_obj, 1, esp32_pwm_init);
-
-STATIC mp_obj_t esp32_pwm_deinit(mp_obj_t self_in) {
- esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
+STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
int chan = self->channel;
// Valid channel?
@@ -238,63 +224,27 @@ STATIC mp_obj_t esp32_pwm_deinit(mp_obj_t self_in) {
self->channel = -1;
gpio_matrix_out(self->pin, SIG_GPIO_OUT_IDX, false, false);
}
- return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_pwm_deinit_obj, esp32_pwm_deinit);
-STATIC mp_obj_t esp32_pwm_freq(size_t n_args, const mp_obj_t *args) {
- if (n_args == 1) {
- // get
- return MP_OBJ_NEW_SMALL_INT(timer_cfg.freq_hz);
- }
+STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
+ return MP_OBJ_NEW_SMALL_INT(timer_cfg.freq_hz);
+}
- // set
- int tval = mp_obj_get_int(args[1]);
- if (!set_freq(tval)) {
- mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("bad frequency %d"), tval);
+STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
+ if (!set_freq(freq)) {
+ mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("bad frequency %d"), freq);
}
- return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_pwm_freq_obj, 1, 2, esp32_pwm_freq);
-
-STATIC mp_obj_t esp32_pwm_duty(size_t n_args, const mp_obj_t *args) {
- esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- int duty;
-
- if (n_args == 1) {
- // get
- duty = ledc_get_duty(PWMODE, self->channel);
- duty <<= PWRES - timer_cfg.duty_resolution;
- return MP_OBJ_NEW_SMALL_INT(duty);
- }
+STATIC mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self) {
+ int duty = ledc_get_duty(PWMODE, self->channel);
+ duty <<= PWRES - timer_cfg.duty_resolution;
+ return MP_OBJ_NEW_SMALL_INT(duty);
+}
- // set
- duty = mp_obj_get_int(args[1]);
+STATIC void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty) {
duty &= ((1 << PWRES) - 1);
duty >>= PWRES - timer_cfg.duty_resolution;
ledc_set_duty(PWMODE, self->channel, duty);
ledc_update_duty(PWMODE, self->channel);
-
- return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_pwm_duty_obj,
- 1, 2, esp32_pwm_duty);
-
-STATIC const mp_rom_map_elem_t esp32_pwm_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&esp32_pwm_init_obj) },
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_pwm_deinit_obj) },
- { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&esp32_pwm_freq_obj) },
- { MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&esp32_pwm_duty_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(esp32_pwm_locals_dict,
- esp32_pwm_locals_dict_table);
-
-const mp_obj_type_t machine_pwm_type = {
- { &mp_type_type },
- .name = MP_QSTR_PWM,
- .print = esp32_pwm_print,
- .make_new = esp32_pwm_make_new,
- .locals_dict = (mp_obj_dict_t *)&esp32_pwm_locals_dict,
-};
diff --git a/ports/esp32/main/CMakeLists.txt b/ports/esp32/main/CMakeLists.txt
index 057ec02441..75e123f4e0 100644
--- a/ports/esp32/main/CMakeLists.txt
+++ b/ports/esp32/main/CMakeLists.txt
@@ -62,7 +62,6 @@ set(MICROPY_SOURCE_PORT
${PROJECT_DIR}/machine_dac.c
${PROJECT_DIR}/machine_i2c.c
${PROJECT_DIR}/machine_i2s.c
- ${PROJECT_DIR}/machine_pwm.c
${PROJECT_DIR}/machine_uart.c
${PROJECT_DIR}/modmachine.c
${PROJECT_DIR}/modnetwork.c
diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c
index 5f94007d49..00271a37ed 100644
--- a/ports/esp32/modmachine.c
+++ b/ports/esp32/modmachine.c
@@ -53,6 +53,7 @@
#include "extmod/machine_mem.h"
#include "extmod/machine_signal.h"
#include "extmod/machine_pulse.h"
+#include "extmod/machine_pwm.h"
#include "extmod/machine_i2c.h"
#include "extmod/machine_spi.h"
#include "modmachine.h"
diff --git a/ports/esp32/modmachine.h b/ports/esp32/modmachine.h
index 7bf03b0cab..afc2ab07f4 100644
--- a/ports/esp32/modmachine.h
+++ b/ports/esp32/modmachine.h
@@ -15,7 +15,6 @@ extern const mp_obj_type_t machine_pin_type;
extern const mp_obj_type_t machine_touchpad_type;
extern const mp_obj_type_t machine_adc_type;
extern const mp_obj_type_t machine_dac_type;
-extern const mp_obj_type_t machine_pwm_type;
extern const mp_obj_type_t machine_hw_i2c_type;
extern const mp_obj_type_t machine_hw_spi_type;
extern const mp_obj_type_t machine_i2s_type;
diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h
index b306be937d..6a48ce5023 100644
--- a/ports/esp32/mpconfigport.h
+++ b/ports/esp32/mpconfigport.h
@@ -158,6 +158,10 @@
#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_PY_MACHINE_BITSTREAM (1)
#define MICROPY_PY_MACHINE_PULSE (1)
+#define MICROPY_PY_MACHINE_PWM (1)
+#define MICROPY_PY_MACHINE_PWM_INIT (1)
+#define MICROPY_PY_MACHINE_PWM_DUTY (1)
+#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/esp32/machine_pwm.c"
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_SOFTI2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile
index 9ea4498f41..e771d8f7d3 100644
--- a/ports/esp8266/Makefile
+++ b/ports/esp8266/Makefile
@@ -96,7 +96,6 @@ SRC_C = \
modmachine.c \
machine_bitstream.c \
machine_pin.c \
- machine_pwm.c \
machine_rtc.c \
machine_adc.c \
machine_uart.c \
diff --git a/ports/esp8266/machine_pwm.c b/ports/esp8266/machine_pwm.c
index 1d6a6cfe58..f8cd937b80 100644
--- a/ports/esp8266/machine_pwm.c
+++ b/ports/esp8266/machine_pwm.c
@@ -24,28 +24,25 @@
* THE SOFTWARE.
*/
-#include <stdio.h>
-#include <stdint.h>
-
-#include "esppwm.h"
-
#include "py/runtime.h"
#include "modmachine.h"
-typedef struct _pyb_pwm_obj_t {
+#include "esppwm.h"
+
+typedef struct _machine_pwm_obj_t {
mp_obj_base_t base;
pyb_pin_obj_t *pin;
uint8_t active;
uint8_t channel;
-} pyb_pwm_obj_t;
+} machine_pwm_obj_t;
STATIC bool pwm_inited = false;
/******************************************************************************/
// MicroPython bindings for PWM
-STATIC void pyb_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
+STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "PWM(%u", self->pin->phys_port);
if (self->active) {
mp_printf(print, ", freq=%u, duty=%u",
@@ -54,7 +51,7 @@ STATIC void pyb_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
mp_printf(print, ")");
}
-STATIC void pyb_pwm_init_helper(pyb_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_freq, ARG_duty };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} },
@@ -80,13 +77,13 @@ STATIC void pyb_pwm_init_helper(pyb_pwm_obj_t *self, size_t n_args, const mp_obj
pwm_start();
}
-STATIC mp_obj_t pyb_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
pyb_pin_obj_t *pin = mp_obj_get_pin_obj(args[0]);
// create PWM object from the given pin
- pyb_pwm_obj_t *self = m_new_obj(pyb_pwm_obj_t);
- self->base.type = &pyb_pwm_type;
+ machine_pwm_obj_t *self = m_new_obj(machine_pwm_obj_t);
+ self->base.type = &machine_pwm_type;
self->pin = pin;
self->active = 0;
self->channel = -1;
@@ -100,71 +97,39 @@ STATIC mp_obj_t pyb_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_
// start the PWM running for this channel
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
- pyb_pwm_init_helper(self, n_args - 1, args + 1, &kw_args);
+ mp_machine_pwm_init_helper(self, n_args - 1, args + 1, &kw_args);
return MP_OBJ_FROM_PTR(self);
}
-STATIC mp_obj_t pyb_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
- pyb_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);
- return mp_const_none;
-}
-MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pwm_init_obj, 1, pyb_pwm_init);
-
-STATIC mp_obj_t pyb_pwm_deinit(mp_obj_t self_in) {
- pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
+STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
pwm_delete(self->channel);
self->active = 0;
pwm_start();
- return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pwm_deinit_obj, pyb_pwm_deinit);
-
-STATIC mp_obj_t pyb_pwm_freq(size_t n_args, const mp_obj_t *args) {
- // pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
- if (n_args == 1) {
- // get
- return MP_OBJ_NEW_SMALL_INT(pwm_get_freq(0));
- } else {
- // set
- pwm_set_freq(mp_obj_get_int(args[1]), 0);
- pwm_start();
- return mp_const_none;
- }
+
+STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
+ return MP_OBJ_NEW_SMALL_INT(pwm_get_freq(0));
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pwm_freq_obj, 1, 2, pyb_pwm_freq);
-STATIC mp_obj_t pyb_pwm_duty(size_t n_args, const mp_obj_t *args) {
- pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
+ pwm_set_freq(freq, 0);
+ pwm_start();
+}
+
+STATIC mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self) {
if (!self->active) {
pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func);
self->active = 1;
}
- if (n_args == 1) {
- // get
- return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel));
- } else {
- // set
- pwm_set_duty(mp_obj_get_int(args[1]), self->channel);
- pwm_start();
- return mp_const_none;
+ return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel));
+}
+
+STATIC void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty) {
+ if (!self->active) {
+ pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func);
+ self->active = 1;
}
+ pwm_set_duty(duty, self->channel);
+ pwm_start();
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pwm_duty_obj, 1, 2, pyb_pwm_duty);
-
-STATIC const mp_rom_map_elem_t pyb_pwm_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_pwm_init_obj) },
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_pwm_deinit_obj) },
- { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_pwm_freq_obj) },
- { MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&pyb_pwm_duty_obj) },
-};
-
-STATIC MP_DEFINE_CONST_DICT(pyb_pwm_locals_dict, pyb_pwm_locals_dict_table);
-
-const mp_obj_type_t pyb_pwm_type = {
- { &mp_type_type },
- .name = MP_QSTR_PWM,
- .print = pyb_pwm_print,
- .make_new = pyb_pwm_make_new,
- .locals_dict = (mp_obj_dict_t *)&pyb_pwm_locals_dict,
-};
diff --git a/ports/esp8266/modmachine.c b/ports/esp8266/modmachine.c
index 6cd4583431..39a890f56f 100644
--- a/ports/esp8266/modmachine.c
+++ b/ports/esp8266/modmachine.c
@@ -39,6 +39,7 @@
#include "extmod/machine_mem.h"
#include "extmod/machine_signal.h"
#include "extmod/machine_pulse.h"
+#include "extmod/machine_pwm.h"
#include "extmod/machine_i2c.h"
#include "extmod/machine_spi.h"
#include "modmachine.h"
@@ -423,7 +424,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&esp_wdt_type) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pyb_pin_type) },
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
- { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pyb_pwm_type) },
+ { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
#if MICROPY_PY_MACHINE_I2C
diff --git a/ports/esp8266/modmachine.h b/ports/esp8266/modmachine.h
index be4debd335..4a73d3b8e8 100644
--- a/ports/esp8266/modmachine.h
+++ b/ports/esp8266/modmachine.h
@@ -4,7 +4,6 @@
#include "py/obj.h"
extern const mp_obj_type_t pyb_pin_type;
-extern const mp_obj_type_t pyb_pwm_type;
extern const mp_obj_type_t machine_adc_type;
extern const mp_obj_type_t pyb_rtc_type;
extern const mp_obj_type_t pyb_uart_type;
diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h
index 78263efec5..7d6d0a34c3 100644
--- a/ports/esp8266/mpconfigport.h
+++ b/ports/esp8266/mpconfigport.h
@@ -81,6 +81,10 @@
#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_PY_MACHINE_BITSTREAM (1)
#define MICROPY_PY_MACHINE_PULSE (1)
+#define MICROPY_PY_MACHINE_PWM (1)
+#define MICROPY_PY_MACHINE_PWM_INIT (1)
+#define MICROPY_PY_MACHINE_PWM_DUTY (1)
+#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/esp8266/machine_pwm.c"
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_SOFTI2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt
index fd7ec65e0f..2e7347fd53 100644
--- a/ports/rp2/CMakeLists.txt
+++ b/ports/rp2/CMakeLists.txt
@@ -85,7 +85,6 @@ set(MICROPY_SOURCE_PORT
machine_adc.c
machine_i2c.c
machine_pin.c
- machine_pwm.c
machine_rtc.c
machine_spi.c
machine_timer.c
@@ -113,7 +112,6 @@ set(MICROPY_SOURCE_QSTR
${PROJECT_SOURCE_DIR}/machine_adc.c
${PROJECT_SOURCE_DIR}/machine_i2c.c
${PROJECT_SOURCE_DIR}/machine_pin.c
- ${PROJECT_SOURCE_DIR}/machine_pwm.c
${PROJECT_SOURCE_DIR}/machine_rtc.c
${PROJECT_SOURCE_DIR}/machine_spi.c
${PROJECT_SOURCE_DIR}/machine_timer.c
diff --git a/ports/rp2/machine_pwm.c b/ports/rp2/machine_pwm.c
index ff40c5503f..2952a43062 100644
--- a/ports/rp2/machine_pwm.c
+++ b/ports/rp2/machine_pwm.c
@@ -34,8 +34,6 @@
/******************************************************************************/
// MicroPython bindings for machine.PWM
-const mp_obj_type_t machine_pwm_type;
-
typedef struct _machine_pwm_obj_t {
mp_obj_base_t base;
uint8_t slice;
@@ -61,13 +59,13 @@ STATIC machine_pwm_obj_t machine_pwm_obj[] = {
{{&machine_pwm_type}, 7, PWM_CHAN_B},
};
-STATIC void machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "<PWM slice=%u channel=%u>", self->slice, self->channel);
}
// PWM(pin)
-STATIC mp_obj_t machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
+STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
// Check number of arguments
mp_arg_check_num(n_args, n_kw, 1, 1, false);
@@ -85,113 +83,78 @@ STATIC mp_obj_t machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, s
return MP_OBJ_FROM_PTR(self);
}
-STATIC mp_obj_t machine_pwm_deinit(mp_obj_t self_in) {
- machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
+STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self) {
pwm_set_enabled(self->slice, false);
- return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pwm_deinit_obj, machine_pwm_deinit);
-// PWM.freq([value])
-STATIC mp_obj_t machine_pwm_freq(size_t n_args, const mp_obj_t *args) {
- machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self) {
uint32_t source_hz = clock_get_hz(clk_sys);
- if (n_args == 1) {
- // Get frequency.
- uint32_t div16 = pwm_hw->slice[self->slice].div;
- uint32_t top = pwm_hw->slice[self->slice].top;
- uint32_t pwm_freq = 16 * source_hz / div16 / top;
- return MP_OBJ_NEW_SMALL_INT(pwm_freq);
- } else {
- // Set the frequency, making "top" as large as possible for maximum resolution.
- // Maximum "top" is set at 65534 to be able to achieve 100% duty with 65535.
- #define TOP_MAX 65534
- mp_int_t freq = mp_obj_get_int(args[1]);
- uint32_t div16_top = 16 * source_hz / freq;
- uint32_t top = 1;
- for (;;) {
- // Try a few small prime factors to get close to the desired frequency.
- if (div16_top >= 16 * 5 && div16_top % 5 == 0 && top * 5 <= TOP_MAX) {
- div16_top /= 5;
- top *= 5;
- } else if (div16_top >= 16 * 3 && div16_top % 3 == 0 && top * 3 <= TOP_MAX) {
- div16_top /= 3;
- top *= 3;
- } else if (div16_top >= 16 * 2 && top * 2 <= TOP_MAX) {
- div16_top /= 2;
- top *= 2;
- } else {
- break;
- }
- }
- if (div16_top < 16) {
- mp_raise_ValueError(MP_ERROR_TEXT("freq too large"));
- } else if (div16_top >= 256 * 16) {
- mp_raise_ValueError(MP_ERROR_TEXT("freq too small"));
+ uint32_t div16 = pwm_hw->slice[self->slice].div;
+ uint32_t top = pwm_hw->slice[self->slice].top;
+ uint32_t pwm_freq = 16 * source_hz / div16 / top;
+ return MP_OBJ_NEW_SMALL_INT(pwm_freq);
+}
+
+STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq) {
+ // Set the frequency, making "top" as large as possible for maximum resolution.
+ // Maximum "top" is set at 65534 to be able to achieve 100% duty with 65535.
+ #define TOP_MAX 65534
+ uint32_t source_hz = clock_get_hz(clk_sys);
+ uint32_t div16_top = 16 * source_hz / freq;
+ uint32_t top = 1;
+ for (;;) {
+ // Try a few small prime factors to get close to the desired frequency.
+ if (div16_top >= 16 * 5 && div16_top % 5 == 0 && top * 5 <= TOP_MAX) {
+ div16_top /= 5;
+ top *= 5;
+ } else if (div16_top >= 16 * 3 && div16_top % 3 == 0 && top * 3 <= TOP_MAX) {
+ div16_top /= 3;
+ top *= 3;
+ } else if (div16_top >= 16 * 2 && top * 2 <= TOP_MAX) {
+ div16_top /= 2;
+ top *= 2;
+ } else {
+ break;
}
- pwm_hw->slice[self->slice].div = div16_top;
- pwm_hw->slice[self->slice].top = top;
- return mp_const_none;
}
+ if (div16_top < 16) {
+ mp_raise_ValueError(MP_ERROR_TEXT("freq too large"));
+ } else if (div16_top >= 256 * 16) {
+ mp_raise_ValueError(MP_ERROR_TEXT("freq too small"));
+ }
+ pwm_hw->slice[self->slice].div = div16_top;
+ pwm_hw->slice[self->slice].top = top;
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_freq_obj, 1, 2, machine_pwm_freq);
-// PWM.duty_u16([value])
-STATIC mp_obj_t machine_pwm_duty_u16(size_t n_args, const mp_obj_t *args) {
- machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+STATIC mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self) {
uint32_t top = pwm_hw->slice[self->slice].top;
- if (n_args == 1) {
- // Get duty cycle.
- uint32_t cc = pwm_hw->slice[self->slice].cc;
- cc = (cc >> (self->channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB)) & 0xffff;
- return MP_OBJ_NEW_SMALL_INT(cc * 65535 / (top + 1));
- } else {
- // Set duty cycle.
- mp_int_t duty_u16 = mp_obj_get_int(args[1]);
- uint32_t cc = duty_u16 * (top + 1) / 65535;
- pwm_set_chan_level(self->slice, self->channel, cc);
- pwm_set_enabled(self->slice, true);
- return mp_const_none;
- }
+ uint32_t cc = pwm_hw->slice[self->slice].cc;
+ cc = (cc >> (self->channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB)) & 0xffff;
+ return MP_OBJ_NEW_SMALL_INT(cc * 65535 / (top + 1));
+}
+
+STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16) {
+ uint32_t top = pwm_hw->slice[self->slice].top;
+ uint32_t cc = duty_u16 * (top + 1) / 65535;
+ pwm_set_chan_level(self->slice, self->channel, cc);
+ pwm_set_enabled(self->slice, true);
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_u16_obj, 1, 2, machine_pwm_duty_u16);
-// PWM.duty_ns([value])
-STATIC mp_obj_t machine_pwm_duty_ns(size_t n_args, const mp_obj_t *args) {
- machine_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
+STATIC mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self) {
uint32_t source_hz = clock_get_hz(clk_sys);
uint32_t slice_hz = 16 * source_hz / pwm_hw->slice[self->slice].div;
- if (n_args == 1) {
- // Get duty cycle.
- uint32_t cc = pwm_hw->slice[self->slice].cc;
- cc = (cc >> (self->channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB)) & 0xffff;
- return MP_OBJ_NEW_SMALL_INT((uint64_t)cc * 1000000000ULL / slice_hz);
- } else {
- // Set duty cycle.
- mp_int_t duty_ns = mp_obj_get_int(args[1]);
- uint32_t cc = (uint64_t)duty_ns * slice_hz / 1000000000ULL;
- if (cc > 65535) {
- mp_raise_ValueError(MP_ERROR_TEXT("duty larger than period"));
- }
- pwm_set_chan_level(self->slice, self->channel, cc);
- pwm_set_enabled(self->slice, true);
- return mp_const_none;
- }
+ uint32_t cc = pwm_hw->slice[self->slice].cc;
+ cc = (cc >> (self->channel ? PWM_CH0_CC_B_LSB : PWM_CH0_CC_A_LSB)) & 0xffff;
+ return MP_OBJ_NEW_SMALL_INT((uint64_t)cc * 1000000000ULL / slice_hz);
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pwm_duty_ns_obj, 1, 2, machine_pwm_duty_ns);
-STATIC const mp_rom_map_elem_t machine_pwm_locals_dict_table[] = {
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_pwm_deinit_obj) },
- { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_pwm_freq_obj) },
- { MP_ROM_QSTR(MP_QSTR_duty_u16), MP_ROM_PTR(&machine_pwm_duty_u16_obj) },
- { MP_ROM_QSTR(MP_QSTR_duty_ns), MP_ROM_PTR(&machine_pwm_duty_ns_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(machine_pwm_locals_dict, machine_pwm_locals_dict_table);
-
-const mp_obj_type_t machine_pwm_type = {
- { &mp_type_type },
- .name = MP_QSTR_PWM,
- .print = machine_pwm_print,
- .make_new = machine_pwm_make_new,
- .locals_dict = (mp_obj_dict_t *)&machine_pwm_locals_dict,
-};
+STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns) {
+ uint32_t source_hz = clock_get_hz(clk_sys);
+ uint32_t slice_hz = 16 * source_hz / pwm_hw->slice[self->slice].div;
+ uint32_t cc = (uint64_t)duty_ns * slice_hz / 1000000000ULL;
+ if (cc > 65535) {
+ mp_raise_ValueError(MP_ERROR_TEXT("duty larger than period"));
+ }
+ pwm_set_chan_level(self->slice, self->channel, cc);
+ pwm_set_enabled(self->slice, true);
+}
diff --git a/ports/rp2/modmachine.c b/ports/rp2/modmachine.c
index 1b2b2adad7..32dc3d22cc 100644
--- a/ports/rp2/modmachine.c
+++ b/ports/rp2/modmachine.c
@@ -30,6 +30,7 @@
#include "extmod/machine_i2c.h"
#include "extmod/machine_mem.h"
#include "extmod/machine_pulse.h"
+#include "extmod/machine_pwm.h"
#include "extmod/machine_signal.h"
#include "extmod/machine_spi.h"
diff --git a/ports/rp2/modmachine.h b/ports/rp2/modmachine.h
index c79bcfdad1..0c48565299 100644
--- a/ports/rp2/modmachine.h
+++ b/ports/rp2/modmachine.h
@@ -6,7 +6,6 @@
extern const mp_obj_type_t machine_adc_type;
extern const mp_obj_type_t machine_hw_i2c_type;
extern const mp_obj_type_t machine_pin_type;
-extern const mp_obj_type_t machine_pwm_type;
extern const mp_obj_type_t machine_rtc_type;
extern const mp_obj_type_t machine_spi_type;
extern const mp_obj_type_t machine_timer_type;
diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h
index 4da34cd038..dea3775a85 100644
--- a/ports/rp2/mpconfigport.h
+++ b/ports/rp2/mpconfigport.h
@@ -131,6 +131,9 @@
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_PY_MACHINE_PULSE (1)
+#define MICROPY_PY_MACHINE_PWM (1)
+#define MICROPY_PY_MACHINE_PWM_DUTY_U16_NS (1)
+#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/rp2/machine_pwm.c"
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_SOFTI2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
diff --git a/py/py.mk b/py/py.mk
index 609ba6cae3..be8296e5e8 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -189,6 +189,7 @@ PY_EXTMOD_O_BASENAME = \
extmod/machine_pinbase.o \
extmod/machine_signal.o \
extmod/machine_pulse.o \
+ extmod/machine_pwm.o \
extmod/machine_i2c.o \
extmod/machine_spi.o \
extmod/modbluetooth.o \