rework wifi Interface around this new concept and patch up some old uses of notifications to follow new paradigm compile out old UI code because notification refactor broke it.
184 lines
5.5 KiB
C++
184 lines
5.5 KiB
C++
|
|
#include "display.hpp"
|
|
#include "Wire.h"
|
|
#include "driver/ledc.h"
|
|
#include "omoteconfig.h"
|
|
|
|
std::shared_ptr<Display> Display::getInstance() {
|
|
if (DisplayAbstract::mInstance == nullptr) {
|
|
DisplayAbstract::mInstance =
|
|
std::shared_ptr<Display>(new Display(LCD_BL, LCD_EN));
|
|
}
|
|
return std::static_pointer_cast<Display>(mInstance);
|
|
}
|
|
|
|
Display::Display(int backlight_pin, int enable_pin)
|
|
: DisplayAbstract(), mBacklightPin(backlight_pin), mEnablePin(enable_pin),
|
|
tft(TFT_eSPI()), touch(Adafruit_FT6206()) {
|
|
pinMode(mEnablePin, OUTPUT);
|
|
digitalWrite(mEnablePin, HIGH);
|
|
pinMode(mBacklightPin, OUTPUT);
|
|
digitalWrite(mBacklightPin, HIGH);
|
|
|
|
setupBacklight(); // This eliminates the flash of the backlight
|
|
|
|
// Slowly charge the VSW voltage to prevent a brownout
|
|
// Workaround for hardware rev 1!
|
|
for (int i = 0; i < 100; i++) {
|
|
digitalWrite(this->mEnablePin, HIGH); // LCD Logic off
|
|
delayMicroseconds(1);
|
|
digitalWrite(this->mEnablePin, LOW); // LCD Logic on
|
|
}
|
|
|
|
setupTFT();
|
|
setupTouchScreen();
|
|
mFadeTaskMutex = xSemaphoreCreateBinary();
|
|
xSemaphoreGive(mFadeTaskMutex);
|
|
}
|
|
|
|
void Display::setupBacklight() {
|
|
// Configure the backlight PWM
|
|
// Manual setup because ledcSetup() briefly turns on the backlight
|
|
ledc_channel_config_t ledc_channel_left;
|
|
ledc_channel_left.gpio_num = (gpio_num_t)mBacklightPin;
|
|
ledc_channel_left.speed_mode = LEDC_HIGH_SPEED_MODE;
|
|
ledc_channel_left.channel = LEDC_CHANNEL_5;
|
|
ledc_channel_left.intr_type = LEDC_INTR_DISABLE;
|
|
ledc_channel_left.timer_sel = LEDC_TIMER_1;
|
|
ledc_channel_left.flags.output_invert = 1; // Can't do this with ledcSetup()
|
|
ledc_channel_left.duty = 0;
|
|
ledc_channel_left.hpoint = 0;
|
|
ledc_timer_config_t ledc_timer;
|
|
ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
|
|
ledc_timer.duty_resolution = LEDC_TIMER_8_BIT;
|
|
ledc_timer.timer_num = LEDC_TIMER_1;
|
|
ledc_timer.clk_cfg = LEDC_AUTO_CLK;
|
|
ledc_timer.freq_hz = 640;
|
|
ledc_channel_config(&ledc_channel_left);
|
|
ledc_timer_config(&ledc_timer);
|
|
}
|
|
|
|
void Display::setupTFT() {
|
|
delay(100);
|
|
tft.init();
|
|
tft.initDMA();
|
|
tft.setRotation(0);
|
|
tft.fillScreen(TFT_BLACK);
|
|
tft.setSwapBytes(true);
|
|
}
|
|
|
|
void Display::setupTouchScreen() {
|
|
// Configure i2c pins and set frequency to 400kHz
|
|
Wire.begin(TFT_SDA, TFT_SCL, 400000);
|
|
touch.begin(128); // Initialize touchscreen and set sensitivity threshold
|
|
}
|
|
|
|
void Display::setBrightness(uint8_t brightness) {
|
|
mAwakeBrightness = brightness;
|
|
Serial.print("Set Brightness:");
|
|
Serial.println(mAwakeBrightness);
|
|
startFade();
|
|
}
|
|
|
|
uint8_t Display::getBrightness() { return mAwakeBrightness; }
|
|
|
|
void Display::setCurrentBrightness(uint8_t brightness) {
|
|
mBrightness = brightness;
|
|
auto duty = static_cast<int>(mBrightness);
|
|
ledcWrite(LCD_BACKLIGHT_LEDC_CHANNEL, duty);
|
|
// Serial.print("Current Brightness:");
|
|
// Serial.println(mBrightness);
|
|
}
|
|
|
|
void Display::turnOff() {
|
|
digitalWrite(this->mBacklightPin, HIGH);
|
|
digitalWrite(this->mEnablePin, HIGH);
|
|
pinMode(this->mBacklightPin, INPUT);
|
|
pinMode(this->mEnablePin, INPUT);
|
|
gpio_hold_en((gpio_num_t)mBacklightPin);
|
|
gpio_hold_en((gpio_num_t)mEnablePin);
|
|
}
|
|
|
|
void Display::screenInput(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) {
|
|
// int16_t touchX, touchY;
|
|
touchPoint = touch.getPoint();
|
|
int16_t touchX = touchPoint.x;
|
|
int16_t touchY = touchPoint.y;
|
|
bool touched = false;
|
|
if ((touchX > 0) || (touchY > 0)) {
|
|
touched = true;
|
|
mTouchEvent->notify(touchPoint);
|
|
}
|
|
|
|
if (!touched) {
|
|
data->state = LV_INDEV_STATE_REL;
|
|
} else {
|
|
data->state = LV_INDEV_STATE_PR;
|
|
|
|
// Set the coordinates
|
|
data->point.x = SCREEN_WIDTH - touchX;
|
|
data->point.y = SCREEN_HEIGHT - touchY;
|
|
|
|
// Serial.print( "touchpoint: x" );
|
|
// Serial.print( touchX );
|
|
// Serial.print( " y" );
|
|
// Serial.println( touchY );
|
|
// tft.drawFastHLine(0, screenHeight - touchY, screenWidth, TFT_RED);
|
|
// tft.drawFastVLine(screenWidth - touchX, 0, screenHeight, TFT_RED);
|
|
}
|
|
}
|
|
|
|
void Display::fadeImpl(void *) {
|
|
bool fadeDone = false;
|
|
while (!fadeDone) {
|
|
fadeDone = getInstance()->fade();
|
|
vTaskDelay(3 / portTICK_PERIOD_MS); // 3 miliseconds between steps
|
|
// 0 - 255 will take about .75 seconds to fade up.
|
|
}
|
|
|
|
xSemaphoreTake(getInstance()->mFadeTaskMutex, portMAX_DELAY);
|
|
getInstance()->mDisplayFadeTask = nullptr;
|
|
xSemaphoreGive(getInstance()->mFadeTaskMutex);
|
|
|
|
vTaskDelete(nullptr); // Delete Fade Task
|
|
}
|
|
|
|
bool Display::fade() {
|
|
// Early return no fade needed.
|
|
if (mBrightness == mAwakeBrightness || isAsleep && mBrightness == 0) {
|
|
return true;
|
|
}
|
|
|
|
bool fadeDown = isAsleep || mBrightness > mAwakeBrightness;
|
|
if (fadeDown) {
|
|
setCurrentBrightness(mBrightness - 1);
|
|
auto setPoint = isAsleep ? 0 : mAwakeBrightness;
|
|
return mBrightness == setPoint;
|
|
} else {
|
|
setCurrentBrightness(mBrightness + 1);
|
|
return mBrightness == mAwakeBrightness;
|
|
}
|
|
}
|
|
|
|
void Display::startFade() {
|
|
xSemaphoreTake(mFadeTaskMutex, portMAX_DELAY);
|
|
// Only Create Task if it is needed
|
|
if (mDisplayFadeTask == nullptr) {
|
|
xTaskCreate(&Display::fadeImpl, "Display Fade Task", 1024, nullptr, 5,
|
|
&mDisplayFadeTask);
|
|
}
|
|
xSemaphoreGive(mFadeTaskMutex);
|
|
}
|
|
|
|
void Display::flushDisplay(lv_disp_drv_t *disp, const lv_area_t *area,
|
|
lv_color_t *color_p) {
|
|
uint32_t w = (area->x2 - area->x1 + 1);
|
|
uint32_t h = (area->y2 - area->y1 + 1);
|
|
|
|
tft.startWrite();
|
|
tft.setAddrWindow(area->x1, area->y1, w, h);
|
|
tft.pushPixelsDMA((uint16_t *)&color_p->full, w * h);
|
|
tft.endWrite();
|
|
|
|
lv_disp_flush_ready(disp);
|
|
}
|