summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--locale/circuitpython.pot17
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PulseOut.c10
-rw-r--r--ports/cxd56/common-hal/pulseio/PulseOut.c12
-rw-r--r--ports/esp32s2/background.c7
-rw-r--r--ports/esp32s2/common-hal/neopixel_write/__init__.c3
-rw-r--r--ports/esp32s2/common-hal/pulseio/PulseIn.c151
-rw-r--r--ports/esp32s2/common-hal/pulseio/PulseIn.h9
-rw-r--r--ports/esp32s2/common-hal/pulseio/PulseOut.c59
-rw-r--r--ports/esp32s2/common-hal/pulseio/PulseOut.h6
-rw-r--r--ports/esp32s2/mpconfigport.h13
-rw-r--r--ports/esp32s2/peripherals/rmt.c12
-rw-r--r--ports/esp32s2/peripherals/rmt.h1
-rw-r--r--ports/esp32s2/supervisor/port.c5
-rw-r--r--ports/mimxrt10xx/common-hal/pulseio/PulseOut.c5
-rw-r--r--ports/nrf/common-hal/pulseio/PulseOut.c10
-rw-r--r--ports/stm/common-hal/pulseio/PulseOut.c10
-rw-r--r--shared-bindings/pulseio/PulseOut.c29
-rw-r--r--shared-bindings/pulseio/PulseOut.h6
18 files changed, 308 insertions, 57 deletions
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot
index ffb2e91ef..1e227dcbc 100644
--- a/locale/circuitpython.pot
+++ b/locale/circuitpython.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-14 09:36-0400\n"
+"POT-Creation-Date: 2020-08-18 11:19-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -744,7 +744,7 @@ msgstr ""
#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c
#: shared-bindings/microcontroller/Pin.c
-#: shared-bindings/neopixel_write/__init__.c shared-bindings/pulseio/PulseOut.c
+#: shared-bindings/neopixel_write/__init__.c
#: shared-bindings/terminalio/Terminal.c
msgid "Expected a %q"
msgstr ""
@@ -1328,6 +1328,15 @@ msgstr ""
msgid "Polygon needs at least 3 points"
msgstr ""
+#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
+#: ports/cxd56/common-hal/pulseio/PulseOut.c
+#: ports/nrf/common-hal/pulseio/PulseOut.c
+#: ports/stm/common-hal/pulseio/PulseOut.c
+msgid ""
+"Port does not accept pins or frequency. "
+"Construct and pass a PWMOut Carrier instead"
+msgstr ""
+
#: shared-bindings/_bleio/Adapter.c
msgid "Prefix buffer must be on the heap"
msgstr ""
@@ -1340,6 +1349,10 @@ msgstr ""
msgid "Pull not used when direction is output."
msgstr ""
+#: ports/stm/ref/pulseout-pre-timeralloc.c
+msgid "PulseOut not supported on this chip"
+msgstr ""
+
#: ports/stm/common-hal/os/__init__.c
msgid "RNG DeInit Error"
msgstr ""
diff --git a/ports/atmel-samd/common-hal/pulseio/PulseOut.c b/ports/atmel-samd/common-hal/pulseio/PulseOut.c
index e9b2137cb..b53c8da2b 100644
--- a/ports/atmel-samd/common-hal/pulseio/PulseOut.c
+++ b/ports/atmel-samd/common-hal/pulseio/PulseOut.c
@@ -96,7 +96,15 @@ void pulseout_reset() {
}
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
- const pulseio_pwmout_obj_t* carrier) {
+ const pulseio_pwmout_obj_t* carrier,
+ const mcu_pin_obj_t* pin,
+ uint32_t frequency,
+ uint16_t duty_cycle) {
+ if (!carrier || pin || frequency) {
+ mp_raise_NotImplementedError(translate("Port does not accept pins or frequency. \
+ Construct and pass a PWMOut Carrier instead"));
+ }
+
if (refcount == 0) {
// Find a spare timer.
Tc *tc = NULL;
diff --git a/ports/cxd56/common-hal/pulseio/PulseOut.c b/ports/cxd56/common-hal/pulseio/PulseOut.c
index 21b4c77e5..08081020f 100644
--- a/ports/cxd56/common-hal/pulseio/PulseOut.c
+++ b/ports/cxd56/common-hal/pulseio/PulseOut.c
@@ -58,8 +58,16 @@ static bool pulseout_timer_handler(unsigned int *next_interval_us, void *arg)
return true;
}
-void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
- const pulseio_pwmout_obj_t *carrier) {
+void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
+ const pulseio_pwmout_obj_t* carrier,
+ const mcu_pin_obj_t* pin,
+ uint32_t frequency,
+ uint16_t duty_cycle) {
+ if (!carrier || pin || frequency) {
+ mp_raise_NotImplementedError(translate("Port does not accept pins or frequency. \
+ Construct and pass a PWMOut Carrier instead"));
+ }
+
if (pulse_fd < 0) {
pulse_fd = open("/dev/timer0", O_RDONLY);
}
diff --git a/ports/esp32s2/background.c b/ports/esp32s2/background.c
index 40ce9ecfd..3160d9974 100644
--- a/ports/esp32s2/background.c
+++ b/ports/esp32s2/background.c
@@ -35,10 +35,17 @@
#include "shared-module/displayio/__init__.h"
#endif
+#if CIRCUITPY_PULSEIO
+#include "common-hal/pulseio/PulseIn.h"
+#endif
+
void port_background_task(void) {
// Zero delay in case FreeRTOS wants to switch to something else.
vTaskDelay(0);
+ #if CIRCUITPY_PULSEIO
+ pulsein_background();
+ #endif
}
void port_start_background_task(void) {}
diff --git a/ports/esp32s2/common-hal/neopixel_write/__init__.c b/ports/esp32s2/common-hal/neopixel_write/__init__.c
index 1fc976ec3..193d754f4 100644
--- a/ports/esp32s2/common-hal/neopixel_write/__init__.c
+++ b/ports/esp32s2/common-hal/neopixel_write/__init__.c
@@ -93,6 +93,9 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
// Reserve channel
uint8_t number = digitalinout->pin->number;
rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt();
+ if (channel == RMT_CHANNEL_MAX) {
+ mp_raise_RuntimeError(translate("All timers in use"));
+ }
// Configure Channel
rmt_config_t config = RMT_DEFAULT_CONFIG_TX(number, channel);
diff --git a/ports/esp32s2/common-hal/pulseio/PulseIn.c b/ports/esp32s2/common-hal/pulseio/PulseIn.c
index 65fc6631d..f7429ec12 100644
--- a/ports/esp32s2/common-hal/pulseio/PulseIn.c
+++ b/ports/esp32s2/common-hal/pulseio/PulseIn.c
@@ -25,51 +25,184 @@
*/
#include "common-hal/pulseio/PulseIn.h"
+#include "shared-bindings/microcontroller/__init__.h"
#include "py/runtime.h"
-// STATIC void pulsein_handler(uint8_t num) {
-// }
+STATIC uint8_t refcount = 0;
+STATIC pulseio_pulsein_obj_t * handles[RMT_CHANNEL_MAX];
+
+// Requires rmt.c void esp32s2_peripherals_reset_all(void) to reset
+
+STATIC void update_internal_buffer(pulseio_pulsein_obj_t* self) {
+ uint32_t length = 0;
+ rmt_item32_t *items = (rmt_item32_t *) xRingbufferReceive(self->buf_handle, &length, 0);
+ if (items) {
+ length /= 4;
+ for (size_t i=0; i < length; i++) {
+ uint16_t pos = (self->start + self->len) % self->maxlen;
+ self->buffer[pos] = items[i].duration0 * 3;
+ // Check if second item exists before incrementing
+ if (items[i].duration1) {
+ self->buffer[pos+1] = items[i].duration1 * 3;
+ if (self->len < (self->maxlen - 1)) {
+ self->len += 2;
+ } else {
+ self->start += 2;
+ }
+ } else {
+ if (self->len < self->maxlen) {
+ self->len++;
+ } else {
+ self->start++;
+ }
+ }
+ }
+ vRingbufferReturnItem(self->buf_handle, (void *) items);
+ }
+}
+
+// We can't access the RMT interrupt, so we need a global service to prevent
+// the ringbuffer from overflowing and crashing the peripheral
+void pulsein_background(void) {
+ for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) {
+ if (handles[i]) {
+ update_internal_buffer(handles[i]);
+ UBaseType_t items_waiting;
+ vRingbufferGetInfo(handles[i]->buf_handle, NULL, NULL, NULL, NULL, &items_waiting);
+ }
+ }
+}
void pulsein_reset(void) {
+ for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) {
+ handles[i] = NULL;
+ }
+ supervisor_disable_tick();
+ refcount = 0;
}
void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin,
uint16_t maxlen, bool idle_state) {
- mp_raise_NotImplementedError(translate("PulseIn not supported on this chip"));
+ self->buffer = (uint16_t *) m_malloc(maxlen * sizeof(uint16_t), false);
+ if (self->buffer == NULL) {
+ mp_raise_msg_varg(&mp_type_MemoryError, translate("Failed to allocate RX buffer of %d bytes"), maxlen * sizeof(uint16_t));
+ }
+ self->pin = pin;
+ self->maxlen = maxlen;
+ self->idle_state = idle_state;
+ self->start = 0;
+ self->len = 0;
+ self->paused = false;
+
+ // Set pull settings
+ gpio_pullup_dis(pin->number);
+ gpio_pulldown_dis(pin->number);
+ if (idle_state) {
+ gpio_pullup_en(pin->number);
+ } else {
+ gpio_pulldown_en(pin->number);
+ }
+
+ // Find a free RMT Channel and configure it
+ rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt();
+ if (channel == RMT_CHANNEL_MAX) {
+ mp_raise_RuntimeError(translate("All timers in use"));
+ }
+ rmt_config_t config = RMT_DEFAULT_CONFIG_RX(pin->number, channel);
+ config.rx_config.filter_en = true;
+ config.rx_config.idle_threshold = 30000; // 30*3=90ms idle required to register a sequence
+ config.clk_div = 240; // All measurements are divided by 3 to accomodate 65ms pulses
+ rmt_config(&config);
+ rmt_driver_install(channel, 1000, 0); //TODO: pick a more specific buffer size?
+
+ // Store this object and the buffer handle for background updates
+ self->channel = channel;
+ handles[channel] = self;
+ rmt_get_ringbuf_handle(channel, &(self->buf_handle));
+
+ // start RMT RX, and enable ticks so the core doesn't turn off.
+ rmt_rx_start(channel, true);
+ supervisor_enable_tick();
+ refcount++;
}
bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) {
- return false;
+ return handles[self->channel] ? false : true;
}
void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
+ handles[self->channel] = NULL;
+ esp32s2_peripherals_free_rmt(self->channel);
+ reset_pin_number(self->pin->number);
+ refcount--;
+ if (refcount == 0) {
+ supervisor_disable_tick();
+ }
}
void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) {
+ self->paused = true;
+ rmt_rx_stop(self->channel);
}
void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint16_t trigger_duration) {
+ // Make sure we're paused.
+ if ( !self->paused ) {
+ common_hal_pulseio_pulsein_pause(self);
+ }
+
+ if (trigger_duration > 0) {
+ gpio_set_direction(self->pin->number, GPIO_MODE_DEF_OUTPUT);
+ gpio_set_level(self->pin->number, !self->idle_state);
+ common_hal_mcu_delay_us((uint32_t)trigger_duration);
+ gpio_set_level(self->pin->number, self->idle_state);
+ gpio_set_direction(self->pin->number, GPIO_MODE_INPUT); // should revert to pull direction
+ }
+
+ self->paused = false;
+ rmt_rx_start(self->channel, false);
}
void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) {
+ // Buffer only updates in BG tasks or fetches, so no extra protection is needed
+ self->start = 0;
+ self->len = 0;
}
uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) {
- return false;
+ update_internal_buffer(self);
+ if (index < 0) {
+ index += self->len;
+ }
+ if (index < 0 || index >= self->len) {
+ mp_raise_IndexError(translate("index out of range"));
+ }
+ uint16_t value = self->buffer[(self->start + index) % self->maxlen];
+ return value;
}
uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) {
- return false;
+ update_internal_buffer(self);
+
+ if (self->len == 0) {
+ mp_raise_IndexError(translate("pop from an empty PulseIn"));
+ }
+
+ uint16_t value = self->buffer[self->start];
+ self->start = (self->start + 1) % self->maxlen;
+ self->len--;
+
+ return value;
}
uint16_t common_hal_pulseio_pulsein_get_maxlen(pulseio_pulsein_obj_t* self) {
- return false;
+ return self->maxlen;
}
bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t* self) {
- return false;
+ return self->paused;
}
uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self) {
- return false;
+ return self->len;
}
diff --git a/ports/esp32s2/common-hal/pulseio/PulseIn.h b/ports/esp32s2/common-hal/pulseio/PulseIn.h
index b317c516c..97d70d4b0 100644
--- a/ports/esp32s2/common-hal/pulseio/PulseIn.h
+++ b/ports/esp32s2/common-hal/pulseio/PulseIn.h
@@ -30,24 +30,27 @@
#include "common-hal/microcontroller/Pin.h"
#include "py/obj.h"
+#include "driver/rmt.h"
+#include "rmt.h"
typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t* pin;
+ rmt_channel_t channel;
bool idle_state;
bool paused;
- volatile bool first_edge;
+
+ RingbufHandle_t buf_handle;
uint16_t* buffer;
uint16_t maxlen;
volatile uint16_t start;
volatile uint16_t len;
- volatile uint32_t last_overflow;
- volatile uint16_t last_count;
} pulseio_pulsein_obj_t;
void pulsein_reset(void);
+void pulsein_background(void);
#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_PULSEIO_PULSEIN_H
diff --git a/ports/esp32s2/common-hal/pulseio/PulseOut.c b/ports/esp32s2/common-hal/pulseio/PulseOut.c
index c448c578d..d3c163ca8 100644
--- a/ports/esp32s2/common-hal/pulseio/PulseOut.c
+++ b/ports/esp32s2/common-hal/pulseio/PulseOut.c
@@ -29,32 +29,63 @@
#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 pulseio_pwmout_obj_t* carrier,
+ const mcu_pin_obj_t* pin,
+ uint32_t frequency,
+ uint16_t duty_cycle) {
+ if (carrier || !pin || !frequency) {
+ mp_raise_NotImplementedError(translate("Port does not accept PWM carrier. \
+ Pass a pin, frequency and duty cycle instead"));
+ }
-// STATIC void start_timer(void) {
-// }
+ rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt();
+ if (channel == RMT_CHANNEL_MAX) {
+ mp_raise_RuntimeError(translate("All timers in use"));
+ }
-// 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 = (duty_cycle * 100) / (1<<16);
+ 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);
+ while (rmt_wait_tx_done(self->channel, 0) != ESP_OK) {
+ RUN_BACKGROUND_TASKS;
+ }
}
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..07f83434a 100644
--- a/ports/esp32s2/mpconfigport.h
+++ b/ports/esp32s2/mpconfigport.h
@@ -28,19 +28,18 @@
#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 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..b7629dbd5 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]) {
@@ -36,8 +44,8 @@ rmt_channel_t esp32s2_peripherals_find_and_reserve_rmt(void) {
return i;
}
}
- mp_raise_RuntimeError(translate("All timers in use"));
- return false;
+ // Returning the max indicates a reservation failure.
+ return RMT_CHANNEL_MAX;
}
void esp32s2_peripherals_free_rmt(rmt_channel_t chan) {
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..46590b551 100644
--- a/ports/esp32s2/supervisor/port.c
+++ b/ports/esp32s2/supervisor/port.c
@@ -39,9 +39,12 @@
#include "common-hal/busio/SPI.h"
#include "common-hal/busio/UART.h"
#include "common-hal/pulseio/PWMOut.h"
+#include "common-hal/pulseio/PulseIn.h"
#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,7 +69,9 @@ void reset_port(void) {
vTaskDelay(4);
#if CIRCUITPY_PULSEIO
+ esp32s2_peripherals_rmt_reset();
pwmout_reset();
+ pulsein_reset();
#endif
#if CIRCUITPY_BUSIO
i2c_reset();
diff --git a/ports/mimxrt10xx/common-hal/pulseio/PulseOut.c b/ports/mimxrt10xx/common-hal/pulseio/PulseOut.c
index ffa885688..3aefd8766 100644
--- a/ports/mimxrt10xx/common-hal/pulseio/PulseOut.c
+++ b/ports/mimxrt10xx/common-hal/pulseio/PulseOut.c
@@ -94,7 +94,10 @@ void pulseout_reset() {
}
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
- const pulseio_pwmout_obj_t* carrier) {
+ const pulseio_pwmout_obj_t* carrier,
+ const mcu_pin_obj_t* pin,
+ uint32_t frequency,
+ uint16_t duty_cycle) {
// if (refcount == 0) {
// // Find a spare timer.
// Tc *tc = NULL;
diff --git a/ports/nrf/common-hal/pulseio/PulseOut.c b/ports/nrf/common-hal/pulseio/PulseOut.c
index 270cb45d6..bdc5cfbef 100644
--- a/ports/nrf/common-hal/pulseio/PulseOut.c
+++ b/ports/nrf/common-hal/pulseio/PulseOut.c
@@ -100,7 +100,15 @@ void pulseout_reset() {
}
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
- const pulseio_pwmout_obj_t* carrier) {
+ const pulseio_pwmout_obj_t* carrier,
+ const mcu_pin_obj_t* pin,
+ uint32_t frequency,
+ uint16_t duty_cycle) {
+ if (!carrier || pin || frequency) {
+ mp_raise_NotImplementedError(translate("Port does not accept pins or frequency. \
+ Construct and pass a PWMOut Carrier instead"));
+ }
+
if (refcount == 0) {
timer = nrf_peripherals_allocate_timer_or_throw();
}
diff --git a/ports/stm/common-hal/pulseio/PulseOut.c b/ports/stm/common-hal/pulseio/PulseOut.c
index bcc25d817..eec1049dd 100644
--- a/ports/stm/common-hal/pulseio/PulseOut.c
+++ b/ports/stm/common-hal/pulseio/PulseOut.c
@@ -113,7 +113,15 @@ void pulseout_reset() {
}
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
- const pulseio_pwmout_obj_t* carrier) {
+ const pulseio_pwmout_obj_t* carrier,
+ const mcu_pin_obj_t* pin,
+ uint32_t frequency,
+ uint16_t duty_cycle) {
+ if (!carrier || pin || frequency) {
+ mp_raise_NotImplementedError(translate("Port does not accept pins or frequency. \
+ Construct and pass a PWMOut Carrier instead"));
+ }
+
// Add to active PulseOuts
refcount++;
TIM_TypeDef * tim_instance = stm_peripherals_find_timer();
diff --git a/shared-bindings/pulseio/PulseOut.c b/shared-bindings/pulseio/PulseOut.c
index 3d35f0544..3fd722558 100644
--- a/shared-bindings/pulseio/PulseOut.c
+++ b/shared-bindings/pulseio/PulseOut.c
@@ -64,20 +64,29 @@
//| 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) {
- mp_arg_check_num(n_args, kw_args, 1, 1, false);
- mp_obj_t carrier_obj = args[0];
+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) {
- 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);
self->base.type = &pulseio_pulseout_type;
- common_hal_pulseio_pulseout_construct(self, (pulseio_pwmout_obj_t *)MP_OBJ_TO_PTR(carrier_obj));
-
+ mp_obj_t carrier_obj = pos_args[0];
+ if (MP_OBJ_IS_TYPE(carrier_obj, &pulseio_pwmout_type)) {
+ // Use a PWMOut Carrier
+ mp_arg_check_num(n_args, kw_args, 1, 1, false);
+ common_hal_pulseio_pulseout_construct(self, (pulseio_pwmout_obj_t *)MP_OBJ_TO_PTR(carrier_obj), NULL, 0, 0);
+ } else {
+ // Use a Pin, frequency, and duty cycle
+ 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_QSTR_duty_cycle, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1<<15} },
+ };
+ 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, NULL, pin, args[ARG_frequency].u_int, args[ARG_frequency].u_int);
+ }
return MP_OBJ_FROM_PTR(self);
}
diff --git a/shared-bindings/pulseio/PulseOut.h b/shared-bindings/pulseio/PulseOut.h
index 390910ff6..9d4778e93 100644
--- a/shared-bindings/pulseio/PulseOut.h
+++ b/shared-bindings/pulseio/PulseOut.h
@@ -34,7 +34,11 @@
extern const mp_obj_type_t pulseio_pulseout_type;
extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
- const pulseio_pwmout_obj_t* carrier);
+ const pulseio_pwmout_obj_t* carrier,
+ const mcu_pin_obj_t* pin,
+ uint32_t frequency,
+ uint16_t duty_cycle);
+
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,