feat: Initial esp32-hacking project with firmware sources and docs
This commit is contained in:
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
|
||||
Reference in New Issue
Block a user