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
 | 
			
		||||
 | 
			
		||||
enum Brightness {
 | 
			
		||||
    Normal,
 | 
			
		||||
    Bright,
 | 
			
		||||
// TODO: reverse engineer builtin and custom bitmaps
 | 
			
		||||
 | 
			
		||||
// 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) {
 | 
			
		||||
    // debugging
 | 
			
		||||
    Serial.print("Sending text \"");
 | 
			
		||||
    Serial.print(text);
 | 
			
		||||
    Serial.println("\"");
 | 
			
		||||
enum class Brightness {
 | 
			
		||||
    Normal = 'a',
 | 
			
		||||
    Bright = 'b',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
    // TODO: find out how the brightness attribute in the LED sign is encoded in the UART signal
 | 
			
		||||
    Serial1.print("f01A\\s");
 | 
			
		||||
    Serial1.print(text);
 | 
			
		||||
    Serial1.print("\r\r\r");
 | 
			
		||||
enum class Method {
 | 
			
		||||
    Cyclic = 'A',
 | 
			
		||||
    Immediate = 'B',
 | 
			
		||||
    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