• 1 Post
  • 552 Comments
Joined 1 year ago
cake
Cake day: June 23rd, 2024

help-circle


  • I travelled with DB to enjoy the 2022 9-€ Ticket. The cross-border train ČD drove into Germany got stopped in the first city and got cancelled because it “didn’t meet standards”. I mean, it was missing a car, there was no AC, it was super loud and crowded, but it was a train and went on time. DB’s replacement was literally nothing so I was stuck waiting in Schwandorf for an hour. This happens dozens of times every year.

    Meanwhile, my trip last year was an orderly experience, probably because I went through former East Germany via Dresden instead. Communists did a lot of bad shit but they understood the power of trains (and streetcars).


  • I studied electronics and GSM was a big part of the telecommunications subject. I visited the HQ of a mobile provider, was shown around and met the cartel boss (in hindsight, I wonder how much a Luigi moment would have affected the triopoly). I also visited a museum of technology and used an early touch-click model still connected to the network (pre-DTMF so not touch-tone, and no buffer so you had to wait for the simulated dial to stop clicking).

    But still, I don’t know the basics of wired phones cuz I’ve never really used them. How does voice travel both ways on a single twisted pair? How can Inspector Clouseau the telephone engineer in The Pink Panther (1978) hear a conversation from other phones in the house? How does the exchange know I’ve dialed the last digit? Can I use voice services on rotary phones, and what if I need to press * or #? All these would be obvious to 1980s kids…







  • Contrary to popular belief, this wasn’t made by making a very error-resistant code and sticking an image on top, as most “Logo-QR” codes are made today. AFAIK, the code is not only error-free but also up to spec*, unlike this Bad Apple one that, while also impressive, uses non-standard padding bytes after the actual data.

    * Except the XOR mask pattern is not chosen to minimize problematic patterns like solid color areas in the result, obviously – but I’m not buying a $270 standard just to see if it says “should” or “must”.

    https://analognowhere.com/#815956000955341196626324525376426508044011799516042661339518686677364520931952256954853578523008163894957991180853268570682643959895730628162682682661506593341503383997517938597366696669325062682725512003951964556693309309170041341332991998000490597366

    The URL is very interesting. I’m trying to reverse-engineer the creation process of this code.

    • The version (size) is 6 (41×41), just small enough to not have alignment patterns (extra squares).
    • The masking pattern is 2, probably since that encodes as 3 black pixels as part of the picture.
    • The error correction is set to the minimum or L, allowing the maximum possible number of bytes to be user-controlled. The number of content bits is 1088. Since one byte is used for length, the longest string that can be encoded is 134 bytes.

    Here it is “unmasked”:

    There can be multiple data types in a QR code. This one first has a bytes section, which readers interpret as text, and then a numeric section. Blue is the text part of the URL, red-orange is the numeric part, and green is error correction.
    The raw data in the QR code is:

    0b 0100                    Encoding: Bytes (Latin-1 text)
    0b 00011011                Content Length: 27
    0x 68 74 74 70 73 3A 2F 2F "https://"
    0x 61 6E 61 6C 6F 67 6E 6F "analogno"
    0x 77 68 65 72 65 2E 63 6F "where.co"
    0x 6D 2F 23                "m/#"
    0b 0001                    Encoding: Numeric
    0b 0011111100              Content Length: 252
    0b 1100101111              [815]
    0b 1110111100              [956]
    0b 0000000000              [000]
    0b 1110111011              [955]
    0b 0101010101              [341]
    0b 0011000100              [196]
    0b 1001110010              [626]
    0b 0101000100              [324]
    0b 1000001101              [525]
    0b 0101111000              [376]
    0b 0110101010              [426]
    0b 0111111100              [508]
    0b 0000101100              [044]
    0b 0000001011              [011]
    0b 1100011111              [799]
    0b 1000000100              [516]
    0b 0000101010              [042]
    0b 1010010101              [661]
    0b 0101010011              [339]
    0b 1000000110              [518]
    0b 1010101110              [686]
    0b 1010100101              [677]
    0b 0101101100              [364]
    0b 1000001000              [520]
    0b 1110100011              [931]
    0b 1110111000              [952]
    0b 0100000000              [256]
    0b 1110111010              [954]
    0b 1101010101              [853]
    0b 1001000010              [578]
    0b 1000001011              [523]
    0b 0000001000              [008]
    0b 0010100011              [163]
    0b 1101111110              [894]
    0b 1110111101              [957]
    0b 1111011111              [991]
    0b 0010110100              [180]
    0b 1101010101              [853]
    0b 0100001100              [268]
    0b 1000111010              [570]
    0b 1010101010              [682]
    0b 1010000011              [643]
    0b 1110111111              [959]
    0b 1101111111              [895]
    0b 1011011010              [730]
    0b 1001110100              [628]
    0b 0010100010              [162]
    0b 1010101010              [682]
    0b 1010101010              [682]
    0b 1010010101              [661]
    0b 0111111010              [506]
    0b 1001010001              [593]
    0b 0101010101              [341]
    0b 0111110111              [503]
    0b 0101111111              [383]
    0b 1111100101              [997]
    0b 1000000101              [517]
    0b 1110101010              [938]
    0b 1001010101              [597]
    0b 0101101110              [366]
    0b 1010111000              [696]
    0b 1010011101              [669]
    0b 0101000101              [325]
    0b 0000111110              [062]
    0b 1010101010              [682]
    0b 1011010101              [725]
    0b 1000000000              [512]
    0b 0000000011              [003]
    0b 1110110111              [951]
    0b 1111000100              [964]
    0b 1000101100              [556]
    0b 1010110101              [693]
    0b 0100110101              [309]
    0b 0100110101              [309]
    0b 0010101010              [170]
    0b 0000101001              [041]
    0b 0101010101              [341]
    0b 0101001100              [332]
    0b 1111011111              [991]
    0b 1111100110              [998]
    0b 0000000000              [000]
    0b 0111101010              [490]
    0b 1001010101              [597]
    0b 0101101110              [366]
    0b 0000                    End
    0b 00
    

    Note that the numeric encoding uses 10 bits for each group of 3 digits. Let’s call it triplet-BCD. The last two bits are only to round up the data section to a whole number of bytes, specifically these 88 bytes:

    41 B6 87 47 47 07 33 A2 
    F2 F6 16 E6 16 C6 F6 76 
    E6 F7 76 86 57 26 52 E6 
    36 F6 D2 F2 31 3F 32 FE 
    F0 00 EE D5 53 12 72 51 
    20 D5 E1 AA 7F 02 C0 2F 
    1F 81 02 AA 55 53 81 AA 
    EA 95 6C 82 3A 3E E1 00 
    EE B5 59 0A 0B 02 0A 3D 
    FB BD F7 CB 4D 55 0C 8E 
    AA AA 0F BF DF ED A9 D0 
    A2 AA AA AA 55 FA 94 55 
    57 DD 7F F9 60 5E AA 55 
    5B AB 8A 75 45 0F AA AB 
    56 00 00 FB 7F 12 2C AD 
    53 54 D4 AA 0A 55 55 33 
    DF F9 80 07 AA 55 5B 80
    

    What follows in the QR code is error correction bytes, 36 of them. The numbers in the right and mid-upper section of the image must have been chosen so that the error correction bytes end up forming the left half of the face, presumably via lots of trial-and-error. However, what I find very odd is that the decimal number the numeric section encodes, which you see at the end of the URL, translates to this in hex:

    0x1c7dbd97f32cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
    

    This is not a floating point error, the triplet-BCD-encoded data really produces 501222037467851 × 2788, a very round number in binary!! I have no idea how that coincides with so many digits being used as part of the face in the weird triplet-BCD encoding.

    Also, I haven’t been able to replicate the error correction algorithm: I think it’s the same as reedsolo in Python but

    >>> from reedsolo import RSCodec
    >>> rawbytes=b"\x41\xB6\x87\x47\x47\x07\x33\xA2\xF2\xF6\x16\xE6\x16\xC6\xF6\x76\xE6\xF7\x76\x86\x57\x26\x52\xE6\x36\xF6\xD2\xF2\x31\x3F\x32\xFE\xF0\x00\xEE\xD5\x53\x12\x72\x51\x20\xD5\xE1\xAA\x7F\x02\xC0\x2F\x1F\x81\x02\xAA\x55\x53\x81\xAA\xEA\x95\x6C\x82\x3A\x3E\xE1\x00\xEE\xB5\x59\x0A\x0B\x02\x0A\x3D\xFB\xBD\xF7\xCB\x4D\x55\x0C\x8E\xAA\xAA\x0F\xBF\xDF\xED\xA9\xD0\xA2\xAA\xAA\xAA\x55\xFA\x94\x55\x57\xDD\x7F\xF9\x60\x5E\xAA\x55\x5B\xAB\x8A\x75\x45\x0F\xAA\xAB\x56\x00\x00\xFB\x7F\x12\x2C\xAD\x53\x54\xD4\xAA\x0A\x55\x55\x33\xDF\xF9\x80\x07\xAA\x55\x5B\x80"
    >>> rsc = RSCodec(36); print(rsc.encode(rawbytes).hex())
    41b68747470733a2f2f616e616c6f676e6f77686572652e636f6d2f2313f32fef000eed55312725120d5e1aa7f02c02f1f8102aa555381aaea956c823a3ee100eeb5590a0b020a3dfbbdf7cb4d550c8eaaaa0fbfdfeda9d0a2aaaaaa55fa945557dd7ff9605eaa555bab8a75450faaab560000fb7f122cad5354d4aa0a555533dff98007aa555b80662d719c3ef320500601c1e3f6fd3b517a3e1f06c9a7d4140c7c78af219b3b39f5dd2053
    

    does not yield the expected error correction bytes I can see in the unmasked code (green)…









  • On Slavic layouts, the right Alt key (AltGr) lets us type symbols like [, ], {, }, &, @, #, ×, ÷, , đ since 0-9 is for diacritical letters by default and numbers with Shift. Still, Czech Windows users mostly use Alt codes, which is a point of friction when switching to Linux. But there, I’m happy with how I can customize the AltGr and the new AltGr+Shift layers with curly quotes, em dash, nbsp, hair space, arrows, middle dot, pi (π), pretty pi (𝛑), mu, Omega etc. My Compose key is RCtrl.