diff options
| author | Lucian Copeland <hierophect@gmail.com> | 2020-08-04 10:59:05 -0400 |
|---|---|---|
| committer | Lucian Copeland <hierophect@gmail.com> | 2020-08-14 12:21:41 -0400 |
| commit | f9512983ff0c63a719d7708496e1a827a2ca8a64 (patch) | |
| tree | ad4348994c8ff40faa4ea733940fc75195d78af5 | |
| parent | 98469322b7d35748f0f2cb03cc5bd4d470ea6339 (diff) | |
Add PulseOut
| -rw-r--r-- | ports/esp32s2/common-hal/pulseio/PulseOut.c | 48 | ||||
| -rw-r--r-- | ports/esp32s2/common-hal/pulseio/PulseOut.h | 6 | ||||
| -rw-r--r-- | ports/esp32s2/mpconfigport.h | 13 | ||||
| -rw-r--r-- | ports/esp32s2/peripherals/rmt.c | 8 | ||||
| -rw-r--r-- | ports/esp32s2/peripherals/rmt.h | 1 | ||||
| -rw-r--r-- | ports/esp32s2/supervisor/port.c | 3 | ||||
| -rw-r--r-- | shared-bindings/pulseio/PulseOut.c | 26 | ||||
| -rw-r--r-- | shared-bindings/pulseio/PulseOut.h | 6 |
8 files changed, 82 insertions, 29 deletions
diff --git a/ports/esp32s2/common-hal/pulseio/PulseOut.c b/ports/esp32s2/common-hal/pulseio/PulseOut.c index c448c578d..dc93d7e96 100644 --- a/ports/esp32s2/common-hal/pulseio/PulseOut.c +++ b/ports/esp32s2/common-hal/pulseio/PulseOut.c @@ -29,32 +29,52 @@ #include "shared-bindings/pulseio/PWMOut.h" #include "py/runtime.h" -// STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) { -// } +// Requires rmt.c void esp32s2_peripherals_reset_all(void) to reset -// STATIC void turn_off(pulseio_pulseout_obj_t *pulseout) { -// } +void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self, + const mcu_pin_obj_t* pin, + uint32_t frequency) { -// STATIC void start_timer(void) { -// } + rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt(); -// STATIC void pulseout_event_handler(void) { -// } + // Configure Channel + rmt_config_t config = RMT_DEFAULT_CONFIG_TX(pin->number, channel); + config.tx_config.carrier_en = true; + config.tx_config.carrier_duty_percent = 50; + config.tx_config.carrier_freq_hz = frequency; + config.clk_div = 80; -void pulseout_reset() { -} + rmt_config(&config); + rmt_driver_install(channel, 0, 0); -void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self, - const pulseio_pwmout_obj_t* carrier) { - mp_raise_NotImplementedError(translate("PulseOut not supported on this chip")); + self->channel = channel; } bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) { - return false; + return (self->channel == RMT_CHANNEL_MAX); } void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self) { + esp32s2_peripherals_free_rmt(self->channel); + self->channel = RMT_CHANNEL_MAX; + } void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pulses, uint16_t length) { + rmt_item32_t items[length]; + + // Circuitpython allows 16 bit pulse values, while ESP32 only allows 15 bits + // Thus, we use entire items for one pulse, rather than switching inside each item + for (size_t i = 0; i < length; i++) { + // Setting the RMT duration to 0 has undefined behavior, so avoid that pre-emptively. + if (pulses[i] == 0) { + pulses[i] = 1; + } + uint32_t level = (i % 2) ? 0 : 1; + const rmt_item32_t item = {{{ (pulses[i] & 0x8000 ? 0x7FFF : 1), level, (pulses[i] & 0x7FFF), level}}}; + items[i] = item; + } + + rmt_write_items(self->channel, items, length, true); + rmt_wait_tx_done(self->channel, pdMS_TO_TICKS(100)); } diff --git a/ports/esp32s2/common-hal/pulseio/PulseOut.h b/ports/esp32s2/common-hal/pulseio/PulseOut.h index f465d0079..513905992 100644 --- a/ports/esp32s2/common-hal/pulseio/PulseOut.h +++ b/ports/esp32s2/common-hal/pulseio/PulseOut.h @@ -29,14 +29,14 @@ #include "common-hal/microcontroller/Pin.h" #include "common-hal/pulseio/PWMOut.h" +#include "driver/rmt.h" +#include "rmt.h" #include "py/obj.h" typedef struct { mp_obj_base_t base; - pulseio_pwmout_obj_t *pwmout; + rmt_channel_t channel; } pulseio_pulseout_obj_t; -void pulseout_reset(void); - #endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_PULSEIO_PULSEOUT_H diff --git a/ports/esp32s2/mpconfigport.h b/ports/esp32s2/mpconfigport.h index d340bb480..6b070afea 100644 --- a/ports/esp32s2/mpconfigport.h +++ b/ports/esp32s2/mpconfigport.h @@ -28,19 +28,20 @@ #ifndef ESP32S2_MPCONFIGPORT_H__ #define ESP32S2_MPCONFIGPORT_H__ -#define CIRCUITPY_INTERNAL_NVM_SIZE (0) -#define MICROPY_NLR_THUMB (0) +#define CIRCUITPY_INTERNAL_NVM_SIZE (0) +#define MICROPY_NLR_THUMB (0) -#define MICROPY_PY_UJSON (0) -#define MICROPY_USE_INTERNAL_PRINTF (0) +#define MICROPY_PY_UJSON (0) +#define MICROPY_USE_INTERNAL_PRINTF (0) #include "py/circuitpy_mpconfig.h" +#define CPY_PULSEOUT_USES_DIGITALIO (1) #define MICROPY_PORT_ROOT_POINTERS \ CIRCUITPY_COMMON_ROOT_POINTERS -#define MICROPY_NLR_SETJMP (1) -#define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000 +#define MICROPY_NLR_SETJMP (1) +#define CIRCUITPY_DEFAULT_STACK_SIZE (0x6000) #endif // __INCLUDED_ESP32S2_MPCONFIGPORT_H diff --git a/ports/esp32s2/peripherals/rmt.c b/ports/esp32s2/peripherals/rmt.c index f17957c1c..16605edf5 100644 --- a/ports/esp32s2/peripherals/rmt.c +++ b/ports/esp32s2/peripherals/rmt.c @@ -29,6 +29,14 @@ bool rmt_reserved_channels[RMT_CHANNEL_MAX]; +void esp32s2_peripherals_rmt_reset(void) { + for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) { + if (rmt_reserved_channels[i]) { + esp32s2_peripherals_free_rmt(i); + } + } +} + rmt_channel_t esp32s2_peripherals_find_and_reserve_rmt(void) { for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) { if (!rmt_reserved_channels[i]) { diff --git a/ports/esp32s2/peripherals/rmt.h b/ports/esp32s2/peripherals/rmt.h index 4741a5bc5..01ed09907 100644 --- a/ports/esp32s2/peripherals/rmt.h +++ b/ports/esp32s2/peripherals/rmt.h @@ -31,6 +31,7 @@ #include "driver/rmt.h" #include <stdint.h> +void esp32s2_peripherals_rmt_reset(void); rmt_channel_t esp32s2_peripherals_find_and_reserve_rmt(void); void esp32s2_peripherals_free_rmt(rmt_channel_t chan); diff --git a/ports/esp32s2/supervisor/port.c b/ports/esp32s2/supervisor/port.c index e4767e514..d287079b7 100644 --- a/ports/esp32s2/supervisor/port.c +++ b/ports/esp32s2/supervisor/port.c @@ -42,6 +42,8 @@ #include "supervisor/memory.h" #include "supervisor/shared/tick.h" +#include "rmt.h" + STATIC esp_timer_handle_t _tick_timer; void tick_timer_cb(void* arg) { @@ -66,6 +68,7 @@ void reset_port(void) { vTaskDelay(4); #if CIRCUITPY_PULSEIO + esp32s2_peripherals_rmt_reset(); pwmout_reset(); #endif #if CIRCUITPY_BUSIO diff --git a/shared-bindings/pulseio/PulseOut.c b/shared-bindings/pulseio/PulseOut.c index 3d35f0544..10524f51b 100644 --- a/shared-bindings/pulseio/PulseOut.c +++ b/shared-bindings/pulseio/PulseOut.c @@ -64,19 +64,33 @@ //| pulse.send(pulses)""" //| ... //| -STATIC mp_obj_t pulseio_pulseout_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { +STATIC mp_obj_t pulseio_pulseout_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + + pulseio_pulseout_obj_t *self = m_new_obj(pulseio_pulseout_obj_t); + self->base.type = &pulseio_pulseout_type; + + #ifndef CPY_PULSEOUT_USES_DIGITALIO + // Most ports pass a PWMOut mp_arg_check_num(n_args, kw_args, 1, 1, false); mp_obj_t carrier_obj = args[0]; - if (!MP_OBJ_IS_TYPE(carrier_obj, &pulseio_pwmout_type)) { mp_raise_TypeError_varg(translate("Expected a %q"), pulseio_pwmout_type.name); } + common_hal_pulseio_pulseout_construct(self, (pulseio_pwmout_obj_t *)MP_OBJ_TO_PTR(carrier_obj)); + #else + // ESP32-S2 Special Case + enum { ARG_pin, ARG_frequency}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 38000} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - // create Pulse object from the given pin - pulseio_pulseout_obj_t *self = m_new_obj(pulseio_pulseout_obj_t); - self->base.type = &pulseio_pulseout_type; + const mcu_pin_obj_t* pin = validate_obj_is_free_pin(args[ARG_pin].u_obj); - common_hal_pulseio_pulseout_construct(self, (pulseio_pwmout_obj_t *)MP_OBJ_TO_PTR(carrier_obj)); + common_hal_pulseio_pulseout_construct(self, pin, args[ARG_frequency].u_int); + #endif return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/pulseio/PulseOut.h b/shared-bindings/pulseio/PulseOut.h index 390910ff6..090f6d15c 100644 --- a/shared-bindings/pulseio/PulseOut.h +++ b/shared-bindings/pulseio/PulseOut.h @@ -33,8 +33,14 @@ extern const mp_obj_type_t pulseio_pulseout_type; +#ifndef CPY_PULSEOUT_USES_DIGITALIO extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self, const pulseio_pwmout_obj_t* carrier); +#else +extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self, + const mcu_pin_obj_t* pin, uint32_t frequency); +#endif + extern void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self); extern bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self); extern void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, |
