Expand PulseOut API, debug cleanup

This commit is contained in:
Lucian Copeland 2020-08-14 16:33:24 -04:00
parent 88fcc19e24
commit 0fc730bc5a
12 changed files with 102 additions and 103 deletions

View File

@ -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 PWM Carrier instead"));
}
if (refcount == 0) {
// Find a spare timer.
Tc *tc = NULL;

View File

@ -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 PWM Carrier instead"));
}
if (pulse_fd < 0) {
pulse_fd = open("/dev/timer0", O_RDONLY);
}

View File

@ -25,6 +25,7 @@
*/
#include "common-hal/pulseio/PulseIn.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "py/runtime.h"
STATIC uint8_t refcount = 0;
@ -33,17 +34,11 @@ 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
@ -69,25 +64,16 @@ STATIC void update_internal_buffer(pulseio_pulsein_obj_t* self) {
// 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;
}
@ -103,48 +89,48 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu
}
self->pin = pin;
self->maxlen = maxlen;
// self->idle_state = idle_state;
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;
// 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();
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;
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);
size_t len = 1000; //TODO: pick a reasonable number for this?
// size_t len = maxlen * 4;
rmt_driver_install(channel, len, 0);
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;
// Store handle for background updates
handles[channel] = self;
rmt_get_ringbuf_handle(channel, &(self->buf_handle));
rmt_rx_start(channel, true);
// 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 handles[self->channel] ? true : 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);
reset_pin_number(self->pin->number);
refcount--;
if (refcount == 0) {
supervisor_disable_tick();
@ -153,7 +139,7 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) {
self->paused = true;
rmt_rx_stop();
rmt_rx_stop(self->channel);
}
void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint16_t trigger_duration) {
@ -162,17 +148,25 @@ void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint16_t tri
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();
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) {
//mp_printf(&mp_plat_print, "Call GetItem\n");
update_internal_buffer(self);
if (index < 0) {
index += self->len;
@ -185,7 +179,6 @@ uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_
}
uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) {
mp_printf(&mp_plat_print, "Call PopLeft\n");
update_internal_buffer(self);
if (self->len == 0) {
@ -197,28 +190,6 @@ uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) {
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) {

View File

@ -42,15 +42,12 @@ typedef struct {
bool paused;
RingbufHandle_t buf_handle;
volatile bool first_edge;
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);

View File

@ -32,15 +32,21 @@
// Requires rmt.c void esp32s2_peripherals_reset_all(void) to reset
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
const mcu_pin_obj_t* pin,
uint32_t frequency) {
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"));
}
rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt();
// 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 = 50;
config.tx_config.carrier_duty_percent = (duty_cycle * 100) / (1<<16);
config.tx_config.carrier_freq_hz = frequency;
config.clk_div = 80;

View File

@ -36,8 +36,6 @@
#include "py/circuitpy_mpconfig.h"
#define CPY_PULSEOUT_USES_DIGITALIO (1)
#define MICROPY_PORT_ROOT_POINTERS \
CIRCUITPY_COMMON_ROOT_POINTERS
#define MICROPY_NLR_SETJMP (1)

View File

@ -30,7 +30,6 @@
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);

View File

@ -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;

View File

@ -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 PWM Carrier instead"));
}
if (refcount == 0) {
timer = nrf_peripherals_allocate_timer_or_throw();
}

View File

@ -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 PWM Carrier instead"));
}
// Add to active PulseOuts
refcount++;
TIM_TypeDef * tim_instance = stm_peripherals_find_timer();

View File

@ -69,29 +69,24 @@ STATIC mp_obj_t pulseio_pulseout_make_new(const mp_obj_type_t *type, size_t n_ar
pulseio_pulseout_obj_t *self = m_new_obj(pulseio_pulseout_obj_t);
self->base.type = &pulseio_pulseout_type;
#ifndef CPY_PULSEOUT_USES_DIGITALIO
// Most ports pass a PWMOut
mp_arg_check_num(n_args, kw_args, 1, 1, false);
mp_obj_t carrier_obj = args[0];
if (!MP_OBJ_IS_TYPE(carrier_obj, &pulseio_pwmout_type)) {
mp_raise_TypeError_varg(translate("Expected a %q"), pulseio_pwmout_type.name);
mp_obj_t carrier_obj = pos_args[0];
if (MP_OBJ_IS_TYPE(carrier_obj, &pulseio_pwmout_type)) {
// PWM 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 {
// Pin and Frequency
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);
}
common_hal_pulseio_pulseout_construct(self, (pulseio_pwmout_obj_t *)MP_OBJ_TO_PTR(carrier_obj));
#else
// ESP32-S2 Special Case
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_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, pin, args[ARG_frequency].u_int);
#endif
return MP_OBJ_FROM_PTR(self);
}

View File

@ -33,13 +33,11 @@
extern const mp_obj_type_t pulseio_pulseout_type;
#ifndef CPY_PULSEOUT_USES_DIGITALIO
extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
const pulseio_pwmout_obj_t* carrier);
#else
extern void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
const mcu_pin_obj_t* pin, uint32_t frequency);
#endif
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);