PuckJS "E" object is empty?

Posted on
  • Any help appreciated! I have a PuckJS.
    I wanted to use E.connectSDCard() after wiring an SD card to pins, but I got

    Uncaught Error: Function "connectSDCard" not found!

    So I printed the keys of E with print( Object.keys( E ) + " < Those were E's Keys" );
    And got:

    [ ] < Those were Es Keys

    I did a hard-reset by holding the button while inserting the battery, then waiting for the LEDs to finish their color changes and the red LED flashed 5 times, then held the button for 1 more second, like the instructions said.
    But E is still an empty object. According to the documentation, it should have many functions available on it. https://www.espruino.com/Reference#E

    I tried looking up the error, but the troubleshooting documentation just tells me to check for a typo. :-(

    Edit: I updated the firmware using the WebIDE a while ago if memory serves, but I have not put any custom firmware on it or anything.

    I have been using the PuckJS to control an E-Ink display over SPI, which is working fine. Only the E object is not working. Is there any other relevant information? Hmm.

    It's a PuckJS V2. The one with almost no pins and an FET.

    I have been trying to make an e-reader by attaching it to a 4.2 inch, 400*300 e-ink display.
    The e-ink display's pixels are 1 bit each (for black-white images). The PuckJS didn't have anywhere near enough power to render a 15KB page from a font using bitwise math ops, nor enough RAM to hold more than 1 page in memory. It would take minutes just to "turn the page".

    I had the idea of streaming a pre-rendered 15KB page over bluetooth, but that turned out to be amazingly difficult. You can't stream binary data over PuckJS's bluetooth, because it uses the ASCII control codes as connection commands. I modified the "puck.js" library to accept array buffers, and used escape characters to work around character codes < 32 (as well as dealing with JavaScript string escapes).

    const hex = code => code.toString(16).padStart(2,0).split(""­).map( c => c.charCodeAt( 0 ) );
    
    const streamableBinaryArray = [];
    for( const code of binaryArray ) {
        if( code === 0x22 ) streamableBinaryArray.push( 0x5c, 0x22 );
        else if( code === 0x5c ) streamableBinaryArray.push( 0x5c, 0x5c );
        else if( code === 0xa ) streamableBinaryArray.push( 0x5c, 0x6e );
        else if( ( code >= 0x00 && code <= 0x1f ) || code === 0x7f ) streamableBinaryArray.push( 0x5c, 0x78, ...hex( code ) );
        else streamableBinaryArray.push( code );
    }
    

    I managed to get streaming 1 page down to under 12 seconds, a huge improvement over the several minute mark, but not usable for every page turn.

    Still, it would take about an hour to stream a 300 page book. My idea was to stream the entire book, saving individual pages as files on an SD card. Then, on a page turn forward or back, I could read the appropriate file from the SD card into the array buffer, then stream the array buffer to the e-ink display. (How long will that take? It's still untested...)

    HOWEVER! I cannot. Because E.connectSDCard does not exist. :-|

    I checked Espruino's source over on GitHub, and "jswrap_file.c" defines "connectSDCard", so I don't think it's deprecated. "spi_diskio.c" looks like it's setting up and controlling an SD card, so I think the functionality does actually exist.

    The documentation says "This is not available in devices with low flash memory", but that's a frustratingly useless and ambiguous warning. There's nothing anywhere that I've been able to find specifying what devices have "low flash memory". >:-(
    Does it mean if you use up too high a RAM % the code will become unavailable? Does it mean nothing running Espruino ever has this functionality? (Espruino was specifically designed to run on devices with low memory.) Does it mean certain devices from Espruino's shop do / do not have this functionality? (I don't really care in general, I just want to get an SD card working on my PuckJS. I'm sure I can write the SPI commands myself if that's what I'm supposed to do.)


    2 Attachments

    • 20230317_061140.jpg
    • 20230317_060823.jpg
  • So I printed the keys of E with print( Object.keys( E ) + " < Those were E's Keys" );

    And got:

    [ ] < Those were Es Keys

    can you instead connect interactively to the device and use tab completion? type E. and the tab key?

    it is likely builtin native methods are not in Object.keys

    There's nothing anywhere that I've been able to find specifying what devices have "low flash memory". >:-(
    Does it mean if you use up too high a RAM % the code will become unavailable?

    No it means the firmware is built in such way. The board files have SAVE_ON_FLASH defined
    https://github.com/espruino/Espruino/sea­rch?l=Python&q=SAVE_ON_FLASH

  • here https://github.com/espruino/Espruino/blo­b/master/libs/filesystem/jswrap_file.c#L­115

    It is defined in libs/filesystem so it gets included in boards that use FILESYSTEM module/library which PUCK doesn't have enabled
    https://github.com/espruino/Espruino/blo­b/master/boards/PUCKJS.py#L40

  • Thank you so much! That is very helpful. :-)
    I will code the SD card SPI commands in JS and hopefully still have enough RAM... Somehow.

  • Or you'd need to make custom build. I just tried but the space is tight so you'd need to sacrifice internal storage, reduce it from 40 to 32KB

    Or start from PUCKJS_MINIMAL https://github.com/espruino/Espruino/blo­b/master/boards/PUCKJS_MINIMAL.py
    or just remove stuff you don't use. here is the list
    https://github.com/espruino/Espruino/blo­b/master/boards/PUCKJS.py#L35

  • In my experience, trying to get a compiler to work takes days, while writing a code library takes hours.
    And why would 4 tiny SPI functions need 8KB of RAM??? It will be much less than 1KB in JS. I have maybe 2KB I can sacrifice at most.
    I will work on it when I get home. Thank you again.

  • why would 4 tiny SPI functions need 8KB of RAM

    it is whole filesystem module - file IO methods + FAT filesystem implementation

    and it is not RAM

  • Oh, sorry; I don't understand well enough. I thought Puck had 512 KB of storage and 64KB of RAM. But you said "reduce it from 40 to 32KB."

    In any case, I won't mess with C or compilers. The only reason I'm using Puck instead of Raspberry Pi zero is to avoid wasted time with compilers.

  • I thought Puck had 512 KB of storage and 64KB of RAM. But you said "reduce it from 40 to 32KB."

    out of 512 you only have 10 4kb pages for storage of your code
    https://github.com/espruino/Espruino/blo­b/master/boards/PUCKJS.py#L78

    instead of Raspberry Pi zero

    or Raspberry Pico W

  • Wow! I knew some storage must be used up, but I had no idea free space was so limited. I don't think it will affect me as long as I can get the SD card working.
    If I ever do go the trouble of getting compilers running on my current PC (other than Bellard's TinyC :-) ), I might try messing with Puck's firmware. Thank you for all the information.

  • Just to add that Object.keys(E) returning nothing is expected - it's because E is defined as if it's an object that extends an object that has all the functions (eg Object.keys([]) wouldn't include push/pop/etc) - although in this case it's a bit confusing.

    As @fanoush says tab complete should work, or Object.getOwnPropertyNames(E) will work too.

    But yes, it seems connectSDcard isn't built into the Puck firmware. If you ever do want to go that route let us know though - you don't actually need to set up a compiler - you just fork the GitHub repo, enable GitHub actions, make the change to boards/PUCKJS_MINIMAL.py which you can do with the online editor, and magically you'll have the file available to download after a few minutes a bit like: https://github.com/espruino/Espruino/act­ions/runs/4408348448#artifacts

  • you just fork the GitHub repo, enable GitHub actions, make the change to boards/PUCKJS_MINIMAL.py which you can do with the online editor, and magically you'll have the file available to download after a few minutes a bit like: https://github.com/espruino/Espruino/act­ions/runs/4408348448#artifacts

    Oh, this is actually pretty cool and very useful for cases like this one. It would be nice to actually allow it to run on demand (instead of every commit) with board file as parameter. According to github docs it should be possible https://docs.github.com/en/actions/manag­ing-workflow-runs/manually-running-a-wor­kflow . I'll try to add this to the https://github.com/espruino/Espruino/blo­b/master/.github/workflows/build.yml template and maybe make a PR with this if I succeed.

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

PuckJS "E" object is empty?

Posted by Avatar for user154581 @user154581

Actions