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
161 changes: 82 additions & 79 deletions components/i2s_out/esp32/pin.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ static void clear_gpio_pin(gpio_num_t gpio)
int i2s_out_pin_init(struct i2s_out *i2s_out)
{

for (int i = 0; i < I2S_OUT_PARALLEL_SIZE; i++) {
for (int i = 0; i < I2S_OUT_GPIO_PINS_MAX; i++) {
i2s_out->bck_gpios[i] = -1;
i2s_out->data_gpios[i] = -1;
i2s_out->inv_data_gpios[i] = -1;
Expand All @@ -78,20 +78,12 @@ int i2s_out_pin_setup(struct i2s_out *i2s_out, const struct i2s_out_options *opt

switch (options->mode) {
case I2S_OUT_MODE_16BIT_SERIAL:
LOG_DEBUG("port=%d: mode=I2S_OUT_MODE_16BIT_SERIAL bck_gpio=%d serial_data_gpio=%d inv_data_gpio=%d", i2s_out->port,
options->bck_gpio,
options->data_gpio,
options->inv_data_gpio
);
LOG_DEBUG("port=%d: mode=I2S_OUT_MODE_16BIT_SERIAL ", i2s_out->port);

break;

case I2S_OUT_MODE_32BIT_SERIAL:
LOG_DEBUG("port=%d: mode=I2S_OUT_MODE_32BIT_SERIAL bck_gpio=%d serial_data_gpio=%d inv_data_gpio=%d", i2s_out->port,
options->bck_gpio,
options->data_gpio,
options->inv_data_gpio
);
LOG_DEBUG("port=%d: mode=I2S_OUT_MODE_32BIT_SERIAL", i2s_out->port);

break;

Expand All @@ -101,17 +93,7 @@ int i2s_out_pin_setup(struct i2s_out *i2s_out, const struct i2s_out_options *opt
return -1;
}

LOG_DEBUG("port=%d: mode=I2S_OUT_MODE_8BIT_PARALLEL bck_gpio=%d parallel_data_gpio=[%d, %d, %d, %d, %d, %d, %d, %d]", i2s_out->port,
options->bck_gpio,
options->data_gpios[0],
options->data_gpios[1],
options->data_gpios[2],
options->data_gpios[3],
options->data_gpios[4],
options->data_gpios[5],
options->data_gpios[6],
options->data_gpios[7]
);
LOG_DEBUG("port=%d: mode=I2S_OUT_MODE_8BIT_PARALLEL", i2s_out->port);

break;

Expand All @@ -120,74 +102,95 @@ int i2s_out_pin_setup(struct i2s_out *i2s_out, const struct i2s_out_options *opt
return -1;
}

taskENTER_CRITICAL(&i2s_out->mux);

switch (options->mode) {
case I2S_OUT_MODE_16BIT_SERIAL:
case I2S_OUT_MODE_32BIT_SERIAL:
if (options->bck_gpio > 0) {
i2s_out->bck_gpio_inv = options->bck_inv;
i2s_out->bck_gpios[0] = options->bck_gpio;

setup_gpio_pin(options->bck_gpio);
setup_rtc_pin(options->bck_gpio);

esp_rom_gpio_connect_out_signal(options->bck_gpio, i2s_bck_out_sig[i2s_out->port], options->bck_inv, false);
}

if (options->data_gpio > 0) {
i2s_out->data_gpios[0] = options->data_gpio;

setup_gpio_pin(options->data_gpio);
setup_rtc_pin(options->data_gpio);

esp_rom_gpio_connect_out_signal(options->data_gpio, i2s_serial_data_out_sig[i2s_out->port], false, false);
}

if (options->inv_data_gpio > 0) {
i2s_out->inv_data_gpios[0] = options->inv_data_gpio;
LOG_DEBUG("port=%d: bck_inv=%d bck_gpios=[%d, %d, %d, %d, %d, %d, %d, %d]", i2s_out->port,
options->bck_inv,
options->bck_gpios[0],
options->bck_gpios[1],
options->bck_gpios[2],
options->bck_gpios[3],
options->bck_gpios[4],
options->bck_gpios[5],
options->bck_gpios[6],
options->bck_gpios[7]
);
LOG_DEBUG("port=%d: data_gpios=[%d, %d, %d, %d, %d, %d, %d, %d]", i2s_out->port,
options->data_gpios[0],
options->data_gpios[1],
options->data_gpios[2],
options->data_gpios[3],
options->data_gpios[4],
options->data_gpios[5],
options->data_gpios[6],
options->data_gpios[7]
);
LOG_DEBUG("port=%d: inv_data_gpios=[%d, %d, %d, %d, %d, %d, %d, %d]", i2s_out->port,
options->inv_data_gpios[0],
options->inv_data_gpios[1],
options->inv_data_gpios[2],
options->inv_data_gpios[3],
options->inv_data_gpios[4],
options->inv_data_gpios[5],
options->inv_data_gpios[6],
options->inv_data_gpios[7]
);

setup_gpio_pin(options->inv_data_gpio);
setup_rtc_pin(options->inv_data_gpio);
taskENTER_CRITICAL(&i2s_out->mux);

// invert gpio output pin
esp_rom_gpio_connect_out_signal(options->inv_data_gpio, i2s_serial_data_out_sig[i2s_out->port], true, false);
}
for (int i = 0; i < I2S_OUT_GPIO_PINS_MAX; i++) {
unsigned data_out_sig;

switch (options->mode) {
case I2S_OUT_MODE_16BIT_SERIAL:
case I2S_OUT_MODE_32BIT_SERIAL:
// each gpio is a copy of the same serial data signal
data_out_sig = i2s_serial_data_out_sig[i2s_out->port];

break;

case I2S_OUT_MODE_8BIT_PARALLEL:
// loop over the used parallel data signals, repeating as necessary
// data[0] is mapped to the most significant bit, which is OUT7
// data[7] -> OUT0
if (options->parallel_data_bits) {
data_out_sig = i2s_parallel8_data_out_sig[i2s_out->port] + 8 - (i % options->parallel_data_bits) - 1;
} else {
data_out_sig = i2s_parallel8_data_out_sig[i2s_out->port] + 8 - i - 1;
}

break;
break;

default:
LOG_FATAL("mode=%d", options->mode);
}

case I2S_OUT_MODE_8BIT_PARALLEL:
for (int i = 0; i < I2S_OUT_PARALLEL_SIZE; i++) {
if (options->bck_gpios[i] > 0) {
i2s_out->bck_gpio_inv = options->bck_inv;
i2s_out->bck_gpios[i] = options->bck_gpios[i];
if (options->bck_gpios[i] > 0) {
i2s_out->bck_gpio_inv = options->bck_inv;
i2s_out->bck_gpios[i] = options->bck_gpios[i];

setup_gpio_pin(options->bck_gpios[i]);
setup_rtc_pin(options->bck_gpios[i]);
setup_gpio_pin(options->bck_gpios[i]);
setup_rtc_pin(options->bck_gpios[i]);

esp_rom_gpio_connect_out_signal(options->bck_gpios[i], i2s_bck_out_sig[i2s_out->port], options->bck_inv, false);
}
esp_rom_gpio_connect_out_signal(options->bck_gpios[i], i2s_bck_out_sig[i2s_out->port], options->bck_inv, false);
}

if (options->data_gpios[i] > 0) {
i2s_out->data_gpios[i] = options->data_gpios[i];
if (options->data_gpios[i] > 0) {
i2s_out->data_gpios[i] = options->data_gpios[i];

setup_gpio_pin(options->data_gpios[i]);
setup_rtc_pin(options->data_gpios[i]);
setup_gpio_pin(options->data_gpios[i]);
setup_rtc_pin(options->data_gpios[i]);

// data[0] is mapped to the most significant bit, which is OUT7
esp_rom_gpio_connect_out_signal(options->data_gpios[i], i2s_parallel8_data_out_sig[i2s_out->port] + 8 - i - 1, false, false);
}
esp_rom_gpio_connect_out_signal(options->data_gpios[i], data_out_sig, false, false);
}

if (options->inv_data_gpios[i] > 0) {
i2s_out->inv_data_gpios[i] = options->inv_data_gpios[i];
if (options->inv_data_gpios[i] > 0) {
i2s_out->inv_data_gpios[i] = options->inv_data_gpios[i];

setup_gpio_pin(options->inv_data_gpios[i]);
setup_rtc_pin(options->inv_data_gpios[i]);
setup_gpio_pin(options->inv_data_gpios[i]);
setup_rtc_pin(options->inv_data_gpios[i]);

// data[0] is mapped to the most significant bit, which is OUT7
esp_rom_gpio_connect_out_signal(options->inv_data_gpios[i], i2s_parallel8_data_out_sig[i2s_out->port] + 8 - i - 1, true, false);
}
}
// invert gpio output pin
esp_rom_gpio_connect_out_signal(options->inv_data_gpios[i], data_out_sig, true, false);
}
}

taskEXIT_CRITICAL(&i2s_out->mux);
Expand All @@ -203,7 +206,7 @@ void i2s_out_pin_teardown(struct i2s_out *i2s_out)

// place output into a safe state

for (int i = 0; i < I2S_OUT_PARALLEL_SIZE; i++) {
for (int i = 0; i < I2S_OUT_GPIO_PINS_MAX; i++) {
if (i2s_out->bck_gpios[i] >= 0) {
clear_gpio_pin(i2s_out->bck_gpios[i]);

Expand Down
6 changes: 3 additions & 3 deletions components/i2s_out/i2s_out.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ struct i2s_out {
SemaphoreHandle_t pin_mutex;
#if CONFIG_IDF_TARGET_ESP32
bool bck_gpio_inv;
gpio_num_t bck_gpios[I2S_OUT_PARALLEL_SIZE];
gpio_num_t data_gpios[I2S_OUT_PARALLEL_SIZE];
gpio_num_t inv_data_gpios[I2S_OUT_PARALLEL_SIZE];
gpio_num_t bck_gpios[I2S_OUT_GPIO_PINS_MAX];
gpio_num_t data_gpios[I2S_OUT_GPIO_PINS_MAX];
gpio_num_t inv_data_gpios[I2S_OUT_GPIO_PINS_MAX];
#endif

/* dma */
Expand Down
44 changes: 20 additions & 24 deletions components/i2s_out/include/i2s_out.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ typedef int i2s_port_t;
#define I2S_PORT_MAX 2

#define I2S_OUT_GPIO_PINS_SUPPORTED 1
#define I2S_OUT_GPIO_PINS_MAX 8
#define I2S_OUT_PARALLEL_SUPPORTED 1
#define I2S_OUT_PARALLEL_SIZE 8
#define I2S_OUT_PARALLEL_DATA_BITS_MAX 8

#define I2S_OUT_BASE_CLOCK (2 * APB_CLK_FREQ)

Expand Down Expand Up @@ -105,30 +106,25 @@ struct i2s_out_options {
TickType_t pin_timeout;

#if I2S_OUT_GPIO_PINS_SUPPORTED
// Use GPIO pin for bit clock out signal, -1 to disable
union {
gpio_num_t bck_gpio; // -1 to disable
# if I2S_OUT_PARALLEL_SUPPORTED
gpio_num_t bck_gpios[I2S_OUT_PARALLEL_SIZE]; // parallel
# endif
};
bool bck_inv; // invert bck signal

// Use GPIO pin for data out signal, -1 to disable
union {
gpio_num_t data_gpio; // serial
# if I2S_OUT_PARALLEL_SUPPORTED
gpio_num_t data_gpios[I2S_OUT_PARALLEL_SIZE]; // parallel
# endif
};
// Use GPIO pin > 0 for bit clock out signal
// Each gpio is a copy of the same clock out signal
gpio_num_t bck_gpios[I2S_OUT_GPIO_PINS_MAX];

// Use GPIO pin for inverted data out signal, -1 to disable
union {
gpio_num_t inv_data_gpio; // serial
# if I2S_OUT_PARALLEL_SUPPORTED
gpio_num_t inv_data_gpios[I2S_OUT_PARALLEL_SIZE]; // parallel
# endif
};
// Invert bck signal
bool bck_inv;

// Use GPIO pin > 0 for data out signal
// In serial mode, each gpio > 0 is a copy of the data bit
// In parallel mode, each gpio > 0 is a separate data bit up to parallel_data_bits, remaining ones repeat
gpio_num_t data_gpios[I2S_OUT_GPIO_PINS_MAX];

// Use GPIO pin > 0 for inverted data out signal
gpio_num_t inv_data_gpios[I2S_OUT_GPIO_PINS_MAX];
#endif

#if I2S_OUT_PARALLEL_SUPPORTED
// number of parallel data bits in use, 0 -> all
unsigned parallel_data_bits;
#endif
};

Expand Down
8 changes: 4 additions & 4 deletions components/leds/i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,24 @@
#endif

#if CONFIG_LEDS_I2S_ENABLED && I2S_OUT_PARALLEL_SUPPORTED
size_t leds_i2s_parallel_buffer_size(enum leds_protocol protocol, unsigned led_count, unsigned pin_count)
size_t leds_i2s_parallel_buffer_size(enum leds_protocol protocol, unsigned led_count, unsigned parallel)
{
const struct leds_protocol_type *protocol_type = leds_protocol_type(protocol);

if (protocol_type->i2s_interface_mode) {
return leds_interface_i2s_buffer_size(protocol_type->i2s_interface_mode, led_count, pin_count);
return leds_interface_i2s_buffer_size(protocol_type->i2s_interface_mode, led_count, parallel);
} else {
// not defined
return 0;
}
}

size_t leds_i2s_parallel_buffer_align(enum leds_protocol protocol, unsigned pin_count)
size_t leds_i2s_parallel_buffer_align(enum leds_protocol protocol, unsigned parallel)
{
const struct leds_protocol_type *protocol_type = leds_protocol_type(protocol);

if (protocol_type->i2s_interface_mode) {
return leds_interface_i2s_buffer_align(protocol_type->i2s_interface_mode, pin_count);
return leds_interface_i2s_buffer_align(protocol_type->i2s_interface_mode, parallel);
} else {
// not defined
return 0;
Expand Down
55 changes: 20 additions & 35 deletions components/leds/include/leds.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
#if CONFIG_LEDS_I2S_ENABLED
# include <i2s_out.h>
# define LEDS_I2S_GPIO_PINS_ENABLED I2S_OUT_GPIO_PINS_SUPPORTED
# define LEDS_I2S_DATA_PINS_ENABLED I2S_OUT_PARALLEL_SUPPORTED
# define LEDS_I2S_DATA_PINS_SIZE I2S_OUT_PARALLEL_SIZE
# define LEDS_I2S_GPIO_PINS_SIZE I2S_OUT_GPIO_PINS_MAX
# define LEDS_I2S_PARALLEL_ENABLED I2S_OUT_PARALLEL_SUPPORTED
# define LEDS_I2S_PARALLEL_MAX I2S_OUT_PARALLEL_DATA_BITS_MAX
#endif

#if CONFIG_LEDS_SPI_ENABLED && CONFIG_IDF_TARGET_ESP8266
Expand Down Expand Up @@ -219,39 +220,23 @@ enum leds_interface leds_interface_for_protocol(enum leds_protocol protocol);

TickType_t pin_timeout;

#if LEDS_I2S_GPIO_PINS_ENABLED
# if LEDS_I2S_DATA_PINS_ENABLED
unsigned data_pins_count; // default 0 -> serial output with a single data_pin
# endif

// use GPIO_NUM_NC < 0 to disable
union {
gpio_num_t data_pin; // for pin_count == 0 -> serial output
#if LEDS_I2S_DATA_PINS_ENABLED
gpio_num_t data_pins[LEDS_I2S_DATA_PINS_SIZE]; // for pin_count >= 1 -> parallel output
#endif
};

// use GPIO_NUM_NC < 0 to disable
union {
gpio_num_t inv_data_pin; // for pin_count == 0 -> serial output
#if LEDS_I2S_DATA_PINS_ENABLED
gpio_num_t inv_data_pins[LEDS_I2S_DATA_PINS_SIZE]; // for pin_count >= 1 -> parallel output
#endif
};
#endif

// only used for protocols with separate clock/data lines
int clock_rate;

#if LEDS_I2S_GPIO_PINS_ENABLED
// use GPIO_NUM_NC < 0 to disable
union {
gpio_num_t clock_pin;
#if LEDS_I2S_DATA_PINS_ENABLED
gpio_num_t clock_pins[LEDS_I2S_DATA_PINS_SIZE]; // for pin_count >= 1 -> parallel output
#endif
};
unsigned gpio_pins_count; // up to LEDS_I2S_GPIO_PINS_SIZE

// in serial mode, each pin outputs a copy of the same data signal
// in parallel mode, the first `parallel` pins each output their own data signal, and any remaining pins loop over to repeat the earlier data signals
gpio_num_t clock_pins[LEDS_I2S_GPIO_PINS_SIZE]; // use GPIO_NUM_NC <= 0 to disable
gpio_num_t data_pins[LEDS_I2S_GPIO_PINS_SIZE]; // use GPIO_NUM_NC <= 0 to disable
gpio_num_t inv_data_pins[LEDS_I2S_GPIO_PINS_SIZE]; // use GPIO_NUM_NC <= 0 to disable
#endif

#if LEDS_I2S_PARALLEL_ENABLED
// enable parallel mode with up to LEDS_I2S_PARALLEL_MAX separate outputs
// default 0 -> serial output with a single data signal
unsigned parallel;
#endif
};

Expand All @@ -263,14 +248,14 @@ enum leds_interface leds_interface_for_protocol(enum leds_protocol protocol);
size_t leds_i2s_serial_buffer_size(enum leds_protocol protocol, unsigned led_count);
size_t leds_i2s_serial_buffer_align(enum leds_protocol protocol);

#if LEDS_I2S_DATA_PINS_ENABLED
#if LEDS_I2S_PARALLEL_ENABLED
/*
* Returns total TX buffer size/align required for protocol with `led_count` LEDs across `pin_count` parallel pins.
* Returns total TX buffer size/align required for protocol with `led_count` LEDs across `parallel` pins.
*
* @return 0 if not supported for protocol
*/
size_t leds_i2s_parallel_buffer_size(enum leds_protocol protocol, unsigned led_count, unsigned pin_count);
size_t leds_i2s_parallel_buffer_align(enum leds_protocol protocol, unsigned pin_count);
size_t leds_i2s_parallel_buffer_size(enum leds_protocol protocol, unsigned led_count, unsigned parallel);
size_t leds_i2s_parallel_buffer_align(enum leds_protocol protocol, unsigned parallel);
#endif
#endif

Expand Down
Loading
Loading