<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/rss-style.xsl" type="text/xsl"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	     xmlns:dc="http://purl.org/dc/elements/1.1/"
	   xmlns:atom="http://www.w3.org/2005/Atom"
	     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>watchy &#8211; Terence Eden’s Blog</title>
	<atom:link href="https://shkspr.mobi/blog/tag/watchy/feed/" rel="self" type="application/rss+xml" />
	<link>https://shkspr.mobi/blog</link>
	<description>Regular nonsense about tech and its effects 🙃</description>
	<lastBuildDate>Sat, 16 Aug 2025 08:02:24 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://shkspr.mobi/blog/wp-content/uploads/2023/07/cropped-avatar-32x32.jpeg</url>
	<title>watchy &#8211; Terence Eden’s Blog</title>
	<link>https://shkspr.mobi/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title><![CDATA[Fixing clock drift on the Watchy]]></title>
		<link>https://shkspr.mobi/blog/2023/08/fixing-clock-drift-on-the-watchy/</link>
					<comments>https://shkspr.mobi/blog/2023/08/fixing-clock-drift-on-the-watchy/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 16 Aug 2023 11:34:23 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[watchy]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=46450</guid>

					<description><![CDATA[I&#039;m getting increasingly annoyed with SQFMI&#039;s Watchy. The documentation is terrible, the device is fragile, and now it turns out that the &#34;Real Time Clock&#34; loses several seconds per day!  Which means, after a couple of weeks the watch is a couple of minutes fast.  Ugh.  But, on the other hand, you can reprogram it in C++. So swings and roundabouts...  Anyway, this is the code you need to stick…]]></description>
										<content:encoded><![CDATA[<p>I'm getting increasingly annoyed with <a href="https://shkspr.mobi/blog/tag/watchy">SQFMI's Watchy</a>. The documentation is terrible, the device is fragile, and now it turns out that the "Real Time Clock" loses several seconds <em>per day</em>!  Which means, after a couple of weeks the watch is a couple of minutes fast.</p>

<p>Ugh.</p>

<p>But, on the other hand, you can reprogram it in C++. So swings and roundabouts...</p>

<p>Anyway, this is the code you need to stick into your watch face to have it perform an NTP sync at, for example, 5am:</p>

<pre><code class="language-C">if ( minute == 0 ) {
  if ( hour == 5 ) {
    if (connectWiFi()) {
      syncNTP();
      WiFi.mode(WIFI_OFF);
      btStop();
    }
  }
}
</code></pre>

<p>You will need to have first configured your WiFi. You will also need to set your NTP server and preferred timezone in <code>settings.h</code>:</p>

<pre><code class="language-C">#define NTP_SERVER "pool.ntp.org"
#define GMT_OFFSET_SEC 3600 * +1 // GMT is 0, BST is +1
</code></pre>

<p>Now every morning you will start with a freshly sync'd watch - with minimal impact on the battery life.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=46450&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/08/fixing-clock-drift-on-the-watchy/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Discord is not Documentation]]></title>
		<link>https://shkspr.mobi/blog/2023/07/discord-is-not-documentation/</link>
					<comments>https://shkspr.mobi/blog/2023/07/discord-is-not-documentation/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 16 Jul 2023 11:34:04 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[rant]]></category>
		<category><![CDATA[watchy]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=46240</guid>

					<description><![CDATA[I&#039;m going to be slightly contrarian and say that I like Discord. It&#039;s great to be able to get real-time help on a problem. And it is fun to see, again in real-time, what other people are working on and struggling with.  In truth, Discord is no harder to sign up to than Slack, Matrix, Gitter, IRC, or whatever. And of course Open Source projects will follow the maxim of &#34;go where your audience…]]></description>
										<content:encoded><![CDATA[<p>I'm going to be slightly contrarian and say that I <em>like</em> Discord. It's great to be able to get real-time help on a problem. And it is fun to see, again in real-time, what other people are working on and struggling with.</p>

<p>In truth, Discord is no harder to sign up to than Slack, Matrix, Gitter, IRC, or whatever. And of course Open Source projects will follow the maxim of "go where your audience are". There's no point posting everything to MySpace when everyone's already on Facebook.</p>

<p>Do I care that Discord isn't open source? Well, kinda. But I can open it in Firefox and it works just fine.</p>

<p>Discord is perfect for <em>ephemeral</em> communications.</p>

<p>But it is not a fucking substitute for documentation!</p>

<p>I'm currently getting started, and increasingly frustrated, with the <a href="https://watchy.sqfmi.com/">Watchy</a> development platform. They've effectively said "here's a barebones guide to setting it up - anything else, ask on Discord" - and it fucking sucks.</p>

<p>There's no API documentation - I have to scroll through a million messages to find anything.</p>

<p>I can't use search, because people don't know how to thread. So I can see questions but not replies.</p>

<p>When I do find replies, it's hard to know how relevant they are.  A typical Discord chat looks like:</p>

<ul>
<li>Alice: What's the command to go fullscreen?</li>
<li>Bob: Anyone know how I irrevocably format my disk without confirmation?</li>
<li>Carol: Oh, yeah, it's easy. Just pass the <code>-f</code> flag.</li>
</ul>

<p>Errrr...</p>

<p>And then you get the people who get snippy with newbie for asking a question which is frequently seen!  So infuriating.</p>

<p>I'm not necessarily advocating for <a href="https://documentation.divio.com/">the Four-Document Model</a> - which has <a href="https://www.hillelwayne.com/post/problems-with-the-4doc-model/">some critics</a> - but I just don't understand why wouldn't at least collate all of the common questions and put the answers in one place.</p>

<p>Look, writing a FAQ is probably not the right way to approach comprehensive documentation. But if you can't even be bothered to do that, perhaps you shouldn't be releasing a product in the first place?</p>

<p>/rant</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=46240&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/07/discord-is-not-documentation/feed/</wfw:commentRss>
			<slash:comments>14</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[A whimsical fuzzy clock]]></title>
		<link>https://shkspr.mobi/blog/2023/07/a-whimsical-fuzzy-clock/</link>
					<comments>https://shkspr.mobi/blog/2023/07/a-whimsical-fuzzy-clock/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 13 Jul 2023 11:34:07 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[watchy]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=46216</guid>

					<description><![CDATA[I&#039;m sure I remembered there once being a clock app for Linux which was deliberately vague.  It would declare the time as &#34;Nearly tea-time&#34; or &#34;A little after elevenses&#34; or &#34;Quite late&#34; or &#34;Gosh, that&#039;s early&#34;.  But I can find no evidence that it ever existed and am beginning to wonder if I dreamt it.  So I built it.  First thing&#039;s first - there are a lot of existing fuzzy clocks. But they mostly…]]></description>
										<content:encoded><![CDATA[<p>I'm sure I remembered there once being a clock app for Linux which was deliberately vague.</p>

<p>It would declare the time as "Nearly tea-time" or "A little after elevenses" or "Quite late" or "Gosh, that's early".</p>

<p>But I can find no evidence that it ever existed and am beginning to wonder if I dreamt it.</p>

<p>So I built it<sup id="fnref:I"><a href="https://shkspr.mobi/blog/2023/07/a-whimsical-fuzzy-clock/#fn:I" class="footnote-ref" title="OK, I prompt-engineered my way to success" role="doc-noteref">0</a></sup>.</p>

<p>First thing's first - there are <a href="https://askubuntu.com/questions/750815/fuzzy-clock-for-ubuntu">a <em>lot</em> of existing fuzzy clocks</a>. But they mostly say things like "afternoon" or "nearly 3 o'clock". There's even a <a href="https://github.com/BraininaBowl/Hobbit-Time-for-Watchy">Hobbit Time for Watchy</a>. However, I wanted something a bit more vague and human than those.</p>

<p>Here's an example of what I mean:</p>

<pre><code class="language-C">    if (hour &gt;= 5 &amp;&amp; hour &lt; 7) {
        printf("Blimey! That's early.\n");
    } else if (hour &gt;= 7 &amp;&amp; hour &lt; 11) {
        printf("Good morning! Rise and shine!\n");
    } else if (hour &gt;= 11 &amp;&amp; hour &lt; 13) {
        printf("Goodness me! Elevenses!\n");
    } else if (hour &gt;= 13 &amp;&amp; hour &lt; 17) {
        printf("Afternoon tea time! Care for a cuppa?\n");
    } else if (hour &gt;= 17 &amp;&amp; hour &lt; 20) {
        printf("Evening is upon us. Time to unwind.\n");
    } else if (hour &gt;= 20 &amp;&amp; hour &lt; 23) {
        printf("Nighttime adventures await! Off we go!\n");
    } else {
        printf("Bedtime beckons. Rest well, my friend.\n");
    }
</code></pre>

<p>And here they are rewritten as Shakespearean-style timestamps:</p>

<pre><code class="language-C">   if (hour &gt;= 5 &amp;&amp; hour &lt; 7) {
        printf("Good morrow! 'Tis the break of day.\n");
    } else if (hour &gt;= 7 &amp;&amp; hour &lt; 11) {
        printf("Hail, fair morn! Arise and be joyful.\n");
    } else if (hour &gt;= 11 &amp;&amp; hour &lt; 13) {
        printf("Goodness me! 'Tis the hour of elevenses!\n");
    } else if (hour &gt;= 13 &amp;&amp; hour &lt; 17) {
        printf("Afternoon doth approach! Wouldst thou like some tea?\n");
    } else if (hour &gt;= 17 &amp;&amp; hour &lt; 20) {
        printf("Evening doth draw nigh. 'Tis time to unwind.\n");
    } else if (hour &gt;= 20 &amp;&amp; hour &lt; 23) {
        printf("Nightfall is upon us. Adventure beckons!\n");
    } else {
        printf("Bedtime doth approach. Rest well, good sir/madam.\n");
    }
</code></pre>

<p>And here we come to a central problem with any fuzzy system - repetitiveness.   How to make it say something new every time it is called?  I guess there are three main approaches:</p>

<ol>
<li>An exhaustive list of every possible saying.</li>
<li>A computable way of saying "[Gosh|Blimey|Wow] it's [almost|nearly|just gone] [morning|lunchtime|snooze o'clock]"</li>
<li>Use an LLM every time to generate something new.</li>
</ol>

<p>I had some success with 1. I got the AI to spit out dozens of responses.
<img src="https://shkspr.mobi/blog/wp-content/uploads/2023/07/responses-fs8.png" alt="Beneath the moon's glow, secrets find their release.
In this enchanted hour, let desires run wild.
Tread lightly, for mischief lurks in every shadow.
Oh, sweet temptation! Yield to its seductive call.
In the realm of dreams, reality fades away.
Embrace the whimsy that dances upon moonlit beams.
Amidst the night's embrace, secrets are whispered." width="772" height="627" class="aligncenter size-full wp-image-46217"></p>

<p>But they either need manually fitting into appropriate timeslots, or a bit more prompt-work to get the LLM to spit them out in the right order. Even with a few hundred, it's likely to get repetitive quickly. And, on an embedded system, are liable to take up a lot of memory.</p>

<p>Option 2 also has similar drawbacks. Even with a large amount of stock phrases, the structure and permutations will start to become noticeable. It's possible to reduce that with an enhanced semantic structure - but it becomes quite complex to automate.</p>

<p>Finally Option 3. Ah... It is computationally expensive (not to mention financially prohibitive) to call a network API every time we want to know the time. And on a battery-powered system, every time the WiFi has to wake is a dent in the longevity of the device.</p>

<p>My ultimate goal is to have this as a fuzzy-watchface for the <a href="https://shkspr.mobi/blog/2023/06/review-watchy-an-eink-watch-full-of-interesting-compromises/">Watchy eInk device</a>.</p>

<p>At the moment, my plan is to use a mixture of 2 and 3.</p>

<p>If you've done something like this before, please let me know 😊</p>

<div id="footnotes" role="doc-endnotes">
<hr aria-label="Footnotes">
<ol start="0">

<li id="fn:I">
<p>OK, I prompt-engineered my way to success&nbsp;<a href="https://shkspr.mobi/blog/2023/07/a-whimsical-fuzzy-clock/#fnref:I" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

</ol>
</div>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=46216&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/07/a-whimsical-fuzzy-clock/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[How to make the Watchy vibrate]]></title>
		<link>https://shkspr.mobi/blog/2023/07/how-to-make-the-watchy-vibrate/</link>
					<comments>https://shkspr.mobi/blog/2023/07/how-to-make-the-watchy-vibrate/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 09 Jul 2023 11:34:42 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[watchy]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=46247</guid>

					<description><![CDATA[I am enjoying playing with the eInk Watchy. It is a cute package and is everything I want in a Smart-Watch; geeky, long battery life, and not obnoxious.  But - fuck me! - the documentation is atrocious! Well, that&#039;s a lie. There is no documentation. It has the &#34;Chat to us on Discord&#34; anti-pattern that infects so many otherwise great projects.  So I&#039;m left to figure out how to make the Watchy&#039;s…]]></description>
										<content:encoded><![CDATA[<p>I am enjoying playing with the eInk Watchy. It is a cute package and is everything I want in a Smart-Watch; geeky, long battery life, and not obnoxious.</p>

<p>But - fuck me! - the documentation is atrocious! Well, that's a lie. There is no documentation. It has the "Chat to us on Discord" anti-pattern that infects so many otherwise great projects.</p>

<p>So I'm left to figure out how to make the Watchy's haptics work.</p>

<p>The example watchfaces have a file called <code>settings.h</code> which contains <a href="https://github.com/sqfmi/Watchy/blob/342eb48a497eb3dcb1ec03c5c156937fdec07ba9/examples/WatchFaces/7_SEG/settings.h#L24"><code>.vibrateOClock = true</code></a>. Set that and you'll get a little buzz on the hour, <em>every</em> hour.</p>

<p>But how do you make it buzz when you've hit your step-count goal? Or when the time is 13:37? Or whenever <em>you</em> want?</p>

<p>There's no documentation. And searching the code for "vibrate" or "vibe" or "vibration" yielded nothing.  But I accidentally typo'd my search and entered "vib" - and that did the trick.</p>

<p>In <code>config.h</code> there's this line: <a href="https://github.com/sqfmi/Watchy/blob/342eb48a497eb3dcb1ec03c5c156937fdec07ba9/src/config.h#L25"><code>#define VIB_MOTOR_PIN 13</code></a>.</p>

<p>So, pin 13 is wired in to the vibration motor. We can add that line to our own config file. But how do we turn the buzzer on and off?</p>

<p>With a bit of help from Discord, it became clear:</p>

<pre><code class="language-c">pinMode(VIB_MOTOR_PIN, OUTPUT);     // Set vibration motor pin as an output.
digitalWrite(VIB_MOTOR_PIN, true);  // Enable vibration motor
delay(150);                         // Vibe for 150 ms.
digitalWrite(VIB_MOTOR_PIN, false); // Disable vibration motor.
delay(500);                         // Wait half a second
digitalWrite(VIB_MOTOR_PIN, true);  // Enable vibration motor
delay(250);                         // Vibe for quarter of a second
digitalWrite(VIB_MOTOR_PIN, false); // Stop vibrating
</code></pre>

<p>That's the same as the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/vibrate">HTML5 Vibrate API</a> - you can't control the intensity, but you can <a href="https://shkspr.mobi/blog/2014/01/malicious-use-of-the-html5-vibrate-api/">program your own vibration patterns</a>.</p>

<p>I just don't understand why hardware vendors are <em>so</em> crap at writing documentation. Don't they like people using their products?</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=46247&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/07/how-to-make-the-watchy-vibrate/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[An eInk, Wrist-Mounted, TOTP Generator]]></title>
		<link>https://shkspr.mobi/blog/2023/07/an-eink-wrist-mounted-totp-generator/</link>
					<comments>https://shkspr.mobi/blog/2023/07/an-eink-wrist-mounted-totp-generator/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 08 Jul 2023 11:34:09 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[2fa]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[eink]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[watchy]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=46213</guid>

					<description><![CDATA[Behold! Thanks to the power of the Watchy development platform, I now have all my 2FA codes available at the flick of my wrist!    HOWTO  This uses Luca Dentella&#039;s TOTP-Arduino library.  You will need a pre-shared secret which is then converted into a Hex array. Use the OTP Tool for Arduino TOTP Library to get the Hex array, Base32 Encoded Key, and a QR Code to scan into your normal TOTP…]]></description>
										<content:encoded><![CDATA[<p>Behold! Thanks to the power of the <a href="https://shkspr.mobi/blog/2023/06/review-watchy-an-eink-watch-full-of-interesting-compromises/">Watchy</a> development platform, I now have all my 2FA codes available at the flick of my wrist!</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2023/07/Wrist-TOTP.jpg" alt="A chunky wristwatch showing the time and a selection of 6 digit codes and their corresponding entities." width="1024" height="1024" class="aligncenter size-full wp-image-46214">

<h2 id="howto"><a href="https://shkspr.mobi/blog/2023/07/an-eink-wrist-mounted-totp-generator/#howto">HOWTO</a></h2>

<p>This uses <a href="https://github.com/lucadentella/TOTP-Arduino/">Luca Dentella's TOTP-Arduino library</a>.</p>

<p>You will need a pre-shared secret which is then converted into a Hex array. Use the <a href="https://www.lucadentella.it/OTP/">OTP Tool for Arduino TOTP Library</a> to get the Hex array, Base32 Encoded Key, and a QR Code to scan into your normal TOTP generator.</p>

<p>Add the Hex array into the code below.</p>

<p>To check that it is functioning correctly, either scan the QR code from the OTP Tool above, or use the Base32 Encoded Key with <a href="https://totp.danhersam.com/">an online TOTP generator</a>.</p>

<p>Here's how the code interfaces with the Watchy:</p>

<pre><code class="language-c">#include &lt;Watchy.h&gt; //include the Watchy library
#include "settings.h"
#include "sha1.h"
#include "TOTP.h"

class MyFirstWatchFace : public Watchy{ //inherit and extend Watchy class
    public:
        MyFirstWatchFace(const watchySettings&amp; s) : Watchy(s) {}
        void drawWatchFace(){

          ...

          RTC.read(currentTime);
          time_t epoch = makeTime(currentTime) - 3600; // BST offset


          // The shared secret - convert at https://www.lucadentella.it/OTP/
          uint8_t hmacKey[] = {}; // e.g. {0x4d, 0x79, 0x4c, 0x65, 0x67, 0x6f, 0x44, 0x6f, 0x6f, 0x72};
          int hmacKeyLength = sizeof(hmacKey) / sizeof(hmacKey[0]);

          TOTP totp = TOTP(hmacKey, hmacKeyLength);
          char* epochCode = totp.getCode( epoch );

          display.print(  "TOTP Code Twitter: ");
          display.println( epochCode );

          ...
</code></pre>

<p><a href="https://gitlab.com/edent/watchy-faces/-/tree/main">You can grab the full code from GitLab</a>.</p>

<p>I'm not very good at C++ - so please let me know what terrible mistakes I've made.</p>

<h2 id="is-this-a-good-idea"><a href="https://shkspr.mobi/blog/2023/07/an-eink-wrist-mounted-totp-generator/#is-this-a-good-idea">Is this a good idea?</a></h2>

<p>Well... Yes and no.</p>

<p>TOTP is a strong-ish form of Multi-Factor Authentication. It helps prevent attacks where someone already knows your username and password.  Having a convenient way to get your TOTP codes may make you more likely to use them. It also prevents you from getting locked out of your accounts if your phone dies or is stolen.</p>

<p>Convenient security is <em>good</em> security.</p>

<p>But... Having them on your wrist for everyone to see? I've deliberately made the font as small as I can so it is only readable up close. However, if someone is shoulder-surfing your details, they may well see your wrist. The watch isn't encrypted - so even if you hid the codes behind a button press, anyone who steals your watch will have your codes. If they steal your phone, they need to get through your PIN / biometrics.</p>

<p>Who are your adversaries? If you are trying to evade state-level actors, thieves specifically targeting you for your crypto-holdings, or an untrustworthy spouse - this probably isn't a great idea.  If you don't use 2FA because you don't keep your phone with you - this will probably increase your security posture.</p>

<p>Ultimately, all security measures are a trade-off between convenience and control.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=46213&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/07/an-eink-wrist-mounted-totp-generator/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Stupidly Small eInk Font]]></title>
		<link>https://shkspr.mobi/blog/2023/07/stupidly-small-eink-font/</link>
					<comments>https://shkspr.mobi/blog/2023/07/stupidly-small-eink-font/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 07 Jul 2023 11:34:06 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[arduino]]></category>
		<category><![CDATA[eink]]></category>
		<category><![CDATA[watchy]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=46206</guid>

					<description><![CDATA[I have the new Watchy eInk watch. It has a cute little screen with a resolution of 200x200 pixels.  How much text can we cram in there?  A typical watch face looks like this:    My new watch face is far superior and looks like this:    That&#039;s using the GNU Unifont - which works brilliantly on tiny devices.  HOWTO   Download the GNU Unifont Download and compile HarfBuzz Run the HarfBuzz Font…]]></description>
										<content:encoded><![CDATA[<p>I have the new Watchy eInk watch. It has a cute little screen with a resolution of 200x200 pixels.  How much text can we cram in there?</p>

<p>A typical watch face looks like this:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2023/06/blackberry.jpg" alt="Watch with a big USB cable plugged in." width="2024" height="1518" class="aligncenter size-full wp-image-46198">

<p>My new watch face is <em>far</em> superior and looks like this:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2023/06/smol.jpg" alt="A chunky eInk watch with a ridiculously small font." width="1024" height="1024" class="aligncenter size-full wp-image-46207">

<p>That's using the GNU Unifont - which works brilliantly on tiny devices.</p>

<h2 id="howto"><a href="https://shkspr.mobi/blog/2023/07/stupidly-small-eink-font/#howto">HOWTO</a></h2>

<ul>
<li>Download the <a href="https://unifoundry.com/unifont/index.html">GNU Unifont</a></li>
<li>Download and compile <a href="https://harfbuzz.github.io/building.html">HarfBuzz</a></li>
<li>Run the <a href="https://harfbuzz.github.io/utilities.html#utilities-command-line-hbsubset">HarfBuzz Font Subsetter</a></li>
<li><code>./hb-subset unifont-15.0.06.ttf abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\!\"\£\$\%\^\&amp;\*\(\)\-\_\=\+\@\~\'\#\,\.\/\?\:\;\&lt;\&gt;\\\| -o latin.ttf</code></li>
<li>Convert the output to AdaFruit's GFX format using <a href="https://rop.nl/truetype2gfx/">truetype2gfx</a> (set the Font Size to 5 points for about the smallest you can reasonably go. But Font Size of 8 is a better compromise between size and readability.)</li>
<li>Follow the <a href="https://watchy.sqfmi.com/docs/create-watchface#basics">tutorial to create a new watch face</a>

<ul>
<li><strong>NOTE</strong> If you put the font file in the same director as the <code>.ino</code> file, you need to include it using <code>#include "latin5pt7b.h"</code></li>
</ul></li>
<li>Compile and upload to your watchy via USB.</li>
</ul>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2023/06/face.jpg" alt="A tiny pixelated font showing the time." width="600" height="599" class="aligncenter size-full wp-image-46208">

<p>Nice!</p>

<h2 id="next-steps"><a href="https://shkspr.mobi/blog/2023/07/stupidly-small-eink-font/#next-steps">Next Steps</a></h2>

<p>I dunno. Make it bounce around? Print a Shakespearean sonnet? Give me some suggestions!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=46206&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/07/stupidly-small-eink-font/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Review: Watchy - an eInk watch full of interesting compromises ★★★⯪☆]]></title>
		<link>https://shkspr.mobi/blog/2023/06/review-watchy-an-eink-watch-full-of-interesting-compromises/</link>
					<comments>https://shkspr.mobi/blog/2023/06/review-watchy-an-eink-watch-full-of-interesting-compromises/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 30 Jun 2023 11:34:12 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[eink]]></category>
		<category><![CDATA[gadget]]></category>
		<category><![CDATA[review]]></category>
		<category><![CDATA[watch]]></category>
		<category><![CDATA[watchy]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=46196</guid>

					<description><![CDATA[The last smartwatch that I tried was some awful early Sony device with a locked-down ROM. The battery died after a day and I couldn&#039;t find the proprietary charger. It slurped up all my data. It was garish to look at. And it was expensive.  The Watchy is the opposite in every single conceivable way.  It is an Arduino powered, open source, eInk display, with no data guzzling tendancies. And is only …]]></description>
										<content:encoded><![CDATA[<p>The last smartwatch that I tried was some awful early Sony device with a locked-down ROM. The battery died after a day and I couldn't find the proprietary charger. It slurped up all my data. It was garish to look at. And it was expensive.</p>

<p>The Watchy is the opposite in every single conceivable way.</p>

<p>It is an Arduino powered, open source, eInk display, with no data guzzling tendancies. And is only <a href="https://thepihut.com/products/sqfmi-watchy">£60 including delivery</a>.  It's gorgeous to look at without being distracting, has a massive battery life, and allows for a bunch of tinkering.</p>

<p>But...</p>

<p>Ah... Let's get it out of the way. This is <em>not</em> a consumer product. It is fiddly to assemble, has very little protection for its delicate components, and <a href="https://github.com/sqfmi/Watchy/issues/235">to change the timezone you have to recompile the firmware</a>!</p>

<p>Oh, and it uses USB-Micro rather than USB-C 😡</p>

<p>The watch ships in kit form and is not overly satisfying to build. The buttons are especially fiddly to fit, the instructions assume you know how to open a ribbon connector, and there's warnings about how fragile everything is. Took me about 20 minutes all in - and that was mostly aligning the buttons.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2023/06/assembly.jpg" alt="Raw circuit board and battery." width="1024" height="1365" class="aligncenter size-full wp-image-46201">

<p>But, once built, it does look great.  Here are my first impressions:</p>

<div style="position: relative; padding-top: 56.25%;"><iframe title="First impressions of the SQFMI Watchy" src="https://tube.tchncs.de/videos/embed/afc2384b-b10a-4257-9f2a-f831e8200f5c" allowfullscreen="" sandbox="allow-same-origin allow-scripts allow-popups" style="position: absolute; inset: 0px;" width="100%" height="100%" frameborder="0"></iframe></div>

<p>It is an fun device to play with. But the whole thing is built on a set of (very reasonable) compromises.</p>

<p>The eInk screen is a delight to look at and helps keep the battery lasting for ages. There's no backlight - but that also makes it less of a flashy distraction.</p>

<p>The eInk screen is <em>fragile</em>. Yet, bizarrely, the watch comes with <em>zero</em> protection. There is no plastic shield to keep it from getting bumped or scratched. I appreciate that might cause glare or get dust trapped in it - but I don't think the deep bezel is going to protect that screen.</p>

<p>Similarly, there's no water ingress protection. I wasn't expecting a diver's watch with rubber gaskets - but I'd be nervous about wearing this in the rain.  You can 3D print your own case, or buy a different one - but that adds to the cost.</p>

<p>There's no speaker - again, less distracting than other watches. The vibration motor is sufficiently powerful to discreetly alert you to anything important.</p>

<p>There's no touchscreen - again, saves on power and protects the screen. But the buttons are hard, loud, and just don't feel nice. Luckily WiFi can be set up by connecting to the device's own SSID. I was dreading the thought of having to enter details using those buttons!</p>

<p>It won't monitor your heart rate, sweatiness, or blood pressure - nor will it try to sell those data to perverts on the Internet. It does have a step-counter which uses an accelerometer to keep track of your movement.</p>

<p>It can't pair to your headphones for listening to music - but you can use BLE for firmware updates and WiFi for NTP.</p>

<p>You can reprogram it! But there's only 3,673,264 bytes to play with, so you can't squeeze to much in there.  Oh, and the instructions are the usual half-finished &amp; untested set of scattered files beloved by hackers.</p>

<p>There's no weird proprietary connectors needed to charge it. But it uses USB-<em>Micro</em>. So you'll have to dig out one of those old cables that you kept when the world moved over to USB-C.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2023/06/blackberry.jpg" alt="Watch with a big USB cable plugged in." width="2024" height="1518" class="aligncenter size-full wp-image-46198">

<p>Do you see what I mean? It isn't quite as spartan as the <a href="https://en.wikipedia.org/wiki/Casio_F-91W">Casio F-91W</a>, but it is missing some things you may find essential in a modern watch.</p>

<p>I'm conflicted. I love everything eInk. I like devices which are fully under my control. I don't want to wear something expensive and distracting on my wrist. I want to change the watchface to match my mood.</p>

<p>But... I don't want to wear something fragile. If I go abroad, I don't want to lug a laptop with me just to change timezone. I'm not sure I want to learn yet another programming paradigm. And, if I'm recharging something, I want it to use the same connector as every other gadget I've bought in the last few years.</p>

<p>I enjoy tinkering. But the instruction on the website are incomplete and hard to follow. I've sent a pull request to fix some of the errors I found. Eventually, after some confusion, I was able to download a face, edit the settings, and flash it.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2023/06/watchycode.jpg" alt="A watch showing the correct time. There is some blurred code on the computer screen behind it." width="2024" height="1518" class="aligncenter size-full wp-image-46204">

<p>I'm going to spend a few weeks playing with it. The Watchy is <em>crammed</em> full of possibilities. But it remains to be seen if I can fulfil them.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=46196&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/06/review-watchy-an-eink-watch-full-of-interesting-compromises/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
	</channel>
</rss>
