Sfoglia il codice sorgente

Add asynchronous DMA support and fix timing issues

S3
jrhoffa 3 anni fa
parent
commit
0760976400
6 ha cambiato i file con 70 aggiunte e 38 eliminazioni
  1. +13
    -2
      main/leds.cpp
  2. +2
    -2
      main/leds.hpp
  3. +9
    -8
      main/main.cpp
  4. +37
    -22
      main/spi_leds.cpp
  5. +4
    -2
      main/spi_leds.hpp
  6. +5
    -2
      main/utils.cpp

+ 13
- 2
main/leds.cpp Vedi File

@@ -37,8 +37,19 @@ void Pattern::step(Color pixels[], int len, int64_t &last_us, Fixed &offset) con
last_us = now_us;
//ESP_LOGI(TAG, "duration %d", duration_us);

/*
int period_us = 1000000 / 60;
int n_skipped = (duration_us - period_us / 2) / period_us;
if (n_skipped) {
ESP_LOGW(TAG, "Skipped %d frames", n_skipped);
}
*/
// Don't make a major animation jump if it's been terribly long
if (duration_us > 100000) duration_us = 100000;


int offset_delta = (duration_us << shift) / (cycle_time_ms * 1000);
if (reverse) offset -= offset_delta; else offset += offset_delta;
if (reverse) offset += offset_delta; else offset -= offset_delta;
Fixed off = march ?
(((int)offset * cycle_length) & ~((1 << shift) - 1)) / cycle_length :
offset;
@@ -73,7 +84,7 @@ static std::string termcolor(Color c) {
std::to_string((int)c.b) + "m";
}

