feat: Initial esp32-hacking project with firmware sources and docs

This commit is contained in:
user
2026-02-04 12:59:28 +01:00
commit 298e98befb
120 changed files with 22094 additions and 0 deletions

109
esp-crab/slave_recv/.gitignore vendored Normal file
View File

@@ -0,0 +1,109 @@
.config
*.o
*.pyc
*.orig
# gtags
GTAGS
GRTAGS
GPATH
# emacs
.dir-locals.el
# emacs temp file suffixes
*~
.#*
\#*#
# eclipse setting
.settings
# MacOS directory files
.DS_Store
# Components Unit Test Apps files
components/**/build
components/**/sdkconfig
components/**/sdkconfig.old
# Example project files
examples/**/sdkconfig
examples/**/sdkconfig.old
examples/**/build
# 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/
# Downloaded font files
docs/_static/DejaVuSans.ttf
docs/_static/NotoSansSC-Regular.otf
# Unit test app files
tools/unit-test-app/sdkconfig
tools/unit-test-app/sdkconfig.old
tools/unit-test-app/build
tools/unit-test-app/builds
tools/unit-test-app/output
tools/unit-test-app/test_configs
# Unit Test CMake compile log folder
log_ut_cmake
# test application build files
tools/test_apps/**/build
tools/test_apps/**/sdkconfig
tools/test_apps/**/sdkconfig.old
# IDF monitor test
tools/test_idf_monitor/outputs
TEST_LOGS
# gcov coverage reports
*.gcda
*.gcno
coverage.info
coverage_report/
test_multi_heap_host
# VS Code Settings
.vscode/
# VIM files
*.swp
*.swo
# Clion IDE CMake build & config
.idea/
cmake-build-*/
# Results for the checking of the Python coding style and static analysis
.mypy_cache
flake8_output.txt
# ESP-IDF default build directory name
build
build_esp*/
build_linux*/
size_info.txt
# lock files for examples and components
dependencies.lock
# managed_components for examples
managed_components
# pytest log
pytest_embedded_log/
pytest_log/
.pytest_cache/
XUNIT_RESULT.xml

View File

@@ -0,0 +1,15 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctlycmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.5)
add_compile_options(-fdiagnostics-color=always)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
message("EXTRA_COMPONENT_DIRS: " ${EXTRA_COMPONENT_DIRS})
add_definitions(-D CHIP_ID=0)
string(REGEX REPLACE ".*/\(.*\)" "\\1" CURDIR ${CMAKE_CURRENT_SOURCE_DIR})
project(${CURDIR})
git_describe(PROJECT_VERSION ${COMPONENT_DIR})
message("Project commit: " ${PROJECT_VERSION})

View File

@@ -0,0 +1 @@
../../master_recv/components/bsp_C5_dual_antenna

View File

