Add PulseOut
This commit is contained in:
parent
98469322b7
commit
f9512983ff
|
@ -29,32 +29,52 @@
|
||||||
#include "shared-bindings/pulseio/PWMOut.h"
|
#include "shared-bindings/pulseio/PWMOut.h"
|
||||||
#include "py/runtime.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) {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// STATIC void start_timer(void) {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// STATIC void pulseout_event_handler(void) {
|
|
||||||
// }
|
|
||||||
|
|
||||||
void pulseout_reset() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
|
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
|
||||||
const pulseio_pwmout_obj_t* carrier) {
|
const mcu_pin_obj_t* pin,
|
||||||
mp_raise_NotImplementedError(translate("PulseOut not supported on this chip"));
|
uint32_t frequency) {
|
||||||
|
|
||||||
|
rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt();
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
rmt_config(&config);
|
||||||
|
rmt_driver_install(channel, 0, 0);
|
||||||
|
|
||||||
|
self->channel = channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) {
|
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) {
|
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) {
|
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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,14 +29,14 @@
|
||||||
|
|
||||||
#include "common-hal/microcontroller/Pin.h"
|
#include "common-hal/microcontroller/Pin.h"
|
||||||
#include "common-hal/pulseio/PWMOut.h"
|
#include "common-hal/pulseio/PWMOut.h"
|
||||||
|
#include "driver/rmt.h"
|
||||||
|
#include "rmt.h"
|
||||||
|
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
pulseio_pwmout_obj_t *pwmout;
|
rmt_channel_t channel;
|
||||||
} pulseio_pulseout_obj_t;
|
} pulseio_pulseout_obj_t;
|
||||||
|
|
||||||
void pulseout_reset(void);
|
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_PULSEIO_PULSEOUT_H
|
#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_PULSEIO_PULSEOUT_H
|
||||||
|
|
|
@ -28,19 +28,20 @@
|
||||||
#ifndef ESP32S2_MPCONFIGPORT_H__
|
#ifndef ESP32S2_MPCONFIGPORT_H__
|
||||||
#define ESP32S2_MPCONFIGPORT_H__
|
#define ESP32S2_MPCONFIGPORT_H__
|
||||||
|
|
||||||
#define CIRCUITPY_INTERNAL_NVM_SIZE (0)
|
#define CIRCUITPY_INTERNAL_NVM_SIZE (0)
|
||||||
#define MICROPY_NLR_THUMB (0)
|
#define MICROPY_NLR_THUMB (0)
|
||||||
|
|
||||||
#define MICROPY_PY_UJSON (0)
|
#define MICROPY_PY_UJSON (0)
|
||||||
#define MICROPY_USE_INTERNAL_PRINTF (0)
|
#define MICROPY_USE_INTERNAL_PRINTF (0)
|
||||||
|
|
||||||
#include "py/circuitpy_mpconfig.h"
|
#include "py/circuitpy_mpconfig.h"
|
||||||
|
|
||||||
|
#define CPY_PULSEOUT_USES_DIGITALIO (1)
|
||||||
|
|
||||||
#define MICROPY_PORT_ROOT_POINTERS \
|
#define MICROPY_PORT_ROOT_POINTERS \
|
||||||
CIRCUITPY_COMMON_ROOT_POINTERS
|
CIRCUITPY_COMMON_ROOT_POINTERS
|
||||||
#define MICROPY_NLR_SETJMP (1)
|
#define MICROPY_NLR_SETJMP (1)
|
||||||
#define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000
|
#define CIRCUITPY_DEFAULT_STACK_SIZE (0x6000)
|
||||||
|
|
||||||
|
|
||||||
#endif // __INCLUDED_ESP32S2_MPCONFIGPORT_H
|
#endif // __INCLUDED_ESP32S2_MPCONFIGPORT_H
|
||||||
|
|
|
@ -29,6 +29,14 @@
|
||||||
|
|
||||||
bool rmt_reserved_channels[RMT_CHANNEL_MAX];
|
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) {
|
rmt_channel_t esp32s2_peripherals_find_and_reserve_rmt(void) {
|
||||||
for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) {
|
for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) {
|
||||||
if (!rmt_reserved_channels[i]) {
|
if (!rmt_reserved_channels[i]) {
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "driver/rmt.h"
|
#include "driver/rmt.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void esp32s2_peripherals_rmt_reset(void);
|
||||||
rmt_channel_t esp32s2_peripherals_find_and_reserve_rmt(void);
|
rmt_channel_t esp32s2_peripherals_find_and_reserve_rmt(void);
|
||||||
void esp32s2_peripherals_free_rmt(rmt_channel_t chan);
|
void esp32s2_peripherals_free_rmt(rmt_channel_t chan);
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
#include "supervisor/memory.h"
|
#include "supervisor/memory.h"
|
||||||
#include "supervisor/shared/tick.h"
|
#include "supervisor/shared/tick.h"
|
||||||
|
|
||||||
|
#include "rmt.h"
|
||||||
|
|
||||||
STATIC esp_timer_handle_t _tick_timer;
|
STATIC esp_timer_handle_t _tick_timer;
|
||||||
|
|
||||||
void tick_timer_cb(void* arg) {
|
void tick_timer_cb(void* arg) {
|
||||||
|
@ -66,6 +68,7 @@ void reset_port(void) {
|
||||||
vTaskDelay(4);
|
vTaskDelay(4);
|
||||||
|
|
||||||
#if CIRCUITPY_PULSEIO
|
#if CIRCUITPY_PULSEIO
|
||||||
|
esp32s2_peripherals_rmt_reset();
|
||||||
pwmout_reset();
|
pwmout_reset();
|
||||||
#endif
|
#endif
|
||||||
#if CIRCUITPY_BUSIO
|
#if CIRCUITPY_BUSIO
|
||||||
|
|
|
@ -64,19 +64,33 @@
|
||||||
//| pulse.send(pulses)"""
|
//| 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) {
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// create Pulse object from the given pin
|
|
||||||
pulseio_pulseout_obj_t *self = m_new_obj(pulseio_pulseout_obj_t);
|
pulseio_pulseout_obj_t *self = m_new_obj(pulseio_pulseout_obj_t);
|
||||||
self->base.type = &pulseio_pulseout_type;
|
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));
|
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);
|
||||||
|
|
||||||
|
const mcu_pin_obj_t* pin = validate_obj_is_free_pin(args[ARG_pin].u_obj);
|
||||||
|
|
||||||
|
common_hal_pulseio_pulseout_construct(self, pin, args[ARG_frequency].u_int);
|
||||||
|
#endif
|
||||||
|
|
||||||
return MP_OBJ_FROM_PTR(self);
|
return MP_OBJ_FROM_PTR(self);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,14 @@
|
||||||
|
|
||||||
extern const mp_obj_type_t pulseio_pulseout_type;
|
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,
|
extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
|
||||||
const pulseio_pwmout_obj_t* carrier);
|
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 void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self);
|
||||||
extern bool common_hal_pulseio_pulseout_deinited(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,
|
extern void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self,
|
||||||
|
|
Loading…
Reference in New Issue