| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- /*
- *
- * Copyright (c) 2020-2023 Project CHIP Authors
- * Copyright (c) 2018 Nest Labs, Inc.
- * All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <string.h>
- #include "driver/ledc.h"
- #include "esp_log.h"
- #include "esp_system.h"
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "freertos/timers.h"
- #include "Display.h"
- #if CONFIG_HAVE_DISPLAY
- // Brightness picked such that it's easy for cameras to focus on
- #define DEFAULT_BRIGHTNESS_PERCENT 10
- // 8MHz is the recommended SPI speed to init the driver with
- // It later gets set to the preconfigured defaults within the driver
- #define TFT_SPI_CLOCK_INIT_HZ 8000000
- // The frequency used by the ledc timer
- // value chosen to eliminate flicker
- #define LEDC_PWM_HZ 1000
- // with a duty resolution of LEDC_TIMER_8_BIT
- // the highest possible brightness value is 255
- #define BRIGHTNESS_MAX 255
- // The M5Stack's backlight is on Channel 7
- #define BACKLIGHT_CHANNEL LEDC_CHANNEL_7
- static const char * TAG = "Display";
- uint16_t DisplayHeight = 0;
- uint16_t DisplayWidth = 0;
- bool awake = false;
- #if CONFIG_DISPLAY_AUTO_OFF
- // FreeRTOS timer used to turn the display off after a short while
- TimerHandle_t displayTimer = NULL;
- #endif
- #if CONFIG_DISPLAY_AUTO_OFF
- static void TimerCallback(TimerHandle_t xTimer);
- #endif
- static void SetupBrightnessControl();
- static void SetBrightness(uint16_t brightness_percent);
- esp_err_t InitDisplay()
- {
- esp_err_t err;
- spi_lobo_device_handle_t spi;
- // configured based on the display driver's examples
- spi_lobo_bus_config_t buscfg;
- memset((void *) &buscfg, 0, sizeof(buscfg));
- buscfg.miso_io_num = PIN_NUM_MISO; // set SPI MISO pin
- buscfg.mosi_io_num = PIN_NUM_MOSI; // set SPI MOSI pin
- buscfg.sclk_io_num = PIN_NUM_CLK; // set SPI CLK pin
- buscfg.quadwp_io_num = -1;
- buscfg.quadhd_io_num = -1;
- spi_lobo_device_interface_config_t devcfg;
- memset((void *) &devcfg, 0, sizeof(devcfg));
- devcfg.clock_speed_hz = TFT_SPI_CLOCK_INIT_HZ;
- devcfg.mode = 0; // SPI mode 0
- devcfg.spics_io_num = -1; // we will use external CS pin
- devcfg.spics_ext_io_num = PIN_NUM_CS; // external CS pin
- devcfg.flags = LB_SPI_DEVICE_HALFDUPLEX; // ALWAYS SET to HALF DUPLEX MODE!! for display spi
- tft_max_rdclock = TFT_SPI_CLOCK_INIT_HZ;
- // Initialize all pins used by display driver.
- TFT_PinsInit();
- // Initialize SPI bus and add a device for the display.
- err = spi_lobo_bus_add_device(TFT_HSPI_HOST, &buscfg, &devcfg, &spi);
- if (err != ESP_OK)
- return err;
- // Configure the display to use the new SPI device.
- tft_disp_spi = spi;
- err = spi_lobo_device_select(spi, 1);
- if (err != ESP_OK)
- return err;
- err = spi_lobo_device_deselect(spi);
- if (err != ESP_OK)
- return err;
- // Initialize the display driver.
- TFT_display_init();
- // Detect maximum read speed and set it.
- tft_max_rdclock = find_rd_speed();
- // Set the SPI clock speed overriding the initialized 8MHz speed
- spi_lobo_set_speed(spi, DEFAULT_SPI_CLOCK);
- TFT_setGammaCurve(0);
- TFT_setRotation(LANDSCAPE);
- TFT_resetclipwin();
- DisplayWidth = (uint16_t)(1 + tft_dispWin.x2 - tft_dispWin.x1);
- DisplayHeight = (uint16_t)(1 + tft_dispWin.y2 - tft_dispWin.y1);
- ESP_LOGI(TAG, "Display initialized (height %u, width %u)", DisplayHeight, DisplayWidth);
- TFT_invertDisplay(INVERT_DISPLAY);
- // prepare the display for brightness control
- SetupBrightnessControl();
- #if CONFIG_DISPLAY_AUTO_OFF
- displayTimer = xTimerCreate("DisplayTimer", pdMS_TO_TICKS(DISPLAY_TIMEOUT_MS), false, NULL, TimerCallback);
- #endif
- // lower the brightness of the screen
- WakeDisplay();
- return err;
- }
- void SetBrightness(uint16_t brightness_percent)
- {
- uint16_t brightness = (brightness_percent * BRIGHTNESS_MAX) / 100;
- if (ledc_set_duty(LEDC_HIGH_SPEED_MODE, BACKLIGHT_CHANNEL, brightness) ||
- ledc_update_duty(LEDC_HIGH_SPEED_MODE, BACKLIGHT_CHANNEL))
- {
- ESP_LOGE(TAG, "Failed to set display brightness...");
- }
- }
- bool WakeDisplay()
- {
- bool woken = !awake;
- awake = true;
- SetBrightness(DEFAULT_BRIGHTNESS_PERCENT);
- #if CONFIG_DISPLAY_AUTO_OFF
- xTimerStart(displayTimer, 0);
- ESP_LOGI(TAG, "Display awake but will switch off automatically in %d seconds", DISPLAY_TIMEOUT_MS / 1000);
- #endif
- return woken;
- }
- void ClearDisplay()
- {
- ClearRect();
- }
- void ClearRect(uint16_t x_percent_start, uint16_t y_percent_start, uint16_t x_percent_end, uint16_t y_percent_end)
- {
- if (x_percent_end < x_percent_start)
- {
- x_percent_end = x_percent_start;
- }
- if (y_percent_end < y_percent_start)
- {
- y_percent_end = y_percent_start;
- }
- uint16_t start_x = (DisplayWidth * x_percent_start) / 100;
- uint16_t start_y = (DisplayHeight * y_percent_start) / 100;
- uint16_t end_x = (DisplayWidth * x_percent_end) / 100;
- uint16_t end_y = (DisplayHeight * y_percent_end) / 100;
- TFT_fillRect(start_x, start_y, end_x, end_y, TFT_BLACK);
- }
- void DisplayStatusMessage(char * msg, uint16_t vpos)
- {
- TFT_setFont(SMALL_FONT, NULL);
- uint16_t msgX = 0;
- uint16_t msgY = (DisplayHeight * vpos) / 100;
- TFT_print(msg, msgX, msgY);
- }
- void TimerCallback(TimerHandle_t xTimer)
- {
- ESP_LOGI(TAG, "Display going to sleep...");
- SetBrightness(0);
- awake = false;
- }
- void SetupBrightnessControl()
- {
- ledc_timer_config_t ledc_timer;
- memset(&ledc_timer, 0, sizeof(ledc_timer));
- ledc_timer.duty_resolution = LEDC_TIMER_8_BIT; // resolution of PWM duty
- ledc_timer.freq_hz = LEDC_PWM_HZ; // frequency of PWM signal
- ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE; // timer mode
- ledc_timer.timer_num = LEDC_TIMER_0; // timer index
- ledc_timer_config(&ledc_timer);
- ledc_timer_set(LEDC_HIGH_SPEED_MODE, LEDC_TIMER_0, LEDC_PWM_HZ, LEDC_TIMER_8_BIT, LEDC_REF_TICK);
- ledc_channel_config_t ledc_channel;
- memset(&ledc_channel, 0, sizeof(ledc_channel));
- ledc_channel.channel = BACKLIGHT_CHANNEL;
- ledc_channel.duty = BRIGHTNESS_MAX;
- ledc_channel.gpio_num = PIN_NUM_BCKL;
- ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
- ledc_channel.timer_sel = LEDC_TIMER_0;
- ledc_channel_config(&ledc_channel);
- }
- #endif // CONFIG_HAVE_DISPLAY
|