feat: Initial esp32-hacking project with firmware sources and docs
This commit is contained in:
109
esp-crab/slave_recv/.gitignore
vendored
Normal file
109
esp-crab/slave_recv/.gitignore
vendored
Normal 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
|
||||
|
||||
15
esp-crab/slave_recv/CMakeLists.txt
Normal file
15
esp-crab/slave_recv/CMakeLists.txt
Normal 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})
|
||||
1
esp-crab/slave_recv/components/bsp_C5_dual_antenna
Symbolic link
1
esp-crab/slave_recv/components/bsp_C5_dual_antenna
Symbolic link
@@ -0,0 +1 @@
|
||||
../../master_recv/components/bsp_C5_dual_antenna
|
||||
5
esp-crab/slave_recv/main/CMakeLists.txt
Normal file
5
esp-crab/slave_recv/main/CMakeLists.txt
Normal 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})
|
||||
43
esp-crab/slave_recv/main/app/app_gpio.c
Normal file
43
esp-crab/slave_recv/main/app/app_gpio.c
Normal 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);
|
||||
}
|
||||
|
||||
11
esp-crab/slave_recv/main/app/app_gpio.h
Normal file
11
esp-crab/slave_recv/main/app/app_gpio.h
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void init_gpio(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
162
esp-crab/slave_recv/main/app/app_ifft.c
Normal file
162
esp-crab/slave_recv/main/app/app_ifft.c
Normal 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);
|
||||
}
|
||||
26
esp-crab/slave_recv/main/app/app_ifft.h
Normal file
26
esp-crab/slave_recv/main/app/app_ifft.h
Normal 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
|
||||
43
esp-crab/slave_recv/main/app/app_uart.c
Normal file
43
esp-crab/slave_recv/main/app/app_uart.c
Normal 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);
|
||||
// }
|
||||
// }
|
||||
26
esp-crab/slave_recv/main/app/app_uart.h
Normal file
26
esp-crab/slave_recv/main/app/app_uart.h
Normal 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
|
||||
291
esp-crab/slave_recv/main/app_main.c
Normal file
291
esp-crab/slave_recv/main/app_main.c
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
7
esp-crab/slave_recv/main/idf_component.yml
Normal file
7
esp-crab/slave_recv/main/idf_component.yml
Normal 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
|
||||
5
esp-crab/slave_recv/partitions.csv
Normal file
5
esp-crab/slave_recv/partitions.csv
Normal 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
|
||||
|
32
esp-crab/slave_recv/sdkconfig.defaults
Normal file
32
esp-crab/slave_recv/sdkconfig.defaults
Normal 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
|
||||
Reference in New Issue
Block a user