Skip to content

Commit f951298

Browse files
committed
Add PulseOut
1 parent 9846932 commit f951298

File tree

8 files changed

+82
-29
lines changed

8 files changed

+82
-29
lines changed

ports/esp32s2/common-hal/pulseio/PulseOut.c

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,32 +29,52 @@
2929
#include "shared-bindings/pulseio/PWMOut.h"
3030
#include "py/runtime.h"
3131

32-
// STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) {
33-
// }
32+
// Requires rmt.c void esp32s2_peripherals_reset_all(void) to reset
3433

35-
// STATIC void turn_off(pulseio_pulseout_obj_t *pulseout) {
36-
// }
34+
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
35+
const mcu_pin_obj_t* pin,
36+
uint32_t frequency) {
3737

38-
// STATIC void start_timer(void) {
39-
// }
38+
rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt();
4039

41-
// STATIC void pulseout_event_handler(void) {
42-
// }
40+
// Configure Channel
41+
rmt_config_t config = RMT_DEFAULT_CONFIG_TX(pin->number, channel);
42+
config.tx_config.carrier_en = true;
43+
config.tx_config.carrier_duty_percent = 50;
44+
config.tx_config.carrier_freq_hz = frequency;
45+
config.clk_div = 80;
4346

44-
void pulseout_reset() {
45-
}
47+
rmt_config(&config);
48+
rmt_driver_install(channel, 0, 0);
4649

47-
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
48-
const pulseio_pwmout_obj_t* carrier) {
49-
mp_raise_NotImplementedError(translate("PulseOut not supported on this chip"));
50+
self->channel = channel;
5051
}
5152

5253
bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) {
53-
return false;
54+
return (self->channel == RMT_CHANNEL_MAX);
5455
}
5556

5657
void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self) {
58+
esp32s2_peripherals_free_rmt(self->channel);
59+
self->channel = RMT_CHANNEL_MAX;
60+
5761
}
5862

5963
void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pulses, uint16_t length) {
64+
rmt_item32_t items[length];
65+
66+
// Circuitpython allows 16 bit pulse values, while ESP32 only allows 15 bits
67+
// Thus, we use entire items for one pulse, rather than switching inside each item
68+
for (size_t i = 0; i < length; i++) {
69+
// Setting the RMT duration to 0 has undefined behavior, so avoid that pre-emptively.
70+
if (pulses[i] == 0) {
71+
pulses[i] = 1;
72+
}
73+
uint32_t level = (i % 2) ? 0 : 1;
74+
const rmt_item32_t item = {{{ (pulses[i] & 0x8000 ? 0x7FFF : 1), level, (pulses[i] & 0x7FFF), level}}};
75+
items[i] = item;
76+
}
77+
78+
rmt_write_items(self->channel, items, length, true);
79+
rmt_wait_tx_done(self->channel, pdMS_TO_TICKS(100));
6080
}

ports/esp32s2/common-hal/pulseio/PulseOut.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@
2929

3030
#include "common-hal/microcontroller/Pin.h"
3131
#include "common-hal/pulseio/PWMOut.h"
32+
#include "driver/rmt.h"
33+
#include "rmt.h"
3234

3335
#include "py/obj.h"
3436

3537
typedef struct {
3638
mp_obj_base_t base;
37-
pulseio_pwmout_obj_t *pwmout;
39+
rmt_channel_t channel;
3840
} pulseio_pulseout_obj_t;
3941

40-
void pulseout_reset(void);
41-
4242
#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_PULSEIO_PULSEOUT_H

ports/esp32s2/mpconfigport.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,20 @@
2828
#ifndef ESP32S2_MPCONFIGPORT_H__
2929
#define ESP32S2_MPCONFIGPORT_H__
3030

31-
#define CIRCUITPY_INTERNAL_NVM_SIZE (0)
32-
#define MICROPY_NLR_THUMB (0)
31+
#define CIRCUITPY_INTERNAL_NVM_SIZE (0)
32+
#define MICROPY_NLR_THUMB (0)
3333

34-
#define MICROPY_PY_UJSON (0)
35-
#define MICROPY_USE_INTERNAL_PRINTF (0)
34+
#define MICROPY_PY_UJSON (0)
35+
#define MICROPY_USE_INTERNAL_PRINTF (0)
3636

3737
#include "py/circuitpy_mpconfig.h"
3838

39+
#define CPY_PULSEOUT_USES_DIGITALIO (1)
3940

