Working around the lack of an XTINY font on the Fenix 5

I just posted this image in another thread showing the difference in the font sizes between the Fenix 3 and the Fenix 5.



And it got me wondering if anyone else is experiencing some challenges porting apps to the Fenix 5 with the loss of a truly extra tiny font? I know that there's nothing to be done really other than use a custom font as a workaround but I'm curious if anyone else relies on the extra tiny font to display "nice to have" info but without sacrificing too much screen real estate.

I'm guessing the authors of some of the popular and complex watch faces, like ActiFace and GearMin, will be challenged to port their watch face over the Fenix 5 series while at the same time keeping the look the same. Even keeping it close to the same might be a challenge given the dramatic difference in size between XTINY on the two devices.

Cheers,
Douglas
  • Actually, an option is to change your widget into a watch-app, as while a widget can only be 58k, a watch app can be 122k. You'll loose the "quick view" nature of a widget. Or do a widget for the 5x and a watch-app for the 5s and 5.
    Thanks. I had not thought of that option.
  • And finally, given that I can put a microSD card measuring 15x11×1 mm with 64 GB on it into my phone I see little reason why you would have available memory limits for apps in the kBs, unless it's a hardware and/or OS issue.


    There is actually another memory limit for CIQ you may not have run into get. There is a limit of 16 CIQ apps installed on the watch ("slots"). There is also a max for how much mass store space can be used by all the CIQ apps. On a phone, you can see this info with <your device>/Connect IQ/Manage Storage. The mass store space used by an app can be very different than how much memory it uses to run. - an app that peaks at 48k memory, could be far larger in mass store space, due to bitmaps that get loaded when needed, it being a build with the debug symbols, etc. (I've seen apps that run in less than 64k, that take 100-200k of mass store space)

    The limit on some devices is only 1meg for all 16 apps together, and the store won't let you load (or even update) an app that would put you beyond the limit. It's so there's always enough mass store space for things like FW updates, and recording activites.
  • There is also an object limit. I hit this before the memory limit and had to combine objects as a workaround and split them up as needed.
  • Thanks. I had not thought of that option.


    Actually something else to consider is widgets aren't just for watches, as you can do them on the Edge, Oregon, and Rino devices too (you can also do apps for those), and memory sizes on some are quite large for CIQ. It kind of depends on what your app is used for.
  • There is also an object limit. I hit this before the memory limit and had to combine objects as a workaround and split them up as needed.


    You may be able to restructure your data and avoid the problem all together. (hint1: DO NOT use large multidimensional arrays! :) )

    Maybe post how you handle "large data" (even a code snip), and someone can suggest a cheaper (object wise) way to do it.

    update: here's a thread that goes into objects counts and things to do.
    https://forums.garmin.com/showthread.php?367458-Capacity-of-MC-on-VA-HR
  • In the past one of my watchfaces was about 450 KB. It was working fine in Fenix 3 but a user complained for his Vivoactive. Then I limited colors to 16 color palette and with other optimisations decreased it to 120KB; so that it worked fine later. Memory limit wasn't a big issue with limited colors. With newer watches processor speed and SRAM dedicated to CIQ increased but with colors but I hoped limits increased more...
    At first it was fun to code. I wrote my game before I bought my F3. But then different devices with different screens, it turned hard to keep up all watchfaces up to date. I even wouldn't surprise if F5 had a triangle display. :D Now, we have new devices with different font properties and screen sizes. Also I can't run their emulator on Linux like old versions...
  • You may be able to restructure your data and avoid the problem all together. (hint1: DO NOT use large multidimensional arrays!


    I would like to know why multi-dimensional arrays are an issue, and take up more space. That is, I know that they do but I don't understand why.

    The memory used by an array should basically be a contiguous block regardless of dimension. Then for multi-dimensional arrays there should be a few extra bytes describing the dimensions, at least with most languages I've ever dealt with. Is there something I'm missing with respect to multi-dimensional arrays on small memory footprint hardware or is this a case of an implementation that needs some major improvement?

    Cheers,
    Douglas
  • I think multi dimensional arrays are a problem since each entry is a separate object which needs to be reference counted so it's not simply a matter of the memory they use. There is an object limit as well as a memory limit.

    This was indeed my problem. I had a large mxn array, but either all of a row was needed or none. So, I changed it into a single dimensional array of strings ~ separated. I wrote a split function to split a row into it's own array when I needed the data from that row.

    So, the same memory was probably needed but a factor of n fewer objects.
  • I would like to know why multi-dimensional arrays are an issue, and take up more space. That is, I know that they do but I don't understand why.

    MonkeyC has a limit to the number of complex objects that you can use. A normal array like array below is 1 complex object.

    var array = new [100];


    If you have a multidimensional array that is 100x2 like array below, it is stored as one array with 100 elements, and 100 arrays with two elements. That array alone would count 101 objects toward the limit.

    var array = new [100];
    for (var i = 0; i < array.size(); ++i) {
    array= new [2];
    }
    [/CODE]

    The memory used by an array should basically be a contiguous block regardless of dimension.

    No. MonkeyC doesn't have a native multidimensional array, so most people implement it as shown above. You could implement one that allocates a single contiguous block and maintains an array of the dimensions, something like this...

    class MultiArray
    {
    function initialize(dims) {
    Test.assertNotEqual(dims.size(), 0);
    _M_dims = dims;

    var elements = 1;
    for (var i = 0; i < _M_dims.size(); ++i) {
    elements *= _M_dims;
    }

    _M_data = new [elements];
    }

    hidden function _index(indices) {
    Test.assertEqual(_M_data.size(), indices.size());

    // I think this part is right, but I've not compiled it
    var index = indices[0];
    for (var i = 1, j = indices.size(); i < j; ++i) {
    index = (_M_dims* index) + indices;
    }

    return off;
    }

    function get(indices) {
    return _M_data[ _index(indices) ];
    }

    function put(indices, value) {
    _M_data[ _index(indices) ] = value;
    }
    }
    [/CODE]

    or is this a case of an implementation that needs some major improvement?

    Personally, I don't think it is necessary. Few have needed a multidimensional array, and when they do they can usually only need a 2d array, which is implemented pretty easily. If they need a N-dimensional array, it does take a bit more work, but I've never seen someone needing that.

    Travis
  • I would like to know why multi-dimensional arrays are an issue, and take up more space. That is, I know that they do but I don't understand why.

    Travis explained it, it's not so much the memory, but the objects used. There is a limit of 512 (IIRC) objects with 2.x apps.

    using a 100x2 example, as Travis said, that takes 101 objects. And if you decide to make it 150x2, it's 151, so if you increase the size you increase the objects needed.

    Some easy ways to get around this:

    1) use a separate arrays for the second dimension, so you would have something like
    var dim0=new[100];
    var dim1=new[100];

    Only 2 objects are used, and if you change to 150 from 100, still only 2

    2) use a single array, but large enough for both dimension (this could also be used where the dimensions can change at runtime)
    if you wanted it to act like a 100x2, make it 200 long, and do something like using 0-99 for dim0 and 100-199 for dim1.
    This is the cheapest object wise, at it always uses just 1 object.

    And in the event you wanted 100x5, the same logic could be used (new[100*5]), and still only 1 object.

    If the "100" part isn't a fixed thing (say you want to increase it's size it if you are running on a device with more memory, you do do something like:

    var maxsz=100;
    if(<on device with more memory>) { maxsz=250;}

    var array=new[maxsz*5];

    and still only one object. And if you wanted an option where the 5 could be 10 (so 250x10 in some cases instead of 100x5), you could use the same basic logic. For the 1) approach, you'd have to know the second dimension before hand to have proper number of arrays, and # of objects would go up by one for each dimension.

    -----------
    Once you have your object-cheap simulated 2 dimensional array, how you store something can make a difference too. Let's say you want to have an array of 500 lat/lon pairs. How you store the data in the array can be an impact. See the thread starting at this post in the thread I linked above:

    https://forums.garmin.com/showthread.php?367458-Capacity-of-MC-on-VA-HR&p=936474#post936474