Skip to content

Commit 43aef8a

Browse files
authored
Merge pull request #22 from adafruit/main
Merge from adafruit main
2 parents 0311c34 + 4007010 commit 43aef8a

File tree

25 files changed

+350
-60
lines changed

25 files changed

+350
-60
lines changed

lib/mp-readline/readline.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ int readline_process_char(int c) {
144144
goto right_arrow_key;
145145
} else if (c == CHAR_CTRL_K) {
146146
// CTRL-K is kill from cursor to end-of-line, inclusive
147-
vstr_cut_tail_bytes(rl.line, last_line_len - rl.cursor_pos);
147+
vstr_cut_tail_bytes(rl.line, rl.line->len - rl.cursor_pos);
148148
// set redraw parameters
149149
redraw_from_cursor = true;
150150
} else if (c == CHAR_CTRL_N) {
@@ -155,6 +155,7 @@ int readline_process_char(int c) {
155155
goto up_arrow_key;
156156
} else if (c == CHAR_CTRL_U) {
157157
// CTRL-U is kill from beginning-of-line up to cursor
158+
cont_chars = count_cont_bytes(rl.line->buf+rl.orig_line_len, rl.line->buf+rl.cursor_pos);
158159
vstr_cut_out_bytes(rl.line, rl.orig_line_len, rl.cursor_pos - rl.orig_line_len);
159160
// set redraw parameters
160161
redraw_step_back = rl.cursor_pos - rl.orig_line_len;
@@ -342,6 +343,7 @@ int readline_process_char(int c) {
342343
if (c == '~') {
343344
if (rl.escape_seq_buf[0] == '1' || rl.escape_seq_buf[0] == '7') {
344345
home_key:
346+
cont_chars = count_cont_bytes(rl.line->buf+rl.orig_line_len, rl.line->buf+rl.cursor_pos);
345347
redraw_step_back = rl.cursor_pos - rl.orig_line_len;
346348
} else if (rl.escape_seq_buf[0] == '4' || rl.escape_seq_buf[0] == '8') {
347349
end_key:
@@ -352,7 +354,12 @@ int readline_process_char(int c) {
352354
delete_key:
353355
#endif
354356
if (rl.cursor_pos < rl.line->len) {
355-
vstr_cut_out_bytes(rl.line, rl.cursor_pos, 1);
357+
size_t len = 1;
358+
while (UTF8_IS_CONT(rl.line->buf[rl.cursor_pos+len]) &&
359+
rl.cursor_pos+len < rl.line->len) {
360+
len++;
361+
}
362+
vstr_cut_out_bytes(rl.line, rl.cursor_pos, len);
356363
redraw_from_cursor = true;
357364
}
358365
} else {

locale/circuitpython.pot

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ msgid ""
88
msgstr ""
99
"Project-Id-Version: PACKAGE VERSION\n"
1010
"Report-Msgid-Bugs-To: \n"
11-
"POT-Creation-Date: 2020-08-14 09:36-0400\n"
11+
"POT-Creation-Date: 2020-08-18 11:19-0400\n"
1212
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1313
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1414
"Language-Team: LANGUAGE <[email protected]>\n"
@@ -744,7 +744,7 @@ msgstr ""
744744

745745
#: shared-bindings/aesio/aes.c shared-bindings/busio/SPI.c
746746
#: shared-bindings/microcontroller/Pin.c
747-
#: shared-bindings/neopixel_write/__init__.c shared-bindings/pulseio/PulseOut.c
747+
#: shared-bindings/neopixel_write/__init__.c
748748
#: shared-bindings/terminalio/Terminal.c
749749
msgid "Expected a %q"
750750
msgstr ""
@@ -1328,6 +1328,15 @@ msgstr ""
13281328
msgid "Polygon needs at least 3 points"
13291329
msgstr ""
13301330

1331+
#: ports/atmel-samd/common-hal/pulseio/PulseOut.c
1332+
#: ports/cxd56/common-hal/pulseio/PulseOut.c
1333+
#: ports/nrf/common-hal/pulseio/PulseOut.c
1334+
#: ports/stm/common-hal/pulseio/PulseOut.c
1335+
msgid ""
1336+
"Port does not accept pins or frequency. "
1337+
"Construct and pass a PWMOut Carrier instead"
1338+
msgstr ""
1339+
13311340
#: shared-bindings/_bleio/Adapter.c
13321341
msgid "Prefix buffer must be on the heap"
13331342
msgstr ""
@@ -1340,6 +1349,10 @@ msgstr ""
13401349
msgid "Pull not used when direction is output."
13411350
msgstr ""
13421351

1352+
#: ports/stm/ref/pulseout-pre-timeralloc.c
1353+
msgid "PulseOut not supported on this chip"
1354+
msgstr ""
1355+
13431356
#: ports/stm/common-hal/os/__init__.c
13441357
msgid "RNG DeInit Error"
13451358
msgstr ""

ports/atmel-samd/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ ifeq ($(CHIP_FAMILY), same54)
103103
PERIPHERALS_CHIP_FAMILY=sam_d5x_e5x
104104
OPTIMIZATION_FLAGS ?= -O2
105105
# TinyUSB defines
106-
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
106+
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
107107
endif
108108

109109
# option to override default optimization level, set in boards/$(BOARD)/mpconfigboard.mk

ports/atmel-samd/common-hal/pulseio/PulseOut.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,15 @@ void pulseout_reset() {
9696
}
9797

9898
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
99-
const pulseio_pwmout_obj_t* carrier) {
99+
const pulseio_pwmout_obj_t* carrier,
100+
const mcu_pin_obj_t* pin,
101+
uint32_t frequency,
102+
uint16_t duty_cycle) {
103+
if (!carrier || pin || frequency) {
104+
mp_raise_NotImplementedError(translate("Port does not accept pins or frequency. \
105+
Construct and pass a PWMOut Carrier instead"));
106+
}
107+
100108
if (refcount == 0) {
101109
// Find a spare timer.
102110
Tc *tc = NULL;

ports/atmel-samd/mpconfigport.mk

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,5 @@ endif # samd51
9191
INTERNAL_LIBM = 1
9292

9393
USB_SERIAL_NUMBER_LENGTH = 32
94+
95+
USB_NUM_EP = 8

ports/cxd56/common-hal/pulseio/PulseOut.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,16 @@ static bool pulseout_timer_handler(unsigned int *next_interval_us, void *arg)
5858
return true;
5959
}
6060

61-
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t *self,
62-
const pulseio_pwmout_obj_t *carrier) {
61+
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
62+
const pulseio_pwmout_obj_t* carrier,
63+
const mcu_pin_obj_t* pin,
64+
uint32_t frequency,
65+
uint16_t duty_cycle) {
66+
if (!carrier || pin || frequency) {
67+
mp_raise_NotImplementedError(translate("Port does not accept pins or frequency. \
68+
Construct and pass a PWMOut Carrier instead"));
69+
}
70+
6371
if (pulse_fd < 0) {
6472
pulse_fd = open("/dev/timer0", O_RDONLY);
6573
}

ports/cxd56/supervisor/port.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include "boards/board.h"
3737

3838
#include "supervisor/port.h"
39+
#include "supervisor/background_callback.h"
40+
#include "supervisor/usb.h"
3941
#include "supervisor/shared/tick.h"
4042

4143
#include "common-hal/microcontroller/Pin.h"
@@ -114,13 +116,20 @@ uint32_t port_get_saved_word(void) {
114116
return _ebss;
115117
}
116118

119+
static background_callback_t callback;
120+
static void usb_background_do(void* unused) {
121+
usb_background();
122+
}
123+
117124
volatile bool _tick_enabled;
118125
void board_timerhook(void)
119126
{
120127
// Do things common to all ports when the tick occurs
121128
if (_tick_enabled) {
122129
supervisor_tick();
123130
}
131+
132+
background_callback_add(&callback, usb_background_do, NULL);
124133
}
125134

126135
uint64_t port_get_raw_ticks(uint8_t* subticks) {

ports/esp32s2/background.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,17 @@
3535
#include "shared-module/displayio/__init__.h"
3636
#endif
3737

38+
#if CIRCUITPY_PULSEIO
39+
#include "common-hal/pulseio/PulseIn.h"
40+
#endif
41+
3842

3943
void port_background_task(void) {
4044
// Zero delay in case FreeRTOS wants to switch to something else.
4145
vTaskDelay(0);
46+
#if CIRCUITPY_PULSEIO
47+
pulsein_background();
48+
#endif
4249
}
4350

4451
void port_start_background_task(void) {}

ports/esp32s2/common-hal/neopixel_write/__init__.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
9393
// Reserve channel
9494
uint8_t number = digitalinout->pin->number;
9595
rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt();
96+
if (channel == RMT_CHANNEL_MAX) {
97+
mp_raise_RuntimeError(translate("All timers in use"));
98+
}
9699

97100
// Configure Channel
98101
rmt_config_t config = RMT_DEFAULT_CONFIG_TX(number, channel);

ports/esp32s2/common-hal/pulseio/PulseIn.c

Lines changed: 142 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,51 +25,184 @@
2525
*/
2626

2727
#include "common-hal/pulseio/PulseIn.h"
28+
#include "shared-bindings/microcontroller/__init__.h"
2829
#include "py/runtime.h"
2930

30-
// STATIC void pulsein_handler(uint8_t num) {
31-
// }
31+
STATIC uint8_t refcount = 0;
32+
STATIC pulseio_pulsein_obj_t * handles[RMT_CHANNEL_MAX];
33+
34+
// Requires rmt.c void esp32s2_peripherals_reset_all(void) to reset
35+
36+
STATIC void update_internal_buffer(pulseio_pulsein_obj_t* self) {
37+
uint32_t length = 0;
38+
rmt_item32_t *items = (rmt_item32_t *) xRingbufferReceive(self->buf_handle, &length, 0);
39+
if (items) {
40+
length /= 4;
41+
for (size_t i=0; i < length; i++) {
42+
uint16_t pos = (self->start + self->len) % self->maxlen;
43+
self->buffer[pos] = items[i].duration0 * 3;
44+
// Check if second item exists before incrementing
45+
if (items[i].duration1) {
46+
self->buffer[pos+1] = items[i].duration1 * 3;
47+
if (self->len < (self->maxlen - 1)) {
48+
self->len += 2;
49+
} else {
50+
self->start += 2;
51+
}
52+
} else {
53+
if (self->len < self->maxlen) {
54+
self->len++;
55+
} else {
56+
self->start++;
57+
}
58+
}
59+
}
60+
vRingbufferReturnItem(self->buf_handle, (void *) items);
61+
}
62+
}
63+
64+
// We can't access the RMT interrupt, so we need a global service to prevent
65+
// the ringbuffer from overflowing and crashing the peripheral
66+
void pulsein_background(void) {
67+
for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) {
68+
if (handles[i]) {
69+
update_internal_buffer(handles[i]);
70+
UBaseType_t items_waiting;
71+
vRingbufferGetInfo(handles[i]->buf_handle, NULL, NULL, NULL, NULL, &items_waiting);
72+
}
73+
}
74+
}
3275

3376
void pulsein_reset(void) {
77+
for (size_t i = 0; i < RMT_CHANNEL_MAX; i++) {
78+
handles[i] = NULL;
79+
}
80+
supervisor_disable_tick();
81+
refcount = 0;
3482
}
3583

3684
void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin,
3785
uint16_t maxlen, bool idle_state) {
38-
mp_raise_NotImplementedError(translate("PulseIn not supported on this chip"));
86+
self->buffer = (uint16_t *) m_malloc(maxlen * sizeof(uint16_t), false);
87+
if (self->buffer == NULL) {
88+
mp_raise_msg_varg(&mp_type_MemoryError, translate("Failed to allocate RX buffer of %d bytes"), maxlen * sizeof(uint16_t));
89+
}
90+
self->pin = pin;
91+
self->maxlen = maxlen;
92+
self->idle_state = idle_state;
93+
self->start = 0;
94+
self->len = 0;
95+
self->paused = false;
96+
97+
// Set pull settings
98+
gpio_pullup_dis(pin->number);
99+
gpio_pulldown_dis(pin->number);
100+
if (idle_state) {
101+
gpio_pullup_en(pin->number);
102+
} else {
103+
gpio_pulldown_en(pin->number);
104+
}
105+
106+
// Find a free RMT Channel and configure it
107+
rmt_channel_t channel = esp32s2_peripherals_find_and_reserve_rmt();
108+
if (channel == RMT_CHANNEL_MAX) {
109+
mp_raise_RuntimeError(translate("All timers in use"));
110+
}
111+
rmt_config_t config = RMT_DEFAULT_CONFIG_RX(pin->number, channel);
112+
config.rx_config.filter_en = true;
113+
config.rx_config.idle_threshold = 30000; // 30*3=90ms idle required to register a sequence
114+
config.clk_div = 240; // All measurements are divided by 3 to accomodate 65ms pulses
115+
rmt_config(&config);
116+
rmt_driver_install(channel, 1000, 0); //TODO: pick a more specific buffer size?
117+
118+
// Store this object and the buffer handle for background updates
119+
self->channel = channel;
120+
handles[channel] = self;
121+
rmt_get_ringbuf_handle(channel, &(self->buf_handle));
122+
123+
// start RMT RX, and enable ticks so the core doesn't turn off.
124+
rmt_rx_start(channel, true);
125+
supervisor_enable_tick();
126+
refcount++;
39127
}
40128

41129
bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) {
42-
return false;
130+
return handles[self->channel] ? false : true;
43131
}
44132

45133
void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
134+
handles[self->channel] = NULL;
135+
esp32s2_peripherals_free_rmt(self->channel);
136+
reset_pin_number(self->pin->number);
137+
refcount--;
138+
if (refcount == 0) {
139+
supervisor_disable_tick();
140+
}
46141
}
47142

48143
void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) {
144+
self->paused = true;
145+
rmt_rx_stop(self->channel);
49146
}
50147

51148
void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint16_t trigger_duration) {
149+
// Make sure we're paused.
150+
if ( !self->paused ) {
151+
common_hal_pulseio_pulsein_pause(self);
152+
}
153+
154+
if (trigger_duration > 0) {
155+
gpio_set_direction(self->pin->number, GPIO_MODE_DEF_OUTPUT);
156+
gpio_set_level(self->pin->number, !self->idle_state);
157+
common_hal_mcu_delay_us((uint32_t)trigger_duration);
158+
gpio_set_level(self->pin->number, self->idle_state);
159+
gpio_set_direction(self->pin->number, GPIO_MODE_INPUT); // should revert to pull direction
160+
}
161+
162+
self->paused = false;
163+
rmt_rx_start(self->channel, false);
52164
}
53165

54166
void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) {
167+
// Buffer only updates in BG tasks or fetches, so no extra protection is needed
168+
self->start = 0;
169+
self->len = 0;
55170
}
56171

57172
uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) {
58-
return false;
173+
update_internal_buffer(self);
174+
if (index < 0) {
175+
index += self->len;
176+
}
177+
if (index < 0 || index >= self->len) {
178+
mp_raise_IndexError(translate("index out of range"));
179+
}
180+
uint16_t value = self->buffer[(self->start + index) % self->maxlen];
181+
return value;
59182
}
60183

61184
uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) {
62-
return false;
185+
update_internal_buffer(self);
186+
187+
if (self->len == 0) {
188+
mp_raise_IndexError(translate("pop from an empty PulseIn"));
189+
}
190+
191+
uint16_t value = self->buffer[self->start];
192+
self->start = (self->start + 1) % self->maxlen;
193+
self->len--;
194+
195+
return value;
63196
}
64197

65198
uint16_t common_hal_pulseio_pulsein_get_maxlen(pulseio_pulsein_obj_t* self) {
66-
return false;
199+
return self->maxlen;
67200
}
68201

69202
bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t* self) {
70-
return false;
203+
return self->paused;
71204
}
72205

73206
uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self) {
74-
return false;
207+
return self->len;
75208
}

0 commit comments

Comments
 (0)