@@ -0,0 +1,5 @@
set(APP_DIR app)
file(GLOB_RECURSE APP_SOURCES ${APP_DIR}/*.c)
idf_component_register(SRCS "app_main.c" ${APP_SOURCES}
INCLUDE_DIRS "." ${APP_DIR})

View File

@@ -0,0 +1,43 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp_log.h"
#include <sys/types.h>
#define GPIO_INPUT_IO 27 // 设置要使用的 GPIO 引脚编号
#define GPIO_INPUT_PIN_SEL (1ULL << GPIO_INPUT_IO) // GPIO 位掩码
extern int64_t time_zero;
static const char *TAG = "GPIO";
extern QueueHandle_t csi_send_queue;
// 中断服务回调函数
static void IRAM_ATTR gpio_isr_handler(void *arg) {
xQueueReset(csi_send_queue);
time_zero = esp_timer_get_time();
uint32_t gpio_num = (uint32_t)arg; // 获取中断的 GPIO 引脚编号
// ets_printf("GPIO %ld triggered! time: %lld", gpio_num,time_since_boot);
}
// GPIO 配置和中断初始化
void init_gpio() {
// 配置 GPIO
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_NEGEDGE, // 设置为下降沿中断
.mode = GPIO_MODE_INPUT, // 设置为输入模式
.pin_bit_mask = GPIO_INPUT_PIN_SEL, // 设置 GPIO 位掩码
.pull_up_en = GPIO_PULLUP_ENABLE, // 启用上拉
.pull_down_en = GPIO_PULLDOWN_DISABLE, // 禁用下拉
};
gpio_config(&io_conf);
// 安装 GPIO 中断服务
gpio_install_isr_service(0);
// 添加中断处理程序
gpio_isr_handler_add(GPIO_INPUT_IO, gpio_isr_handler, (void *)GPIO_INPUT_IO);
ESP_LOGI(TAG, "GPIO %d configured with negative edge interrupt.", GPIO_INPUT_IO);
}

View File

@@ -0,0 +1,11 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void init_gpio(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,162 @@
/* SPI Slave example, receiver (uses SPI Slave driver to communicate with sender)
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 <stdint.h>
#include <stddef.h>
#include <string.h>
#include <math.h>
#include "freertos/FreeRTOS.h"
#include "esp_log.h"
#include "app_ifft.h"
#include "IQmathLib.h"
#define PI 3.14159265358979323846f
#define PI_IQ _IQ(3.14159265358979323846)
#define PI_IQ_N2 _IQ(-6.28318530717958647692)
const int bitReverseTable[64] = {
0, 32, 16, 48, 8, 40, 24, 56,
4, 36, 20, 52, 12, 44, 28, 60,
2, 34, 18, 50, 10, 42, 26, 58,
6, 38, 22, 54, 14, 46, 30, 62,
1, 33, 17, 49, 9, 41, 25, 57,
5, 37, 21, 53, 13, 45, 29, 61,
3, 35, 19, 51, 11, 43, 27, 59,
7, 39, 23, 55, 15, 47, 31, 63
};
void IRAM_ATTR fft_iq(Complex_Iq *X, int inverse)
{
int log2N = 6;
int N = 64;
Complex_Iq *temp = (Complex_Iq *)malloc(64 * sizeof(Complex_Iq));
// Bit-reversed addressing permutation
for (int i = 0; i < N; i++) {
temp[i] = X[bitReverseTable[i]];
}
for (int i = 0; i < N; i++) {
X[i] = temp[i];
}
// Cooley-Tukey iterative FFT
for (int s = 1; s <= log2N; ++s) {
int m = 1 << s; // 2 power s
int m2 = m >> 1; // m/2
Complex_Iq w;
w.real = _IQ16(1.0);
w.imag = _IQ16(0.0);
Complex_Iq wm;
_iq16 angle = _IQ16div(PI_IQ_N2, m);
wm.real = _IQ16cos(angle);
wm.imag = _IQ16sin(angle);
if (inverse) wm.imag = -wm.imag;
for (int j = 0; j < m2; ++j) {
for (int k = j; k < N; k += m) {
Complex_Iq t, u;
u = X[k];
t.real = _IQ16mpy(w.real , X[k + m2].real) - _IQ16mpy(w.imag , X[k + m2].imag);
t.imag = _IQ16mpy(w.real , X[k + m2].imag) + _IQ16mpy(w.imag , X[k + m2].real);
X[k].real = u.real + t.real;
X[k].imag = u.imag + t.imag;
X[k + m2].real = u.real - t.real;
X[k + m2].imag = u.imag - t.imag;
}
float tmpReal = _IQ16mpy(w.real , wm.real) - _IQ16mpy(w.imag , wm.imag);
w.imag = _IQ16mpy(w.real , wm.imag) + _IQ16mpy(w.imag , wm.real);
w.real = tmpReal;
}
}
// Scale for inverse FFT
if (inverse) {
for (int i = 0; i < N; i++) {
X[i].real = _IQdiv64(X[i].real);
X[i].imag = _IQdiv64(X[i].imag);
}
}
free(temp);
}
// Bit reversal of given index 'x' with 'log2n' bits
unsigned int inline bitReverse(unsigned int x, int log2n) {
int n = 0;
for (int i = 0; i < log2n; i++) {
n <<= 1;
n |= (x & 1);
x >>= 1;
}
return n;
}
void IRAM_ATTR fft(Complex *X, int N, int inverse)
{
int log2N = log2(N);
Complex *temp = (Complex *)malloc(N * sizeof(Complex));
// Bit-reversed addressing permutation
for (int i = 0; i < N; i++) {
temp[i] = X[bitReverse(i, log2N)];
}
for (int i = 0; i < N; i++) {
X[i] = temp[i];
}
// Cooley-Tukey iterative FFT
for (int s = 1; s <= log2N; ++s) {
int m = 1 << s; // 2 power s
int m2 = m >> 1; // m/2
Complex w;
w.real = 1.0;
w.imag = 0.0;
Complex wm;
wm.real = cosf(-2.0f * PI / m);
wm.imag = sinf(-2.0f * PI / m);
if (inverse) wm.imag = -wm.imag;
for (int j = 0; j < m2; ++j) {
for (int k = j; k < N; k += m) {
Complex t, u;
u = X[k];
t.real = w.real * X[k + m2].real - w.imag * X[k + m2].imag;
t.imag = w.real * X[k + m2].imag + w.imag * X[k + m2].real;
X[k].real = u.real + t.real;
X[k].imag = u.imag + t.imag;
X[k + m2].real = u.real - t.real;
X[k + m2].imag = u.imag - t.imag;
}
float tmpReal = w.real * wm.real - w.imag * wm.imag;
w.imag = w.real * wm.imag + w.imag * wm.real;
w.real = tmpReal;
}
}
// Scale for inverse FFT
if (inverse) {
for (int i = 0; i < N; i++) {
X[i].real /= N;
X[i].imag /= N;
}
}
free(temp);
}
float complex_magnitude_iq(Complex_Iq z) {
return _IQ16toF(_IQ16mag(z.real, z.imag));
}
float complex_phase_iq(Complex_Iq z) {
return _IQ16toF(_IQ16atan2(z.imag, z.real));
}
float complex_magnitude(Complex z) {
return sqrt(z.real * z.real + z.imag * z.imag);
}
float complex_phase(Complex z) {
return atan2(z.imag, z.real);
}

View File

@@ -0,0 +1,26 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "IQmathLib.h"
typedef struct {
float real;
float imag;
} Complex;
typedef struct {
_iq16 real;
_iq16 imag;
} Complex_Iq;
void IRAM_ATTR fft_iq(Complex_Iq *X, int inverse) ;
void IRAM_ATTR fft(Complex *X, int N, int inverse);
float complex_magnitude_iq(Complex_Iq z);
float complex_phase_iq(Complex_Iq z);
float complex_magnitude(Complex z);
float complex_phase(Complex z);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,43 @@
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "app_uart.h"
static const char *TAG = "UART";
void init_uart() {
uart_config_t uart_config = {
.baud_rate = UART_BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
int intr_alloc_flags = 0;
#if CONFIG_UART_ISR_IN_IRAM
intr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endif
ESP_ERROR_CHECK(uart_driver_install(UART_PORT_NUM, BUF_SIZE * 2, 0 , 0, NULL, intr_alloc_flags));
ESP_ERROR_CHECK(uart_param_config(UART_PORT_NUM, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(UART_PORT_NUM, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
ESP_LOGI("UART", "UART initialized");
}
int uart_send_data(const char *data, uint8_t len) {
return uart_write_bytes(UART_PORT_NUM, data, len);
}
// void uart_receive_data() {
// uint8_t data[BUF_SIZE];
// int length = uart_read_bytes(UART_PORT_NUM, data, BUF_SIZE, 20 / portTICK_RATE_MS);
// if (length > 0) {
// data[length] = '\0';
// ESP_LOGI("UART", "Received %d bytes: '%s'", length, (char *)data);
// }
// }

View File

@@ -0,0 +1,26 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define UART_PORT_NUM UART_NUM_0
#define UART_BAUD_RATE 2000000
#define TXD_PIN (GPIO_NUM_11)
#define RXD_PIN (GPIO_NUM_12)
#define BUF_SIZE 4096
typedef struct {
uint8_t start[2];
uint32_t id;
int64_t time_delta;
float cir[4];
uint8_t end[2];
} __attribute__((packed)) csi_data_t;
void init_uart(void);
int uart_send_data(const char *data, uint8_t len);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,291 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/* Esp-crab Example
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 <stdlib.h>
#include <sys/types.h>
#include "nvs_flash.h"
#include "esp_mac.h"
#include "rom/ets_sys.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_netif.h"
#include "esp_now.h"
#include "app_ifft.h"
#include "app_gpio.h"
#include "esp_timer.h"
#include "app_uart.h"
#include "IQmathLib.h"
#include "bsp_C5_dual_antenna.h"
#include "esp_csi_gain_ctrl.h"
#define CONFIG_LESS_INTERFERENCE_CHANNEL 40
#define CONFIG_WIFI_BAND_MODE WIFI_BAND_MODE_5G_ONLY
#define CONFIG_WIFI_2G_BANDWIDTHS WIFI_BW_HT40
#define CONFIG_WIFI_5G_BANDWIDTHS WIFI_BW_HT40
#define CONFIG_WIFI_2G_PROTOCOL WIFI_PROTOCOL_11N
#define CONFIG_WIFI_5G_PROTOCOL WIFI_PROTOCOL_11N
#define CONFIG_ESP_NOW_PHYMODE WIFI_PHY_MODE_HT40
#define CONFIG_GAIN_CONTROL 1 // 1:enable gain control, 0:disable gain control
#define CONFIG_FORCE_GAIN 0 // 1:force gain control, 0:automatic gain control
#define CONFIG_PRINT_CSI_DATA 1
int64_t time_zero = 0;
typedef struct {
uint32_t id;
uint32_t time;
uint8_t fft_gain;
uint8_t agc_gain;
int8_t buf[256];
} csi_send_queue_t;
uint32_t recv_cnt = 0;
QueueHandle_t csi_send_queue;
static const uint8_t CONFIG_CSI_SEND_MAC[] = {0x1a, 0x00, 0x00, 0x00, 0x00, 0x00};
static const char *TAG = "csi_recv";
static void wifi_init()
{
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(esp_netif_init());
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
ESP_ERROR_CHECK(esp_wifi_start());
esp_wifi_set_band_mode(CONFIG_WIFI_BAND_MODE);
wifi_protocols_t protocols = {
.ghz_2g = CONFIG_WIFI_2G_PROTOCOL,
.ghz_5g = CONFIG_WIFI_5G_PROTOCOL
};
ESP_ERROR_CHECK(esp_wifi_set_protocols(ESP_IF_WIFI_STA, &protocols));
wifi_bandwidths_t bandwidth = {
.ghz_2g = CONFIG_WIFI_2G_BANDWIDTHS,
.ghz_5g = CONFIG_WIFI_5G_BANDWIDTHS
};
ESP_ERROR_CHECK(esp_wifi_set_bandwidths(ESP_IF_WIFI_STA, &bandwidth));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_NONE));
if ((CONFIG_WIFI_BAND_MODE == WIFI_BAND_MODE_2G_ONLY && CONFIG_WIFI_2G_BANDWIDTHS == WIFI_BW_HT20) || (CONFIG_WIFI_BAND_MODE == WIFI_BAND_MODE_5G_ONLY && CONFIG_WIFI_5G_BANDWIDTHS == WIFI_BW_HT20)) {
ESP_ERROR_CHECK(esp_wifi_set_channel(CONFIG_LESS_INTERFERENCE_CHANNEL, WIFI_SECOND_CHAN_NONE));
} else {
ESP_ERROR_CHECK(esp_wifi_set_channel(CONFIG_LESS_INTERFERENCE_CHANNEL, WIFI_SECOND_CHAN_BELOW));
}
ESP_ERROR_CHECK(esp_wifi_set_mac(WIFI_IF_STA, CONFIG_CSI_SEND_MAC));
}
static void wifi_esp_now_init(esp_now_peer_info_t peer)
{
ESP_ERROR_CHECK(esp_now_init());
ESP_ERROR_CHECK(esp_now_set_pmk((uint8_t *)"pmk1234567890123"));
esp_now_rate_config_t rate_config = {
.phymode = CONFIG_ESP_NOW_PHYMODE,
.rate = WIFI_PHY_RATE_MCS0_LGI,
.ersu = false,
.dcm = false
};
ESP_ERROR_CHECK(esp_now_add_peer(&peer));
ESP_ERROR_CHECK(esp_now_set_peer_rate_config(peer.peer_addr, &rate_config));
}
static void wifi_csi_rx_cb(void *ctx, wifi_csi_info_t *info)
{
static int64_t last_time = 0;
if (!info || !info->buf) {
ESP_LOGW(TAG, "<%s> wifi_csi_cb", esp_err_to_name(ESP_ERR_INVALID_ARG));
return;
}
if (memcmp(info->mac, CONFIG_CSI_SEND_MAC, 6)) {
return;
}
const wifi_pkt_rx_ctrl_t *rx_ctrl = &info->rx_ctrl;
static int s_count = 0;
static uint8_t agc_gain = 0;
static int8_t fft_gain = 0;
#if CONFIG_GAIN_CONTROL
static uint8_t agc_gain_baseline = 0;
static int8_t fft_gain_baseline = 0;
esp_csi_gain_ctrl_get_rx_gain(info, &agc_gain, &fft_gain);
if (s_count < 100) {
esp_csi_gain_ctrl_record_rx_gain(agc_gain, fft_gain);
} else if (s_count == 100) {
esp_csi_gain_ctrl_get_rx_gain_baseline(&agc_gain_baseline, &fft_gain_baseline);
#if CONFIG_FORCE_GAIN
esp_csi_gain_ctrl_set_rx_force_gain(agc_gain_baseline, fft_gain_baseline);
ESP_LOGI(TAG, "fft_force %d, agc_force %d", fft_gain_baseline, agc_gain_baseline);
#endif
}
#endif
csi_send_queue_t *csi_send_queuedata = (csi_send_queue_t *)calloc(1, sizeof(csi_send_queue_t));
memcpy(&(csi_send_queuedata->id), info->payload + 15, sizeof(uint32_t));
csi_send_queuedata->time = info->rx_ctrl.timestamp;
csi_send_queuedata->agc_gain = agc_gain;
csi_send_queuedata->fft_gain = fft_gain;
memset(csi_send_queuedata->buf, 0, 256);
memcpy(csi_send_queuedata->buf + 8, info->buf, info->len);
xQueueSend(csi_send_queue, &csi_send_queuedata, 0);
#if CONFIG_PRINT_CSI_DATA
if (!s_count) {
ESP_LOGI(TAG, "================ CSI RECV ================");
ets_printf("type,id,mac,rssi,rate,noise_floor,fft_gain,agc_gain,channel,local_timestamp,ant,rx_state,len,first_word,data\n");
}
ets_printf("CSI_DATA,%d," MACSTR ",%d,%d,%d,%d,%d,%d,%d,%d,%d",
csi_send_queuedata->id, MAC2STR(info->mac), rx_ctrl->rssi, rx_ctrl->rate,
rx_ctrl->noise_floor, fft_gain, agc_gain, rx_ctrl->channel,
rx_ctrl->timestamp, rx_ctrl->sig_len, rx_ctrl->rx_state);
ets_printf(",%d,%d,\"[%d", info->len, info->first_word_invalid, info->buf[0]);
for (int i = 1; i < info->len; i++) {
ets_printf(",%d", info->buf[i]);
}
ets_printf("]\"\n");
#endif
s_count++;
recv_cnt++;
}
static void wifi_csi_init()
{
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
csi_send_queue = xQueueCreate(20, sizeof(csi_send_queue_t *));
wifi_csi_config_t csi_config = {
.enable = true,
.acquire_csi_legacy = false,
.acquire_csi_force_lltf = false,
.acquire_csi_ht20 = true,
.acquire_csi_ht40 = true,
.acquire_csi_vht = true,
.acquire_csi_su = false,
.acquire_csi_mu = false,
.acquire_csi_dcm = false,
.acquire_csi_beamformed = false,
.acquire_csi_he_stbc_mode = 2,
.val_scale_cfg = false,
.dump_ack_en = false,
.reserved = false
};
ESP_ERROR_CHECK(esp_wifi_set_csi_config(&csi_config));
ESP_ERROR_CHECK(esp_wifi_set_csi_rx_cb(wifi_csi_rx_cb, NULL));
ESP_ERROR_CHECK(esp_wifi_set_csi(true));
}
static void uart_send_task(void *pvParameter)
{
static int s_count = 0;
csi_send_queue_t *csi_send_queue_data = NULL;
Complex_Iq x_iq[64];
float cir[2] = {};
float pha[2] = {};
while (xQueueReceive(csi_send_queue, &csi_send_queue_data, portMAX_DELAY) == pdTRUE) {
UBaseType_t queueLength = uxQueueMessagesWaiting(csi_send_queue);
if (queueLength > 10) {
ESP_LOGW(TAG, "csi queueLength:%d", queueLength);
}
#if !CONFIG_FORCE_GAIN && CONFIG_GAIN_CONTROL
float scaling_factor = 0;
esp_csi_gain_ctrl_get_gain_compensation(&scaling_factor, csi_send_queue_data->agc_gain, csi_send_queue_data->fft_gain);
#else
float scaling_factor = 1.0f;
#endif
for (int i = 0; i < 64; i++) {
x_iq[i].real = _IQ16(csi_send_queue_data->buf[2 * i]);
x_iq[i].imag = _IQ16(csi_send_queue_data->buf[2 * i + 1]);
}
fft_iq(x_iq, 1);
cir[0] = complex_magnitude_iq(x_iq[0]) * scaling_factor;
pha[0] = complex_phase_iq(x_iq[0]);
for (int i = 64; i < 128; i++) {
x_iq[i - 64].real = _IQ16(csi_send_queue_data->buf[2 * i]);
x_iq[i - 64].imag = _IQ16(csi_send_queue_data->buf[2 * i + 1]);
}
fft_iq(x_iq, 1);
cir[1] = complex_magnitude_iq(x_iq[0]) * scaling_factor;
pha[1] = complex_phase_iq(x_iq[0]);
csi_data_t data = {
.start = {0xAA, 0x55},
.id = csi_send_queue_data->id,
.time_delta = csi_send_queue_data->time - time_zero,
.cir = {cir[0], cir[1], pha[0], pha[1]},
.end = {0x55, 0xAA},
};
uart_send_data((const char *)&data, sizeof(data));
free(csi_send_queue_data);
}
}
void app_main()
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
wifi_init();
/**
* @brief Initialize ESP-NOW
* ESP-NOW protocol see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_now.html
*/
esp_now_peer_info_t peer = {
.channel = CONFIG_LESS_INTERFERENCE_CHANNEL,
.ifidx = WIFI_IF_STA,
.encrypt = false,
.peer_addr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
};
#if CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C6
wifi_esp_now_init(peer);
#endif
init_gpio();
init_uart();
bsp_led_init();
wifi_csi_init();
xTaskCreate(uart_send_task, "uart_send_task", 4096, NULL, 6, NULL);
uint32_t recv_cnt_prv = 0;
while (1) {
static bool level = 1;
static uint8_t time = 100;
if ((recv_cnt - recv_cnt_prv) >= 20) {
recv_cnt_prv = recv_cnt;
time = 100;
bsp_led_set(0, level * 30, level * 30, level * 30);
level = !level;
}
if (time > 0) {
time -= 1;
} else {
bsp_led_set(0, 0, 0, 0);
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}

View File

@@ -0,0 +1,7 @@
## IDF Component Manager Manifest File
dependencies:
idf: '>=4.4.1'
esp_csi_gain_ctrl: ">=0.1.0"
espressif/iqmath: ^1.11.0

View File

@@ -0,0 +1,5 @@
# Name, Type, SubType, Offset, Size
nvs, data, nvs, 0x9000, 0x5000
otadata, data, ota, 0xe000, 0x2000
phy_init, data, phy, 0x10000, 0x1000
factory, app, factory, 0x20000, 0x200000
1 # Name Type SubType Offset Size
2 nvs data nvs 0x9000 0x5000
3 otadata data ota 0xe000 0x2000
4 phy_init data phy 0x10000 0x1000
5 factory app factory 0x20000 0x200000

View File

@@ -0,0 +1,32 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) 5.5.0 Project Minimal Configuration
#
CONFIG_IDF_TARGET="esp32c5"
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_ESP_CONSOLE_UART_CUSTOM=y
CONFIG_ESP_CONSOLE_UART_BAUDRATE=921600
CONFIG_ESP_TASK_WDT_TIMEOUT_S=30
CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=128
CONFIG_ESP_WIFI_CSI_ENABLED=y
CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=n
CONFIG_LV_COLOR_16_SWAP=y
CONFIG_LV_FONT_MONTSERRAT_10=y
CONFIG_LV_FONT_MONTSERRAT_12=y
CONFIG_LV_FONT_MONTSERRAT_16=y
CONFIG_LV_FONT_MONTSERRAT_18=y
CONFIG_LV_FONT_MONTSERRAT_20=y
CONFIG_LV_FONT_MONTSERRAT_22=y
CONFIG_LV_FONT_MONTSERRAT_24=y
CONFIG_LV_FONT_MONTSERRAT_26=y
CONFIG_LV_FONT_MONTSERRAT_28=y
CONFIG_LV_FONT_MONTSERRAT_30=y
CONFIG_LV_FONT_MONTSERRAT_32=y
CONFIG_LV_FONT_MONTSERRAT_34=y
CONFIG_LV_FONT_MONTSERRAT_36=y
CONFIG_LV_FONT_MONTSERRAT_38=y
CONFIG_LV_FONT_MONTSERRAT_40=y
CONFIG_LV_FONT_MONTSERRAT_42=y
CONFIG_LV_FONT_MONTSERRAT_44=y
CONFIG_LV_FONT_MONTSERRAT_46=y
CONFIG_LV_FONT_MONTSERRAT_48=y