diff --git a/components/esp_driver_parlio/test_apps/parlio/main/CMakeLists.txt b/components/esp_driver_parlio/test_apps/parlio/main/CMakeLists.txt index 070c011970..928db0ab8b 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/CMakeLists.txt +++ b/components/esp_driver_parlio/test_apps/parlio/main/CMakeLists.txt @@ -25,4 +25,6 @@ idf_component_register(SRCS ${srcs} if(CONFIG_SOC_BITSCRAMBLER_SUPPORTED) target_bitscrambler_add_src("test_parlio_tx_LSB_to_MSB.bsasm") target_bitscrambler_add_src("test_parlio_tx_multiply.bsasm") + target_bitscrambler_add_src("test_parlio_tx_in8_out32.bsasm") + target_bitscrambler_add_src("test_parlio_tx_in32_out8.bsasm") endif() diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_bitscrambler.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_bitscrambler.c index 7670128be3..da09362379 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_bitscrambler.c +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_bitscrambler.c @@ -21,13 +21,21 @@ BITSCRAMBLER_PROGRAM(bitscrambler_program_test_tx_LSB_to_MSB, "test_parlio_tx_LSB_to_MSB"); BITSCRAMBLER_PROGRAM(bitscrambler_program_test_tx_multiply, "test_parlio_tx_multiply"); +BITSCRAMBLER_PROGRAM(bitscrambler_program_test_tx_in8_out32, "test_parlio_tx_in8_out32"); +BITSCRAMBLER_PROGRAM(bitscrambler_program_test_tx_in32_out8, "test_parlio_tx_in32_out8"); + +typedef struct { + TaskHandle_t task; + size_t recv_bytes; +} test_parlio_bitscrambler_rx_ctx_t; TEST_PARLIO_CALLBACK_ATTR static bool test_parlio_rx_done_callback(parlio_rx_unit_handle_t rx_unit, const parlio_rx_event_data_t *edata, void *user_ctx) { BaseType_t high_task_wakeup = pdFALSE; - TaskHandle_t task = (TaskHandle_t)user_ctx; - vTaskNotifyGiveFromISR(task, &high_task_wakeup); + test_parlio_bitscrambler_rx_ctx_t *ctx = (test_parlio_bitscrambler_rx_ctx_t *)user_ctx; + ctx->recv_bytes = edata->recv_bytes; + vTaskNotifyGiveFromISR(ctx->task, &high_task_wakeup); return high_task_wakeup == pdTRUE; } @@ -105,10 +113,13 @@ static void test_parlio_bitscrambler(void) }; TEST_ESP_OK(parlio_new_rx_level_delimiter(&lvl_deli_cfg, &deli)); printf("register receive_done event callback\r\n"); + test_parlio_bitscrambler_rx_ctx_t rx_ctx = { + .task = xTaskGetCurrentTaskHandle(), + }; parlio_rx_event_callbacks_t rx_cbs = { .on_receive_done = test_parlio_rx_done_callback, }; - TEST_ESP_OK(parlio_rx_unit_register_event_callbacks(rx_unit, &rx_cbs, xTaskGetCurrentTaskHandle())); + TEST_ESP_OK(parlio_rx_unit_register_event_callbacks(rx_unit, &rx_cbs, &rx_ctx)); parlio_receive_config_t recv_config = { .delimiter = deli, @@ -121,11 +132,12 @@ static void test_parlio_bitscrambler(void) // Rx in MSB mode printf("enable parlio and transmit\r\n"); TEST_ESP_OK(parlio_tx_unit_enable(tx_unit)); - TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, 1)); + TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, true)); TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, rx_payload, TEST_PAYLOAD_SIZE, &recv_config)); TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, tx_payload, TEST_PAYLOAD_SIZE * sizeof(uint8_t) * 8, &transmit_config)); TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000))); + TEST_ASSERT_EQUAL(TEST_PAYLOAD_SIZE, rx_ctx.recv_bytes); for (int i = 0; i < TEST_PAYLOAD_SIZE; i++) { printf("%.3d ", (rx_payload[i])); @@ -148,6 +160,7 @@ static void test_parlio_bitscrambler(void) TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, tx_payload, TEST_PAYLOAD_SIZE * sizeof(uint8_t) * 8, &transmit_config)); TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000))); + TEST_ASSERT_EQUAL(TEST_PAYLOAD_SIZE, rx_ctx.recv_bytes); for (int i = 0; i < TEST_PAYLOAD_SIZE; i++) { printf("%.3d ", (rx_payload[i])); @@ -166,6 +179,7 @@ static void test_parlio_bitscrambler(void) TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, tx_payload, TEST_PAYLOAD_SIZE * sizeof(uint8_t) * 8, &transmit_config)); TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000))); + TEST_ASSERT_EQUAL(TEST_PAYLOAD_SIZE, rx_ctx.recv_bytes); for (int i = 0; i < TEST_PAYLOAD_SIZE; i++) { printf("%.3d ", (rx_payload[i])); @@ -187,3 +201,156 @@ TEST_CASE("parlio_tx_bitscrambler_test", "[parlio_bitscrambler]") { test_parlio_bitscrambler(); } + +#if SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA +static void test_parlio_bitscrambler_different_input_output_sizes(void) +{ + parlio_tx_unit_handle_t tx_unit = NULL; + parlio_tx_unit_config_t tx_config = { + .clk_src = PARLIO_CLK_SRC_DEFAULT, + .data_width = 4, + .clk_in_gpio_num = -1, // use internal clock source + .valid_gpio_num = TEST_VALID_GPIO, + .clk_out_gpio_num = TEST_CLK_GPIO, + .data_gpio_nums = { + TEST_DATA0_GPIO, + TEST_DATA1_GPIO, + TEST_DATA2_GPIO, + TEST_DATA3_GPIO, + }, + .output_clk_freq_hz = 1 * 1000 * 1000, + .trans_queue_depth = 8, + .max_transfer_size = 256, + .bit_pack_order = PARLIO_BIT_PACK_ORDER_LSB, + .sample_edge = PARLIO_SAMPLE_EDGE_POS, + }; + + parlio_rx_unit_handle_t rx_unit = NULL; + parlio_rx_unit_config_t rx_config = { + .trans_queue_depth = 10, + .max_recv_size = 1024, + .data_width = 4, + .clk_src = PARLIO_CLK_SRC_DEFAULT, + .ext_clk_freq_hz = 0, + .clk_in_gpio_num = -1, + .exp_clk_freq_hz = 1 * 1000 * 1000, + .clk_out_gpio_num = -1, + .valid_gpio_num = TEST_VALID_GPIO, + .data_gpio_nums = { + TEST_DATA0_GPIO, + TEST_DATA1_GPIO, + TEST_DATA2_GPIO, + TEST_DATA3_GPIO, + }, + .flags = { + .clk_gate_en = false, + } + }; + + printf("install parlio unit\r\n"); + TEST_ESP_OK(parlio_new_tx_unit(&tx_config, &tx_unit)); + TEST_ESP_OK(parlio_new_rx_unit(&rx_config, &rx_unit)); + + printf("decorate tx unit with bitscrambler\r\n"); + TEST_ESP_OK(parlio_tx_unit_decorate_bitscrambler(tx_unit)); + + parlio_transmit_config_t transmit_config = { + .idle_value = 0x00, + .bitscrambler_program = bitscrambler_program_test_tx_in32_out8, + }; + + parlio_rx_delimiter_handle_t deli = NULL; + parlio_rx_level_delimiter_config_t lvl_deli_cfg = { + .valid_sig_line_id = PARLIO_RX_UNIT_MAX_DATA_WIDTH - 1, + .sample_edge = PARLIO_SAMPLE_EDGE_POS, + .bit_pack_order = PARLIO_BIT_PACK_ORDER_LSB, + .eof_data_len = TEST_PAYLOAD_SIZE, + .timeout_ticks = 0, + .flags = { + .active_low_en = 0, + }, + }; + TEST_ESP_OK(parlio_new_rx_level_delimiter(&lvl_deli_cfg, &deli)); + printf("register receive_done event callback\r\n"); + test_parlio_bitscrambler_rx_ctx_t rx_ctx = { + .task = xTaskGetCurrentTaskHandle(), + }; + parlio_rx_event_callbacks_t rx_cbs = { + .on_receive_done = test_parlio_rx_done_callback, + }; + TEST_ESP_OK(parlio_rx_unit_register_event_callbacks(rx_unit, &rx_cbs, &rx_ctx)); + + parlio_receive_config_t recv_config = { + .delimiter = deli, + .flags.partial_rx_en = false, + }; + + uint8_t tx_payload[TEST_PAYLOAD_SIZE * 4] = {0}; + for (int i = 0; i < TEST_PAYLOAD_SIZE * 4; i++) { + tx_payload[i] = i; + } + + __attribute__((aligned(TEST_PAYLOAD_SIZE))) uint8_t rx_payload[TEST_PAYLOAD_SIZE] = {0}; + TEST_ESP_OK(parlio_tx_unit_enable(tx_unit)); + TEST_ESP_OK(parlio_rx_unit_enable(rx_unit, true)); + + // test input size is larger than output size + TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, rx_payload, TEST_PAYLOAD_SIZE, &recv_config)); + TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, tx_payload, 4 * TEST_PAYLOAD_SIZE * sizeof(uint8_t) * 8, &transmit_config)); + + TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000))); + TEST_ASSERT_EQUAL(TEST_PAYLOAD_SIZE, rx_ctx.recv_bytes); + + for (int i = 0; i < TEST_PAYLOAD_SIZE; i++) { + printf("%.3d ", (rx_payload[i])); + TEST_ASSERT_EQUAL(tx_payload[i * 4 + 3], rx_payload[i]); + if ((i + 1) % 16 == 0) { + printf("\n"); + } + } + printf("\n"); + + // test input size is smaller than output size + transmit_config.bitscrambler_program = bitscrambler_program_test_tx_in8_out32; + + TEST_ESP_OK(parlio_rx_unit_receive(rx_unit, rx_payload, TEST_PAYLOAD_SIZE, &recv_config)); + TEST_ESP_OK(parlio_tx_unit_transmit(tx_unit, tx_payload, (TEST_PAYLOAD_SIZE / 4) * sizeof(uint8_t) * 8, &transmit_config)); + + TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000))); + TEST_ASSERT_EQUAL(TEST_PAYLOAD_SIZE, rx_ctx.recv_bytes); + + for (int i = 0; i < TEST_PAYLOAD_SIZE / 4; i++) { + uint32_t *test_value = (uint32_t *)&rx_payload[i * 4]; + printf("0x%lx ", *test_value); + switch (i % 4) { + case 0: + TEST_ASSERT_EQUAL(0x11111, *test_value); + break; + case 1: + TEST_ASSERT_EQUAL(0x22222, *test_value); + break; + case 2: + TEST_ASSERT_EQUAL(0x33333, *test_value); + break; + case 3: + TEST_ASSERT_EQUAL(0x00000, *test_value); + break; + } + if ((i + 1) % 4 == 0) { + printf("\n"); + } + } + + TEST_ESP_OK(parlio_tx_unit_disable(tx_unit)); + TEST_ESP_OK(parlio_tx_unit_undecorate_bitscrambler(tx_unit)); + TEST_ESP_OK(parlio_del_tx_unit(tx_unit)); + TEST_ESP_OK(parlio_rx_unit_disable(rx_unit)); + TEST_ESP_OK(parlio_del_rx_delimiter(deli)); + TEST_ESP_OK(parlio_del_rx_unit(rx_unit)); +} + +TEST_CASE("parlio_tx_bitscrambler_different_input_output_sizes_test", "[parlio_bitscrambler]") +{ + test_parlio_bitscrambler_different_input_output_sizes(); +} +#endif // SOC_PARLIO_TX_SUPPORT_EOF_FROM_DMA diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx_in32_out8.bsasm b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx_in32_out8.bsasm new file mode 100644 index 0000000000..947003b2a8 --- /dev/null +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx_in32_out8.bsasm @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 + + +cfg prefetch true # enable data prefetch +cfg eof_on upstream # set EOF on upstream +cfg trailing_bytes 9 # due to prefetch is enable, upstream is 8 bytes ahead of downstream + +loop: + set 0..7 24..31, + + write 8, + read 32, + jmp loop diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx_in8_out32.bsasm b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx_in8_out32.bsasm new file mode 100644 index 0000000000..486430fc82 --- /dev/null +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_tx_in8_out32.bsasm @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 + +cfg prefetch false # disable data prefetch +cfg eof_on upstream # set EOF on upstream +cfg trailing_bytes 9 +cfg lut_width_bits 32 + +# Define contents that stored in the lookup table +lut 0x00011111 # index 0 +lut 0x00022222 # index 1 +lut 0x00033333 # index 2 +lut 0x00000000 # index 3 + +set 16..18 L # init the LUT index: 0 (0b000) + +loop: + read 8, + set 31..0 L31..L0, + write 32, + jmp loop