Better description of encodeNumber method (ByteArray class)

Hi,

is there anybody who can give me better description of encodeNumber method in the ByteArray class (CIQ 3.1.0+)? What does the format mean, value is an object (?), and are the options obligatory? Any examples? I'm totally lost and confused by the doc and simulator triggers exceptions for all my attempts to use it - what does the method really do? Thanks.

  • The main place I've seen encodeNumber and decodeNumber uses is in relation to BLE (data sent/received over BLE),  You'll see decodeNumber used in the NordicThingy52 sample in the SDK for example.

    It's used to build ByteArrays or read them.  What is it you're looking to do?

  • Thanks. I'm looking for the fastest (code is in OnPartialUpdate) conversion from the Number (0..100000, e.g. steps) to some digits array or decimal place values array because I want to process the result digit-by-digit (I would like to implement faster number displaying than standard drawText). I can use 'format', but it results in a string which is hard to access character-by-character. That's why I'm looking for a different method.

  • This won't do what you're looking for, as it will do something like take a Number and convert it into a byte representation of that value. using 1, 2, or 4 bytes for example.

  • Couple of things..  The easiest way to do what you want if just using math..

    if(steps>10000) {...}

    else if(steps>1000} {...}

    (etc)

    Also, last I checked, doing steps with 1hz (onPartical update), you only see steps change at most a few times a minute, and not every second, and you also want to include logic to only do  steps if the change, not each time onPartialUpdate is called.  You won't need to set a clip reason for them unless they changes, which can help the power budget.  And in general, if you have multiple clip regions, you want them as close together (row wise) as possible, as the more rows involed, the higher the hit on the power budget.  (The combined clip region is the lowest row to the highest row)

  • Thanks jim_m_58 for your time. I understand now - encodeNumber only projects binary representation of a number to byteArray, nothing for me.
    As for the conversion, I finished with the idea you described above -> I go from back with a sequence of "value % 10" and "value / 10" until value == 0, the chars are draw into dedicated bitmap buffer from right to left.
    And yes, I have a scheduler under onPartialUpdate, which triggers steps calculation 2 times per minute at max.:
    1. When the second hand is overlapping step field (somewhere around 45 sec) && the steps changed from last displayed value (I have to draw dedicated bitmap buffer anyway so I update steps value just before).
    2. When the second hand is in opposite side (around 15 sec)  when the y coordinates of the clipping area are close -> minimal impact on the clipping area extension in y axis.

    I also figured out that clipping area y coordinates has big impact on  the Display Time, whereas the x not (at simulator at least). I guess that Garmin uses SPI interface with DMA to transfer data from frame buffer in Cortex RAM to display memory. And as the display rows have horizontal arrangement and display memory contains pixels in row-by-row organization with 1 byte/pixel in my case (Fenix 5 Plus 2-2-2 color depth), it is more effective to transfer whole rows with only one DMA settings per whole clipping area instead of fractions of rows. So the most time demanding (on display time) is second hand around 0 and 30 sec. My solution is to move second hand once per two seconds. The question is about the mcu current consumption during execution/graphic time and display time. If, during display time, mcu only waits for DMA transfer complete in sleep... This is only speculation, I have to minimize all the times and then see the battery draining. Thanks again..

  • The display updates by row, so the more rows, the more impact on battery.

    What might not be clear is say you have a clip region that's 20 rows at the top of the screen and another at the 20 rows at the bottom of the screen, the combined clip region is from the top of the screen to the bottom, which can really impact your power budget.

    "View Watch Face Diagnostics" is handy to see how you're doing on the power budget, where you want to stay under a "total time" of 30000 at most times and you can see a slip as far as how that time is used.

    If you exceed the 30ms avg, you stop getting onPartialUpdate() calls, and if you're tight on 240x240 displays, you will run into problems on 280x280 displays.

  • Agree, I noted mentioned clip region behavior during my experiments with the analog watchface example. There are my observations for onPartialUpdate(dc) (CIQ 3.1.5):

    1. clearClip() is equivalent to setClip(0, 0, full_display_width, full_display_height) -> clearClip() seems to be only a shortcut.

    2. The x and width parameters in setClip() are only important for the draw commands (it works as a clipping rectangle). On the contrary, for the frame buffer (dc) to display memory copying (background display process), only the y and height are used, because the block of the whole rows is transferred to display memory in one bunch.

    3. To disable the copying from the frame buffer to the display memory after the onPartialUpdate() is finished (for example I want to skip drawing each odd second to be under 30 ms avg limit), there must not be any draw command to the frame buffer during this onPartialUpdate() call. Then it doesn't matter what the clip region coordinates at the exit of onPartialUpdate() are. The display time is 0 us.
    Note: Alternatively, it is possible to use conditional setClip(0,0,0,0) (or more generally setClip(?, ?, ?, 0)) just before any draw command within onPartialUpdate() to move all following draw commands out of the game. But I figured out that in this case the simulator shows nonzero but small Display time (~200us) if I draw something anywhere in the frame buffer. Probably zero height is not enough to block background display process totally.
    -> So my conclusion is: I must not draw anything to the frame buffer within onPartialUpdate() if I want not to run display process after onPartialUpdate().

    4. On onPartialUpdate() entry, the last clip region (from previous onPartialUpdate() exit) is preset (excluding onUpdate() effect). But it can be overwritten by setClip() just before any draw command is used.

    5. I can use setClip() several times in one call of onPartialUpdate(), but once I draw anything (even single pixel) to frame buffer, the last entered setClip() coordinates are memorized. If I change clip region by setClip() again and draw something into it, the memorized clip region coordinates are changed to cover both entered clip regions.

    -> There is a space for Garmin guys to replace the only one set of memorized clip region coordinates by the stack of, let's say, four or eight sets of clip region coordinates (the user do not need to know about it or, better say, the user do not need to care about it, because the API is the same). This enables to have several "live" fields, i.e. rectangular regions, where the contents can be updated each second with minimized impact on the Display time. Yes, it is possible to arrange such "live" fields to one line but sometimes it has an impact on the watchface lucidity.

    Note: What is interesting is that the setClip() region coordinates are memorized (or updates memorized one) even if I draw something out of the actual clip region, e.g.
        dc.setClip(50, 50, 20, 20);
        dc.drawPoint(0, 0);

    I hope that described behavior is correct and corresponds to yours.