Skip to content

Commit cc77f30

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents 5d0b0d0 + 1cd3faa commit cc77f30

File tree

5 files changed

+32
-30
lines changed

5 files changed

+32
-30
lines changed

ports/atmel-samd/common-hal/neopixel_write/__init__.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ static void neopixel_send_buffer_core(volatile uint32_t *clraddr, uint32_t pinMa
100100
"");
101101
}
102102

103-
uint64_t next_start_raw_ticks = 0;
103+
STATIC uint64_t next_start_raw_ticks = 0;
104104

105105
void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout, uint8_t *pixels, uint32_t numBytes) {
106106
// This is adapted directly from the Adafruit NeoPixel library SAMD21G18A code:

ports/espressif/common-hal/microcontroller/Pin.c

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,6 @@
3636
STATIC uint32_t never_reset_pins[2];
3737
STATIC uint32_t in_use[2];
3838

39-
STATIC void floating_gpio_reset(gpio_num_t pin_number) {
40-
// This is the same as gpio_reset_pin(), but without the pullup.
41-
// Note that gpio_config resets the iomatrix to GPIO_FUNC as well.
42-
gpio_config_t cfg = {
43-
.pin_bit_mask = BIT64(pin_number),
44-
.mode = GPIO_MODE_DISABLE,
45-
.pull_up_en = false,
46-
.pull_down_en = false,
47-
.intr_type = GPIO_INTR_DISABLE,
48-
};
49-
gpio_config(&cfg);
50-
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin_number], 0);
51-
}
52-
5339
void never_reset_pin_number(gpio_num_t pin_number) {
5440
if (pin_number == NO_PIN) {
5541
return;
@@ -72,7 +58,7 @@ void reset_pin_number(gpio_num_t pin_number) {
7258
never_reset_pins[pin_number / 32] &= ~(1 << pin_number % 32);
7359
in_use[pin_number / 32] &= ~(1 << pin_number % 32);
7460

75-
floating_gpio_reset(pin_number);
61+
gpio_reset_pin(pin_number);
7662
}
7763

7864
void common_hal_mcu_pin_reset_number(uint8_t i) {
@@ -93,7 +79,7 @@ void reset_all_pins(void) {
9379
(never_reset_pins[i / 32] & (1 << i % 32)) != 0) {
9480
continue;
9581
}
96-
floating_gpio_reset(i);
82+
gpio_reset_pin(i);
9783
}
9884
in_use[0] = never_reset_pins[0];
9985
in_use[1] = never_reset_pins[1];

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

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,23 @@
4343
#include "py/mphal.h"
4444
#include "py/runtime.h"
4545
#include "shared-bindings/neopixel_write/__init__.h"
46+
#include "supervisor/port.h"
4647
#include "components/driver/include/driver/rmt.h"
4748
#include "peripherals/rmt.h"
4849

49-
#define WS2812_T0H_NS (350)
50-
#define WS2812_T0L_NS (1000)
51-
#define WS2812_T1H_NS (1000)
52-
#define WS2812_T1L_NS (350)
53-
#define WS2812_RESET_US (280)
50+
// 416 ns is 1/3 of the 1250ns period of a 800khz signal.
51+
#define WS2812_T0H_NS (416)
52+
#define WS2812_T0L_NS (416 * 2)
53+
#define WS2812_T1H_NS (416 * 2)
54+
#define WS2812_T1L_NS (416)
5455

5556
static uint32_t ws2812_t0h_ticks = 0;
5657
static uint32_t ws2812_t1h_ticks = 0;
5758
static uint32_t ws2812_t0l_ticks = 0;
5859
static uint32_t ws2812_t1l_ticks = 0;
5960

61+
static uint64_t next_start_raw_ticks = 0;
62+
6063
static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size,
6164
size_t wanted_num, size_t *translated_size, size_t *item_num) {
6265
if (src == NULL || dest == NULL) {
@@ -107,21 +110,29 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
107110
if (rmt_get_counter_clock(config.channel, &counter_clk_hz) != ESP_OK) {
108111
mp_raise_RuntimeError(translate("Could not retrieve clock"));
109112
}
110-
float ratio = (float)counter_clk_hz / 1e9;
111-
ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS);
112-
ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS);
113-
ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS);
114-
ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS);
113+
size_t ns_per_tick = 1e9 / counter_clk_hz;
114+
ws2812_t0h_ticks = WS2812_T0H_NS / ns_per_tick;
115+
ws2812_t0l_ticks = WS2812_T0L_NS / ns_per_tick;
116+
ws2812_t1h_ticks = WS2812_T1H_NS / ns_per_tick;
117+
ws2812_t1l_ticks = WS2812_T1L_NS / ns_per_tick;
115118

116119
// Initialize automatic timing translator
117120
rmt_translator_init(config.channel, ws2812_rmt_adapter);
118121

122+
// Wait to make sure we don't append onto the last transmission. This should only be a tick or
123+
// two.
124+
while (port_get_raw_ticks(NULL) < next_start_raw_ticks) {
125+
}
126+
119127
// Write and wait to finish
120128
if (rmt_write_sample(config.channel, pixels, (size_t)numBytes, true) != ESP_OK) {
121129
mp_raise_RuntimeError(translate("Input/output error"));
122130
}
123131
rmt_wait_tx_done(config.channel, pdMS_TO_TICKS(100));
124132

133+
// Update the next start to +2 ticks. It ensures that we've gone 300+ us.
134+
next_start_raw_ticks = port_get_raw_ticks(NULL) + 2;
135+
125136
// Free channel again
126137
peripherals_free_rmt(config.channel);
127138
// Swap pin back to GPIO mode

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,6 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
9898
gpio_init(digitalinout->pin->number);
9999
common_hal_digitalio_digitalinout_switch_to_output((digitalio_digitalinout_obj_t *)digitalinout, false, DRIVE_MODE_PUSH_PULL);
100100

101-
// Update the next start.
102-
next_start_raw_ticks = port_get_raw_ticks(NULL) + 1;
101+
// Update the next start to +2 ticks. This ensures we give it at least 300us.
102+
next_start_raw_ticks = port_get_raw_ticks(NULL) + 2;
103103
}

supervisor/shared/status_leds.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ uint8_t rgb_status_brightness = 63;
4848
#define MICROPY_HW_NEOPIXEL_COUNT (1)
4949
#endif
5050

51+
static uint64_t next_start_raw_ticks;
5152
static uint8_t status_neopixel_color[3 * MICROPY_HW_NEOPIXEL_COUNT];
5253
static digitalio_digitalinout_obj_t status_neopixel;
5354

@@ -218,6 +219,10 @@ void status_led_init() {
218219

219220
void status_led_deinit() {
220221
#ifdef MICROPY_HW_NEOPIXEL
222+
// Make sure the pin stays low for the reset period. The pin reset may pull
223+
// it up and stop the reset period.
224+
while (port_get_raw_ticks(NULL) < next_start_raw_ticks) {
225+
}
221226
common_hal_reset_pin(MICROPY_HW_NEOPIXEL);
222227

223228
#elif defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
@@ -265,7 +270,7 @@ void new_status_color(uint32_t rgb) {
265270
status_neopixel_color[3 * i + 2] = rgb_adjusted & 0xff;
266271
}
267272
common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3 * MICROPY_HW_NEOPIXEL_COUNT);
268-
273+
next_start_raw_ticks = port_get_raw_ticks(NULL) + 2;
269274
#elif defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
270275
for (size_t i = 0; i < MICROPY_HW_APA102_COUNT; i++) {
271276
// Skip 4 + offset to skip the header bytes too.

0 commit comments

Comments
 (0)