diff --git a/firmware/lib/cw-commons/CWPreferences.h b/firmware/lib/cw-commons/CWPreferences.h index 6a464ff..fadc4ab 100644 --- a/firmware/lib/cw-commons/CWPreferences.h +++ b/firmware/lib/cw-commons/CWPreferences.h @@ -12,6 +12,7 @@ struct ClockwiseParams Preferences preferences; const char* const PREF_SWAP_BLUE_GREEN = "swapBlueGreen"; + const char* const PREF_SWAP_BLUE_RED = "swapBlueRed"; const char* const PREF_USE_24H_FORMAT = "use24hFormat"; const char* const PREF_DISPLAY_BRIGHT = "displayBright"; const char* const PREF_DISPLAY_ABC_MIN = "autoBrightMin"; @@ -25,8 +26,12 @@ struct ClockwiseParams const char* const PREF_CANVAS_SERVER = "canvasServer"; const char* const PREF_MANUAL_POSIX = "manualPosix"; const char* const PREF_DISPLAY_ROTATION = "displayRotation"; + const char* const PREF_DRIVER = "driver"; + const char* const PREF_I2CSPEED = "i2cSpeed"; + const char* const PREF_E_PIN = "E_pin"; bool swapBlueGreen; + bool swapBlueRed; bool use24hFormat; uint8_t displayBright; uint16_t autoBrightMin; @@ -40,7 +45,9 @@ struct ClockwiseParams String canvasServer; String manualPosix; uint8_t displayRotation; - + uint8_t driver; + uint32_t i2cSpeed; + uint8_t E_pin; ClockwiseParams() { preferences.begin("clockwise", false); @@ -56,6 +63,7 @@ struct ClockwiseParams void save() { preferences.putBool(PREF_SWAP_BLUE_GREEN, swapBlueGreen); + preferences.putBool(PREF_SWAP_BLUE_RED, swapBlueRed); preferences.putBool(PREF_USE_24H_FORMAT, use24hFormat); preferences.putUInt(PREF_DISPLAY_BRIGHT, displayBright); preferences.putUInt(PREF_DISPLAY_ABC_MIN, autoBrightMin); @@ -69,11 +77,15 @@ struct ClockwiseParams preferences.putString(PREF_CANVAS_SERVER, canvasServer); preferences.putString(PREF_MANUAL_POSIX, manualPosix); preferences.putUInt(PREF_DISPLAY_ROTATION, displayRotation); + preferences.putUInt(PREF_DRIVER, driver); + preferences.putUInt(PREF_I2CSPEED, i2cSpeed); + preferences.putUInt(PREF_E_PIN, E_pin); } void load() { swapBlueGreen = preferences.getBool(PREF_SWAP_BLUE_GREEN, false); + swapBlueRed = preferences.getBool(PREF_SWAP_BLUE_RED, false); use24hFormat = preferences.getBool(PREF_USE_24H_FORMAT, true); displayBright = preferences.getUInt(PREF_DISPLAY_BRIGHT, 32); autoBrightMin = preferences.getUInt(PREF_DISPLAY_ABC_MIN, 0); @@ -87,6 +99,9 @@ struct ClockwiseParams canvasServer = preferences.getString(PREF_CANVAS_SERVER, "raw.githubusercontent.com"); manualPosix = preferences.getString(PREF_MANUAL_POSIX, ""); displayRotation = preferences.getUInt(PREF_DISPLAY_ROTATION, 0); + driver = preferences.getUInt(PREF_DRIVER, 0); + i2cSpeed = preferences.getUInt(PREF_I2CSPEED, (uint32_t)8000000); + E_pin = preferences.getUInt(PREF_E_PIN, 18); } }; diff --git a/firmware/lib/cw-commons/CWWebServer.h b/firmware/lib/cw-commons/CWWebServer.h index 8eebdee..fa80bc0 100644 --- a/firmware/lib/cw-commons/CWWebServer.h +++ b/firmware/lib/cw-commons/CWWebServer.h @@ -111,6 +111,8 @@ struct ClockwiseWebServer ClockwiseParams::getInstance()->autoBrightMax = value.substring(5,9).toInt(); } else if (key == ClockwiseParams::getInstance()->PREF_SWAP_BLUE_GREEN) { ClockwiseParams::getInstance()->swapBlueGreen = (value == "1"); + } else if (key == ClockwiseParams::getInstance()->PREF_SWAP_BLUE_RED) { + ClockwiseParams::getInstance()->swapBlueRed = (value == "1"); } else if (key == ClockwiseParams::getInstance()->PREF_USE_24H_FORMAT) { ClockwiseParams::getInstance()->use24hFormat = (value == "1"); } else if (key == ClockwiseParams::getInstance()->PREF_LDR_PIN) { @@ -127,6 +129,12 @@ struct ClockwiseWebServer ClockwiseParams::getInstance()->manualPosix = value; } else if (key == ClockwiseParams::getInstance()->PREF_DISPLAY_ROTATION) { ClockwiseParams::getInstance()->displayRotation = value.toInt(); + } else if (key == ClockwiseParams::getInstance()->PREF_DRIVER) { + ClockwiseParams::getInstance()->driver = value.toInt(); + } else if (key == ClockwiseParams::getInstance()->PREF_I2CSPEED) { + ClockwiseParams::getInstance()->i2cSpeed = value.toInt(); + } else if (key == ClockwiseParams::getInstance()->PREF_E_PIN) { + ClockwiseParams::getInstance()->E_pin = value.toInt(); } ClockwiseParams::getInstance()->save(); client.println("HTTP/1.0 204 No Content"); @@ -154,6 +162,7 @@ struct ClockwiseWebServer client.printf(HEADER_TEMPLATE_D, ClockwiseParams::getInstance()->PREF_DISPLAY_ABC_MIN, ClockwiseParams::getInstance()->autoBrightMin); client.printf(HEADER_TEMPLATE_D, ClockwiseParams::getInstance()->PREF_DISPLAY_ABC_MAX, ClockwiseParams::getInstance()->autoBrightMax); client.printf(HEADER_TEMPLATE_D, ClockwiseParams::getInstance()->PREF_SWAP_BLUE_GREEN, ClockwiseParams::getInstance()->swapBlueGreen); + client.printf(HEADER_TEMPLATE_D, ClockwiseParams::getInstance()->PREF_SWAP_BLUE_RED, ClockwiseParams::getInstance()->swapBlueRed); client.printf(HEADER_TEMPLATE_D, ClockwiseParams::getInstance()->PREF_USE_24H_FORMAT, ClockwiseParams::getInstance()->use24hFormat); client.printf(HEADER_TEMPLATE_D, ClockwiseParams::getInstance()->PREF_LDR_PIN, ClockwiseParams::getInstance()->ldrPin); client.printf(HEADER_TEMPLATE_S, ClockwiseParams::getInstance()->PREF_TIME_ZONE, ClockwiseParams::getInstance()->timeZone.c_str()); @@ -163,6 +172,9 @@ struct ClockwiseWebServer client.printf(HEADER_TEMPLATE_S, ClockwiseParams::getInstance()->PREF_CANVAS_SERVER, ClockwiseParams::getInstance()->canvasServer.c_str()); client.printf(HEADER_TEMPLATE_S, ClockwiseParams::getInstance()->PREF_MANUAL_POSIX, ClockwiseParams::getInstance()->manualPosix.c_str()); client.printf(HEADER_TEMPLATE_D, ClockwiseParams::getInstance()->PREF_DISPLAY_ROTATION, ClockwiseParams::getInstance()->displayRotation); + client.printf(HEADER_TEMPLATE_D, ClockwiseParams::getInstance()->PREF_DRIVER, ClockwiseParams::getInstance()->driver); + client.printf(HEADER_TEMPLATE_D, ClockwiseParams::getInstance()->PREF_I2CSPEED, ClockwiseParams::getInstance()->i2cSpeed); + client.printf(HEADER_TEMPLATE_D, ClockwiseParams::getInstance()->PREF_E_PIN, ClockwiseParams::getInstance()->E_pin); client.printf(HEADER_TEMPLATE_S, "CW_FW_VERSION", CW_FW_VERSION); client.printf(HEADER_TEMPLATE_S, "CW_FW_NAME", CW_FW_NAME); diff --git a/firmware/lib/cw-commons/SettingsWebPage.h b/firmware/lib/cw-commons/SettingsWebPage.h index 7a42c3f..503ba18 100644 --- a/firmware/lib/cw-commons/SettingsWebPage.h +++ b/firmware/lib/cw-commons/SettingsWebPage.h @@ -77,6 +77,14 @@ const char SETTINGS_PAGE[] PROGMEM = R""""( save: "updatePreference('swapBlueGreen', Number(swapBG.checked))", property: "swapBlueGreen" }, + { + title: "Swap Blue/Red pins?", + description: "Swap Blue and Red pins", + formInput: "", + icon: "fa-random", + save: "updatePreference('swapBlueRed', Number(swapBR.checked))", + property: "swapBlueRed" + }, { title: "Timezone", description: "Consult your TZ identifier here. Examples: America/Sao_Paulo, Europe/Lisbon", @@ -143,7 +151,31 @@ const char SETTINGS_PAGE[] PROGMEM = R""""( icon: "fa-rotate-right", save: "updatePreference('displayRotation', rotation.value)", property: "displayRotation" - } + }, + { + title: "Matrix Shift Driver", + description: "Hardware-specific chips used to drive matrix modules (default: SHIFTREG).", + formInput: "", + icon: "fa-microchip", + save: "updatePreference('driver', driver.value)", + property: "driver" + }, + { + title: "I2C Speed", + description: "I2S clock speed selector (default: HZ_8M).", + formInput: "", + save: "updatePreference('i2cSpeed', speed.value)", + icon: "fa-microchip", + property: "i2cSpeed" + }, + { + title: "E Pin", + description: "E pin is Address Line E used for 64-row LED panels to select specific rows (default: 18).", + formInput: "", + icon: "fa-microchip", + save: "updatePreference('E_pin', E_pin.value)", + property: "E_pin" + } ]; var base = document.querySelector('#base'); @@ -229,7 +261,7 @@ const char SETTINGS_PAGE[] PROGMEM = R""""( } //Local - //createCards({ "displayBright": 30, "swapBlueGreen": 1, "use24hFormat": 0, "timeZone": "Europe/Lisbon", "ntpServer": "pool.ntp.org", "wifiSsid": "test", "autoBrightMin":0, "autoBrightMax":800, "ldrPin":35, "cw_fw_version":"1.2.2", "clockface_name":"cw-cf-0x07", "canvasServer":"raw.githubusercontent.com", "canvasFile":"star-wars.json" }); + //createCards({ "displayBright": 30, "swapBlueGreen": 1, "swapBlueRed": 0, "use24hFormat": 0, "timeZone": "Europe/Lisbon", "ntpServer": "pool.ntp.org", "wifiSsid": "test", "autoBrightMin":0, "autoBrightMax":800, "ldrPin":35, "driver":1, "i2cspeed":16000000, "e_pin":18, "cw_fw_version":"1.2.2", "clockface_name":"cw-cf-0x07", "canvasServer":"raw.githubusercontent.com", "canvasFile":"star-wars.json" }); //Embedded begin(); diff --git a/firmware/src/main.cpp b/firmware/src/main.cpp index 61ca80d..6aeb2c9 100644 --- a/firmware/src/main.cpp +++ b/firmware/src/main.cpp @@ -26,7 +26,17 @@ bool autoBrightEnabled; long autoBrightMillis = 0; uint8_t currentBrightSlot = -1; -void displaySetup(bool swapBlueGreen, uint8_t displayBright, uint8_t displayRotation) +bool isValidI2SSpeed(uint32_t speed) { + return speed == 8000000 || speed == 16000000 || speed == 20000000; +} + +bool isValidDriver(uint32_t drv) { + return drv >= 0 && drv <= 5; +} + + + +void displaySetup(bool swapBlueGreen, bool swapBlueRed, uint8_t displayBright, uint8_t displayRotation, uint8_t driver, uint32_t i2cSpeed, uint8_t E_pin) { HUB75_I2S_CFG mxconfig(64, 64, 1); @@ -39,9 +49,29 @@ void displaySetup(bool swapBlueGreen, uint8_t displayBright, uint8_t displayRota mxconfig.gpio.g2 = 13; } - mxconfig.gpio.e = 18; + if (swapBlueRed) + { + // Swap Blue and Red pins. + mxconfig.gpio.b1 = 25; + mxconfig.gpio.b2 = 14; + mxconfig.gpio.r1 = 27; + mxconfig.gpio.r2 = 13; + } + + mxconfig.gpio.e = E_pin; mxconfig.clkphase = false; + if (isValidDriver(driver)) { + mxconfig.driver = static_cast(driver); + } else { + Serial.printf("[ERROR] Invalid driver from config:%d\n", driver); + } + if (isValidI2SSpeed(i2cSpeed)) { + mxconfig.i2sspeed = static_cast(i2cSpeed); + } else { + Serial.printf("[ERROR] Invalid I2S speed from config:%d\n", i2cSpeed); + } + // Display Setup dma_display = new MatrixPanel_I2S_DMA(mxconfig); dma_display->begin(); @@ -89,7 +119,11 @@ void setup() pinMode(ClockwiseParams::getInstance()->ldrPin, INPUT); - displaySetup(ClockwiseParams::getInstance()->swapBlueGreen, ClockwiseParams::getInstance()->displayBright, ClockwiseParams::getInstance()->displayRotation); + uint8_t driver = ClockwiseParams::getInstance()->driver; + uint32_t i2cSpeed = ClockwiseParams::getInstance()->i2cSpeed; + uint8_t E_pin = ClockwiseParams::getInstance()->E_pin; + + displaySetup(ClockwiseParams::getInstance()->swapBlueGreen, ClockwiseParams::getInstance()->swapBlueRed, ClockwiseParams::getInstance()->displayBright, ClockwiseParams::getInstance()->displayRotation, driver, i2cSpeed, E_pin); clockface = new Clockface(dma_display); autoBrightEnabled = (ClockwiseParams::getInstance()->autoBrightMax > 0);