1hz Watch Faces - Q&A

I'm not sure if many folks have been trying the new "always active" watch faces in 2.3.x, but the 2.3.0.beta1 has been out for a month or so now. It's probably getting close to the 2.3.1 SDK release, and thought I'd start a Q&A for the feature, and start with some of what I've picked up in adapting a number of watch faces to use 1hz.

I'll be calling this feature "1hz", as that's what it really is - being able to change the screen on a watch face every second.
The most common thing will likely being the ability to display seconds all the time. One thing I'll note right off, is while you can update the screen every second, the underlying data still changes at the rate it did before, so if you use 1hz for the HR, you won't see the HR change every second.

A few basics.

  • 1hz is only available on some watches. The f5, f5s, f5x, 935, and Q5, but if you support a bunch of different watches, you can easily have it on some and not others.
  • 1hz happens by way of a new onPartialUpdate() for watch faces. onUpdate() is just like it was in the past, and when you are allowed to do a 1hz update, onPartialUpdated() is called. You don't have to change a thing in your code if you don't want to use 1hz.
  • onPartialUpdate() is VERY strict as to how long it can run. You have a "power budget", and the rule is that each minute, the average run time each second can't be greater than 30 milliseconds. This is the tricky part! :)



I started with the Analog Sample in the SDK, which does show what to do, but has some things you don't need to do for digital watch faces - there's no second hand passing over a bunch of different places on the screen with a digital one. The time is in a fixed spot on the screen in most cases.



Anyway's, the first thing I did was cut back to the basics of what was needed for a digital WF. I'll attached a project with a very basic 1hz watch face, but first a few notes about it.

  • vs1hzapp.mc shows how to use the delegate for the power exceeded deligate on watches that have 1hz, and still run on watches that don't do 1hz.
  • vs1hzview.mc I tried to comment as to where to do things, where not to do things, but took a simple approach where I don't just update the seconds at 1hz, I actually do hh:mm:ss. In real code, you likely have a separate space for seconds, and your setClip() will be adjusted for that. I just wanted to get the ball rolling here :). Also, note onEnterSleep() and the code there for 1hz...
  • In onPartialUpdate(), I have a comment about a simple change to make the watch face exceed the power budget, so you can see how that works



Ask questions, suggest other ideas, whatever. That's what this thread is for!

So here's the project! (it might be a bit different than the original one that was lost in the forum update) :

VS1hz-old.zip



NOTE: I should have mentioned this before, but you want to use a 2.3.x SDK for this project!

  • You can draw anti-aliased fonts into a buffered bitmap if it does not have a reduced color palette. Buffered Bitmaps are not going to be useful for your moving objects. They are helpful when you have something slow to draw in the background of your display. For instance, text is slow to draw, and bitmaps are much faster. By creating a bitmap and drawing something like the date into it, you can redraw that behind a moving analog hand every second much more cheaply than if you had to blank and redraw the text from scratch.


    I am very happy to dig into the “how” to make things work. That’s the fun part! I do, however, need to understand the philosophy a bit more (the “when” and “why”).

    Let’s say I created this conceptual watchface (just a quick PowerPoint rendering, but imagine it’s a live watchface). Assume I currently redraw everything at every onUpdate using stock fonts and graphics tools (Gfx fonts, fill rectangle, drawline, and polygon tools), but now I want to support 1 Hz.

    If it is a partial update:
    • I would not update the green status bar every second. That can wait for the minute update.
    • Same with Day/Date. If the user selects a different day/date format from ConnectIQ mobile app, then the full onUpdate function is called anyway, correct?
    • Hour and minute would only be updated on full refresh.
    • That leaves the second hand only, I think.

    Do I create a buffered bitmap of the entire watchface before checking the second so that I can pull a partial section from it when updating the second hand? The on partial update, I "blank out" the last position by pulling from the specific region from the buffered bitmap?

    Since I am not limited the color pallet and since I am using stock font, I don’t not have to reprint the day/date if the second is over it, I can just pull from the buffered bitmap image, correct?
    community.garmin.com/.../1269137.jpg
  • Former Member
    Former Member over 7 years ago
    That all sounds correct. This is very similar to what the "Analog" sample found in the SDK does.

    One thing you may run into an issue with though is that a full screen/full color buffered bitmap will take up a huge percentage of your memory, which may significantly limit the code space you have left to work with. You may need to try to limit your colors for the full background and store the digit glyphs in smaller buffered bitmaps to use the AA fonts there. (The sample sort of does this. It uses non-AA fonts for the digits, but uses a separate buffer for the date, which does use an AA font)
  • It seems that something broke in the forum as far as .zip files. If you PM your email address to me, I'll send the same to you.. I'll also try posting it again here.

    Yeah, I'm resurrecting an old thread.

    Jim, is it possible to post your source again now? I wanted to see how you do the delegates.

    Right now I'm having SDK 3.0.2 giving me a warning, "Class 'AnalogDelegate' does not initialize its super class, 'WatchFaceDelegate'" even on the regular Analog sample. I'm hoping your source might be able to shed a little light onto this.
  • Out-o-breath Add the following to your AnalogDelegate:

    function initialize() {
    WatchFaceDelegate.initialize();
    }


    It seems the sample code need to be updated by the ConnectIQ team.
  • @Out-of-breath As far as the source for the sample, the forum seems to have problems with it for some users/browsers. PM me your email or use contact developer in the store, and I'll email it to you.

    But what Hermo posted is probably all you need.
  • HermoT Created a ticket to look into updating the Analog Delegate sample (weretech-6178).
  • Kamau.ConnectIQ Thank you for the quick response!
  • Thanks for this post and the quick response for issues I've faced :+1: