• Uint8Arrays are obviously not arrays...

    ...as executed in console:

    >var arr = new Uint8Array([70, 82, 65, 77, 64, 53, 49, 50]);
    =new Uint8Array([70, 82, 65, 77, 64, 53, 49, 50])
    >String.fromCharCode.apply(null,arr);
    WARNING: Second argument to Function.apply must be an array
    

    I do not really mind if there is another simple way to make a String out of Uint8Array.

    May be in [1v71] Uint#Arrays are arrays.

  • ArrayBufferViews aren't ever really arrays (I don't believe they are in normal JS either). It looks like Function.apply should still take them though - I've just filed a bug for that.

    I'm sure there was a nice way to get from an ArrayBufferView to an array, but I can't remember it right now! (there's a way to go the other way)

    The best I can think of right now is:

    ArrayBufferView.prototype.asString = function() {
     var s = "";
     this.forEach(function(d) { s+=String.fromCharCode(d); });  
     return s;
    }
    
  • May be I should have been a bit more precise: implement (essential part of) array protocol, because the following works:

    >var arr = new Array(70, 82, 65, 77, 64, 53, 49, 50);
    =[ 70, 82, 65, 77, 64, 53, 49, 50 ]
    ="FRAM@512"
    > 
    

    and so does

    >String.fromCharCode.apply(null,[70, 82, 65, 77, 64, 53, 49, 50]);
    ="FRAM@512"
    > 
    

    All browser's w/ name do too, because of MDN's String and Function definition (fromCharCode() and call()).
    The the statement is a valid statement -

    Regarding your suggestion: I tried to avoid in a loop the in and out of the JS engine AND the String concatenation.

    What about overall performance - Is string concatenation not the recipe for increased garbage collection activities? ...of course, 'it all depends', since many things in a system contribute combined to results for better or worse.

    Why I was looking for this is for my FRAMS module, where this construct comes in very handy for reading back as a String (see http://forum.espruino.com/conversations/­257994).

  • If you want data out of SPI as a string, just give it a string to start with - that would be the fastest method :)

    I've just fixed Function.apply - so 1v72 will now work - although the maximum number of arguments (and hence characters) is still 64.

    Is string concatenation not the recipe for increased garbage collection activities

    Actually no - because Espruino is reference counted it's actually very good at stuff like that - and the blocks of memory also make concatenation much more efficient than you'd expect :)

  • Ic. ...but not really, or may be I need a bit shoe-horning: it is in regard to SPI... if I do SPI.send() of a String vs. and Uint8Array, I will get back a String? ...that would be the call for 'in the first place' (after also resolving the efficient creation of an 0x00 initialized String of a defined length).

    While touching on the SPI.send() subject: it is now the second time that I would like to have something different from having to create a chunk of 'meaningless' memory for the SPI.send() to keep the receive clock ticking... (ILI9341 needs the same for reading from display memory). May be the very same chunk is simultaneously used as the reception buffer for what the send returns... but I don't think so: it would destroy the input. The SPI.write has this nice feature of providing an object with data and count. Adding this parameter option to the SPI.send() would save me the double amount of memory. Right?

    To adjust my high-level thinking to what is 'below the line water line', I guess it is the time for me to look into the vm... (almost) ...to get a better understanding of the limitations (having implemented a few myself - limitations AND vms, quite a while ago).

    Regarding String garbage collection, I expected an answer like this, because the way Espruino manages its memory (followed a bit the evolution regarding decreasing size of int, vars, etc. and read through the available performance information).

    Thanks for being so responsive!

  • @allObjects I'm new to all this and have been reading up on SPI & sending dummy data in order to read - I found it very confusing but this is what I now understand:

    SPI is always dual-direction (even if the data in one direction is sometimes ignored) so if the master expects to receive 24 bits of data from the slave, then it must send out 24 bits to generate all the clocking for the 24 bits sent in the other direction.

    Some implementations may provide a "read" SPI function which provides the clocks without you having to specifically supply some "dummy" data to write.

    I read that it may be more appropriate to use 0xFF rather than 0x00 for the dummy bytes
    since the idle state is usually high - so sending FF is effectively doing nothing (not sure if this is correct?)

    It may help clear things up a bit (I'm still not 100% clear)

    I made use of your getPixel function in my buffered ILI9341 code - I was totally stuck without it - thanks.

  • One quick question - when receiving an unknown number of bytes how can I tell that the "stream" of data has been fully received and how many dummy bytes should I send at a time?

    Or maybe I need to ask the slave device how many bytes I should expect to receive (e.g. the size of a file)

  • I guess I could add a read function that would pump out however many bytes were needed - as you say, 0xFF might be best. It's not a massive problem to create an array of bytes to stick into send though.

    You could always write something like:

    if (!SPI.prototype.read) SPI.prototype.read = function(n,p) { var a = new Uint8Array(n); a.fill(0xFF); return this.send(a,p); }
    

    and then if a read function does get added, you code should swap over gracefully.

    In terms of expecting data - I think you just have to 'know' - sometimes you can ask the device, but sometimes you'll just have to check the datasheet and figure it out.

  • Having to create a chunk of memory just to keep a clock going with all the same sent byte can throw you into "Out of Memory" jail... I would prefer having similar solution as with the write. Even though an object definition costs too, for larger amounts of bytes it still provides a less memory intensive solution.

    Another options is to have 2nd argument as a count, and current optional ssn pin argument type checked: with no repetition count pin is 2nd argument, with repetition count, pin is 3rd argument - pin is though always last element if present. 1st argument is still single argument.

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

Uint8Array - is it really an array? And what about the other Uint#Arrays?

Posted by Avatar for allObjects @allObjects

Actions