4041
#define MICROPY_PORT_ROOT_POINTERS \
4142
CIRCUITPY_COMMON_ROOT_POINTERS
42-
#define MICROPY_NLR_SETJMP (1)
43-
#define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000
43+
#define MICROPY_NLR_SETJMP (1)
44+
#define CIRCUITPY_DEFAULT_STACK_SIZE (0x6000)
4445

4546

4647
#endif // __INCLUDED_ESP32S2_MPCONFIGPORT_H

ports/esp32s2/peripherals/rmt.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@
2929

3030
bool rmt_reserved_channels[RMT_CHANNEL_MAX];
3131

32+
void esp32s2_peripherals_rmt_reset(void) {
33+
for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) {
34+
if (rmt_reserved_channels[i]) {
35+
esp32s2_peripherals_free_rmt(i);
36+
}
37+
}
38+
}
39+
3240
rmt_channel_t esp32s2_peripherals_find_and_reserve_rmt(void) {
3341
for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) {
3442
if (!rmt_reserved_channels[i]) {

ports/esp32s2/peripherals/rmt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "driver/rmt.h"
3232
#include <stdint.h>
3333

34+
void esp32s2_peripherals_rmt_reset(void);
3435
rmt_channel_t esp32s2_peripherals_find_and_reserve_rmt(void);
3536
void esp32s2_peripherals_free_rmt(rmt_channel_t chan);
3637

ports/esp32s2/supervisor/port.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
#include "supervisor/memory.h"
4343
#include "supervisor/shared/tick.h"
4444

45+
#include "rmt.h"
46+
4547
STATIC esp_timer_handle_t _tick_timer;
4648

4749
void tick_timer_cb(void* arg) {
@@ -66,6 +68,7 @@ void reset_port(void) {
6668
vTaskDelay(4);
6769

6870
#if CIRCUITPY_PULSEIO
71+
esp32s2_peripherals_rmt_reset();
6972
pwmout_reset();
7073
#endif
7174
#if CIRCUITPY_BUSIO

shared-bindings/pulseio/PulseOut.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,33 @@
6464
//| pulse.send(pulses)"""
6565
//| ...
6666
//|
67-
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) {
67+
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) {
68+
69+
pulseio_pulseout_obj_t *self = m_new_obj(pulseio_pulseout_obj_t);
70+
self->base.type = &pulseio_pulseout_type;
71+
72+
#ifndef CPY_PULSEOUT_USES_DIGITALIO
73+
// Most ports pass a PWMOut
6874
mp_arg_check_num(n_args, kw_args, 1, 1, false);
6975
mp_obj_t carrier_obj = args[0];
70-
7176
if (!MP_OBJ_IS_TYPE(carrier_obj, &pulseio_pwmout_type)) {
7277
mp_raise_TypeError_varg(translate("Expected a %q"), pulseio_pwmout_type.name);
7378
}
79+
common_hal_pulseio_pulseout_construct(self, (pulseio_pwmout_obj_t *)MP_OBJ_TO_PTR(carrier_obj));
80+
#else
81+
// ESP32-S2 Special Case
82+
enum { ARG_pin, ARG_frequency};
83+
static const mp_arg_t allowed_args[] = {
84+
{ MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ },
85+
{ MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 38000} },
86+
};
87+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
88+
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
7489

75-
// create Pulse object from the given pin
76-
pulseio_pulseout_obj_t *self = m_new_obj(pulseio_pulseout_obj_t);
77-
self->base.type = &pulseio_pulseout_type;
90+
const mcu_pin_obj_t* pin = validate_obj_is_free_pin(args[ARG_pin].u_obj);
7891

79-
common_hal_pulseio_pulseout_construct(self, (pulseio_pwmout_obj_t *)MP_OBJ_TO_PTR(carrier_obj));
92+
common_hal_pulseio_pulseout_construct(self, pin, args[ARG_frequency].u_int);
93+
#endif
8094

8195
return MP_OBJ_FROM_PTR(self);
8296
}

shared-bindings/pulseio/PulseOut.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,14 @@
3333

3434
extern const mp_obj_type_t pulseio_pulseout_type;
3535

36+
#ifndef CPY_PULSEOUT_USES_DIGITALIO
3637
extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
3738
const pulseio_pwmout_obj_t* carrier);
39+
#else
40+
extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
41+
const mcu_pin_obj_t* pin, uint32_t frequency);
42+
#endif
43+
3844
extern void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self);
3945
extern bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self);
4046
extern void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self,

0 commit comments

Comments
 (0)