Skip to content

Commit

Permalink
feat(examples): Add noglib example
Browse files Browse the repository at this point in the history
  • Loading branch information
tore-espressif committed Aug 27, 2024
1 parent 1938819 commit edc1549
Show file tree
Hide file tree
Showing 11 changed files with 467 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .build-test-rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ examples:
- if: IDF_VERSION_MAJOR < 5 and IDF_VERSION_MINOR < 3 and CONFIG_NAME == "esp32_p4_function_ev_board"
reason: Example depends on BSP, which is supported only for IDF >= 5.3

examples/noglib:
disable:
- if: ENV_BUILD_NOGLIB == 0

components/lcd/esp_lcd_gc9503:
disable:
- if: IDF_VERSION_MAJOR < 5 or (IDF_VERSION_MAJOR == 5 and IDF_VERSION_MINOR == 0 and ESP_IDF_VERSION_PATCH < 5) or (IDF_VERSION_MAJOR == 5 and IDF_VERSION_MINOR == 1 and ESP_IDF_VERSION_PATCH == 1)
Expand Down
7 changes: 7 additions & 0 deletions examples/noglib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# The following five 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)

set(COMPONENTS main)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(noglib)
23 changes: 23 additions & 0 deletions examples/noglib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# No Graphical Library BSP example

BSPs are by default shipped with LVGL graphical library. This example shows how you can use 'noglib' version of BSPs (without LVGL).

More information about noglib BSPs can be found in root [README file](../../README.md).

## How to use the example

### Hardware Required

* Any of the supported boards

### Compile and flash

This example is used mainly for CI testing purposes. If you want to build it locally, follow these steps:

1. Create a noglib version of your BSP with `python ./.github/ci/bsp_noglib.py <name_of_your_bsp>`
2. Update [idf_component.yml](main/idf_component.yml) with your BSP
3. Compile and flash as usual `idf.py -p COMx flash monitor`

### Example outputs

Following picture will be displayed with wave effect: ![](image.jpg)
Binary file added examples/noglib/image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions examples/noglib/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRCS "noglib_main.c" "pretty_effect.c"
INCLUDE_DIRS ".")
7 changes: 7 additions & 0 deletions examples/noglib/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## IDF Component Manager Manifest File
dependencies:
## Required IDF version
idf: ">=5.1"
esp_wrover_kit_noglib:
version: "*"
override_path: "../../../bsp/esp_wrover_kit_noglib"
251 changes: 251 additions & 0 deletions examples/noglib/main/image.c

Large diffs are not rendered by default.

95 changes: 95 additions & 0 deletions examples/noglib/main/noglib_main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/

#include <stdbool.h>
#include "esp_err.h"
#include "esp_heap_caps.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_io.h"
#include "driver/spi_master.h"

#include "bsp/esp-bsp.h"
#include "pretty_effect.h"

// 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
#define PARALLEL_LINES (240 / 5)
#define FRAME_BUF_SIZE (320 * PARALLEL_LINES * BSP_LCD_BITS_PER_PIXEL / 8)
#define FRAME_BUF_NUM (2)

// The number of frames to show before rotate the graph
#define ROTATE_FRAME 30

// 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[FRAME_BUF_NUM];
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 < 240; 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 + 320, y + PARALLEL_LINES, s_lines[sending_line]);
}
}
}

void app_main(void)
{
bool is_rotated = false;

// Non-graphical API can be used without any restrictions in noglib version
ESP_ERROR_CHECK(bsp_leds_init());

// Only API from bsp/display.h can be used in noglib version
ESP_ERROR_CHECK(bsp_display_brightness_init());
ESP_ERROR_CHECK(bsp_display_backlight_off());

esp_lcd_panel_handle_t lcd_panel;
esp_lcd_panel_io_handle_t lcd_panel_io;
const bsp_display_config_t lcd_config = {
.max_transfer_sz = FRAME_BUF_SIZE,
};
ESP_ERROR_CHECK(bsp_display_new(&lcd_config, &lcd_panel, &lcd_panel_io));

// The LCD can be accessed through esp_lcd API
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(lcd_panel, true));
ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(lcd_panel, true));
ESP_ERROR_CHECK(bsp_display_backlight_on());

// Allocate memory for the pixel buffers
for (int i = 0; i < FRAME_BUF_NUM; i++) {
s_lines[i] = heap_caps_malloc(FRAME_BUF_SIZE, MALLOC_CAP_DMA);
assert(s_lines[i] != NULL);
}

// Start and rotate
while (1) {
// Set driver configuration to rotate 180 degrees each time
ESP_ERROR_CHECK(esp_lcd_panel_mirror(lcd_panel, is_rotated, is_rotated));
// Display
display_pretty_colors(lcd_panel);
is_rotated = !is_rotated;

ESP_ERROR_CHECK(bsp_led_set(BSP_LED_BLUE, is_rotated));
}

// Clean-up with esp_lcd API
esp_lcd_panel_del(lcd_panel);
esp_lcd_panel_io_del(lcd_panel_io);
spi_bus_free(BSP_LCD_SPI_NUM);
}
55 changes: 55 additions & 0 deletions examples/noglib/main/pretty_effect.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/

#include <math.h>
#include "pretty_effect.h"
#include "image.c"

uint16_t *pixels = (uint16_t *)(&image[0]);

//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 image[(y * 320) + 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 values whenever 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]);
}
}
}
19 changes: 19 additions & 0 deletions examples/noglib/main/pretty_effect.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/

#pragma once
#include <stdint.h>
#include "esp_err.h"

/**
* @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);
4 changes: 4 additions & 0 deletions examples/noglib/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) 5.4.0 Project Minimal Configuration
#
CONFIG_BSP_LCD_ST7789=y

0 comments on commit edc1549

Please sign in to comment.