Facade
A dual world time zone analog watch face for most Garmin watches.
Analog watch face with support for dual world wide time zones,
features include:
- Analog face with second hand
- Second timezone selectable from 327 countries/cities
- Day of week and day month
- Metrics can be shown in each of the 4 corners (ignoring the fact that this is a round watch face with no corners)
- Battery charge indication
- Heart rate
- Total daily step count
- Phase of the moon
- Calories expended
- Distance traveled
- Meters ascended
- Active minutes
- Rrespiration rate
- Current temperature
Note the red or green triangle on the
outer edge of the dial.
This triangle marks the hour hand position
for the second time zone (or the
first time zone if there is no
second timezone selected).
This triangle will be red to indicate
AM and green to indicate PM.
For example,
the clock face on the left shows the
local time of 10:10AM,
the clock face in the middle shows the
local time of 10:10PM,
and the clock face on the right shows the
local time of 11:33AM when it's 5:33PM
in Central European Time.
The main timzone is always displayed by
the analog clock in the center of the display
with hour, minute, and second hands. If a second
timezone is selected then the hour of that timezone is shown by
the triangle on the edge of the face.
If the second timezone is not Local then the 3-5 letter
abbreviation for that timezone is shown at the bottom
of the watch face.
A triangle on the outer edge shows
the hour of the second timezone.
If the second timezone has a 0 minute offset
then the main minute hand is correct for both
the main and second timezones.
If the second timezone has a non-0 minute
offset then a yellow dot is displayed on
the outer edge
(you can interpret the second minute by
observing the distance the second hour
triange is between two hours but that
is rather difficult,
the yellow dot is a lot easier).
Daylight Savings Time (DST) is automatically
detected for USA/CANADA/EU.
The indicated time will be moved forward
during DST and the timezone abbreviation
displayed with be the one for DST.
For other timezones there is a setting
that can be set
(using Connect IQ or Garmin Express,
this is no available on the watch itself
as it would make the watch settings too
The Main DST and Second DST
settings can be set to one of 3 different values:
- Auto - Automatic detection. Works for USA/CANADA/EU,
all others will always display standard time.
- Off - This timezone will only display standard time.
- On - This timezone will only display DST time.
Timezones
can be selected from one of 327 countries.
The user can select which metric to display
in the 4 different corners of the watch face.
You can obtain this watchface from the Connect IQ store.
or by going to
this
direct link.
Facade is licensed under the GPL V3.0.
The latest source tree is available
for browsing
here
and tarballs for the latest and older versions are located at the following links:
Configuration
The watch face can be configured from the Connect IQ store,
the Garmin Express app,
or the watch itself.
The most convenient way to configure things
is from the on device settings
(screenshots of these settings are pictured above)
on the watch itself
(these instructions are for
the Venu, your mileage may
vary for other models):
- press and hold the back button
- tap on Watch Face
- tap on the pencil icon below the Facade watch face image
- finally tap on Settings
Note that there is no way to cancel changes,
the only way out of the configuration menu
is to press the back button which will save
the current settings.
Timezone configuration
Tap either the Timezone 1 and Timezone 2
buttons
(which show the currently selected timezones
as sub-labels)
to bring up the timezone select menu.
This menu shows 28 selections:
- Cache - brings up a cache of the
last 8 timezones that have been selected.
This cache makes it easy to switch
between a set of commonly used
timezones.
Every time a timezone is selected,
either for the first or second timezone,
that timezone is added to this cache.
- USA/Local - brings up a list
of the local timezone and the USA timezones
(sorry, I'm from the USA, I wrote the program,
I'm allowed to be a little USA centric).
- A-Z - tapping one of these
letters brings up a page with all the timezones
that begin with that letter.
Trying to navigate through 327 different timezones
on a watch face is still cumbersome but,
hopefully
(especialy with the cache),
it is still doable on this watch.
Seconds
Tapping on the Seconds button brings up
the Second indicator page.
From here you can customize how seconds are
displayed on the watch:
- Seconds - tapping on this button
configures the second hand to either a
traditional sweep hand, a diamond shape the
moves around the outer edge of the bezel,
or having the bezel minute hash marks change
color sequentially around the bezel.
- Color - tapping this button
changes the color of the second indicator from
red -> green -> blue -> cyan -> magenta -> yellow
-> white -> custom.
Note that the custom color can only be changed
from the Connect IQ store or the Garmin Express app,
trying to input a 6 digit hex number on the watch
itself is too difficult.
Controls
Tapping this button brings up a page
with buttons that control the operation
of the watch face:
- AM/PM -
Tapping this button switches between one of
three different settings for the AM/PM indication:
- AM/PM off -
there is no AM/PM indication
on the watch face
(I guess you have to look out the window and see
if the sun is shining).
- PM only -
in the afternoon PM will be shown just below
the center of the watch.
- AM/PM -
an AM or PM,
as appropriate,
will always be displayed just below
the center of the watch.
- Hands CCW -
if set the hands of the watch will run
counter clockwise.
(I don't recommend using this all the time
unless you're a masochist that likes headaches,
it is remarkably disconcerting to read
the time when the hands are going backward but,
as a prank, you can really mess with someone who
insists upon borrowing your watch).
- Backing store -
many Garmin watches have a backing store
bitmap that can be used to more efficiently
update the display, especially when changing
just the seconds indicator.
Unfortunately,
because of technical issues
1
, I don't recommend using this
backing store.
If you are having performance issues
(second indicator randomly pausing)
you can try this option but it
really shouldn't be needed.
- Reset TZ cache -
this will reset the timezone cache
so that all entries are deleted
except one for the Local timezone,
and, as an obvious side effect, this will
set the main and secondary timzones to Local.
Metrics
Metrics display,
at a glance,
certain information maintained
by the watch.
Most of the metrics are just
a number to represent the metric
and an icon below that number
to indicate which metric is
being display.
Each corner of the watch
can be independently configured
to show nothing or one of the
10 available metrics.
-  Battery percentage.
Shows the current battery level as a percentage
of the maximum charge.
An arc surrounds the number giving an
analog indication of the charge percentage,
going from a full circle for 100% to a half
circle for 50% to nothing for 0%
(although the whole screen will probably
be blank if the battery is truly at 0%).
Also the color of this metric changes
to indicate the level of charge going
from green (50% - 100% charge),
to yellow (25% - 50%),
and finally red (less than 25%).
-  Heart rate.
Current heart rate measured in Beats Per Minute (BPM).
-  Step count.
Steps taken since midnight.
-  Moon Phase.
This will show an icon that shows an approximation
of the moon phase.
More details about the moon phase icon are found in the
Moon Phase Indicator section.
-  Calories expended.
Calories expended during the day, measured in kCals since midnight.
-  Distance traveled.
$istance traveled throughout the day, measured in kilometers since midnight.
-  Meters ascended.
Vertical distance ascended, measured in meters since midnight.
-  Active minutes.
Time not spent lazing on the couch.
-  Respiration.
How fast you are breathing, measured in Breaths Per Minute (BPM).
-  Temperature.
Shows the cached value for the temperature as reported by the watch.
Personally, I have two problems with the temperature metric:
- Stale cached data.
The watch only caches the last weather data from the attached phone,
which typically updates its data every 20 min
(I've heard rumors that Apple phones only
check the weather every hour).
To give some hint of how stale the
weather data is Facade will
colorize the temperature metric,
going from green
(data less that 35 min old),
to yellow
(data less that 65 min old)
to orange
(data less that 125 min old)
to red
(data greater than 125 min old).
- Locaion.
Note that the temperature reported is
not the temperature where you are standing.
Garmin gets its weather data
from the closest official
weather station.
Note the two ill defined terms in that
sentence.
Since Garmin refuses to identify which
weather station it is using you are left
to assume that the watch is showing
you the temperature somewhere,
presumably nearby.
Moon Phase Indicator
The moon phase is displayed as one of
30 different icons
going from new moon to full moon and back.
The new moon and full moon icons are in white to
distinguish them from all the other phases.
Waxing phases are in green while waning phases
are in tan.
Moon phase approximation
(Basically an apology for why Facade is only
approximately correct about moon phases.)
There are two issues that make identifying the
correct moon phase extremely hard:
- Lunar cycle
The moon completes its cycle of phases
in 29.5 days
(more precisely in 29.530588853 but who's
keeping track).
- Lunar orbit
It's an elipse rather than a circle
which means the various phases other than
a new moon can appear at slightly
different times during the lunar cycle.
This makes computing the precise
moon phase extremely difficult and
way beyond the capabilities of Facade.
Having said that,
Facade attempts to be fairly
accurate.
It calculates the current lunar
day by
comparing the current date to the
reference date of the new moon on
January 6, 2000
(I wanted to use the reference
date of Januaray 1, 1900 but the
Garmin date/time routines don't
like dates before the Unix epoch
of January 1, 1972), modulo 29.5(30588853).
This calculation seems to be fairly
accurate
(the same calculation
is certainly correct for
the 44,206 days from the new moon on
January 1, 1900
to the new moon on
January 12, 2021).
This results in a lunar day of 1 - 29
(actually, some months it turns out
to be 1-30 because of roundoff with the
lunar period).
The lunar day is then converted into
one of 30 different icons
(representing the moon
waxing from new moon to full moon and
then waning back to a new moon).
Note that the icons for the day of the
new and full moon are obvious since they
are in white.
Conversely, the icons for the gibbous
moon a few days before and after the
full moon look very similar to a full moon,
this is where the tan and green colors
are handy.
Building from soure
Building from source is just a matter of installing
the source tree in Monkey C Visual Code Studio
and then do a build,
that should work just fine.
The problem comes in if you need to change
the timezone data like adding a new timezone
or deleting one.
By definition the Garmin architecture
requires at least 2 linked source files,
the settings.xml file that shows
the timezones presented to the user in the
settings app and the actual timezone data
that is encoded in the Tz.mc
file.2
Basic design
The basic design is to do the obvious,
the settings.xml entries have an index
and then that index is used to select
the appropriate entry from a table
in the Tz.mc file.
There are 2 problems with this basic design:
- Having 2 different files that need to
be kept in sync is a maintenance nightmare
and devotely to be avoided.
- Keeping all the data for 327 timezones
consumes a noticable amout of memory.
The second problem was exacerbated by the
original design which was to encode the
timezone info into an array where each
element of the array had 5 items to identify
the timezone - minute offset, standard time abbreviation,
daylinght savings abbreviation, automatic timezone
algorithm, and full name, e.g.
var TzData = [
[ +(0*60+0), "", "", -1, "Local" ],
[ -(5*60+0), "EST", "EDT", 0, "USA, East" ],
.
.
.
];
This design,
which was obvious and made
things simple at run time,
blew the memory available on
devices like a Forerunner 55.
Chunk design
The original solution to the
memory problem
was solved by breaking up the timezone
data into 25 entry chunks and then storing each chunk
is a separate MC file,
the TzData0.mc
to TzData13.mc files.
This way the code only has to have in memory
25 timezone entries at a time rather than 327.
The code in Tz.mc did the translation
from one of the 327 timezone indices to
an appropriate index in the appropriate TzData
file.
With this design the code barely fits
in a Forerunner 55
(with only 4K of memory to spare).
String design
Unfortunately,
expanding the moon phase from 8
to 30 icons expanded the memory and
the code no longer fit on a Forerunner 55
(and no amount of futzing with the
TzData chunk size made it fit).
A new design is required.
Rather than storing separate data items
for each timezone entry
the code now just
stores a long string for each
timezone,
where each data item
(fullname, minute offset, standard time abbreviation,
daylinght savings abbreviation, and automatic timezone
algorithm)
is separated by a semicolon
within that string, e.g.
var TzData = [
"Local;0;;;-1",
"USA, East;-300;EST;EDT;0",
.
.
.
];
The downside to this design is that
we now have to parse the appropriate string
at runtime but the upside is a consderable
savings in memory.
This design saved approximately 20K of
memory and the code with 30 moon icons
now fits on a Forerunner 55 with plenty
of room to spare -
the
core/speed
3
trace off was definitely worth it.
Chunked string design
Adding support for on watch timezone settings
consumed more memory
4and, you guessed it,
blew the memory on a Forerunner 55,
yet another design required.
Fortunately,
the chunked design comes to the rescue.
The current design now puts all of the
timezone data strings into 27 different
files indexed by the first letter of
the country name
(26 letters in alphabet plus we put Local
and USA timezones in the 0th entry).
With this design we only need at most
40 timezone data strings in memory at
one time and now the program now fits on
a Forerunner 55.
Helper program
Although the new design obviates the
need for multiple TzData
files there is still a problem that
we have to keep multiple related files
in sync with each other -
the settings.xml used to
select timezones, the TzOffsets.mc
used to identify which country names begin
with the same letter,
and Tz?.mc
which contains all of the
actual timezone info.
The solution is to maintain a
canonical timezone data base file,
support/country.txt and
use the Pearl script support/tz.pl
to extrace everything we need from
the data file.
Running the command tz.pl support/country.txt
will generate a settings.xml file,
TzOffsets.mc file,
and all of the
Tz?.mc files.
After generating these files you have to
manually
(sorry about that,
there doesn't seem to be
a way to do includes in settings
files)
add the generated lines in settings.xml
to the appropriate places in the
actual resources/settings/settings.xml file.
Then copy TzOffsets.mc into source/TzOffsets.mc,
copy all of the Tz?.mc files
into source/TzData
and you should be ready to build.
1.
The backing store can exist in
two different areas - system memory or a
part of the users data space.
If your watch provides system backing store
then it will work just fine.
If your watch only provides user space backing
store then I can pretty much guarantee that
enabling this option will blow memory and
crash your watch (check out the
Building from source for more details
on the limited memory available in Garmin watches).
Since I can't test this watch face on every
single Garmin watch it is possible that
there might be performance glitches that
could be fixed by using the backing store
on your specific model.
Note that it is safe try to enable backing
store even on watches that don't have enough
memory to use it.
To use the backing store the code
temporarity disables this option,
allocates the backing store,
if the allocation works then it
re-enables this option and continues.
If the allocation fails then
this option is disabled and
restarting the watch will run
the watch face without backing store.
I have to do it this way because there's
no way to know before hand if there's enough
memory for the backing store and there's
no way to catch/recover from the memory fault
it allocatiing the backing store fails.
2.
What I really wanted to do was
to define a unique table of timezone data
(one entry per unique timezone info rather than
the current design of one entry per country)
and then
have the entries in the settings.xml file
index into the appropriate entry in that table.
Since there are multiple countries that share the
same timezone this would reduce the table size
needed in the code by about a factor of 2.
Unfortunately,
that design is not possible because
arrays in the settings.xml file
have to have unique indices.
3.
For the youngsters reading this
we used to refer to memory as
core
(Google memory core to see why)
back in the dark ages of computers.
Yes,
I'm old enough to remember those days.
4.
Can I just have a minor rant here that,
in the 21st century,
on a device with 32M of memory
(I'm talking to you Forerunner 55)
I still have to fight with a system
the only lets me have 96K of data space.
And on a Venu 3 with 8G of memory
I only have 128K of data to work with.