summaryrefslogtreecommitdiff
path: root/ports
diff options
context:
space:
mode:
authorScott Shawcroft <scott@adafruit.com>2020-08-11 11:04:39 -0700
committerGitHub <noreply@github.com>2020-08-11 11:04:39 -0700
commitbbac68e77c8dac0b8b20825bbf83a09a3eaf2559 (patch)
tree12bc0d595db59efb8294cddfe766495bc2cbdb1b /ports
parentbccfb8b4cdd604fcaa41bc36851141ca751d2d79 (diff)
parent4613b58a31c8d439d92961f2034eb9f60b0d97c1 (diff)
Merge pull request #3232 from hierophect/esp32-neopixel
ESP32-S2: Add Neopixel support
Diffstat (limited to 'ports')
-rw-r--r--ports/esp32s2/Makefile1
-rw-r--r--ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.h2
-rw-r--r--ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.mk2
-rw-r--r--ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.h2
-rw-r--r--ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.mk2
-rw-r--r--ports/esp32s2/boards/espressif_saola_1_wrover/pins.c2
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk3
-rw-r--r--ports/esp32s2/common-hal/microcontroller/Pin.c33
-rw-r--r--ports/esp32s2/common-hal/microcontroller/Pin.h4
-rw-r--r--ports/esp32s2/common-hal/neopixel_write/__init__.c98
-rw-r--r--ports/esp32s2/common-hal/pulseio/PWMOut.c22
-rw-r--r--ports/esp32s2/mpconfigport.mk25
-rw-r--r--ports/esp32s2/peripherals/rmt.c46
-rw-r--r--ports/esp32s2/peripherals/rmt.h37
14 files changed, 248 insertions, 31 deletions
diff --git a/ports/esp32s2/Makefile b/ports/esp32s2/Makefile
index 55db73604..19b89a13a 100644
--- a/ports/esp32s2/Makefile
+++ b/ports/esp32s2/Makefile
@@ -171,6 +171,7 @@ SRC_C += \
lib/utils/stdout_helpers.c \
lib/utils/sys_stdio_mphal.c \
peripherals/pins.c \
+ peripherals/rmt.c \
supervisor/shared/memory.c
ifneq ($(USB),FALSE)
diff --git a/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.h b/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.h
index 78652e215..a94f10ea4 100644
--- a/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.h
+++ b/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.h
@@ -29,4 +29,6 @@
#define MICROPY_HW_BOARD_NAME "Saola 1 w/Wroom"
#define MICROPY_HW_MCU_NAME "ESP32S2"
+#define MICROPY_HW_NEOPIXEL (&pin_GPIO18)
+
#define AUTORESET_DELAY_MS 500
diff --git a/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.mk b/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.mk
index 6e7627265..9c9ca6169 100644
--- a/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.mk
+++ b/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.mk
@@ -10,8 +10,6 @@ LONGINT_IMPL = MPZ
# so increase it to 32.
CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
-CIRCUITPY_NEOPIXEL_WRITE = 0
-
CIRCUITPY_ESP_FLASH_MODE=dio
CIRCUITPY_ESP_FLASH_FREQ=40m
CIRCUITPY_ESP_FLASH_SIZE=4MB
diff --git a/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.h b/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.h
index 7d08ccf7f..338186dc5 100644
--- a/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.h
+++ b/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.h
@@ -29,4 +29,6 @@
#define MICROPY_HW_BOARD_NAME "Saola 1 w/Wrover"
#define MICROPY_HW_MCU_NAME "ESP32S2"
+#define MICROPY_HW_NEOPIXEL (&pin_GPIO18)
+
#define AUTORESET_DELAY_MS 500
diff --git a/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.mk b/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.mk
index 1437df7f4..d5ff1c5ac 100644
--- a/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.mk
+++ b/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.mk
@@ -10,8 +10,6 @@ LONGINT_IMPL = MPZ
# so increase it to 32.
CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
-CIRCUITPY_NEOPIXEL_WRITE = 0
-
CIRCUITPY_ESP_FLASH_MODE=dio
CIRCUITPY_ESP_FLASH_FREQ=40m
CIRCUITPY_ESP_FLASH_SIZE=4MB
diff --git a/ports/esp32s2/boards/espressif_saola_1_wrover/pins.c b/ports/esp32s2/boards/espressif_saola_1_wrover/pins.c
index 1d4e2c4eb..0562d9331 100644
--- a/ports/esp32s2/boards/espressif_saola_1_wrover/pins.c
+++ b/ports/esp32s2/boards/espressif_saola_1_wrover/pins.c
@@ -42,5 +42,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) },
{ MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) },
{ MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO18) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk
index ea3484d2f..294736d17 100644
--- a/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk
+++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk
@@ -4,7 +4,6 @@ USB_PRODUCT = "FeatherS2"
USB_MANUFACTURER = "UnexpectedMaker"
USB_DEVICES = "CDC,MSC,HID"
-
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = MPZ
@@ -12,8 +11,6 @@ LONGINT_IMPL = MPZ
# so increase it to 32.
CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
-CIRCUITPY_NEOPIXEL_WRITE = 0
-
CIRCUITPY_ESP_FLASH_MODE=qio
CIRCUITPY_ESP_FLASH_FREQ=40m
CIRCUITPY_ESP_FLASH_SIZE=16MB
diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.c b/ports/esp32s2/common-hal/microcontroller/Pin.c
index 5a059f0bb..03a83cfe6 100644
--- a/ports/esp32s2/common-hal/microcontroller/Pin.c
+++ b/ports/esp32s2/common-hal/microcontroller/Pin.c
@@ -26,12 +26,18 @@
*/
#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "supervisor/shared/rgb_led_status.h"
#include "py/mphal.h"
#include "esp-idf/components/driver/include/driver/gpio.h"
#include "esp-idf/components/soc/include/hal/gpio_hal.h"
+#ifdef MICROPY_HW_NEOPIXEL
+bool neopixel_in_use;
+#endif
+
STATIC uint32_t never_reset_pins[2];
STATIC uint32_t in_use[2];
@@ -50,6 +56,14 @@ void common_hal_never_reset_pin(const mcu_pin_obj_t* pin) {
void reset_pin_number(gpio_num_t pin_number) {
never_reset_pins[pin_number / 32] &= ~(1 << pin_number % 32);
in_use[pin_number / 32] &= ~(1 << pin_number % 32);
+
+ #ifdef MICROPY_HW_NEOPIXEL
+ if (pin_number == MICROPY_HW_NEOPIXEL->number) {
+ neopixel_in_use = false;
+ rgb_led_status_init();
+ return;
+ }
+ #endif
}
void common_hal_reset_pin(const mcu_pin_obj_t* pin) {
@@ -69,13 +83,32 @@ void reset_all_pins(void) {
}
in_use[0] = 0;
in_use[1] = 0;
+
+ #ifdef MICROPY_HW_NEOPIXEL
+ neopixel_in_use = false;
+ #endif
}
void claim_pin(const mcu_pin_obj_t* pin) {
in_use[pin->number / 32] |= (1 << pin->number % 32);
+ #ifdef MICROPY_HW_NEOPIXEL
+ if (pin == MICROPY_HW_NEOPIXEL) {
+ neopixel_in_use = true;
+ }
+ #endif
+}
+
+void common_hal_mcu_pin_claim(const mcu_pin_obj_t* pin) {
+ claim_pin(pin);
}
bool pin_number_is_free(gpio_num_t pin_number) {
+ #ifdef MICROPY_HW_NEOPIXEL
+ if (pin_number == MICROPY_HW_NEOPIXEL->number) {
+ return !neopixel_in_use;
+ }
+ #endif
+
uint8_t offset = pin_number / 32;
uint8_t mask = 1 << pin_number % 32;
return (never_reset_pins[offset] & mask) == 0 && (in_use[offset] & mask) == 0;
diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.h b/ports/esp32s2/common-hal/microcontroller/Pin.h
index 19985bda6..f6c008703 100644
--- a/ports/esp32s2/common-hal/microcontroller/Pin.h
+++ b/ports/esp32s2/common-hal/microcontroller/Pin.h
@@ -34,6 +34,10 @@
extern bool apa102_mosi_in_use;
extern bool apa102_sck_in_use;
+#ifdef MICROPY_HW_NEOPIXEL
+extern bool neopixel_in_use;
+#endif
+
void reset_all_pins(void);
// reset_pin_number takes the pin number instead of the pointer so that objects don't
// need to store a full pointer.
diff --git a/ports/esp32s2/common-hal/neopixel_write/__init__.c b/ports/esp32s2/common-hal/neopixel_write/__init__.c
index a9b42fc96..1fc976ec3 100644
--- a/ports/esp32s2/common-hal/neopixel_write/__init__.c
+++ b/ports/esp32s2/common-hal/neopixel_write/__init__.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2018 hathach for Adafruit Industries
+ * Copyright (c) 2020 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,10 +24,102 @@
* THE SOFTWARE.
*/
+/* Uses code from Espressif RGB LED Strip demo and drivers
+ * Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include "py/mphal.h"
+#include "py/runtime.h"
#include "shared-bindings/neopixel_write/__init__.h"
+#include "driver/rmt.h"
+#include "rmt.h"
+
+#define WS2812_T0H_NS (350)
+#define WS2812_T0L_NS (1000)
+#define WS2812_T1H_NS (1000)
+#define WS2812_T1L_NS (350)
+#define WS2812_RESET_US (280)
+
+static uint32_t ws2812_t0h_ticks = 0;
+static uint32_t ws2812_t1h_ticks = 0;
+static uint32_t ws2812_t0l_ticks = 0;
+static uint32_t ws2812_t1l_ticks = 0;
+
+static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size,
+ size_t wanted_num, size_t *translated_size, size_t *item_num)
+{
+ if (src == NULL || dest == NULL) {
+ *translated_size = 0;
+ *item_num = 0;
+ return;
+ }
+ const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0
+ const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1
+ size_t size = 0;
+ size_t num = 0;
+ uint8_t *psrc = (uint8_t *)src;
+ rmt_item32_t *pdest = dest;
+ while (size < src_size && num < wanted_num) {
+ for (int i = 0; i < 8; i++) {
+ // MSB first
+ if (*psrc & (1 << (7 - i))) {
+ pdest->val = bit1.val;
+ } else {
+ pdest->val = bit0.val;
+ }
+ num++;
+ pdest++;
+ }
+ size++;
+ psrc++;
+ }
+ *translated_size = size;
+ *item_num = num;
+}
void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout, uint8_t *pixels, uint32_t numBytes) {
- (void)digitalinout;
- (void)numBytes;
+ // Reserve channel
+ uint8_t number = digitalinout->pin->number;
+ rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt();
+
+ // Configure Channel
+ rmt_config_t config = RMT_DEFAULT_CONFIG_TX(number, channel);
+ config.clk_div = 2; // set counter clock to 40MHz
+ rmt_config(&config);
+ rmt_driver_install(config.channel, 0, 0);
+
+ // Convert NS timings to ticks
+ uint32_t counter_clk_hz = 0;
+ if (rmt_get_counter_clock(config.channel, &counter_clk_hz) != ESP_OK) {
+ mp_raise_RuntimeError(translate("Could not retrieve clock"));
+ }
+ float ratio = (float)counter_clk_hz / 1e9;
+ ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS);
+ ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS);
+ ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS);
+ ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS);
+
+ // Initialize automatic timing translator
+ rmt_translator_init(config.channel, ws2812_rmt_adapter);
+
+ // Write and wait to finish
+ if(rmt_write_sample(config.channel, pixels, (size_t)numBytes, true) != ESP_OK) {
+ mp_raise_RuntimeError(translate("Input/output error"));
+ }
+ rmt_wait_tx_done(config.channel, pdMS_TO_TICKS(100));
+
+ // Free channel again
+ esp32s2_peripherals_free_rmt(config.channel);
}
diff --git a/ports/esp32s2/common-hal/pulseio/PWMOut.c b/ports/esp32s2/common-hal/pulseio/PWMOut.c
index c4f5e18dd..0ac42852a 100644
--- a/ports/esp32s2/common-hal/pulseio/PWMOut.c
+++ b/ports/esp32s2/common-hal/pulseio/PWMOut.c
@@ -3,8 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
- * Uses code from Micropython, Copyright (c) 2013-2016 Damien P. George
+ * Copyright (c) 2020 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -33,6 +32,7 @@
#define INDEX_EMPTY 0xFF
+STATIC bool not_first_reset = false;
STATIC uint32_t reserved_timer_freq[LEDC_TIMER_MAX];
STATIC uint8_t reserved_channels[LEDC_CHANNEL_MAX];
STATIC bool never_reset_tim[LEDC_TIMER_MAX];
@@ -40,17 +40,22 @@ STATIC bool never_reset_chan[LEDC_CHANNEL_MAX];
void pwmout_reset(void) {
for (size_t i = 0; i < LEDC_CHANNEL_MAX; i++ ) {
- ledc_stop(LEDC_LOW_SPEED_MODE, i, 0);
+ if (reserved_channels[i] != INDEX_EMPTY && not_first_reset) {
+ ledc_stop(LEDC_LOW_SPEED_MODE, i, 0);
+ }
if (!never_reset_chan[i]) {
reserved_channels[i] = INDEX_EMPTY;
}
}
for (size_t i = 0; i < LEDC_TIMER_MAX; i++ ) {
- ledc_timer_rst(LEDC_LOW_SPEED_MODE, i);
+ if (reserved_timer_freq[i]) {
+ ledc_timer_rst(LEDC_LOW_SPEED_MODE, i);
+ }
if (!never_reset_tim[i]) {
reserved_timer_freq[i] = 0;
}
}
+ not_first_reset = true;
}
pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
@@ -158,7 +163,10 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
if (common_hal_pulseio_pwmout_deinited(self)) {
return;
}
- ledc_stop(LEDC_LOW_SPEED_MODE, self->chan_handle.channel, 0);
+
+ if (reserved_channels[self->chan_handle.channel] != INDEX_EMPTY) {
+ ledc_stop(LEDC_LOW_SPEED_MODE, self->chan_handle.channel, 0);
+ }
// Search if any other channel is using the timer
bool taken = false;
for (size_t i =0; i < LEDC_CHANNEL_MAX; i++) {
@@ -168,7 +176,9 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
}
// Variable frequency means there's only one channel on the timer
if (!taken || self->variable_frequency) {
- ledc_timer_rst(LEDC_LOW_SPEED_MODE, self->tim_handle.timer_num);
+ if (reserved_timer_freq[self->tim_handle.timer_num] != 0) {
+ ledc_timer_rst(LEDC_LOW_SPEED_MODE, self->tim_handle.timer_num);
+ }
reserved_timer_freq[self->tim_handle.timer_num] = 0;
}
reset_pin_number(self->pin_number);
diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk
index c2d21e084..a7873aa46 100644
--- a/ports/esp32s2/mpconfigport.mk
+++ b/ports/esp32s2/mpconfigport.mk
@@ -12,26 +12,21 @@ USB_SERIAL_NUMBER_LENGTH = 12
# Longints can be implemented as mpz, as longlong, or not
LONGINT_IMPL = MPZ
-CIRCUITPY_FULL_BUILD = 0
+# These modules are implemented in ports/<port>/common-hal:
CIRCUITPY_ANALOGIO = 0
+CIRCUITPY_NVM = 0
CIRCUITPY_AUDIOBUSIO = 0
CIRCUITPY_AUDIOIO = 0
-CIRCUITPY_BITBANGIO = 1
-CIRCUITPY_BOARD = 1
-CIRCUITPY_DIGITALIO = 1
-CIRCUITPY_BUSIO = 1
-CIRCUITPY_DISPLAYIO = 1
-CIRCUITPY_FREQUENCYIO = 0
-CIRCUITPY_I2CPERIPHERAL = 0
-CIRCUITPY_MICROCONTROLLER = 1
-CIRCUITPY_NVM = 0
-CIRCUITPY_PULSEIO = 1
CIRCUITPY_ROTARYIO = 0
CIRCUITPY_RTC = 0
-CIRCUITPY_TOUCHIO = 0
+CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_I2CPERIPHERAL = 0
+CIRCUITPY_COUNTIO = 0
-# Enable USB HID support
-CIRCUITPY_USB_HID = 1
-CIRCUITPY_USB_MIDI = 0
+# These modules are implemented in shared-module/ - they can be included in
+# any port once their prerequisites in common-hal are complete.
+CIRCUITPY_RANDOM = 0 # Requires OS
+CIRCUITPY_USB_MIDI = 0 # Requires USB
+CIRCUITPY_ULAB = 0 # No requirements, but takes extra flash
CIRCUITPY_MODULE ?= none
diff --git a/ports/esp32s2/peripherals/rmt.c b/ports/esp32s2/peripherals/rmt.c
new file mode 100644
index 000000000..f17957c1c
--- /dev/null
+++ b/ports/esp32s2/peripherals/rmt.c
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Lucian Copeland for Adafruit Industries
+ *
+ * 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 "rmt.h"
+#include "py/runtime.h"
+
+bool rmt_reserved_channels[RMT_CHANNEL_MAX];
+
+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]) {
+ rmt_reserved_channels[i] = true;
+ return i;
+ }
+ }
+ mp_raise_RuntimeError(translate("All timers in use"));
+ return false;
+}
+
+void esp32s2_peripherals_free_rmt(rmt_channel_t chan) {
+ rmt_reserved_channels[chan] = false;
+ rmt_driver_uninstall(chan);
+}
diff --git a/ports/esp32s2/peripherals/rmt.h b/ports/esp32s2/peripherals/rmt.h
new file mode 100644
index 000000000..4741a5bc5
--- /dev/null
+++ b/ports/esp32s2/peripherals/rmt.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Lucian Copeland for Adafruit Industries
+ *
+ * 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_ESP32S2_PERIPHERALS_RMT_H
+#define MICROPY_INCLUDED_ESP32S2_PERIPHERALS_RMT_H
+
+#include "py/mphal.h"
+#include "driver/rmt.h"
+#include <stdint.h>
+
+rmt_channel_t esp32s2_peripherals_find_and_reserve_rmt(void);
+void esp32s2_peripherals_free_rmt(rmt_channel_t chan);
+
+#endif