5#if defined(ESP32) && defined(CONFIG_IDF_TARGET_ESP32)
8#include "driver/ledc.h"
9#include "driver/periph_ctrl.h"
10#include "esp_intr_alloc.h"
11#include "rom/lldesc.h"
12#include "esp32/rom/gpio.h"
13#include "soc/gpio_periph.h"
14#include "soc/i2s_reg.h"
15#include "soc/i2s_struct.h"
16#include "soc/io_mux_reg.h"
21namespace logic_analyzer {
29static volatile bool i2s_capture_dma_done =
false;
30static intr_handle_t i2s_capture_intr_handle =
nullptr;
32static void IRAM_ATTR i2s_capture_isr(
void *arg) {
33 if (I2S0.int_raw.in_suc_eof) {
34 i2s_capture_dma_done =
true;
35 esp_intr_disable(i2s_capture_intr_handle);
36 I2S0.conf.rx_start = 0;
38 I2S0.int_clr.val = I2S0.int_raw.val;
73 clk_out_pin = clkOutPin;
74 clk_in_pin = clkInPin;
75 for (
int j = 0; j < 8; j++) data_pins[j] = pinStart + j;
80 for (
int j = 0; j < 8; j++) data_pins[j] = pins[j];
90 log(
"Number of samples: %u", (
unsigned) n_samples);
91 log(
"Time in us: %lu", run_time_us);
103 return run_time_us == 0 ? 0 : 1000000.0f * n_samples / run_time_us;
110 uint32_t n_samples = 0;
111 unsigned long start_time = 0;
112 unsigned long run_time_us = 0;
113 bool is_setup =
false;
115 static const size_t desc_size = 2000;
116 lldesc_t *dma_desc =
nullptr;
117 uint8_t **dma_buf =
nullptr;
118 size_t dma_desc_count = 0;
122 if (is_setup)
return;
125 int sig_data_base = I2S0I_DATA_IN0_IDX;
126 for (
int j = 0; j < 8; j++) gpioSetupIn(data_pins[j], sig_data_base + j);
127 gpioSetupIn(clk_in_pin, I2S0I_WS_IN_IDX);
131 gpio_matrix_in(0x38, I2S0I_V_SYNC_IDX,
false);
132 gpio_matrix_in(0x38, I2S0I_H_SYNC_IDX,
false);
133 gpio_matrix_in(0x38, I2S0I_H_ENABLE_IDX,
false);
135 periph_module_enable(PERIPH_I2S0_MODULE);
138 I2S0.conf.rx_slave_mod = 1;
140 I2S0.conf2.lcd_en = 1;
141 I2S0.conf2.camera_en = 1;
143 I2S0.clkm_conf.val = 0;
144 I2S0.clkm_conf.clka_en = 0;
145 I2S0.clkm_conf.clkm_div_a = 1;
146 I2S0.clkm_conf.clkm_div_b = 0;
147 I2S0.clkm_conf.clkm_div_num = 4;
149 I2S0.fifo_conf.dscr_en = 1;
150 I2S0.fifo_conf.rx_fifo_mod = 1;
151 I2S0.fifo_conf.rx_fifo_mod_force_en = 1;
152 I2S0.conf_chan.rx_chan_mod = 1;
154 I2S0.conf.rx_right_first = 1;
155 I2S0.conf.rx_msb_right = 0;
156 I2S0.conf.rx_msb_shift = 0;
157 I2S0.conf.rx_mono = 1;
158 I2S0.conf.rx_short_sync = 1;
161 I2S0.sample_rate_conf.val = 0;
162 I2S0.sample_rate_conf.rx_bits_mod = 8;
163 I2S0.sample_rate_conf.rx_bck_div_num = 1;
165 esp_intr_alloc(ETS_I2S0_INTR_SOURCE,
166 ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM,
167 &i2s_capture_isr,
nullptr, &i2s_capture_intr_handle);
170 static void gpioSetupIn(
int gpio,
int sig) {
171 if (gpio < 0)
return;
172 PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
173 gpio_set_direction((gpio_num_t) gpio, GPIO_MODE_INPUT);
174 gpio_matrix_in(gpio, sig,
false);
177 static void i2sConfReset() {
178 I2S0.lc_conf.in_rst = 1; I2S0.lc_conf.in_rst = 0;
179 I2S0.lc_conf.ahbm_rst = 1; I2S0.lc_conf.ahbm_rst = 0;
180 I2S0.lc_conf.ahbm_fifo_rst = 1; I2S0.lc_conf.ahbm_fifo_rst = 0;
181 I2S0.conf.rx_reset = 1; I2S0.conf.rx_reset = 0;
182 I2S0.conf.rx_fifo_reset = 1; I2S0.conf.rx_fifo_reset = 0;
183 while (I2S0.state.rx_fifo_reset_back) {}
191 size_t total_bytes = ((sampleCount + 1) / 2) * 4;
192 dma_desc_count = (total_bytes + desc_size - 1) / desc_size;
193 if (dma_desc_count == 0) dma_desc_count = 1;
195 dma_buf = (uint8_t **) malloc(
sizeof(uint8_t *) * dma_desc_count);
196 dma_desc = (lldesc_t *) malloc(
sizeof(lldesc_t) * dma_desc_count);
198 for (
size_t i = 0; i < dma_desc_count; i++) {
199 dma_buf[i] = (uint8_t *) malloc(desc_size);
200 lldesc_t *pd = &dma_desc[i];
201 pd->length = desc_size;
202 pd->size = desc_size;
205 pd->buf = dma_buf[i];
208 bool last = (i + 1 == dma_desc_count);
209 pd->eof = last ? 1 : 0;
210 pd->qe.stqe_next = last ? nullptr : &dma_desc[i + 1];
215 if (dma_buf !=
nullptr) {
216 for (
size_t i = 0; i < dma_desc_count; i++) free(dma_buf[i]);
220 if (dma_desc !=
nullptr) {
229 ledcAttach(clk_out_pin, freqHz, 1);
230 ledcWrite(clk_out_pin, 1);
240 for (
size_t i = 0; i < dma_desc_count; i++) memset(dma_buf[i], 0, desc_size);
245 i2s_capture_dma_done =
false;
247 I2S0.rx_eof_num = (n_samples + 1) / 2;
248 I2S0.in_link.addr = (uint32_t) &dma_desc[0];
249 I2S0.in_link.start = 1;
250 I2S0.int_clr.val = I2S0.int_raw.val;
251 I2S0.int_ena.val = 0;
252 I2S0.int_ena.in_suc_eof = 1;
255 start_time = micros();
256 esp_intr_enable(i2s_capture_intr_handle);
257 I2S0.conf.rx_start = 1;
260 void waitForResult() {
261 log(
"waitForResult()");
264 unsigned long deadline = millis() + 5000;
265 while (!i2s_capture_dma_done && millis() < deadline) delay(1);
266 run_time_us = micros() - start_time;
267 ledcDetach(clk_out_pin);
272 for (
size_t i = 0; i < dma_desc_count && written < n_samples; i++) {
273 uint8_t *b = dma_buf[i];
277 for (
size_t off = 0; off + 3 < desc_size && written < n_samples; off += 4) {
278 buf.write((PinBitArray) b[off + 1]);
280 if (written < n_samples) {
281 buf.write((PinBitArray) b[off + 3]);
286 log(
"waitForResult() -> %u records", (
unsigned) buf.available());
Abstract Class for Capturing Logic. Create your own subclass if you want to implement your own optimi...
Definition logic_analyzer.h:316
LogicAnalyzer & logicAnalyzer()
Provides access to the LogicAnalyzer.
Definition logic_analyzer.h:329
virtual void setStatus(Status status)
Sets the status.
Definition logic_analyzer.h:339
Hardware-timed 8 bit parallel GPIO capture for the original ESP32, using the I2S0 peripheral's undocu...
Definition capture_esp32_i2s.h:69
void allocDma(uint32_t sampleCount)
(Re)allocates the DMA descriptor chain for the requested sample count
Definition capture_esp32_i2s.h:187
void setupOnce()
One-time GPIO/I2S peripheral setup.
Definition capture_esp32_i2s.h:121
void setDataPins(const int pins[8])
Defines the 8 data pins individually if they are not contiguous.
Definition capture_esp32_i2s.h:79
CaptureESP32I2S(int pinStart=19, int clkOutPin=32, int clkInPin=34)
Default Constructor - uses GPIO19..GPIO26 as the 8 bit data bus.
Definition capture_esp32_i2s.h:72
void captureAll() override
Used to measure the speed - capture into memory w/o dump.
Definition capture_esp32_i2s.h:95
void capture() override
starts the capturing of the data
Definition capture_esp32_i2s.h:84
void enableSampleClock(uint32_t freqHz)
Drives the sample clock via LEDC PWM on clk_out_pin, looped back into clk_in_pin.
Definition capture_esp32_i2s.h:228
float frequencyMeasured()
Provides the measured capturing frequency (based on the last capture)
Definition capture_esp32_i2s.h:102
RingBuffer & buffer()
Provides access to the buffer.
Definition logic_analyzer.h:626
size_t available()
returns the avialable buffer entries
Definition logic_analyzer.h:734
uint64_t captureFrequency()
provides the caputring frequency
Definition logic_analyzer.h:685
int readCount()
provides the read count
Definition logic_analyzer.h:664
void clear()
clears all entries
Definition logic_analyzer.h:214
Generic implementation of SUMP based logic analyzer.
void write(PinBitArray bits)
writes the status of all activated pins to the capturing device
Definition logic_analyzer.h:64
void log(const char *fmt,...)
Prints the content to the logger output stream.
Definition logic_analyzer.h:104