add some code
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
set(srcs "pretty_effect.c"
|
||||
"lcd_tjpgd_example_main.c"
|
||||
"decode_image.c"
|
||||
)
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS "."
|
||||
EMBED_FILES image.jpg
|
||||
PRIV_REQUIRES esp_lcd)
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,16 @@
|
||||
dependencies:
|
||||
esp-box:
|
||||
rules:
|
||||
- if: target == esp32s3
|
||||
version: ^2.4
|
||||
esp32_s2_kaluga_kit:
|
||||
rules:
|
||||
- if: target == esp32s2
|
||||
version: ^3.0
|
||||
esp_jpeg:
|
||||
version: '>=1.0.2'
|
||||
esp_wrover_kit:
|
||||
rules:
|
||||
- if: target == esp32
|
||||
version: ^1.5
|
||||
idf: '>=5.0'
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Calculate the effect for a bunch of lines.
|
||||
*
|
||||
* @param dest Destination for the pixels. Assumed to be LINECT * 320 16-bit pixel values.
|
||||
* @param line Starting line of the chunk of lines.
|
||||
* @param frame Current frame, used for animation
|
||||
* @param linect Amount of lines to calculate
|
||||
*/
|
||||
void pretty_effect_calc_lines(uint16_t *dest, int line, int frame, int linect);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize the effect
|
||||
*
|
||||
* @return ESP_OK on success, an error from the jpeg decoder otherwise.
|
||||
*/
|
||||
esp_err_t pretty_effect_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user