Add information on (mostly reversed) protocol
Also fixes the basic functionality of sending a text to the sign with the default parameters.
This commit is contained in:
		
							
								
								
									
										316
									
								
								src/util.h
									
									
									
									
									
								
							
							
						
						
									
										316
									
								
								src/util.h
									
									
									
									
									
								
							@@ -1,18 +1,310 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum Brightness {
 | 
					// TODO: reverse engineer builtin and custom bitmaps
 | 
				
			||||||
    Normal,
 | 
					
 | 
				
			||||||
    Bright,
 | 
					// seems like our sign listens to messages on this address
 | 
				
			||||||
 | 
					// it is also the software's default value
 | 
				
			||||||
 | 
					static constexpr auto SIGN_ADDRESS = 128;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class FontType {
 | 
				
			||||||
 | 
					    Font5x6Short = 'q',
 | 
				
			||||||
 | 
					    Font5x11ShortAndWide = 'r',
 | 
				
			||||||
 | 
					    Font7x6Default = 's',
 | 
				
			||||||
 | 
					    Font7x11Wide = 't',
 | 
				
			||||||
 | 
					    Font7x9 = 'u',
 | 
				
			||||||
 | 
					    Font7x17ExtraWide = 'v',
 | 
				
			||||||
 | 
					    FontSmallFont = 'w',
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void sendTextToSign(String text, Brightness brightness = Bright) {
 | 
					enum class Brightness {
 | 
				
			||||||
    // debugging
 | 
					    Normal = 'a',
 | 
				
			||||||
    Serial.print("Sending text \"");
 | 
					    Bright = 'b',
 | 
				
			||||||
    Serial.print(text);
 | 
					};
 | 
				
			||||||
    Serial.println("\"");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO: find out how the brightness attribute in the LED sign is encoded in the UART signal
 | 
					enum class Method {
 | 
				
			||||||
    Serial1.print("f01A\\s");
 | 
					    Cyclic = 'A',
 | 
				
			||||||
    Serial1.print(text);
 | 
					    Immediate = 'B',
 | 
				
			||||||
    Serial1.print("\r\r\r");
 | 
					    OpenFromRight = 'C',
 | 
				
			||||||
 | 
					    OpenFromLeft = 'D',
 | 
				
			||||||
 | 
					    OpenFromCenter = 'E',
 | 
				
			||||||
 | 
					    OpenToCenter = 'F',
 | 
				
			||||||
 | 
					    CoverFromCenter = 'G',
 | 
				
			||||||
 | 
					    CoverFromRight = 'H',
 | 
				
			||||||
 | 
					    CoverFromLeft = 'I',
 | 
				
			||||||
 | 
					    CoverToCenter = 'J',
 | 
				
			||||||
 | 
					    ScrollUp = 'K',
 | 
				
			||||||
 | 
					    ScrollDown = 'L',
 | 
				
			||||||
 | 
					    InterlaceToCenter = 'M',
 | 
				
			||||||
 | 
					    InterlaceCover = 'N',
 | 
				
			||||||
 | 
					    CoverUp = 'O',
 | 
				
			||||||
 | 
					    CoverDown = 'P',
 | 
				
			||||||
 | 
					    ScanLine = 'Q',
 | 
				
			||||||
 | 
					    Explode = 'R',
 | 
				
			||||||
 | 
					    PacMan = 'S',
 | 
				
			||||||
 | 
					    FallAndStack = 'T',
 | 
				
			||||||
 | 
					    Shoot = 'U',
 | 
				
			||||||
 | 
					    Flash = 'V',
 | 
				
			||||||
 | 
					    Random = 'W',
 | 
				
			||||||
 | 
					    SlideIn = 'X',
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// macros are literal characters prefixed by ^
 | 
				
			||||||
 | 
					enum class Macros {
 | 
				
			||||||
 | 
					    CurrentTime12hWithoutAmPm = 'D',
 | 
				
			||||||
 | 
					    CurrentTime12hWithAmPm = 'E',
 | 
				
			||||||
 | 
					    CurrentTime24h = 'F',
 | 
				
			||||||
 | 
					    CurrentDateMmDdYyyy = 'A',
 | 
				
			||||||
 | 
					    CurrentDateYyyy_Mm_Dd = 'B',
 | 
				
			||||||
 | 
					    CurrentDateMm_Dd_Yyyy = 'C',
 | 
				
			||||||
 | 
					    CurrentDateDd_Mm_Yyyy = 'a',
 | 
				
			||||||
 | 
					    Beep1 = 'q',
 | 
				
			||||||
 | 
					    Beep2 = 'r',
 | 
				
			||||||
 | 
					    Beep3 = 's',
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// symbols should be inserted as string representations of their numeric value prefixed by ^
 | 
				
			||||||
 | 
					enum class Symbols {
 | 
				
			||||||
 | 
					    Sun = 66,
 | 
				
			||||||
 | 
					    CloudOrWind = 67,
 | 
				
			||||||
 | 
					    UmbrellaRaining = 68,
 | 
				
			||||||
 | 
					    WallClock = 69,
 | 
				
			||||||
 | 
					    Telephone = 70,
 | 
				
			||||||
 | 
					    Glasses = 71,
 | 
				
			||||||
 | 
					    Faucet = 72,
 | 
				
			||||||
 | 
					    RocketOrSyringeOrSo = 73,
 | 
				
			||||||
 | 
					    WhatTheHell = 74,
 | 
				
			||||||
 | 
					    Key = 75,
 | 
				
			||||||
 | 
					    Shirt = 76,
 | 
				
			||||||
 | 
					    Helicopter = 77,
 | 
				
			||||||
 | 
					    Car = 78,
 | 
				
			||||||
 | 
					    Tank = 79,
 | 
				
			||||||
 | 
					    House = 80,
 | 
				
			||||||
 | 
					    Teapot = 81,
 | 
				
			||||||
 | 
					    Trees = 82,
 | 
				
			||||||
 | 
					    Duck = 83,
 | 
				
			||||||
 | 
					    Scooter = 84,
 | 
				
			||||||
 | 
					    Bicycle = 85,
 | 
				
			||||||
 | 
					    Crown = 86,
 | 
				
			||||||
 | 
					    AppleOrSo = 87,
 | 
				
			||||||
 | 
					    ArrowRight = 88,
 | 
				
			||||||
 | 
					    ArrowLeft = 89,
 | 
				
			||||||
 | 
					    ArrowDownLeft = 90,
 | 
				
			||||||
 | 
					    ArrowUpLeft = 91,
 | 
				
			||||||
 | 
					    Cup = 92,
 | 
				
			||||||
 | 
					    Chair = 93,
 | 
				
			||||||
 | 
					    HighHeel = 94,
 | 
				
			||||||
 | 
					    PrizeCup = 95,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// cartoons are represented as these characters prefixed by ^
 | 
				
			||||||
 | 
					enum class Cartoon {
 | 
				
			||||||
 | 
					    MerryXMas = 'i',
 | 
				
			||||||
 | 
					    HappyNewYear = 'j',
 | 
				
			||||||
 | 
					    FourthOfJuly = 'k',
 | 
				
			||||||
 | 
					    HappyEaster = 'l',
 | 
				
			||||||
 | 
					    HappyHalloween = 'm',
 | 
				
			||||||
 | 
					    DontDrinkAndDrive = 'n',
 | 
				
			||||||
 | 
					    NoSmoking = 'o',
 | 
				
			||||||
 | 
					    Welcome = 'p',
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// the descriptions originate from the UTF-16 specification, https://www.ssec.wisc.edu/~tomw/java/unicode.html
 | 
				
			||||||
 | 
					// the extended charset starts where ASCII ends
 | 
				
			||||||
 | 
					enum class ExtendedChar {
 | 
				
			||||||
 | 
					    // Ç
 | 
				
			||||||
 | 
					    LatinCapitalLetterCWithCedilla = 0x80,
 | 
				
			||||||
 | 
					    // ü
 | 
				
			||||||
 | 
					    LatinSmallLetterUWithDiaeresis = 0x81,
 | 
				
			||||||
 | 
					    // é
 | 
				
			||||||
 | 
					    LatinSmallLetterEWithAcute = 0x82,
 | 
				
			||||||
 | 
					    // â
 | 
				
			||||||
 | 
					    LatinSmallLetterAWithCircumflex = 0x83,
 | 
				
			||||||
 | 
					    // ä
 | 
				
			||||||
 | 
					    LatinSmallLetterAWithDiaeresis = 0x84,
 | 
				
			||||||
 | 
					    // á
 | 
				
			||||||
 | 
					    LatinSmallLetterAWithGrave = 0x85,
 | 
				
			||||||
 | 
					    // å
 | 
				
			||||||
 | 
					    LatinSmallLetterAWithRingAbove = 0x86,
 | 
				
			||||||
 | 
					    // ç
 | 
				
			||||||
 | 
					    LatinSmallLetterCWithCedilla = 0x87,
 | 
				
			||||||
 | 
					    // ê
 | 
				
			||||||
 | 
					    LatinSmallLetterEWithCircumflex = 0x88,
 | 
				
			||||||
 | 
					    // ë
 | 
				
			||||||
 | 
					    LatinSmallLetterEWithDiaeresis = 0x89,
 | 
				
			||||||
 | 
					    // è
 | 
				
			||||||
 | 
					    LatinSmallLetterEWithGrave = 0x8a,
 | 
				
			||||||
 | 
					    // Ï
 | 
				
			||||||
 | 
					    LatinCapitalLetterIWithDiaeresis = 0x8b,
 | 
				
			||||||
 | 
					    // Î
 | 
				
			||||||
 | 
					    LatinCapitalLetterIWithCircumflex = 0x8c,
 | 
				
			||||||
 | 
					    // Ì
 | 
				
			||||||
 | 
					    LatinCapitalLetterIWithGrave = 0x8d,
 | 
				
			||||||
 | 
					    // Ä
 | 
				
			||||||
 | 
					    LatinCapitalLetterAWithDiaeresis = 0x8f,
 | 
				
			||||||
 | 
					    // Å
 | 
				
			||||||
 | 
					    LatinCapitalLetterAWithRingAbove = 0x8f,
 | 
				
			||||||
 | 
					    // É
 | 
				
			||||||
 | 
					    LatinCapitalLetterEWithAcute = 0x90,
 | 
				
			||||||
 | 
					    // æ
 | 
				
			||||||
 | 
					    LatinSmallLetterAe = 0x91,
 | 
				
			||||||
 | 
					    // Æ
 | 
				
			||||||
 | 
					    LatinCapitalLetterAe = 0x92,
 | 
				
			||||||
 | 
					    // ô
 | 
				
			||||||
 | 
					    LatinSmallLetterOWithCircumflex = 0x93,
 | 
				
			||||||
 | 
					    // ö
 | 
				
			||||||
 | 
					    LatinSmallLetterOWithDiaeresis = 0x94,
 | 
				
			||||||
 | 
					    // ò
 | 
				
			||||||
 | 
					    LatinSmallLetterOWithGrave = 0x95,
 | 
				
			||||||
 | 
					    // û
 | 
				
			||||||
 | 
					    LatinSmallLetterUWithCircumflex = 0x96,
 | 
				
			||||||
 | 
					    // ù
 | 
				
			||||||
 | 
					    LatinSmallLetterUWithGrave = 0x97,
 | 
				
			||||||
 | 
					    // ÿ
 | 
				
			||||||
 | 
					    LatinSmallLetterYWithDiaeresis = 0x98,
 | 
				
			||||||
 | 
					    // Ö
 | 
				
			||||||
 | 
					    LatinCapitalLLetterOWithDiaeresis = 0x99,
 | 
				
			||||||
 | 
					    // Ü
 | 
				
			||||||
 | 
					    LatinCapitalLetterUWithDiaeresis = 0x9a,
 | 
				
			||||||
 | 
					    // ¢
 | 
				
			||||||
 | 
					    CentSign = 0x9b,
 | 
				
			||||||
 | 
					    // £
 | 
				
			||||||
 | 
					    PoundSign = 0x9c,
 | 
				
			||||||
 | 
					    // ¥
 | 
				
			||||||
 | 
					    YenSign = 0x9d,
 | 
				
			||||||
 | 
					    // urm...
 | 
				
			||||||
 | 
					    UnknownPCurrencySign = 0x9e,
 | 
				
			||||||
 | 
					    // ƒ
 | 
				
			||||||
 | 
					    LatinSmallLetterFWithHook = 0x9f,
 | 
				
			||||||
 | 
					    // á
 | 
				
			||||||
 | 
					    LatinSmallLetterAWithAcute = 0xa0,
 | 
				
			||||||
 | 
					    // Í
 | 
				
			||||||
 | 
					    LatinCapitalLetterIWithAcute = 0xa1,
 | 
				
			||||||
 | 
					    // Ó
 | 
				
			||||||
 | 
					    LatinCapitalLetterOWithAcute = 0xa2,
 | 
				
			||||||
 | 
					    // ú
 | 
				
			||||||
 | 
					    LatinSmallLetterUWithAcute = 0xa3,
 | 
				
			||||||
 | 
					    // ñ
 | 
				
			||||||
 | 
					    LatinSmallLetterNWithTilde = 0xa4,
 | 
				
			||||||
 | 
					    // Ñ
 | 
				
			||||||
 | 
					    LatinCapitalLetterNWithTilde = 0xa5,
 | 
				
			||||||
 | 
					    // a̱
 | 
				
			||||||
 | 
					    LatinSmallLetterAWithMacronBelow = 0xa6,
 | 
				
			||||||
 | 
					    // couldn't find that one in the UTF-16 table
 | 
				
			||||||
 | 
					    LatinSmallLetterOWithMacronBelow = 0xa7,
 | 
				
			||||||
 | 
					    // ¿
 | 
				
			||||||
 | 
					    InvertedQuestionMark = 0xa8,
 | 
				
			||||||
 | 
					    // you can probably imagine what it'll look like
 | 
				
			||||||
 | 
					    LatinCapitalLetterZWithRingAbove = 0xa9,
 | 
				
			||||||
 | 
					    // Ź
 | 
				
			||||||
 | 
					    LatinCapitalLetterZWithAcute = 0xaa,
 | 
				
			||||||
 | 
					    // ń
 | 
				
			||||||
 | 
					    LatinSmallLetterNWithAcute = 0xab,
 | 
				
			||||||
 | 
					    // some weird L with a diagonal line
 | 
				
			||||||
 | 
					    AnotherWeirdSign = 0xac,
 | 
				
			||||||
 | 
					    // Ś or ś, can't tell for sure, let's assume capital
 | 
				
			||||||
 | 
					    LatinCapitalLetterSWithAcute = 0xab,
 | 
				
			||||||
 | 
					    // Ć
 | 
				
			||||||
 | 
					    LatinCapitalLetterCWithAcute = 0xac,
 | 
				
			||||||
 | 
					    // ȩ
 | 
				
			||||||
 | 
					    LatinSmallLetterEWithCedilla = 0xad,
 | 
				
			||||||
 | 
					    // well, you can imagine what it'll look like
 | 
				
			||||||
 | 
					    LatinSmallLetterAWithCedilla = 0xb0,
 | 
				
			||||||
 | 
					    // €
 | 
				
			||||||
 | 
					    EuroSign = 0xb1,
 | 
				
			||||||
 | 
					    // E with some vertical line below
 | 
				
			||||||
 | 
					    LatinCapitalLetterEWithSomeLineBelow = 0xb3,
 | 
				
			||||||
 | 
					    // a with some vertical line below
 | 
				
			||||||
 | 
					    LatinSmallLetterAWithSomeWeirdLineBelow = 0xb4,
 | 
				
			||||||
 | 
					    // α
 | 
				
			||||||
 | 
					    GreekSmallLetterAlpha = 0xe0,
 | 
				
			||||||
 | 
					    // β
 | 
				
			||||||
 | 
					    GreekSmallLetterBeta = 0xe1,
 | 
				
			||||||
 | 
					    // Γ
 | 
				
			||||||
 | 
					    GreekCapitalLetterGamma = 0xe2,
 | 
				
			||||||
 | 
					    // π
 | 
				
			||||||
 | 
					    GreekSmallLetterPi = 0xe3,
 | 
				
			||||||
 | 
					    // Σ
 | 
				
			||||||
 | 
					    GreekCapitalLetterSigma = 0xe4,
 | 
				
			||||||
 | 
					    // σ
 | 
				
			||||||
 | 
					    GreekSmallLetterSigma = 0xe5,
 | 
				
			||||||
 | 
					    // μ
 | 
				
			||||||
 | 
					    GreekSmallLetterMu = 0xe6,
 | 
				
			||||||
 | 
					    // τ
 | 
				
			||||||
 | 
					    GreekSmallLetterTau = 0xe7,
 | 
				
			||||||
 | 
					    // Φ
 | 
				
			||||||
 | 
					    GreekCapitalLetterPhi = 0xe8,
 | 
				
			||||||
 | 
					    // θ
 | 
				
			||||||
 | 
					    GreekSmallLetterTheta = 0xe9,
 | 
				
			||||||
 | 
					    // Ω
 | 
				
			||||||
 | 
					    GreekCapitalLetterOmega = 0xea,
 | 
				
			||||||
 | 
					    // δ
 | 
				
			||||||
 | 
					    GreekSmallLetterDelta = 0xeb,
 | 
				
			||||||
 | 
					    // ∞
 | 
				
			||||||
 | 
					    Infinity = 0xec,
 | 
				
			||||||
 | 
					    // φ
 | 
				
			||||||
 | 
					    GreekSmallLetterPhi = 0xed,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Message syntax:
 | 
				
			||||||
 | 
					 * separator: ~
 | 
				
			||||||
 | 
					 * address (int string): 128
 | 
				
			||||||
 | 
					 * separator: ~
 | 
				
			||||||
 | 
					 * random string(?): f01
 | 
				
			||||||
 | 
					 * method (single char)
 | 
				
			||||||
 | 
					 * format string (see below)
 | 
				
			||||||
 | 
					 * end of message: \r\r\r
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * the format string contains the message along with control characters that define some of the formatting
 | 
				
			||||||
 | 
					 * note: we have not tested the UTF-8 capabilities, so far only ASCII
 | 
				
			||||||
 | 
					 * it supports multiple lines (yet to be tested)
 | 
				
			||||||
 | 
					 * you can also insert macros (e.g., current time/date), symbols (e.g., a sun) and cartoons
 | 
				
			||||||
 | 
					 * the specials are preceded by a caret following the respective character
 | 
				
			||||||
 | 
					 * then, there is an extended charset that supports a small subset of UTF-16 (yes, that's right, it's not just UTF-8)
 | 
				
			||||||
 | 
					 * it can further contain information that should be used from their occurrence on
 | 
				
			||||||
 | 
					 * the formatting escape sequences are prefixed by a literal backspace following a char that represents the format
 | 
				
			||||||
 | 
					 * brightness is \<ab>, speed is Y<1-8>, "stay time" is \Z<1-8>, font type is \[A-X]
 | 
				
			||||||
 | 
					 * new lines are introduced by a single \r, the end of the message is marked by three of them
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * default formatting:
 | 
				
			||||||
 | 
					 *   - method: cyclic
 | 
				
			||||||
 | 
					 *   - font type: 7x6
 | 
				
			||||||
 | 
					 *   - speed: 5
 | 
				
			||||||
 | 
					 *   - stay time: 4
 | 
				
			||||||
 | 
					 *   - brightness: bright
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sendTextToSign(
 | 
				
			||||||
 | 
					    const String &text,
 | 
				
			||||||
 | 
					    const Method method = Method::Cyclic,
 | 
				
			||||||
 | 
					    const FontType fontType = FontType::Font7x6Default,
 | 
				
			||||||
 | 
					    const int speed = 5,
 | 
				
			||||||
 | 
					    const int stayTime = 4,
 | 
				
			||||||
 | 
					    const Brightness brightness = Brightness::Bright
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    if (speed < 0 || speed > 8) {
 | 
				
			||||||
 | 
					        Serial.println("Invalid speed: " + String(speed, DEC));
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (stayTime < 0 || stayTime > 8) {
 | 
				
			||||||
 | 
					        Serial.println("Invalid stayTime: " + String(stayTime, DEC));
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Serial.println("Sending text: \"" + text + "\"");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    String toSend = "~" + String(SIGN_ADDRESS, DEC) + "~f01" + (char) method + "\\" + (char) brightness + "\\Y" + String(speed, DEC) + "\\Z" + String(stayTime, DEC) + "\\" + (char) fontType + text + "\r\r\r";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Serial1.print(toSend);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Serial.println("Text sent to device: " + toSend);
 | 
				
			||||||
 | 
					    Serial.print("Hex dump: ");
 | 
				
			||||||
 | 
					    for (size_t i = 0; i < toSend.length(); ++i) {
 | 
				
			||||||
 | 
					        auto hexChar = String(toSend[i], HEX);
 | 
				
			||||||
 | 
					        if (hexChar.length() == 1) {
 | 
				
			||||||
 | 
					            hexChar = '0' + hexChar;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Serial.print(hexChar + ' ');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Serial.println();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user