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

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