feat(driver): BitScrambler support

This adds an assembler for the BitScrambler assembly language,
plus unit tests for it. It also adds the loopback driver,
which can do BitScrambler operations on memory-to-memory
transfers. Documentation is also included.
This commit is contained in:
Jeroen Domburg
2023-12-06 15:13:45 +08:00
parent cc8bef395e
commit a88e719e33
74 changed files with 3419 additions and 2 deletions

View File

@@ -38,6 +38,12 @@ examples/peripherals/analog_comparator:
- esp_driver_gpio
- esp_driver_ana_cmpr
examples/peripherals/bitscrambler:
disable:
- if: SOC_BITSCRAMBLER_SUPPORTED != 1
depends_components:
- esp_driver_bitscrambler
examples/peripherals/camera/dvp_isp_dsi:
disable:
- if: SOC_ISP_DVP_SUPPORTED != 1 or SOC_MIPI_DSI_SUPPORTED != 1

View File

@@ -0,0 +1,8 @@
# For more information about build system see
# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(bitscrambler_example)

View File

@@ -0,0 +1,29 @@
| Supported Targets | ESP32-P4 |
| ----------------- | -------- |
# BitScrambler Loopback Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to load and control the BitScrambler. Specifically, the loopback mode of the BitScrambler is used to transform a buffer of data into a different format.
## How to Use Example
### Build and Flash
Build the project and flash it to the board, then run monitor tool to view serial output:
```
idf.py -p PORT build flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example Output
## Troubleshooting
For any technical queries, please open an [issue](https://github.com/espressif/esp-idf/issues) on GitHub. We will get back to you soon.

View File

@@ -0,0 +1,6 @@
idf_component_register(SRCS "bitscrambler_example_main.c"
PRIV_REQUIRES "esp_driver_bitscrambler"
INCLUDE_DIRS ".")
target_bitscrambler_add_src("example.bsasm")

View File

@@ -0,0 +1,63 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_check.h"
#include <stdio.h>
#include "driver/bitscrambler_loopback.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_heap_caps.h"
//Assign a symbol to the example bitscrambler program. Note that the actual
//assembly and including in the binary happens in the CMakeLists.txt file.
BITSCRAMBLER_PROGRAM(bitscrambler_program_example, "example");
static const char *TAG = "bs_example";
static const uint8_t testdata[] = {
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, //should give ff 00 ....
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, //should come out as 80 80 80...
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, //'unity matrix', should come out the same
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, //should come out as 00 ff 00 ff ...
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, //should come out as ff 00 ff 00 ...
};
void app_main(void)
{
ESP_LOGI(TAG, "BitScrambler example main");
uint8_t *data_in, *data_out;
int len = sizeof(testdata);
data_in = heap_caps_calloc(len, 1, MALLOC_CAP_DMA);
data_out = heap_caps_calloc(len, 1, MALLOC_CAP_DMA);
assert(data_in);
assert(data_out);
memcpy(data_in, testdata, len);
bitscrambler_handle_t bs;
ESP_ERROR_CHECK(bitscrambler_loopback_create(&bs, SOC_BITSCRAMBLER_ATTACH_I2S0, len));
ESP_ERROR_CHECK(bitscrambler_load_program(bs, bitscrambler_program_example));
size_t size;
ESP_ERROR_CHECK(bitscrambler_loopback_run(bs, data_in, len, data_out, len, &size));
bitscrambler_free(bs);
printf("BitScrambler program complete. Input %d, output %d bytes:\n", len, size);
for (int i = 0; i < size; i++) {
printf("%02X ", data_out[i]);
if ((i & 7) == 7) {
printf("\n");
}
}
printf("\n");
}

View File

@@ -0,0 +1,100 @@
# Example bitscrambler program. Reads in 8 bytes and spits out 8 bytes are
# the 'rotated' version of the input bytes. Specifically, output byte 0
# consists of bit 0 of input byte 0, bit 0 of input byte 1, bit 0 of input
# byte 2 etc. Output byte 1 consists of bit 1 of input byte 0, bit 1 of
# input byte 1, bit 1 of input byte 2, etc.
cfg trailing_bytes 64 #If we have an EOF on the input, we still
#need to process the 64 bits in M0/M1
cfg prefetch true #We expect M0/M1 to be filled
cfg lut_width_bits 8 #Not really applicable here
loop:
# Note: we start with 64 bits in M0 and M1, so we can immediately start outputting.
#output byte 0
set 0 0,
set 1 8,
set 2 16,
set 3 24,
set 4 32,
set 5 40,
set 6 48,
set 7 56,
#output byte 1
set 8 1,
set 9 9,
set 10 17,
set 11 25,
set 12 33,
set 13 41,
set 14 49,
set 15 57,
#output byte 2
set 16 2,
set 17 10,
set 18 18,
set 19 26,
set 20 34,
set 21 42,
set 22 50,
set 23 58,
#output byte 3
set 24 3,
set 25 11,
set 26 19,
set 27 27,
set 28 35,
set 29 43,
set 30 51,
set 31 59,
#as we can only write 32 bits at the same time, we write these and
#route the other 32 bits in the next instruction.
write 32
#2nd instruction: route the other 32 bits and write.
#output byte 4
set 0 4,
set 1 12,
set 2 20,
set 3 28,
set 4 36,
set 5 44,
set 6 52,
set 7 60,
#output byte 5
set 8 5,
set 9 13,
set 10 21,
set 11 29,
set 12 37,
set 13 45,
set 14 53,
set 15 61,
#output byte 6
set 16 6,
set 17 14,
set 18 22,
set 19 30,
set 20 38,
set 21 46,
set 22 54,
set 23 62,
#output byte 7
set 24 7,
set 25 15,
set 26 23,
set 27 31,
set 28 39,
set 29 47,
set 30 55,
set 31 63,
#Write these last 32 bits.
write 32,
#Note we can read the first half of the next 64 bits into the
#input buffer as the load happens at the end of the instruction.
read 32
#Read the 2nd half of the 64 bits in, and loop back to the start.
read 32,
jmp loop