From 43dbbd3a98ada2f7f23625ff88f01a40bc7e1eee Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 20 Aug 2018 18:07:19 +0200 Subject: [PATCH] Add more display functionality * Add display define USE_DISPLAY_MODES1TO5 to select display modes 1 to 5 * Add command DisplayRotate 0..3 to select persistent display rotation --- sonoff/_changelog.ino | 2 + sonoff/settings.h | 4 +- sonoff/user_config.h | 27 +++--- sonoff/xdrv_13_display.ino | 170 +++++++++++++++++++++---------------- sonoff/xdsp_01_lcd.ino | 93 ++++++++++---------- sonoff/xdsp_02_ssd1306.ino | 98 ++++++++++----------- sonoff/xdsp_03_matrix.ino | 125 +++++++++++++-------------- sonoff/xdsp_04_ili9341.ino | 114 +++++++++++-------------- sonoff/xdsp_05_epaper.ino | 18 ++-- 9 files changed, 333 insertions(+), 318 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index ac041fdf8..5ddaa8058 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -2,6 +2,8 @@ * Add initial display support for Lcd, Oled, Matrix, Tft and e-paper - Need more docs * Fix SDM120 reporting wrong negative values to Domoticz (#3521) * Fix iFan02 power on state (#3412, #3530) + * Add display define USE_DISPLAY_MODES1TO5 to select display modes 1 to 5 + * Add command DisplayRotate 0..3 to select persistent display rotation * * 6.1.1.6 * Add modulo option to rules like rule1 on Time#Minute|5 do backlog power on;delay 200;power off endon (#3466) diff --git a/sonoff/settings.h b/sonoff/settings.h index c400e803d..fcc4d17b8 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -222,9 +222,7 @@ struct SYSCFG { uint16_t pwm_value[MAX_PWMS]; // 2EC int16_t altitude; // 2F6 uint16_t tele_period; // 2F8 - - byte free_2fa[1]; // 2FA - + uint8_t display_rotate; // 2FA uint8_t ledstate; // 2FB uint8_t param[PARAM8_SIZE]; // 2FC SetOption32 .. SetOption49 int16_t toffset[2]; // 30E diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 211270d68..63541183f 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -298,17 +298,18 @@ // #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code) // #define USE_DISPLAY // Add I2C Display Support for LCD, Oled and up to eigth Matrices (+19k code) - #define USE_DISPLAY_LCD // Enable Lcd display (I2C addresses 0x27 and 0x3F) - #define USE_DISPLAY_SSD1306 // Enable Oled 128x64 display (I2C addresses 0x3C and 0x3D) -// #define USE_DISPLAY_MATRIX // Enable 8x8 Matrix display (I2C adresses below) - #define MTX_ADDRESS1 0x71 // [DisplayAddress[1]] I2C address of first 8x8 matrix module - #define MTX_ADDRESS2 0x74 // [DisplayAddress[2]] I2C address of second 8x8 matrix module - #define MTX_ADDRESS3 0x75 // [DisplayAddress[3]] I2C address of third 8x8 matrix module - #define MTX_ADDRESS4 0x72 // [DisplayAddress[4]] I2C address of fourth 8x8 matrix module - #define MTX_ADDRESS5 0x73 // [DisplayAddress[5]] I2C address of fifth 8x8 matrix module - #define MTX_ADDRESS6 0x76 // [DisplayAddress[6]] I2C address of sixth 8x8 matrix module - #define MTX_ADDRESS7 0x00 // [DisplayAddress[7]] I2C address of seventh 8x8 matrix module - #define MTX_ADDRESS8 0x00 // [DisplayAddress[8]] I2C address of eigth 8x8 matrix module + #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 + #define USE_DISPLAY_LCD // [DisplayModel 1] Enable Lcd display (I2C addresses 0x27 and 0x3F) + #define USE_DISPLAY_SSD1306 // [DisplayModel 2] Enable SSD1306 Oled 128x64 display (I2C addresses 0x3C and 0x3D) + #define USE_DISPLAY_MATRIX // [DisplayModel 3] Enable 8x8 Matrix display (I2C adresseses see below) + #define MTX_ADDRESS1 0x71 // [DisplayAddress1] I2C address of first 8x8 matrix module + #define MTX_ADDRESS2 0x74 // [DisplayAddress2] I2C address of second 8x8 matrix module + #define MTX_ADDRESS3 0x75 // [DisplayAddress3] I2C address of third 8x8 matrix module + #define MTX_ADDRESS4 0x72 // [DisplayAddress4] I2C address of fourth 8x8 matrix module + #define MTX_ADDRESS5 0x73 // [DisplayAddress5] I2C address of fifth 8x8 matrix module + #define MTX_ADDRESS6 0x76 // [DisplayAddress6] I2C address of sixth 8x8 matrix module + #define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module + #define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module #endif // USE_I2C @@ -319,8 +320,8 @@ #ifndef USE_DISPLAY #define USE_DISPLAY // Add SPI Display support for 320x240 and 480x320 TFT #endif - #define USE_DISPLAY_ILI9341 // Enable Tft 480x320 display -// #define USE_DISPLAY_EPAPER // Enable e-paper display + #define USE_DISPLAY_ILI9341 // [DisplayModel 4] Enable ILI9341 Tft 480x320 display +// #define USE_DISPLAY_EPAPER // [DisplayModel 5] Enable e-paper display #endif // USE_SPI diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 4664d3844..9c4fd4ff2 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -37,6 +37,7 @@ #define D_CMND_DISP_REFRESH "Refresh" #define D_CMND_DISP_ROWS "Rows" #define D_CMND_DISP_SIZE "Size" +#define D_CMND_DISP_ROTATE "Rotate" #define D_CMND_DISP_TEXT "Text" enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_EVERY_50_MSECOND, FUNC_DISPLAY_EVERY_SECOND, @@ -50,24 +51,18 @@ enum XdspFunctions { FUNC_DISPLAY_INIT_DRIVER, FUNC_DISPLAY_INIT, FUNC_DISPLAY_E enum DisplayInitModes { DISPLAY_INIT_MODE, DISPLAY_INIT_PARTIAL, DISPLAY_INIT_FULL }; enum DisplayCommands { CMND_DISP_MODEL, CMND_DISP_MODE, CMND_DISP_REFRESH, CMND_DISP_DIMMER, CMND_DISP_COLS, CMND_DISP_ROWS, - CMND_DISP_SIZE, CMND_DISP_TEXT, CMND_DISP_ADDRESS }; + CMND_DISP_SIZE, CMND_DISP_ROTATE, CMND_DISP_TEXT, CMND_DISP_ADDRESS }; const char kDisplayCommands[] PROGMEM = D_CMND_DISP_MODEL "|" D_CMND_DISP_MODE "|" D_CMND_DISP_REFRESH "|" D_CMND_DISP_DIMMER "|" D_CMND_DISP_COLS "|" D_CMND_DISP_ROWS "|" - D_CMND_DISP_SIZE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS ; + D_CMND_DISP_SIZE "|" D_CMND_DISP_ROTATE "|" D_CMND_DISP_TEXT "|" D_CMND_DISP_ADDRESS ; const char S_JSON_DISPLAY_COMMAND_VALUE[] PROGMEM = "{\"" D_CMND_DISPLAY "%s\":\"%s\"}"; const char S_JSON_DISPLAY_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_DISPLAY "%s\":%d}"; const char S_JSON_DISPLAY_COMMAND_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DISPLAY "%s%d\":%d}"; -char disp_log_buffer[DISPLAY_LOG_ROWS][DISPLAY_LOG_COLS]; -char disp_temp[2]; // C or F -uint8_t disp_log_buffer_idx = 0; -uint8_t disp_log_buffer_ptr = 0; -bool disp_log_buffer_active = false; -uint8_t disp_refresh = 1; uint8_t disp_power = 0; uint8_t disp_device = 0; -uint8_t disp_subscribed = 0; +uint8_t disp_refresh = 1; int16_t disp_xpos = 0; int16_t disp_ypos = 0; @@ -76,7 +71,6 @@ uint8_t dsp_init; uint8_t dsp_font; uint8_t dsp_flag; uint8_t dsp_on; -uint8_t dsp_rotation; uint16_t dsp_x; uint16_t dsp_y; uint16_t dsp_x2; @@ -86,6 +80,17 @@ uint16_t dsp_color; int16_t dsp_len; char *dsp_str; +#ifdef USE_DISPLAY_MODES1TO5 +char disp_log_buffer[DISPLAY_LOG_ROWS][DISPLAY_LOG_COLS]; +char disp_temp[2]; // C or F +uint8_t disp_log_buffer_idx = 0; +uint8_t disp_log_buffer_ptr = 0; +bool disp_log_buffer_active = false; +uint8_t disp_subscribed = 0; +#endif // USE_DISPLAY_MODES1TO5 + +/*********************************************************************************************/ + void DisplayInit(uint8_t mode) { dsp_init = mode; @@ -170,13 +175,13 @@ void DisplayDrawFrame() void DisplaySetFontorSize(uint8_t font) { - Settings.display_size = font; + Settings.display_size = font &3; XdspCall(FUNC_DISPLAY_FONT_SIZE); } void DisplaySetRotation(uint8_t rotation) { - dsp_rotation = rotation; + Settings.display_rotate = rotation &3; XdspCall(FUNC_DISPLAY_ROTATION); } @@ -228,7 +233,7 @@ uint8_t atoiV(char *cp, uint16_t *res) return index; } -/*********************************************************************************************/ +/*-------------------------------------------------------------------------------------------*/ #define DISPLAY_BUFFER_COLS 128 // Max number of characters in linebuf @@ -451,6 +456,10 @@ void DisplayText() DisplayDrawFrame(); } +/*********************************************************************************************/ + +#ifdef USE_DISPLAY_MODES1TO5 + void DisplayLogBufferIdxInc() { disp_log_buffer_idx++; @@ -639,34 +648,6 @@ void DisplayAnalyzeJson(char *topic, char *json) } } -/*********************************************************************************************\ - * Public -\*********************************************************************************************/ - -void DisplayInitDriver() -{ - XdspCall(FUNC_DISPLAY_INIT_DRIVER); - -// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model); -// AddLog(LOG_LEVEL_DEBUG); - - if (Settings.display_model) { - devices_present++; - disp_device = devices_present; - snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit()); - - DisplayLogBufferInit(); - } -} - -void DisplaySetPower() -{ - disp_power = bitRead(XdrvMailbox.index, disp_device -1); - if (Settings.display_model) { - XdspCall(FUNC_DISPLAY_POWER); - } -} - void DisplayMqttSubscribe() { /* Subscribe to tele messages only @@ -726,6 +707,40 @@ void DisplayLocalSensor() } } +#endif // USE_DISPLAY_MODES1TO5 + +/*********************************************************************************************\ + * Public +\*********************************************************************************************/ + +void DisplayInitDriver() +{ + XdspCall(FUNC_DISPLAY_INIT_DRIVER); + +// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model); +// AddLog(LOG_LEVEL_DEBUG); + + if (Settings.display_model) { + devices_present++; + disp_device = devices_present; + +#ifndef USE_DISPLAY_MODES1TO5 + Settings.display_mode = 0; +#else + snprintf_P(disp_temp, sizeof(disp_temp), PSTR("%c"), TempUnit()); + DisplayLogBufferInit(); +#endif // USE_DISPLAY_MODES1TO5 + } +} + +void DisplaySetPower() +{ + disp_power = bitRead(XdrvMailbox.index, disp_device -1); + if (Settings.display_model) { + XdspCall(FUNC_DISPLAY_POWER); + } +} + /*********************************************************************************************\ * Commands \*********************************************************************************************/ @@ -754,9 +769,8 @@ boolean DisplayCommand() snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_model); } else if (CMND_DISP_MODE == command_code) { -/* - * Matrix LCD / Oled TFT - * 0 = Text Text Text +#ifdef USE_DISPLAY_MODES1TO5 +/* Matrix LCD / Oled TFT * 1 = Text up and time Time * 2 = Date Local sensors Local sensors * 3 = Day Local sensors and time Local sensors and time @@ -779,20 +793,9 @@ boolean DisplayCommand() } } } +#endif // USE_DISPLAY_MODES1TO5 snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_mode); } - else if (CMND_DISP_REFRESH == command_code) { - if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) { - Settings.display_refresh = XdrvMailbox.payload; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_refresh); - } - else if ((CMND_DISP_COLS == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_SCREEN_COLS)) { - Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_cols[XdrvMailbox.index -1]); - } else if (CMND_DISP_DIMMER == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { Settings.display_dimmer = ((XdrvMailbox.payload +1) * 100) / 666; // Correction for Domoticz (0 - 15) @@ -805,27 +808,32 @@ boolean DisplayCommand() } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_dimmer); } - else if (CMND_DISP_ROWS == command_code) { - if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_SCREEN_ROWS)) { - Settings.display_rows = XdrvMailbox.payload; - } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rows); - } else if (CMND_DISP_SIZE == command_code) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { Settings.display_size = XdrvMailbox.payload; } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_size); } + else if (CMND_DISP_ROTATE == command_code) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { + Settings.display_rotate = XdrvMailbox.payload; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rotate); + } else if (CMND_DISP_TEXT == command_code) { mqtt_data[0] = '\0'; if (disp_device && XdrvMailbox.data_len > 0) { +#ifndef USE_DISPLAY_MODES1TO5 + DisplayText(); + +#else if (!Settings.display_mode) { DisplayText(); } else { strlcpy(disp_log_buffer[disp_log_buffer_idx], XdrvMailbox.data, sizeof(disp_log_buffer[disp_log_buffer_idx])); DisplayLogBufferIdxInc(); } +#endif // USE_DISPLAY_MODES1TO5 } else { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("No Text")); } @@ -839,6 +847,24 @@ boolean DisplayCommand() } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_address[XdrvMailbox.index -1]); } + else if (CMND_DISP_REFRESH == command_code) { + if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) { + Settings.display_refresh = XdrvMailbox.payload; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_refresh); + } + else if ((CMND_DISP_COLS == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_SCREEN_COLS)) { + Settings.display_cols[XdrvMailbox.index -1] = XdrvMailbox.payload; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_cols[XdrvMailbox.index -1]); + } + else if (CMND_DISP_ROWS == command_code) { + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_SCREEN_ROWS)) { + Settings.display_rows = XdrvMailbox.payload; + } + snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rows); + } else serviced = false; // Unknown command } else serviced = false; // Unknown command @@ -850,9 +876,9 @@ boolean DisplayCommand() * Interface \*********************************************************************************************/ -#define XDRV_98 +#define XDRV_13 -boolean Xdrv98(byte function) +boolean Xdrv13(byte function) { boolean result = false; @@ -862,26 +888,28 @@ boolean Xdrv98(byte function) DisplayInitDriver(); break; case FUNC_EVERY_50_MSECOND: - if (Settings.display_model && Settings.display_mode) { XdspCall(FUNC_DISPLAY_EVERY_50_MSECOND); } - break; - case FUNC_EVERY_SECOND: - if (Settings.display_model && Settings.display_mode) { XdspCall(FUNC_DISPLAY_EVERY_SECOND); } + if (Settings.display_model) { XdspCall(FUNC_DISPLAY_EVERY_50_MSECOND); } break; case FUNC_COMMAND: result = DisplayCommand(); break; + case FUNC_SET_POWER: + DisplaySetPower(); + break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_EVERY_SECOND: + if (Settings.display_model && Settings.display_mode) { XdspCall(FUNC_DISPLAY_EVERY_SECOND); } + break; case FUNC_MQTT_SUBSCRIBE: DisplayMqttSubscribe(); break; case FUNC_MQTT_DATA: result = DisplayMqttData(); break; - case FUNC_SET_POWER: - DisplaySetPower(); - break; case FUNC_SHOW_SENSOR: DisplayLocalSensor(); break; +#endif // USE_DISPLAY_MODES1TO5 } } return result; diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index 051346c8d..b69490eb4 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -34,56 +34,14 @@ LiquidCrystal_I2C *lcd; -char lcd_screen_buffer[LCD_BUFFER_ROWS][LCD_BUFFER_COLS +1]; - -void LcdInitFull() -{ - lcd->init(); - lcd->clear(); - memset(lcd_screen_buffer[Settings.display_rows -1], 0x20, Settings.display_cols[0]); - lcd_screen_buffer[Settings.display_rows -1][Settings.display_cols[0]] = 0; -} - -void LcdDrawStringAt() -{ - lcd->setCursor(dsp_x, dsp_y); - lcd->print(dsp_str); -} - -void LcdDisplayOnOff(uint8_t on) -{ - if (on) { - lcd->backlight(); - } else { - lcd->noBacklight(); - } -} - -/*********************************************************************************************/ - -void LcdCenter(byte row, char* txt) -{ - int offset; - int len; - char line[Settings.display_cols[0] +2]; - - memset(line, 0x20, Settings.display_cols[0]); - line[Settings.display_cols[0]] = 0; - len = strlen(txt); - offset = (len < Settings.display_cols[0]) ? offset = (Settings.display_cols[0] - len) / 2 : 0; - strncpy(line +offset, txt, len); - lcd->setCursor(0, row); - lcd->print(line); -} - /*********************************************************************************************/ void LcdInitMode() { lcd->init(); lcd->clear(); - memset(lcd_screen_buffer[Settings.display_rows -1], 0x20, Settings.display_cols[0]); - lcd_screen_buffer[Settings.display_rows -1][Settings.display_cols[0]] = 0; +// memset(lcd_screen_buffer[Settings.display_rows -1], 0x20, Settings.display_cols[0]); +// lcd_screen_buffer[Settings.display_rows -1][Settings.display_cols[0]] = 0; } void LcdInit(uint8_t mode) @@ -118,6 +76,42 @@ void LcdInitDriver() } } +void LcdDrawStringAt() +{ + lcd->setCursor(dsp_x, dsp_y); + lcd->print(dsp_str); +} + +void LcdDisplayOnOff(uint8_t on) +{ + if (on) { + lcd->backlight(); + } else { + lcd->noBacklight(); + } +} + +/*********************************************************************************************/ + +#ifdef USE_DISPLAY_MODES1TO5 + +char lcd_screen_buffer[LCD_BUFFER_ROWS][LCD_BUFFER_COLS +1]; + +void LcdCenter(byte row, char* txt) +{ + int offset; + int len; + char line[Settings.display_cols[0] +2]; + + memset(line, 0x20, Settings.display_cols[0]); + line[Settings.display_cols[0]] = 0; + len = strlen(txt); + offset = (len < Settings.display_cols[0]) ? offset = (Settings.display_cols[0] - len) / 2 : 0; + strncpy(line +offset, txt, len); + lcd->setCursor(0, row); + lcd->print(line); +} + void LcdPrintLogLine() { uint8_t last_row = Settings.display_rows -1; @@ -194,6 +188,8 @@ void LcdRefresh() // Every second } } +#endif // USE_DISPLAY_MODES1TO5 + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -214,13 +210,9 @@ boolean Xdsp01(byte function) case FUNC_DISPLAY_INIT: LcdInit(dsp_init); break; - case FUNC_DISPLAY_EVERY_SECOND: - LcdRefresh(); - break; case FUNC_DISPLAY_POWER: LcdDisplayOnOff(disp_power); break; - case FUNC_DISPLAY_CLEAR: lcd->clear(); break; @@ -248,6 +240,11 @@ boolean Xdsp01(byte function) break; // case FUNC_DISPLAY_ROTATION: // break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + LcdRefresh(); + break; +#endif // USE_DISPLAY_MODES1TO5 } } } diff --git a/sonoff/xdsp_02_ssd1306.ino b/sonoff/xdsp_02_ssd1306.ino index 1afc89ea8..fd32bba40 100644 --- a/sonoff/xdsp_02_ssd1306.ino +++ b/sonoff/xdsp_02_ssd1306.ino @@ -38,54 +38,14 @@ Adafruit_SSD1306 *oled; -char oled_screen_buffer[OLED_BUFFER_ROWS][OLED_BUFFER_COLS +1]; - uint8_t ssd1306_font_x = OLED_FONT_WIDTH; uint8_t ssd1306_font_y = OLED_FONT_HEIGTH; -void Ssd1306InitFull() -{ - oled->invertDisplay(false); - oled->clearDisplay(); - oled->setTextWrap(false); // Allow text to run off edges - oled->cp437(true); - - oled->setTextSize(Settings.display_size); - oled->setTextColor(WHITE); - oled->setCursor(0,0); - oled->display(); -} - -void Ssd1306Clear() -{ - oled->clearDisplay(); - oled->setCursor(0, 0); - oled->display(); -} - -void Ssd1306DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - if (!flag) { - oled->setCursor(x, y); - } else { - oled->setCursor((x-1) * ssd1306_font_x * Settings.display_size, (y-1) * ssd1306_font_y * Settings.display_size); - } - oled->println(str); -} - -void Ssd1306DisplayOnOff(uint8_t on) -{ - if (on) { - oled->ssd1306_command(SSD1306_DISPLAYON); - } else { - oled->ssd1306_command(SSD1306_DISPLAYOFF); - } -} - /*********************************************************************************************/ void Ssd1306InitMode() { + oled->setRotation(Settings.display_rotate); // 0 oled->invertDisplay(false); oled->clearDisplay(); oled->setTextWrap(false); // Allow text to run off edges @@ -130,6 +90,44 @@ void Ssd1306InitDriver() } } +void Ssd1306Clear() +{ + oled->clearDisplay(); + oled->setCursor(0, 0); + oled->display(); +} + +void Ssd1306DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + if (!flag) { + oled->setCursor(x, y); + } else { + oled->setCursor((x-1) * ssd1306_font_x * Settings.display_size, (y-1) * ssd1306_font_y * Settings.display_size); + } + oled->println(str); +} + +void Ssd1306DisplayOnOff(uint8_t on) +{ + if (on) { + oled->ssd1306_command(SSD1306_DISPLAYON); + } else { + oled->ssd1306_command(SSD1306_DISPLAYOFF); + } +} + +void Ssd1306OnOff() +{ + Ssd1306DisplayOnOff(disp_power); + oled->display(); +} + +/*********************************************************************************************/ + +#ifdef USE_DISPLAY_MODES1TO5 + +char oled_screen_buffer[OLED_BUFFER_ROWS][OLED_BUFFER_COLS +1]; + void Ssd1306PrintLogLine() { uint8_t last_row = Settings.display_rows -1; @@ -175,12 +173,6 @@ void Ssd1306PrintLog() } } -void Ssd1306OnOff() -{ - Ssd1306DisplayOnOff(disp_power); - oled->display(); -} - void Ssd1306Time() { char line[12]; @@ -212,6 +204,8 @@ void Ssd1306Refresh() // Every second } } +#endif // USE_DISPLAY_MODES1TO5 + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -235,9 +229,6 @@ boolean Xdsp02(byte function) case FUNC_DISPLAY_INIT: Ssd1306Init(dsp_init); break; - case FUNC_DISPLAY_EVERY_SECOND: - Ssd1306Refresh(); - break; case FUNC_DISPLAY_POWER: Ssd1306OnOff(); break; @@ -278,8 +269,13 @@ boolean Xdsp02(byte function) Ssd1306DisplayOnOff(dsp_on); break; case FUNC_DISPLAY_ROTATION: - oled->setRotation(dsp_rotation); + oled->setRotation(Settings.display_rotate); break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + Ssd1306Refresh(); + break; +#endif // USE_DISPLAY_MODES1TO5 } } } diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index 617ce498f..3785953c7 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -34,6 +34,10 @@ uint8_t mtx_counter = 0; int16_t mtx_x = 0; int16_t mtx_y = 0; +char mtx_buffer[80]; +uint8_t mtx_mode = 0; +uint8_t mtx_loop = 0; + /*********************************************************************************************/ void MatrixWrite() @@ -51,31 +55,6 @@ void MatrixClear() MatrixWrite(); } -/* -void MatrixAll() // On based on Text value (1 - 6) -{ - int value = atoi(Settings.text); - for (byte i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - if (i < value) { - matrix[i]->fillRect(0,0, 8,8, LED_ON); - } - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); -} - -void MatrixAllOn() -{ - for (byte i = 0; i < mtx_matrices; i++) { - matrix[i]->clear(); - matrix[i]->fillRect(0,0, 8,8, LED_ON); - matrix[i]->setBrightness(Settings.display_dimmer); - } - MatrixWrite(); -} -*/ - void MatrixFixed(char* txt) { for (byte i = 0; i < mtx_matrices; i++) { @@ -186,40 +165,12 @@ void MatrixScrollUp(char* txt, int loop) } } -void MatrixBufferScroll(uint8_t direction) -{ - if (disp_log_buffer_idx != disp_log_buffer_ptr) { - if (!mtx_state) { - mtx_state = 1; - } - - char *pch = strchr(disp_log_buffer[disp_log_buffer_ptr],'~'); // = 0x7E (~) Replace degrees character (276 octal) - if (pch != NULL) { - disp_log_buffer[disp_log_buffer_ptr][pch - disp_log_buffer[disp_log_buffer_ptr]] = '\370'; // = 0xF8 - } - - if (direction) { - MatrixScrollUp(disp_log_buffer[disp_log_buffer_ptr], 0); - } else { - MatrixScrollLeft(disp_log_buffer[disp_log_buffer_ptr], 0); - } - if (!mtx_state) { - DisplayLogBufferPtrInc(); - } - } else { - char disp_time[9]; // 13:45:43 - - snprintf_P(disp_time, sizeof(disp_time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); - MatrixFixed(disp_time); - } -} - /*********************************************************************************************/ void MatrixInitMode() { for (byte i = 0; i < mtx_matrices; i++) { - matrix[i]->setRotation(1); + matrix[i]->setRotation(Settings.display_rotate); // 1 matrix[i]->setBrightness(Settings.display_dimmer); matrix[i]->blinkRate(0); // 0 - 3 matrix[i]->setTextWrap(false); // Allow text to run off edges @@ -272,12 +223,64 @@ void MatrixOnOff() } } +void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + snprintf(mtx_buffer, sizeof(mtx_buffer), str); + mtx_mode = x; + mtx_loop = y; + if (!mtx_state) { mtx_state = 1; } +} + +/*********************************************************************************************/ + +#ifdef USE_DISPLAY_MODES1TO5 + +void MatrixBufferScroll(uint8_t direction) +{ + if (disp_log_buffer_idx != disp_log_buffer_ptr) { + if (!mtx_state) { + mtx_state = 1; + } + + char *pch = strchr(disp_log_buffer[disp_log_buffer_ptr],'~'); // = 0x7E (~) Replace degrees character (276 octal) + if (pch != NULL) { + disp_log_buffer[disp_log_buffer_ptr][pch - disp_log_buffer[disp_log_buffer_ptr]] = '\370'; // = 0xF8 + } + + if (direction) { + MatrixScrollUp(disp_log_buffer[disp_log_buffer_ptr], 0); + } else { + MatrixScrollLeft(disp_log_buffer[disp_log_buffer_ptr], 0); + } + if (!mtx_state) { + DisplayLogBufferPtrInc(); + } + } else { + char disp_time[9]; // 13:45:43 + + snprintf_P(disp_time, sizeof(disp_time), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d"), RtcTime.hour, RtcTime.minute, RtcTime.second); + MatrixFixed(disp_time); + } +} + +#endif // USE_DISPLAY_MODES1TO5 + void MatrixRefresh() // Every second { if (disp_power) { switch (Settings.display_mode) { - case 0: -// MatrixScrollLeft(Settings.text, Settings.loop); + case 0: { + switch (mtx_mode) { + case 0: + MatrixScrollLeft(mtx_buffer, mtx_loop); + break; + case 1: + MatrixScrollUp(mtx_buffer, mtx_loop); + break; + } + break; + } +#ifdef USE_DISPLAY_MODES1TO5 case 2: { char disp_date[9]; // 24-04-17 snprintf_P(disp_date, sizeof(disp_date), PSTR("%02d" D_MONTH_DAY_SEPARATOR "%02d" D_YEAR_MONTH_SEPARATOR "%02d"), RtcTime.day_of_month, RtcTime.month, RtcTime.year -2000); @@ -297,12 +300,7 @@ void MatrixRefresh() // Every second case 5: // Time, user text and MQTT MatrixBufferScroll(1); break; -// case 8: -// MatrixAllOn(); -// break; -// case 9: -// MatrixAll(); -// break; +#endif // USE_DISPLAY_MODES1TO5 } } } @@ -333,6 +331,9 @@ boolean Xdsp03(byte function) case FUNC_DISPLAY_POWER: MatrixOnOff(); break; + case FUNC_DISPLAY_DRAW_STRING: + MatrixDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag); + break; } } } diff --git a/sonoff/xdsp_04_ili9341.ino b/sonoff/xdsp_04_ili9341.ino index dd8360f03..105b29000 100644 --- a/sonoff/xdsp_04_ili9341.ino +++ b/sonoff/xdsp_04_ili9341.ino @@ -38,64 +38,9 @@ uint16_t tft_scroll; /*********************************************************************************************/ -void Ili9341Clear() -{ - tft->fillScreen(ILI9341_BLACK); - tft->setCursor(0, 0); -} - -void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) -{ - uint16_t active_color = ILI9341_WHITE; - - tft->setTextSize(Settings.display_size); - if (!flag) { - tft->setCursor(x, y); - } else { - tft->setCursor((x-1) * TFT_FONT_WIDTH * Settings.display_size, (y-1) * TFT_FONT_HEIGTH * Settings.display_size); - } - if (color) { active_color = color; } - tft->setTextColor(active_color, ILI9341_BLACK); - tft->println(str); -} - -void Ili9341DisplayOnOff(uint8_t on) -{ -// tft->showDisplay(on); -// tft->invertDisplay(on); - if (pin[GPIO_BACKLIGHT] < 99) { - pinMode(pin[GPIO_BACKLIGHT], OUTPUT); - digitalWrite(pin[GPIO_BACKLIGHT], on); - } -} - -/*********************************************************************************************/ - -void DisplayTftPrint(byte size, char *txt) -{ - uint16_t theight; - - tft->setCursor(0, tft_scroll); - tft->setTextSize(size); - theight = size * TFT_FONT_HEIGTH; - tft->fillRect(0, tft_scroll, tft->width(), theight, ILI9341_BLACK); - - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "[%s]"), txt); - AddLog(LOG_LEVEL_DEBUG); - - tft->print(txt); - tft_scroll += theight; - if (tft_scroll >= (tft->height() - TFT_BOTTOM)) { - tft_scroll = TFT_TOP; - } - tft->setScrollStart(tft_scroll); -} - -/*********************************************************************************************/ - void Ili9341InitMode() { - tft->setRotation(0); + tft->setRotation(Settings.display_rotate); // 0 tft->invertDisplay(0); tft->fillScreen(ILI9341_BLACK); tft->setTextWrap(false); // Allow text to run off edges @@ -141,6 +86,46 @@ void Ili9341InitDriver() } } +void Ili9341Clear() +{ + tft->fillScreen(ILI9341_BLACK); + tft->setCursor(0, 0); +} + +void Ili9341DrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag) +{ + uint16_t active_color = ILI9341_WHITE; + + tft->setTextSize(Settings.display_size); + if (!flag) { + tft->setCursor(x, y); + } else { + tft->setCursor((x-1) * TFT_FONT_WIDTH * Settings.display_size, (y-1) * TFT_FONT_HEIGTH * Settings.display_size); + } + if (color) { active_color = color; } + tft->setTextColor(active_color, ILI9341_BLACK); + tft->println(str); +} + +void Ili9341DisplayOnOff(uint8_t on) +{ +// tft->showDisplay(on); +// tft->invertDisplay(on); + if (pin[GPIO_BACKLIGHT] < 99) { + pinMode(pin[GPIO_BACKLIGHT], OUTPUT); + digitalWrite(pin[GPIO_BACKLIGHT], on); + } +} + +void Ili9341OnOff() +{ + Ili9341DisplayOnOff(disp_power); +} + +/*********************************************************************************************/ + +#ifdef USE_DISPLAY_MODES1TO5 + void Ili9341PrintLogLine() { tft->setTextColor(ILI9341_CYAN, ILI9341_BLACK); // Add background color to solve flicker @@ -179,11 +164,6 @@ void Ili9341PrintLog() } } -void Ili9341OnOff() -{ - Ili9341DisplayOnOff(disp_power); -} - void Ili9341Refresh() // Every second { if (Settings.display_mode) { // Mode 0 is User text @@ -211,6 +191,8 @@ void Ili9341Refresh() // Every second } } +#endif // USE_DISPLAY_MODES1TO5 + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -234,9 +216,6 @@ boolean Xdsp04(byte function) case FUNC_DISPLAY_INIT: Ili9341Init(dsp_init); break; - case FUNC_DISPLAY_EVERY_SECOND: - Ili9341Refresh(); - break; case FUNC_DISPLAY_POWER: Ili9341OnOff(); break; @@ -277,8 +256,13 @@ boolean Xdsp04(byte function) Ili9341DisplayOnOff(dsp_on); break; case FUNC_DISPLAY_ROTATION: - tft->setRotation(dsp_rotation); + tft->setRotation(Settings.display_rotate); break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + Ili9341Refresh(); + break; +#endif // USE_DISPLAY_MODES1TO5 } } } diff --git a/sonoff/xdsp_05_epaper.ino b/sonoff/xdsp_05_epaper.ino index 9e4acafc2..a28005f8a 100644 --- a/sonoff/xdsp_05_epaper.ino +++ b/sonoff/xdsp_05_epaper.ino @@ -60,9 +60,9 @@ void EpdInitMode() selected_font = &Font12; + paint.SetRotate(Settings.display_rotate); /* // Welcome text - paint.SetRotate(ROTATE_90); paint.Clear(UNCOLORED); paint.DrawStringAt(50, 50, "Waveshare E-Paper Display!", selected_font, COLORED); epd.SetFrameMemory(paint.GetImage(), 0, 0, paint.GetWidth(), paint.GetHeight()); @@ -163,6 +163,10 @@ void EpdOnOff() EpdDisplayOnOff(disp_power); } +/*********************************************************************************************/ + +#ifdef USE_DISPLAY_MODES1TO5 + void EpdRefresh() // Every second { if (Settings.display_mode) { // Mode 0 is User text @@ -170,6 +174,8 @@ void EpdRefresh() // Every second } } +#endif // USE_DISPLAY_MODES1TO5 + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -193,9 +199,6 @@ boolean Xdsp05(byte function) case FUNC_DISPLAY_INIT: EpdInit(dsp_init); break; - case FUNC_DISPLAY_EVERY_SECOND: - EpdRefresh(); - break; case FUNC_DISPLAY_POWER: EpdOnOff(); break; @@ -237,8 +240,13 @@ boolean Xdsp05(byte function) EpdDisplayOnOff(dsp_on); break; case FUNC_DISPLAY_ROTATION: - paint.SetRotate(dsp_rotation); + paint.SetRotate(Settings.display_rotate); break; +#ifdef USE_DISPLAY_MODES1TO5 + case FUNC_DISPLAY_EVERY_SECOND: + EpdRefresh(); + break; +#endif // USE_DISPLAY_MODES1TO5 } } }