
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
 <channel>
   <title>Bokeh</title>
   <link>https://https://ericbariaux.statichost.page//</link>
   <description>Recent content on Bokeh</description>
   <generator>Hugo -- gohugo.io</generator>
   <language>en-us</language>
   <lastBuildDate>Tue, 03 Mar 2026 00:00:00 +0200</lastBuildDate>
   
       <atom:link href="https://https://ericbariaux.statichost.page//index.xml" rel="self" type="application/rss+xml" />
   
   
     <item>
       <title>Exploring Uncut - March 3rd, 2026</title>
       <link>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20260303/</link>
       <pubDate>Tue, 03 Mar 2026 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20260303/</guid>
       <description>&lt;p&gt;&lt;em&gt;Update 2026-03-07: Added example of generated output. Clarified usage of Codex instead of ChatGPT. Some styling improvements.&lt;/em&gt;&lt;/p&gt;&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;This time, the focus is solely on providing an update on my exploration of getting a Mandelbrot set renderer running on an STM32F746G-DISCO board.&lt;/p&gt;&lt;p&gt;I had hoped to also cover “The Egg Project” and some Home Assistant improvements I’ve been working on. However, there is already plenty to discuss here, and the other projects have been moving forward more slowly due to a collection of minor but frustrating issues, from ordering the wrong components, to chasing down unexpected sensor behavior, to tracking a Wi-Fi authentication failure caused by a simple case mismatch.&lt;/p&gt;&lt;h1 id=&#34;mandelbrot-update&#34;&gt;Mandelbrot update&lt;/h1&gt;&lt;h2 id=&#34;removing-swift-numerics&#34;&gt;Removing Swift Numerics&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/exploring-uncut-20251206/#LoopCrash&#34;&gt;Last time&lt;/a&gt;, I was faced with the issue that as soon as I introduced an additional external loop around my working code, it crashed.&lt;/p&gt;&lt;p&gt;At this stage I was still using Swift Numerics. I didn’t think this was the culprit, but to rule it out definitively, I removed the package dependency and reimplemented to core computation using only &lt;code&gt;Float&lt;/code&gt;s.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; maxIterations: UInt8 = &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; cReal: Float = &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; cImag: Float = &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; zReal: Float = &lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; zImag: Float = &lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; iterations: UInt8 = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; iterations &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; maxIterations {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; magnitudeSquared = zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; magnitudeSquared &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4.0&lt;/span&gt; {  &lt;span style=&#34;color:#75715e&#34;&gt;// 2.0 squared = 4.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// z = z * z + c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// (a + bi) * (a + bi) = (a² - b²) + (2ab)i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; zRealTemp = zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; cReal&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        zImag = &lt;span style=&#34;color:#ae81ff&#34;&gt;2.0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; cImag&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        zReal = zRealTemp&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        iterations &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Iterations: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\(&lt;/span&gt;iterations&lt;span style=&#34;color:#e6db74&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The behavior was exactly the same. If I change the range of that &lt;code&gt;for&lt;/code&gt; loop to have more than one iteration, the code crashes.&lt;/p&gt;&lt;p&gt;No progress so far.&lt;/p&gt;&lt;h2 id=&#34;moving-to-c&#34;&gt;Moving to C&lt;/h2&gt;&lt;p&gt;To further simplify things, I implemented the main algorithm in C and called it from Swift.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;oneRound&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; maxIterations &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; cReal &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; cImag &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; iterations &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (iterations &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; maxIterations) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; magnitudeSquared &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (magnitudeSquared &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4.0&lt;/span&gt;) {  &lt;span style=&#34;color:#75715e&#34;&gt;// 2.0 squared = 4.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// z = z * z + c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// (a + bi) * (a + bi) = (a² - b²) + (2ab)i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; zRealTemp &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; cReal;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zImag &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2.0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; cImag;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zReal &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; zRealTemp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    iterations&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; iterations;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; iterations: UInt8 = oneRound()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Iterations: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\(&lt;/span&gt;iterations&lt;span style=&#34;color:#e6db74&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This worked correctly for one, two, twenty, or any number of iterations through the loop.&lt;/p&gt;&lt;h2 id=&#34;passing-coordinates&#34;&gt;Passing coordinates&lt;/h2&gt;&lt;p&gt;However, this isn’t very interesting, since the calculation is always performed for the same coordinate.&lt;br&gt;What we would need is to perform it for different coordinates.&lt;br&gt;So we need to pass &lt;code&gt;cReal&lt;/code&gt; and &lt;code&gt;cImag&lt;/code&gt; as parameters.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;oneRound&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; cReal, &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; cImag) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; maxIterations &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; iterations &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (iterations &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; maxIterations) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; magnitudeSquared &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (magnitudeSquared &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4.0&lt;/span&gt;) {  &lt;span style=&#34;color:#75715e&#34;&gt;// 2.0 squared = 4.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// z = z * z + c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// (a + bi) * (a + bi) = (a² - b²) + (2ab)i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; zRealTemp &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; cReal;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zImag &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2.0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; cImag;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zReal &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; zRealTemp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    iterations&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; iterations;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But for our first test, let&amp;rsquo;s still pass the same coordinates for each call.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; iterations: UInt8 = oneRound(&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Iterations: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\(&lt;/span&gt;iterations&lt;span style=&#34;color:#e6db74&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And with this, we&amp;rsquo;re back to our previous behavior: one pass through the loop is fine; more than one, and execution crashes.&lt;/p&gt;&lt;p&gt;Experimenting some more in this codebase, I updated the loop to what it typically is for rendering the typical Mandelbrot set.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; xMin: Float = &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2.5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; xMax: Float = &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; yMin: Float = &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.25&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; yMax: Float = &lt;span style=&#34;color:#ae81ff&#34;&gt;1.25&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; y: Int32 &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; x: Int32 &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; cReal: Float = xMin &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; (Float(x) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10.0&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; (xMax &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; xMin)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; cImag: Float = yMin &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; (Float(y) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10.0&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; (yMax &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; yMin)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; iterations: UInt8 = oneRound(cReal, cImag)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Iterations: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\(&lt;/span&gt;iterations&lt;span style=&#34;color:#e6db74&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As anticipated, this also crashes.&lt;/p&gt;&lt;h2 id=&#34;computing-the-coordinates-in-c&#34;&gt;Computing the coordinates in C&lt;/h2&gt;&lt;p&gt;Trying one more variation, I decided to pass x and y to the C function and let it calculate the cReal and cImag values.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;oneRound&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; x, &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; y) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; maxIterations &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; xMin &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2.5&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; xMax &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; yMin &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.25&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; yMax &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1.25&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;uint8_t&lt;/span&gt; iterations &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; cReal &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; xMin &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; (x &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10.0&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; (xMax &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; xMin);&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; cImag &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; yMin &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; (y &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10.0&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; (yMax &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; yMin);&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (iterations &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; maxIterations) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; magnitudeSquared &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (magnitudeSquared &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4.0&lt;/span&gt;) {  &lt;span style=&#34;color:#75715e&#34;&gt;// 2.0 squared = 4.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// z = z * z + c&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// (a + bi) * (a + bi) = (a² - b²) + (2ab)i&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;float&lt;/span&gt; zRealTemp &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; cReal;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zImag &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2.0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zReal &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; zImag &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; cImag;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    zReal &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; zRealTemp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    iterations&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; iterations;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; y: UInt32 &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; x: UInt32 &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; iterations: UInt8 = oneRound(x, y)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Iterations: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\(&lt;/span&gt;iterations&lt;span style=&#34;color:#e6db74&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\r&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And this worked fine.&lt;/p&gt;&lt;h2 id=&#34;setting-some-flags&#34;&gt;Setting some flags&lt;/h2&gt;&lt;p&gt;Slightly running out of ideas on variations to try out, I explained all those tests to ChatGPT and asked for advice.The fact that passing &lt;code&gt;int&lt;/code&gt; parameters worked but not &lt;code&gt;float&lt;/code&gt; ones led it to believe there might be an ABI mismatch issue with e.g. one language using soft-float ABI and the other using hard-float ABI.&lt;br&gt;The suggestion was to add explicit build flags to ensure everything was aligned.&lt;br&gt;I ended up adding&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-Xcc&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-mcpu=cortex-m7&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-Xcc&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-mthumb&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-Xcc&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-mfpu=fpv5-d16&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-Xcc&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-mfloat-abi=hard&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to the Swift compiler options in my &lt;code&gt;toolset.json&lt;/code&gt; file.&lt;br&gt;However, that was not enough. This only ensures that the C code compiled as part of the Swift build gets those flags applied.&lt;br&gt;I still needed to ensure that the same flags were used when compiling the standalone C source files (i.e. Support.c). This required adding a completely new section to &lt;code&gt;toolset.json&lt;/code&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;cCompiler&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;extraCLIOptions&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-mcpu=cortex-m7&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-mthumb&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-mfpu=fpv5-d16&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-mfloat-abi=hard&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Looking at the commands executed during the build, I could see those flags properly passed everywhere they were required (and confirmed they were not specified before).&lt;/p&gt;&lt;p&gt;But this did not change anything.&lt;/p&gt;&lt;h2 id=&#34;single-vs-double-precision&#34;&gt;Single vs double precision&lt;/h2&gt;&lt;p&gt;The astute reader might notice the use of &lt;code&gt;fpv5-d16&lt;/code&gt; for the FPU specification.&lt;br&gt;This indicates a double-precision-capable FPU, which I thought was the case, as glancing through the 250+ page &lt;a href=&#34;https://www.st.com/resource/en/programming_manual/pm0253-stm32f7-series-and-stm32h7-series-cortexm7-processor-programming-manual-stmicroelectronics.pdf&#34;&gt;STM32F7 Series and STM32H7 Series Cortex®-M7 processor programming manual&lt;/a&gt;, I had read&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Floating-point unit&lt;/strong&gt;&lt;br&gt;The FPU provides IEEE754-compliant operations on 32-bit single-precision and 64-bit double-precision floating-point values.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Unfortunately, this refers to the specifications of the Cortex-M7 processor options as used in general in different STM32 products.&lt;/p&gt;&lt;p&gt;Since I&amp;rsquo;m using an STM32F746G-DISCO board, I glanced at the 1700+ page of the&lt;a href=&#34;https://www.st.com/resource/en/reference_manual/rm0385-stm32f75xxx-and-stm32f74xxx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf&#34;&gt;STM32F75xxx and STM32F74xxx advanced Arm&lt;!-- raw HTML omitted --&gt;®&lt;!-- raw HTML omitted --&gt;-based 32-bit MCUs - Reference manual&lt;/a&gt;, without finding any additional information.&lt;/p&gt;&lt;p&gt;Finally, in the &lt;a href=&#34;https://www.st.com/resource/en/datasheet/stm32f745ie.pdf&#34;&gt;Datasheet - STM32F745xx STM32F746xx - ARM®-based Cortex®-M7 32b MCU+FPU, 462DMIPS, up to 1MB Flash/320+16+ 4KB&lt;/a&gt;, another 250+ page document, it states&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;The Cortex®-M7 core features a single floating point unit (SFPU) precision which supports all Arm® single-precision data-processing instructions and data types.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;So I changed the &lt;code&gt;fpu&lt;/code&gt; flag definition to &lt;code&gt;fpv5-sp-d16&lt;/code&gt; instead of &lt;code&gt;fpv5-d16&lt;/code&gt;.But it crashed just the same.&lt;/p&gt;&lt;style type=&#34;text/css&#34;&gt;         .notice {        --title-color: #fff;        --title-background-color: #6be;        --content-color: #444;        --content-background-color: #e7f2fa;    }    .notice.info {        --title-background-color: #fb7;        --content-background-color: #fec;    }    .notice.tip {        --title-background-color: #5a5;        --content-background-color: #efe;    }    .notice.warning {        --title-background-color: #c33;        --content-background-color: #fee;    }         @media (prefers-color-scheme:dark) {        .notice {            --title-color: #fff;            --title-background-color: #069;            --content-color: #ddd;            --content-background-color: #023;        }        .notice.info {            --title-background-color: #a50;            --content-background-color: #420;        }        .notice.tip {            --title-background-color: #363;            --content-background-color: #121;        }        .notice.warning {            --title-background-color: #800;            --content-background-color: #400;        }    }    body.dark .notice {        --title-color: #fff;        --title-background-color: #069;        --content-color: #ddd;        --content-background-color: #023;    }    body.dark .notice.info {        --title-background-color: #a50;        --content-background-color: #420;    }    body.dark .notice.tip {        --title-background-color: #363;        --content-background-color: #121;    }    body.dark .notice.warning {        --title-background-color: #800;        --content-background-color: #400;    }         .notice {        padding: 18px;        line-height: 24px;        margin-bottom: 24px;        border-radius: 4px;        color: var(--content-color);        background: var(--content-background-color);    }    .notice p:last-child {        margin-bottom: 0    }         .notice-title {        margin: -18px -18px 12px;        padding: 4px 18px;        border-radius: 4px 4px 0 0;        font-weight: 700;        color: var(--title-color);        background: var(--title-background-color);    }         .icon-notice {        display: inline-flex;        align-self: center;        margin-right: 8px;    }    .icon-notice img,    .icon-notice svg {        height: 1em;        width: 1em;        fill: currentColor;    }    .icon-notice img,    .icon-notice.baseline svg {        top: .125em;        position: relative;    }&lt;/style&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;Full disclaimer, ChatGPT had proposed to test using single precision and I also used it afterwards to find the exact documents where the information could be found.&lt;br&gt;I only had a vague recollection of seeing that information.&lt;/p&gt;&lt;/div&gt;&lt;h2 id=&#34;revising-the-fpu-enable-code&#34;&gt;Revising the FPU enable code&lt;/h2&gt;&lt;p&gt;The last suggestion of ChatGPT was that I was enabling the FPU too late. This seemed strange to me, as it was the first instruction called in my Swift code.Still, it proposed to move it earlier, directly in the reset handler.&lt;/p&gt;&lt;p&gt;So I removed the &lt;code&gt;enableFPU()&lt;/code&gt; call that started the &lt;code&gt;main()&lt;/code&gt; method in &lt;code&gt;Application.swift&lt;/code&gt; and added some bits of assembly directly in the reset routine in &lt;code&gt;startup.S&lt;/code&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  // ---- enable FPU here ----&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ldr   r1, =0xE000ED88&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ldr   r0, [r1]&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  orr   r0, r0, #(0xF &amp;lt;&amp;lt; 20)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  str   r0, [r1]&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  dsb&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  isb&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  // -------------------------&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And this worked just fine. The loops are going over all coordinates and printing the expected iteration numbers, as shown in the last few lines of the console output from the board.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;…&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;11&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Iterations: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Starting echo&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I do not understand the reason why this works, which is frustrating me, but it does.&lt;/p&gt;&lt;p&gt;Now that I had something working, I reverted some of the other changes I made, such as adding the compiler flags, or implementing the logic in C instead of Swift, verifying at each step of the way that it was still properly working.&lt;br&gt;And eventually, I got back to using SwiftNumerics and the &lt;code&gt;Complex&amp;lt;Float&amp;gt;&lt;/code&gt; type in my calculations and all was well.&lt;/p&gt;&lt;h2 id=&#34;getting-a-grasp-on-whats-happening&#34;&gt;Getting a grasp on what&amp;rsquo;s happening&lt;/h2&gt;&lt;p&gt;As mentioned above, I don&amp;rsquo;t like the black magic feeling of changing things around and having something working without a clue as to why.&lt;br&gt;I&amp;rsquo;m strongly in the camp that there&amp;rsquo;s always a good reason for why something is working or not. It might be very complex and intricate, you might not understand it, but there is logic underneath.&lt;br&gt;At least in the context of software engineering, when it comes to philosophy, psychology or quantum physics, things are less clearly defined. This annoys and fascinates me at the same time and although this is primarily a technical blog, I may write about that topic at some point.&lt;/p&gt;&lt;p&gt;But I digress. To avoid that lingering frustration, and since ChatGPT had been helpful so far, I used AI again, this time using the Codex CLI, to ask for an explanation.&lt;br&gt;When building the project, quite a few files are generated, including a &lt;code&gt;.build/armv7em-apple-none-macho/release/Application.disassembly&lt;/code&gt; that contains the &amp;ldquo;readable&amp;rdquo; assembly listing of the whole program.&lt;/p&gt;&lt;p&gt;So I built the project twice, once where I enabled the FPU at the top of the &lt;code&gt;main()&lt;/code&gt; function of my Swift code and once where I enabled it from the reset routine. For each, I saved the &lt;code&gt;Application.disassembly&lt;/code&gt; file and then I asked ChatGPT to compare the two, explain the differences in the code and the crash I was observing.&lt;/p&gt;&lt;p&gt;It pointed out some of the obvious differences (like the one in the reset routine) but also similarities.&lt;br&gt;For both projects, the way the &lt;code&gt;main()&lt;/code&gt; function from &lt;code&gt;Application.swift&lt;/code&gt; was called was identical, including the fact there&amp;rsquo;s a generated function prologue that includes a &lt;code&gt;vpush {d8-d13}&lt;/code&gt; instruction.&lt;/p&gt;&lt;p&gt;So I asked follow-up questions to understand exactly what was going on, like what does &lt;code&gt;vpush&lt;/code&gt; do and what is this function prologue?&lt;/p&gt;&lt;p&gt;Given those answers, let me try to explain what&amp;rsquo;s happening here.&lt;/p&gt;&lt;p&gt;Processor or FPU registers being used in the code of a function fall in two categories:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;call-clobbered (or caller-saved) registers hold temporary information and there&amp;rsquo;s no requirement on their values after the call. If the caller wants to keep the values in such registers around, it needs to save them itself.&lt;/li&gt;&lt;li&gt;callee-saved registers, on the other hand, are used to hold long-lived values that should be preserved across calls, and it is the responsibility of the callee to save those registers.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The function prologue is compiler-generated code that performs some preliminary setup before the function is called.&lt;/p&gt;&lt;p&gt;In our case, as FPU callee-saved registers were used in the code of our &lt;code&gt;main()&lt;/code&gt; function, the compiler generated code to save those as part of the prologue. This is what the &lt;code&gt;vpush&lt;/code&gt; instruction does.&lt;/p&gt;&lt;p&gt;Schematically, you can represent the calling sequence as&lt;br&gt;&lt;code&gt;Reset → main prologue (vpush) → enableFPU() → code using FPU&lt;/code&gt;&lt;/p&gt;&lt;p&gt;Since the prologue executes before the function body, the &lt;code&gt;vpush&lt;/code&gt; is being executed before executing the first instruction of our &lt;code&gt;main()&lt;/code&gt; function, which is enabling the FPU. Executing an FPU instruction before the FPU is enabled led to a crash.&lt;/p&gt;&lt;p&gt;By enabling the FPU in the reset routine, the calling sequence looked like&lt;br&gt;&lt;code&gt;Reset (enableFPU) → main prologue (vpush) → code using FPU&lt;/code&gt;&lt;br&gt;making sure the FPU is enabled before the &lt;code&gt;vpush&lt;/code&gt; is executed.&lt;/p&gt;&lt;p&gt;But why did this crash occur only when I added an outer loop?&lt;br&gt;The way the compiler generates and optimizes the code and decides on which register to use for which operations is obviously quite complex (at least to me). But by saving the &lt;code&gt;disassembly&lt;/code&gt; files for an outer loop with one iteration or a loop with more than one iteration, I could confirm that different registers were used and that only in the latter case were callee-saved registers involved. This meant the prologue only contained the &lt;code&gt;vpush&lt;/code&gt; instruction for that latter case. In the first case, our calling sequence looked like &lt;code&gt;Reset → enableFPU() → code using FPU&lt;/code&gt;which is perfectly fine.&lt;/p&gt;&lt;p&gt;Using the same mechanism, I confirmed that the behavior was exactly the same between the code that was calling my C function using &lt;code&gt;int&lt;/code&gt; parameters vs the call using &lt;code&gt;float&lt;/code&gt; parameters.&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;In this post, I showed you how I debugged the implementation of the Mandelbrot set computation in Embedded Swift on the STM32F746G-DISCO board and how ChatGPT has helped both find and fix the issues but also understand what was really happening.&lt;/p&gt;&lt;p&gt;The source code for this experiment, including all the intermediate steps, is available on &lt;a href=&#34;https://github.com/nelcea/stm32-mandelbrot-tests&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;But so far, I have code that prints the number of iterations at each coordinate. The end goal is of course to draw a picture, and to do that, that iteration count needs to be mapped to a color value.&lt;/p&gt;&lt;p&gt;If the journey so far is any indication as what lies ahead, I&amp;rsquo;m sure I&amp;rsquo;ll be facing quite a few challenges and will have more stories to share. Stay tuned for a follow-up on this topic and on the other ongoing projects.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Exploring Uncut - December 6th, 2025</title>
       <link>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20251206/</link>
       <pubDate>Sat, 06 Dec 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20251206/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;I’ve had drafts of Exploring Uncut posts on my computer for months now. They contain bullet points of things I wanted to talk about, sometimes with additional notes, sometimes a draft of a few paragraphs. But as time went by, the potential post only became bigger and the time it would take me to finish it would only grow.&lt;/p&gt;&lt;p&gt;So here&amp;rsquo;s a new post focusing on what I&amp;rsquo;m working on right now. I&amp;rsquo;ll tackle those other topics when the time is right.&lt;/p&gt;&lt;h1 id=&#34;mandelbrot&#34;&gt;Mandelbrot&lt;/h1&gt;&lt;h2 id=&#34;the-goal&#34;&gt;The goal&lt;/h2&gt;&lt;p&gt;While preparing the talk I did at &lt;a href=&#34;https://www.youtube.com/watch?v=yHQneZk_LsY&amp;amp;list=PL9n3PIcFyBqFt2ZPNa-dD2fQD5uJ9TUmY&#34;&gt;SwiftLeeds&lt;/a&gt; on Open-Source packages Apple offers, I wanted to find a nice use case for Swift Numerics. As it includes a module to handle complex numbers, I thought drawing a Mandelbrot set would fit nicely.&lt;/p&gt;&lt;p&gt;And as I also wanted to show the package could work on Embedded, I opened a PR to the &lt;a href=&#34;https://github.com/apple/swift-numerics&#34;&gt;Swift Numerics&lt;/a&gt; repository to ensure it would compile in that mode. Nothing major, disabling &lt;code&gt;Codable&lt;/code&gt; and &lt;code&gt;CustomDebugStringConvertible&lt;/code&gt; conformance under Embedded Swift.&lt;/p&gt;&lt;p&gt;Once this was done, I created a quick test to generate a &lt;a href=&#34;https://en.wikipedia.org/wiki/Mandelbrot_set&#34;&gt;Mandelbrot set&lt;/a&gt; based on the &lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples/tree/main/stm32-lcd-logo&#34;&gt;stm32-lcd-logo&lt;/a&gt; example from the &lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples/tree/main&#34;&gt;swift-embedded-examples&lt;/a&gt; GitHub repository.It compiled just fine but when executing on my STM32F746G-DISCO board, it just crashed.&lt;/p&gt;&lt;h2 id=&#34;investigating-the-issue&#34;&gt;Investigating the issue&lt;/h2&gt;&lt;p&gt;To investigate the issue, I worked on a minimal test case, starting from the &lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples/tree/main/stm32-uart-echo&#34;&gt;stm32-uart-echo&lt;/a&gt; example.&lt;br&gt;In that test, I&amp;rsquo;m evaluating the sequence of the typical f(z) = z² + c function for only one given complex number and with a very limited number of iterations.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; maxIterations: UInt8 = &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; c = Complex&amp;lt;Float&amp;gt;(&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; z = Complex&amp;lt;Float&amp;gt;.zero&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; iterations: UInt8 = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; iterations &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; maxIterations &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; z.magnitude &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2.0&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;z = z &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; z &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; c&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iterations &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  print(iterations)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Before going into more details, let&amp;rsquo;s do the math manually. The sequence of values for z go like&lt;/p&gt;&lt;table&gt;  &lt;thead&gt;      &lt;tr&gt;          &lt;th&gt;Calculation&lt;/th&gt;          &lt;th&gt;z&lt;/th&gt;          &lt;th&gt;Magnitude&lt;/th&gt;          &lt;th&gt;Iteration&lt;/th&gt;      &lt;/tr&gt;  &lt;/thead&gt;  &lt;tbody&gt;      &lt;tr&gt;          &lt;td&gt;z₀ = (0.0, 0.0)&lt;/td&gt;          &lt;td&gt;(0.0, 0.0)&lt;/td&gt;          &lt;td&gt;0.0&lt;/td&gt;          &lt;td&gt;1&lt;/td&gt;      &lt;/tr&gt;      &lt;tr&gt;          &lt;td&gt;z₁ = (0.0, 0.0)² + (-1.0, 1.0) = (0.0, 0.0) + (-1.0, 1.0)&lt;/td&gt;          &lt;td&gt;(-1.0, 1.0)&lt;/td&gt;          &lt;td&gt;1.414&lt;/td&gt;          &lt;td&gt;2&lt;/td&gt;      &lt;/tr&gt;      &lt;tr&gt;          &lt;td&gt;z₂ = (-1.0, 1.0)² + (-1.0, 1.0) = (0.0 - 1.0, -2.0 + 1.0) + (-1.0, 1.0) = (-1.0, -1.0) + (-1.0, 1.0)&lt;/td&gt;          &lt;td&gt;(-2.0, 0.0)&lt;/td&gt;          &lt;td&gt;2.0&lt;/td&gt;          &lt;td&gt;3&lt;/td&gt;      &lt;/tr&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;As you can see, we get out of the loop as soon as &lt;code&gt;iterations&lt;/code&gt; equals 3 because of the magnitude test.&lt;br&gt;Building and running the above code on the board worked fine and printed the value of 3.&lt;br&gt;But changing &lt;code&gt;maxIterations&lt;/code&gt; to a bigger value, starting at 9, would make the program crash.&lt;/p&gt;&lt;p&gt;That left me scratching my head, in both cases, as we&amp;rsquo;ve seen above, the program should only go through the loop 3 times, as the condition on the magnitude would make it exit, not the condition on the number of iterations.&lt;br&gt;What I also observed was that the final application binary had different sizes based on that value. So the generated code was different.&lt;br&gt;I did take a quick look at the assembly but I need to take a refresher and learn ARM assembly. The last time I worked with assembly was in the previous century on 68k and x86 processors.&lt;br&gt;I tried several flags but could only make it crash more often, not make it work.&lt;/p&gt;&lt;p&gt;I posted about this on the &amp;ldquo;The Swift Programming Language&amp;rdquo; Discord server, in the embedded channel and after some back and forth, got an answer from &lt;a href=&#34;https://icmd.tech/&#34;&gt;CMD&lt;/a&gt; that, based on the assembly output, indicated I probably needed to initialize the FPU coprocessor.&lt;br&gt;This was confirmed soon after by &lt;a href=&#34;https://hachyderm.io/@rauhul&#34;&gt;Rauhul&lt;/a&gt;, pointing me to &lt;a href=&#34;https://github.com/swiftlang/swift-embedded-examples/blob/main/stm32-neopixel/Sources/Support/Support.c#L65&#34;&gt;sample code&lt;/a&gt; for performing that.&lt;br&gt;And this fixed my problem. A huge thank you to both of them for the help.&lt;/p&gt;&lt;p&gt;Although I understand the reason for the crash and the fix, I&amp;rsquo;m at loss as to how to get there when faced with the initial problem.&lt;br&gt;I suppose learning ARM assembly and the tools to inspect a binary build and reading the ARM / STMicro technical documentation would help but that seems like a huge learning curve to get a simple example working.&lt;/p&gt;&lt;h2 id=&#34;LoopCrash&#34;&gt;On to the next one&lt;/h2&gt;&lt;p&gt;Now that I had this fixed, I could proceed with my initial project, but it still crashed.&lt;br&gt;So back to the test snippet and I embedded the above calculation in a loop.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; maxIterations: UInt8 = &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; c = Complex&amp;lt;Float&amp;gt;(&lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; z = Complex&amp;lt;Float&amp;gt;.zero&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; iterations: UInt8 = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; iterations &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; maxIterations &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; z.magnitude &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2.0&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;z = z &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; z &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; c&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;iterations &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  print(iterations)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And this crashes.&lt;/p&gt;&lt;p&gt;As said above, I&amp;rsquo;m again not sure where to start to investigate that problem.&lt;br&gt;I can change some bits of the code, maybe not use Swift Numerics and &lt;code&gt;Complex&lt;/code&gt; types but do the math using only &lt;code&gt;Float&lt;/code&gt; types.&lt;br&gt;And I&amp;rsquo;ll definitely read more on ARM assembly and technical literature on the board, as it anyway interests me to know more about that, but I think trying to get an actual debugger working with Embedded Swift and the different boards I&amp;rsquo;m using would be the bigger win.&lt;/p&gt;&lt;h1 id=&#34;the-egg-project&#34;&gt;The Egg Project&lt;/h1&gt;&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;&lt;p&gt;In May 2025, Jony Ive and Sam Altman announced that io Products joined OpenAI.&lt;br&gt;The team is working on a new kind of product, incorporating OpenAI technology in a new form factor.&lt;br&gt;Not much is really known about it, just a lot of rumors.&lt;/p&gt;&lt;p&gt;In &lt;a href=&#34;https://atp.fm/640&#34;&gt;Episode 640&lt;/a&gt;, the ATP podcast team discussed the announcement at length and speculated on what the device could be.&lt;br&gt;Marco Arment was going for a watch while John Siracusa proposed a potato (or more specifically that if the product delivers on its features, it could be shaped like a potato and still be great).&lt;/p&gt;&lt;p&gt;In &lt;a href=&#34;https://atp.fm/641&#34;&gt;Episode 641&lt;/a&gt; they reviewed information that was now available, mainly from the rumor mill.&lt;br&gt;That includes the fact that it&amp;rsquo;s not a phone, it&amp;rsquo;s not glasses, and Jony Ive was not keen on a wearable device. That device would probably have cameras and microphones for environmental detection.&lt;br&gt;And this is where the egg form factor idea came from.&lt;/p&gt;&lt;p&gt;After that first mention of the egg, I thought about creating such a device.&lt;br&gt;But the idea of creating a 3D printed egg with electronics fitted inside made me think it wasn&amp;rsquo;t an appropriate shape.&lt;br&gt;I then considered an &amp;ldquo;all-seeing eye pyramid&amp;rdquo; as both an easier shape to model and an appropriate symbol for a device that would capture your environment. And then I moved on.&lt;/p&gt;&lt;p&gt;But as I was listening to &lt;a href=&#34;https://atp.fm/667&#34;&gt;Episode 667&lt;/a&gt;, where they discussed the latest news (not much) and reiterated the egg idea, I thought &amp;ldquo;Why not?&amp;rdquo;.&lt;br&gt;And so that’s one more project on the list.&lt;/p&gt;&lt;h2 id=&#34;the-project&#34;&gt;The project&lt;/h2&gt;&lt;p&gt;I&amp;rsquo;ll disclose as much information on the project as io Products does 😉.&lt;br&gt;It&amp;rsquo;s an egg,&lt;br&gt;it uses Swift as much as possible,&lt;br&gt;and it&amp;rsquo;s fully open source.&lt;/p&gt;&lt;p&gt;You can find the repository on GitHub at &lt;a href=&#34;https://github.com/nelcea/TheEggProject&#34;&gt;The Egg Project&lt;/a&gt;.&lt;/p&gt;&lt;h2 id=&#34;egg-modeler&#34;&gt;Egg Modeler&lt;/h2&gt;&lt;p&gt;The first step is to model an egg for 3D printing.&lt;/p&gt;&lt;p&gt;After a quick search, I discovered there was ample literature on the subject and many equations available to model an egg.&lt;br&gt;So I created a SwiftUI-based app to play around with different equations, their parameters, and come up with a shape I liked.&lt;br&gt;It can generate a 3D model using &lt;a href=&#34;https://github.com/tomasf/Cadova&#34;&gt;Cadova&lt;/a&gt;, a Swift library made for that purpose. I discovered it only a few weeks ago and used it for several small prints and I&amp;rsquo;m loving it. I&amp;rsquo;ll definitely dedicate a post to it.&lt;/p&gt;&lt;p&gt;As for the egg modelling equations, I based the math in that tool on &lt;a href=&#34;https://mathling.com/art/20220623_egg.html&#34;&gt;The Universal Egg Equation&lt;/a&gt; and &lt;a href=&#34;https://scipython.com/blog/a-universal-formula-for-egg-shape/&#34;&gt;A &amp;ldquo;universal&amp;rdquo; formula for egg shape&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&#34;no-shadow&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20251206/EggModeler.png&#34;    alt=&#34;The Egg Modeler allows you to test different equations and parameters to model an egg shape&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The Egg Modeler allows you to test different equations and parameters to model an egg shape&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;h2 id=&#34;whats-next&#34;&gt;What’s next&lt;/h2&gt;&lt;p&gt;The UI can certainly use a little more polish and the code a bit of cleaning.&lt;br&gt;But the main focus at this stage will be on the 3D model improvements, as it needs to be updated to support integrating the different electronic components.&lt;/p&gt;&lt;h1 id=&#34;meta&#34;&gt;Meta&lt;/h1&gt;&lt;p&gt;Two pieces of news about Meta this week caught my attention.&lt;/p&gt;&lt;p&gt;The first is about Alan Dye leaving Apple for Meta. As reported by Bloomberg in&lt;a href=&#34;https://www.bloomberg.com/news/articles/2025-12-03/apple-design-executive-alan-dye-poached-by-meta-in-major-coup&#34;&gt;Apple’s Top Designer Alan Dye Poached by Meta in Major Coup - Bloomberg&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;From the Apple side, as discussed by the community (see &lt;a href=&#34;https://daringfireball.net/2025/12/dye_cook_blind_spot&#34;&gt;Daring Fireball: Alan Dye Was in Tim Cook’s Blind Spot&lt;/a&gt; or&lt;a href=&#34;https://atp.fm/668&#34;&gt;ATP 668: So Happy for All Parties Involved — Accidental Tech Podcast&lt;/a&gt;), many people caring about the Apple platforms, myself included, consider this very good news.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Meta Platforms Inc. has poached Apple Inc.’s most prominent design executive in a major coup that underscores a push by the social networking giant into AI-equipped consumer devices.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;From the Meta side, as this quote from Mark Gurman indicates, this is part of the push towards delivering AI-enabled consumer devices.&lt;/p&gt;&lt;p&gt;The second piece of news this week is about Meta acquiring Limitless (formerly known as Rewind), see &lt;a href=&#34;https://www.cnbc.com/2025/12/05/meta-limitless-ai-wearable.html&#34;&gt;Meta acquiring AI wearable company Limitless&lt;/a&gt; and the current home page of &lt;a href=&#34;https://www.limitless.ai/&#34;&gt;Limitless&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I first started looking into Rewind when they announced their initial product. A desktop application for macOS that would capture all the information you manipulate on your Mac, be it text or voice and allow you to search through it and chat with it using AI (much like what Microsoft wanted to do with Recall).&lt;br&gt;I signed up to test it, even got a Pro subscription for a while (through a free offer they ran), downloaded it but never installed it. Although the company was very open about the privacy measures in place, it still worried me.&lt;br&gt;And maybe I was right, because even if Rewind/Limitless was caring a lot about privacy, now that it&amp;rsquo;s part of Meta, I don&amp;rsquo;t know what would happen to my data.&lt;/p&gt;&lt;p&gt;I could not help but be cynical when I read part of the e-mail Dan Siroker, Limitless CEO, sent to all registered users.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Whether you choose to continue to use the Pendant or not, your data will remain safe. We just launched a feature to make it easy to &lt;a href=&#34;https://help.limitless.ai/en/articles/13004987-how-to-download-your-limitless-transcripts-and-account-info&#34;&gt;export all of your data&lt;/a&gt;. And of course, if you want to &lt;a href=&#34;https://help.limitless.ai/en/articles/13005203-how-to-delete-your-limitless-account-and-data&#34;&gt;delete all of your data&lt;/a&gt;, that is also very easy to do within the app.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Stating your data is safe but then immediately explaining how to export and delete your data in the same paragraph strikes me as deeply ironic (and suspicious, and worrying).&lt;/p&gt;&lt;p&gt;Looking at these two moves from Meta and renewed bits of (non-)information about the work of  the io Products team, I am convinced we will see a few of those AI-powered consumer devices coming to the market.&lt;br&gt;After the Humane and Rabbit R1 fiascos, will this next iteration of such products be useful or will we need one (or more) other rounds ?&lt;br&gt;And will I trust any of them enough to give them a try ?&lt;br&gt;I don&amp;rsquo;t know, though certain safeguards like local AI models or end-to-end encryption could help.&lt;/p&gt;&lt;p&gt;Regardless of whether I&amp;rsquo;ll use them or not, I&amp;rsquo;m very keen to see what awaits us.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Exploring Uncut - July 14th, 2025</title>
       <link>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250714/</link>
       <pubDate>Mon, 14 Jul 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250714/</guid>
       <description>&lt;h1 id=&#34;game-follow-up&#34;&gt;Game follow-up&lt;/h1&gt;&lt;p&gt;As we had another &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250310/&#34;&gt;GeekClub&lt;/a&gt; meeting at the beginning of the month, I wanted to make some progress on my embedded game development so I would have something cool to show my friends.&lt;/p&gt;&lt;h2 id=&#34;3d-modeling&#34;&gt;3D Modeling&lt;/h2&gt;&lt;p&gt;&lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250324/#RoundDisplaySupport&#34;&gt;Back in March&lt;/a&gt;, I described how I modeled and 3D-printed a screen support, partly using ChatGPT to help me get there.&lt;/p&gt;&lt;p&gt;On the one hand, there were small issues with the print, like a small gap at the top of the screen, a bit of a loose fit on the LEGO® base and the screws I had in stock were too long so the screen would easily detach from its support. On the other hand, from a modeling point of view, I used hacks to reach the final result, I used extra volumes and steps and the final shape was not exactly what I had in mind. So I wanted to clean-up the model.&lt;/p&gt;&lt;p&gt;AI had helped get there, but it didn&amp;rsquo;t really teach me anything. The next time I would need to model something, I would still struggle and hack my way around it (probably again with some help from AI).&lt;/p&gt;&lt;p&gt;As I want to learn and get better at modeling, I searched for some video tutorials (this works best for me, I read reference material but prefer watching tutorials). And I found a great playlist on YouTube: &lt;a href=&#34;https://www.youtube.com/playlist?list=PLLm7Yjr9z_z07ohtjFGkA5w-j_NMj8B3J&#34;&gt;Fusion 360 Tutorials For Absolute Beginners&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I watch a few episodes at a time, take some notes, then apply the learnings in some of my modeling. This gives me foundational knowledge and a deeper understanding of what I do, why I do it and some additional context. I might still use AI for specific questions but at least I&amp;rsquo;m equipped with the tools to understand the answer and better adjust my prompts.&lt;/p&gt;&lt;p&gt;The same channel also proposes &lt;a href=&#34;https://www.youtube.com/playlist?list=PLLm7Yjr9z_z3pBOjfdjfFgeG4vPThttfz&#34;&gt;Fusion 360 Tutorials for Intermediate Users&lt;/a&gt; but I&amp;rsquo;m not at that level yet.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250714/RoundDisplaySupport.png&#34;    alt=&#34;The new support removes the gap that was present around the screen&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The new support removes the gap that was present around the screen&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;The resulting model is freely available for download: &lt;a href=&#34;https://makerworld.com/en/models/1605819-seeed-studio-round-display-support#profileId-1693266&#34;&gt;Seeed Studio Round Display Support&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&#34;game-progress&#34;&gt;Game progress&lt;/h2&gt;&lt;p&gt;It seems I didn&amp;rsquo;t really post follow-ups on the game&amp;rsquo;s development since that March post ( &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250324/&#34;&gt;Exploring Uncut - March 24th, 2025&lt;/a&gt;), in which I only explained how I got the screen output and joystick input working.&lt;/p&gt;&lt;p&gt;Over the last few months, I had the ship rotating around the screen, controlled by the joystick and I could fire some projectiles that would disappear towards the center of the screen.&lt;/p&gt;&lt;p&gt;But so far, I had no enemies. I wasn&amp;rsquo;t sure how they should appear, their movement patterns, if they should animate, and I couldn&amp;rsquo;t find appropriate graphical assets to use. So as a first try, I added meteorites that would come from the center towards the ship.&lt;/p&gt;&lt;p&gt;The animation worked OK, but nothing happened when the meteorite hit the spaceship or was hit by a missile.&lt;/p&gt;&lt;h2 id=&#34;collisions&#34;&gt;Collisions&lt;/h2&gt;&lt;p&gt;So I needed to detect collisions between my objects. I first checked if LVGL offered collision checking between images out of the box, but I didn&amp;rsquo;t find anything. I then searched for information on how to implement collision detection and found this YouTube playlist: &lt;a href=&#34;https://www.youtube.com/playlist?list=PLiLH0sbSgD_z_xnVKepl2M0Eous34_C3L&#34;&gt;2D Game Physics&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;This not only provided me with the basic information I needed but the intro video hinted at a lot of interesting topics to be covered by the series. Unfortunately, the playlist only contains four episodes. It&amp;rsquo;s a pity, but I can&amp;rsquo;t blame the author. I understand the amount of work that goes into producing such content.&lt;/p&gt;&lt;p&gt;Armed with that information, I did a first implementation of collision detection on my LVGL images struct.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LVGLImage&lt;/span&gt;: LVGLObject {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; pointer: UnsafeMutablePointer&amp;lt;lv_obj_t&amp;gt;?&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;⋮&lt;/span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;collideWith&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; other: LVGLImage) -&amp;gt; Bool {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; myCoord = lv_area_t()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; otherCoord = lv_area_t()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lv_obj_get_coords(&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.pointer, &amp;amp;myCoord)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lv_obj_get_coords(other.pointer, &amp;amp;otherCoord)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; otherCoord.x1 &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; myCoord.x2 &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; myCoord.x1 &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; otherCoord.x2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; otherCoord.y1 &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; myCoord.y2 &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; myCoord.y1 &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; otherCoord.y2&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And used it to handle collisions between missiles and meteorites. This worked fine and was visually OK. So I applied the same logic for the spaceship collision but there was a catch.&lt;/p&gt;&lt;p&gt;The way I implemented the spaceship rotation around the center of the screen was by moving the spaceship away from the center at start-up and using the center of the screen for the rotation anchor point.&lt;/p&gt;&lt;p&gt;And the LVGL manual indicates&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Note that the real coordinates of image objects won&amp;rsquo;t change during transformation. That is lv_obj_get_width/height/x/y() will return the original, non-zoomed coordinates.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;This means that in effect, the coordinates of the ship image never change and my collision detection formula above is bogus.&lt;/p&gt;&lt;p&gt;Rotating the ship image around its center and moving that center by computing its coordinates is geometrically equivalent. With that change, the ship now has proper coordinates to work with.&lt;/p&gt;&lt;p&gt;But computing a bounding box around a rotated shape is tricky. If you rotate the bounding box, it&amp;rsquo;s not axis-aligned anymore and the basic collision formulas stop working. If you don&amp;rsquo;t rotate the box and still want it to enclose the whole shape, it&amp;rsquo;ll vary in size based on the rotation angle and leads to false positives in the detection.&lt;/p&gt;&lt;p&gt;The easiest option when rotation is involved, is to use bounding circles instead of bounding boxes. So I created the types to support that.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Point&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; x: Int16&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; y: Int16&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Circle&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; center: Point&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; radius: Int16&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;collideWith&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; other: Circle) -&amp;gt; Bool {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// Using (r1+r2)^2&amp;gt;(x2-x1)^2+(y2-y1)^2 for efficient detection, no square roots involved&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; (radius &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; other.radius) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; (radius &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; other.radius)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; (other.center.x &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; center.x) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; (other.center.x &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; center.x)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; (other.center.y &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; center.y) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; (other.center.y &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; center.y)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And used it in my image struct.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LVGLImage&lt;/span&gt;: LVGLObject {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; pointer: UnsafeMutablePointer&amp;lt;lv_obj_t&amp;gt;?&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;⋮&lt;/span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; boundingCircle: Circle {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; coords = lv_area_t()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lv_obj_get_coords(pointer, &amp;amp;coords)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; width = lv_area_get_width(&amp;amp;coords)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; height = lv_area_get_height(&amp;amp;coords)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; Circle(&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      center: Point(x: (coords.x1 &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; coords.x2) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, y: (coords.y1 &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; coords.y2) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;),&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      radius: min(width, height) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;collideWith&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; other: LVGLImage) -&amp;gt; Bool {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; boundingCircle.collideWith(other.boundingCircle)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that I don&amp;rsquo;t compute the exact radius. This would require using Pythagoras formula, which requires calculating a square root, which is expensive. There are several approximation methods. But in the end, given the use case and the shapes of my different graphical elements, using the minimum between the width and the height got me the best gameplay feeling.&lt;br&gt;I&amp;rsquo;m leaving out a few details here that I&amp;rsquo;ll be sure to address when I write a series of posts on the complete implementation of the game.&lt;/p&gt;&lt;figure class=&#34;small no-shadow&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250714/Game.png&#34;    alt=&#34;The spaceship avoiding a meteorite and firing some missiles&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The spaceship avoiding a meteorite and firing some missiles&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;h1 id=&#34;swiftly-release&#34;&gt;Swiftly release&lt;/h1&gt;&lt;p&gt;Back in April, Apple released swiftly, that makes installing the Swift toolchain a breeze. There was however a small glitch when used in combination with SourceKit-LSP , which I mentioned in &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/swiftly-swift-6-1/&#34;&gt;Swiftly and Swift 6.1 released&lt;/a&gt;. That was not problematic as a workaround was available (see &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/swiftly-embedded-followup/&#34;&gt;Swiftly and SourceKit-LSP issue follow-up&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;Swiftly 1.0.1 is now available and fixes the issue. No workaround is necessary anymore and selecting the desired toolchain with swiftly is all that is required.&lt;/p&gt;&lt;h1 id=&#34;conferences-season&#34;&gt;Conferences season&lt;/h1&gt;&lt;p&gt;The September to November period in Europe is packed with Swift related conferences. This means a lot of them have their Call for Papers deadline in June or July.&lt;br&gt;So I spent a bit of time writing proposals for several talk ideas I had and submitted to two conferences. There are two more submissions I plan to make in July, but I&amp;rsquo;m waiting for feedback on the current ones to potentially tweak them a bit.&lt;/p&gt;&lt;h1 id=&#34;wwdc&#34;&gt;WWDC&lt;/h1&gt;&lt;p&gt;WWDC week was quite intense. As many, I watched the keynote and the State of the Union &amp;ldquo;live&amp;rdquo;. I then downloaded all the session videos as they became available (all on the first day for the first time). I installed macOS 26 and iOS 26 on test devices. I participated in five group labs. I watched several of the sessions that interested me most. And I tried to compile some of my code with the latest SDKs.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve made some tweaks to my apps, fixing some issues that appeared with the new design, but I haven&amp;rsquo;t taken the time yet to push forward with some ideas I have to make good use of the new features that are now available. I&amp;rsquo;m particularly excited about SpeechAnalyzer and the Foundation Models framework and think it&amp;rsquo;ll be a great fit to make progress on my &lt;a href=&#34;https://github.com/nelcea/pal&#34;&gt;PAL&lt;/a&gt; project.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m also happy seeing Apple propose some additional &lt;a href=&#34;https://developer.apple.com/events/view/upcoming-events&#34;&gt;in person events&lt;/a&gt; to help developers work with the newly announced technologies. Unfortunately, I didn&amp;rsquo;t get accepted in the first one to which I applied. Hopefully I&amp;rsquo;ll have better luck next time.&lt;/p&gt;&lt;h1 id=&#34;retro-computing&#34;&gt;Retro-computing&lt;/h1&gt;&lt;p&gt;Last week I was in Eindhoven, visiting the &lt;a href=&#34;https://www.openremote.io&#34;&gt;OpenRemote&lt;/a&gt; offices and meeting with the whole team for a few days. And I finally managed to go visit the &lt;a href=&#34;https://www.homecomputermuseum.nl/en/#intro&#34;&gt;Home Computer Museum&lt;/a&gt;. It&amp;rsquo;s less than 20 minutes away by car but although I&amp;rsquo;ve been around a few times this year, I never managed to fit that into my schedule.&lt;/p&gt;&lt;p&gt;I first heard about the museum when watching &lt;a href=&#34;https://www.youtube.com/watch?v=294aoiduwks&#34;&gt;HomeComputerMuseum: The interactive computer museum as a business – Bart van den Akker&lt;/a&gt;. I had no idea there was such a museum so close to Belgium.&lt;/p&gt;&lt;p&gt;By the way, the &lt;a href=&#34;https://vcfed.org/&#34;&gt;Vintage Computer Federation – VCF&lt;/a&gt; has a ton of other videos (and other information) available; it&amp;rsquo;s a great resource for retro-computing enthusiasts.&lt;/p&gt;&lt;p&gt;Back to the Home Computer Museum. It has a very large collection of home computers. You&amp;rsquo;ll find the usual suspects from Apple, Atari, Commodore, IBM, Sinclair and many others. But you&amp;rsquo;ll also encounter computers that you&amp;rsquo;ve probably never heard of, let alone see.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250714/Collection.png&#34;    alt=&#34;A small section of the computers on display&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;A small section of the computers on display&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250714/Holborn.png&#34;    alt=&#34;The Holborn computer, a machine I never heard of&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The Holborn computer, a machine I never heard of&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;That&amp;rsquo;s already a great treat but the best is that you can use a lot of them. Play a game, sit in front of the keyboard and try to remember some of those BASIC instructions you typed several decades ago.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250714/AltairAndImsai.png&#34;    alt=&#34;The early days: Altair 8800 and IMSAI 8080&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The early days: Altair 8800 and IMSAI 8080&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250714/DAI.png&#34;    alt=&#34;The DAI, a home computer made in Belgium&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The DAI, a home computer made in Belgium&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;There&amp;rsquo;s also a huge collection of games, some magazines and books, the main game consoles powered-up ready for you to remember those killer moves.&lt;/p&gt;&lt;p&gt;Finally, the staff is super friendly and ready to help you and answer your questions. They also offer a service to have their technical staff repair your old machines. And have some items for sale if you want to add something to your collection (not taking that PowerMac G5 home with me seriously tested my willpower).&lt;/p&gt;&lt;p&gt;If retro-computing is a topic of interest for you, follow me on  &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt;. Every Thursday I post some fond memories I have about old computers, software or gadget I&amp;rsquo;ve encountered through the years.&lt;/p&gt;&lt;h1 id=&#34;miscellaneous&#34;&gt;Miscellaneous&lt;/h1&gt;&lt;p&gt;As June came, so did the nice weather. Meaning spending more time in the garden, relaxing but also taking care of the growing grass and vegetation. I could use that as an excuse to explain I didn&amp;rsquo;t write any post last month, but who would I be fooling?&lt;/p&gt;&lt;p&gt;That did give me an excuse to buy a new toy though. After watching many reviews on YouTube but also getting a better understanding of the &lt;a href=&#34;https://en.wikipedia.org/wiki/Real-time_kinematic_positioning&#34;&gt;RTK technology&lt;/a&gt;, I finally took the plunge and bought a &lt;a href=&#34;https://mammotion.com/pages/luba-2-awd&#34;&gt;Mammotion LUBA 2 AWD 3000X&lt;/a&gt;.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250714/Luba.png&#34;    alt=&#34;The Luba handling one of the tricky slopes&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The Luba handling one of the tricky slopes&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;I&amp;rsquo;ve only had it for about a month now but I&amp;rsquo;m quite happy with it. The garden looks definitely better than it did the previous years and it&amp;rsquo;s freed me a bit of time, mostly to take care of more manual tasks in the garden. The only caveat so far is that I was hoping for a slightly higher positioning accuracy to mow closer to fences without getting stuck.&lt;/p&gt;&lt;p&gt;Sadly, June also brought us the passing of Bill Atkison. As many, I admired what he accomplished over his years at Apple. There are several videos available on-line with interviews of him. I remember enjoying his discussions on Triangulation:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=6tUWoy1tJkE&#34;&gt;Triangulation 244: Bill Atkinson&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=7aEafjfGWao&#34;&gt;Bill Atkinson Part 1 - Triangulation 361&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=xN-bLcJWch8&#34;&gt;Bill Atkinson Part 2 - Triangulation 362&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Finally, the Embedded Swift Community Hour held its fourth occurence last Friday. This was a quite successful session with about 25 participants, a big increase compared to the previous sessions.&lt;br&gt;We had interesting discussions about ESP32, bare metal vs SDK usage and build systems. You can find a more detailed summary of the session on the &lt;a href=&#34;https://forums.swift.org/t/embedded-swift-community-hour-july-11-2025/80964/7&#34;&gt;Swift Forums - Embedded Swift Community Hour (July 11, 2025)&lt;/a&gt;.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Exploring Uncut - May 26th, 2025</title>
       <link>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250526/</link>
       <pubDate>Mon, 26 May 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250526/</guid>
       <description>&lt;h1 id=&#34;hws-livestream&#34;&gt;HWS+ livestream&lt;/h1&gt;&lt;p&gt;Saturday, May 17th marked another Hacking with Swift+ subscriber livestream. This time, &lt;a href=&#34;https://mastodon.social/@twostraws&#34;&gt;Paul&lt;/a&gt; walked us through building a macOS application that uses the AppStoreConnect API to retrieve information about our published apps.&lt;/p&gt;&lt;p&gt;It was the longest session I ever attended but was super interesting, both from a coding perspective and in terms of the resulting app.&lt;/p&gt;&lt;p&gt;In fact, it was so compelling that Paul decided to open source the app, called &lt;a href=&#34;https://github.com/twostraws/ShipShape&#34;&gt;ShipShape&lt;/a&gt;.To help those who want to contribute, he also opened up the &lt;a href=&#34;https://www.hackingwithswift.com/plus/live-streams/shipshape&#34;&gt;livestream recording&lt;/a&gt; to everyone.&lt;/p&gt;&lt;p&gt;You might already be using &lt;a href=&#34;https://helm-app.com&#34;&gt;Helm&lt;/a&gt; for this purpose. I tested it in the past, it works great and I have a lot of respect for the work done by &lt;a href=&#34;https://iosdev.space/@polpielladev&#34;&gt;Pol&lt;/a&gt; and &lt;a href=&#34;https://mastodon.design/@hidde&#34;&gt;Hidde&lt;/a&gt;. But being able to participate in the creation of the application and somehow drive where it&amp;rsquo;s going is really interesting. Plus, enabling the application to be available to the widest audience possible feels really rewarding.&lt;/p&gt;&lt;p&gt;If you have some ideas, design or coding skills or a bit of time, join me in contributing to this great initiative.&lt;/p&gt;&lt;h1 id=&#34;swiftcraft&#34;&gt;SwiftCraft&lt;/h1&gt;&lt;p&gt;SwiftCraft held its second edition last week, and as for the first one, I was there.&lt;/p&gt;&lt;p&gt;The conference takes place in Folkstone, UK at a great venue call the Leas Cliff Hall.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250526/SwiftCraft-Venue.png&#34;    alt=&#34;A great view on the beach from the venue&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;A great view on the beach from the venue&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;They made some changes compared to the previous edition, the major one being that it was now a single track, which I appreciated very much.&lt;br&gt;The speaker lineup was diverse, featuring returning speakers, high-profile keynotes presenters and new speakers who where taking their first stab at presenting.&lt;br&gt;Overall the quality was excellent and I connected with most sessions.&lt;/p&gt;&lt;p&gt;They also hosted a one-hour slot for lightning talks, and I had the privilege of giving a 5-minute presentation on cryptography basics. I was thrilled to receive positive feedback afterward and will probably submit a longer version to upcoming conferences.&lt;br&gt;If you want to check it out, the slides are available on &lt;a href=&#34;https://github.com/ebariaux/slides/blob/main/Cryptography%20101%20-%20SwiftCraft%20-%2020250520.pdf&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I was surprised attendance wasn’t higher for this second edition, but honestly, I didn’t mind. The cozy vibe was a great opportunity to talk with the speakers and the participants. I thoroughly enjoyed talking to familiar faces and meeting new ones.&lt;/p&gt;&lt;h1 id=&#34;creating-a-badge&#34;&gt;Creating a badge&lt;/h1&gt;&lt;p&gt;Of course, when going to a conference, I always have an idea for a specific project, and of course it&amp;rsquo;s always a last minute thing.&lt;/p&gt;&lt;p&gt;When presenting at &lt;a href=&#34;https://www.pragmaconference.com/&#34;&gt;#pragma 2024&lt;/a&gt; last year, I had created the &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-ArcReactor&#34;&gt;Arc Reactor&lt;/a&gt; to show case an Embedded Swift project but also as a high-tech conference badge. It turned out rather un-practical, with the finished contraption being quite heavy.&lt;/p&gt;&lt;p&gt;This time, I tried another spin on the badge concept, using a lightweight and power efficient eInk screen.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250526/eBadgeFront.png&#34;    alt=&#34;Badge based on eInk screen, clipped on shirt pocket&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Badge based on eInk screen, clipped on shirt pocket&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;It is still powered by Embedded Swift, running on a nRF52840 microcontroller. It displays typical badge info, a logo of the conference or a QR code linking to this blog. All of this is controlled from an iPhone app over BLE.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250526/eBadgeBack.png&#34;    alt=&#34;Badge using nRF52840 microcontroller, in 3D printed enclosure&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Badge using nRF52840 microcontroller, in 3D printed enclosure&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;While I reused some code from the Arc Reactor project, it was still done in a rush, with some code debugging on-site during session breaks.&lt;br&gt;As with my other projects, I intend to fully open source it, including the 3D models that I created for the enclosure. It might take a while though, as the code is really not in a &amp;ldquo;share-worthy&amp;rdquo; state.&lt;/p&gt;&lt;h1 id=&#34;embedded-swift-documentation-effort&#34;&gt;Embedded Swift documentation effort&lt;/h1&gt;&lt;p&gt;A few weeks ago, &lt;a href=&#34;https://hachyderm.io/@rauhul&#34;&gt;Rauhul&lt;/a&gt; posted on the &lt;a href=&#34;https://forums.swift.org/&#34;&gt;Swift forums&lt;/a&gt; about &lt;a href=&#34;https://forums.swift.org/t/evolving-embedded-swift-documentation/79818&#34;&gt;Evolving Embedded Swift Documentation&lt;/a&gt; and invited community contributions.&lt;/p&gt;&lt;p&gt;Given my involvement with Embedded Swift and my interest in writing about it, I was immediately on board.&lt;/p&gt;&lt;p&gt;Last Thursday, just after returning from SwiftCraft, I joined a call with some community members to discuss the next steps. Over the week-end, I reviewed the existing documentation and submitted some early fixes.&lt;/p&gt;&lt;p&gt;I believe the current state of this documentation is already a major step forward compared to what was available last year when Embedded Swift was announced. But we must, as a community, continue the effort, in order to foster a wider adoption of Swift in this space.&lt;/p&gt;&lt;p&gt;It doesn&amp;rsquo;t have to be big, even just indicating what you feel is missing from the doc or which part you had trouble understanding, are incredibly valuable. Take a look at the aforementioned post and welcome on-board.&lt;/p&gt;&lt;h1 id=&#34;tech-news&#34;&gt;Tech news&lt;/h1&gt;&lt;p&gt;A lot has happened in the tech world over the past few days.&lt;/p&gt;&lt;p&gt;Anthropic announced &lt;a href=&#34;https://www.anthropic.com/news/claude-4&#34;&gt;Claude 4 models&lt;/a&gt;, and they look promising. While I still mostly use ChatGPT, I&amp;rsquo;ve started trying Claude for programming related tasks.&lt;/p&gt;&lt;p&gt;Google hosted its &lt;a href=&#34;https://io.google/2025/&#34;&gt;Google IO&lt;/a&gt; conference, during which they made a ton of announcements related to AI but also in the AR/XR space. I&amp;rsquo;ve only watched a quick recap but I get the feeling Android is not the star of the show it once was.&lt;/p&gt;&lt;p&gt;And of course, it was difficult to miss the &lt;a href=&#34;https://openai.com/sam-and-jony/&#34;&gt;Sam and Jony&lt;/a&gt; show, OpenAI acqui-hire of Jony Ive&amp;rsquo;s io company.&lt;br&gt;That last one reignited my interest in AI wearables and I finally took a bit of time to do a quick, super long overdue, update on the &lt;a href=&#34;https://https://ericbariaux.statichost.page//pinboard/&#34;&gt;list&lt;/a&gt; of such products I maintain (more updates to come).&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;That&amp;rsquo;s it for this time, and honestly, it&amp;rsquo;s probably too much. I should limit the number of projects I&amp;rsquo;m working on. But then again, who&amp;rsquo;s counting when you&amp;rsquo;re having fun?&lt;/p&gt;&lt;p&gt;If you&amp;rsquo;d like to share which one is your favorite, ping me on &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Swiftly and SourceKit-LSP issue follow-up</title>
       <link>https://https://ericbariaux.statichost.page//posts/swiftly-embedded-followup/</link>
       <pubDate>Sun, 04 May 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/swiftly-embedded-followup/</guid>
       <description>&lt;p&gt;&lt;em&gt;Update 2025-07-12: Swiftly 1.0.1 has now been released and it fixes the problem described in this post. No workaround is necessary anymore.&lt;/em&gt;&lt;/p&gt;&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;A few weeks ago, I wrote a &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/swiftly-swift-6-1/&#34;&gt;post about Swiftly&lt;/a&gt; and mentioned that I experienced issues with code-completion and the likes when doing embedded development in VSCode. I pointed to a SourceKit-LSP error I was seeing but did not take the time to investigate much further.&lt;/p&gt;&lt;p&gt;Last week, &lt;a href=&#34;https://mastodon.social/@kubamracek&#34;&gt;Kuba Mracek&lt;/a&gt; kindly tagged me in a &lt;a href=&#34;https://github.com/swiftlang/sourcekit-lsp/issues/2128#issuecomment-2840432295&#34;&gt;GitHub issue&lt;/a&gt; he opened in the &lt;a href=&#34;https://github.com/swiftlang/sourcekit-lsp&#34;&gt;SourceKit-LSP&lt;/a&gt; project.&lt;br&gt;The issue describes a similar problem and &lt;a href=&#34;https://github.com/bnbarham&#34;&gt;Ben Barham&lt;/a&gt; provided a workaround for it.&lt;/p&gt;&lt;h1 id=&#34;compile_commandsjson&#34;&gt;compile_commands.json&lt;/h1&gt;&lt;p&gt;Based on the explanation in the aforementioned issue, I double-checked the content of the generated &lt;code&gt;compile_commands.json&lt;/code&gt; file.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;directory&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;…&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/.swiftly/bin/swiftc -target armv7em-none-none-eabi …&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/EmbeddedSwift-nRF52-BLEExamples/L3_E2/Main.swift&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CMakeFiles/app_swift.dir/Main.swift.obj&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here we can see that the command refers to &lt;code&gt;swiftc&lt;/code&gt; within the &lt;code&gt;.swiftly&lt;/code&gt; folder in my home directory.&lt;br&gt;Looking at that file (&lt;code&gt;swiftc -&amp;gt; /Users/…/.swiftly/bin/swiftly&lt;/code&gt;), we can see it&amp;rsquo;s in fact a symbolic link to the &lt;code&gt;swiftly&lt;/code&gt; executable itself.&lt;/p&gt;&lt;h1 id=&#34;pointing-to-the-proper-compiler&#34;&gt;Pointing to the proper compiler&lt;/h1&gt;&lt;p&gt;Based on the comment in the issue, I tried to set the &lt;code&gt;SWIFT_EXEC&lt;/code&gt; environment variable appropriately. Working in VSCode and with the nRF Connect SDK, I used a similar technique to what I did before when defining environment variables and added the following snippet to the &lt;code&gt;.vscode/settings.json&lt;/code&gt; file within my project&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nrf-connect.west.env&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; {        &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;$base&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;terminal&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;SWIFT_EXEC&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$(swiftly use -p)/usr/bin/swiftc&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But this did not change anything.&lt;/p&gt;&lt;p&gt;Looking at &lt;a href=&#34;https://github.com/swiftlang/swift/blob/main/docs/HowToGuides/FAQ.md&#34;&gt;Swift - Frequently Asked Questions&lt;/a&gt;, I can see &lt;code&gt;SWIFT_EXEC&lt;/code&gt; being mentioned, but in the context of SwiftPM or Xcode, not CMake.&lt;/p&gt;&lt;p&gt;Searching the &lt;a href=&#34;https://cmake.org/cmake/help/latest/envvar/SWIFTC.html#swiftc&#34;&gt;CMake documentation&lt;/a&gt;, I instead found that &lt;code&gt;SWIFTC&lt;/code&gt; was the environment variable that indicated the Swift compiler to use. And so tried this instead&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nrf-connect.west.env&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; {        &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;$base&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;terminal&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;SWIFTC&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$(swiftly use -p)/usr/bin/swiftc&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;but this gave an error&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Could not find compiler set in environment variable SWIFTC&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;$(&lt;/span&gt;swiftly use -p&lt;span style=&#34;color:#66d9ef&#34;&gt;)&lt;/span&gt;/usr/bin/swiftc.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It looks like the environment variable does not get evaluated but is used verbatim instead.&lt;/p&gt;&lt;p&gt;I searched the VSCode documentation on &lt;a href=&#34;https://code.visualstudio.com/docs/configure/settings&#34;&gt;User and workspace settings&lt;/a&gt; and &lt;a href=&#34;https://code.visualstudio.com/docs/reference/variables-reference#_command-variables&#34;&gt;Variables reference&lt;/a&gt; but could not really find a way to make this work.&lt;/p&gt;&lt;p&gt;So I tried hardcoding the path&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nrf-connect.west.env&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; {        &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;$base&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;terminal&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;SWIFTC&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin/swiftc&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and this worked fine.&lt;/p&gt;&lt;p&gt;In &lt;code&gt;compile_commands.json&lt;/code&gt; the command references the actual swiftc compiler and code-completion now works as expected (if you have a Swift file opened in an editor, close and re-open it for things to work properly)&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;directory&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;…&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin/swiftc -target armv7em-none-none-eabi …&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/EmbeddedSwift-nRF52-BLEExamples/L3_E2/Main.swift&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CMakeFiles/app_swift.dir/Main.swift.obj&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works but we&amp;rsquo;ve now hardcoded the path to our swiftc compiler. Using the &lt;code&gt;swift-latest.xctoolchain&lt;/code&gt; symbolic link makes it slightly better though, as this we won&amp;rsquo;t need to change the configuration every time we install a new snapshot release and it&amp;rsquo;s probably the version we want to use anyway.&lt;/p&gt;&lt;p&gt;But can we do slightly better?&lt;/p&gt;&lt;h1 id=&#34;set-the-compiler-from-within-cmake&#34;&gt;Set the compiler from within CMake&lt;/h1&gt;&lt;p&gt;Taking another look at what the &lt;a href=&#34;https://cmake.org/cmake/help/latest/envvar/SWIFTC.html#swiftc&#34;&gt;CMake documentation&lt;/a&gt; says about &lt;code&gt;SWIFTC&lt;/code&gt;, we read that it&amp;rsquo;s used to set the value of the &lt;code&gt;CMAKE_Swift_COMPILER&lt;/code&gt; variable.&lt;/p&gt;&lt;p&gt;Looking at our existing &lt;code&gt;CMakeLists.txt&lt;/code&gt; file, we see that at the top, certain similar variables are already set&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Use the armv7em-none-none-eabi target triple for Swift&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;set(&lt;span style=&#34;color:#e6db74&#34;&gt;CMAKE_Swift_COMPILER_TARGET&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;armv7em-none-none-eabi&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Enable &amp;#34;wmo&amp;#34; as needed by Embedded Swift&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;set(&lt;span style=&#34;color:#e6db74&#34;&gt;CMAKE_Swift_COMPILATION_MODE&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;wholemodule&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s try something similar&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;execute_process(&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;COMMAND&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;bash&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;-c&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;swiftly use -p&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;OUTPUT_VARIABLE&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;toolchainPath&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;OUTPUT_STRIP_TRAILING_WHITESPACE&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;set (&lt;span style=&#34;color:#e6db74&#34;&gt;CMAKE_Swift_COMPILER&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;${toolchainPath}/usr/bin/swiftc&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works fine and we can indeed see in &lt;code&gt;compile_commands.json&lt;/code&gt; that the actual path to the currently selected toolchain is used&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;directory&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;…&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain/usr/bin/swiftc -target armv7em-none-none-eabi -j 10 …&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;file&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/EmbeddedSwift/Public/EmbeddedSwift-nRF52-BLEExamples/L3_E2/Main.swift&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CMakeFiles/app_swift.dir/Main.swift.obj&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;style type=&#34;text/css&#34;&gt;         .notice {        --title-color: #fff;        --title-background-color: #6be;        --content-color: #444;        --content-background-color: #e7f2fa;    }    .notice.info {        --title-background-color: #fb7;        --content-background-color: #fec;    }    .notice.tip {        --title-background-color: #5a5;        --content-background-color: #efe;    }    .notice.warning {        --title-background-color: #c33;        --content-background-color: #fee;    }         @media (prefers-color-scheme:dark) {        .notice {            --title-color: #fff;            --title-background-color: #069;            --content-color: #ddd;            --content-background-color: #023;        }        .notice.info {            --title-background-color: #a50;            --content-background-color: #420;        }        .notice.tip {            --title-background-color: #363;            --content-background-color: #121;        }        .notice.warning {            --title-background-color: #800;            --content-background-color: #400;        }    }    body.dark .notice {        --title-color: #fff;        --title-background-color: #069;        --content-color: #ddd;        --content-background-color: #023;    }    body.dark .notice.info {        --title-background-color: #a50;        --content-background-color: #420;    }    body.dark .notice.tip {        --title-background-color: #363;        --content-background-color: #121;    }    body.dark .notice.warning {        --title-background-color: #800;        --content-background-color: #400;    }         .notice {        padding: 18px;        line-height: 24px;        margin-bottom: 24px;        border-radius: 4px;        color: var(--content-color);        background: var(--content-background-color);    }    .notice p:last-child {        margin-bottom: 0    }         .notice-title {        margin: -18px -18px 12px;        padding: 4px 18px;        border-radius: 4px 4px 0 0;        font-weight: 700;        color: var(--title-color);        background: var(--title-background-color);    }         .icon-notice {        display: inline-flex;        align-self: center;        margin-right: 8px;    }    .icon-notice img,    .icon-notice svg {        height: 1em;        width: 1em;        fill: currentColor;    }    .icon-notice img,    .icon-notice.baseline svg {        top: .125em;        position: relative;    }&lt;/style&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;I first had an issue properly building the path, caused by an extra newline in the output of the command.&lt;br&gt;Looking at the &lt;a href=&#34;https://cmake.org/cmake/help/latest/command/execute_process.html&#34;&gt;execute_process — CMake 4.0.1 Documentation&lt;/a&gt; pointed me to the &lt;code&gt;OUTPUT_STRIP_TRAILING_WHITESPACE&lt;/code&gt; option that solved the issue.&lt;br&gt;It&amp;rsquo;s always a good idea to check the doc!&lt;/p&gt;&lt;/div&gt;&lt;h1 id=&#34;being-generic&#34;&gt;Being generic&lt;/h1&gt;&lt;p&gt;The above change in the &lt;code&gt;CMakeLists.txt&lt;/code&gt; works great when Swiftly is installed but what happens if it&amp;rsquo;s not.&lt;/p&gt;&lt;p&gt;My first reaction was to be cautious and test for the presence of Swiftly before executing the code&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmake&#34; data-lang=&#34;cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;find_program(&lt;span style=&#34;color:#e6db74&#34;&gt;SWIFTLY&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;swiftly&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;IF(&lt;span style=&#34;color:#e6db74&#34;&gt;SWIFTLY&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    execute_process(&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;COMMAND&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;bash&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;-c&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;swiftly use -p&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;OUTPUT_VARIABLE&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;toolchainPath&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;OUTPUT_STRIP_TRAILING_WHITESPACE&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    )&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;    set (&lt;span style=&#34;color:#e6db74&#34;&gt;CMAKE_Swift_COMPILER&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;${toolchainPath}/usr/bin/swiftc&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;ENDIF()&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So in this case, we&amp;rsquo;re falling back to the old behavior and defining the &lt;code&gt;TOOLCHAIN&lt;/code&gt; environment variable to indicate to compiler to use.&lt;/p&gt;&lt;p&gt;While writing this post, as I wanted to explain why I made the above test, I tried the original code &lt;em&gt;without&lt;/em&gt; Swiftly installed. And to my surprise, it also worked.&lt;/p&gt;&lt;p&gt;The explanation is that, if Swiftly is not installed, the &lt;code&gt;toolchainPath&lt;/code&gt;  variable is empty. And  &lt;code&gt;CMAKE_Swift_COMPILER&lt;/code&gt; resolves to &lt;code&gt;/usr/bin/swiftc&lt;/code&gt;, which is executing the proper compiler.&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;In this post, I explained how to get code-completion working within VSCode when installing the Swift toolchain using Swiftly.&lt;/p&gt;&lt;p&gt;A big thank you to &lt;a href=&#34;https://mastodon.social/@kubamracek&#34;&gt;Kuba Mracek&lt;/a&gt; and &lt;a href=&#34;https://github.com/bnbarham&#34;&gt;Ben Barham&lt;/a&gt; for providing the initial information on the workaround. I&amp;rsquo;m grateful for the spirit of the Swift community, with so many people helping each other and striving to help grow the platform.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m hoping the blog posts I write and the code I open source are a small contribution to this. If you have any topic you&amp;rsquo;d like me to cover, don&amp;rsquo;t hesitate to reach out on &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Exploring Uncut - April 28th, 2025</title>
       <link>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250428/</link>
       <pubDate>Mon, 28 Apr 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250428/</guid>
       <description>&lt;p&gt;It&amp;rsquo;s been a while since the last &amp;ldquo;Exploring Uncut&amp;rdquo; post, so without further ado, here’s a recap of some of the fun and important things from the past few weeks.&lt;/p&gt;&lt;h1 id=&#34;home-assistant&#34;&gt;Home Assistant&lt;/h1&gt;&lt;p&gt;I’ve been interested in home automation for a very (very) long time, nearly 40 years.&lt;br&gt;As a teenager, I had seen an article on how to control your home using some custom electronics on your Commodore 64. That piqued my curiosity and I started researching the available products and technologies.&lt;br&gt;Looking at &lt;a href=&#34;https://en.wikipedia.org/wiki/X10_(industry_standard)&#34;&gt;X10&lt;/a&gt;, &lt;a href=&#34;https://en.wikipedia.org/wiki/CEBus&#34;&gt;CEBus&lt;/a&gt;, Phast and drooling in front of Crestron touch panels (considered state of the art back then they were ridiculously tiny monochrome panels costing thousands of dollars).&lt;/p&gt;&lt;p&gt;As I started working and earning more money, I bought smart remote controls from Nevo, then Phillips Pronto. Eventually, this became my part time job and I went after all kinds of certifications: AMX VIP, RTi certified, Vantage, Crestron, Lutron, …&lt;/p&gt;&lt;p&gt;In the early 2010s, I came across &lt;a href=&#34;https://openremote.io&#34;&gt;OpenRemote&lt;/a&gt;, an open source project that, at the time, was focused on home automation. They were doing cool things, so I used it at home and joined the team.&lt;br&gt;But home automation is a complicated market and unless your community reaches some critical mass or you&amp;rsquo;re a major player that can somehow impose a standard (and even then, HomeKit is OK but it did not became a defacto standard), this will be a constant struggle. There will always be that one other device or one other protocol that you absolutely need to support.&lt;br&gt;The project moved away from the home market and is now an IoT platform focusing on use cases such as Energy Management, Fleet Management or Smart Cities. And part of my professional time is still spent as a member of this team.&lt;/p&gt;&lt;p&gt;I kept using it for my home for several years after the switch, but eventually I had to move on and find some other solution.&lt;br&gt;At the time, the main project I was working on (in the digital identity domain, nothing to do with home automation), was moving to kubernetes and micro-services. So as a research project, I developed a custom home automation system. The idea was to use an MQTT bus as the backbone and have each pod encapsulate a protocol adapter or some business logic. I developed each service using Java and SpringBoot and had a web UI developed with Angular and using MQTT over WebSocket. Eventually I implemented a native Swift client, mainly to have a UI accessible on my AppleTVs.&lt;/p&gt;&lt;p&gt;It was a great learning experience and fun to get it running but eventually the maintenance burden became too significant. Every new device I would have liked to add required custom development, and keeping up with the dependencies updates or fixing the occasional glitch was just too much.&lt;/p&gt;&lt;p&gt;So I decided to take the plunge and try &lt;a href=&#34;https://www.home-assistant.io&#34;&gt; Home Assistant&lt;/a&gt;. I’ve known about it for several years. It’s become the market leader, most of my geek friends are using it, but I never tried it.&lt;/p&gt;&lt;p&gt;For testing purposes, I installed it inside a VM on my Mac mini. I then went through the configuration steps and was amazed at how many devices were immediately discovered or could be added with a few clicks. In no time, I had a simple dashboard with control over some basic elements like lights, media players or security cameras.&lt;/p&gt;&lt;p&gt;Going further will still take a bit of reading or watching some videos. And we&amp;rsquo;ll see how stable the system will be and how much effort I&amp;rsquo;ll need to put into keeping it running, but so far I&amp;rsquo;m impressed with what I&amp;rsquo;ve seen.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ll still do some custom developments and experiments though, as I have ideas for small devices that I could interface using Embedded Swift (although I could change my mind when looking at ESPHome).&lt;/p&gt;&lt;h1 id=&#34;computer-history-museum-videos&#34;&gt;&lt;a href=&#34;https://www.youtube.com/@ComputerHistory&#34;&gt;Computer History Museum&lt;/a&gt; videos&lt;/h1&gt;&lt;p&gt;Some of you following me on &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt; might have seen my &lt;code&gt;#ThrowbackThursday&lt;/code&gt; toots, featuring all kinds of older software or hardware from several decades ago. Looking at that brings back memories of those times when, as a child, I was discovering computers and programming; experimenting with side projects as I ran into some cool new tech or previous jobs I worked at.&lt;br&gt;But unrelated to my personal experience, I feel strongly about the fact that knowing the history of our field is important. If you&amp;rsquo;re studying painting, literature, architecture or many other topics, you&amp;rsquo;ll take history classes. You&amp;rsquo;ll understand how we got here, how the techniques evolved over time and why, who were the key contributors.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve got a big collection of books about the history of computers and software programming but I also sometimes re-read old technical books, as they convey the ideas underpinning the technology at the time. And I also watch several YouTube channels about retro computing and computing history.&lt;/p&gt;&lt;p&gt;Lately I&amp;rsquo;ve started watching several of the &lt;a href=&#34;https://www.youtube.com/playlist?list=PLQsxaNhYv8daKdGi7s85ubzbWdTB36-_q&#34;&gt;Oral History&lt;/a&gt; videos published by the &lt;a href=&#34;https://computerhistory.org/&#34;&gt;Computer History Museum&lt;/a&gt;, where they have long-format interviews with key players in our field, giving them the opportunity to tell their story as they recall.&lt;/p&gt;&lt;p&gt;Being slightly biased towards Apple and NeXT history, I&amp;rsquo;ve started with interviews from &lt;a href=&#34;https://youtu.be/SCTTvhRXIq4?si=okXgjqloqi9KVIcp&#34;&gt;Rich Page&lt;/a&gt;, &lt;a href=&#34;https://youtu.be/vwCdKU9uYnE?si=qNnItpfqxzhEVcg7&#34;&gt;Avie Tevanian&lt;/a&gt; and &lt;a href=&#34;https://youtu.be/qpIuIImN0YI?si=a6eod9jvR5SKHYMs&#34;&gt;Bertrand Serlet&lt;/a&gt;.&lt;br&gt;Having seen the people speaking about macOS change over the years in the Apple keynotes, it&amp;rsquo;s funny to see the link with NeXT&amp;rsquo;s history. Avie was Bertrand&amp;rsquo;s boss and mentor, Bertrand worked with Scott Forestall on AppKit and later hired Craig Federighi to work on EOF.&lt;/p&gt;&lt;h1 id=&#34;miscellaneous&#34;&gt;Miscellaneous&lt;/h1&gt;&lt;p&gt;I continued working on porting the examples from the &lt;a href=&#34;https://academy.nordicsemi.com/courses/bluetooth-low-energy-fundamentals/&#34;&gt;Bluetooth Low Energy Fundamentals&lt;/a&gt; course from Nordic Developer Academy to Embedded Swift. I posted all examples from lesson 2 (see &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-BLEExamples&#34;&gt;Embedded Swift version of the Nordic Dev Academy BLE examples&lt;/a&gt;) and have all examples from lesson 3 running (but a bit of cleaning is required before posting).&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m now using &lt;a href=&#34;https://www.swift.org/swiftly/documentation/swiftlydocs/&#34;&gt;Swiftly&lt;/a&gt; to manage my Swift toolchains. Overall it makes things easier but there are a couple of glitches still. I wrote about it in &lt;a href=&#34;https://www.ericbariaux.com/posts/swiftly-swift-6-1/&#34;&gt;Swiftly and Swift 6.1 released&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;And I just submitted two talk proposals for &lt;a href=&#34;https://swiftleeds.co.uk/&#34;&gt;SwiftLeeds&lt;/a&gt;. Let&amp;rsquo;s see how that goes.&lt;/p&gt;&lt;p&gt;I really enjoy presenting at conferences, so if you have any topics you&amp;rsquo;d like to see me talk about, let me know on &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt; and I&amp;rsquo;ll see if I can bring some interesting thoughts on the subject.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Swiftly and Swift 6.1 released</title>
       <link>https://https://ericbariaux.statichost.page//posts/swiftly-swift-6-1/</link>
       <pubDate>Mon, 14 Apr 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/swiftly-swift-6-1/</guid>
       <description>&lt;p&gt;&lt;em&gt;Update 2025-07-12: Swiftly 1.0.1 has now been released and it fixes the problem described in this post. No workaround is necessary anymore.&lt;/em&gt;&lt;br&gt;&lt;em&gt;Update 2025-05-04: There is now a workaround for the SourceKit-LSP issue mentioned at the &lt;a href=&#34;#end&#34;&gt;end of this post&lt;/a&gt;, see &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/swiftly-embedded-followup/&#34;&gt;Swiftly and SourceKit-LSP issue follow-up&lt;/a&gt; for more information.&lt;/em&gt;&lt;/p&gt;&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;End of March was a busy time for Apple, with the release of &lt;a href=&#34;https://www.swift.org/blog/introducing-swiftly_10/&#34;&gt;swiftly 1.0&lt;/a&gt; and a few days later &lt;a href=&#34;https://www.swift.org/blog/swift-6.1-released/&#34;&gt;Swift 6.1&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s explore what this means for toolchain selection, mostly when doing Embedded Swift development on macOS.&lt;/p&gt;&lt;h1 id=&#34;xcode-toolchain&#34;&gt;Xcode toolchain&lt;/h1&gt;&lt;p&gt;Xcode 16.3 comes bundled with Swift 6.1.If you don&amp;rsquo;t install anything else, open a terminal and check the current version of swift&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift -print-target-info&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;compilerVersion&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Apple Swift version 6.1 (swiftlang-6.1.0.110.21 clang-1700.0.13.3)&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;target&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;triple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macosx15.0&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unversionedTriple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;moduleTriple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macos&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;compatibilityLibraries&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;librariesRequireRPath&amp;#34;&lt;/span&gt;: false&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;paths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeLibraryPaths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/usr/lib/swift&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeLibraryImportPaths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeResourcePath&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You see a final 6.1 release&lt;/p&gt;&lt;style type=&#34;text/css&#34;&gt;         .notice {        --title-color: #fff;        --title-background-color: #6be;        --content-color: #444;        --content-background-color: #e7f2fa;    }    .notice.info {        --title-background-color: #fb7;        --content-background-color: #fec;    }    .notice.tip {        --title-background-color: #5a5;        --content-background-color: #efe;    }    .notice.warning {        --title-background-color: #c33;        --content-background-color: #fee;    }         @media (prefers-color-scheme:dark) {        .notice {            --title-color: #fff;            --title-background-color: #069;            --content-color: #ddd;            --content-background-color: #023;        }        .notice.info {            --title-background-color: #a50;            --content-background-color: #420;        }        .notice.tip {            --title-background-color: #363;            --content-background-color: #121;        }        .notice.warning {            --title-background-color: #800;            --content-background-color: #400;        }    }    body.dark .notice {        --title-color: #fff;        --title-background-color: #069;        --content-color: #ddd;        --content-background-color: #023;    }    body.dark .notice.info {        --title-background-color: #a50;        --content-background-color: #420;    }    body.dark .notice.tip {        --title-background-color: #363;        --content-background-color: #121;    }    body.dark .notice.warning {        --title-background-color: #800;        --content-background-color: #400;    }         .notice {        padding: 18px;        line-height: 24px;        margin-bottom: 24px;        border-radius: 4px;        color: var(--content-color);        background: var(--content-background-color);    }    .notice p:last-child {        margin-bottom: 0    }         .notice-title {        margin: -18px -18px 12px;        padding: 4px 18px;        border-radius: 4px 4px 0 0;        font-weight: 700;        color: var(--title-color);        background: var(--title-background-color);    }         .icon-notice {        display: inline-flex;        align-self: center;        margin-right: 8px;    }    .icon-notice img,    .icon-notice svg {        height: 1em;        width: 1em;        fill: currentColor;    }    .icon-notice img,    .icon-notice.baseline svg {        top: .125em;        position: relative;    }&lt;/style&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;Running &lt;code&gt;swift --version&lt;/code&gt; or &lt;code&gt;swift -v --version&lt;/code&gt; gives us some information but the above command also gives information about the runtime path.&lt;/p&gt;&lt;/div&gt;&lt;p&gt;Creating a &lt;code&gt;main.swift&lt;/code&gt; file with this one-liner&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello World!&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;we can compile it using&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift main.swift&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;this generates an executable &lt;code&gt;main&lt;/code&gt; file.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s try running&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded main.swift&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;that gives an error&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: Whole module optimization &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;wmo&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; must be enabled with embedded Swift.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This indicates that the compiler recognizes Embedded mode.&lt;/p&gt;&lt;p&gt;But running&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo main.swift&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;gives&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;unknown&amp;gt;:0: error: module &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Swift&amp;#39;&lt;/span&gt; cannot be imported in embedded Swift mode&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We could maybe try to specify a target ? Let&amp;rsquo;s check what targets are available.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clang -print-targets&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Registered Targets:&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aarch64    - AArch64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aarch64_32 - AArch64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian ILP32&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aarch64_be - AArch64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    arm        - ARM&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    arm64      - ARM64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    arm64_32   - ARM64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian ILP32&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    armeb      - ARM &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    thumb      - Thumb&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    thumbeb    - Thumb &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x86        - 32-bit X86: Pentium-Pro and above&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x86-64     - 64-bit X86: EM64T and AMD64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Clearly not all that&amp;rsquo;s required for embedded, but let&amp;rsquo;s try one&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo -target thumb-none-none-eabi main.swift &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: unableToFind&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;tool: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;swift-autolink-extract&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And what about just creating an object file, no linking&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo -c -target thumb-none-none-eabi main.swift&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;unknown&amp;gt;:0: error: unable to load standard library &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; target &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;thumb-none-none-eabi&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Enough for the default Swift installation, let&amp;rsquo;s check with another one.&lt;/p&gt;&lt;h1 id=&#34;manually-downloading-a-toolchain&#34;&gt;Manually downloading a toolchain&lt;/h1&gt;&lt;p&gt;Since starting with Embedded Swift, what I&amp;rsquo;ve done so far is go to &lt;a href=&#34;https://www.swift.org/install/macos/&#34;&gt;https://www.swift.org/install/macos/&lt;/a&gt; and download the latest development snapshot. This would give me a &lt;code&gt;.pkg&lt;/code&gt; file. Installing it would add a toolchain under &lt;code&gt;/Library/Developer/Toolchains&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;I then extract the toolchain identifier using&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plutil -extract CFBundleIdentifier raw /Library/Developer/Toolchains/swift-latest.xctoolchain/Info.plist&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;org.swift.62202504031a&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And references the toolchain I want to use with&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export TOOLCHAINS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;org.swift.62202504031a&amp;#39;&lt;/span&gt;                                       &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;This only works if you have Xcode installed, see &lt;a href=&#34;https://forums.swift.org/t/embedded-swift-on-esp32-with-idf-error-on-build/72230/8&#34;&gt;https://forums.swift.org/t/embedded-swift-on-esp32-with-idf-error-on-build/72230/8&lt;/a&gt; for more details.&lt;/p&gt;&lt;/div&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;When using nRF Connect SDK from within VSCode, I added this variable to the West environment, as explained in &lt;a href=&#34;https://www.ericbariaux.com/posts/nrfx-blink-step-by-step/&#34;&gt;nrfx-blink Step by Step&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;p&gt;With this in place, let&amp;rsquo;s check the Swift version we now have&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift -print-target-info&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;compilerVersion&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Apple Swift version 6.2-dev (LLVM 3f3fde0d5f85709, Swift 0c5fd6a3017961d)&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;target&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;triple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macosx15.0&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unversionedTriple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;moduleTriple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macos&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;platform&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pointerWidthInBits&amp;#34;&lt;/span&gt;: 64,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pointerWidthInBytes&amp;#34;&lt;/span&gt;: 8,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;swiftRuntimeCompatibilityVersion&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;6.0&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;compatibilityLibraries&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;librariesRequireRPath&amp;#34;&lt;/span&gt;: false&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;paths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeLibraryPaths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain/usr/lib/swift/macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/usr/lib/swift&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeLibraryImportPaths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain/usr/lib/swift/macosx&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeResourcePath&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain/usr/lib/swift&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo main.swift&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;now works and generates an executable &lt;code&gt;main&lt;/code&gt;file.&lt;/p&gt;&lt;p&gt;We also have many more targets&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clang -print-targets&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Registered Targets:&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aarch64    - AArch64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aarch64_32 - AArch64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian ILP32&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aarch64_be - AArch64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    arm        - ARM&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    arm64      - ARM64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    arm64_32   - ARM64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian ILP32&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    armeb      - ARM &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    avr        - Atmel AVR Microcontroller&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mips       - MIPS &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;32-bit big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mips64     - MIPS &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;64-bit big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mips64el   - MIPS &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;64-bit little endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mipsel     - MIPS &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;32-bit little endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppc32      - PowerPC &lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppc32le    - PowerPC &lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt; LE&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppc64      - PowerPC &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppc64le    - PowerPC &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; LE&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    riscv32    - 32-bit RISC-V&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    riscv64    - 64-bit RISC-V&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    systemz    - SystemZ&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    thumb      - Thumb&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    thumbeb    - Thumb &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wasm32     - WebAssembly 32-bit&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wasm64     - WebAssembly 64-bit&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x86        - 32-bit X86: Pentium-Pro and above&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x86-64     - 64-bit X86: EM64T and AMD64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So let&amp;rsquo;s try building for one of them.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo -c -target riscv32-none-none-eabi main.swift&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;properly generates a main.o object file.&lt;/p&gt;&lt;h1 id=&#34;enter-swiftly&#34;&gt;Enter swiftly&lt;/h1&gt;&lt;p&gt;Installing swiftly is straightforward, go to &lt;a href=&#34;https://www.swift.org/install/macos/swiftly/&#34;&gt;Swift.org - Getting Started with Swiftly on macOS&lt;/a&gt; and follow the instructions.&lt;/p&gt;&lt;p&gt;As noted in the documentation, running &lt;code&gt;swiftly init&lt;/code&gt; automatically downloads the latest swift toolchain.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s check the installed version.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift -print-target-info&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;compilerVersion&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Apple Swift version 6.1 (swift-6.1-RELEASE)&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;target&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;triple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macosx15.0&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unversionedTriple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;moduleTriple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macos&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;compatibilityLibraries&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;librariesRequireRPath&amp;#34;&lt;/span&gt;: false&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;paths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeLibraryPaths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-6.1-RELEASE.xctoolchain/usr/lib/swift/macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/usr/lib/swift&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeLibraryImportPaths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-6.1-RELEASE.xctoolchain/usr/lib/swift/macosx&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeResourcePath&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-6.1-RELEASE.xctoolchain/usr/lib/swift&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The version reported is very similar to the one displayed for the default Xcode version, except it doesn&amp;rsquo;t show a specific swiftlang and clang version.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s try to compile in Embedded mode&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo main.swift&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: link command failed with exit code &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;use -v to see invocation&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ld: library &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;System&amp;#39;&lt;/span&gt; not found&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clang: error: linker command failed with exit code &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;use -v to see invocation&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This also results in an error, but only during the linking phase.&lt;/p&gt;&lt;p&gt;What if we just generate an object file?&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo -c main.swift&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;properly generates a main.o object file.&lt;/p&gt;&lt;p&gt;And what about other targets?&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clang -print-targets&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Registered Targets:&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aarch64    - AArch64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aarch64_32 - AArch64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian ILP32&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    aarch64_be - AArch64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    arm        - ARM&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    arm64      - ARM64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    arm64_32   - ARM64 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;little endian ILP32&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    armeb      - ARM &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    avr        - Atmel AVR Microcontroller&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mips       - MIPS &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;32-bit big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mips64     - MIPS &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;64-bit big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mips64el   - MIPS &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;64-bit little endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mipsel     - MIPS &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;32-bit little endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppc32      - PowerPC &lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppc32le    - PowerPC &lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt; LE&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppc64      - PowerPC &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppc64le    - PowerPC &lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt; LE&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    riscv32    - 32-bit RISC-V&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    riscv64    - 64-bit RISC-V&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    systemz    - SystemZ&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    thumb      - Thumb&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    thumbeb    - Thumb &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;big endian&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wasm32     - WebAssembly 32-bit&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    wasm64     - WebAssembly 64-bit&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x86        - 32-bit X86: Pentium-Pro and above&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x86-64     - 64-bit X86: EM64T and AMD64&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo -c -target riscv32-none-none-eabi main.swift&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;also properly generates a main.o object file.&lt;/p&gt;&lt;p&gt;By the way, the clang version is quite similar to the one reported by the default Xcode toolchain&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clang --version&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Apple clang version 17.0.0 &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;https://github.com/swiftlang/llvm-project.git 901f89886dcd5d1eaf07c8504d58c90f37b0cfdf&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Target: arm64-apple-darwin24.4.0&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Thread model: posix&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;InstalledDir: /Users/…/Library/Developer/Toolchains/swift-6.1-RELEASE.xctoolchain/usr/bin&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Build config: +assertions&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;using-snapshot-versions&#34;&gt;Using snapshot versions&lt;/h1&gt;&lt;p&gt;Swiftly allows us to download additional toolchains, including snapshot ones.Let&amp;rsquo;s see what&amp;rsquo;s available&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftly list-available main-snapshot&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Available main development snapshot toolchains&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;----------------------------------------------&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;main-snapshot-2025-04-03&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;main-snapshot-2025-04-02&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;main-snapshot-2025-03-28&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;main-snapshot-2025-03-25&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;…&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This lists a lot of versions, going way back to 2021.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s install and use that latest one available at the time of writing (which is the same version as the one I manually downloaded above).&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftly install main-snapshot-2025-04-03&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftly use main-snapshot-2025-04-03&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And check the version&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift -print-target-info&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;compilerVersion&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Apple Swift version 6.2-dev (LLVM 3f3fde0d5f85709, Swift 0c5fd6a3017961d)&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;target&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;triple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macosx15.0&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unversionedTriple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;moduleTriple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macos&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;platform&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pointerWidthInBits&amp;#34;&lt;/span&gt;: 64,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pointerWidthInBytes&amp;#34;&lt;/span&gt;: 8,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;swiftRuntimeCompatibilityVersion&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;6.0&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;compatibilityLibraries&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;librariesRequireRPath&amp;#34;&lt;/span&gt;: false&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;paths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeLibraryPaths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain/usr/lib/swift/macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/usr/lib/swift&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeLibraryImportPaths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain/usr/lib/swift/macosx&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeResourcePath&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain/usr/lib/swift&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Just like with the main version, building in Embedded mode fails&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo main.swift&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: link command failed with exit code &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;use -v to see invocation&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ld: library &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;System&amp;#39;&lt;/span&gt; not found&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;clang: error: linker command failed with exit code &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;use -v to see invocation&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;What? This is really strange, it worked when we installed this toolchain manually and referenced it with the &lt;code&gt;TOOLCHAIN&lt;/code&gt; variable. So why does it fail here?&lt;/p&gt;&lt;p&gt;Are the toolchains different? Let&amp;rsquo;s check with&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;diff -r /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain ~/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No difference, they&amp;rsquo;re exactly the same.&lt;br&gt;I have so far no explanation for the different behaviors.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s move on, building just an object file&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo -c main.swift&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;including for another target&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo -c -target riscv32-none-none-eabi main.swift&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;works fine, similar to the main toolchain.&lt;/p&gt;&lt;p&gt;By the way, if you try to build for a non-existent target, it provides you with a list of the supported ones.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc -enable-experimental-feature Embedded -wmo -target m68k-none-none-eabi main.swift&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;unknown&amp;gt;:0: error: could not find module &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;Swift&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; target &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;m68k-none-none-eabi&amp;#39;&lt;/span&gt;; found: riscv32-none-none-eabi, arm64e-apple-none-macho, armv4t-none-none-eabi, riscv64-none-none-eabi, i686-unknown-none-elf, armv7-apple-none-macho, armv6m-none-none-eabi, aarch64-none-none-elf, wasm64-unknown-none-wasm, arm64-apple-macos, x86_64-unknown-none-elf, arm64-apple-none-macho, armv7-none-none-eabi, armv7m-apple-none-macho, arm64e-apple-ios, armv7em-none-none-eabi, arm64e-apple-macos, x86_64-apple-macos, avr-none-none-elf, armv6-apple-none-macho, armv6m-apple-none-macho, wasm32-unknown-none-wasm, arm64-apple-ios, armv7em-apple-none-macho, armv6-none-none-eabi, at: /Users/…/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain/usr/lib/swift/embedded/Swift.swiftmodule&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;toolchain-priorities&#34;&gt;Toolchain priorities&lt;/h2&gt;&lt;p&gt;With the snapshot version installed via swiftly, I tried to perform other tests with the toolchain I manually downloaded and so set the &lt;code&gt;TOOLCHAIN&lt;/code&gt; variable.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export TOOLCHAINS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;org.swift.62202504031a&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, printing the version information shows I&amp;rsquo;m still using the toolchain installed via swiftly.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift -print-target-info&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;compilerVersion&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Apple Swift version 6.2-dev (LLVM 3f3fde0d5f85709, Swift 0c5fd6a3017961d)&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;target&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;triple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macosx15.0&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;unversionedTriple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;moduleTriple&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64-apple-macos&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;platform&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arch&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arm64&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pointerWidthInBits&amp;#34;&lt;/span&gt;: 64,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;pointerWidthInBytes&amp;#34;&lt;/span&gt;: 8,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;swiftRuntimeCompatibilityVersion&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;6.0&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;compatibilityLibraries&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;librariesRequireRPath&amp;#34;&lt;/span&gt;: false&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;paths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeLibraryPaths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain/usr/lib/swift/macosx&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/usr/lib/swift&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeLibraryImportPaths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain/usr/lib/swift/macosx&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;runtimeResourcePath&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/Users/…/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2025-04-03-a.xctoolchain/usr/lib/swift&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As we&amp;rsquo;ve seen above, the toolchain installed manually and via swiftly are identical. But they reside at different locations on the filesystem.&lt;br&gt;Since the one installed by swiftly resides in my user account, and the manually installed one is in a system-wide location, the swiftly version takes precedence.&lt;br&gt;Logging in as another user that does not use swiftly, setting the &lt;code&gt;TOOLCHAINS&lt;/code&gt; variable and checking the version correctly indicates that I&amp;rsquo;m using the manually installed version.&lt;/p&gt;&lt;h2 id=&#34;end&#34;&gt;Impact for Embedded Swift&lt;/h2&gt;&lt;p&gt;As shown in &lt;a href=&#34;https://www.ericbariaux.com/posts/nrfx-blink-step-by-step/&#34;&gt;nrfx-blink Step by Step&lt;/a&gt;, I used to have the following snippet in my &lt;code&gt;settings.json&lt;/code&gt; file for Visual Studio Code.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;nrf-connect.west.env&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;:&lt;/span&gt; {        &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;$base&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;terminal&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;TOOLCHAINS&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;org.swift.61202408261a&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This ensured the proper toolchain would be used when building Embedded Swift projects based on nRF Connect SDK.&lt;/p&gt;&lt;p&gt;This is not required anymore, the toolchain selected by swiftly is properly used by West.&lt;/p&gt;&lt;p&gt;But code-completion and jump-to-definition features, although working for C code (e.g. from &lt;code&gt;BridgingHeader.h&lt;/code&gt;), are broken for Swift files.&lt;/p&gt;&lt;p&gt;Looking at the SourceKit-LSP logs (under Output tab, SourceKit Language Server), we see this&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;Error - 17:27:48&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Request textDocument/codeAction failed.&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Message: No language service &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;file:///Users/…/Development/Nelcea/EmbeddedSwift/Public/EmbeddedSwift-nRF52-Examples/Timer/Main.swift&amp;#39;&lt;/span&gt; found&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Code: -32001 &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I have not found a way to make it work so far, except mostly going back to the old way of working.&lt;br&gt;I say &lt;em&gt;mostly&lt;/em&gt; because I still used swiftly to install the snapshot toolchain, but I commented out the call to &lt;code&gt;~/.swiftly/env.sh&lt;/code&gt; from my &lt;code&gt;.zprofile&lt;/code&gt; file and re-added the &lt;code&gt;TOOLCHAINS&lt;/code&gt; definition in &lt;code&gt;settings.json&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Update 2025-05-04: There is now a workaround for this issue, see &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/swiftly-embedded-followup/&#34;&gt;Swiftly and SourceKit-LSP issue follow-up&lt;/a&gt; for more information.&lt;/em&gt;&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;In this post, I&amp;rsquo;ve shown how I used to manually select a toolchain for my builds and how swiftly changes that.&lt;br&gt;I&amp;rsquo;ve also shown how different toolchains behave when working in Embedded mode.&lt;/p&gt;&lt;p&gt;However, some behaviors are not always what I expected, and I don&amp;rsquo;t know exactly what some error messages imply. If you have more information on what&amp;rsquo;s happening here, don&amp;rsquo;t hesitate to reach out on &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I did not really talk about Swift 6.1 in this post. I will simple mention that it introduces package traits in packages definitions. This is indicated as a useful option for Embedded Swift but given all environments I use are CMake based, I haven&amp;rsquo;t looked into that yet.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Exploring Uncut - April 7th, 2025</title>
       <link>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250407/</link>
       <pubDate>Mon, 07 Apr 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250407/</guid>
       <description>&lt;h1 id=&#34;battery-low&#34;&gt;Battery low&lt;/h1&gt;&lt;p&gt;As you might have noticed, there was no post last week. I had a couple of bullet points in my note but come Sunday evening, I had not started writing any draft. I was also contemplating writing a more in-depth article on a particular topic, as I did before, but I could not decide on which one and commit to it.&lt;/p&gt;&lt;p&gt;I just needed to disconnect and relax and did not have the energy for it.&lt;/p&gt;&lt;p&gt;So instead of pushing through it, most probably missing the point of what I had to say, or shifting by one day, I decided to just skip a week.&lt;/p&gt;&lt;p&gt;So here is an update on what happened during the last two weeks.&lt;/p&gt;&lt;h1 id=&#34;embedded-swift-community-hour&#34;&gt;Embedded Swift Community Hour&lt;/h1&gt;&lt;p&gt;On Friday, March 28th, the second edition took place.&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://mastodon.social/@kubamracek&#34;&gt;Kuba&lt;/a&gt; started by doing a show and tell of configuring SourceKit-LSP with Embedded Swift on different editors so code completion would work correctly.&lt;br&gt;The main attention points are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;you need a working build in CMake first for SourceKit-LSP to work&lt;/li&gt;&lt;li&gt;the CMAKE_EXPORT_COMPILE_COMMANDS is required (a compile_commands.json file must be present)&lt;/li&gt;&lt;li&gt;you must make sure (e.g. check in the logs) that SourceKit-LSP picks up the correct toolchain.&lt;br&gt;If Xcode is not installed, exporting a TOOLCHAINS variable will not work. You then need to add the /usr/bin folder of your toolchain to the PATH variable.&lt;br&gt;&lt;em&gt;Now that &lt;a href=&#34;https://www.swift.org/blog/introducing-swiftly_10/&#34;&gt;swiftly 1.0&lt;/a&gt; has been released, it&amp;rsquo;s the easiest method to install and reference Swift toolchains.&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The open discussion then moved on to debugging and other pain point areas of Embedded Swift development. I mentioned one, where the linker would fail with no error message whatsoever.&lt;br&gt;I went on to implement a test project showing such a case. You can find it in&lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-ClassVsStruct&#34;&gt;EmbeddedSwift-nRF52-ClassVsStruct&lt;/a&gt;.&lt;br&gt;&lt;a href=&#34;https://mastodon.social/@kubamracek&#34;&gt;Kuba&lt;/a&gt; replied a few days later with a solution for this particular case. It turns out the optimization level was causing the issue.  Using &lt;code&gt;-O&lt;/code&gt; instead of &lt;code&gt;-Osize&lt;/code&gt; fixes the issue.&lt;br&gt;I would like to further understand how the optimization level is affecting the generated code and causing the link issue. This aligns with the research I started doing several weeks ago on getting a better understanding of SIL and LLVM IR. Still a lot of work on that front.&lt;/p&gt;&lt;h1 id=&#34;ios-dev-happy-hour&#34;&gt;iOS Dev Happy Hour&lt;/h1&gt;&lt;p&gt;On Saturday, I had some availability in the afternoon and so attended the &lt;a href=&#34;https://www.iosdevhappyhour.com&#34;&gt;iOS Dev Happy Hour&lt;/a&gt; virtual meet-up for the first time.&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://www.linkedin.com/in/vincentpradeilles/&#34;&gt;Vincent Pradeilles 👨🏻‍💻&lt;/a&gt; started with a presentation of some interesting SwiftUI features introduced in previous versions of iOS (from iOS 15 onwards). I always find this kind of presentation useful as it&amp;rsquo;s nearly impossible to remember all the SwiftUI types and modifiers unless you use them frequently. Moreover, when you&amp;rsquo;re faced with a particular problem, finding the appropriate way to tackle it is also not easy. Having regular reminders of how people use SwiftUI to implement particular UI/UX behaviors helps me deal with that.&lt;/p&gt;&lt;p&gt;After the presentation, the participants split into different discussion rooms, where smaller groups (of around 10 people maximum) can chat about a particular topic or simply get to know each other.&lt;br&gt;I had the opportunity to discuss upcoming conferences, AVFoundation, and visionOS as well as get to know some community members (and say hello to some I already know).&lt;/p&gt;&lt;p&gt;I enjoyed the format a lot, which remembers me of the vibe and energy you get from networking at physical conferences. I&amp;rsquo;ll definitely try to be part of future occurrences.&lt;/p&gt;&lt;h1 id=&#34;ble-in-embedded-swift&#34;&gt;BLE in Embedded Swift&lt;/h1&gt;&lt;p&gt;Last week, in &lt;a href=&#34;https://discord.gg/J9nDXGTXVZ&#34;&gt;The Swift Programming Language Discord&lt;/a&gt;, somebody posted a question about working with BLE in Embedded Swift. As I had done quite a bit of work on that for my &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-ArcReactor&#34;&gt;Arc Reactor&lt;/a&gt; project, I happily answered.&lt;/p&gt;&lt;p&gt;But I never published the BLE code as it required cleanup. It was rushed together just in time for it to be ready for a conference talk. Twice!&lt;br&gt;The first time, for Pragma in November 2024, I had quite a bit of C glue code to relay between the Zephyr BLE API and my Swift code. That bothered me.&lt;br&gt;Later, for FOSDEM in February 2025, I managed to get rid of the C code altogether. But it was still prototype code with known issues (e.g. memory leaks).&lt;br&gt;At that time, I also started putting together smaller examples showing specific features of using BLE from Embedded Swift. The goal was to publish that code and write a series of articles to accompany it. But I put that on hold and never progressed on it.&lt;br&gt;Now that I know these examples would actually benefit someone, I&amp;rsquo;ll take the required time to publish something.&lt;br&gt;I&amp;rsquo;ll publish the examples on GitHub at &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-BLEExamples&#34;&gt;Embedded Swift version of the Nordic Dev Academy BLE examples&lt;/a&gt;. The first example is already online, others will follow as I find the time to properly implement them.&lt;/p&gt;&lt;p&gt;That&amp;rsquo;s it for this week, as always, feel free to get in touch on &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt;, I&amp;rsquo;d love to hear your thoughts.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Exploring Uncut - March 24th, 2025</title>
       <link>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250324/</link>
       <pubDate>Mon, 24 Mar 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250324/</guid>
       <description>&lt;h1 id=&#34;structs-classes-and-memory&#34;&gt;Structs, classes and memory&lt;/h1&gt;&lt;p&gt;I continued my reflection on how value and reference semantic impacts the memory allocation in the generated code.&lt;/p&gt;&lt;p&gt;Given there&amp;rsquo;s now an active Embedded Swift channel on &lt;a href=&#34;https://discord.gg/J9nDXGTXVZ&#34;&gt;The Swift Programming Language Discord&lt;/a&gt;, I asked the question there. Some comments led me to revisite the &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-HeapOrStack&#34;&gt;test examples&lt;/a&gt; I made earlier and update them. It started to make slightly more sense but not yet totally.&lt;/p&gt;&lt;p&gt;But then &lt;a href=&#34;https://github.com/AliMark71&#34;&gt;AliMark71&lt;/a&gt; posted a link to the &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2024/10217&#34;&gt;Explore Swift performance&lt;/a&gt; video by John McCall from WWDC 2024. And this video answers most of the questions I had, explaining in detail the different cases of how Swift would decide where to allocate memory from. I highly recommend watching this video and in fact will watch it again as it contains quite a bit of information to ingest.&lt;/p&gt;&lt;p&gt;And as is often the case with WWDC videos, I went down the dependency tree and started watching referenced videos:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2016/416&#34;&gt;Understanding Swift Performance&lt;/a&gt; by Kyle Macomber and Arnold Schwaighofer from WWDC 2016&lt;/li&gt;&lt;li&gt;Building Better Apps with Value Types in Swift by Doug Gregor and Bill Dudney from WWDC 2015&lt;/li&gt;&lt;li&gt;Protocol-Oriented Programming in Swift by Dave Abrahams from WWDC 2015&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;It&amp;rsquo;s a pity but it seems videos of the later are not available on-line anymore. However you can check the &lt;a href=&#34;https://wwdcnotes.com/documentation/wwdcnotes&#34;&gt;WWDC Notes&lt;/a&gt; for all those videos:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://wwdcnotes.com/documentation/wwdcnotes/wwdc24-10217-explore-swift-performance&#34;&gt;Explore Swift performance&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://wwdcnotes.com/documentation/wwdcnotes/wwdc16-416-understanding-swift-performance&#34;&gt;Understanding Swift Performance&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://wwdcnotes.com/documentation/wwdcnotes/wwdc15-414-building-better-apps-with-value-types-in-swift/&#34;&gt;Building Better Apps with Value Types in Swift&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://wwdcnotes.com/documentation/wwdcnotes/wwdc15-408-protocoloriented-programming-in-swift&#34;&gt;Protocol-Oriented Programming in Swift&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Those presentations contain a lot of useful information, sometimes covering things I&amp;rsquo;m using in my Swift code but did not grasp the fundamentals of or the ideas behind them to their full extent.&lt;/p&gt;&lt;h1 id=&#34;getting-the-round-display-working&#34;&gt;Getting the round display working&lt;/h1&gt;&lt;h2 id=&#34;debugging-the-screen&#34;&gt;Debugging the screen&lt;/h2&gt;&lt;p&gt;The &lt;a href=&#34;https://fr.aliexpress.com/item/1005007112122595.html&#34;&gt;Logic Analyzer&lt;/a&gt; I ordered arrived last week. This is a cheap Chinese version I ordered on Ali Express. Quite incredible that this thing costs less than 6 €. For the software, there are multiple choices available, but to start I decided to try out &lt;a href=&#34;https://www.saleae.com/pages/downloads?srsltid=AfmBOoqtFCyIIO5Yrr4aEv9MCNZXm7rRVxSRi7kzf1ak8lazv-EpRSlX&#34;&gt;Logic 2&lt;/a&gt; from &lt;a href=&#34;https://www.saleae.com&#34;&gt;Saleae&lt;/a&gt;. The freely available software is designed for their hardware but also works with many other ones. I&amp;rsquo;m not sure how they feel about people using their software this way but I can&amp;rsquo;t justify spending 500 € or more on their hardware for my usage. I might move to the open source &lt;a href=&#34;https://sigrok.org/wiki/PulseView&#34;&gt;PulseView - sigrok&lt;/a&gt; software in the future tough.&lt;/p&gt;&lt;p&gt;In order to connect the signals to capture to the analyzer, I connected the display to a bread board first and from there to the boards. First to the XIAO board, that works as expected, then to the nRF 52840 DK.&lt;/p&gt;&lt;figure class=&#34;mid&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250324/DisplayWithLogicAnalyzer.png&#34;    alt=&#34;Cabling the display through a bread board to allow connecting the logic analyzer.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Cabling the display through a bread board to allow connecting the logic analyzer.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;I was hoping to clearly see some missing or wrong signal, but at first glance, I could not see much difference between the two captures. Also this is my first time working with a logic analyzer and I only have a very high level knowledge of how SPI works.&lt;/p&gt;&lt;p&gt;&lt;figure class=&#34;mid no-shadow&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250324/Capture_XIAO.png&#34;    alt=&#34;Capture of the working display on a Seeed Studio XIAO nRF52840.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Capture of the working display on a Seeed Studio XIAO nRF52840.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;figure class=&#34;mid no-shadow&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250324/Capture_nRF52840.png&#34;    alt=&#34;Capture of the blank display on a nRF52840 DK. I don&amp;#39;t know what to make out of this.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Capture of the blank display on a nRF52840 DK. I don&amp;rsquo;t know what to make out of this.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;&lt;p&gt;The logical next step I would take would be to study in more detail what I don&amp;rsquo;t know. Use a simple sensor connected via SPI where I could send a few bytes at a time and check the capture. Read about what the capture software can do and experiment with it. Understand SPI in much more details. Look at the source code of the display driver and how it uses SPI under the hood.&lt;/p&gt;&lt;p&gt;But I wasn&amp;rsquo;t thrilled about how much time this would take and was eager to get the display working.&lt;/p&gt;&lt;p&gt;So I gave ChatGPT a try. I explained what I wanted to do, indicated the connections I had made, the PINs I used and the DTS configuration I wrote. It pointed out that my cabling was wrong and proposed another one. It turned out that the proposed cabling was even less correct but it had correctly discovered an issue with mine. After triple checking I found the error and fixed it.&lt;/p&gt;&lt;p&gt;But the display stayed blank.&lt;/p&gt;&lt;p&gt;I continued my discussion with ChatGPT and as I had enabled logging at the SPI level using the following snippet&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;CONFIG_LOG=y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;CONFIG_DISPLAY_LOG_LEVEL_DBG=y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;CONFIG_SPI_LOG_LEVEL_DBG=y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;in my prj.conf file, I also provided debug logs (those seemed to indicate that the SPI transactions were successful tough).&lt;br&gt;ChatGPT proposed other configuration changes (mostly incorrect) but also listed some additional checks and changes I could try. One of those was talking about the frequency used for SPI and indeed, that turned out to be the issue.&lt;br&gt;When I set the frequency to a lower value, I finally had the display working as expected.&lt;/p&gt;&lt;h2 id=&#34;integrating-the-joystick-control&#34;&gt;Integrating the joystick control&lt;/h2&gt;&lt;p&gt;Instead of having the spaceship go round the screen, I now wanted to control it with the joystick. So I hooked up my adapter to some available PINs, configured the GPIOs in the project, wrote the code to read the joystick position and move the spaceship accordingly. And nothing happened—the spaceship was motion less!&lt;/p&gt;&lt;p&gt;This time I had a good hunch for what the issue could be (I knew I was just being lazy but took my chance anyway). Looking into the board DTS files (nrf52840dk_nrf52840-pinctrl.dtsi and nrf52840dk_nrf52840.dts) confirmed that the PINs I was connected to were used by SPI1, enabled by default. As it is not in used, I disabled it in my overlay and all was fine.&lt;/p&gt;&lt;p&gt;I had quickly slapped together some test code and now wanted to organise it a bit better.&lt;br&gt;I thought &amp;ldquo;why re-invent the wheel ?&amp;rdquo;. Could I use some standard API, one that Swift developers might already know?&lt;br&gt;Apple has a whole &lt;a href=&#34;https://developer.apple.com/documentation/gamecontroller/&#34;&gt;Game Controller API&lt;/a&gt; available, could I make an implementation of that ? Turns out, this API is quite generic and has a large surface, too much for my first prototype here.&lt;/p&gt;&lt;p&gt;I only took a bit of inspiration from it and ended up with this simple code for now.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;DirectionPadState&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; upPressed: Bool&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; downPressed: Bool&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; leftPressed: Bool&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; rightPressed: Bool&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Joystick&lt;/span&gt; {  &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; dpadState: DirectionPadState&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; fireButtonPressed: Bool&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; upGPIO: UnsafeMutablePointer&amp;lt;gpio_dt_spec&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; downGPIO: UnsafeMutablePointer&amp;lt;gpio_dt_spec&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; leftGPIO: UnsafeMutablePointer&amp;lt;gpio_dt_spec&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; rightGPIO: UnsafeMutablePointer&amp;lt;gpio_dt_spec&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; buttonGPIO: UnsafeMutablePointer&amp;lt;gpio_dt_spec&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(upGPIO: UnsafeMutablePointer&amp;lt;gpio_dt_spec&amp;gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        downGPIO: UnsafeMutablePointer&amp;lt;gpio_dt_spec&amp;gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        leftGPIO: UnsafeMutablePointer&amp;lt;gpio_dt_spec&amp;gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rightGPIO: UnsafeMutablePointer&amp;lt;gpio_dt_spec&amp;gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        buttonGPIO: UnsafeMutablePointer&amp;lt;gpio_dt_spec&amp;gt;) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.upGPIO = upGPIO&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.downGPIO = downGPIO&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.leftGPIO = leftGPIO&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.rightGPIO = rightGPIO&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.buttonGPIO = buttonGPIO&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_pin_configure_dt(upGPIO, GPIO_INPUT)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_pin_configure_dt(downGPIO, GPIO_INPUT)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_pin_configure_dt(leftGPIO, GPIO_INPUT)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_pin_configure_dt(rightGPIO, GPIO_INPUT)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_pin_configure_dt(buttonGPIO, GPIO_INPUT)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dpadState = DirectionPadState(upPressed: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;, downPressed: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;, leftPressed: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;, rightPressed: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fireButtonPressed = &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;mutating&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;readState&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.dpadState = DirectionPadState(upPressed: gpio_pin_get_dt(upGPIO) == &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                downPressed: gpio_pin_get_dt(downGPIO) == &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                leftPressed: gpio_pin_get_dt(leftGPIO) == &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                rightPressed: gpio_pin_get_dt(rightGPIO) == &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.fireButtonPressed = gpio_pin_get_dt(buttonGPIO) == &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;RoundDisplaySupport&#34;&gt;Modelling a screen support&lt;/h2&gt;&lt;p&gt;Now that I started developing some basic interactions in the game, I needed to look at the screen more often. But with this contraption of cables connecting it to the board, it was difficult to get a clear view on it as it had a tendency to mostly lay flat on my desk.&lt;/p&gt;&lt;p&gt;I thus decided to 3D print a support for it and as I had already used some Lego© blocks to host my board in another project, I designed the support to attach to a Lego© plate.&lt;/p&gt;&lt;p&gt;I fired up Fusion 360, extracted some basic enclosure I already did in the past and extended it. The Seeed Studio round display has three threads at its back that you can use to screw it to a support. I remembered that in my previous project, although I made some measurement and tests, I was still slightly off for my support holes and I had used a drill to make them loose for the screws to fit.&lt;/p&gt;&lt;figure class=&#34;mid&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250310/XIAOOnDisplay.png&#34;    alt=&#34;Three threads at the back of Seeed Studio Round Display allow to attach it to a support.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Three threads at the back of Seeed Studio Round Display allow to attach it to a support.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;There&amp;rsquo;s an STL file on the Seeed Studio website with some enclosure for that display, with the holes properly positioned. As I did not know how to import the STL in Fusion AND keep the proper dimensions, I opened the STL file in Bambu Studio and use the measurement tool in there. This gave me some measurements but not the ones I was looking for (the angles between the holes as measured from the center of the display).&lt;/p&gt;&lt;p&gt;I could compute those angles based on some trigonometry formulae. But I never remember if I need to use sine or cosine, for the adjacent or opposite side… So I was lazy (and curious). Having drawn a schematic representation of the back of the display, with the measurements I had and the values I was looking for, I asked ChatGPT.&lt;/p&gt;&lt;figure class=&#34;mid&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250324/Angles.jpeg&#34;    alt=&#34;The doodle I gave ChatGPT to work with.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The doodle I gave ChatGPT to work with.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;I eventually got the values I was after but it took several tries and I had to give additional information to ChatGPT to get there. In particular, the values it proposed did not pass the most basic test of common sense. For instance, it first gave me a value of alpha of about 30 degrees while it&amp;rsquo;s clear on the graph that it&amp;rsquo;s an obtuse angle. After I pointed that out, it answered something like 220 degrees. Again, obtuse angle. I also had to point out that beta and gamma where equals and that the sum of all three angles had to be 360 degrees.&lt;/p&gt;&lt;p&gt;What ChatGPT can accomplish is quite extraordinary, and it amazed me that it could make any sense out of the doodle I gave it. But I interpret this example as a proof that the generative AI extracts features of a text corpus but does not learn a model of the world based on it.&lt;br&gt;It is interesting to note that having that common sense is sometimes also missing in humans (and I&amp;rsquo;m certainly guilty as charged in certain situations to behave as such). For instance children learning maths or physics will trust the result of their calculation even when the answer doesn&amp;rsquo;t make any sense.&lt;/p&gt;&lt;p&gt;I kept using ChatGPT throughout the design process. For instance, I would capture my current Fusion 360 sketch, annotate it with some scribble of what I was after and ask for step by step instructions on how to make that happen. And for this task, the results were really good. It got me to the desired result much faster than using a search engine to lookup software features.&lt;/p&gt;&lt;p&gt;And at the end of the afternoon, I had my screen nicely vertically mounted. I was thrilled with the result so far and spend a good minute making the spaceship go left and right.&lt;br&gt;Now, all that&amp;rsquo;s left is writing more code.&lt;/p&gt;&lt;figure class=&#34;mid&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250324/FinalSetup.png&#34;    alt=&#34;The final setup, with the display attached in its 3D printed support.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The final setup, with the display attached in its 3D printed support.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;h1 id=&#34;hacking-with-swift-livestream&#34;&gt;Hacking with Swift+ livestream&lt;/h1&gt;&lt;p&gt;Past Saturday, &lt;a href=&#34;https://mastodon.social/@twostraws&#34;&gt;Paul Hudson&lt;/a&gt; hosted another of his monthly livestream during which we build an application from scratch. This time, it was a iOS word game.&lt;/p&gt;&lt;p&gt;Although I did not learn much in terms of code or API, I still get a lot of value out of those sessions.Practicing using the APIs for real applications, seeing when and why choosing one over the other makes sense and what the final result is gets them deeper under your skin (or in your head). So when it comes time to develop your own application, you&amp;rsquo;re that much more productive. As the saying goes &amp;ldquo;practice makes perfect&amp;rdquo;.&lt;/p&gt;&lt;p&gt;Then there&amp;rsquo;s the community of course. Working together towards that goal feels great. Seeing the questions other people have is really interesting. You get to help them if you can but it also makes you think about things in a different way. And as someone would likes to write and present talks, it&amp;rsquo;s interesting to understand what concepts people have more difficulties to grasp and what explanation makes more sense to them.&lt;/p&gt;&lt;p&gt;And finally, seeing what can be accomplished in less than two hours is a great reminder that you don&amp;rsquo;t need that much time to explore some idea you have and build something that people are interested in. This is an important source of motivation.&lt;/p&gt;&lt;figure class=&#34;small no-shadow&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250324/Scramblet.png&#34;    alt=&#34;Scramblet, a word game Paul had us made in a bit more than an hour.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Scramblet, a word game Paul had us made in a bit more than an hour.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;h1 id=&#34;embedded-swift-community-hour&#34;&gt;Embedded Swift Community Hour&lt;/h1&gt;&lt;p&gt;The &lt;a href=&#34;https://forums.swift.org/t/embedded-swift-community-hour-march-28-2025/78733&#34;&gt;next meet-up&lt;/a&gt; happens this Friday March 28th at  6PM CET. Join us for a nice conversation between people passionate about Embedded Swift.&lt;/p&gt;&lt;p&gt;In the meantime, feel free to get in touch on &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt;.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Exploring Uncut - March 17th, 2025</title>
       <link>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250317/</link>
       <pubDate>Mon, 17 Mar 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250317/</guid>
       <description>&lt;h1 id=&#34;embedded-swift-community-hour&#34;&gt;Embedded Swift Community Hour&lt;/h1&gt;&lt;p&gt;Last Friday, &lt;a href=&#34;https://hachyderm.io/@rauhul&#34;&gt;Rauhul&lt;/a&gt; organized an &lt;a href=&#34;https://forums.swift.org/t/embedded-swift-community-hour/78406&#34;&gt;Embedded Swift Community Hour&lt;/a&gt; call on Discord, where members of the community interested in Embedded Swift gathered, presented their projects and talked about the future of this topic.&lt;/p&gt;&lt;p&gt;It was super interesting to virtually meet such a nice group of people, motivated to explore, share their findings and push the boundaries of Embedded Swift forward. I discovered super nice projects such as &lt;a href=&#34;https://github.com/mortenbekditlevsen/thelittlegame&#34;&gt;thelittlegame&lt;/a&gt; by &lt;a href=&#34;https://mastodon.social/@mortenbekditlevsen&#34;&gt;Morten&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;One of the core ideas of Swift is progressive disclosure — the ability to start simple but then progressively move to more complex projects without starting all over again.&lt;/p&gt;&lt;p&gt;We discussed how this is not currently true when targeting embedded platforms with Swift, the current hurdles that newcomers face, and the fact that the diversity of available platforms makes this even worse.&lt;br&gt;Starting up requires dealing with quite a few low-level concepts and working with C APIs. The true power of Swift only comes when you’ve created abstractions on top of those.&lt;br&gt;A few people, myself included, have created such abstractions and we discussed the challenge of sharing this code. We then extrapolated to how to potentially create a Swift based HAL.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Update 2025-03-18: For a more factual / in-depth recap of the meeting, check out Rauhul&amp;rsquo;s post: &lt;a href=&#34;https://forums.swift.org/t/embedded-swift-community-hour/78406/16&#34;&gt;Embedded Swift Community Hour – March 14th, 2025 – Recap&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;&lt;h1 id=&#34;game-follow-up&#34;&gt;Game follow-up&lt;/h1&gt;&lt;p&gt;As I mentioned last week, I haven’t succeeded in connecting the Seeed Studio Round Display to the nRF 52840 DK. I did try two different SPIs, read some posts online, but quickly ran out of ideas on how to easily debug this with the information at hand. I thought maybe the easiest would be to check the SPI signals using a logic analyzer. As I don’t own one, I ordered a cheap one online and parked that problem for a bit.&lt;/p&gt;&lt;p&gt;Another aspect I wanted to explore for the game is using a joystick as input. I dug an old joystick from my Amiga times out of the attic, now all I needed was a way to connect it to my microcontroller board.&lt;/p&gt;&lt;p&gt;So I soldered a breakout cable to connect any old &amp;ldquo;DB-9 connector&amp;rdquo; joystick (such as used on the Commodore 64 and Amiga) to the nRF 52840 DK.&lt;/p&gt;&lt;figure class=&#34;mid&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250317/JoystickOnDK.png&#34;    alt=&#34;An old joystick connected to a nRF52840 DK board via a custom made breakout cable.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;An old joystick connected to a nRF52840 DK board via a custom made breakout cable.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;I then wrote a quick test program to detect the movements of the joystick and fire button presses and print information on the console. I’ll write a full article on this topic soon.&lt;/p&gt;&lt;h1 id=&#34;down-the-rabbit-hole&#34;&gt;Down the rabbit hole&lt;/h1&gt;&lt;p&gt;As indicated two weeks ago, I did not finish writing all I had been exploring in time for publishing the post, so I postponed writing about it until this week.&lt;/p&gt;&lt;p&gt;After publishing &lt;a href=&#34;https://www.ericbariaux.com/posts/previous_oversights_nrf52/&#34;&gt;Addressing previous oversights&lt;/a&gt;, I noticed some other weird behavior in my code during further testing. Re-reading the post, I feel like I introduced more confusion than I clarified things and realized I do not grasp the subject as well as I wanted to.&lt;/p&gt;&lt;p&gt;Part of the issue, I think, is understanding how the reference vs value type dichotomy translates into heap vs stack allocations.&lt;/p&gt;&lt;p&gt;One might think the rule is simple: reference types are allocated on the heap and value types on the stack. But this is not true. I’ve tried conducting experiments with different code samples, just observing the output of print statements but I could not deduce any conclusive rules.&lt;/p&gt;&lt;p&gt;I’ve thought about several ways to get a better understanding, from using a custom build toolchain that I could run in a debugger (or simply adding some log statements in it at appropriate places) to looking at the final assembly code.&lt;/p&gt;&lt;p&gt;I’m wondering whether reading the generated SIL output would get me the information I want and would be the simplest option.&lt;/p&gt;&lt;p&gt;Anyway, these are all well beyond my comfort zone and I did not know exactly where to start to fill in the numerous gaps in my current knowledge.&lt;/p&gt;&lt;p&gt;So I searched for conference talks about SIL, as this is my preferred learning method.I have already watched&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=NH-qIKOoKgA&#34;&gt;🖇 Introduction to Swift Intermediate Language — Alex Blewitt&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.conf42.com/Mobile_2022_Pawel_Lopusinski_obscure_swift&#34;&gt;Conf42: Obscure Swift by Pawel Lopusinski&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;and I started watching &lt;a href=&#34;https://www.youtube.com/watch?v=Ntj8ab-5cvE&#34;&gt;2015 LLVM Developers’ Meeting: J. seph Groff &amp;amp; Chris Lattner “Swift&amp;rsquo;s High-Level IR: A Case Study&amp;hellip;&amp;quot;&lt;/a&gt; but that last one is a bit tough for a compiler newbie&lt;/p&gt;&lt;p&gt;I now need to put that into practice and look at some of the SIL code from my test projects. I’ll be sure to report further as I do that.&lt;/p&gt;&lt;p&gt;That&amp;rsquo;s it for this week, as always, feel free to get in touch on &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt;, I&amp;rsquo;d love to hear your thoughts.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Exploring Uncut - March 10th, 2025</title>
       <link>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250310/</link>
       <pubDate>Mon, 10 Mar 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250310/</guid>
       <description>&lt;h1 id=&#34;a-bit-of-a-social-life&#34;&gt;A bit of a social life&lt;/h1&gt;&lt;p&gt;Not much happened this week in terms of exploration.&lt;br&gt;Being an introvert, I try to space out social events so I have time to recharge in between. This week was a bit of a failure on that front, with one concert, two family dinners, lunch with a friend, and a GeekClub meeting.&lt;br&gt;You might be wondering—what exactly is GeekClub?&lt;/p&gt;&lt;p&gt;I’ve been a CoderDojo coach for several years now. We meet about once a month to help kids between 7 and 17 years discover programming.&lt;br&gt;Watching kids tackle exciting programming projects at CoderDojo is always inspiring. But as coaches, we started to feel like spectators and were longing for more.&lt;br&gt;Some of the coachs and I invited a few friends and started meeting once a month to discuss tech (and more) over drinks. This month’s topics included full stack development in Swift or Python, Software Defined Radios and antenna shapes, Home Assistant and Modus, 3D printing filaments and more.&lt;/p&gt;&lt;h1 id=&#34;round-display-follow-up&#34;&gt;Round display follow-up&lt;/h1&gt;&lt;p&gt;Last week, I built a quick prototype of a spaceship orbiting the edge of a round display. The next step is to control the ship using buttons or an old joystick.&lt;/p&gt;&lt;p&gt;The Seeed Studio Round Display integrates seamlessly with the XIAO chips, such as the nRF 52840. Solder header pins on the XIAO module, plug it into the display and voilà!&lt;/p&gt;&lt;figure class=&#34;small&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250310/XIAOOnDisplay.png&#34;    alt=&#34;A XIAO nRF52840 board on the Seeed Studio Round Display.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;A XIAO nRF52840 board on the Seeed Studio Round Display.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;But there’s a catch: the XIAO plugs directly into the display, using up all its GPIO pins—leaving no room for extra controls, which I need for game input.&lt;/p&gt;&lt;p&gt;I’ve identified two options to overcome this:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;use the recently released Plus version of the XIAO chip, that exposes 9 more pins&lt;/li&gt;&lt;li&gt;or make custom connections to a different board&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&#34;no-shadow&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250310/XIAOPlusPinout.png&#34;    alt=&#34;Pinout for the XIAO nRF52840 Sense Plus.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Pinout for the XIAO nRF52840 Sense Plus.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;I explored the second option with a nRF52840 DK and ran some preliminary tests, but without much success. The backlight turns on, but nothing gets drawn on the screen.&lt;/p&gt;&lt;h1 id=&#34;unwrap-live&#34;&gt;Unwrap live&lt;/h1&gt;&lt;p&gt;This past Saturday, &lt;a href=&#34;https://mastodon.social/@twostraws&#34;&gt;Paul Hudson&lt;/a&gt; hosted his &lt;a href=&#34;https://www.hackingwithswift.com/articles/274/take-on-apple-intelligence-at-unwrap-live-2025&#34;&gt;Unwrap Live&lt;/a&gt; event. This year, the theme was Apple Intelligence, with a big focus on using App Intents in your apps.&lt;br&gt;They allow an app to expose actions and content, making it part of the Apple Intelligence mechanism. At least, that&amp;rsquo;s the promise. For now, it&amp;rsquo;s mostly exposed to shortcuts and Siri. But that&amp;rsquo;s already a big deal and it revived some ideas I had for existing and future apps.&lt;/p&gt;&lt;p&gt;As usual, it was a very interesting (and intense) session offered by Paul where I learned not only about the main topic but picked up a few additional tidbits along the way.&lt;/p&gt;&lt;p&gt;For instance, I always forget how to initialize &lt;code&gt;@State&lt;/code&gt;variables using an initializer and the &lt;code&gt;_&lt;/code&gt; notation to initiliaze the wrapped value. The following example demonstrates using that technique for safely initializing a SwiftData container.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyApp&lt;/span&gt;: App {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @State &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; modelContainer: ModelContainer&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; modelContainer: ModelContainer&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            modelContainer = &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; ModelContainer(&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt;: MyModel.&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#66d9ef&#34;&gt;catch&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error loading ModelContainer, switching to in-memory storage.&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; config = ModelConfiguration(isStoredInMemoryOnly: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            modelContainer = &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt;! ModelContainer(&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt;: MyModel.&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;, configurations: config)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;._modelContainer = .&lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(initialValue: modelContainer)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Or that I can use the shorter, key path based, notation to access a property with a function that takes in a closure, such as in a map operation, using&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;items.map(&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;.name)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;instead of&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;items.map { $0.name }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it for this week, as always, feel free to get in touch on &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt;, I&amp;rsquo;d love to hear your thoughts.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Exploring Uncut - March 3rd, 2025</title>
       <link>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250303/</link>
       <pubDate>Mon, 03 Mar 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/exploring-uncut-20250303/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;I would like to publish more often on this blog. I really do.&lt;/p&gt;&lt;p&gt;In fact, I have a long list of topics to write about. I even have several draft posts that I should &lt;em&gt;just&lt;/em&gt; finalize and publish.&lt;/p&gt;&lt;p&gt;One main issue is that, as I reread a post to put the finishing touches on it, I ask myself more questions. Is it totally exact ? Does it need more background information ? Why can I write this and can I prove it somehow ?&lt;/p&gt;&lt;p&gt;I don&amp;rsquo;t think that this is wrong per se, but it&amp;rsquo;s in conflict with the desire to publish more often. And I believe a lot of the information that will end up in those posts would already be helpful to some people right now. Even if incomplete or potentially wrong, as long as I make that clear in my writing.&lt;br&gt;I also think that my journey to get to that final post and the process I use to overcome the challenges along the way have value in themselves.&lt;/p&gt;&lt;p&gt;I thus decided to start this new &amp;ldquo;Exploring Uncut&amp;rdquo; series, through which I&amp;rsquo;ll make public the explorations that have been keeping me busy during the week.&lt;br&gt;I might certainly abandon some of those or put them aside for a while. There will probably be more questions than answers, failures than success, ideas than achievements. But I don&amp;rsquo;t care, at least I&amp;rsquo;ll get something out there that one person might find interesting or useful.&lt;br&gt;And if not, I will have cleared my head for a fresh week.&lt;/p&gt;&lt;h1 id=&#34;shall-we-play-a-game&#34;&gt;Shall we play a game&lt;/h1&gt;&lt;h2 id=&#34;getting-an-idea&#34;&gt;Getting an idea&lt;/h2&gt;&lt;p&gt;Several weeks ago, &lt;a href=&#34;https://mastodon.social/@franklefebvre&#34;&gt;Frank Lefebvre&lt;/a&gt; posted a &lt;a href=&#34;https://mastodon.social/@franklefebvre/113923163280746147&#34;&gt;video&lt;/a&gt; of a small game he was developing in Embedded Swift, in preparation of his &lt;a href=&#34;https://dev.events/conferences/ar-ctic-conference-av8apvom&#34;&gt;workshop&lt;/a&gt; at &lt;a href=&#34;https://dev.events/conferences/ar-ctic-conference-av8apvom&#34;&gt;ARCtic Conference&lt;/a&gt;. I find this really cool and was inspired to think about games I could develop using Embedded Swift. And why not even build a portable gaming console (we&amp;rsquo;ll see for that one).&lt;/p&gt;&lt;p&gt;As I have a couple of &lt;a href=&#34;https://wiki.seeedstudio.com/get_start_round_display/&#34;&gt;Seeed Studio Round Displays&lt;/a&gt; lying around, that I&amp;rsquo;ve already used in a &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-ArcReactor&#34;&gt;project&lt;/a&gt;, I was wondering what would be a good use for it.&lt;/p&gt;&lt;p&gt;The format of the screen reminded me of a video game I loved to play as a kid on my Commodore 64: Gyruss. I think this can be a great fit, as the game graphics are arranged in a circle.&lt;/p&gt;&lt;p&gt;I did some quick research and found this YouTube video: &lt;a href=&#34;https://www.youtube.com/watch?v=hz1SwpUQNYE&#34;&gt;The History of Gyruss - Arcade console documentary&lt;/a&gt;, from which I learned that this kind of layout / animation in games has a name: Tubeshooters.&lt;/p&gt;&lt;p&gt;Finding this video had the adverse side effect of loosing me quite a bit of time. Being a fan (and collector) of old computers, I did spend the next few hours looking at retro gaming / retro computer videos.&lt;/p&gt;&lt;h2 id=&#34;a-first-test&#34;&gt;A first test&lt;/h2&gt;&lt;p&gt;After that interlude, I started the first test. Can I make a spaceship go round the border of the display?&lt;br&gt;So first step was to get an icon for my ship. I remembered &lt;a href=&#34;https://mastodon.social/@twostraws&#34;&gt;Paul Hudson&lt;/a&gt; mentioning a great site with free artwork that could be used for game development during an HWS+ session: &lt;a href=&#34;https://www.kenney.nl/&#34;&gt;Kenney&lt;/a&gt;.&lt;br&gt;And sure enough, I found my space ship (&lt;a href=&#34;https://www.kenney.nl/assets/space-shooter-extension&#34;&gt;Space Shooter Extension · Kenney&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;I already had used LVGL (Light and Versatile Graphics Library), a free and open-source graphics library widely used in the embedded space for a previous project. And I already had written some Swift types to wrap the core features I needed, like managing &lt;code&gt;Screen&lt;/code&gt;s and displaying &lt;code&gt;Image&lt;/code&gt;s.&lt;br&gt;Starting from there, I added the ability to move and rotate images and was nearly ready for some testing.&lt;/p&gt;&lt;p&gt;The final step was to convert my spaceship image to the appropriate format. First, since the screen has a diameter of 240 pixels, I needed to resize the icon I downloaded. But more importantly, the most efficient way to use an image from LVGL is to have it as a byte array compiled in the code, not to load it from a file (certainly not in a compressed format).&lt;/p&gt;&lt;p&gt;There&amp;rsquo;s an on-line &lt;a href=&#34;https://lvgl.io/tools/imageconverter&#34;&gt;Image Converter&lt;/a&gt; that you can use for that, but there&amp;rsquo;s also an &lt;a href=&#34;https://github.com/lvgl/lv_img_conv.git&#34;&gt;offline version&lt;/a&gt; that I had installed before. I went to a terminal and used the following command&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./lv_img_conv.js SpaceShip.png  -f -c CF_INDEXED_2_BIT&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This generates C code. Although I could use it as is and Swift C Interop would perfectly handle that, the C code is so simple that I preferred to convert it to Swift.This now looks something like&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SpaceShip&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; data: [UInt8] = [&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;/*Pixel format: Alpha 8 bit, Red: 5 bit, Green: 6 bit, Blue: 5 bit  BUT the 2  color bytes are swapped*/&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ae81ff&#34;&gt;0x00&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x00&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x00&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x00&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x00&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x00&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x00&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x00&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x00&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0x00&lt;/span&gt;, &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ]&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; description = {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;Self&lt;/span&gt;.data.withUnsafeBufferPointer { ptr &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      lv_img_dsc_t(&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        header: lv_img_header_t(cf: UInt32(LV_IMG_CF_TRUE_COLOR_ALPHA), always_zero: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, reserved: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, w: &lt;span style=&#34;color:#ae81ff&#34;&gt;40&lt;/span&gt;, h: &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;),&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        data_size: &lt;span style=&#34;color:#ae81ff&#34;&gt;1200&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; UInt32(LV_IMG_PX_SIZE_ALPHA_BYTE),&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        data: ptr.baseAddress)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I already thought about making a fork so the tool can directly generate the Swift code, but this is not my priority right now.&lt;/p&gt;&lt;p&gt;The first test was not very conclusive, as the ship was not rotating around an axis perpendicular to the screen but kind of flipping around a vertical axis in a way not really correlated to the provided angle.&lt;/p&gt;&lt;p&gt;The LVGL documentation is quite good, so reading it provided valuable information.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;The transformations require the whole image to be available. Therefore indexed images, alpha only images or images from files can not be transformed.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Indeed as you might have noticed, when using the converter, we need to indicate a color format. And I initially used &lt;code&gt;CF_INDEXED_2_BIT&lt;/code&gt;, the image being pretty simple, that would have limited the size.&lt;br&gt;Changing the color format to &lt;code&gt;CF_TRUE_COLOR_ALPHA&lt;/code&gt; made the rotation work as expected.&lt;/p&gt;&lt;h2 id=&#34;the-result&#34;&gt;The result&lt;/h2&gt;&lt;p&gt;Here&amp;rsquo;s the result of the first test, a spaceship going round the screen.&lt;/p&gt;&lt;figure class=&#34;no-shadow&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250303/RotatingShip.gif&#34;    alt=&#34;The spaceship going round the screen.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The spaceship going round the screen.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;It&amp;rsquo;s not super fast and there are some artefacts when the screen is redrawn, but we&amp;rsquo;ll see how this goes as we progress with the game development&lt;/p&gt;&lt;p&gt;I haven&amp;rsquo;t pushed any code yet at this stage but here is most of what I&amp;rsquo;ve got so far.Note that nRF Connect SDK v2.7 is using LVGL version 8.4. Most APIs have been renamed in the newer LVGL 9 versions.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; lvgl = LVGL(device: display_dev)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; screen = LVGLScreen()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    screen.setActive()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; spaceShip = LVGLImage(parent: screen, imageDescription: SpaceShip.description)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    spaceShip.setPosition(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    spaceShip.setPivot(&lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt;, &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;85&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lvgl.taskHandler()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lvgl.displayBlankingOff()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; value: Int16 = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;16&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      value &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; value &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;360&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        value = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      spaceShip.setAngle(value &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      lvgl.taskHandler()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// &lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;MARK:&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; LVGL&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LVGLScreen&lt;/span&gt;: LVGLObject, Equatable {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; screens = [LVGLScreen]()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(pointer: UnsafeMutablePointer&amp;lt;lv_obj_t&amp;gt;? = lv_obj_create(&lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.pointer = pointer&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;Self&lt;/span&gt;.screens.append(&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; pointer: UnsafeMutablePointer&amp;lt;lv_obj_t&amp;gt;?&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getActive&lt;/span&gt;() -&amp;gt; LVGLScreen? {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; activeScreen = lv_scr_act()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;Self&lt;/span&gt;.screens.first { $0.pointer == activeScreen }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; == (lhs: LVGLScreen, rhs: LVGLScreen) -&amp;gt; Bool {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lhs.pointer == rhs.pointer&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; isActive: Bool {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;Self&lt;/span&gt;.getActive() == &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setActive&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; pointer {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      lv_disp_load_scr(pointer)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;deinit&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;Self&lt;/span&gt;.screens.removeAll { $0 == &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LVGL&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; device: UnsafePointer&amp;lt;device&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(device: UnsafePointer&amp;lt;device&amp;gt;) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;device_is_ready(device) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      fatalError(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Device not ready, aborting test&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.device = device&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;taskHandler&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lv_task_handler()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;displayBlankingOff&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    display_blanking_off(device)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;protocol&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LVGLObject&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; pointer: UnsafeMutablePointer&amp;lt;lv_obj_t&amp;gt;? { &lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;extension&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LVGLObject&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setPosition&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; x: Int16, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; y: Int16) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lv_obj_set_pos(&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.pointer, x, y)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LVGLAlignment&lt;/span&gt;: UInt8 {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; `&lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt;` = &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; topLeft&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; topMid&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; topRight&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; bottomLeft&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; bottomMid&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; bottomRight&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; leftMid&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; rightMid&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; center&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outTopLeft&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outTopMid&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outTopRight&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outBottomLeft&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outBottomMid&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outBottomRight&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outLeftTop&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outLeftMid&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outLeftBottom&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outRightTop&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outRightMid&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; outRightBottom&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LVGLImage&lt;/span&gt;: LVGLObject {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; imgDesc: UnsafeMutablePointer&amp;lt;lv_img_dsc_t&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; pointer: UnsafeMutablePointer&amp;lt;lv_obj_t&amp;gt;?&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    parent: LVGLScreen? = &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    imageDescription: lv_img_dsc_t,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    alignment: LVGLAlignment = .center&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; imgObj = lv_img_create(parent?.pointer) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      fatalError(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Failed to create image&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.pointer = imgObj&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    imgDesc = UnsafeMutablePointer&amp;lt;lv_img_dsc_t&amp;gt;.allocate(capacity: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    imgDesc.initialize(to: imageDescription)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lv_img_set_src(imgObj, imgDesc)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lv_obj_align(imgObj, alignment.rawValue, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setPivot&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; x: Int16, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; y: Int16) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      lv_img_set_pivot(&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.pointer, x, y)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setAngle&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; angle: Int16) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lv_img_set_angle(&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.pointer, angle)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;reviving-an-old-project&#34;&gt;Reviving an old project&lt;/h1&gt;&lt;p&gt;Nearly a year ago, I posted about &lt;a href=&#34;https://www.ericbariaux.com/posts/portable-ai/&#34;&gt;Portable AI&lt;/a&gt; devices and started exploring open source propositions in the field. I found an interesting project that back then was called Friend (it&amp;rsquo;s now called Omi) and started playing around with it.Although I generally liked what they were doing, and even made some small contributions, a few things were bothering me:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;all data was sent to a server in the cloud (they later released the source code for the server side too)&lt;/li&gt;&lt;li&gt;I was not very familiar with the development stack used&lt;/li&gt;&lt;li&gt;the way development efforts on the project were organized was a bit too chaotic for me&lt;/li&gt;&lt;li&gt;I was more interested in learning than using an existing product and wanted to freedom to explore in whichever direction I felt interesting or intriguing&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So I did assemble a device as per their instructions and wrote an iOS app that would record and store the audio on the phone. My first use case was to record work meetings and I&amp;rsquo;ll figure out later how I can make use of the data I collected.&lt;/p&gt;&lt;p&gt;Back then I did not have a 3D printer and quickly created a case with what I had lying around.&lt;/p&gt;&lt;figure class=&#34;small&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250303/OriginalEnclosure.png&#34;    alt=&#34;The original enclosure used for the device.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The original enclosure used for the device, a recycled clear plastic box with holes in it.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;BTW around the same time, &lt;a href=&#34;https://mastodon.social/@stuffmc&#34;&gt;StuffMc&lt;/a&gt; pointed me to the Embedded Swift vision document and that&amp;rsquo;s how I got interested in this technology, ended presenting about it at several conferences and writing a lot about it on this blog.&lt;/p&gt;&lt;p&gt;Although I wanted to explore processing the data on the phone (transcribing and then being able to query using an LLM), I thought exploring that on a server first would be easier and offer more possibilities.&lt;br&gt;I thus started writing server code that could receive the audio data from the phone. As I already had iOS code in Swift, and this was an exploration project, I decided to write the server code in Swift also (and at some point rewrite the existing firmware in Swift).&lt;/p&gt;&lt;p&gt;Then several things happened at the same time: I took a sabbatical and did not have any meeting to record anymore, I had acquired a 3D printer and taken the device apart so I could model a new case, I hit a bug in Vapor that halted my backend development and I spent most of my time exploring Embedded Swift. The project came to an halt and the device (rather its components) slept in a drawer.&lt;/p&gt;&lt;p&gt;In the meantime, the bug in Vapor has been fixed, my sabbatical is over, I again attend more work meetings and I got a bit of experience modelling and printing 3D objects. As I always wanted to continue the project, now seemed like a good time to do so.&lt;/p&gt;&lt;p&gt;To start recording again, I wanted to put the device back together. So last week, I finished the 3D model and printed it.&lt;/p&gt;&lt;p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250303/NewEnclosure.png&#34;    alt=&#34;The new enclosure, looks a bit like a pack of gum.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The new enclosure, looks a bit like a pack of gum.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/eu-20250303/NewEnclosureOpen.png&#34;    alt=&#34;Device inside the new enclosure, pretty tightly packed.&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Device inside the new enclosure, pretty tightly packed.&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;&lt;p&gt;I can now look back at the code and continue &lt;a href=&#34;https://www.ericbariaux.com/posts/the-pal-project/&#34;&gt;The PAL Project&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I also want to address the on-line meetings aspect. For now, I&amp;rsquo;m using &lt;a href=&#34;https://rogueamoeba.com/audiohijack/&#34;&gt;Audio Hijack&lt;/a&gt; from &lt;a href=&#34;https://rogueamoeba.com/&#34;&gt;Rogue Amoeba&lt;/a&gt; to gather the audio. We might talk about open source alternatives to &lt;a href=&#34;https://www.rewind.ai/&#34;&gt;Rewind.ai&lt;/a&gt; some other time.&lt;/p&gt;&lt;p&gt;Oh yes, I know there are lots of questions about these types of devices, their usefulness and certainly their commercial viability (good bye &lt;a href=&#34;https://humane.com/media/humane-hp&#34;&gt;Humane&lt;/a&gt;) but I still want to explore the field and maybe others want to follow along.&lt;/p&gt;&lt;h1 id=&#34;posting&#34;&gt;Posting&lt;/h1&gt;&lt;p&gt;That’s it for this week! There&amp;rsquo;s a bit more I wanted to talk about but it&amp;rsquo;ll have to wait for next week, as otherwise I will just postpone posting this, exactly the opposite of what I&amp;rsquo;m going for with this series.&lt;/p&gt;&lt;p&gt;Until next time, and I’d love to hear any thoughts or suggestions. You can reach me on &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt;, my preferred communication channel.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Addressing previous oversights</title>
       <link>https://https://ericbariaux.statichost.page//posts/previous_oversights_nrf52/</link>
       <pubDate>Sat, 08 Feb 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/previous_oversights_nrf52/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;Back in November 2024, as I closed my &lt;a href=&#34;https://youtu.be/8YAtCWtDQgw&#34;&gt;Blink them to death using Embedded Swift&lt;/a&gt; presentation at Pragma Conf, I promised to release the source code of the 3 projects I presented before the end of the year. I thought this would be an easy goal to achieve and that I&amp;rsquo;d finish way sooner.&lt;/p&gt;&lt;p&gt;Of course the projects had been prototypes so far, so I wanted to cleanup the code and recheck everything was working as expected. This ended up taking much longer than expected (plus, daily life got in the way—but that’s another story).&lt;/p&gt;&lt;p&gt;In the end, I pushed code for the third project on the last day of 2024 (and I cheated a bit as I removed some features compared to what I had in the prototypes). So all 3 projects are available:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Examples/tree/main/TrafficLight&#34;&gt;TrafficLight&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Swatak&#34;&gt;Swatak&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-ArcReactor&#34;&gt;ArcReactor&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;And while doing the cleaning, I discovered that I had some loose ends in how I did things so far, and that included some of the code in my previously published posts.In this post, I&amp;rsquo;ll review those oversights and provide an improved version of what I initially presented.&lt;/p&gt;&lt;h1 id=&#34;memory-safety-is-nice&#34;&gt;Memory safety is nice&lt;/h1&gt;&lt;p&gt;Swift is a language that provides memory safety and this is really nice, it catches a whole category of bugs at compile time.But with Embedded Swift, you sometimes need to perform some manual memory management and work without that safety net.&lt;/p&gt;&lt;p&gt;I was bitten by this issue as I experienced a very strange bug when working on &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Swatak&#34;&gt;Swatak&lt;/a&gt;, where the LEDs seemed to lit up in a completely random fashion. The root cause turned out to be a memory corruption.&lt;/p&gt;&lt;p&gt;Let me walk you through a simplified reproduction of the problem.&lt;/p&gt;&lt;p&gt;Based on the &lt;code&gt;Button&lt;/code&gt; code that I published in &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/button_embedded_swift_nrf52_part2/&#34;&gt;Creating a Swift type for button input on nRF52 - Part 2&lt;/a&gt;, here is a bit of code that uses a &lt;code&gt;Context&lt;/code&gt; object to store some message and print it out on button press.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; context: Context = Context(message: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; _ = Button&amp;lt;Context&amp;gt;(gpio: &amp;amp;button, context: context) { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, callback, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; context = Button&amp;lt;Context&amp;gt;.getContext(callback)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Btn pressed &amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\(&lt;/span&gt;context.message&lt;span style=&#34;color:#e6db74&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;lt;&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Context&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; message: String&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(message: String) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.message = message&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And here is the output of running this on an nRF52840DK board&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Using Zephyr OS v3.6.99-100befc70c74 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Btn pressed &amp;gt;Hello&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Btn pressed &amp;gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On the first button press, the message is properly printed out, but on the second one, nothing is printed out.&lt;/p&gt;&lt;p&gt;Something strange is going on with &lt;code&gt;Context&lt;/code&gt; here. Let&amp;rsquo;s implement a deinitializer and print a message when it gets deallocated.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;deinit&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Context deinit&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Flashing this version to the board, we see that the message is printed out immediately. Even before the button is pressed.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Using Zephyr OS v3.6.99-100befc70c74 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Context deinit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s look at the &lt;code&gt;Button&lt;/code&gt; code. Below is an extract, keeping only the code related to the context storage.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Button&lt;/span&gt;&amp;lt;T: AnyObject&amp;gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; context: T&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;, context: T, handle: GpioCallbackHandler?) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.context = context&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.pin_cb_data.pointee.context = Unmanaged.passUnretained(context).toOpaque()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As we have a property in &lt;code&gt;Button&lt;/code&gt; that references the context, the latter will be kept alive as long is the button exists.&lt;br&gt;In addition, we store a pointer to the context in the &lt;code&gt;pin_cb_data&lt;/code&gt;structure, and there we use &lt;code&gt;passUnretained&lt;/code&gt; as to not keep an extra reference to the context.&lt;br&gt;Could it then be that the &lt;code&gt;Button&lt;/code&gt; instance itself is getting deallocated?&lt;br&gt;Let&amp;rsquo;s add a deinitialized with a print statement to &lt;code&gt;Button&lt;/code&gt; (changing it to a class for this test).&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;deinit&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Button deinit&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Our output is now&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Using Zephyr OS v3.6.99-100befc70c74 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Button deinit&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Context deinit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And indeed, we can see that the &lt;code&gt;Button&lt;/code&gt; instance is deallocated immediately, which in turns triggers the deallocation of the context.&lt;/p&gt;&lt;p&gt;Changing our main code to keep a reference to the button when it is created fixes the issue.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; btn1 = Button&amp;lt;Context&amp;gt;(gpio: &amp;amp;button, context: context) { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, callback, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; context = Button&amp;lt;Context&amp;gt;.getContext(callback)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Btn pressed &amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\(&lt;/span&gt;context.message&lt;span style=&#34;color:#e6db74&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;lt;&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Using Zephyr OS v3.6.99-100befc70c74 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Btn pressed &amp;gt;Hello&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Btn pressed &amp;gt;Hello&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But this now generates a warning during compilation because the value is not used.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.../ButtonDeinitBug/Main.swift:6:9: warning: initialization of immutable value &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;btn1&amp;#39;&lt;/span&gt; was never used; consider replacing with assignment to &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;_&amp;#39;&lt;/span&gt; or removing it&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;4&lt;/span&gt; |     let context: Context &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Context&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;message: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; |     &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;6&lt;/span&gt; |     let btn1 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Button&amp;lt;Context&amp;gt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gpio: &amp;amp;button, context: context&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; _, callback, _ in&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   |         &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;- warning: initialization of immutable value &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;btn1&amp;#39;&lt;/span&gt; was never used; consider replacing with assignment to &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;_&amp;#39;&lt;/span&gt; or removing it&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;7&lt;/span&gt; |       let context &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Button&amp;lt;Context&amp;gt;.getContext&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;callback&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt; |       print&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Btn pressed &amp;gt;\(context.message)&amp;lt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;AFAIK there is still no way to silence this single warning in Swift.However, it is possible to rewrite the code in such a way that we retain the button and avoid the warning.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; = Unmanaged.passRetained(Button&amp;lt;Context&amp;gt;(gpio: &amp;amp;button, context: context) { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, callback, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; context = Button&amp;lt;Context&amp;gt;.getContext(callback)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Btn pressed &amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\(&lt;/span&gt;context.message&lt;span style=&#34;color:#e6db74&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;lt;&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    })&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But this makes the code slightly less readable.&lt;br&gt;I leave it up to you to decide which is the lesser of the two evils.&lt;/p&gt;&lt;h1 id=&#34;making-it-safe-by-default&#34;&gt;Making it safe by default&lt;/h1&gt;&lt;p&gt;We now understand why we saw an undefined behaviour and how to prevent it. But the &lt;code&gt;Button&lt;/code&gt; code is still unsafe and we could easily fall into the same trap again later.We should instead make it so that users of this code would be &lt;a href=&#34;https://blog.codinghorror.com/falling-into-the-pit-of-success/&#34;&gt;Falling Into The Pit of Success&lt;/a&gt;, a concept I heard about in Alex Ozun&amp;rsquo;s talk at Swift Craft 2024 on &lt;a href=&#34;https://www.youtube.com/watch?v=cCZ00b_RNyc&#34;&gt;Type-Driven Design with Swift&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;One safe thing to do is to ensure that, if we would not retain the button, and it gets deallocated, we don&amp;rsquo;t access the context data i.e. making sure its callback closure is not called anymore.And just as nRF Connect SDK provides a &lt;code&gt;gpio_add_callback&lt;/code&gt; function, there&amp;rsquo;s the corresponding &lt;code&gt;gpio_remove_callback&lt;/code&gt;one that we can use here.&lt;/p&gt;&lt;p&gt;By the way, also notice that in our &lt;code&gt;Button&lt;/code&gt; initializer, we allocated a &lt;code&gt;pin_cb_data&lt;/code&gt; structure&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.pin_cb_data = UnsafeMutablePointer&amp;lt;extended_callback&amp;gt;.allocate(capacity: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which we never deallocated.&lt;/p&gt;&lt;p&gt;Taking care of both of the above issues, we now add a deinitializer to our &lt;code&gt;Button&lt;/code&gt; class.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;deinit&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Button deinit&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_remove_callback(gpio.pointee.port, &amp;amp;pin_cb_data.pointee.callback)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    pin_cb_data.deallocate()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Having reverted our main code to not retain the button and flashing the board, we observe the following output&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Using Zephyr OS v3.6.99-100befc70c74 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Button deinit&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Context deinit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So the &lt;code&gt;Button&lt;/code&gt; and the &lt;code&gt;Context&lt;/code&gt; instances are deallocated at startup. But now, we can press the button as much as we want and nothing will happen. I might not do what we want, but the code is safe from accessing random data or crashing the board.&lt;/p&gt;&lt;h1 id=&#34;class-or-struct&#34;&gt;Class or struct&lt;/h1&gt;&lt;p&gt;Our &lt;code&gt;Button&lt;/code&gt;started as a struct and we now made it a class, only  because we needed a &lt;code&gt;deinit&lt;/code&gt;method. An alternative would have been to make the struct non copyable, this also supports &lt;code&gt;deinit&lt;/code&gt;. Which one makes the most sense ?&lt;/p&gt;&lt;p&gt;If you consider the &lt;code&gt;Button&lt;/code&gt; type as a representation of the physical button, I would argue that there should only be one user of this button at a time. This aligns nicely with the ownership semantics of non-copyable structs.&lt;/p&gt;&lt;p&gt;But if you consider the &lt;code&gt;Button&lt;/code&gt; type as representing the handler associated with the button press event, it does not really hurt to have multiple references to it and a class would work fine.&lt;/p&gt;&lt;p&gt;At this point, I&amp;rsquo;m only raising the point so you can consider this aspect in your own design. I&amp;rsquo;ll address this topic in more details in a future post.&lt;/p&gt;&lt;h1 id=&#34;better-understanding-the-underlying-sdk&#34;&gt;Better understanding the underlying SDK&lt;/h1&gt;&lt;p&gt;In a previous post, &lt;a href=&#34;http://localhost:1313/posts/led_embedded_swift_nrf52/&#34;&gt;Controlling an LED using Embedded Swift on nRF52&lt;/a&gt;, I created a Led struct with simple on, off and toggle methods, controlling one of the on-board LED on the nRF52840 dk board. As it is one of the default LED for the board, its low-level definition is part of the SDK (in a device tree configuration file).&lt;/p&gt;&lt;p&gt;For the &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Swatak&#34;&gt;Swatak&lt;/a&gt; project mentioned above, I slightly changed the code, so that I could have a &lt;code&gt;state&lt;/code&gt; property to proxy for the LED status.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; state: Bool {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;didSet&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      gpio_pin_set_dt(gpio, state ? &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; : &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I mostly kept the same initializer code as in the original example, except I added the initialization of the state variable.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;, state: Bool = &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.gpio = gpio&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.state = state&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  gpio_pin_configure_dt(gpio, GPIO_OUTPUT &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_OUTPUT_INIT_HIGH &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_OUTPUT_INIT_LOGICAL)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And with the blinking LED example, I did not notice anything wrong.&lt;/p&gt;&lt;h2 id=&#34;invalid-initial-state-of-the-physical-led&#34;&gt;Invalid initial state of the physical LED&lt;/h2&gt;&lt;p&gt;However, when I started using the code in &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Swatak&#34;&gt;Swatak&lt;/a&gt;, the LEDs were all on, even though the default &lt;code&gt;state&lt;/code&gt; value is &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;In reusing old example code, I did not pay attention to the parameters of the &lt;code&gt;gpio_pin_configure_dt()&lt;/code&gt; function. But of course, they matter.&lt;br&gt;Looking at the definition of the &lt;code&gt;GPIO_OUTPUT_INIT_HIGH&lt;/code&gt; constant and its companion &lt;code&gt;GPIO_OUTPUT_INIT_LOW&lt;/code&gt; provides some useful information.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/* Initializes output to a low state. */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define GPIO_OUTPUT_INIT_LOW    (1U &amp;lt;&amp;lt; 18)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/* Initializes output to a high state. */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define GPIO_OUTPUT_INIT_HIGH   (1U &amp;lt;&amp;lt; 19)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, by always passing &lt;code&gt;GPIO_OUTPUT_INIT_HIGH&lt;/code&gt; to the &lt;code&gt;gpio_pin_configure_dt()&lt;/code&gt; call, the LED always started on, irrelevant of the initial state.&lt;br&gt;The problem can be fixed by adapting the initializer and passing the proper constant based on the initial state.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;, state: Bool = &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.gpio = gpio&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.state = state&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  gpio_pin_configure_dt(gpio, GPIO_OUTPUT&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; (state ? GPIO_OUTPUT_INIT_HIGH : GPIO_OUTPUT_INIT_LOW)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_OUTPUT_INIT_LOGICAL)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;when-the-physical-and-virtual-world-dont-agree&#34;&gt;When the physical and virtual world don&amp;rsquo;t agree&lt;/h2&gt;&lt;p&gt;For both the &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Examples/tree/main/TrafficLight&#34;&gt;TrafficLight&lt;/a&gt; and &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Swatak&#34;&gt;Swatak&lt;/a&gt; projects, I needed to use external GPIO PINs on which I had attached my own LEDs. This meant using a custom device tree configuration (dts) file.&lt;/p&gt;&lt;p&gt;So I opened the original dts file for the board (&lt;a href=&#34;https://github.com/zephyrproject-rtos/zephyr/blob/main/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts&#34;&gt;boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts&lt;/a&gt; in the Zephyr SDK source) and looked up how it defined its LED.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;led0&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;led_0 {&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;gpios = &amp;lt;&amp;amp;gpio0 13 GPIO_ACTIVE_LOW&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;label = &amp;#34;Green LED 0&amp;#34;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#ae81ff&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I copied that snippet to my own project and adapted it for the GPIO pin my LED is connected to.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;greenled&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;green_led {&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;gpios = &amp;lt;&amp;amp;gpio1 10 GPIO_ACTIVE_LOW&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;label = &amp;#34;LED P1.10&amp;#34;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#ae81ff&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the LED behavior I was seeing did not make any sense. After a moment, I understood that the LED visual state was the opposite of the actual &lt;code&gt;state&lt;/code&gt;variable value. Why is that ?&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s again turn to the constants definitions.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/** GPIO pin is active (has logical value &amp;#39;1&amp;#39;) in low state. */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define GPIO_ACTIVE_LOW         (1 &amp;lt;&amp;lt; 0)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/** GPIO pin is active (has logical value &amp;#39;1&amp;#39;) in high state. */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define GPIO_ACTIVE_HIGH        (0 &amp;lt;&amp;lt; 0)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above definition, using the &lt;code&gt;GPIO_ACTIVE_LOW&lt;/code&gt; constant, means that there&amp;rsquo;s voltage on the PIN when the value is 0 and there&amp;rsquo;s no voltage when the value is 1.&lt;/p&gt;&lt;p&gt;Looking at the &lt;a href=&#34;https://docs.nordicsemi.com/bundle/ug_nrf52840_dk/page/UG/dk/intro.html&#34;&gt;nRF52840 DK Hardware&lt;/a&gt; user guide (always a good idea) and more specifically the &lt;a href=&#34;https://docs.nordicsemi.com/bundle/ug_nrf52840_dk/page/UG/dk/hw_buttons_leds.html&#34;&gt;Buttons and LEDs&lt;/a&gt; section, one can read&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;The LEDs are active low, meaning that writing a logical zero (0) to the output pin turns on the LED.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;So the above configuration is appropriate for the how the on-board LEDs are wired on the development board. But not for how my external LEDs are wired.Once I understood that, I could adapt the configuration.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;greenled&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;green_led {&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;gpios = &amp;lt;&amp;amp;gpio1 10 GPIO_ACTIVE_HIGH&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;label = &amp;#34;LED P1.10&amp;#34;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#ae81ff&#34;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The LEDs now behaved as expected.&lt;/p&gt;&lt;style type=&#34;text/css&#34;&gt;         .notice {        --title-color: #fff;        --title-background-color: #6be;        --content-color: #444;        --content-background-color: #e7f2fa;    }    .notice.info {        --title-background-color: #fb7;        --content-background-color: #fec;    }    .notice.tip {        --title-background-color: #5a5;        --content-background-color: #efe;    }    .notice.warning {        --title-background-color: #c33;        --content-background-color: #fee;    }         @media (prefers-color-scheme:dark) {        .notice {            --title-color: #fff;            --title-background-color: #069;            --content-color: #ddd;            --content-background-color: #023;        }        .notice.info {            --title-background-color: #a50;            --content-background-color: #420;        }        .notice.tip {            --title-background-color: #363;            --content-background-color: #121;        }        .notice.warning {            --title-background-color: #800;            --content-background-color: #400;        }    }    body.dark .notice {        --title-color: #fff;        --title-background-color: #069;        --content-color: #ddd;        --content-background-color: #023;    }    body.dark .notice.info {        --title-background-color: #a50;        --content-background-color: #420;    }    body.dark .notice.tip {        --title-background-color: #363;        --content-background-color: #121;    }    body.dark .notice.warning {        --title-background-color: #800;        --content-background-color: #400;    }         .notice {        padding: 18px;        line-height: 24px;        margin-bottom: 24px;        border-radius: 4px;        color: var(--content-color);        background: var(--content-background-color);    }    .notice p:last-child {        margin-bottom: 0    }         .notice-title {        margin: -18px -18px 12px;        padding: 4px 18px;        border-radius: 4px 4px 0 0;        font-weight: 700;        color: var(--title-color);        background: var(--title-background-color);    }         .icon-notice {        display: inline-flex;        align-self: center;        margin-right: 8px;    }    .icon-notice img,    .icon-notice svg {        height: 1em;        width: 1em;        fill: currentColor;    }    .icon-notice img,    .icon-notice.baseline svg {        top: .125em;        position: relative;    }&lt;/style&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;Device tree configuration is a complex topic that goes far beyond the scope of this post.&lt;br&gt;I find the &lt;a href=&#34;https://interrupt.memfault.com/tags#practical-zephyr-series&#34;&gt;Practical Zephyr &lt;/a&gt; posts series on the &lt;a href=&#34;https://interrupt.memfault.com/blog/&#34;&gt;Memfault Interrupt blog&lt;/a&gt; a very detailed, yet approchable and very well written source of information on the topic.&lt;/p&gt;&lt;/div&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;Although the goal of Embedded Swift is to allow us to use a familiar language and easily transpose the work we&amp;rsquo;ve been going on iOS, macOS or other platforms to the embedded world, it is not yet that straightforward.&lt;/p&gt;&lt;p&gt;At this stage, we still need to understand that the underlying system has its own rules, that we should be aware of and understand.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;m hopeful that as the platform matures, the community will develop higher-level abstractions, allowing developers to distance themselves from some of the lower-level details. I&amp;rsquo;d like to believe that some of the articles I write and the code I publish help contribute to that evolution.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Rolling back a brew formula</title>
       <link>https://https://ericbariaux.statichost.page//posts/brew_rollback/</link>
       <pubDate>Tue, 21 Jan 2025 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/brew_rollback/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;I find Homebrew super convenient to install and keep up to date the large collection of tools I rely on. But sometimes, things do not work out the way you plan.&lt;/p&gt;&lt;style type=&#34;text/css&#34;&gt;         .notice {        --title-color: #fff;        --title-background-color: #6be;        --content-color: #444;        --content-background-color: #e7f2fa;    }    .notice.info {        --title-background-color: #fb7;        --content-background-color: #fec;    }    .notice.tip {        --title-background-color: #5a5;        --content-background-color: #efe;    }    .notice.warning {        --title-background-color: #c33;        --content-background-color: #fee;    }         @media (prefers-color-scheme:dark) {        .notice {            --title-color: #fff;            --title-background-color: #069;            --content-color: #ddd;            --content-background-color: #023;        }        .notice.info {            --title-background-color: #a50;            --content-background-color: #420;        }        .notice.tip {            --title-background-color: #363;            --content-background-color: #121;        }        .notice.warning {            --title-background-color: #800;            --content-background-color: #400;        }    }    body.dark .notice {        --title-color: #fff;        --title-background-color: #069;        --content-color: #ddd;        --content-background-color: #023;    }    body.dark .notice.info {        --title-background-color: #a50;        --content-background-color: #420;    }    body.dark .notice.tip {        --title-background-color: #363;        --content-background-color: #121;    }    body.dark .notice.warning {        --title-background-color: #800;        --content-background-color: #400;    }         .notice {        padding: 18px;        line-height: 24px;        margin-bottom: 24px;        border-radius: 4px;        color: var(--content-color);        background: var(--content-background-color);    }    .notice p:last-child {        margin-bottom: 0    }         .notice-title {        margin: -18px -18px 12px;        padding: 4px 18px;        border-radius: 4px 4px 0 0;        font-weight: 700;        color: var(--title-color);        background: var(--title-background-color);    }         .icon-notice {        display: inline-flex;        align-self: center;        margin-right: 8px;    }    .icon-notice img,    .icon-notice svg {        height: 1em;        width: 1em;        fill: currentColor;    }    .icon-notice img,    .icon-notice.baseline svg {        top: .125em;        position: relative;    }&lt;/style&gt;&lt;div class=&#34;notice warning&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;126 76.5 300 300&#34;&gt;  &lt;path d=&#34;M297.431 324.397v-34.255c0-3.245-2.344-5.95-5.358-5.95h-32.146c-3.014 0-5.358 2.705-5.358 5.95v34.255c0 3.245 2.344 5.95 5.358 5.95h32.146c3.014 0 5.358-2.705 5.358-5.95Zm-.335-67.428 3.014-82.753c0-1.081-.502-2.524-1.674-3.425-1.005-.902-2.512-1.983-4.019-1.983h-36.834c-1.507 0-3.014 1.081-4.019 1.983-1.172.901-1.674 2.704-1.674 3.786l2.846 82.392c0 2.344 2.512 4.146 5.693 4.146h30.975c3.013 0 5.525-1.803 5.692-4.146Zm-2.344-168.39L423.34 342.425c3.683 7.032 3.516 15.686-.335 22.717-3.85 7.031-10.883 11.358-18.417 11.358H147.413c-7.534 0-14.566-4.327-18.417-11.358-3.85-7.031-4.018-15.685-.335-22.716L257.248 88.578C260.93 81.188 268.13 76.5 276 76.5c7.87 0 15.069 4.688 18.752 12.08Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Warning&lt;/p&gt;&lt;p&gt;At the time of this writing, a malware site masquerading as the Homebrew site is being spread through Google Ads, see &lt;a href=&#34;https://x.com/ryanchenkie/status/1880730173634699393&#34;&gt;this post on X by Ryan Chenkie&lt;/a&gt; for more details.&lt;/p&gt;&lt;/div&gt;&lt;p&gt;Some weeks ago, I was cleaning up the code for an Embedded Swift project before publishing it on &lt;a href=&#34;&#34;&gt;GitHub&lt;/a&gt;, and as a last check, I wanted to verify everything still worked fine with the latest versions of the various components: latest Swift snapshot toolchain, nRF Connect SDK 2.9.0 and latest cmake version.&lt;br&gt;Since I had installed cmake using brew, I did a &lt;code&gt;brew upgrade&lt;/code&gt; and this updated cmake from 3.31.1 to 3.31.2.&lt;/p&gt;&lt;p&gt;Suddenly, things began to fall apart. I could not complete a successful build after those updates.&lt;br&gt;I first rolled back nRF Connect SDK as this was probably where the biggest changes did occur.  This did not help.&lt;br&gt;Next I tried with a previous Swift toolchain, which did not help either.&lt;br&gt;This pointed to cmake as the most probable culprit, so I wanted to roll it back.&lt;br&gt;And that proved to be more difficult than I thought.&lt;/p&gt;&lt;h1 id=&#34;tldr&#34;&gt;TL;DR&lt;/h1&gt;&lt;p&gt;In the rest of this post, I will outline my research process, the challenges I encountered, and the steps I followed to resolve them.&lt;/p&gt;&lt;p&gt;If you are not interested in the whole story, the following commands should work to install a specific version of a helm formula&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew tap-new $USER/local-cmake&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew tap homebrew/core --force&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew extract --version&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;3.31.1 cmake $USER/local-cmake&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install $USER/local-cmake/cmake@3.31.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;trying-to-find-an-easy-way&#34;&gt;Trying to find an easy way&lt;/h1&gt;&lt;p&gt;I opened a terminal and typed &lt;code&gt;brew --help&lt;/code&gt;, hoping to find a revert/rollback command but I did not find any such option, only a full uninstall command.&lt;/p&gt;&lt;p&gt;So I turned to Google; and found several posts indicating how to install a specific version of a package, but most of those posts were outdated and referenced commands and ways to proceed that do not work anymore.For instance:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code&gt;brew versions&lt;/code&gt; does not work, as the &lt;code&gt;versions&lt;/code&gt; command is not available anymore.&lt;/li&gt;&lt;li&gt;same for &lt;code&gt;brew switch&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code&gt;brew list --versions &amp;lt;package name&amp;gt;&lt;/code&gt; does work but always returns the latest, currently installed version for me&lt;/li&gt;&lt;li&gt;using the &lt;code&gt;&amp;lt;package name&amp;gt;@&amp;lt;version&amp;gt;&lt;/code&gt; as done when using npm does not work (it happens that some package names use this format e.g. postgresql@14, but this is their naming convention, not a generic mechanism used by brew)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;And indeed, &lt;code&gt;brew --help install&lt;/code&gt; does not indicate any way to install a specific version.&lt;/p&gt;&lt;h1 id=&#34;going-the-complex-route&#34;&gt;Going the complex route&lt;/h1&gt;&lt;p&gt;I found several posts indicating the possibility to install a specific version (using the install command) by forging a specific URL, referencing the formula using a git commit hash, so it would point to the desired version.&lt;br&gt;Something like &lt;code&gt;brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/4cfc96448e261e9b16d9b51dc6d563c717003bfd/Formula/c/cmake.rb&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;However, this method is no longer supported and returns the error message&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Error: Non-checksummed download of cmake formula file from an arbitrary URL is unsupported! &lt;code&gt;brew extract&lt;/code&gt; or &lt;code&gt;brew create&lt;/code&gt; and &lt;code&gt;brew tap-new&lt;/code&gt; to create a formula file in a tap on GitHub instead.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;So I searched online for the suggested commands and tried&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; brew tap-new $USER/local-cmake&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; brew extract --version&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;3.31.1 cmake $USER/local-cmake&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The first line worked OK and created a local tap, essentially a local git repository, located under /opt/homebrew/Library/Taps, to store formulas. See &lt;a href=&#34;https://docs.brew.sh/How-to-Create-and-Maintain-a-Tap&#34;&gt;How to Create and Maintain a Tap — Homebrew Documentation&lt;/a&gt; for some background on this command.&lt;br&gt;The second failed though, with the message&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Error: No available formula with the name &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;homebrew/core/cmake&amp;#34;&lt;/span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Please tap it and &lt;span style=&#34;color:#66d9ef&#34;&gt;then&lt;/span&gt; try again: brew tap homebrew/core&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Executing the command that was suggested gave another error&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew tap homebrew/core&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Error: Tapping homebrew/core is no longer typically necessary.&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Add --force &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; you are sure you need it &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; contributing to Homebrew.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That error message leaves a door open. Although it does not make it super clear when you would really need to do it, the use of &amp;ldquo;typically&amp;rdquo; suggests this is still sometimes required.&lt;/p&gt;&lt;p&gt;I considered this was the case here&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew tap homebrew/core --force&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt;&amp;gt; Tapping homebrew/core&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Cloning into &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/opt/homebrew/Library/Taps/homebrew/homebrew-core&amp;#39;&lt;/span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;did indeed work, cloning the (pretty large) homebrew core repo locally.&lt;/p&gt;&lt;p&gt;I could now get back to the extract from above&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew extract --version&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;3.31.1 cmake $USER/local-cmake&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt;&amp;gt; Searching repository history&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt;&amp;gt; Writing formula &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; cmake at 3.31.1 from revision 4cfc964 to:&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/opt/homebrew/Library/Taps/ebariaux/homebrew-local-cmake/Formula/cmake@3.31.1.rb&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which indeed, extracted a specific version of the cmake formula in the local git repo that I initially created.&lt;/p&gt;&lt;p&gt;And with that, I was finally able to install the desired version of the formula&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install $USER/local-cmake/cmake@3.31.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;In this post, I explained how to install a specific version of a brew formula. This comes in handy when performing a general &lt;code&gt;brew upgrade&lt;/code&gt; and discovering that certain commands no longer function as expected.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Timers in Swift on nRF52</title>
       <link>https://https://ericbariaux.statichost.page//posts/timer_swift_nrf52/</link>
       <pubDate>Thu, 05 Dec 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/timer_swift_nrf52/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;In this post, we&amp;rsquo;ll continue exploring Embedded Swift on an nRF 52840 dk, using the nRF Connect SDK. Our goal this time is to execute code after a certain delay, with optional periodic repetition.&lt;br&gt;In Swift, one would typically use a &lt;code&gt;Timer&lt;/code&gt; class to implement such a feature. Can we use that with Embedded Swift?&lt;/p&gt;&lt;h1 id=&#34;foundation&#34;&gt;Foundation&lt;/h1&gt;&lt;p&gt;Embedded Swift is really about the Swift language, and the language only includes the Swift runtime and the standard library, both having some limitations in Embedded Swift.&lt;br&gt;&lt;code&gt;Timer&lt;/code&gt; is not part of those, it is included in Foundation. In the Apple ecosystem, we take Foundation for granted, but really it is a separate library, that&amp;rsquo;s not part of the language.&lt;/p&gt;&lt;p&gt;Foundation is a complex system, originating over 30 years ago, it evolved from NeXT’s early days. And it&amp;rsquo;s still going through quite a bit of change, on its way to being fully open sourced and unified across all platforms where Swift is available.&lt;/p&gt;&lt;p&gt;The code is available on GitHub, mainly in 2 repositories:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/swiftlang/swift-corelibs-foundation&#34;&gt;swift-corelibs-foundation&lt;/a&gt;: The Foundation Project, providing core utilities, internationalization, and OS independence. It is providing the implementation of these functionalities on non Darwin platforms.&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://github.com/swiftlang/swift-foundation&#34;&gt;swift-foundation&lt;/a&gt;: The Foundation project, a cross platform implementation of several fundamental types and functions.&lt;/li&gt;&lt;/ul&gt;&lt;style type=&#34;text/css&#34;&gt;         .notice {        --title-color: #fff;        --title-background-color: #6be;        --content-color: #444;        --content-background-color: #e7f2fa;    }    .notice.info {        --title-background-color: #fb7;        --content-background-color: #fec;    }    .notice.tip {        --title-background-color: #5a5;        --content-background-color: #efe;    }    .notice.warning {        --title-background-color: #c33;        --content-background-color: #fee;    }         @media (prefers-color-scheme:dark) {        .notice {            --title-color: #fff;            --title-background-color: #069;            --content-color: #ddd;            --content-background-color: #023;        }        .notice.info {            --title-background-color: #a50;            --content-background-color: #420;        }        .notice.tip {            --title-background-color: #363;            --content-background-color: #121;        }        .notice.warning {            --title-background-color: #800;            --content-background-color: #400;        }    }    body.dark .notice {        --title-color: #fff;        --title-background-color: #069;        --content-color: #ddd;        --content-background-color: #023;    }    body.dark .notice.info {        --title-background-color: #a50;        --content-background-color: #420;    }    body.dark .notice.tip {        --title-background-color: #363;        --content-background-color: #121;    }    body.dark .notice.warning {        --title-background-color: #800;        --content-background-color: #400;    }         .notice {        padding: 18px;        line-height: 24px;        margin-bottom: 24px;        border-radius: 4px;        color: var(--content-color);        background: var(--content-background-color);    }    .notice p:last-child {        margin-bottom: 0    }         .notice-title {        margin: -18px -18px 12px;        padding: 4px 18px;        border-radius: 4px 4px 0 0;        font-weight: 700;        color: var(--title-color);        background: var(--title-background-color);    }         .icon-notice {        display: inline-flex;        align-self: center;        margin-right: 8px;    }    .icon-notice img,    .icon-notice svg {        height: 1em;        width: 1em;        fill: currentColor;    }    .icon-notice img,    .icon-notice.baseline svg {        top: .125em;        position: relative;    }&lt;/style&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;If you&amp;rsquo;re interested in knowing more about this split and the structure of Foundation, check out the posts &lt;a href=&#34;https://www.swift.org/blog/future-of-foundation/&#34;&gt;The Future of Foundation&lt;/a&gt; and &lt;a href=&#34;https://www.swift.org/blog/foundation-preview-now-available/&#34;&gt;Foundation Package Preview Now Available&lt;/a&gt; on the &lt;a href=&#34;https://www.swift.org/blog/&#34;&gt;Swift.org Blog&lt;/a&gt; as well as the &lt;a href=&#34;https://www.youtube.com/watch?v=wn6C_XEv1Mo&amp;amp;t=1489s&#34;&gt;Swift &amp;amp; Interoperability&lt;/a&gt; video from this year&amp;rsquo;s &lt;a href=&#34;https://www.serversideswift.info/&#34;&gt;ServerSide.swift Conference&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s look at the code for &lt;a href=&#34;https://github.com/swiftlang/swift-corelibs-foundation/blob/main/Sources/Foundation/Timer.swift&#34;&gt;Timer.swift in swift-corelibs-foundation&lt;/a&gt;.&lt;br&gt;A quick glance already shows that it&amp;rsquo;s a class inheriting from &lt;code&gt;NSObject&lt;/code&gt; and that it integrates with the &lt;code&gt;CFRunLoop&lt;/code&gt; mechanism.&lt;/p&gt;&lt;p&gt;Taking that code as is and building it with Embedded Swift is clearly not gonna fly, but maybe we can keep the same API and implement it for our platform?&lt;/p&gt;&lt;h1 id=&#34;timers-in-nrf-connect-sdk&#34;&gt;Timers in nRF Connect SDK&lt;/h1&gt;&lt;p&gt;Before we do that, we need to understand how timers work in nRF Connect SDK and what API is available.&lt;br&gt;So let&amp;rsquo;s check the nRF Connect SDK documentation for the &lt;a href=&#34;https://docs.nordicsemi.com/bundle/ncs-1.9.2-dev1/page/zephyr/reference/kernel/timing/timers.html&#34;&gt;Timers&lt;/a&gt; services.&lt;/p&gt;&lt;p&gt;Here are a few key takeaways from reading the documentation:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Timers trigger after a certain delay (timeout) and optionally repeat with a given period&lt;/li&gt;&lt;li&gt;A timer is defined using a variable of type &lt;code&gt;k_timer&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Timers can be defined at compile-time using macros or at run-time&lt;/li&gt;&lt;li&gt;In the later case, the timer is initialized with the &lt;code&gt;k_timer_init&lt;/code&gt; function and started with &lt;code&gt;k_timer_start&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Timers can be stopped and restarted, potentially changing their delay and period&lt;/li&gt;&lt;li&gt;The expiry function code is executed in an interrupt context, its execution time should be kept to a minimum and it should not block; submit a work item to the system work queue if required&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Equipped with that knowledge, we can now create our own implementation of the Foundation Timer API.&lt;/p&gt;&lt;h1 id=&#34;re-implementing-the-timer-api&#34;&gt;Re-implementing the Timer API&lt;/h1&gt;&lt;p&gt;In addition to the &lt;a href=&#34;https://github.com/swiftlang/swift-corelibs-foundation/blob/main/Sources/Foundation/Timer.swift&#34;&gt;Timer source code&lt;/a&gt;, we can also use the &lt;a href=&#34;https://developer.apple.com/documentation/foundation/timer&#34;&gt;Timer Documentation&lt;/a&gt; as a guide to know how to implement the API.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s go over the functions and properties defined by the API:&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;func&lt;/span&gt; scheduledTimer(withTimeInterval: TimeInterval, repeats: Bool, block: (Timer) -&amp;gt; Void) -&amp;gt; Timer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Creates a timer and schedules it on the current run loop in the default mode.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;✅ Can implement: We can implement that, dynamically creating a timer with &lt;code&gt;k_timer_init&lt;/code&gt; and starting it with &lt;code&gt;k_timer_start&lt;/code&gt;.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;func&lt;/span&gt; scheduledTimer(timeInterval: TimeInterval, target: Any, selector: Selector, userInfo: Any?, repeats: Bool) -&amp;gt; Timer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Creates a timer and schedules it on the current run loop in the default mode.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;❌ Skip: Uses target and selector, an heritage from Objective-C, requiring dynamic runtime lookup of the implementation to call.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;func&lt;/span&gt; scheduledTimer(timeInterval: TimeInterval, invocation: NSInvocation, repeats: Bool) -&amp;gt; Timer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Creates a new timer and schedules it on the current run loop in the default mode.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;❌ Skip: Uses an &lt;code&gt;NSInvocation&lt;/code&gt;, similar issue to the previous function.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(timeInterval: TimeInterval, repeats: Bool, block: (Timer) -&amp;gt; Void)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Initializes a timer object with the specified time interval and block.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;❌ Skip: Only creates the timers but requires the timer to be added to a &lt;code&gt;CFRunLoop&lt;/code&gt;, which is an API we don&amp;rsquo;t have / want to implement at this stage.&lt;/p&gt;&lt;p&gt;For the same reasons, we&amp;rsquo;ll skip the other initializers.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(timeInterval: TimeInterval, target: Any, selector: Selector, userInfo: Any?, repeats: Bool)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(timeInterval: TimeInterval, invocation: NSInvocation, repeats: Bool)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(fire: Date, interval: TimeInterval, repeats: Bool, block: (Timer) -&amp;gt; Void)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(fireAt: Date, interval: TimeInterval, target: Any, selector: Selector, userInfo: Any?, repeats: Bool)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;fire&lt;/span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Causes the timer&amp;rsquo;s message to be sent to its target.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;✅ Can implement: We can store a closure and call it anytime.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;invalidate&lt;/span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Stops the timer from ever firing again and requests its removal from its run loop.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;✅ Can implement: The &lt;code&gt;k_timer_stop&lt;/code&gt; function will prevent the timer from firing again.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; isValid: Bool&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;A Boolean value that indicates whether the timer is currently valid.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;✅ Can implement: We can manage a state, setting it to invalid when &lt;code&gt;invalidate&lt;/code&gt; is called.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; fireDate: Date&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;The date at which the timer will fire.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;❌ Skip: &lt;code&gt;Date&lt;/code&gt; is also part of Foundation, so we don&amp;rsquo;t have it by default in Embedded Swift and would need to implement something ourself. That&amp;rsquo;s something we&amp;rsquo;ll look at in a later post but let&amp;rsquo;s skip for now.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; timeInterval: TimeInterval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;The timer’s time interval, in seconds.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;✅ Can implement: That&amp;rsquo;s an information we have.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; userInfo: Any?&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;The receiver&amp;rsquo;s &lt;code&gt;userInfo&lt;/code&gt; object.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;❌ Skip: Embedded Swift does not support existential types, so &lt;code&gt;Any&lt;/code&gt; is a no go.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; tolerance: TimeInterval&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;The amount of time after the scheduled fire date that the timer may fire.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;❌ Skip: Although a Zephyr timer could fire later than expected if the system can&amp;rsquo;t honour the exact requested timing, we have no information or control over the potential shift.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;publish&lt;/span&gt;(every: TimeInterval, tolerance: TimeInterval?, on: RunLoop, &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;: RunLoop.Mode, options: RunLoop.SchedulerOptions?) -&amp;gt; Timer.TimerPublisher&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Returns a publisher that repeatedly emits the current date on the given interval.&lt;/em&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Timer&lt;/span&gt;.TimerPublisher&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;A publisher that repeatedly emits the current date on a given interval.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;❌ Skip: Those 2 are about Combine, which we don&amp;rsquo;t have under Embedded Swift.&lt;/p&gt;&lt;p&gt;As we can see, we need to skip over a large chunk of the API, not implementing it or providing some stub implementation that does not really behave as its original counterpart.&lt;br&gt;In those conditions, implementing the same API doesn&amp;rsquo;t make a lot of sense and could actually prove dangerous as code using our implementation would behave differently than expected.&lt;/p&gt;&lt;h1 id=&#34;our-own-api&#34;&gt;Our own API&lt;/h1&gt;&lt;p&gt;So, instead, let&amp;rsquo;s implement a &lt;code&gt;Timer&lt;/code&gt; type that provides similar functionalities, but with its own API (but still inspired by the existing Timer API).&lt;/p&gt;&lt;p&gt;We&amp;rsquo;ll keep the idea of having a static function create and start a timer and the initializer create the timer without starting it. We&amp;rsquo;ll thus need a method to start the timer.&lt;br&gt;When creating a timer, we want to pass a delay, an optional period and the code to execute on trigger.&lt;/p&gt;&lt;p&gt;In Zephyr, the expiry function type is defined as&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;k_timer_expiry_t&lt;/span&gt;)(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; k_timer &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;timer)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;so we&amp;rsquo;ll create the equivalent in Swift&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typealias&lt;/span&gt; TimerExpiry = @convention(c) (&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; timer: UnsafeMutablePointer&amp;lt;k_timer&amp;gt;?&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;) -&amp;gt; Void&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can now define our code skeleton&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Timer&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scheduledTimer&lt;/span&gt;(delay: UInt32, period: UInt32? = &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;, handler: TimerExpiry?) -&amp;gt; Timer {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(delay: UInt32, period: UInt32? = &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;, handler: TimerExpiry?) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;start&lt;/span&gt;() {    &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The initializer is straightforward. We just add properties to remember the delay and period, and a property to store the &lt;code&gt;k_timer&lt;/code&gt; structure; we initialize it with a reference to the code to execute.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Timer&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; timer = UnsafeMutablePointer&amp;lt;k_timer&amp;gt;.allocate(capacity: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; delay: UInt32&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; period: UInt32?&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(delay: UInt32, period: UInt32? = &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;, handler: TimerExpiry?) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.delay = delay&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.period = period&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    k_timer_init(timer, handler, &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s now look at starting the timer, the Zephyr call to do that is&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;k_timer_start&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; k_timer &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;timer, &lt;span style=&#34;color:#66d9ef&#34;&gt;k_timeout_t&lt;/span&gt; duration, &lt;span style=&#34;color:#66d9ef&#34;&gt;k_timeout_t&lt;/span&gt; period)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The function takes the duration and period parameters as &lt;code&gt;k_timeout_t&lt;/code&gt; structures. Those are typically constructed in C using the macros &lt;code&gt;K_MSEC()&lt;/code&gt; or &lt;code&gt;K_NO_WAIT&lt;/code&gt; and &lt;code&gt;K_FOREVER&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Trying to use that in our code&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;func &lt;span style=&#34;color:#a6e22e&#34;&gt;start&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;k_timer_start&lt;/span&gt;(timer, &lt;span style=&#34;color:#a6e22e&#34;&gt;K_MSEC&lt;/span&gt;(self.delay), &lt;span style=&#34;color:#a6e22e&#34;&gt;K_MSEC&lt;/span&gt;(self.period))&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;leads to compilation errors&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;macro &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;K_MSEC&amp;#39;&lt;/span&gt; unavailable: &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; like macros not supported&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;ve already seen this error in previous posts, as the Swift C Interop only deals with simply macros.&lt;br&gt;Let&amp;rsquo;s look at the definition of the C macro&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define K_MSEC(ms)     Z_TIMEOUT_MS(ms)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;which further expands to&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# define Z_TIMEOUT_MS(t) Z_TIMEOUT_TICKS((k_ticks_t)k_ms_to_ticks_ceil64(MAX(t, 0)))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and this goes on several levels.&lt;/p&gt;&lt;p&gt;Going through the different definitions, we find out that the macro converts milliseconds to a &lt;code&gt;k_timeout_t&lt;/code&gt; struct with its ticks element initialized. The conversion is based on the &lt;code&gt;CONFIG_SYS_CLOCK_TICKS_PER_SEC&lt;/code&gt; constant and the results is a 64bit Int, rounded up.&lt;/p&gt;&lt;p&gt;With this understanding, we can write the following helper functions in Swift.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;msToTimeout&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; delay: UInt32) -&amp;gt; k_timeout_t {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  k_timeout_t(ticks: msToTick(delay))&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;msToTick&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; delay: UInt32) -&amp;gt; Int64 {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; Int64((Double(UInt64(CONFIG_SYS_CLOCK_TICKS_PER_SEC) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; UInt64(delay)) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1000.0&lt;/span&gt;).rounded(.up))&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and implement our &lt;code&gt;start()&lt;/code&gt; function&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;start&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  k_timer_start(timer, msToTimeout(&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.delay), msToTimeout(&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.period == &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt; ? &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; : &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.period!))&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And finally, we can implement the static function&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scheduledTimer&lt;/span&gt;(delay: UInt32, period: UInt32? = &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;, handler: TimerExpiry?) -&amp;gt; Timer {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; t = Timer(delay: delay, period: period, handler: handler)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  t.start()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; t&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;testing&#34;&gt;Testing&lt;/h1&gt;&lt;p&gt;Let&amp;rsquo;s write a small test program using what we have so far and observe its behaviour.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; _ = Timer.scheduledTimer(delay: &lt;span style=&#34;color:#ae81ff&#34;&gt;10000&lt;/span&gt;) { timer &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;10 seconds have elapsed&amp;#34;&lt;/span&gt;)    &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; _ = Timer.scheduledTimer(delay: &lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;, period: &lt;span style=&#34;color:#ae81ff&#34;&gt;2000&lt;/span&gt;) { timer &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Ticking every 2 seconds&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Building and flashing this to our board shows the following output&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;*** Using Zephyr OS v3.6.99-100befc70c74 ***&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Ticking every &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; seconds&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Ticking every &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; seconds&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Ticking every &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; seconds&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt; seconds have elapsed&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Ticking every &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; seconds&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Ticking every &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt; seconds&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;clean-up&#34;&gt;Clean-up&lt;/h1&gt;&lt;p&gt;The current implementation works but there&amp;rsquo;s one issue. We initialize the timer property by allocating a &lt;code&gt;k_timer&lt;/code&gt; structure, which is never deallocated.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; timer = UnsafeMutablePointer&amp;lt;k_timer&amp;gt;.allocate(capacity: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s a memory leak. To prevent it, we must ensure we deallocate the structure when it&amp;rsquo;s no longer required.&lt;br&gt;A good place to do it is in  &lt;code&gt;deinit&lt;/code&gt;. For this, we need to make our struct non-copyable (or switch to using a class).&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s do that and implement clean-up in the &lt;code&gt;deinit&lt;/code&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Timer&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;~&lt;/span&gt;Copyable {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;deinit&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    k_timer_stop(timer)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    timer.deallocate()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;in which we stop the underlying Zephyr timer and release the previously allocated memory.&lt;/p&gt;&lt;p&gt;With this change in place, if we run our above example, no message will be printed anymore.&lt;br&gt;This is because we don&amp;rsquo;t keep a reference to the created timers and so they get de-initialized.&lt;/p&gt;&lt;p&gt;To make it work again, let&amp;rsquo;s change the code to&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; timer1 = Timer.scheduledTimer(delay: &lt;span style=&#34;color:#ae81ff&#34;&gt;10000&lt;/span&gt;) { timer &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;10 seconds have elapsed&amp;#34;&lt;/span&gt;)    &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; timer2 = Timer.scheduledTimer(delay: &lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;, period: &lt;span style=&#34;color:#ae81ff&#34;&gt;2000&lt;/span&gt;) { timer &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Ticking every 2 seconds&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;user-data&#34;&gt;User data&lt;/h1&gt;&lt;p&gt;As with our button example from a previous post (&lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/button_embedded_swift_nrf52_part2/&#34;&gt;Creating a Swift type for button input on nRF52 - Part 2&lt;/a&gt;), the closure can not capture its context and we need some work around to access data from it.&lt;br&gt;And as with the button, it&amp;rsquo;s possible to associate some context data with the timer.&lt;br&gt;The &lt;code&gt;k_timer&lt;/code&gt; structure contains a &lt;code&gt;user_data&lt;/code&gt; member; a void pointer to some data we want to pass around with the timer.&lt;/p&gt;&lt;p&gt;We&amp;rsquo;ll make the &lt;code&gt;Timer&lt;/code&gt; generic for the user data, which can be any reference type&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Timer&lt;/span&gt;&amp;lt;T: AnyObject&amp;gt;: &lt;span style=&#34;color:#f92672&#34;&gt;~&lt;/span&gt;Copyable {&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;add a property to store the user data&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; userData: T&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and update the initializer to take the user data as parameter and store it in the &lt;code&gt;timer&lt;/code&gt; structure&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(userData: T, delay: UInt32, period: UInt32? = &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;, handler: TimerExpiry?) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.delay = delay&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.period = period&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  k_timer_init(timer, handler, &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.userData = userData&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  timer.pointee.user_data = Unmanaged.passUnretained(userData).toOpaque()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As we keep a reference to &lt;code&gt;userData&lt;/code&gt; in a property, we use &lt;code&gt;passUnretained&lt;/code&gt; when storing the pointer in the &lt;code&gt;timer&lt;/code&gt; structure&amp;rsquo;s &lt;code&gt;user_data&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;We&amp;rsquo;ll also provide a static function to extract the user data from a &lt;code&gt;timer&lt;/code&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getUserData&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; timer: UnsafeMutablePointer&amp;lt;k_timer&amp;gt;?) -&amp;gt; T {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; Unmanaged.fromOpaque(timer!.pointee.user_data).takeUnretainedValue()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And update the &lt;code&gt;scheduledTimer&lt;/code&gt; convenience method to pass the user data to the initializer&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;scheduledTimer&lt;/span&gt;(userData: T, delay: UInt32, period: UInt32? = &lt;span style=&#34;color:#66d9ef&#34;&gt;nil&lt;/span&gt;, handler: TimerExpiry?) -&amp;gt; Timer {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; t = Timer(userData: userData, delay: delay, period: period, handler: handler)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  t.start()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; t&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With that in place, we can for instance toggle an LED using a timer, such as in the sample code below (Led is a class in this case).&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; led = Led(gpio: &amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; timer = Timer&amp;lt;Led&amp;gt;.scheduledTimer(userData: led, delay: &lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;, period: &lt;span style=&#34;color:#ae81ff&#34;&gt;2000&lt;/span&gt;) { timer &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Timer&amp;lt;Led&amp;gt;.getUserData(timer).toggle()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;work-queue&#34;&gt;Work queue&lt;/h1&gt;&lt;p&gt;As was mentioned in the beginning of this post and in the original post on button (see &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/button_embedded_swift_nrf52/&#34;&gt;Creating a Swift type for button input on nRF52 - Part 1&lt;/a&gt;), the closure is executed in an ISR context. The code of that closure should execute fast and never block.&lt;br&gt;If this is not the case, the typical way to address this is to use work queues and schedule the code as a work item so it gets executed in another thread.&lt;/p&gt;&lt;p&gt;This is a topic we&amp;rsquo;ll look at in a future post.&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;In this post, we&amp;rsquo;ve built a &lt;code&gt;Timer&lt;/code&gt; struct, with an API inspired by (but not compatible with) the native &lt;code&gt;Timer&lt;/code&gt; class from Foundation. It allows us to easily schedule a closure for later execution and optional repetition.&lt;/p&gt;&lt;p&gt;Foundation offers many more classes revolving around times and dates, an area to explore in a future post.&lt;/p&gt;&lt;p&gt;As always, the code from this post is available on &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Examples&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;If you have any questions, or specific topic you&amp;rsquo;d like me to cover, feel free to contact me on &lt;a href=&#34;https://mastodon.social/@ebariaux&#34;&gt;Mastodon&lt;/a&gt;, &lt;a href=&#34;https://twitter.com/ebariaux&#34;&gt;X&lt;/a&gt; or &lt;a href=&#34;https://linkedin.com/in/ebariaux&#34;&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Randomness on nRF52 using Embedded Swift</title>
       <link>https://https://ericbariaux.statichost.page//posts/random_nrf52/</link>
       <pubDate>Sat, 09 Nov 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/random_nrf52/</guid>
       <description>&lt;p&gt;&lt;em&gt;Update 2025-07-12: Added import statement for getentropy() implementation in stubs.c&lt;/em&gt;&lt;/p&gt;&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;Randomness comes in handy in many different places. It&amp;rsquo;s useful in the logic of many games to make enemies behave in an unpredictable fashion, it can distribute the timing of events when used within a retry mechanism and random data is sometimes integral to AI algorithms.&lt;br&gt;In this post, we&amp;rsquo;ll see how to generate random numbers in Embedded Swift on an nRF52840 DK using the nRF Connect SDK.&lt;/p&gt;&lt;h1 id=&#34;reading-documentation&#34;&gt;Reading documentation&lt;/h1&gt;&lt;p&gt;The &lt;a href=&#34;https://github.com/swiftlang/swift/blob/main/docs/EmbeddedSwift/UserManual.md#external-dependencies&#34;&gt;External dependencies&lt;/a&gt; section of the &lt;a href=&#34;https://github.com/swiftlang/swift/blob/main/docs/EmbeddedSwift/UserManual.md&#34;&gt;Embedded Swift — User Manual&lt;/a&gt; lists some external dependencies that need to be present at link-time, as the Swift standard library or Embedded Swift runtime might need to call them.&lt;br&gt;Of particular interest to us is:&lt;/p&gt;&lt;blockquote&gt;&lt;ul&gt;&lt;li&gt;using Hashable, Set, Dictionary, or random-number generating APIs.&lt;ul&gt;&lt;li&gt;dependency: &lt;code&gt;void arc4random_buf(void *, size_t);&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;h1 id=&#34;testing-the-code&#34;&gt;Testing the code&lt;/h1&gt;&lt;p&gt;Let&amp;rsquo;s write some basic code to print a random digit every 5 seconds and try to compile that.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; randomDigit = Int.random(&lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;..&lt;span style=&#34;color:#ae81ff&#34;&gt;9&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Digit: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\(&lt;/span&gt;randomDigit&lt;span style=&#34;color:#e6db74&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;5000&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From the documentation above, the linker should report an undefined symbol: &lt;code&gt;arc4random_buf&lt;/code&gt;. However, the error message we receive is slightly different.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/opt/nordic/ncs/toolchains/f8037e9b83/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld.bfd: /opt/nordic/ncs/toolchains/f8037e9b83/opt/zephyr-sdk/arm-zephyr-eabi/arm-zephyr-eabi/lib/thumb/v7e-m/nofp/libc_nano.a&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;lib_a-arc4random.o&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;: in &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;_rs_stir_if_needed&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;arc4random.c:(.text._rs_stir_if_needed+0x16): undefined reference to `getentropy&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;indicating that the &lt;code&gt;getentropy&lt;/code&gt;symbol is undefined.&lt;/p&gt;&lt;h1 id=&#34;c-standard-library&#34;&gt;C standard library&lt;/h1&gt;&lt;p&gt;nRF Connect SDK (Zephyr) provides, by default, an implementation of the C standard library. In fact, it provides multiple.&lt;br&gt;We&amp;rsquo;re using &lt;a href=&#34;https://sourceware.org/newlib/&#34;&gt;newlib&lt;/a&gt; in our project. This is configured in prj.conf with the parameter&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-properties&#34; data-lang=&#34;properties&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;CONFIG_NEWLIB_LIBC&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is the configuration used in the &lt;a href=&#34;https://github.com/apple/swift-embedded-examples/tree/main/nrfx-blink-sdk&#34;&gt;nrfx-blink-sdk&lt;/a&gt; sample from Apple.&lt;/p&gt;&lt;p&gt;Looking at the source code of newlib, we find in file &lt;a href=&#34;https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/stdlib/arc4random.c;h=09a134c3b9dabec8ae414223f082e9dfdcaaeb3a;hb=HEAD&#34;&gt;newlib/libc/stdlib/arc4random.c&lt;/a&gt;, the &lt;a href=&#34;https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/stdlib/arc4random.c;h=09a134c3b9dabec8ae414223f082e9dfdcaaeb3a;hb=HEAD#l209&#34;&gt;arc4random_buf()&lt;/a&gt;function that the Embedded Swift documentation instructs us to implement.&lt;br&gt;Following the code logic, we eventually find a call to &lt;a href=&#34;https://sourceware.org/git/?p=newlib-cygwin.git;a=blob;f=newlib/libc/stdlib/arc4random.c;h=09a134c3b9dabec8ae414223f082e9dfdcaaeb3a;hb=HEAD#l101&#34;&gt;getentropy()&lt;/a&gt;, the undefined symbol that our linker error mentioned.&lt;/p&gt;&lt;p&gt;As newlib does not provide an implementation of this function, it is up to us to do so.&lt;/p&gt;&lt;h1 id=&#34;bridging-the-gap&#34;&gt;Bridging the gap&lt;/h1&gt;&lt;p&gt;Let&amp;rsquo;s start by researching the intended purpose of this function. The &lt;a href=&#34;https://man7.org/linux/man-pages/man3/getentropy.3.html&#34;&gt;getentropy(3) - Linux manual page&lt;/a&gt; gives us the answer&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;fill a buffer with random bytes&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Does Zephyr provide functionality to support this implementation ?&lt;br&gt;Looking through the documentation, we find a section on &lt;a href=&#34;https://docs.zephyrproject.org/latest/services/crypto/random/index.html&#34;&gt;Random Number Generation&lt;/a&gt;.&lt;br&gt;This section indicates that indeed, Zephyr provides multiple possibilities for generating random numbers. Clicking through to the &lt;a href=&#34;https://docs.zephyrproject.org/latest/doxygen/html/group__random__api.html&#34;&gt;Random Function APIs documentation&lt;/a&gt;, we find the &lt;a href=&#34;https://docs.zephyrproject.org/latest/doxygen/html/group__random__api.html#gaf4f6792ac29c876d59ace1deae53bbd7&#34;&gt;sys_rand_get()&lt;/a&gt; function that provides the functionality we&amp;rsquo;re looking for.&lt;/p&gt;&lt;p&gt;With this, we can glue everything together by implementing the required &lt;code&gt;getentropy()&lt;/code&gt;function in the &lt;code&gt;Stubs.c&lt;/code&gt; file.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;zephyr/random/random.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;⋮&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getentropy&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;buffer, &lt;span style=&#34;color:#66d9ef&#34;&gt;size_t&lt;/span&gt; length) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;sys_rand_get&lt;/span&gt;(buffer, length);&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We also make sure we&amp;rsquo;re telling Zephyr to use one of the available random number generators by setting the proper configuration option in prj.conf&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-properties&#34; data-lang=&#34;properties&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;CONFIG_TEST_RANDOM_GENERATOR&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s build and flash what we have so far. Connecting to the board, we can see random digits being generated&lt;/p&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;*** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ****** Using Zephyr OS v3.6.99-100befc70c74 ***Digit: 4Digit: 9Digit: 9Digit: 4&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&#34;better-randomness&#34;&gt;Better randomness&lt;/h1&gt;&lt;p&gt;Although the values printed out appear random, the documentation for our &lt;code&gt;CONFIG_TEST_RANDOM_GENERATOR&lt;/code&gt;parameter indicates that&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;For testing, this option allows a non-random number generator to be used and permits random number APIs to return values that are not truly random.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;To improve this, let&amp;rsquo;s adjust our prj.conf file and select another generator&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-properties&#34; data-lang=&#34;properties&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this change, our project fails to build&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/opt/nordic/ncs/toolchains/f8037e9b83/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld.bfd: app/libapp.a&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;Stubs.c.obj&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;: in &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;sys_rand_get&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;/.../EmbeddedSwift-nRF52-Examples/Random/build/zephyr/include/generated/syscalls/random.h:37: undefined reference to `z_impl_sys_rand_get&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Taking a closer look at the&lt;a href=&#34;https://docs.zephyrproject.org/latest/kconfig.html#CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR&#34;&gt;CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR&lt;/a&gt; documentation, it states that it uses the enabled hardware entropy gathering driver to generate random numbers.&lt;br&gt;It&amp;rsquo;s not explicit but reading between the lines, we can deduct that we should enable the entropy driver, which is done by adding this configuration option.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-properties&#34; data-lang=&#34;properties&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;CONFIG_ENTROPY_GENERATOR&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;y&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And with this, our project builds again and we can flash it to our board to test.&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;In this post, I&amp;rsquo;ve shown you how to generate random numbers in Embedded Swift when using the nRF Connect SDK. The code is available on &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Examples&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;In our test program, we used &lt;code&gt;Int.random(in:)&lt;/code&gt;to generate a random integer. But of course we can also use other randomness-based functions, like&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; array = [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Jobs&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Wozniak&amp;#34;&lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; element = array.randomElement()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And as indicated in the &lt;a href=&#34;https://github.com/swiftlang/swift/blob/main/docs/EmbeddedSwift/UserManual.md&#34;&gt;Embedded Swift — User Manual&lt;/a&gt;, you can now also use dictionaries and sets&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; dictionary = [&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Jobs&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Wozniak&amp;#34;&lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; set : Set&amp;lt;Int&amp;gt; = [&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Dictionaries ?&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; dictionary = [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Jobs&amp;#34;&lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Really ?&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Main.swift.obj:&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;.text.$ss7UnicodeO14_NFDNormalizerV7_resume9consumingAB6ScalarV6scalar_AB9_NormDataV04normH0tSgAHSgyXE_tF+0x1d4&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;: undefined reference to &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;_swift_stdlib_getNormData&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Well that&amp;rsquo;s another problem not related to random number generation that we&amp;rsquo;ll address in a future post.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Creating a Swift type for button input on nRF52 - Part 2</title>
       <link>https://https://ericbariaux.statichost.page//posts/button_embedded_swift_nrf52_part2/</link>
       <pubDate>Mon, 14 Oct 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/button_embedded_swift_nrf52_part2/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;In the last post, &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/button_embedded_swift_nrf52/&#34;&gt;Creating a Swift type for button input on nRF52 - Part 1&lt;/a&gt;, we worked on code to abstract interacting with a button in Swift code. We had a working prototype, but things fell apart as soon as we cleaned up the code and encapsulated it in a struct.&lt;/p&gt;&lt;h1 id=&#34;investigating-the-issue&#34;&gt;Investigating the issue&lt;/h1&gt;&lt;p&gt;Let&amp;rsquo;s see if there&amp;rsquo;s valuable information in the documentation.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/**&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @brief GPIO callback structure&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; *&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * Used to register a callback in the driver instance callback list.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * As many callbacks as needed can be added as long as each of them&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * are unique pointers of struct gpio_callback.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * Beware such structure should not be allocated on stack.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; *&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * Note: To help setting it, see gpio_init_callback() below&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_callback {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/** This is meant to be used in the driver and the user should not&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * mess with it (see drivers/gpio/gpio_utils.h)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;sys_snode_t&lt;/span&gt; node;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/** Actual callback function being called when relevant. */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;gpio_callback_handler_t&lt;/span&gt; handler;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/** A mask of pins the callback is interested in, if 0 the callback&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * will never be called. Such pin_mask can be modified whenever&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * necessary by the owner, and thus will affect the handler being&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * called or not. The selected pins must be configured to trigger&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * an interrupt.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;gpio_port_pins_t&lt;/span&gt; pin_mask;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The documentation for the definition of the &lt;code&gt;gpio_callback&lt;/code&gt; gives an interesting piece of information.&lt;br&gt;Can you spot it?&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Beware such structure should not be allocated on stack.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Let&amp;rsquo;s look at our Swift code again&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Button&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; pin_cb_data = gpio_callback()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here we&amp;rsquo;re creating a &lt;code&gt;gpio_callback&lt;/code&gt; as a stored property of a Swift struct. That struct being a value type, it will be allocated on the stack, which the above comment explicitly advises against.&lt;br&gt;An easy fix is to make the Button a class, which as a reference type, will be allocated on the heap.&lt;/p&gt;&lt;style type=&#34;text/css&#34;&gt;         .notice {        --title-color: #fff;        --title-background-color: #6be;        --content-color: #444;        --content-background-color: #e7f2fa;    }    .notice.info {        --title-background-color: #fb7;        --content-background-color: #fec;    }    .notice.tip {        --title-background-color: #5a5;        --content-background-color: #efe;    }    .notice.warning {        --title-background-color: #c33;        --content-background-color: #fee;    }         @media (prefers-color-scheme:dark) {        .notice {            --title-color: #fff;            --title-background-color: #069;            --content-color: #ddd;            --content-background-color: #023;        }        .notice.info {            --title-background-color: #a50;            --content-background-color: #420;        }        .notice.tip {            --title-background-color: #363;            --content-background-color: #121;        }        .notice.warning {            --title-background-color: #800;            --content-background-color: #400;        }    }    body.dark .notice {        --title-color: #fff;        --title-background-color: #069;        --content-color: #ddd;        --content-background-color: #023;    }    body.dark .notice.info {        --title-background-color: #a50;        --content-background-color: #420;    }    body.dark .notice.tip {        --title-background-color: #363;        --content-background-color: #121;    }    body.dark .notice.warning {        --title-background-color: #800;        --content-background-color: #400;    }         .notice {        padding: 18px;        line-height: 24px;        margin-bottom: 24px;        border-radius: 4px;        color: var(--content-color);        background: var(--content-background-color);    }    .notice p:last-child {        margin-bottom: 0    }         .notice-title {        margin: -18px -18px 12px;        padding: 4px 18px;        border-radius: 4px 4px 0 0;        font-weight: 700;        color: var(--title-color);        background: var(--title-background-color);    }         .icon-notice {        display: inline-flex;        align-self: center;        margin-right: 8px;    }    .icon-notice img,    .icon-notice svg {        height: 1em;        width: 1em;        fill: currentColor;    }    .icon-notice img,    .icon-notice.baseline svg {        top: .125em;        position: relative;    }&lt;/style&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;The idea that value types are always created on the stack and reference types on the heap is not entirely true. I have not yet been able to find an exact rule but the approximation works for now and for this particular case.&lt;/p&gt;&lt;p&gt;A safer way (which would also allow to keep our Button as a struct) is to explicitly allocate the &lt;code&gt;gpio_callback&lt;/code&gt; structure on the heap. This however opens a can of worms that is too much for this article. But it&amp;rsquo;s a topic we&amp;rsquo;ll revisit later and in great details.&lt;/p&gt;&lt;/div&gt;&lt;h1 id=&#34;beyond-printing-a-message&#34;&gt;Beyond printing a message&lt;/h1&gt;&lt;p&gt;The code is now working again, but all it does is print a message when the button is pressed. Let&amp;rsquo;s move to something slightly more interesting and, re-using code from our first example (&lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/led_embedded_swift_nrf52/&#34;&gt;Controlling an LED using Embedded Swift on nRF52&lt;/a&gt;), make the button toggle an LED.&lt;/p&gt;&lt;p&gt;We&amp;rsquo;ll use a simplified version of the Led code, omitting the error handling and not throwing any errors, as to make things more readable.&lt;/p&gt;&lt;p&gt;We can then update the closure passed to the button so it toggles the LED when the button is pressed.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; led = Led(gpio: &amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; myButton = Button(gpio: &amp;amp;button) { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      led.toggle()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But this makes the build fail&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;…/EmbeddedSwift-nRF52-Examples/Button-and-LED/Main.swift:52:42: error: a C &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; pointer cannot be formed from a closure that captures context&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;50&lt;/span&gt; |     let led &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Led&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gpio: &amp;amp;led0&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;51&lt;/span&gt; | &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;52&lt;/span&gt; |     let myButton &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; Button&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gpio: &amp;amp;button&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt; _, _, _ in&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    |                                          &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;- error: a C &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; pointer cannot be formed from a closure that captures context&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;53&lt;/span&gt; |       led.toggle&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;54&lt;/span&gt; |     &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As the error message indicates, the closure cannot capture references to variables from its context.&lt;br&gt;We have two main possibilities to fix this:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;make the variable that we want to reference globally available&lt;/li&gt;&lt;li&gt;somehow pass the reference to the C function&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Let&amp;rsquo;s explore these 2 options in more details.&lt;/p&gt;&lt;h1 id=&#34;making-our-led-variable-globally-available&#34;&gt;Making our led variable globally available&lt;/h1&gt;&lt;p&gt;There are multiple ways to achieve this.&lt;/p&gt;&lt;h2 id=&#34;global-variable&#34;&gt;Global variable&lt;/h2&gt;&lt;p&gt;The first and easiest way is to just make it a global variable for the module.&lt;/p&gt;&lt;p&gt;Moving the &lt;code&gt;let led = Led(gpio: &amp;amp;led0)&lt;/code&gt; declaration outside of the &lt;code&gt;Main&lt;/code&gt; struct makes it available from within the closure.&lt;/p&gt;&lt;p&gt;The code would look something like this&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; led = Led(gpio: &amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; myButton = Button(gpio: &amp;amp;button) { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      led.toggle()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This builds and works fine, and is OK for simple cases but it&amp;rsquo;s definitely not the best code organisation and does not scale very well.&lt;/p&gt;&lt;h2 id=&#34;static-variable-on-a-type&#34;&gt;Static variable on a type&lt;/h2&gt;&lt;p&gt;Instead, we can define a static constant property on the existing &lt;code&gt;Led&lt;/code&gt; type&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Led&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; firstLed = Led(gpio: &amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and refer to it from the closure&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; myButton = Button(gpio: &amp;amp;button) { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Led.firstLed.toggle()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you don&amp;rsquo;t want to modify the &lt;code&gt;Led&lt;/code&gt; type and keep it generic (for instance because it&amp;rsquo;s coming from an external package), you can create a dedicated type (an enum in this case) to hold the static constants.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Leds&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; firstLed = Led(gpio: &amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; myButton = Button(gpio: &amp;amp;button) { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Leds.firstLed.toggle()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;application-logic-singleton&#34;&gt;Application logic singleton&lt;/h2&gt;&lt;p&gt;In all the above examples, we&amp;rsquo;ve used different strategies to allow global access to a single definition of the &lt;code&gt;Led&lt;/code&gt; constant.&lt;/p&gt;&lt;p&gt;If we would have multiple elements to expose, or we would want to encapsulate those elements behind some more advanced logic, we can create a class to host that logic and make it a singleton.&lt;br&gt;The singleton pattern ensures that the class would only have one instance and provides a global access point to that instance.&lt;/p&gt;&lt;p&gt;The code could look something like this.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AppLogic&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; shared = AppLogic()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;() { }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; firstLed = Led(gpio: &amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;toggleLed&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      firstLed.toggle()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With the button closure using the logic exposed by the singleton.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; myButton = Button(gpio: &amp;amp;button) { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  AppState.shared.toggleLed()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;In the above implementation of the singleton, the &lt;code&gt;AppLogic&lt;/code&gt; instance is only created when the shared static property is first accessed. And so is the initialisation of our &lt;code&gt;Led&lt;/code&gt; instance. This means this only happens on the first button press.&lt;br&gt;If this is not acceptable for some reason, you could always read the shared property in your main function to trigger the instantiation earlier.&lt;/p&gt;&lt;/div&gt;&lt;h1 id=&#34;passing-the-reference-to-the-c-function&#34;&gt;Passing the reference to the C function&lt;/h1&gt;&lt;h2 id=&#34;exploring-the-possibilities&#34;&gt;Exploring the possibilities&lt;/h2&gt;&lt;p&gt;The general idea is that the required information comes via the parameter(s) of the C function (closure) that&amp;rsquo;s being called. As we&amp;rsquo;re implementing a callback whose prototype is defined by the Zephyr SDK, we cannot add the parameter ourself.&lt;br&gt;But is there already something in the API that we can use? Let&amp;rsquo;s take another look at the callback prototype.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/**&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @typedef gpio_callback_handler_t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @brief Define the application callback handler function signature&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; *&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @param port Device struct for the GPIO device.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @param cb Original struct gpio_callback owning this handler&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @param pins Mask of pins that triggers the callback handler&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; *&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * Note: cb pointer can be used to retrieve private data through&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * CONTAINER_OF() if original struct gpio_callback is stored in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * another private structure.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;void&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;gpio_callback_handler_t&lt;/span&gt;)(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; device &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;port,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_callback &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;cb,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;gpio_port_pins_t&lt;/span&gt; pins);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Do you see the note in the documentation ? The API has foreseen a way to pass private data to this handler. Let&amp;rsquo;s try to figure out how that works.&lt;/p&gt;&lt;p&gt;Searching the Zephyr documentation for &lt;code&gt;CONTAINER_OF&lt;/code&gt;, we find some information in &lt;a href=&#34;https://docs.zephyrproject.org/apidoc/latest/group__sys-util.html#gac5bc561d1bfd1bf68877fe577779bd2f&#34;&gt;Zephyr API Documentation: Utility Functions&lt;/a&gt;. The basic idea is that given an element of a struct, we&amp;rsquo;re able to get back to the containing struct.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s look at the example from the documentation&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; foo {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; bar;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; };&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; foo my_foo;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;ptr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;my_foo.bar;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; foo &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;container &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;CONTAINER_OF&lt;/span&gt;(ptr, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; foo, bar);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here we see that, knowing the address of &lt;code&gt;bar&lt;/code&gt;, an element of &lt;code&gt;my_foo&lt;/code&gt;, the &lt;code&gt;CONTAINER_OF&lt;/code&gt; macro will return the address of that &lt;code&gt;my_foo&lt;/code&gt; struct.&lt;/p&gt;&lt;p&gt;If the struct &lt;code&gt;foo&lt;/code&gt; would contain a &lt;code&gt;struct gpio_callback&lt;/code&gt; instead of an &lt;code&gt;int&lt;/code&gt;, that would read&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; foo {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_callback cb;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; };&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; foo my_foo;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;ptr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;my_foo.cb;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; foo &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;container &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;CONTAINER_OF&lt;/span&gt;(ptr, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; foo, cb);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;re getting to a containing structure from the &lt;code&gt;gpio_callback&lt;/code&gt; element, which is one of the parameters we receive in our GPIO handler function.&lt;/p&gt;&lt;h2 id=&#34;understanding-container_of&#34;&gt;Understanding CONTAINER_OF&lt;/h2&gt;&lt;p&gt;Looking at the definition of CONTAINER_OF, we see it&amp;rsquo;s a &amp;ldquo;complex&amp;rdquo; macro&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define CONTAINER_OF(ptr, type, field)                               \&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;({                                                           \&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;CONTAINER_OF_VALIDATE(ptr, type, field)              \&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;((type *)(((char *)(ptr)) - offsetof(type, field))); \&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;})&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and we&amp;rsquo;ve seen in the previous post that Swift C Interop only supports simple macros.&lt;/p&gt;&lt;p&gt;Instead of trying to see how we could call this macro from Swift, let&amp;rsquo;s understand what it does and re-implement the same behaviour using Swift native constructs.&lt;/p&gt;&lt;p&gt;Setting aside some validation, the macro implements some basic pointer arithmetics. Considering the containing struct is represented by a contiguous block of memory, knowing the address of one of its property and the offset of that property from the start, by subtracting that offset from the address we get back the starting address of the memory block i.e. the address of the containing structure.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s extend our &lt;code&gt;foo&lt;/code&gt; structure with some int property, create a variable of that type and see how the maths work&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; foo {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; bar;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_callback cb;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; foo my_foo;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;ptr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;my_foo.cb;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s pretend &lt;code&gt;my_foo&lt;/code&gt; is at address 0x00001000. The addresses of the structure look like&lt;/p&gt;&lt;table class=&#34;small&#34;&gt;  &lt;thead&gt;      &lt;tr&gt;          &lt;th&gt;Address&lt;/th&gt;          &lt;th&gt;Element&lt;/th&gt;      &lt;/tr&gt;  &lt;/thead&gt;  &lt;tbody&gt;      &lt;tr&gt;          &lt;td&gt;0x00001000&lt;/td&gt;          &lt;td&gt;bar&lt;/td&gt;      &lt;/tr&gt;      &lt;tr&gt;          &lt;td&gt;0x00001004&lt;/td&gt;          &lt;td&gt;cb&lt;/td&gt;      &lt;/tr&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;code&gt;ptr&lt;/code&gt; is the address of &lt;code&gt;cb&lt;/code&gt; and would have value 0x00001004. &lt;code&gt;offsetof(struct foo, cb)&lt;/code&gt; would return 4. Subtracting that from &lt;code&gt;ptr&lt;/code&gt; gives 0x00001000, which is indeed the address of &lt;code&gt;my_foo&lt;/code&gt;.&lt;/p&gt;&lt;h2 id=&#34;pointer-arithmetics-in-swift&#34;&gt;Pointer arithmetics in Swift&lt;/h2&gt;&lt;p&gt;Swift provides several types for &lt;a href=&#34;https://developer.apple.com/documentation/swift/manual-memory-management&#34;&gt;Manual Memory Management&lt;/a&gt;, you can spot them by their name following the &lt;code&gt;Unsafe…Pointer&lt;/code&gt; pattern.&lt;br&gt;Of the different flavours available, &lt;code&gt;UnsafeRawPointer&lt;/code&gt; is one of the simplest, providing untyped access to raw bytes in memory. It corresponds to a &lt;code&gt;void *&lt;/code&gt; pointer in C.&lt;br&gt;Raw pointers support basic arithmetic operations at the byte level. When you add to or subtract from a raw pointer, the result is a new raw pointer offset by that number of bytes.&lt;br&gt;Using &lt;code&gt;UnsafeRawPointer&lt;/code&gt;will allow us to implement the above subtraction from our CONTAINER_OF formula.&lt;/p&gt;&lt;p&gt;What about the &lt;code&gt;offsetof()&lt;/code&gt; call ? This is an ANSI C macro that evaluates to the offset (in bytes) of a given member within a struct or union type.&lt;br&gt;It happens that Swift provides the same functionality with the &lt;a href=&#34;https://developer.apple.com/documentation/swift/memorylayout/offset(of:)&#34;&gt;offset(of:)&lt;/a&gt; function of the &lt;a href=&#34;https://developer.apple.com/documentation/swift/memorylayout&#34;&gt;MemoryLayout&lt;/a&gt; type.&lt;/p&gt;&lt;p&gt;Finally, once done with the pointer arithmetic, we would like to &amp;ldquo;cast&amp;rdquo; the result to the type of our container structure. We can achieve that using the &lt;a href=&#34;https://developer.apple.com/documentation/swift/unsaferawpointer/assumingmemorybound(to:)&#34;&gt;assumingMemoryBound(to:)&lt;/a&gt; on our &lt;code&gt;UnsafeRawPointer&lt;/code&gt;, that will return us an &lt;code&gt;UnsafePointer&lt;/code&gt; typed to the requested type.&lt;/p&gt;&lt;h2 id=&#34;putting-it-all-together&#34;&gt;Putting it all together&lt;/h2&gt;&lt;p&gt;In our project, we wanted the &lt;code&gt;Led&lt;/code&gt; to be available with the button handler closure. We thus create a container structure, that in addition to the original callback structure, contains our &lt;code&gt;Led&lt;/code&gt;.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ExtendedCallback&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; callback: gpio_callback&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; led: Led&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We then add, on that structure, a function to perform the pointer arithmetic, and return, given a pointer to the &lt;code&gt;callback&lt;/code&gt; element, the &lt;code&gt;ExtendedCallback&lt;/code&gt;.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ExtendedCallback&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; callback: gpio_callback&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; led: Led&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;containerFrom&lt;/span&gt;(callback ptr: UnsafePointer&amp;lt;gpio_callback&amp;gt;) -&amp;gt; ExtendedCallback {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; containerPtr = UnsafeRawPointer(ptr) &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; MemoryLayout.offset(of: &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;\&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;Self&lt;/span&gt;.callback)&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; containerPtr.assumingMemoryBound(to: &lt;span style=&#34;color:#66d9ef&#34;&gt;Self&lt;/span&gt;.&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;).pointee&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With that in place, we can now access the &lt;code&gt;Led&lt;/code&gt; from within the button closure.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; myButton = Button(gpio: &amp;amp;button) { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, callback, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExtendedCallback.containerFrom(callback: callback!).led.toggle()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, we need to properly initialise this property. We edit our &lt;code&gt;Button&lt;/code&gt; class so that, the &lt;code&gt;pin_cb_data&lt;/code&gt; property is initialized with an &lt;code&gt;ExtendedCallback&lt;/code&gt;, encapsulating both our initial &lt;code&gt;gpio_callback&lt;/code&gt;and our &lt;code&gt;Led&lt;/code&gt;.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; pin_cb_data = ExtendedCallback(callback: gpio_callback(), led: Led(gpio: &amp;amp;led0))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Within our initializer, we need to adapt the calls that are taking the &lt;code&gt;gpio_callback&lt;/code&gt; as parameters, as we still need to pass that original structure and not the container.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gpio_init_callback(&amp;amp;pin_cb_data.callback, &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.btnHandler, bit(gpio.pointee.pin))&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gpio_add_callback(gpio.pointee.port, &amp;amp;pin_cb_data.callback)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With that in place, we can build the project and test that indeed, the LED toggles as the user pushes the button.&lt;/p&gt;&lt;p&gt;We&amp;rsquo;ve been able to use this strategy here because the API was designed in such a way that some object accessible to us during initialization, was propagated to the callback. This will not always be the case and you&amp;rsquo;ll need to adapt based on the specific use case.&lt;/p&gt;&lt;h2 id=&#34;making-it-generic&#34;&gt;Making it generic&lt;/h2&gt;&lt;p&gt;There are 2 shortcomings to the above code:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;we have hardcoded in the &lt;code&gt;ExtendedCallback&lt;/code&gt; structure that the extra information is a &lt;code&gt;Led&lt;/code&gt;&lt;/li&gt;&lt;li&gt;that &lt;code&gt;Led&lt;/code&gt; is instantiated as part of the &lt;code&gt;Button&lt;/code&gt; code&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Let&amp;rsquo;s use generics to get rid of those limitations.&lt;/p&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;Embedded Swift supports generics but uses specialisation i.e. the generic type is known at compile-time at the caller site and the compiler creates a specialized instantiation of the generic type that is no longer generic.&lt;/p&gt;&lt;p&gt;Generic instantiation at run-time is not supported, as that would require access to type metadata, which does not exist in Embedded Swift.&lt;/p&gt;&lt;/div&gt;&lt;p&gt;We start by making the extra parameter generic&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ExtendedCallback&lt;/span&gt;&amp;lt;T&amp;gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; callback: gpio_callback&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; context: T&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We also need to modify the &lt;code&gt;Button&lt;/code&gt; class in accordance&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Button&lt;/span&gt;&amp;lt;T&amp;gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; btnHandler: GpioCallbackHandler&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; pin_cb_data: ExtendedCallback&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;, context: T, btnHandler: GpioCallbackHandler) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.gpio = gpio&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.btnHandler = btnHandler&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.pin_cb_data = ExtendedCallback(callback: gpio_callback(), context: context)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We make the class generic, the &lt;code&gt;pin_cb_data&lt;/code&gt; is now the generic version of &lt;code&gt;ExtendedCallback&lt;/code&gt; and that property is initialized in the initializer, receiving the context as a parameter.&lt;/p&gt;&lt;p&gt;The closure needs a slight update, as &lt;code&gt;ExtendedCallback&lt;/code&gt; must be specialized for us to call its the static function.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; myButton = Button&amp;lt;Led&amp;gt;(gpio: &amp;amp;button, context: Led(gpio: &amp;amp;led0)) { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, callback, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ExtendedCallback&amp;lt;Led&amp;gt;.containerFrom(callback: callback!).context.toggle()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;In this post, we fixed the issue we encountered last time when encapsulating our logic within a Button type.&lt;br&gt;We then encountered a limitation of closures used as C function pointers and explored several strategies on how the closure can access information defined outside of its scope.&lt;/p&gt;&lt;p&gt;With these core concepts covered in this post and the previous two, we have some building blocks to start tackling more complex and interesting projects.&lt;br&gt;Stay tuned as we&amp;rsquo;ll cover that in a future post.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Creating a Swift type for button input on nRF52 - Part 1</title>
       <link>https://https://ericbariaux.statichost.page//posts/button_embedded_swift_nrf52/</link>
       <pubDate>Thu, 26 Sep 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/button_embedded_swift_nrf52/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;In my previous post, &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/led_embedded_swift_nrf52/&#34;&gt;Controlling an LED using Embedded Swift on nRF52&lt;/a&gt;, we created a Swift struct to encapsulate the C code required to control an LED. In this post, we&amp;rsquo;ll do the same for a button.&lt;/p&gt;&lt;p&gt;If you want to follow along, the code is available on &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Examples&#34;&gt;GitHub&lt;/a&gt; with each step having its own commit.&lt;/p&gt;&lt;h1 id=&#34;starting-from-working-code&#34;&gt;Starting from working code&lt;/h1&gt;&lt;p&gt;As a starting point, we will write the whole code in C. This code is based on the &lt;a href=&#34;https://github.com/NordicDeveloperAcademy/ncs-fund/tree/main/v2.x.x/lesson2/fund_less2_exer2_solution&#34;&gt;Lesson 2 - Exercise 2&lt;/a&gt; sample code from the &lt;a href=&#34;https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/&#34;&gt;nRF Connect SDK Fundamentals&lt;/a&gt; course from the &lt;a href=&#34;https://academy.nordicsemi.com/&#34;&gt;Nordic Developer Academy&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;In the button.c file, we define a single function that performs the whole setup.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;zephyr/drivers/gpio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;#34;button.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define SW0_NODE DT_ALIAS(sw0)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_dt_spec button &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GPIO_DT_SPEC_GET&lt;/span&gt;(SW0_NODE, gpios);&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_callback pin_cb_data;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setupButton&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; ret;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;gpio_is_ready_dt&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;button)) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ret &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;gpio_pin_configure_dt&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;button, GPIO_INPUT);&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (ret &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;gpio_pin_interrupt_configure_dt&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;button, GPIO_INT_EDGE_TO_ACTIVE);&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;pin_isr&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; device &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;dev, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_callback &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;cb, &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; pins) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;printk&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Button pressed&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;gpio_init_callback&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;pin_cb_data, pin_isr, &lt;span style=&#34;color:#a6e22e&#34;&gt;BIT&lt;/span&gt;(button.pin));&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;gpio_add_callback&lt;/span&gt;(button.port, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;pin_cb_data);&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The button.h file only contains the prototype of the setup function (and a single include that is required by both the C and Swift code).&lt;/p&gt;&lt;style type=&#34;text/css&#34;&gt;         .notice {        --title-color: #fff;        --title-background-color: #6be;        --content-color: #444;        --content-background-color: #e7f2fa;    }    .notice.info {        --title-background-color: #fb7;        --content-background-color: #fec;    }    .notice.tip {        --title-background-color: #5a5;        --content-background-color: #efe;    }    .notice.warning {        --title-background-color: #c33;        --content-background-color: #fee;    }         @media (prefers-color-scheme:dark) {        .notice {            --title-color: #fff;            --title-background-color: #069;            --content-color: #ddd;            --content-background-color: #023;        }        .notice.info {            --title-background-color: #a50;            --content-background-color: #420;        }        .notice.tip {            --title-background-color: #363;            --content-background-color: #121;        }        .notice.warning {            --title-background-color: #800;            --content-background-color: #400;        }    }    body.dark .notice {        --title-color: #fff;        --title-background-color: #069;        --content-color: #ddd;        --content-background-color: #023;    }    body.dark .notice.info {        --title-background-color: #a50;        --content-background-color: #420;    }    body.dark .notice.tip {        --title-background-color: #363;        --content-background-color: #121;    }    body.dark .notice.warning {        --title-background-color: #800;        --content-background-color: #400;    }         .notice {        padding: 18px;        line-height: 24px;        margin-bottom: 24px;        border-radius: 4px;        color: var(--content-color);        background: var(--content-background-color);    }    .notice p:last-child {        margin-bottom: 0    }         .notice-title {        margin: -18px -18px 12px;        padding: 4px 18px;        border-radius: 4px 4px 0 0;        font-weight: 700;        color: var(--title-color);        background: var(--title-background-color);    }         .icon-notice {        display: inline-flex;        align-self: center;        margin-right: 8px;    }    .icon-notice img,    .icon-notice svg {        height: 1em;        width: 1em;        fill: currentColor;    }    .icon-notice img,    .icon-notice.baseline svg {        top: .125em;        position: relative;    }&lt;/style&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;In C, a function prototype defines the function name, its parameter(s) and return type.&lt;br&gt;It&amp;rsquo;s very similar to a method signature in Swift.&lt;/p&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;zephyr/kernel.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setupButton&lt;/span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the BridgingHeader.h file makes it all visible to our Swift code.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;autoconf.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;#34;button.h&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All the Swift code has to do for now, is call that single function.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    setupButton()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Try building and running the code on your hardware at this point. Do you see the expected message in your console when the button is pressed?&lt;/p&gt;&lt;h1 id=&#34;chi-va-piano-va-sano&#34;&gt;Chi va piano va sano&lt;/h1&gt;&lt;p&gt;Let&amp;rsquo;s follow that Italian saying (that translates to &lt;em&gt;&amp;ldquo;Slow and steady wins the race&amp;rdquo;&lt;/em&gt; ) and begin transforming each section into Swift, step by step; making sure the code compiles and runs at each step.&lt;/p&gt;&lt;p&gt;We first start by moving the static variable referencing the GPIO used for the button directly to the BridgingHeader.h file.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;autoconf.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;zephyr/kernel.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;zephyr/drivers/gpio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define SW0_NODE DT_ALIAS(sw0)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_dt_spec button &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GPIO_DT_SPEC_GET&lt;/span&gt;(SW0_NODE, gpios);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then we check the GPIO is ready. This is similar to what we did for the LED, so it works as expected.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; gpio_is_ready_dt(&amp;amp;button) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, we configure the pin, similar to the LED configuration, but this time as an input.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; gpio_is_ready_dt(&amp;amp;button) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; ret = gpio_pin_configure_dt(&amp;amp;button, GPIO_INPUT)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; ret == &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The next step is to configure the pin so it triggers when it transitions to an active state.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; gpio_is_ready_dt(&amp;amp;button) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; ret = gpio_pin_configure_dt(&amp;amp;button, GPIO_INPUT)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; ret == &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_pin_interrupt_configure_dt(&amp;amp;button, GPIO_INT_EDGE_TO_ACTIVE)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and this causes a build error&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;…/EmbeddedSwift-nRF52-Examples/Button/Main.swift:18:50: error: cannot find &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;GPIO_INT_EDGE_TO_ACTIVE&amp;#39;&lt;/span&gt; in scope&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;16&lt;/span&gt; |       let ret &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; gpio_pin_configure_dt&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&amp;amp;button, GPIO_INPUT&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;17&lt;/span&gt; |       &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; ret &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;18&lt;/span&gt; |         gpio_pin_interrupt_configure_dt&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&amp;amp;button, GPIO_INT_EDGE_TO_ACTIVE&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   |                                                  &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;- error: cannot find &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;GPIO_INT_EDGE_TO_ACTIVE&amp;#39;&lt;/span&gt; in scope&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;19&lt;/span&gt; |       &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;20&lt;/span&gt; |         print&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Can&amp;#39;t configure the GPIO as input&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/opt/nordic/ncs/v2.7.0/zephyr/include/zephyr/drivers/gpio.h:202:9: note: macro &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;GPIO_INT_EDGE_TO_ACTIVE&amp;#39;&lt;/span&gt; unavailable: structure not supported&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt; |  * level &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; and enables it.&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;201&lt;/span&gt; |  */&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;202&lt;/span&gt; | &lt;span style=&#34;color:#75715e&#34;&gt;#define GPIO_INT_EDGE_TO_ACTIVE        (GPIO_INT_ENABLE | \&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     |         &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;- note: macro &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;GPIO_INT_EDGE_TO_ACTIVE&amp;#39;&lt;/span&gt; unavailable: structure not supported&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;203&lt;/span&gt; |                                  GPIO_INT_LEVELS_LOGICAL | &lt;span style=&#34;color:#ae81ff&#34;&gt;\&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;204&lt;/span&gt; |                                  GPIO_INT_EDGE | &lt;span style=&#34;color:#ae81ff&#34;&gt;\&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;ninja: build stopped: subcommand failed.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Swift compiler is chocking on the &lt;code&gt;GPIO_INT_EDGE_TO_ACTIVE&lt;/code&gt; macro, let&amp;rsquo;s check its definition.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/** Configures GPIO interrupt to be triggered on pin state change to logical&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * level 1 and enables it.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define GPIO_INT_EDGE_TO_ACTIVE        (GPIO_INT_ENABLE | \&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;GPIO_INT_LEVELS_LOGICAL | \&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;GPIO_INT_EDGE | \&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;GPIO_INT_HIGH_1)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Looking at the Swift C Interop documentation from Apple, &lt;a href=&#34;https://developer.apple.com/documentation/swift/using-imported-c-macros-in-swift&#34;&gt;Using Imported C Macros in Swift&lt;/a&gt; confirms that only simple macros are supported.&lt;/p&gt;&lt;p&gt;This macro is just defining a constant, something we can easily redo in a more Swifty way.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GpioInterrupts&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; edgeToActive = GPIO_INT_ENABLE &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_INT_LEVELS_LOGICAL &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_INT_EDGE &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_INT_HIGH_1&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and use that in our call&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_pin_interrupt_configure_dt(&amp;amp;button, GpioInterrupts.edgeToActive)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;handling-the-handler&#34;&gt;Handling the handler&lt;/h1&gt;&lt;p&gt;The next step is about setting up the code that runs when the button is pressed.&lt;br&gt;Let&amp;rsquo;s take a look back at how this is done in the C code.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;pin_isr&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; device &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;dev, &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_callback &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;cb, &lt;span style=&#34;color:#66d9ef&#34;&gt;uint32_t&lt;/span&gt; pins) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;printk&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Button pressed&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;gpio_init_callback&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;pin_cb_data, pin_isr, &lt;span style=&#34;color:#a6e22e&#34;&gt;BIT&lt;/span&gt;(button.pin));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This code declares a function to be executed on button press and uses it in the &lt;code&gt;gpio_init_callback()&lt;/code&gt;call. Let&amp;rsquo;s look at the prototype of this function.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/**&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @brief Helper to initialize a struct gpio_callback properly&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @param callback A valid Application&amp;#39;s callback structure pointer.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @param handler A valid handler function pointer.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @param pin_mask A bit mask of relevant pins for the handler&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;gpio_init_callback&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_callback &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;callback,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;gpio_callback_handler_t&lt;/span&gt; handler,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;gpio_port_pins_t&lt;/span&gt; pin_mask)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The most interesting part for us at this stage is the &lt;code&gt;handler&lt;/code&gt;parameter, let&amp;rsquo;s look at its type.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;/**&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @typedef gpio_callback_handler_t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @brief Define the application callback handler function signature&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; *&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @param port Device struct for the GPIO device.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @param cb Original struct gpio_callback owning this handler&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * @param pins Mask of pins that triggers the callback handler&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; *&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * Note: cb pointer can be used to retrieve private data through&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * CONTAINER_OF() if original struct gpio_callback is stored in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; * another private structure.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt; */&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;void&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;gpio_callback_handler_t&lt;/span&gt;)(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; device &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;port,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_callback &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;cb,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;gpio_port_pins_t&lt;/span&gt; pins);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As, in Swift, we&amp;rsquo;ll want to define a closure to be passed to this function, let&amp;rsquo;s define a type alias similar to the C typedef.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typealias&lt;/span&gt; GpioCallbackHandler = @convention(c) (&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; port: UnsafePointer&amp;lt;device&amp;gt;?,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; callback: UnsafeMutablePointer&amp;lt;gpio_callback&amp;gt;?,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; pins: UInt32&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;) -&amp;gt; Void&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice the &lt;code&gt;@convention(c)&lt;/code&gt; attribute, indicating C function pointer calling convention.&lt;br&gt;Also notice that the &lt;code&gt;const&lt;/code&gt;keyword in C results in the usage of an &lt;code&gt;UnsafePointer&lt;/code&gt; vs an &lt;code&gt;UnsafeMutablePointer&lt;/code&gt; when it&amp;rsquo;s not present.&lt;br&gt;Finally, notice the usage of optionals, as nothing in C ensures that those parameters cannot be NULL.&lt;/p&gt;&lt;p&gt;With that in place, we can define our closure and call the init function.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; btnHandler: GpioCallbackHandler? = { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Button pressed&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; pin_cb_data = gpio_callback()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_init_callback(&amp;amp;pin_cb_data, btnHandler, BIT(button.pin))&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However this code fails to build, we&amp;rsquo;re facing another macro issue.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;…/EmbeddedSwift-nRF52-Examples/Button/Main.swift:54:50: error: cannot find &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;BIT&amp;#39;&lt;/span&gt; in scope&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;52&lt;/span&gt; |     var pin_cb_data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; gpio_callback&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;53&lt;/span&gt; | &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;54&lt;/span&gt; |     gpio_init_callback&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;&amp;amp;pin_cb_data, btnHandler, BIT&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;button.pin&lt;span style=&#34;color:#f92672&#34;&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   |                                                  &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;- error: cannot find &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;BIT&amp;#39;&lt;/span&gt; in scope&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;55&lt;/span&gt; | &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;56&lt;/span&gt; |     &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; true &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/opt/nordic/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:44:9: note: macro &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;BIT&amp;#39;&lt;/span&gt; unavailable: &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; like macros not supported&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;42&lt;/span&gt; |  * assembly language&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;43&lt;/span&gt; |  */&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;44&lt;/span&gt; | &lt;span style=&#34;color:#75715e&#34;&gt;#define BIT(n)  (1UL &amp;lt;&amp;lt; (n))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    |         &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;- note: macro &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;BIT&amp;#39;&lt;/span&gt; unavailable: &lt;span style=&#34;color:#66d9ef&#34;&gt;function&lt;/span&gt; like macros not supported&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;45&lt;/span&gt; | &lt;span style=&#34;color:#75715e&#34;&gt;#endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;46&lt;/span&gt; | &lt;span style=&#34;color:#75715e&#34;&gt;#endif&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Similar to above, this type of macro is not supported, but as the name indicates (function-like), it can easily be replaced by a function.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;bit&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; n: UInt8) -&amp;gt; UInt32 {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  UInt32(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; n&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using that in our call fixes the issue.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_init_callback(&amp;amp;pin_cb_data, btnHandler, bit(button.pin))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And we can add the final call required for our callback configuration.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gpio_add_callback(button.port, &amp;amp;pin_cb_data)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Building and flashing this code should give you the same behaviour as before, a message printed to the console on button press.&lt;/p&gt;&lt;div class=&#34;notice warning&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;126 76.5 300 300&#34;&gt;  &lt;path d=&#34;M297.431 324.397v-34.255c0-3.245-2.344-5.95-5.358-5.95h-32.146c-3.014 0-5.358 2.705-5.358 5.95v34.255c0 3.245 2.344 5.95 5.358 5.95h32.146c3.014 0 5.358-2.705 5.358-5.95Zm-.335-67.428 3.014-82.753c0-1.081-.502-2.524-1.674-3.425-1.005-.902-2.512-1.983-4.019-1.983h-36.834c-1.507 0-3.014 1.081-4.019 1.983-1.172.901-1.674 2.704-1.674 3.786l2.846 82.392c0 2.344 2.512 4.146 5.693 4.146h30.975c3.013 0 5.525-1.803 5.692-4.146Zm-2.344-168.39L423.34 342.425c3.683 7.032 3.516 15.686-.335 22.717-3.85 7.031-10.883 11.358-18.417 11.358H147.413c-7.534 0-14.566-4.327-18.417-11.358-3.85-7.031-4.018-15.685-.335-22.716L257.248 88.578C260.93 81.188 268.13 76.5 276 76.5c7.87 0 15.069 4.688 18.752 12.08Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Warning&lt;/p&gt;&lt;p&gt;The call back is in fact an ISR (Interrupt Service Routine) and there are several constraints and best practices on the code that should be executed in an ISR. First and foremost to keep it fast.&lt;br&gt;Printing from an ISR is not advised and is used here for demonstration purposes.&lt;/p&gt;&lt;/div&gt;&lt;h1 id=&#34;tidying-up&#34;&gt;Tidying up&lt;/h1&gt;&lt;p&gt;During prototyping, we wrote all our code within the &lt;code&gt;main&lt;/code&gt; function.&lt;br&gt;Now that we have working code, let&amp;rsquo;s encapsulate that in a dedicated struct.&lt;br&gt;The initializer allows to configure the pin the button is connected to and the closure to execute on button press.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Button&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; btnHandler: GpioCallbackHandler&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; pin_cb_data = gpio_callback()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;, btnHandler: GpioCallbackHandler) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.gpio = gpio&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.btnHandler = btnHandler&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; gpio_is_ready_dt(gpio) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; ret = gpio_pin_configure_dt(gpio, GPIO_INPUT)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; ret == &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_pin_interrupt_configure_dt(gpio, GpioInterrupts.edgeToActive)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_init_callback(&amp;amp;pin_cb_data, &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.btnHandler, bit(gpio.pointee.pin))&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_add_callback(gpio.pointee.port, &amp;amp;pin_cb_data)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The closure being the last parameter, we can use a trailing closure at the calling site.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; myButton = Button(gpio: &amp;amp;button) { &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Button pressed&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This builds and can be flashed to the board, but nothing happens anymore when pressing the button!&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;In this post, we have seen how to work with a button (or more generally a digital input) in Swift code.&lt;/p&gt;&lt;p&gt;However, we&amp;rsquo;re left on a bitter note, as our try to encapsulate our logic in a reusable Swift type results in non-working code. In the next post, we&amp;rsquo;ll look at why this is and ways to fix it.&lt;/p&gt;&lt;p&gt;If that cliffhanger is too much for you, ping me on social media and I&amp;rsquo;ll give you a hint as to how to solve this.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Controlling an LED using Embedded Swift on nRF52</title>
       <link>https://https://ericbariaux.statichost.page//posts/led_embedded_swift_nrf52/</link>
       <pubDate>Sat, 14 Sep 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/led_embedded_swift_nrf52/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;In my previous post, &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/nrfx-blink-step-by-step/&#34;&gt;nrfx-blink Step by Step&lt;/a&gt;, I took you through the steps required to configure your development environment to build and flash the &amp;ldquo;Blinky&amp;rdquo; Embedded Swift example from Apple on an nRF52840 DK. In this post, we’ll explore that example more deeply,  grow from there, and adapt it to be more natural for Swift developers.&lt;/p&gt;&lt;p&gt;If you want to follow along, the code is available on &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Examples&#34;&gt;GitHub&lt;/a&gt; with each step having its own commit.&lt;/p&gt;&lt;h1 id=&#34;exploring-the-apple-provided-project&#34;&gt;Exploring the Apple provided project&lt;/h1&gt;&lt;p&gt;Let&amp;rsquo;s open the project in VS Code and explore its content.&lt;style type=&#34;text/css&#34;&gt;         .notice {        --title-color: #fff;        --title-background-color: #6be;        --content-color: #444;        --content-background-color: #e7f2fa;    }    .notice.info {        --title-background-color: #fb7;        --content-background-color: #fec;    }    .notice.tip {        --title-background-color: #5a5;        --content-background-color: #efe;    }    .notice.warning {        --title-background-color: #c33;        --content-background-color: #fee;    }         @media (prefers-color-scheme:dark) {        .notice {            --title-color: #fff;            --title-background-color: #069;            --content-color: #ddd;            --content-background-color: #023;        }        .notice.info {            --title-background-color: #a50;            --content-background-color: #420;        }        .notice.tip {            --title-background-color: #363;            --content-background-color: #121;        }        .notice.warning {            --title-background-color: #800;            --content-background-color: #400;        }    }    body.dark .notice {        --title-color: #fff;        --title-background-color: #069;        --content-color: #ddd;        --content-background-color: #023;    }    body.dark .notice.info {        --title-background-color: #a50;        --content-background-color: #420;    }    body.dark .notice.tip {        --title-background-color: #363;        --content-background-color: #121;    }    body.dark .notice.warning {        --title-background-color: #800;        --content-background-color: #400;    }         .notice {        padding: 18px;        line-height: 24px;        margin-bottom: 24px;        border-radius: 4px;        color: var(--content-color);        background: var(--content-background-color);    }    .notice p:last-child {        margin-bottom: 0    }         .notice-title {        margin: -18px -18px 12px;        padding: 4px 18px;        border-radius: 4px 4px 0 0;        font-weight: 700;        color: var(--title-color);        background: var(--title-background-color);    }         .icon-notice {        display: inline-flex;        align-self: center;        margin-right: 8px;    }    .icon-notice img,    .icon-notice svg {        height: 1em;        width: 1em;        fill: currentColor;    }    .icon-notice img,    .icon-notice.baseline svg {        top: .125em;        position: relative;    }&lt;/style&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;For instructions on how to work with Embedded Swift projects in VS Code, see my previous post &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/nrfx-blink-step-by-step/&#34;&gt;nrfx-blink Step by Step&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/LEDnRF/nrfx-blink-VSCode.png&#34;    alt=&#34;The nrfx-blink example project opened in VS Code&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The nrfx-blink example project opened in VS Code&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Let&amp;rsquo;s start by looking at the (start of the) CMakeLists.txt file.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Cmake&#34; data-lang=&#34;Cmake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cmake_minimum_required(&lt;span style=&#34;color:#e6db74&#34;&gt;VERSION&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;3.29&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;find_package(&lt;span style=&#34;color:#e6db74&#34;&gt;Zephyr&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;REQUIRED&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;HINTS&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;$ENV{&lt;/span&gt;ZEPHYR_BASE&lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Use the armv7em-none-none-eabi target triple for Swift&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;set(&lt;span style=&#34;color:#e6db74&#34;&gt;CMAKE_Swift_COMPILER_TARGET&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;armv7em-none-none-eabi&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Enable &amp;#34;wmo&amp;#34; as needed by Embedded Swift&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;set(&lt;span style=&#34;color:#e6db74&#34;&gt;CMAKE_Swift_COMPILATION_MODE&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;wholemodule&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# FIXME: Skip checking if the compiler works&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;set(&lt;span style=&#34;color:#e6db74&#34;&gt;CMAKE_Swift_COMPILER_WORKS&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;true&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Create a new project called &amp;#34;blinky&amp;#34; and enable &amp;#34;Swift&amp;#34; as a supported language&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;project(&lt;span style=&#34;color:#e6db74&#34;&gt;blinky&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;Swift&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Set global Swift compiler flags&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;add_compile_options(&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Enable Embedded Swift&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;$&amp;lt;$&amp;lt;COMPILE_LANGUAGE:Swift&amp;gt;:SHELL:-enable-experimental-feature Embedded&amp;gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is the configuration file for the CMake tool, which is some form of meta-build tool used by nRF Connect SDK projects. Based on the above file, it&amp;rsquo;ll generate the configuration for the final build tool, in this case Ninja.&lt;/p&gt;&lt;p&gt;From the extract above, you can notice some key configuration options related to Swift usage.`&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-CMake&#34; data-lang=&#34;CMake&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cmake_minimum_required(&lt;span style=&#34;color:#e6db74&#34;&gt;VERSION&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;3.29&lt;/span&gt;)&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This indicates the minimum version required for this build. Note that this is a higher version than the one included in the nRF Connect SDK toolchain (at least the current 2.7.0 version).&lt;/p&gt;&lt;p&gt;We then see a series of instructions related to Swift compilation, like enabling Swift support and setting compiler flags. Look at the comments in the CMakeFiles.txt file for more information.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s now take a look at the Swift source code.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Note: &amp;amp; in Swift is not the &amp;#34;address of&amp;#34; operator, but on a global variable declared in C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// it will give the correct address of the global.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_pin_configure_dt(&amp;amp;led0, GPIO_OUTPUT &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_OUTPUT_INIT_HIGH &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_OUTPUT_INIT_LOGICAL)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      gpio_pin_toggle_dt(&amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While this may look like standard Swift code, there are calls to functions like &lt;code&gt;gpio_pin_configure_dt&lt;/code&gt; and references to &lt;code&gt;&amp;amp;led0&lt;/code&gt;and &lt;code&gt;GPIO_OUTPUT&lt;/code&gt;, where do these from from ?&lt;/p&gt;&lt;p&gt;To get some idea about that, let&amp;rsquo;s look at the BridgingHeader.h file.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;autoconf.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;zephyr/kernel.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;zephyr/drivers/gpio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define LED0_NODE DT_ALIAS(led0)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_dt_spec led0 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GPIO_DT_SPEC_GET&lt;/span&gt;(LED0_NODE, gpios);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a standard C header file that&amp;rsquo;s used to expose C functions (or C code in general) to Swift. If you look in CMakeLists.txt, you&amp;rsquo;ll see the &lt;code&gt;-import-bridging-header&lt;/code&gt; flag referencing this file being passed to the Swift compiler.&lt;/p&gt;&lt;p&gt;In the header file above, we can see we&amp;rsquo;re importing the headers for the Zephyr SDK (on which nRF Connect SDK is based) and we&amp;rsquo;re declaring a static variable &lt;code&gt;led0&lt;/code&gt; (with the help of the macros provided by the SDK).&lt;/p&gt;&lt;p&gt;We can use those C constructs in our Swift code thanks to the Swift C Interop, which is part of the language since day one. You can find more information about this in &lt;a href=&#34;https://developer.apple.com/documentation/swift/c-interoperability&#34;&gt;C Interoperability&lt;/a&gt; , in the Apple Developer Documentation.&lt;/p&gt;&lt;p&gt;Taking another look at our main function, it doesn&amp;rsquo;t feel very &amp;ldquo;Swifty&amp;rdquo;, in fact it&amp;rsquo;s mostly glue code around C calls.&lt;/p&gt;&lt;h1 id=&#34;creating-a-basic-struct&#34;&gt;Creating a basic struct&lt;/h1&gt;&lt;p&gt;To make the code more &amp;ldquo;Swifty&amp;rdquo; and abstract the C-level details, let&amp;rsquo;s create a &lt;code&gt;Led&lt;/code&gt; struct that isolates the C calls and provides a clean Swift interface to its caller.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Led&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Note: &amp;amp; in Swift is not the &amp;#34;address of&amp;#34; operator, but on a global variable declared in C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// it will give the correct address of the global.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_pin_configure_dt(&amp;amp;led0, GPIO_OUTPUT &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_OUTPUT_INIT_HIGH &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_OUTPUT_INIT_LOGICAL)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;toggle&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     gpio_pin_toggle_dt(&amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With that in place, our main function reads much more like typical Swift code, instantiating a struct and calling a method on it.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; led = Led()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      led.toggle()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;making-it-configurable&#34;&gt;Making it configurable&lt;/h1&gt;&lt;p&gt;This version however, hardcodes the GPIO pin that is used to drive the LED. That doesn&amp;rsquo;t make for re-usable code.&lt;br&gt;To make it configurable, we need to pass the GPIO pin driving the LED to our struct initializer.&lt;/p&gt;&lt;p&gt;Looking back at the declaration of the &lt;code&gt;led0&lt;/code&gt; variable&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; gpio_dt_spec led0 &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GPIO_DT_SPEC_GET&lt;/span&gt;(LED0_NODE, gpios);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and the way it&amp;rsquo;s used in the calls&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gpio_pin_toggle_dt(&amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;we see we&amp;rsquo;re using a C pointer to a C struct.&lt;/p&gt;&lt;p&gt;The &lt;a href=&#34;https://developer.apple.com/documentation/swift/calling-functions-with-pointer-parameters&#34;&gt;Calling Functions With Pointer Parameters&lt;/a&gt; page of the Apple Developer Documentation gives some explanations on the topic and points to using UnsafePointer, as shown in the code below.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Led&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;.gpio = gpio&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// Note: &amp;amp; in Swift is not the &amp;#34;address of&amp;#34; operator, but on a global variable declared in C&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// it will give the correct address of the global.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gpio_pin_configure_dt(gpio, GPIO_OUTPUT &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_OUTPUT_INIT_HIGH &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; GPIO_OUTPUT_INIT_LOGICAL)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;toggle&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     gpio_pin_toggle_dt(gpio)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And in our main function, we can just initialize our struct using&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; led = Led(gpio: &amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We now have a re-usable struct that can be used to control an LED connected to any of the  GPIO of the system.&lt;/p&gt;&lt;h1 id=&#34;handling-errors&#34;&gt;Handling errors&lt;/h1&gt;&lt;p&gt;When following the &lt;a href=&#34;https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-2-reading-buttons-and-controlling-leds/topic/gpio-generic-api/&#34;&gt;nRF Connect SDK Fundamentals&lt;/a&gt; training from the Nordic Developer Academy, one can read that &amp;ldquo;before using the device pointer contained in gpio_dt_spec, we need to check if it’s ready using gpio_is_ready_dt()&amp;rdquo;.&lt;/p&gt;&lt;p&gt;Let&amp;rsquo;s create an error to represent that condition&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LedError&lt;/span&gt;: Error {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;case&lt;/span&gt; notReady&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and perform the test in our initializer, making it throwing&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Led&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;throws&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;gpio_is_ready_dt(gpio)) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; LedError.notReady&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For now, we&amp;rsquo;ll just ignore the thrown error&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; led = &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt;? Led(gpio: &amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; led {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        led.toggle()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;As you can see above, throwing initializers are nice as you can also use them as failable initializers if you&amp;rsquo;re not interested in the exact error that occurred.&lt;/p&gt;&lt;/div&gt;&lt;p&gt;And the build fails !&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;…/EmbeddedSwift-nRF52-Examples/LED/Main.swift:30:22: error: cannot use a value of protocol type &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;any Error&amp;#39;&lt;/span&gt; in embedded Swift&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt; | //&lt;span style=&#34;color:#f92672&#34;&gt;===&lt;/span&gt;----------------------------------------------------------------------&lt;span style=&#34;color:#f92672&#34;&gt;===&lt;/span&gt;//&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;11&lt;/span&gt; | &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;12&lt;/span&gt; | @main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   | &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;- note: called from here&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;13&lt;/span&gt; | struct Main &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;14&lt;/span&gt; |   static func main&lt;span style=&#34;color:#f92672&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;15&lt;/span&gt; |     let led &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; try? Led&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gpio: &amp;amp;led0&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   |                    &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;- note: called from here&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;16&lt;/span&gt; |     &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; true &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;17&lt;/span&gt; |       &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; let led &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   :&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;28&lt;/span&gt; |   init&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;&lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; throws &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;29&lt;/span&gt; |     &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;!gpio_is_ready_dt&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt;gpio&lt;span style=&#34;color:#f92672&#34;&gt;))&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt; |       throw LedError.notReady&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   |                      &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;- error: cannot use a value of protocol type &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;any Error&amp;#39;&lt;/span&gt; in embedded Swift&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;31&lt;/span&gt; |     &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;32&lt;/span&gt; | &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ninja: build stopped: subcommand failed.&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FATAL ERROR: command exited with status 1: /opt/nordic/ncs/toolchains/f8037e9b83/bin/cmake --build …/EmbeddedSwift-nRF52-Examples/LED/build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The error mentions any Error, that is because a simple throws statement is identical to throws any Error. And that&amp;rsquo;s an existential type, which is not supported by Embedded Swift.&lt;/p&gt;&lt;p&gt;This is easily fixed by using Typed throws, introduced with Swift 6.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;init&lt;/span&gt;(gpio: UnsafePointer&amp;lt;gpio_dt_spec&amp;gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;throws&lt;/span&gt;(LedError) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#f92672&#34;&gt;!&lt;/span&gt;gpio_is_ready_dt(gpio)) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;throw&lt;/span&gt; .notReady&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;…&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As one can see above, this has the added benefit that we don&amp;rsquo;t need to specify the type at the throw site, as it&amp;rsquo;s defined in the throws declaration.&lt;/p&gt;&lt;h1 id=&#34;really-handling-errors&#34;&gt;Really handling errors&lt;/h1&gt;&lt;p&gt;In the code above, we&amp;rsquo;ve just ignored the thrown error, let&amp;rsquo;s now catch it and print an error message in case of error.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@main&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Main&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; led = &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; Led(gpio: &amp;amp;led0)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        led.toggle()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        k_msleep(&lt;span style=&#34;color:#ae81ff&#34;&gt;100&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#66d9ef&#34;&gt;catch&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Could not initialize LED&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the build fails again !&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;3/7&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt; Linking C executable zephyr/zephyr_pre0.elf&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FAILED: zephyr/zephyr_pre0.elf zephyr/zephyr_pre0.map …/EmbeddedSwift-nRF52-Examples/LED/build/zephyr/zephyr_pre0.map &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ccache /opt/nordic/ncs/toolchains/f8037e9b83/opt/zephyr-sdk/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc  -gdwarf-4 zephyr/CMakeFiles/zephyr_pre0.dir/misc/empty_file.c.obj -o zephyr/zephyr_pre0.elf  zephyr/CMakeFiles/offsets.dir/./arch/arm/core/offsets/offsets.c.obj  -fuse-ld&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;bfd  -T  zephyr/linker_zephyr_pre0.cmd  -Wl,-Map&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;…/EmbeddedSwift-nRF52-Examples/LED/build/zephyr/zephyr_pre0.map  -Wl,--whole-archive  app/libapp.a  zephyr/libzephyr.a  zephyr/arch/common/libarch__common.a  zephyr/arch/arch/arm/core/libarch__arm__core.a  zephyr/arch/arch/arm/core/cortex_m/libarch__arm__core__cortex_m.a  zephyr/arch/arch/arm/core/mpu/libarch__arm__core__mpu.a  zephyr/lib/libc/picolibc/liblib__libc__picolibc.a  zephyr/lib/libc/common/liblib__libc__common.a  zephyr/soc/soc/nrf52840/libsoc__nordic.a  zephyr/drivers/clock_control/libdrivers__clock_control.a  zephyr/drivers/console/libdrivers__console.a  zephyr/drivers/gpio/libdrivers__gpio.a  zephyr/drivers/pinctrl/libdrivers__pinctrl.a  zephyr/drivers/serial/libdrivers__serial.a  zephyr/drivers/timer/libdrivers__timer.a  modules/nrf/drivers/hw_cc3xx/lib..__nrf__drivers__hw_cc3xx.a  modules/hal_nordic/nrfx/libmodules__hal_nordic__nrfx.a  modules/segger/libmodules__segger.a  -Wl,--no-whole-archive  zephyr/kernel/libkernel.a  -L&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/opt/nordic/ncs/toolchains/f8037e9b83/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/thumb/v7e-m/nofp&amp;#34;&lt;/span&gt;  -L…/EmbeddedSwift-nRF52-Examples/LED/build/zephyr  -lgcc  zephyr/arch/common/libisr_tables.a  -mcpu&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;cortex-m4  -mthumb  -mabi&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;aapcs  -mfp16-format&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;ieee  -mtp&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;soft  -Wl,--gc-sections  -Wl,--build-id&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;none  -Wl,--sort-common&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;descending  -Wl,--sort-section&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;alignment  -Wl,-u,_OffsetAbsSyms  -Wl,-u,_ConfigAbsSyms  -nostdlib  -static  -Wl,-X  -Wl,-N  -Wl,--orphan-handling&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;warn  -Wl,-no-pie  -DPICOLIBC_LONG_LONG_PRINTF_SCANF  /opt/nordic/ncs/v2.7.0/nrfxlib/crypto/nrf_cc310_platform/lib/cortex-m4/soft-float/no-interrupts/libnrf_cc310_platform_0.9.19.a  --specs&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;picolibc.specs  -lc  -lgcc &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; cd …/EmbeddedSwift-nRF52-Examples/LED/build/zephyr &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; /opt/homebrew/Cellar/cmake/3.30.2/bin/cmake -E true&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/opt/nordic/ncs/toolchains/f8037e9b83/opt/zephyr-sdk/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/12.2.0/../../../../arm-zephyr-eabi/bin/ld.bfd: warning: orphan section &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;.swift_modhash&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39; from `app/libapp.a(Main.swift.obj)&amp;#39;&lt;/span&gt; being placed in section &lt;span style=&#34;color:#e6db74&#34;&gt;`&lt;/span&gt;.swift_modhash&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;collect2: error: ld returned &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; exit status&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ninja: build stopped: subcommand failed.&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;FATAL ERROR: command exited with status 1: /opt/nordic/ncs/toolchains/f8037e9b83/bin/cmake --build …/EmbeddedSwift-nRF52-Examples/LED/build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This time however, the error is not coming from the Swift compiler but from a later phase in the process, and it&amp;rsquo;s the linker that&amp;rsquo;s complaining, with a very explicit &amp;ldquo;ld returned 1&amp;rdquo; error message.&lt;/p&gt;&lt;p&gt;At this point I was very puzzled and this got me into a rabbit hole of trying to understand more about the build system and how to get more verbose information; the different stages of the build process with compilers, linkers, linker scripts, sections… and many more low-level aspects.&lt;br&gt;I grew my general understanding but could not find the solution.&lt;/p&gt;&lt;p&gt;Then one day, I checked again the &lt;a href=&#34;https://github.com/apple/swift-embedded-examples&#34;&gt;swift-embedded-examples&lt;/a&gt; repository from Apple and saw that Kuba Mracek, the engineer that presented the &lt;a href=&#34;https://developer.apple.com/videos/play/wwdc2024/10197/?time=7&#34;&gt;Embedded Swift session&lt;/a&gt; during &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/wwdc2024/&#34;&gt;WWDC 2024&lt;/a&gt;), had made a &lt;a href=&#34;https://github.com/apple/swift-embedded-examples/commit/9fa675115d412132f944fea9c9f392ead0b50f21&#34;&gt;commit&lt;/a&gt; on the project.&lt;/p&gt;&lt;p&gt;I updated my project with his changes and it worked!&lt;/p&gt;&lt;p&gt;The bit of the commit that fixed the issue is&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-make&#34; data-lang=&#34;make&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Disable PIC&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;$&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;lt;&lt;/span&gt;$&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;lt;COMPILE_LANGUAGE:Swift&amp;gt;:SHELL:-Xcc -fno-pic&amp;gt;&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;pic stands for Position-Independent Code and although at a very high-level, after having read more on the topic, I think I understand why it might cause issues,  I doubt I would have found the solution by myself (in a bounded amount of time); more on this in the conclusion.&lt;/p&gt;&lt;p&gt;Anyway, with that in place, we can put the finishing touches and handle all potential errors thrown by the C code. You&amp;rsquo;ll find that implementation in the example code on &lt;a href=&#34;https://github.com/nelcea/EmbeddedSwift-nRF52-Examples&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;In this post, I have shown how, starting from Apple sample code, we can create a Swift struct that encapsulate an LED behaviour and make the code that uses it feel natural to Swift developers.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve shown some of the challenges I faced during that implementation and how I overcame them. Sometimes it&amp;rsquo;s about learning more on topics that are less common to typical iOS or macOS development. Sometimes it took persistence and some fortunate timing to find the right solution; but don&amp;rsquo;t be too stubborn (like I sometime was) and reach out for help. &lt;br&gt;Embedded Swift is still in its infancy, I would encourage you to check the &lt;a href=&#34;https://forums.swift.org/c/development/embedded/107/l/latest&#34;&gt;Embedded topics&lt;/a&gt; on the swift.org forums or the blogs and projects from the community.&lt;/p&gt;&lt;p&gt;Now that we’ve encapsulated an LED, the next step is adding some interactivity. In the next post of this series, we’ll explore how to make button code more Swift-friendly.&lt;/p&gt;&lt;figure class=&#34;small&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/LEDnRF/Button.png&#34;    alt=&#34;A push button: our next challenge&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Our next challenge&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;</description>
     </item>
   
     <item>
       <title>nrfx-blink Step by Step</title>
       <link>https://https://ericbariaux.statichost.page//posts/nrfx-blink-step-by-step/</link>
       <pubDate>Wed, 04 Sep 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/nrfx-blink-step-by-step/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;When getting started with Embedded Swift, the examples published by Apple are really an incredible resource. However they&amp;rsquo;re just that —  examples, right to the point and sometimes with minimal information. If you&amp;rsquo;re new to embedded development, you&amp;rsquo;ll need to do some additional digging (which isn&amp;rsquo;t too bad, that&amp;rsquo;s how you learn).&lt;/p&gt;&lt;p&gt;Embedded Swift development is very specific to the chipset that you&amp;rsquo;re targeting. As you can see, there are several examples in the repository, targeted at different boards and using different options (bare metal vs SDK/RTOS).&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve been mostly using the nRF52840 chip and in this post, I&amp;rsquo;ll be using an nRF52840 DK board, programming it using the nRF Connect SDK, which is based on the Zephyr RTOS project.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/nRF52840DK.png&#34;    alt=&#34;Nordic Semiconductor nRF52840 DK&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Nordic Semiconductor nRF52840 DK&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;This is the same board that the &lt;a href=&#34;https://github.com/apple/swift-embedded-examples/tree/main/nrfx-blink-sdk&#34;&gt;swift-embedded-examples/nrfx-blink-sdk&lt;/a&gt; example from Apple is using. The README file for that example mentions the pre-requisites to run the example, directly using Zephyr and the commands to use in a terminal to get the example running on your board.This works, and is a worthwhile test, but I don&amp;rsquo;t find it a viable way to proceed further with development.&lt;/p&gt;&lt;p&gt;I wanted to have the same experience in Swift that I had when developing in C with the nRF Connect SDK. That means working in an IDE (VS Code) with syntax highlighting, code completion, documentation… and a simple one-click build-and-flash mechanism.&lt;/p&gt;&lt;p&gt;In this post, I&amp;rsquo;ll walk you through the detailed steps to get there.&lt;/p&gt;&lt;h1 id=&#34;pre-requisites&#34;&gt;Pre-requisites&lt;/h1&gt;&lt;p&gt;If you don&amp;rsquo;t have Xcode installed on your machine, start there. This will make sure Git is available (which is required by some components during the installation) and that you&amp;rsquo;ll be able to select the proper toolchain for Embedded Swift compilation.Also, just launch Xcode at least once to ensure all extra components are installed and you automatically accept the license agreement.&lt;/p&gt;&lt;p&gt;For this post, I worked on macOS Sonoma, using Xcode 15.4&lt;/p&gt;&lt;h1 id=&#34;installing-the-native-toolchain&#34;&gt;Installing the native toolchain&lt;/h1&gt;&lt;p&gt;Instead of installing the Zephyr SDK as suggested in the example, I&amp;rsquo;ll be working from the nRF Connect SDK, which is Nordic Semiconductor&amp;rsquo;s take on Zephyr and makes working with their board slightly easier.&lt;/p&gt;&lt;p&gt;They have a &lt;a href=&#34;https://youtu.be/EAJdOqsL9m8?list=PLx_tBuQ_KSqEt7NK-H7Lu78lT2OijwIMl&#34;&gt;video tutorial&lt;/a&gt; for that, but I&amp;rsquo;ll go through all the steps here.&lt;/p&gt;&lt;h3 id=&#34;nrf-command-line-tools&#34;&gt;nRF Command Line Tools&lt;/h3&gt;&lt;p&gt;Start by installing the nRF Command Line Tools, which you can download from &lt;a href=&#34;https://www.nordicsemi.com/Products/Development-tools/nRF-Command-Line-Tools/Download?lang=en#infotabs&#34;&gt;the Nordic Semiconductor site&lt;/a&gt;.Scroll down to the &lt;em&gt;Downloads&lt;/em&gt; section, select your platform (macOS in this case) and download the installer.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/nRFCommandLineInstaller.png&#34;    alt=&#34;nRF Command Line Tools installer disk image&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;nRF Command Line Tools installer disk image&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Launch the &lt;em&gt;Install nRF Tools&lt;/em&gt; installer and proceed, keeping the proposed options.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/nRFCommandLineInstallOptions.png&#34;    alt=&#34;nRF Command Line Tools installer options&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;nRF Command Line Tools installer options&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;h3 id=&#34;j-link-software&#34;&gt;J-Link software&lt;/h3&gt;&lt;p&gt;In addition to the command line tools, the installer disk image also contains a version of the J-Link software from SEGGER. This is an older version and I prefer downloading a more recent one directly from the SEGGER website at &lt;a href=&#34;https://www.segger.com/downloads/jlink/&#34;&gt;SEGGER - The Embedded Experts - Downloads - J-Link / J-Trace&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/JLinkDownload.png&#34;    alt=&#34;SEGGER J-Link Software download&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;SEGGER J-Link Software download&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Select that latest version (with the same major version as the one bundled with the nRF tools, V7 at this time) and download the appropriate version for your OS.&lt;br&gt;The site displays the checksum for the download. It&amp;rsquo;s always a good idea to verify it.&lt;/p&gt;&lt;p&gt;This command achieves this in one go&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;diff -s &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt; printf &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;%s\n&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;9161779d712d22341117a905901c0b12&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;(&lt;/span&gt; md5 -q - JLink_MacOSX_V798e_arm64.pkg &lt;span style=&#34;color:#f92672&#34;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once the signature checks out OK, proceed with the installation of the downloaded package.&lt;/p&gt;&lt;h3 id=&#34;vs-code-and-nrf-connect-sdk-extension&#34;&gt;VS Code and nRF Connect SDK extension&lt;/h3&gt;&lt;p&gt;The next step is to install VS Code, download it from &lt;a href=&#34;https://code.visualstudio.com/download&#34;&gt;Download Visual Studio Code - Mac, Linux, Windows&lt;/a&gt;, extract the downloaded zip and move that to the /Applications folder.&lt;/p&gt;&lt;p&gt;Launch it, select the &lt;em&gt;Extensions&lt;/em&gt; View from the &lt;em&gt;Activity&lt;/em&gt; Bar on the left and search for &amp;ldquo;nrf connect&amp;rdquo;. You will have multiple matches, make sure you select &amp;ldquo;nRF Connect for VS Code Extension Pack&amp;rdquo; and click &amp;ldquo;Install&amp;rdquo;.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/nRFConnectVSCodeExtension.png&#34;    alt=&#34;Install the nRF Connect for CS Code Extension Pack&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Install the nRF Connect for VS Code Extension Pack&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Once the installation is finished, new icons appear in the &lt;em&gt;Activity&lt;/em&gt; Bar, select the &lt;em&gt;nRF Connect&lt;/em&gt; View.&lt;br&gt;The only thing the view should contain at this point is an &amp;ldquo;Install Toolchain&amp;rdquo; button, click on it to proceed.&lt;br&gt;From the list that appears, select the latest version of the toolchain available.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/SelectToolchain.png&#34;    alt=&#34;Select nRF Connect SDK Toolchain to install&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Select nRF Connect SDK Toolchain to install&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Once the toolchain is installed, the view refreshes with several options. Select the &amp;ldquo;Manage SDKs&amp;rdquo; one, then &amp;ldquo;Install SDK&amp;rdquo; and select the latest stable SDK available; currently this is v2.6.1.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/SelectSDK.png&#34;    alt=&#34;Select nRF Connect SDK to install&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Select nRF Connect SDK to install&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;If you don&amp;rsquo;t have Xcode installed, this will trigger an installer for the command line developer tools, so that Git is available. Watch for the installer icon appearing in the dock and its window behind the VS Code one.&lt;/p&gt;&lt;/div&gt;&lt;div class=&#34;notice warning&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;126 76.5 300 300&#34;&gt;  &lt;path d=&#34;M297.431 324.397v-34.255c0-3.245-2.344-5.95-5.358-5.95h-32.146c-3.014 0-5.358 2.705-5.358 5.95v34.255c0 3.245 2.344 5.95 5.358 5.95h32.146c3.014 0 5.358-2.705 5.358-5.95Zm-.335-67.428 3.014-82.753c0-1.081-.502-2.524-1.674-3.425-1.005-.902-2.512-1.983-4.019-1.983h-36.834c-1.507 0-3.014 1.081-4.019 1.983-1.172.901-1.674 2.704-1.674 3.786l2.846 82.392c0 2.344 2.512 4.146 5.693 4.146h30.975c3.013 0 5.525-1.803 5.692-4.146Zm-2.344-168.39L423.34 342.425c3.683 7.032 3.516 15.686-.335 22.717-3.85 7.031-10.883 11.358-18.417 11.358H147.413c-7.534 0-14.566-4.327-18.417-11.358-3.85-7.031-4.018-15.685-.335-22.716L257.248 88.578C260.93 81.188 268.13 76.5 276 76.5c7.87 0 15.069 4.688 18.752 12.08Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Warning&lt;/p&gt;&lt;p&gt;I have sometimes seen the installation trigger a Git error and getting stuck at this point.&lt;/p&gt;&lt;p&gt;It that happens to you, cancel the installation and quit VSCode.&lt;br&gt;Open a terminal window and execute the following commands (this cleans the folder with a partial bogus installation. Adapt the folder name based on the SDK version you tried to install).&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cd /opt/nordic/ncs&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -rf v2.6.1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then enter this command, it&amp;rsquo;ll fix the Git issue encountered before&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git config --global http.postBuffer &lt;span style=&#34;color:#ae81ff&#34;&gt;157286400&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Re-launch VS Code and re-start the SDK installation, this time it should go through.&lt;/p&gt;&lt;/div&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/GitErrorDuringSDKInstallation.png&#34;    alt=&#34;Git error during nRF Connect SDK installation&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Git error during nRF Connect SDK installation&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;An alternative method to install the nRF Connect SDK is to first install the &lt;a href=&#34;https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop&#34;&gt;nRF Connect for Desktop&lt;/a&gt; application, then install the Toolchain Manager, then install the SDK from there.&lt;br&gt;Using that method, I have not encountered the Git error mentioned above.&lt;/p&gt;&lt;/div&gt;&lt;p&gt;With these steps, we&amp;rsquo;re done installing the nRF Connect tools and SDK.&lt;/p&gt;&lt;h1 id=&#34;installing-the-swift-snapshot-toolchain&#34;&gt;Installing the Swift snapshot toolchain&lt;/h1&gt;&lt;p&gt;Embedded Swift requires a recent snapshot version of the Swift toolchain, which can be found at &lt;a href=&#34;https://www.swift.org/download/#snapshots&#34;&gt;Swift.org - Download Swift&lt;/a&gt;. Download the package and install it.&lt;/p&gt;&lt;p&gt;After installation, perform a quick check; in a terminal, run&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swift --version&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should display the standard swift version bundle with your installed Xcode, that would be 5.10 for Xcode 15.4&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ls -l /Library/Developer/Toolchains&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;should list all the available toolchains, including the one you just installed. Running&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plutil -extract CFBundleIdentifier raw /Library/Developer/Toolchains/swift-latest.xctoolchain/Info.plist&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;provides you with the ID of the latest installed toolchain; which you can use in your export statement, such as in&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export TOOLCHAINS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;org.swift.61202408261a&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;swiftc --version&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;should now reference the Swift version you just installed.&lt;/p&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;For more information on installing and selecting a Swift toolchain, as well as potential gotchas, check out the great &lt;a href=&#34;https://oleb.net/2024/swift-toolchains/&#34;&gt;Building with nightly Swift toolchains on macOS&lt;/a&gt; post  by Ole Begemann.&lt;/p&gt;&lt;/div&gt;&lt;h1 id=&#34;installing-cmake&#34;&gt;Installing Cmake&lt;/h1&gt;&lt;p&gt;The nRF Connect toolchain installed via VS Code includes Cmake, but it&amp;rsquo;s currently an older version, one that does not support Swift.&lt;/p&gt;&lt;p&gt;You&amp;rsquo;ll need to install a newer version, which I found most easily done via Homebrew.&lt;/p&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;If you don&amp;rsquo;t have Homebrew installed yet, head over to &lt;a href=&#34;https://brew.sh/&#34;&gt;Homebrew — The Missing Package Manager for macOS (or Linux)&lt;/a&gt; and follow the instructions.&lt;/p&gt;&lt;/div&gt;&lt;p&gt;From a terminal, simply run&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;brew install cmake&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and you should be good.&lt;/p&gt;&lt;h1 id=&#34;build-the-blinky-example-via-the-terminal&#34;&gt;Build the blinky example via the terminal&lt;/h1&gt;&lt;p&gt;Let&amp;rsquo;s verify that we can build an Embedded Swift program using the Apple provided examples.&lt;br&gt;Clone the repository from &lt;a href=&#34;https://github.com/apple/swift-embedded-examples/tree/main&#34;&gt;apple/swift-embedded-examples: A collection of example projects using Embedded Swift&lt;/a&gt;&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git clone https://github.com/apple/swift-embedded-examples.git&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Go into the  nrfx-blink-sdk folder and run&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;export TOOLCHAINS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;org.swift.61202408261a&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cmake -B build -G Ninja -DBOARD&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;nrf52840dk_nrf52840 -DUSE_CCACHE&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; .&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cmake --build build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;to build the example.&lt;/p&gt;&lt;p&gt;That should return a success. Now clean-up the build folder as we&amp;rsquo;ll re-create it from within VS Code&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -rf build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;in-vs-code&#34;&gt;In VS Code&lt;/h1&gt;&lt;p&gt;From the menu, select &amp;ldquo;File&amp;rdquo; -&amp;gt; &amp;ldquo;Open Folder…&amp;rdquo; and select the nrfx-blink-sdk folder. Open the &lt;em&gt;nRF Connect&lt;/em&gt; View from the &lt;em&gt;Activity&lt;/em&gt; Ba* and under &lt;em&gt;Appllications&lt;/em&gt;, click on &amp;ldquo;Add build configuration&amp;rdquo;.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/AddBuildConfiguration.png&#34;     alt=&#34;Add a build configuration to the nrfx-blink-sdk project&#34;&gt;&lt;figcaption&gt;       &lt;p&gt;Add a build configuration to the nrfx-blink-sdk project&lt;/p&gt;     &lt;/figcaption&gt; &lt;/figure&gt;&lt;p&gt;The correct board (nrf52840dk_nrf52840) is already selected by default (adapt if you&amp;rsquo;re using a different board). Scroll down and click on &amp;ldquo;Build Configuration&amp;rdquo;.&lt;/p&gt;&lt;p&gt;This will fail, reporting an insufficient version of CMake. As mentioned above, the version included in the nRF toolchain is outdated and we need to use a newer one.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/IncorrectCMakeVersionError.png&#34;    alt=&#34;Build error caused by incorrect CMake version&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Build error caused by incorrect CMake version&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;As I did not find a way in VS Code / nRF Connect extension to specify the CMake version to use, I reverted to changing the CMake version within the nRF toolchain using a symbolic link, using the following commands (you will need to adapt paths if you don&amp;rsquo;t have the exact same versions as I do)&lt;/p&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;cd /opt/nordic/ncs/toolchains/f8037e9b83/Cellar/cmakemv 3.21.0 3.21.0.originalln -s /opt/homebrew/Cellar/cmake/3.30.2 3.21.0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Delete the build folder (this can be done from the &lt;em&gt;Explorer&lt;/em&gt; view within VS Code) and re-add the build configuration. It still fails, but with a different error.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/IncorrectSwiftVersionError.png&#34;    alt=&#34;Build error caused by incorrect version of the Swift toolchain&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Build error caused by incorrect version of the Swift toolchain&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;The unknown argument &amp;lsquo;-import-bridging-header&amp;rsquo; error is caused by the wrong version of the Swift toolchain being used. We need to use the same &amp;ldquo;export TOOLCHAINS&amp;rdquo; as we used above in our terminal examples.&lt;/p&gt;&lt;p&gt;This time, it can be fixed with configuration.&lt;br&gt;Open &lt;em&gt;Settings&lt;/em&gt; (⌘, shortcut), make sure that &lt;em&gt;Workspace&lt;/em&gt; (under the search box) is selected to apply changes to your project only and under Extensions, select the &lt;em&gt;nRF DeviceTree&lt;/em&gt; entry. Scroll a little bit up and you&amp;rsquo;ll see a section for &lt;em&gt;West: Env&lt;/em&gt;. Click on the &amp;ldquo;Edit in settings.json&amp;rdquo; button.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/WestEnvSettings.png&#34;     alt=&#34;Access the nRF Connect settings within VS Code&#34;&gt;&lt;figcaption&gt;       &lt;p&gt;Access the nRF Connect settings within VS Code&lt;/p&gt;     &lt;/figcaption&gt; &lt;/figure&gt;&lt;p&gt;This opens up your settings.json file. Add the definition of the TOOLCHAINS environment variable under the &amp;ldquo;nrf-connect.west.env&amp;rdquo; key. Your settings.json file should look something like&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;nrf-connect.toolchain.path&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;${nrf-connect.toolchain:2.6.1}&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;nrf-connect.west.env&amp;#34;&lt;/span&gt;: {        &lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;$base&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;terminal&amp;#34;&lt;/span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;TOOLCHAINS&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;org.swift.61202408261a&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As above, delete the build folder, re-add the build configuration and now the build should be successful.&lt;/p&gt;&lt;p&gt;You can now use all the actions for the nRF Connect SDK extension within your Swift projects, including, if your setup supports it, flash and debug.&lt;/p&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;This is the case for the nRF52840 DK board, but it might not always be the case. For instance, with a &lt;a href=&#34;https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html&#34;&gt;Seeed Studio XIAO nRF52840 (Sense)&lt;/a&gt;, you&amp;rsquo;ll need an external debugger. See &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/xiao_nrf52840_swd/&#34;&gt;Using SWD pins on Seeed Studio XIAO nRF52840&lt;/a&gt; for instructions on how to use an nRF52840 DK as the external debugger.&lt;/p&gt;&lt;/div&gt;&lt;h1 id=&#34;working-with-swift&#34;&gt;Working with Swift&lt;/h1&gt;&lt;p&gt;We now have the nRF Connect part covered but Swift support is limited to the bare minimum. This is easily fixed by installing the Swift extension. Select the &lt;em&gt;Extensions&lt;/em&gt; View from the Activity &lt;em&gt;Bar&lt;/em&gt; on the left and search for &amp;ldquo;Swift&amp;rdquo;. Install the official extension from the Swift Server Work Group.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/SwiftExtension.png&#34;     alt=&#34;Install the Swift extension in VS Code&#34;&gt;&lt;figcaption&gt;       &lt;p&gt;Install the Swift extension in VS Code&lt;/p&gt;     &lt;/figcaption&gt; &lt;/figure&gt;&lt;p&gt;Once installed, configure the toolchain used by the Swift extension to be the same as the one used in your project. Open the &lt;em&gt;Command Palette&lt;/em&gt; (⇧⌘P), type &amp;ldquo;Swift sel&amp;rdquo; and select &amp;ldquo;Swift: Select Toolchain&amp;hellip;&amp;rdquo;. Select the toolchain matching the one you configured in your project. In the next step, select &amp;ldquo;Workspace Configuration&amp;rdquo; so the setting only applies to this project also. You&amp;rsquo;ll need to relaunch the extensions.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/SwiftExtensionSelectToolchain.png&#34;     alt=&#34;Select the proper Swift toolchain for the VS Code Swift extension&#34;&gt;&lt;figcaption&gt;       &lt;p&gt;Select the proper Swift toolchain for the VS Code Swift extension&lt;/p&gt;     &lt;/figcaption&gt; &lt;/figure&gt;&lt;p&gt;Once done, you&amp;rsquo;ll have syntax highlighting, code completion, code navigation, refactoring and then some.&lt;/p&gt;&lt;figure class=&#34;figure-window-screenshot&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/NrfxBlinkSbS/SwiftCodeCompletion.png&#34;     alt=&#34;Code completion for Swift code within VS Code&#34;&gt;&lt;figcaption&gt;       &lt;p&gt;Code completion for Swift code within VS Code&lt;/p&gt;     &lt;/figcaption&gt; &lt;/figure&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;In this post, I&amp;rsquo;ve explained the steps required to configure a proper development environment for Embedded Swift targeting boards supported by the nRF Connect SDK.&lt;/p&gt;&lt;p&gt;With that in place, you&amp;rsquo;re in a good starting position to work on your ambitious Embedded Swift projects.&lt;/p&gt;&lt;p&gt;That&amp;rsquo;s what we&amp;rsquo;ll do in an upcoming series of posts, starting from the blink example and taking it much further.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Using SWD pins on Seeed Studio XIAO nRF52840</title>
       <link>https://https://ericbariaux.statichost.page//posts/xiao_nrf52840_swd/</link>
       <pubDate>Sat, 17 Aug 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/xiao_nrf52840_swd/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;When I discovered the &lt;a href=&#34;https://github.com/BasedHardware/Omi&#34;&gt;Omi (previously Friend)&lt;/a&gt; project and wanted to build myself a device, I followed the instructions on their getting started page. For the firmware, this meant: open the project in VSCode, build, double-click reset on the nRF board, and drap-and-drop the zephyr.uf2 file into the flash drive that appeared on the computer.&lt;/p&gt;&lt;p&gt;As I wanted to make some changes to the firmware code, I wanted to improve on this process, most importantly, get feedback on what&amp;rsquo;s happening on the board, through console logs.&lt;/p&gt;&lt;p&gt;I thus started to look at how I could use the SWD pins present on the board.&lt;/p&gt;&lt;h1 id=&#34;tldr&#34;&gt;TL;DR&lt;/h1&gt;&lt;p&gt;It turns out you don&amp;rsquo;t need to do anything to get access to the console output. Simply plug your board into your computer and a new serial port should appear.Connecting to the port with a terminal application gives you access to the logs.&lt;/p&gt;&lt;p&gt;As to using those SWD pins, I did accomplish it using a &lt;a href=&#34;https://www.nordicsemi.com/Products/Development-hardware/nRF52840-DK&#34;&gt;nRF52840 DK&lt;/a&gt;, a &lt;a href=&#34;https://wiki.seeedstudio.com/Seeeduino-XIAO-Expansion-Board/&#34;&gt;Seeed Studio Expansion Board Base&lt;/a&gt; and the following cabling:&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/XIAO_SWD/FinalCabling.png&#34;    alt=&#34;Final cabling connecting J-Link debugger to XIAO board&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Final cabling connecting J-Link debugger to XIAO board&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;style type=&#34;text/css&#34;&gt;         .notice {        --title-color: #fff;        --title-background-color: #6be;        --content-color: #444;        --content-background-color: #e7f2fa;    }    .notice.info {        --title-background-color: #fb7;        --content-background-color: #fec;    }    .notice.tip {        --title-background-color: #5a5;        --content-background-color: #efe;    }    .notice.warning {        --title-background-color: #c33;        --content-background-color: #fee;    }         @media (prefers-color-scheme:dark) {        .notice {            --title-color: #fff;            --title-background-color: #069;            --content-color: #ddd;            --content-background-color: #023;        }        .notice.info {            --title-background-color: #a50;            --content-background-color: #420;        }        .notice.tip {            --title-background-color: #363;            --content-background-color: #121;        }        .notice.warning {            --title-background-color: #800;            --content-background-color: #400;        }    }    body.dark .notice {        --title-color: #fff;        --title-background-color: #069;        --content-color: #ddd;        --content-background-color: #023;    }    body.dark .notice.info {        --title-background-color: #a50;        --content-background-color: #420;    }    body.dark .notice.tip {        --title-background-color: #363;        --content-background-color: #121;    }    body.dark .notice.warning {        --title-background-color: #800;        --content-background-color: #400;    }         .notice {        padding: 18px;        line-height: 24px;        margin-bottom: 24px;        border-radius: 4px;        color: var(--content-color);        background: var(--content-background-color);    }    .notice p:last-child {        margin-bottom: 0    }         .notice-title {        margin: -18px -18px 12px;        padding: 4px 18px;        border-radius: 4px 4px 0 0;        font-weight: 700;        color: var(--title-color);        background: var(--title-background-color);    }         .icon-notice {        display: inline-flex;        align-self: center;        margin-right: 8px;    }    .icon-notice img,    .icon-notice svg {        height: 1em;        width: 1em;        fill: currentColor;    }    .icon-notice img,    .icon-notice.baseline svg {        top: .125em;        position: relative;    }&lt;/style&gt;&lt;div class=&#34;notice warning&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;126 76.5 300 300&#34;&gt;  &lt;path d=&#34;M297.431 324.397v-34.255c0-3.245-2.344-5.95-5.358-5.95h-32.146c-3.014 0-5.358 2.705-5.358 5.95v34.255c0 3.245 2.344 5.95 5.358 5.95h32.146c3.014 0 5.358-2.705 5.358-5.95Zm-.335-67.428 3.014-82.753c0-1.081-.502-2.524-1.674-3.425-1.005-.902-2.512-1.983-4.019-1.983h-36.834c-1.507 0-3.014 1.081-4.019 1.983-1.172.901-1.674 2.704-1.674 3.786l2.846 82.392c0 2.344 2.512 4.146 5.693 4.146h30.975c3.013 0 5.525-1.803 5.692-4.146Zm-2.344-168.39L423.34 342.425c3.683 7.032 3.516 15.686-.335 22.717-3.85 7.031-10.883 11.358-18.417 11.358H147.413c-7.534 0-14.566-4.327-18.417-11.358-3.85-7.031-4.018-15.685-.335-22.716L257.248 88.578C260.93 81.188 268.13 76.5 276 76.5c7.87 0 15.069 4.688 18.752 12.08Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Warning&lt;/p&gt;&lt;p&gt;Do NOT connect the XIAO board via USB-C when using this configuration !&lt;/p&gt;&lt;/div&gt;&lt;h1 id=&#34;where-to-connect-those-swd-pins-&#34;&gt;Where to connect those SWD pins ?&lt;/h1&gt;&lt;p&gt;The &lt;a href=&#34;https://wiki.seeedstudio.com/XIAO_BLE/&#34;&gt;Getting Started&lt;/a&gt; guide on the seeed studio wiki briefly mentions how to &lt;a href=&#34;https://wiki.seeedstudio.com/XIAO_BLE/#access-the-swd-pins-for-debugging-and-reflashing-bootloader&#34;&gt;access the SWD Pins for Debugging and Reflashing Bootloader&lt;/a&gt;. But the information there is quite terse. And it points to using a J-Link device from Segger, the cheapest found on-line being around 400 €. That&amp;rsquo;s a bit too much for a hobby.&lt;/p&gt;&lt;p&gt;After some more research, I found using an &lt;a href=&#34;https://www.nordicsemi.com/Products/Development-hardware/nRF52840-DK&#34;&gt;nRF52840 DK&lt;/a&gt; was a possible alternative. Indeed its product page indicates&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;It comes with an on-board SEGGER J-Link debugger allowing programming and debugging both the on-board SoC and external targets through the debug out header.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;That board can be found for less than 60 € from many on-line resellers and it&amp;rsquo;s also a great board to use standalone for experimentation (it has LEDs, buttons, is compatible with Arduino shields&amp;hellip;). So I bought one.&lt;/p&gt;&lt;p&gt;But I still had no explanation of how to connect the SWD pins on the back of the XIAO board to the &lt;em&gt;debug out header&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;The answer in this post (&lt;a href=&#34;https://devzone.nordicsemi.com/f/nordic-q-a/108033/vs-code-nrf-connect-extension-connected-devices-not-capturing-my-device?ReplySortBy=CreatedDate&amp;amp;ReplySortOrder=Ascending&#34;&gt;VS Code nRF Connect extension &amp;ldquo;Connected Devices&amp;rdquo; not capturing my device. - Nordic Q&amp;amp;A - Nordic DevZone - Nordic DevZone&lt;/a&gt;) gave some pointers but mostly indicated that using a &lt;a href=&#34;https://wiki.seeedstudio.com/Seeeduino-XIAO-Expansion-Board/&#34;&gt;Seeed Studio Expansion Board Base for XIAO&lt;/a&gt; made things much easier, eliminating the need to solder directly the SWD pins on the nRF board. But still no clear connection diagram.&lt;/p&gt;&lt;p&gt;I did however order an expansion board, as well as header pins for the XIAO board.&lt;/p&gt;&lt;p&gt;And I continued doing more research (including in the Friend discord channel) and looked at the connectors on the board.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/XIAO_SWD/ExtensionBoard_SWD_PINs.png&#34;    alt=&#34;Expansion board SWD PINs, on the schema and on the board&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Expansion board SWD PINs, on the schema and on the board&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Eventually, connecting this to the corresponding PINs on the nRF52840 DK, I ended-up with a cabling that looked like this&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/XIAO_SWD/InitialCabling.png&#34;    alt=&#34;Initial cabling between nRF 52840 DK and expansion board&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Initial cabling between nRF 52840 DK and expansion board&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;&lt;p&gt;But when looking at the connected devices in the nRF Connect extension in VS Code, all I could see is the nRF52840 DK, not the XIAO board.&lt;figure class=&#34;mid&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/XIAO_SWD/nRFNotShowing.png&#34;    alt=&#34;nRF52840 DK showing up instead of XIAO board&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;nRF52840 DK showing up instead of XIAO board&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;&lt;h1 id=&#34;finding-the-fix&#34;&gt;Finding the fix&lt;/h1&gt;&lt;p&gt;I double-checked the cabling multiple times, re-read the articles I had found and searched for new ones.Eventually, I found this &lt;a href=&#34;https://devzone.nordicsemi.com/f/nordic-q-a/102480/how-to-program-an-external-board-using-a-dk-board&#34;&gt;post&lt;/a&gt;, where in the first answer, somebody explains that, with the latest DK version (revision 3, which I have), you need to bridge the 2 pins between the existing cables. On my board, those are labeled VDD nRF and SWD SEL.&lt;/p&gt;&lt;figure class=&#34;mid&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/XIAO_SWD/BridgingPINs.png&#34;    alt=&#34;Bridging VDD nRF and SWD SEL pins&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Bridging VDD nRF and SWD SEL pins&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;And with that in place, the XIAO board is now showing properly in VS Code.&lt;/p&gt;&lt;figure class=&#34;mid&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/XIAO_SWD/nRFShowing.png&#34;    alt=&#34;XIAO board showing up as expected in VS Code&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;XIAO board showing up as expected in VS Code&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;h1 id=&#34;what-can-i-do-with-this-&#34;&gt;What can I do with this ?&lt;/h1&gt;&lt;p&gt;As expected, I can now use the Flash command from the nRF Connect extension in VS Code to directly flash the XIAO board, no more double-clicking that ridiculously small reset button and copying a file.&lt;/p&gt;&lt;p&gt;I should also be able to debug and step through the program running on the board, inspect processor registers, &amp;hellip; but this is something I haven&amp;rsquo;t looked at in details yet.&lt;/p&gt;&lt;p&gt;But one thing I could not do, is see the console logs, the COM ports appearing under the connected device being the ones from the DK, not the XIAO.&lt;/p&gt;&lt;h1 id=&#34;where-are-my-logs-&#34;&gt;Where are my logs ?&lt;/h1&gt;&lt;p&gt;I found the answer by chance, while looking at an introduction &lt;a href=&#34;https://youtu.be/CPi44L0uzmo?t=316&#34;&gt;video&lt;/a&gt; to the XIAO nRF52840 board, where the presenter mentions that a serial port is created when you plug-in the board.&lt;/p&gt;&lt;div class=&#34;notice info&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;92 59.5 300 300&#34;&gt;  &lt;path d=&#34;M292 303.25V272c0-3.516-2.734-6.25-6.25-6.25H267v-100c0-3.516-2.734-6.25-6.25-6.25h-62.5c-3.516 0-6.25 2.734-6.25 6.25V197c0 3.516 2.734 6.25 6.25 6.25H217v62.5h-18.75c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h87.5c3.516 0 6.25-2.734 6.25-6.25Zm-25-175V97c0-3.516-2.734-6.25-6.25-6.25h-37.5c-3.516 0-6.25 2.734-6.25 6.25v31.25c0 3.516 2.734 6.25 6.25 6.25h37.5c3.516 0 6.25-2.734 6.25-6.25Zm125 81.25c0 82.813-67.188 150-150 150-82.813 0-150-67.188-150-150 0-82.813 67.188-150 150-150 82.813 0 150 67.188 150 150Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Info&lt;/p&gt;&lt;p&gt;As an aside, check out the &lt;a href=&#34;https://www.youtube.com/@wsniot&#34;&gt;WSN &amp;amp; IoT&lt;/a&gt; YouTube channel, there are quite a few interesting videos there, covering different topics related to embedded systems.&lt;/p&gt;&lt;/div&gt;&lt;p&gt;So I started a serial terminal app (I&amp;rsquo;m using &lt;a href=&#34;https://apps.apple.com/be/app/serialtools/id611021963?mt=12&#34;&gt;SerialTools&lt;/a&gt; on the Mac) and checked the existing serial ports.&lt;/p&gt;&lt;figure class=&#34;mid&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/XIAO_SWD/Serial_NotConnected.png&#34;    alt=&#34;Serial ports on my Mac before connecting the XIAO board&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Serial ports on my Mac before connecting the XIAO board&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;I then plugged in the XIAO board and indeed a new port appeared. I could connect to it and there were my logs.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/XIAO_SWD/Serial_Connected.png&#34;    alt=&#34;Connected to the XIAO board serial port and looking at the logs&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Connected to the XIAO board serial port and looking at the logs&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;div class=&#34;notice warning&#34; &gt;    &lt;p class=&#34;notice-title&#34;&gt;        &lt;span class=&#34;icon-notice baseline&#34;&gt;            &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;126 76.5 300 300&#34;&gt;  &lt;path d=&#34;M297.431 324.397v-34.255c0-3.245-2.344-5.95-5.358-5.95h-32.146c-3.014 0-5.358 2.705-5.358 5.95v34.255c0 3.245 2.344 5.95 5.358 5.95h32.146c3.014 0 5.358-2.705 5.358-5.95Zm-.335-67.428 3.014-82.753c0-1.081-.502-2.524-1.674-3.425-1.005-.902-2.512-1.983-4.019-1.983h-36.834c-1.507 0-3.014 1.081-4.019 1.983-1.172.901-1.674 2.704-1.674 3.786l2.846 82.392c0 2.344 2.512 4.146 5.693 4.146h30.975c3.013 0 5.525-1.803 5.692-4.146Zm-2.344-168.39L423.34 342.425c3.683 7.032 3.516 15.686-.335 22.717-3.85 7.031-10.883 11.358-18.417 11.358H147.413c-7.534 0-14.566-4.327-18.417-11.358-3.85-7.031-4.018-15.685-.335-22.716L257.248 88.578C260.93 81.188 268.13 76.5 276 76.5c7.87 0 15.069 4.688 18.752 12.08Z&#34;/&gt;&lt;/svg&gt;        &lt;/span&gt;Warning&lt;/p&gt;&lt;p&gt;In this &lt;a href=&#34;https://devzone.nordicsemi.com/f/nordic-q-a/102480/how-to-program-an-external-board-using-a-dk-board&#34;&gt;post&lt;/a&gt; referenced earlier, it clearly mentioned to NOT plug in the target board (XIAO), that it should only be getting power from the programming board (DK).&lt;/p&gt;&lt;p&gt;However, this meant I could not get my logs anymore. So I tried not patching the 3V3 supply on the expansion board from the DK and plugging in the USB-C on the XIAO board.&lt;/p&gt;&lt;p&gt;It did not work reliably for me and led to all sorts of issues with the board. Just don&amp;rsquo;t do it.&lt;/p&gt;&lt;/div&gt;&lt;h1 id=&#34;board-issues&#34;&gt;Board issues&lt;/h1&gt;&lt;p&gt;When trying the above configuration (connecting both the DK and the XIAO board), here is what I observed:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Initially, I could connect to the serial port and see my logs and I also saw my board appear in VS Code.&lt;/li&gt;&lt;li&gt;I flashed an application via VS Code and it indicated a successful operation, however my program was not executing on the board, I had to manually press reset on the XIAO to start it.&lt;/li&gt;&lt;li&gt;The second time I flashed the application, the program did not start but a reset did not do anything.&lt;/li&gt;&lt;li&gt;I removed the XIAO board from the DK and connected it directly via USB, nothing happened, no LED, no serial port appeared. Double-clicking the reset button did not make the board appear as a USB drive on my Mac.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;At this point, I thought the board might be dead. But if I connected it via the DK (and only via the DK), I could still see it in VS Code.&lt;/p&gt;&lt;p&gt;After some research, I thought maybe the bootloader was gone/corrupted and I followed the procedure in &lt;a href=&#34;https://github.com/Embeddronics-ltd/Flashing-Bootloader-Xiao-BlE&#34;&gt;Embeddronics-ltd/Flashing-Bootloader-Xiao-BlE: Installation of bootloader in xiao ble&lt;/a&gt;, using J-Flash to flash it back on the board.&lt;/p&gt;&lt;p&gt;That worked and I could then re-use the board as before. I tried a second time, not connecting the 3V3 and the ground cables but ended up with similar issues. So for now, I&amp;rsquo;ll just choose between seeing the logs or using the SWD flash/debug features.&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;Now with this setup, I&amp;rsquo;m better equipped to continue exploring the world of embedded dev, which is quite new for me.&lt;/p&gt;&lt;p&gt;As I progress through this journey, I&amp;rsquo;m putting together a list of interesting resources related to embedded systems, you can find it at &lt;a href=&#34;https://https://ericbariaux.statichost.page//pinboard/#EmbeddedDevResources&#34;&gt;Embedded development resources&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;My end goal is to use (Embedded) Swift as the programming language for most of my embedded projects. I&amp;rsquo;ll be posting a lot about this in the coming months, so if you&amp;rsquo;re interested, come back often and follow me on the different social media.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Opus Decoding in Swift</title>
       <link>https://https://ericbariaux.statichost.page//posts/opus-decoding-in-swift/</link>
       <pubDate>Sat, 27 Jul 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/opus-decoding-in-swift/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;&lt;a href=&#34;https://https://ericbariaux.statichost.page//pinboard/#Friend&#34;&gt;Friend&lt;/a&gt; is an open-source wearable AI device that captures your conversations, transcribes and summarises them, and offers a ton of features based on that information.&lt;/p&gt;&lt;p&gt;The wearable device captures the audio signal and sends it to your phone over BLE, which offers a limited bandwidth. Initially, Friend was sending raw PCM data (16 bits, 8kHz), meaning the audio quality was quite low and so was the transcription accuracy.&lt;/p&gt;&lt;p&gt;To improve that, last weekend I re-enabled the Opus codec in their firmware, allowing higher audio quality while using less bandwidth.&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://opus-codec.org/&#34;&gt;Opus&lt;/a&gt; is an open, royalty-free codec that works great with voice content. The available &lt;a href=&#34;https://github.com/xiph/opus&#34;&gt;library&lt;/a&gt; can be used on various platforms, including on embedded devices.&lt;/p&gt;&lt;p&gt;Although you can use the official Friend app, I&amp;rsquo;m developing a native iOS app that records conversations from the Friend device as part of my &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/the-pal-project/&#34;&gt;PAL project&lt;/a&gt;. And now that the device supports Opus, I needed to add that to my codebase.&lt;/p&gt;&lt;h1 id=&#34;integrating-libopus-in-a-swift-code-base&#34;&gt;Integrating libopus in a Swift code base&lt;/h1&gt;&lt;p&gt;I started by doing a quick search for a swift package that supports Opus and found &lt;a href=&#34;https://github.com/alta/swift-opus&#34;&gt;alta/swift-opus: Opus audio codec for Swift Package Manager&lt;/a&gt;.&lt;br&gt;It provides an API that integrates nicely with the native AVFoundation concepts such as AVAudioFormat and AVAudioPCMBuffer, which I was already using in my code for recording the PCM data used so far.&lt;/p&gt;&lt;p&gt;And there is recent activity on the project, which is always a plus.&lt;/p&gt;&lt;p&gt;The way the Friend firmware works is that it takes 10ms of audio data, encodes it (or not for PCM) and sends that packet as one BLE characteristic notification.&lt;/p&gt;&lt;p&gt;In order to optimise the writing to the audio file, I&amp;rsquo;m collecting a series of packets, appending everything in a &lt;strong&gt;&lt;em&gt;Data&lt;/em&gt;&lt;/strong&gt; structure and every 100 packets, converting that to an AVAudioPCMBuffer and writing to the file.&lt;/p&gt;&lt;p&gt;And so my first naive try was to keep the same mechanism and pass my big data blob to the &lt;a href=&#34;https://github.com/alta/swift-opus/blob/6f3cb6bd3ffed1fe5f06d00a962d5c191a50daf8/Sources/Opus/Opus.Decoder.swift#L41&#34;&gt;decode&lt;/a&gt; method which conveniently returned an AVAudioPCMBuffer&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; input: Data) &lt;span style=&#34;color:#66d9ef&#34;&gt;throws&lt;/span&gt; -&amp;gt; AVAudioPCMBuffer {&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the code did not work, the &lt;strong&gt;&lt;em&gt;decode&lt;/em&gt;&lt;/strong&gt; call was always throwing an &lt;strong&gt;&lt;em&gt;Opus.Opus.Error error -4&lt;/em&gt;&lt;/strong&gt;, which is &lt;strong&gt;&lt;em&gt;OPUS_INVALID_PACKET&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;h1 id=&#34;packet-boundaries-are-important&#34;&gt;Packet boundaries are important&lt;/h1&gt;&lt;p&gt;Why was my packet invalid ? I reviewed the low-level code that gets the data from Bluetooth and populates the buffer but all looked OK and it worked for PCM, so why not here.&lt;/p&gt;&lt;p&gt;Glancing at the opus site, I saw this information&lt;/p&gt;&lt;blockquote&gt;&lt;ul&gt;&lt;li&gt;Frame sizes from 2.5 ms to 60 ms&lt;/li&gt;&lt;/ul&gt;&lt;/blockquote&gt;&lt;p&gt;Got it, my packets are too big, I need to feed the decoder smaller ones. So I updated the code to split my big buffer in small chunks and iterated on the call to &lt;strong&gt;&lt;em&gt;decode&lt;/em&gt;&lt;/strong&gt;. Same error, although at some point, when playing around with the chunk size, I could successfully decode one packet ?!?&lt;/p&gt;&lt;p&gt;I went back to the firmware code, checking the parameters such as sampling rate, making sure everything was aligned on both sides. And then it hit me. On the firmware side, we&amp;rsquo;re encoding one 10ms packet at a time and sending that encoded packet over BLE. So it makes perfect sense that on the decoding side, it&amp;rsquo;s that same packet that needs to be fed to the decoder.&lt;/p&gt;&lt;p&gt;But the code in place does pack several packets it receives over BLE together before handing it over to the decoder. And because we&amp;rsquo;re using Variable Bit Rate for encoding, I can not split the buffer back into the initial packets in the decoder.&lt;/p&gt;&lt;p&gt;I reworked the code so that instead of storing the raw bytes in a &lt;strong&gt;&lt;em&gt;Data&lt;/em&gt;&lt;/strong&gt; structure, I collected the different packets in an &lt;strong&gt;&lt;em&gt;Array&lt;/em&gt;&lt;/strong&gt;, each entry storing an individual packet. So when the decoder receives the &lt;strong&gt;&lt;em&gt;Array&lt;/em&gt;&lt;/strong&gt;, it can now decode each packet individually.&lt;/p&gt;&lt;p&gt;And this worked. It seems obvious in hindsight, but by adding the decoding logic within the structure of the existing code without looking at the bigger picture, I had gone in the wrong direction.&lt;/p&gt;&lt;h1 id=&#34;state-matters&#34;&gt;State matters&lt;/h1&gt;&lt;p&gt;No more decoding errors, the audio file was properly written and it had the correct length, great.&lt;br&gt;But when I listened to the recording, the sound was heavily distorted. Not complete garbage, I could barely understand what I had said during the recording but loads of crackling, saturation and other artefacts.&lt;/p&gt;&lt;p&gt;Back to looking at the code, did I make a mistake in my byte manipulation logic ? Was it an endianness problem ? I tried different changes but to no avail.&lt;/p&gt;&lt;p&gt;The Friend native app, written in Dart with Flutter was producing correct audio, so the issue was on the decoding side. I looked at their code, looked at the Dart Opus plugin (which is using the same libopus library underneath) but nothing stood out.&lt;/p&gt;&lt;p&gt;So I applied a technique I use a lot when faced with a problem in my apps. I try to reproduce it in an isolated context, as small and focused as possible, getting rid of as much overhead as possible so I can iterate fast.&lt;br&gt;I updated my code to store the raw packets I receive from BLE to a file (so I had a test fixture and I did not need to connect to a BLE device and record a bit of audio for every test). From there, I created a simple command line tool on the Mac to read those packets and decode them to a WAV file.&lt;br&gt;And to my surprise, the audio was perfect, clean and pristine sound.&lt;/p&gt;&lt;p&gt;Huh ? Comparing the code in my app with the simple test I made, I saw that in the app, again because of the structure in place and because I first wanted to get something working before refactoring the code, I re-created the Opus decoder for every packet.So I updated my test to do the same. And boom, same artefacts in the decoded audio.&lt;/p&gt;&lt;p&gt;Updating the app code to use the same decoder for the whole duration of a single recording session fixed the issue.&lt;/p&gt;&lt;p&gt;Once again, after having fixed the issue, it makes perfect sense. My limited knowledge of how the codec works made me take a shortcut that had a huge impact on its output.&lt;/p&gt;&lt;h1 id=&#34;optimising-the-processing&#34;&gt;Optimising the processing&lt;/h1&gt;&lt;p&gt;I now had a working app, but to fix some of the problems, I had to adapt the code in place.&lt;/p&gt;&lt;p&gt;Because of the API of the Opus Decoder&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;decode&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; input: Data) &lt;span style=&#34;color:#66d9ef&#34;&gt;throws&lt;/span&gt; -&amp;gt; AVAudioPCMBuffer {&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and of AVAudioFile&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;open &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;write&lt;/span&gt;(from buffer: AVAudioPCMBuffer) &lt;span style=&#34;color:#66d9ef&#34;&gt;throws&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and the fact there&amp;rsquo;s no API to easily concatenate 2 &lt;strong&gt;&lt;em&gt;AVAudioPCMBuffer&lt;/em&gt;&lt;/strong&gt; s together, I was now writing each decoded packet to the audio file.&lt;/p&gt;&lt;p&gt;I did not scientifically investigate the topic, but it bothered me to make frequent calls to an API that results in disk I/O.&lt;/p&gt;&lt;p&gt;My solution was to &lt;a href=&#34;https://github.com/nelcea/swift-opus&#34;&gt;fork&lt;/a&gt; the swift-opus package and add a method to decode to a &lt;strong&gt;&lt;em&gt;Data&lt;/em&gt;&lt;/strong&gt; structure and not an &lt;strong&gt;&lt;em&gt;AVAudioPCMBuffer&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;decodeToData&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;_&lt;/span&gt; input: Data) &lt;span style=&#34;color:#66d9ef&#34;&gt;throws&lt;/span&gt; -&amp;gt; Data {&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With that in place, I could now properly decode each packet, build a big data buffer by appending together the &lt;strong&gt;decoded&lt;/strong&gt; bytes, create a single &lt;strong&gt;&lt;em&gt;AVAudioPCMBuffer&lt;/em&gt;&lt;/strong&gt; buffer from there and write that to the audio file.&lt;/p&gt;&lt;p&gt;The fork also includes an update of libopus to the latest 1.4.x version. I tried updating to 1.5.1 (the latest version at this time) but the project did not compile and I did not bother to investigate further.&lt;/p&gt;&lt;p&gt;I think that given my limited usage, I could also directly include libopus into my app and bypass the need for an extra package altogether. That might be work for some other time.&lt;/p&gt;&lt;h1 id=&#34;key-takeaways&#34;&gt;Key takeaways&lt;/h1&gt;&lt;p&gt;Specifically for Opus decoding:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;decode the packets as they&amp;rsquo;ve been encoded, don&amp;rsquo;t try to manipulate them in any way&lt;/li&gt;&lt;li&gt;make sure to use the same decoder instance for the whole audio segment, state matters so the lifetime of the decoder should be similar to the one of the encoder&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;More generally with regards to software development:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;don&amp;rsquo;t let existing code inform your decisions too much, take the time to think about the bigger picture and how this can impact what&amp;rsquo;s in place&lt;/li&gt;&lt;li&gt;once faced with a problem, try to replicate it in an isolated context, with the least overhead possible on the debugging process&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If you want to take a look at the final source code, the PAL project is fully open-source on &lt;a href=&#34;https://github.com/nelcea/PAL&#34;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>The PAL Project</title>
       <link>https://https://ericbariaux.statichost.page//posts/the-pal-project/</link>
       <pubDate>Fri, 05 Jul 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/the-pal-project/</guid>
       <description>&lt;p&gt;Several weeks ago, I created the &lt;a href=&#34;https://github.com/nelcea/PAL&#34;&gt;nelcea/PAL: Wearable AI exploration&lt;/a&gt; repository on GitHub. I want to take a minute to explain in slight more detail what this open-source project is about.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;PAL&lt;/strong&gt; is the vehicle for my research in the world of Wearable AI, with an initial focus on the fields of “Personal Knowledge Management” and “Building a Second Brain” (BASB).&lt;br&gt;The initial use case is to capture conversations I’m having, store their text somewhere, and make it possible for me to consult, process, or interact with them.&lt;/p&gt;&lt;p&gt;I have plenty of other ideas extending the use cases to connect many other domains, but I’ll address those in a separate post.&lt;/p&gt;&lt;p&gt;The solution I&amp;rsquo;m currently working on is based on:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A &lt;a href=&#34;https://github.com/BasedHardware/Friend&#34;&gt;Friend&lt;/a&gt; device to capture the conversations.&lt;/li&gt;&lt;li&gt;An iPhone app to record them, transcribe them and interact with the notes.&lt;/li&gt;&lt;li&gt;A server-side component for heavier processing.&lt;/li&gt;&lt;li&gt;Potentially some desktop/web app for further interaction.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The goal of this project is for me to explore and learn in public, not to build a polished project suitable for a large user base.&lt;br&gt;I encourage typical users to check out what &lt;a href=&#34;https://basedhardware.com/&#34;&gt;Based Hardware&lt;/a&gt; is doing—they’re addressing the most typical use cases. I think they’re doing a great job moving quickly to provide useful features to their early adopters, and I’m happy to help with their project whenever I can.&lt;/p&gt;&lt;p&gt;While learning, I intend to delve deeply into all required topics, publishing the code and writing blog posts about my discoveries. I will link to those here as they become available.&lt;/p&gt;&lt;p&gt;This will cover a broad range of topics, as the use case above will already require:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;BLE connectivity between the Friend and iPhone.&lt;/li&gt;&lt;li&gt;Audio recording and codec usage.&lt;/li&gt;&lt;li&gt;Audio processing to get the cleanest sound possible for transcription.&lt;/li&gt;&lt;li&gt;Automatic speech recognition, including diarisation.&lt;/li&gt;&lt;li&gt;Text processing for e.g. summarisation or extracting actions.&lt;/li&gt;&lt;li&gt;Chat interface to interact with the content, using RAG and vector databases.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In addition, I have the following requirements:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Use the Swift programming language for everything: iPhone app, server component and eventually firmware (at first I&amp;rsquo;ll use stock Friend firmware)&lt;/li&gt;&lt;li&gt;Run everything locally, either on the iPhone or on a local server, and avoid sending any data out to a cloud service. A conclusion might be that it&amp;rsquo;s not possible to get acceptable results with that constraint, but that&amp;rsquo;s also part of the experiment.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Do not hesitate to spread the word and contact me on X or Mastodon to join me on this journey.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>WWDC 2024</title>
       <link>https://https://ericbariaux.statichost.page//posts/wwdc2024/</link>
       <pubDate>Sat, 15 Jun 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/wwdc2024/</guid>
       <description>&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/WWDC2024.jpg&#34;    alt=&#34;WWDC 2024 logo&#34;&gt;&lt;/figure&gt;&lt;p&gt;And just like that, WWDC week has come and gone&amp;hellip;&lt;/p&gt;&lt;p&gt;As expected, there were plenty of announcements across all OSes, both user-facing and technical - including the big one on Apple Intelligence. I don&amp;rsquo;t think there were many surprises this year.&lt;/p&gt;&lt;p&gt;I won&amp;rsquo;t go into details on the announcements as many people are already doing that, but I do want to point you to a few interesting resources:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/articles/269/whats-new-in-swift-6&#34;&gt;What&amp;rsquo;s new in Swift 6.0? – Hacking with Swift&lt;/a&gt;Blog post from Paul Hudson on the changes in Swift 6.0, covering of course the big focus on concurrency as well as many small additions throughout the language.&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.swift.org/migration/documentation/migrationguide/&#34;&gt;The Swift 6 migration guide on swift.org&lt;/a&gt;Guide from the Swift team on migrating to the new Swift 6 language model, mainly focusing on concurrency.&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.hackingwithswift.com/articles/270/whats-new-in-swiftui-for-ios-18&#34;&gt;What’s new in SwiftUI for iOS 18 – Hacking with Swift&lt;/a&gt;Blog post from Paul Hudson, this time on all the changes Apple in bringing to SwiftUI.&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=YcRpTXvZZZk&#34;&gt;WWDC24: Key Updates for macOS Development with SwiftUI&lt;/a&gt;YouTube video from Karin Prater going over some new stuff for macOS development, which is nice given the focus is mostly on iOS/iPadOS. Covered updates include customisations for windows behaviour and styling, keyboard and mouse pointers modifiers and changes to TabView.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Apple released all the betas (although some key features will be coming later in the year) on Monday evening, and the session videos were made available progressively throughout the week.&lt;/p&gt;&lt;p&gt;Unless you were lucky enough to have a golden ticket and attend the conference in Cupertino or one of the many community events in the area, many people spent their time watching the released videos and testing out some of the new features.&lt;/p&gt;&lt;p&gt;Unfortunately, I had a lot of professional obligations during that week and couldn&amp;rsquo;t dedicate as much time to WWDC as I would have liked.So, make sure to clear your calendar during that week – even if you&amp;rsquo;re staying at home, it should be a conference week.&lt;/p&gt;&lt;p&gt;However, one thing I did manage to fit in was the labs. I think this is a fantastic opportunity offered by Apple that&amp;rsquo;s often overlooked by many developers. Before COVID, you had to be physically present in California to benefit from them, but now that they&amp;rsquo;re remote, everyone can participate. You just need to be quick – as soon as the sessions are announced on Monday evening, book the ones you&amp;rsquo;re interested in, as some of them become unavailable quite fast.&lt;/p&gt;&lt;p&gt;This is your chance to have one-on-one sessions (I even had two engineers answering my questions in one of the calls) with the engineers who developed the tech you&amp;rsquo;re using. In addition to being super competent, they&amp;rsquo;re also really approachable and happy to help – even with basic questions. They&amp;rsquo;re also eager to learn what you&amp;rsquo;re doingwith the stuff they worked on.&lt;/p&gt;&lt;p&gt;And it doesn&amp;rsquo;t have to be just questions about this year&amp;rsquo;s tech – I collected questions about things I was working on during the year that didn&amp;rsquo;t work as expected or where the code I ended up with didn&amp;rsquo;t make a lot of sense. Just come prepared as much as you can, in addition to helping you make the most of your limited time (30 minutes per session), it&amp;rsquo;s also a matter of respecting the time of the engineer helping you.&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;To wrap things up, I want to thank the engineers at Apple for all their hard work in developing great tools and technologies – and for taking the time to interact with developers during the labs and help bring their ideas to life.&lt;/p&gt;&lt;p&gt;And as a conclusion, here is my checklist for next year&amp;rsquo;s WWDC:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;During the year, keep track of questions or items worth discussing during the labs&lt;/li&gt;&lt;li&gt;As soon as Apple announces WWDC, clear out my agenda for that week&lt;/li&gt;&lt;li&gt;As soon as the labs are announced, book all sessions that interest me&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>On the proper usage of commonFormat for AVAudioFile</title>
       <link>https://https://ericbariaux.statichost.page//posts/avaudiofile_commonformat_usage/</link>
       <pubDate>Sat, 08 Jun 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/avaudiofile_commonformat_usage/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;I started looking into AVAudioFile while working on &lt;a href=&#34;https://github.com/nelcea/PAL&#34;&gt;PALApp&lt;/a&gt;, my exploration into the world of portable AI. The MVP I was implementing is receiving audio over BLE from a &lt;a href=&#34;https://github.com/BasedHardware/Friend&#34;&gt;Friend&lt;/a&gt; wearable and storing it in an audio file on the device.&lt;/p&gt;&lt;h1 id=&#34;try-1&#34;&gt;Try 1&lt;/h1&gt;&lt;p&gt;The Friend audio samples are 16-bit little-endian integers.&lt;/p&gt;&lt;p&gt;To ease testing, I can simulate this by populating a buffer with a simple sine wave&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; samples: [Int16] = {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; s = [Int16]()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.&lt;/span&gt;.&amp;lt;&lt;span style=&#34;color:#ae81ff&#34;&gt;16000&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        s.append(Int16(sinf(Float(i) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; Float(Int16.max)))&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; s&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Given that input, I started by creating a simple AVAudioFile and an AVAudioPCMBuffer using that format, filled the buffer with the samples coming from Friend and tried to save the file.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; audioFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: sampleRate, channels: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, interleaved: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error creating audio format&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; pcmBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: &lt;span style=&#34;color:#ae81ff&#34;&gt;16000&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error creating PCM buffer&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pcmBuffer.frameLength = &lt;span style=&#34;color:#ae81ff&#34;&gt;16000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; channels = UnsafeBufferPointer(start: pcmBuffer.int16ChannelData, count: Int(pcmBuffer.format.channelCount))&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; data = samples.withUnsafeBufferPointer( { Data(buffer: $0 )})&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;UnsafeMutableRawPointer(channels[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;]).withMemoryRebound(to: UInt8.&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;, capacity: data.count) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(bytes: UnsafeMutablePointer&amp;lt;UInt8&amp;gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;data.copyBytes(to: bytes, count: data.count)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; audioFile = &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt;? AVAudioFile(forWriting: URL(fileURLWithPath: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;generated.wav&amp;#34;&lt;/span&gt;), settings: audioFormat.settings) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fatalError(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error initializing AVAudioFile&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; audioFile.write(from: pcmBuffer)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;catch&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(error.localizedDescription)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And this crashed, the write() call was not even throwing an error, the code crashed, with a failing assertion:&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex; background-color:#3c3d38&#34;&gt;&lt;span&gt;CABufferList.h:&lt;span style=&#34;color:#ae81ff&#34;&gt;184&lt;/span&gt;   ASSERTION FAILURE [(nBytes &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;=&lt;/span&gt; buf-&amp;gt;mDataByteSize) &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;is&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;]:&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I tried to understand the error, looking into how I was filling the buffer, copying bytes, did I properly calculate the number of samples, the size of the data ?&lt;br&gt;Searching the web with that error message did not help much and my (incorrect) conclusion at the time was that somehow, AVAudioFile did not support writing to Int16 format.&lt;/p&gt;&lt;h1 id=&#34;try-2&#34;&gt;Try 2&lt;/h1&gt;&lt;p&gt;As some of the example code I saw during my search were using the Float32 format, I updated my code to only use that. Making that work, meant doing some manual conversion of the data received in Int16 format. That ended-up being several lines of code that just did not feel right.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; audioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: sampleRate, channels: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, interleaved: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error creating audio format&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; pcmBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: &lt;span style=&#34;color:#ae81ff&#34;&gt;16000&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error creating PCM buffer&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pcmBuffer.frameLength = &lt;span style=&#34;color:#ae81ff&#34;&gt;16000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; f32Array = samples.map({Float32($0) &lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt; Float32(Int16.max)})&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; channels = UnsafeBufferPointer(start: pcmBuffer.floatChannelData, count: Int(pcmBuffer.format.channelCount))&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; data = f32Array.withUnsafeBufferPointer( { Data(buffer: $0 )})&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;UnsafeMutableRawPointer(channels[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;]).withMemoryRebound(to: UInt8.&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;, capacity: data.count) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(bytes: UnsafeMutablePointer&amp;lt;UInt8&amp;gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;data.copyBytes(to: bytes, count: data.count)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; audioFile = &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt;? AVAudioFile(forWriting: URL(fileURLWithPath: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;generated.wav&amp;#34;&lt;/span&gt;), settings: audioFormat.settings) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fatalError(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error initializing AVAudioFile&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; audioFile.write(from: pcmBuffer)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;catch&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(error.localizedDescription)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This worked, it saved a proper WAV file that contained the audio I was expecting.&lt;br&gt;However, inspecting the file in the finder shows it uses 32 bits per sample, which is a waste considering the source data I&amp;rsquo;m working with.&lt;/p&gt;&lt;figure class=&#34;mid&#34;&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/WAVFile32bits.png&#34;    alt=&#34;Inspecting WAV file shows it uses 32 bits per sample&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Inspecting WAV file shows it uses 32 bits per sample&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;h1 id=&#34;try-3&#34;&gt;Try 3&lt;/h1&gt;&lt;p&gt;Until now, I had created my code by searching the internet, looking at code snippets I could modify for my use and quickly glancing at the reference documentation in Xcode. But I never took the time to understand in more details the audio framework that Apple was providing.&lt;br&gt;So I went back to my WWDC videos collection and found one that introduced the classes I was using, session 501 from WWDC 2014, &amp;ldquo;What&amp;rsquo;s New in Core Audio&amp;rdquo; (that unfortunately is no more available from the Apple website).&lt;br&gt;In that session, they talked about the concept of the &amp;ldquo;processing format&amp;rdquo;, that is the PCM format with which you interact with the file. You can specify that with the initializer that takes a &lt;em&gt;commonFormat&lt;/em&gt; parameter.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; audioFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: sampleRate, channels: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, interleaved: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error creating audio format&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; pcmBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: &lt;span style=&#34;color:#ae81ff&#34;&gt;16000&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error creating PCM buffer&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pcmBuffer.frameLength = &lt;span style=&#34;color:#ae81ff&#34;&gt;16000&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; channels = UnsafeBufferPointer(start: pcmBuffer.int16ChannelData, count: Int(pcmBuffer.format.channelCount))&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; data = samples.withUnsafeBufferPointer( { Data(buffer: $0 )})&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;UnsafeMutableRawPointer(channels[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;]).withMemoryRebound(to: UInt8.&lt;span style=&#34;color:#66d9ef&#34;&gt;self&lt;/span&gt;, capacity: data.count) {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(bytes: UnsafeMutablePointer&amp;lt;UInt8&amp;gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;in&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;data.copyBytes(to: bytes, count: data.count)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; recordingAudioFormat = AVAudioFormat(commonFormat: .pcmFormatInt16, sampleRate: sampleRate, channels: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, interleaved: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error creating recording audio format&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;guard&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;let&lt;/span&gt; audioFile = &lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt;? AVAudioFile(forWriting: URL(fileURLWithPath: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;generated_int16.wav&amp;#34;&lt;/span&gt;), settings: recordingAudioFormat.settings, commonFormat: .pcmFormatInt16, interleaved: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fatalError(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Error initializing AVAudioFile&amp;#34;&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;do&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; audioFile.write(from: pcmBuffer)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;catch&lt;/span&gt; {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(error.localizedDescription)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works, with simpler code, less data manipulation (which means it&amp;rsquo;s faster and uses less memory) and the generated WAV file uses 16 bits per sample, which matches the original data format.&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;Most of the time, if you encounter an error in your code and it feels like you&amp;rsquo;re fighting the framework, ending-up implementing some weird workaround, you&amp;rsquo;re probably doing it wrong.&lt;/p&gt;&lt;p&gt;It&amp;rsquo;s worth going back to basics, reading the Apple documentation and understanding the classes you&amp;rsquo;re working with. I find that searching the WWDC video archives, for the video of when a particular topic was first introduced can help a lot (pro tip: as Apple is removing those as time goes by, keep a local copy of all the videos they publish, just in case).&lt;/p&gt;&lt;p&gt;You can find a sample project illustrating the use of the above code on GitHub at &lt;a href=&#34;https://github.com/nelcea/Test_AVAudioFile&#34;&gt;Test_AVAudioFile&lt;/a&gt;.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Portable AI, a month later</title>
       <link>https://https://ericbariaux.statichost.page//posts/portable-ai-a-month-later/</link>
       <pubDate>Fri, 03 May 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/portable-ai-a-month-later/</guid>
       <description>&lt;p&gt;It&amp;rsquo;s been a bit more than one month since my initial post on &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/portable-ai/&#34;&gt;Portable AI&lt;/a&gt; and things are moving fast. The &lt;a href=&#34;https://https://ericbariaux.statichost.page//pinboard/#Humane&#34;&gt;Humane Ai Pin&lt;/a&gt; has started shipping, the &lt;a href=&#34;https://https://ericbariaux.statichost.page//pinboard/#r1&#34;&gt;rabbit R1&lt;/a&gt; has started shipping, &lt;a href=&#34;https://https://ericbariaux.statichost.page//pinboard/#Friend&#34;&gt;Friend&lt;/a&gt; has a kickstarter campaign, Rewind became &lt;a href=&#34;https://https://ericbariaux.statichost.page//pinboard/#Limitless&#34;&gt;Limitless&lt;/a&gt; and a lot of people are now talking about those new &amp;ldquo;AI devices&amp;rdquo;.&lt;/p&gt;&lt;p&gt;The Humane Ai Pin was the first to ship and the reviews are it. Unfortunately, they&amp;rsquo;re not glowing, as the device disappoints on many levels: it&amp;rsquo;s slow, prone to providing incorrect answers, overheats to the point of shutdown, has a barely readable display in daylight, is limited in what it can do and lacks integration with your Apple/Google account&amp;hellip;Its hefty starting price of 700$ and the fact it turns into a paperweight as soon as you stop paying the 24$/month subscription does not help.&lt;/p&gt;&lt;p&gt;The Rabbit R1 has also hit the shelves, with a pickup event in NYC on April 24th. While it&amp;rsquo;s marginally better received than the Humane Ai Pin, criticisms still abound. Although faster than its competitor and sporting a traditional screen (but that presents some usability concerns, e.g. navigation in the menu with the scroll wheel instead of using touch), it&amp;rsquo;s lower price of 199$ is not enough to forgive some of the drawbacks. The build quality matches the price tag and, like the Humane Ai Pin, if confidently provides incorrect answers to your queries and offers limited features at this stage.&lt;/p&gt;&lt;p&gt;Reviewers have noted a trend in the rush to release AI-powered devices, often resulting in pre-beta, half-baked products.. There is a huge disconnect between what&amp;rsquo;s promised (sometimes even demonstrated) and what users can actually do with the device they receive.&lt;/p&gt;&lt;p&gt;One very plausible reason is they fear an announcement from Google (Google I/O starting on May 14th) or Apple (WWDC starting on Jun 10th) and want to push as many devices as possible in the hands of end-users before those.Indeed, Apple and Google control their platform and can provide a tight integration on a device you already own and within an ecosystem you&amp;rsquo;re already locked into. A thought offering to beat.This is potentially the same reason why Humane and Rabbit are exploring different form factors, that work outside of the established ecosystems.&lt;/p&gt;&lt;p&gt;On April 15th, Rewind unveiled its new product called, Limitless. Alongside this announcement, the company rebranded itself as Limitless.Limitless offers a web app and desktop apps that records everything you&amp;rsquo;ve seen, said or heard. It&amp;rsquo;s clearly targeted at meetings, providing a pre-meeting context based on previous information it collected, real-time transcription and note-taking during the meeting and post-meeting summaries.While I haven&amp;rsquo;t had the chance to try it yet, I like the idea of focusing on a given use case and (hopefully) delivering it right instead of promising a lot of possibilities and falling short on most of them.&lt;/p&gt;&lt;p&gt;As a companion to its apps, Limitless plans to release a wearable, the Limitless Pendant. This is not shipping yet (planned for Q4 2024) and is the evolution of their previous Rewind Pendant that never shipped. But it changes the form factor and I really like what they&amp;rsquo;re promising here. It seems like a well thought out product proposed at a reasonable price. And the Consent Mode where they perform voice identification and recognise that a user has given its permission to be recorded would be quite incredible, IF it works reliably.&lt;/p&gt;&lt;p&gt;Finally, there&amp;rsquo;s the open-source Friend project that I&amp;rsquo;m following closely (e.g. on their Discord channel) and it&amp;rsquo;s moving quite fast. They&amp;rsquo;ve joined forces with &lt;a href=&#34;https://https://ericbariaux.statichost.page//pinboard/#ADeus&#34;&gt;ADeus&lt;/a&gt;, launched a successful &lt;a href=&#34;https://www.kickstarter.com/projects/kodjima333/friend-open-source-ai-wearable-recording-device&#34;&gt;Kickstart campaign&lt;/a&gt; and are building a company.The energy is great, but it&amp;rsquo;s in a period of flux, making it difficult at this stage to know where they&amp;rsquo;re going and what the end goal is. At some point, they express interest in focusing on hardware and firmware development while fostering a community of &lt;a href=&#34;https://basedhardware.com/&#34;&gt;external applications&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;As I continue to monitor developments in this space, I regularly update my list of &lt;a href=&#34;https://https://ericbariaux.statichost.page//pinboard/&#34;&gt;wearable AI projects&lt;/a&gt;. Be sure to check it out for the latest updates.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Building a wearable AI Device</title>
       <link>https://https://ericbariaux.statichost.page//posts/building-wearable-ai-device/</link>
       <pubDate>Fri, 19 Apr 2024 00:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/building-wearable-ai-device/</guid>
       <description>&lt;p&gt;As &lt;a href=&#34;https://github.com/adamcohenhillel/ADeus&#34;&gt;ADeus&lt;/a&gt; was the first wearable AI open-source project I discovered, I started building a device based on the hardware they were using, and more specifically on the tutorial at &lt;a href=&#34;https://github.com/kodjima33/ADeus/blob/main/docs/guides/assemble_hardware.md&#34;&gt;ADeus - Raspberry Pi Zero W Setup Guide&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I ordered the Pi and the same microphone but as I did not want to play around with 3D printing a case for now, I ended-up ordering the standard Raspberry Pi Zero Case. Using the case meant I could not use the standard header connector and had to solder the microphone cable directly on the board.&lt;/p&gt;&lt;p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/PiZero2WithMicrophoneCableSoldered.png&#34;    alt=&#34;Back of the board with microphone cable directly soldered to it&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Back of the board with microphone cable directly soldered to it&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/MicrophoneSolderedToPiZero2.png&#34;    alt=&#34;MEMS microphone, this thing is tiny!&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;MEMS microphone, this thing is tiny!&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;&lt;p&gt;As the standard case also comes with a cover supporting the camera module, I went on ordering one (even if ADeus doesn&amp;rsquo;t make use of it for now). I initially ordered the camera module 3, which is the current one but it does not work in the standard case. I then ordered a camera module 2 but, as can be seen on the picture below, the fit is not perfect either, it seems the case was made for the original version of the module and there were some changes since then.&lt;/p&gt;&lt;p&gt;For the finishing touches, I used hot glue to attach the microphone, protecting it with a foam cover, and at the back I re-used a clip/pin from a conference badge fixed with strong double-sided adhesive.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/AssembledWearableV1.png&#34;    alt=&#34;Final assembled device, front and back&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Final assembled device, front and back&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;This keeps the form factor relatively small (shallow at least) but it doesn&amp;rsquo;t include a battery. This means going the VisionPro way, using an external battery pack.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/WearableAIV1WithExternalBattery.png&#34;    alt=&#34;Going VisionPro with an external battery pack&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Going VisionPro with an external battery pack&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Which in the end, is not too much of an issue when wearing it with a shirt.&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/WearingTheWearableAIV1.png&#34;    alt=&#34;Wearing it with a shirt&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Wearing it with a shirt&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;/p&gt;&lt;p&gt;With the hardware part ready, I can move on to installing and testing ADeus but also writing some of my own code. More on that in a later post.&lt;/p&gt;&lt;h3 id=&#34;list-of-material&#34;&gt;List of material&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&#34;https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/&#34;&gt;Raspberry Pi Zero 2 W&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.raspberrypi.com/products/raspberry-pi-zero-case/&#34;&gt;Raspberry Pi Zero Case&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.raspberrypi.com/products/camera-module-v2/&#34;&gt;Raspberry Pi Camera Module 2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.amazon.com.be/dp/B08218WSXH&#34;&gt;INMP441 MEMS omnidirectionnel microphone with I2S interface&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.amazon.com.be/dp/B092TNMFYB&#34;&gt;Belkin 10000mAh battery pack&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&#34;https://www.amazon.com.be/dp/B0B45V7V97&#34;&gt;Mini foam cover for microphone&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</description>
     </item>
   
     <item>
       <title>Portable AI</title>
       <link>https://https://ericbariaux.statichost.page//posts/portable-ai/</link>
       <pubDate>Sat, 06 Apr 2024 15:14:35 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/portable-ai/</guid>
       <description>&lt;p&gt;AI, LLMs and generative models have now been known and used by a majority of the population, technical or not. But they&amp;rsquo;re mostly used from your desktop or your mobile phone. I&amp;rsquo;m now seeing a growing proposition of portable AI, new form factors that use or fit within the AI eco-system.&lt;/p&gt;&lt;h1 id=&#34;commercial-offering&#34;&gt;Commercial offering&lt;/h1&gt;&lt;p&gt;One of the first I got to know is the AI pin from &lt;a href=&#34;https://humane.com/&#34;&gt;Humane&lt;/a&gt;. I stumbled upon it through this TEDx video: &lt;a href=&#34;https://www.ted.com/talks/imran_chaudhri_the_disappearing_computer_and_a_world_where_you_can_take_ai_everywhere&#34;&gt;Imran Chaudhri: The disappearing computer — and a world where you can take AI everywhere | TED Talk&lt;/a&gt;and immediately went to the web site and signed-in to get notified of any release.Although it includes AI in its name, that&amp;rsquo;s not the focal point for me. The AI pin is a wearable device that offers new, less obtrusive ways, to interact with your digital world. You don&amp;rsquo;t need to take a device out of your pocket and stare at the screen. You can tap and talk and make gestures and it replies via audio or can project a basic UI on your hand.It&amp;rsquo;s one a the few devices that ships now, however I&amp;rsquo;m a bit disappointed with the price point, the fact it&amp;rsquo;s US only and requires to a pricey subscription.&lt;/p&gt;&lt;p&gt;Another alternative I knew about (because I already followed-up on what Rewind was doing, more on this in a future most) is the &lt;a href=&#34;https://www.rewind.ai/pendant&#34;&gt;Rewind Pendant&lt;/a&gt;. This is not an interactive AI assistant, but a always on sensor (microphone) used to populate your personal knowledge base, as a complement to the other sources Rewind already uses. You then use AI afterwards on your phone or desktop to interact with that knowledge base. It’s not available yet though, so let’s wait and re-evaluate when it ships.&lt;/p&gt;&lt;p&gt;Then there is the &lt;a href=&#34;https://www.rabbit.tech/&#34;&gt;rabbit r1&lt;/a&gt;, which was all the rave at CES 2024. Quickly browsing through the web site, I&amp;rsquo;m not sure I get the concept. Most of what it does could be done with an app on your phone. The form factor is very similar to a phone so it still requires you to take it out of your pocket, tap a button, look at a screen. Watching their keynote provides some more information. They&amp;rsquo;re touting that their Large Action Model, that can learn a UI and understand how to take action, just like a human would do, is the big differentiator and bridges the gap between understanding what you do (what LLMs do) and actually making things happen.At 199 USD without any subscription, their pricing is attractive. It&amp;rsquo;s not yet shipping but should be coming out really soon.&lt;/p&gt;&lt;p&gt;In a different category, following the traces of Google Glass or Meta Ray-Ban smart glasses, is the &lt;a href=&#34;https://brilliant.xyz/&#34;&gt;Brilliant Frame&lt;/a&gt;. What&amp;rsquo;s great about that project is that it&amp;rsquo;s very opened and is really a platform to tinker with. But that also means that at this stage (still in pre-order anyway), there are no really useful, end-user oriented applications. I was tempted to pre-order one and play around with it but preferred to wait. I&amp;rsquo;ll definitely keep on eye on what they&amp;rsquo;re doing and what use cases developers are coming up with.&lt;/p&gt;&lt;h1 id=&#34;diy-approach&#34;&gt;DIY approach&lt;/h1&gt;&lt;p&gt;Then I thought it could be cool to try to build such a system myself. And if I have this idea, somebody else surely already had it. Searching for an open-source alternative to the above mentioned products quickly lead to an existing project: &lt;a href=&#34;https://github.com/adamcohenhillel/ADeus?tab=readme-ov-file&#34;&gt;ADeus&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I looked at their repo, started building hardware to test what they&amp;rsquo;re doing, took a look at the discord channel and found quite a few other projects (open or not) in this space: &lt;a href=&#34;https://github.com/OwlAIProject/Owl&#34;&gt;Owl&lt;/a&gt;, &lt;a href=&#34;https://github.com/kaeladair/Friend?tab=readme-ov-file&#34;&gt;Friend&lt;/a&gt;, &lt;a href=&#34;https://github.com/OpenInterpreter/01&#34;&gt;O1&lt;/a&gt;, &lt;a href=&#34;https://mytab.ai/&#34;&gt;Tab&lt;/a&gt; and I&amp;rsquo;m sure I&amp;rsquo;m missing quite a few.&lt;/p&gt;&lt;p&gt;In this very interesting video (&lt;a href=&#34;https://www.youtube.com/watch?v=HXB4yBv9pfM&#34;&gt;Owl: Open Source Wearable AI - OpenCV Live 130&lt;/a&gt;), Bart Trzynadlowski, one of the co-founder of Owl, mentions quite a few of them and talks about the opportunities and the challenges for those projects.&lt;/p&gt;&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;I think their is indeed a lot of potential to further develop such projects and find real-life use cases that can have a profound impact on our everyday life. I&amp;rsquo;ll definitely look in more details at those projects, hopefully trying them myself and reporting here and I&amp;rsquo;ll most probably will have a go at developing my own project. Stay tuned&amp;hellip;&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Vision OS for an existing app</title>
       <link>https://https://ericbariaux.statichost.page//posts/visionos-for-existing-app/</link>
       <pubDate>Wed, 07 Feb 2024 20:19:38 +0100</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/visionos-for-existing-app/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;As a simple intro into visionOS, I used the most simple app I have, &lt;a href=&#34;https://apps.apple.com/be/app/awg-convert/id288990217&#34;&gt;AWG Convert&lt;/a&gt;, and set-up to add native support for visionOS to it.&lt;/p&gt;&lt;p&gt;I added an &amp;ldquo;Apple Vision&amp;rdquo; destination to my project, launched the app in the simulator and started to tweak the code to make it look slightly better in the Vision Pro. Just the basics here, not really taking advantage of Spatial Computing, baby steps.&lt;/p&gt;&lt;p&gt;The biggest work I had to do was in making the UI more responsive, as the iPhone version was locked to only portrait mode. See &lt;a href=&#34;https://https://ericbariaux.statichost.page//posts/visionos-interface-orientation/&#34;&gt;Interface orientation in visionOS&lt;/a&gt; for some exploration I did as a preparation to this.&lt;/p&gt;&lt;p&gt;When I thought I had something OK, that at least was better than the &amp;ldquo;compatibility mode&amp;rdquo;, I went on to publishing the update on the AppStore and discovered there were a few &amp;ldquo;details&amp;rdquo; I still needed to take care of.&lt;/p&gt;&lt;h1 id=&#34;providing-an-app-icon&#34;&gt;Providing an app icon&lt;/h1&gt;&lt;p&gt;I naively thought that, as I already had an icon for my iPhone app, the same one would just be used. Not the case.&lt;/p&gt;&lt;p&gt;Looking at &lt;a href=&#34;https://developer.apple.com/documentation/xcode/configuring-your-app-icon&#34;&gt;Configuring your app icon | Apple Developer Documentation&lt;/a&gt; I could see that tvOS and visionOS have specific OS variants for the app icon. And those are not simple images but multi-layered.&lt;/p&gt;&lt;p&gt;I thus added the variant in Xcode in the assets catalog.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/Adding%20a%20vision%20OS%20App%20Icon.png&#34;    alt=&#34;Adding a vision OS App Icon&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;Adding a vision OS App Icon&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;A visionOS has by default 3 layers (the maximum it can have) and must have minimum 2 layers.&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://www.rudrank.com/vision-os-fundamentals-creating-app-icon/&#34;&gt;Exploring visionOS Fundaments: Creating the App Icon&lt;/a&gt; is a nice article with some more information on creating icons for visionOS.&lt;/p&gt;&lt;h1 id=&#34;taking-a-screenshot&#34;&gt;Taking a screenshot&lt;/h1&gt;&lt;p&gt;Searching in Apple documentation on how to take screenshots for Vision Pro, all I could find was &lt;a href=&#34;https://developer.apple.com/documentation/visionos/capturing-screenshots-and-video-from-your-apple-vision-pro-for-2d-viewing&#34;&gt;Capturing screenshots and video from Apple Vision Pro for 2D viewing | Apple Developer Documentation&lt;/a&gt;. But this requires a physical device, there is no indication on how to capture using the simulator.&lt;/p&gt;&lt;p&gt;So I did it like for other iOS devices and used the &amp;ldquo;Save Screen&amp;rdquo; button in the simulator.&lt;/p&gt;&lt;p&gt;Doing this results in images with a resolution of 2732 x 2048 pixels. But looking at the specifications from Apple (&lt;a href=&#34;https://developer.apple.com/help/app-store-connect/reference/screenshot-specifications/&#34;&gt;Screenshot specifications - Reference - App Store Connect - Help - Apple Developer&lt;/a&gt;), it indicates that the screenshots for Apple Vision Pro must have a resolution of 3840 x 2160.&lt;/p&gt;&lt;p&gt;So a bit of post-processing is required. You can definitely do it using your favorite tool like Pixelmator or PhotoShop but I wanted a quick and easy solution for my first test submission.&lt;/p&gt;&lt;p&gt;Luckily enough, macOS includes a command-line tool that comes in handy. Using the following 2 commands, I got an image at the right resolution.&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; sips -z &lt;span style=&#34;color:#ae81ff&#34;&gt;2879&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3840&lt;/span&gt; Simulator&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;Screenshot&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;-&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;Apple&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;Vision&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;Pro&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;-&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;2024-02-02&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;at&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;21.16.15.png&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; sips -c &lt;span style=&#34;color:#ae81ff&#34;&gt;2160&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;3840&lt;/span&gt; Simulator&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;Screenshot&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;-&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;Apple&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;Vision&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;Pro&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;-&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;2024-02-02&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;at&lt;span style=&#34;color:#ae81ff&#34;&gt;\ &lt;/span&gt;21.16.15.png&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This first command scales-up the image to the desired width, the second crops it vertically to get the desired final resolution. So be careful how you center your app content when taking the screenshot, as some part at the top and bottom will be discarded.&lt;/p&gt;&lt;h1 id=&#34;a-separate-distribution-for-visionos&#34;&gt;A separate distribution for visionOS&lt;/h1&gt;&lt;p&gt;So I logged into App Store Connect and looked at creating a new version of my application.&lt;/p&gt;&lt;p&gt;So far I only had applications that were targeted at iPhones and iPads and I thought targetting Vision Pro in addition would work the same.&lt;/p&gt;&lt;p&gt;But no, I saw that I needed to add a different Platform for the application (for visionOS) and that the iOS and visionOS apps can have different lifecycles. But the make things cleaner, I aligned the version numbers for both platforms.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/iOS%20and%20visionOS%20platforms%20in%20AppStoreConnect.png&#34;    alt=&#34;iOS and visionOS platforms added in App Store Connect&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;iOS and visionOS platforms added in App Store Connect&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;h1 id=&#34;building-for-distribution&#34;&gt;Building for distribution&lt;/h1&gt;&lt;p&gt;The next surprise came when I wanted to create an archive of the project for uploading to the App Store, as there was no destination for a visionOS device available.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/No%20destination%20for%20visionOS.png&#34;    alt=&#34;visionOS does not appear in the list of destination&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;visionOS does not appear in the list of destination&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Googling a bit, I quickly found an answer on the Apple Developer Forums: &lt;a href=&#34;https://forums.developer.apple.com/forums/thread/743246?answerId=774803022#774803022&#34;&gt;Xcode Not showing Vision Pro Archive destination&lt;/a&gt;. And although it mentions Xcode 15.2 Beta, it&amp;rsquo;s still the case with the final 15.2 version.&lt;/p&gt;&lt;p&gt;So changing the Base SDK from it&amp;rsquo;s original iOS&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/Base%20SDK%20iOS.png&#34;    alt=&#34;iOS is set as the base SDK for the project&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;iOS is set as the base SDK for the project&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;to visionOS&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/Base%20SDK%20visionOS.png&#34;    alt=&#34;After changing the base SDK to visionOS&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;After changing the base SDK to visionOS&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;made the required destination appear in the menu.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/Destination%20for%20visionOS.png&#34;    alt=&#34;visionOS now does appear in the list of destination&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;visionOS now does appear in the list of destination&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;And with that, I was able to create a build and upload it to the App Store.&lt;/p&gt;&lt;h1 id=&#34;being-on-the-store&#34;&gt;Being on the store&lt;/h1&gt;&lt;p&gt;The review process took 3 days and my app was accepted on the store.&lt;/p&gt;&lt;p&gt;So AWG Convert is now available for &lt;a href=&#34;https://apps.apple.com/us/app/awg-convert/id288990217?platform=appleVisionPro&#34;&gt;Apple Vision Pro&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Not much to brag about, as this was the bare minimum for native visionOS support, but at least it helped me discovered the steps required to release an app for Vision Pro.&lt;/p&gt;&lt;p&gt;Now let&amp;rsquo;s get to work on the next one&amp;hellip;&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Interface orientation in visionOS</title>
       <link>https://https://ericbariaux.statichost.page//posts/visionos-interface-orientation/</link>
       <pubDate>Sun, 28 Jan 2024 16:20:57 +0100</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/visionos-interface-orientation/</guid>
       <description>&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;&lt;p&gt;Yesterday, during the super interesting &lt;a href=&#34;https://www.hackingwithswift.com/articles/264/take-on-visionos-at-unwrap-live-2024&#34;&gt;Unwrap Live 2024 stream on visionOS&lt;/a&gt; from Paul Hudson, I asked the question on whether it was possible to have your visionOS start in &amp;ldquo;portrait mode&amp;rdquo;.&lt;/p&gt;&lt;p&gt;The reason I asked is because I&amp;rsquo;m extending a small utility app (&lt;a href=&#34;https://apps.apple.com/be/app/awg-convert/id288990217&#34;&gt;AWG Convert&lt;/a&gt;) that I&amp;rsquo;ve coded on the iPhone to have native support for the Vision Pro. There is no iPad version (for now), and the iPhone version only supports portrait orientation. So my first idea was to port &amp;ldquo;as is&amp;rdquo; to Vision Pro. And I was thinking people can just have a small vertical window arranged on the side of other windows in their environment.&lt;/p&gt;&lt;p&gt;The answer Paul gave was that Apple made it clear that humans have more scope from left to right than up and down and so it makes much more sense to go wide than tall.&lt;/p&gt;&lt;p&gt;That makes a lot of sense and checking information on human field of view (FOV), although you can find varying information, usually indicates that humans of about 200° of horizontal FOV (both eyes combined) and 135° of vertical FOV.&lt;/p&gt;&lt;h1 id=&#34;being-stubborn&#34;&gt;Being stubborn&lt;/h1&gt;&lt;p&gt;Let&amp;rsquo;s say I still wanted to go ahead and have my app start with a vertical window.&lt;/p&gt;&lt;p&gt;The article &lt;a href=&#34;https://developer.apple.com/documentation/visionos/positioning-and-sizing-windows&#34;&gt;Positioning and sizing windows | Apple Developer Documentation&lt;/a&gt; gives the key to it and leads to the following code&lt;/p&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WindowGroup {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContentView()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.defaultSize(width: &lt;span style=&#34;color:#ae81ff&#34;&gt;400&lt;/span&gt;, height: &lt;span style=&#34;color:#ae81ff&#34;&gt;700&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But this does not prevent the user from resizing the window to a wide aspect ratio. The following code would achieve this&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-swift&#34; data-lang=&#34;swift&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;WindowGroup {&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ContentView()&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.frame(minWidth: &lt;span style=&#34;color:#ae81ff&#34;&gt;300&lt;/span&gt;, maxWidth: &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;, minHeight: &lt;span style=&#34;color:#ae81ff&#34;&gt;600&lt;/span&gt;, maxHeight: &lt;span style=&#34;color:#ae81ff&#34;&gt;800&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.background(.red)&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.windowResizability(.contentSize)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/p&gt;&lt;p&gt;but let&amp;rsquo;s face it, this is fighting the system and will lead to an alien app in the Apple ecosystem.&lt;/p&gt;&lt;h1 id=&#34;playing-nice&#34;&gt;Playing nice&lt;/h1&gt;&lt;p&gt;The app should adapt to whatever window size and aspect ratio the user chooses.&lt;/p&gt;&lt;p&gt;How would you achieve this?&lt;/p&gt;&lt;p&gt;Under iOS, it&amp;rsquo;s possible to check for the device orientation and adapt to it (some information on how to do it in &lt;a href=&#34;https://www.hackingwithswift.com/quick-start/swiftui/how-to-detect-device-rotation&#34;&gt;How to detect device rotation - a free SwiftUI by Example tutorial&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;But under visionOS, UIDevice.current.orientation is unavailable. Of course, the device orientation doesn&amp;rsquo;t make sense for the Vision Pro.&lt;/p&gt;&lt;p&gt;Anyway, this is not the recommended way to adapt your UI layout, as e.g. on the iPad, with multitasking, your device can by in landscape orientation but your UI canvas be in portrait.&lt;/p&gt;&lt;p&gt;I believe the recommended way to address this, is by checking the reported size classes and adapting the layout based on that.&lt;/p&gt;&lt;p&gt;But testing this on the Vision Pro simulator always reports a size class of regular for both horizontal and vertical directions, irrelevant of the window size or aspect ratio. So that will not help.&lt;/p&gt;&lt;p&gt;For now, the solution I&amp;rsquo;ll be testing further is to use GeometryReader to get the size available for my interface and adapt accordingly (even though GeometryReader comes with its shortcomings too).&lt;/p&gt;&lt;h1 id=&#34;trying-it-out-yourself&#34;&gt;Trying it out yourself&lt;/h1&gt;&lt;p&gt;I created a small projet to test out device orientation, size classes and GeometryReader information as reported under different platforms, it&amp;rsquo;s available on GitHub for you to test it out: &lt;a href=&#34;https://github.com/nelcea/Test_DeviceOrientation&#34;&gt;Test_DeviceOrientation&lt;/a&gt;&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Obsidian on Multiple Devices</title>
       <link>https://https://ericbariaux.statichost.page//posts/obsidian-on-multiple-devices/</link>
       <pubDate>Sat, 14 Oct 2023 12:00:00 +0200</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/obsidian-on-multiple-devices/</guid>
       <description>&lt;p&gt;As I&amp;rsquo;m getting more serious about using Obsidian as my primary note taking application, having the content available on multiple devices becomes critical.&lt;/p&gt;&lt;p&gt;Living in the Apple eco-system, I had two options: Obsidian sync or iCloud.&lt;br&gt;I went for the second option.And for those concerned with privacy, Apple now supports end-to-end encryption using your own keys for your iCloud storage with the &lt;a href=&#34;https://support.apple.com/en-us/HT202303#:~:text=End%2Dto%2Dend%20encrypted%20data%20can%20be%20decrypted%20only%20on,data%20breach%20in%20the%20cloud&#34;&gt;Advanced Data Protection&lt;/a&gt; option.&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://medium.com/@philiprpowis/setting-up-obsidian-sync-with-icloud-drive-459a14e5e070&#34;&gt;Setting up Obsidian Sync with iCloud Drive&lt;/a&gt; is a good article on the process of setting up sync.And it covers the use-case I was faced with of having created a vault on the Mac before wanting to sync on a mobile device.&lt;/p&gt;&lt;p&gt;There&amp;rsquo;s however one gotcha I encountered that was not covered: when copying files from your existing vault to the iCloud one using the Finder, hidden files (starting with a dot) are not copied.&lt;br&gt;And Obsidian stores its settings in such a file (by default .obsidian). So if you don&amp;rsquo;t copy this file (as I initially did), your new iCloud enabled vault will have the default obsidian settings and you&amp;rsquo;ll loose any adjustments you might have made for your original vault.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>The Wait is Over</title>
       <link>https://https://ericbariaux.statichost.page//posts/the-wait-is-over/</link>
       <pubDate>Tue, 12 Aug 2014 00:00:00 +0000</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/the-wait-is-over/</guid>
       <description>&lt;p&gt;Or so I thought&amp;hellip;&lt;/p&gt;&lt;p&gt;Last week, I had received a shipping notification for my Rift DK2, indicating a delivery for this Monday. So I spent a bit of the week-end preparing a PC to use with it. It&amp;rsquo;s a powerful desktop system that I built a bit less than 2 years ago, to work on GWT projects (because building GWT projects can take a long time). When I started with that idea, the goal was to have a fast machine for that task, while keeping the budget low. So I would spend the bulk of the budget on the components that matter, mainly the CPU (6-Core i7), motherboard and RAM (16 GB) and re-use components that I had lying around. The later included an old graphics card.&lt;/p&gt;&lt;p&gt;This worked but I was not too happy working under CentOS, and being an OS X user, I wondered if there was any way to run OS X on this. Looking a bit at the Hackintosh community, it turned out it was not that difficult, more so if you picked your components from a list of well supported ones. So I &amp;ldquo;invested&amp;rdquo; in a new graphics card, picking one based on my requirements : Hackintosh friendly, powerful enough to run an IDE and a web browser (which means anything sold at that time would do) and cheap. And I ended up with a Sapphire Radeon HD5450 card that perfectly fit the job.&lt;/p&gt;&lt;p&gt;As last week-end, the Oculus SDK was still Windows only (and anyway a lot of demos are still Windows only), I decided to put a new disk in that machine, install a brand new Windows 8.1, the DK2 run-time and the SDK. Everything was now ready, one more time to sleep.&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/Rift%20DK2%20package.png&#34;    alt=&#34;And the long awaited package arrived as planned&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;And the long awaited package arrived as planned&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;I carefully unpack, follow the Quick Start Guide to connect all the components, launch the Oculus Config Util, go through the required steps, click &amp;ldquo;Show Demo Scene&amp;rdquo; and &amp;hellip; judder, lag, choppiness, in a word: unusable.&lt;/p&gt;&lt;p&gt;Going through the forums, I see people reporting similar issues and problems with AMD based graphics cards. After some reading and tweaking, which took me quite a bit of time as I mostly stopped using Windows about 8 years ago, I could improve the situation a bit but not really fix the issue. I might be able to improve the situation even more but anyway, I&amp;rsquo;m only getting about 25 fps with the SDK demo.&lt;/p&gt;&lt;p&gt;Having watched Cymatic Bruce&amp;rsquo; stream last Sunday, where he tested  &amp;ldquo;Miku Beach Concert&amp;rdquo; and reported it as a solid experience, I decided to give that demo a spin. On the forums, people are reporting performances of above 200fps. I&amp;rsquo;m getting about 50 fps. The verdict is clear, that HD5450 card is really slow, way too slow for this kind of rendering. Upgrading to the new SDK 0.4.1 release did not help.&lt;/p&gt;&lt;p&gt;Turns out I have a new Retina Mac Book Pro on its way, sporting an Nvidia GT750M chipset, that should perform way better than this desktop machine.&lt;/p&gt;&lt;p&gt;Given that situation, I will not provide any comment on my experience with the Rift until I&amp;rsquo;ve had a chance to test it on a decent setup.&lt;/p&gt;&lt;p&gt;A so the wait continues&amp;hellip;&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Virtual Insanity</title>
       <link>https://https://ericbariaux.statichost.page//posts/virtual-insanity/</link>
       <pubDate>Wed, 16 Jul 2014 00:00:00 +0000</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/virtual-insanity/</guid>
       <description>&lt;p&gt;As about 40.000 people on the planet, I&amp;rsquo;m patiently waiting for my Oculus Rift DK2 to arrive.&lt;/p&gt;&lt;p&gt;Although I&amp;rsquo;m impatient to get it, I&amp;rsquo;m not going insane, a trait that some members on the Oculus dev forums or subreddit are clearly exhibiting. Am I annoyed ? Slightly. Am I mad at Oculus ? Definitely no (though if I ever run into Palmer Luckey I&amp;rsquo;ll only buy him regular juice and not that expensive organic cranberry apple juice).&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve been shipping software long enough to understand that it&amp;rsquo;s tough to make estimates, even more so when you&amp;rsquo;re innovating.&lt;/p&gt;&lt;p&gt;I&amp;rsquo;ve been in small start-ups and not so small corporations and understand that PR is a tricky job. And although I&amp;rsquo;m a firm believer in being open and honest, there&amp;rsquo;s a way and a time to present information. There&amp;rsquo;s no way to please everybody, it&amp;rsquo;s a balancing act and there will always be someone to call out the conspiracy theory.&lt;/p&gt;&lt;p&gt;I also do understand the slight difference between making a prototype, making 100 copies of some hardware and making several tens of thousands of pieces in a month. Can you make yourself a sandwich ? Can you make sandwiches for all of E3 attendees lunch ?&lt;/p&gt;&lt;figure&gt;&lt;img src=&#34;https://https://ericbariaux.statichost.page//images/Rift%20DK2.jpeg&#34;    alt=&#34;The Rift DK2&#34;&gt;&lt;figcaption&gt;      &lt;p&gt;The Rift DK2&lt;/p&gt;    &lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;But seriously, Oculus, where is my rift ? What am I gonna do without it ? Well I&amp;rsquo;m just gonna do the same thing I did yesterday.&lt;/p&gt;&lt;p&gt;Looking at forum posts, I think some clarification of the meaning of urgency is required:&lt;/p&gt;&lt;p&gt;Getting the organ for that transplant that will save a life: urgentDrilling a hole to put a nuclear warhead in a meteorite and save the earth: urgentGetting the latest tech gadget to play around or even to work on your next great invention: no so urgentSeriously, instead of just waiting and whining, do something for VR. I&amp;rsquo;m sure you can still create some 3D models, improve that bit of code, re-think the UX of your game or simply listen to the many great podcasts on the topic.&lt;/p&gt;&lt;p&gt;I can hear the critics say &amp;ldquo;It&amp;rsquo;s just because you&amp;rsquo;re not a core VR enthusiast&amp;rdquo;. Well it&amp;rsquo;s true I did not participate in the kick starter (can&amp;rsquo;t remember if I even noticed it before it closed) or even ordered a DK1 (I nearly did a couple of times but never pulled the trigger).&lt;/p&gt;&lt;p&gt;But the truth is I&amp;rsquo;m not a new comer to VR either (more on this in follow up posts) and it took me a bit of time to realize that, this time, VR is here to stay. So, with or without a rift, I&amp;rsquo;m fully on board.&lt;/p&gt;</description>
     </item>
   
     <item>
       <title>Welcome (again)</title>
       <link>https://https://ericbariaux.statichost.page//posts/welcome-again/</link>
       <pubDate>Tue, 24 Jun 2014 00:00:00 +0000</pubDate>
       
       <guid>https://https://ericbariaux.statichost.page//posts/welcome-again/</guid>
       <description>&lt;p&gt;I&amp;rsquo;ll confess, focus is not my forte! I tend to be interested by a lot of different topics, even more so when it comes to technical and scientific ones.&lt;/p&gt;&lt;p&gt;Over the last few years, pumped up by the then latest and greatest idea I just had, I&amp;rsquo;ve started several blogs. I followed-up with a couple of posts and then swamped by work or some other real-life &amp;ldquo;obligation&amp;rdquo;, I let it fall into oblivion, piling up in some dead internet sites landfill, waiting for the DNS registration to expire.&lt;/p&gt;&lt;p&gt;Did I learn something since then? Maybe, maybe not, but I want to believe in my mental sanity.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Insanity: doing the same thing over and over again and expecting different results.&lt;/p&gt;&lt;p&gt;&amp;ndash; &lt;!-- raw HTML omitted --&gt;Albert Einstein&lt;!-- raw HTML omitted --&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;So I&amp;rsquo;ll go by the above quote, attributed to Albert Einstein, and do things differently this time. Well, sort of.&lt;/p&gt;&lt;p&gt;You might say that you&amp;rsquo;re reading a new blog that I started and so consider that I&amp;rsquo;m doing it all over again. I beg to differ.&lt;/p&gt;&lt;p&gt;I did not register yet another domain name but decided to locate this blog at the URL I used for my SPOC site. Although this might seem like a technical detail, it&amp;rsquo;s not. It is a conscious choice in setting the tone of this site, which I want to be much more about me. But fear not, the goal is not to write an egomaniacal soap opera like series praising my greatness, but to give me the opportunity to talk about my thoughts, experiences or ideas as they evolve thru time, without being constrained to a specific topic to which the entire blog is dedicated. This will also allow me to go broader, talking about things that would have never warranted a dedicated blog but might make for an interesting post.&lt;/p&gt;&lt;p&gt;This time, I&amp;rsquo;m not starting from scratch either. I&amp;rsquo;m bringing the few posts I did on Geekstorian over. Not that there was that much content over there, but I feel like this is an important topic for me and I still want to explore it, maybe not tomorrow but I&amp;rsquo;m pretty sure, some day, there will be follow-up posts.&lt;/p&gt;&lt;p&gt;So let&amp;rsquo;s see where this takes us and anyway, as the proverb says : &amp;ldquo;The Journey is the Reward&amp;rdquo;.&lt;/p&gt;</description>
     </item>
   
 </channel>
</rss>
