• Hi everyone !

    I interested in messing with a VGA/HDMI/.. connector & the data exchanged between a device connected to it, read on ! ;p

    As a reminder, EDID looks like that:

    header:          00 ff ff ff ff ff ff 00
    serial number:   50 a6 87 46 e1 0b 04 01 27 19
    version:         01 03
    basic params:    80 10 09 78 0a
    chroma info:     ee 91 a3 54 4c 99 26 0f 50 54
    established:     21 08 00
    standard:        81 80 a9 40 01 01 01 01 01 01 01 01 01 01 01 01
    descriptor 1:

    For a current project, I need to:

    • read EDID data from a monitor/tv screen connected over hdmi ( using i2c )
    • modify ( parts of ) this data
    • send this data when requested by other devices connected over hdmi ( using i2c )

    The goal is more or less an "HDMI DDC EDID MitM" ( we can change a lot of infos found in the original EDID )^^
    Along with the above, it should also act as a "fast hdmi switcher", doing EDID handling & messing with hotplug pins ( since EDID is no longer re-read from the monitor when it's switching to a particular source, but instead read once, when the device connecting to the monitor does so in the background )

    my current prototype consists of:

    • a hacked hdmi switch & hdmi breakouts.
    • an original Espruino connected to the monitor/tv screen's hdmi i2c & hotplug pins
    • an Arduino connected to an hdmi 'source' device ( laptop, game console, .. )

    The Espruino listens for a pin rising ( the monitor's hdmi connector's hotplug pin ) before acting as an i2c master to then write & read data a monitor's ( fixed ) i2c adress 0X50.

    The Arduino simulates a 'source' device connection by toggling its hdmi connector's hotplug pin before acting as an i2c slave with address 0x50 & provides EDID data whenever being requested to over i2c.

    I am currently wondering what'd be the simplest & most robust way to communicate between the Espruino & the Arduino ( knowing that having a 3IN<->1OUT hdmi switch, I plan to use 2 more Arduinos, one for each hdmi IN ).
    Every Arduino has only one hdmi device's i2c pins connected to it, and the Espruino is also using different i2c pins to communicate with the screen.

    I hesitate between SPI & serial, and the only limitation ( at least those I see for now .. ) is using a pin for each on the Espruino & using a watch to listen for an Arduino's request of the ( modded ) monitor's EDID ( store within the Espruino's program & refreshed on boot ).

    Moreover, we have limited memory on both the Espruino & the Arduino & although I did get away with modding the Arduino's "Wire" ( i2c ) lib, it seemed I couldn't get more than 256 bytes out of it at once ( and I couldn't figure out if this was coming from the Espruino side ? .. ) & while increasing the buffer seemed to free memory Arduino-side, I still can't get more than ~253 bytes when reading from an i2c address using Espruino ( I still have to run tests using an Arduino as i2c master to better identify the source of the trouble ).

    To bypass this current limitation, I re-wrote the Arduino code to act more like my laptop ( & surely other 'source' devices ) does ( writing a byte to select the portion to be read from i2c, then reading max 128 bytes of data ).

    As the EDID is 128 bytes big & so does the Extended one, writing 0x00 then reading 128 bytes gives to EDID, and writing 0x80 then reading 128 bytes gives to Extended data.
    Also, writing a byte < 256 & then reading a number of bytes gives the n bytes starting from the previously written one ( seems to be the common way for i2c memory chips ? .. ).
    This being said, it seems reading 128 bytes again & again without writing any returns the EDID or the Extended One alternatively in a cycle

    I mostly replicated this behavior ( although I have to fix the code handling switching between sending alternatively each & sending only 128 bytes from a previously received one on the Arduino-side - which works but is still not working wip since it doesn't handle cycling without receiving a byte beforehand for now .. and yet it's not-that-bad-enough to work ;) )

    Once the above was nearly ok, I decided to try scanning the available i2c devices in the monitor, but sadly none of the i2c scanners I found for Espruino worked :/ ..
    .. so I modified a little bit the EDID sniffing code to instead trigger an i2c scan right after sensing a rise on the monitor's hotplog pin & it seems to work, albeit very slow for now
    I'll try to mod an existing i2c scanner to do the work faster & give a prettier output, but part of my other code seems needed, at least for my monitor ( compared to other i2c devices I guess ? .. )

    Code provided below is for:

    • monitor EDID sniffer ( Espruino ): fetches & decodes EDID & E-EDID data
    • monitor i2c addr scanner ( Espruino ): lists i2c peripherials in connected screen
    • EDID fuzzer ( Arduino ): acts as a connected monitor & send EDID data when asked
    • wip js to decode & encode data in the EDID format ( could be improved A LOT .. and it 'll need to if I want it to fit on the original Espruino .. )
  • ( not fitting in one post .. :/ )

    So, the said-prototype produces the following when connected to ( currently a laptop )

    ps: among other stuff, there's a "possible easter egg' somewhere in it .. will you find it ? ^^

    EDID version: 1.3
    Manufacturer: TEF Model 4687 Serial Number 17042401
    Made in week 39 of 2015
    Digital display
    Maximum image size: 16 cm x 9 cm
    Gamma: 2.20
    RGB color display
    First detailed timing is preferred timing
    Display x,y Chromaticity:
      Red:   0.6396, 0.3300
      Green: 0.2998, 0.5996
      Blue:  0.1503, 0.0595
      White: 0.3125, 0.3291
    Established timings supported:
      640x480@60Hz 4:3 HorFreq: 31469 Hz Clock: 25.175 MHz
      800x600@60Hz 4:3 HorFreq: 37900 Hz Clock: 40.000 MHz
      1024x768@60Hz 4:3 HorFreq: 48400 Hz Clock: 65.000 MHz
    Standard timings supported:
      1280x1024@60Hz 5:4 HorFreq: 64000 Hz Clock: 108.000 MHz
      1600x1200@60Hz 4:3 HorFreq: 75000 Hz Clock: 162.000 MHz
    Detailed mode: Clock 148.500 MHz, 160 mm x 90 mm
                   1920 2008 2052 2200 hborder 0
                   1080 1084 1089 1125 vborder 0
                   +hsync +vsync 
                   VertFreq: 60 Hz, HorFreq: 67500 Hz
    Detailed mode: Clock 85.500 MHz, 160 mm x 90 mm
                   1360 1424 1536 1792 hborder 0
                    768  771  777  795 vborder 0
                   +hsync +vsync 
                   VertFreq: 60 Hz, HorFreq: 47712 Hz
    Monitor ranges (GTF): 23-61Hz V, 26-76kHz H, max dotclock 230MHz
    Monitor name: VIRTUOSA
    Has 1 extension blocks
    Checksum: 0x18 (valid)

    4 Attachments

  • Wow, nice idea! I'd say definitely go for Serial between Espruino and the Arduino - it's nice and easy to wire up, and to debug with a USB-TTL converter.

    To be honest even the I2C reader & decoder on something like Pixl.js would be a great debug tool - you could plug it into any HDMI device and see what it was capable of.

    I should really add I2C and SPI slave support to Espruino - the issue really has been how to handle it when the JS takes so long to execute. It could just be a bunch of registers since that's what most I2C devices seem to do - but anyway, that's sidetracking the thread - I guess it should be a GitHub issue.

  • Hi there !

    thanks ;)

    It indeed seems that Arduino <-serial->Espruino is the quickest & handy path to choose
    ( I am currently doing so to control & get feedbacks on a Teensy 3.6 - acting as an Xbox 360 controller - from Espruino ;) )

    As I get enough time to do so, I'll update the reader/decoder part & start building a lib from those ( nb: it 'd require a whole lot of work additionally to the current one to get all the infos for a particular monitor, though )

    As I currently don't own a Pixl.js ( I'd be more interested in a MDBT42Q breakout ;p ), I'll just pack the interesting bits & give that away in the forums ( or try building a canvas pixl.js screen emulator ? )

    On the I2C & SPI slave subject, it 'd be really awesome to have, as this is one of the reason I still need to keep an Arduino closeby when messing with stuff ( on a side note, I currently face somewhat close ends as I'm trying to use a custom usb device descriptor different that a HID one ( that's why I'm using a Teensy for now to do the USB talk ;p ).
    I guess I can help on neither, as I currently don't know either enough to be of any actual help implementing those on the Espruino platform :/

  • or try building a canvas pixl.js screen emulator ?

    The Pixl just offers a global variable called g for graphics... If you just do something like http://www.espruino.com/Pico+LCD+Hello+W­orld before you call your code then you're basically there with emulation :)

    I2C slave

    Do you think having the slave implemented as a bunch of registers would actually work in this case?

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

EDID fuzzer, EDID sniffer & Monitor/TV screen i2c addr scanner :)

Posted by Avatar for stephaneAG @stephaneAG