/* LICENCE see end of file! */ /* Environemental note The program is created for Arduino/ESP8266 and is tested on WIN10 only! */ /* --->>> READ THIS: <<<--- Developer, don't forget to update the version number here! */ // Values visible in THIS file only! // namespace SelfValues { // static constexpr char FILE_AND_VERSION[] = "00.0025"; // } #ifndef DUMMY // Macro statements ============================================= #ifndef DUMMY // 3rd party includes ------------------------------------------- // 3rd party files #include #include // For convenient printouts to Serial // already is supplied by Arduino.h #include #include #include // Custom files #endif // 3rd party includes #ifndef DUMMY // Serial related ----------------------------------------------- #ifndef SERIAL_BAUDRATE #define SERIAL_BAUDRATE 74880 #endif #endif // Serial related #ifndef DUMMY // OLED device related ------------------------------------------ #ifndef DUMMY // OLED HW-related #ifndef MCU_SCL_PIN #define MCU_SCL_PIN D1 // OLED clock-pin #endif #ifndef MCU_SDA_PIN #define MCU_SDA_PIN D2 // OLED data-pin #endif #ifndef OLED_SCREEN_WIDTH #define OLED_SCREEN_WIDTH 128 #endif #ifndef OLED_SCREEN_HEIGHT #define OLED_SCREEN_HEIGHT 64 #endif #ifndef MAX_DISPLAY_WIDTH #define MAX_DISPLAY_WIDTH 21 // 21 chars, including the \0 terminator #endif #ifndef OLED_DEFAULT_CONTRAST #define OLED_DEFAULT_CONTRAST 50 #endif #ifndef OLED_TESTING_CONTRAST #define OLED_TESTING_CONTRAST 15 #endif #endif // OLED HW-related #ifndef DUMMY // OLED SW-related /* Font data: * - u8g2_font_6x10_mr is monospaced * - approx. 21.33 characters per line * - chars 10 pixel high * - approx. 6.4 lines of text in 64 pixel * (without vertical gaps between lines!) * - the descent of the font is 2 pixels * * Thus, a total of 12 pixels in height would suffice * for ordinary text (= message text). */ #define OLED_FONT u8g2_font_6x10_mr // Font chosen // Which leads to: #define OLED_FONT_WIDTH 6 /* 6 pixel */ #define OLED_FONT_HEIGHT 10 /* 10 pixel */ #define OLED_CHARS_PER_LINE 21 /* 21 chars per line, including the \0 terminator */ #define OLED_LINE_HEIGHT 12 /* 10 + 2 pix line gap */ #define OLED_VERT_LINES_MSG 5 /* Allowed line capacity of display */ #define OLED_VERT_LINES_MENU 4 /* Allowed line capacity of display */ /* Printing and typography */ #ifndef OLED_DEFAULT_TYPING_SPEED #define OLED_DEFAULT_TYPING_SPEED 200 // 200 chars per minute #endif #ifndef MIN_CHARS_LEADING #define MIN_CHARS_LEADING 3 // Min. leading chars when hyphenating #endif #ifndef MIN_CHARS_TRAILING #define MIN_CHARS_TRAILING 2 // Min. trailing chars when hyphenating #endif #endif // OLED SW-related #endif // OLED device related #ifndef DUMMY // Special string settings -------------------------------------- #ifndef SIZE_RESERVED_STRING_XXL #define SIZE_RESERVED_STRING_XXL 300 #endif #ifndef MAX_NUM_WORDS #define MAX_NUM_WORDS 50 #endif #ifndef MAX_NUM_LINES #define MAX_NUM_LINES 25 #endif #endif // Special string data #endif // Macro statements #ifndef DUMMY // Global elements, structs, variables ========================== // Pairs ---------------------------------------------------------------------- // indexPairsOfWords[]: // Contains the start and end indices of all 'words' in a message text std::pair indexPairsOfWords[MAX_NUM_WORDS]; // indexPairsOfRows[]: // Contains the start and end indices for all 'rows' to be displayed on OLED std::pair indexPairsOfRows[MAX_NUM_LINES]; uint8_t pairsOfRows; // Used for control of MAX_NUM_LINES! // Strings -------------------------------------------------------------------- String textMsg_XXL = ""; // Declare a structure to hold pairs of indices struct WordBoundaries { uint8_t start; // Start index of a 'word' in a string uint8_t end; // Index of last 'word' in a string }; // Declare an array of type WordBoundaries named wordBoundaries WordBoundaries wordBoundaries[10]; // Define a Vector named words for WordBoundaries for ease of management Vector words(wordBoundaries); // Retrieve the 7th word from myString: // String extractedWord = myString.substring(words[6].start, words[6].end + 1); struct RowBoundaries { uint8_t start; // Start index of a string-section uint8_t end; // Index of last char in a string-section }; RowBoundaries rowBoundaries[10]; // Declare an array of type RowBoundaries named rowBoundaries Vector rows(rowBoundaries); // Define a Vector named rows for rowBoundarie for ease of management // Retrieve the 7th row from of myString: // String extractedRow = myString.substring(rows[6].start, rows[6].end + 1); #endif // Global elements #ifndef DUMMY // Control of file- and custom-includes ========================= #ifndef DUMMY // EDIT SWITCHES as required: ----------------------------------- #define INCLUDED_ARE_ALL_FILES false // All files are included #define TEST_ALL false // All tests are activated #define INCLUDED_IS_SplitText true // Include SplitText() #define TEST_splitText true // Test splitText() #define INCLUDED_IS_populateTextRows false #define TEST_populateTextRows false #define INCLUDED_IS_OledPrint false #define TEST_oledPrint false #endif // EDIT SWITCHES as required #ifndef DUMMY // #include statements (custom files) --------------------------- #if (INCLUDED_ARE_ALL_FILES || INCLUDED_IS_SplitText ) #include "FC10_SplitText.h" #endif #if (INCLUDED_ARE_ALL_FILES || INCLUDED_IS_SplitText ) #include "FC10_SplitText.h" #endif #if (INCLUDED_ARE_ALL_FILES || INCLUDED_IS_populateTextRows ) #include "FC11_populateTextRows.h" #endif #endif // #include statements #endif // Control of file- and custom-includes void setup() { #ifndef DUMMY // General setup() statements =================================== Serial.begin(SERIAL_BAUDRATE); // Do not use while (!Serial)! // In some environements this may block the program flow! yield(); // seems to be neccessary delay(5000); // 5000ms seem to be the minimum on my machine (WIN10)... Serial << endl; Serial << "Serial is ready-1." << endl; Serial << "Serial is ready-2." << endl; #endif // General setup() statements #ifndef DUMMY // Memory allocation (reserve) for Strings ====================== textMsg_XXL.reserve(SIZE_RESERVED_STRING_XXL); #endif // Memory allocation for Strings #ifndef DUMMY // Tests ======================================================== #if (TEST_oledPrint || TEST_ALL) // Test oledPrint() -------------------------- // Supply fresh text-data splitText.freshSplitData( /* Plain text source: */ /* "Erster Test von oledPrint()." */ /* Hyphenation following Duden-rules applied (by ChatGPT): */ /* "Ers|ter Test von oled|Print()." */ "Ers|ter Test von oled|Print().", " " ); #endif // Test oledPrint() #if (TEST_splitText || TEST_ALL) // Test splitText() -------------------------- #ifndef DUMMY // Tests freshSplitData() // Trigger 1.1 Error if delimiter sequences of length > 2 are existing - */ textMsg_XXL = "Ein Text, der einen dreifachen Delimiter enthält."; splitText.freshSplitData(textMsg_XXL, " "); // tested OK // Trigger 1.2) Error if protected delimiters are not paired textMsg_XXL = "Ein Text mit ungepaarten geschützten Delimitern."; splitText.freshSplitData(textMsg_XXL, " "); #endif // Tests freshSplitData() #ifndef DUMMY // Tests getNextSplitPositions() String tmpDelimiter ; String tmpWord ; String tmpLeadPadding1 ; String tmpLeadPadding2 ; std::pair tmpPos ; #ifndef DUMMY // 2.1 A simple phrase Serial << endl; Serial << endl; // Init tmpPos = std::make_pair(0, 0); // Input: textMsg_XXL = "Ein einfacher Satz."; tmpDelimiter = " "; splitText.freshSplitData(textMsg_XXL, tmpDelimiter); // Output: Serial << "Input (2.1):" << endl; Serial << "Text >>>" << textMsg_XXL << "<<<" << endl; Serial << "Delimiter >>>" << tmpDelimiter << "<<<" << endl; Serial << endl; Serial << "Output:" << endl; while (true) { // Check for end of textMsg_XXL if (tmpPos.first == -1 && tmpPos.second == -1) { Serial << endl << "No more words to extract." << endl; break; } // Get the next word positions tmpPos = splitText.getNextSplitPositions(); tmpLeadPadding1=""; if (tmpPos.first > -1 && tmpPos.first < 10) {tmpLeadPadding1=" ";} tmpLeadPadding2=""; if (tmpPos.second > -1 && tmpPos.second < 10) {tmpLeadPadding2=" ";} Serial << "Indices " << tmpLeadPadding1 << tmpPos.first << " to " << tmpLeadPadding2 << tmpPos.second; tmpWord = textMsg_XXL.substring(tmpPos.first, tmpPos.second); Serial << ": >>" << tmpWord << "<<" << endl; } #endif // 2.1 A simple phrase #ifndef DUMMY // 2.2 Delimiter am Anfang und am Ende Serial << endl; Serial << endl; // Init tmpPos = std::make_pair(0, 0); // Input: textMsg_XXL = " Mit Delimiter am Anfang und am Ende. "; tmpDelimiter = " "; splitText.freshSplitData(textMsg_XXL, tmpDelimiter); // Output: Serial << "Input (2.2):" << endl; Serial << "Text >>>" << textMsg_XXL << "<<<" << endl; Serial << "Delimiter >>>" << tmpDelimiter << "<<<" << endl; Serial << endl; Serial << "Output:" << endl; while (true) { // Check for end of textMsg_XXL if (tmpPos.first == -1 && tmpPos.second == -1) { Serial << endl << "No more words to extract." << endl; break; } // Get the next word positions tmpPos = splitText.getNextSplitPositions(); tmpLeadPadding1=""; if (tmpPos.first > -1 && tmpPos.first < 10) {tmpLeadPadding1=" ";} tmpLeadPadding2=""; if (tmpPos.second > -1 && tmpPos.second < 10) {tmpLeadPadding2=" ";} Serial << "Indices " << tmpLeadPadding1 << tmpPos.first << " to " << tmpLeadPadding2 << tmpPos.second; tmpWord = textMsg_XXL.substring(tmpPos.first, tmpPos.second); Serial << ": >>" << tmpWord << "<<" << endl; } #endif // 2.2 Delimiter am Anfang und am Ende #ifndef DUMMY // 2.3 Protected 'word' in the middle Serial << endl; Serial << endl; // Init tmpPos = std::make_pair(0, 0); // Input: textMsg_XXL = "Text mit gepaartem Doppel-Delimiter bzw. geschütztem 'Wort' ."; tmpDelimiter = " "; splitText.freshSplitData(textMsg_XXL, tmpDelimiter); // Output: Serial << "Input (2.3):" << endl; Serial << "Text >>>" << textMsg_XXL << "<<<" << endl; Serial << "Delimiter >>>" << tmpDelimiter << "<<<" << endl; Serial << endl; Serial << "Output:" << endl; while (true) { // Check for end of textMsg_XXL if (tmpPos.first == -1 && tmpPos.second == -1) { Serial << endl << "No more words to extract." << endl; break; } // Get the next word positions tmpPos = splitText.getNextSplitPositions(); tmpLeadPadding1=""; if (tmpPos.first > -1 && tmpPos.first < 10) {tmpLeadPadding1=" ";} tmpLeadPadding2=""; if (tmpPos.second > -1 && tmpPos.second < 10) {tmpLeadPadding2=" ";} Serial << "Indices " << tmpLeadPadding1 << tmpPos.first << " to " << tmpLeadPadding2 << tmpPos.second; tmpWord = textMsg_XXL.substring(tmpPos.first, tmpPos.second); Serial << ": >>" << tmpWord << "<<" << endl; } #endif // 2.3 Protected 'word' in the middle #ifndef DUMMY // 2.4 Protected section at the beginning and at the end Serial << endl; Serial << endl; // Init tmpPos = std::make_pair(0, 0); // Input: textMsg_XXL = " Geschützte Sektion am Anfang und am Ende "; tmpDelimiter = " "; splitText.freshSplitData(textMsg_XXL, tmpDelimiter); // Output: Serial << "Input (2.4):" << endl; Serial << "Text >>>" << textMsg_XXL << "<<<" << endl; Serial << "Delimiter >>>" << tmpDelimiter << "<<<" << endl; Serial << endl; Serial << "Output:" << endl; while (true) { // Check for end of textMsg_XXL if (tmpPos.first == -1 && tmpPos.second == -1) { Serial << endl << "No more words to extract." << endl; break; } // Get the next word positions tmpPos = splitText.getNextSplitPositions(); tmpLeadPadding1=""; if (tmpPos.first > -1 && tmpPos.first < 10) {tmpLeadPadding1=" ";} tmpLeadPadding2=""; if (tmpPos.second > -1 && tmpPos.second < 10) {tmpLeadPadding2=" ";} Serial << "Indices " << tmpLeadPadding1 << tmpPos.first << " to " << tmpLeadPadding2 << tmpPos.second; tmpWord = textMsg_XXL.substring(tmpPos.first, tmpPos.second); Serial << ": >>" << tmpWord << "<<" << endl; } #endif // 2.4 Protected section at the beginning and at the end #endif // Tests getNextSplitPositions() #endif // Test splitText() #endif // Tests } void loop() { } /* History: * 2025-08-10: (#024) * - SplitText() (as an include file) now successfully may be tested, using * the switches in 'File- and custom-includes control' * 2024-06-28 to 2025-07-31: * - Fermenting control was set up only */ /***** LICENCE by Uli / ulisblog.info / ulrich-hauser.de *****/ /***** Fermenting Box Control © 2024 *****/ /* This licence is including related header- and .cpp files and is licensed * under: * * Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International * * CC BY-NC-SA 4.0 * * To view a copy of this license, please visit: * https://creativecommons.org/licenses/by-nc-sa/4.0// * */