-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #198 from espressif/examples/esp_jpeg_example
esp_jpeg: Added example
- Loading branch information
Showing
13 changed files
with
400 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# The following lines of boilerplate have to be in your project's CMakeLists | ||
# in this exact order for cmake to work correctly | ||
cmake_minimum_required(VERSION 3.16) | ||
|
||
include($ENV{IDF_PATH}/tools/cmake/project.cmake) | ||
project(lcd_tjpgd) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | | ||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | | ||
|
||
## LCD tjpgd example | ||
|
||
This example shows how to decode a jpeg image and display it on an SPI-interfaced LCD, and rotates the image periodically. | ||
|
||
Example using initialization of the LCD from [ESP-BSP](https://github.com/espressif/esp-bsp) project. For change the Espressif's board, go to [idf_component.yml](main/idf_component.yml) and change `esp-box` to another board from BSP. | ||
|
||
## How to Use Example | ||
|
||
### Hardware Required | ||
|
||
* An ESP development board | ||
* An SPI-interfaced LCD | ||
* An USB cable for power supply and programming | ||
|
||
### Hardware Connection | ||
|
||
The connection between ESP Board and the LCD is as follows: | ||
|
||
``` | ||
ESP Board LCD Screen | ||
+---------+ +---------------------------------+ | ||
| | | | | ||
| 3V3 +--------------+ VCC +----------------------+ | | ||
| | | | | | | ||
| GND +--------------+ GND | | | | ||
| | | | | | | ||
| DATA0 +--------------+ MOSI | | | | ||
| | | | | | | ||
| PCLK +--------------+ SCK | | | | ||
| | | | | | | ||
| CS +--------------+ CS | | | | ||
| | | | | | | ||
| D/C +--------------+ D/C | | | | ||
| | | | | | | ||
| RST +--------------+ RST | | | | ||
| | | | | | | ||
|BK_LIGHT +--------------+ BCKL +----------------------+ | | ||
| | | | | ||
+---------+ +---------------------------------+ | ||
``` | ||
|
||
The GPIO numbers used by this example is taken from BSP. | ||
|
||
### Build and Flash | ||
|
||
Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. A flowing picture will be shown on the LCD screen. | ||
|
||
(To exit the serial monitor, type ``Ctrl-]``.) | ||
|
||
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. | ||
|
||
## Troubleshooting | ||
|
||
For any technical queries, please open an [issue] (https://github.com/espressif/idf-extra-components/issues) on GitHub. We will get back to you soon. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
set(srcs "pretty_effect.c" | ||
"lcd_tjpgd_example_main.c" | ||
"decode_image.c" | ||
) | ||
|
||
idf_component_register(SRCS ${srcs} | ||
INCLUDE_DIRS "." | ||
EMBED_FILES image.jpg) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
menu "Example Configuration" | ||
config EXAMPLE_LCD_FLUSH_PARALLEL_LINES | ||
int "LCD flush parallel lines" | ||
default 12 if IDF_TARGET_ESP32C2 | ||
default 16 | ||
help | ||
To speed up transfers, every SPI transfer sends a bunch of lines. | ||
|
||
endmenu |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: CC0-1.0 | ||
*/ | ||
|
||
/* | ||
The image used for the effect on the LCD in the SPI master example is stored in flash | ||
as a jpeg file. This file contains the decode_image routine, which uses the tiny JPEG | ||
decoder library to decode this JPEG into a format that can be sent to the display. | ||
Keep in mind that the decoder library cannot handle progressive files (will give | ||
``Image decoder: jd_prepare failed (8)`` as an error) so make sure to save in the correct | ||
format if you want to use a different image file. | ||
*/ | ||
|
||
#include <string.h> | ||
#include "decode_image.h" | ||
#include "jpeg_decoder.h" | ||
#include "esp_log.h" | ||
#include "esp_check.h" | ||
#include "freertos/FreeRTOS.h" | ||
|
||
//Reference the binary-included jpeg file | ||
extern const uint8_t image_jpg_start[] asm("_binary_image_jpg_start"); | ||
extern const uint8_t image_jpg_end[] asm("_binary_image_jpg_end"); | ||
//Define the height and width of the jpeg file. Make sure this matches the actual jpeg | ||
//dimensions. | ||
|
||
const char *TAG = "ImageDec"; | ||
|
||
//Decode the embedded image into pixel lines that can be used with the rest of the logic. | ||
esp_err_t decode_image(uint16_t **pixels) | ||
{ | ||
*pixels = NULL; | ||
esp_err_t ret = ESP_OK; | ||
|
||
//Alocate pixel memory. Each line is an array of IMAGE_W 16-bit pixels; the `*pixels` array itself contains pointers to these lines. | ||
*pixels = calloc(IMAGE_H * IMAGE_W, sizeof(uint16_t)); | ||
ESP_GOTO_ON_FALSE((*pixels), ESP_ERR_NO_MEM, err, TAG, "Error allocating memory for lines"); | ||
|
||
//JPEG decode config | ||
esp_jpeg_image_cfg_t jpeg_cfg = { | ||
.indata = (uint8_t *)image_jpg_start, | ||
.indata_size = image_jpg_end - image_jpg_start, | ||
.outbuf = (uint8_t *)(*pixels), | ||
.outbuf_size = IMAGE_W * IMAGE_H * sizeof(uint16_t), | ||
.out_format = JPEG_IMAGE_FORMAT_RGB565, | ||
.out_scale = JPEG_IMAGE_SCALE_0, | ||
.flags = { | ||
.swap_color_bytes = 1, | ||
} | ||
}; | ||
|
||
//JPEG decode | ||
esp_jpeg_image_output_t outimg; | ||
esp_jpeg_decode(&jpeg_cfg, &outimg); | ||
|
||
ESP_LOGI(TAG, "JPEG image decoded! Size of the decoded image is: %dpx x %dpx", outimg.width, outimg.height); | ||
|
||
return ret; | ||
err: | ||
//Something went wrong! Exit cleanly, de-allocating everything we allocated. | ||
if (*pixels != NULL) { | ||
free(*pixels); | ||
} | ||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: CC0-1.0 | ||
*/ | ||
|
||
#pragma once | ||
#include <stdint.h> | ||
#include "esp_err.h" | ||
|
||
#define IMAGE_W 320 | ||
#define IMAGE_H 240 | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** | ||
* @brief Decode the jpeg ``image.jpg`` embedded into the program file into pixel data. | ||
* | ||
* @param pixels A pointer to a pointer for an array of rows, which themselves are an array of pixels. | ||
* Effectively, you can get the pixel data by doing ``decode_image(&myPixels); pixelval=myPixels[ypos][xpos];`` | ||
* @return - ESP_ERR_NOT_SUPPORTED if image is malformed or a progressive jpeg file | ||
* - ESP_ERR_NO_MEM if out of memory | ||
* - ESP_OK on succesful decode | ||
*/ | ||
esp_err_t decode_image(uint16_t **pixels); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
dependencies: | ||
idf: ">=5.0" | ||
esp_jpeg: | ||
version: ">=1.0.2" | ||
override_path: "../../../" | ||
esp-box: | ||
version: "^2.4" | ||
rules: | ||
- if: "target == esp32s3" | ||
esp32_s2_kaluga_kit: | ||
version: "^2.2" | ||
rules: | ||
- if: "target == esp32s2" | ||
esp_wrover_kit: | ||
version: "^1.4" | ||
rules: | ||
- if: "target == esp32" |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: CC0-1.0 | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include "sdkconfig.h" | ||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/task.h" | ||
#include "esp_lcd_panel_ops.h" | ||
#include "esp_heap_caps.h" | ||
#include "pretty_effect.h" | ||
#include "bsp/esp-bsp.h" | ||
#include "bsp/display.h" | ||
|
||
// Using SPI2 in the example, as it also supports octal modes on some targets | ||
#define LCD_HOST SPI2_HOST | ||
// To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. | ||
// More means more memory use, but less overhead for setting up / finishing transfers. Make sure 240 | ||
// is dividable by this. | ||
#define PARALLEL_LINES CONFIG_EXAMPLE_LCD_FLUSH_PARALLEL_LINES | ||
// The number of frames to show before rotate the graph | ||
#define ROTATE_FRAME 30 | ||
|
||
#if BSP_LCD_H_RES > BSP_LCD_V_RES | ||
#define EXAMPLE_LCD_SWAP 0 | ||
#define EXAMPLE_LCD_H_RES BSP_LCD_H_RES | ||
#define EXAMPLE_LCD_V_RES BSP_LCD_V_RES | ||
#else | ||
#define EXAMPLE_LCD_SWAP 1 | ||
#define EXAMPLE_LCD_H_RES BSP_LCD_V_RES | ||
#define EXAMPLE_LCD_V_RES BSP_LCD_H_RES | ||
#endif | ||
|
||
// Simple routine to generate some patterns and send them to the LCD. Because the | ||
// SPI driver handles transactions in the background, we can calculate the next line | ||
// while the previous one is being sent. | ||
static uint16_t *s_lines[2]; | ||
static void display_pretty_colors(esp_lcd_panel_handle_t panel_handle) | ||
{ | ||
int frame = 0; | ||
// Indexes of the line currently being sent to the LCD and the line we're calculating | ||
int sending_line = 0; | ||
int calc_line = 0; | ||
|
||
// After ROTATE_FRAME frames, the image will be rotated | ||
while (frame <= ROTATE_FRAME) { | ||
frame++; | ||
for (int y = 0; y < EXAMPLE_LCD_V_RES; y += PARALLEL_LINES) { | ||
// Calculate a line | ||
pretty_effect_calc_lines(s_lines[calc_line], y, frame, PARALLEL_LINES); | ||
sending_line = calc_line; | ||
calc_line = !calc_line; | ||
// Send the calculated data | ||
esp_lcd_panel_draw_bitmap(panel_handle, 0, y, 0 + EXAMPLE_LCD_H_RES, y + PARALLEL_LINES, s_lines[sending_line]); | ||
} | ||
} | ||
} | ||
|
||
void app_main(void) | ||
{ | ||
esp_lcd_panel_io_handle_t io_handle = NULL; | ||
esp_lcd_panel_handle_t panel_handle = NULL; | ||
|
||
bsp_display_config_t disp_cfg = { | ||
.max_transfer_sz = EXAMPLE_LCD_H_RES * PARALLEL_LINES * sizeof(uint16_t), | ||
}; | ||
// Display initialize from BSP | ||
bsp_display_new(&disp_cfg, &panel_handle, &io_handle); | ||
esp_lcd_panel_disp_on_off(panel_handle, true); | ||
bsp_display_backlight_on(); | ||
|
||
// Initialize the effect displayed | ||
ESP_ERROR_CHECK(pretty_effect_init()); | ||
|
||
// "Rotate or not" flag | ||
bool is_rotated = false; | ||
|
||
// Allocate memory for the pixel buffers | ||
for (int i = 0; i < 2; i++) { | ||
s_lines[i] = heap_caps_malloc(EXAMPLE_LCD_H_RES * PARALLEL_LINES * sizeof(uint16_t), MALLOC_CAP_DMA); | ||
assert(s_lines[i] != NULL); | ||
} | ||
|
||
#if EXAMPLE_LCD_SWAP | ||
esp_lcd_panel_swap_xy(panel_handle, true); | ||
#endif | ||
|
||
// Start and rotate | ||
while (1) { | ||
// Set driver configuration to rotate 180 degrees each time | ||
ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, is_rotated, is_rotated)); | ||
// Display | ||
display_pretty_colors(panel_handle); | ||
is_rotated = !is_rotated; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: CC0-1.0 | ||
*/ | ||
|
||
#include <math.h> | ||
#include "pretty_effect.h" | ||
#include "decode_image.h" | ||
|
||
uint16_t *pixels; | ||
|
||
//Grab a rgb16 pixel from the esp32_tiles image | ||
static inline uint16_t get_bgnd_pixel(int x, int y) | ||
{ | ||
//Get color of the pixel on x,y coords | ||
return (uint16_t) * (pixels + (y * IMAGE_W) + x); | ||
} | ||
|
||
//This variable is used to detect the next frame. | ||
static int prev_frame = -1; | ||
|
||
//Instead of calculating the offsets for each pixel we grab, we pre-calculate the valueswhenever a frame changes, then re-use | ||
//these as we go through all the pixels in the frame. This is much, much faster. | ||
static int8_t xofs[320], yofs[240]; | ||
static int8_t xcomp[320], ycomp[240]; | ||
|
||
//Calculate the pixel data for a set of lines (with implied line size of 320). Pixels go in dest, line is the Y-coordinate of the | ||
//first line to be calculated, linect is the amount of lines to calculate. Frame increases by one every time the entire image | ||
//is displayed; this is used to go to the next frame of animation. | ||
void pretty_effect_calc_lines(uint16_t *dest, int line, int frame, int linect) | ||
{ | ||
if (frame != prev_frame) { | ||
//We need to calculate a new set of offset coefficients. Take some random sines as offsets to make everything | ||
//look pretty and fluid-y. | ||
for (int x = 0; x < 320; x++) { | ||
xofs[x] = sin(frame * 0.15 + x * 0.06) * 4; | ||
} | ||
for (int y = 0; y < 240; y++) { | ||
yofs[y] = sin(frame * 0.1 + y * 0.05) * 4; | ||
} | ||
for (int x = 0; x < 320; x++) { | ||
xcomp[x] = sin(frame * 0.11 + x * 0.12) * 4; | ||
} | ||
for (int y = 0; y < 240; y++) { | ||
ycomp[y] = sin(frame * 0.07 + y * 0.15) * 4; | ||
} | ||
prev_frame = frame; | ||
} | ||
for (int y = line; y < line + linect; y++) { | ||
for (int x = 0; x < 320; x++) { | ||
*dest++ = get_bgnd_pixel(x + yofs[y] + xcomp[x], y + xofs[x] + ycomp[y]); | ||
} | ||
} | ||
} | ||
|
||
|
||
esp_err_t pretty_effect_init(void) | ||
{ | ||
return decode_image(&pixels); | ||
} |
Oops, something went wrong.