diff --git a/src/SplitFlapDisplay.cpp b/src/SplitFlapDisplay.cpp index ebe0fe2..6f0b668 100644 --- a/src/SplitFlapDisplay.cpp +++ b/src/SplitFlapDisplay.cpp @@ -13,6 +13,7 @@ void SplitFlapDisplay::init() { magnetPosition = settings.getInt("magnetPosition"); maxVel = settings.getFloat("maxVel"); charSetSize = settings.getInt("charset"); + String customCharsetString = settings.getString("custom_charset"); std::vector settingAddresses = settings.getIntVector("moduleAddresses"); for (int i = 0; i < numModules; i++) { @@ -33,7 +34,12 @@ void SplitFlapDisplay::init() { for (uint8_t i = 0; i < numModules; i++) { modules[i] = SplitFlapModule( - moduleAddresses[i], stepsPerRot, moduleOffsets[i] + displayOffset, magnetPosition, charSetSize + moduleAddresses[i], + stepsPerRot, + moduleOffsets[i] + displayOffset, + magnetPosition, + charSetSize, + customCharsetString ); } diff --git a/src/SplitFlapDisplay.ino b/src/SplitFlapDisplay.ino index c8cb9ae..a3c2934 100644 --- a/src/SplitFlapDisplay.ino +++ b/src/SplitFlapDisplay.ino @@ -39,7 +39,8 @@ JsonSettings settings = JsonSettings("config", { {"sclPin", JsonSetting(9)}, {"stepsPerRot", JsonSetting(2048)}, {"maxVel", JsonSetting(15.0f)}, - {"charset", JsonSetting(37)}, + {"charset", JsonSetting(48)}, + {"custom_charset", JsonSetting(" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789':?!.-/@$#%")}, // Operational States {"mode", JsonSetting(0)} }); diff --git a/src/SplitFlapModule.cpp b/src/SplitFlapModule.cpp index bd7fc25..71bca99 100644 --- a/src/SplitFlapModule.cpp +++ b/src/SplitFlapModule.cpp @@ -15,20 +15,44 @@ const char SplitFlapModule::ExtendedChars[48] = { bool hasErrored = false; // Default Constructor -SplitFlapModule::SplitFlapModule() - : address(0), position(0), stepNumber(0), stepsPerRot(0), chars(StandardChars), numChars(37), charSetSize(37) { +SplitFlapModule::SplitFlapModule() : SplitFlapModule(0x20, 2048, 0, 710, 37, String()) { magnetPosition = 710; } // Constructor implementation SplitFlapModule::SplitFlapModule( - uint8_t I2Caddress, int stepsPerFullRotation, int stepOffset, int magnetPos, int charsetSize + uint8_t I2Caddress, int stepsPerFullRotation, int stepOffset, int magnetPos, int charsetSize, + const String &charsetStr ) - : address(I2Caddress), position(0), stepNumber(0), stepsPerRot(stepsPerFullRotation), charSetSize(charsetSize) { + : address(I2Caddress), position(0), stepNumber(0), stepsPerRot(stepsPerFullRotation) { magnetPosition = magnetPos + stepOffset; - chars = (charsetSize == 48) ? ExtendedChars : StandardChars; - numChars = (charsetSize == 48) ? 48 : 37; + int len = charsetStr.length(); + + if (len < 37) { + // Use StandardChars as fallback + Serial.println("Fallback StandardChars"); + charSetSize = numChars = 37; + usingCustomChars = false; + for (int i = 0; i < numChars; i++) { + customChars[i] = StandardChars[i]; + } + } else if (len >= 37) { + // Use custom charset, but truncate to either 37 or 48 + usingCustomChars = true; + charSetSize = numChars = (len >= 48) ? 48 : 37; + for (int i = 0; i < numChars; i++) { + customChars[i] = charsetStr[i]; + } + customChars[numChars] = '\0'; + } else { + // Fallback if empty + charSetSize = numChars = 37; + usingCustomChars = false; + for (int i = 0; i < numChars; i++) { + customChars[i] = StandardChars[i]; + } + } } void SplitFlapModule::writeIO(uint16_t data) { @@ -83,12 +107,14 @@ void SplitFlapModule::init() { int SplitFlapModule::getCharPosition(char inputChar) { inputChar = toupper(inputChar); + for (int i = 0; i < charSetSize; i++) { - if (chars[i] == inputChar) { + if (customChars[i] == inputChar) { return charPositions[i]; } } - return 0; // Character not found, return blank + + return 0; // fallback } void SplitFlapModule::stop() { diff --git a/src/SplitFlapModule.h b/src/SplitFlapModule.h index 3eed10f..e20e02e 100644 --- a/src/SplitFlapModule.h +++ b/src/SplitFlapModule.h @@ -8,7 +8,10 @@ class SplitFlapModule { // Constructor declarationS SplitFlapModule(); // default constructor required to allocate memory for // SplitFlapDisplay class - SplitFlapModule(uint8_t I2Caddress, int stepsPerFullRotation, int stepOffset, int magnetPos, int charSetSize); + SplitFlapModule( + uint8_t I2Caddress, int stepsPerFullRotation, int stepOffset, int magnetPos, int charsetSize, + const String &charset + ); void init(); @@ -42,10 +45,11 @@ class SplitFlapModule { static const int motorPins[]; // Array of motor pins static const int HallEffectPIN; // Hall Effect Sensor Pin (On PCF8575) - const char *chars; // pointer to active character set int charPositions[48]; // support up to 48 characters int numChars; // current number of characters int charSetSize; + bool usingCustomChars = false; + char customChars[50]; static const char StandardChars[37]; static const char ExtendedChars[48]; diff --git a/src/SplitFlapWebServer.cpp b/src/SplitFlapWebServer.cpp index ff8d952..cfe4432 100644 --- a/src/SplitFlapWebServer.cpp +++ b/src/SplitFlapWebServer.cpp @@ -369,7 +369,13 @@ void SplitFlapWebServer::startWebServer() { if (json["otaPass"].is() && json["otaPass"].as() != settings.getString("otaPass")) { rebootRequired = true; // OTA password change can only be applied by rebooting - response["message"] = "Settings updated successfully, OTA Password has changed. Rebooting..."; + } + + if ((json["moduleCount"].is() && json["moduleCount"].as() != settings.getInt("moduleCount")) || + (json["charset"].is() && json["charset"].as() != settings.getInt("charset")) || + (json["custom_charset"].is() && + json["custom_charset"].as() != settings.getString("custom_charset"))) { + rebootRequired = true; } if (json["mdns"].is() && json["mdns"].as() != settings.getString("mdns")) { @@ -397,6 +403,10 @@ void SplitFlapWebServer::startWebServer() { return request->send(400, "application/json", response.as()); } + if (rebootRequired) { + response["message"] = "Settings updated successfully, Rebooting..."; + } + response["type"] = "success"; response["persistent"] = reconnect; diff --git a/src/web/settings.html b/src/web/settings.html index 995bafa..163e789 100644 --- a/src/web/settings.html +++ b/src/web/settings.html @@ -148,18 +148,24 @@
-
-
- - -
+
+ + +
+

  • Number of modules: How many split-flap modules are connected.
  • -
  • Character Set: 37 = standard (A-Z0-9), 48 = extended (includes symbols).
  • +
  • Character Set: 37 = standard (A-Z 0-9), 48 = extended (includes symbols).
  • +
  • Customise Characters: Specify your custom characters and symbols.
  • Addresses: I²C address for each module. Typically starts at 32 and increases per module.
  • Offsets: Fine-tune each module’s zero position if flaps are misaligned.
  • @@ -480,6 +526,42 @@ + +
    + +
    + + +
    +
    +