Skip to content
Merged
55 changes: 3 additions & 52 deletions include/config/ConfigManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,17 @@
#include "config/SecureStorage.h"
#include <string>
#include <cstdint>
#include <SPI.h>

// LCD configuration defaults for hellocubic lite
static constexpr bool LCD_ENABLE = true;
static constexpr int16_t LCD_W = 240;
static constexpr int16_t LCD_H = 240;
static constexpr uint8_t LCD_ROTATION = 4;
static constexpr int8_t LCD_MOSI_GPIO = 13;
static constexpr int8_t LCD_SCK_GPIO = 14;
static constexpr int8_t LCD_CS_GPIO = 2;
static constexpr int8_t LCD_DC_GPIO = 0;
static constexpr int8_t LCD_RST_GPIO = 15;
static constexpr bool LCD_CS_ACTIVE_HIGH = true;
static constexpr bool LCD_DC_CMD_HIGH = false;
static constexpr uint8_t LCD_SPI_MODE = 0;
static constexpr int8_t LCD_RST_GPIO = 2;
static constexpr uint8_t LCD_SPI_MODE = SPI_MODE3;
static constexpr uint32_t LCD_SPI_HZ = 40000000;
static constexpr int8_t LCD_BACKLIGHT_GPIO = 5;
static constexpr bool LCD_BACKLIGHT_ACTIVE_LOW = true;
Expand All @@ -50,63 +47,17 @@ class ConfigManager {
void setWiFi(const char* newSsid, const char* newPassword);
const char* getSSID() const;
const char* getPassword() const;
bool getLCDEnable() const;
int16_t getLCDWidth() const;
int16_t getLCDHeight() const;
uint8_t getLCDRotation() const;
int8_t getLCDMosiGpio() const;
int8_t getLCDSckGpio() const;
int8_t getLCDCsGpio() const;
int8_t getLCDDcGpio() const;
int8_t getLCDRstGpio() const;
bool getLCDCsActiveHigh() const;
bool getLCDDcCmdHigh() const;
uint8_t getLCDSpiMode() const;
bool getLCDKeepCsAsserted() const;
uint32_t getLCDSpiHz() const;
int8_t getLCDBacklightGpio() const;
bool getLCDBacklightActiveLow() const;
bool migrateWiFiToSecureStorage(String ssid, String password);

public:
bool getLCDEnableSafe() const { return lcd_enable; }
int16_t getLCDWidthSafe() const { return (lcd_w > 0) ? lcd_w : LCD_W; }
int16_t getLCDHeightSafe() const { return (lcd_h > 0) ? lcd_h : LCD_H; }
uint8_t getLCDRotationSafe() const { return lcd_rotation; }
int8_t getLCDMosiGpioSafe() const { return (lcd_mosi_gpio >= 0) ? lcd_mosi_gpio : LCD_MOSI_GPIO; }
int8_t getLCDSckGpioSafe() const { return (lcd_sck_gpio >= 0) ? lcd_sck_gpio : LCD_SCK_GPIO; }
int8_t getLCDCsGpioSafe() const { return (lcd_cs_gpio >= 0) ? lcd_cs_gpio : LCD_CS_GPIO; }
int8_t getLCDDcGpioSafe() const { return (lcd_dc_gpio >= 0) ? lcd_dc_gpio : LCD_DC_GPIO; }
int8_t getLCDRstGpioSafe() const { return (lcd_rst_gpio >= 0) ? lcd_rst_gpio : LCD_RST_GPIO; }
bool getLCDCsActiveHighSafe() const { return lcd_cs_active_high; }
bool getLCDDcCmdHighSafe() const { return lcd_dc_cmd_high; }
uint8_t getLCDSpiModeSafe() const { return lcd_spi_mode; }
bool getLCDKeepCsAssertedSafe() const { return lcd_keep_cs_asserted; }
uint32_t getLCDSpiHzSafe() const { return (lcd_spi_hz > 0) ? lcd_spi_hz : LCD_SPI_HZ; }
int8_t getLCDBacklightGpioSafe() const {
return (lcd_backlight_gpio >= 0) ? lcd_backlight_gpio : LCD_BACKLIGHT_GPIO;
}
bool getLCDBacklightActiveLowSafe() const { return lcd_backlight_active_low; }
std::string ssid;
std::string password;
std::string filename;
SecureStorage secure;
bool lcd_enable = true;
int16_t lcd_w = 240;
int16_t lcd_h = 240;
uint8_t lcd_rotation = 4;
int8_t lcd_mosi_gpio = 13;
int8_t lcd_sck_gpio = 14;
int8_t lcd_cs_gpio = 2;
int8_t lcd_dc_gpio = 0;
int8_t lcd_rst_gpio = 15;
bool lcd_cs_active_high = true;
bool lcd_dc_cmd_high = false;
uint8_t lcd_spi_mode = 0;
bool lcd_keep_cs_asserted = true;
uint32_t lcd_spi_hz = 40000000;
int8_t lcd_backlight_gpio = 5;
bool lcd_backlight_active_low = true;
};

