Skip to content

Commit

Permalink
fix compile on original esp32
Browse files Browse the repository at this point in the history
  • Loading branch information
vroland committed Feb 11, 2024
1 parent 3c16dfd commit d198277
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 29 deletions.
5 changes: 5 additions & 0 deletions src/diff.S
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include <xtensa/config/core-isa.h>
#include <xtensa/config/core-matmap.h>
#include "output_common/render_method.h"

#ifdef RENDER_METHOD_LCD

.text
.align 4
Expand Down Expand Up @@ -152,3 +155,5 @@ epd_apply_line_mask_VE:
.loop_end_mask:

retw.n

#endif
2 changes: 1 addition & 1 deletion src/highlevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ EpdiyHighlevelState epd_hl_init(const EpdWaveform* waveform) {
assert(state.difference_fb != NULL);
state.dirty_lines = malloc(epd_height() * sizeof(bool));
assert(state.dirty_lines != NULL);
state.dirty_columns = heap_caps_aligned_alloc(16, epd_width() / 2, MALLOC_CAP_INTERNAL);
state.dirty_columns = heap_caps_aligned_alloc(16, epd_width() / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
assert(state.dirty_columns != NULL);
state.waveform = waveform;

Expand Down
13 changes: 9 additions & 4 deletions src/output_common/line_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
static inline int ceil_div(int x, int y) { return x / y + (x % y != 0); }

/// Initialize the line queue and allocate memory.
LineQueue_t lq_init(int queue_len, int element_size) {
LineQueue_t lq_init(int queue_len, int element_size, bool use_mask) {
LineQueue_t queue;
queue.element_size = element_size;
queue.size = queue_len;
Expand All @@ -27,9 +27,14 @@ LineQueue_t lq_init(int queue_len, int element_size) {
assert(queue.bufs[i] != NULL);
}

queue.mask_buffer_len = elem_buf_size;
queue.mask_buffer = heap_caps_aligned_alloc(16, elem_buf_size, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
assert(queue.mask_buffer != NULL);
if (use_mask) {
queue.mask_buffer_len = elem_buf_size;
queue.mask_buffer = heap_caps_aligned_alloc(16, elem_buf_size, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
assert(queue.mask_buffer != NULL);
} else {
queue.mask_buffer_len = 0;
queue.mask_buffer = NULL;
}

return queue;
}
Expand Down
3 changes: 2 additions & 1 deletion src/output_common/line_queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <stdatomic.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>


Expand All @@ -22,7 +23,7 @@ typedef struct {
} LineQueue_t;

/// Initialize the line queue and allocate memory.
LineQueue_t lq_init(int queue_len, int element_size);
LineQueue_t lq_init(int queue_len, int element_size, bool use_mask);

/// Deinitialize the line queue and free memory.
void lq_free(LineQueue_t* queue);
Expand Down
4 changes: 4 additions & 0 deletions src/output_common/lut.S
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include <xtensa/config/core-isa.h>
#include <xtensa/config/core-matmap.h>
#include "render_method.h"

#ifdef RENDER_METHOD_LCD

.text
.align 4
Expand Down Expand Up @@ -139,3 +142,4 @@ calc_epd_input_1ppB_1k_S3_VE:
movi.n a2, 0 // return status ESP_OK
retw.n

#endif
4 changes: 0 additions & 4 deletions src/output_i2s/render_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,6 @@ void IRAM_ATTR i2s_fetch_frame_data(RenderContext_t *ctx, int thread_id) {

memcpy(buf, lp, lq->element_size);

if (line_start_x > 0 || line_end_x < ctx->display_width) {
//mask_line_buffer(line_buf, line_bytes, line_start_x, line_end_x);
}

lq_commit(lq);

if (shifted) {
Expand Down
53 changes: 34 additions & 19 deletions src/render.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,27 @@ static inline int rounded_display_height() {
return (((epd_height() + 7) / 8) * 8);
}


/**
* Populate an output line mask from line dirtyness with one nibble per pixel.
* If the dirtyness data is NULL, set the mask to neutral.
*/
static void populate_line_mask(uint8_t* line_mask, const uint8_t* dirty_columns, int mask_len) {
if (dirty_columns == NULL) {
memset(line_mask, 0xFF, mask_len);
} else {
assert(epd_width() / 4 <= mask_len);
for (int c = 0; c < epd_width() / 2; c += 2) {
uint8_t mask = 0;
mask |= (dirty_columns[c + 1] & 0xF0) != 0 ? 0xC0 : 0x00;
mask |= (dirty_columns[c + 1] & 0x0F) != 0 ? 0x30 : 0x00;
mask |= (dirty_columns[c] & 0xF0) != 0 ? 0x0C : 0x00;
mask |= (dirty_columns[c] & 0x0F) != 0 ? 0x03 : 0x00;
line_mask[c / 2] = mask;
}
}
}

// FIXME: fix misleading naming:
// area -> buffer dimensions
// crop -> area taken out of buffer
Expand Down Expand Up @@ -135,13 +156,15 @@ enum EpdDrawError IRAM_ATTR epd_draw_base(
return EPD_DRAW_INVALID_CROP;
}

#ifdef RENDER_METHOD_LCD
if (mode & MODE_PACKING_1PPB_DIFFERENCE && render_context.conversion_lut_size > 1 << 10) {
ESP_LOGI(
"epdiy",
"Using optimized vector implementation on the ESP32-S3, only 1k of %d LUT in use!",
render_context.conversion_lut_size
);
}
#endif

render_context.area = area;
render_context.crop_to = crop_to;
Expand All @@ -166,21 +189,9 @@ enum EpdDrawError IRAM_ATTR epd_draw_base(
#ifdef RENDER_METHOD_I2S
i2s_do_update(&render_context);
#elif defined(RENDER_METHOD_LCD)

for (int i = 0; i < NUM_RENDER_THREADS; i++) {
LineQueue_t* queue = &render_context.line_queues[i];
if (drawn_columns == NULL) {
memset(queue->mask_buffer, 0xFF, queue->mask_buffer_len);
} else {
for (int c = 0; c < epd_width() / 2; c += 2) {
uint8_t mask = 0;
mask |= (drawn_columns[c + 1] & 0xF0) != 0 ? 0xC0 : 0x00;
mask |= (drawn_columns[c + 1] & 0x0F) != 0 ? 0x30 : 0x00;
mask |= (drawn_columns[c] & 0xF0) != 0 ? 0x0C : 0x00;
mask |= (drawn_columns[c] & 0x0F) != 0 ? 0x03 : 0x00;
queue->mask_buffer[c / 2] = mask;
}
}
populate_line_mask(queue->mask_buffer, drawn_columns, queue->mask_buffer_len);
}

lcd_do_update(&render_context);
Expand Down Expand Up @@ -297,13 +308,15 @@ void epd_renderer_init(enum EpdInitOptions options) {
}

#ifdef RENDER_METHOD_LCD
bool use_lq_mask = true;
size_t queue_elem_size = render_context.display_width / 4;
#elif defined(RENDER_METHOD_I2S)
bool use_lq_mask = false;
size_t queue_elem_size = epd_width();
#endif

for (int i = 0; i < NUM_RENDER_THREADS; i++) {
render_context.line_queues[i] = lq_init(queue_len, queue_elem_size);
render_context.line_queues[i] = lq_init(queue_len, queue_elem_size, use_lq_mask);
render_context.feed_line_buffers[i] = (uint8_t*)heap_caps_malloc(
render_context.display_width, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL
);
Expand Down Expand Up @@ -363,12 +376,14 @@ static bool interlace_line(
int fb_width
) {
uint32_t dirty = 0;
uint32_t to_addr = (uint32_t)to;
int unaligned_start = 0;
int unaligned_len = fb_width;

int unaligned_start;
int unaligned_len;
// use Vector Extensions with the ESP32-S3
#ifdef RENDER_METHOD_LCD
// since display horizontal resolutions should be divisible by 16,
// only one end should be unaligned by 8 bytes (16 pixels)
uint32_t to_addr = (uint32_t)to;
if (to_addr % 16 > 0) {
unaligned_start = 0;
unaligned_len = (16 - (to_addr % 16)) * 2;
Expand All @@ -382,13 +397,13 @@ static bool interlace_line(
to + alignment_offset, from + alignment_offset, interlaced + alignment_offset * 2,
col_dirtyness + alignment_offset, fb_width
);

#endif
for (int x = unaligned_start; x < unaligned_start + unaligned_len; x++) {
uint8_t t = *(to + x / 2);
uint8_t f = *(from + x / 2);
col_dirtyness[x / 2] |= (t ^ f);
t = (x % 2) ? (t >> 4) : (t & 0x0f);
f = (x % 2) ? (f >> 4) : (f & 0x0f);
col_dirtyness[x / 2] |= (t ^ f);
dirty |= (t ^ f);
interlaced[x] = (t << 4) | f;
}
Expand Down

0 comments on commit d198277

Please sign in to comment.