Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ports/atmel-samd/common-hal/neopixel_write/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ static void neopixel_send_buffer_core(volatile uint32_t *clraddr, uint32_t pinMa
"");
}

uint64_t next_start_raw_ticks = 0;
STATIC uint64_t next_start_raw_ticks = 0;

void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout, uint8_t *pixels, uint32_t numBytes) {
// This is adapted directly from the Adafruit NeoPixel library SAMD21G18A code:
Expand Down
18 changes: 2 additions & 16 deletions ports/espressif/common-hal/microcontroller/Pin.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,6 @@
STATIC uint32_t never_reset_pins[2];
STATIC uint32_t in_use[2];

STATIC void floating_gpio_reset(gpio_num_t pin_number) {
// This is the same as gpio_reset_pin(), but without the pullup.
// Note that gpio_config resets the iomatrix to GPIO_FUNC as well.
gpio_config_t cfg = {
.pin_bit_mask = BIT64(pin_number),
.mode = GPIO_MODE_DISABLE,
.pull_up_en = false,
.pull_down_en = false,
.intr_type = GPIO_INTR_DISABLE,
};
gpio_config(&cfg);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pin_number], 0);
}

void never_reset_pin_number(gpio_num_t pin_number) {
if (pin_number == NO_PIN) {
return;
Expand All @@ -72,7 +58,7 @@ void reset_pin_number(gpio_num_t pin_number) {
never_reset_pins[pin_number / 32] &= ~(1 << pin_number % 32);
in_use[pin_number / 32] &= ~(1 << pin_number % 32);

floating_gpio_reset(pin_number);
gpio_reset_pin(pin_number);
}

void common_hal_mcu_pin_reset_number(uint8_t i) {
Expand All @@ -93,7 +79,7 @@ void reset_all_pins(void) {
(never_reset_pins[i / 32] & (1 << i % 32)) != 0) {
continue;
}
floating_gpio_reset(i);
gpio_reset_pin(i);
}
in_use[0] = never_reset_pins[0];
in_use[1] = never_reset_pins[1];
Expand Down
31 changes: 21 additions & 10 deletions ports/espressif/common-hal/neopixel_write/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,23 @@
#include "py/mphal.h"
#include "py/runtime.h"
#include "shared-bindings/neopixel_write/__init__.h"
#include "supervisor/port.h"
#include "components/driver/include/driver/rmt.h"
#include "peripherals/rmt.h"

#define WS2812_T0H_NS (350)
#define WS2812_T0L_NS (1000)
#define WS2812_T1H_NS (1000)
#define WS2812_T1L_NS (350)
#define WS2812_RESET_US (280)
// 416 ns is 1/3 of the 1250ns period of a 800khz signal.
#define WS2812_T0H_NS (416)
#define WS2812_T0L_NS (416 * 2)
#define WS2812_T1H_NS (416 * 2)
#define WS2812_T1L_NS (416)

static uint32_t ws2812_t0h_ticks = 0;
static uint32_t ws2812_t1h_ticks = 0;
static uint32_t ws2812_t0l_ticks = 0;
static uint32_t ws2812_t1l_ticks = 0;

static uint64_t next_start_raw_ticks = 0;

static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size,
size_t wanted_num, size_t *translated_size, size_t *item_num) {
if (src == NULL || dest == NULL) {
Expand Down Expand Up @@ -107,21 +110,29 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
if (rmt_get_counter_clock(config.channel, &counter_clk_hz) != ESP_OK) {
mp_raise_RuntimeError(translate("Could not retrieve clock"));
}
float ratio = (float)counter_clk_hz / 1e9;
ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS);
ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS);
ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS);
ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS);
size_t ns_per_tick = 1e9 / counter_clk_hz;
ws2812_t0h_ticks = WS2812_T0H_NS / ns_per_tick;
ws2812_t0l_ticks = WS2812_T0L_NS / ns_per_tick;
ws2812_t1h_ticks = WS2812_T1H_NS / ns_per_tick;
ws2812_t1l_ticks = WS2812_T1L_NS / ns_per_tick;

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

// Wait to make sure we don't append onto the last transmission. This should only be a tick or
// two.
while (port_get_raw_ticks(NULL) < next_start_raw_ticks) {
}

// Write and wait to finish
if (rmt_write_sample(config.channel, pixels, (size_t)numBytes, true) != ESP_OK) {
mp_raise_RuntimeError(translate("Input/output error"));
}
rmt_wait_tx_done(config.channel, pdMS_TO_TICKS(100));

// Update the next start to +2 ticks. It ensures that we've gone 300+ us.
next_start_raw_ticks = port_get_raw_ticks(NULL) + 2;

// Free channel again
peripherals_free_rmt(config.channel);
// Swap pin back to GPIO mode
Expand Down
4 changes: 2 additions & 2 deletions ports/raspberrypi/common-hal/neopixel_write/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,6 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
gpio_init(digitalinout->pin->number);
common_hal_digitalio_digitalinout_switch_to_output((digitalio_digitalinout_obj_t *)digitalinout, false, DRIVE_MODE_PUSH_PULL);

// Update the next start.
next_start_raw_ticks = port_get_raw_ticks(NULL) + 1;
// Update the next start to +2 ticks. This ensures we give it at least 300us.
next_start_raw_ticks = port_get_raw_ticks(NULL) + 2;
}
7 changes: 6 additions & 1 deletion supervisor/shared/status_leds.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ uint8_t rgb_status_brightness = 63;
#define MICROPY_HW_NEOPIXEL_COUNT (1)
#endif

static uint64_t next_start_raw_ticks;
static uint8_t status_neopixel_color[3 * MICROPY_HW_NEOPIXEL_COUNT];
static digitalio_digitalinout_obj_t status_neopixel;

Expand Down Expand Up @@ -218,6 +219,10 @@ void status_led_init() {

void status_led_deinit() {
#ifdef MICROPY_HW_NEOPIXEL
// Make sure the pin stays low for the reset period. The pin reset may pull
// it up and stop the reset period.
while (port_get_raw_ticks(NULL) < next_start_raw_ticks) {
}
common_hal_reset_pin(MICROPY_HW_NEOPIXEL);

#elif defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
Expand Down Expand Up @@ -265,7 +270,7 @@ void new_status_color(uint32_t rgb) {
status_neopixel_color[3 * i + 2] = rgb_adjusted & 0xff;
}
common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3 * MICROPY_HW_NEOPIXEL_COUNT);

next_start_raw_ticks = port_get_raw_ticks(NULL) + 2;
#elif defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)
for (size_t i = 0; i < MICROPY_HW_APA102_COUNT; i++) {
// Skip 4 + offset to skip the header bytes too.
Expand Down