commit
43aef8af2f
@ -144,7 +144,7 @@ int readline_process_char(int c) {
|
||||
goto right_arrow_key;
|
||||
} else if (c == CHAR_CTRL_K) {
|
||||
// CTRL-K is kill from cursor to end-of-line, inclusive
|
||||
vstr_cut_tail_bytes(rl.line, last_line_len - rl.cursor_pos);
|
||||
vstr_cut_tail_bytes(rl.line, rl.line->len - rl.cursor_pos);
|
||||
// set redraw parameters
|
||||
redraw_from_cursor = true;
|
||||
} else if (c == CHAR_CTRL_N) {
|
||||
@ -155,6 +155,7 @@ int readline_process_char(int c) {
|
||||
goto up_arrow_key;
|
||||
} else if (c == CHAR_CTRL_U) {
|
||||
// CTRL-U is kill from beginning-of-line up to cursor
|
||||
cont_chars = count_cont_bytes(rl.line->buf+rl.orig_line_len, rl.line->buf+rl.cursor_pos);
|
||||
vstr_cut_out_bytes(rl.line, rl.orig_line_len, rl.cursor_pos - rl.orig_line_len);
|
||||
// set redraw parameters
|
||||
redraw_step_back = rl.cursor_pos - rl.orig_line_len;
|
||||
@ -342,6 +343,7 @@ left_arrow_key:
|
||||
if (c == '~') {
|
||||
if (rl.escape_seq_buf[0] == '1' || rl.escape_seq_buf[0] == '7') {
|
||||
home_key:
|
||||
cont_chars = count_cont_bytes(rl.line->buf+rl.orig_line_len, rl.line->buf+rl.cursor_pos);
|
||||
redraw_step_back = rl.cursor_pos - rl.orig_line_len;
|
||||
} else if (rl.escape_seq_buf[0] == '4' || rl.escape_seq_buf[0] == '8') {
|
||||
end_key:
|
||||
@ -352,7 +354,12 @@ end_key:
|
||||
delete_key:
|
||||
#endif
|
||||
if (rl.cursor_pos < rl.line->len) {
|
||||
vstr_cut_out_bytes(rl.line, rl.cursor_pos, 1);
|
||||
size_t len = 1;
|
||||
while (UTF8_IS_CONT(rl.line->buf[rl.cursor_pos+len]) &&
|
||||
rl.cursor_pos+len < rl.line->len) {
|
||||
len++;
|
||||
}
|
||||
vstr_cut_out_bytes(rl.line, rl.cursor_pos, len);
|
||||
redraw_from_cursor = true;
|
||||
}
|
||||
} else {
|
||||
|
@ -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 ""
|
||||
|
@ -103,7 +103,7 @@ ifeq ($(CHIP_FAMILY), same54)
|
||||
PERIPHERALS_CHIP_FAMILY=sam_d5x_e5x
|
||||
OPTIMIZATION_FLAGS ?= -O2
|
||||
# TinyUSB defines
|
||||
CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD51 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
|
||||
CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAME5X -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
|
||||
endif
|
||||
|
||||
# option to override default optimization level, set in boards/$(BOARD)/mpconfigboard.mk
|
||||
|
@ -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;
|
||||
|
@ -91,3 +91,5 @@ endif # samd51
|
||||
INTERNAL_LIBM = 1
|
||||
|
||||
USB_SERIAL_NUMBER_LENGTH = 32
|
||||
|
||||
USB_NUM_EP = 8
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include "boards/board.h"
|
||||
|
||||
#include "supervisor/port.h"
|
||||
#include "supervisor/background_callback.h"
|
||||
#include "supervisor/usb.h"
|
||||
#include "supervisor/shared/tick.h"
|
||||
|
||||
#include "common-hal/microcontroller/Pin.h"
|
||||
@ -114,6 +116,11 @@ uint32_t port_get_saved_word(void) {
|
||||
return _ebss;
|
||||
}
|
||||
|
||||
static background_callback_t callback;
|
||||
static void usb_background_do(void* unused) {
|
||||
usb_background();
|
||||
}
|
||||
|
||||
volatile bool _tick_enabled;
|
||||
void board_timerhook(void)
|
||||
{
|
||||
@ -121,6 +128,8 @@ void board_timerhook(void)
|
||||
if (_tick_enabled) {
|
||||
supervisor_tick();
|
||||
}
|
||||
|
||||
background_callback_add(&callback, usb_background_do, NULL);
|
||||
}
|
||||
|
||||
uint64_t port_get_raw_ticks(uint8_t* subticks) {
|
||||
|
@ -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) {}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -29,32 +29,63 @@
|
||||
#include "shared-bindings/pulseio/PWMOut.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
// STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) {
|
||||
// }
|
||||
|
||||
// STATIC void turn_off(pulseio_pulseout_obj_t *pulseout) {
|
||||
// }
|
||||
|
||||
// STATIC void start_timer(void) {
|
||||
// }
|
||||
|
||||
// STATIC void pulseout_event_handler(void) {
|
||||
// }
|
||||
|
||||
void pulseout_reset() {
|
||||
}
|
||||
// Requires rmt.c void esp32s2_peripherals_reset_all(void) to reset
|
||||
|
||||
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"));
|
||||
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();
|
||||
if (channel == RMT_CHANNEL_MAX) {
|
||||
mp_raise_RuntimeError(translate("All timers in use"));
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
rmt_config(&config);
|
||||
rmt_driver_install(channel, 0, 0);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -171,6 +171,10 @@ ifndef USB_MIDI_EP_NUM_IN
|
||||
USB_MIDI_EP_NUM_IN = 0
|
||||
endif
|
||||
|
||||
ifndef USB_NUM_EP
|
||||
USB_NUM_EP = 0
|
||||
endif
|
||||
|
||||
USB_DESCRIPTOR_ARGS = \
|
||||
--manufacturer $(USB_MANUFACTURER)\
|
||||
--product $(USB_PRODUCT)\
|
||||
@ -180,6 +184,7 @@ USB_DESCRIPTOR_ARGS = \
|
||||
--interface_name $(USB_INTERFACE_NAME)\
|
||||
--devices $(USB_DEVICES)\
|
||||
--hid_devices $(USB_HID_DEVICES)\
|
||||
--max_ep $(USB_NUM_EP) \
|
||||
--cdc_ep_num_notification $(USB_CDC_EP_NUM_NOTIFICATION)\
|
||||
--cdc_ep_num_data_out $(USB_CDC_EP_NUM_DATA_OUT)\
|
||||
--cdc_ep_num_data_in $(USB_CDC_EP_NUM_DATA_IN)\
|
||||
|
@ -58,15 +58,20 @@ filtered_characters = all_characters
|
||||
# Try to pre-load all of the glyphs. Misses will still be slow later.
|
||||
f.load_glyphs(set(ord(c) for c in all_characters))
|
||||
|
||||
missing = 0
|
||||
# Get each glyph.
|
||||
for c in set(all_characters):
|
||||
if ord(c) not in f._glyphs:
|
||||
missing += 1
|
||||
filtered_characters = filtered_characters.replace(c, "")
|
||||
continue
|
||||
g = f.get_glyph(ord(c))
|
||||
if g["shift"][1] != 0:
|
||||
raise RuntimeError("y shift")
|
||||
|
||||
if missing > 0:
|
||||
print("Font missing", missing, "characters", file=sys.stderr)
|
||||
|
||||
x, y, dx, dy = f.get_bounding_box()
|
||||
tile_x, tile_y = x - dx, y - dy
|
||||
total_bits = tile_x * len(all_characters)
|
||||
|
@ -62,6 +62,8 @@ parser.add_argument('--midi_ep_num_out', type=int, default=0,
|
||||
help='endpoint number of MIDI OUT')
|
||||
parser.add_argument('--midi_ep_num_in', type=int, default=0,
|
||||
help='endpoint number of MIDI IN')
|
||||
parser.add_argument('--max_ep', type=int, default=0,
|
||||
help='total number of endpoints available')
|
||||
parser.add_argument('--output_c_file', type=argparse.FileType('w', encoding='UTF-8'), required=True)
|
||||
parser.add_argument('--output_h_file', type=argparse.FileType('w', encoding='UTF-8'), required=True)
|
||||
|
||||
@ -376,6 +378,15 @@ if 'AUDIO' in args.devices:
|
||||
# interface cross-references.
|
||||
interfaces = util.join_interfaces(interfaces_to_join, renumber_endpoints=args.renumber_endpoints)
|
||||
|
||||
if args.max_ep != 0:
|
||||
for interface in interfaces:
|
||||
for subdescriptor in interface.subdescriptors:
|
||||
endpoint_address = getattr(subdescriptor, 'bEndpointAddress', 0) & 0x7f
|
||||
if endpoint_address > args.max_ep:
|
||||
raise ValueError("Endpoint address %d of %s may not exceed %d" % (endpoint_address & 0x7f, interface.description, args.max_ep))
|
||||
else:
|
||||
print("Unable to check whether maximum number of endpoints is respected", file=sys.stderr)
|
||||
|
||||
# Now adjust the CDC interface cross-references.
|
||||
|
||||
cdc_union.bMasterInterface = cdc_comm_interface.bInterfaceNumber
|
||||
|
Loading…
Reference in New Issue
Block a user