summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucian Copeland <hierophect@gmail.com>2020-08-10 12:14:16 -0400
committerLucian Copeland <hierophect@gmail.com>2020-08-14 15:30:48 -0400
commit88fcc19e24597140fb3e5f45ab8d87705fb4f5ed (patch)
treea7a275e9ccb56d24732179a2ec30479dcf03af73
parentf9512983ff0c63a719d7708496e1a827a2ca8a64 (diff)
Add PulseIn
-rw-r--r--ports/esp32s2/background.c7
-rw-r--r--ports/esp32s2/common-hal/pulseio/PulseIn.c177
-rw-r--r--ports/esp32s2/common-hal/pulseio/PulseIn.h6
-rw-r--r--ports/esp32s2/peripherals/rmt.c1
-rw-r--r--ports/esp32s2/supervisor/port.c2
5 files changed, 184 insertions, 9 deletions
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/pulseio/PulseIn.c b/ports/esp32s2/common-hal/pulseio/PulseIn.c
index 65fc6631d..5209c51ca 100644
--- a/ports/esp32s2/common-hal/pulseio/PulseIn.c
+++ b/ports/esp32s2/common-hal/pulseio/PulseIn.c
@@ -27,49 +27,208 @@
#include "common-hal/pulseio/PulseIn.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) {
+ //mp_printf(&mp_plat_print, "Update internal Buffer\n");
+ uint32_t length = 0;
+ rmt_item32_t *items = (rmt_item32_t *) xRingbufferReceive(self->buf_handle, &length, 0);
+ if (items) {
+ length /= 4;
+ //mp_printf(&mp_plat_print, "Length%d\n",length);
+ // TODO: If the size of the recieve is larger than the buffer, reset it?
+
+ for (size_t i=0; i < length; i++) {
+ //mp_printf(&mp_plat_print, "Item d0:%d, l0:%d, d1:%d, l1:%d\n",(items[i].duration0 * 3),
+ // items[i].level0,(items[i].duration1 * 3),items[i].level1);
+ 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) {
+ //mp_printf(&mp_plat_print, "BG Task!\n");
+ for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) {
+ if (handles[i]) {
+ //mp_printf(&mp_plat_print, "Located viable handle:%d\n",i);
+ update_internal_buffer(handles[i]);
+ UBaseType_t items_waiting;
+ vRingbufferGetInfo(handles[i]->buf_handle, NULL, NULL, NULL, NULL, &items_waiting);
+ //mp_printf(&mp_plat_print, "items waiting:%d\n",items_waiting);
+ // if (items_waiting > handles[i]->maxlen) {
+ // mp_printf(&mp_plat_print, "Overage!\n");
+ // mp_printf(&mp_plat_print, "Items waiting detected:%d\n", items_waiting);
+ // update_internal_buffer(handles[i]);
+ // }
+ }
+ }
+}
void pulsein_reset(void) {
+ mp_printf(&mp_plat_print, "Pulsein Reset called\n");
+ 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->first_edge = true;
+ self->paused = false;
+ // self->last_overflow = 0;
+ // self->last_count = 0;
+
+ rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt();
+ mp_printf(&mp_plat_print, "Selected Channel:%d!\n",channel);
+
+ // Configure Channel
+ rmt_config_t config = RMT_DEFAULT_CONFIG_RX(pin->number, channel);
+ config.rx_config.filter_en = true;
+ config.rx_config.idle_threshold = 30000;
+ config.clk_div = 240;
+
+ rmt_config(&config);
+ size_t len = 1000; //TODO: pick a reasonable number for this?
+ // size_t len = maxlen * 4;
+ rmt_driver_install(channel, len, 0);
+
+ self->channel = channel;
+
+ // Store handle for background updates
+ handles[channel] = self;
+
+ rmt_get_ringbuf_handle(channel, &(self->buf_handle));
+ 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] ? true : false;
}
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);
+ refcount--;
+ if (refcount == 0) {
+ supervisor_disable_tick();
+ }
}
void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) {
+ self->paused = true;
+ rmt_rx_stop();
}
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);
+ }
+
+ self->paused = false;
+ rmt_rx_start();
}
void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) {
+ self->start = 0;
+ self->len = 0;
}
uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) {
- return false;
+ //mp_printf(&mp_plat_print, "Call GetItem\n");
+ 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;
+ mp_printf(&mp_plat_print, "Call PopLeft\n");
+ 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;
+
+
+ // uint32_t length = 0;
+ // rmt_item32_t *items = (rmt_item32_t *) xRingbufferReceive(self->buf_handle, &length, 10);
+ // mp_printf(&mp_plat_print, "Length%d\n",length);
+ // if (items) {
+ // length /= 4;
+ // mp_printf(&mp_plat_print, "Length%d\n",length);
+ // for (size_t i=0; i < length; i++) {
+ // mp_printf(&mp_plat_print, "Item d0:%d, l0:%d, d1:%d, l1:%d\n",(items[i].duration0 * 3),
+ // items[i].level0,(items[i].duration1 * 3),items[i].level1);
+ // }
+ // vRingbufferReturnItem(self->buf_handle, (void *) items);
+ // }
+ // // while(items) {
+ // // mp_printf(&mp_plat_print, "Length%d",length);
+ // // mp_printf(&mp_plat_print, "Item val0:%d, val1:%d, val:%d",items->duration0,
+ // // items->duration1,items->val);
+ // // vRingbufferReturnItem(self->buf_handle, (void *) items);
+ // // items = (rmt_item32_t *) xRingbufferReceive(self->buf_handle, &length, 1);
+ // // }
+ // return items ? items[0].duration0 : false;
}
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..1ac47cfe1 100644
--- a/ports/esp32s2/common-hal/pulseio/PulseIn.h
+++ b/ports/esp32s2/common-hal/pulseio/PulseIn.h
@@ -30,13 +30,18 @@
#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;
+
+ RingbufHandle_t buf_handle;
volatile bool first_edge;
uint16_t* buffer;
@@ -49,5 +54,6 @@ typedef struct {
} 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/peripherals/rmt.c b/ports/esp32s2/peripherals/rmt.c
index 16605edf5..c3a063eec 100644
--- a/ports/esp32s2/peripherals/rmt.c
+++ b/ports/esp32s2/peripherals/rmt.c
@@ -30,6 +30,7 @@
bool rmt_reserved_channels[RMT_CHANNEL_MAX];
void esp32s2_peripherals_rmt_reset(void) {
+ mp_printf(&mp_plat_print, "RMT Reset called\n");
for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) {
if (rmt_reserved_channels[i]) {
esp32s2_peripherals_free_rmt(i);
diff --git a/ports/esp32s2/supervisor/port.c b/ports/esp32s2/supervisor/port.c
index d287079b7..46590b551 100644
--- a/ports/esp32s2/supervisor/port.c
+++ b/ports/esp32s2/supervisor/port.c
@@ -39,6 +39,7 @@
#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"
@@ -70,6 +71,7 @@ void reset_port(void) {
#if CIRCUITPY_PULSEIO
esp32s2_peripherals_rmt_reset();
pwmout_reset();
+ pulsein_reset();
#endif
#if CIRCUITPY_BUSIO
i2c_reset();