#endif // CONFIG_MANAGER_H
2 changes: 0 additions & 2 deletions include/display/DisplayManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ static constexpr int THREE_LINES_SPACE = 60;
class DisplayManager {
public:
static void begin();
static bool isReady();
static void ensureInit();
static Arduino_GFX* getGfx();
static void drawStartup(String currentIP);
static void drawTextWrapped(int16_t xPos, int16_t yPos, const String& text, uint8_t textSize, uint16_t fgColor,
Expand Down
65 changes: 0 additions & 65 deletions include/display/GeekMagicSPIBus.h

This file was deleted.

29 changes: 12 additions & 17 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
- **Resolution**: 240x240 pixels
- **Color Format**: RGB565 (16-bit color)
- **Interface**: SPI (Serial Peripheral Interface)
- **SPI Speed**: up to 80 MHz (40 MHz is more stable)
- **SPI Speed**: 40 MHz (80 MHz is possible, but unstable and outside datasheet spec)
- **Rotation**: Upside-down for cube display, normal for the small tv

### Pin wiring
Expand All @@ -83,9 +83,9 @@ The display is connected to the ESP8266 using the following GPIO pins:
| ------------- | -------- | ----------------------------------------------------- |
| **MOSI** | GPIO 13 | SPI Master Out Slave In (data from ESP8266 to screen) |
| **SCK** | GPIO 14 | SPI Clock |
| **CS** | GPIO 2 | Chip Select (Active HIGH) |
| **CS** | GND | Chip Select, tied permanently to GND |
| **DC** | GPIO 0 | Data/Command select (LOW=command, HIGH=data) |
| **RST** | GPIO 15 | Reset pin |
| **RST** | GPIO 2 | Reset pin |
| **Backlight** | GPIO 5 | Backlight control (Active LOW) |

<div align="center">
Expand All @@ -96,9 +96,9 @@ The display is connected to the ESP8266 using the following GPIO pins:

### Important configuration details

**Chip select (CS) polarity**: This board uses **active-high** CS, which is non-standard. Most SPI displays use active-low CS. The CS pin must be driven HIGH to select the display
**Chip select (CS) polarity**: This board ties CS of the display permanently to GND.

**SPI mode**: SPI Mode 0 (CPOL=0, CPHA=0)
**SPI mode**: SPI Mode 3 (CPOL=1, CPHA=1)

**Data/command pin**: LOW for commands, HIGH for data

Expand All @@ -109,8 +109,8 @@ The display is connected to the ESP8266 using the following GPIO pins:
### Initialization sequence

1. **Backlight control**: GPIO 5 is set as output and driven LOW to turn on the backlight
2. **Hardware reset**: The RST pin (GPIO 15) is toggled to reset the ST7789 controller
3. **SPI bus setup**: Hardware SPI is initialized with 80 MHz clock speed and Mode 0
2. **Hardware reset**: The RST pin (GPIO 2) is toggled to reset the ST7789 controller
3. **SPI bus setup**: Hardware SPI is initialized with 40 MHz clock speed and Mode 3
4. **Display controller init**: The ST7789 is configured using a vendor-specific initialization sequence that includes:
- Sleep out (0x11)
- Porch settings (0xB2)
Expand All @@ -128,19 +128,15 @@ The display is connected to the ESP8266 using the following GPIO pins:

The display uses **SPI** protocol for communication:

1. **Chip select**: CS is driven HIGH to select the display
2. **Command/data mode**: The DC pin indicates whether the data on MOSI is a command (DC=LOW) or pixel data (DC=HIGH)
3. **Data transfer**: Data is shifted out on the MOSI pin, synchronized with the SCK clock signal
4. **Chip deselect**: CS can be kept HIGH during continuous operations for better performance, or dropped LOW between operations
1. **Command/data mode**: The DC pin indicates whether the data on MOSI is a command (DC=LOW) or pixel data (DC=HIGH)
2. **Data transfer**: Data is shifted out on the MOSI pin, synchronized with the SCK clock signal

### Drawing to the screen

The firmware uses the Arduino_GFX library with a custom ESP8266SPIWithCustomCS bus driver that handles the active-high CS polarity. Graphics operations:

1. **Begin write**: Assert CS (set HIGH)
2. **Write commands**: Set DC LOW, send command bytes via SPI
3. **Write data**: Set DC HIGH, send pixel data via SPI
4. **End write**: Optionally deassert CS (set LOW) - can be kept asserted for continuous operations
1. **Write commands**: Set DC LOW, send command bytes via SPI
2. **Write data**: Set DC HIGH, send pixel data via SPI

### Color format

Expand All @@ -160,8 +156,7 @@ Example colors:

### Performance optimizations

- **High SPI speed**: 80 MHz clock for fast data transfer
- **CS kept asserted**: During continuous operations, CS stays HIGH to reduce overhead
- **High SPI speed**: 40 MHz clock for fast data transfer
- **Hardware SPI**: Uses ESP8266's hardware SPI peripheral for efficient transfers
- **Batch writes**: Multiple operations are batched between beginWrite/endWrite calls
- **Direct frame buffer writes**: GIF frames are streamed directly to avoid intermediate buffering
Expand Down
117 changes: 0 additions & 117 deletions src/config/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,7 @@ auto ConfigManager::load() -> bool {
String ssid = doc["wifi_ssid"] | "";
String password = doc["wifi_password"] | "";

this->lcd_enable = doc["lcd_enable"] | lcd_enable;
this->lcd_w = doc["lcd_w"] | lcd_w;
this->lcd_h = doc["lcd_h"] | lcd_h;
this->lcd_rotation = doc["lcd_rotation"] | lcd_rotation;
this->lcd_mosi_gpio = doc["lcd_mosi_gpio"] | lcd_mosi_gpio;
this->lcd_sck_gpio = doc["lcd_sck_gpio"] | lcd_sck_gpio;
this->lcd_cs_gpio = doc["lcd_cs_gpio"] | lcd_cs_gpio;
this->lcd_dc_gpio = doc["lcd_dc_gpio"] | lcd_dc_gpio;
this->lcd_rst_gpio = doc["lcd_rst_gpio"] | lcd_rst_gpio;
this->lcd_cs_active_high = doc["lcd_cs_active_high"] | lcd_cs_active_high;
this->lcd_dc_cmd_high = doc["lcd_dc_cmd_high"] | lcd_dc_cmd_high;
this->lcd_spi_mode = doc["lcd_spi_mode"] | lcd_spi_mode;
this->lcd_keep_cs_asserted = doc["lcd_keep_cs_asserted"] | lcd_keep_cs_asserted;
this->lcd_spi_hz = doc["lcd_spi_hz"] | lcd_spi_hz;
this->lcd_backlight_gpio = doc["lcd_backlight_gpio"] | lcd_backlight_gpio;
this->lcd_backlight_active_low = doc["lcd_backlight_active_low"] | lcd_backlight_active_low;

String nvs_ssid = secure.get("wifi_ssid", "");
String nvs_password = secure.get("wifi_password", "");
Expand Down Expand Up @@ -118,115 +103,13 @@ auto ConfigManager::getSSID() const -> const char* { return ssid.c_str(); }
*/
auto ConfigManager::getPassword() const -> const char* { return password.c_str(); }

/**
* @brief Returns the current status of the LCD enable flag
*
* @return true if the LCD is enabled false otherwise
*/
auto ConfigManager::getLCDEnable() const -> bool { return lcd_enable; }

/**
* @brief Retrieves the LCD width
*
* @return The width of the LCD in pixels
*/
auto ConfigManager::getLCDWidth() const -> int16_t { return lcd_w; }
/**
* @brief Retrieves the LCD height
*
* @return The height of the LCD in pixels
*/
auto ConfigManager::getLCDHeight() const -> int16_t { return lcd_h; }
/**
* @brief Retrieves the LCD rotation setting
*
* @return The rotation of the LCD
*/
auto ConfigManager::getLCDRotation() const -> uint8_t { return lcd_rotation; }

/**
* @brief Retrieves the GPIO pin number for LCD MOSI
*
* @return The GPIO pin number for LCD MOSI
*/
auto ConfigManager::getLCDMosiGpio() const -> int8_t { return lcd_mosi_gpio; }

/**
* @brief Retrieves the GPIO pin number for LCD SCK
*
* @return The GPIO pin number for LCD SCK
*/
auto ConfigManager::getLCDSckGpio() const -> int8_t { return lcd_sck_gpio; }

/**
* @brief Retrieves the GPIO pin number for LCD CS
*
* @return The GPIO pin number for LCD CS
*/
auto ConfigManager::getLCDCsGpio() const -> int8_t { return lcd_cs_gpio; }

/**
* @brief Retrieves the GPIO pin number for LCD DC
*
* @return The GPIO pin number for LCD DC
*/
auto ConfigManager::getLCDDcGpio() const -> int8_t { return lcd_dc_gpio; }

/**
* @brief Retrieves the GPIO pin number for LCD RST
*
* @return The GPIO pin number for LCD RST
*/
auto ConfigManager::getLCDRstGpio() const -> int8_t { return lcd_rst_gpio; }

/**
* @brief Returns whether the LCD CS pin is active high
*
* @return true if the LCD CS pin is active high false otherwise
*/
auto ConfigManager::getLCDCsActiveHigh() const -> bool { return lcd_cs_active_high; }
/**
* @brief Returns whether the LCD DC pin is command high
*
* @return true if the LCD DC pin is command high false otherwise
*/
auto ConfigManager::getLCDDcCmdHigh() const -> bool { return lcd_dc_cmd_high; }

/**
* @brief Retrieves the LCD SPI mode
*
* @return The SPI mode of the LCD
*/
auto ConfigManager::getLCDSpiMode() const -> uint8_t { return lcd_spi_mode; }

/**
* @brief Returns whether the LCD CS pin is kept asserted
*
* @return true if the LCD CS pin is kept asserted false otherwise
*/
auto ConfigManager::getLCDKeepCsAsserted() const -> bool { return lcd_keep_cs_asserted; }

/**
* @brief Retrieves the SPI clock frequency for the LCD
*
* @return The SPI clock frequency in Hz
*/
auto ConfigManager::getLCDSpiHz() const -> uint32_t { return lcd_spi_hz; }

/**
* @brief Retrieves the GPIO pin number for the LCD backlight
*
* @return The GPIO pin number for the LCD backlight
*/
auto ConfigManager::getLCDBacklightGpio() const -> int8_t { return lcd_backlight_gpio; }

/**
* @brief Returns whether the LCD backlight pin is active low
*
* @return true if the LCD backlight pin is active low false otherwise
*/
auto ConfigManager::getLCDBacklightActiveLow() const -> bool { return lcd_backlight_active_low; }

/**
* @brief Set WiFi credentials in memory
* @param newSsid The SSID
Expand Down
Loading