mirror of
https://github.com/espressif/esp-sr.git
synced 2025-09-15 15:28:44 +08:00
feat: add unity ci for multinet
This commit is contained in:
parent
686ee06302
commit
f4d7793d68
10
test_apps/CMakeLists.txt
Normal file
10
test_apps/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
# This is the project CMakeLists.txt file for the test subproject
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# Include the components directory of the main application:
|
||||
#
|
||||
set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components"
|
||||
"../../esp-sr")
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(esp_sr_test)
|
||||
6230
test_apps/da_kai_kong_tiao.h
Normal file
6230
test_apps/da_kai_kong_tiao.h
Normal file
File diff suppressed because it is too large
Load Diff
15
test_apps/dependencies.lock
Normal file
15
test_apps/dependencies.lock
Normal file
@ -0,0 +1,15 @@
|
||||
dependencies:
|
||||
espressif/esp-dsp:
|
||||
component_hash: 59a67ce3be799201752ebde99890b0ab947054eff6463d83e944f2d4165d6905
|
||||
source:
|
||||
service_url: https://api.components.espressif.com/
|
||||
type: service
|
||||
version: 1.4.4
|
||||
idf:
|
||||
component_hash: null
|
||||
source:
|
||||
type: idf
|
||||
version: 5.0.2
|
||||
manifest_hash: 47ee996a7c9b6dd8cb942a47ad68d70a24d315c7af8e456eeb0945d3e9575eff
|
||||
target: esp32s3
|
||||
version: 1.0.0
|
||||
17
test_apps/main/CMakeLists.txt
Normal file
17
test_apps/main/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
if(IDF_TARGET STREQUAL "esp32s3")
|
||||
|
||||
set(srcs
|
||||
"test_app_main.c"
|
||||
"test_wakenet.c"
|
||||
"test_multinet.c"
|
||||
"test_afe.c"
|
||||
"test_chinese_tts.c"
|
||||
)
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES unity esp-sr
|
||||
WHOLE_ARCHIVE)
|
||||
|
||||
|
||||
endif()
|
||||
4025
test_apps/main/alexa.h
Normal file
4025
test_apps/main/alexa.h
Normal file
File diff suppressed because it is too large
Load Diff
6230
test_apps/main/da_kai_kong_tiao.h
Normal file
6230
test_apps/main/da_kai_kong_tiao.h
Normal file
File diff suppressed because it is too large
Load Diff
7554
test_apps/main/hilexin.h
Normal file
7554
test_apps/main/hilexin.h
Normal file
File diff suppressed because it is too large
Load Diff
5608
test_apps/main/tell_me_a_joke.h
Normal file
5608
test_apps/main/tell_me_a_joke.h
Normal file
File diff suppressed because it is too large
Load Diff
78
test_apps/main/test_afe.c
Normal file
78
test_apps/main/test_afe.c
Normal file
@ -0,0 +1,78 @@
|
||||
/* test_mean.c: Implementation of a testable component.
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "string.h"
|
||||
#include <limits.h>
|
||||
#include "unity.h"
|
||||
|
||||
#include "model_path.h"
|
||||
#include "esp_wn_iface.h"
|
||||
#include "esp_wn_models.h"
|
||||
#include "esp_afe_sr_models.h"
|
||||
#include "dl_lib_convq_queue.h"
|
||||
#include <sys/time.h>
|
||||
|
||||
TEST_CASE("audio_front_end create/destroy API & memory leak", "[afe]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_WN_PREFIX, NULL);
|
||||
|
||||
esp_afe_sr_iface_t *afe_handle = (esp_afe_sr_iface_t *)&ESP_AFE_SR_HANDLE;
|
||||
afe_config_t afe_config = AFE_CONFIG_DEFAULT();
|
||||
afe_config.memory_alloc_mode = AFE_MEMORY_ALLOC_MORE_PSRAM;
|
||||
afe_config.wakenet_init = true;
|
||||
afe_config.wakenet_model_name = model_name;
|
||||
afe_config.voice_communication_init = false;
|
||||
|
||||
|
||||
// test model loading time
|
||||
struct timeval tv_start, tv_end;
|
||||
gettimeofday(&tv_start, NULL);
|
||||
esp_afe_sr_data_t *afe_data = afe_handle->create_from_config(&afe_config);
|
||||
gettimeofday(&tv_end, NULL);
|
||||
int tv_ms = (tv_end.tv_sec - tv_start.tv_sec) * 1000 + (tv_end.tv_usec - tv_start.tv_usec) / 1000;
|
||||
printf("create latency:%d ms\n", tv_ms);
|
||||
|
||||
// test model memory concumption
|
||||
int create_size = start_size - heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int create_internal_size = start_internal_size - heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
printf("Internal RAM: %d, PSRAM:%d\n", create_internal_size, create_size - create_internal_size);
|
||||
afe_handle->destroy(afe_data);
|
||||
esp_srmodel_deinit(models);
|
||||
|
||||
// test memory leak
|
||||
int first_end_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int last_end_size = first_end_size;
|
||||
int mem_leak = start_size - last_end_size;
|
||||
printf("create&destroy times:%d, memory leak:%d\n", 1, mem_leak);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
printf("init partition ...\n");
|
||||
models = esp_srmodel_init("model");
|
||||
model_name = esp_srmodel_filter(models, ESP_WN_PREFIX, NULL);
|
||||
|
||||
printf("create ...\n");
|
||||
afe_data = afe_handle->create_from_config(&afe_config);
|
||||
|
||||
|
||||
printf("destroy ...\n");
|
||||
afe_handle->destroy(afe_data);
|
||||
esp_srmodel_deinit(models);
|
||||
|
||||
last_end_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
mem_leak = start_size - last_end_size;
|
||||
printf("create&destroy times:%d, memory leak:%d\n", i + 2, mem_leak);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL(true, (mem_leak) < 1000 && last_end_size == first_end_size);
|
||||
}
|
||||
55
test_apps/main/test_app_main.c
Normal file
55
test_apps/main/test_app_main.c
Normal file
@ -0,0 +1,55 @@
|
||||
/* Example test application for testable component.
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
|
||||
static void print_banner(const char* text);
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
/* These are the different ways of running registered tests.
|
||||
* In practice, only one of them is usually needed.
|
||||
*
|
||||
* UNITY_BEGIN() and UNITY_END() calls tell Unity to print a summary
|
||||
* (number of tests executed/failed/ignored) of tests executed between these calls.
|
||||
*/
|
||||
// print_banner("Executing one test by its name");
|
||||
// UNITY_BEGIN();
|
||||
// unity_run_test_by_name("Mean of an empty array is zero");
|
||||
// UNITY_END();
|
||||
|
||||
// print_banner("Running tests with [mean] tag");
|
||||
// UNITY_BEGIN();
|
||||
// unity_run_tests_by_tag("[mean]", false);
|
||||
// UNITY_END();
|
||||
|
||||
// print_banner("Running tests without [fails] tag");
|
||||
// UNITY_BEGIN();
|
||||
// unity_run_tests_by_tag("[fails]", true);
|
||||
// UNITY_END();
|
||||
|
||||
// print_banner("Running all the registered tests");
|
||||
// UNITY_BEGIN();
|
||||
// unity_run_all_tests();
|
||||
// UNITY_END();
|
||||
|
||||
// print_banner("Starting interactive test menu");
|
||||
/* This function will not return, and will be busy waiting for UART input.
|
||||
* Make sure that task watchdog is disabled if you use this function.
|
||||
*/
|
||||
unity_run_menu();
|
||||
// unity_run_all_tests();
|
||||
}
|
||||
|
||||
static void print_banner(const char* text)
|
||||
{
|
||||
printf("\n#### %s #####\n\n", text);
|
||||
}
|
||||
96
test_apps/main/test_chinese_tts.c
Normal file
96
test_apps/main/test_chinese_tts.c
Normal file
@ -0,0 +1,96 @@
|
||||
/* test_mean.c: Implementation of a testable component.
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "string.h"
|
||||
#include <limits.h>
|
||||
#include "unity.h"
|
||||
#include <sys/time.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_tts.h"
|
||||
#include "esp_tts_voice_xiaole.h"
|
||||
#include "esp_tts_voice_template.h"
|
||||
#include "esp_tts_player.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
TEST_CASE("chinese tts create/destroy API & memory leak", "[tts]")
|
||||
{
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
/*** 1. create esp tts handle ***/
|
||||
void* voicedata;
|
||||
const esp_partition_t* partition=esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "voice_data");
|
||||
assert(partition != NULL);
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
esp_partition_mmap_handle_t mmap_handle;
|
||||
ESP_ERROR_CHECK(esp_partition_mmap(partition, 0, partition->size, ESP_PARTITION_MMAP_DATA, &voicedata, &mmap_handle));
|
||||
#else
|
||||
spi_flash_mmap_handle_t mmap_handle;
|
||||
ESP_ERROR_CHECK(esp_partition_mmap(partition, 0, partition->size, SPI_FLASH_MMAP_DATA, &voicedata, &mmap_handle));
|
||||
#endif
|
||||
|
||||
// test model loading time
|
||||
struct timeval tv_start, tv_end;
|
||||
gettimeofday(&tv_start, NULL);
|
||||
esp_tts_voice_t *voice=esp_tts_voice_set_init(&esp_tts_voice_template, (int16_t*)voicedata);
|
||||
esp_tts_handle_t *tts_handle=esp_tts_create(voice);
|
||||
gettimeofday(&tv_end, NULL);
|
||||
int tv_ms = (tv_end.tv_sec - tv_start.tv_sec) * 1000 + (tv_end.tv_usec - tv_start.tv_usec) / 1000;
|
||||
printf("create latency:%d ms\n", tv_ms);
|
||||
|
||||
// test model memory concumption
|
||||
int create_size = start_size - heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int create_internal_size = start_internal_size - heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
printf("Internal RAM: %d, PSRAM:%d\n", create_internal_size, create_size - create_internal_size);
|
||||
|
||||
// test memory leak
|
||||
esp_tts_voice_set_free(voice);
|
||||
esp_tts_destroy(tts_handle);
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
esp_partition_munmap(mmap_handle); // support esp-idf v5
|
||||
#else
|
||||
spi_flash_munmap(mmap_handle); // support esp-idf v4
|
||||
#endif
|
||||
int first_end_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int last_end_size = first_end_size;
|
||||
int mem_leak = start_size - last_end_size;
|
||||
printf("create&destroy times:%d, memory leak:%d\n", 1, mem_leak);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
printf("init partition ...\n");
|
||||
partition=esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "voice_data");
|
||||
assert(partition != NULL);
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
ESP_ERROR_CHECK(esp_partition_mmap(partition, 0, partition->size, ESP_PARTITION_MMAP_DATA, &voicedata, &mmap_handle));
|
||||
#else
|
||||
ESP_ERROR_CHECK(esp_partition_mmap(partition, 0, partition->size, SPI_FLASH_MMAP_DATA, &voicedata, &mmap_handle));
|
||||
#endif
|
||||
|
||||
printf("create ...\n");
|
||||
voice=esp_tts_voice_set_init(&esp_tts_voice_template, (int16_t*)voicedata);
|
||||
tts_handle=esp_tts_create(voice);
|
||||
|
||||
printf("destroy ...\n");
|
||||
esp_tts_voice_set_free(voice);
|
||||
esp_tts_destroy(tts_handle);
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
esp_partition_munmap(mmap_handle); // support esp-idf v5
|
||||
#else
|
||||
spi_flash_munmap(mmap_handle); // support esp-idf v4
|
||||
#endif
|
||||
last_end_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
mem_leak = start_size - last_end_size;
|
||||
printf("create&destroy times:%d, memory leak:%d\n", i + 2, mem_leak);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL(true, (mem_leak) < 1000 && last_end_size == first_end_size);
|
||||
}
|
||||
416
test_apps/main/test_multinet.c
Normal file
416
test_apps/main/test_multinet.c
Normal file
@ -0,0 +1,416 @@
|
||||
/* test_mean.c: Implementation of a testable component.
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRAMTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include "string.h"
|
||||
#include <limits.h>
|
||||
#include "unity.h"
|
||||
|
||||
#include "model_path.h"
|
||||
#include "esp_mn_iface.h"
|
||||
#include "esp_mn_models.h"
|
||||
#include "da_kai_kong_tiao.h"
|
||||
#include "tell_me_a_joke.h"
|
||||
#include "alexa.h"
|
||||
#include "dl_lib_convq_queue.h"
|
||||
#include <sys/time.h>
|
||||
#include "esp_mn_speech_commands.h"
|
||||
#include "esp_process_sdkconfig.h"
|
||||
|
||||
TEST_CASE("multinet create/destroy API & memory leak", "[mn]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_MN_PREFIX, NULL);
|
||||
esp_mn_iface_t *multinet = esp_mn_handle_from_name(model_name);
|
||||
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
struct timeval tv_start, tv_end;
|
||||
gettimeofday(&tv_start, NULL);
|
||||
|
||||
model_iface_data_t *model_data = multinet->create(model_name, 6000);
|
||||
int create_size = start_size - heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int create_internal_size = start_internal_size - heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
printf("Internal RAM: %d, PSRAM:%d\n", create_internal_size, create_size-create_internal_size);
|
||||
|
||||
gettimeofday(&tv_end, NULL);
|
||||
int tv_ms=(tv_end.tv_sec-tv_start.tv_sec)*1000+(tv_end.tv_usec-tv_start.tv_usec)/1000;
|
||||
printf("create latency:%d ms\n", tv_ms);
|
||||
multinet->destroy(model_data);
|
||||
|
||||
int first_end_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int first_end_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
int last_end_size = first_end_size;
|
||||
int mem_leak = start_size - last_end_size;
|
||||
printf("create&destroy times:%d, memory leak:%d\n", 1, mem_leak);
|
||||
|
||||
|
||||
for (int i=0; i<3; i++) {
|
||||
printf("create ...\n");
|
||||
model_data = multinet->create(model_name, 6000);
|
||||
printf("destroy ...\n");
|
||||
multinet->destroy(model_data);
|
||||
last_end_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
mem_leak = start_size - last_end_size;
|
||||
printf("create&destroy times:%d, memory leak:%d\n", i+2, mem_leak);
|
||||
}
|
||||
|
||||
esp_srmodel_deinit(models);
|
||||
TEST_ASSERT_EQUAL(true, (mem_leak) < 1000 && last_end_size == first_end_size);
|
||||
}
|
||||
|
||||
TEST_CASE("multinet cpu loading", "[mn]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_MN_PREFIX, NULL);
|
||||
esp_mn_iface_t *multinet = esp_mn_handle_from_name(model_name);
|
||||
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
model_iface_data_t *model_data = multinet->create(model_name, 6000);
|
||||
int frequency = multinet->get_samp_rate(model_data);
|
||||
int audio_chunksize = multinet->get_samp_chunksize(model_data) * sizeof(int16_t);
|
||||
char *lang = multinet->get_language(model_data);
|
||||
esp_mn_commands_update_from_sdkconfig(multinet, model_data);
|
||||
unsigned char* data = NULL;
|
||||
int data_size = 0;
|
||||
if (strcmp(lang, ESP_MN_ENGLISH) == 0) {
|
||||
data = tell_me_a_joke;
|
||||
data_size = sizeof(tell_me_a_joke);
|
||||
printf("commands: tell me a joke, size:%d\n", data_size);
|
||||
} else if(strcmp(lang, ESP_MN_CHINESE) == 0) {
|
||||
data = da_kai_kong_tiao;
|
||||
data_size = sizeof(da_kai_kong_tiao);
|
||||
printf("commands: da kai kong tiao, size:%d\n", data_size);
|
||||
}
|
||||
|
||||
int16_t *buffer = malloc(audio_chunksize);
|
||||
int chunks = 0;
|
||||
struct timeval tv_start, tv_end;
|
||||
gettimeofday(&tv_start, NULL);
|
||||
esp_mn_state_t mn_state;
|
||||
|
||||
while (1) {
|
||||
if ((chunks + 1)*audio_chunksize <= data_size) {
|
||||
memcpy(buffer, data + chunks * audio_chunksize, audio_chunksize);
|
||||
} else {
|
||||
memset(buffer, 0, audio_chunksize);
|
||||
}
|
||||
mn_state = multinet->detect(model_data, buffer);
|
||||
if (mn_state == ESP_MN_STATE_DETECTED) {
|
||||
esp_mn_results_t *mn_result = multinet->get_results(model_data);
|
||||
if (mn_result > 0)
|
||||
printf("detected: command id:%d, string:%s\n",mn_result->command_id[0], mn_result->string);
|
||||
else
|
||||
printf("timeout\n");
|
||||
break;
|
||||
}
|
||||
chunks++;
|
||||
if (chunks > 600)
|
||||
break;
|
||||
}
|
||||
gettimeofday(&tv_end, NULL);
|
||||
int tv_ms=(tv_end.tv_sec-tv_start.tv_sec)*1000+(tv_end.tv_usec-tv_start.tv_usec)/1000;
|
||||
chunks -= 7;
|
||||
int run_ms = (chunks)*audio_chunksize/sizeof(int16_t)*1000/frequency;
|
||||
printf("Done! Took %d ms to parse %d ms worth of samples in %d iterations. CPU loading(single core):%.1f%%\n",
|
||||
tv_ms, run_ms, chunks, tv_ms*100.0/run_ms);
|
||||
|
||||
multinet->destroy(model_data);
|
||||
esp_srmodel_deinit(models);
|
||||
TEST_ASSERT_EQUAL(true, mn_state == ESP_MN_STATE_DETECTED);
|
||||
}
|
||||
|
||||
TEST_CASE("multinet set commands", "[mn]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_MN_PREFIX, NULL);
|
||||
esp_mn_iface_t *multinet = esp_mn_handle_from_name(model_name);
|
||||
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
model_iface_data_t *model_data = multinet->create(model_name, 6000);
|
||||
char *lang = multinet->get_language(model_data);
|
||||
esp_mn_error_t *error_phrases = NULL;
|
||||
printf("MODEL NAME %s\n", model_name);
|
||||
esp_err_t state = ESP_OK;
|
||||
|
||||
// first
|
||||
if (strcmp(lang, ESP_MN_ENGLISH) == 0) {
|
||||
if (strcmp(model_name, "mn5q8_en") == 0) {
|
||||
TEST_ESP_OK(esp_mn_commands_add(1, "TfL Mm c qbK"));
|
||||
TEST_ESP_OK(esp_mn_commands_add(2, "hicST qbK"));
|
||||
} else {
|
||||
TEST_ESP_OK(esp_mn_commands_add(1, "TURN ON THE LIGHT"));
|
||||
TEST_ESP_OK(esp_mn_commands_add(2, "TURN OFF THE KITCHEN LIGHT"));
|
||||
}
|
||||
error_phrases = esp_mn_commands_update();
|
||||
} else if(strcmp(lang, ESP_MN_CHINESE) == 0) {
|
||||
TEST_ESP_OK(esp_mn_commands_add(1, "da kai dian deng"));
|
||||
TEST_ESP_OK(esp_mn_commands_add(2, "guan bi chu fang dian deng"));
|
||||
error_phrases = esp_mn_commands_update();
|
||||
} else {
|
||||
printf("Invalid language\n");
|
||||
}
|
||||
TEST_ASSERT_EQUAL(true, error_phrases == NULL);
|
||||
|
||||
// second
|
||||
if (strcmp(lang, ESP_MN_ENGLISH) == 0) {
|
||||
if (strcmp(model_name, "mn5q8_en") == 0) {
|
||||
TEST_ESP_OK(esp_mn_commands_add(3, "TkN nN eL jc LiTS"));
|
||||
TEST_ESP_OK(esp_mn_commands_add(4, "TkN eF eL jc LiTS"));
|
||||
} else {
|
||||
TEST_ESP_OK(esp_mn_commands_add(3, "TURN OFF THE LIGHT"));
|
||||
TEST_ESP_OK(esp_mn_commands_add(4, "TURN OM THE KITCHEN LIGHT"));
|
||||
}
|
||||
error_phrases = esp_mn_commands_update();
|
||||
} else if(strcmp(lang, ESP_MN_CHINESE) == 0) {
|
||||
esp_mn_commands_add(3, "guan bi dian deng");
|
||||
esp_mn_commands_add(4, "da kai chu fang dian deng");
|
||||
error_phrases = esp_mn_commands_update();
|
||||
} else {
|
||||
printf("Invalid language\n");
|
||||
}
|
||||
|
||||
multinet->destroy(model_data);
|
||||
esp_srmodel_deinit(models);
|
||||
TEST_ASSERT_EQUAL(true, error_phrases == NULL);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("multinet add incorrect commands", "[mn]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_MN_PREFIX, NULL);
|
||||
esp_mn_iface_t *multinet = esp_mn_handle_from_name(model_name);
|
||||
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
model_iface_data_t *model_data = multinet->create(model_name, 6000);
|
||||
char *lang = multinet->get_language(model_data);
|
||||
esp_mn_error_t *error_phrases = NULL;
|
||||
esp_err_t state = ESP_OK;
|
||||
|
||||
if (strcmp(lang, ESP_MN_ENGLISH) == 0) {
|
||||
state = esp_mn_commands_add(1, "TURN ON THE LIGHT 123");
|
||||
assert(state == ESP_ERR_INVALID_STATE);
|
||||
state = esp_mn_commands_add(2, "TURN. OFF THE LIGHT?");
|
||||
assert(state == ESP_ERR_INVALID_STATE);
|
||||
} else if(strcmp(lang, ESP_MN_CHINESE) == 0) {
|
||||
if (strcmp(model_name, "mn6_cn_ac") == 0 || strcmp(model_name, "mn6_cn") == 0) {
|
||||
state = esp_mn_commands_add(1, "dakai dian deng");
|
||||
assert(state == ESP_ERR_INVALID_STATE);
|
||||
state = esp_mn_commands_add(2, "关闭电灯");
|
||||
assert(state == ESP_ERR_INVALID_STATE);
|
||||
} else {
|
||||
state = esp_mn_commands_add(1, "k");
|
||||
assert(state == ESP_ERR_INVALID_STATE);
|
||||
}
|
||||
} else {
|
||||
printf("Invalid language\n");
|
||||
}
|
||||
|
||||
multinet->destroy(model_data);
|
||||
esp_srmodel_deinit(models);
|
||||
TEST_ASSERT_EQUAL(true, error_phrases == NULL);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("multinet add duplicated commands", "[mn]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_MN_PREFIX, NULL);
|
||||
esp_mn_iface_t *multinet = esp_mn_handle_from_name(model_name);
|
||||
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
model_iface_data_t *model_data = multinet->create(model_name, 6000);
|
||||
char *lang = multinet->get_language(model_data);
|
||||
esp_mn_error_t *error_phrases = NULL;
|
||||
|
||||
if (strcmp(lang, ESP_MN_ENGLISH) == 0) {
|
||||
if (strcmp(model_name, "mn5q8_en") == 0) {
|
||||
esp_mn_commands_add(1, "TfL Mm c qbK");
|
||||
esp_mn_commands_add(1, "TfL Mm c qbK");
|
||||
} else {
|
||||
esp_mn_commands_add(1, "TURN ON THE LIGHT");
|
||||
esp_mn_commands_add(1, "TURN ON THE LIGHT");
|
||||
}
|
||||
} else if(strcmp(lang, ESP_MN_CHINESE) == 0) {
|
||||
esp_mn_commands_add(1, "da kai dian deng");
|
||||
esp_mn_commands_add(1, "da kai dian deng");
|
||||
} else {
|
||||
printf("Invalid language\n");
|
||||
}
|
||||
|
||||
multinet->destroy(model_data);
|
||||
esp_srmodel_deinit(models);
|
||||
TEST_ASSERT_EQUAL(true, error_phrases == NULL);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("multinet print active commands", "[mn]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_MN_PREFIX, NULL);
|
||||
esp_mn_iface_t *multinet = esp_mn_handle_from_name(model_name);
|
||||
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
model_iface_data_t *model_data = multinet->create(model_name, 6000);
|
||||
char *lang = multinet->get_language(model_data);
|
||||
esp_mn_commands_update_from_sdkconfig(multinet, model_data);
|
||||
|
||||
if (strcmp(lang, ESP_MN_ENGLISH) == 0) {
|
||||
if (strcmp(model_name, "mn5q8_en") == 0) {
|
||||
esp_mn_commands_add(1, "TfL Mm qbK");
|
||||
} else {
|
||||
esp_mn_commands_add(1, "THIS SHOULD NOT APPEAR IN ACTIVE COMMANDS");
|
||||
}
|
||||
} else if(strcmp(lang, ESP_MN_CHINESE) == 0) {
|
||||
esp_mn_commands_add(1, "bu ying gai chu xian zai biao zhong");
|
||||
} else {
|
||||
printf("Invalid language\n");
|
||||
}
|
||||
|
||||
multinet->print_active_speech_commands(model_data);
|
||||
|
||||
multinet->destroy(model_data);
|
||||
esp_srmodel_deinit(models);
|
||||
TEST_ASSERT_EQUAL(true, 1);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("multinet remove commands", "[mn]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_MN_PREFIX, NULL);
|
||||
esp_mn_iface_t *multinet = esp_mn_handle_from_name(model_name);
|
||||
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
model_iface_data_t *model_data = multinet->create(model_name, 6000);
|
||||
char *lang = multinet->get_language(model_data);
|
||||
esp_mn_error_t *error_phrases = NULL;
|
||||
esp_mn_commands_update_from_sdkconfig(multinet, model_data);
|
||||
|
||||
if (strcmp(lang, ESP_MN_ENGLISH) == 0) {
|
||||
if (strcmp(model_name, "mn5q8_en") == 0) {
|
||||
esp_mn_commands_remove("TfL Mm c qbK");
|
||||
} else {
|
||||
esp_mn_commands_remove("TURN ON THE LIGHT");;
|
||||
}
|
||||
} else if(strcmp(lang, ESP_MN_CHINESE) == 0) {
|
||||
esp_mn_commands_remove("da kai dian deng");
|
||||
} else {
|
||||
printf("Invalid language\n");
|
||||
}
|
||||
|
||||
esp_mn_commands_update();
|
||||
multinet->print_active_speech_commands(model_data);
|
||||
|
||||
multinet->destroy(model_data);
|
||||
esp_srmodel_deinit(models);
|
||||
TEST_ASSERT_EQUAL(true, 1);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("multinet clear and add commands", "[mn]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_MN_PREFIX, NULL);
|
||||
esp_mn_iface_t *multinet = esp_mn_handle_from_name(model_name);
|
||||
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
model_iface_data_t *model_data = multinet->create(model_name, 6000);
|
||||
char *lang = multinet->get_language(model_data);
|
||||
esp_mn_error_t *error_phrases = NULL;
|
||||
esp_mn_commands_update_from_sdkconfig(multinet, model_data);
|
||||
|
||||
esp_mn_commands_clear();
|
||||
|
||||
if (strcmp(lang, ESP_MN_ENGLISH) == 0) {
|
||||
if (strcmp(model_name, "mn5q8_en") == 0) {
|
||||
esp_mn_commands_add(1, "TfL Mm c qbK");
|
||||
} else {
|
||||
esp_mn_commands_add(1, "TURN ON THE LIGHT");
|
||||
}
|
||||
} else if(strcmp(lang, ESP_MN_CHINESE) == 0) {
|
||||
esp_mn_commands_add(1, "da kai dian deng");
|
||||
} else {
|
||||
printf("Invalid language\n");
|
||||
}
|
||||
|
||||
esp_mn_commands_update();
|
||||
esp_mn_commands_print();
|
||||
multinet->print_active_speech_commands(model_data);
|
||||
|
||||
if (strcmp(lang, ESP_MN_ENGLISH) == 0) {
|
||||
if (strcmp(model_name, "mn5q8_en") == 0) {
|
||||
esp_mn_commands_add(2, "Sgl c Sel");
|
||||
} else {
|
||||
esp_mn_commands_add(2, "SING A SONG");
|
||||
}
|
||||
} else if(strcmp(lang, ESP_MN_CHINESE) == 0) {
|
||||
esp_mn_commands_add(1, "guan bi dian deng");
|
||||
} else {
|
||||
printf("Invalid language\n");
|
||||
}
|
||||
|
||||
esp_mn_commands_update();
|
||||
esp_mn_commands_print();
|
||||
multinet->print_active_speech_commands(model_data);
|
||||
|
||||
multinet->destroy(model_data);
|
||||
esp_srmodel_deinit(models);
|
||||
TEST_ASSERT_EQUAL(true, 1);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("multinet modify commands", "[mn]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_MN_PREFIX, NULL);
|
||||
esp_mn_iface_t *multinet = esp_mn_handle_from_name(model_name);
|
||||
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
model_iface_data_t *model_data = multinet->create(model_name, 6000);
|
||||
char *lang = multinet->get_language(model_data);
|
||||
esp_mn_error_t *error_phrases = NULL;
|
||||
esp_mn_commands_update_from_sdkconfig(multinet, model_data);
|
||||
|
||||
if (strcmp(lang, ESP_MN_ENGLISH) == 0) {
|
||||
if (strcmp(model_name, "mn5q8_en") == 0) {
|
||||
esp_mn_commands_modify("TfL Mm c qbK", "TfL TfL Mm c qbK");
|
||||
} else {
|
||||
esp_mn_commands_modify("TURN ON THE LIGHT", "TURN ON THE KITCHEN LIGHT");
|
||||
}
|
||||
} else if(strcmp(lang, ESP_MN_CHINESE) == 0) {
|
||||
esp_mn_commands_modify("da kai dian deng", "da kai chu fang deng");
|
||||
} else {
|
||||
printf("Invalid language\n");
|
||||
}
|
||||
|
||||
esp_mn_commands_update();
|
||||
multinet->print_active_speech_commands(model_data);
|
||||
|
||||
multinet->destroy(model_data);
|
||||
esp_srmodel_deinit(models);
|
||||
TEST_ASSERT_EQUAL(true, 1);
|
||||
}
|
||||
121
test_apps/main/test_wakenet.c
Normal file
121
test_apps/main/test_wakenet.c
Normal file
@ -0,0 +1,121 @@
|
||||
/* test_mean.c: Implementation of a testable component.
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include "string.h"
|
||||
#include <limits.h>
|
||||
#include "unity.h"
|
||||
|
||||
#include "model_path.h"
|
||||
#include "esp_wn_iface.h"
|
||||
#include "esp_wn_models.h"
|
||||
#include "hilexin.h"
|
||||
#include "dl_lib_convq_queue.h"
|
||||
#include <sys/time.h>
|
||||
|
||||
TEST_CASE("wakenet create/destroy API & memory leak", "[wn]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
int start_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int start_internal_size = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_WN_PREFIX, NULL);
|
||||
esp_wn_iface_t *wakenet = esp_wn_handle_from_name(model_name);
|
||||
|
||||
// test model loading time
|
||||
struct timeval tv_start, tv_end;
|
||||
gettimeofday(&tv_start, NULL);
|
||||
model_iface_data_t *model_data = wakenet->create(model_name, DET_MODE_3CH_95);
|
||||
gettimeofday(&tv_end, NULL);
|
||||
int tv_ms = (tv_end.tv_sec - tv_start.tv_sec) * 1000 + (tv_end.tv_usec - tv_start.tv_usec) / 1000;
|
||||
printf("create latency:%d ms\n", tv_ms);
|
||||
|
||||
// test model memory concumption
|
||||
int create_size = start_size - heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int create_internal_size = start_internal_size - heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
printf("Internal RAM: %d, PSRAM:%d\n", create_internal_size, create_size - create_internal_size);
|
||||
wakenet->destroy(model_data);
|
||||
esp_srmodel_deinit(models);
|
||||
|
||||
// test memory leak
|
||||
int first_end_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
int last_end_size = first_end_size;
|
||||
int mem_leak = start_size - last_end_size;
|
||||
printf("create&destroy times:%d, memory leak:%d\n", 1, mem_leak);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
printf("init partition ...\n");
|
||||
models = esp_srmodel_init("model");
|
||||
model_name = esp_srmodel_filter(models, ESP_WN_PREFIX, NULL);
|
||||
wakenet = esp_wn_handle_from_name(model_name);
|
||||
|
||||
printf("create ...\n");
|
||||
// typedef enum {
|
||||
// DET_MODE_90 = 0, // Normal
|
||||
// DET_MODE_95 = 1, // Aggressive
|
||||
// DET_MODE_2CH_90 = 2,
|
||||
// DET_MODE_2CH_95 = 3,
|
||||
// DET_MODE_3CH_90 = 4,
|
||||
// DET_MODE_3CH_95 = 5,
|
||||
// } det_mode_t;
|
||||
model_data = wakenet->create(model_name, i);
|
||||
|
||||
printf("destroy ...\n");
|
||||
wakenet->destroy(model_data);
|
||||
esp_srmodel_deinit(models);
|
||||
|
||||
last_end_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
mem_leak = start_size - last_end_size;
|
||||
printf("create&destroy times:%d, memory leak:%d\n", i + 2, mem_leak);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL(true, (mem_leak) < 1000 && last_end_size == first_end_size);
|
||||
}
|
||||
|
||||
TEST_CASE("wakenet detect API & cpu loading", "[wn]")
|
||||
{
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
srmodel_list_t *models = esp_srmodel_init("model");
|
||||
char *model_name = esp_srmodel_filter(models, ESP_WN_PREFIX, NULL);
|
||||
esp_wn_iface_t *wakenet = esp_wn_handle_from_name(model_name);
|
||||
model_iface_data_t *model_data = wakenet->create(model_name, DET_MODE_95);
|
||||
int frequency = wakenet->get_samp_rate(model_data);
|
||||
int audio_chunksize = wakenet->get_samp_chunksize(model_data) * sizeof(int16_t);
|
||||
int16_t *buffer = malloc(audio_chunksize);
|
||||
int chunks = 0;
|
||||
int detected = 0;
|
||||
struct timeval tv_start, tv_end;
|
||||
gettimeofday(&tv_start, NULL);
|
||||
|
||||
while (1) {
|
||||
if ((chunks + 1)*audio_chunksize <= sizeof(hilexin)) {
|
||||
memcpy(buffer, hilexin + chunks * audio_chunksize, audio_chunksize);
|
||||
} else {
|
||||
memset(buffer, 0, audio_chunksize);
|
||||
}
|
||||
int res = wakenet->detect(model_data, buffer);
|
||||
if (res > 0) {
|
||||
detected = 1;
|
||||
}
|
||||
|
||||
chunks++;
|
||||
if (detected == 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
gettimeofday(&tv_end, NULL);
|
||||
int tv_ms = (tv_end.tv_sec - tv_start.tv_sec) * 1000 + (tv_end.tv_usec - tv_start.tv_usec) / 1000;
|
||||
int run_ms = (chunks) * audio_chunksize / sizeof(int16_t) * 1000 / frequency;
|
||||
float cpu_loading = tv_ms * 100.0 / run_ms;
|
||||
printf("Done! Took %d ms to parse %d ms worth of samples in %d iterations. CPU loading(single core):%.1f%%\n",
|
||||
tv_ms, run_ms, chunks, cpu_loading);
|
||||
|
||||
wakenet->destroy(model_data);
|
||||
esp_srmodel_deinit(models);
|
||||
TEST_ASSERT_EQUAL(true, (cpu_loading < 75 && detected == 1));
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
59a67ce3be799201752ebde99890b0ab947054eff6463d83e944f2d4165d6905
|
||||
56
test_apps/managed_components/espressif__esp-dsp/.gitignore
vendored
Normal file
56
test_apps/managed_components/espressif__esp-dsp/.gitignore
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
.config
|
||||
*.o
|
||||
*.pyc
|
||||
|
||||
# gtags
|
||||
GTAGS
|
||||
GRTAGS
|
||||
GPATH
|
||||
|
||||
# emacs
|
||||
.dir-locals.el
|
||||
|
||||
# emacs temp file suffixes
|
||||
*~
|
||||
.#*
|
||||
\#*#
|
||||
|
||||
# eclipse setting
|
||||
.settings
|
||||
|
||||
# MacOS directory files
|
||||
.DS_Store
|
||||
|
||||
# Example project files
|
||||
examples/**/sdkconfig
|
||||
examples/**/sdkconfig.old
|
||||
examples/**/build
|
||||
examples/**/dependencies.lock
|
||||
exmaples/**/managed_components
|
||||
|
||||
# Test app files
|
||||
test_app/build
|
||||
test_app/sdkconfig
|
||||
test_app/sdkconfig.old
|
||||
|
||||
# Doc build artifacts
|
||||
docs/_build/
|
||||
docs/doxygen-warning-log.txt
|
||||
docs/sphinx-warning-log.txt
|
||||
docs/sphinx-warning-log-sanitized.txt
|
||||
docs/xml/
|
||||
docs/xml_in/
|
||||
docs/man/
|
||||
docs/doxygen_sqlite3.db
|
||||
|
||||
TEST_LOGS
|
||||
|
||||
|
||||
# gcov coverage reports
|
||||
*.gcda
|
||||
*.gcno
|
||||
coverage.info
|
||||
coverage_report/
|
||||
|
||||
# VS Code Settings
|
||||
.vscode/
|
||||
64
test_apps/managed_components/espressif__esp-dsp/CHANGELOG.md
Normal file
64
test_apps/managed_components/espressif__esp-dsp/CHANGELOG.md
Normal file
@ -0,0 +1,64 @@
|
||||
# Esp-dsp Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- Target tests
|
||||
|
||||
### Fixed
|
||||
- Add Bi-Quad for esp32s3 into common CMakeLists.txt
|
||||
### Changed
|
||||
- Update documentation build
|
||||
|
||||
|
||||
### Removed
|
||||
|
||||
## [1.4.0] 2023-05-29
|
||||
|
||||
### Added
|
||||
- Complex signal generator dsps_cplx_gen()
|
||||
- FIR f32 filter optimized for esp32s3
|
||||
- Memcpy and Memset optimized for esp32s3
|
||||
|
||||
### Fixed
|
||||
- Fix in tests to pass
|
||||
- Minimum coeffcient length for fird_s16
|
||||
- Include malloc.h into dsps_fft4r_fc32_ansi.c
|
||||
- Fix for calculation length for dsps_corr_f32_axxx
|
||||
|
||||
### Changed
|
||||
|
||||
### Removed
|
||||
|
||||
## [1.3.0] 2023-03-10
|
||||
|
||||
### Added
|
||||
|
||||
- Fixed point FIR filter with decimation
|
||||
- Update tag to 1.2.1 for component manager
|
||||
- Extend dsp_power_of_two() to 32-bit value
|
||||
|
||||
### Fixed
|
||||
|
||||
- add various links to idf_component.yml, exclude unnecessary files
|
||||
- cmake: update component CMakeLists.txt file syntax to IDF v4.x+
|
||||
- docs: move instructions for contributors into CONTRIBUTING.md
|
||||
- docs: update README.md to use IDF component manager for installation
|
||||
- drop IDF v4.0 and v4.1 support, add a CI build with IDF release/v5.0
|
||||
- examples: remove GNU Make instructions from README files
|
||||
- examples: allow examples to be installed from the component manager
|
||||
- Fix for fft_cplx2reC_f32 function
|
||||
- Wno-format-fix related errors
|
||||
- Wrong path for extra component directory
|
||||
|
||||
### Changed
|
||||
|
||||
### Removed
|
||||
|
||||
## [1.2.0] 2022-09-22
|
||||
|
||||
160
test_apps/managed_components/espressif__esp-dsp/CMakeLists.txt
Normal file
160
test_apps/managed_components/espressif__esp-dsp/CMakeLists.txt
Normal file
@ -0,0 +1,160 @@
|
||||
set(srcs "modules/common/misc/dsps_pwroftwo.cpp"
|
||||
"modules/common/misc/aes3_tie_log.c"
|
||||
"modules/dotprod/float/dsps_dotprod_f32_ae32.S"
|
||||
"modules/dotprod/float/dsps_dotprod_f32_m_ae32.S"
|
||||
"modules/dotprod/float/dsps_dotprode_f32_ae32.S"
|
||||
"modules/dotprod/float/dsps_dotprode_f32_m_ae32.S"
|
||||
"modules/dotprod/float/dsps_dotprod_f32_ansi.c"
|
||||
"modules/dotprod/float/dsps_dotprode_f32_ansi.c"
|
||||
"modules/dotprod/float/dsps_dotprod_f32_aes3.S"
|
||||
|
||||
"modules/dotprod/fixed/dsps_dotprod_s16_ae32.S"
|
||||
"modules/dotprod/fixed/dsps_dotprod_s16_m_ae32.S"
|
||||
"modules/dotprod/fixed/dsps_dotprod_s16_ansi.c"
|
||||
|
||||
"modules/dotprod/float/dspi_dotprod_f32_ansi.c"
|
||||
"modules/dotprod/float/dspi_dotprod_off_f32_ansi.c"
|
||||
"modules/dotprod/fixed/dspi_dotprod_s16_ansi.c"
|
||||
"modules/dotprod/fixed/dspi_dotprod_u16_ansi.c"
|
||||
"modules/dotprod/fixed/dspi_dotprod_s8_ansi.c"
|
||||
"modules/dotprod/fixed/dspi_dotprod_u8_ansi.c"
|
||||
"modules/dotprod/fixed/dspi_dotprod_off_s16_ansi.c"
|
||||
"modules/dotprod/fixed/dspi_dotprod_off_u16_ansi.c"
|
||||
"modules/dotprod/fixed/dspi_dotprod_off_s8_ansi.c"
|
||||
"modules/dotprod/fixed/dspi_dotprod_off_u8_ansi.c"
|
||||
|
||||
"modules/dotprod/fixed/dspi_dotprod_s16_aes3.S"
|
||||
"modules/dotprod/fixed/dspi_dotprod_u16_aes3.S"
|
||||
"modules/dotprod/fixed/dspi_dotprod_off_s16_aes3.S"
|
||||
"modules/dotprod/fixed/dspi_dotprod_off_u16_aes3.S"
|
||||
"modules/dotprod/fixed/dspi_dotprod_s8_aes3.S"
|
||||
"modules/dotprod/fixed/dspi_dotprod_u8_aes3.S"
|
||||
"modules/dotprod/fixed/dspi_dotprod_off_u8_aes3.S"
|
||||
"modules/dotprod/fixed/dspi_dotprod_off_s8_aes3.S"
|
||||
|
||||
|
||||
"modules/matrix/float/dspm_mult_3x3x1_f32_ae32.S"
|
||||
"modules/matrix/float/dspm_mult_3x3x3_f32_ae32.S"
|
||||
"modules/matrix/float/dspm_mult_4x4x1_f32_ae32.S"
|
||||
"modules/matrix/float/dspm_mult_4x4x4_f32_ae32.S"
|
||||
"modules/matrix/float/dspm_mult_f32_ae32.S"
|
||||
"modules/matrix/float/dspm_mult_f32_aes3.S"
|
||||
"modules/matrix/float/dspm_mult_f32_ansi.c"
|
||||
"modules/matrix/fixed/dspm_mult_s16_ae32.S"
|
||||
"modules/matrix/fixed/dspm_mult_s16_m_ae32_vector.S"
|
||||
"modules/matrix/fixed/dspm_mult_s16_m_ae32.S"
|
||||
"modules/matrix/fixed/dspm_mult_s16_ansi.c"
|
||||
"modules/matrix/fixed/dspm_mult_s16_aes3.S"
|
||||
"modules/matrix/mat/mat.cpp"
|
||||
"modules/math/mulc/float/dsps_mulc_f32_ansi.c"
|
||||
"modules/math/addc/float/dsps_addc_f32_ansi.c"
|
||||
"modules/math/mulc/fixed/dsps_mulc_s16_ansi.c"
|
||||
"modules/math/mulc/fixed/dsps_mulc_s16_ae32.S"
|
||||
"modules/math/add/float/dsps_add_f32_ansi.c"
|
||||
"modules/math/add/fixed/dsps_add_s16_ansi.c"
|
||||
"modules/math/add/fixed/dsps_add_s16_ae32.S"
|
||||
"modules/math/sub/float/dsps_sub_f32_ansi.c"
|
||||
"modules/math/mul/float/dsps_mul_f32_ansi.c"
|
||||
"modules/math/mul/fixed/dsps_mul_s16_ansi.c"
|
||||
"modules/math/mulc/float/dsps_mulc_f32_ae32.S"
|
||||
"modules/math/addc/float/dsps_addc_f32_ae32.S"
|
||||
"modules/math/add/float/dsps_add_f32_ae32.S"
|
||||
"modules/math/sub/float/dsps_sub_f32_ae32.S"
|
||||
"modules/math/mul/float/dsps_mul_f32_ae32.S"
|
||||
"modules/math/sqrt/float/dsps_sqrt_f32_ansi.c"
|
||||
|
||||
"modules/fft/float/dsps_fft2r_fc32_ae32_.S"
|
||||
"modules/fft/float/dsps_fft2r_fc32_aes3_.S"
|
||||
"modules/fft/float/dsps_fft2r_fc32_ansi.c"
|
||||
"modules/fft/float/dsps_fft2r_fc32_ae32.c"
|
||||
"modules/fft/float/dsps_bit_rev_lookup_fc32_aes3.S"
|
||||
"modules/fft/float/dsps_fft4r_fc32_ansi.c"
|
||||
"modules/fft/float/dsps_fft4r_fc32_ae32.c"
|
||||
"modules/fft/float/dsps_fft2r_bitrev_tables_fc32.c"
|
||||
"modules/fft/float/dsps_fft4r_bitrev_tables_fc32.c"
|
||||
"modules/fft/fixed/dsps_fft2r_sc16_ae32.S"
|
||||
"modules/fft/fixed/dsps_fft2r_sc16_ansi.c"
|
||||
"modules/fft/fixed/dsps_fft2r_sc16_aes3.S"
|
||||
|
||||
"modules/dct/float/dsps_dct_f32.c"
|
||||
"modules/support/snr/float/dsps_snr_f32.cpp"
|
||||
"modules/support/sfdr/float/dsps_sfdr_f32.cpp"
|
||||
"modules/support/misc/dsps_d_gen.c"
|
||||
"modules/support/misc/dsps_h_gen.c"
|
||||
"modules/support/misc/dsps_tone_gen.c"
|
||||
"modules/support/cplx_gen/dsps_cplx_gen.c"
|
||||
"modules/support/cplx_gen/dsps_cplx_gen.S"
|
||||
"modules/support/cplx_gen/dsps_cplx_gen_init.c"
|
||||
"modules/support/mem/esp32s3/dsps_memset_aes3.S"
|
||||
"modules/support/mem/esp32s3/dsps_memcpy_aes3.S"
|
||||
"modules/support/view/dsps_view.cpp"
|
||||
"modules/windows/hann/float/dsps_wind_hann_f32.c"
|
||||
"modules/windows/blackman/float/dsps_wind_blackman_f32.c"
|
||||
"modules/windows/blackman_harris/float/dsps_wind_blackman_harris_f32.c"
|
||||
"modules/windows/blackman_nuttall/float/dsps_wind_blackman_nuttall_f32.c"
|
||||
"modules/windows/nuttall/float/dsps_wind_nuttall_f32.c"
|
||||
"modules/windows/flat_top/float/dsps_wind_flat_top_f32.c"
|
||||
"modules/conv/float/dsps_conv_f32_ansi.c"
|
||||
"modules/conv/float/dsps_conv_f32_ae32.S"
|
||||
"modules/conv/float/dsps_corr_f32_ansi.c"
|
||||
"modules/conv/float/dsps_corr_f32_ae32.S"
|
||||
"modules/conv/float/dsps_ccorr_f32_ansi.c"
|
||||
"modules/conv/float/dsps_ccorr_f32_ae32.S"
|
||||
"modules/iir/biquad/dsps_biquad_f32_ae32.S"
|
||||
"modules/iir/biquad/dsps_biquad_f32_aes3.S"
|
||||
"modules/iir/biquad/dsps_biquad_f32_ansi.c"
|
||||
"modules/iir/biquad/dsps_biquad_gen_f32.c"
|
||||
"modules/fir/float/dsps_fir_f32_ae32.S"
|
||||
"modules/fir/float/dsps_fir_f32_aes3.S"
|
||||
"modules/fir/float/dsps_fird_f32_ae32.S"
|
||||
"modules/fir/float/dsps_fir_f32_ansi.c"
|
||||
"modules/fir/float/dsps_fir_init_f32.c"
|
||||
"modules/fir/float/dsps_fird_f32_ansi.c"
|
||||
"modules/fir/float/dsps_fird_init_f32.c"
|
||||
"modules/fir/fixed/dsps_fird_init_s16.c"
|
||||
"modules/fir/fixed/dsps_fird_s16_ansi.c"
|
||||
"modules/fir/fixed/dsps_fird_s16_ae32.S"
|
||||
"modules/fir/fixed/dsps_fir_s16_m_ae32.S"
|
||||
"modules/fir/fixed/dsps_fird_s16_aes3.S"
|
||||
# EKF files
|
||||
"modules/kalman/ekf/common/ekf.cpp"
|
||||
"modules/kalman/ekf_imu13states/ekf_imu13states.cpp"
|
||||
)
|
||||
|
||||
|
||||
|
||||
set(include_dirs "modules/dotprod/include"
|
||||
"modules/support/include"
|
||||
"modules/support/mem/include"
|
||||
"modules/windows/include"
|
||||
"modules/windows/hann/include"
|
||||
"modules/windows/blackman/include"
|
||||
"modules/windows/blackman_harris/include"
|
||||
"modules/windows/blackman_nuttall/include"
|
||||
"modules/windows/nuttall/include"
|
||||
"modules/windows/flat_top/include"
|
||||
"modules/iir/include"
|
||||
"modules/fir/include"
|
||||
"modules/math/include"
|
||||
"modules/math/add/include"
|
||||
"modules/math/sub/include"
|
||||
"modules/math/mul/include"
|
||||
"modules/math/addc/include"
|
||||
"modules/math/mulc/include"
|
||||
"modules/math/sqrt/include"
|
||||
"modules/matrix/include"
|
||||
"modules/fft/include"
|
||||
"modules/dct/include"
|
||||
"modules/conv/include"
|
||||
"modules/common/include"
|
||||
# EKF files
|
||||
"modules/kalman/ekf/include"
|
||||
"modules/kalman/ekf_imu13states/include"
|
||||
)
|
||||
|
||||
set(priv_include_dirs "modules/dotprod/float"
|
||||
"modules/dotprod/fixed")
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS ${include_dirs}
|
||||
PRIV_INCLUDE_DIRS ${priv_include_dirs})
|
||||
@ -0,0 +1,64 @@
|
||||
# Contributing
|
||||
|
||||
Contributions to ESP-DSP project in the form of pull requests, bug reports, and feature requests are welcome!
|
||||
|
||||
This document covers various topics related to contributions to the ESP-DSP projects. Please read it if you plan to submit a PR!
|
||||
|
||||
## CLA
|
||||
|
||||
We require accepting the contributor's license agreement for all pull requests. When opening a pull request the first time you will be prompted to sign the CLA by the [CLA Assistant](https://cla-assistant.io/) service.
|
||||
|
||||
## Large-scale Changes
|
||||
|
||||
If you'd like to propose a change to the existing APIs or a large-scale refactoring of the implementation, we recommend opening an issue first to discuss this.
|
||||
|
||||
## Updating the Benchmarks Table
|
||||
|
||||
The benchmarks table [esp-dsp-benchmarks.rst](docs/esp-dsp-benchmarks.rst) contains benchmarks for ESP32 and ESP32-S3 CPUs. The benchmarks are collected with compiler optimizations for speed (-Os) and for size (-O2). This table may need to be updated if you have changed the implementations of some of the functions.
|
||||
|
||||
To build this table:
|
||||
|
||||
- Build the test application in the `test_app` directory.
|
||||
- Run "DSP Benchmarks data" test and copy the output into the CSV file [docs/esp_bm_results.csv](docs/esp_bm_results.csv).
|
||||
- Run the [docs/build_bm_table.py](docs/build_bm_table.py) script to update the benchmarks table [esp-dsp-benchmarks.rst](docs/esp-dsp-benchmarks.rst).
|
||||
|
||||
If you have added new functions, modify the [benchmarks test](test/test_dsp.c) to call these new functions.
|
||||
|
||||
## Supported IDF Versions
|
||||
|
||||
The component is expected to be usable with multiple supported IDF versions. You can find the list in the [CI workflow file](.gitlab-ci.yml).
|
||||
|
||||
Note that for compatibility reasons, the component has to support the legacy GNU Make build system which was present up until ESP-IDF v5.0. Remember to add or update `component.mk` and `Makefile` files when adding or changing examples. GNU Make support can be removed from ESP-DSP when IDF v4.4 maintenance period expires.
|
||||
|
||||
## Releasing a new version
|
||||
|
||||
Maintainers should follow the steps below to release a new version of ESP-DSP component. Assuming the new version is `vX.Y.Z`:
|
||||
|
||||
1. Ensure you are on the latest `master` branch, then create a new branch:
|
||||
```bash
|
||||
git checkout master
|
||||
git pull --ff-only origin master
|
||||
git checkout -b update_version_vX.Y.Z
|
||||
```
|
||||
1. Update the version in [idf_component.yml](idf_component.yml):
|
||||
```yml
|
||||
version: "X.Y.Z"
|
||||
```
|
||||
1. Commit the changes:
|
||||
```bash
|
||||
git add idf_component.yml
|
||||
git commit -s -m "version: update to vX.Y.Z"
|
||||
```
|
||||
1. Create the new tag:
|
||||
```bash
|
||||
git tag -s -a -m "vX.Y.Z" vX.Y.Z
|
||||
```
|
||||
1. Push the tag and the branch to the internal repository:
|
||||
```bash
|
||||
git push origin update_version_vX.Y.Z
|
||||
git push origin vX.Y.Z
|
||||
```
|
||||
1. Create the merge request, get it reviewed and merged.
|
||||
1. CI will automatically push the tag to Github and will upload the new version to the IDF Component Registry.
|
||||
1. Go to https://github.com/espressif/esp-dsp/releases and create a release from the tag vX.Y.Z.
|
||||
1. Write the release notes and publish the release.
|
||||
61
test_apps/managed_components/espressif__esp-dsp/Kconfig
Normal file
61
test_apps/managed_components/espressif__esp-dsp/Kconfig
Normal file
@ -0,0 +1,61 @@
|
||||
menu "DSP Library"
|
||||
|
||||
|
||||
config DSP_OPTIMIZATIONS_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3
|
||||
|
||||
choice DSP_OPTIMIZATION
|
||||
bool "DSP Optimization"
|
||||
default DSP_OPTIMIZED if DSP_OPTIMIZATIONS_SUPPORTED
|
||||
default DSP_ANSI
|
||||
help
|
||||
An ANSI C version could be used for verification and debug purpose,
|
||||
or for chips where an optimized version is not available.
|
||||
|
||||
config DSP_ANSI
|
||||
bool "ANSI C"
|
||||
config DSP_OPTIMIZED
|
||||
bool "Optimized"
|
||||
depends on DSP_OPTIMIZATIONS_SUPPORTED
|
||||
endchoice
|
||||
|
||||
config DSP_OPTIMIZATION
|
||||
int
|
||||
default 0 if DSP_ANSI
|
||||
default 1 if DSP_OPTIMIZED
|
||||
|
||||
choice DSP_MAX_FFT_SIZE
|
||||
bool "Maximum FFT length"
|
||||
default DSP_MAX_FFT_SIZE_4096
|
||||
help
|
||||
This is default FFT size for internal usage.
|
||||
|
||||
config DSP_MAX_FFT_SIZE_512
|
||||
bool "512"
|
||||
config DSP_MAX_FFT_SIZE_1024
|
||||
bool "1024"
|
||||
config DSP_MAX_FFT_SIZE_2048
|
||||
bool "2048"
|
||||
config DSP_MAX_FFT_SIZE_4096
|
||||
bool "4096"
|
||||
config DSP_MAX_FFT_SIZE_8192
|
||||
bool "8192"
|
||||
config DSP_MAX_FFT_SIZE_16384
|
||||
bool "16384"
|
||||
config DSP_MAX_FFT_SIZE_32768
|
||||
bool "32768"
|
||||
endchoice
|
||||
|
||||
config DSP_MAX_FFT_SIZE
|
||||
int
|
||||
default 512 if DSP_MAX_FFT_SIZE_512
|
||||
default 1024 if DSP_MAX_FFT_SIZE_1024
|
||||
default 2048 if DSP_MAX_FFT_SIZE_2048
|
||||
default 4096 if DSP_MAX_FFT_SIZE_4096
|
||||
default 8192 if DSP_MAX_FFT_SIZE_8192
|
||||
default 16384 if DSP_MAX_FFT_SIZE_16384
|
||||
default 32768 if DSP_MAX_FFT_SIZE_32768
|
||||
|
||||
endmenu
|
||||
202
test_apps/managed_components/espressif__esp-dsp/LICENSE
Normal file
202
test_apps/managed_components/espressif__esp-dsp/LICENSE
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
82
test_apps/managed_components/espressif__esp-dsp/README.md
Normal file
82
test_apps/managed_components/espressif__esp-dsp/README.md
Normal file
@ -0,0 +1,82 @@
|
||||
[](https://components.espressif.com/components/espressif/esp-dsp)
|
||||
|
||||
# Espressif DSP Library
|
||||
|
||||
ESP-DSP is the official DSP library for [ESP32](https://espressif.com/en/products/hardware/esp32/overview) and [ESP32-S3](https://espressif.com/en/products/hardware/esp32s3/overview) chips.
|
||||
|
||||
## Overview
|
||||
|
||||
ESP-DSP is intended to be used as an [ESP-IDF](https://github.com/espressif/esp-idf) component. For the introduction to ESP-IDF, refer to the [ESP-IDF Programming Guide](https://docs.espressif.com/projects/esp-idf/en/latest/).
|
||||
|
||||
The ESP-DSP library includes implementations of the following functions:
|
||||
- Matrix multiplication: [reference](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-apis.html#matrix-operations-apis)
|
||||
- Dot product: [reference](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-apis.html#dot-product), [example](https://github.com/espressif/esp-dsp/tree/master/examples/dotprod)
|
||||
- FFT: [reference](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-apis.html#fft), [example](https://github.com/espressif/esp-dsp/tree/master/examples/fft)
|
||||
- IIR: [reference](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-apis.html#iir), [example](https://github.com/espressif/esp-dsp/tree/master/examples/iir)
|
||||
- FIR: [reference](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-apis.html#fir)
|
||||
- Vector math operations: [reference](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-apis.html#math)
|
||||
- Kalman filter: [reference](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-apis.html#kalman)
|
||||
|
||||
Many of the library functions are written in assembly and are optimized for the CPU configuration used in the ESP32. In addition to the optimized implementations, reference implementations written in ANSI C are provided.
|
||||
|
||||
Function implementations are provided for single precision floating point (32-bit float), and 16-bit signed integers.
|
||||
|
||||
## Documentation
|
||||
|
||||
- [ESP-DSP Overview](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-library.html)
|
||||
- [ESP-DSP API Reference](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-apis.html)
|
||||
- [ESP-DSP Benchmarks](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-benchmarks.html)
|
||||
|
||||
Documentation found in the above links is automatically generated from the contents of this repository. If you find that some information is missing or incomplete, please report an issue.
|
||||
|
||||
## Installation and Usage
|
||||
|
||||
The ESP-DSP library is a component for the [ESP-IDF build system](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html).
|
||||
|
||||
The recommended way to use the component is to install it from the [IDF Component Registry](https://components.espressif.com/components/espressif/esp-dsp).
|
||||
|
||||
### Adding ESP-DSP component to an existing project
|
||||
|
||||
In the project directory, run:
|
||||
```bash
|
||||
idf.py add-dependency "espressif/esp-dsp"
|
||||
```
|
||||
This will add the esp-dsp component as a dependency to the `main` component of your project. You can also add it by editing the `idf_component.yml` file manually.
|
||||
|
||||
### Downloading ESP-DSP examples
|
||||
|
||||
You can download the example projects from the IDF Component Registry website or use the `idf.py create-project-from-example` command. For example:
|
||||
|
||||
```bash
|
||||
idf.py create-project-from-example "espressif/esp-dsp:basic_math"
|
||||
```
|
||||
|
||||
Please refer to the [IDF Component Registry](https://components.espressif.com/components/espressif/esp-dsp) for the download links and the instructions.
|
||||
|
||||
You can also use Git to clone this repository and find all the examples in the `examples/` subdirectory. For the list of the examples, please see [README.md](examples/README.md) in the examples directory.
|
||||
|
||||
### Building and running ESP-DSP examples
|
||||
|
||||
Build, flash and monitor as this is usually done for ESP-IDF projects:
|
||||
|
||||
```bash
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
where `PORT` is the UART port name of your development board, such as `/dev/ttyUSB0` or `COM1`.
|
||||
|
||||
Note that you need to set up ESP-IDF before building the project. Refer to the [ESP-IDF Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) if you don't have the environment set up yet.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
If you have found an issue in ESP-DSP, or wish to submit an enhancement request, please use the [Issues](https://github.com/espressif/esp-dsp/issues) section on Github.
|
||||
|
||||
For general questions related to this library, please use the [esp32.com forum](https://esp32.com/).
|
||||
|
||||
## Contributing to ESP-DSP
|
||||
|
||||
Please check [CONTRIBUTING.md](CONTRIBUTING.md) if you'd like to contribute to ESP-DSP.
|
||||
|
||||
## Copyrights and License
|
||||
|
||||
All original source code in this repository is Copyright (C) 2018-2023 Espressif Systems. This source code is licensed under the Apache License 2.0 as described in the file LICENSE.
|
||||
84
test_apps/managed_components/espressif__esp-dsp/build_all.sh
Executable file
84
test_apps/managed_components/espressif__esp-dsp/build_all.sh
Executable file
@ -0,0 +1,84 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Build the test app and all examples from the examples directory.
|
||||
# Expects EXAMPLE_TARGETS and TEST_TARGETS environment variables to be set.
|
||||
# Each variable is the list of IDF_TARGET values to build the examples and
|
||||
# the test app for, respectively.
|
||||
#
|
||||
# -----------------------------------------------------------------------------
|
||||
# Safety settings (see https://gist.github.com/ilg-ul/383869cbb01f61a51c4d).
|
||||
|
||||
if [[ -n "${DEBUG_SHELL}" ]]
|
||||
then
|
||||
set -x # Activate the expand mode if DEBUG is anything but empty.
|
||||
fi
|
||||
|
||||
if [[ -z "${EXAMPLE_TARGETS}" || -z "${TEST_TARGETS}" ]]
|
||||
then
|
||||
echo "EXAMPLE_TARGETS and TEST_TARGETS environment variables must be set before calling this script"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${SKIP_GNU_MAKE_BUILD}" ]]
|
||||
then
|
||||
echo "SKIP_GNU_MAKE_BUILD not set, will build with GNU Make based build system as well."
|
||||
export SKIP_GNU_MAKE_BUILD=0
|
||||
fi
|
||||
|
||||
set -o errexit # Exit if command failed.
|
||||
set -o pipefail # Exit if pipe failed.
|
||||
set -o nounset # Exit if variable not set.
|
||||
|
||||
|
||||
STARS='***************************************************'
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
die() {
|
||||
echo "${1:-"Unknown Error"}" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# build_for_targets <target list>
|
||||
# call this in the project directory
|
||||
function build_for_targets
|
||||
{
|
||||
target_list="$1"
|
||||
for IDF_TARGET in ${target_list}
|
||||
do
|
||||
export IDF_TARGET
|
||||
if [[ "${IDF_TARGET}" = "esp32" ]] && [[ "${SKIP_GNU_MAKE_BUILD}" = "0" ]]
|
||||
then
|
||||
echo "${STARS}"
|
||||
echo "Building in $PWD with Make"
|
||||
# -j option will be set via MAKEFLAGS in .gitlab-ci.yml
|
||||
# shellcheck disable=SC2015
|
||||
make defconfig && make || die "Make build in ${PWD} has failed"
|
||||
rm -rf build
|
||||
fi
|
||||
|
||||
echo "${STARS}"
|
||||
echo "Building in $PWD with CMake for ${IDF_TARGET}"
|
||||
rm -f sdkconfig
|
||||
idf.py set-target "${IDF_TARGET}"
|
||||
idf.py build || die "CMake build in ${PWD} has failed for ${IDF_TARGET}"
|
||||
idf.py fullclean || true
|
||||
done
|
||||
}
|
||||
|
||||
# Build the test app
|
||||
echo "${STARS}"
|
||||
pushd test_app
|
||||
build_for_targets "${TEST_TARGETS}"
|
||||
popd
|
||||
|
||||
# Build the examples
|
||||
pushd examples
|
||||
EXAMPLES=$(find . -maxdepth 1 -mindepth 1 -type d | cut -d '/' -f 2)
|
||||
for NAME in ${EXAMPLES}
|
||||
do
|
||||
pushd "${NAME}"
|
||||
build_for_targets "${EXAMPLE_TARGETS}"
|
||||
popd
|
||||
done
|
||||
popd
|
||||
@ -0,0 +1,20 @@
|
||||
# ESP-DSP Examples
|
||||
|
||||
This directory contains a range of examples for ESP-DSP library.
|
||||
|
||||
These examples are intended to demonstrate part of ESP-DSP functionality (e.g. initialization, execution) and to provide code that you can copy and adapt into your own projects.
|
||||
|
||||
See the [README.md](../README.md) file in the upper level directory for more information about ESP-DSP.
|
||||
|
||||
# Example Layout
|
||||
|
||||
The examples are grouped into subdirectories by category. Each category directory contains one or more example projects:
|
||||
|
||||
* [Dot Product Calculation](./dotprod/README.md) Example
|
||||
* [Basic Math Operations](./basic_math/README.md) Example
|
||||
* [FFT](./fft/README.md) Example
|
||||
* [Matrix](./matrix/README.md) Example
|
||||
* [FFT Window](./fft_window/README.md) Example
|
||||
* [IIR Filter](./iir/README.md) Example
|
||||
* [Kalman Filter](./kalman/README.md) Example
|
||||
* [FIR Filter](.fir/README.md) Example
|
||||
@ -0,0 +1,6 @@
|
||||
# The following 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.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(basic_math)
|
||||
@ -0,0 +1,75 @@
|
||||
# Basic Math Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to use basic math functions from esp-dsp library. Example does the following steps:
|
||||
|
||||
1. Initialize the library
|
||||
2. Initialize input signals with 1024 samples
|
||||
3. Apply window to input signal by standard C loop.
|
||||
4. Calculate FFT for 1024 complex samples and show the result
|
||||
5. Show results on the plots
|
||||
6. Apply window to input signal by basic math functions dsps_mul_f32 and dsps_mulc_f32.
|
||||
7. Calculate FFT for 1024 complex samples
|
||||
8. Show results on the plots
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware required
|
||||
|
||||
This example does not require any special hardware, and can be run on any common development board.
|
||||
|
||||
### Configure the project
|
||||
|
||||
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
|
||||
|
||||
### Build and flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
|
||||
|
||||
```
|
||||
idf.py -p PORT 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
|
||||
|
||||
Here is an typical example console output.
|
||||
|
||||
```bash
|
||||
I (132) main: *** Start Example. ***
|
||||
I (132) main: *** Multiply tone signal with Hann window by standard C loop. ***
|
||||
I (152) view: Data min[432] = -173.749878, Data max[205] = 23.849705
|
||||
________________________________________________________________
|
||||
0 | |
|
||||
1 | |
|
||||
2 | |
|
||||
3 || |
|
||||
4 | | |
|
||||
5 || | |
|
||||
6 ||| || |
|
||||
7 ||||| |||| |
|
||||
8||||||||||||||| |||||| |
|
||||
9 |||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (162) view: Plot: Length=512, min=-120.000000, max=40.000000
|
||||
I (162) main: *** Multiply tone signal with Hann window by esp-dsp basic math functions. ***
|
||||
I (162) view: Data min[432] = -173.749878, Data max[205] = 23.849705
|
||||
________________________________________________________________
|
||||
0 | |
|
||||
1 | |
|
||||
2 | |
|
||||
3 || |
|
||||
4 | | |
|
||||
5 || | |
|
||||
6 ||| || |
|
||||
7 ||||| |||| |
|
||||
8||||||||||||||| |||||| |
|
||||
9 |||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (172) view: Plot: Length=512, min=-120.000000, max=40.000000
|
||||
I (172) main: *** End Example. ***
|
||||
```
|
||||
@ -0,0 +1 @@
|
||||
idf_component_register(SRCS "dsps_math_main.c")
|
||||
@ -0,0 +1,96 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "soc/gpio_struct.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "esp_dsp.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// This example shows how to use FFT from esp-dsp library
|
||||
|
||||
#define N_SAMPLES 1024
|
||||
int N = N_SAMPLES;
|
||||
// Input test array
|
||||
__attribute__((aligned(16)))
|
||||
float x1[N_SAMPLES];
|
||||
// Window coefficients
|
||||
__attribute__((aligned(16)))
|
||||
float wind[N_SAMPLES];
|
||||
// working complex array
|
||||
__attribute__((aligned(16)))
|
||||
float y_cf[N_SAMPLES*2];
|
||||
// Pointers to result arrays
|
||||
float* y1_cf = &y_cf[0];
|
||||
|
||||
static void process_and_show(float* data, int length)
|
||||
{
|
||||
dsps_fft2r_fc32(data, length);
|
||||
// Bit reverse
|
||||
dsps_bit_rev_fc32(data, length);
|
||||
// Convert one complex vector to two complex vectors
|
||||
dsps_cplx2reC_fc32(data, length);
|
||||
|
||||
for (int i = 0 ; i < length/2 ; i++) {
|
||||
data[i] = 10 * log10f((data[i * 2 + 0] * data[i * 2 + 0] + data[i * 2 + 1] * data[i * 2 + 1])/N);
|
||||
}
|
||||
|
||||
// Show power spectrum in 64x10 window from -100 to 0 dB from 0..N/4 samples
|
||||
dsps_view(data, length/2, 64, 10, -120, 40, '|');
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
esp_err_t ret;
|
||||
ESP_LOGI(TAG, "*** Start Example. ***");
|
||||
ret = dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate Hann window
|
||||
dsps_wind_hann_f32(wind, N);
|
||||
|
||||
ESP_LOGI(TAG, "*** Multiply tone signal with Hann window by standard C loop. ***");
|
||||
// Generate input signal
|
||||
dsps_tone_gen_f32(x1, N, 1., 0.2, 0);
|
||||
// Convert two input vectors to one complex vector
|
||||
for (int i=0 ; i< N ; i++)
|
||||
{
|
||||
y_cf[i*2 + 0] = x1[i]*wind[i];
|
||||
y_cf[i*2 + 1] = 0;
|
||||
}
|
||||
process_and_show(y_cf, N);
|
||||
|
||||
ESP_LOGI(TAG, "*** Multiply tone signal with Hann window by esp-dsp basic math functions. ***");
|
||||
// Convert two input vectors to one complex vector with basic functions
|
||||
dsps_mul_f32(x1, wind, y_cf, N, 1, 1, 2); // Multiply input array with window and store as real part
|
||||
dsps_mulc_f32(&y_cf[1], &y_cf[1], N, 0, 2, 2); // Clear imaginary part of the complex signal
|
||||
process_and_show(y_cf, N);
|
||||
ESP_LOGI(TAG, "*** End Example. ***");
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/esp-dsp:
|
||||
override_path: "../../../"
|
||||
version: "*"
|
||||
@ -0,0 +1,6 @@
|
||||
# The following 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.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(dotprod)
|
||||
@ -0,0 +1,42 @@
|
||||
# Dot Product Calculation Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to use dotprod dsps_dotprod_f32 from esp-dsp library. Example does the following steps:
|
||||
|
||||
1. Initialize the input arrays
|
||||
2. Calculate dot product of two arrays
|
||||
3. Compare results and calculate execution time in cycles.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware required
|
||||
|
||||
This example does not require any special hardware, and can be run on any common development board.
|
||||
|
||||
### Configure the project
|
||||
|
||||
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
|
||||
|
||||
### Build and flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
|
||||
|
||||
```
|
||||
idf.py -p PORT 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
|
||||
|
||||
Here is an typical example console output.
|
||||
|
||||
```
|
||||
I (55) main: Start Example.
|
||||
I (55) main: The sum of 101 elements from 0..100 = 5050.000000
|
||||
I (55) main: Operation for 101 samples took 1381 cycles
|
||||
I (65) main: End Example.
|
||||
```
|
||||
@ -0,0 +1 @@
|
||||
idf_component_register(SRCS "dsps_dotproduct_main.c")
|
||||
@ -0,0 +1,65 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "soc/gpio_struct.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "soc/uart_struct.h"
|
||||
|
||||
#include "esp_dsp.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// This example shows how to use dsps_dotprod_f32 and dsps_dotprode_f32 functions
|
||||
|
||||
#define N_SAMPLES 256
|
||||
int N = N_SAMPLES;
|
||||
__attribute__((aligned(16)))
|
||||
float input1[N_SAMPLES];
|
||||
__attribute__((aligned(16)))
|
||||
float input2[N_SAMPLES];
|
||||
|
||||
void app_main()
|
||||
{
|
||||
esp_err_t ret;
|
||||
ESP_LOGI(TAG, "Start Example.");
|
||||
|
||||
// The example will calculate n!
|
||||
//Initialize an input arrays
|
||||
for (int i=0 ; i< N ; i++)
|
||||
{
|
||||
input1[i] = 1;
|
||||
input2[i] = i;
|
||||
}
|
||||
float result1 = 0;
|
||||
unsigned int start_b = dsp_get_cpu_cycle_count();
|
||||
ret = dsps_dotprod_f32(input1, input2, &result1, 101);
|
||||
unsigned int end_b = dsp_get_cpu_cycle_count();
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Operation error = %i", ret);
|
||||
}
|
||||
ESP_LOGI(TAG, "The sum of 101 elements from 0..100 = %f", result1);
|
||||
ESP_LOGI(TAG, "Operation for 101 samples take %i cycles", end_b - start_b);
|
||||
|
||||
ESP_LOGI(TAG, "End Example.");
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/esp-dsp:
|
||||
override_path: "../../../"
|
||||
version: "*"
|
||||
@ -0,0 +1,6 @@
|
||||
# The following 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.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(fft2r)
|
||||
@ -0,0 +1,91 @@
|
||||
# FFT Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to use FFT functionality from esp-dsp library. Example does the following steps:
|
||||
|
||||
1. Initialize the library
|
||||
2. Initialize input signals with 1024 samples: one 0 dB, second with -20 dB
|
||||
3. Combine two signals as one complex input signal and apply window to input signals paar.
|
||||
4. Calculate FFT for 1024 complex samples
|
||||
5. Apply bit reverse operation for output complex vector
|
||||
6. Split one complex FFT output spectrum to two real signal spectrums
|
||||
7. Show results on the plots
|
||||
8. Show execution time of FFT
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware required
|
||||
|
||||
This example does not require any special hardware, and can be run on any common development board.
|
||||
|
||||
### Configure the project
|
||||
|
||||
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
|
||||
|
||||
### Build and flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
|
||||
|
||||
```
|
||||
idf.py -p PORT 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
|
||||
|
||||
Here is an typical example console output.
|
||||
|
||||
```
|
||||
I (59) main: Start Example.
|
||||
W (89) main: Signal x1
|
||||
I (89) view: Data min[495] = -162.760925, Data max[164] = 23.938747
|
||||
________________________________________________________________
|
||||
0 |
|
||||
1 | |
|
||||
2 | |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | |
|
||||
6 | | |
|
||||
7 | | |
|
||||
8 || || |
|
||||
9|||||||||||||||||| ||||||||||||||||||||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (159) view: Plot: Length=512, min=-60.000000, max=40.000000
|
||||
W (169) main: Signal x2
|
||||
I (169) view: Data min[502] = -164.545135, Data max[205] = 3.857752
|
||||
________________________________________________________________
|
||||
0 |
|
||||
1 |
|
||||
2 |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | |
|
||||
6 | |
|
||||
7 || |
|
||||
8 | | |
|
||||
9|||||||||||||||||||||||| ||||||||||||||||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (249) view: Plot: Length=512, min=-60.000000, max=40.000000
|
||||
W (249) main: Signals x1 and x2 on one plot
|
||||
I (259) view: Data min[505] = -159.215271, Data max[164] = 23.938747
|
||||
________________________________________________________________
|
||||
0 |
|
||||
1 | |
|
||||
2 | |
|
||||
3 | | |
|
||||
4 | | |
|
||||
5 | | |
|
||||
6 | | | |
|
||||
7 | | || |
|
||||
8 || || | | |
|
||||
9|||||||||||||||||| | ||||||||||||||||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (339) view: Plot: Length=512, min=-60.000000, max=40.000000
|
||||
I (339) main: FFT for 1024 complex points take 140472 cycles
|
||||
I (349) main: End Example.
|
||||
```
|
||||
@ -0,0 +1 @@
|
||||
idf_component_register(SRCS "dsps_fft_main.c")
|
||||
@ -0,0 +1,106 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "soc/gpio_struct.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "esp_dsp.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// This example shows how to use FFT from esp-dsp library
|
||||
|
||||
#define N_SAMPLES 1024
|
||||
int N = N_SAMPLES;
|
||||
// Input test array
|
||||
__attribute__((aligned(16)))
|
||||
float x1[N_SAMPLES];
|
||||
__attribute__((aligned(16)))
|
||||
float x2[N_SAMPLES];
|
||||
// Window coefficients
|
||||
__attribute__((aligned(16)))
|
||||
float wind[N_SAMPLES];
|
||||
// working complex array
|
||||
__attribute__((aligned(16)))
|
||||
float y_cf[N_SAMPLES*2];
|
||||
// Pointers to result arrays
|
||||
float* y1_cf = &y_cf[0];
|
||||
float* y2_cf = &y_cf[N_SAMPLES];
|
||||
|
||||
// Sum of y1 and y2
|
||||
__attribute__((aligned(16)))
|
||||
float sum_y[N_SAMPLES/2];
|
||||
|
||||
void app_main()
|
||||
{
|
||||
esp_err_t ret;
|
||||
ESP_LOGI(TAG, "Start Example.");
|
||||
ret = dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate hann window
|
||||
dsps_wind_hann_f32(wind, N);
|
||||
// Generate input signal for x1 A=1 , F=0.1
|
||||
dsps_tone_gen_f32(x1, N, 1.0, 0.16, 0);
|
||||
// Generate input signal for x2 A=0.1,F=0.2
|
||||
dsps_tone_gen_f32(x2, N, 0.1, 0.2, 0);
|
||||
|
||||
// Convert two input vectors to one complex vector
|
||||
for (int i=0 ; i< N ; i++)
|
||||
{
|
||||
y_cf[i*2 + 0] = x1[i] * wind[i];
|
||||
y_cf[i*2 + 1] = x2[i] * wind[i];
|
||||
}
|
||||
// FFT
|
||||
unsigned int start_b = dsp_get_cpu_cycle_count();
|
||||
dsps_fft2r_fc32(y_cf, N);
|
||||
unsigned int end_b = dsp_get_cpu_cycle_count();
|
||||
// Bit reverse
|
||||
dsps_bit_rev_fc32(y_cf, N);
|
||||
// Convert one complex vector to two complex vectors
|
||||
dsps_cplx2reC_fc32(y_cf, N);
|
||||
|
||||
for (int i = 0 ; i < N/2 ; i++) {
|
||||
y1_cf[i] = 10 * log10f((y1_cf[i * 2 + 0] * y1_cf[i * 2 + 0] + y1_cf[i * 2 + 1] * y1_cf[i * 2 + 1])/N);
|
||||
y2_cf[i] = 10 * log10f((y2_cf[i * 2 + 0] * y2_cf[i * 2 + 0] + y2_cf[i * 2 + 1] * y2_cf[i * 2 + 1])/N);
|
||||
// Simple way to show two power spectrums as one plot
|
||||
sum_y[i] = fmax(y1_cf[i], y2_cf[i]);
|
||||
}
|
||||
|
||||
// Show power spectrum in 64x10 window from -100 to 0 dB from 0..N/4 samples
|
||||
ESP_LOGW(TAG, "Signal x1");
|
||||
dsps_view(y1_cf, N/2, 64, 10, -60, 40, '|');
|
||||
ESP_LOGW(TAG, "Signal x2");
|
||||
dsps_view(y2_cf, N/2, 64, 10, -60, 40, '|');
|
||||
ESP_LOGW(TAG, "Signals x1 and x2 on one plot");
|
||||
dsps_view(sum_y, N/2, 64, 10, -60, 40, '|');
|
||||
ESP_LOGI(TAG, "FFT for %i complex points take %i cycles", N, end_b - start_b);
|
||||
|
||||
ESP_LOGI(TAG, "End Example.");
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/esp-dsp:
|
||||
override_path: "../../../"
|
||||
version: "*"
|
||||
@ -0,0 +1,6 @@
|
||||
# The following 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.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(fft4real)
|
||||
@ -0,0 +1,91 @@
|
||||
# FFT 4 Real Input Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to use FFT functionality from esp-dsp library. Example does the following steps:
|
||||
|
||||
1. Initialize the library
|
||||
2. Initialize input signals with 1024 samples: one 0 dB, second with -20 dB
|
||||
3. Calculate FFT Radix-2 for 1024 complex samples
|
||||
4. Calculate FFT Radix-4 for 1024 complex samples
|
||||
5. Apply bit reverse operation for output complex vectors
|
||||
6. Show results on the plots
|
||||
7. Show execution time of FFTs
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware required
|
||||
|
||||
This example does not require any special hardware, and can be run on any common development board.
|
||||
|
||||
### Configure the project
|
||||
|
||||
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
|
||||
|
||||
### Build and flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
|
||||
|
||||
```
|
||||
idf.py -p PORT 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
|
||||
|
||||
Here is an typical example console output.
|
||||
|
||||
```
|
||||
I (344) main: Start Example.
|
||||
W (424) main: Signal x1
|
||||
I (424) view: Data min[673] = -103.113297, Data max[328] = 20.490950
|
||||
________________________________________________________________
|
||||
0 |
|
||||
1 | |
|
||||
2 | |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | |
|
||||
6 | |
|
||||
7 | | |
|
||||
8 | | |
|
||||
9||||||||||||||||||| |||||||||||||||||||||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (494) view: Plot: Length=1024, min=-60.000000, max=40.000000
|
||||
W (504) main: Signal x2
|
||||
I (504) view: Data min[582] = -103.113297, Data max[328] = 20.490950
|
||||
________________________________________________________________
|
||||
0 |
|
||||
1 | |
|
||||
2 | |
|
||||
3 | |
|
||||
4 | |
|
||||
5 | |
|
||||
6 | |
|
||||
7 | | |
|
||||
8 | | |
|
||||
9||||||||||||||||||| |||||||||||||||||||||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (584) view: Plot: Length=1024, min=-60.000000, max=40.000000
|
||||
W (593) main: Difference between signals x1 and x2 on one plot
|
||||
I (594) view: Data min[0] = 0.000000, Data max[392] = 0.313019
|
||||
________________________________________________________________
|
||||
0 |
|
||||
1 |
|
||||
2 |
|
||||
3 |
|
||||
4 |
|
||||
5 |
|
||||
6 |
|
||||
7 |
|
||||
8----------------------------------------------------------------|
|
||||
9 |
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (674) view: Plot: Length=1024, min=0.000000, max=40.000000
|
||||
I (674) main: FFT Radix 2 for 1024 complex points take 168652 cycles
|
||||
I (684) main: FFT Radix 4 for 1024 complex points take 104665 cycles
|
||||
I (694) main: End Example.
|
||||
```
|
||||
@ -0,0 +1 @@
|
||||
idf_component_register(SRCS "dsps_fft4real_main.c")
|
||||
@ -0,0 +1,118 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "soc/gpio_struct.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "esp_dsp.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// This example shows how to use FFT from esp-dsp library
|
||||
|
||||
#define N_SAMPLES 2048 // Amount of real input samples
|
||||
int N = N_SAMPLES;
|
||||
// Input test array
|
||||
__attribute__((aligned(16)))
|
||||
float x1[N_SAMPLES];
|
||||
__attribute__((aligned(16)))
|
||||
float x2[N_SAMPLES];
|
||||
// Window coefficients
|
||||
__attribute__((aligned(16)))
|
||||
float wind[N_SAMPLES];
|
||||
// Pointers to result arrays
|
||||
float* y1_cf = &x1[0];
|
||||
float* y2_cf = &x2[0];
|
||||
|
||||
// diff of y1 and y2
|
||||
__attribute__((aligned(16)))
|
||||
float diff_y[N_SAMPLES/2];
|
||||
|
||||
void app_main()
|
||||
{
|
||||
esp_err_t ret;
|
||||
ESP_LOGI(TAG, "Start Example.");
|
||||
ret = dsps_fft2r_init_fc32(NULL, N>>1);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Not possible to initialize FFT2R. Error = %i", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = dsps_fft4r_init_fc32(NULL, N >> 1);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Not possible to initialize FFT4R. Error = %i", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate hann window
|
||||
dsps_wind_hann_f32(wind, N);
|
||||
// Generate input signal for x1 A=1 , F=0.1
|
||||
dsps_tone_gen_f32(x1, N, 1.0, 0.16, 0);
|
||||
|
||||
// Convert two input vectors to one complex vector
|
||||
for (int i=0 ; i< N ; i++)
|
||||
{
|
||||
x1[i] = x1[i] * wind[i];
|
||||
x2[i] = x1[i];
|
||||
}
|
||||
// FFT Radix-2
|
||||
unsigned int start_r2 = dsp_get_cpu_cycle_count();
|
||||
dsps_fft2r_fc32(x1, N>>1);
|
||||
// Bit reverse
|
||||
dsps_bit_rev2r_fc32(x1, N>>1);
|
||||
// Convert one complex vector with length N/2 to one real spectrum vector with length N/2
|
||||
dsps_cplx2real_fc32(x1, N>>1);
|
||||
unsigned int end_r2 = dsp_get_cpu_cycle_count();
|
||||
|
||||
// FFT Radix-4
|
||||
unsigned int start_r4 = dsp_get_cpu_cycle_count();
|
||||
dsps_fft4r_fc32(x2, N>>1);
|
||||
// Bit reverse
|
||||
dsps_bit_rev4r_fc32(x2, N>>1);
|
||||
// Convert one complex vector with length N/2 to one real spectrum vector with length N/2
|
||||
dsps_cplx2real_fc32(x2, N>>1);
|
||||
unsigned int end_r4 = dsp_get_cpu_cycle_count();
|
||||
|
||||
for (int i = 0 ; i < N/2 ; i++) {
|
||||
x1[i] = 10 * log10f((x1[i * 2 + 0] * x1[i * 2 + 0] + x1[i * 2 + 1] * x1[i * 2 + 1] + 0.0000001)/N);
|
||||
x2[i] = 10 * log10f((x2[i * 2 + 0] * x2[i * 2 + 0] + x2[i * 2 + 1] * x2[i * 2 + 1] + 0.0000001)/N);
|
||||
// Simple way to show two power spectrums as one plot
|
||||
diff_y[i] = fabs(x1[i] - x2[i]);
|
||||
}
|
||||
|
||||
// Show power spectrum in 64x10 window from -100 to 0 dB from 0..N/4 samples
|
||||
ESP_LOGW(TAG, "Signal x1");
|
||||
dsps_view(x1, N/2, 64, 10, -60, 40, '|');
|
||||
ESP_LOGW(TAG, "Signal x2");
|
||||
dsps_view(x2, N/2, 64, 10, -60, 40, '|');
|
||||
ESP_LOGW(TAG, "Difference between signals x1 and x2 on one plot");
|
||||
dsps_view(diff_y, N/2, 64, 10, 0, 40, '-');
|
||||
ESP_LOGI(TAG, "FFT Radix 2 for %i complex points take %i cycles", N/2, end_r2 - start_r2);
|
||||
ESP_LOGI(TAG, "FFT Radix 4 for %i complex points take %i cycles", N/2, end_r4 - start_r4);
|
||||
|
||||
ESP_LOGI(TAG, "End Example.");
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/esp-dsp:
|
||||
override_path: "../../../"
|
||||
version: "*"
|
||||
@ -0,0 +1,9 @@
|
||||
[mapping:dsp]
|
||||
archive: libdsp.a
|
||||
entries:
|
||||
* (noflash)
|
||||
|
||||
[mapping:esp-dsp]
|
||||
archive: libesp-dsp.a
|
||||
entries:
|
||||
* (noflash)
|
||||
@ -0,0 +1,6 @@
|
||||
# The following 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.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(fft_window)
|
||||
@ -0,0 +1,134 @@
|
||||
# FFT Window Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to use Window and FFT functionality from esp-dsp library. Example does the following steps:
|
||||
|
||||
1. Initialize the library
|
||||
2. Initialize input signals with 1024 samples
|
||||
3. Apply window to input signal.
|
||||
4. Calculate FFT for 1024 complex samples
|
||||
5. Apply bit reverse operation for output complex vector
|
||||
6. Split one complex FFT output spectrum to two real signal spectrums
|
||||
7. Show results on the plots
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware required
|
||||
|
||||
This example does not require any special hardware, and can be run on any common development board.
|
||||
|
||||
### Configure the project
|
||||
|
||||
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
|
||||
|
||||
### Build and flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
|
||||
|
||||
```
|
||||
idf.py -p PORT 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
|
||||
|
||||
Here is an typical example console output.
|
||||
|
||||
```
|
||||
I (128) main: Start Example.
|
||||
W (128) main: Hann Window
|
||||
I (128) view: Data min[256] = -inf, Data max[1] = 24.086628
|
||||
________________________________________________________________
|
||||
0| |
|
||||
1| |
|
||||
2| |
|
||||
3| |
|
||||
4| |
|
||||
5 | |
|
||||
6 | |
|
||||
7 ||||| |
|
||||
8 ||||||||||||||| |
|
||||
9 ||||||||||||||||||||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (138) view: Plot: Length=512, min=-120.000000, max=40.000000
|
||||
W (138) main: Blackman Window
|
||||
I (148) view: Data min[355] = -165.295654, Data max[1] = 24.083012
|
||||
________________________________________________________________
|
||||
0| |
|
||||
1| |
|
||||
2| |
|
||||
3| |
|
||||
4| |
|
||||
5| |
|
||||
6 | |
|
||||
7 ||| |
|
||||
8 ||||||||| |
|
||||
9 |||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (158) view: Plot: Length=512, min=-120.000000, max=40.000000
|
||||
W (158) main: Blackman-Harris Window
|
||||
I (168) view: Data min[128] = -inf, Data max[1] = 23.874702
|
||||
________________________________________________________________
|
||||
0| |
|
||||
1| |
|
||||
2| |
|
||||
3| |
|
||||
4| |
|
||||
5| |
|
||||
6| |
|
||||
7|| |
|
||||
8| |||| |
|
||||
9 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (178) view: Plot: Length=512, min=-120.000000, max=40.000000
|
||||
W (178) main: Blackman-Nuttall Window
|
||||
I (188) view: Data min[128] = -inf, Data max[1] = 23.890663
|
||||
________________________________________________________________
|
||||
0| |
|
||||
1| |
|
||||
2| |
|
||||
3| |
|
||||
4| |
|
||||
5| |
|
||||
6| |
|
||||
7 || |
|
||||
8 |||| | |
|
||||
9 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (198) view: Plot: Length=512, min=-120.000000, max=40.000000
|
||||
W (198) main: Nuttall Window
|
||||
I (208) view: Data min[203] = -175.147400, Data max[1] = 23.858671
|
||||
________________________________________________________________
|
||||
0| |
|
||||
1| |
|
||||
2| |
|
||||
3| |
|
||||
4| |
|
||||
5| |
|
||||
6| |
|
||||
7|| |
|
||||
8 ||| |
|
||||
9 ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (218) view: Plot: Length=512, min=-120.000000, max=40.000000
|
||||
W (218) main: Flat-Top Window
|
||||
I (228) view: Data min[256] = -inf, Data max[1] = 22.490753
|
||||
________________________________________________________________
|
||||
0| |
|
||||
1| |
|
||||
2| |
|
||||
3| |
|
||||
4| |
|
||||
5| |
|
||||
6| |
|
||||
7 || |
|
||||
8 ||||| |
|
||||
9 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (238) view: Plot: Length=512, min=-120.000000, max=40.000000
|
||||
I (238) main: End Example.
|
||||
```
|
||||
@ -0,0 +1 @@
|
||||
idf_component_register(SRCS "dsps_window_main.c")
|
||||
@ -0,0 +1,145 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "soc/gpio_struct.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "esp_dsp.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// This example shows how to use FFT from esp-dsp library
|
||||
|
||||
#define N_SAMPLES 1024
|
||||
int N = N_SAMPLES;
|
||||
// Input test array
|
||||
__attribute__((aligned(16)))
|
||||
float x1[N_SAMPLES];
|
||||
// Window coefficients
|
||||
__attribute__((aligned(16)))
|
||||
float wind[N_SAMPLES];
|
||||
// working complex array
|
||||
__attribute__((aligned(16)))
|
||||
float y_cf[N_SAMPLES*2];
|
||||
// Pointers to result arrays
|
||||
__attribute__((aligned(16)))
|
||||
float* y1_cf = &y_cf[0];
|
||||
|
||||
void process_and_show(float* data, int length)
|
||||
{
|
||||
dsps_fft2r_fc32(data, length);
|
||||
// Bit reverse
|
||||
dsps_bit_rev_fc32(data, length);
|
||||
// Convert one complex vector to two complex vectors
|
||||
dsps_cplx2reC_fc32(data, length);
|
||||
|
||||
for (int i = 0 ; i < length/2 ; i++) {
|
||||
data[i] = 10 * log10f((data[i * 2 + 0] * data[i * 2 + 0] + data[i * 2 + 1] * data[i * 2 + 1])/N);
|
||||
}
|
||||
|
||||
// Show power spectrum in 64x10 window from -100 to 0 dB from 0..N/4 samples
|
||||
dsps_view(data, length/2, 64, 10, -120, 40, '|');
|
||||
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
esp_err_t ret;
|
||||
ESP_LOGI(TAG, "Start Example.");
|
||||
ret = dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "Hann Window");
|
||||
// Generate Hann window
|
||||
dsps_wind_hann_f32(wind, N);
|
||||
// Convert two input vectors to one complex vector
|
||||
for (int i=0 ; i< N ; i++)
|
||||
{
|
||||
y_cf[i*2 + 0] = wind[i];
|
||||
y_cf[i*2 + 1] = 0;
|
||||
}
|
||||
process_and_show(y_cf, N);
|
||||
|
||||
ESP_LOGW(TAG, "Blackman Window");
|
||||
// Generate Blackman window
|
||||
dsps_wind_blackman_f32(wind, N);
|
||||
// Convert two input vectors to one complex vector
|
||||
for (int i=0 ; i< N ; i++)
|
||||
{
|
||||
y_cf[i*2 + 0] = wind[i];
|
||||
y_cf[i*2 + 1] = 0;
|
||||
}
|
||||
process_and_show(y_cf, N);
|
||||
|
||||
ESP_LOGW(TAG, "Blackman-Harris Window");
|
||||
// Generate Blackman-Harris window
|
||||
dsps_wind_blackman_harris_f32(wind, N);
|
||||
// Convert two input vectors to one complex vector
|
||||
for (int i=0 ; i< N ; i++)
|
||||
{
|
||||
y_cf[i*2 + 0] = wind[i];
|
||||
y_cf[i*2 + 1] = 0;
|
||||
}
|
||||
process_and_show(y_cf, N);
|
||||
|
||||
ESP_LOGW(TAG, "Blackman-Nuttall Window");
|
||||
// Generate Blackman-Nuttall window
|
||||
dsps_wind_blackman_nuttall_f32(wind, N);
|
||||
// Convert two input vectors to one complex vector
|
||||
for (int i=0 ; i< N ; i++)
|
||||
{
|
||||
y_cf[i*2 + 0] = wind[i];
|
||||
y_cf[i*2 + 1] = 0;
|
||||
}
|
||||
process_and_show(y_cf, N);
|
||||
|
||||
ESP_LOGW(TAG, "Nuttall Window");
|
||||
// Generate Nuttall window
|
||||
dsps_wind_nuttall_f32(wind, N);
|
||||
// Convert two input vectors to one complex vector
|
||||
for (int i=0 ; i< N ; i++)
|
||||
{
|
||||
y_cf[i*2 + 0] = wind[i];
|
||||
y_cf[i*2 + 1] = 0;
|
||||
}
|
||||
process_and_show(y_cf, N);
|
||||
|
||||
ESP_LOGW(TAG, "Flat-Top Window");
|
||||
// Generate Flat-Top window
|
||||
dsps_wind_flat_top_f32(wind, N);
|
||||
// Convert two input vectors to one complex vector
|
||||
for (int i=0 ; i< N ; i++)
|
||||
{
|
||||
y_cf[i*2 + 0] = wind[i];
|
||||
y_cf[i*2 + 1] = 0;
|
||||
}
|
||||
process_and_show(y_cf, N);
|
||||
|
||||
ESP_LOGI(TAG, "End Example.");
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/esp-dsp:
|
||||
override_path: "../../../"
|
||||
version: "*"
|
||||
@ -0,0 +1,6 @@
|
||||
# The following 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.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(fir)
|
||||
@ -0,0 +1,87 @@
|
||||
# FIR Filter Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to use FIR filter functionality from esp-dsp library. Example does the following steps:
|
||||
|
||||
1. Initialize the FFT library
|
||||
2. Initialize input signal
|
||||
* 1st Sine wave (f = 0.2Fs)
|
||||
* 2nd Sine wave (f = 0.4Fs)
|
||||
* Combine the waves
|
||||
3. Show input signal
|
||||
* Calculate windows coefficients
|
||||
* Apply the windowing to the input signal
|
||||
* Do the FFT
|
||||
* Show the frequency response on a plot
|
||||
* Calculate execution performance
|
||||
4. Show filtered signal
|
||||
* Initialize the FIR filter library
|
||||
* Calculate Windowed-Sinc coefficients of FIR filter
|
||||
* Apply the FIR filter to the input signal
|
||||
* Do the FFT
|
||||
* Show the frequency response on a plot
|
||||
* Calculate execution performance
|
||||
|
||||
## How to use the example
|
||||
|
||||
### Hardware required
|
||||
|
||||
This example does not require any special hardware, and can be run on any common development board.
|
||||
|
||||
### Configure the project
|
||||
|
||||
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
|
||||
|
||||
### Build and flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
|
||||
|
||||
```
|
||||
idf.py -p PORT 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
|
||||
|
||||
Here is a typical example of console output.
|
||||
|
||||
```
|
||||
I (340) main: Start Example.
|
||||
I (400) view: Data min[388] = -108.419342, Data max[205] = 30.267143
|
||||
________________________________________________________________
|
||||
0 | | |
|
||||
1 | || |
|
||||
2 || || |
|
||||
3 || || |
|
||||
4 || || |
|
||||
5 || ||| |
|
||||
6 || || | | |
|
||||
7|||||||||||||||||||||||| |||||||||||||||||||||| ||||||||||||
|
||||
8 |
|
||||
9 |
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (470) view: Plot: Length=512, min=-120.000000, max=40.000000
|
||||
|
||||
|
||||
I (490) view: Data min[254] = -114.853371, Data max[205] = 27.247583
|
||||
________________________________________________________________
|
||||
0 | |
|
||||
1 | |
|
||||
2 | |
|
||||
3 | | |
|
||||
4 | | |
|
||||
5 | | |
|
||||
6 | ||| ||| |
|
||||
7||||||||||||||||||||||||||||||||||||||||||||||| | ||||| |
|
||||
8 |||||
|
||||
9 |
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (560) view: Plot: Length=256, min=-120.000000, max=40.000000
|
||||
I (560) main: FIR for 1024 samples and decimation 2 takes 763647 cycles
|
||||
I (570) main: End Example.
|
||||
|
||||
```
|
||||
@ -0,0 +1 @@
|
||||
idf_component_register(SRCS "dsps_fir_main.c")
|
||||
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "soc/gpio_struct.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include <math.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "esp_dsp.h"
|
||||
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// This example shows how to use FIR filters from esp-dsp library
|
||||
|
||||
#define FIR_COEFFS_LEN 64 // Number of FIR filter coefficients
|
||||
#define DECIMATION 2 // Decimation ratio of the FIR filter
|
||||
#define N_SAMPLES 1024 // Input samples
|
||||
#define FIR_DELAY (FIR_COEFFS_LEN / DECIMATION) // Amount of samples not being considered for the FFT
|
||||
#define FIR_BUFF_OUT_LEN (N_SAMPLES + FIR_DELAY) // Total length of samples
|
||||
|
||||
|
||||
// Function shows the result of the FIR filter
|
||||
void show_FFT(float *input_signal, const unsigned int fft_len){
|
||||
|
||||
dsps_fft2r_fc32(input_signal, fft_len>>1);
|
||||
dsps_bit_rev2r_fc32(input_signal, fft_len>>1);
|
||||
dsps_cplx2real_fc32(input_signal, fft_len>>1);
|
||||
|
||||
// Correction factor for the FFT spectrum
|
||||
const float correction_factor = fft_len * 3;
|
||||
|
||||
// Calculating power of spectrum in dB
|
||||
for (int i = 0 ; i < fft_len / 2 ; i++) {
|
||||
input_signal[i] = 10 * log10f((input_signal[i * 2 + 0] * input_signal[i * 2 + 0] + input_signal[i * 2 + 1] * input_signal[i * 2 + 1] + 0.0000001)/correction_factor);
|
||||
}
|
||||
|
||||
// Display power spectrum
|
||||
dsps_view(input_signal, fft_len / 2, 64, 10, -120, 40, '|');
|
||||
}
|
||||
|
||||
|
||||
// Generate Windowed-Sinc filter coefficients
|
||||
void generate_FIR_coefficients(float *fir_coeffs, const unsigned int fir_len, const float ft){
|
||||
|
||||
// Even or odd length of the FIR filter
|
||||
const bool is_odd = (fir_len % 2) ? (true) : (false);
|
||||
const float fir_order = (float)(fir_len - 1);
|
||||
|
||||
// Window coefficients
|
||||
float *fir_window = (float*)malloc(fir_len * sizeof(float));
|
||||
dsps_wind_blackman_f32(fir_window, fir_len);
|
||||
|
||||
for(int i = 0; i < fir_len; i++){
|
||||
if((i == fir_order / 2) && (is_odd))
|
||||
fir_coeffs[i] = 2 * ft;
|
||||
else
|
||||
fir_coeffs[i] = sinf((2 * M_PI * ft * (i - fir_order / 2))) / (M_PI * (i - fir_order / 2));
|
||||
|
||||
fir_coeffs[i] *= fir_window[i];
|
||||
}
|
||||
|
||||
free(fir_window);
|
||||
}
|
||||
|
||||
|
||||
void app_main()
|
||||
{
|
||||
const int16_t fir_len = FIR_COEFFS_LEN;
|
||||
const float fir_ft = 0.5 / DECIMATION; // Transition frequency of the FIR filter
|
||||
const int32_t N = N_SAMPLES; // Number of input samples
|
||||
const int16_t fir_decim = DECIMATION; // FIR filter decimation
|
||||
const int32_t N_buff = FIR_BUFF_OUT_LEN; // Total length of samples with ignored
|
||||
|
||||
__attribute__((aligned(16))) float tone_combined[N_buff];
|
||||
__attribute__((aligned(16))) float fir_coeffs[fir_len];
|
||||
__attribute__((aligned(16))) float delay_line[fir_len];
|
||||
|
||||
fir_f32_t fir1;
|
||||
esp_err_t ret;
|
||||
|
||||
// Ignoring the first set of samples, due to the delay line of the FIR filter
|
||||
const int fir_out_offset = ((FIR_DELAY / 2) - 1);
|
||||
|
||||
ESP_LOGI(TAG, "Start Example.");
|
||||
|
||||
// If a user doesn't care about buffer allocation, the default
|
||||
// initialization could be used as shown here:
|
||||
ret = dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = dsps_fft4r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate input signal as 2 sine waves
|
||||
float *tone_1 = (float*)malloc(N_buff * sizeof(float));
|
||||
float *tone_2 = (float*)malloc(N_buff * sizeof(float));
|
||||
|
||||
dsps_tone_gen_f32(tone_1, N_buff, 5, 0.2, 0);
|
||||
dsps_tone_gen_f32(tone_2, N_buff, 5, 0.4, 0);
|
||||
|
||||
// Generate windowing coefficients
|
||||
float *window = (float*)malloc(N * sizeof(float));
|
||||
dsps_wind_blackman_harris_f32(window, N);
|
||||
|
||||
// Add the two waves together
|
||||
for (int i = 0 ; i < N_buff ; i++){
|
||||
tone_combined[i] = tone_1[i] + tone_2[i];
|
||||
}
|
||||
|
||||
free(tone_1);
|
||||
free(tone_2);
|
||||
|
||||
// Apply the windowing
|
||||
for (int i = 0 ; i < N ; i++){
|
||||
window[i] *= tone_combined[i];
|
||||
}
|
||||
|
||||
// Show FFT spectrum
|
||||
show_FFT(window, N);
|
||||
|
||||
// Calculate coefficients for the FIR filter
|
||||
generate_FIR_coefficients(fir_coeffs, fir_len, fir_ft);
|
||||
ESP_LOGI(TAG, "\n");
|
||||
|
||||
// Filter the input signal with FIR filter
|
||||
float *fir_out = (float*)malloc( N_buff * sizeof(float));
|
||||
dsps_fird_init_f32(&fir1, fir_coeffs, delay_line, fir_len, fir_decim, 0);
|
||||
|
||||
unsigned int start_b = dsp_get_cpu_cycle_count();
|
||||
dsps_fird_f32_ansi(&fir1, tone_combined, fir_out, N_buff);
|
||||
unsigned int end_b = dsp_get_cpu_cycle_count();
|
||||
|
||||
// Generate windowing coefficients and apply the windowing
|
||||
dsps_wind_blackman_harris_f32(window, (N / fir_decim));
|
||||
for (int i = 0 ; i < N / fir_decim ; i++){
|
||||
window[i] *= fir_out[fir_out_offset + i];
|
||||
}
|
||||
|
||||
// Show FFT spectrum, ignoring first samples from the delay line
|
||||
show_FFT(window, N / fir_decim);
|
||||
ESP_LOGI(TAG, "FIR for %"PRId32" samples and decimation %"PRId16" takes %"PRId16" cycles", N, fir_decim, (int16_t)(end_b - start_b));
|
||||
ESP_LOGI(TAG, "End Example.");
|
||||
|
||||
free(fir_out);
|
||||
free(window);
|
||||
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/esp-dsp:
|
||||
override_path: "../../../"
|
||||
version: "*"
|
||||
@ -0,0 +1,6 @@
|
||||
# The following 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.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(iir)
|
||||
@ -0,0 +1,107 @@
|
||||
# IIR Filter Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to use IIR filters functionality from esp-dsp library. Example does the following steps:
|
||||
|
||||
1. Initialize the library
|
||||
2. Initialize input signal
|
||||
3. Show LPF filter with Q factor 1
|
||||
* Calculate iir filter coefficients
|
||||
* Filter the input test signal (delta function)
|
||||
* Shows impulse response on the plot
|
||||
* Shows frequency response on the plot
|
||||
* Calculate execution performance
|
||||
4. The same for LPF filter with Q factor 10
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware required
|
||||
|
||||
This example does not require any special hardware, and can be run on any common development board.
|
||||
|
||||
### Configure the project
|
||||
|
||||
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
|
||||
|
||||
### Build and flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
|
||||
|
||||
```
|
||||
idf.py -p PORT 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
|
||||
|
||||
Here is an typical example console output.
|
||||
|
||||
```
|
||||
I (58) main: Start Example.
|
||||
I (58) main: Impulse response of IIR filter with F=0.100000, qFactor=1.000000
|
||||
I (68) view: Data min[8] = -0.060052, Data max[2] = 0.333517
|
||||
________________________________________________________________
|
||||
0 |
|
||||
1 |
|
||||
2 - |
|
||||
3- - |
|
||||
4 -------------------------------------------------------------|
|
||||
5 |
|
||||
6 |
|
||||
7 |
|
||||
8 |
|
||||
9 |
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (138) view: Plot: Length=128, min=-1.000000, max=1.000000
|
||||
I (148) view: Data min[511] = -149.983795, Data max[0] = 0.000000
|
||||
________________________________________________________________
|
||||
0 |
|
||||
1 |
|
||||
2----------------- |
|
||||
3 ---------- |
|
||||
4 ------------- |
|
||||
5 ---------- |
|
||||
6 ------- |
|
||||
7 --- |
|
||||
8 -- |
|
||||
9 --|
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (228) view: Plot: Length=512, min=-100.000000, max=0.000000
|
||||
I (228) main: IIR for 1024 samples take 20276 cycles
|
||||
I (238) main: Impulse response of IIR filter with F=0.100000, qFactor=10.000000
|
||||
I (248) view: Data min[7] = -0.453739, Data max[2] = 0.526114
|
||||
________________________________________________________________
|
||||
0 |
|
||||
1 |
|
||||
2 - - |
|
||||
3- - - - --- --- - - |
|
||||
4- - - - - ---- -------------------------------------|
|
||||
5 -- -- -- -- |
|
||||
6 |
|
||||
7 |
|
||||
8 |
|
||||
9 |
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (318) view: Plot: Length=128, min=-1.000000, max=1.000000
|
||||
I (328) view: Data min[511] = -149.480377, Data max[0] = 0.000000
|
||||
________________________________________________________________
|
||||
0 -- |
|
||||
1 -- - |
|
||||
2---------- ----- |
|
||||
3 -------- |
|
||||
4 ------------ |
|
||||
5 ---------- |
|
||||
6 ------- |
|
||||
7 --- |
|
||||
8 -- |
|
||||
9 --|
|
||||
0123456789012345678901234567890123456789012345678901234567890123
|
||||
I (408) view: Plot: Length=512, min=-100.000000, max=0.000000
|
||||
I (408) main: IIR for 1024 samples take 17456 cycles
|
||||
I (418) main: End Example.
|
||||
|
||||
```
|
||||
@ -0,0 +1 @@
|
||||
idf_component_register(SRCS "dsps_iir_main.c")
|
||||
@ -0,0 +1,115 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "soc/gpio_struct.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/uart.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "esp_dsp.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// This example shows how to use iir filters from esp-dsp library
|
||||
|
||||
#define N_SAMPLES 1024
|
||||
int N = N_SAMPLES;
|
||||
// Input test array
|
||||
__attribute__((aligned(16)))
|
||||
float d[N_SAMPLES];
|
||||
// output array
|
||||
__attribute__((aligned(16)))
|
||||
float y[N_SAMPLES];
|
||||
__attribute__((aligned(16)))
|
||||
float y_cf[N_SAMPLES*2];
|
||||
|
||||
// Function shows result of IIR filter
|
||||
void ShowIIRfilter(float freq, float qFactor)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
float coeffs_lpf[5];
|
||||
float w_lpf[5] = {0,0};
|
||||
// Calculate iir filter coefficients
|
||||
ret = dsps_biquad_gen_lpf_f32(coeffs_lpf, freq, qFactor);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Operation error = %i", ret);
|
||||
return;
|
||||
}
|
||||
// Process input signal
|
||||
unsigned int start_b = dsp_get_cpu_cycle_count();
|
||||
ret = dsps_biquad_f32(d, y, N, coeffs_lpf, w_lpf);
|
||||
unsigned int end_b = dsp_get_cpu_cycle_count();
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Operation error = %i", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show result as a plot
|
||||
ESP_LOGI(TAG, "Impulse response of IIR filter with F=%f, qFactor=%f", freq, qFactor);
|
||||
dsps_view(y, 128, 64, 10, -1, 1, '-');
|
||||
|
||||
// Show result as frequency responce on the plot
|
||||
for (int i=0 ; i< N ; i++)
|
||||
{
|
||||
y_cf[i*2 + 0] = y[i];
|
||||
y_cf[i*2 + 1] = 0;
|
||||
}
|
||||
|
||||
// We making FFT transform
|
||||
dsps_fft2r_fc32_ansi(y_cf, N);
|
||||
// Bit reverse
|
||||
dsps_bit_rev_fc32_ansi(y_cf, N);
|
||||
// Calculating power of spectrum in dB
|
||||
for (int i = 0 ; i < N/2 ; i++) {
|
||||
y_cf[i] = 10 * log10f((y_cf[i * 2 + 0] * y_cf[i * 2 + 0] + y_cf[i * 2 + 1] * y_cf[i * 2 + 1])/N);
|
||||
}
|
||||
// Show power spectrum in 64x10 window from -100 to 0 dB from 0..N/2 samples
|
||||
dsps_view(y_cf, N/2, 64, 10, -100, 0, '-');
|
||||
ESP_LOGI(TAG, "IIR for %i samples take %i cycles", N, end_b - start_b);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
esp_err_t ret;
|
||||
ESP_LOGI(TAG, "Start Example.");
|
||||
// If user don't care about buffer allocation, the defalt
|
||||
// initialization could be used as shown here:
|
||||
ret = dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize input signal
|
||||
// Generate d function as input signal
|
||||
dsps_d_gen_f32(d, N, 0);
|
||||
|
||||
// Show filter with Q factor 1
|
||||
ShowIIRfilter(0.1, 1);
|
||||
// Show filter with Q factor 10
|
||||
ShowIIRfilter(0.1, 10);
|
||||
|
||||
ESP_LOGI(TAG, "End Example.");
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/esp-dsp:
|
||||
override_path: "../../../"
|
||||
version: "*"
|
||||
@ -0,0 +1,6 @@
|
||||
# The following 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.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(ekf13states)
|
||||
@ -0,0 +1,149 @@
|
||||
# Extended Kalman Filter
|
||||
|
||||
This example emulate system with IMU sensors and show how to use Extended Kalman Filter (EKF), with 13 values states vector,
|
||||
to estimate gyroscope errors and calculate system attitude.
|
||||
Also, this example show how to use esp-dsp library to operate with matrices and vectors.
|
||||
|
||||
In real system, the emulated sensors values should be replace by the real sensors values.
|
||||
Then, in real system, a calibration phase should be implemented and after the calibration
|
||||
phase the state vector X and covariance matrix P should be saved and restored next time, when
|
||||
filter called. It will save time for initial phase.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware required
|
||||
|
||||
This example does not require any special hardware, and can be run on any common development board.
|
||||
|
||||
### Configure the project
|
||||
|
||||
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
|
||||
|
||||
### Build and flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
|
||||
|
||||
```
|
||||
idf.py -p PORT 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
|
||||
|
||||
```
|
||||
I (380) spi_flash: detected chip: gd
|
||||
I (383) spi_flash: flash io: dio
|
||||
W (387) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
|
||||
I (404) cpu_start: Starting scheduler on PRO CPU.
|
||||
I (0) cpu_start: Starting scheduler on APP CPU.
|
||||
I (413) main: Start Example.
|
||||
Gyro error: 0.1 0.2 0.3
|
||||
|
||||
Calibration phase started:
|
||||
Loop 1000 from 48000, State data : 0.998361 0.0152476 0.0211183 0.0509682 0.00463435 0.00919946 0.01352 0.998156 0.00619182 -0.000683098 -0.00117112 0.0063196 -0.000952147
|
||||
Loop 2000 from 48000, State data : 0.941757 0.0877462 0.170681 0.276156 0.016951 0.0334337 0.0498731 0.998804 0.0162317 -0.00225174 0.00389746 0.0110905 -0.000489083
|
||||
Loop 3000 from 48000, State data : 0.372216 0.24247 0.488788 0.750832 0.0323164 0.0642265 0.0962768 0.997295 0.0269348 -0.00481966 0.00605674 0.00779719 0.00494921
|
||||
Loop 4000 from 48000, State data : 0.944725 0.0951798 0.165878 0.266308 0.0470155 0.0946294 0.141251 0.998213 0.0337875 -0.00704064 0.00422252 0.0124181 0.00485692
|
||||
Loop 5000 from 48000, State data : 0.944287 0.102183 0.168344 0.263706 0.0597481 0.12037 0.179946 0.997498 0.0378795 -0.00841348 0.0053515 0.0104612 0.00666854
|
||||
Loop 6000 from 48000, State data : 0.379137 0.258284 0.476853 0.74977 0.0697741 0.140876 0.210702 0.995523 0.0410914 -0.00911293 0.00510267 0.00764586 0.00913832
|
||||
Loop 7000 from 48000, State data : 0.947048 0.112494 0.165382 0.251187 0.0773002 0.156661 0.233985 0.996358 0.0425222 -0.00994576 0.00353348 0.00969652 0.00849919
|
||||
Loop 8000 from 48000, State data : 0.945556 0.120624 0.169212 0.250481 0.082995 0.16838 0.251493 0.995914 0.0433827 -0.0102827 0.0039165 0.00846988 0.00913964
|
||||
Loop 9000 from 48000, State data : 0.381034 0.276875 0.4647 0.749805 0.0871785 0.177046 0.264439 0.995073 0.0441243 -0.0103565 0.00391002 0.0071649 0.00997719
|
||||
Loop 10000 from 48000, State data : 0.946592 0.132375 0.168307 0.241068 0.0902326 0.183443 0.273873 0.995445 0.0443655 -0.0106197 0.00326065 0.00799655 0.00960479
|
||||
Loop 11000 from 48000, State data : 0.944297 0.140946 0.172816 0.242015 0.0924658 0.188118 0.280807 0.995187 0.0445766 -0.0106806 0.00346742 0.00749049 0.00979064
|
||||
Loop 12000 from 48000, State data : 0.378334 0.295555 0.452859 0.751285 0.0941005 0.191525 0.285886 0.994796 0.0447763 -0.0106511 0.0034986 0.00695604 0.0100697
|
||||
Loop 13000 from 48000, State data : 0.944329 0.1532 0.172826 0.234315 0.0953075 0.194011 0.289567 0.994899 0.0448155 -0.0107384 0.00323858 0.00728781 0.00989103
|
||||
Loop 14000 from 48000, State data : 0.941572 0.16194 0.177533 0.236008 0.0961574 0.195842 0.292257 0.994735 0.0448801 -0.0107422 0.00334282 0.0070798 0.00993131
|
||||
Loop 15000 from 48000, State data : 0.373427 0.314041 0.441061 0.753256 0.0967899 0.197167 0.294234 0.994523 0.0449438 -0.0107112 0.00335898 0.00685221 0.0100213
|
||||
Loop 16000 from 48000, State data : 0.941028 0.174338 0.177916 0.228952 0.0972752 0.198121 0.295664 0.994518 0.0449512 -0.0107403 0.0032445 0.00697761 0.00993463
|
||||
Loop 17000 from 48000, State data : 0.937959 0.183145 0.18262 0.230959 0.0975883 0.198844 0.296697 0.994396 0.0449757 -0.0107339 0.0032963 0.00688409 0.00992845
|
||||
Loop 18000 from 48000, State data : 0.3675 0.33233 0.429142 0.755207 0.0978324 0.199358 0.297465 0.994256 0.0450002 -0.0107104 0.00330113 0.00677742 0.00995297
|
||||
Loop 19000 from 48000, State data : 0.937014 0.195546 0.183166 0.224089 0.0980371 0.199716 0.298023 0.994211 0.0450036 -0.0107164 0.00324275 0.00681997 0.00990755
|
||||
Loop 20000 from 48000, State data : 0.933698 0.204372 0.187784 0.226223 0.0981422 0.200008 0.29842 0.994114 0.0450155 -0.0107065 0.00327025 0.00677405 0.00988484
|
||||
Loop 21000 from 48000, State data : 0.361055 0.350426 0.417036 0.756916 0.0982358 0.200208 0.29872 0.99401 0.0450272 -0.0106858 0.00326787 0.00671759 0.0098834
|
||||
Loop 22000 from 48000, State data : 0.932425 0.216717 0.188413 0.219358 0.0983318 0.200334 0.298938 0.993947 0.0450303 -0.0106798 0.00323017 0.00672916 0.00985372
|
||||
Loop 23000 from 48000, State data : 0.928888 0.225543 0.19291 0.221546 0.0983561 0.200458 0.299082 0.993866 0.0450371 -0.0106664 0.00324701 0.00670354 0.00982584
|
||||
Loop 24000 from 48000, State data : 0.354297 0.36833 0.404722 0.758292 0.0983915 0.200535 0.299203 0.993773 0.045044 -0.0106443 0.00324109 0.00666712 0.00981608
|
||||
Loop 25000 from 48000, State data : 0.927316 0.237803 0.19359 0.214612 0.0984453 0.200572 0.299291 0.993709 0.0450468 -0.0106303 0.00321085 0.00666748 0.00979369
|
||||
Loop 26000 from 48000, State data : 0.92357 0.246618 0.197954 0.216824 0.0984385 0.200632 0.299342 0.993629 0.0450514 -0.0106123 0.00322403 0.00665109 0.00976504
|
||||
Loop 27000 from 48000, State data : 0.347305 0.386034 0.392194 0.759303 0.0984521 0.200663 0.299393 0.993546 0.0450564 -0.0105864 0.00321847 0.00662376 0.00975319
|
||||
Loop 28000 from 48000, State data : 0.92171 0.258777 0.198672 0.209796 0.0984898 0.200666 0.299433 0.993475 0.045059 -0.0105663 0.00319366 0.00662077 0.00973562
|
||||
Loop 29000 from 48000, State data : 0.917761 0.267574 0.202895 0.212019 0.0984714 0.2007 0.299446 0.9934 0.0450631 -0.0105437 0.00320563 0.0066091 0.00970881
|
||||
Loop 30000 from 48000, State data : 0.340113 0.403531 0.379459 0.759933 0.0984762 0.200711 0.299466 0.993322 0.0450673 -0.0105132 0.00320031 0.00658594 0.00969804
|
||||
Loop 31000 from 48000, State data : 0.915619 0.279623 0.203648 0.204891 0.0985076 0.2007 0.299484 0.993253 0.0450696 -0.0104878 0.00317637 0.00658294 0.00968329
|
||||
Loop 32000 from 48000, State data : 0.91147 0.288396 0.207727 0.207121 0.0984838 0.200725 0.299481 0.99318 0.0450732 -0.0104599 0.00318786 0.00657435 0.00965871
|
||||
Loop 33000 from 48000, State data : 0.332734 0.420812 0.366519 0.760177 0.0984844 0.20073 0.299492 0.993105 0.045077 -0.0104242 0.00318322 0.00655352 0.00964965
|
||||
Loop 34000 from 48000, State data : 0.909049 0.300327 0.208511 0.199891 0.0985129 0.200714 0.299506 0.993034 0.0450794 -0.0103941 0.0031609 0.00655179 0.00963774
|
||||
Loop 35000 from 48000, State data : 0.904704 0.309072 0.212442 0.202124 0.0984875 0.200736 0.299498 0.992959 0.0450829 -0.0103612 0.0031732 0.00654506 0.00961709
|
||||
Loop 36000 from 48000, State data : 0.325179 0.437867 0.353384 0.760034 0.098487 0.200738 0.299504 0.992885 0.0450865 -0.0103208 0.00317079 0.00652607 0.00961171
|
||||
Loop 37000 from 48000, State data : 0.325177 0.437848 0.353377 0.760049 0.0989011 0.200534 0.299617 0.992838 0.0450912 -0.0103039 0.00319877 0.00652725 0.00959415
|
||||
Loop 38000 from 48000, State data : 0.325194 0.437821 0.353363 0.760064 0.099202 0.200388 0.299726 0.992838 0.0450926 -0.0102998 0.00320422 0.00652895 0.00959084
|
||||
Loop 39000 from 48000, State data : 0.325211 0.437798 0.353354 0.760074 0.0994169 0.200278 0.299826 0.992816 0.045093 -0.0102979 0.00320263 0.0065278 0.00959847
|
||||
Loop 40000 from 48000, State data : 0.325222 0.437784 0.353346 0.760081 0.0995754 0.200199 0.299886 0.992816 0.0450925 -0.0102967 0.00320118 0.00652683 0.00960376
|
||||
Loop 41000 from 48000, State data : 0.325231 0.437773 0.353342 0.760085 0.0996929 0.200142 0.299945 0.992816 0.0450925 -0.0102966 0.00320043 0.00652627 0.00960631
|
||||
Loop 42000 from 48000, State data : 0.325238 0.437769 0.353336 0.760087 0.0997802 0.200119 0.299978 0.992816 0.0450913 -0.0102965 0.00320007 0.0065261 0.00960773
|
||||
Loop 43000 from 48000, State data : 0.32524 0.437762 0.353331 0.760093 0.099842 0.200089 0.299979 0.992816 0.0450913 -0.0102961 0.00320001 0.00652608 0.00960857
|
||||
Loop 44000 from 48000, State data : 0.325241 0.43776 0.353327 0.760095 0.099883 0.200059 0.299979 0.992816 0.045089 -0.0102953 0.00319975 0.00652622 0.00960868
|
||||
Loop 45000 from 48000, State data : 0.325243 0.437759 0.353325 0.760096 0.0999138 0.200045 0.299979 0.992816 0.0450878 -0.0102956 0.0031996 0.00652593 0.00960985
|
||||
Loop 46000 from 48000, State data : 0.325245 0.437756 0.353324 0.760097 0.0999355 0.200042 0.299979 0.992816 0.0450878 -0.0102959 0.00319972 0.0065261 0.00960944
|
||||
Loop 47000 from 48000, State data : 0.325246 0.437757 0.353322 0.760098 0.0999504 0.200039 0.299979 0.992816 0.0450878 -0.0102959 0.00319952 0.00652634 0.00960984
|
||||
Calibration phase finished.
|
||||
|
||||
Regular calculation started:
|
||||
Loop 1000 from 48000, State data : 0.9996 6.68374e-06 -7.71055e-05 0.028269 0.0999599 0.199742 0.298758 0.992397 0.0506049 -0.00981295 0.00516875 0.00517689 0.0102406
|
||||
Loop 2000 from 48000, State data : 0.95186 0.0747648 0.154942 0.253704 0.0997667 0.199899 0.298983 0.992397 0.0504132 -0.0098162 0.00510809 0.00522702 0.0102249
|
||||
Loop 3000 from 48000, State data : 0.395338 0.237819 0.486861 0.741698 0.0994409 0.200091 0.299095 0.992397 0.0502891 -0.00981838 0.00506923 0.00525921 0.0102147
|
||||
Loop 4000 from 48000, State data : 0.952465 0.0877289 0.155254 0.247002 0.0992076 0.200299 0.299271 0.992397 0.0502054 -0.00981973 0.00504271 0.00528111 0.0102076
|
||||
Loop 5000 from 48000, State data : 0.950016 0.096521 0.160702 0.249654 0.0990023 0.200426 0.299306 0.992397 0.05013 -0.00982108 0.00501929 0.00530046 0.0102013
|
||||
Loop 6000 from 48000, State data : 0.389808 0.256786 0.476033 0.745321 0.0988748 0.200476 0.299331 0.992397 0.050078 -0.00982208 0.0050032 0.00531378 0.0101971
|
||||
Loop 7000 from 48000, State data : 0.950306 0.109383 0.161046 0.242937 0.0987883 0.200581 0.299444 0.992397 0.0500379 -0.00982289 0.0049906 0.00532416 0.0101938
|
||||
Loop 8000 from 48000, State data : 0.947646 0.118155 0.166392 0.2456 0.0986931 0.200633 0.299434 0.992397 0.0499987 -0.00982366 0.00497852 0.00533416 0.0101903
|
||||
Loop 9000 from 48000, State data : 0.383995 0.275557 0.464951 0.748623 0.0986473 0.200627 0.299425 0.992397 0.0499702 -0.00982415 0.00496994 0.00534126 0.0101879
|
||||
Loop 10000 from 48000, State data : 0.94764 0.130939 0.166769 0.238794 0.0986203 0.200694 0.299509 0.992397 0.0499475 -0.00982454 0.004963 0.00534698 0.0101861
|
||||
Loop 11000 from 48000, State data : 0.944771 0.139703 0.171999 0.241471 0.0985699 0.200714 0.299481 0.992397 0.0499252 -0.00982467 0.00495605 0.00535274 0.0101844
|
||||
Loop 12000 from 48000, State data : 0.377949 0.294161 0.453622 0.751566 0.0985571 0.200685 0.299459 0.992397 0.0499092 -0.00982467 0.00495124 0.0053567 0.0101832
|
||||
Loop 13000 from 48000, State data : 0.944475 0.152413 0.172408 0.234549 0.0985539 0.200736 0.299532 0.992397 0.0498962 -0.00982467 0.00494735 0.0053599 0.0101823
|
||||
Loop 14000 from 48000, State data : 0.941398 0.16117 0.177516 0.237239 0.0985215 0.200743 0.299498 0.992397 0.0498826 -0.00982467 0.0049434 0.00536316 0.0101813
|
||||
Loop 15000 from 48000, State data : 0.371694 0.312599 0.442052 0.754132 0.0985222 0.200704 0.299474 0.992397 0.049874 -0.00982467 0.00494084 0.0053653 0.0101808
|
||||
Loop 16000 from 48000, State data : 0.940819 0.173801 0.177954 0.230187 0.0985277 0.20075 0.299544 0.992397 0.0498671 -0.00982467 0.00493887 0.00536698 0.0101804
|
||||
Loop 17000 from 48000, State data : 0.937532 0.182552 0.182939 0.232897 0.0985023 0.200752 0.299507 0.992397 0.0498602 -0.00982467 0.0049367 0.0053688 0.0101799
|
||||
Loop 18000 from 48000, State data : 0.365235 0.33087 0.43025 0.756316 0.0985084 0.200708 0.299482 0.992397 0.0498562 -0.00982467 0.00493555 0.0053698 0.0101796
|
||||
Loop 19000 from 48000, State data : 0.936669 0.195102 0.183407 0.225717 0.0985175 0.200754 0.299549 0.992397 0.0498532 -0.00982467 0.00493474 0.00537051 0.0101794
|
||||
Loop 20000 from 48000, State data : 0.933178 0.203841 0.188264 0.22844 0.0984953 0.200754 0.299511 0.992397 0.0498502 -0.00982467 0.00493366 0.00537141 0.010179
|
||||
Loop 21000 from 48000, State data : 0.35858 0.348967 0.41822 0.758113 0.0985034 0.200709 0.299484 0.992397 0.0498495 -0.00982467 0.00493334 0.00537172 0.0101788
|
||||
Loop 22000 from 48000, State data : 0.93203 0.216304 0.188763 0.221136 0.0985129 0.200755 0.299549 0.992397 0.0498497 -0.00982467 0.00493327 0.00537182 0.0101787
|
||||
Loop 23000 from 48000, State data : 0.928336 0.225027 0.193488 0.22387 0.0984918 0.200754 0.29951 0.992397 0.0498497 -0.00982467 0.00493298 0.00537209 0.0101787
|
||||
Loop 24000 from 48000, State data : 0.351735 0.366882 0.405969 0.759519 0.0985006 0.200707 0.299482 0.992397 0.0498508 -0.00982467 0.00493324 0.00537189 0.0101787
|
||||
Loop 25000 from 48000, State data : 0.926905 0.237397 0.194017 0.216443 0.0985107 0.200755 0.299545 0.992397 0.0498526 -0.00982467 0.00493366 0.00537159 0.0101787
|
||||
Loop 26000 from 48000, State data : 0.92301 0.246099 0.198608 0.219185 0.0984902 0.200753 0.299511 0.992397 0.0498537 -0.00982467 0.00493391 0.00537146 0.0101787
|
||||
Loop 27000 from 48000, State data : 0.344708 0.384605 0.393502 0.760534 0.0984992 0.200706 0.299488 0.992397 0.0498556 -0.00982467 0.00493459 0.00537092 0.0101787
|
||||
Loop 28000 from 48000, State data : 0.921297 0.258369 0.199166 0.211636 0.0985091 0.200757 0.299555 0.992397 0.0498579 -0.00982467 0.00493535 0.00537033 0.0101787
|
||||
Loop 29000 from 48000, State data : 0.917204 0.267048 0.203621 0.214385 0.0984891 0.200754 0.29952 0.992397 0.0498601 -0.00982467 0.00493597 0.0053698 0.0101787
|
||||
Loop 30000 from 48000, State data : 0.337501 0.402129 0.380825 0.761156 0.0984981 0.200706 0.299491 0.992397 0.0498626 -0.00982467 0.00493691 0.00536903 0.0101787
|
||||
Loop 31000 from 48000, State data : 0.915208 0.279212 0.204208 0.206723 0.0985072 0.200758 0.299553 0.992397 0.0498654 -0.00982467 0.00493789 0.00536824 0.0101787
|
||||
Loop 32000 from 48000, State data : 0.910918 0.287861 0.208526 0.209479 0.0984873 0.200754 0.299515 0.992397 0.0498676 -0.00982467 0.00493879 0.00536752 0.0101787
|
||||
Loop 33000 from 48000, State data : 0.330116 0.419445 0.367945 0.761385 0.0984966 0.200704 0.299489 0.992397 0.0498701 -0.00982467 0.00493986 0.00536667 0.0101787
|
||||
Loop 34000 from 48000, State data : 0.908641 0.299912 0.209141 0.201703 0.0985056 0.200757 0.299551 0.992397 0.0498728 -0.00982467 0.00494093 0.00536582 0.0101787
|
||||
Loop 35000 from 48000, State data : 0.904158 0.308528 0.213318 0.204462 0.0984862 0.200752 0.299518 0.992397 0.0498751 -0.00982467 0.00494188 0.00536507 0.0101787
|
||||
Loop 36000 from 48000, State data : 0.322561 0.436541 0.354869 0.761219 0.0984953 0.200702 0.299495 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Loop 37000 from 48000, State data : 0.322549 0.436508 0.354868 0.761243 0.0989076 0.200506 0.299634 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Loop 38000 from 48000, State data : 0.322568 0.436485 0.354851 0.761257 0.099208 0.200371 0.299726 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Loop 39000 from 48000, State data : 0.322581 0.436466 0.354841 0.761267 0.0994207 0.200267 0.299799 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Loop 40000 from 48000, State data : 0.322592 0.436454 0.354831 0.761274 0.099581 0.200208 0.299849 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Loop 41000 from 48000, State data : 0.322601 0.436443 0.354826 0.761278 0.099701 0.20015 0.299901 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Loop 42000 from 48000, State data : 0.322606 0.436435 0.35482 0.761283 0.0997844 0.200101 0.299931 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Loop 43000 from 48000, State data : 0.322611 0.436429 0.35482 0.761285 0.0998457 0.200072 0.299961 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Loop 44000 from 48000, State data : 0.322615 0.436425 0.354818 0.761286 0.0998883 0.200057 0.29999 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Loop 45000 from 48000, State data : 0.322617 0.436423 0.354816 0.761287 0.099912 0.200042 0.300002 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Loop 46000 from 48000, State data : 0.322617 0.436421 0.354815 0.761289 0.0999343 0.20003 0.300002 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Loop 47000 from 48000, State data : 0.322618 0.436421 0.354814 0.761289 0.0999444 0.20003 0.300002 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Final State data : 0.322618 0.436421 0.354814 0.761289 0.0999518 0.20003 0.300002 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
|
||||
Estimated error : 0.0999518 0.20003 0.300002
|
||||
Difference between real and estimated errors : 4.81904e-05 -2.99811e-05 -2.17557e-06
|
||||
|
||||
Expected Euler angels (degree) : -29.8215 64.9692 150.241
|
||||
Calculated Euler angels (degree) : -35.1525 63.3067 156.167
|
||||
```
|
||||
@ -0,0 +1 @@
|
||||
idf_component_register(SRCS "ekf_imu13states_main.cpp")
|
||||
@ -0,0 +1,196 @@
|
||||
// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "dsp_platform.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_dsp.h"
|
||||
#include "ekf_imu13states.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
extern "C" void app_main();
|
||||
|
||||
// This example reproduce system with gyroscope, accelerometer, and magnetometer
|
||||
// True gyroscope values will be transformed and applied to the rotation and reference measurements.
|
||||
void app_main()
|
||||
{
|
||||
ekf_imu13states *ekf13 = new ekf_imu13states();
|
||||
ekf13->Init();
|
||||
ESP_LOGI(TAG, "Start Example.");
|
||||
|
||||
// Set up some initial values to emulate and calculate system values
|
||||
int total_N = 3000;
|
||||
// Pi value
|
||||
float pi = std::atan(1) * 4;
|
||||
|
||||
// gyroscope bias error
|
||||
float gyro_err_data[] = {0.1, 0.2, 0.3}; // static constatnt error
|
||||
dspm::Mat gyro_err(gyro_err_data, 3, 1);
|
||||
|
||||
|
||||
// Measurement noise covariance values for diagonal covariance matrix.
|
||||
// For the real system these values could be adjusted!
|
||||
// These calues depends on how noisy the measurement.
|
||||
//
|
||||
float R[10];
|
||||
for (size_t i = 0; i < 10; i++) {
|
||||
R[i] = 0.01;
|
||||
}
|
||||
|
||||
// Reference vectors
|
||||
float accel0_data[] = {0, 0, 1};
|
||||
// In real system magnetometer vector will have different value and direction
|
||||
// The EKF will calculate them. This value is used as initial state.
|
||||
float magn0_data[] = {1, 0, 0};
|
||||
|
||||
dspm::Mat accel0(accel0_data, 3, 1);
|
||||
dspm::Mat magn0(magn0_data, 3, 1);
|
||||
|
||||
float dt = 0.01;
|
||||
|
||||
dspm::Mat gyro_data(3, 1);
|
||||
int count = 0;
|
||||
|
||||
// Initial rotation matrix
|
||||
dspm::Mat Rm = dspm::Mat::eye(3);
|
||||
dspm::Mat Re = dspm::Mat::eye(3);
|
||||
|
||||
gyro_err *= 1;
|
||||
|
||||
std::cout << "Gyro error: " << gyro_err.t() << std::endl;
|
||||
std::cout << "Calibration phase started: " << std::endl;
|
||||
for (size_t n = 1; n < total_N * 16; n++) {
|
||||
if ((n % 1000) == 0) {
|
||||
std::cout << "Loop " << n << " from " << total_N * 16;
|
||||
std::cout << ", State data : " << ekf13->X.t();
|
||||
}
|
||||
//
|
||||
// This part of the loop related to the system emulation
|
||||
//
|
||||
|
||||
// Generate gyro values for system emulation
|
||||
gyro_data *= 0; // reset gyro value
|
||||
if ((n >= (total_N / 2)) && (n < total_N * 12)) {
|
||||
gyro_data(0, 0) = 1 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
|
||||
gyro_data(1, 0) = 2 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
|
||||
gyro_data(2, 0) = 3 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
|
||||
count++;
|
||||
}
|
||||
dspm::Mat gyro_sample = gyro_data + gyro_err;
|
||||
|
||||
gyro_data *= dt;
|
||||
// Calculate rotation for the last time interval
|
||||
Re = ekf::eul2rotm(gyro_data.data);
|
||||
// Ally rotation to the system rotation matrix
|
||||
Rm = Rm * Re;
|
||||
// Convert rotation matrix to the system attitude quaternion
|
||||
dspm::Mat attitude = ekf::rotm2quat(Rm);
|
||||
// We have to rotate accel and magn to the opposite direction
|
||||
dspm::Mat accel_data = Rm.t() * accel0;
|
||||
dspm::Mat magn_data = Rm.t() * magn0;
|
||||
|
||||
dspm::Mat accel_norm = accel_data / accel_data.norm();
|
||||
dspm::Mat magn_norm = magn_data / magn_data.norm();
|
||||
|
||||
//
|
||||
// This part of the loop related to the real system
|
||||
// Here gyro_sample values must be replaced by measured gyroscope values
|
||||
// and accel_norm and magn_norm should be real measured accel and magn values
|
||||
// The dt in this case should be real time difference in seconds between samples
|
||||
// Fill the input control values with measured gyro values
|
||||
float input_u[] = {gyro_sample(0, 0), gyro_sample(1, 0), gyro_sample(2, 0)};
|
||||
// Process input values to new state
|
||||
ekf13->Process(input_u, dt);
|
||||
dspm::Mat q_norm(ekf13->X.data, 4, 1);
|
||||
q_norm /= q_norm.norm();
|
||||
// Correct state and calculate gyro and magnetometer values.
|
||||
// Here accel_norm and magn_norm should be real measured accel and magn values
|
||||
ekf13->UpdateRefMeasurementMagn(accel_norm.data, magn_norm.data, R);
|
||||
}
|
||||
std::cout << "Calibration phase finished." << std::endl << std::endl;
|
||||
|
||||
std::cout << "Regular calculation started:" << std::endl;
|
||||
|
||||
// Reset rotation nmatrix
|
||||
Rm = dspm::Mat::eye(3);
|
||||
Re = dspm::Mat::eye(3);
|
||||
|
||||
count = 0;
|
||||
// Set initial state
|
||||
ekf13->X(0,0) = 1;
|
||||
ekf13->X(0,1) = 0;
|
||||
ekf13->X(0,2) = 0;
|
||||
ekf13->X(0,3) = 0;
|
||||
|
||||
for (size_t n = 1; n < total_N * 16; n++) {
|
||||
if ((n % 1000) == 0) {
|
||||
std::cout << "Loop " << n << " from " << total_N * 16;
|
||||
std::cout << ", State data : " << ekf13->X.t();
|
||||
}
|
||||
//
|
||||
// This part of the loop related to the system emulation
|
||||
//
|
||||
|
||||
// Generate gyro values for system emulation
|
||||
gyro_data *= 0; // reset gyro value
|
||||
if ((n >= (total_N / 2)) && (n < total_N * 12)) {
|
||||
gyro_data(0, 0) = 1 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
|
||||
gyro_data(1, 0) = 2 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
|
||||
gyro_data(2, 0) = 3 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
|
||||
count++;
|
||||
}
|
||||
dspm::Mat gyro_sample = gyro_data + gyro_err;
|
||||
|
||||
gyro_data *= dt;
|
||||
// Calculate rotation for the last time interval
|
||||
Re = ekf::eul2rotm(gyro_data.data);
|
||||
// Ally rotation to the system rotation matrix
|
||||
Rm = Rm * Re;
|
||||
// Convert rotation matrix to the system attitude quaternion
|
||||
dspm::Mat attitude = ekf::rotm2quat(Rm);
|
||||
// We have to rotate accel and magn to the opposite direction
|
||||
dspm::Mat accel_data = Rm.t() * accel0;
|
||||
dspm::Mat magn_data = Rm.t() * magn0;
|
||||
|
||||
dspm::Mat accel_norm = accel_data / accel_data.norm();
|
||||
dspm::Mat magn_norm = magn_data / magn_data.norm();
|
||||
|
||||
//
|
||||
// This part of the loop related to the real system
|
||||
// Here gyro_sample values must be replaced by measured gyroscope values
|
||||
// and accel_norm and magn_norm should be real measured accel and magn values
|
||||
// The dt in this case should be real time difference in seconds between samples
|
||||
// Fill the input control values with measured gyro values
|
||||
float input_u[] = {gyro_sample(0, 0), gyro_sample(1, 0), gyro_sample(2, 0)};
|
||||
// Process input values to new state
|
||||
ekf13->Process(input_u, dt);
|
||||
dspm::Mat q_norm(ekf13->X.data, 4, 1);
|
||||
q_norm /= q_norm.norm();
|
||||
// Correct state and calculate gyro and magnetometer values.
|
||||
// Here accel_norm and magn_norm should be real measured accel and magn values
|
||||
ekf13->UpdateRefMeasurement(accel_norm.data, magn_norm.data, R);
|
||||
}
|
||||
|
||||
std::cout << "Final State data : " << ekf13->X.t();
|
||||
dspm::Mat estimated_error(&ekf13->X.data[4], 3, 1);
|
||||
std::cout << "Estimated error : " << estimated_error.t();
|
||||
std::cout << "Difference between real and estimated errors : " << (gyro_err - estimated_error).t() << std::endl;
|
||||
|
||||
std::cout << "Expected Euler angels (degree) : " << (180/pi*ekf::quat2eul(ekf::rotm2quat(Rm).data)).t();
|
||||
std::cout << "Calculated Euler angels (degree) : " << (180/pi*ekf::quat2eul(ekf13->X.data)).t() << std::endl;
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/esp-dsp:
|
||||
override_path: "../../../"
|
||||
version: "*"
|
||||
@ -0,0 +1,21 @@
|
||||
#
|
||||
# DSP Library
|
||||
#
|
||||
# CONFIG_DSP_ANSI is not set
|
||||
CONFIG_DSP_OPTIMIZED=y
|
||||
# CONFIG_DSP_MAX_FFT_SIZE_512 is not set
|
||||
# CONFIG_DSP_MAX_FFT_SIZE_1024 is not set
|
||||
# CONFIG_DSP_MAX_FFT_SIZE_2048 is not set
|
||||
CONFIG_DSP_MAX_FFT_SIZE_4096=y
|
||||
# CONFIG_DSP_MAX_FFT_SIZE_8192 is not set
|
||||
# CONFIG_DSP_MAX_FFT_SIZE_16384 is not set
|
||||
# CONFIG_DSP_MAX_FFT_SIZE_32768 is not set
|
||||
CONFIG_DSP_MAX_FFT_SIZE=4096
|
||||
# end of DSP Library
|
||||
|
||||
#
|
||||
# ESP System Settings
|
||||
#
|
||||
CONFIG_ESP_INT_WDT=n
|
||||
CONFIG_ESP_TASK_WDT=n
|
||||
# end of ESP System Settings
|
||||
@ -0,0 +1,6 @@
|
||||
# The following 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.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(matrix)
|
||||
@ -0,0 +1,54 @@
|
||||
# Matrix Operations Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example demonstrates how to use Mat class functionality from esp-dsp library. Example does the following steps:
|
||||
|
||||
1. Initialize a matrix A and matirx x
|
||||
2. Calculate matrix b: b = A*x
|
||||
3. Find roots x1_: A*x1_ = b, with different methods
|
||||
4. Print result
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware required
|
||||
|
||||
This example does not require any special hardware, and can be run on any common development board.
|
||||
|
||||
### Configure the project
|
||||
|
||||
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
|
||||
|
||||
### Build and flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
|
||||
|
||||
```
|
||||
idf.py -p PORT 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
|
||||
|
||||
Here is an typical example console output.
|
||||
|
||||
```
|
||||
I (215) main: Start Example.
|
||||
I (215) main: Original vector x:
|
||||
0
|
||||
1
|
||||
2
|
||||
I (215) main: Solve result:
|
||||
0
|
||||
1
|
||||
2
|
||||
I (215) main: Roots result:
|
||||
0
|
||||
1
|
||||
2
|
||||
I (215) main: End Example.
|
||||
|
||||
```
|
||||
@ -0,0 +1 @@
|
||||
idf_component_register(SRCS "dspm_matrix_main.cpp")
|
||||
@ -0,0 +1,62 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "dsp_platform.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_dsp.h"
|
||||
|
||||
static const char *TAG = "main";
|
||||
|
||||
// This example shows how to use Mat class from esp-dsp library.
|
||||
//
|
||||
// First we create matix A and x, and then calculating matrix b as result
|
||||
// A*x = b
|
||||
// Then we can find x as roots of matrices X and b
|
||||
//
|
||||
extern "C" void app_main();
|
||||
|
||||
void app_main()
|
||||
{
|
||||
ESP_LOGI(TAG, "Start Example.");
|
||||
int M = 3;
|
||||
int N = 3;
|
||||
dspm::Mat A(M, N);
|
||||
dspm::Mat x(N, 1);
|
||||
for (int m = 0 ; m < M ; m++) {
|
||||
for (int n = 0 ; n < N ; n++) {
|
||||
A(m, n) = N * m + n;
|
||||
}
|
||||
x(m, 0) = m;
|
||||
}
|
||||
A(0, 0) = 10;
|
||||
A(0, 1) = 11;
|
||||
|
||||
dspm::Mat b = A * x;
|
||||
// Gaussian method
|
||||
dspm::Mat x1_ = dspm::Mat::solve(A, b);
|
||||
// Non Gaussian method
|
||||
dspm::Mat x2_ = dspm::Mat::roots(A, b);
|
||||
|
||||
ESP_LOGI(TAG, "Original vector x:");
|
||||
std::cout << x;
|
||||
ESP_LOGI(TAG, "Solve result:");
|
||||
std::cout << x1_;
|
||||
ESP_LOGI(TAG, "Roots result:");
|
||||
std::cout << x2_;
|
||||
ESP_LOGI(TAG, "End Example.");
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
dependencies:
|
||||
espressif/esp-dsp:
|
||||
override_path: "../../../"
|
||||
version: "*"
|
||||
@ -0,0 +1,9 @@
|
||||
dependencies:
|
||||
idf:
|
||||
version: '>=4.2'
|
||||
description: ESP-DSP is the official DSP library for Espressif SoCs.
|
||||
documentation: https://docs.espressif.com/projects/esp-dsp/en/latest/index.html
|
||||
issues: https://github.com/espressif/esp-dsp/issues
|
||||
repository: https://github.com/espressif/esp-dsp.git
|
||||
url: https://github.com/espressif/esp-dsp
|
||||
version: 1.4.4
|
||||
@ -0,0 +1,83 @@
|
||||
// Copyright 2018-2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _dsp_common_H_
|
||||
#define _dsp_common_H_
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "dsp_err.h"
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||
#include "esp_cpu.h"
|
||||
#else
|
||||
#include "soc/cpu.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief check power of two
|
||||
* The function check if the argument is power of 2.
|
||||
* The implementation use ANSI C and could be compiled and run on any platform
|
||||
*
|
||||
* @return
|
||||
* - true if x is power of two
|
||||
* - false if no
|
||||
*/
|
||||
bool dsp_is_power_of_two(int x);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Power of two
|
||||
* The function return power of 2 for values 2^N.
|
||||
* The implementation use ANSI C and could be compiled and run on any platform
|
||||
*
|
||||
* @return
|
||||
* - power of two
|
||||
*/
|
||||
int dsp_power_of_two(int x);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Logginng for esp32s3 TIE core
|
||||
* Registers covered q0 to q7, ACCX and SAR_BYTE
|
||||
*
|
||||
* @param n_regs: number of registers to be logged at once
|
||||
* @param ...: register codes 0, 1, 2, 3, 4, 5, 6, 7, 'a', 's'
|
||||
*
|
||||
* @return ESP_OK
|
||||
*
|
||||
*/
|
||||
esp_err_t tie_log(int n_regs, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// esp_cpu_get_ccount function is implemented in IDF 4.1 and later
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
#define dsp_get_cpu_cycle_count esp_cpu_get_cycle_count
|
||||
#else
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 0)
|
||||
#define dsp_get_cpu_cycle_count esp_cpu_get_ccount
|
||||
#else
|
||||
#define dsp_get_cpu_cycle_count xthal_get_ccount
|
||||
#endif
|
||||
#endif // ESP_IDF_VERSION
|
||||
|
||||
#endif // _dsp_common_H_
|
||||
@ -0,0 +1,23 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#ifndef _DSP_ERR_H_
|
||||
#define _DSP_ERR_H_
|
||||
|
||||
#include "stdint.h"
|
||||
#include "esp_err.h"
|
||||
#include "dsp_err_codes.h"
|
||||
|
||||
#endif // _DSP_ERR_H_
|
||||
@ -0,0 +1,28 @@
|
||||
// Copyright 2018-2022 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _dsp_error_codes_H_
|
||||
#define _dsp_error_codes_H_
|
||||
|
||||
#define DSP_OK 0 // For internal use only. Please use ESP_OK instead
|
||||
#define ESP_ERR_DSP_BASE 0x70000
|
||||
#define ESP_ERR_DSP_INVALID_LENGTH (ESP_ERR_DSP_BASE + 1)
|
||||
#define ESP_ERR_DSP_INVALID_PARAM (ESP_ERR_DSP_BASE + 2)
|
||||
#define ESP_ERR_DSP_PARAM_OUTOFRANGE (ESP_ERR_DSP_BASE + 3)
|
||||
#define ESP_ERR_DSP_UNINITIALIZED (ESP_ERR_DSP_BASE + 4)
|
||||
#define ESP_ERR_DSP_REINITIALIZED (ESP_ERR_DSP_BASE + 5)
|
||||
#define ESP_ERR_DSP_ARRAY_NOT_ALIGNED (ESP_ERR_DSP_BASE + 6)
|
||||
|
||||
|
||||
#endif // _dsp_error_codes_H_
|
||||
@ -0,0 +1,30 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#ifndef dsp_platform_h_
|
||||
#define dsp_platform_h_
|
||||
#include "esp_idf_version.h"
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||
#include "esp_cpu.h"
|
||||
#else
|
||||
#include "soc/cpu.h"
|
||||
#endif
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/portable.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#endif // dsp_platform_h_
|
||||
@ -0,0 +1,37 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _DSP_TESTS_H_
|
||||
#define _DSP_TESTS_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
#define TEST_ASSERT_EXEC_IN_RANGE(min_exec, max_exec, actual) \
|
||||
if (actual >= max_exec) { \
|
||||
ESP_LOGE("", "Time error. Expected max: %i, reached: %i", (int)max_exec, (int)actual);\
|
||||
TEST_ASSERT_MESSAGE (false, "Exec time takes more than expected! ");\
|
||||
}\
|
||||
if (actual < min_exec) {\
|
||||
ESP_LOGE("", "Time error. Expected min: %i, reached: %i", (int)min_exec, (int)actual);\
|
||||
TEST_ASSERT_MESSAGE (false, "Exec time takes less then expected!");\
|
||||
}
|
||||
|
||||
|
||||
// memalign function is implemented in IDF 4.3 and later
|
||||
#if ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(4, 3, 0)
|
||||
#define memalign(align_, size_) malloc(size_)
|
||||
#endif
|
||||
|
||||
#endif // _DSP_TESTS_H_
|
||||
@ -0,0 +1,40 @@
|
||||
#ifndef _dsp_types_H_
|
||||
#define _dsp_types_H_
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
// union to simplify access to the 16 bit data
|
||||
typedef union sc16_u
|
||||
{
|
||||
struct
|
||||
{
|
||||
int16_t re;
|
||||
int16_t im;
|
||||
};
|
||||
uint32_t data;
|
||||
}sc16_t;
|
||||
|
||||
typedef union fc32_u
|
||||
{
|
||||
struct
|
||||
{
|
||||
float re;
|
||||
float im;
|
||||
};
|
||||
uint64_t data;
|
||||
}fc32_t;
|
||||
|
||||
typedef struct image2d_s
|
||||
{
|
||||
void* data; // could be int8_t, unt8_t, int16_t, unt16_t, float
|
||||
int step_x; // step of elements by X
|
||||
int step_y; // step of elements by Y, usually is 1
|
||||
int stride_x; // stride width: size of the elements in X axis * by step_x + padding
|
||||
int stride_y; // stride height: size of the elements in Y axis * by step_y + padding
|
||||
// Point[x,y] = data[width*y*step_y + x*step_x];
|
||||
// Full data size = width*height
|
||||
|
||||
} image2d_t;
|
||||
|
||||
#endif // _dsp_types_H_
|
||||
@ -0,0 +1,65 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _esp_dsp_H_
|
||||
#define _esp_dsp_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
// Common includes
|
||||
#include "dsp_common.h"
|
||||
#include "dsp_types.h"
|
||||
|
||||
// Signal processing
|
||||
#include "dsps_dotprod.h"
|
||||
#include "dsps_math.h"
|
||||
#include "dsps_fir.h"
|
||||
#include "dsps_biquad.h"
|
||||
#include "dsps_biquad_gen.h"
|
||||
#include "dsps_wind.h"
|
||||
#include "dsps_conv.h"
|
||||
#include "dsps_corr.h"
|
||||
|
||||
#include "dsps_d_gen.h"
|
||||
#include "dsps_h_gen.h"
|
||||
#include "dsps_tone_gen.h"
|
||||
#include "dsps_snr.h"
|
||||
#include "dsps_sfdr.h"
|
||||
|
||||
#include "dsps_fft2r.h"
|
||||
#include "dsps_fft4r.h"
|
||||
#include "dsps_dct.h"
|
||||
|
||||
// Matrix operations
|
||||
#include "dspm_mult.h"
|
||||
|
||||
// Support functions
|
||||
#include "dsps_view.h"
|
||||
|
||||
// Image processing functions:
|
||||
#include "dspi_dotprod.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "mat.h"
|
||||
#endif
|
||||
|
||||
#endif // _esp_dsp_H_
|
||||
@ -0,0 +1,21 @@
|
||||
// Copyright 2018-2020 spressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This file include defenitions that are emulate esp-idf error codes
|
||||
|
||||
#ifndef _esp_attr_h_
|
||||
#define _esp_attr_h_
|
||||
|
||||
|
||||
#endif // _esp_attr_h_
|
||||
@ -0,0 +1,29 @@
|
||||
// Copyright 2018-2020 spressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This file include defenitions that are emulate esp-idf error codes
|
||||
|
||||
#ifndef _esp_err_h_
|
||||
#define _esp_err_h_
|
||||
|
||||
#include <stdlib.h>
|
||||
typedef int esp_err_t;
|
||||
|
||||
#define ESP_OK 0
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif // M_PI
|
||||
|
||||
#endif // _esp_err_h_
|
||||
@ -0,0 +1,24 @@
|
||||
// Copyright 2018-2020 spressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This file include defenitions that are emulate esp-idf error codes
|
||||
|
||||
#ifndef _esp_log_h_
|
||||
#define _esp_log_h_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ESP_LOGD
|
||||
|
||||
#endif // _esp_log_h_
|
||||
@ -0,0 +1,4 @@
|
||||
#ifndef _sdkconfig_h_
|
||||
#define _sdkconfig_h_
|
||||
|
||||
#endif // _sdkconfig_h_
|
||||
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "dsp_common.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#define TIE_LOG_ENABLED 1
|
||||
|
||||
#if (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
esp_err_t tie_log(int n_regs, ...){
|
||||
|
||||
#if !TIE_LOG_ENABLED
|
||||
return ESP_OK;
|
||||
#else
|
||||
|
||||
va_list list;
|
||||
va_start(list, n_regs);
|
||||
|
||||
uint32_t reg_128_bits[4] = {0, 0, 0, 0};
|
||||
int reg_code;
|
||||
|
||||
for(int i = 0; i < n_regs; i++){
|
||||
reg_code = va_arg(list, int);
|
||||
|
||||
// ACCX register
|
||||
if( reg_code == 'a'){
|
||||
asm volatile("rur.accx_0 %0" : "=a" (reg_128_bits[0]));
|
||||
asm volatile("rur.accx_1 %0" : "=a" (reg_128_bits[1]));
|
||||
printf("ACCX - %02x %08x", (unsigned int)reg_128_bits[1], (unsigned int)reg_128_bits[0]);
|
||||
printf(" --- %llu\n", (long long unsigned)reg_128_bits[1] << 32 | (unsigned int)reg_128_bits[0]);
|
||||
}
|
||||
|
||||
// SAR:_BYTE register
|
||||
else if( reg_code == 's'){
|
||||
asm volatile("rur.sar_byte %0" : "=a" (reg_128_bits[0]));
|
||||
printf("SAR_BYTE - %d\n", (unsigned int)reg_128_bits[0]);
|
||||
}
|
||||
|
||||
// Q0 - Q7 registers
|
||||
else if((reg_code >= 0) && (reg_code <= 7)){
|
||||
switch(reg_code){
|
||||
case 0 : {
|
||||
asm volatile("ee.movi.32.a q0, %0, 0" : "=a" (reg_128_bits[0]));
|
||||
asm volatile("ee.movi.32.a q0, %0, 1" : "=a" (reg_128_bits[1]));
|
||||
asm volatile("ee.movi.32.a q0, %0, 2" : "=a" (reg_128_bits[2]));
|
||||
asm volatile("ee.movi.32.a q0, %0, 3" : "=a" (reg_128_bits[3]));
|
||||
printf("Q0");
|
||||
break;
|
||||
}
|
||||
case 1 : {
|
||||
asm volatile("ee.movi.32.a q1, %0, 0" : "=a" (reg_128_bits[0]));
|
||||
asm volatile("ee.movi.32.a q1, %0, 1" : "=a" (reg_128_bits[1]));
|
||||
asm volatile("ee.movi.32.a q1, %0, 2" : "=a" (reg_128_bits[2]));
|
||||
asm volatile("ee.movi.32.a q1, %0, 3" : "=a" (reg_128_bits[3]));
|
||||
printf("Q1");
|
||||
break;
|
||||
}
|
||||
case 2 : {
|
||||
asm volatile("ee.movi.32.a q2, %0, 0" : "=a" (reg_128_bits[0]));
|
||||
asm volatile("ee.movi.32.a q2, %0, 1" : "=a" (reg_128_bits[1]));
|
||||
asm volatile("ee.movi.32.a q2, %0, 2" : "=a" (reg_128_bits[2]));
|
||||
asm volatile("ee.movi.32.a q2, %0, 3" : "=a" (reg_128_bits[3]));
|
||||
printf("Q2");
|
||||
break;
|
||||
}
|
||||
case 3 : {
|
||||
asm volatile("ee.movi.32.a q3, %0, 0" : "=a" (reg_128_bits[0]));
|
||||
asm volatile("ee.movi.32.a q3, %0, 1" : "=a" (reg_128_bits[1]));
|
||||
asm volatile("ee.movi.32.a q3, %0, 2" : "=a" (reg_128_bits[2]));
|
||||
asm volatile("ee.movi.32.a q3, %0, 3" : "=a" (reg_128_bits[3]));
|
||||
printf("Q3");
|
||||
break;
|
||||
}
|
||||
case 4 : {
|
||||
asm volatile("ee.movi.32.a q4, %0, 0" : "=a" (reg_128_bits[0]));
|
||||
asm volatile("ee.movi.32.a q4, %0, 1" : "=a" (reg_128_bits[1]));
|
||||
asm volatile("ee.movi.32.a q4, %0, 2" : "=a" (reg_128_bits[2]));
|
||||
asm volatile("ee.movi.32.a q4, %0, 3" : "=a" (reg_128_bits[3]));
|
||||
printf("Q4");
|
||||
break;
|
||||
}
|
||||
case 5 : {
|
||||
asm volatile("ee.movi.32.a q5, %0, 0" : "=a" (reg_128_bits[0]));
|
||||
asm volatile("ee.movi.32.a q5, %0, 1" : "=a" (reg_128_bits[1]));
|
||||
asm volatile("ee.movi.32.a q5, %0, 2" : "=a" (reg_128_bits[2]));
|
||||
asm volatile("ee.movi.32.a q5, %0, 3" : "=a" (reg_128_bits[3]));
|
||||
printf("Q5");
|
||||
break;
|
||||
}
|
||||
case 6 : {
|
||||
asm volatile("ee.movi.32.a q6, %0, 0" : "=a" (reg_128_bits[0]));
|
||||
asm volatile("ee.movi.32.a q6, %0, 1" : "=a" (reg_128_bits[1]));
|
||||
asm volatile("ee.movi.32.a q6, %0, 2" : "=a" (reg_128_bits[2]));
|
||||
asm volatile("ee.movi.32.a q6, %0, 3" : "=a" (reg_128_bits[3]));
|
||||
printf("Q6");
|
||||
break;
|
||||
}
|
||||
case 7 : {
|
||||
asm volatile("ee.movi.32.a q7, %0, 0" : "=a" (reg_128_bits[0]));
|
||||
asm volatile("ee.movi.32.a q7, %0, 1" : "=a" (reg_128_bits[1]));
|
||||
asm volatile("ee.movi.32.a q7, %0, 2" : "=a" (reg_128_bits[2]));
|
||||
asm volatile("ee.movi.32.a q7, %0, 3" : "=a" (reg_128_bits[3]));
|
||||
printf("Q7");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf(" - 0x%08X %08X %08X %08X --- ", (unsigned int)reg_128_bits[3], (unsigned int)reg_128_bits[2], (unsigned int)reg_128_bits[1], (unsigned int)reg_128_bits[0]);
|
||||
printf("%u %u %u %u %u %u %u %u\n", (unsigned int)reg_128_bits[3] >> 16, (unsigned int)reg_128_bits[3] & 0x0000FFFF,
|
||||
(unsigned int)reg_128_bits[2] >> 16, (unsigned int)reg_128_bits[2] & 0x0000FFFF,
|
||||
(unsigned int)reg_128_bits[1] >> 16, (unsigned int)reg_128_bits[1] & 0x0000FFFF,
|
||||
(unsigned int)reg_128_bits[0] >> 16, (unsigned int)reg_128_bits[0] & 0x0000FFFF);
|
||||
}
|
||||
else{
|
||||
printf("Bad register code");
|
||||
}
|
||||
}
|
||||
printf("------------------------------------------------------------------------------------\n");
|
||||
|
||||
return ESP_OK;
|
||||
#endif //TIE_LOG_ENABLED
|
||||
}
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S3
|
||||
@ -0,0 +1,30 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "dsp_common.h"
|
||||
|
||||
bool dsp_is_power_of_two(int x)
|
||||
{
|
||||
return (x != 0) && ((x & (x - 1)) == 0);
|
||||
}
|
||||
|
||||
int dsp_power_of_two(int x)
|
||||
{
|
||||
for (size_t i = 0; i < 32; i++)
|
||||
{
|
||||
x = x >> 1;
|
||||
if(0 == x) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,144 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "dsps_conv_platform.h"
|
||||
#if (dsps_ccorr_f32_ae32_enabled == 1)
|
||||
|
||||
#include "dsps_conv_f32_m_ae32.S"
|
||||
|
||||
// This is dot product function for ESP32 processor.
|
||||
.text
|
||||
.align 4
|
||||
.global dsps_ccorr_f32_ae32
|
||||
.type dsps_ccorr_f32_ae32,@function
|
||||
// The function implements the C code from dsps_ccorr_f32_ansi:
|
||||
//esp_err_t dsps_ccorr_f32_ansi(const float *Signal, const int siglen, const float *Kernel, const int kernlen, float *corrout);
|
||||
//
|
||||
dsps_ccorr_f32_ae32:
|
||||
// Signal - a2
|
||||
// siglen - a3
|
||||
// Kernel - a4
|
||||
// kernlen - a5
|
||||
// corrout - a6
|
||||
//
|
||||
// a11 - loop length
|
||||
|
||||
entry a1, 16
|
||||
// Array increment for floating point data should be 4
|
||||
sub a10, a3, a5
|
||||
bgez a10, dsps_ccorr_positive
|
||||
addi a10, a2, 0
|
||||
addi a2, a4, 0
|
||||
addi a4, a10, 0
|
||||
|
||||
addi a10, a3, 0
|
||||
addi a3, a5, 0
|
||||
addi a5, a10, 0
|
||||
|
||||
dsps_ccorr_positive:
|
||||
movi.n a8, 4
|
||||
addi a11, a5, 0 // lkern - loop counter
|
||||
movi.n a14, 0
|
||||
addi a9, a14, 1
|
||||
|
||||
movi.n a7, 4
|
||||
movi.n a8, -4
|
||||
|
||||
mull a13, a5, a7 // a13 - kernlen*4
|
||||
add a13, a13, a4 // a13 - Kernel[kernlen]
|
||||
addi a13, a13, -4 // a13 - Kernel[kernlen - 1]
|
||||
ccorr_loop1:
|
||||
// Clear initial state of the result register
|
||||
addi a10, a13, 0 // a10 - Kernel
|
||||
addi a12, a2, 0 // a12 - Signal
|
||||
wfr f1, a14 // clear output: convout[n] = 0;
|
||||
|
||||
// a12 - sig[0]
|
||||
// a10 - kern[n];
|
||||
// a9 - n+1
|
||||
// a7 - 4,
|
||||
// a8 - -4,
|
||||
conv_f32_ae32 a12, a10, a9, a7, a7, loop1
|
||||
|
||||
addi a9, a9, 1 // (n+1)++
|
||||
addi a13, a13, -4 // kern[n] - a4--
|
||||
|
||||
ssi f1, a6, 0 // Store result from f1 to memory at a6
|
||||
addi a6, a6, 4 // convout++ - increment output pointer
|
||||
|
||||
addi a11, a11, -1
|
||||
bnez a11, ccorr_loop1
|
||||
|
||||
// a11 - loop counter = siglen - kernlen - 1
|
||||
addi a9, a2, 4 // sig[1] - sig[kmin]
|
||||
addi a13, a5, 0
|
||||
|
||||
// skip loop if 0
|
||||
sub a11, a3, a5 // a11 - loop counter
|
||||
beqz a11, skip_ccorr_loop2
|
||||
|
||||
ccorr_loop2:
|
||||
|
||||
// Clear initial state of the result register
|
||||
addi a12, a9, 0 // a12 - Signal[kmin]
|
||||
addi a10, a4, 0 // a10 - Kernel
|
||||
wfr f1, a14 // clear output: convout[n] = 0;
|
||||
|
||||
// a12 - sig[kmin]
|
||||
// a10 - kern[0];
|
||||
// a11 - kernlen
|
||||
// a7 - 4,
|
||||
conv_f32_ae32 a12, a10, a13, a7, a7, loop2
|
||||
|
||||
addi a9, a9, 4 // in1++
|
||||
|
||||
ssi f1, a6, 0 // Store result from f1 to memory at a6
|
||||
addi a6, a6, 4 // convout++ - increment output pointer
|
||||
|
||||
addi a11, a11, -1
|
||||
bnez a11, ccorr_loop2
|
||||
|
||||
|
||||
skip_ccorr_loop2:
|
||||
|
||||
// a9 - the same
|
||||
addi a11, a5, -1
|
||||
addi a13, a5, -1
|
||||
ccorr_loop3:
|
||||
|
||||
// Clear initial state of the result register
|
||||
addi a12, a9, 0 // a12 - Signal[kmin]
|
||||
addi a10, a4, 0 // a10 - Kernel
|
||||
wfr f1, a14 // clear output: convout[n] = 0;
|
||||
|
||||
// a12 - sig[kmin]
|
||||
// a10 - kern[n - kmin];
|
||||
// a11 - length
|
||||
// a7 - 4,
|
||||
// a8 - -4,
|
||||
conv_f32_ae32 a12, a10, a11, a7, a7, loop3
|
||||
|
||||
addi a9, a9, 4 // n++
|
||||
|
||||
ssi f1, a6, 0 // Store result from f1 to memory at a6
|
||||
addi a6, a6, 4 // convout++ - increment output pointer
|
||||
|
||||
addi a11, a11, -1
|
||||
bnez a11, ccorr_loop3
|
||||
skip_ccorr_loop3:
|
||||
|
||||
movi.n a2, 0 // return status ESP_OK
|
||||
retw.n
|
||||
|
||||
#endif // dsps_ccorr_f32_ae32_enabled
|
||||
@ -0,0 +1,81 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "dsps_conv.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "dsps_conv";
|
||||
|
||||
esp_err_t dsps_ccorr_f32_ansi(const float *Signal, const int siglen, const float *Kernel, const int kernlen, float *corrvout)
|
||||
{
|
||||
if (NULL == Signal) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
if (NULL == Kernel) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
if (NULL == corrvout) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
|
||||
float *sig = (float *)Signal;
|
||||
float *kern = (float *)Kernel;
|
||||
int lsig = siglen;
|
||||
int lkern = kernlen;
|
||||
|
||||
if (siglen < kernlen) {
|
||||
sig = (float *)Kernel;
|
||||
kern = (float *)Signal;
|
||||
lsig = kernlen;
|
||||
lkern = siglen;
|
||||
}
|
||||
|
||||
for (int n = 0; n < lkern; n++) {
|
||||
size_t k;
|
||||
size_t kmin = lkern - 1 - n;
|
||||
corrvout[n] = 0;
|
||||
|
||||
for (k = 0; k <= n; k++) {
|
||||
corrvout[n] += sig[k] * kern[kmin + k];
|
||||
}
|
||||
ESP_LOGV(TAG, "L1 k = %i, n = %i , kmin= %i, kmax= %i", 0, n, kmin, kmin + n);
|
||||
}
|
||||
for (int n = lkern; n < lsig; n++) {
|
||||
size_t kmin, kmax, k;
|
||||
|
||||
corrvout[n] = 0;
|
||||
|
||||
kmin = n - lkern + 1;
|
||||
kmax = n;
|
||||
for (k = kmin; k <= kmax; k++) {
|
||||
corrvout[n] += sig[k] * kern[k - kmin];
|
||||
}
|
||||
ESP_LOGV(TAG, "L2 n=%i, kmin = %i, kmax = %i , k-kmin = %i", n, kmin, kmax, 0);
|
||||
}
|
||||
|
||||
for (int n = lsig; n < lsig + lkern - 1; n++) {
|
||||
size_t kmin, kmax, k;
|
||||
|
||||
corrvout[n] = 0;
|
||||
|
||||
kmin = n - lkern + 1;
|
||||
kmax = lsig - 1;
|
||||
|
||||
for (k = kmin; k <= kmax; k++) {
|
||||
corrvout[n] += sig[k] * kern[k - kmin];
|
||||
}
|
||||
ESP_LOGV(TAG, "L3 n=%i, kmin = %i, kmax = %i , k - kmin = %i", n, kmin, kmax, kmax - kmin);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -0,0 +1,147 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "dsps_conv_platform.h"
|
||||
#if (dsps_conv_f32_ae32_enabled == 1)
|
||||
|
||||
#include "dsps_conv_f32_m_ae32.S"
|
||||
|
||||
// This is dot product function for ESP32 processor.
|
||||
.text
|
||||
.align 4
|
||||
.global dsps_conv_f32_ae32
|
||||
.type dsps_conv_f32_ae32,@function
|
||||
// The function implements the C code from dsps_conv_f32_ansi:
|
||||
//esp_err_t dsps_conv_f32_ansi(const float *Signal, const int siglen, const float *Kernel, const int kernlen, float *convout);
|
||||
//
|
||||
dsps_conv_f32_ae32:
|
||||
// Signal - a2
|
||||
// siglen - a3
|
||||
// Kernel - a4
|
||||
// kernlen - a5
|
||||
// convout - a6
|
||||
//
|
||||
// a11 - loop length
|
||||
|
||||
entry a1, 16
|
||||
// Array increment for floating point data should be 4
|
||||
sub a10, a3, a5
|
||||
bgez a10, dsps_conv_positive
|
||||
addi a10, a2, 0
|
||||
addi a2, a4, 0
|
||||
addi a4, a10, 0
|
||||
|
||||
addi a10, a3, 0
|
||||
addi a3, a5, 0
|
||||
addi a5, a10, 0
|
||||
|
||||
dsps_conv_positive:
|
||||
movi.n a8, 4
|
||||
addi a11, a5, 0 // lkern - loop counter
|
||||
movi.n a14, 0
|
||||
addi a9, a14, 1
|
||||
|
||||
movi.n a7, 4
|
||||
movi.n a8, -4
|
||||
|
||||
conv_loop1:
|
||||
// Clear initial state of the result register
|
||||
addi a10, a4, 0 // a10 - Kernel
|
||||
addi a12, a2, 0 // a12 - Signal
|
||||
wfr f1, a14 // clear output: convout[n] = 0;
|
||||
|
||||
// a12 - sig[0]
|
||||
// a10 - kern[n];
|
||||
// a9 - n+1
|
||||
// a7 - 4,
|
||||
// a8 - -4,
|
||||
conv_f32_ae32 a12, a10, a9, a7, a8, loop1
|
||||
|
||||
addi a9, a9, 1 // (n+1)++
|
||||
addi a4, a4, 4 // kern[n] - a4++
|
||||
|
||||
ssi f1, a6, 0 // Store result from f1 to memory at a6
|
||||
addi a6, a6, 4 // convout++ - increment output pointer
|
||||
|
||||
addi a11, a11, -1
|
||||
bnez a11, conv_loop1
|
||||
|
||||
|
||||
// a11 - loop counter = siglen - kernlen - 1
|
||||
addi a9, a2, 0 // sig[1] - sig[kmin]
|
||||
addi a13, a5, 0
|
||||
|
||||
// skip loop if 0
|
||||
sub a11, a3, a5 // a11 - loop counter
|
||||
beqz a11, skip_conv_loop2
|
||||
|
||||
conv_loop2:
|
||||
|
||||
// Clear initial state of the result register
|
||||
addi a12, a9, 4 // a12 - Signal[kmin]
|
||||
addi a10, a4, -4 // a10 - Kernel
|
||||
wfr f1, a14 // clear output: convout[n] = 0;
|
||||
|
||||
// a12 - sig[kmin]
|
||||
// a10 - kern[n - kmin];
|
||||
// a11 - length
|
||||
// a7 - 4,
|
||||
// a8 - -4,
|
||||
conv_f32_ae32 a12, a10, a13, a7, a8, loop2
|
||||
|
||||
addi a9, a9, 4 // (n+1)++
|
||||
|
||||
ssi f1, a6, 0 // Store result from f1 to memory at a6
|
||||
addi a6, a6, 4 // convout++ - increment output pointer
|
||||
|
||||
addi a11, a11, -1
|
||||
bnez a11, conv_loop2
|
||||
|
||||
skip_conv_loop2:
|
||||
|
||||
// sub a11, a3, a5 // a11 - loop counter
|
||||
// beqz a11, skip_conv_loop3
|
||||
// a9 - the same
|
||||
addi a11, a5, -1
|
||||
addi a13, a5, -1
|
||||
// beqz a11, skip_conv_loop3
|
||||
conv_loop3:
|
||||
|
||||
// Clear initial state of the result register
|
||||
addi a12, a9, 4 // a12 - Signal[kmin]
|
||||
addi a10, a4, -4 // a10 - Kernel
|
||||
wfr f1, a14 // clear output: convout[n] = 0;
|
||||
|
||||
// a12 - sig[kmin]
|
||||
// a10 - kern[n - kmin];
|
||||
// a11 - length
|
||||
// a7 - 4,
|
||||
// a8 - -4,
|
||||
conv_f32_ae32 a12, a10, a13, a7, a8, loop3
|
||||
|
||||
addi a9, a9, 4 // (n+1)++
|
||||
|
||||
ssi f1, a6, 0 // Store result from f1 to memory at a6
|
||||
addi a6, a6, 4 // convout++ - increment output pointer
|
||||
|
||||
addi a13, a13, -1
|
||||
|
||||
addi a11, a11, -1
|
||||
bnez a11, conv_loop3
|
||||
skip_conv_loop3:
|
||||
|
||||
movi.n a2, 0 // return status ESP_OK
|
||||
retw.n
|
||||
|
||||
#endif // dsps_conv_f32_ae32_enabled
|
||||
@ -0,0 +1,81 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "dsps_conv.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "dsps_conv";
|
||||
|
||||
esp_err_t dsps_conv_f32_ansi(const float *Signal, const int siglen, const float *Kernel, const int kernlen, float *convout)
|
||||
{
|
||||
if (NULL == Signal) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
if (NULL == Kernel) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
if (NULL == convout) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
|
||||
float *sig = (float *)Signal;
|
||||
float *kern = (float *)Kernel;
|
||||
int lsig = siglen;
|
||||
int lkern = kernlen;
|
||||
|
||||
if (siglen < kernlen) {
|
||||
sig = (float *)Kernel;
|
||||
kern = (float *)Signal;
|
||||
lsig = kernlen;
|
||||
lkern = siglen;
|
||||
}
|
||||
|
||||
for (int n = 0; n < lkern; n++) {
|
||||
size_t k;
|
||||
|
||||
convout[n] = 0;
|
||||
|
||||
for (k = 0; k <= n; k++) {
|
||||
convout[n] += sig[k] * kern[n - k];
|
||||
}
|
||||
ESP_LOGV(TAG,"L1 kmin = %i, kmax = %i , n-kmin = %i", 0, n, n);
|
||||
}
|
||||
for (int n = lkern; n < lsig; n++) {
|
||||
size_t kmin, kmax, k;
|
||||
|
||||
convout[n] = 0;
|
||||
|
||||
kmin = n - lkern + 1;
|
||||
kmax = n;
|
||||
ESP_LOGV(TAG,"L2 n=%i, kmin = %i, kmax = %i , n-kmin = %i", n, kmin, kmax, n-kmin);
|
||||
for (k = kmin; k <= kmax; k++) {
|
||||
convout[n] += sig[k] * kern[n - k];
|
||||
}
|
||||
}
|
||||
|
||||
for (int n = lsig; n < lsig + lkern - 1; n++) {
|
||||
size_t kmin, kmax, k;
|
||||
|
||||
convout[n] = 0;
|
||||
|
||||
kmin = n - lkern + 1;
|
||||
kmax = lsig - 1;
|
||||
|
||||
for (k = kmin; k <= kmax; k++) {
|
||||
convout[n] += sig[k] * kern[n - k];
|
||||
}
|
||||
ESP_LOGV(TAG,"L3 n=%i, kmin = %i, kmax = %i , n-kmin = %i", n, kmin, kmax, n-kmin);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
.macro conv_f32_ae32 x1 x2 count step1 step2 name
|
||||
// This macro calculates floating point dot product for count float samples
|
||||
// x1, x2 - input arrays
|
||||
// count - amount of samples
|
||||
// step1 - start step
|
||||
//,step2 - A register for array step increment. (should be divided by 4)
|
||||
// f1 - contains initial value
|
||||
//
|
||||
// result in f1
|
||||
//
|
||||
// Macros body:
|
||||
// f1 += x1[]*x2[]; i: 0..counter-1
|
||||
// affected: f0, f1, f2
|
||||
// Example: conv_f32_ae32 a2 a3 a5 a8 a9
|
||||
// a8 == 4, step is 4 bytes
|
||||
// a5 == 32, length of array is 32
|
||||
//
|
||||
lsxp f0, \x2, \step2
|
||||
loopnez \count, loop_mac_end_m_ae32\name
|
||||
lsxp f2, \x1, \step1
|
||||
madd.s f1, f2, f0
|
||||
lsxp f0, \x2, \step2
|
||||
loop_mac_end_m_ae32\name:
|
||||
.endm
|
||||
@ -0,0 +1,77 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "dsps_conv_platform.h"
|
||||
#if (dsps_corr_f32_ae32_enabled == 1)
|
||||
|
||||
#include "dsps_dotprod_f32_m_ae32.S"
|
||||
|
||||
// This is dot product function for ESP32 processor.
|
||||
.text
|
||||
.align 4
|
||||
.global dsps_corr_f32_ae32
|
||||
.type dsps_corr_f32_ae32,@function
|
||||
// The function implements the following C code:
|
||||
//esp_err_t dsps_corr_f32_ansi(const float *Signal, const int siglen, const float *Pattern, const int patlen, float *dest)
|
||||
//{
|
||||
// for (size_t n = 0; n < (siglen - patlen); n++) {
|
||||
// float k_corr = 0;
|
||||
// for (size_t m = 0; m < patlen; m++) {
|
||||
// k_corr += Signal[n + m] * Pattern[m];
|
||||
// }
|
||||
// dest[n] = k_corr;
|
||||
// }
|
||||
// return ESP_OK;
|
||||
//}
|
||||
|
||||
dsps_corr_f32_ae32:
|
||||
// Signal - a2
|
||||
// siglen - a3
|
||||
// Pattern - a4
|
||||
// patlen - a5
|
||||
// dest - a6
|
||||
// a11 - loop length
|
||||
|
||||
entry a1, 16
|
||||
// Array increment for floating point data should be 4
|
||||
movi.n a8, 4
|
||||
movi.n a13, 4
|
||||
sub a11, a3, a5 // a11 = loop length
|
||||
addi a11, a11, 1
|
||||
addi a12, a2, 0 // move input pointer to the a12
|
||||
movi.n a9, 0
|
||||
movi.n a14, 0
|
||||
|
||||
corr_loop:
|
||||
// Clear initial state of the result register
|
||||
addi a10, a4, 0 // a10 - pattern
|
||||
movi.n a9, 0 // clear a9
|
||||
wfr f1, a9 // clrar f1
|
||||
// a12 - input1
|
||||
// a10 - input2
|
||||
// a5 - length
|
||||
// a8 - 4, step in arrays
|
||||
// a9 - 0
|
||||
dotprod_f32_ae32 a12, a10, a5, a9, a8;
|
||||
|
||||
ssi f1, a6, 0 // Store result from f1 to memory at a6
|
||||
addi a6, a6, 4 // y++ - increment output pointer
|
||||
addi a12, a12, 4 // Signal++
|
||||
addi a11, a11, -1
|
||||
bnez a11, corr_loop
|
||||
|
||||
movi.n a2, 0 // return status ESP_OK
|
||||
retw.n
|
||||
|
||||
#endif // dsps_corr_f32_ae32_enabled
|
||||
@ -0,0 +1,40 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "dsps_corr.h"
|
||||
|
||||
esp_err_t dsps_corr_f32_ansi(const float *Signal, const int siglen, const float *Pattern, const int patlen, float *dest)
|
||||
{
|
||||
if (NULL == Signal) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
if (NULL == Pattern) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
if (NULL == dest) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
if (siglen < patlen) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
|
||||
for (size_t n = 0; n <= (siglen - patlen); n++) {
|
||||
float k_corr = 0;
|
||||
for (size_t m = 0; m < patlen; m++) {
|
||||
k_corr += Signal[n + m] * Pattern[m];
|
||||
}
|
||||
dest[n] = k_corr;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
// Copyright 2018-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _dsps_ccorr_H_
|
||||
#define _dsps_ccorr_H_
|
||||
#include "dsp_err.h"
|
||||
|
||||
#include "dsps_conv_platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/**@{*/
|
||||
/**
|
||||
* @brief Cross correlation
|
||||
*
|
||||
* The function make cross correlate between two ignals.
|
||||
* The implementation use ANSI C and could be compiled and run on any platform
|
||||
*
|
||||
* @param[in] Signal1: input array with input 1 signal values
|
||||
* @param[in] siglen1: length of the input 1 signal array
|
||||
* @param[in] Signal2: input array with input 2 signal values
|
||||
* @param[in] siglen2: length of the input signal array
|
||||
* @param corrout: output array with result of cross correlation. The size of dest array must be (siglen1 + siglen2 - 1) !!!
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - One of the error codes from DSP library (one of the input array are NULL, or if (siglen < patlen))
|
||||
*/
|
||||
esp_err_t dsps_ccorr_f32_ansi(const float *Signal, const int siglen, const float *Pattern, const int patlen, float *corrout);
|
||||
esp_err_t dsps_ccorr_f32_ae32(const float *Signal, const int siglen, const float *Pattern, const int patlen, float *corrout);
|
||||
/**}@*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_DSP_OPTIMIZED
|
||||
#if (dsps_ccorr_f32_ae32_enabled == 1)
|
||||
#define dsps_ccorr_f32 dsps_ccorr_f32_ae32
|
||||
#else
|
||||
#define dsps_ccorr_f32 dsps_ccorr_f32_ansi
|
||||
#endif // dsps_ccorr_f32_ae32_enabled
|
||||
#else
|
||||
#define dsps_ccorr_f32 dsps_ccorr_f32_ansi
|
||||
#endif
|
||||
|
||||
#endif // _dsps_conv_H_
|
||||
@ -0,0 +1,65 @@
|
||||
// Copyright 2018-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _dsps_conv_H_
|
||||
#define _dsps_conv_H_
|
||||
#include "dsp_err.h"
|
||||
|
||||
#include "dsps_conv_platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/**@{*/
|
||||
/**
|
||||
* @brief Convolution
|
||||
*
|
||||
* The function convolve Signal array with Kernel array.
|
||||
* The implementation use ANSI C and could be compiled and run on any platform
|
||||
*
|
||||
* @param[in] Signal: input array with signal
|
||||
* @param[in] siglen: length of the input signal
|
||||
* @param[in] Kernel: input array with convolution kernel
|
||||
* @param[in] kernlen: length of the Kernel array
|
||||
* @param convout: output array with convolution result length of (siglen + Kernel -1)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - One of the error codes from DSP library
|
||||
*/
|
||||
esp_err_t dsps_conv_f32_ae32(const float *Signal, const int siglen, const float *Kernel, const int kernlen, float *convout);
|
||||
esp_err_t dsps_conv_f32_ansi(const float *Signal, const int siglen, const float *Kernel, const int kernlen, float *convout);
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_DSP_OPTIMIZED
|
||||
|
||||
#if (dsps_conv_f32_ae32_enabled == 1)
|
||||
#define dsps_conv_f32 dsps_conv_f32_ae32
|
||||
#else
|
||||
#define dsps_conv_f32 dsps_conv_f32_ansi
|
||||
#endif // dsps_conv_f32_ae32_enabled
|
||||
|
||||
#else
|
||||
#define dsps_conv_f32 dsps_conv_f32_ansi
|
||||
#endif
|
||||
|
||||
#endif // _dsps_conv_H_
|
||||
@ -0,0 +1,20 @@
|
||||
#ifndef _dsps_conv_platform_H_
|
||||
#define _dsps_conv_platform_H_
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __XTENSA__
|
||||
#include <xtensa/config/core-isa.h>
|
||||
#include <xtensa/config/core-matmap.h>
|
||||
|
||||
|
||||
#if ((XCHAL_HAVE_FP == 1) && (XCHAL_HAVE_LOOPS == 1))
|
||||
|
||||
#define dsps_conv_f32_ae32_enabled 1
|
||||
#define dsps_ccorr_f32_ae32_enabled 1
|
||||
#define dsps_corr_f32_ae32_enabled 1
|
||||
|
||||
#endif
|
||||
#endif // __XTENSA__
|
||||
|
||||
#endif // _dsps_conv_platform_H_
|
||||
@ -0,0 +1,63 @@
|
||||
// Copyright 2018-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _dsps_corr_H_
|
||||
#define _dsps_corr_H_
|
||||
#include "dsp_err.h"
|
||||
|
||||
#include "dsps_conv_platform.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/**@{*/
|
||||
/**
|
||||
* @brief Correlation with pattern
|
||||
*
|
||||
* The function correlate input sigla array with pattern array.
|
||||
* The implementation use ANSI C and could be compiled and run on any platform
|
||||
*
|
||||
* @param[in] Signal: input array with signal values
|
||||
* @param[in] siglen: length of the signal array
|
||||
* @param[in] Pattern: input array with pattern values
|
||||
* @param[in] patlen: length of the pattern array. The siglen must be bigger then patlen!
|
||||
* @param dest: output array with result of correlation
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - One of the error codes from DSP library (one of the input array are NULL, or if (siglen < patlen))
|
||||
*/
|
||||
esp_err_t dsps_corr_f32_ansi(const float *Signal, const int siglen, const float *Pattern, const int patlen, float *dest);
|
||||
esp_err_t dsps_corr_f32_ae32(const float *Signal, const int siglen, const float *Pattern, const int patlen, float *dest);
|
||||
/**@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_DSP_OPTIMIZED
|
||||
#if (dsps_corr_f32_ae32_enabled == 1)
|
||||
#define dsps_corr_f32 dsps_corr_f32_ae32
|
||||
#else
|
||||
#define dsps_corr_f32 dsps_corr_f32_ansi
|
||||
#endif // dsps_corr_f32_ae32_enabled
|
||||
#else
|
||||
#define dsps_corr_f32 dsps_corr_f32_ansi
|
||||
#endif
|
||||
|
||||
#endif // _dsps_corr_H_
|
||||
@ -0,0 +1,81 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
#include "dsp_platform.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "dsps_ccorr.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
static const char *TAG = "dsps_ccorr";
|
||||
|
||||
#define lenA 8
|
||||
#define lenB 4
|
||||
|
||||
static float inputA[lenA];
|
||||
static float inputB[lenB];
|
||||
static float output[lenA + lenB - 1 + 2];
|
||||
static float output_ref[lenA + lenB - 1 + 2];
|
||||
|
||||
TEST_CASE("dsps_ccorr_f32_ae32 functionality", "[dsps]")
|
||||
{
|
||||
for (int i = 0 ; i < lenA ; i++) {
|
||||
inputA[i] = i + 3;
|
||||
}
|
||||
for (int i = 0 ; i < lenB ; i++) {
|
||||
inputB[i] = i + 10;
|
||||
}
|
||||
for (int i = 0 ; i < (lenA + lenB + 2 - 1); i++) {
|
||||
output[i] = -1;
|
||||
output_ref[i] = -1;
|
||||
}
|
||||
dsps_ccorr_f32_ae32(inputA, lenA, inputB, lenB, &output[0]);
|
||||
dsps_ccorr_f32_ansi(inputA, lenA, inputB, lenB, &output_ref[0]);
|
||||
for (size_t i = 0; i < (lenA + lenB - 1) + 2; i++) {
|
||||
ESP_LOGI(TAG, "Data[%i] = %2.2f, expected = %2.2f", i, output[i], output_ref[i]);
|
||||
}
|
||||
for (size_t i = 0; i < (lenA + lenB - 1) + 2; i++) {
|
||||
TEST_ASSERT_EQUAL(output_ref[i], output[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("dsps_ccorr_f32_ae32 benchmark", "[dsps]")
|
||||
{
|
||||
int max_N = 1024;
|
||||
int ccorr_size = 64;
|
||||
float *x = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(x);
|
||||
float *y = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(y);
|
||||
float *z = (float *)malloc((max_N + ccorr_size - 1) * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(z);
|
||||
|
||||
for (int i = 0 ; i < max_N ; i++) {
|
||||
x[i] = 0;
|
||||
y[i] = 1000;
|
||||
}
|
||||
|
||||
unsigned int start_b = xthal_get_ccount();
|
||||
dsps_ccorr_f32_ae32(x, max_N, y, ccorr_size, &z[0]);
|
||||
unsigned int end_b = xthal_get_ccount();
|
||||
|
||||
float cycles = end_b - start_b;
|
||||
ESP_LOGI(TAG, "dsps_ccorr_f32_ae32 - %f cycles for signal %i and pattern %i", cycles, max_N, ccorr_size);
|
||||
free(x);
|
||||
free(y);
|
||||
free(z);
|
||||
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "unity.h"
|
||||
#include "dsp_platform.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "dsps_ccorr.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_dsp.h"
|
||||
|
||||
static const char *TAG = "dsps_ccorr";
|
||||
|
||||
#define lenA 20
|
||||
#define lenB 20
|
||||
|
||||
static float inputA[lenA];
|
||||
static float inputB[lenB];
|
||||
static float output_fwd[lenA + lenB - 1 + 2];
|
||||
static float output_back[lenA + lenB - 1 + 2];
|
||||
|
||||
TEST_CASE("dsps_ccorr_f32_ansi functionality", "[dsps]")
|
||||
{
|
||||
for (size_t la = 1; la < lenA; la++) {
|
||||
for (size_t lb = 1; lb < lenB; lb++) {
|
||||
for (int i = 0 ; i < lenA ; i++) {
|
||||
inputA[i] = (float)rand() / INT32_MAX;
|
||||
}
|
||||
for (int i = 0 ; i < lenB ; i++) {
|
||||
inputB[i] = (float)rand() / INT32_MAX;
|
||||
}
|
||||
for (int i = 0 ; i < (lenA + lenB - 1 + 2); i++) {
|
||||
output_fwd[i] = -1;
|
||||
output_back[i] = -1;
|
||||
}
|
||||
dsps_ccorr_f32_ansi(inputA, la, inputB, lb, &output_fwd[1]);
|
||||
dsps_ccorr_f32_ansi(inputB, lb, inputA, la, &output_back[1]);
|
||||
TEST_ASSERT_EQUAL(output_fwd[0], -1);
|
||||
TEST_ASSERT_EQUAL(output_fwd[la + lb], -1);
|
||||
TEST_ASSERT_EQUAL(output_back[0], -1);
|
||||
TEST_ASSERT_EQUAL(output_back[la + lb], -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("dsps_ccorr_f32_ansi draw", "[dsps]")
|
||||
{
|
||||
int max_N = 1024;
|
||||
float *x = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(x);
|
||||
float *y = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(y);
|
||||
float *z = (float *)malloc((max_N * 2 + 1) * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(z);
|
||||
int l1 = 8;
|
||||
int l2 = 4;
|
||||
for (int i = 0 ; i < max_N ; i++) {
|
||||
x[i] = 0;
|
||||
y[i] = 0;
|
||||
z[i] = 0;
|
||||
}
|
||||
x[0] = 20;
|
||||
x[7] = 30;
|
||||
y[0] = 10;
|
||||
y[3] = 8;
|
||||
dsps_ccorr_f32_ansi(x, l1, y, l2, &z[0]);
|
||||
|
||||
dsps_view(z, l1 + l2, l1 + l2, 10, -1, 400, '+');
|
||||
for (int i = 0 ; i < (l1 + l2 - 1) ; i++) {
|
||||
ESP_LOGI(TAG, "Z[%i] = %2.2f", i, z[i]);
|
||||
}
|
||||
|
||||
free(x);
|
||||
free(y);
|
||||
free(z);
|
||||
}
|
||||
|
||||
TEST_CASE("dsps_ccorr_f32_ansi benchmark", "[dsps]")
|
||||
{
|
||||
int max_N = 1024;
|
||||
int conv_size = 64;
|
||||
float *x = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(x);
|
||||
float *y = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(y);
|
||||
float *z = (float *)malloc((max_N * 2 + 1) * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(z);
|
||||
|
||||
for (int i = 0 ; i < max_N ; i++) {
|
||||
x[i] = 0;
|
||||
y[i] = 1000;
|
||||
}
|
||||
|
||||
unsigned int start_b = xthal_get_ccount();
|
||||
dsps_ccorr_f32_ansi(x, max_N, y, conv_size, &z[0]);
|
||||
unsigned int end_b = xthal_get_ccount();
|
||||
|
||||
float cycles = end_b - start_b;
|
||||
ESP_LOGI(TAG, "dsps_conv_f32_ansi - %f cycles for signal %i and pattern %i", cycles, max_N, conv_size);
|
||||
free(x);
|
||||
free(y);
|
||||
free(z);
|
||||
}
|
||||
@ -0,0 +1,123 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "unity.h"
|
||||
#include "dsp_platform.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "dsps_conv.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
static const char *TAG = "dsps_conv";
|
||||
|
||||
#define lenA 30
|
||||
#define lenB 30
|
||||
|
||||
static float inputA[lenA];
|
||||
static float inputB[lenB];
|
||||
static float output_ref[lenA + lenB - 1 + 2];
|
||||
static float output_fwd[lenA + lenB - 1 + 2];
|
||||
static float output_back[lenA + lenB - 1 + 2];
|
||||
|
||||
TEST_CASE("dsps_conv_f32_ae32 test output", "[dsps]")
|
||||
{
|
||||
int la = 3;
|
||||
int lb = 2;
|
||||
|
||||
for (int i = 0; i < lenA; i++) {
|
||||
inputA[i] = 10 + i;
|
||||
}
|
||||
for (int i = 0; i < lenB; i++) {
|
||||
inputB[i] = 20 + i;
|
||||
}
|
||||
for (int i = 0; i < (lenA + lenB - 1 + 2); i++) {
|
||||
output_ref[i] = -1;
|
||||
output_fwd[i] = -1;
|
||||
output_back[i] = -1;
|
||||
}
|
||||
dsps_conv_f32_ansi(inputA, la, inputB, lb, &output_ref[1]);
|
||||
dsps_conv_f32_ae32(inputA, la, inputB, lb, &output_fwd[1]);
|
||||
|
||||
for (size_t i = 0; i < (la + lb + 1); i++) {
|
||||
ESP_LOGD(TAG, "la=%i, lb=%i, i=%i, ref=%2.3f, fwd=%2.3f", la, lb, i, output_ref[i], output_fwd[i]);
|
||||
}
|
||||
float max_eps = 0.000001;
|
||||
for (size_t i = 0; i < (la + lb + 1); i++) {
|
||||
if (fabs(output_ref[i] - output_fwd[i]) > max_eps) {
|
||||
ESP_LOGE(TAG, "la=%i, lb=%i, i=%i, ref=%2.3f, fwd=%2.3f", la, lb, i, output_ref[i], output_fwd[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(output_ref[i], output_fwd[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("dsps_conv_f32_ae32 functionality", "[dsps]")
|
||||
{
|
||||
for (size_t la = 2; la < lenA; la++) {
|
||||
for (size_t lb = 2; lb < lenB; lb++) {
|
||||
for (int i = 0 ; i < lenA ; i++) {
|
||||
inputA[i] = (float)rand() / INT32_MAX;
|
||||
}
|
||||
for (int i = 0 ; i < lenB ; i++) {
|
||||
inputB[i] = (float)rand() / INT32_MAX;
|
||||
}
|
||||
for (int i = 0 ; i < (lenA + lenB - 1 + 2); i++) {
|
||||
output_ref[i] = -1;
|
||||
output_fwd[i] = -1;
|
||||
output_back[i] = -1;
|
||||
}
|
||||
dsps_conv_f32_ansi(inputA, la, inputB, lb, &output_ref[1]);
|
||||
dsps_conv_f32_ae32(inputA, la, inputB, lb, &output_fwd[1]);
|
||||
dsps_conv_f32_ae32(inputB, lb, inputA, la, &output_back[1]);
|
||||
float max_eps = 0.000001;
|
||||
for (size_t i = 0; i < (la + lb + 1); i++) {
|
||||
if ((fabs(output_ref[i] - output_fwd[i]) > max_eps) || (fabs(output_ref[i] - output_back[i]) > max_eps) || (fabs(output_back[i] - output_fwd[i]) > max_eps)) {
|
||||
ESP_LOGE(TAG, "la=%i, lb=%i, i=%i, ref=%2.3f, fwd=%2.3f, back=%2.3f", la, lb, i, output_ref[i], output_fwd[i], output_back[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(output_ref[i], output_fwd[i]);
|
||||
TEST_ASSERT_EQUAL(output_ref[i], output_back[i]);
|
||||
TEST_ASSERT_EQUAL(output_back[i], output_fwd[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("dsps_conv_f32_ae32 benchmark", "[dsps]")
|
||||
{
|
||||
int max_N = 1024;
|
||||
int conv_size = 64;
|
||||
float *x = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(x);
|
||||
float *y = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(y);
|
||||
float *z = (float *)malloc((max_N * 2 + 1) * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(z);
|
||||
|
||||
for (int i = 0 ; i < max_N ; i++) {
|
||||
x[i] = 0;
|
||||
y[i] = 1000;
|
||||
}
|
||||
|
||||
unsigned int start_b = xthal_get_ccount();
|
||||
dsps_conv_f32_ae32(x, max_N, y, conv_size, &z[0]);
|
||||
unsigned int end_b = xthal_get_ccount();
|
||||
|
||||
float cycles = end_b - start_b;
|
||||
ESP_LOGI(TAG, "dsps_conv_f32_ae32 - %f cycles for signal %i and pattern %i", cycles, max_N, conv_size);
|
||||
free(x);
|
||||
free(y);
|
||||
free(z);
|
||||
}
|
||||
@ -0,0 +1,146 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "unity.h"
|
||||
#include "dsp_platform.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "dsps_conv.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_dsp.h"
|
||||
|
||||
static const char *TAG = "dsps_conv";
|
||||
|
||||
#define lenA 20
|
||||
#define lenB 20
|
||||
|
||||
static float inputA[lenA];
|
||||
static float inputB[lenB];
|
||||
static float output_ref[lenA + lenB - 1 + 2];
|
||||
static float output_fwd[lenA + lenB - 1 + 2];
|
||||
static float output_back[lenA + lenB - 1 + 2];
|
||||
|
||||
|
||||
esp_err_t dsps_conv_f32_ref(const float *Signal, const int siglen, const float *Kernel, const int kernlen, float *convout)
|
||||
{
|
||||
if (NULL == Signal) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
if (NULL == Kernel) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
if (NULL == convout) {
|
||||
return ESP_ERR_DSP_PARAM_OUTOFRANGE;
|
||||
}
|
||||
|
||||
|
||||
for (int n = 0; n < siglen + kernlen - 1; n++) {
|
||||
size_t kmin, kmax, k;
|
||||
|
||||
convout[n] = 0;
|
||||
|
||||
kmin = (n >= kernlen - 1) ? n - (kernlen - 1) : 0;
|
||||
kmax = (n < siglen - 1) ? n : siglen - 1;
|
||||
|
||||
for (k = kmin; k <= kmax; k++) {
|
||||
convout[n] += Signal[k] * Kernel[n - k];
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
TEST_CASE("dsps_conv_f32_ansi functionality", "[dsps]")
|
||||
{
|
||||
for (size_t la = 1; la < lenA; la++) {
|
||||
for (size_t lb = 1; lb < lenB; lb++) {
|
||||
for (int i = 0 ; i < lenA ; i++) {
|
||||
inputA[i] = (float)rand() / INT32_MAX;
|
||||
}
|
||||
for (int i = 0 ; i < lenB ; i++) {
|
||||
inputB[i] = (float)rand() / INT32_MAX;
|
||||
}
|
||||
for (int i = 0 ; i < (lenA + lenB - 1 + 2); i++) {
|
||||
output_ref[i] = -1;
|
||||
output_fwd[i] = -1;
|
||||
output_back[i] = -1;
|
||||
}
|
||||
dsps_conv_f32_ref(inputA, la, inputB, lb, &output_ref[1]);
|
||||
dsps_conv_f32_ansi(inputA, la, inputB, lb, &output_fwd[1]);
|
||||
dsps_conv_f32_ansi(inputB, lb, inputA, la, &output_back[1]);
|
||||
float max_eps = 0.000001;
|
||||
for (size_t i = 0; i < (la + lb + 1); i++) {
|
||||
if ((fabs(output_ref[i] - output_fwd[i]) > max_eps) || (fabs(output_ref[i] - output_back[i]) > max_eps) || (fabs(output_back[i] - output_fwd[i]) > max_eps)) {
|
||||
ESP_LOGE(TAG, "la=%i, lb=%i, i=%i, ref=%2.3f, fwd=%2.3f, back=%2.3f", la, lb, i, output_ref[i], output_fwd[i], output_back[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(output_ref[i], output_fwd[i]);
|
||||
TEST_ASSERT_EQUAL(output_ref[i], output_back[i]);
|
||||
TEST_ASSERT_EQUAL(output_back[i], output_fwd[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("dsps_conv_f32_ansi draw", "[dsps]")
|
||||
{
|
||||
int max_N = 1024;
|
||||
float *x = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(x);
|
||||
float *y = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(y);
|
||||
float *z = (float *)malloc((max_N * 2 + 1) * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(z);
|
||||
|
||||
for (int i = 0 ; i < max_N ; i++) {
|
||||
x[i] = 10;
|
||||
y[i] = 20;
|
||||
z[i] = 0;
|
||||
}
|
||||
|
||||
dsps_conv_f32_ansi(x, 32, y, 16, &z[0]);
|
||||
|
||||
dsps_view(z, 32 + 16, 32 + 16, 10, -1, 4000, '+');
|
||||
|
||||
free(x);
|
||||
free(y);
|
||||
free(z);
|
||||
}
|
||||
|
||||
TEST_CASE("dsps_conv_f32_ansi benchmark", "[dsps]")
|
||||
{
|
||||
int max_N = 1024;
|
||||
int conv_size = 64;
|
||||
float *x = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(x);
|
||||
float *y = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(y);
|
||||
float *z = (float *)malloc((max_N * 2 + 1) * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(z);
|
||||
|
||||
for (int i = 0 ; i < max_N ; i++) {
|
||||
x[i] = 0;
|
||||
y[i] = 1000;
|
||||
}
|
||||
|
||||
unsigned int start_b = xthal_get_ccount();
|
||||
dsps_conv_f32_ansi(x, max_N, y, conv_size, &z[0]);
|
||||
unsigned int end_b = xthal_get_ccount();
|
||||
|
||||
float cycles = end_b - start_b;
|
||||
ESP_LOGI(TAG, "dsps_conv_f32_ansi - %f cycles for signal %i and pattern %i", cycles, max_N, conv_size);
|
||||
free(x);
|
||||
free(y);
|
||||
free(z);
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
#include "dsp_platform.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "dsps_corr.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
static const char *TAG = "dsps_corr";
|
||||
|
||||
#define lenA 15
|
||||
#define lenB 10
|
||||
|
||||
static float inputA[lenA];
|
||||
static float inputB[lenB];
|
||||
static float output[lenA + lenB - 1 + 2];
|
||||
static float output_ref[lenA + lenB - 1 + 2];
|
||||
|
||||
TEST_CASE("dsps_corr_f32_ae32 functionality", "[dsps]")
|
||||
{
|
||||
for (int i = 0 ; i < lenA ; i++) {
|
||||
inputA[i] = i;
|
||||
}
|
||||
for (int i = 0 ; i < lenB ; i++) {
|
||||
inputB[i] = 10 + i;
|
||||
}
|
||||
for (int i = 0 ; i < (lenA - lenB + 2); i++) {
|
||||
output[i] = -1;
|
||||
output_ref[i] = -1;
|
||||
}
|
||||
inputB[0] = 1;
|
||||
dsps_corr_f32_ae32(inputA, lenA, inputB, lenB, &output[1]);
|
||||
dsps_corr_f32_ansi(inputA, lenA, inputB, lenB, &output_ref[1]);
|
||||
for (size_t i = 0; i < (lenA - lenB) + 2; i++) {
|
||||
ESP_LOGD(TAG, "Data[%i] = %2.2f, expected = %2.2f", i, output[i], output_ref[i]);
|
||||
}
|
||||
for (size_t i = 0; i < (lenA - lenB) + 2; i++) {
|
||||
TEST_ASSERT_EQUAL(output_ref[i], output[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("dsps_corr_f32_ae32 benchmark", "[dsps]")
|
||||
{
|
||||
int max_N = 1024;
|
||||
int corr_size = 64;
|
||||
float *x = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(x);
|
||||
float *y = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(y);
|
||||
float *z = (float *)malloc(max_N * sizeof(float));
|
||||
TEST_ASSERT_NOT_NULL(z);
|
||||
|
||||
for (int i = 0 ; i < max_N ; i++) {
|
||||
x[i] = 0;
|
||||
y[i] = 1000;
|
||||
}
|
||||
|
||||
unsigned int start_b = xthal_get_ccount();
|
||||
dsps_corr_f32_ae32(x, max_N, y, corr_size, &z[0]);
|
||||
unsigned int end_b = xthal_get_ccount();
|
||||
|
||||
float cycles = end_b - start_b;
|
||||
ESP_LOGI(TAG, "dsps_corr_f32_ae32 - %f cycles for signal %i and pattern %i", cycles, max_N, corr_size);
|
||||
free(x);
|
||||
free(y);
|
||||
free(z);
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user