• In order to write to an LCD screen, I need to send over I2C a 1024 byte buffer, prefixed with "DIM\x00\x00\x80\x40". The only way I know to do this is to convert the buffer to a string, by looping over it one character at a time, and then just add the two together.

    exports.connect = function(i2c) {
    
      var LCD = Graphics.createArrayBuffer(128,64,1);
      LCD.i2c=i2c;
      LCD.flip = function () {
        this.i2c.writeTo(0x27,"DIM\x00\x00\x80\x­40"+this.atos(this.buffer)); 
      };  
    
      LCD.atos= function (a) {
        var s = "";
        for (var j in a) { 
          s+=String.fromCharCode(j);  
        }
        return s };
      }
      return LCD;
    };
    

    This is slow enough that the flip() function would take a fraction of a second to return - but the display wants the bits in each byte to be in the opposite order than what the Espruino normally outputs them as... So I've been doing this, and it works, but it takes about a second to return.... Any thoughts on how to do this better?

    exports.connect = function(i2c) {
      var LCD = Graphics.createArrayBuffer(128,64,1);
      LCD.i2c=i2c;
      LCD.flip = function () {
        this.i2c.writeTo(0x27,"DIM\x00\x00\x80\x­40"+this.reverse(this.buffer)); 
      };  
    
      LCD.reverse = function (a) {
        var s = "";
        for (var h in a) { 
          var i=a[h];                                                                                  
          j=(i>>7|(i>>5&0x02)|(i>>3&0x04)|(i>>1&0x­08)|(i<<1&0x10)|(i<<3&0x20)|(i<<5&0x40)|­(i<<7&0x80));
          s+=String.fromCharCode(j);  
        }
        return s };
      }
      return LCD;
    };
    

    Thanks in advance...

  • I'd consider using ArrayBuffer.map. It's something that's on arrays in ES5, but has been extended to ArrayBuffers in ES6 (and Espruino :) ).

      LCD.reverse = function (a) {
        return h.map(function(i) { 
          return (i>>7|(i>>5&0x02)|(i>>3&0x04)|(i>>1&0x08­)|(i<<1&0x10)|(i<<3&0x20)|(i<<5&0x40)|(i­<<7&0x80));
        });
      }
    

    But for bit reversal you can be faster as well - there's a fun (and scary) website here full of tricks: http://graphics.stanford.edu/~seander/bi­thacks.html

      LCD.reverse = function (a) {
        return h.map(function(b) {return (((b*0x0802&0x22110)|(b*0x8020&0x88440))­*0x10101>>16)&0xFF;});
      }
    

    You can do it even faster with 64 bit maths (which Espruino supports) but it's something that I may be removing soon to make Espruino faster, smaller, and more JS compliant so I won't post that here ;)

    Finally, you can use ArrayBuffers instead of Strings, and can predefine the code you want to add:

    var preamble = E.toArrayBuffer("DIM\x00\x00\x80\x40");
      LCD.flip = function () {
        var d = new Uint8Array(this.buffer.length+preamble.l­ength);
        d.set(preamble,0);
        d.set(this.buffer,preamble.length);
        this.i2c.writeTo(0x27,d); 
      };  
    

    Hope that helps! I think I should probably add E.reverseByte as this comes up quite a lot. If that happens then you could be super fast and could just do: array.map(E.reverseByte)

    Of course there's always the inline assembler too ;)

  • Just added E.reverseByte - you can get it in the latest build, or can wait for 1v63:

      var preamble = E.toArrayBuffer("DIM\x00\x00\x80\x40");
      LCD.flip = function () {
        var d = new Uint8Array(this.buffer.length+preamble.l­ength);
        d.set(preamble,0);
        d.set(new Uint8Array(this.buffer).map(E.reverseByt­e), preamble.length);
        this.i2c.writeTo(0x27,d); 
      };  
    
  • Awesome, thanks, will report back on the performance of this tonight :-)

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

Help optimizing this - converting 1024 byte arraybuffer to string after reversing bits in each byte

Posted by Avatar for DrAzzy @DrAzzy

Actions