|
29 | 29 | #include "shared-bindings/pulseio/PWMOut.h" |
30 | 30 | #include "py/runtime.h" |
31 | 31 |
|
32 | | -// STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) { |
33 | | -// } |
| 32 | +// Requires rmt.c void esp32s2_peripherals_reset_all(void) to reset |
34 | 33 |
|
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) { |
37 | 37 |
|
38 | | -// STATIC void start_timer(void) { |
39 | | -// } |
| 38 | + rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt(); |
40 | 39 |
|
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; |
43 | 46 |
|
44 | | -void pulseout_reset() { |
45 | | -} |
| 47 | + rmt_config(&config); |
| 48 | + rmt_driver_install(channel, 0, 0); |
46 | 49 |
|
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; |
50 | 51 | } |
51 | 52 |
|
52 | 53 | bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) { |
53 | | - return false; |
| 54 | + return (self->channel == RMT_CHANNEL_MAX); |
54 | 55 | } |
55 | 56 |
|
56 | 57 | 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 | + |
57 | 61 | } |
58 | 62 |
|
59 | 63 | 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)); |
60 | 80 | } |
0 commit comments