• Hey,

    I'm working on a clock face - It's a gradient generator with some themes and configuration.

    The themes are each two colours, and a function in the watch generates more colours based on the passed number of steps.

    It then creates an array and appends the reversed version to it to create one smooth gradient field.

    Using the accelerometer to decide the direction the gradient moves in so you get an effect of the background moving - you can also switch it between horizontal and vertical

    To get this working effectively I'm using LCD Mode "doublebuffered" which works great - if I try it in normal I get a lot of flickering and haven't really figured of if it's possible with that I'm doing to do in that mode.

    But I've noticed that despite my best efforts, the screen never goes off with the LCD Timeout, and I'm wondering what I'm doing wrong? This isn't the most memory-efficient clock, and it does a lot of drawing (once per 100ms to be smooth) by shifting the entire array of colours so when the screen isn't on I'd definitely like to stop any running timers.

    Can anyone spot what I'm doing wrong?


    1 Attachment

  • Also in the emulator, it works - but the background animation doesn't happen (it's just still) but all other functions work - and with doublebuffered it's very flickery around the top where the widgets should be


    2 Attachments

    • Screenshot 2021-03-02 at 10.34.48.png
    • Screenshot 2021-03-02 at 10.58.36.png
  • Thinking about I'm wondering - would it be better to generate an image from the array,it would need to be a full 8bpp, could probably get away with 5 or 6.

    If I can make the image roll around the screen then I can use that as the pre-calculated background?
    I think having to shift or unshift the arrays is where it's slowing down so it seems like a good place generate it once and reuse it

    For the effect, Each filled rectangle width is (screen width / total gradient array length) so you get the effect of each colour at the edge and the wide bar of each colour, and a pretty smooth gradient effect.

    I was thinking also pre-storing all the theme steps instead of generating them each time, but if it's only run once I think having the function seems better as it's only a single calculation each time.

    I also wanted a random option, but BangleJS's Math.random isn't random enough! I even tried adding a multiplier from the accelerator each time the function was called to make it more random but it was still generating colour combinations too close to each other.

  • Ahh - unfortunately that's a known issue - that g.flip() forces the screen to stay on. The widget area flickering is expected too - basically the double buffer means you have two buffers that swap, and widgets may only be drawn to one of them (you could fix that with Bangle.drawWidgets();g.flip();Bangle.dra­wWidgets().

    What I'd suggest is the offscreen buffer as you say, with a palette which you could cycle (which would actually be more efficient to render anyway). Looking at it, it likely wouldn't have to be full-res - maybe 1/2 or 1/3 res?

    Something like this might do it:

    const imgGfx = Graphics.createArrayBuffer(w, h, 8);
    const pal = new Uint16Array(256);
    const img = {width: w, height: h, bpp: 8, palette: pal, buffer: imgGfx.buffer};
    //....
    g.drawImage(img, 0,24, {scale:2});
    

    Math.random isn't random enough

    Hmm, I'd be surprised about that to be honest. While it's Pseudo-random it's quite a well-used algorithm.

  • OK @Gordon I understand the concept, but I'm missing some details (I was never good at graphics programming)

    First off, before I did try to create an 8bpp image I usually get LOW_MEMORY warnings - so I gave up and stuck to the doublebuffer and drawing.

    I looked at the animated clock example - I see they have a pre-computed palette file that is some binary data? For the Uint16Array I don't quite understand what needs to go in it?

    At the moment I'm using RGB values, and when drawing converting them to the correct 0...1 value.

    I assume from what I'm reading the array maps to each individual pixel? Instead of shifting the data, I'd just move the palette X pixels to the left to right? In that case, do I need to draw a background, or am I just palette shifting at this point to get the same desired effect?

    Then I assume here it's draw image and flip? (or is clear better?)

  • I did try to create an 8bpp image I usually get LOW_MEMORY

    Yes - you have around 40k memory usable - if you go for full resolution you can't really store a full res image, but if you go for half res, maybe 120*80, that's then 9600 bytes which should fit fine.

    I see they have a pre-computed palette file

    Yes - this is just one 16 bit entry for each of the 256 colours you can have in the image. The 16 bits are the form the LCD takes, which is RGB565. For example https://github.com/espruino/BangleApps/b­lob/master/apps/geissclk/precompute.js#L­4

      for (var i=0;i<256;i++) {
        var r = 0 to 255;
        var g = 0 to 255;
        var b = 0 to 255;
        pal[i] = (b>>3) | ((g&0xFC)<<3) | ((r&0xF8)<<8); // push the data into 16 bits
      }
    

    Or It's actually more sensible to just use pal[i] = g.toColor(r,g,b) (works the same as g.setColor) - I just keep forgetting it's there!

    Instead of shifting the data, I'd just move the palette X pixels to the left to right? In that case, do I need to draw a background, or am I just palette shifting at this point to get the same desired effect?

    You can just palette shift - so basically the only time you need to redraw with imgGfx is when the time changes.

    Then I assume here it's draw image and flip? (or is clear better?)

    You don't even need a flip (because you won't be using the double buffered mode any more). You literally just draw.

    Because you'll be drawing the new image over what's there already, there shouldn't be any flicker

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

Screen draw and LCD timeout (esp with doublebuffered)

Posted by Avatar for tanepiper @tanepiper

Actions