Skip to content

Commit

Permalink
Merge pull request #72 from martinberlin/develop
Browse files Browse the repository at this point in the history
Add software rotation
  • Loading branch information
vroland committed Apr 11, 2021
2 parents 2d76ac7 + bde584b commit 5901b49
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 46 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.pio
.vscode
build/
sdkconfig.old
**/build/
Expand Down
2 changes: 1 addition & 1 deletion examples/demo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.16.0)
cmake_minimum_required(VERSION 3.10.0)
set(EXTRA_COMPONENT_DIRS "../../src")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(firmware)
70 changes: 42 additions & 28 deletions examples/demo/main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,30 @@ void draw_progress_bar(int x, int y, int width, int percent, uint8_t* fb) {
void idf_loop() {

enum EpdDrawError err;

temperature = epd_ambient_temperature();
printf("current temperature: %d\n", temperature);

uint8_t* fb = epd_hl_get_framebuffer(&hl);


epd_poweron();
epd_clear();
epd_poweroff();


int cursor_x = EPD_WIDTH / 2;
int cursor_y = EPD_HEIGHT / 2 - 100;
epd_fill_circle(30,30,15,0,fb);
int cursor_x = epd_rotated_display_width() / 2;
int cursor_y = epd_rotated_display_height() / 2 - 100;
EpdFontProperties font_props = epd_font_properties_default();
font_props.flags = EPD_DRAW_ALIGN_CENTER;
epd_write_string(&FONT, "Loading demo...", &cursor_x, &cursor_y, fb, &font_props);

int bar_x = EPD_WIDTH / 2 - 200;
int bar_y = EPD_HEIGHT / 2;
char srotation[32];
sprintf(srotation, "Loading demo...\nRotation: %d", epd_get_rotation());

epd_write_string(&FONT, srotation, &cursor_x, &cursor_y, fb, &font_props);

int bar_x = epd_rotated_display_width() / 2 - 200;
int bar_y = epd_rotated_display_height() / 2;

epd_poweron();
vTaskDelay(100);
Expand All @@ -109,8 +115,8 @@ void idf_loop() {
vTaskDelay(1);
}

cursor_x = EPD_WIDTH / 2;
cursor_y = EPD_HEIGHT / 2 + 200;
cursor_x = epd_rotated_display_width() / 2;
cursor_y = epd_rotated_display_height() / 2 + 100;

epd_write_string(&FONT, "Just kidding,\n this is a demo animation 😉", &cursor_x, &cursor_y, fb, &font_props);
epd_poweron();
Expand All @@ -125,15 +131,13 @@ void idf_loop() {
vTaskDelay(1);
}

cursor_y = EPD_HEIGHT / 2 + 200;
cursor_x = EPD_WIDTH / 2;

delay(1000);
cursor_y = epd_rotated_display_height() / 2 + 200;
cursor_x = epd_rotated_display_width() / 2;

EpdRect clear_area = {
.x = 0,
.y = EPD_HEIGHT / 2 + 100,
.width = EPD_WIDTH,
.y = epd_rotated_display_height() / 2 + 100,
.width = epd_rotated_display_width(),
.height = 300,
};

Expand All @@ -149,39 +153,44 @@ void idf_loop() {
epd_hl_set_all_white(&hl);

EpdRect giraffe_area = {
.x = EPD_WIDTH / 2 - img_giraffe_width / 2,
.x = epd_rotated_display_width() / 2 - img_giraffe_width / 2,
.y = 25,
.width = img_giraffe_width,
.height = img_giraffe_height,
};
epd_copy_to_framebuffer(giraffe_area, img_giraffe_data, fb);

epd_draw_rotated_image(giraffe_area, img_giraffe_data, fb);

epd_poweron();
err = epd_hl_update_screen(&hl, MODE_GC16, temperature);
epd_poweroff();

delay(5000);
epd_hl_set_all_white(&hl);

EpdRect zebra_area = {
.x = EPD_WIDTH / 2 - img_zebra_width / 2,
.y = EPD_HEIGHT / 2 - img_zebra_height / 2,
.x = epd_rotated_display_width() / 2 - img_zebra_width / 2,
.y = epd_rotated_display_height() / 2 - img_zebra_height / 2,
.width = img_zebra_width,
.height = img_zebra_height,
};
epd_copy_to_framebuffer(zebra_area, img_zebra_data, fb);

epd_draw_rotated_image(zebra_area, img_zebra_data, fb);
epd_poweron();
err = epd_hl_update_screen(&hl, MODE_GC16, temperature);
epd_poweroff();

delay(5000);

EpdRect board_area = {
.x = EPD_WIDTH / 2 - img_board_width / 2,
.y = EPD_HEIGHT / 2 - img_board_height / 2,
.x = epd_rotated_display_width() / 2 - img_board_width / 2,
.y = epd_rotated_display_height() / 2 - img_board_height / 2,
.width = img_board_width,
.height = img_board_height,
};
epd_copy_to_framebuffer(board_area, img_board_data, fb);
cursor_x = EPD_WIDTH / 2;

epd_draw_rotated_image(board_area, img_board_data, fb);
cursor_x = epd_rotated_display_width() / 2;
cursor_y = board_area.y;
font_props.flags |= EPD_DRAW_BACKGROUND;
epd_write_string(&FONT, "↓ Thats the V2 board. ↓", &cursor_x, &cursor_y, fb, &font_props);
Expand All @@ -191,14 +200,13 @@ void idf_loop() {
epd_poweroff();

delay(5000);

epd_hl_set_all_white(&hl);

EpdRect border_rect = {
.x = 20,
.y = 20,
.width = EPD_WIDTH - 40,
.height = EPD_HEIGHT - 40
.width = epd_rotated_display_width() - 40,
.height = epd_rotated_display_height() - 40
};
epd_draw_rect(border_rect, 0, fb);

Expand All @@ -220,7 +228,8 @@ void idf_loop() {
.width = img_beach_width,
.height = img_beach_height,
};
epd_copy_to_framebuffer(img_beach_area, img_beach_data, fb);

epd_draw_rotated_image(img_beach_area, img_beach_data, fb);

epd_poweron();
err = epd_hl_update_screen(&hl, MODE_GC16, temperature);
Expand All @@ -236,6 +245,11 @@ void idf_setup() {

epd_init(EPD_LUT_1K);
hl = epd_hl_init(WAVEFORM);

// Default orientation is EPD_ROT_LANDSCAPE
epd_set_rotation(EPD_ROT_LANDSCAPE);

printf("Dimensions after rotation, width: %d height: %d\n\n", epd_rotated_display_width(), epd_rotated_display_height());
}

#ifndef ARDUINO_ARCH_ESP32
Expand Down
122 changes: 119 additions & 3 deletions src/epd_driver/epd_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@
#include "esp_log.h"
#include "esp_types.h"

// Simple x and y coordinate
typedef struct {
uint16_t x;
uint16_t y;
} Coord_xy;

// Display rotation. Can be updated using epd_set_rotation(enum EpdRotation)
static enum EpdRotation display_rotation = EPD_ROT_LANDSCAPE;

#ifndef _swap_int
#define _swap_int(a, b) \
Expand All @@ -16,7 +24,6 @@
}
#endif


EpdRect epd_full_screen() {
EpdRect area = {.x = 0, .y = 0, .width = EPD_WIDTH, .height = EPD_HEIGHT};
return area;
Expand All @@ -40,13 +47,41 @@ void epd_draw_vline(int x, int y, int length, uint8_t color,
}
}

Coord_xy _rotate(uint16_t x, uint16_t y) {
switch (display_rotation) {
case EPD_ROT_LANDSCAPE:
break;
case EPD_ROT_PORTRAIT:
_swap_int(x, y);
x = EPD_WIDTH - x - 1;
break;
case EPD_ROT_INVERTED_LANDSCAPE:
x = EPD_WIDTH - x - 1;
y = EPD_HEIGHT - y - 1;
break;
case EPD_ROT_INVERTED_PORTRAIT:
_swap_int(x, y);
y = EPD_HEIGHT - y - 1;
break;
}
Coord_xy coord = {
x, y
};
return coord;
}

void epd_draw_pixel(int x, int y, uint8_t color, uint8_t *framebuffer) {
if (x < 0 || x >= EPD_WIDTH) {
if (x < 0 || x >= epd_rotated_display_width()) {
return;
}
if (y < 0 || y >= EPD_HEIGHT) {
if (y < 0 || y >= epd_rotated_display_height()) {
return;
}
// Check rotation and move pixel around if necessary
Coord_xy coord = _rotate(x, y);
x = coord.x;
y = coord.y;

uint8_t *buf_ptr = &framebuffer[y * EPD_WIDTH / 2 + x / 2];
if (x % 2) {
*buf_ptr = (*buf_ptr & 0x0F) | (color & 0xF0);
Expand Down Expand Up @@ -342,3 +377,84 @@ enum EpdDrawError epd_draw_image(EpdRect area, const uint8_t *data, const EpdWav
};
return epd_draw_base(area, data, no_crop, EPD_MODE_DEFAULT, temperature, NULL, waveform);
}

void epd_set_rotation(enum EpdRotation rotation) {
display_rotation = rotation;
}

enum EpdRotation epd_get_rotation() {
return display_rotation;
}

int epd_rotated_display_width() {
int display_width = EPD_WIDTH;
switch (display_rotation) {
case EPD_ROT_PORTRAIT:
display_width = EPD_HEIGHT;
break;
case EPD_ROT_INVERTED_PORTRAIT:
display_width = EPD_HEIGHT;
break;
case EPD_ROT_INVERTED_LANDSCAPE:
case EPD_ROT_LANDSCAPE:
break;
}
return display_width;
}

int epd_rotated_display_height() {
int display_height = EPD_HEIGHT;
switch (display_rotation) {
case EPD_ROT_PORTRAIT:
display_height = EPD_WIDTH;
break;
case EPD_ROT_INVERTED_PORTRAIT:
display_height = EPD_WIDTH;
break;
case EPD_ROT_INVERTED_LANDSCAPE:
case EPD_ROT_LANDSCAPE:
break;
}
return display_height;
}

uint8_t epd_get_pixel(int x, int y, int fb_width, int fb_height, const uint8_t *framebuffer) {
if (x < 0 || x >= fb_width) {
return 0;
}
if (y < 0 || y >= fb_height) {
return 0;
}
int fb_width_bytes = fb_width / 2 + fb_width % 2;
uint8_t buf_val = framebuffer[y * fb_width_bytes + x / 2];
if (x % 2) {
buf_val = (buf_val & 0xF0) >> 4;
} else {
buf_val = (buf_val & 0x0F);
}

// epd_draw_pixel needs a 0 -> 255 value
return buf_val<<4;
}

void epd_draw_rotated_image(EpdRect image_area, const uint8_t *image_buffer, uint8_t *framebuffer) {
if (epd_get_rotation() != EPD_ROT_LANDSCAPE) {
uint16_t x_offset = 0;
uint16_t y_offset = 0;
for (uint16_t y = 0; y < image_area.height; y++) {
for (uint16_t x = 0; x < image_area.width; x++) {
x_offset = image_area.x + x;
y_offset = image_area.y + y;
if (x_offset >= epd_rotated_display_width()) continue;
if (y_offset >= epd_rotated_display_height()) continue;
epd_draw_pixel(
x_offset,
y_offset,
epd_get_pixel(x, y, image_area.width, image_area.height, image_buffer),
framebuffer);
}
}
} else {
epd_copy_to_framebuffer(image_area, image_buffer, framebuffer);
}
}
16 changes: 5 additions & 11 deletions src/epd_driver/font.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,28 +154,24 @@ static enum EpdDrawError IRAM_ATTR draw_char(const EpdFont *font, uint8_t *buffe

for (int y = 0; y < height; y++) {
int yy = cursor_y - glyph->top + y;
if (yy < 0 || yy >= buf_height) {
if (yy < 0 || yy >= epd_rotated_display_height()) {
continue;
}
int start_pos = *cursor_x + left;
bool byte_complete = start_pos % 2;
int x = max(0, -start_pos);
int max_x = min(start_pos + width, buf_width * 2);
uint8_t color;

for (int xx = start_pos; xx < max_x; xx++) {
uint32_t buf_pos = yy * buf_width + xx / 2;
uint8_t old = buffer[buf_pos];
uint8_t bm = bitmap[y * byte_width + x / 2];
if ((x & 1) == 0) {
bm = bm & 0xF;
} else {
bm = bm >> 4;
}

if ((xx & 1) == 0) {
buffer[buf_pos] = (old & 0xF0) | color_lut[bm];
} else {
buffer[buf_pos] = (old & 0x0F) | (color_lut[bm] << 4);
}
color = color_lut[bm] << 4;
epd_draw_pixel(xx, yy, color, buffer);
byte_complete = !byte_complete;
x++;
}
Expand Down Expand Up @@ -292,8 +288,6 @@ static enum EpdDrawError epd_write_line(
return EPD_DRAW_NO_DRAWABLE_CHARACTERS;
}

int baseline_height = *cursor_y - y1;

int buf_width = EPD_WIDTH / 2;
int buf_height = EPD_HEIGHT;

Expand Down

0 comments on commit 5901b49

Please sign in to comment.