void TerminalLEDs::show() const {
void TerminalLEDs::show() {
std::string line;
for (int i = 0; i < length; i++) {
line += termcolor(pixels[i]) + " ";


+ 2
- 2
main/leds.hpp Vedi File

@@ -36,7 +36,7 @@ public:

void step();

virtual void show() const = 0;
virtual void show() = 0;
virtual void length_changing(int) {};

void setPattern(const Pattern *_pattern) { pattern = _pattern; }
@@ -58,5 +58,5 @@ private:
class TerminalLEDs : public LEDStrip {
public:
TerminalLEDs(int length = 0) : LEDStrip(length) {}
void show() const;
void show();
};

+ 9
- 8
main/main.cpp Vedi File

@@ -131,6 +131,7 @@ std::string gen_config(bool is_on, const std::string &effect) {

constexpr char config_path[] = "/spiffs/blinky.json";

//#define PROFILE

// Entry Point

@@ -214,16 +215,16 @@ extern "C" void app_main(void) {
int period_us = 1000000 / 60;
int64_t start = time_us();
int64_t target_us = start;
/*
#ifdef PROFILE
int64_t total_delay_us = 0;
int n_delays = 0;
int64_t after_sleep_us = 0;
int n_processes = 0;
int64_t total_process_us = 0;
*/
#endif // PROFILE
while (true) {
int64_t now = time_us();
/*
#ifdef PROFILE
if (after_sleep_us > 0) {
total_process_us += now - after_sleep_us;
++n_processes;
@@ -240,23 +241,23 @@ extern "C" void app_main(void) {

start = now;
}
*/
#endif // PROFILE
int64_t delay_us = target_us - now;
if (delay_us < 0) delay_us = 0;
if (device.wait(delay_us / 1000)) {
// If the semaphore is set, go back to top of outer loop
break;
}
/*

target_us = now + delay_us + period_us;
#ifdef PROFILE
after_sleep_us = time_us();

total_delay_us += (after_sleep_us - now);
++n_delays;
*/
#endif // PROFILE
LEDs->step();
LEDs->show();

target_us += period_us;
}
}
}


+ 37
- 22
main/spi_leds.cpp Vedi File

@@ -16,7 +16,8 @@ static const char *TAG = "spi_leds";
SPI_LEDs::SPI_LEDs(int _gpio, int length) :
LEDStrip(length),
host(SPI3_HOST), gpio(_gpio), device(NULL),
out_buf(NULL) {
out_buf(NULL)
{
int ret;

spi_bus_config_t buscfg = {
@@ -53,7 +54,7 @@ SPI_LEDs::SPI_LEDs(int _gpio, int length) :
.cs_ena_posttrans = 0, // moot
// Datasheet implies 3.2 MHz => 1.25 us / 4
// We can get away with 4.4_ MHz => 900 ns / 4
.clock_speed_hz = 4444444,
.clock_speed_hz = 3200000,
.input_delay_ns = 0, // moot
.spics_io_num = -1,
.flags = 0, // Keep it MSB first
@@ -77,6 +78,19 @@ void SPI_LEDs::configure(int len) {
if (len <= 0) return;

out_buf = (uint8_t*)heap_caps_malloc(tx_len(len), MALLOC_CAP_DMA);

memset(out_buf + tx_len(len) - reset_bytes, 0, reset_bytes);

transaction = {
.flags = 0,
.cmd = 0,
.addr = 0,
.length = tx_len(len) * 8,
.rxlength = 0,
.user = NULL,
.tx_buffer = out_buf,
.rx_buffer = NULL,
};
}

// Inverted
@@ -92,7 +106,8 @@ static uint8_t* encode_byte(uint8_t *out, uint8_t in) {
return out;
}

void SPI_LEDs::show() const {
void SPI_LEDs::show() {
static int index = 0;
int ret;
const Color *pixel = pixels;
uint8_t *out = out_buf;
@@ -104,24 +119,24 @@ void SPI_LEDs::show() const {
++pixel;
}

// TODO: Reset pad? Or should we check clocks?

spi_transaction_ext_t transaction_ext = {
.base = {
.flags = 0,
.cmd = 0,
.addr = 0,
.length = tx_len(length) * 8,
.rxlength = 0,
.user = NULL,
.tx_buffer = out_buf,
.rx_buffer = NULL,
},
.command_bits = 160,
.address_bits = 0,
.dummy_bits = 160,
};
++index;

ret = spi_device_transmit(device, &transaction_ext.base);
RET_ON_ERR(spi_device_transmit, ret);
ret = spi_device_queue_trans(device, &transaction, portMAX_DELAY);
RET_ON_ERR(spi_device_queue_trans, ret);

/*
while ((ret = spi_device_queue_trans(device, &transaction, 0)) != ESP_OK) {
if (ret == ESP_ERR_TIMEOUT) {
// Wait for the previous transaction to finish
ESP_LOGI(TAG, "SPI transaction collision (# %d)", index);
spi_transaction_t *ret_trans;
ret = spi_device_get_trans_result(device, &ret_trans, portMAX_DELAY);
RET_ON_ERR(spi_device_get_trans_result, ret);
ESP_LOGI(TAG, "Transaction complete (# %d)", index);

} else {
RET_ON_ERR(spi_device_queue_trans, ret);
}
}
*/
}

+ 4
- 2
main/spi_leds.hpp Vedi File

@@ -8,7 +8,7 @@
class SPI_LEDs : public LEDStrip {
public:
SPI_LEDs(int gpio, int length = 0);
void show() const;
void show();
void length_changing(int len) { configure(len); }

private:
@@ -16,8 +16,10 @@ private:
int gpio;
spi_device_handle_t device;
uint8_t *out_buf;
spi_transaction_t transaction;

static size_t tx_len(int len) { return (len * 3) * 4; }
static constexpr int reset_bytes = 30;
static size_t tx_len(int len) { return (len * 3) * 4 + reset_bytes; }

void configure(int length);
};

+ 5
- 2
main/utils.cpp Vedi File

@@ -4,7 +4,10 @@


int64_t time_us() {
struct timeval tv_now;
/*struct timeval tv_now;
gettimeofday(&tv_now, NULL);
return (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec;
return (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec;*/
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (int64_t)ts.tv_sec * 1000000L + (int64_t)ts.tv_nsec / 1000L;
}

Loading…
Annulla
Salva